diff options
author | Dominik Schürmann <dominik@dominikschuermann.de> | 2012-12-12 13:58:22 +0100 |
---|---|---|
committer | Dominik Schürmann <dominik@dominikschuermann.de> | 2012-12-12 13:58:22 +0100 |
commit | e3fea30abe9f9f16dbfa5e989e7058842b085b7e (patch) | |
tree | 06c5bdcb4e8d18d315115a8a0fc414a1d0d64ccc /APG/android-libs | |
parent | a4ea3e65a7feb9175e206b4aa93662bf51457072 (diff) | |
download | open-keychain-e3fea30abe9f9f16dbfa5e989e7058842b085b7e.tar.gz open-keychain-e3fea30abe9f9f16dbfa5e989e7058842b085b7e.tar.bz2 open-keychain-e3fea30abe9f9f16dbfa5e989e7058842b085b7e.zip |
Update ActionBarSherlock
Diffstat (limited to 'APG/android-libs')
113 files changed, 3797 insertions, 209 deletions
diff --git a/APG/android-libs/ActionBarSherlock/AndroidManifest.xml b/APG/android-libs/ActionBarSherlock/AndroidManifest.xml index c4a75f32c..7b8a84824 100644 --- a/APG/android-libs/ActionBarSherlock/AndroidManifest.xml +++ b/APG/android-libs/ActionBarSherlock/AndroidManifest.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> -<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="90" android:versionName="4.1.0" package="com.actionbarsherlock"> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="100" android:versionName="4.2.0" package="com.actionbarsherlock"> - <uses-sdk android:minSdkVersion="7" android:targetSdkVersion="15"/> + <uses-sdk android:minSdkVersion="7" android:targetSdkVersion="16"/> </manifest> diff --git a/APG/android-libs/ActionBarSherlock/build.xml b/APG/android-libs/ActionBarSherlock/build.xml index 3948e7c6a..56bc65293 100644 --- a/APG/android-libs/ActionBarSherlock/build.xml +++ b/APG/android-libs/ActionBarSherlock/build.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<project name="com_actionbarsherlock" default="help"> +<project name="ActionBarSherlock" default="help"> <!-- The local.properties file is created and updated by the 'android' tool. It contains the path to the SDK. It should *NOT* be checked into @@ -28,6 +28,15 @@ --> <property file="ant.properties" /> + <!-- if sdk.dir was not set from one of the property file, then + get it from the ANDROID_HOME env var. + This must be done before we load project.properties since + the proguard config can use sdk.dir --> + <property environment="env" /> + <condition property="sdk.dir" value="${env.ANDROID_HOME}"> + <isset property="env.ANDROID_HOME" /> + </condition> + <!-- The project.properties file is created and updated by the 'android' tool, as well as ADT. @@ -41,25 +50,23 @@ <!-- quick check on sdk.dir --> <fail - message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through an env var" + message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable." unless="sdk.dir" /> - -<!-- extension targets. Uncomment the ones where you want to do custom work - in between standard targets --> -<!-- - <target name="-pre-build"> - </target> - <target name="-pre-compile"> - </target> - - /* This is typically used for code obfuscation. - Compiled code location: ${out.classes.absolute.dir} - If this is not done in place, override ${out.dex.input.absolute.dir} */ - <target name="-post-compile"> - </target> ---> + <!-- + Import per project custom build rules if present at the root of the project. + This is the place to put custom intermediary targets such as: + -pre-build + -pre-compile + -post-compile (This is typically used for code obfuscation. + Compiled code location: ${out.classes.absolute.dir} + If this is not done in place, override ${out.dex.input.absolute.dir}) + -post-package + -post-build + -pre-clean + --> + <import file="custom_rules.xml" optional="true" /> <!-- Import the actual build file. diff --git a/APG/android-libs/ActionBarSherlock/libs/android-support-v4.jar b/APG/android-libs/ActionBarSherlock/libs/android-support-v4.jar Binary files differindex feaf44f80..99e063b33 100644 --- a/APG/android-libs/ActionBarSherlock/libs/android-support-v4.jar +++ b/APG/android-libs/ActionBarSherlock/libs/android-support-v4.jar diff --git a/APG/android-libs/ActionBarSherlock/pom.xml b/APG/android-libs/ActionBarSherlock/pom.xml index 5373fb012..3b6ce40ce 100644 --- a/APG/android-libs/ActionBarSherlock/pom.xml +++ b/APG/android-libs/ActionBarSherlock/pom.xml @@ -3,15 +3,14 @@ <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> - <groupId>com.actionbarsherlock</groupId> - <artifactId>library</artifactId> + <artifactId>actionbarsherlock</artifactId> <name>ActionBarSherlock</name> <packaging>apklib</packaging> <parent> <groupId>com.actionbarsherlock</groupId> <artifactId>parent</artifactId> - <version>4.1.0</version> + <version>4.2.0</version> <relativePath>../pom.xml</relativePath> </parent> @@ -27,11 +26,6 @@ </dependency> <dependency> - <groupId>com.pivotallabs</groupId> - <artifactId>robolectric</artifactId> - <scope>test</scope> - </dependency> - <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <scope>test</scope> @@ -47,6 +41,9 @@ <groupId>com.jayway.maven.plugins.android.generation2</groupId> <artifactId>android-maven-plugin</artifactId> <extensions>true</extensions> + <configuration> + <nativeLibrariesDirectory>ignored</nativeLibrariesDirectory> + </configuration> </plugin> <plugin> @@ -132,7 +129,7 @@ <pluginExecutionFilter> <groupId>com.google.code.maven-replacer-plugin</groupId> <artifactId>maven-replacer-plugin</artifactId> - <versionRange>[1.4.1,)</versionRange> + <versionRange>[1.4.0,)</versionRange> <goals> <goal>replace</goal> </goals> diff --git a/APG/android-libs/ActionBarSherlock/proguard-project.txt b/APG/android-libs/ActionBarSherlock/proguard-project.txt new file mode 100644 index 000000000..f2fe1559a --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/proguard-project.txt @@ -0,0 +1,20 @@ +# To enable ProGuard in your project, edit project.properties +# to define the proguard.config property as described in that file. +# +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in ${sdk.dir}/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the ProGuard +# include property in project.properties. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# Add any project specific keep options here: + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} diff --git a/APG/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_share_pack_holo_dark.9.png b/APG/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_share_pack_holo_dark.9.png Binary files differindex 6c1415772..81b87b86c 100644 --- a/APG/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_share_pack_holo_dark.9.png +++ b/APG/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_share_pack_holo_dark.9.png diff --git a/APG/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_share_pack_holo_light.9.png b/APG/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_share_pack_holo_light.9.png Binary files differindex f4ff16be7..8fc83e22e 100644 --- a/APG/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_share_pack_holo_light.9.png +++ b/APG/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_share_pack_holo_light.9.png diff --git a/APG/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_clear_disabled.png b/APG/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_clear_disabled.png Binary files differnew file mode 100644 index 000000000..d97c342d5 --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_clear_disabled.png diff --git a/APG/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_clear_normal.png b/APG/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_clear_normal.png Binary files differnew file mode 100644 index 000000000..33ad8d4b8 --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_clear_normal.png diff --git a/APG/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_clear_search_api_disabled_holo_light.png b/APG/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_clear_search_api_disabled_holo_light.png Binary files differnew file mode 100644 index 000000000..3edbd7408 --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_clear_search_api_disabled_holo_light.png diff --git a/APG/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_clear_search_api_holo_light.png b/APG/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_clear_search_api_holo_light.png Binary files differnew file mode 100644 index 000000000..90db01b5b --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_clear_search_api_holo_light.png diff --git a/APG/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_go.png b/APG/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_go.png Binary files differnew file mode 100644 index 000000000..97b825e83 --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_go.png diff --git a/APG/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_go_search_api_holo_light.png b/APG/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_go_search_api_holo_light.png Binary files differnew file mode 100644 index 000000000..7e1ba2adc --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_go_search_api_holo_light.png diff --git a/APG/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_search.png b/APG/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_search.png Binary files differnew file mode 100644 index 000000000..4be72f108 --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_search.png diff --git a/APG/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_search_api_holo_light.png b/APG/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_search_api_holo_light.png Binary files differnew file mode 100644 index 000000000..72e207bc5 --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_search_api_holo_light.png diff --git a/APG/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_voice_search.png b/APG/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_voice_search.png Binary files differnew file mode 100644 index 000000000..66d14aec0 --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_voice_search.png diff --git a/APG/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_voice_search_api_holo_light.png b/APG/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_voice_search_api_holo_light.png Binary files differnew file mode 100644 index 000000000..3481c9828 --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_voice_search_api_holo_light.png diff --git a/APG/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_default_holo_dark.9.png b/APG/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_default_holo_dark.9.png Binary files differnew file mode 100644 index 000000000..70c0e7396 --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_default_holo_dark.9.png diff --git a/APG/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_default_holo_light.9.png b/APG/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_default_holo_light.9.png Binary files differnew file mode 100644 index 000000000..36e71d85d --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_default_holo_light.9.png diff --git a/APG/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_right_default_holo_dark.9.png b/APG/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_right_default_holo_dark.9.png Binary files differnew file mode 100644 index 000000000..4be4af5fa --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_right_default_holo_dark.9.png diff --git a/APG/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_right_default_holo_light.9.png b/APG/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_right_default_holo_light.9.png Binary files differnew file mode 100644 index 000000000..e72193f59 --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_right_default_holo_light.9.png diff --git a/APG/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_right_selected_holo_dark.9.png b/APG/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_right_selected_holo_dark.9.png Binary files differnew file mode 100644 index 000000000..8f20b9d26 --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_right_selected_holo_dark.9.png diff --git a/APG/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_right_selected_holo_light.9.png b/APG/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_right_selected_holo_light.9.png Binary files differnew file mode 100644 index 000000000..04f657e1d --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_right_selected_holo_light.9.png diff --git a/APG/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_selected_holo_dark.9.png b/APG/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_selected_holo_dark.9.png Binary files differnew file mode 100644 index 000000000..99309ef6d --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_selected_holo_dark.9.png diff --git a/APG/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_selected_holo_light.9.png b/APG/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_selected_holo_light.9.png Binary files differnew file mode 100644 index 000000000..9bde7fbdc --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_selected_holo_light.9.png diff --git a/APG/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_share_pack_holo_dark.9.png b/APG/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_share_pack_holo_dark.9.png Binary files differindex ed4ba34ec..738cb38d0 100644 --- a/APG/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_share_pack_holo_dark.9.png +++ b/APG/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_share_pack_holo_dark.9.png diff --git a/APG/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_share_pack_holo_light.9.png b/APG/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_share_pack_holo_light.9.png Binary files differindex 8f10bd522..2ed75a767 100644 --- a/APG/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_share_pack_holo_light.9.png +++ b/APG/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_share_pack_holo_light.9.png diff --git a/APG/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_clear_disabled.png b/APG/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_clear_disabled.png Binary files differnew file mode 100644 index 000000000..79228baed --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_clear_disabled.png diff --git a/APG/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_clear_normal.png b/APG/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_clear_normal.png Binary files differnew file mode 100644 index 000000000..86944a879 --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_clear_normal.png diff --git a/APG/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_clear_search_api_disabled_holo_light.png b/APG/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_clear_search_api_disabled_holo_light.png Binary files differnew file mode 100644 index 000000000..c0bdf0641 --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_clear_search_api_disabled_holo_light.png diff --git a/APG/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_clear_search_api_holo_light.png b/APG/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_clear_search_api_holo_light.png Binary files differnew file mode 100644 index 000000000..15b86cbb2 --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_clear_search_api_holo_light.png diff --git a/APG/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_go.png b/APG/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_go.png Binary files differnew file mode 100644 index 000000000..bf19833f2 --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_go.png diff --git a/APG/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_go_search_api_holo_light.png b/APG/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_go_search_api_holo_light.png Binary files differnew file mode 100644 index 000000000..8518498eb --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_go_search_api_holo_light.png diff --git a/APG/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_search.png b/APG/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_search.png Binary files differnew file mode 100644 index 000000000..4be72f108 --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_search.png diff --git a/APG/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_search_api_holo_light.png b/APG/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_search_api_holo_light.png Binary files differnew file mode 100644 index 000000000..f2e26f883 --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_search_api_holo_light.png diff --git a/APG/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_voice_search.png b/APG/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_voice_search.png Binary files differnew file mode 100644 index 000000000..73c6be654 --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_voice_search.png diff --git a/APG/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_voice_search_api_holo_light.png b/APG/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_voice_search_api_holo_light.png Binary files differnew file mode 100644 index 000000000..71d838e73 --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_voice_search_api_holo_light.png diff --git a/APG/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_default_holo_dark.9.png b/APG/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_default_holo_dark.9.png Binary files differnew file mode 100644 index 000000000..081657ee7 --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_default_holo_dark.9.png diff --git a/APG/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_default_holo_light.9.png b/APG/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_default_holo_light.9.png Binary files differnew file mode 100644 index 000000000..3f312b465 --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_default_holo_light.9.png diff --git a/APG/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_right_default_holo_dark.9.png b/APG/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_right_default_holo_dark.9.png Binary files differnew file mode 100644 index 000000000..b086fae87 --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_right_default_holo_dark.9.png diff --git a/APG/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_right_default_holo_light.9.png b/APG/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_right_default_holo_light.9.png Binary files differnew file mode 100644 index 000000000..73c336a77 --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_right_default_holo_light.9.png diff --git a/APG/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_right_selected_holo_dark.9.png b/APG/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_right_selected_holo_dark.9.png Binary files differnew file mode 100644 index 000000000..726e0ff42 --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_right_selected_holo_dark.9.png diff --git a/APG/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_right_selected_holo_light.9.png b/APG/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_right_selected_holo_light.9.png Binary files differnew file mode 100644 index 000000000..726e0ff42 --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_right_selected_holo_light.9.png diff --git a/APG/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_selected_holo_dark.9.png b/APG/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_selected_holo_dark.9.png Binary files differnew file mode 100644 index 000000000..1767c169e --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_selected_holo_dark.9.png diff --git a/APG/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_selected_holo_light.9.png b/APG/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_selected_holo_light.9.png Binary files differnew file mode 100644 index 000000000..1767c169e --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_selected_holo_light.9.png diff --git a/APG/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_share_pack_holo_dark.9.png b/APG/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_share_pack_holo_dark.9.png Binary files differindex 55099d49d..9a70a5d1e 100644 --- a/APG/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_share_pack_holo_dark.9.png +++ b/APG/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_share_pack_holo_dark.9.png diff --git a/APG/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_share_pack_holo_light.9.png b/APG/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_share_pack_holo_light.9.png Binary files differindex 3c4701fc2..14fbee101 100644 --- a/APG/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_share_pack_holo_light.9.png +++ b/APG/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_share_pack_holo_light.9.png diff --git a/APG/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_clear_disabled.png b/APG/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_clear_disabled.png Binary files differnew file mode 100644 index 000000000..e35c5f05e --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_clear_disabled.png diff --git a/APG/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_clear_search_api_disabled_holo_light.png b/APG/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_clear_search_api_disabled_holo_light.png Binary files differnew file mode 100644 index 000000000..7fd7aeb2a --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_clear_search_api_disabled_holo_light.png diff --git a/APG/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_clear_search_api_holo_light.png b/APG/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_clear_search_api_holo_light.png Binary files differnew file mode 100644 index 000000000..53cfbd311 --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_clear_search_api_holo_light.png diff --git a/APG/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_go.png b/APG/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_go.png Binary files differnew file mode 100644 index 000000000..1e2dcfa02 --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_go.png diff --git a/APG/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_go_search_api_holo_light.png b/APG/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_go_search_api_holo_light.png Binary files differnew file mode 100644 index 000000000..f12eafcdc --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_go_search_api_holo_light.png diff --git a/APG/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_search.png b/APG/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_search.png Binary files differnew file mode 100644 index 000000000..998f91be9 --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_search.png diff --git a/APG/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_search_api_holo_light.png b/APG/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_search_api_holo_light.png Binary files differnew file mode 100644 index 000000000..a4cdf1c79 --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_search_api_holo_light.png diff --git a/APG/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_voice_search.png b/APG/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_voice_search.png Binary files differnew file mode 100644 index 000000000..c625a3602 --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_voice_search.png diff --git a/APG/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_voice_search_api_holo_light.png b/APG/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_voice_search_api_holo_light.png Binary files differnew file mode 100644 index 000000000..c332ba08c --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_voice_search_api_holo_light.png diff --git a/APG/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_default_holo_dark.9.png b/APG/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_default_holo_dark.9.png Binary files differnew file mode 100644 index 000000000..8fdbbf3ad --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_default_holo_dark.9.png diff --git a/APG/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_default_holo_light.9.png b/APG/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_default_holo_light.9.png Binary files differnew file mode 100644 index 000000000..4e9ae43c2 --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_default_holo_light.9.png diff --git a/APG/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_right_default_holo_dark.9.png b/APG/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_right_default_holo_dark.9.png Binary files differnew file mode 100644 index 000000000..98f4871bb --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_right_default_holo_dark.9.png diff --git a/APG/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_right_default_holo_light.9.png b/APG/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_right_default_holo_light.9.png Binary files differnew file mode 100644 index 000000000..733373ed3 --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_right_default_holo_light.9.png diff --git a/APG/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_right_selected_holo_dark.9.png b/APG/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_right_selected_holo_dark.9.png Binary files differnew file mode 100644 index 000000000..0c6bb036d --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_right_selected_holo_dark.9.png diff --git a/APG/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_right_selected_holo_light.9.png b/APG/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_right_selected_holo_light.9.png Binary files differnew file mode 100644 index 000000000..0c6bb036d --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_right_selected_holo_light.9.png diff --git a/APG/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_selected_holo_dark.9.png b/APG/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_selected_holo_dark.9.png Binary files differnew file mode 100644 index 000000000..e5bfd8ad3 --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_selected_holo_dark.9.png diff --git a/APG/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_selected_holo_light.9.png b/APG/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_selected_holo_light.9.png Binary files differnew file mode 100644 index 000000000..1743da6b4 --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_selected_holo_light.9.png diff --git a/APG/android-libs/ActionBarSherlock/res/drawable/abs__ic_clear.xml b/APG/android-libs/ActionBarSherlock/res/drawable/abs__ic_clear.xml new file mode 100644 index 000000000..a16f4b22e --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/drawable/abs__ic_clear.xml @@ -0,0 +1,22 @@ +<?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:drawable="@drawable/abs__ic_clear_disabled" /> + <item + android:drawable="@drawable/abs__ic_clear_normal" /> +</selector> diff --git a/APG/android-libs/ActionBarSherlock/res/drawable/abs__ic_clear_holo_light.xml b/APG/android-libs/ActionBarSherlock/res/drawable/abs__ic_clear_holo_light.xml new file mode 100644 index 000000000..256de80fb --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/drawable/abs__ic_clear_holo_light.xml @@ -0,0 +1,22 @@ +<?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:drawable="@drawable/abs__ic_clear_search_api_disabled_holo_light" /> + <item + android:drawable="@drawable/abs__ic_clear_search_api_holo_light" /> +</selector> diff --git a/APG/android-libs/ActionBarSherlock/res/drawable/abs__search_dropdown_dark.xml b/APG/android-libs/ActionBarSherlock/res/drawable/abs__search_dropdown_dark.xml new file mode 100644 index 000000000..26284187a --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/drawable/abs__search_dropdown_dark.xml @@ -0,0 +1,22 @@ +<?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. +--> + +<shape xmlns:android="http://schemas.android.com/apk/res/android"> + <solid android:color="#F0A0A0A0"/> + <stroke android:width="2dp" color="#A00080FF"/> + <padding android:left="5dp" android:top="0dp" + android:right="5dp" android:bottom="1dp" /> +</shape> diff --git a/APG/android-libs/ActionBarSherlock/res/drawable/abs__search_dropdown_light.xml b/APG/android-libs/ActionBarSherlock/res/drawable/abs__search_dropdown_light.xml new file mode 100644 index 000000000..0d00c5878 --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/drawable/abs__search_dropdown_light.xml @@ -0,0 +1,22 @@ +<?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. +--> + +<shape xmlns:android="http://schemas.android.com/apk/res/android"> + <solid android:color="#F0FFFFFF"/> + <stroke android:width="1dp" color="#A00080FF"/> + <padding android:left="5dp" android:top="0dp" + android:right="5dp" android:bottom="1dp" /> +</shape> diff --git a/APG/android-libs/ActionBarSherlock/res/drawable/abs__textfield_searchview_holo_dark.xml b/APG/android-libs/ActionBarSherlock/res/drawable/abs__textfield_searchview_holo_dark.xml new file mode 100644 index 000000000..b6d58c040 --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/drawable/abs__textfield_searchview_holo_dark.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2011 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_focused="true" + android:drawable="@drawable/abs__textfield_search_selected_holo_dark" /> + <item android:drawable="@drawable/abs__textfield_search_default_holo_dark" /> +</selector> + diff --git a/APG/android-libs/ActionBarSherlock/res/drawable/abs__textfield_searchview_holo_light.xml b/APG/android-libs/ActionBarSherlock/res/drawable/abs__textfield_searchview_holo_light.xml new file mode 100644 index 000000000..3d6acf808 --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/drawable/abs__textfield_searchview_holo_light.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2011 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_focused="true" + android:drawable="@drawable/abs__textfield_search_selected_holo_light" /> + <item android:drawable="@drawable/abs__textfield_search_default_holo_light" /> +</selector> + diff --git a/APG/android-libs/ActionBarSherlock/res/drawable/abs__textfield_searchview_right_holo_dark.xml b/APG/android-libs/ActionBarSherlock/res/drawable/abs__textfield_searchview_right_holo_dark.xml new file mode 100644 index 000000000..05ff4eda5 --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/drawable/abs__textfield_searchview_right_holo_dark.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2011 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_focused="true" + android:drawable="@drawable/abs__textfield_search_right_selected_holo_dark" /> + <item android:drawable="@drawable/abs__textfield_search_right_default_holo_dark" /> +</selector> + diff --git a/APG/android-libs/ActionBarSherlock/res/drawable/abs__textfield_searchview_right_holo_light.xml b/APG/android-libs/ActionBarSherlock/res/drawable/abs__textfield_searchview_right_holo_light.xml new file mode 100644 index 000000000..f6d61e57a --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/drawable/abs__textfield_searchview_right_holo_light.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2011 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_focused="true" + android:drawable="@drawable/abs__textfield_search_right_selected_holo_light" /> + <item android:drawable="@drawable/abs__textfield_search_right_default_holo_light" /> +</selector> + diff --git a/APG/android-libs/ActionBarSherlock/res/layout/abs__activity_chooser_view.xml b/APG/android-libs/ActionBarSherlock/res/layout/abs__activity_chooser_view.xml index 019d14ef4..6a0ac9ece 100644 --- a/APG/android-libs/ActionBarSherlock/res/layout/abs__activity_chooser_view.xml +++ b/APG/android-libs/ActionBarSherlock/res/layout/abs__activity_chooser_view.xml @@ -19,7 +19,7 @@ <com.actionbarsherlock.internal.widget.IcsLinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/abs__activity_chooser_view_content" android:layout_width="wrap_content" - android:layout_height="fill_parent" + android:layout_height="wrap_content" android:layout_gravity="center" style="?attr/activityChooserViewStyle"> diff --git a/APG/android-libs/ActionBarSherlock/res/layout/abs__dialog_title_holo.xml b/APG/android-libs/ActionBarSherlock/res/layout/abs__dialog_title_holo.xml index 6402f28be..ab2b0ee6c 100644 --- a/APG/android-libs/ActionBarSherlock/res/layout/abs__dialog_title_holo.xml +++ b/APG/android-libs/ActionBarSherlock/res/layout/abs__dialog_title_holo.xml @@ -35,7 +35,7 @@ enabled. android:layout_height="2dip" android:background="@color/abs__holo_blue_light" /> <FrameLayout - android:layout_width="wrap_content" android:layout_height="0dp" + android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:orientation="vertical" android:foreground="?attr/windowContentOverlay"> diff --git a/APG/android-libs/ActionBarSherlock/res/layout/abs__search_dropdown_item_icons_2line.xml b/APG/android-libs/ActionBarSherlock/res/layout/abs__search_dropdown_item_icons_2line.xml new file mode 100644 index 000000000..e1d3dc49c --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/layout/abs__search_dropdown_item_icons_2line.xml @@ -0,0 +1,89 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 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. +*/ +--> + +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:paddingLeft="@dimen/abs__dropdownitem_text_padding_left" + android:paddingRight="4dip" + android:layout_width="match_parent" + android:layout_height="?attr/searchResultListItemHeight" > + + <!-- Icons come first in the layout, since their placement doesn't depend on + the placement of the text views. --> + <ImageView android:id="@android:id/icon1" + android:layout_width="@dimen/abs__dropdownitem_icon_width" + android:layout_height="48dip" + android:scaleType="centerInside" + android:layout_alignParentLeft="true" + android:layout_alignParentTop="true" + android:layout_alignParentBottom="true" + android:visibility="invisible" /> + + <ImageView android:id="@+id/edit_query" + android:layout_width="48dip" + android:layout_height="48dip" + android:scaleType="centerInside" + android:layout_alignParentRight="true" + android:layout_alignParentTop="true" + android:layout_alignParentBottom="true" + android:src="?attr/searchViewEditQuery" + android:background="?attr/searchViewEditQueryBackground" + android:visibility="gone" /> + + <ImageView android:id="@android:id/icon2" + android:layout_width="48dip" + android:layout_height="48dip" + android:scaleType="centerInside" + android:layout_alignWithParentIfMissing="true" + android:layout_toLeftOf="@id/edit_query" + android:layout_alignParentTop="true" + android:layout_alignParentBottom="true" + android:visibility="gone" /> + + + <!-- The subtitle comes before the title, since the height of the title depends on whether the + subtitle is visible or gone. --> + <TextView android:id="@android:id/text2" + style="?android:attr/dropDownItemStyle" + android:textAppearance="?attr/textAppearanceSearchResultSubtitle" + android:singleLine="true" + android:layout_width="match_parent" + android:layout_height="29dip" + android:paddingBottom="4dip" + android:gravity="top" + android:layout_toRightOf="@android:id/icon1" + android:layout_toLeftOf="@android:id/icon2" + android:layout_alignWithParentIfMissing="true" + android:layout_alignParentBottom="true" + android:visibility="gone" /> + + <!-- The title is placed above the subtitle, if there is one. If there is no + subtitle, it fills the parent. --> + <TextView android:id="@android:id/text1" + style="?android:attr/dropDownItemStyle" + android:textAppearance="?attr/textAppearanceSearchResultTitle" + android:singleLine="true" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_centerVertical="true" + android:layout_toRightOf="@android:id/icon1" + android:layout_toLeftOf="@android:id/icon2" + android:layout_above="@android:id/text2" /> + +</RelativeLayout> diff --git a/APG/android-libs/ActionBarSherlock/res/layout/abs__search_view.xml b/APG/android-libs/ActionBarSherlock/res/layout/abs__search_view.xml new file mode 100644 index 000000000..6ba319121 --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/layout/abs__search_view.xml @@ -0,0 +1,159 @@ +<?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. + */ + +--> +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/abs__search_bar" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="horizontal" + > + + <!-- This is actually used for the badge icon *or* the badge label (or neither) --> + <TextView + android:id="@+id/abs__search_badge" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:gravity="center_vertical" + android:layout_marginBottom="2dip" + android:drawablePadding="0dip" + android:textAppearance="?android:attr/textAppearanceMedium" + android:textColor="?attr/textColorPrimary" + android:visibility="gone" + /> + + <ImageView + android:id="@+id/abs__search_button" + style="?android:attr/actionButtonStyle" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:layout_gravity="center_vertical" + android:src="?attr/searchViewSearchIcon" + android:contentDescription="@string/abs__searchview_description_search" + /> + + <LinearLayout + android:id="@+id/abs__search_edit_frame" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_weight="1" + android:layout_gravity="center_vertical" + android:layout_marginTop="4dip" + android:layout_marginBottom="4dip" + android:layout_marginLeft="8dip" + android:layout_marginRight="8dip" + android:orientation="horizontal"> + + <ImageView + android:id="@+id/abs__search_mag_icon" + android:layout_width="@dimen/abs__dropdownitem_icon_width" + android:layout_height="wrap_content" + android:scaleType="centerInside" + android:layout_marginLeft="@dimen/abs__dropdownitem_text_padding_left" + android:layout_gravity="center_vertical" + android:src="?attr/searchViewSearchIcon" + android:visibility="gone" + /> + + <!-- Inner layout contains the app icon, button(s) and EditText --> + <LinearLayout + android:id="@+id/abs__search_plate" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_weight="1" + android:layout_gravity="center_vertical" + android:orientation="horizontal" + android:background="?attr/searchViewTextField"> + + <view class="com.actionbarsherlock.widget.SearchView$SearchAutoComplete" + style="?attr/searchAutoCompleteTextView" + android:id="@+id/abs__search_src_text" + android:layout_height="36dip" + android:layout_width="0dp" + android:layout_weight="1" + android:minWidth="@dimen/abs__search_view_text_min_width" + android:layout_gravity="bottom" + android:paddingLeft="@dimen/abs__dropdownitem_text_padding_left" + android:paddingRight="@dimen/abs__dropdownitem_text_padding_right" + android:singleLine="true" + android:ellipsize="end" + android:background="@null" + android:inputType="text|textAutoComplete|textNoSuggestions" + android:imeOptions="actionSearch" + android:dropDownHeight="wrap_content" + android:dropDownAnchor="@id/abs__search_edit_frame" + android:dropDownVerticalOffset="0dip" + android:dropDownHorizontalOffset="0dip" + android:contentDescription="@string/abs__searchview_description_query" + /> + + <ImageView + android:id="@+id/abs__search_close_btn" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:paddingLeft="8dip" + android:paddingRight="8dip" + android:layout_gravity="center_vertical" + android:background="?attr/selectableItemBackground" + android:src="?attr/searchViewCloseIcon" + android:focusable="true" + android:contentDescription="@string/abs__searchview_description_clear" + /> + + </LinearLayout> + + <LinearLayout + android:id="@+id/abs__submit_area" + android:orientation="horizontal" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:background="?attr/searchViewTextFieldRight"> + + <ImageView + android:id="@+id/abs__search_go_btn" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:layout_gravity="center_vertical" + android:paddingLeft="16dip" + android:paddingRight="16dip" + android:background="?attr/selectableItemBackground" + android:src="?attr/searchViewGoIcon" + android:visibility="gone" + android:focusable="true" + android:contentDescription="@string/abs__searchview_description_submit" + /> + + <ImageView + android:id="@+id/abs__search_voice_btn" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:layout_gravity="center_vertical" + android:paddingLeft="16dip" + android:paddingRight="16dip" + android:src="?attr/searchViewVoiceIcon" + android:background="?attr/selectableItemBackground" + android:visibility="gone" + android:focusable="true" + android:contentDescription="@string/abs__searchview_description_voice" + /> + + </LinearLayout> + </LinearLayout> + +</LinearLayout> diff --git a/APG/android-libs/ActionBarSherlock/res/layout/abs__simple_dropdown_hint.xml b/APG/android-libs/ActionBarSherlock/res/layout/abs__simple_dropdown_hint.xml new file mode 100644 index 000000000..8fc0eb12c --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/res/layout/abs__simple_dropdown_hint.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 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. +*/ +--> +<TextView xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@android:id/text1" + android:textAppearance="?android:attr/dropDownHintAppearance" + android:singleLine="true" + android:layout_marginLeft="3dip" + android:layout_marginTop="3dip" + android:layout_marginRight="3dip" + android:layout_marginBottom="3dip" + android:layout_width="match_parent" + android:layout_height="wrap_content" /> diff --git a/APG/android-libs/ActionBarSherlock/res/values-v14/abs__styles.xml b/APG/android-libs/ActionBarSherlock/res/values-v14/abs__styles.xml index f2aa64d2d..88a60dd92 100644 --- a/APG/android-libs/ActionBarSherlock/res/values-v14/abs__styles.xml +++ b/APG/android-libs/ActionBarSherlock/res/values-v14/abs__styles.xml @@ -85,6 +85,11 @@ <style name="Widget.Sherlock.Light.ProgressBar.Horizontal" parent="android:Widget.Holo.Light.ProgressBar.Horizontal"> </style> + <style name="Widget.Sherlock.SearchAutoCompleteTextView" parent="android:Widget.Holo.AutoCompleteTextView"> + </style> + <style name="Widget.Sherlock.Light.SearchAutoCompleteTextView" parent="android:Widget.Holo.Light.AutoCompleteTextView"> + </style> + <style name="TextAppearance.Sherlock.Widget.ActionBar.Menu" parent="android:TextAppearance.Holo.Widget.ActionBar.Menu"> </style> diff --git a/APG/android-libs/ActionBarSherlock/res/values-v14/abs__themes.xml b/APG/android-libs/ActionBarSherlock/res/values-v14/abs__themes.xml index ceb960737..5fac1ab58 100644 --- a/APG/android-libs/ActionBarSherlock/res/values-v14/abs__themes.xml +++ b/APG/android-libs/ActionBarSherlock/res/values-v14/abs__themes.xml @@ -10,10 +10,12 @@ <item name="actionBarSize">?android:attr/actionBarSize</item> <!-- Needed for our bug-fix dropdown list navigation layout. :( --> <item name="dropdownListPreferredItemHeight">48dp</item> - <!-- Needed for our ShareActionProvider implementation. --> + <!-- Needed for our ShareActionProvider and SearchView implementation. --> <item name="android:actionBarWidgetTheme">@style/Theme.Sherlock</item> <!-- For crazy people who use IcsSpinner. --> <item name="dropDownListViewStyle">?android:attr/dropDownListViewStyle</item> + <!-- Needed for our SearchView implementation. --> + <item name="selectableItemBackground">?android:attr/selectableItemBackground</item> </style> <style name="Theme.Sherlock.NoActionBar"> diff --git a/APG/android-libs/ActionBarSherlock/res/values/abs__attrs.xml b/APG/android-libs/ActionBarSherlock/res/values/abs__attrs.xml index 81c347108..32631ca8d 100644 --- a/APG/android-libs/ActionBarSherlock/res/values/abs__attrs.xml +++ b/APG/android-libs/ActionBarSherlock/res/values/abs__attrs.xml @@ -74,6 +74,9 @@ <!-- Small Button style. --> <attr name="buttonStyleSmall" format="reference" /> + <!-- Background drawable for standalone items that need focus/pressed states. --> + <attr name="selectableItemBackground" format="reference" /> + <!-- This Drawable is overlaid over the foreground of the Window's content area, usually @@ -97,6 +100,40 @@ <attr name="spinnerItemStyle" format="reference" /> <attr name="spinnerDropDownItemStyle" format="reference" /> + <!-- ============================ --> + <!-- SearchView styles and assets --> + <!-- ============================ --> + <eat-comment /> + <!-- SearchView AutoCompleteTextView style --> + <attr name="searchAutoCompleteTextView" format="reference" /> + <!-- SearchView dropdown background --> + <attr name="searchDropdownBackground" format="reference" /> + <!-- SearchView close button icon --> + <attr name="searchViewCloseIcon" format="reference" /> + <!-- SearchView Go button icon --> + <attr name="searchViewGoIcon" format="reference" /> + <!-- SearchView Search icon --> + <attr name="searchViewSearchIcon" format="reference" /> + <!-- SearchView Voice button icon --> + <attr name="searchViewVoiceIcon" format="reference" /> + <!-- SearchView query refinement icon --> + <attr name="searchViewEditQuery" format="reference" /> + <!-- SearchView query refinement icon background --> + <attr name="searchViewEditQueryBackground" format="reference" /> + <!-- SearchView text field background for the left section --> + <attr name="searchViewTextField" format="reference" /> + <!-- SearchView text field background for the right section --> + <attr name="searchViewTextFieldRight" format="reference" /> + <!-- Text color for urls in search suggestions, used by things like global search and the browser. @hide --> + <attr name="textColorSearchUrl" format="reference|color" /> + <!-- The list item height for search results. @hide --> + <attr name="searchResultListItemHeight" format="dimension" /> + <!-- Text color, typeface, size, and style for system search result title. Defaults to primary inverse text color. --> + <attr name="textAppearanceSearchResultTitle" format="reference" /> + <!-- Text color, typeface, size, and style for system search result subtitle. Defaults to primary inverse text color. --> + <attr name="textAppearanceSearchResultSubtitle" format="reference" /> + + <!-- =========== --> <!-- List styles --> <!-- =========== --> @@ -144,9 +181,6 @@ <!-- Drawable used as a background for activated items. --> <attr name="activatedBackgroundIndicator" format="reference" /> - <!-- Specified if we are forcing an action item overflow menu. --> - <attr name="absForceOverflow" format="boolean" /> - <attr name="android:windowIsFloating" /> </declare-styleable> @@ -377,4 +411,22 @@ <!-- Gravity setting for positioning the currently selected item. --> <attr name="android:gravity" /> </declare-styleable> + + <declare-styleable name="SherlockSearchView"> + <!-- The default state of the SearchView. If true, it will be iconified when not in + use and expanded when clicked. --> + <attr name="iconifiedByDefault" format="boolean"/> + <!-- An optional maximum width of the SearchView. --> + <attr name="android:maxWidth" /> + <!-- An optional query hint string to be displayed in the empty query field. --> + <attr name="queryHint" format="string" /> + <!-- The IME options to set on the query text field. --> + <attr name="android:imeOptions" /> + <!-- The input type to set on the query text field. --> + <attr name="android:inputType" /> + </declare-styleable> + + <declare-styleable name="SherlockView"> + <attr name="android:focusable"/> + </declare-styleable> </resources> diff --git a/APG/android-libs/ActionBarSherlock/res/values/abs__dimens.xml b/APG/android-libs/ActionBarSherlock/res/values/abs__dimens.xml index 0a409756c..831289e07 100644 --- a/APG/android-libs/ActionBarSherlock/res/values/abs__dimens.xml +++ b/APG/android-libs/ActionBarSherlock/res/values/abs__dimens.xml @@ -30,15 +30,15 @@ <dimen name="abs__action_bar_subtitle_top_margin">-3dp</dimen> <!-- Bottom margin for action bar subtitles --> <dimen name="abs__action_bar_subtitle_bottom_margin">5dip</dimen> - + <integer name="abs__max_action_buttons">2</integer> <!-- Minimum width for an action button in the menu area of an action bar --> <dimen name="abs__action_button_min_width">56dip</dimen> - + <!-- Dialog title height --> <dimen name="abs__alert_dialog_title_height">64dip</dimen> - + <!-- The platform's desired minimum size for a dialog's width when it is along the major axis (that is the screen is landscape). This may be either a fraction or a dimension. --> @@ -47,4 +47,21 @@ is along the minor axis (that is the screen is portrait). This may be either a fraction or a dimension. --> <item type="dimen" name="abs__dialog_min_width_minor">95%</item> + + + <!-- Text padding for dropdown items --> + <dimen name="abs__dropdownitem_text_padding_left">8dip</dimen> + + <!-- Text padding for dropdown items --> + <dimen name="abs__dropdownitem_text_padding_right">8dip</dimen> + + <!-- Width of the icon in a dropdown list --> + <dimen name="abs__dropdownitem_icon_width">32dip</dimen> + + + <!-- Minimum width of the search view text entry area. --> + <dimen name="abs__search_view_text_min_width">160dip</dimen> + + <!-- Preferred width of the search view. --> + <dimen name="abs__search_view_preferred_width">320dip</dimen> </resources> diff --git a/APG/android-libs/ActionBarSherlock/res/values/abs__strings.xml b/APG/android-libs/ActionBarSherlock/res/values/abs__strings.xml index 1e1c7022c..06a2a2af4 100644 --- a/APG/android-libs/ActionBarSherlock/res/values/abs__strings.xml +++ b/APG/android-libs/ActionBarSherlock/res/values/abs__strings.xml @@ -39,4 +39,15 @@ <string name="abs__shareactionprovider_share_with">Share with</string> <!-- Description of a share target (both in the list of such or the default share button) in a ShareActionProvider (share UI). [CHAR LIMIT=NONE] --> <string name="abs__shareactionprovider_share_with_application">Share with <xliff:g id="application_name" example="Bluetooth">%s</xliff:g></string> + + <!-- SearchView accessibility description for search button [CHAR LIMIT=NONE] --> + <string name="abs__searchview_description_search">Search</string> + <!-- SearchView accessibility description for search text field [CHAR LIMIT=NONE] --> + <string name="abs__searchview_description_query">Search query</string> + <!-- SearchView accessibility description for clear button [CHAR LIMIT=NONE] --> + <string name="abs__searchview_description_clear">Clear query</string> + <!-- SearchView accessibility description for submit button [CHAR LIMIT=NONE] --> + <string name="abs__searchview_description_submit">Submit query</string> + <!-- SearchView accessibility description for voice button [CHAR LIMIT=NONE] --> + <string name="abs__searchview_description_voice">Voice search</string> </resources> diff --git a/APG/android-libs/ActionBarSherlock/res/values/abs__styles.xml b/APG/android-libs/ActionBarSherlock/res/values/abs__styles.xml index 8cbd36484..45a18c183 100644 --- a/APG/android-libs/ActionBarSherlock/res/values/abs__styles.xml +++ b/APG/android-libs/ActionBarSherlock/res/values/abs__styles.xml @@ -182,6 +182,7 @@ <item name="android:divider">?attr/dividerVertical</item> <item name="android:showDividers">middle</item> <item name="android:dividerPadding">6dip</item> + <item name="android:minHeight">?attr/actionBarSize</item> </style> <style name="Widget.Sherlock.ActivityChooserView" parent="Sherlock.__Widget.ActivityChooserView"> </style> @@ -279,6 +280,28 @@ + <style name="Sherlock.__Widget.SearchAutoCompleteTextView" parent="Widget"> + <item name="android:focusable">true</item> + <item name="android:focusableInTouchMode">true</item> + <item name="android:clickable">true</item> + <item name="android:textAppearance">?android:attr/textAppearanceMediumInverse</item> + <item name="android:textColor">?attr/textColorPrimary</item> + <item name="android:gravity">center_vertical</item> + <item name="android:completionHintView">@layout/abs__simple_dropdown_hint</item> + <item name="android:completionThreshold">2</item> + <item name="android:dropDownWidth">wrap_content</item> + </style> + <style name="Widget.Sherlock.SearchAutoCompleteTextView" parent="Sherlock.__Widget.SearchAutoCompleteTextView"> + <item name="android:dropDownSelector">@drawable/abs__list_selector_holo_dark</item> + <item name="android:popupBackground">@drawable/abs__menu_dropdown_panel_holo_dark</item> + </style> + <style name="Widget.Sherlock.Light.SearchAutoCompleteTextView" parent="Sherlock.__Widget.SearchAutoCompleteTextView"> + <item name="android:dropDownSelector">@drawable/abs__list_selector_holo_light</item> + <item name="android:popupBackground">@drawable/abs__menu_dropdown_panel_holo_light</item> + </style> + + + <style name="DialogWindowTitle.Sherlock" parent="Widget"> <item name="android:maxLines">1</item> <item name="android:scrollHorizontally">true</item> @@ -381,4 +404,9 @@ </style> <style name="TextAppearance.Sherlock.Light.Small" parent="TextAppearance.Sherlock.Small"> </style> + + <style name="TextAppearance.Sherlock.Widget.DropDownHint" parent="Widget"> + <item name="android:textColor">?textColorPrimary</item> + <item name="android:textSize">14sp</item> + </style> </resources> diff --git a/APG/android-libs/ActionBarSherlock/res/values/abs__themes.xml b/APG/android-libs/ActionBarSherlock/res/values/abs__themes.xml index 5300dedd6..634fa798b 100644 --- a/APG/android-libs/ActionBarSherlock/res/values/abs__themes.xml +++ b/APG/android-libs/ActionBarSherlock/res/values/abs__themes.xml @@ -11,7 +11,7 @@ </style> <style name="Sherlock.__Theme.Dialog" parent="android:Theme.Dialog"> </style> - + <style name="Theme.Sherlock" parent="Sherlock.__Theme"> <!-- Action bar styles (from Theme.Holo) --> <item name="actionDropDownStyle">@style/Widget.Sherlock.Spinner.DropDown.ActionBar</item> @@ -29,41 +29,53 @@ <item name="actionBarSize">@dimen/abs__action_bar_default_height</item> <!-- Internal --><item name="actionModePopupWindowStyle">@style/Widget.Sherlock.PopupWindow.ActionMode</item> <item name="actionBarWidgetTheme">@null</item> - + <!-- Action bar styles (defaults from Theme) --> <item name="actionBarSplitStyle">?attr/actionBarStyle</item> <item name="actionMenuTextAppearance">@style/TextAppearance.Sherlock.Widget.ActionBar.Menu</item> <item name="actionMenuTextColor">?attr/textColorPrimary</item> <item name="actionBarDivider">?attr/dividerVertical</item> - <item name="actionBarItemBackground">@drawable/abs__item_background_holo_dark</item> + <item name="actionBarItemBackground">?attr/selectableItemBackground</item> <item name="buttonStyleSmall">@style/Widget.Sherlock.Button.Small</item> - + + <item name="selectableItemBackground">@drawable/abs__item_background_holo_dark</item> + <item name="activatedBackgroundIndicator">@drawable/abs__activated_background_holo_dark</item> <item name="actionModeShareDrawable">@drawable/abs__ic_menu_share_holo_dark</item> <item name="activityChooserViewStyle">@style/Widget.Sherlock.ActivityChooserView</item> - + <item name="homeAsUpIndicator">@drawable/abs__ic_ab_back_holo_dark</item> - + <item name="dividerVertical">@drawable/abs__list_divider_holo_dark</item> - + <item name="spinnerDropDownItemStyle">@style/Widget.Sherlock.DropDownItem.Spinner</item> <item name="spinnerItemStyle">@style/Widget.Sherlock.TextView.SpinnerItem</item> - + <item name="textColorPrimary">@color/abs__primary_text_holo_dark</item> <item name="textColorPrimaryDisableOnly">@color/abs__primary_text_disable_only_holo_dark</item> <item name="textColorPrimaryInverse">@color/abs__primary_text_holo_light</item> - + <!-- Internal --><item name="dropdownListPreferredItemHeight">48dip</item> <item name="dropDownListViewStyle">@style/Widget.Sherlock.ListView.DropDown</item> <item name="textAppearanceSmall">@style/TextAppearance.Sherlock.Small</item> <item name="textAppearanceLargePopupMenu">@style/TextAppearance.Sherlock.Widget.PopupMenu.Large</item> <item name="textAppearanceSmallPopupMenu">@style/TextAppearance.Sherlock.Widget.PopupMenu.Small</item> - + <item name="popupMenuStyle">@style/Widget.Sherlock.PopupMenu</item> <!-- Internal --><item name="listPopupWindowStyle">@style/Widget.Sherlock.ListPopupWindow</item> - + + <item name="searchDropdownBackground">@drawable/abs__search_dropdown_dark</item> + <item name="searchViewTextField">@drawable/abs__textfield_searchview_holo_dark</item> + <item name="searchViewTextFieldRight">@drawable/abs__textfield_searchview_right_holo_dark</item> + <item name="searchViewCloseIcon">@drawable/abs__ic_clear</item> + <item name="searchViewSearchIcon">@drawable/abs__ic_search</item> + <item name="searchViewGoIcon">@drawable/abs__ic_go</item> + <item name="searchViewVoiceIcon">@drawable/abs__ic_voice_search</item> + <item name="searchAutoCompleteTextView">@style/Widget.Sherlock.SearchAutoCompleteTextView</item> + <item name="android:dropDownHintAppearance">@style/TextAppearance.Sherlock.Widget.DropDownHint</item> + <item name="windowActionBar">true</item> <item name="windowActionModeOverlay">false</item> <item name="windowContentOverlay">@null</item> @@ -85,41 +97,53 @@ <item name="actionBarSize">@dimen/abs__action_bar_default_height</item> <!-- Internal --><item name="actionModePopupWindowStyle">@style/Widget.Sherlock.Light.PopupWindow.ActionMode</item> <item name="actionBarWidgetTheme">@null</item> - + <!-- Action bar styles (defaults from Theme) --> <item name="actionBarSplitStyle">?attr/actionBarStyle</item> <item name="actionMenuTextAppearance">@style/TextAppearance.Sherlock.Widget.ActionBar.Menu</item> <item name="actionMenuTextColor">?attr/textColorPrimary</item> <item name="actionBarDivider">?attr/dividerVertical</item> - <item name="actionBarItemBackground">@drawable/abs__item_background_holo_light</item> + <item name="actionBarItemBackground">?attr/selectableItemBackground</item> <item name="buttonStyleSmall">@style/Widget.Sherlock.Light.Button.Small</item> - + + <item name="selectableItemBackground">@drawable/abs__item_background_holo_light</item> + <item name="activatedBackgroundIndicator">@drawable/abs__activated_background_holo_light</item> <item name="actionModeShareDrawable">@drawable/abs__ic_menu_share_holo_light</item> <item name="activityChooserViewStyle">@style/Widget.Sherlock.Light.ActivityChooserView</item> - + <item name="homeAsUpIndicator">@drawable/abs__ic_ab_back_holo_light</item> - + <item name="dividerVertical">@drawable/abs__list_divider_holo_light</item> - + <item name="spinnerDropDownItemStyle">@style/Widget.Sherlock.Light.DropDownItem.Spinner</item> <item name="spinnerItemStyle">@style/Widget.Sherlock.TextView.SpinnerItem</item> - + <item name="textColorPrimary">@color/abs__primary_text_holo_light</item> <item name="textColorPrimaryDisableOnly">@color/abs__primary_text_disable_only_holo_light</item> <item name="textColorPrimaryInverse">@color/abs__primary_text_holo_dark</item> - + <!-- Internal --><item name="dropdownListPreferredItemHeight">48dip</item> <item name="dropDownListViewStyle">@style/Widget.Sherlock.Light.ListView.DropDown</item> <item name="textAppearanceSmall">@style/TextAppearance.Sherlock.Light.Small</item> <item name="textAppearanceLargePopupMenu">@style/TextAppearance.Sherlock.Light.Widget.PopupMenu.Large</item> <item name="textAppearanceSmallPopupMenu">@style/TextAppearance.Sherlock.Light.Widget.PopupMenu.Small</item> - + <item name="popupMenuStyle">@style/Widget.Sherlock.Light.PopupMenu</item> <!-- Internal --><item name="listPopupWindowStyle">@style/Widget.Sherlock.Light.ListPopupWindow</item> - + + <item name="searchDropdownBackground">@drawable/abs__search_dropdown_light</item> + <item name="searchViewTextField">@drawable/abs__textfield_searchview_holo_light</item> + <item name="searchViewTextFieldRight">@drawable/abs__textfield_searchview_right_holo_light</item> + <item name="searchViewCloseIcon">@drawable/abs__ic_clear_holo_light</item> + <item name="searchViewSearchIcon">@drawable/abs__ic_search_api_holo_light</item> + <item name="searchViewGoIcon">@drawable/abs__ic_go_search_api_holo_light</item> + <item name="searchViewVoiceIcon">@drawable/abs__ic_voice_search_api_holo_light</item> + <item name="searchAutoCompleteTextView">@style/Widget.Sherlock.Light.SearchAutoCompleteTextView</item> + <item name="android:dropDownHintAppearance">@style/TextAppearance.Sherlock.Widget.DropDownHint</item> + <item name="windowActionBar">true</item> <item name="windowActionModeOverlay">false</item> <item name="windowContentOverlay">@null</item> @@ -145,11 +169,11 @@ <item name="actionModeStyle">@style/Widget.Sherlock.Light.ActionMode.Inverse</item> <item name="actionModeCloseButtonStyle">@style/Widget.Sherlock.ActionButton.CloseMode</item> <item name="actionModePopupWindowStyle">@style/Widget.Sherlock.PopupWindow.ActionMode</item> - + <item name="actionModeShareDrawable">@drawable/abs__ic_menu_share_holo_dark</item> </style> - - + + <style name="Theme.Sherlock.NoActionBar"> <item name="windowActionBar">false</item> <item name="windowNoTitle">true</item> @@ -158,19 +182,8 @@ <item name="windowActionBar">false</item> <item name="windowNoTitle">true</item> </style> - - - <style name="Theme.Sherlock.ForceOverflow"> - <item name="absForceOverflow">true</item> - </style> - <style name="Theme.Sherlock.Light.ForceOverflow"> - <item name="absForceOverflow">true</item> - </style> - <style name="Theme.Sherlock.Light.DarkActionBar.ForceOverflow"> - <item name="absForceOverflow">true</item> - </style> - - + + <style name="Theme.Sherlock.Dialog" parent="android:Theme"> <item name="android:windowFrame">@null</item> <item name="android:windowTitleStyle">@style/DialogWindowTitle.Sherlock</item> @@ -179,21 +192,21 @@ <item name="android:windowContentOverlay">@null</item> <item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item> <item name="android:windowSoftInputMode">stateUnspecified|adjustPan</item> - + <item name="android:windowActionBar">false</item> <item name="android:windowActionModeOverlay">true</item> <item name="android:windowCloseOnTouchOutside">true</item> <item name="android:windowNoTitle">true</item> <item name="android:backgroundDimAmount">0.6</item> - + <item name="android:colorBackgroundCacheHint">@null</item> - + <item name="android:textColorPrimary">@color/abs__primary_text_holo_dark</item> <item name="android:textColorPrimaryInverse">@color/abs__primary_text_holo_light</item> - + <item name="windowMinWidthMajor">@dimen/abs__dialog_min_width_major</item> <item name="windowMinWidthMinor">@dimen/abs__dialog_min_width_minor</item> - + <item name="windowActionBar">false</item> <item name="windowContentOverlay">@null</item> </style> @@ -205,21 +218,21 @@ <item name="android:windowContentOverlay">@null</item> <item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item> <item name="android:windowSoftInputMode">stateUnspecified|adjustPan</item> - + <item name="android:windowActionBar">false</item> <item name="android:windowActionModeOverlay">true</item> <item name="android:windowCloseOnTouchOutside">true</item> <item name="android:windowNoTitle">true</item> <item name="android:backgroundDimAmount">0.6</item> - + <item name="android:colorBackgroundCacheHint">@null</item> - + <item name="android:textColorPrimary">@color/abs__primary_text_holo_light</item> <item name="android:textColorPrimaryInverse">@color/abs__primary_text_holo_dark</item> - + <item name="windowMinWidthMajor">@dimen/abs__dialog_min_width_major</item> <item name="windowMinWidthMinor">@dimen/abs__dialog_min_width_minor</item> - + <item name="windowActionBar">false</item> <item name="windowContentOverlay">@null</item> </style> diff --git a/APG/android-libs/ActionBarSherlock/src/android/support/v4/app/Watson.java b/APG/android-libs/ActionBarSherlock/src/android/support/v4/app/Watson.java new file mode 100644 index 000000000..d93de4c6a --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/src/android/support/v4/app/Watson.java @@ -0,0 +1,144 @@ +package android.support.v4.app; + +import android.util.Log; +import android.view.View; +import android.view.Window; +import com.actionbarsherlock.ActionBarSherlock.OnCreatePanelMenuListener; +import com.actionbarsherlock.ActionBarSherlock.OnMenuItemSelectedListener; +import com.actionbarsherlock.ActionBarSherlock.OnPreparePanelListener; +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuInflater; +import com.actionbarsherlock.view.MenuItem; + +import java.util.ArrayList; + +/** I'm in ur package. Stealing ur variables. */ +public abstract class Watson extends FragmentActivity implements OnCreatePanelMenuListener, OnPreparePanelListener, OnMenuItemSelectedListener { + private static final boolean DEBUG = false; + private static final String TAG = "Watson"; + + /** Fragment interface for menu creation callback. */ + public interface OnCreateOptionsMenuListener { + public void onCreateOptionsMenu(Menu menu, MenuInflater inflater); + } + /** Fragment interface for menu preparation callback. */ + public interface OnPrepareOptionsMenuListener { + public void onPrepareOptionsMenu(Menu menu); + } + /** Fragment interface for menu item selection callback. */ + public interface OnOptionsItemSelectedListener { + public boolean onOptionsItemSelected(MenuItem item); + } + + private ArrayList<Fragment> mCreatedMenus; + + + /////////////////////////////////////////////////////////////////////////// + // Sherlock menu handling + /////////////////////////////////////////////////////////////////////////// + + @Override + public boolean onCreatePanelMenu(int featureId, Menu menu) { + if (DEBUG) Log.d(TAG, "[onCreatePanelMenu] featureId: " + featureId + ", menu: " + menu); + + if (featureId == Window.FEATURE_OPTIONS_PANEL) { + boolean result = onCreateOptionsMenu(menu); + if (DEBUG) Log.d(TAG, "[onCreatePanelMenu] activity create result: " + result); + + MenuInflater inflater = getSupportMenuInflater(); + boolean show = false; + ArrayList<Fragment> newMenus = null; + if (mFragments.mAdded != null) { + for (int i = 0; i < mFragments.mAdded.size(); i++) { + Fragment f = mFragments.mAdded.get(i); + if (f != null && !f.mHidden && f.mHasMenu && f.mMenuVisible && f instanceof OnCreateOptionsMenuListener) { + show = true; + ((OnCreateOptionsMenuListener)f).onCreateOptionsMenu(menu, inflater); + if (newMenus == null) { + newMenus = new ArrayList<Fragment>(); + } + newMenus.add(f); + } + } + } + + if (mCreatedMenus != null) { + for (int i = 0; i < mCreatedMenus.size(); i++) { + Fragment f = mCreatedMenus.get(i); + if (newMenus == null || !newMenus.contains(f)) { + f.onDestroyOptionsMenu(); + } + } + } + + mCreatedMenus = newMenus; + + if (DEBUG) Log.d(TAG, "[onCreatePanelMenu] fragments create result: " + show); + result |= show; + + if (DEBUG) Log.d(TAG, "[onCreatePanelMenu] returning " + result); + return result; + } + return false; + } + + @Override + public boolean onPreparePanel(int featureId, View view, Menu menu) { + if (DEBUG) Log.d(TAG, "[onPreparePanel] featureId: " + featureId + ", view: " + view + " menu: " + menu); + + if (featureId == Window.FEATURE_OPTIONS_PANEL) { + boolean result = onPrepareOptionsMenu(menu); + if (DEBUG) Log.d(TAG, "[onPreparePanel] activity prepare result: " + result); + + boolean show = false; + if (mFragments.mAdded != null) { + for (int i = 0; i < mFragments.mAdded.size(); i++) { + Fragment f = mFragments.mAdded.get(i); + if (f != null && !f.mHidden && f.mHasMenu && f.mMenuVisible && f instanceof OnPrepareOptionsMenuListener) { + show = true; + ((OnPrepareOptionsMenuListener)f).onPrepareOptionsMenu(menu); + } + } + } + + if (DEBUG) Log.d(TAG, "[onPreparePanel] fragments prepare result: " + show); + result |= show; + + result &= menu.hasVisibleItems(); + if (DEBUG) Log.d(TAG, "[onPreparePanel] returning " + result); + return result; + } + return false; + } + + @Override + public boolean onMenuItemSelected(int featureId, MenuItem item) { + if (DEBUG) Log.d(TAG, "[onMenuItemSelected] featureId: " + featureId + ", item: " + item); + + if (featureId == Window.FEATURE_OPTIONS_PANEL) { + if (onOptionsItemSelected(item)) { + return true; + } + + if (mFragments.mAdded != null) { + for (int i = 0; i < mFragments.mAdded.size(); i++) { + Fragment f = mFragments.mAdded.get(i); + if (f != null && !f.mHidden && f.mHasMenu && f.mMenuVisible && f instanceof OnOptionsItemSelectedListener) { + if (((OnOptionsItemSelectedListener)f).onOptionsItemSelected(item)) { + return true; + } + } + } + } + } + return false; + } + + public abstract boolean onCreateOptionsMenu(Menu menu); + + public abstract boolean onPrepareOptionsMenu(Menu menu); + + public abstract boolean onOptionsItemSelected(MenuItem item); + + public abstract MenuInflater getSupportMenuInflater(); +} diff --git a/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/ActionBarSherlock.java b/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/ActionBarSherlock.java index 8340fb591..ab160f836 100644 --- a/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/ActionBarSherlock.java +++ b/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/ActionBarSherlock.java @@ -537,6 +537,9 @@ public abstract class ActionBarSherlock { */
public void dispatchDestroy() {}
+ public void dispatchSaveInstanceState(Bundle outState) {}
+
+ public void dispatchRestoreInstanceState(Bundle savedInstanceState) {}
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
@@ -769,7 +772,7 @@ public abstract class ActionBarSherlock { // Make sure that action views can get an appropriate theme.
if (mMenuInflater == null) {
if (getActionBar() != null) {
- mMenuInflater = new MenuInflater(getThemedContext());
+ mMenuInflater = new MenuInflater(getThemedContext(), mActivity);
} else {
mMenuInflater = new MenuInflater(mActivity);
}
diff --git a/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/app/ActionBar.java b/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/app/ActionBar.java index 2497d24ff..03755be2b 100644 --- a/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/app/ActionBar.java +++ b/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/app/ActionBar.java @@ -17,6 +17,7 @@ package com.actionbarsherlock.app;
import android.content.Context;
+import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.support.v4.app.FragmentTransaction;
import android.util.AttributeSet;
@@ -895,6 +896,10 @@ public abstract class ActionBar { * @attr ref android.R.styleable#ActionBar_LayoutParams_layout_gravity
*/
public static class LayoutParams extends MarginLayoutParams {
+ private static final int[] ATTRS = new int[] {
+ android.R.attr.layout_gravity
+ };
+
/**
* Gravity for the view associated with these LayoutParams.
*
@@ -918,6 +923,10 @@ public abstract class ActionBar { public LayoutParams(Context c, AttributeSet attrs) {
super(c, attrs);
+
+ TypedArray a = c.obtainStyledAttributes(attrs, ATTRS);
+ gravity = a.getInt(0, -1);
+ a.recycle();
}
public LayoutParams(int width, int height) {
diff --git a/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockActivity.java b/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockActivity.java index 9cb57e95a..7b4543640 100644 --- a/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockActivity.java +++ b/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockActivity.java @@ -116,6 +116,17 @@ public abstract class SherlockActivity extends Activity implements OnCreatePanel return super.dispatchKeyEvent(event);
}
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ getSherlock().dispatchSaveInstanceState(outState);
+ }
+
+ @Override
+ protected void onRestoreInstanceState(Bundle savedInstanceState) {
+ super.onRestoreInstanceState(savedInstanceState);
+ getSherlock().dispatchRestoreInstanceState(savedInstanceState);
+ }
///////////////////////////////////////////////////////////////////////////
// Native menu handling
diff --git a/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockFragmentActivity.java b/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockFragmentActivity.java index 5cd13ba7c..3d092f033 100644 --- a/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockFragmentActivity.java +++ b/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockFragmentActivity.java @@ -2,7 +2,7 @@ package com.actionbarsherlock.app; import android.content.res.Configuration; import android.os.Bundle; -import android.support.v4.app._ActionBarSherlockTrojanHorse; +import android.support.v4.app.Watson; import android.util.Log; import android.view.KeyEvent; import android.view.View; @@ -17,8 +17,8 @@ import com.actionbarsherlock.view.MenuItem; import static com.actionbarsherlock.ActionBarSherlock.OnActionModeFinishedListener; import static com.actionbarsherlock.ActionBarSherlock.OnActionModeStartedListener; -/** @see {@link _ActionBarSherlockTrojanHorse} */ -public class SherlockFragmentActivity extends _ActionBarSherlockTrojanHorse implements OnActionModeStartedListener, OnActionModeFinishedListener { +/** @see {@link android.support.v4.app.Watson} */ +public class SherlockFragmentActivity extends Watson implements OnActionModeStartedListener, OnActionModeFinishedListener { private static final boolean DEBUG = false; private static final String TAG = "SherlockFragmentActivity"; @@ -122,6 +122,17 @@ public class SherlockFragmentActivity extends _ActionBarSherlockTrojanHorse impl return super.dispatchKeyEvent(event); } + @Override + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + getSherlock().dispatchSaveInstanceState(outState); + } + + @Override + protected void onRestoreInstanceState(Bundle savedInstanceState) { + super.onRestoreInstanceState(savedInstanceState); + getSherlock().dispatchRestoreInstanceState(savedInstanceState); + } /////////////////////////////////////////////////////////////////////////// // Native menu handling diff --git a/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockListActivity.java b/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockListActivity.java index 00c00fee5..aba6d85e8 100644 --- a/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockListActivity.java +++ b/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockListActivity.java @@ -116,6 +116,17 @@ public abstract class SherlockListActivity extends ListActivity implements OnCre return super.dispatchKeyEvent(event);
}
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ getSherlock().dispatchSaveInstanceState(outState);
+ }
+
+ @Override
+ protected void onRestoreInstanceState(Bundle savedInstanceState) {
+ super.onRestoreInstanceState(savedInstanceState);
+ getSherlock().dispatchRestoreInstanceState(savedInstanceState);
+ }
///////////////////////////////////////////////////////////////////////////
// Native menu handling
diff --git a/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockPreferenceActivity.java b/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockPreferenceActivity.java index 4f80be515..bee72cb25 100644 --- a/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockPreferenceActivity.java +++ b/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockPreferenceActivity.java @@ -116,6 +116,17 @@ public abstract class SherlockPreferenceActivity extends PreferenceActivity impl return super.dispatchKeyEvent(event);
}
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ getSherlock().dispatchSaveInstanceState(outState);
+ }
+
+ @Override
+ protected void onRestoreInstanceState(Bundle savedInstanceState) {
+ super.onRestoreInstanceState(savedInstanceState);
+ getSherlock().dispatchRestoreInstanceState(savedInstanceState);
+ }
///////////////////////////////////////////////////////////////////////////
// Native menu handling
diff --git a/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/ActionBarSherlockCompat.java b/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/ActionBarSherlockCompat.java index 05353d28c..5e69275c7 100644 --- a/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/ActionBarSherlockCompat.java +++ b/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/ActionBarSherlockCompat.java @@ -52,6 +52,7 @@ public class ActionBarSherlockCompat extends ActionBarSherlock implements MenuBu /** Window features which are enabled by default. */ protected static final int DEFAULT_FEATURES = 0; + static private final String PANELS_TAG = "sherlock:Panels"; public ActionBarSherlockCompat(Activity activity, int flags) { super(activity, flags); @@ -71,8 +72,6 @@ public class ActionBarSherlockCompat extends ActionBarSherlock implements MenuBu private MenuBuilder mMenu; /** Map between native options items and sherlock items. */ protected HashMap<android.view.MenuItem, MenuItemImpl> mNativeItemMap; - /** Indication of a long-press on the hardware menu key. */ - private boolean mMenuKeyIsLongPress = false; /** Parent view of the window decoration (action bar, mode, etc.). */ private ViewGroup mDecor; @@ -293,7 +292,10 @@ public class ActionBarSherlockCompat extends ActionBarSherlock implements MenuBu return false; } - return wActionBar.hideOverflowMenu(); + if (wActionBar != null) { + return wActionBar.hideOverflowMenu(); + } + return false; } @Override @@ -424,27 +426,8 @@ public class ActionBarSherlockCompat extends ActionBarSherlock implements MenuBu } } - boolean result = false; - if (keyCode == KeyEvent.KEYCODE_MENU && isReservingOverflow()) { - if (event.getAction() == KeyEvent.ACTION_DOWN && event.isLongPress()) { - mMenuKeyIsLongPress = true; - } else if (event.getAction() == KeyEvent.ACTION_UP) { - if (!mMenuKeyIsLongPress) { - if (mActionMode == null && wActionBar != null) { - if (wActionBar.isOverflowMenuShowing()) { - wActionBar.hideOverflowMenu(); - } else { - wActionBar.showOverflowMenu(); - } - } - result = true; - } - mMenuKeyIsLongPress = false; - } - } - - if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning " + result); - return result; + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false"); + return false; } @Override @@ -452,6 +435,19 @@ public class ActionBarSherlockCompat extends ActionBarSherlock implements MenuBu mIsDestroyed = true; } + @Override + public void dispatchSaveInstanceState(Bundle outState) { + if (mMenu != null) { + mMenuFrozenActionViewState = new Bundle(); + mMenu.saveActionViewStates(mMenuFrozenActionViewState); + } + outState.putParcelable(PANELS_TAG, mMenuFrozenActionViewState); + } + + @Override + public void dispatchRestoreInstanceState(Bundle savedInstanceState) { + mMenuFrozenActionViewState = savedInstanceState.getParcelable(PANELS_TAG); + } /////////////////////////////////////////////////////////////////////////// // Menu callback lifecycle and creation diff --git a/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/ActionBarSherlockNative.java b/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/ActionBarSherlockNative.java index 9afca185a..0824d3848 100644 --- a/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/ActionBarSherlockNative.java +++ b/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/ActionBarSherlockNative.java @@ -208,7 +208,12 @@ public class ActionBarSherlockNative extends ActionBarSherlock { //is where we will set the new instance to mActionMode since we need //to pass it through to the sherlock callbacks and the call below //will not have returned yet to store its value. - mActivity.startActionMode(wrapped); + if (mActivity.startActionMode(wrapped) == null) { + mActionMode = null; + } + if (mActivity instanceof OnActionModeStartedListener && mActionMode != null) { + ((OnActionModeStartedListener)mActivity).onActionModeStarted(mActionMode); + } return mActionMode; } @@ -241,6 +246,9 @@ public class ActionBarSherlockNative extends ActionBarSherlock { @Override public void onDestroyActionMode(android.view.ActionMode mode) { mCallback.onDestroyActionMode(mActionMode); + if (mActivity instanceof OnActionModeFinishedListener) { + ((OnActionModeFinishedListener)mActivity).onActionModeFinished(mActionMode); + } } } diff --git a/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/app/ActionBarImpl.java b/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/app/ActionBarImpl.java index 6ae0402c0..d022a2465 100644 --- a/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/app/ActionBarImpl.java +++ b/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/app/ActionBarImpl.java @@ -26,6 +26,7 @@ import android.content.res.Resources; import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Handler; +import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentTransaction; import android.util.TypedValue; import android.view.ContextThemeWrapper; @@ -36,7 +37,6 @@ import android.view.accessibility.AccessibilityEvent; import android.widget.SpinnerAdapter; import com.actionbarsherlock.R; import com.actionbarsherlock.app.ActionBar; -import com.actionbarsherlock.app.SherlockFragmentActivity; import com.actionbarsherlock.internal.nineoldandroids.animation.Animator; import com.actionbarsherlock.internal.nineoldandroids.animation.AnimatorListenerAdapter; import com.actionbarsherlock.internal.nineoldandroids.animation.AnimatorSet; @@ -506,8 +506,8 @@ public class ActionBarImpl extends ActionBar { } FragmentTransaction trans = null; - if (mActivity instanceof SherlockFragmentActivity) { - trans = ((SherlockFragmentActivity)mActivity).getSupportFragmentManager().beginTransaction() + if (mActivity instanceof FragmentActivity) { + trans = ((FragmentActivity)mActivity).getSupportFragmentManager().beginTransaction() .disallowAddToBackStack(); } diff --git a/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/app/ActionBarWrapper.java b/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/app/ActionBarWrapper.java index e390ea428..840cb3d27 100644 --- a/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/app/ActionBarWrapper.java +++ b/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/app/ActionBarWrapper.java @@ -6,12 +6,12 @@ import java.util.Set; import android.app.Activity; import android.content.Context; import android.graphics.drawable.Drawable; +import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentTransaction; import android.view.View; import android.widget.SpinnerAdapter; import com.actionbarsherlock.app.ActionBar; -import com.actionbarsherlock.app.SherlockFragmentActivity; public class ActionBarWrapper extends ActionBar implements android.app.ActionBar.OnNavigationListener, android.app.ActionBar.OnMenuVisibilityListener { private final Activity mActivity; @@ -319,8 +319,8 @@ public class ActionBarWrapper extends ActionBar implements android.app.ActionBar public void onTabReselected(android.app.ActionBar.Tab tab, android.app.FragmentTransaction ft) { if (mListener != null) { FragmentTransaction trans = null; - if (mActivity instanceof SherlockFragmentActivity) { - trans = ((SherlockFragmentActivity)mActivity).getSupportFragmentManager().beginTransaction() + if (mActivity instanceof FragmentActivity) { + trans = ((FragmentActivity)mActivity).getSupportFragmentManager().beginTransaction() .disallowAddToBackStack(); } @@ -336,8 +336,8 @@ public class ActionBarWrapper extends ActionBar implements android.app.ActionBar public void onTabSelected(android.app.ActionBar.Tab tab, android.app.FragmentTransaction ft) { if (mListener != null) { - if (mFragmentTransaction == null && mActivity instanceof SherlockFragmentActivity) { - mFragmentTransaction = ((SherlockFragmentActivity)mActivity).getSupportFragmentManager().beginTransaction() + if (mFragmentTransaction == null && mActivity instanceof FragmentActivity) { + mFragmentTransaction = ((FragmentActivity)mActivity).getSupportFragmentManager().beginTransaction() .disallowAddToBackStack(); } @@ -356,8 +356,8 @@ public class ActionBarWrapper extends ActionBar implements android.app.ActionBar public void onTabUnselected(android.app.ActionBar.Tab tab, android.app.FragmentTransaction ft) { if (mListener != null) { FragmentTransaction trans = null; - if (mActivity instanceof SherlockFragmentActivity) { - trans = ((SherlockFragmentActivity)mActivity).getSupportFragmentManager().beginTransaction() + if (mActivity instanceof FragmentActivity) { + trans = ((FragmentActivity)mActivity).getSupportFragmentManager().beginTransaction() .disallowAddToBackStack(); mFragmentTransaction = trans; } diff --git a/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/widget/NineFrameLayout.java b/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/widget/NineFrameLayout.java index 2c428e907..953e3e844 100644 --- a/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/widget/NineFrameLayout.java +++ b/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/widget/NineFrameLayout.java @@ -9,18 +9,10 @@ import com.actionbarsherlock.internal.nineoldandroids.view.animation.AnimatorPro public class NineFrameLayout extends FrameLayout { private final AnimatorProxy mProxy; - public NineFrameLayout(Context context) { - super(context); - mProxy = AnimatorProxy.NEEDS_PROXY ? AnimatorProxy.wrap(this) : null; - } public NineFrameLayout(Context context, AttributeSet attrs) { super(context, attrs); mProxy = AnimatorProxy.NEEDS_PROXY ? AnimatorProxy.wrap(this) : null; } - public NineFrameLayout(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - mProxy = AnimatorProxy.NEEDS_PROXY ? AnimatorProxy.wrap(this) : null; - } @Override public void setVisibility(int visibility) { diff --git a/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/widget/NineLinearLayout.java b/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/widget/NineLinearLayout.java index a670b1f64..1f381013a 100644 --- a/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/widget/NineLinearLayout.java +++ b/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/widget/NineLinearLayout.java @@ -9,18 +9,10 @@ import com.actionbarsherlock.internal.nineoldandroids.view.animation.AnimatorPro public class NineLinearLayout extends LinearLayout { private final AnimatorProxy mProxy; - public NineLinearLayout(Context context) { - super(context); - mProxy = AnimatorProxy.NEEDS_PROXY ? AnimatorProxy.wrap(this) : null; - } public NineLinearLayout(Context context, AttributeSet attrs) { super(context, attrs); mProxy = AnimatorProxy.NEEDS_PROXY ? AnimatorProxy.wrap(this) : null; } - public NineLinearLayout(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - mProxy = AnimatorProxy.NEEDS_PROXY ? AnimatorProxy.wrap(this) : null; - } @Override public void setVisibility(int visibility) { diff --git a/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/ActionMenuPresenter.java b/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/ActionMenuPresenter.java index 6f568c698..876a22c58 100644 --- a/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/ActionMenuPresenter.java +++ b/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/ActionMenuPresenter.java @@ -23,7 +23,6 @@ import java.util.Set; import android.content.Context; import android.content.res.Configuration; import android.content.res.Resources; -import android.content.res.TypedArray; import android.os.Build; import android.os.Parcel; import android.os.Parcelable; @@ -119,14 +118,6 @@ public class ActionMenuPresenter extends BaseMenuPresenter } public static boolean reserveOverflow(Context context) { - //Check for theme-forced overflow action item - TypedArray a = context.getTheme().obtainStyledAttributes(R.styleable.SherlockTheme); - boolean result = a.getBoolean(R.styleable.SherlockTheme_absForceOverflow, false); - a.recycle(); - if (result) { - return true; - } - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) { return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB); } else { @@ -621,6 +612,8 @@ public class ActionMenuPresenter extends BaseMenuPresenter for (View_OnAttachStateChangeListener listener : mListeners) { listener.onViewDetachedFromWindow(this); } + + if (mOverflowPopup != null) mOverflowPopup.dismiss(); } @Override diff --git a/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/ActionMenuView.java b/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/ActionMenuView.java index e090677a1..0e3b1ae0d 100644 --- a/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/ActionMenuView.java +++ b/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/ActionMenuView.java @@ -520,6 +520,9 @@ public class ActionMenuView extends IcsLinearLayout implements MenuBuilder.ItemI //@Override protected boolean hasDividerBeforeChildAt(int childIndex) { + if (childIndex == 0) { + return false; + } final View childBefore = getChildAt(childIndex - 1); final View child = getChildAt(childIndex); boolean result = false; diff --git a/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuItemWrapper.java b/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuItemWrapper.java index 907a7aa04..aaf2997b7 100644 --- a/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuItemWrapper.java +++ b/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuItemWrapper.java @@ -2,10 +2,12 @@ package com.actionbarsherlock.internal.view.menu; import android.content.Intent; import android.graphics.drawable.Drawable; -import android.view.View; import android.view.ContextMenu.ContextMenuInfo; +import android.view.View; import com.actionbarsherlock.internal.view.ActionProviderWrapper; +import com.actionbarsherlock.internal.widget.CollapsibleActionViewWrapper; import com.actionbarsherlock.view.ActionProvider; +import com.actionbarsherlock.view.CollapsibleActionView; import com.actionbarsherlock.view.MenuItem; import com.actionbarsherlock.view.SubMenu; @@ -215,19 +217,35 @@ public class MenuItemWrapper implements MenuItem, android.view.MenuItem.OnMenuIt @Override public MenuItem setActionView(View view) { + if (view != null && view instanceof CollapsibleActionView) { + view = new CollapsibleActionViewWrapper(view); + } mNativeItem.setActionView(view); return this; } @Override public MenuItem setActionView(int resId) { + //Allow the native menu to inflate the resource mNativeItem.setActionView(resId); + if (resId != 0) { + //Get newly created view + View view = mNativeItem.getActionView(); + if (view instanceof CollapsibleActionView) { + //Wrap it and re-set it + mNativeItem.setActionView(new CollapsibleActionViewWrapper(view)); + } + } return this; } @Override public View getActionView() { - return mNativeItem.getActionView(); + View actionView = mNativeItem.getActionView(); + if (actionView instanceof CollapsibleActionViewWrapper) { + return ((CollapsibleActionViewWrapper)actionView).unwrap(); + } + return actionView; } @Override diff --git a/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuWrapper.java b/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuWrapper.java index 64fc4aeaa..3d4dd42fd 100644 --- a/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuWrapper.java +++ b/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuWrapper.java @@ -79,10 +79,15 @@ public class MenuWrapper implements Menu { @Override public int addIntentOptions(int groupId, int itemId, int order, ComponentName caller, Intent[] specifics, Intent intent, int flags, MenuItem[] outSpecificItems) { - android.view.MenuItem[] nativeOutItems = new android.view.MenuItem[outSpecificItems.length]; - int result = mNativeMenu.addIntentOptions(groupId, itemId, order, caller, specifics, intent, flags, nativeOutItems); - for (int i = 0, length = outSpecificItems.length; i < length; i++) { - outSpecificItems[i] = new MenuItemWrapper(nativeOutItems[i]); + int result; + if (outSpecificItems != null) { + android.view.MenuItem[] nativeOutItems = new android.view.MenuItem[outSpecificItems.length]; + result = mNativeMenu.addIntentOptions(groupId, itemId, order, caller, specifics, intent, flags, nativeOutItems); + for (int i = 0, length = outSpecificItems.length; i < length; i++) { + outSpecificItems[i] = new MenuItemWrapper(nativeOutItems[i]); + } + } else { + result = mNativeMenu.addIntentOptions(groupId, itemId, order, caller, specifics, intent, flags, null); } return result; } diff --git a/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/ActionBarContainer.java b/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/ActionBarContainer.java index 5e5aa2867..1d9c68b37 100644 --- a/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/ActionBarContainer.java +++ b/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/ActionBarContainer.java @@ -18,8 +18,11 @@ package com.actionbarsherlock.internal.widget; import android.content.Context; import android.content.res.TypedArray; +import android.graphics.Bitmap; import android.graphics.Canvas; +import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; +import android.os.Build; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; @@ -60,6 +63,16 @@ public class ActionBarContainer extends NineFrameLayout { mStackedBackground = a.getDrawable( R.styleable.SherlockActionBar_backgroundStacked); + //Fix for issue #379 + if (mStackedBackground instanceof ColorDrawable && Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { + Bitmap bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888); + Canvas c = new Canvas(bitmap); + mStackedBackground.draw(c); + int color = bitmap.getPixel(0, 0); + bitmap.recycle(); + mStackedBackground = new IcsColorDrawable(color); + } + if (getId() == R.id.abs__split_action_bar) { mIsSplit = true; mSplitBackground = a.getDrawable( diff --git a/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/CapitalizingTextView.java b/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/CapitalizingTextView.java index 673ec554f..cae8b8aed 100644 --- a/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/CapitalizingTextView.java +++ b/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/CapitalizingTextView.java @@ -1,12 +1,13 @@ package com.actionbarsherlock.internal.widget; -import java.util.Locale; import android.content.Context; import android.content.res.TypedArray; import android.os.Build; import android.util.AttributeSet; import android.widget.TextView; +import java.util.Locale; + public class CapitalizingTextView extends TextView { private static final boolean SANS_ICE_CREAM = Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH; private static final boolean IS_GINGERBREAD = Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD; @@ -33,7 +34,12 @@ public class CapitalizingTextView extends TextView { public void setTextCompat(CharSequence text) { if (SANS_ICE_CREAM && mAllCaps && text != null) { if (IS_GINGERBREAD) { - setText(text.toString().toUpperCase(Locale.ROOT)); + try { + setText(text.toString().toUpperCase(Locale.ROOT)); + } catch (NoSuchFieldError e) { + //Some manufacturer broke Locale.ROOT. See #572. + setText(text.toString().toUpperCase()); + } } else { setText(text.toString().toUpperCase()); } diff --git a/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/CollapsibleActionViewWrapper.java b/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/CollapsibleActionViewWrapper.java new file mode 100644 index 000000000..14f092c81 --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/CollapsibleActionViewWrapper.java @@ -0,0 +1,30 @@ +package com.actionbarsherlock.internal.widget; + +import android.view.View; +import android.widget.FrameLayout; +import com.actionbarsherlock.view.CollapsibleActionView; + +/** + * Wraps an ABS collapsible action view in a native container that delegates the calls. + */ +public class CollapsibleActionViewWrapper extends FrameLayout implements android.view.CollapsibleActionView { + private final CollapsibleActionView child; + + public CollapsibleActionViewWrapper(View child) { + super(child.getContext()); + this.child = (CollapsibleActionView) child; + addView(child); + } + + @Override public void onActionViewExpanded() { + child.onActionViewExpanded(); + } + + @Override public void onActionViewCollapsed() { + child.onActionViewCollapsed(); + } + + public View unwrap() { + return getChildAt(0); + } +} diff --git a/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsColorDrawable.java b/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsColorDrawable.java new file mode 100644 index 000000000..a78b3f71b --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsColorDrawable.java @@ -0,0 +1,41 @@ +package com.actionbarsherlock.internal.widget; + +import android.graphics.Canvas; +import android.graphics.ColorFilter; +import android.graphics.Paint; +import android.graphics.drawable.Drawable; + +/** + * A version of {@link android.graphics.drawable.ColorDrawable} that respects bounds. + */ +public class IcsColorDrawable extends Drawable { + private int color; + private final Paint paint = new Paint(); + + public IcsColorDrawable(int color) { + this.color = color; + } + + @Override public void draw(Canvas canvas) { + if ((color >>> 24) != 0) { + paint.setColor(color); + canvas.drawRect(getBounds(), paint); + } + } + + @Override + public void setAlpha(int alpha) { + if (alpha != (color >>> 24)) { + color = (color & 0x00FFFFFF) & (alpha << 24); + invalidateSelf(); + } + } + + @Override public void setColorFilter(ColorFilter colorFilter) { + //Ignored + } + + @Override public int getOpacity() { + return color >>> 24; + } +} diff --git a/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsLinearLayout.java b/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsLinearLayout.java index 1b4463a59..4947c41df 100644 --- a/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsLinearLayout.java +++ b/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsLinearLayout.java @@ -6,6 +6,8 @@ import android.graphics.Canvas; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.view.View; +import android.widget.LinearLayout; + import com.actionbarsherlock.internal.nineoldandroids.widget.NineLinearLayout; /** @@ -16,14 +18,16 @@ import com.actionbarsherlock.internal.nineoldandroids.widget.NineLinearLayout; * {@link android.widget.FrameLayout} so it can receive the margin. */ public class IcsLinearLayout extends NineLinearLayout { - private static final int[] LinearLayout = new int[] { + private static final int[] R_styleable_LinearLayout = new int[] { /* 0 */ android.R.attr.divider, - /* 1 */ android.R.attr.showDividers, - /* 2 */ android.R.attr.dividerPadding, + /* 1 */ android.R.attr.measureWithLargestChild, + /* 2 */ android.R.attr.showDividers, + /* 3 */ android.R.attr.dividerPadding, }; private static final int LinearLayout_divider = 0; - private static final int LinearLayout_showDividers = 1; - private static final int LinearLayout_dividerPadding = 2; + private static final int LinearLayout_measureWithLargestChild = 1; + private static final int LinearLayout_showDividers = 2; + private static final int LinearLayout_dividerPadding = 3; /** * Don't show any dividers. @@ -49,15 +53,17 @@ public class IcsLinearLayout extends NineLinearLayout { private int mShowDividers; private int mDividerPadding; + private boolean mUseLargestChild; public IcsLinearLayout(Context context, AttributeSet attrs) { super(context, attrs); - TypedArray a = context.obtainStyledAttributes(attrs, /*com.android.internal.R.styleable.*/LinearLayout); + TypedArray a = context.obtainStyledAttributes(attrs, /*com.android.internal.R.styleable.*/R_styleable_LinearLayout); setDividerDrawable(a.getDrawable(/*com.android.internal.R.styleable.*/LinearLayout_divider)); mShowDividers = a.getInt(/*com.android.internal.R.styleable.*/LinearLayout_showDividers, SHOW_DIVIDER_NONE); mDividerPadding = a.getDimensionPixelSize(/*com.android.internal.R.styleable.*/LinearLayout_dividerPadding, 0); + mUseLargestChild = a.getBoolean(/*com.android.internal.R.styleable.*/LinearLayout_measureWithLargestChild, false); a.recycle(); } @@ -199,7 +205,7 @@ public class IcsLinearLayout extends NineLinearLayout { if (child == null) { bottom = getHeight() - getPaddingBottom() - mDividerHeight; } else { - final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + //final LayoutParams lp = (LayoutParams) child.getLayoutParams(); bottom = child.getBottom()/* + lp.bottomMargin*/; } drawHorizontalDivider(canvas, bottom); @@ -226,7 +232,7 @@ public class IcsLinearLayout extends NineLinearLayout { if (child == null) { right = getWidth() - getPaddingRight() - mDividerWidth; } else { - final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + //final LayoutParams lp = (LayoutParams) child.getLayoutParams(); right = child.getRight()/* + lp.rightMargin*/; } drawVerticalDivider(canvas, right); @@ -269,4 +275,136 @@ public class IcsLinearLayout extends NineLinearLayout { } return false; } + + /** + * When true, all children with a weight will be considered having + * the minimum size of the largest child. If false, all children are + * measured normally. + * + * @return True to measure children with a weight using the minimum + * size of the largest child, false otherwise. + * + * @attr ref android.R.styleable#LinearLayout_measureWithLargestChild + */ + public boolean isMeasureWithLargestChildEnabled() { + return mUseLargestChild; + } + + /** + * When set to true, all children with a weight will be considered having + * the minimum size of the largest child. If false, all children are + * measured normally. + * + * Disabled by default. + * + * @param enabled True to measure children with a weight using the + * minimum size of the largest child, false otherwise. + * + * @attr ref android.R.styleable#LinearLayout_measureWithLargestChild + */ + public void setMeasureWithLargestChildEnabled(boolean enabled) { + mUseLargestChild = enabled; + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + + if (mUseLargestChild) { + final int orientation = getOrientation(); + switch (orientation) { + case HORIZONTAL: + useLargestChildHorizontal(); + break; + + case VERTICAL: + useLargestChildVertical(); + break; + } + } + } + + private void useLargestChildHorizontal() { + final int childCount = getChildCount(); + + // Find largest child width + int largestChildWidth = 0; + for (int i = 0; i < childCount; i++) { + final View child = getChildAt(i); + largestChildWidth = Math.max(child.getMeasuredWidth(), largestChildWidth); + } + + int totalWidth = 0; + // Re-measure childs + for (int i = 0; i < childCount; i++) { + final View child = getChildAt(i); + + if (child == null || child.getVisibility() == View.GONE) { + continue; + } + + final LinearLayout.LayoutParams lp = + (LinearLayout.LayoutParams) child.getLayoutParams(); + + float childExtra = lp.weight; + if (childExtra > 0) { + child.measure( + MeasureSpec.makeMeasureSpec(largestChildWidth, + MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec(child.getMeasuredHeight(), + MeasureSpec.EXACTLY)); + totalWidth += largestChildWidth; + + } else { + totalWidth += child.getMeasuredWidth(); + } + + totalWidth += lp.leftMargin + lp.rightMargin; + } + + totalWidth += getPaddingLeft() + getPaddingRight(); + setMeasuredDimension(totalWidth, getMeasuredHeight()); + } + + private void useLargestChildVertical() { + final int childCount = getChildCount(); + + // Find largest child width + int largestChildHeight = 0; + for (int i = 0; i < childCount; i++) { + final View child = getChildAt(i); + largestChildHeight = Math.max(child.getMeasuredHeight(), largestChildHeight); + } + + int totalHeight = 0; + // Re-measure childs + for (int i = 0; i < childCount; i++) { + final View child = getChildAt(i); + + if (child == null || child.getVisibility() == View.GONE) { + continue; + } + + final LinearLayout.LayoutParams lp = + (LinearLayout.LayoutParams) child.getLayoutParams(); + + float childExtra = lp.weight; + if (childExtra > 0) { + child.measure( + MeasureSpec.makeMeasureSpec(child.getMeasuredWidth(), + MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec(largestChildHeight, + MeasureSpec.EXACTLY)); + totalHeight += largestChildHeight; + + } else { + totalHeight += child.getMeasuredHeight(); + } + + totalHeight += lp.leftMargin + lp.rightMargin; + } + + totalHeight += getPaddingLeft() + getPaddingRight(); + setMeasuredDimension(getMeasuredWidth(), totalHeight); + } } diff --git a/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/ScrollingTabContainerView.java b/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/ScrollingTabContainerView.java index 1a532e06c..48fb5d8b4 100644 --- a/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/ScrollingTabContainerView.java +++ b/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/ScrollingTabContainerView.java @@ -188,6 +188,7 @@ public class ScrollingTabContainerView extends NineHorizontalScrollView private IcsLinearLayout createTabLayout() { final IcsLinearLayout tabLayout = (IcsLinearLayout) LayoutInflater.from(getContext()) .inflate(R.layout.abs__action_bar_tab_bar_view, null); + tabLayout.setMeasureWithLargestChildEnabled(true); tabLayout.setLayoutParams(new LinearLayout.LayoutParams( LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT)); return tabLayout; diff --git a/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/view/MenuInflater.java b/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/view/MenuInflater.java index 969459749..5a0f40859 100644 --- a/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/view/MenuInflater.java +++ b/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/view/MenuInflater.java @@ -67,6 +67,7 @@ public class MenuInflater { private final Object[] mActionProviderConstructorArguments;
private Context mContext;
+ private Object mRealOwner;
/**
* Constructs a menu inflater.
@@ -75,6 +76,20 @@ public class MenuInflater { */
public MenuInflater(Context context) {
mContext = context;
+ mRealOwner = context;
+ mActionViewConstructorArguments = new Object[] {context};
+ mActionProviderConstructorArguments = mActionViewConstructorArguments;
+ }
+
+ /**
+ * Constructs a menu inflater.
+ *
+ * @see Activity#getMenuInflater()
+ * @hide
+ */
+ public MenuInflater(Context context, Object realOwner) {
+ mContext = context;
+ mRealOwner = realOwner;
mActionViewConstructorArguments = new Object[] {context};
mActionProviderConstructorArguments = mActionViewConstructorArguments;
}
@@ -192,12 +207,12 @@ public class MenuInflater { implements MenuItem.OnMenuItemClickListener {
private static final Class<?>[] PARAM_TYPES = new Class[] { MenuItem.class };
- private Context mContext;
+ private Object mRealOwner;
private Method mMethod;
- public InflatedOnMenuItemClickListener(Context context, String methodName) {
- mContext = context;
- Class<?> c = context.getClass();
+ public InflatedOnMenuItemClickListener(Object realOwner, String methodName) {
+ mRealOwner = realOwner;
+ Class<?> c = realOwner.getClass();
try {
mMethod = c.getMethod(methodName, PARAM_TYPES);
} catch (Exception e) {
@@ -212,9 +227,9 @@ public class MenuInflater { public boolean onMenuItemClick(MenuItem item) {
try {
if (mMethod.getReturnType() == Boolean.TYPE) {
- return (Boolean) mMethod.invoke(mContext, item);
+ return (Boolean) mMethod.invoke(mRealOwner, item);
} else {
- mMethod.invoke(mContext, item);
+ mMethod.invoke(mRealOwner, item);
return true;
}
} catch (Exception e) {
@@ -358,8 +373,16 @@ public class MenuInflater { itemListenerMethodName = a.getString(R.styleable.SherlockMenuItem_android_onClick);
itemActionViewLayout = a.getResourceId(R.styleable.SherlockMenuItem_android_actionLayout, 0);
- itemActionViewClassName = a.getString(R.styleable.SherlockMenuItem_android_actionViewClass);
- itemActionProviderClassName = a.getString(R.styleable.SherlockMenuItem_android_actionProviderClass);
+
+ // itemActionViewClassName = a.getString(R.styleable.SherlockMenuItem_android_actionViewClass);
+ value = new TypedValue();
+ a.getValue(R.styleable.SherlockMenuItem_android_actionViewClass, value);
+ itemActionViewClassName = value.type == TypedValue.TYPE_STRING ? value.string.toString() : null;
+
+ // itemActionProviderClassName = a.getString(R.styleable.SherlockMenuItem_android_actionProviderClass);
+ value = new TypedValue();
+ a.getValue(R.styleable.SherlockMenuItem_android_actionProviderClass, value);
+ itemActionProviderClassName = value.type == TypedValue.TYPE_STRING ? value.string.toString() : null;
final boolean hasActionProvider = itemActionProviderClassName != null;
if (hasActionProvider && itemActionViewLayout == 0 && itemActionViewClassName == null) {
@@ -407,7 +430,7 @@ public class MenuInflater { + "be used within a restricted context");
}
item.setOnMenuItemClickListener(
- new InflatedOnMenuItemClickListener(mContext, itemListenerMethodName));
+ new InflatedOnMenuItemClickListener(mRealOwner, itemListenerMethodName));
}
if (itemCheckable >= 2) {
diff --git a/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/widget/ActivityChooserModel.java b/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/widget/ActivityChooserModel.java index 379207471..d7f110fc6 100644 --- a/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/widget/ActivityChooserModel.java +++ b/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/widget/ActivityChooserModel.java @@ -25,7 +25,6 @@ import android.os.Handler; import android.text.TextUtils; import android.util.Log; import android.util.Xml; - import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; @@ -39,11 +38,11 @@ import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashSet; -import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.Executor; +import java.util.concurrent.Executors; /** * <p> @@ -562,33 +561,7 @@ class ActivityChooserModel extends DataSetObservable { } } - private static final SerialExecutor SERIAL_EXECUTOR = new SerialExecutor(); - - private static class SerialExecutor implements Executor { - final LinkedList<Runnable> mTasks = new LinkedList<Runnable>(); - Runnable mActive; - - public synchronized void execute(final Runnable r) { - mTasks.offer(new Runnable() { - public void run() { - try { - r.run(); - } finally { - scheduleNext(); - } - } - }); - if (mActive == null) { - scheduleNext(); - } - } - - protected synchronized void scheduleNext() { - if ((mActive = mTasks.poll()) != null) { - mActive.run(); - } - } - } + private static final Executor SERIAL_EXECUTOR = Executors.newSingleThreadExecutor(); /** * Persists the history data to the backing file if the latter diff --git a/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/widget/ActivityChooserView.java b/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/widget/ActivityChooserView.java index da13bc99f..e19ea9e9e 100644 --- a/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/widget/ActivityChooserView.java +++ b/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/widget/ActivityChooserView.java @@ -405,7 +405,11 @@ class ActivityChooserView extends ViewGroup implements ActivityChooserModelClien super.onDetachedFromWindow(); ActivityChooserModel dataModel = mAdapter.getDataModel(); if (dataModel != null) { - dataModel.unregisterObserver(mModelDataSetOberver); + try { + dataModel.unregisterObserver(mModelDataSetOberver); + } catch (IllegalStateException e) { + //Oh, well... fixes issue #557 + } } ViewTreeObserver viewTreeObserver = getViewTreeObserver(); if (viewTreeObserver.isAlive()) { @@ -526,6 +530,7 @@ class ActivityChooserView extends ViewGroup implements ActivityChooserModelClien mActivityChooserContent.setBackgroundDrawable(mActivityChooserContentBackground); } else { mActivityChooserContent.setBackgroundDrawable(null); + mActivityChooserContent.setPadding(0, 0, 0, 0); } } @@ -648,7 +653,11 @@ class ActivityChooserView extends ViewGroup implements ActivityChooserModelClien public void setDataModel(ActivityChooserModel dataModel) { ActivityChooserModel oldDataModel = mAdapter.getDataModel(); if (oldDataModel != null && isShown()) { - oldDataModel.unregisterObserver(mModelDataSetOberver); + try { + oldDataModel.unregisterObserver(mModelDataSetOberver); + } catch (IllegalStateException e) { + //Oh, well... fixes issue #557 + } } mDataModel = dataModel; if (dataModel != null && isShown()) { diff --git a/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/widget/SearchView.java b/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/widget/SearchView.java new file mode 100644 index 000000000..c9e7897d4 --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/widget/SearchView.java @@ -0,0 +1,1811 @@ +/* + * 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. + */ + +package com.actionbarsherlock.widget; + +import android.app.PendingIntent; +import android.app.SearchManager; +import android.app.SearchableInfo; +import android.content.ActivityNotFoundException; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.database.Cursor; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.net.Uri; +import android.os.Build; +import android.os.Bundle; +import android.os.ResultReceiver; +import android.speech.RecognizerIntent; +import android.support.v4.view.KeyEventCompat; +import android.support.v4.widget.CursorAdapter; +import android.text.Editable; +import android.text.InputType; +import android.text.Spannable; +import android.text.SpannableStringBuilder; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.text.style.ImageSpan; +import android.util.AttributeSet; +import android.util.Log; +import android.util.TypedValue; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewTreeObserver; +import android.view.accessibility.AccessibilityEvent; +import android.view.accessibility.AccessibilityNodeInfo; +import android.view.inputmethod.EditorInfo; +import android.view.inputmethod.InputMethodManager; +import android.widget.AdapterView; +import android.widget.AdapterView.OnItemClickListener; +import android.widget.AdapterView.OnItemSelectedListener; +import android.widget.AutoCompleteTextView; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.TextView; +import android.widget.TextView.OnEditorActionListener; +import com.actionbarsherlock.R; +import com.actionbarsherlock.view.CollapsibleActionView; + +import java.lang.reflect.Method; +import java.util.WeakHashMap; + +import static com.actionbarsherlock.widget.SuggestionsAdapter.getColumnString; + +/** + * A widget that provides a user interface for the user to enter a search query and submit a request + * to a search provider. Shows a list of query suggestions or results, if available, and allows the + * user to pick a suggestion or result to launch into. + * + * <p> + * When the SearchView is used in an ActionBar as an action view for a collapsible menu item, it + * needs to be set to iconified by default using {@link #setIconifiedByDefault(boolean) + * setIconifiedByDefault(true)}. This is the default, so nothing needs to be done. + * </p> + * <p> + * If you want the search field to always be visible, then call setIconifiedByDefault(false). + * </p> + * + * <div class="special reference"> + * <h3>Developer Guides</h3> + * <p>For information about using {@code SearchView}, read the + * <a href="{@docRoot}guide/topics/search/index.html">Search</a> developer guide.</p> + * </div> + * + * @see android.view.MenuItem#SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW + * @attr ref android.R.styleable#SearchView_iconifiedByDefault + * @attr ref android.R.styleable#SearchView_imeOptions + * @attr ref android.R.styleable#SearchView_inputType + * @attr ref android.R.styleable#SearchView_maxWidth + * @attr ref android.R.styleable#SearchView_queryHint + */ +public class SearchView extends LinearLayout implements CollapsibleActionView { + + private static final boolean DBG = false; + private static final String LOG_TAG = "SearchView"; + + /** + * Private constant for removing the microphone in the keyboard. + */ + private static final String IME_OPTION_NO_MICROPHONE = "nm"; + + private OnQueryTextListener mOnQueryChangeListener; + private OnCloseListener mOnCloseListener; + private OnFocusChangeListener mOnQueryTextFocusChangeListener; + private OnSuggestionListener mOnSuggestionListener; + private OnClickListener mOnSearchClickListener; + + private boolean mIconifiedByDefault; + private boolean mIconified; + private CursorAdapter mSuggestionsAdapter; + private View mSearchButton; + private View mSubmitButton; + private View mSearchPlate; + private View mSubmitArea; + private ImageView mCloseButton; + private View mSearchEditFrame; + private View mVoiceButton; + private SearchAutoComplete mQueryTextView; + private View mDropDownAnchor; + private ImageView mSearchHintIcon; + private boolean mSubmitButtonEnabled; + private CharSequence mQueryHint; + private boolean mQueryRefinement; + private boolean mClearingFocus; + private int mMaxWidth; + private boolean mVoiceButtonEnabled; + private CharSequence mOldQueryText; + private CharSequence mUserQuery; + private boolean mExpandedInActionView; + private int mCollapsedImeOptions; + + private SearchableInfo mSearchable; + private Bundle mAppSearchData; + + /* + * SearchView can be set expanded before the IME is ready to be shown during + * initial UI setup. The show operation is asynchronous to account for this. + */ + private Runnable mShowImeRunnable = new Runnable() { + public void run() { + InputMethodManager imm = (InputMethodManager) + getContext().getSystemService(Context.INPUT_METHOD_SERVICE); + + if (imm != null) { + showSoftInputUnchecked(SearchView.this, imm, 0); + } + } + }; + + private Runnable mUpdateDrawableStateRunnable = new Runnable() { + public void run() { + updateFocusedState(); + } + }; + + private Runnable mReleaseCursorRunnable = new Runnable() { + public void run() { + if (mSuggestionsAdapter != null && mSuggestionsAdapter instanceof SuggestionsAdapter) { + mSuggestionsAdapter.changeCursor(null); + } + } + }; + + // For voice searching + private final Intent mVoiceWebSearchIntent; + private final Intent mVoiceAppSearchIntent; + + // A weak map of drawables we've gotten from other packages, so we don't load them + // more than once. + private final WeakHashMap<String, Drawable.ConstantState> mOutsideDrawablesCache = + new WeakHashMap<String, Drawable.ConstantState>(); + + /** + * Callbacks for changes to the query text. + */ + public interface OnQueryTextListener { + + /** + * Called when the user submits the query. This could be due to a key press on the + * keyboard or due to pressing a submit button. + * The listener can override the standard behavior by returning true + * to indicate that it has handled the submit request. Otherwise return false to + * let the SearchView handle the submission by launching any associated intent. + * + * @param query the query text that is to be submitted + * + * @return true if the query has been handled by the listener, false to let the + * SearchView perform the default action. + */ + boolean onQueryTextSubmit(String query); + + /** + * Called when the query text is changed by the user. + * + * @param newText the new content of the query text field. + * + * @return false if the SearchView should perform the default action of showing any + * suggestions if available, true if the action was handled by the listener. + */ + boolean onQueryTextChange(String newText); + } + + public interface OnCloseListener { + + /** + * The user is attempting to close the SearchView. + * + * @return true if the listener wants to override the default behavior of clearing the + * text field and dismissing it, false otherwise. + */ + boolean onClose(); + } + + /** + * Callback interface for selection events on suggestions. These callbacks + * are only relevant when a SearchableInfo has been specified by {@link #setSearchableInfo}. + */ + public interface OnSuggestionListener { + + /** + * Called when a suggestion was selected by navigating to it. + * @param position the absolute position in the list of suggestions. + * + * @return true if the listener handles the event and wants to override the default + * behavior of possibly rewriting the query based on the selected item, false otherwise. + */ + boolean onSuggestionSelect(int position); + + /** + * Called when a suggestion was clicked. + * @param position the absolute position of the clicked item in the list of suggestions. + * + * @return true if the listener handles the event and wants to override the default + * behavior of launching any intent or submitting a search query specified on that item. + * Return false otherwise. + */ + boolean onSuggestionClick(int position); + } + + public SearchView(Context context) { + this(context, null); + } + + public SearchView(Context context, AttributeSet attrs) { + super(context, attrs); + + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.FROYO) { + throw new IllegalStateException("SearchView is API 8+ only."); + } + + LayoutInflater inflater = (LayoutInflater) context + .getSystemService(Context.LAYOUT_INFLATER_SERVICE); + inflater.inflate(R.layout.abs__search_view, this, true); + + mSearchButton = findViewById(R.id.abs__search_button); + mQueryTextView = (SearchAutoComplete) findViewById(R.id.abs__search_src_text); + mQueryTextView.setSearchView(this); + + mSearchEditFrame = findViewById(R.id.abs__search_edit_frame); + mSearchPlate = findViewById(R.id.abs__search_plate); + mSubmitArea = findViewById(R.id.abs__submit_area); + mSubmitButton = findViewById(R.id.abs__search_go_btn); + mCloseButton = (ImageView) findViewById(R.id.abs__search_close_btn); + mVoiceButton = findViewById(R.id.abs__search_voice_btn); + mSearchHintIcon = (ImageView) findViewById(R.id.abs__search_mag_icon); + + mSearchButton.setOnClickListener(mOnClickListener); + mCloseButton.setOnClickListener(mOnClickListener); + mSubmitButton.setOnClickListener(mOnClickListener); + mVoiceButton.setOnClickListener(mOnClickListener); + mQueryTextView.setOnClickListener(mOnClickListener); + + mQueryTextView.addTextChangedListener(mTextWatcher); + mQueryTextView.setOnEditorActionListener(mOnEditorActionListener); + mQueryTextView.setOnItemClickListener(mOnItemClickListener); + mQueryTextView.setOnItemSelectedListener(mOnItemSelectedListener); + mQueryTextView.setOnKeyListener(mTextKeyListener); + // Inform any listener of focus changes + mQueryTextView.setOnFocusChangeListener(new OnFocusChangeListener() { + + public void onFocusChange(View v, boolean hasFocus) { + if (mOnQueryTextFocusChangeListener != null) { + mOnQueryTextFocusChangeListener.onFocusChange(SearchView.this, hasFocus); + } + } + }); + + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SherlockSearchView, 0, 0); + setIconifiedByDefault(a.getBoolean(R.styleable.SherlockSearchView_iconifiedByDefault, true)); + int maxWidth = a.getDimensionPixelSize(R.styleable.SherlockSearchView_android_maxWidth, -1); + if (maxWidth != -1) { + setMaxWidth(maxWidth); + } + CharSequence queryHint = a.getText(R.styleable.SherlockSearchView_queryHint); + if (!TextUtils.isEmpty(queryHint)) { + setQueryHint(queryHint); + } + int imeOptions = a.getInt(R.styleable.SherlockSearchView_android_imeOptions, -1); + if (imeOptions != -1) { + setImeOptions(imeOptions); + } + int inputType = a.getInt(R.styleable.SherlockSearchView_android_inputType, -1); + if (inputType != -1) { + setInputType(inputType); + } + + a.recycle(); + + boolean focusable = true; + + a = context.obtainStyledAttributes(attrs, R.styleable.SherlockView, 0, 0); + focusable = a.getBoolean(R.styleable.SherlockView_android_focusable, focusable); + a.recycle(); + setFocusable(focusable); + + // Save voice intent for later queries/launching + mVoiceWebSearchIntent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH); + mVoiceWebSearchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + mVoiceWebSearchIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, + RecognizerIntent.LANGUAGE_MODEL_WEB_SEARCH); + + mVoiceAppSearchIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); + mVoiceAppSearchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + + mDropDownAnchor = findViewById(mQueryTextView.getDropDownAnchor()); + if (mDropDownAnchor != null) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + mDropDownAnchor.addOnLayoutChangeListener(new OnLayoutChangeListener() { + @Override + public void onLayoutChange(View v, int left, int top, int right, int bottom, + int oldLeft, int oldTop, int oldRight, int oldBottom) { + adjustDropDownSizeAndPosition(); + } + }); + } else { + mDropDownAnchor.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { + @Override public void onGlobalLayout() { + adjustDropDownSizeAndPosition(); + } + }); + } + } + + updateViewsVisibility(mIconifiedByDefault); + updateQueryHint(); + } + + /** + * Sets the SearchableInfo for this SearchView. Properties in the SearchableInfo are used + * to display labels, hints, suggestions, create intents for launching search results screens + * and controlling other affordances such as a voice button. + * + * @param searchable a SearchableInfo can be retrieved from the SearchManager, for a specific + * activity or a global search provider. + */ + public void setSearchableInfo(SearchableInfo searchable) { + mSearchable = searchable; + if (mSearchable != null) { + updateSearchAutoComplete(); + updateQueryHint(); + } + // Cache the voice search capability + mVoiceButtonEnabled = hasVoiceSearch(); + + if (mVoiceButtonEnabled) { + // Disable the microphone on the keyboard, as a mic is displayed near the text box + // TODO: use imeOptions to disable voice input when the new API will be available + mQueryTextView.setPrivateImeOptions(IME_OPTION_NO_MICROPHONE); + } + updateViewsVisibility(isIconified()); + } + + /** + * Sets the APP_DATA for legacy SearchDialog use. + * @param appSearchData bundle provided by the app when launching the search dialog + * @hide + */ + public void setAppSearchData(Bundle appSearchData) { + mAppSearchData = appSearchData; + } + + /** + * Sets the IME options on the query text field. + * + * @see TextView#setImeOptions(int) + * @param imeOptions the options to set on the query text field + * + * @attr ref android.R.styleable#SearchView_imeOptions + */ + public void setImeOptions(int imeOptions) { + mQueryTextView.setImeOptions(imeOptions); + } + + /** + * Returns the IME options set on the query text field. + * @return the ime options + * @see TextView#setImeOptions(int) + * + * @attr ref android.R.styleable#SearchView_imeOptions + */ + public int getImeOptions() { + return mQueryTextView.getImeOptions(); + } + + /** + * Sets the input type on the query text field. + * + * @see TextView#setInputType(int) + * @param inputType the input type to set on the query text field + * + * @attr ref android.R.styleable#SearchView_inputType + */ + public void setInputType(int inputType) { + mQueryTextView.setInputType(inputType); + } + + /** + * Returns the input type set on the query text field. + * @return the input type + * + * @attr ref android.R.styleable#SearchView_inputType + */ + public int getInputType() { + return mQueryTextView.getInputType(); + } + + /** @hide */ + @Override + public boolean requestFocus(int direction, Rect previouslyFocusedRect) { + // Don't accept focus if in the middle of clearing focus + if (mClearingFocus) return false; + // Check if SearchView is focusable. + if (!isFocusable()) return false; + // If it is not iconified, then give the focus to the text field + if (!isIconified()) { + boolean result = mQueryTextView.requestFocus(direction, previouslyFocusedRect); + if (result) { + updateViewsVisibility(false); + } + return result; + } else { + return super.requestFocus(direction, previouslyFocusedRect); + } + } + + /** @hide */ + @Override + public void clearFocus() { + mClearingFocus = true; + setImeVisibility(false); + super.clearFocus(); + mQueryTextView.clearFocus(); + mClearingFocus = false; + } + + /** + * Sets a listener for user actions within the SearchView. + * + * @param listener the listener object that receives callbacks when the user performs + * actions in the SearchView such as clicking on buttons or typing a query. + */ + public void setOnQueryTextListener(OnQueryTextListener listener) { + mOnQueryChangeListener = listener; + } + + /** + * Sets a listener to inform when the user closes the SearchView. + * + * @param listener the listener to call when the user closes the SearchView. + */ + public void setOnCloseListener(OnCloseListener listener) { + mOnCloseListener = listener; + } + + /** + * Sets a listener to inform when the focus of the query text field changes. + * + * @param listener the listener to inform of focus changes. + */ + public void setOnQueryTextFocusChangeListener(OnFocusChangeListener listener) { + mOnQueryTextFocusChangeListener = listener; + } + + /** + * Sets a listener to inform when a suggestion is focused or clicked. + * + * @param listener the listener to inform of suggestion selection events. + */ + public void setOnSuggestionListener(OnSuggestionListener listener) { + mOnSuggestionListener = listener; + } + + /** + * Sets a listener to inform when the search button is pressed. This is only + * relevant when the text field is not visible by default. Calling {@link #setIconified + * setIconified(false)} can also cause this listener to be informed. + * + * @param listener the listener to inform when the search button is clicked or + * the text field is programmatically de-iconified. + */ + public void setOnSearchClickListener(OnClickListener listener) { + mOnSearchClickListener = listener; + } + + /** + * Returns the query string currently in the text field. + * + * @return the query string + */ + public CharSequence getQuery() { + return mQueryTextView.getText(); + } + + /** + * Sets a query string in the text field and optionally submits the query as well. + * + * @param query the query string. This replaces any query text already present in the + * text field. + * @param submit whether to submit the query right now or only update the contents of + * text field. + */ + public void setQuery(CharSequence query, boolean submit) { + mQueryTextView.setText(query); + if (query != null) { + mQueryTextView.setSelection(mQueryTextView.length()); + mUserQuery = query; + } + + // If the query is not empty and submit is requested, submit the query + if (submit && !TextUtils.isEmpty(query)) { + onSubmitQuery(); + } + } + + /** + * Sets the hint text to display in the query text field. This overrides any hint specified + * in the SearchableInfo. + * + * @param hint the hint text to display + * + * @attr ref android.R.styleable#SearchView_queryHint + */ + public void setQueryHint(CharSequence hint) { + mQueryHint = hint; + updateQueryHint(); + } + + /** + * Gets the hint text to display in the query text field. + * @return the query hint text, if specified, null otherwise. + * + * @attr ref android.R.styleable#SearchView_queryHint + */ + public CharSequence getQueryHint() { + if (mQueryHint != null) { + return mQueryHint; + } else if (mSearchable != null) { + CharSequence hint = null; + int hintId = mSearchable.getHintId(); + if (hintId != 0) { + hint = getContext().getString(hintId); + } + return hint; + } + return null; + } + + /** + * Sets the default or resting state of the search field. If true, a single search icon is + * shown by default and expands to show the text field and other buttons when pressed. Also, + * if the default state is iconified, then it collapses to that state when the close button + * is pressed. Changes to this property will take effect immediately. + * + * <p>The default value is true.</p> + * + * @param iconified whether the search field should be iconified by default + * + * @attr ref android.R.styleable#SearchView_iconifiedByDefault + */ + public void setIconifiedByDefault(boolean iconified) { + if (mIconifiedByDefault == iconified) return; + mIconifiedByDefault = iconified; + updateViewsVisibility(iconified); + updateQueryHint(); + } + + /** + * Returns the default iconified state of the search field. + * @return + * + * @attr ref android.R.styleable#SearchView_iconifiedByDefault + */ + public boolean isIconfiedByDefault() { + return mIconifiedByDefault; + } + + /** + * Iconifies or expands the SearchView. Any query text is cleared when iconified. This is + * a temporary state and does not override the default iconified state set by + * {@link #setIconifiedByDefault(boolean)}. If the default state is iconified, then + * a false here will only be valid until the user closes the field. And if the default + * state is expanded, then a true here will only clear the text field and not close it. + * + * @param iconify a true value will collapse the SearchView to an icon, while a false will + * expand it. + */ + public void setIconified(boolean iconify) { + if (iconify) { + onCloseClicked(); + } else { + onSearchClicked(); + } + } + + /** + * Returns the current iconified state of the SearchView. + * + * @return true if the SearchView is currently iconified, false if the search field is + * fully visible. + */ + public boolean isIconified() { + return mIconified; + } + + /** + * Enables showing a submit button when the query is non-empty. In cases where the SearchView + * is being used to filter the contents of the current activity and doesn't launch a separate + * results activity, then the submit button should be disabled. + * + * @param enabled true to show a submit button for submitting queries, false if a submit + * button is not required. + */ + public void setSubmitButtonEnabled(boolean enabled) { + mSubmitButtonEnabled = enabled; + updateViewsVisibility(isIconified()); + } + + /** + * Returns whether the submit button is enabled when necessary or never displayed. + * + * @return whether the submit button is enabled automatically when necessary + */ + public boolean isSubmitButtonEnabled() { + return mSubmitButtonEnabled; + } + + /** + * Specifies if a query refinement button should be displayed alongside each suggestion + * or if it should depend on the flags set in the individual items retrieved from the + * suggestions provider. Clicking on the query refinement button will replace the text + * in the query text field with the text from the suggestion. This flag only takes effect + * if a SearchableInfo has been specified with {@link #setSearchableInfo(SearchableInfo)} + * and not when using a custom adapter. + * + * @param enable true if all items should have a query refinement button, false if only + * those items that have a query refinement flag set should have the button. + * + * @see SearchManager#SUGGEST_COLUMN_FLAGS + * @see SearchManager#FLAG_QUERY_REFINEMENT + */ + public void setQueryRefinementEnabled(boolean enable) { + mQueryRefinement = enable; + if (mSuggestionsAdapter instanceof SuggestionsAdapter) { + ((SuggestionsAdapter) mSuggestionsAdapter).setQueryRefinement( + enable ? SuggestionsAdapter.REFINE_ALL : SuggestionsAdapter.REFINE_BY_ENTRY); + } + } + + /** + * Returns whether query refinement is enabled for all items or only specific ones. + * @return true if enabled for all items, false otherwise. + */ + public boolean isQueryRefinementEnabled() { + return mQueryRefinement; + } + + /** + * You can set a custom adapter if you wish. Otherwise the default adapter is used to + * display the suggestions from the suggestions provider associated with the SearchableInfo. + * + * @see #setSearchableInfo(SearchableInfo) + */ + public void setSuggestionsAdapter(CursorAdapter adapter) { + mSuggestionsAdapter = adapter; + + mQueryTextView.setAdapter(mSuggestionsAdapter); + } + + /** + * Returns the adapter used for suggestions, if any. + * @return the suggestions adapter + */ + public CursorAdapter getSuggestionsAdapter() { + return mSuggestionsAdapter; + } + + /** + * Makes the view at most this many pixels wide + * + * @attr ref android.R.styleable#SearchView_maxWidth + */ + public void setMaxWidth(int maxpixels) { + mMaxWidth = maxpixels; + + requestLayout(); + } + + /** + * Gets the specified maximum width in pixels, if set. Returns zero if + * no maximum width was specified. + * @return the maximum width of the view + * + * @attr ref android.R.styleable#SearchView_maxWidth + */ + public int getMaxWidth() { + return mMaxWidth; + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + // Let the standard measurements take effect in iconified state. + if (isIconified()) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + return; + } + + int widthMode = MeasureSpec.getMode(widthMeasureSpec); + int width = MeasureSpec.getSize(widthMeasureSpec); + + switch (widthMode) { + case MeasureSpec.AT_MOST: + // If there is an upper limit, don't exceed maximum width (explicit or implicit) + if (mMaxWidth > 0) { + width = Math.min(mMaxWidth, width); + } else { + width = Math.min(getPreferredWidth(), width); + } + break; + case MeasureSpec.EXACTLY: + // If an exact width is specified, still don't exceed any specified maximum width + if (mMaxWidth > 0) { + width = Math.min(mMaxWidth, width); + } + break; + case MeasureSpec.UNSPECIFIED: + // Use maximum width, if specified, else preferred width + width = mMaxWidth > 0 ? mMaxWidth : getPreferredWidth(); + break; + } + widthMode = MeasureSpec.EXACTLY; + super.onMeasure(MeasureSpec.makeMeasureSpec(width, widthMode), heightMeasureSpec); + } + + private int getPreferredWidth() { + return getContext().getResources() + .getDimensionPixelSize(R.dimen.abs__search_view_preferred_width); + } + + private void updateViewsVisibility(final boolean collapsed) { + mIconified = collapsed; + // Visibility of views that are visible when collapsed + final int visCollapsed = collapsed ? VISIBLE : GONE; + // Is there text in the query + final boolean hasText = !TextUtils.isEmpty(mQueryTextView.getText()); + + mSearchButton.setVisibility(visCollapsed); + updateSubmitButton(hasText); + mSearchEditFrame.setVisibility(collapsed ? GONE : VISIBLE); + mSearchHintIcon.setVisibility(mIconifiedByDefault ? GONE : VISIBLE); + updateCloseButton(); + updateVoiceButton(!hasText); + updateSubmitArea(); + } + + private boolean hasVoiceSearch() { + if (mSearchable != null && mSearchable.getVoiceSearchEnabled()) { + Intent testIntent = null; + if (mSearchable.getVoiceSearchLaunchWebSearch()) { + testIntent = mVoiceWebSearchIntent; + } else if (mSearchable.getVoiceSearchLaunchRecognizer()) { + testIntent = mVoiceAppSearchIntent; + } + if (testIntent != null) { + ResolveInfo ri = getContext().getPackageManager().resolveActivity(testIntent, + PackageManager.MATCH_DEFAULT_ONLY); + return ri != null; + } + } + return false; + } + + private boolean isSubmitAreaEnabled() { + return (mSubmitButtonEnabled || mVoiceButtonEnabled) && !isIconified(); + } + + private void updateSubmitButton(boolean hasText) { + int visibility = GONE; + if (mSubmitButtonEnabled && isSubmitAreaEnabled() && hasFocus() + && (hasText || !mVoiceButtonEnabled)) { + visibility = VISIBLE; + } + mSubmitButton.setVisibility(visibility); + } + + private void updateSubmitArea() { + int visibility = GONE; + if (isSubmitAreaEnabled() + && (mSubmitButton.getVisibility() == VISIBLE + || mVoiceButton.getVisibility() == VISIBLE)) { + visibility = VISIBLE; + } + mSubmitArea.setVisibility(visibility); + } + + private void updateCloseButton() { + final boolean hasText = !TextUtils.isEmpty(mQueryTextView.getText()); + // Should we show the close button? It is not shown if there's no focus, + // field is not iconified by default and there is no text in it. + final boolean showClose = hasText || (mIconifiedByDefault && !mExpandedInActionView); + mCloseButton.setVisibility(showClose ? VISIBLE : GONE); + mCloseButton.getDrawable().setState(hasText ? ENABLED_STATE_SET : EMPTY_STATE_SET); + } + + private void postUpdateFocusedState() { + post(mUpdateDrawableStateRunnable); + } + + private void updateFocusedState() { + boolean focused = mQueryTextView.hasFocus(); + mSearchPlate.getBackground().setState(focused ? FOCUSED_STATE_SET : EMPTY_STATE_SET); + mSubmitArea.getBackground().setState(focused ? FOCUSED_STATE_SET : EMPTY_STATE_SET); + invalidate(); + } + + @Override + protected void onDetachedFromWindow() { + removeCallbacks(mUpdateDrawableStateRunnable); + post(mReleaseCursorRunnable); + super.onDetachedFromWindow(); + } + + private void setImeVisibility(final boolean visible) { + if (visible) { + post(mShowImeRunnable); + } else { + removeCallbacks(mShowImeRunnable); + InputMethodManager imm = (InputMethodManager) + getContext().getSystemService(Context.INPUT_METHOD_SERVICE); + + if (imm != null) { + imm.hideSoftInputFromWindow(getWindowToken(), 0); + } + } + } + + /** + * Called by the SuggestionsAdapter + * @hide + */ + /* package */void onQueryRefine(CharSequence queryText) { + setQuery(queryText); + } + + private final OnClickListener mOnClickListener = new OnClickListener() { + + public void onClick(View v) { + if (v == mSearchButton) { + onSearchClicked(); + } else if (v == mCloseButton) { + onCloseClicked(); + } else if (v == mSubmitButton) { + onSubmitQuery(); + } else if (v == mVoiceButton) { + onVoiceClicked(); + } else if (v == mQueryTextView) { + forceSuggestionQuery(); + } + } + }; + + /** + * Handles the key down event for dealing with action keys. + * + * @param keyCode This is the keycode of the typed key, and is the same value as + * found in the KeyEvent parameter. + * @param event The complete event record for the typed key + * + * @return true if the event was handled here, or false if not. + */ + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (mSearchable == null) { + return false; + } + + // if it's an action specified by the searchable activity, launch the + // entered query with the action key + // TODO SearchableInfo.ActionKeyInfo actionKey = mSearchable.findActionKey(keyCode); + // TODO if ((actionKey != null) && (actionKey.getQueryActionMsg() != null)) { + // TODO launchQuerySearch(keyCode, actionKey.getQueryActionMsg(), mQueryTextView.getText() + // TODO .toString()); + // TODO return true; + // TODO } + + return super.onKeyDown(keyCode, event); + } + + /** + * React to the user typing "enter" or other hardwired keys while typing in + * the search box. This handles these special keys while the edit box has + * focus. + */ + View.OnKeyListener mTextKeyListener = new View.OnKeyListener() { + public boolean onKey(View v, int keyCode, KeyEvent event) { + // guard against possible race conditions + if (mSearchable == null) { + return false; + } + + if (DBG) { + Log.d(LOG_TAG, "mTextListener.onKey(" + keyCode + "," + event + "), selection: " + + mQueryTextView.getListSelection()); + } + + // If a suggestion is selected, handle enter, search key, and action keys + // as presses on the selected suggestion + if (mQueryTextView.isPopupShowing() + && mQueryTextView.getListSelection() != ListView.INVALID_POSITION) { + return onSuggestionsKey(v, keyCode, event); + } + + // If there is text in the query box, handle enter, and action keys + // The search key is handled by the dialog's onKeyDown(). + if (!mQueryTextView.isEmpty() && KeyEventCompat.hasNoModifiers(event)) { + if (event.getAction() == KeyEvent.ACTION_UP) { + if (keyCode == KeyEvent.KEYCODE_ENTER) { + v.cancelLongPress(); + + // Launch as a regular search. + launchQuerySearch(KeyEvent.KEYCODE_UNKNOWN, null, mQueryTextView.getText() + .toString()); + return true; + } + } + if (event.getAction() == KeyEvent.ACTION_DOWN) { + // TODO SearchableInfo.ActionKeyInfo actionKey = mSearchable.findActionKey(keyCode); + // TODO if ((actionKey != null) && (actionKey.getQueryActionMsg() != null)) { + // TODO launchQuerySearch(keyCode, actionKey.getQueryActionMsg(), mQueryTextView + // TODO .getText().toString()); + // TODO return true; + // TODO } + } + } + return false; + } + }; + + /** + * React to the user typing while in the suggestions list. First, check for + * action keys. If not handled, try refocusing regular characters into the + * EditText. + */ + private boolean onSuggestionsKey(View v, int keyCode, KeyEvent event) { + // guard against possible race conditions (late arrival after dismiss) + if (mSearchable == null) { + return false; + } + if (mSuggestionsAdapter == null) { + return false; + } + if (event.getAction() == KeyEvent.ACTION_DOWN && KeyEventCompat.hasNoModifiers(event)) { + // First, check for enter or search (both of which we'll treat as a + // "click") + if (keyCode == KeyEvent.KEYCODE_ENTER || keyCode == KeyEvent.KEYCODE_SEARCH + || keyCode == KeyEvent.KEYCODE_TAB) { + int position = mQueryTextView.getListSelection(); + return onItemClicked(position, KeyEvent.KEYCODE_UNKNOWN, null); + } + + // Next, check for left/right moves, which we use to "return" the + // user to the edit view + if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT || keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) { + // give "focus" to text editor, with cursor at the beginning if + // left key, at end if right key + // TODO: Reverse left/right for right-to-left languages, e.g. + // Arabic + int selPoint = (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) ? 0 : mQueryTextView + .length(); + mQueryTextView.setSelection(selPoint); + mQueryTextView.setListSelection(0); + mQueryTextView.clearListSelection(); + ensureImeVisible(mQueryTextView, true); + + return true; + } + + // Next, check for an "up and out" move + if (keyCode == KeyEvent.KEYCODE_DPAD_UP && 0 == mQueryTextView.getListSelection()) { + // TODO: restoreUserQuery(); + // let ACTV complete the move + return false; + } + + // Next, check for an "action key" + // TODO SearchableInfo.ActionKeyInfo actionKey = mSearchable.findActionKey(keyCode); + // TODO if ((actionKey != null) + // TODO && ((actionKey.getSuggestActionMsg() != null) || (actionKey + // TODO .getSuggestActionMsgColumn() != null))) { + // TODO // launch suggestion using action key column + // TODO int position = mQueryTextView.getListSelection(); + // TODO if (position != ListView.INVALID_POSITION) { + // TODO Cursor c = mSuggestionsAdapter.getCursor(); + // TODO if (c.moveToPosition(position)) { + // TODO final String actionMsg = getActionKeyMessage(c, actionKey); + // TODO if (actionMsg != null && (actionMsg.length() > 0)) { + // TODO return onItemClicked(position, keyCode, actionMsg); + // TODO } + // TODO } + // TODO } + // TODO } + } + return false; + } + + /** + * For a given suggestion and a given cursor row, get the action message. If + * not provided by the specific row/column, also check for a single + * definition (for the action key). + * + * @param c The cursor providing suggestions + * @param actionKey The actionkey record being examined + * + * @return Returns a string, or null if no action key message for this + * suggestion + */ + // TODO private static String getActionKeyMessage(Cursor c, SearchableInfo.ActionKeyInfo actionKey) { + // TODO String result = null; + // TODO // check first in the cursor data, for a suggestion-specific message + // TODO final String column = actionKey.getSuggestActionMsgColumn(); + // TODO if (column != null) { + // TODO result = SuggestionsAdapter.getColumnString(c, column); + // TODO } + // TODO // If the cursor didn't give us a message, see if there's a single + // TODO // message defined + // TODO // for the actionkey (for all suggestions) + // TODO if (result == null) { + // TODO result = actionKey.getSuggestActionMsg(); + // TODO } + // TODO return result; + // TODO } + + private int getSearchIconId() { + TypedValue outValue = new TypedValue(); + getContext().getTheme().resolveAttribute(R.attr.searchViewSearchIcon, + outValue, true); + return outValue.resourceId; + } + + private CharSequence getDecoratedHint(CharSequence hintText) { + // If the field is always expanded, then don't add the search icon to the hint + if (!mIconifiedByDefault) return hintText; + + SpannableStringBuilder ssb = new SpannableStringBuilder(" "); // for the icon + ssb.append(hintText); + Drawable searchIcon = getContext().getResources().getDrawable(getSearchIconId()); + int textSize = (int) (mQueryTextView.getTextSize() * 1.25); + searchIcon.setBounds(0, 0, textSize, textSize); + ssb.setSpan(new ImageSpan(searchIcon), 1, 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + return ssb; + } + + private void updateQueryHint() { + if (mQueryHint != null) { + mQueryTextView.setHint(getDecoratedHint(mQueryHint)); + } else if (mSearchable != null) { + CharSequence hint = null; + int hintId = mSearchable.getHintId(); + if (hintId != 0) { + hint = getContext().getString(hintId); + } + if (hint != null) { + mQueryTextView.setHint(getDecoratedHint(hint)); + } + } else { + mQueryTextView.setHint(getDecoratedHint("")); + } + } + + /** + * Updates the auto-complete text view. + */ + private void updateSearchAutoComplete() { + // TODO mQueryTextView.setDropDownAnimationStyle(0); // no animation + mQueryTextView.setThreshold(mSearchable.getSuggestThreshold()); + mQueryTextView.setImeOptions(mSearchable.getImeOptions()); + int inputType = mSearchable.getInputType(); + // We only touch this if the input type is set up for text (which it almost certainly + // should be, in the case of search!) + if ((inputType & InputType.TYPE_MASK_CLASS) == InputType.TYPE_CLASS_TEXT) { + // The existence of a suggestions authority is the proxy for "suggestions + // are available here" + inputType &= ~InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE; + if (mSearchable.getSuggestAuthority() != null) { + inputType |= InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE; + // TYPE_TEXT_FLAG_AUTO_COMPLETE means that the text editor is performing + // auto-completion based on its own semantics, which it will present to the user + // as they type. This generally means that the input method should not show its + // own candidates, and the spell checker should not be in action. The text editor + // supplies its candidates by calling InputMethodManager.displayCompletions(), + // which in turn will call InputMethodSession.displayCompletions(). + inputType |= InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS; + } + } + mQueryTextView.setInputType(inputType); + if (mSuggestionsAdapter != null) { + mSuggestionsAdapter.changeCursor(null); + } + // attach the suggestions adapter, if suggestions are available + // The existence of a suggestions authority is the proxy for "suggestions available here" + if (mSearchable.getSuggestAuthority() != null) { + mSuggestionsAdapter = new SuggestionsAdapter(getContext(), + this, mSearchable, mOutsideDrawablesCache); + mQueryTextView.setAdapter(mSuggestionsAdapter); + ((SuggestionsAdapter) mSuggestionsAdapter).setQueryRefinement( + mQueryRefinement ? SuggestionsAdapter.REFINE_ALL + : SuggestionsAdapter.REFINE_BY_ENTRY); + } + } + + /** + * Update the visibility of the voice button. There are actually two voice search modes, + * either of which will activate the button. + * @param empty whether the search query text field is empty. If it is, then the other + * criteria apply to make the voice button visible. + */ + private void updateVoiceButton(boolean empty) { + int visibility = GONE; + if (mVoiceButtonEnabled && !isIconified() && empty) { + visibility = VISIBLE; + mSubmitButton.setVisibility(GONE); + } + mVoiceButton.setVisibility(visibility); + } + + private final OnEditorActionListener mOnEditorActionListener = new OnEditorActionListener() { + + /** + * Called when the input method default action key is pressed. + */ + public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { + onSubmitQuery(); + return true; + } + }; + + private void onTextChanged(CharSequence newText) { + CharSequence text = mQueryTextView.getText(); + mUserQuery = text; + boolean hasText = !TextUtils.isEmpty(text); + updateSubmitButton(hasText); + updateVoiceButton(!hasText); + updateCloseButton(); + updateSubmitArea(); + if (mOnQueryChangeListener != null && !TextUtils.equals(newText, mOldQueryText)) { + mOnQueryChangeListener.onQueryTextChange(newText.toString()); + } + mOldQueryText = newText.toString(); + } + + private void onSubmitQuery() { + CharSequence query = mQueryTextView.getText(); + if (query != null && TextUtils.getTrimmedLength(query) > 0) { + if (mOnQueryChangeListener == null + || !mOnQueryChangeListener.onQueryTextSubmit(query.toString())) { + if (mSearchable != null) { + launchQuerySearch(KeyEvent.KEYCODE_UNKNOWN, null, query.toString()); + setImeVisibility(false); + } + dismissSuggestions(); + } + } + } + + private void dismissSuggestions() { + mQueryTextView.dismissDropDown(); + } + + private void onCloseClicked() { + CharSequence text = mQueryTextView.getText(); + if (TextUtils.isEmpty(text)) { + if (mIconifiedByDefault) { + // If the app doesn't override the close behavior + if (mOnCloseListener == null || !mOnCloseListener.onClose()) { + // hide the keyboard and remove focus + clearFocus(); + // collapse the search field + updateViewsVisibility(true); + } + } + } else { + mQueryTextView.setText(""); + mQueryTextView.requestFocus(); + setImeVisibility(true); + } + + } + + private void onSearchClicked() { + updateViewsVisibility(false); + mQueryTextView.requestFocus(); + setImeVisibility(true); + if (mOnSearchClickListener != null) { + mOnSearchClickListener.onClick(this); + } + } + + private void onVoiceClicked() { + // guard against possible race conditions + if (mSearchable == null) { + return; + } + SearchableInfo searchable = mSearchable; + try { + if (searchable.getVoiceSearchLaunchWebSearch()) { + Intent webSearchIntent = createVoiceWebSearchIntent(mVoiceWebSearchIntent, + searchable); + getContext().startActivity(webSearchIntent); + } else if (searchable.getVoiceSearchLaunchRecognizer()) { + Intent appSearchIntent = createVoiceAppSearchIntent(mVoiceAppSearchIntent, + searchable); + getContext().startActivity(appSearchIntent); + } + } catch (ActivityNotFoundException e) { + // Should not happen, since we check the availability of + // voice search before showing the button. But just in case... + Log.w(LOG_TAG, "Could not find voice search activity"); + } + } + + void onTextFocusChanged() { + updateViewsVisibility(isIconified()); + // Delayed update to make sure that the focus has settled down and window focus changes + // don't affect it. A synchronous update was not working. + postUpdateFocusedState(); + if (mQueryTextView.hasFocus()) { + forceSuggestionQuery(); + } + } + + @Override + public void onWindowFocusChanged(boolean hasWindowFocus) { + super.onWindowFocusChanged(hasWindowFocus); + + postUpdateFocusedState(); + } + + /** + * {@inheritDoc} + */ + @Override + public void onActionViewCollapsed() { + clearFocus(); + updateViewsVisibility(true); + mQueryTextView.setImeOptions(mCollapsedImeOptions); + mExpandedInActionView = false; + } + + /** + * {@inheritDoc} + */ + @Override + public void onActionViewExpanded() { + if (mExpandedInActionView) return; + + mExpandedInActionView = true; + mCollapsedImeOptions = mQueryTextView.getImeOptions(); + mQueryTextView.setImeOptions(mCollapsedImeOptions | EditorInfo.IME_FLAG_NO_FULLSCREEN); + mQueryTextView.setText(""); + setIconified(false); + } + + @Override + public void onInitializeAccessibilityEvent(AccessibilityEvent event) { + super.onInitializeAccessibilityEvent(event); + event.setClassName(SearchView.class.getName()); + } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + info.setClassName(SearchView.class.getName()); + } + + private void adjustDropDownSizeAndPosition() { + if (mDropDownAnchor.getWidth() > 1) { + Resources res = getContext().getResources(); + int anchorPadding = mSearchPlate.getPaddingLeft(); + Rect dropDownPadding = new Rect(); + int iconOffset = mIconifiedByDefault + ? res.getDimensionPixelSize(R.dimen.abs__dropdownitem_icon_width) + + res.getDimensionPixelSize(R.dimen.abs__dropdownitem_text_padding_left) + : 0; + mQueryTextView.getDropDownBackground().getPadding(dropDownPadding); + mQueryTextView.setDropDownHorizontalOffset(-(dropDownPadding.left + iconOffset) + + anchorPadding); + mQueryTextView.setDropDownWidth(mDropDownAnchor.getWidth() + dropDownPadding.left + + dropDownPadding.right + iconOffset - (anchorPadding)); + } + } + + private boolean onItemClicked(int position, int actionKey, String actionMsg) { + if (mOnSuggestionListener == null + || !mOnSuggestionListener.onSuggestionClick(position)) { + launchSuggestion(position, KeyEvent.KEYCODE_UNKNOWN, null); + setImeVisibility(false); + dismissSuggestions(); + return true; + } + return false; + } + + private boolean onItemSelected(int position) { + if (mOnSuggestionListener == null + || !mOnSuggestionListener.onSuggestionSelect(position)) { + rewriteQueryFromSuggestion(position); + return true; + } + return false; + } + + private final OnItemClickListener mOnItemClickListener = new OnItemClickListener() { + + /** + * Implements OnItemClickListener + */ + public void onItemClick(AdapterView<?> parent, View view, int position, long id) { + if (DBG) Log.d(LOG_TAG, "onItemClick() position " + position); + onItemClicked(position, KeyEvent.KEYCODE_UNKNOWN, null); + } + }; + + private final OnItemSelectedListener mOnItemSelectedListener = new OnItemSelectedListener() { + + /** + * Implements OnItemSelectedListener + */ + public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { + if (DBG) Log.d(LOG_TAG, "onItemSelected() position " + position); + SearchView.this.onItemSelected(position); + } + + /** + * Implements OnItemSelectedListener + */ + public void onNothingSelected(AdapterView<?> parent) { + if (DBG) + Log.d(LOG_TAG, "onNothingSelected()"); + } + }; + + /** + * Query rewriting. + */ + private void rewriteQueryFromSuggestion(int position) { + CharSequence oldQuery = mQueryTextView.getText(); + Cursor c = mSuggestionsAdapter.getCursor(); + if (c == null) { + return; + } + if (c.moveToPosition(position)) { + // Get the new query from the suggestion. + CharSequence newQuery = mSuggestionsAdapter.convertToString(c); + if (newQuery != null) { + // The suggestion rewrites the query. + // Update the text field, without getting new suggestions. + setQuery(newQuery); + } else { + // The suggestion does not rewrite the query, restore the user's query. + setQuery(oldQuery); + } + } else { + // We got a bad position, restore the user's query. + setQuery(oldQuery); + } + } + + /** + * Launches an intent based on a suggestion. + * + * @param position The index of the suggestion to create the intent from. + * @param actionKey The key code of the action key that was pressed, + * or {@link KeyEvent#KEYCODE_UNKNOWN} if none. + * @param actionMsg The message for the action key that was pressed, + * or <code>null</code> if none. + * @return true if a successful launch, false if could not (e.g. bad position). + */ + private boolean launchSuggestion(int position, int actionKey, String actionMsg) { + Cursor c = mSuggestionsAdapter.getCursor(); + if ((c != null) && c.moveToPosition(position)) { + + Intent intent = createIntentFromSuggestion(c, actionKey, actionMsg); + + // launch the intent + launchIntent(intent); + + return true; + } + return false; + } + + /** + * Launches an intent, including any special intent handling. + */ + private void launchIntent(Intent intent) { + if (intent == null) { + return; + } + try { + // If the intent was created from a suggestion, it will always have an explicit + // component here. + getContext().startActivity(intent); + } catch (RuntimeException ex) { + Log.e(LOG_TAG, "Failed launch activity: " + intent, ex); + } + } + + /** + * Sets the text in the query box, without updating the suggestions. + */ + private void setQuery(CharSequence query) { + setText(mQueryTextView, query, true); + // Move the cursor to the end + mQueryTextView.setSelection(TextUtils.isEmpty(query) ? 0 : query.length()); + } + + private void launchQuerySearch(int actionKey, String actionMsg, String query) { + String action = Intent.ACTION_SEARCH; + Intent intent = createIntent(action, null, null, query, actionKey, actionMsg); + getContext().startActivity(intent); + } + + /** + * Constructs an intent from the given information and the search dialog state. + * + * @param action Intent action. + * @param data Intent data, or <code>null</code>. + * @param extraData Data for {@link SearchManager#EXTRA_DATA_KEY} or <code>null</code>. + * @param query Intent query, or <code>null</code>. + * @param actionKey The key code of the action key that was pressed, + * or {@link KeyEvent#KEYCODE_UNKNOWN} if none. + * @param actionMsg The message for the action key that was pressed, + * or <code>null</code> if none. + * @return The intent. + */ + private Intent createIntent(String action, Uri data, String extraData, String query, + int actionKey, String actionMsg) { + // Now build the Intent + Intent intent = new Intent(action); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + // We need CLEAR_TOP to avoid reusing an old task that has other activities + // on top of the one we want. We don't want to do this in in-app search though, + // as it can be destructive to the activity stack. + if (data != null) { + intent.setData(data); + } + intent.putExtra(SearchManager.USER_QUERY, mUserQuery); + if (query != null) { + intent.putExtra(SearchManager.QUERY, query); + } + if (extraData != null) { + intent.putExtra(SearchManager.EXTRA_DATA_KEY, extraData); + } + if (mAppSearchData != null) { + intent.putExtra(SearchManager.APP_DATA, mAppSearchData); + } + if (actionKey != KeyEvent.KEYCODE_UNKNOWN) { + intent.putExtra(SearchManager.ACTION_KEY, actionKey); + intent.putExtra(SearchManager.ACTION_MSG, actionMsg); + } + intent.setComponent(mSearchable.getSearchActivity()); + return intent; + } + + /** + * Create and return an Intent that can launch the voice search activity for web search. + */ + private Intent createVoiceWebSearchIntent(Intent baseIntent, SearchableInfo searchable) { + Intent voiceIntent = new Intent(baseIntent); + ComponentName searchActivity = searchable.getSearchActivity(); + voiceIntent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, searchActivity == null ? null + : searchActivity.flattenToShortString()); + return voiceIntent; + } + + /** + * Create and return an Intent that can launch the voice search activity, perform a specific + * voice transcription, and forward the results to the searchable activity. + * + * @param baseIntent The voice app search intent to start from + * @return A completely-configured intent ready to send to the voice search activity + */ + private Intent createVoiceAppSearchIntent(Intent baseIntent, SearchableInfo searchable) { + ComponentName searchActivity = searchable.getSearchActivity(); + + // create the necessary intent to set up a search-and-forward operation + // in the voice search system. We have to keep the bundle separate, + // because it becomes immutable once it enters the PendingIntent + Intent queryIntent = new Intent(Intent.ACTION_SEARCH); + queryIntent.setComponent(searchActivity); + PendingIntent pending = PendingIntent.getActivity(getContext(), 0, queryIntent, + PendingIntent.FLAG_ONE_SHOT); + + // Now set up the bundle that will be inserted into the pending intent + // when it's time to do the search. We always build it here (even if empty) + // because the voice search activity will always need to insert "QUERY" into + // it anyway. + Bundle queryExtras = new Bundle(); + + // Now build the intent to launch the voice search. Add all necessary + // extras to launch the voice recognizer, and then all the necessary extras + // to forward the results to the searchable activity + Intent voiceIntent = new Intent(baseIntent); + + // Add all of the configuration options supplied by the searchable's metadata + String languageModel = RecognizerIntent.LANGUAGE_MODEL_FREE_FORM; + String prompt = null; + String language = null; + int maxResults = 1; + + Resources resources = getResources(); + if (searchable.getVoiceLanguageModeId() != 0) { + languageModel = resources.getString(searchable.getVoiceLanguageModeId()); + } + if (searchable.getVoicePromptTextId() != 0) { + prompt = resources.getString(searchable.getVoicePromptTextId()); + } + if (searchable.getVoiceLanguageId() != 0) { + language = resources.getString(searchable.getVoiceLanguageId()); + } + if (searchable.getVoiceMaxResults() != 0) { + maxResults = searchable.getVoiceMaxResults(); + } + voiceIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, languageModel); + voiceIntent.putExtra(RecognizerIntent.EXTRA_PROMPT, prompt); + voiceIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, language); + voiceIntent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, maxResults); + voiceIntent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, searchActivity == null ? null + : searchActivity.flattenToShortString()); + + // Add the values that configure forwarding the results + voiceIntent.putExtra(RecognizerIntent.EXTRA_RESULTS_PENDINGINTENT, pending); + voiceIntent.putExtra(RecognizerIntent.EXTRA_RESULTS_PENDINGINTENT_BUNDLE, queryExtras); + + return voiceIntent; + } + + /** + * When a particular suggestion has been selected, perform the various lookups required + * to use the suggestion. This includes checking the cursor for suggestion-specific data, + * and/or falling back to the XML for defaults; It also creates REST style Uri data when + * the suggestion includes a data id. + * + * @param c The suggestions cursor, moved to the row of the user's selection + * @param actionKey The key code of the action key that was pressed, + * or {@link KeyEvent#KEYCODE_UNKNOWN} if none. + * @param actionMsg The message for the action key that was pressed, + * or <code>null</code> if none. + * @return An intent for the suggestion at the cursor's position. + */ + private Intent createIntentFromSuggestion(Cursor c, int actionKey, String actionMsg) { + try { + // use specific action if supplied, or default action if supplied, or fixed default + String action = getColumnString(c, SearchManager.SUGGEST_COLUMN_INTENT_ACTION); + + if (action == null) { + action = mSearchable.getSuggestIntentAction(); + } + if (action == null) { + action = Intent.ACTION_SEARCH; + } + + // use specific data if supplied, or default data if supplied + String data = getColumnString(c, SearchManager.SUGGEST_COLUMN_INTENT_DATA); + if (data == null) { + data = mSearchable.getSuggestIntentData(); + } + // then, if an ID was provided, append it. + if (data != null) { + String id = getColumnString(c, SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID); + if (id != null) { + data = data + "/" + Uri.encode(id); + } + } + Uri dataUri = (data == null) ? null : Uri.parse(data); + + String query = getColumnString(c, SearchManager.SUGGEST_COLUMN_QUERY); + String extraData = getColumnString(c, SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA); + + return createIntent(action, dataUri, extraData, query, actionKey, actionMsg); + } catch (RuntimeException e ) { + int rowNum; + try { // be really paranoid now + rowNum = c.getPosition(); + } catch (RuntimeException e2 ) { + rowNum = -1; + } + Log.w(LOG_TAG, "Search suggestions cursor at row " + rowNum + + " returned exception.", e); + return null; + } + } + + private void forceSuggestionQuery() { + try { + Method before = SearchAutoComplete.class.getMethod("doBeforeTextChanged"); + Method after = SearchAutoComplete.class.getMethod("doAfterTextChanged"); + before.setAccessible(true); + after.setAccessible(true); + before.invoke(mQueryTextView); + after.invoke(mQueryTextView); + } catch (Exception e) { + // Oh well... + } + } + + static boolean isLandscapeMode(Context context) { + return context.getResources().getConfiguration().orientation + == Configuration.ORIENTATION_LANDSCAPE; + } + + /** + * Callback to watch the text field for empty/non-empty + */ + private TextWatcher mTextWatcher = new TextWatcher() { + + public void beforeTextChanged(CharSequence s, int start, int before, int after) { } + + public void onTextChanged(CharSequence s, int start, + int before, int after) { + SearchView.this.onTextChanged(s); + } + + public void afterTextChanged(Editable s) { + } + }; + + /** + * Local subclass for AutoCompleteTextView. + * @hide + */ + public static class SearchAutoComplete extends AutoCompleteTextView { + + private int mThreshold; + private SearchView mSearchView; + + public SearchAutoComplete(Context context) { + super(context); + mThreshold = getThreshold(); + } + + public SearchAutoComplete(Context context, AttributeSet attrs) { + super(context, attrs); + mThreshold = getThreshold(); + } + + public SearchAutoComplete(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + mThreshold = getThreshold(); + } + + void setSearchView(SearchView searchView) { + mSearchView = searchView; + } + + @Override + public void setThreshold(int threshold) { + super.setThreshold(threshold); + mThreshold = threshold; + } + + /** + * Returns true if the text field is empty, or contains only whitespace. + */ + private boolean isEmpty() { + return TextUtils.getTrimmedLength(getText()) == 0; + } + + /** + * We override this method to avoid replacing the query box text when a + * suggestion is clicked. + */ + @Override + protected void replaceText(CharSequence text) { + } + + /** + * We override this method to avoid an extra onItemClick being called on + * the drop-down's OnItemClickListener by + * {@link AutoCompleteTextView#onKeyUp(int, KeyEvent)} when an item is + * clicked with the trackball. + */ + @Override + public void performCompletion() { + } + + /** + * We override this method to be sure and show the soft keyboard if + * appropriate when the TextView has focus. + */ + @Override + public void onWindowFocusChanged(boolean hasWindowFocus) { + super.onWindowFocusChanged(hasWindowFocus); + + if (hasWindowFocus && mSearchView.hasFocus() && getVisibility() == VISIBLE) { + InputMethodManager inputManager = (InputMethodManager) getContext() + .getSystemService(Context.INPUT_METHOD_SERVICE); + inputManager.showSoftInput(this, 0); + // If in landscape mode, then make sure that + // the ime is in front of the dropdown. + if (isLandscapeMode(getContext())) { + ensureImeVisible(this, true); + } + } + } + + @Override + protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) { + super.onFocusChanged(focused, direction, previouslyFocusedRect); + mSearchView.onTextFocusChanged(); + } + + /** + * We override this method so that we can allow a threshold of zero, + * which ACTV does not. + */ + @Override + public boolean enoughToFilter() { + return mThreshold <= 0 || super.enoughToFilter(); + } + + @Override + public boolean onKeyPreIme(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK) { + // special case for the back key, we do not even try to send it + // to the drop down list but instead, consume it immediately + if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) { + KeyEvent.DispatcherState state = getKeyDispatcherState(); + if (state != null) { + state.startTracking(event, this); + } + return true; + } else if (event.getAction() == KeyEvent.ACTION_UP) { + KeyEvent.DispatcherState state = getKeyDispatcherState(); + if (state != null) { + state.handleUpEvent(event); + } + if (event.isTracking() && !event.isCanceled()) { + mSearchView.clearFocus(); + mSearchView.setImeVisibility(false); + return true; + } + } + } + return super.onKeyPreIme(keyCode, event); + } + + } + + private static void ensureImeVisible(AutoCompleteTextView view, boolean visible) { + try { + Method method = AutoCompleteTextView.class.getMethod("ensureImeVisible", boolean.class); + method.setAccessible(true); + method.invoke(view, visible); + } catch (Exception e) { + //Oh well... + } + } + + private static void showSoftInputUnchecked(View view, InputMethodManager imm, int flags) { + try { + Method method = imm.getClass().getMethod("showSoftInputUnchecked", int.class, ResultReceiver.class); + method.setAccessible(true); + method.invoke(imm, flags, null); + } catch (Exception e) { + //Fallback to public API which hopefully does mostly the same thing + imm.showSoftInput(view, flags); + } + } + + private static void setText(AutoCompleteTextView view, CharSequence text, boolean filter) { + try { + Method method = AutoCompleteTextView.class.getMethod("setText", CharSequence.class, boolean.class); + method.setAccessible(true); + method.invoke(view, text, filter); + } catch (Exception e) { + //Fallback to public API which hopefully does mostly the same thing + view.setText(text); + } + } +} diff --git a/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/widget/SuggestionsAdapter.java b/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/widget/SuggestionsAdapter.java new file mode 100644 index 000000000..bd5cbd718 --- /dev/null +++ b/APG/android-libs/ActionBarSherlock/src/com/actionbarsherlock/widget/SuggestionsAdapter.java @@ -0,0 +1,733 @@ +/* + * Copyright (C) 2009 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. + */ + +package com.actionbarsherlock.widget; + +import android.app.SearchManager; +import android.app.SearchableInfo; +import android.content.ComponentName; +import android.content.ContentResolver; +import android.content.Context; +import android.content.pm.ActivityInfo; +import android.content.pm.PackageManager; +import android.content.pm.PackageManager.NameNotFoundException; +import android.content.res.ColorStateList; +import android.content.res.Resources; +import android.database.Cursor; +import android.graphics.drawable.Drawable; +import android.net.Uri; +import android.os.Bundle; +import android.support.v4.widget.ResourceCursorAdapter; +import android.text.Spannable; +import android.text.SpannableString; +import android.text.TextUtils; +import android.text.style.TextAppearanceSpan; +import android.util.Log; +import android.util.TypedValue; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; +import com.actionbarsherlock.R; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.util.List; +import java.util.WeakHashMap; + +/** + * Provides the contents for the suggestion drop-down list. + * + * @hide + */ +class SuggestionsAdapter extends ResourceCursorAdapter implements OnClickListener { + + private static final boolean DBG = false; + private static final String LOG_TAG = "SuggestionsAdapter"; + private static final int QUERY_LIMIT = 50; + + static final int REFINE_NONE = 0; + static final int REFINE_BY_ENTRY = 1; + static final int REFINE_ALL = 2; + + private SearchManager mSearchManager; + private SearchView mSearchView; + private Context mProviderContext; + private WeakHashMap<String, Drawable.ConstantState> mOutsideDrawablesCache; + private boolean mClosed = false; + private int mQueryRefinement = REFINE_BY_ENTRY; + + // URL color + private ColorStateList mUrlColor; + + static final int INVALID_INDEX = -1; + + // Cached column indexes, updated when the cursor changes. + private int mText1Col = INVALID_INDEX; + private int mText2Col = INVALID_INDEX; + private int mText2UrlCol = INVALID_INDEX; + private int mIconName1Col = INVALID_INDEX; + private int mIconName2Col = INVALID_INDEX; + private int mFlagsCol = INVALID_INDEX; + + // private final Runnable mStartSpinnerRunnable; + // private final Runnable mStopSpinnerRunnable; + + /** + * The amount of time we delay in the filter when the user presses the delete key. + */ + //private static final long DELETE_KEY_POST_DELAY = 500L; + + public SuggestionsAdapter(Context context, SearchView searchView, + SearchableInfo mSearchable, WeakHashMap<String, Drawable.ConstantState> outsideDrawablesCache) { + super(context, + R.layout.abs__search_dropdown_item_icons_2line, + null, // no initial cursor + true); // auto-requery + mSearchManager = (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE); + mProviderContext = mContext; + mSearchView = searchView; + + mOutsideDrawablesCache = outsideDrawablesCache; + + // mStartSpinnerRunnable = new Runnable() { + // public void run() { + // // mSearchView.setWorking(true); // TODO: + // } + // }; + // + // mStopSpinnerRunnable = new Runnable() { + // public void run() { + // // mSearchView.setWorking(false); // TODO: + // } + // }; + + // delay 500ms when deleting +// TODO getFilter().setDelayer(new Filter.Delayer() { +// +// private int mPreviousLength = 0; +// +// public long getPostingDelay(CharSequence constraint) { +// if (constraint == null) return 0; +// +// long delay = constraint.length() < mPreviousLength ? DELETE_KEY_POST_DELAY : 0; +// mPreviousLength = constraint.length(); +// return delay; +// } +// }); + } + + /** + * Enables query refinement for all suggestions. This means that an additional icon + * will be shown for each entry. When clicked, the suggested text on that line will be + * copied to the query text field. + * <p> + * + * @param refineWhat which queries to refine. Possible values are {@link #REFINE_NONE}, + * {@link #REFINE_BY_ENTRY}, and {@link #REFINE_ALL}. + */ + public void setQueryRefinement(int refineWhat) { + mQueryRefinement = refineWhat; + } + + /** + * Returns the current query refinement preference. + * @return value of query refinement preference + */ + public int getQueryRefinement() { + return mQueryRefinement; + } + + /** + * Overridden to always return <code>false</code>, since we cannot be sure that + * suggestion sources return stable IDs. + */ + @Override + public boolean hasStableIds() { + return false; + } + + /** + * Use the search suggestions provider to obtain a live cursor. This will be called + * in a worker thread, so it's OK if the query is slow (e.g. round trip for suggestions). + * The results will be processed in the UI thread and changeCursor() will be called. + */ + @Override + public Cursor runQueryOnBackgroundThread(CharSequence constraint) { + if (DBG) Log.d(LOG_TAG, "runQueryOnBackgroundThread(" + constraint + ")"); + String query = (constraint == null) ? "" : constraint.toString(); + /** + * for in app search we show the progress spinner until the cursor is returned with + * the results. + */ + Cursor cursor = null; + if (mSearchView.getVisibility() != View.VISIBLE + || mSearchView.getWindowVisibility() != View.VISIBLE) { + return null; + } + //mSearchView.getWindow().getDecorView().post(mStartSpinnerRunnable); // TODO: + try { + cursor = getSuggestions(query, QUERY_LIMIT); + // trigger fill window so the spinner stays up until the results are copied over and + // closer to being ready + if (cursor != null) { + cursor.getCount(); + return cursor; + } + } catch (RuntimeException e) { + Log.w(LOG_TAG, "Search suggestions query threw an exception.", e); + } + // If cursor is null or an exception was thrown, stop the spinner and return null. + // changeCursor doesn't get called if cursor is null + // mSearchView.getWindow().getDecorView().post(mStopSpinnerRunnable); // TODO: + return null; + } + + public Cursor getSuggestions(String query, int limit) { + Uri.Builder uriBuilder = new Uri.Builder() + .scheme(ContentResolver.SCHEME_CONTENT) + .query("") // TODO: Remove, workaround for a bug in Uri.writeToParcel() + .fragment(""); // TODO: Remove, workaround for a bug in Uri.writeToParcel() + + // append standard suggestion query path + uriBuilder.appendPath(SearchManager.SUGGEST_URI_PATH_QUERY); + + // inject query, either as selection args or inline + uriBuilder.appendPath(query); + + if (limit > 0) { + uriBuilder.appendQueryParameter(SearchManager.SUGGEST_PARAMETER_LIMIT, String.valueOf(limit)); + } + + Uri uri = uriBuilder.build(); + + // finally, make the query + return mContext.getContentResolver().query(uri, null, null, null, null); + } + + public void close() { + if (DBG) Log.d(LOG_TAG, "close()"); + changeCursor(null); + mClosed = true; + } + + @Override + public void notifyDataSetChanged() { + if (DBG) Log.d(LOG_TAG, "notifyDataSetChanged"); + super.notifyDataSetChanged(); + + // mSearchView.onDataSetChanged(); // TODO: + + updateSpinnerState(getCursor()); + } + + @Override + public void notifyDataSetInvalidated() { + if (DBG) Log.d(LOG_TAG, "notifyDataSetInvalidated"); + super.notifyDataSetInvalidated(); + + updateSpinnerState(getCursor()); + } + + private void updateSpinnerState(Cursor cursor) { + Bundle extras = cursor != null ? cursor.getExtras() : null; + if (DBG) { + Log.d(LOG_TAG, "updateSpinnerState - extra = " + + (extras != null + ? extras.getBoolean(SearchManager.CURSOR_EXTRA_KEY_IN_PROGRESS) + : null)); + } + // Check if the Cursor indicates that the query is not complete and show the spinner + if (extras != null + && extras.getBoolean(SearchManager.CURSOR_EXTRA_KEY_IN_PROGRESS)) { + // mSearchView.getWindow().getDecorView().post(mStartSpinnerRunnable); // TODO: + return; + } + // If cursor is null or is done, stop the spinner + // mSearchView.getWindow().getDecorView().post(mStopSpinnerRunnable); // TODO: + } + + /** + * Cache columns. + */ + @Override + public void changeCursor(Cursor c) { + if (DBG) Log.d(LOG_TAG, "changeCursor(" + c + ")"); + + if (mClosed) { + Log.w(LOG_TAG, "Tried to change cursor after adapter was closed."); + if (c != null) c.close(); + return; + } + + try { + super.changeCursor(c); + + if (c != null) { + mText1Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_1); + mText2Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_2); + mText2UrlCol = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_2_URL); + mIconName1Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_ICON_1); + mIconName2Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_ICON_2); + mFlagsCol = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_FLAGS); + } + } catch (Exception e) { + Log.e(LOG_TAG, "error changing cursor and caching columns", e); + } + } + + /** + * Tags the view with cached child view look-ups. + */ + @Override + public View newView(Context context, Cursor cursor, ViewGroup parent) { + View v = super.newView(context, cursor, parent); + v.setTag(new ChildViewCache(v)); + return v; + } + + /** + * Cache of the child views of drop-drown list items, to avoid looking up the children + * each time the contents of a list item are changed. + */ + private final static class ChildViewCache { + public final TextView mText1; + public final TextView mText2; + public final ImageView mIcon1; + public final ImageView mIcon2; + public final ImageView mIconRefine; + + public ChildViewCache(View v) { + mText1 = (TextView) v.findViewById(android.R.id.text1); + mText2 = (TextView) v.findViewById(android.R.id.text2); + mIcon1 = (ImageView) v.findViewById(android.R.id.icon1); + mIcon2 = (ImageView) v.findViewById(android.R.id.icon2); + mIconRefine = (ImageView) v.findViewById(R.id.edit_query); + } + } + + @Override + public void bindView(View view, Context context, Cursor cursor) { + ChildViewCache views = (ChildViewCache) view.getTag(); + + int flags = 0; + if (mFlagsCol != INVALID_INDEX) { + flags = cursor.getInt(mFlagsCol); + } + if (views.mText1 != null) { + String text1 = getStringOrNull(cursor, mText1Col); + setViewText(views.mText1, text1); + } + if (views.mText2 != null) { + // First check TEXT_2_URL + CharSequence text2 = getStringOrNull(cursor, mText2UrlCol); + if (text2 != null) { + text2 = formatUrl(text2); + } else { + text2 = getStringOrNull(cursor, mText2Col); + } + + // If no second line of text is indicated, allow the first line of text + // to be up to two lines if it wants to be. + if (TextUtils.isEmpty(text2)) { + if (views.mText1 != null) { + views.mText1.setSingleLine(false); + views.mText1.setMaxLines(2); + } + } else { + if (views.mText1 != null) { + views.mText1.setSingleLine(true); + views.mText1.setMaxLines(1); + } + } + setViewText(views.mText2, text2); + } + + if (views.mIcon1 != null) { + setViewDrawable(views.mIcon1, getIcon1(cursor), View.INVISIBLE); + } + if (views.mIcon2 != null) { + setViewDrawable(views.mIcon2, getIcon2(cursor), View.GONE); + } + if (mQueryRefinement == REFINE_ALL + || (mQueryRefinement == REFINE_BY_ENTRY + && (flags & SearchManager.FLAG_QUERY_REFINEMENT) != 0)) { + views.mIconRefine.setVisibility(View.VISIBLE); + views.mIconRefine.setTag(views.mText1.getText()); + views.mIconRefine.setOnClickListener(this); + } else { + views.mIconRefine.setVisibility(View.GONE); + } + } + + public void onClick(View v) { + Object tag = v.getTag(); + if (tag instanceof CharSequence) { + mSearchView.onQueryRefine((CharSequence) tag); + } + } + + private CharSequence formatUrl(CharSequence url) { + if (mUrlColor == null) { + // Lazily get the URL color from the current theme. + TypedValue colorValue = new TypedValue(); + mContext.getTheme().resolveAttribute(R.attr.textColorSearchUrl, colorValue, true); + mUrlColor = mContext.getResources().getColorStateList(colorValue.resourceId); + } + + SpannableString text = new SpannableString(url); + text.setSpan(new TextAppearanceSpan(null, 0, 0, mUrlColor, null), + 0, url.length(), + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + return text; + } + + private void setViewText(TextView v, CharSequence text) { + // Set the text even if it's null, since we need to clear any previous text. + v.setText(text); + + if (TextUtils.isEmpty(text)) { + v.setVisibility(View.GONE); + } else { + v.setVisibility(View.VISIBLE); + } + } + + private Drawable getIcon1(Cursor cursor) { + if (mIconName1Col == INVALID_INDEX) { + return null; + } + String value = cursor.getString(mIconName1Col); + Drawable drawable = getDrawableFromResourceValue(value); + if (drawable != null) { + return drawable; + } + return getDefaultIcon1(cursor); + } + + private Drawable getIcon2(Cursor cursor) { + if (mIconName2Col == INVALID_INDEX) { + return null; + } + String value = cursor.getString(mIconName2Col); + return getDrawableFromResourceValue(value); + } + + /** + * Sets the drawable in an image view, makes sure the view is only visible if there + * is a drawable. + */ + private void setViewDrawable(ImageView v, Drawable drawable, int nullVisibility) { + // Set the icon even if the drawable is null, since we need to clear any + // previous icon. + v.setImageDrawable(drawable); + + if (drawable == null) { + v.setVisibility(nullVisibility); + } else { + v.setVisibility(View.VISIBLE); + + // This is a hack to get any animated drawables (like a 'working' spinner) + // to animate. You have to setVisible true on an AnimationDrawable to get + // it to start animating, but it must first have been false or else the + // call to setVisible will be ineffective. We need to clear up the story + // about animated drawables in the future, see http://b/1878430. + drawable.setVisible(false, false); + drawable.setVisible(true, false); + } + } + + /** + * Gets the text to show in the query field when a suggestion is selected. + * + * @param cursor The Cursor to read the suggestion data from. The Cursor should already + * be moved to the suggestion that is to be read from. + * @return The text to show, or <code>null</code> if the query should not be + * changed when selecting this suggestion. + */ + @Override + public CharSequence convertToString(Cursor cursor) { + if (cursor == null) { + return null; + } + + String query = getColumnString(cursor, SearchManager.SUGGEST_COLUMN_QUERY); + if (query != null) { + return query; + } + + return null; + } + + /** + * This method is overridden purely to provide a bit of protection against + * flaky content providers. + * + * @see android.widget.ListAdapter#getView(int, View, ViewGroup) + */ + @Override + public View getView(int position, View convertView, ViewGroup parent) { + try { + return super.getView(position, convertView, parent); + } catch (RuntimeException e) { + Log.w(LOG_TAG, "Search suggestions cursor threw exception.", e); + // Put exception string in item title + View v = newView(mContext, mCursor, parent); + if (v != null) { + ChildViewCache views = (ChildViewCache) v.getTag(); + TextView tv = views.mText1; + tv.setText(e.toString()); + } + return v; + } + } + + /** + * Gets a drawable given a value provided by a suggestion provider. + * + * This value could be just the string value of a resource id + * (e.g., "2130837524"), in which case we will try to retrieve a drawable from + * the provider's resources. If the value is not an integer, it is + * treated as a Uri and opened with + * {@link ContentResolver#openOutputStream(android.net.Uri, String)}. + * + * All resources and URIs are read using the suggestion provider's context. + * + * If the string is not formatted as expected, or no drawable can be found for + * the provided value, this method returns null. + * + * @param drawableId a string like "2130837524", + * "android.resource://com.android.alarmclock/2130837524", + * or "content://contacts/photos/253". + * @return a Drawable, or null if none found + */ + private Drawable getDrawableFromResourceValue(String drawableId) { + if (drawableId == null || drawableId.length() == 0 || "0".equals(drawableId)) { + return null; + } + try { + // First, see if it's just an integer + int resourceId = Integer.parseInt(drawableId); + // It's an int, look for it in the cache + String drawableUri = ContentResolver.SCHEME_ANDROID_RESOURCE + + "://" + mProviderContext.getPackageName() + "/" + resourceId; + // Must use URI as cache key, since ints are app-specific + Drawable drawable = checkIconCache(drawableUri); + if (drawable != null) { + return drawable; + } + // Not cached, find it by resource ID + drawable = mProviderContext.getResources().getDrawable(resourceId); + // Stick it in the cache, using the URI as key + storeInIconCache(drawableUri, drawable); + return drawable; + } catch (NumberFormatException nfe) { + // It's not an integer, use it as a URI + Drawable drawable = checkIconCache(drawableId); + if (drawable != null) { + return drawable; + } + Uri uri = Uri.parse(drawableId); + drawable = getDrawable(uri); + storeInIconCache(drawableId, drawable); + return drawable; + } catch (Resources.NotFoundException nfe) { + // It was an integer, but it couldn't be found, bail out + Log.w(LOG_TAG, "Icon resource not found: " + drawableId); + return null; + } + } + + /** + * Gets a drawable by URI, without using the cache. + * + * @return A drawable, or {@code null} if the drawable could not be loaded. + */ + private Drawable getDrawable(Uri uri) { + try { + String scheme = uri.getScheme(); + if (ContentResolver.SCHEME_ANDROID_RESOURCE.equals(scheme)) { + // Load drawables through Resources, to get the source density information + try { + return getTheDrawable(uri); + } catch (Resources.NotFoundException ex) { + throw new FileNotFoundException("Resource does not exist: " + uri); + } + } else { + // Let the ContentResolver handle content and file URIs. + InputStream stream = mProviderContext.getContentResolver().openInputStream(uri); + if (stream == null) { + throw new FileNotFoundException("Failed to open " + uri); + } + try { + return Drawable.createFromStream(stream, null); + } finally { + try { + stream.close(); + } catch (IOException ex) { + Log.e(LOG_TAG, "Error closing icon stream for " + uri, ex); + } + } + } + } catch (FileNotFoundException fnfe) { + Log.w(LOG_TAG, "Icon not found: " + uri + ", " + fnfe.getMessage()); + return null; + } + } + + public Drawable getTheDrawable(Uri uri) throws FileNotFoundException { + String authority = uri.getAuthority(); + Resources r; + if (TextUtils.isEmpty(authority)) { + throw new FileNotFoundException("No authority: " + uri); + } else { + try { + r = mContext.getPackageManager().getResourcesForApplication(authority); + } catch (NameNotFoundException ex) { + throw new FileNotFoundException("No package found for authority: " + uri); + } + } + List<String> path = uri.getPathSegments(); + if (path == null) { + throw new FileNotFoundException("No path: " + uri); + } + int len = path.size(); + int id; + if (len == 1) { + try { + id = Integer.parseInt(path.get(0)); + } catch (NumberFormatException e) { + throw new FileNotFoundException("Single path segment is not a resource ID: " + uri); + } + } else if (len == 2) { + id = r.getIdentifier(path.get(1), path.get(0), authority); + } else { + throw new FileNotFoundException("More than two path segments: " + uri); + } + if (id == 0) { + throw new FileNotFoundException("No resource found for: " + uri); + } + return r.getDrawable(id); + } + + private Drawable checkIconCache(String resourceUri) { + Drawable.ConstantState cached = mOutsideDrawablesCache.get(resourceUri); + if (cached == null) { + return null; + } + if (DBG) Log.d(LOG_TAG, "Found icon in cache: " + resourceUri); + return cached.newDrawable(); + } + + private void storeInIconCache(String resourceUri, Drawable drawable) { + if (drawable != null) { + mOutsideDrawablesCache.put(resourceUri, drawable.getConstantState()); + } + } + + /** + * Gets the left-hand side icon that will be used for the current suggestion + * if the suggestion contains an icon column but no icon or a broken icon. + * + * @param cursor A cursor positioned at the current suggestion. + * @return A non-null drawable. + */ + private Drawable getDefaultIcon1(Cursor cursor) { + // Fall back to a default icon + return mContext.getPackageManager().getDefaultActivityIcon(); + } + + /** + * Gets the activity or application icon for an activity. + * Uses the local icon cache for fast repeated lookups. + * + * @param component Name of an activity. + * @return A drawable, or {@code null} if neither the activity nor the application + * has an icon set. + */ + private Drawable getActivityIconWithCache(ComponentName component) { + // First check the icon cache + String componentIconKey = component.flattenToShortString(); + // Using containsKey() since we also store null values. + if (mOutsideDrawablesCache.containsKey(componentIconKey)) { + Drawable.ConstantState cached = mOutsideDrawablesCache.get(componentIconKey); + return cached == null ? null : cached.newDrawable(mProviderContext.getResources()); + } + // Then try the activity or application icon + Drawable drawable = getActivityIcon(component); + // Stick it in the cache so we don't do this lookup again. + Drawable.ConstantState toCache = drawable == null ? null : drawable.getConstantState(); + mOutsideDrawablesCache.put(componentIconKey, toCache); + return drawable; + } + + /** + * Gets the activity or application icon for an activity. + * + * @param component Name of an activity. + * @return A drawable, or {@code null} if neither the acitivy or the application + * have an icon set. + */ + private Drawable getActivityIcon(ComponentName component) { + PackageManager pm = mContext.getPackageManager(); + final ActivityInfo activityInfo; + try { + activityInfo = pm.getActivityInfo(component, PackageManager.GET_META_DATA); + } catch (NameNotFoundException ex) { + Log.w(LOG_TAG, ex.toString()); + return null; + } + int iconId = activityInfo.getIconResource(); + if (iconId == 0) return null; + String pkg = component.getPackageName(); + Drawable drawable = pm.getDrawable(pkg, iconId, activityInfo.applicationInfo); + if (drawable == null) { + Log.w(LOG_TAG, "Invalid icon resource " + iconId + " for " + + component.flattenToShortString()); + return null; + } + return drawable; + } + + /** + * Gets the value of a string column by name. + * + * @param cursor Cursor to read the value from. + * @param columnName The name of the column to read. + * @return The value of the given column, or <code>null</null> + * if the cursor does not contain the given column. + */ + public static String getColumnString(Cursor cursor, String columnName) { + int col = cursor.getColumnIndex(columnName); + return getStringOrNull(cursor, col); + } + + private static String getStringOrNull(Cursor cursor, int col) { + if (col == INVALID_INDEX) { + return null; + } + try { + return cursor.getString(col); + } catch (Exception e) { + Log.e(LOG_TAG, + "unexpected error retrieving valid column from cursor, " + + "did the remote process die?", e); + return null; + } + } +} diff --git a/APG/android-libs/ActionBarSherlock/test/com/actionbarsherlock/internal/ManifestParsingTest.java b/APG/android-libs/ActionBarSherlock/test/com/actionbarsherlock/internal/ManifestParsingTest.java index 1314248a4..47475c574 100644 --- a/APG/android-libs/ActionBarSherlock/test/com/actionbarsherlock/internal/ManifestParsingTest.java +++ b/APG/android-libs/ActionBarSherlock/test/com/actionbarsherlock/internal/ManifestParsingTest.java @@ -1,13 +1,11 @@ package com.actionbarsherlock.internal; +import org.junit.Test; + +import static com.actionbarsherlock.internal.ActionBarSherlockCompat.cleanActivityName; import static org.hamcrest.CoreMatchers.equalTo; import static org.junit.Assert.assertThat; -import static com.actionbarsherlock.internal.ActionBarSherlockCompat.cleanActivityName; -import com.xtremelabs.robolectric.RobolectricTestRunner; -import org.junit.Test; -import org.junit.runner.RunWith; -@RunWith(RobolectricTestRunner.class) public class ManifestParsingTest { @Test public void testFullyQualifiedClassName() { |