search record details with slider and fragments (honeycomb ui like)
authordrizea <danielrizea27@gmail.com>
Sun, 8 Jul 2012 16:13:02 +0000 (19:13 +0300)
committerdrizea <danielrizea27@gmail.com>
Sun, 8 Jul 2012 16:13:02 +0000 (19:13 +0300)
73 files changed:
Open-ILS/src/Android/.classpath
Open-ILS/src/Android/AndroidManifest.xml
Open-ILS/src/Android/lib/org.openils_idl.jar [deleted file]
Open-ILS/src/Android/lib/org.opensrf2_serialized_reg.jar [deleted file]
Open-ILS/src/Android/lib/simple-xml-2.6.4.jar [deleted file]
Open-ILS/src/Android/libs/android-support-v4.jar [new file with mode: 0644]
Open-ILS/src/Android/libs/org.openils_idl.jar [new file with mode: 0644]
Open-ILS/src/Android/libs/org.opensrf2_serialized_reg.jar [new file with mode: 0644]
Open-ILS/src/Android/libs/simple-xml-2.6.4.jar [new file with mode: 0644]
Open-ILS/src/Android/res/drawable-hdpi/custom_tab_indicator_focused.9.png [new file with mode: 0644]
Open-ILS/src/Android/res/drawable-hdpi/custom_tab_indicator_selected.9.png [new file with mode: 0644]
Open-ILS/src/Android/res/drawable-hdpi/custom_tab_indicator_selected_pressed.9.png [new file with mode: 0644]
Open-ILS/src/Android/res/drawable-hdpi/custom_tab_indicator_unselected.9.png [new file with mode: 0644]
Open-ILS/src/Android/res/drawable-hdpi/custom_tab_indicator_unselected_focused.9.png [new file with mode: 0644]
Open-ILS/src/Android/res/drawable-hdpi/custom_tab_indicator_unselected_pressed.9.png [new file with mode: 0644]
Open-ILS/src/Android/res/drawable-hdpi/vpi__tab_selected_focused_holo.9.png [new file with mode: 0644]
Open-ILS/src/Android/res/drawable-hdpi/vpi__tab_selected_holo.9.png [new file with mode: 0644]
Open-ILS/src/Android/res/drawable-hdpi/vpi__tab_selected_pressed_holo.9.png [new file with mode: 0644]
Open-ILS/src/Android/res/drawable-hdpi/vpi__tab_unselected_focused_holo.9.png [new file with mode: 0644]
Open-ILS/src/Android/res/drawable-hdpi/vpi__tab_unselected_holo.9.png [new file with mode: 0644]
Open-ILS/src/Android/res/drawable-hdpi/vpi__tab_unselected_pressed_holo.9.png [new file with mode: 0644]
Open-ILS/src/Android/res/drawable-ldpi/vpi__tab_selected_focused_holo.9.png [new file with mode: 0644]
Open-ILS/src/Android/res/drawable-ldpi/vpi__tab_selected_holo.9.png [new file with mode: 0644]
Open-ILS/src/Android/res/drawable-ldpi/vpi__tab_selected_pressed_holo.9.png [new file with mode: 0644]
Open-ILS/src/Android/res/drawable-ldpi/vpi__tab_unselected_focused_holo.9.png [new file with mode: 0644]
Open-ILS/src/Android/res/drawable-ldpi/vpi__tab_unselected_holo.9.png [new file with mode: 0644]
Open-ILS/src/Android/res/drawable-ldpi/vpi__tab_unselected_pressed_holo.9.png [new file with mode: 0644]
Open-ILS/src/Android/res/drawable-mdpi/custom_tab_indicator_selected.9.png [new file with mode: 0644]
Open-ILS/src/Android/res/drawable-mdpi/custom_tab_indicator_selected_focused.9.png [new file with mode: 0644]
Open-ILS/src/Android/res/drawable-mdpi/custom_tab_indicator_selected_pressed.9.png [new file with mode: 0644]
Open-ILS/src/Android/res/drawable-mdpi/custom_tab_indicator_unselected.9.png [new file with mode: 0644]
Open-ILS/src/Android/res/drawable-mdpi/custom_tab_indicator_unselected_focused.9.png [new file with mode: 0644]
Open-ILS/src/Android/res/drawable-mdpi/custom_tab_indicator_unselected_pressed.9.png [new file with mode: 0644]
Open-ILS/src/Android/res/drawable-mdpi/vpi__tab_selected_focused_holo.9.png [new file with mode: 0644]
Open-ILS/src/Android/res/drawable-mdpi/vpi__tab_selected_holo.9.png [new file with mode: 0644]
Open-ILS/src/Android/res/drawable-mdpi/vpi__tab_selected_pressed_holo.9.png [new file with mode: 0644]
Open-ILS/src/Android/res/drawable-mdpi/vpi__tab_unselected_focused_holo.9.png [new file with mode: 0644]
Open-ILS/src/Android/res/drawable-mdpi/vpi__tab_unselected_holo.9.png [new file with mode: 0644]
Open-ILS/src/Android/res/drawable-mdpi/vpi__tab_unselected_pressed_holo.9.png [new file with mode: 0644]
Open-ILS/src/Android/res/drawable-xhdpi/vpi__tab_selected_focused_holo.9.png [new file with mode: 0644]
Open-ILS/src/Android/res/drawable-xhdpi/vpi__tab_selected_holo.9.png [new file with mode: 0644]
Open-ILS/src/Android/res/drawable-xhdpi/vpi__tab_selected_pressed_holo.9.png [new file with mode: 0644]
Open-ILS/src/Android/res/drawable-xhdpi/vpi__tab_unselected_focused_holo.9.png [new file with mode: 0644]
Open-ILS/src/Android/res/drawable-xhdpi/vpi__tab_unselected_holo.9.png [new file with mode: 0644]
Open-ILS/src/Android/res/drawable-xhdpi/vpi__tab_unselected_pressed_holo.9.png [new file with mode: 0644]
Open-ILS/src/Android/res/drawable/custom_tab_indicator.xml [new file with mode: 0644]
Open-ILS/src/Android/res/drawable/vpi__tab_indicator.xml [new file with mode: 0644]
Open-ILS/src/Android/res/layout/record_details_basic_fragment.xml [new file with mode: 0644]
Open-ILS/src/Android/res/layout/record_details_info.xml
Open-ILS/src/Android/res/layout/record_details_more_fragment.xml [new file with mode: 0644]
Open-ILS/src/Android/res/layout/record_details_simple.xml
Open-ILS/src/Android/res/layout/simple_tabs.xml [new file with mode: 0644]
Open-ILS/src/Android/res/menu/menu.xml [new file with mode: 0644]
Open-ILS/src/Android/res/values/styles.xml
Open-ILS/src/Android/res/values/vpi__attrs.xml [new file with mode: 0644]
Open-ILS/src/Android/res/values/vpi__colors.xml [new file with mode: 0644]
Open-ILS/src/Android/res/values/vpi__defaults.xml [new file with mode: 0644]
Open-ILS/src/Android/res/values/vpi__styles.xml [new file with mode: 0644]
Open-ILS/src/Android/res/xml/vpi__dark_theme.xml [new file with mode: 0644]
Open-ILS/src/Android/res/xml/vpi__light_theme.xml [new file with mode: 0644]
Open-ILS/src/Android/src/org/evergreen/android/searchCatalog/RecordDetails.java
Open-ILS/src/Android/src/org/evergreen/android/searchCatalog/SearchCatalog.java
Open-ILS/src/Android/src/org/evergreen/android/searchCatalog/SearchCatalogListView.java
Open-ILS/src/Android/src/org/evergreen/android/searchCatalog/TabsView.java [new file with mode: 0644]
Open-ILS/src/Android/src/org/evergreen/android/utils/ui/AdvancedDetailsFragment.java [new file with mode: 0644]
Open-ILS/src/Android/src/org/evergreen/android/utils/ui/BaseSampleActivity.java [new file with mode: 0644]
Open-ILS/src/Android/src/org/evergreen/android/utils/ui/BasicDetailsFragment.java [new file with mode: 0644]
Open-ILS/src/Android/src/org/evergreen/android/utils/ui/PageIndicator.java [new file with mode: 0644]
Open-ILS/src/Android/src/org/evergreen/android/utils/ui/RealViewSwitcher.java [new file with mode: 0644]
Open-ILS/src/Android/src/org/evergreen/android/utils/ui/TabPageIndicator.java [new file with mode: 0644]
Open-ILS/src/Android/src/org/evergreen/android/utils/ui/TestFragment.java [new file with mode: 0644]
Open-ILS/src/Android/src/org/evergreen/android/utils/ui/TestFragmentAdapter.java [new file with mode: 0644]
Open-ILS/src/Android/src/org/evergreen/android/utils/ui/TitlePageIndicator.java [new file with mode: 0644]

index 51d7d3a..1b0ce02 100644 (file)
@@ -4,8 +4,9 @@
        <classpathentry kind="src" path="gen"/>
        <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
        <classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
-       <classpathentry kind="lib" path="lib/simple-xml-2.6.4.jar"/>
-       <classpathentry kind="lib" path="lib/org.opensrf2_serialized_reg.jar"/>
-       <classpathentry kind="lib" path="lib/org.openils_idl.jar"/>
+       <classpathentry kind="lib" path="libs/android-support-v4.jar"/>
+       <classpathentry kind="lib" path="libs/org.openils_idl.jar"/>
+       <classpathentry kind="lib" path="libs/org.opensrf2_serialized_reg.jar"/>
+       <classpathentry kind="lib" path="libs/simple-xml-2.6.4.jar"/>
        <classpathentry kind="output" path="bin/classes"/>
 </classpath>
index 10fe06f..a22d270 100644 (file)
             android:theme="@android:style/Theme.Light.NoTitleBar"
             >
         </activity>
-        <activity
-            android:name=".views.ApplicationPreferences"
-            >
+        <activity android:name="org.evergreen.android.views.ApplicationPreferences"></activity>
+        
             
-        </activity>
+        <!-- Search -->    
+        <activity android:name=".searchCatalog.TabsView"
+            android:label="Tabs/Styled"
+            android:theme="@style/StyledIndicators"
+            ></activity>  
+
         <!-- Checkout Activities -->
         <activity android:name=".accountAccess.checkout.ItemsCheckOutListView"></activity>
         
diff --git a/Open-ILS/src/Android/lib/org.openils_idl.jar b/Open-ILS/src/Android/lib/org.openils_idl.jar
deleted file mode 100644 (file)
index f3f0d6b..0000000
Binary files a/Open-ILS/src/Android/lib/org.openils_idl.jar and /dev/null differ
diff --git a/Open-ILS/src/Android/lib/org.opensrf2_serialized_reg.jar b/Open-ILS/src/Android/lib/org.opensrf2_serialized_reg.jar
deleted file mode 100644 (file)
index 84c9b94..0000000
Binary files a/Open-ILS/src/Android/lib/org.opensrf2_serialized_reg.jar and /dev/null differ
diff --git a/Open-ILS/src/Android/lib/simple-xml-2.6.4.jar b/Open-ILS/src/Android/lib/simple-xml-2.6.4.jar
deleted file mode 100644 (file)
index be60eae..0000000
Binary files a/Open-ILS/src/Android/lib/simple-xml-2.6.4.jar and /dev/null differ
diff --git a/Open-ILS/src/Android/libs/android-support-v4.jar b/Open-ILS/src/Android/libs/android-support-v4.jar
new file mode 100644 (file)
index 0000000..99e063b
Binary files /dev/null and b/Open-ILS/src/Android/libs/android-support-v4.jar differ
diff --git a/Open-ILS/src/Android/libs/org.openils_idl.jar b/Open-ILS/src/Android/libs/org.openils_idl.jar
new file mode 100644 (file)
index 0000000..f3f0d6b
Binary files /dev/null and b/Open-ILS/src/Android/libs/org.openils_idl.jar differ
diff --git a/Open-ILS/src/Android/libs/org.opensrf2_serialized_reg.jar b/Open-ILS/src/Android/libs/org.opensrf2_serialized_reg.jar
new file mode 100644 (file)
index 0000000..84c9b94
Binary files /dev/null and b/Open-ILS/src/Android/libs/org.opensrf2_serialized_reg.jar differ
diff --git a/Open-ILS/src/Android/libs/simple-xml-2.6.4.jar b/Open-ILS/src/Android/libs/simple-xml-2.6.4.jar
new file mode 100644 (file)
index 0000000..be60eae
Binary files /dev/null and b/Open-ILS/src/Android/libs/simple-xml-2.6.4.jar differ
diff --git a/Open-ILS/src/Android/res/drawable-hdpi/custom_tab_indicator_focused.9.png b/Open-ILS/src/Android/res/drawable-hdpi/custom_tab_indicator_focused.9.png
new file mode 100644 (file)
index 0000000..8d36d7d
Binary files /dev/null and b/Open-ILS/src/Android/res/drawable-hdpi/custom_tab_indicator_focused.9.png differ
diff --git a/Open-ILS/src/Android/res/drawable-hdpi/custom_tab_indicator_selected.9.png b/Open-ILS/src/Android/res/drawable-hdpi/custom_tab_indicator_selected.9.png
new file mode 100644 (file)
index 0000000..db329b8
Binary files /dev/null and b/Open-ILS/src/Android/res/drawable-hdpi/custom_tab_indicator_selected.9.png differ
diff --git a/Open-ILS/src/Android/res/drawable-hdpi/custom_tab_indicator_selected_pressed.9.png b/Open-ILS/src/Android/res/drawable-hdpi/custom_tab_indicator_selected_pressed.9.png
new file mode 100644 (file)
index 0000000..7ea6825
Binary files /dev/null and b/Open-ILS/src/Android/res/drawable-hdpi/custom_tab_indicator_selected_pressed.9.png differ
diff --git a/Open-ILS/src/Android/res/drawable-hdpi/custom_tab_indicator_unselected.9.png b/Open-ILS/src/Android/res/drawable-hdpi/custom_tab_indicator_unselected.9.png
new file mode 100644 (file)
index 0000000..43ec872
Binary files /dev/null and b/Open-ILS/src/Android/res/drawable-hdpi/custom_tab_indicator_unselected.9.png differ
diff --git a/Open-ILS/src/Android/res/drawable-hdpi/custom_tab_indicator_unselected_focused.9.png b/Open-ILS/src/Android/res/drawable-hdpi/custom_tab_indicator_unselected_focused.9.png
new file mode 100644 (file)
index 0000000..2162b8b
Binary files /dev/null and b/Open-ILS/src/Android/res/drawable-hdpi/custom_tab_indicator_unselected_focused.9.png differ
diff --git a/Open-ILS/src/Android/res/drawable-hdpi/custom_tab_indicator_unselected_pressed.9.png b/Open-ILS/src/Android/res/drawable-hdpi/custom_tab_indicator_unselected_pressed.9.png
new file mode 100644 (file)
index 0000000..38917bb
Binary files /dev/null and b/Open-ILS/src/Android/res/drawable-hdpi/custom_tab_indicator_unselected_pressed.9.png differ
diff --git a/Open-ILS/src/Android/res/drawable-hdpi/vpi__tab_selected_focused_holo.9.png b/Open-ILS/src/Android/res/drawable-hdpi/vpi__tab_selected_focused_holo.9.png
new file mode 100644 (file)
index 0000000..673e3bf
Binary files /dev/null and b/Open-ILS/src/Android/res/drawable-hdpi/vpi__tab_selected_focused_holo.9.png differ
diff --git a/Open-ILS/src/Android/res/drawable-hdpi/vpi__tab_selected_holo.9.png b/Open-ILS/src/Android/res/drawable-hdpi/vpi__tab_selected_holo.9.png
new file mode 100644 (file)
index 0000000..d57df98
Binary files /dev/null and b/Open-ILS/src/Android/res/drawable-hdpi/vpi__tab_selected_holo.9.png differ
diff --git a/Open-ILS/src/Android/res/drawable-hdpi/vpi__tab_selected_pressed_holo.9.png b/Open-ILS/src/Android/res/drawable-hdpi/vpi__tab_selected_pressed_holo.9.png
new file mode 100644 (file)
index 0000000..6278eef
Binary files /dev/null and b/Open-ILS/src/Android/res/drawable-hdpi/vpi__tab_selected_pressed_holo.9.png differ
diff --git a/Open-ILS/src/Android/res/drawable-hdpi/vpi__tab_unselected_focused_holo.9.png b/Open-ILS/src/Android/res/drawable-hdpi/vpi__tab_unselected_focused_holo.9.png
new file mode 100644 (file)
index 0000000..294991d
Binary files /dev/null and b/Open-ILS/src/Android/res/drawable-hdpi/vpi__tab_unselected_focused_holo.9.png differ
diff --git a/Open-ILS/src/Android/res/drawable-hdpi/vpi__tab_unselected_holo.9.png b/Open-ILS/src/Android/res/drawable-hdpi/vpi__tab_unselected_holo.9.png
new file mode 100644 (file)
index 0000000..19532ab
Binary files /dev/null and b/Open-ILS/src/Android/res/drawable-hdpi/vpi__tab_unselected_holo.9.png differ
diff --git a/Open-ILS/src/Android/res/drawable-hdpi/vpi__tab_unselected_pressed_holo.9.png b/Open-ILS/src/Android/res/drawable-hdpi/vpi__tab_unselected_pressed_holo.9.png
new file mode 100644 (file)
index 0000000..aadc6f8
Binary files /dev/null and b/Open-ILS/src/Android/res/drawable-hdpi/vpi__tab_unselected_pressed_holo.9.png differ
diff --git a/Open-ILS/src/Android/res/drawable-ldpi/vpi__tab_selected_focused_holo.9.png b/Open-ILS/src/Android/res/drawable-ldpi/vpi__tab_selected_focused_holo.9.png
new file mode 100644 (file)
index 0000000..c9972e7
Binary files /dev/null and b/Open-ILS/src/Android/res/drawable-ldpi/vpi__tab_selected_focused_holo.9.png differ
diff --git a/Open-ILS/src/Android/res/drawable-ldpi/vpi__tab_selected_holo.9.png b/Open-ILS/src/Android/res/drawable-ldpi/vpi__tab_selected_holo.9.png
new file mode 100644 (file)
index 0000000..587337c
Binary files /dev/null and b/Open-ILS/src/Android/res/drawable-ldpi/vpi__tab_selected_holo.9.png differ
diff --git a/Open-ILS/src/Android/res/drawable-ldpi/vpi__tab_selected_pressed_holo.9.png b/Open-ILS/src/Android/res/drawable-ldpi/vpi__tab_selected_pressed_holo.9.png
new file mode 100644 (file)
index 0000000..155c4fc
Binary files /dev/null and b/Open-ILS/src/Android/res/drawable-ldpi/vpi__tab_selected_pressed_holo.9.png differ
diff --git a/Open-ILS/src/Android/res/drawable-ldpi/vpi__tab_unselected_focused_holo.9.png b/Open-ILS/src/Android/res/drawable-ldpi/vpi__tab_unselected_focused_holo.9.png
new file mode 100644 (file)
index 0000000..f0cecd1
Binary files /dev/null and b/Open-ILS/src/Android/res/drawable-ldpi/vpi__tab_unselected_focused_holo.9.png differ
diff --git a/Open-ILS/src/Android/res/drawable-ldpi/vpi__tab_unselected_holo.9.png b/Open-ILS/src/Android/res/drawable-ldpi/vpi__tab_unselected_holo.9.png
new file mode 100644 (file)
index 0000000..a2dbf42
Binary files /dev/null and b/Open-ILS/src/Android/res/drawable-ldpi/vpi__tab_unselected_holo.9.png differ
diff --git a/Open-ILS/src/Android/res/drawable-ldpi/vpi__tab_unselected_pressed_holo.9.png b/Open-ILS/src/Android/res/drawable-ldpi/vpi__tab_unselected_pressed_holo.9.png
new file mode 100644 (file)
index 0000000..b1223fe
Binary files /dev/null and b/Open-ILS/src/Android/res/drawable-ldpi/vpi__tab_unselected_pressed_holo.9.png differ
diff --git a/Open-ILS/src/Android/res/drawable-mdpi/custom_tab_indicator_selected.9.png b/Open-ILS/src/Android/res/drawable-mdpi/custom_tab_indicator_selected.9.png
new file mode 100644 (file)
index 0000000..3f6aaa3
Binary files /dev/null and b/Open-ILS/src/Android/res/drawable-mdpi/custom_tab_indicator_selected.9.png differ
diff --git a/Open-ILS/src/Android/res/drawable-mdpi/custom_tab_indicator_selected_focused.9.png b/Open-ILS/src/Android/res/drawable-mdpi/custom_tab_indicator_selected_focused.9.png
new file mode 100644 (file)
index 0000000..569d164
Binary files /dev/null and b/Open-ILS/src/Android/res/drawable-mdpi/custom_tab_indicator_selected_focused.9.png differ
diff --git a/Open-ILS/src/Android/res/drawable-mdpi/custom_tab_indicator_selected_pressed.9.png b/Open-ILS/src/Android/res/drawable-mdpi/custom_tab_indicator_selected_pressed.9.png
new file mode 100644 (file)
index 0000000..7f3a8f2
Binary files /dev/null and b/Open-ILS/src/Android/res/drawable-mdpi/custom_tab_indicator_selected_pressed.9.png differ
diff --git a/Open-ILS/src/Android/res/drawable-mdpi/custom_tab_indicator_unselected.9.png b/Open-ILS/src/Android/res/drawable-mdpi/custom_tab_indicator_unselected.9.png
new file mode 100644 (file)
index 0000000..9689ea1
Binary files /dev/null and b/Open-ILS/src/Android/res/drawable-mdpi/custom_tab_indicator_unselected.9.png differ
diff --git a/Open-ILS/src/Android/res/drawable-mdpi/custom_tab_indicator_unselected_focused.9.png b/Open-ILS/src/Android/res/drawable-mdpi/custom_tab_indicator_unselected_focused.9.png
new file mode 100644 (file)
index 0000000..88759ba
Binary files /dev/null and b/Open-ILS/src/Android/res/drawable-mdpi/custom_tab_indicator_unselected_focused.9.png differ
diff --git a/Open-ILS/src/Android/res/drawable-mdpi/custom_tab_indicator_unselected_pressed.9.png b/Open-ILS/src/Android/res/drawable-mdpi/custom_tab_indicator_unselected_pressed.9.png
new file mode 100644 (file)
index 0000000..defa52f
Binary files /dev/null and b/Open-ILS/src/Android/res/drawable-mdpi/custom_tab_indicator_unselected_pressed.9.png differ
diff --git a/Open-ILS/src/Android/res/drawable-mdpi/vpi__tab_selected_focused_holo.9.png b/Open-ILS/src/Android/res/drawable-mdpi/vpi__tab_selected_focused_holo.9.png
new file mode 100644 (file)
index 0000000..c9972e7
Binary files /dev/null and b/Open-ILS/src/Android/res/drawable-mdpi/vpi__tab_selected_focused_holo.9.png differ
diff --git a/Open-ILS/src/Android/res/drawable-mdpi/vpi__tab_selected_holo.9.png b/Open-ILS/src/Android/res/drawable-mdpi/vpi__tab_selected_holo.9.png
new file mode 100644 (file)
index 0000000..587337c
Binary files /dev/null and b/Open-ILS/src/Android/res/drawable-mdpi/vpi__tab_selected_holo.9.png differ
diff --git a/Open-ILS/src/Android/res/drawable-mdpi/vpi__tab_selected_pressed_holo.9.png b/Open-ILS/src/Android/res/drawable-mdpi/vpi__tab_selected_pressed_holo.9.png
new file mode 100644 (file)
index 0000000..155c4fc
Binary files /dev/null and b/Open-ILS/src/Android/res/drawable-mdpi/vpi__tab_selected_pressed_holo.9.png differ
diff --git a/Open-ILS/src/Android/res/drawable-mdpi/vpi__tab_unselected_focused_holo.9.png b/Open-ILS/src/Android/res/drawable-mdpi/vpi__tab_unselected_focused_holo.9.png
new file mode 100644 (file)
index 0000000..f0cecd1
Binary files /dev/null and b/Open-ILS/src/Android/res/drawable-mdpi/vpi__tab_unselected_focused_holo.9.png differ
diff --git a/Open-ILS/src/Android/res/drawable-mdpi/vpi__tab_unselected_holo.9.png b/Open-ILS/src/Android/res/drawable-mdpi/vpi__tab_unselected_holo.9.png
new file mode 100644 (file)
index 0000000..a2dbf42
Binary files /dev/null and b/Open-ILS/src/Android/res/drawable-mdpi/vpi__tab_unselected_holo.9.png differ
diff --git a/Open-ILS/src/Android/res/drawable-mdpi/vpi__tab_unselected_pressed_holo.9.png b/Open-ILS/src/Android/res/drawable-mdpi/vpi__tab_unselected_pressed_holo.9.png
new file mode 100644 (file)
index 0000000..b1223fe
Binary files /dev/null and b/Open-ILS/src/Android/res/drawable-mdpi/vpi__tab_unselected_pressed_holo.9.png differ
diff --git a/Open-ILS/src/Android/res/drawable-xhdpi/vpi__tab_selected_focused_holo.9.png b/Open-ILS/src/Android/res/drawable-xhdpi/vpi__tab_selected_focused_holo.9.png
new file mode 100644 (file)
index 0000000..c9972e7
Binary files /dev/null and b/Open-ILS/src/Android/res/drawable-xhdpi/vpi__tab_selected_focused_holo.9.png differ
diff --git a/Open-ILS/src/Android/res/drawable-xhdpi/vpi__tab_selected_holo.9.png b/Open-ILS/src/Android/res/drawable-xhdpi/vpi__tab_selected_holo.9.png
new file mode 100644 (file)
index 0000000..587337c
Binary files /dev/null and b/Open-ILS/src/Android/res/drawable-xhdpi/vpi__tab_selected_holo.9.png differ
diff --git a/Open-ILS/src/Android/res/drawable-xhdpi/vpi__tab_selected_pressed_holo.9.png b/Open-ILS/src/Android/res/drawable-xhdpi/vpi__tab_selected_pressed_holo.9.png
new file mode 100644 (file)
index 0000000..155c4fc
Binary files /dev/null and b/Open-ILS/src/Android/res/drawable-xhdpi/vpi__tab_selected_pressed_holo.9.png differ
diff --git a/Open-ILS/src/Android/res/drawable-xhdpi/vpi__tab_unselected_focused_holo.9.png b/Open-ILS/src/Android/res/drawable-xhdpi/vpi__tab_unselected_focused_holo.9.png
new file mode 100644 (file)
index 0000000..f0cecd1
Binary files /dev/null and b/Open-ILS/src/Android/res/drawable-xhdpi/vpi__tab_unselected_focused_holo.9.png differ
diff --git a/Open-ILS/src/Android/res/drawable-xhdpi/vpi__tab_unselected_holo.9.png b/Open-ILS/src/Android/res/drawable-xhdpi/vpi__tab_unselected_holo.9.png
new file mode 100644 (file)
index 0000000..a2dbf42
Binary files /dev/null and b/Open-ILS/src/Android/res/drawable-xhdpi/vpi__tab_unselected_holo.9.png differ
diff --git a/Open-ILS/src/Android/res/drawable-xhdpi/vpi__tab_unselected_pressed_holo.9.png b/Open-ILS/src/Android/res/drawable-xhdpi/vpi__tab_unselected_pressed_holo.9.png
new file mode 100644 (file)
index 0000000..b1223fe
Binary files /dev/null and b/Open-ILS/src/Android/res/drawable-xhdpi/vpi__tab_unselected_pressed_holo.9.png differ
diff --git a/Open-ILS/src/Android/res/drawable/custom_tab_indicator.xml b/Open-ILS/src/Android/res/drawable/custom_tab_indicator.xml
new file mode 100644 (file)
index 0000000..e7f4cf3
--- /dev/null
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <!-- Non focused states -->
+    <item android:state_focused="false" android:state_selected="false" android:state_pressed="false" android:drawable="@drawable/custom_tab_indicator_unselected" />
+    <item android:state_focused="false" android:state_selected="true"  android:state_pressed="false" android:drawable="@drawable/custom_tab_indicator_selected" />
+
+    <!-- Focused states -->
+    <item android:state_focused="true" android:state_selected="false" android:state_pressed="false" android:drawable="@drawable/custom_tab_indicator_unselected_focused" />
+    <item android:state_focused="true" android:state_selected="true"  android:state_pressed="false" android:drawable="@drawable/custom_tab_indicator_selected_focused" />
+
+    <!-- Pressed -->
+    <!--    Non focused states -->
+    <item android:state_focused="false" android:state_selected="false" android:state_pressed="true" android:drawable="@drawable/custom_tab_indicator_unselected_pressed" />
+    <item android:state_focused="false" android:state_selected="true"  android:state_pressed="true" android:drawable="@drawable/custom_tab_indicator_selected_pressed" />
+
+    <!--    Focused states -->
+    <item android:state_focused="true" android:state_selected="false" android:state_pressed="true" android:drawable="@drawable/custom_tab_indicator_unselected_pressed" />
+    <item android:state_focused="true" android:state_selected="true"  android:state_pressed="true" android:drawable="@drawable/custom_tab_indicator_selected_pressed" />
+</selector>
diff --git a/Open-ILS/src/Android/res/drawable/vpi__tab_indicator.xml b/Open-ILS/src/Android/res/drawable/vpi__tab_indicator.xml
new file mode 100644 (file)
index 0000000..520d08c
--- /dev/null
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <!-- Non focused states -->
+    <item android:state_focused="false" android:state_selected="false" android:state_pressed="false" android:drawable="@drawable/vpi__tab_unselected_holo" />
+    <item android:state_focused="false" android:state_selected="true"  android:state_pressed="false" android:drawable="@drawable/vpi__tab_selected_holo" />
+
+    <!-- Focused states -->
+    <item android:state_focused="true" android:state_selected="false" android:state_pressed="false" android:drawable="@drawable/vpi__tab_unselected_focused_holo" />
+    <item android:state_focused="true" android:state_selected="true"  android:state_pressed="false" android:drawable="@drawable/vpi__tab_selected_focused_holo" />
+
+    <!-- Pressed -->
+    <!--    Non focused states -->
+    <item android:state_focused="false" android:state_selected="false" android:state_pressed="true" android:drawable="@drawable/vpi__tab_unselected_pressed_holo" />
+    <item android:state_focused="false" android:state_selected="true"  android:state_pressed="true" android:drawable="@drawable/vpi__tab_selected_pressed_holo" />
+
+    <!--    Focused states -->
+    <item android:state_focused="true" android:state_selected="false" android:state_pressed="true" android:drawable="@drawable/vpi__tab_unselected_pressed_holo" />
+    <item android:state_focused="true" android:state_selected="true"  android:state_pressed="true" android:drawable="@drawable/vpi__tab_selected_pressed_holo" />
+</selector>
diff --git a/Open-ILS/src/Android/res/layout/record_details_basic_fragment.xml b/Open-ILS/src/Android/res/layout/record_details_basic_fragment.xml
new file mode 100644 (file)
index 0000000..b12fd55
--- /dev/null
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"   
+ android:id="@+id/record_details_simple_view">
+<LinearLayout 
+    android:layout_width="fill_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical">
+
+
+           <TextView  
+           xmlns:android="http://schemas.android.com/apk/res/android"
+           style="@style/sectionHeader"  
+           android:text="Basic Information"
+               /> 
+           
+           
+           <TextView 
+               style="@style/textLarge"
+           android:text="TITLE"   
+               />
+       
+            <TextView
+           android:id="@+id/record_details_simple_title"
+               style="@style/textSmall"
+           />
+           
+           <TextView  
+               style="@style/textLarge"
+           android:text="AUTHOR"   
+               />
+           
+           <TextView
+           android:id="@+id/record_details_simple_author"
+               style="@style/textSmall"   
+           />
+               
+           <TextView  
+               style="@style/textLarge"
+           android:text="PUBLISHER"   
+               />
+           
+           <TextView
+           android:id="@+id/record_details_simple_publisher"
+               style="@style/textSmall"   
+               />
+
+           
+          
+       </LinearLayout>
+</ScrollView>
\ No newline at end of file
index a806b6b..f324a31 100644 (file)
@@ -2,7 +2,9 @@
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="fill_parent"
     android:layout_height="fill_parent"
-    android:orientation="vertical">
+    android:orientation="vertical"
+    android:id="@+id/record_details_info_view"
+    >
 
     <TextView 
     android:layout_width="wrap_content"
diff --git a/Open-ILS/src/Android/res/layout/record_details_more_fragment.xml b/Open-ILS/src/Android/res/layout/record_details_more_fragment.xml
new file mode 100644 (file)
index 0000000..e2b2b6d
--- /dev/null
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"   
+ android:id="@+id/record_details_simple_view">
+<LinearLayout 
+    android:layout_width="fill_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical">
+
+
+       <TextView  
+           xmlns:android="http://schemas.android.com/apk/res/android"
+           style="@style/sectionHeader"  
+           android:text="Content"
+               /> 
+           
+               
+                <TextView 
+               style="@style/textLarge"
+           android:text="SUBJECT"   
+               />
+       
+            <TextView
+           android:id="@+id/record_details_simple_subject"
+               style="@style/textSmall"
+           />
+           
+           <TextView  
+               style="@style/textLarge"
+           android:text="SERIES"   
+               />
+           
+           <TextView
+           android:id="@+id/record_details_simple_series"
+               style="@style/textSmall"   
+           />
+               
+           <TextView  
+               style="@style/textLarge"
+           android:text="SYNOPSIS"   
+               />
+           
+           <TextView
+           android:id="@+id/record_details_simple_synopsis"
+               style="@style/textSmall"   
+               />
+               
+               <TextView  
+           xmlns:android="http://schemas.android.com/apk/res/android"
+           style="@style/sectionHeader"  
+           android:text="Other"
+               /> 
+               
+                           <TextView  
+               style="@style/textLarge"
+           android:text="ISBN"   
+               />
+           
+           <TextView
+           android:id="@+id/record_details_simple_isbn"
+               style="@style/textSmall"   
+               />
+               
+               
+       </LinearLayout>
+</ScrollView>
\ No newline at end of file
index 71f6c93..92fc9b7 100644 (file)
@@ -2,8 +2,8 @@
 <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"   
-        
-        >
+ android:id="@+id/record_details_simple_view">
 <LinearLayout 
     android:layout_width="fill_parent"
     android:layout_height="wrap_content"
diff --git a/Open-ILS/src/Android/res/layout/simple_tabs.xml b/Open-ILS/src/Android/res/layout/simple_tabs.xml
new file mode 100644 (file)
index 0000000..d729d59
--- /dev/null
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 Jake Wharton
+
+     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.
+-->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent">
+
+    <org.evergreen.android.utils.ui.TabPageIndicator
+        android:id="@+id/indicator"
+        android:layout_height="wrap_content"
+        android:layout_width="fill_parent"
+        />
+    <android.support.v4.view.ViewPager
+        android:id="@+id/pager"
+        android:layout_width="fill_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1"
+        />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/Open-ILS/src/Android/res/menu/menu.xml b/Open-ILS/src/Android/res/menu/menu.xml
new file mode 100644 (file)
index 0000000..3f3db59
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:id="@+id/random" android:title="Random" />
+    <item android:id="@+id/add_page" android:title="Add Page" />
+    <item android:id="@+id/remove_page" android:title="Remove Page" />
+</menu>
index 376cc04..62ba8d7 100644 (file)
@@ -26,7 +26,7 @@
         <item name="android:textSize">18sp</item>
         <item name="android:paddingLeft">10dip</item>
         <item name="android:paddingTop">5dip</item>
-        <item name="android:textColor">@color/white</item>
+
         <item name="android:layout_width">wrap_content</item>
         <item name="android:layout_height">wrap_content</item>
     </style>
         <item name="android:ellipsize">end</item> 
      </style>
      
+     
+     
+     <!--  Tabs  -->
+     
+      <style name="StyledIndicators" parent="@android:style/Theme.Light">
+        <item name="vpiCirclePageIndicatorStyle">@style/CustomCirclePageIndicator</item>
+        <item name="vpiLinePageIndicatorStyle">@style/CustomLinePageIndicator</item>
+        <item name="vpiTitlePageIndicatorStyle">@style/CustomTitlePageIndicator</item>
+        <item name="vpiTabPageIndicatorStyle">@style/CustomTabPageIndicator</item>
+        <item name="vpiUnderlinePageIndicatorStyle">@style/CustomUnderlinePageIndicator</item>
+    </style>
+
+    <style name="CustomTitlePageIndicator">
+        <item name="android:background">#18FF0000</item>
+        <item name="footerColor">#FFAA2222</item>
+        <item name="footerLineHeight">1dp</item>
+        <item name="footerIndicatorHeight">3dp</item>
+        <item name="footerIndicatorStyle">underline</item>
+        <item name="android:textColor">#AA000000</item>
+        <item name="selectedColor">#FF000000</item>
+        <item name="selectedBold">true</item>
+    </style>
+
+    <style name="CustomLinePageIndicator">
+        <item name="strokeWidth">4dp</item>
+        <item name="lineWidth">30dp</item>
+        <item name="unselectedColor">#FF888888</item>
+        <item name="selectedColor">#FF880000</item>
+    </style>
+
+    <style name="CustomCirclePageIndicator">
+        <item name="fillColor">#FF888888</item>
+        <item name="strokeColor">#FF000000</item>
+        <item name="strokeWidth">2dp</item>
+        <item name="radius">10dp</item>
+        <item name="centered">true</item>
+    </style>
+
+    <style name="CustomTabPageIndicator" parent="Widget.TabPageIndicator">
+        <item name="android:background">@drawable/custom_tab_indicator</item>
+        <item name="android:textColor">#FF555555</item>
+    </style>
+
+    <style name="CustomUnderlinePageIndicator">
+        <item name="selectedColor">#FFCC0000</item>
+        <item name="android:background">#FFCCCCCC</item>
+        <item name="fadeLength">1000</item>
+        <item name="fadeDelay">1000</item>
+    </style>
 </resources>
diff --git a/Open-ILS/src/Android/res/values/vpi__attrs.xml b/Open-ILS/src/Android/res/values/vpi__attrs.xml
new file mode 100644 (file)
index 0000000..8ff0893
--- /dev/null
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 Jake Wharton
+     Copyright (C) 2011 Patrik Ã…kerfeldt
+
+     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.
+-->
+
+<resources>
+    <declare-styleable name="ViewPagerIndicator">
+        <!-- Style of the circle indicator. -->
+        <attr name="vpiCirclePageIndicatorStyle" format="reference"/>
+        <!-- Style of the line indicator. -->
+        <attr name="vpiLinePageIndicatorStyle" format="reference"/>
+        <!-- Style of the title indicator. -->
+        <attr name="vpiTitlePageIndicatorStyle" format="reference"/>
+        <!-- Style of the tab indicator's tabs. -->
+        <attr name="vpiTabPageIndicatorStyle" format="reference"/>
+        <!-- Style of the underline indicator. -->
+        <attr name="vpiUnderlinePageIndicatorStyle" format="reference"/>
+    </declare-styleable>
+
+    <attr name="centered" format="boolean" />
+    <attr name="selectedColor" format="color" />
+    <attr name="strokeWidth" format="dimension" />
+    <attr name="unselectedColor" format="color" />
+
+    <declare-styleable name="CirclePageIndicator">
+        <!-- Whether or not the indicators should be centered. -->
+        <attr name="centered" />
+        <!-- Color of the filled circle that represents the current page. -->
+        <attr name="fillColor" format="color" />
+        <!-- Color of the filled circles that represents pages. -->
+        <attr name="pageColor" format="color" />
+        <!-- Orientation of the indicator. -->
+        <attr name="android:orientation"/>
+        <!-- Radius of the circles. This is also the spacing between circles. -->
+        <attr name="radius" format="dimension" />
+        <!-- Whether or not the selected indicator snaps to the circles. -->
+        <attr name="snap" format="boolean" />
+        <!-- Color of the open circles. -->
+        <attr name="strokeColor" format="color" />
+        <!-- Width of the stroke used to draw the circles. -->
+        <attr name="strokeWidth" />
+    </declare-styleable>
+
+    <declare-styleable name="LinePageIndicator">
+        <!-- Whether or not the indicators should be centered. -->
+        <attr name="centered" />
+        <!-- Color of the unselected lines that represent the pages. -->
+        <attr name="unselectedColor" />
+        <!-- Color of the selected line that represents the current page. -->
+        <attr name="selectedColor" />
+        <!-- Width of each indicator line. -->
+        <attr name="lineWidth" format="dimension" />
+        <!-- Width of each indicator line's stroke. -->
+        <attr name="strokeWidth" />
+        <!-- Width of the gap between each indicator line. -->
+        <attr name="gapWidth" format="dimension" />
+    </declare-styleable>
+
+    <declare-styleable name="TitlePageIndicator">
+        <!-- Screen edge padding. -->
+        <attr name="clipPadding" format="dimension" />
+        <!-- Color of the footer line and indicator. -->
+        <attr name="footerColor" format="color" />
+        <!-- Height of the footer line. -->
+        <attr name="footerLineHeight" format="dimension" />
+        <!-- Style of the indicator. Default is triangle. -->
+        <attr name="footerIndicatorStyle">
+            <enum name="none" value="0" />
+            <enum name="triangle" value="1" />
+            <enum name="underline" value="2" />
+        </attr>
+        <!-- Height of the indicator above the footer line. -->
+        <attr name="footerIndicatorHeight" format="dimension" />
+        <!-- Left and right padding of the underline indicator. -->
+        <attr name="footerIndicatorUnderlinePadding" format="dimension" />
+        <!-- Padding between the bottom of the title and the footer. -->
+        <attr name="footerPadding" format="dimension" />
+        <!-- Color of the selected title. -->
+        <attr name="selectedColor" />
+        <!-- Whether or not the selected item is displayed as bold. -->
+        <attr name="selectedBold" format="boolean" />
+        <!-- Color of regular titles. -->
+        <attr name="android:textColor" />
+        <!-- Size of title text. -->
+        <attr name="android:textSize" />
+        <!-- Padding between titles when bumping into each other. -->
+        <attr name="titlePadding" format="dimension" />
+        <!-- Padding between titles and the top of the View. -->
+        <attr name="topPadding" format="dimension" />
+    </declare-styleable>
+
+    <declare-styleable name="UnderlinePageIndicator">
+        <!-- Whether or not the selected indicator fades. -->
+        <attr name="fades" format="boolean" />
+        <!-- Length of the delay to fade the indicator. -->
+        <attr name="fadeDelay" format="integer" />
+        <!-- Length of the indicator fade to transparent. -->
+        <attr name="fadeLength" format="integer" />
+        <!-- Color of the selected line that represents the current page. -->
+        <attr name="selectedColor" />
+    </declare-styleable>
+</resources>
diff --git a/Open-ILS/src/Android/res/values/vpi__colors.xml b/Open-ILS/src/Android/res/values/vpi__colors.xml
new file mode 100644 (file)
index 0000000..62ca607
--- /dev/null
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 Jake Wharton
+
+     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.
+-->
+
+<resources>
+    <color name="vpi__background_holo_dark">#ff000000</color>
+    <color name="vpi__background_holo_light">#fff3f3f3</color>
+    <color name="vpi__bright_foreground_holo_dark">@color/vpi__background_holo_light</color>
+    <color name="vpi__bright_foreground_holo_light">@color/vpi__background_holo_dark</color>
+    <color name="vpi__bright_foreground_disabled_holo_dark">#ff4c4c4c</color>
+    <color name="vpi__bright_foreground_disabled_holo_light">#ffb2b2b2</color>
+    <color name="vpi__bright_foreground_inverse_holo_dark">@color/vpi__bright_foreground_holo_light</color>
+    <color name="vpi__bright_foreground_inverse_holo_light">@color/vpi__bright_foreground_holo_dark</color>
+</resources>
diff --git a/Open-ILS/src/Android/res/values/vpi__defaults.xml b/Open-ILS/src/Android/res/values/vpi__defaults.xml
new file mode 100644 (file)
index 0000000..245ae92
--- /dev/null
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 Jake Wharton
+
+     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.
+-->
+
+<resources>
+    <bool name="default_circle_indicator_centered">true</bool>
+    <color name="default_circle_indicator_fill_color">#FFFFFFFF</color>
+    <color name="default_circle_indicator_page_color">#00000000</color>
+    <integer name="default_circle_indicator_orientation">0</integer>
+    <dimen name="default_circle_indicator_radius">3dp</dimen>
+    <bool name="default_circle_indicator_snap">false</bool>
+    <color name="default_circle_indicator_stroke_color">#FFDDDDDD</color>
+    <dimen name="default_circle_indicator_stroke_width">1dp</dimen>
+
+    <dimen name="default_line_indicator_line_width">12dp</dimen>
+    <dimen name="default_line_indicator_gap_width">4dp</dimen>
+    <dimen name="default_line_indicator_stroke_width">1dp</dimen>
+    <color name="default_line_indicator_selected_color">#FF33B5E5</color>
+    <color name="default_line_indicator_unselected_color">#FFBBBBBB</color>
+    <bool name="default_line_indicator_centered">true</bool>
+
+    <dimen name="default_title_indicator_clip_padding">4dp</dimen>
+    <color name="default_title_indicator_footer_color">#FF33B5E5</color>
+    <dimen name="default_title_indicator_footer_line_height">2dp</dimen>
+    <integer name="default_title_indicator_footer_indicator_style">2</integer>
+    <dimen name="default_title_indicator_footer_indicator_height">4dp</dimen>
+    <dimen name="default_title_indicator_footer_indicator_underline_padding">20dp</dimen>
+    <dimen name="default_title_indicator_footer_padding">7dp</dimen>
+    <color name="default_title_indicator_selected_color">#FFFFFFFF</color>
+    <bool name="default_title_indicator_selected_bold">true</bool>
+    <color name="default_title_indicator_text_color">#BBFFFFFF</color>
+    <dimen name="default_title_indicator_text_size">15dp</dimen>
+    <dimen name="default_title_indicator_title_padding">5dp</dimen>
+    <dimen name="default_title_indicator_top_padding">7dp</dimen>
+
+    <bool name="default_underline_indicator_fades">true</bool>
+    <integer name="default_underline_indicator_fade_delay">300</integer>
+    <integer name="default_underline_indicator_fade_length">400</integer>
+    <color name="default_underline_indicator_selected_color">#FF33B5E5</color>
+</resources>
\ No newline at end of file
diff --git a/Open-ILS/src/Android/res/values/vpi__styles.xml b/Open-ILS/src/Android/res/values/vpi__styles.xml
new file mode 100644 (file)
index 0000000..c2d5d8c
--- /dev/null
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 Jake Wharton
+
+     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.
+-->
+
+<resources>
+    <style name="Theme.PageIndicatorDefaults" parent="android:Theme">
+        <item name="vpiTabPageIndicatorStyle">@style/Widget.TabPageIndicator</item>
+    </style>
+
+    <style name="Widget">
+    </style>
+
+    <style name="Widget.TabPageIndicator" parent="Widget">
+        <item name="android:gravity">center</item>
+        <item name="android:background">@drawable/vpi__tab_indicator</item>
+        <item name="android:paddingLeft">22dip</item>
+        <item name="android:paddingRight">22dip</item>
+        <item name="android:paddingTop">12dp</item>
+        <item name="android:paddingBottom">12dp</item>
+        <item name="android:textAppearance">@style/TextAppearance.TabPageIndicator</item>
+        <item name="android:textSize">12sp</item>
+        <item name="android:maxLines">1</item>
+    </style>
+
+    <style name="TextAppearance.TabPageIndicator" parent="Widget">
+        <item name="android:textStyle">bold</item>
+        <item name="android:textColor">@xml/vpi__dark_theme</item>
+    </style>
+</resources>
diff --git a/Open-ILS/src/Android/res/xml/vpi__dark_theme.xml b/Open-ILS/src/Android/res/xml/vpi__dark_theme.xml
new file mode 100644 (file)
index 0000000..3e7a08f
--- /dev/null
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_enabled="false" android:color="@color/vpi__bright_foreground_disabled_holo_dark"/>
+    <item android:state_window_focused="false" android:color="@color/vpi__bright_foreground_holo_dark"/>
+    <item android:state_pressed="true" android:color="@color/vpi__bright_foreground_holo_dark"/>
+    <item android:state_selected="true" android:color="@color/vpi__bright_foreground_holo_dark"/>
+    <!--item android:state_activated="true" android:color="@color/vpi__bright_foreground_holo_dark"/-->
+    <item android:color="@color/vpi__bright_foreground_holo_dark"/> <!-- not selected -->
+</selector>
diff --git a/Open-ILS/src/Android/res/xml/vpi__light_theme.xml b/Open-ILS/src/Android/res/xml/vpi__light_theme.xml
new file mode 100644 (file)
index 0000000..f955db7
--- /dev/null
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_enabled="false" android:color="@color/vpi__bright_foreground_disabled_holo_light"/>
+    <item android:state_window_focused="false" android:color="@color/vpi__bright_foreground_holo_light"/>
+    <item android:state_pressed="true" android:color="@color/vpi__bright_foreground_holo_light"/>
+    <item android:state_selected="true" android:color="@color/vpi__bright_foreground_holo_light"/>
+    <!--item android:state_activated="true" android:color="@color/vpi__bright_foreground_holo_light"/-->
+    <item android:color="@color/vpi__bright_foreground_holo_light"/> <!-- not selected -->
+    
+</selector>
+
index a1eb4b9..c2cee37 100644 (file)
@@ -1,47 +1,86 @@
 package org.evergreen.android.searchCatalog;
 
-import android.app.TabActivity;
-import android.content.Intent;
+import org.evergreen.android.R;
+import org.evergreen.android.utils.ui.RealViewSwitcher;
+
+import android.app.Activity;
+import android.graphics.Color;
 import android.os.Bundle;
-import android.widget.TabHost;
-import android.widget.TabHost.TabSpec;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.ScrollView;
+import android.widget.TextView;
 
-public class RecordDetails extends TabActivity{
+public class RecordDetails extends Activity{
 
        @Override
        protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
-               
-        TabHost tabHost = getTabHost();
-        
-        
-        RecordInfo record = (RecordInfo) getIntent().getSerializableExtra("recordInfo");
-        
-        // Tab for Photos
-        TabSpec photospec = tabHost.newTabSpec("Info");
-        // setting Title and Icon for the Tab
-        photospec.setIndicator("Info");
-        Intent photosIntent = new Intent(this, RecordDetails_Info.class);
-        photospec.setContent(photosIntent);
-        photosIntent.putExtra("recordInfo", record);
-        
-        // Tab for Songs
-        TabSpec songspec = tabHost.newTabSpec("Content");
-        songspec.setIndicator("Content");
-        Intent songsIntent = new Intent(this, RecordDetails_Content.class);
-        songspec.setContent(songsIntent);
-        songsIntent.putExtra("recordInfo", record);
-        // Tab for Videos
-        TabSpec videospec = tabHost.newTabSpec("Other");
-        videospec.setIndicator("Other");
-        Intent videosIntent = new Intent(this, RecordDetails_Details.class);
-        videospec.setContent(videosIntent);
-        videosIntent.putExtra("recordInfo",record);
-        // Adding all TabSpec to TabHost
-        tabHost.addTab(photospec); // Adding photos tab
-        tabHost.addTab(songspec); // Adding songs tab
-        tabHost.addTab(videospec); // Adding videos tab
+
+     // create the view switcher
+               RealViewSwitcher realViewSwitcher = new RealViewSwitcher(getApplicationContext());
+
+               // add some views to it
+               final int[] backgroundColors = { Color.RED, Color.BLUE, Color.CYAN, Color.GREEN, Color.YELLOW };
+               for (int i = 0; i < 5; i++) {
+                       
+                       
+                       
+                       TextView textView = new TextView(getApplicationContext());
+                       textView.setText(Integer.toString(i + 1));
+                       textView.setTextSize(100);
+                       textView.setTextColor(Color.BLACK);
+                       textView.setGravity(Gravity.CENTER);
+                       textView.setBackgroundColor(backgroundColors[i]);
+                       realViewSwitcher.addView(textView);
+               }
+
+               LayoutInflater factory = getLayoutInflater();
+
+               
+               LinearLayout layout = (LinearLayout) factory.inflate(R.layout.record_details_info, null);
+               
+               
+               ScrollView scroll = (ScrollView) factory.inflate(R.layout.record_details_simple, null);
+               
+               
+               System.out.println( layout + " scrol" + scroll);
+               
+               realViewSwitcher.addView(layout);
+               realViewSwitcher.addView(scroll);
+               
+               // set as content view
+               setContentView(realViewSwitcher);
+               
+               
+               
+               // yeah, it really is as simple as this :-)
+               
+               // note that you can also define your own views directly in a resource XML, too by using:
+               // <de.marcreichelt.android.RealViewSwitcher
+               //     android:layout_width="fill_parent"
+               //     android:layout_height="fill_parent"
+               //     android:id="@+id/real_view_switcher">
+               //         <!-- your views here -->
+               // </de.marcreichelt.android.RealViewSwitcher>
+               
+               
+               
+               // OPTIONAL: listen for screen changes
+               realViewSwitcher.setOnScreenSwitchListener(onScreenSwitchListener);
                
        }
+       private final RealViewSwitcher.OnScreenSwitchListener onScreenSwitchListener = new RealViewSwitcher.OnScreenSwitchListener() {
+               
+               @Override
+               public void onScreenSwitched(int screen) {
+                       // this method is executed if a screen has been activated, i.e. the screen is completely visible
+                       //  and the animation has stopped (might be useful for removing / adding new views)
+                       Log.d("RealViewSwitcher", "switched to screen: " + screen);
+               }
+               
+       };
 }
index ea490a3..3d613b4 100644 (file)
@@ -34,6 +34,23 @@ public class SearchCatalog {
        /** The METHO d_ sli m_ retrive. */
        public static String METHOD_SLIM_RETRIVE  = "open-ils.search.biblio.record.mods_slim.retrieve";
 
+       /** Method 
+        * @param : no parameters 
+        * @returns : returns array of ccs objects
+        */
+       
+       public static String METHOD_COPY_STATUS_ALL ="open-ils.search.config.copy_status.retrieve.all";
+       
+       /**
+       * Method that returns library where record with id is
+       * @param : record ID to get all libraries, or just book ID, Current Library ID, User ID
+       * @returns : [[["4","","CONCERTO 27","","Stacks",{"0":5}],["4","","PERFORM 27","","Stacks",{"0":2}]]]
+       *    "0":% is the available books
+       *  [org_id, call_number_sufix, copy_location, status1:count, status2:count ..]
+       */
+       public static String METHOD_COPY_LOCATION_COUNTS = "open-ils.search.biblio.copy_location_counts.summary.retrieve";
+
+       
        /** The conn. */
        public HttpConnection conn;
        
index 5ded2c3..42127c6 100644 (file)
@@ -176,7 +176,7 @@ public class SearchCatalogListView extends Activity{
                        else{
                                //start activity with book details
                                
-                               Intent intent = new Intent(getBaseContext(),RecordDetails_Simple.class);
+                               Intent intent = new Intent(getBaseContext(),TabsView.class);
                                //serialize object and pass it to next activity
                                intent.putExtra("recordInfo", info);
                                
diff --git a/Open-ILS/src/Android/src/org/evergreen/android/searchCatalog/TabsView.java b/Open-ILS/src/Android/src/org/evergreen/android/searchCatalog/TabsView.java
new file mode 100644 (file)
index 0000000..37f06f1
--- /dev/null
@@ -0,0 +1,68 @@
+package org.evergreen.android.searchCatalog;
+
+import org.evergreen.android.R;
+import org.evergreen.android.utils.ui.AdvancedDetailsFragment;
+import org.evergreen.android.utils.ui.BaseSampleActivity;
+import org.evergreen.android.utils.ui.BasicDetailsFragment;
+import org.evergreen.android.utils.ui.TabPageIndicator;
+import org.evergreen.android.utils.ui.TestFragment;
+import org.evergreen.android.utils.ui.TestFragmentAdapter;
+
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentManager;
+import android.support.v4.view.ViewPager;
+
+public class TabsView extends BaseSampleActivity {
+    private static final String[] CONTENT = new String[] { "Details", "Advanced"};
+
+    
+    private RecordInfo record;
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.simple_tabs);
+
+        record = (RecordInfo) getIntent().getSerializableExtra("recordInfo");
+               
+        
+        mAdapter = new SearchFragmentAdapter(getSupportFragmentManager());
+
+        
+        //mAdapter.getItem(0).
+        
+        mPager = (ViewPager)findViewById(R.id.pager);
+        mPager.setAdapter(mAdapter);
+
+        mIndicator = (TabPageIndicator)findViewById(R.id.indicator);
+        mIndicator.setViewPager(mPager);
+    }
+
+    class SearchFragmentAdapter extends TestFragmentAdapter {
+        public SearchFragmentAdapter(FragmentManager fm) {
+            super(fm);
+        }
+
+        @Override
+        public Fragment getItem(int position) {
+               
+               if(position == 1)
+                       return AdvancedDetailsFragment.newInstance(record);
+               if(position == 0)
+                       return BasicDetailsFragment.newInstance(record);
+               
+            return TestFragment.newInstance(TabsView.CONTENT[position % TabsView.CONTENT.length]);
+        }
+
+        @Override
+        public int getCount() {
+            return 2;
+               //return TabsView.CONTENT.length;
+        }
+
+        @Override
+        public CharSequence getPageTitle(int position) {
+            return TabsView.CONTENT[position % TabsView.CONTENT.length].toUpperCase();
+        }
+    }
+}
diff --git a/Open-ILS/src/Android/src/org/evergreen/android/utils/ui/AdvancedDetailsFragment.java b/Open-ILS/src/Android/src/org/evergreen/android/utils/ui/AdvancedDetailsFragment.java
new file mode 100644 (file)
index 0000000..1f26697
--- /dev/null
@@ -0,0 +1,69 @@
+package org.evergreen.android.utils.ui;
+
+import org.evergreen.android.R;
+import org.evergreen.android.searchCatalog.RecordInfo;
+
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+import android.widget.ScrollView;
+import android.widget.TextView;
+import android.widget.LinearLayout.LayoutParams;
+
+public class AdvancedDetailsFragment extends Fragment{
+
+       private RecordInfo record;
+       
+       private TextView seriesTextView;
+       private TextView subjectTextView;
+       private TextView synopsisTextView;
+       private TextView isbnTextView;
+       
+       
+       
+           public static AdvancedDetailsFragment newInstance(RecordInfo record) {
+               AdvancedDetailsFragment fragment = new AdvancedDetailsFragment(record);
+
+
+               return fragment;
+           }
+
+           public AdvancedDetailsFragment(RecordInfo record){
+               this.record = record;
+           }
+
+           @Override
+           public void onCreate(Bundle savedInstanceState) {
+               super.onCreate(savedInstanceState);
+
+           }
+
+           @Override
+           public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+           
+               ScrollView layout = (ScrollView) inflater.inflate(R.layout.record_details_more_fragment, null);
+
+                       seriesTextView = (TextView) layout.findViewById(R.id.record_details_simple_series);
+                       subjectTextView = (TextView) layout.findViewById(R.id.record_details_simple_subject);
+                       synopsisTextView = (TextView) layout.findViewById(R.id.record_details_simple_synopsis);
+                       isbnTextView = (TextView) layout.findViewById(R.id.record_details_simple_isbn);
+                       
+               
+                       seriesTextView.setText(record.series);
+                       subjectTextView.setText(record.subject);
+                       synopsisTextView.setText(record.synopsis);
+                       
+                       isbnTextView.setText(record.isbn);
+                       
+               return layout;
+           }
+
+           @Override
+           public void onSaveInstanceState(Bundle outState) {
+               super.onSaveInstanceState(outState);
+           }
+}
diff --git a/Open-ILS/src/Android/src/org/evergreen/android/utils/ui/BaseSampleActivity.java b/Open-ILS/src/Android/src/org/evergreen/android/utils/ui/BaseSampleActivity.java
new file mode 100644 (file)
index 0000000..92c304b
--- /dev/null
@@ -0,0 +1,53 @@
+
+package org.evergreen.android.utils.ui;
+
+
+import java.util.Random;
+
+import org.evergreen.android.R;
+
+import android.support.v4.app.FragmentActivity;
+import android.support.v4.view.ViewPager;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.widget.Toast;
+
+public abstract class BaseSampleActivity extends FragmentActivity {
+    private static final Random RANDOM = new Random();
+
+    public TestFragmentAdapter mAdapter;
+    public ViewPager mPager;
+    public PageIndicator mIndicator;
+
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        getMenuInflater().inflate(R.menu.menu, menu);
+        return true;
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        switch (item.getItemId()) {
+            case R.id.random:
+                final int page = RANDOM.nextInt(mAdapter.getCount());
+                Toast.makeText(this, "Changing to page " + page, Toast.LENGTH_SHORT);
+                mPager.setCurrentItem(page);
+                return true;
+
+            case R.id.add_page:
+                if (mAdapter.getCount() < 10) {
+                    mAdapter.setCount(mAdapter.getCount() + 1);
+                    mIndicator.notifyDataSetChanged();
+                }
+                return true;
+
+            case R.id.remove_page:
+                if (mAdapter.getCount() > 1) {
+                    mAdapter.setCount(mAdapter.getCount() - 1);
+                    mIndicator.notifyDataSetChanged();
+                }
+                return true;
+        }
+        return super.onOptionsItemSelected(item);
+    }
+}
diff --git a/Open-ILS/src/Android/src/org/evergreen/android/utils/ui/BasicDetailsFragment.java b/Open-ILS/src/Android/src/org/evergreen/android/utils/ui/BasicDetailsFragment.java
new file mode 100644 (file)
index 0000000..a954425
--- /dev/null
@@ -0,0 +1,65 @@
+package org.evergreen.android.utils.ui;
+
+import org.evergreen.android.R;
+import org.evergreen.android.searchCatalog.RecordInfo;
+
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+import android.widget.ScrollView;
+import android.widget.TextView;
+import android.widget.LinearLayout.LayoutParams;
+
+public class BasicDetailsFragment extends Fragment{
+
+       
+       private RecordInfo record;
+       
+       private TextView titleTextView;
+       private TextView authorTextView;
+       private TextView publisherTextView;
+       
+           public static BasicDetailsFragment newInstance(RecordInfo record) {
+               BasicDetailsFragment fragment = new BasicDetailsFragment(record);
+               
+               return fragment;
+           }
+
+           public BasicDetailsFragment(RecordInfo record){
+               
+               this.record = record;
+           }
+
+           @Override
+           public void onCreate(Bundle savedInstanceState) {
+               super.onCreate(savedInstanceState);
+
+           }
+
+           @Override
+           public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+           
+               ScrollView layout = (ScrollView) inflater.inflate(R.layout.record_details_basic_fragment, null);
+
+               titleTextView = (TextView) layout.findViewById(R.id.record_details_simple_title);
+                       authorTextView = (TextView) layout.findViewById(R.id.record_details_simple_author);
+                       publisherTextView = (TextView) layout.findViewById(R.id.record_details_simple_publisher);
+               
+                       
+                       titleTextView.setText(record.title);
+                       authorTextView.setText(record.author);
+                       publisherTextView.setText(record.pubdate + " " + record.publisher);
+                       
+               
+               return layout;
+           }
+
+           @Override
+           public void onSaveInstanceState(Bundle outState) {
+               super.onSaveInstanceState(outState);
+           }
+}
diff --git a/Open-ILS/src/Android/src/org/evergreen/android/utils/ui/PageIndicator.java b/Open-ILS/src/Android/src/org/evergreen/android/utils/ui/PageIndicator.java
new file mode 100644 (file)
index 0000000..2622564
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2011 Patrik Akerfeldt
+ * Copyright (C) 2011 Jake Wharton
+ *
+ * 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 org.evergreen.android.utils.ui;
+
+
+import android.support.v4.view.ViewPager;
+
+/**
+ * A PageIndicator is responsible to show an visual indicator on the total views
+ * number and the current visible view.
+ */
+public interface PageIndicator extends ViewPager.OnPageChangeListener {
+    /**
+     * Bind the indicator to a ViewPager.
+     *
+     * @param view
+     */
+    void setViewPager(ViewPager view);
+
+    /**
+     * Bind the indicator to a ViewPager.
+     *
+     * @param view
+     * @param initialPosition
+     */
+    void setViewPager(ViewPager view, int initialPosition);
+
+    /**
+     * <p>Set the current page of both the ViewPager and indicator.</p>
+     *
+     * <p>This <strong>must</strong> be used if you need to set the page before
+     * the views are drawn on screen (e.g., default start page).</p>
+     *
+     * @param item
+     */
+    void setCurrentItem(int item);
+
+    /**
+     * Set a page change listener which will receive forwarded events.
+     *
+     * @param listener
+     */
+    void setOnPageChangeListener(ViewPager.OnPageChangeListener listener);
+
+    /**
+     * Notify the indicator that the fragment list has changed.
+     */
+    void notifyDataSetChanged();
+}
diff --git a/Open-ILS/src/Android/src/org/evergreen/android/utils/ui/RealViewSwitcher.java b/Open-ILS/src/Android/src/org/evergreen/android/utils/ui/RealViewSwitcher.java
new file mode 100644 (file)
index 0000000..16f5e52
--- /dev/null
@@ -0,0 +1,294 @@
+/*
+ * Copyright (C) 2010 Marc Reichelt
+ * 
+ * Work derived from Workspace.java of the Launcher application
+ *  see http://android.git.kernel.org/?p=platform/packages/apps/Launcher.git
+ *
+ * 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 org.evergreen.android.utils.ui;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.VelocityTracker;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.ViewGroup;
+import android.widget.Scroller;
+
+/**
+ * RealViewSwitcher allows users to switch between multiple screens (layouts) in the same way as the Android home screen (Launcher application).
+ * <p>
+ * You can add and remove views using the normal methods {@link ViewGroup#addView(View)}, {@link ViewGroup#removeView(View)} etc. You may want to listen for updates by calling {@link RealViewSwitcher#setOnScreenSwitchListener(OnScreenSwitchListener)}
+ * in order to perform operations once a new screen has been selected.
+ * 
+ * @author Marc Reichelt, <a href="http://www.marcreichelt.de/">http://www.marcreichelt.de/</a>
+ * @version 0.1.0
+ */
+public class RealViewSwitcher extends ViewGroup {
+
+       // TODO: This class does the basic stuff right now, but it would be cool to have certain things implemented,
+       // e.g. using an adapter for getting views instead of setting them directly, memory management and the
+       // possibility of scrolling vertically instead of horizontally. If you have ideas or patches, please visit
+       // my website and drop me a mail. :-)
+
+       /**
+        * Listener for the event that the RealViewSwitcher switches to a new view.
+        */
+       public static interface OnScreenSwitchListener {
+
+               /**
+                * Notifies listeners about the new screen. Runs after the animation completed.
+                * 
+                * @param screen The new screen index.
+                */
+               void onScreenSwitched(int screen);
+
+       }
+
+       private static final int SNAP_VELOCITY = 1000;
+       private static final int INVALID_SCREEN = -1;
+
+       private Scroller mScroller;
+       private VelocityTracker mVelocityTracker;
+
+       private final static int TOUCH_STATE_REST = 0;
+       private final static int TOUCH_STATE_SCROLLING = 1;
+
+       private int mTouchState = TOUCH_STATE_REST;
+
+       private float mLastMotionX;
+       private int mTouchSlop;
+       private int mMaximumVelocity;
+       private int mCurrentScreen;
+       private int mNextScreen = INVALID_SCREEN;
+
+       private boolean mFirstLayout = true;
+
+       private OnScreenSwitchListener mOnScreenSwitchListener;
+
+       public RealViewSwitcher(Context context) {
+               super(context);
+               init();
+       }
+
+       public RealViewSwitcher(Context context, AttributeSet attrs) {
+               super(context, attrs);
+               init();
+       }
+
+       private void init() {
+               mScroller = new Scroller(getContext());
+
+               final ViewConfiguration configuration = ViewConfiguration.get(getContext());
+               mTouchSlop = configuration.getScaledTouchSlop();
+               mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
+       }
+
+       @Override
+       protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+               super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+
+               final int width = MeasureSpec.getSize(widthMeasureSpec);
+               final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
+               if (widthMode != MeasureSpec.EXACTLY) {
+                       throw new IllegalStateException("ViewSwitcher can only be used in EXACTLY mode.");
+               }
+
+               final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
+               if (heightMode != MeasureSpec.EXACTLY) {
+                       throw new IllegalStateException("ViewSwitcher can only be used in EXACTLY mode.");
+               }
+
+               // The children are given the same width and height as the workspace
+               final int count = getChildCount();
+               for (int i = 0; i < count; i++) {
+                       getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec);
+               }
+
+               if (mFirstLayout) {
+                       scrollTo(mCurrentScreen * width, 0);
+                       mFirstLayout = false;
+               }
+       }
+
+       @Override
+       protected void onLayout(boolean changed, int l, int t, int r, int b) {
+               int childLeft = 0;
+
+               final int count = getChildCount();
+               for (int i = 0; i < count; i++) {
+                       final View child = getChildAt(i);
+                       if (child.getVisibility() != View.GONE) {
+                               final int childWidth = child.getMeasuredWidth();
+                               child.layout(childLeft, 0, childLeft + childWidth, child.getMeasuredHeight());
+                               childLeft += childWidth;
+                       }
+               }
+       }
+
+       @Override
+       public boolean onTouchEvent(MotionEvent ev) {
+               if (mVelocityTracker == null) {
+                       mVelocityTracker = VelocityTracker.obtain();
+               }
+               mVelocityTracker.addMovement(ev);
+
+               final int action = ev.getAction();
+               final float x = ev.getX();
+
+               switch (action) {
+               case MotionEvent.ACTION_DOWN:
+                       /*
+                        * If being flinged and user touches, stop the fling. isFinished will be false if being flinged.
+                        */
+                       if (!mScroller.isFinished()) {
+                               mScroller.abortAnimation();
+                       }
+
+                       // Remember where the motion event started
+                       mLastMotionX = x;
+
+                       mTouchState = mScroller.isFinished() ? TOUCH_STATE_REST : TOUCH_STATE_SCROLLING;
+
+                       break;
+
+               case MotionEvent.ACTION_MOVE:
+                       final int xDiff = (int) Math.abs(x - mLastMotionX);
+
+                       boolean xMoved = xDiff > mTouchSlop;
+
+                       if (xMoved) {
+                               // Scroll if the user moved far enough along the X axis
+                               mTouchState = TOUCH_STATE_SCROLLING;
+                       }
+
+                       if (mTouchState == TOUCH_STATE_SCROLLING) {
+                               // Scroll to follow the motion event
+                               final int deltaX = (int) (mLastMotionX - x);
+                               mLastMotionX = x;
+
+                               final int scrollX = getScrollX();
+                               if (deltaX < 0) {
+                                       if (scrollX > 0) {
+                                               scrollBy(Math.max(-scrollX, deltaX), 0);
+                                       }
+                               } else if (deltaX > 0) {
+                                       final int availableToScroll = getChildAt(getChildCount() - 1).getRight() - scrollX - getWidth();
+                                       if (availableToScroll > 0) {
+                                               scrollBy(Math.min(availableToScroll, deltaX), 0);
+                                       }
+                               }
+                       }
+                       break;
+
+               case MotionEvent.ACTION_UP:
+                       if (mTouchState == TOUCH_STATE_SCROLLING) {
+                               final VelocityTracker velocityTracker = mVelocityTracker;
+                               velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
+                               int velocityX = (int) velocityTracker.getXVelocity();
+
+                               if (velocityX > SNAP_VELOCITY && mCurrentScreen > 0) {
+                                       // Fling hard enough to move left
+                                       snapToScreen(mCurrentScreen - 1);
+                               } else if (velocityX < -SNAP_VELOCITY && mCurrentScreen < getChildCount() - 1) {
+                                       // Fling hard enough to move right
+                                       snapToScreen(mCurrentScreen + 1);
+                               } else {
+                                       snapToDestination();
+                               }
+
+                               if (mVelocityTracker != null) {
+                                       mVelocityTracker.recycle();
+                                       mVelocityTracker = null;
+                               }
+                       }
+
+                       mTouchState = TOUCH_STATE_REST;
+
+                       break;
+               case MotionEvent.ACTION_CANCEL:
+                       mTouchState = TOUCH_STATE_REST;
+               }
+
+               return true;
+       }
+
+       private void snapToDestination() {
+               final int screenWidth = getWidth();
+               final int whichScreen = (getScrollX() + (screenWidth / 2)) / screenWidth;
+
+               snapToScreen(whichScreen);
+       }
+
+       private void snapToScreen(int whichScreen) {
+               if (!mScroller.isFinished())
+                       return;
+
+               whichScreen = Math.max(0, Math.min(whichScreen, getChildCount() - 1));
+
+               mNextScreen = whichScreen;
+
+               final int newX = whichScreen * getWidth();
+               final int delta = newX - getScrollX();
+               mScroller.startScroll(getScrollX(), 0, delta, 0, Math.abs(delta) * 2);
+               invalidate();
+       }
+
+       @Override
+       public void computeScroll() {
+               if (mScroller.computeScrollOffset()) {
+                       scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
+                       postInvalidate();
+               } else if (mNextScreen != INVALID_SCREEN) {
+                       mCurrentScreen = Math.max(0, Math.min(mNextScreen, getChildCount() - 1));
+
+                       // notify observer about screen change
+                       if (mOnScreenSwitchListener != null)
+                               mOnScreenSwitchListener.onScreenSwitched(mCurrentScreen);
+
+                       mNextScreen = INVALID_SCREEN;
+               }
+       }
+
+       /**
+        * Returns the index of the currently displayed screen.
+        * 
+        * @return The index of the currently displayed screen.
+        */
+       public int getCurrentScreen() {
+               return mCurrentScreen;
+       }
+
+       /**
+        * Sets the current screen.
+        * 
+        * @param currentScreen The new screen.
+        */
+       public void setCurrentScreen(int currentScreen) {
+               mCurrentScreen = Math.max(0, Math.min(currentScreen, getChildCount() - 1));
+               scrollTo(mCurrentScreen * getWidth(), 0);
+               invalidate();
+       }
+
+       /**
+        * Sets the {@link ViewSwitcher.OnScreenSwitchListener}.
+        * 
+        * @param onScreenSwitchListener The listener for switch events.
+        */
+       public void setOnScreenSwitchListener(OnScreenSwitchListener onScreenSwitchListener) {
+               mOnScreenSwitchListener = onScreenSwitchListener;
+       }
+
+}
diff --git a/Open-ILS/src/Android/src/org/evergreen/android/utils/ui/TabPageIndicator.java b/Open-ILS/src/Android/src/org/evergreen/android/utils/ui/TabPageIndicator.java
new file mode 100644 (file)
index 0000000..a6dcc18
--- /dev/null
@@ -0,0 +1,273 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ * Copyright (C) 2011 Jake Wharton
+ *
+ * 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 org.evergreen.android.utils.ui;
+
+import static android.view.ViewGroup.LayoutParams.FILL_PARENT;
+import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
+
+import org.evergreen.android.R;
+
+import android.content.Context;
+import android.support.v4.view.PagerAdapter;
+import android.support.v4.view.ViewPager;
+import android.support.v4.view.ViewPager.OnPageChangeListener;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.HorizontalScrollView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+/**
+ * This widget implements the dynamic action bar tab behavior that can change
+ * across different configurations or circumstances.
+ */
+public class TabPageIndicator extends HorizontalScrollView implements PageIndicator {
+    /** Title text used when no title is provided by the adapter. */
+    private static final CharSequence EMPTY_TITLE = "";
+
+    /**
+     * Interface for a callback when the selected tab has been reselected.
+     */
+    public interface OnTabReselectedListener {
+        /**
+         * Callback when the selected tab has been reselected.
+         *
+         * @param position Position of the current center item.
+         */
+        void onTabReselected(int position);
+    }
+
+    private Runnable mTabSelector;
+
+    private final OnClickListener mTabClickListener = new OnClickListener() {
+        public void onClick(View view) {
+            TabView tabView = (TabView)view;
+            final int oldSelected = mViewPager.getCurrentItem();
+            final int newSelected = tabView.getIndex();
+            mViewPager.setCurrentItem(newSelected);
+            if (oldSelected == newSelected && mTabReselectedListener != null) {
+                mTabReselectedListener.onTabReselected(newSelected);
+            }
+        }
+    };
+
+    private final LinearLayout mTabLayout;
+    private ViewPager mViewPager;
+    private ViewPager.OnPageChangeListener mListener;
+
+    private int mMaxTabWidth;
+    private int mSelectedTabIndex;
+
+    private OnTabReselectedListener mTabReselectedListener;
+
+    public TabPageIndicator(Context context) {
+        this(context, null);
+    }
+
+    public TabPageIndicator(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        setHorizontalScrollBarEnabled(false);
+
+        mTabLayout = new LinearLayout(getContext());
+        addView(mTabLayout, new ViewGroup.LayoutParams(WRAP_CONTENT, FILL_PARENT));
+    }
+
+    public void setOnTabReselectedListener(OnTabReselectedListener listener) {
+        mTabReselectedListener = listener;
+    }
+
+    @Override
+    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
+        final boolean lockedExpanded = widthMode == MeasureSpec.EXACTLY;
+        setFillViewport(lockedExpanded);
+
+        final int childCount = mTabLayout.getChildCount();
+        if (childCount > 1 && (widthMode == MeasureSpec.EXACTLY || widthMode == MeasureSpec.AT_MOST)) {
+            if (childCount > 2) {
+                mMaxTabWidth = (int)(MeasureSpec.getSize(widthMeasureSpec) * 0.4f);
+            } else {
+                mMaxTabWidth = MeasureSpec.getSize(widthMeasureSpec) / 2;
+            }
+        } else {
+            mMaxTabWidth = -1;
+        }
+
+        final int oldWidth = getMeasuredWidth();
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+        final int newWidth = getMeasuredWidth();
+
+        if (lockedExpanded && oldWidth != newWidth) {
+            // Recenter the tab display if we're at a new (scrollable) size.
+            setCurrentItem(mSelectedTabIndex);
+        }
+    }
+
+    private void animateToTab(final int position) {
+        final View tabView = mTabLayout.getChildAt(position);
+        if (mTabSelector != null) {
+            removeCallbacks(mTabSelector);
+        }
+        mTabSelector = new Runnable() {
+            public void run() {
+                final int scrollPos = tabView.getLeft() - (getWidth() - tabView.getWidth()) / 2;
+                smoothScrollTo(scrollPos, 0);
+                mTabSelector = null;
+            }
+        };
+        post(mTabSelector);
+    }
+
+    @Override
+    public void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        if (mTabSelector != null) {
+            // Re-post the selector we saved
+            post(mTabSelector);
+        }
+    }
+
+    @Override
+    public void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        if (mTabSelector != null) {
+            removeCallbacks(mTabSelector);
+        }
+    }
+
+    private void addTab(CharSequence text, int index) {
+        final TabView tabView = new TabView(getContext());
+        tabView.mIndex = index;
+        tabView.setFocusable(true);
+        tabView.setOnClickListener(mTabClickListener);
+        tabView.setText(text);
+
+        mTabLayout.addView(tabView, new LinearLayout.LayoutParams(0, FILL_PARENT, 1));
+    }
+
+    @Override
+    public void onPageScrollStateChanged(int arg0) {
+        if (mListener != null) {
+            mListener.onPageScrollStateChanged(arg0);
+        }
+    }
+
+    @Override
+    public void onPageScrolled(int arg0, float arg1, int arg2) {
+        if (mListener != null) {
+            mListener.onPageScrolled(arg0, arg1, arg2);
+        }
+    }
+
+    @Override
+    public void onPageSelected(int arg0) {
+        setCurrentItem(arg0);
+        if (mListener != null) {
+            mListener.onPageSelected(arg0);
+        }
+    }
+
+    @Override
+    public void setViewPager(ViewPager view) {
+        if (mViewPager == view) {
+            return;
+        }
+        if (mViewPager != null) {
+            mViewPager.setOnPageChangeListener(null);
+        }
+        final PagerAdapter adapter = view.getAdapter();
+        if (adapter == null) {
+            throw new IllegalStateException("ViewPager does not have adapter instance.");
+        }
+        mViewPager = view;
+        view.setOnPageChangeListener(this);
+        notifyDataSetChanged();
+    }
+
+    public void notifyDataSetChanged() {
+        mTabLayout.removeAllViews();
+        PagerAdapter adapter = mViewPager.getAdapter();
+        final int count = adapter.getCount();
+        for (int i = 0; i < count; i++) {
+            CharSequence title = adapter.getPageTitle(i);
+            if (title == null) {
+                title = EMPTY_TITLE;
+            }
+            addTab(title, i);
+        }
+        if (mSelectedTabIndex > count) {
+            mSelectedTabIndex = count - 1;
+        }
+        setCurrentItem(mSelectedTabIndex);
+        requestLayout();
+    }
+
+    @Override
+    public void setViewPager(ViewPager view, int initialPosition) {
+        setViewPager(view);
+        setCurrentItem(initialPosition);
+    }
+
+    @Override
+    public void setCurrentItem(int item) {
+        if (mViewPager == null) {
+            throw new IllegalStateException("ViewPager has not been bound.");
+        }
+        mSelectedTabIndex = item;
+        mViewPager.setCurrentItem(item);
+
+        final int tabCount = mTabLayout.getChildCount();
+        for (int i = 0; i < tabCount; i++) {
+            final View child = mTabLayout.getChildAt(i);
+            final boolean isSelected = (i == item);
+            child.setSelected(isSelected);
+            if (isSelected) {
+                animateToTab(item);
+            }
+        }
+    }
+
+    @Override
+    public void setOnPageChangeListener(OnPageChangeListener listener) {
+        mListener = listener;
+    }
+
+    private class TabView extends TextView {
+        private int mIndex;
+
+        public TabView(Context context) {
+            super(context, null, R.attr.vpiTabPageIndicatorStyle);
+        }
+
+        @Override
+        public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+
+            // Re-measure if we went beyond our maximum size.
+            if (mMaxTabWidth > 0 && getMeasuredWidth() > mMaxTabWidth) {
+                super.onMeasure(MeasureSpec.makeMeasureSpec(mMaxTabWidth, MeasureSpec.EXACTLY),
+                        heightMeasureSpec);
+            }
+        }
+
+        public int getIndex() {
+            return mIndex;
+        }
+    }
+}
diff --git a/Open-ILS/src/Android/src/org/evergreen/android/utils/ui/TestFragment.java b/Open-ILS/src/Android/src/org/evergreen/android/utils/ui/TestFragment.java
new file mode 100644 (file)
index 0000000..f5d4f0a
--- /dev/null
@@ -0,0 +1,61 @@
+package org.evergreen.android.utils.ui;\r
+\r
+import android.os.Bundle;\r
+import android.support.v4.app.Fragment;\r
+import android.view.Gravity;\r
+import android.view.LayoutInflater;\r
+import android.view.View;\r
+import android.view.ViewGroup;\r
+import android.widget.LinearLayout;\r
+import android.widget.LinearLayout.LayoutParams;\r
+import android.widget.TextView;\r
+\r
+public final class TestFragment extends Fragment {\r
+    private static final String KEY_CONTENT = "TestFragment:Content";\r
+\r
+    public static TestFragment newInstance(String content) {\r
+        TestFragment fragment = new TestFragment();\r
+\r
+        StringBuilder builder = new StringBuilder();\r
+        for (int i = 0; i < 20; i++) {\r
+            builder.append(content).append(" ");\r
+        }\r
+        builder.deleteCharAt(builder.length() - 1);\r
+        fragment.mContent = builder.toString();\r
+\r
+        return fragment;\r
+    }\r
+\r
+    private String mContent = "???";\r
+\r
+    @Override\r
+    public void onCreate(Bundle savedInstanceState) {\r
+        super.onCreate(savedInstanceState);\r
+\r
+        if ((savedInstanceState != null) && savedInstanceState.containsKey(KEY_CONTENT)) {\r
+            mContent = savedInstanceState.getString(KEY_CONTENT);\r
+        }\r
+    }\r
+\r
+    @Override\r
+    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {\r
+        TextView text = new TextView(getActivity());\r
+        text.setGravity(Gravity.CENTER);\r
+        text.setText(mContent);\r
+        text.setTextSize(20 * getResources().getDisplayMetrics().density);\r
+        text.setPadding(20, 20, 20, 20);\r
+\r
+        LinearLayout layout = new LinearLayout(getActivity());\r
+        layout.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));\r
+        layout.setGravity(Gravity.CENTER);\r
+        layout.addView(text);\r
+\r
+        return layout;\r
+    }\r
+\r
+    @Override\r
+    public void onSaveInstanceState(Bundle outState) {\r
+        super.onSaveInstanceState(outState);\r
+        outState.putString(KEY_CONTENT, mContent);\r
+    }\r
+}\r
diff --git a/Open-ILS/src/Android/src/org/evergreen/android/utils/ui/TestFragmentAdapter.java b/Open-ILS/src/Android/src/org/evergreen/android/utils/ui/TestFragmentAdapter.java
new file mode 100644 (file)
index 0000000..c898752
--- /dev/null
@@ -0,0 +1,32 @@
+package org.evergreen.android.utils.ui;\r
+\r
+import android.support.v4.app.Fragment;\r
+import android.support.v4.app.FragmentManager;\r
+import android.support.v4.app.FragmentPagerAdapter;\r
+\r
+public class TestFragmentAdapter extends FragmentPagerAdapter {\r
+    protected static final String[] CONTENT = new String[] { "This", "Is", "A", "Test", };\r
+\r
+    private int mCount = CONTENT.length;\r
+\r
+    public TestFragmentAdapter(FragmentManager fm) {\r
+        super(fm);\r
+    }\r
+\r
+    @Override\r
+    public Fragment getItem(int position) {\r
+        return TestFragment.newInstance(CONTENT[position % CONTENT.length]);\r
+    }\r
+\r
+    @Override\r
+    public int getCount() {\r
+        return mCount;\r
+    }\r
+\r
+    public void setCount(int count) {\r
+        if (count > 0 && count <= 10) {\r
+            mCount = count;\r
+            notifyDataSetChanged();\r
+        }\r
+    }\r
+}
\ No newline at end of file
diff --git a/Open-ILS/src/Android/src/org/evergreen/android/utils/ui/TitlePageIndicator.java b/Open-ILS/src/Android/src/org/evergreen/android/utils/ui/TitlePageIndicator.java
new file mode 100644 (file)
index 0000000..5a0f7f6
--- /dev/null
@@ -0,0 +1,808 @@
+/*
+ * Copyright (C) 2011 Jake Wharton
+ * Copyright (C) 2011 Patrik Akerfeldt
+ * Copyright (C) 2011 Francisco Figueiredo Jr.
+ *
+ * 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 org.evergreen.android.utils.ui;
+
+import java.util.ArrayList;
+
+import org.evergreen.android.R;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.Rect;
+import android.graphics.Typeface;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.support.v4.view.MotionEventCompat;
+import android.support.v4.view.PagerAdapter;
+import android.support.v4.view.ViewConfigurationCompat;
+import android.support.v4.view.ViewPager;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewConfiguration;
+
+/**
+ * A TitlePageIndicator is a PageIndicator which displays the title of left view
+ * (if exist), the title of the current select view (centered) and the title of
+ * the right view (if exist). When the user scrolls the ViewPager then titles are
+ * also scrolled.
+ */
+public class TitlePageIndicator extends View implements PageIndicator {
+    /**
+     * Percentage indicating what percentage of the screen width away from
+     * center should the underline be fully faded. A value of 0.25 means that
+     * halfway between the center of the screen and an edge.
+     */
+    private static final float SELECTION_FADE_PERCENTAGE = 0.25f;
+
+    /**
+     * Percentage indicating what percentage of the screen width away from
+     * center should the selected text bold turn off. A value of 0.05 means
+     * that 10% between the center and an edge.
+     */
+    private static final float BOLD_FADE_PERCENTAGE = 0.05f;
+
+    /**
+     * Title text used when no title is provided by the adapter.
+     */
+    private static final String EMPTY_TITLE = "";
+
+    /**
+     * Interface for a callback when the center item has been clicked.
+     */
+    public interface OnCenterItemClickListener {
+        /**
+         * Callback when the center item has been clicked.
+         *
+         * @param position Position of the current center item.
+         */
+        void onCenterItemClick(int position);
+    }
+
+    public enum IndicatorStyle {
+        None(0), Triangle(1), Underline(2);
+
+        public final int value;
+
+        private IndicatorStyle(int value) {
+            this.value = value;
+        }
+
+        public static IndicatorStyle fromValue(int value) {
+            for (IndicatorStyle style : IndicatorStyle.values()) {
+                if (style.value == value) {
+                    return style;
+                }
+            }
+            return null;
+        }
+    }
+
+    private ViewPager mViewPager;
+    private ViewPager.OnPageChangeListener mListener;
+    private PagerAdapter mPagerAdapter;
+    private int mCurrentPage = -1;
+    private float mPageOffset;
+    private int mScrollState;
+    private final Paint mPaintText = new Paint();
+    private boolean mBoldText;
+    private int mColorText;
+    private int mColorSelected;
+    private Path mPath = new Path();
+    private final Rect mBounds = new Rect();
+    private final Paint mPaintFooterLine = new Paint();
+    private IndicatorStyle mFooterIndicatorStyle;
+    private final Paint mPaintFooterIndicator = new Paint();
+    private float mFooterIndicatorHeight;
+    private float mFooterIndicatorUnderlinePadding;
+    private float mFooterPadding;
+    private float mTitlePadding;
+    private float mTopPadding;
+    /** Left and right side padding for not active view titles. */
+    private float mClipPadding;
+    private float mFooterLineHeight;
+
+    private static final int INVALID_POINTER = -1;
+
+    private int mTouchSlop;
+    private float mLastMotionX = -1;
+    private int mActivePointerId = INVALID_POINTER;
+    private boolean mIsDragging;
+
+    private OnCenterItemClickListener mCenterItemClickListener;
+
+
+    public TitlePageIndicator(Context context) {
+        this(context, null);
+    }
+
+    public TitlePageIndicator(Context context, AttributeSet attrs) {
+        this(context, attrs, R.attr.vpiTitlePageIndicatorStyle);
+    }
+
+    public TitlePageIndicator(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        if (isInEditMode()) return;
+
+        //Load defaults from resources
+        final Resources res = getResources();
+        final int defaultFooterColor = res.getColor(R.color.default_title_indicator_footer_color);
+        final float defaultFooterLineHeight = res.getDimension(R.dimen.default_title_indicator_footer_line_height);
+        final int defaultFooterIndicatorStyle = res.getInteger(R.integer.default_title_indicator_footer_indicator_style);
+        final float defaultFooterIndicatorHeight = res.getDimension(R.dimen.default_title_indicator_footer_indicator_height);
+        final float defaultFooterIndicatorUnderlinePadding = res.getDimension(R.dimen.default_title_indicator_footer_indicator_underline_padding);
+        final float defaultFooterPadding = res.getDimension(R.dimen.default_title_indicator_footer_padding);
+        final int defaultSelectedColor = res.getColor(R.color.default_title_indicator_selected_color);
+        final boolean defaultSelectedBold = res.getBoolean(R.bool.default_title_indicator_selected_bold);
+        final int defaultTextColor = res.getColor(R.color.default_title_indicator_text_color);
+        final float defaultTextSize = res.getDimension(R.dimen.default_title_indicator_text_size);
+        final float defaultTitlePadding = res.getDimension(R.dimen.default_title_indicator_title_padding);
+        final float defaultClipPadding = res.getDimension(R.dimen.default_title_indicator_clip_padding);
+        final float defaultTopPadding = res.getDimension(R.dimen.default_title_indicator_top_padding);
+
+        //Retrieve styles attributes
+        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TitlePageIndicator, defStyle, 0);
+
+        //Retrieve the colors to be used for this view and apply them.
+        mFooterLineHeight = a.getDimension(R.styleable.TitlePageIndicator_footerLineHeight, defaultFooterLineHeight);
+        mFooterIndicatorStyle = IndicatorStyle.fromValue(a.getInteger(R.styleable.TitlePageIndicator_footerIndicatorStyle, defaultFooterIndicatorStyle));
+        mFooterIndicatorHeight = a.getDimension(R.styleable.TitlePageIndicator_footerIndicatorHeight, defaultFooterIndicatorHeight);
+        mFooterIndicatorUnderlinePadding = a.getDimension(R.styleable.TitlePageIndicator_footerIndicatorUnderlinePadding, defaultFooterIndicatorUnderlinePadding);
+        mFooterPadding = a.getDimension(R.styleable.TitlePageIndicator_footerPadding, defaultFooterPadding);
+        mTopPadding = a.getDimension(R.styleable.TitlePageIndicator_topPadding, defaultTopPadding);
+        mTitlePadding = a.getDimension(R.styleable.TitlePageIndicator_titlePadding, defaultTitlePadding);
+        mClipPadding = a.getDimension(R.styleable.TitlePageIndicator_clipPadding, defaultClipPadding);
+        mColorSelected = a.getColor(R.styleable.TitlePageIndicator_selectedColor, defaultSelectedColor);
+        mColorText = a.getColor(R.styleable.TitlePageIndicator_android_textColor, defaultTextColor);
+        mBoldText = a.getBoolean(R.styleable.TitlePageIndicator_selectedBold, defaultSelectedBold);
+
+        final float textSize = a.getDimension(R.styleable.TitlePageIndicator_android_textSize, defaultTextSize);
+        final int footerColor = a.getColor(R.styleable.TitlePageIndicator_footerColor, defaultFooterColor);
+        mPaintText.setTextSize(textSize);
+        mPaintText.setAntiAlias(true);
+        mPaintFooterLine.setStyle(Paint.Style.FILL_AND_STROKE);
+        mPaintFooterLine.setStrokeWidth(mFooterLineHeight);
+        mPaintFooterLine.setColor(footerColor);
+        mPaintFooterIndicator.setStyle(Paint.Style.FILL_AND_STROKE);
+        mPaintFooterIndicator.setColor(footerColor);
+
+        a.recycle();
+
+        final ViewConfiguration configuration = ViewConfiguration.get(context);
+        mTouchSlop = ViewConfigurationCompat.getScaledPagingTouchSlop(configuration);
+    }
+
+
+    public int getFooterColor() {
+        return mPaintFooterLine.getColor();
+    }
+
+    public void setFooterColor(int footerColor) {
+        mPaintFooterLine.setColor(footerColor);
+        mPaintFooterIndicator.setColor(footerColor);
+        invalidate();
+    }
+
+    public float getFooterLineHeight() {
+        return mFooterLineHeight;
+    }
+
+    public void setFooterLineHeight(float footerLineHeight) {
+        mFooterLineHeight = footerLineHeight;
+        mPaintFooterLine.setStrokeWidth(mFooterLineHeight);
+        invalidate();
+    }
+
+    public float getFooterIndicatorHeight() {
+        return mFooterIndicatorHeight;
+    }
+
+    public void setFooterIndicatorHeight(float footerTriangleHeight) {
+        mFooterIndicatorHeight = footerTriangleHeight;
+        invalidate();
+    }
+
+    public float getFooterIndicatorPadding() {
+        return mFooterPadding;
+    }
+
+    public void setFooterIndicatorPadding(float footerIndicatorPadding) {
+        mFooterPadding = footerIndicatorPadding;
+        invalidate();
+    }
+
+    public IndicatorStyle getFooterIndicatorStyle() {
+        return mFooterIndicatorStyle;
+    }
+
+    public void setFooterIndicatorStyle(IndicatorStyle indicatorStyle) {
+        mFooterIndicatorStyle = indicatorStyle;
+        invalidate();
+    }
+
+    public int getSelectedColor() {
+        return mColorSelected;
+    }
+
+    public void setSelectedColor(int selectedColor) {
+        mColorSelected = selectedColor;
+        invalidate();
+    }
+
+    public boolean isSelectedBold() {
+        return mBoldText;
+    }
+
+    public void setSelectedBold(boolean selectedBold) {
+        mBoldText = selectedBold;
+        invalidate();
+    }
+
+    public int getTextColor() {
+        return mColorText;
+    }
+
+    public void setTextColor(int textColor) {
+        mPaintText.setColor(textColor);
+        mColorText = textColor;
+        invalidate();
+    }
+
+    public float getTextSize() {
+        return mPaintText.getTextSize();
+    }
+
+    public void setTextSize(float textSize) {
+        mPaintText.setTextSize(textSize);
+        invalidate();
+    }
+
+    public float getTitlePadding() {
+        return this.mTitlePadding;
+    }
+
+    public void setTitlePadding(float titlePadding) {
+        mTitlePadding = titlePadding;
+        invalidate();
+    }
+
+    public float getTopPadding() {
+        return this.mTopPadding;
+    }
+
+    public void setTopPadding(float topPadding) {
+        mTopPadding = topPadding;
+        invalidate();
+    }
+
+    public float getClipPadding() {
+        return this.mClipPadding;
+    }
+
+    public void setClipPadding(float clipPadding) {
+        mClipPadding = clipPadding;
+        invalidate();
+    }
+
+    public void setTypeface(Typeface typeface) {
+        mPaintText.setTypeface(typeface);
+        invalidate();
+    }
+
+    public Typeface getTypeface() {
+        return mPaintText.getTypeface();
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see android.view.View#onDraw(android.graphics.Canvas)
+     */
+    @Override
+    protected void onDraw(Canvas canvas) {
+        super.onDraw(canvas);
+
+        if (mViewPager == null) {
+            return;
+        }
+        final int count = mViewPager.getAdapter().getCount();
+        if (count == 0) {
+            return;
+        }
+
+        // mCurrentPage is -1 on first start and after orientation changed. If so, retrieve the correct index from viewpager.
+        if(mCurrentPage == -1 && mViewPager != null) mCurrentPage = mViewPager.getCurrentItem();
+
+        //Calculate views bounds
+        ArrayList<Rect> bounds = calculateAllBounds(mPaintText);
+        final int boundsSize = bounds.size();
+
+        //Make sure we're on a page that still exists
+        if (mCurrentPage >= boundsSize) {
+            setCurrentItem(boundsSize - 1);
+            return;
+        }
+
+        final int countMinusOne = count - 1;
+        final float halfWidth = getWidth() / 2f;
+        final int left = getLeft();
+        final float leftClip = left + mClipPadding;
+        final int width = getWidth();
+        final int height = getHeight();
+        final int right = left + width;
+        final float rightClip = right - mClipPadding;
+
+        int page = mCurrentPage;
+        float offsetPercent;
+        if (mPageOffset <= 0.5) {
+            offsetPercent = mPageOffset;
+        } else {
+            page += 1;
+            offsetPercent = 1 - mPageOffset;
+        }
+        final boolean currentSelected = (offsetPercent <= SELECTION_FADE_PERCENTAGE);
+        final boolean currentBold = (offsetPercent <= BOLD_FADE_PERCENTAGE);
+        final float selectedPercent = (SELECTION_FADE_PERCENTAGE - offsetPercent) / SELECTION_FADE_PERCENTAGE;
+
+        //Verify if the current view must be clipped to the screen
+        Rect curPageBound = bounds.get(mCurrentPage);
+        float curPageWidth = curPageBound.right - curPageBound.left;
+        if (curPageBound.left < leftClip) {
+            //Try to clip to the screen (left side)
+            clipViewOnTheLeft(curPageBound, curPageWidth, left);
+        }
+        if (curPageBound.right > rightClip) {
+            //Try to clip to the screen (right side)
+            clipViewOnTheRight(curPageBound, curPageWidth, right);
+        }
+
+        //Left views starting from the current position
+        if (mCurrentPage > 0) {
+            for (int i = mCurrentPage - 1; i >= 0; i--) {
+                Rect bound = bounds.get(i);
+                //Is left side is outside the screen
+                if (bound.left < leftClip) {
+                    int w = bound.right - bound.left;
+                    //Try to clip to the screen (left side)
+                    clipViewOnTheLeft(bound, w, left);
+                    //Except if there's an intersection with the right view
+                    Rect rightBound = bounds.get(i + 1);
+                    //Intersection
+                    if (bound.right + mTitlePadding > rightBound.left) {
+                        bound.left = (int) (rightBound.left - w - mTitlePadding);
+                        bound.right = bound.left + w;
+                    }
+                }
+            }
+        }
+        //Right views starting from the current position
+        if (mCurrentPage < countMinusOne) {
+            for (int i = mCurrentPage + 1 ; i < count; i++) {
+                Rect bound = bounds.get(i);
+                //If right side is outside the screen
+                if (bound.right > rightClip) {
+                    int w = bound.right - bound.left;
+                    //Try to clip to the screen (right side)
+                    clipViewOnTheRight(bound, w, right);
+                    //Except if there's an intersection with the left view
+                    Rect leftBound = bounds.get(i - 1);
+                    //Intersection
+                    if (bound.left - mTitlePadding < leftBound.right) {
+                        bound.left = (int) (leftBound.right + mTitlePadding);
+                        bound.right = bound.left + w;
+                    }
+                }
+            }
+        }
+
+        //Now draw views
+        int colorTextAlpha = mColorText >>> 24;
+        for (int i = 0; i < count; i++) {
+            //Get the title
+            Rect bound = bounds.get(i);
+            //Only if one side is visible
+            if ((bound.left > left && bound.left < right) || (bound.right > left && bound.right < right)) {
+                final boolean currentPage = (i == page);
+                final CharSequence pageTitle = getTitle(i);
+
+                //Only set bold if we are within bounds
+                mPaintText.setFakeBoldText(currentPage && currentBold && mBoldText);
+
+                //Draw text as unselected
+                mPaintText.setColor(mColorText);
+                if(currentPage && currentSelected) {
+                    //Fade out/in unselected text as the selected text fades in/out
+                    mPaintText.setAlpha(colorTextAlpha - (int)(colorTextAlpha * selectedPercent));
+                }
+                canvas.drawText(pageTitle, 0, pageTitle.length(), bound.left, bound.bottom + mTopPadding, mPaintText);
+
+                //If we are within the selected bounds draw the selected text
+                if (currentPage && currentSelected) {
+                    mPaintText.setColor(mColorSelected);
+                    mPaintText.setAlpha((int)((mColorSelected >>> 24) * selectedPercent));
+                    canvas.drawText(pageTitle, 0, pageTitle.length(), bound.left, bound.bottom + mTopPadding, mPaintText);
+                }
+            }
+        }
+
+        //Draw the footer line
+        mPath.reset();
+        mPath.moveTo(0, height - mFooterLineHeight / 2f);
+        mPath.lineTo(width, height - mFooterLineHeight / 2f);
+        mPath.close();
+        canvas.drawPath(mPath, mPaintFooterLine);
+
+        switch (mFooterIndicatorStyle) {
+            case Triangle:
+                mPath.reset();
+                mPath.moveTo(halfWidth, height - mFooterLineHeight - mFooterIndicatorHeight);
+                mPath.lineTo(halfWidth + mFooterIndicatorHeight, height - mFooterLineHeight);
+                mPath.lineTo(halfWidth - mFooterIndicatorHeight, height - mFooterLineHeight);
+                mPath.close();
+                canvas.drawPath(mPath, mPaintFooterIndicator);
+                break;
+
+            case Underline:
+                if (!currentSelected || page >= boundsSize) {
+                    break;
+                }
+
+                Rect underlineBounds = bounds.get(page);
+                mPath.reset();
+                mPath.moveTo(underlineBounds.left  - mFooterIndicatorUnderlinePadding, height - mFooterLineHeight);
+                mPath.lineTo(underlineBounds.right + mFooterIndicatorUnderlinePadding, height - mFooterLineHeight);
+                mPath.lineTo(underlineBounds.right + mFooterIndicatorUnderlinePadding, height - mFooterLineHeight - mFooterIndicatorHeight);
+                mPath.lineTo(underlineBounds.left  - mFooterIndicatorUnderlinePadding, height - mFooterLineHeight - mFooterIndicatorHeight);
+                mPath.close();
+
+                mPaintFooterIndicator.setAlpha((int)(0xFF * selectedPercent));
+                canvas.drawPath(mPath, mPaintFooterIndicator);
+                mPaintFooterIndicator.setAlpha(0xFF);
+                break;
+        }
+    }
+
+    public boolean onTouchEvent(android.view.MotionEvent ev) {
+        if (super.onTouchEvent(ev)) {
+            return true;
+        }
+        if ((mViewPager == null) || (mViewPager.getAdapter().getCount() == 0)) {
+            return false;
+        }
+
+        final int action = ev.getAction();
+
+        switch (action & MotionEventCompat.ACTION_MASK) {
+            case MotionEvent.ACTION_DOWN:
+                mActivePointerId = MotionEventCompat.getPointerId(ev, 0);
+                mLastMotionX = ev.getX();
+                break;
+
+            case MotionEvent.ACTION_MOVE: {
+                final int activePointerIndex = MotionEventCompat.findPointerIndex(ev, mActivePointerId);
+                final float x = MotionEventCompat.getX(ev, activePointerIndex);
+                final float deltaX = x - mLastMotionX;
+
+                if (!mIsDragging) {
+                    if (Math.abs(deltaX) > mTouchSlop) {
+                        mIsDragging = true;
+                    }
+                }
+
+                if (mIsDragging) {
+                    mLastMotionX = x;
+                    if (mViewPager.isFakeDragging() || mViewPager.beginFakeDrag()) {
+                        mViewPager.fakeDragBy(deltaX);
+                    }
+                }
+
+                break;
+            }
+
+            case MotionEvent.ACTION_CANCEL:
+            case MotionEvent.ACTION_UP:
+                if (!mIsDragging) {
+                    final int count = mViewPager.getAdapter().getCount();
+                    final int width = getWidth();
+                    final float halfWidth = width / 2f;
+                    final float sixthWidth = width / 6f;
+                    final float leftThird = halfWidth - sixthWidth;
+                    final float rightThird = halfWidth + sixthWidth;
+                    final float eventX = ev.getX();
+
+                    if (eventX < leftThird) {
+                        if (mCurrentPage > 0) {
+                            mViewPager.setCurrentItem(mCurrentPage - 1);
+                            return true;
+                        }
+                    } else if (eventX > rightThird) {
+                        if (mCurrentPage < count - 1) {
+                            mViewPager.setCurrentItem(mCurrentPage + 1);
+                            return true;
+                        }
+                    } else {
+                        //Middle third
+                        if (mCenterItemClickListener != null) {
+                            mCenterItemClickListener.onCenterItemClick(mCurrentPage);
+                        }
+                    }
+                }
+
+                mIsDragging = false;
+                mActivePointerId = INVALID_POINTER;
+                if (mViewPager.isFakeDragging()) mViewPager.endFakeDrag();
+                break;
+
+            case MotionEventCompat.ACTION_POINTER_DOWN: {
+                final int index = MotionEventCompat.getActionIndex(ev);
+                final float x = MotionEventCompat.getX(ev, index);
+                mLastMotionX = x;
+                mActivePointerId = MotionEventCompat.getPointerId(ev, index);
+                break;
+            }
+
+            case MotionEventCompat.ACTION_POINTER_UP:
+                final int pointerIndex = MotionEventCompat.getActionIndex(ev);
+                final int pointerId = MotionEventCompat.getPointerId(ev, pointerIndex);
+                if (pointerId == mActivePointerId) {
+                    final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
+                    mActivePointerId = MotionEventCompat.getPointerId(ev, newPointerIndex);
+                }
+                mLastMotionX = MotionEventCompat.getX(ev, MotionEventCompat.findPointerIndex(ev, mActivePointerId));
+                break;
+        }
+
+        return true;
+    };
+
+    /**
+     * Set bounds for the right textView including clip padding.
+     *
+     * @param curViewBound
+     *            current bounds.
+     * @param curViewWidth
+     *            width of the view.
+     */
+    private void clipViewOnTheRight(Rect curViewBound, float curViewWidth, int right) {
+        curViewBound.right = (int) (right - mClipPadding);
+        curViewBound.left = (int) (curViewBound.right - curViewWidth);
+    }
+
+    /**
+     * Set bounds for the left textView including clip padding.
+     *
+     * @param curViewBound
+     *            current bounds.
+     * @param curViewWidth
+     *            width of the view.
+     */
+    private void clipViewOnTheLeft(Rect curViewBound, float curViewWidth, int left) {
+        curViewBound.left = (int) (left + mClipPadding);
+        curViewBound.right = (int) (mClipPadding + curViewWidth);
+    }
+
+    /**
+     * Calculate views bounds and scroll them according to the current index
+     *
+     * @param paint
+     * @return
+     */
+    private ArrayList<Rect> calculateAllBounds(Paint paint) {
+        ArrayList<Rect> list = new ArrayList<Rect>();
+        //For each views (If no values then add a fake one)
+        final int count = mViewPager.getAdapter().getCount();
+        final int width = getWidth();
+        final int halfWidth = width / 2;
+        for (int i = 0; i < count; i++) {
+            Rect bounds = calcBounds(i, paint);
+            int w = bounds.right - bounds.left;
+            int h = bounds.bottom - bounds.top;
+            bounds.left = (int)(halfWidth - (w / 2f) + ((i - mCurrentPage - mPageOffset) * width));
+            bounds.right = bounds.left + w;
+            bounds.top = 0;
+            bounds.bottom = h;
+            list.add(bounds);
+        }
+
+        return list;
+    }
+
+    /**
+     * Calculate the bounds for a view's title
+     *
+     * @param index
+     * @param paint
+     * @return
+     */
+    private Rect calcBounds(int index, Paint paint) {
+        //Calculate the text bounds
+        Rect bounds = new Rect();
+        CharSequence title = getTitle(index);
+        bounds.right = (int) paint.measureText(title, 0, title.length());
+        bounds.bottom = (int) (paint.descent() - paint.ascent());
+        return bounds;
+    }
+
+    @Override
+    public void setViewPager(ViewPager view) {
+        if (mViewPager == view) {
+            return;
+        }
+        if (mViewPager != null) {
+            mViewPager.setOnPageChangeListener(null);
+        }
+        mPagerAdapter = view.getAdapter();
+        if (mPagerAdapter == null) {
+            throw new IllegalStateException("ViewPager does not have adapter instance.");
+        }
+        mViewPager = view;
+        mViewPager.setOnPageChangeListener(this);
+        invalidate();
+    }
+
+    @Override
+    public void setViewPager(ViewPager view, int initialPosition) {
+        setViewPager(view);
+        setCurrentItem(initialPosition);
+    }
+
+    @Override
+    public void notifyDataSetChanged() {
+        invalidate();
+    }
+
+    /**
+     * Set a callback listener for the center item click.
+     *
+     * @param listener Callback instance.
+     */
+    public void setOnCenterItemClickListener(OnCenterItemClickListener listener) {
+        mCenterItemClickListener = listener;
+    }
+
+    @Override
+    public void setCurrentItem(int item) {
+        if (mViewPager == null) {
+            throw new IllegalStateException("ViewPager has not been bound.");
+        }
+        mViewPager.setCurrentItem(item);
+        mCurrentPage = item;
+        invalidate();
+    }
+
+    @Override
+    public void onPageScrollStateChanged(int state) {
+        mScrollState = state;
+
+        if (mListener != null) {
+            mListener.onPageScrollStateChanged(state);
+        }
+    }
+
+    @Override
+    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
+        mCurrentPage = position;
+        mPageOffset = positionOffset;
+        invalidate();
+
+        if (mListener != null) {
+            mListener.onPageScrolled(position, positionOffset, positionOffsetPixels);
+        }
+    }
+
+    @Override
+    public void onPageSelected(int position) {
+        if (mScrollState == ViewPager.SCROLL_STATE_IDLE) {
+            mCurrentPage = position;
+            invalidate();
+        }
+
+        if (mListener != null) {
+            mListener.onPageSelected(position);
+        }
+    }
+
+    @Override
+    public void setOnPageChangeListener(ViewPager.OnPageChangeListener listener) {
+        mListener = listener;
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        //Measure our width in whatever mode specified
+        final int measuredWidth = MeasureSpec.getSize(widthMeasureSpec);
+
+        //Determine our height
+        float height = 0;
+        final int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
+        if (heightSpecMode == MeasureSpec.EXACTLY) {
+            //We were told how big to be
+            height = MeasureSpec.getSize(heightMeasureSpec);
+        } else {
+            //Calculate the text bounds
+            mBounds.setEmpty();
+            mBounds.bottom = (int) (mPaintText.descent() - mPaintText.ascent());
+            height = mBounds.bottom - mBounds.top + mFooterLineHeight + mFooterPadding + mTopPadding;
+            if (mFooterIndicatorStyle != IndicatorStyle.None) {
+                height += mFooterIndicatorHeight;
+            }
+        }
+        final int measuredHeight = (int)height;
+
+        setMeasuredDimension(measuredWidth, measuredHeight);
+    }
+
+    @Override
+    public void onRestoreInstanceState(Parcelable state) {
+        SavedState savedState = (SavedState)state;
+        super.onRestoreInstanceState(savedState.getSuperState());
+        mCurrentPage = savedState.currentPage;
+        requestLayout();
+    }
+
+    @Override
+    public Parcelable onSaveInstanceState() {
+        Parcelable superState = super.onSaveInstanceState();
+        SavedState savedState = new SavedState(superState);
+        savedState.currentPage = mCurrentPage;
+        return savedState;
+    }
+
+    static class SavedState extends BaseSavedState {
+        int currentPage;
+
+        public SavedState(Parcelable superState) {
+            super(superState);
+        }
+
+        private SavedState(Parcel in) {
+            super(in);
+            currentPage = in.readInt();
+        }
+
+        @Override
+        public void writeToParcel(Parcel dest, int flags) {
+            super.writeToParcel(dest, flags);
+            dest.writeInt(currentPage);
+        }
+
+        public static final Parcelable.Creator<SavedState> CREATOR = new Parcelable.Creator<SavedState>() {
+            @Override
+            public SavedState createFromParcel(Parcel in) {
+                return new SavedState(in);
+            }
+
+            @Override
+            public SavedState[] newArray(int size) {
+                return new SavedState[size];
+            }
+        };
+    }
+
+    private CharSequence getTitle(int i) {
+        CharSequence title = mPagerAdapter.getPageTitle(i);
+        if (title == null) {
+            title = EMPTY_TITLE;
+        }
+        return title.toString();
+    }
+}