diff options
author | Brint E. Kriebel <bekit@cyngn.com> | 2014-06-30 22:42:18 -0700 |
---|---|---|
committer | Brint E. Kriebel <bekit@cyngn.com> | 2014-06-30 22:42:18 -0700 |
commit | 1cf1cb46e81002f756e6141fcd813eb1df44a2f5 (patch) | |
tree | 74c0a8aa932193154abc4e1981c17a6c238582b4 | |
parent | 4b66843493c8a8cc2bf01ac45566b71b2393a5ec (diff) | |
parent | ebf8f37515c23a167cef2bb8cff04854c52fd35b (diff) | |
download | android_packages_apps_Trebuchet-1cf1cb46e81002f756e6141fcd813eb1df44a2f5.tar.gz android_packages_apps_Trebuchet-1cf1cb46e81002f756e6141fcd813eb1df44a2f5.tar.bz2 android_packages_apps_Trebuchet-1cf1cb46e81002f756e6141fcd813eb1df44a2f5.zip |
Merge branch 'cm-11.0' into stable/cm-11.0
Conflicts:
res/values-et/cm_strings.xml
res/values-th/cm_arrays.xml
res/values-th/cm_strings.xml
Change-Id: If66ec311e06bca36268c52b42b61425c3b044556
1184 files changed, 18613 insertions, 9352 deletions
diff --git a/Android.mk b/Android.mk index f5bdaca84..2d4b0a005 100644 --- a/Android.mk +++ b/Android.mk @@ -26,19 +26,23 @@ LOCAL_MODULE_TAGS := optional LOCAL_STATIC_JAVA_LIBRARIES := android-support-v13 LOCAL_SRC_FILES := $(call all-java-files-under, src) \ + $(call all-java-files-under, WallpaperPicker/src) \ $(call all-renderscript-files-under, src) \ $(call all-proto-files-under, protos) +LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/WallpaperPicker/res $(LOCAL_PATH)/res + +LOCAL_AAPT_FLAGS := --auto-add-overlay LOCAL_PROTOC_OPTIMIZE_TYPE := nano LOCAL_PROTOC_FLAGS := --proto_path=$(LOCAL_PATH)/protos/ -#LOCAL_SDK_VERSION := 19 +# LOCAL_SDK_VERSION := 19 LOCAL_PACKAGE_NAME := Trebuchet LOCAL_PRIVILEGED_MODULE := true #LOCAL_CERTIFICATE := shared -LOCAL_AAPT_FLAGS := --rename-manifest-package com.cyanogenmod.trebuchet +LOCAL_AAPT_FLAGS += --rename-manifest-package com.cyanogenmod.trebuchet LOCAL_OVERRIDES_PACKAGES := Launcher3 @@ -47,3 +51,41 @@ LOCAL_PROGUARD_FLAG_FILES := proguard.flags include $(BUILD_PACKAGE) include $(call all-makefiles-under,$(LOCAL_PATH)) + +# +# Protocol Buffer Debug Utility in Java +# +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := $(call all-java-files-under, util) \ + $(call all-proto-files-under, protos) + +LOCAL_PROTOC_OPTIMIZE_TYPE := nano +LOCAL_PROTOC_FLAGS := --proto_path=$(LOCAL_PATH)/protos/ + +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE := launcher_protoutil_lib +LOCAL_IS_HOST_MODULE := true +LOCAL_JAR_MANIFEST := util/etc/manifest.txt +LOCAL_STATIC_JAVA_LIBRARIES := host-libprotobuf-java-2.3.0-nano + +include $(BUILD_HOST_JAVA_LIBRARY) + +# +# Protocol Buffer Debug Utility Wrapper Script +# +include $(CLEAR_VARS) +LOCAL_IS_HOST_MODULE := true +LOCAL_MODULE_CLASS := EXECUTABLES +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE := launcher_protoutil + +include $(BUILD_SYSTEM)/base_rules.mk + +$(LOCAL_BUILT_MODULE): launcher_protoutil_lib +$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/util/etc/launcher_protoutil | $(ACP) + @echo "Copy: $(PRIVATE_MODULE) ($@)" + $(copy-file-to-new-target) + $(hide) chmod 755 $@ + +INTERNAL_DALVIK_MODULES += $(LOCAL_INSTALLED_MODULE) diff --git a/AndroidManifest.xml b/AndroidManifest.xml index ba7c8b4a7..8262f4886 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -25,12 +25,16 @@ <original-package android:name="com.android.launcher3" /> - <uses-sdk android:minSdkVersion="17" android:targetSdkVersion="19" /> + <uses-sdk android:targetSdkVersion="19" android:minSdkVersion="16"/> <permission android:name="com.android.launcher3.permission.PRELOAD_WORKSPACE" android:permissionGroup="android.permission-group.SYSTEM_TOOLS" - android:protectionLevel="system|signature" /> + android:protectionLevel="signatureOrSystem" /> + <permission + android:name="com.android.launcher.home.permissions.HOME_APP" + android:permissionGroup="android.permission-group.SYSTEM_TOOLS" + android:protectionLevel="dangerous" /> <permission android:name="com.android.launcher3.permission.READ_SETTINGS" android:permissionGroup="android.permission-group.SYSTEM_TOOLS" @@ -40,7 +44,7 @@ <permission android:name="com.android.launcher3.permission.WRITE_SETTINGS" android:permissionGroup="android.permission-group.SYSTEM_TOOLS" - android:protectionLevel="dangerous" + android:protectionLevel="signatureOrSystem" android:label="@string/permlab_write_settings" android:description="@string/permdesc_write_settings"/> @@ -52,16 +56,18 @@ <uses-permission android:name="android.permission.CALL_PHONE" /> <uses-permission android:name="android.permission.SET_WALLPAPER" /> <uses-permission android:name="android.permission.SET_WALLPAPER_HINTS" /> - <uses-permission android:name="android.permission.SET_KEYGUARD_WALLPAPER" /> <uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission.BIND_APPWIDGET" /> <uses-permission android:name="android.permission.GET_ACCOUNTS" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> + <uses-permission android:name="android.permission.INJECT_EVENTS" /> + <uses-permission android:name="android.permission.GET_TASKS"/> <uses-permission android:name="com.android.launcher.permission.READ_SETTINGS" /> <uses-permission android:name="com.android.launcher.permission.WRITE_SETTINGS" /> <uses-permission android:name="com.android.launcher3.permission.READ_SETTINGS" /> <uses-permission android:name="com.android.launcher3.permission.WRITE_SETTINGS" /> <uses-permission android:name="com.android.launcher3.permission.RECEIVE_LAUNCH_BROADCASTS" /> + <uses-permission android:name="cyanogenmod.permission.PROTECTED_APP" /> <application android:name="com.android.launcher3.LauncherApplication" @@ -71,7 +77,7 @@ android:largeHeap="@bool/config_largeHeap" android:supportsRtl="true"> <activity - android:name="com.android.launcher3.Launcher" + android:name="org.cyanogenmod.trebuchet.TrebuchetLauncher" android:launchMode="singleTask" android:clearTaskOnLaunch="true" android:stateNotNeeded="true" @@ -86,23 +92,13 @@ </intent-filter> </activity> - <activity android:name=".settings.SettingsActivity" - android:label="@string/preferences_title"> - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.DEFAULT" /> - <category android:name="com.cyanogenmod.category.LAUNCHER_PREFERENCES" /> - </intent-filter> - </activity> - <activity - android:name=".settings.HiddenAppsActivity" - android:label="@string/hidden_apps_title" - android:exported="false"> - <intent-filter> - <action android:name=".settings.HiddenAppsActivity" /> - <category android:name="android.intent.category.DEFAULT" /> - </intent-filter> + android:name="com.android.launcher3.LauncherWallpaperPickerActivity" + android:theme="@style/Theme.WallpaperCropper" + android:label="@string/pick_wallpaper" + android:icon="@mipmap/ic_launcher_wallpaper" + android:finishOnCloseSystemDialogs="true" + android:process=":wallpaper_chooser"> </activity> <activity @@ -147,6 +143,13 @@ </intent-filter> </receiver> + <receiver + android:name="com.android.launcher3.WallpaperChangedReceiver"> + <intent-filter> + <action android:name="android.intent.action.WALLPAPER_CHANGED" /> + </intent-filter> + </receiver> + <!-- Intent received used to install shortcuts from other applications --> <receiver android:name="com.android.launcher3.InstallShortcutReceiver" @@ -183,6 +186,12 @@ </intent-filter> </receiver> + <receiver android:name="com.android.launcher3.ThemeChangedReceiver" > + <intent-filter> + <action android:name="org.cyanogenmod.intent.action.THEME_CHANGED"/> + </intent-filter> + </receiver> + <!-- The settings provider contains Home's data, like the workspace favorites --> <provider android:name="com.android.launcher3.LauncherProvider" diff --git a/CleanSpec.mk b/CleanSpec.mk index c1323951b..b2c5266fa 100644 --- a/CleanSpec.mk +++ b/CleanSpec.mk @@ -50,6 +50,8 @@ $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/Launcher2_interm $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/Launcher2_intermediates) $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/Launcher2_intermediates) $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/Launcher2.apk) +$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/Launcher2_intermediates) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/Launcher2.apk) # ************************************************ # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST diff --git a/WallpaperPicker/AndroidManifest.xml b/WallpaperPicker/AndroidManifest.xml new file mode 100644 index 000000000..86a94d078 --- /dev/null +++ b/WallpaperPicker/AndroidManifest.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8"?> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.launcher3" + android:versionCode="1" + android:versionName="1.0" + > + + <uses-sdk android:minSdkVersion="15" android:targetSdkVersion="19" /> + +</manifest> diff --git a/WallpaperPicker/README b/WallpaperPicker/README new file mode 100644 index 000000000..d8efb07f6 --- /dev/null +++ b/WallpaperPicker/README @@ -0,0 +1,4 @@ +This project contains the wallpaper picker for Launcher3. It's in a separate +folder to organize the code separately from the rest of the launcher, and has +a manifest so that a separate Eclipse project can exist for the wallpaper +picker (necessary to have the Eclipse build work)
\ No newline at end of file diff --git a/res/drawable-hdpi/ic_actionbar_accept.png b/WallpaperPicker/res/drawable-hdpi/ic_actionbar_accept.png Binary files differindex 53cf6877e..53cf6877e 100755 --- a/res/drawable-hdpi/ic_actionbar_accept.png +++ b/WallpaperPicker/res/drawable-hdpi/ic_actionbar_accept.png diff --git a/res/drawable-hdpi/ic_images.png b/WallpaperPicker/res/drawable-hdpi/ic_images.png Binary files differindex 0003c6c65..0003c6c65 100644 --- a/res/drawable-hdpi/ic_images.png +++ b/WallpaperPicker/res/drawable-hdpi/ic_images.png diff --git a/res/drawable-hdpi/tile_picker_focused.9.png b/WallpaperPicker/res/drawable-hdpi/tile_picker_focused.9.png Binary files differindex c72d6a2c6..c72d6a2c6 100644 --- a/res/drawable-hdpi/tile_picker_focused.9.png +++ b/WallpaperPicker/res/drawable-hdpi/tile_picker_focused.9.png diff --git a/res/drawable-hdpi/tile_picker_pressed.9.png b/WallpaperPicker/res/drawable-hdpi/tile_picker_pressed.9.png Binary files differindex 44c65ac3c..44c65ac3c 100644 --- a/res/drawable-hdpi/tile_picker_pressed.9.png +++ b/WallpaperPicker/res/drawable-hdpi/tile_picker_pressed.9.png diff --git a/res/drawable-hdpi/tile_picker_selected.9.png b/WallpaperPicker/res/drawable-hdpi/tile_picker_selected.9.png Binary files differindex 461bacbcb..461bacbcb 100644 --- a/res/drawable-hdpi/tile_picker_selected.9.png +++ b/WallpaperPicker/res/drawable-hdpi/tile_picker_selected.9.png diff --git a/res/drawable-hdpi/tile_shadow_bottom.9.png b/WallpaperPicker/res/drawable-hdpi/tile_shadow_bottom.9.png Binary files differindex e80558bad..e80558bad 100644 --- a/res/drawable-hdpi/tile_shadow_bottom.9.png +++ b/WallpaperPicker/res/drawable-hdpi/tile_shadow_bottom.9.png diff --git a/res/drawable-hdpi/tile_shadow_top.9.png b/WallpaperPicker/res/drawable-hdpi/tile_shadow_top.9.png Binary files differindex 7e93865e7..7e93865e7 100644 --- a/res/drawable-hdpi/tile_shadow_top.9.png +++ b/WallpaperPicker/res/drawable-hdpi/tile_shadow_top.9.png diff --git a/res/drawable-mdpi/ic_actionbar_accept.png b/WallpaperPicker/res/drawable-mdpi/ic_actionbar_accept.png Binary files differindex 35cda8e11..35cda8e11 100755 --- a/res/drawable-mdpi/ic_actionbar_accept.png +++ b/WallpaperPicker/res/drawable-mdpi/ic_actionbar_accept.png diff --git a/res/drawable-mdpi/ic_images.png b/WallpaperPicker/res/drawable-mdpi/ic_images.png Binary files differindex aabc1237a..aabc1237a 100644 --- a/res/drawable-mdpi/ic_images.png +++ b/WallpaperPicker/res/drawable-mdpi/ic_images.png diff --git a/res/drawable-mdpi/tile_picker_focused.9.png b/WallpaperPicker/res/drawable-mdpi/tile_picker_focused.9.png Binary files differindex 13b325b87..13b325b87 100644 --- a/res/drawable-mdpi/tile_picker_focused.9.png +++ b/WallpaperPicker/res/drawable-mdpi/tile_picker_focused.9.png diff --git a/res/drawable-mdpi/tile_picker_pressed.9.png b/WallpaperPicker/res/drawable-mdpi/tile_picker_pressed.9.png Binary files differindex 4e8196d36..4e8196d36 100644 --- a/res/drawable-mdpi/tile_picker_pressed.9.png +++ b/WallpaperPicker/res/drawable-mdpi/tile_picker_pressed.9.png diff --git a/res/drawable-mdpi/tile_picker_selected.9.png b/WallpaperPicker/res/drawable-mdpi/tile_picker_selected.9.png Binary files differindex eee69ec6d..eee69ec6d 100644 --- a/res/drawable-mdpi/tile_picker_selected.9.png +++ b/WallpaperPicker/res/drawable-mdpi/tile_picker_selected.9.png diff --git a/res/drawable-mdpi/tile_shadow_bottom.9.png b/WallpaperPicker/res/drawable-mdpi/tile_shadow_bottom.9.png Binary files differindex d95787bac..d95787bac 100644 --- a/res/drawable-mdpi/tile_shadow_bottom.9.png +++ b/WallpaperPicker/res/drawable-mdpi/tile_shadow_bottom.9.png diff --git a/res/drawable-mdpi/tile_shadow_top.9.png b/WallpaperPicker/res/drawable-mdpi/tile_shadow_top.9.png Binary files differindex 8da913cc4..8da913cc4 100644 --- a/res/drawable-mdpi/tile_shadow_top.9.png +++ b/WallpaperPicker/res/drawable-mdpi/tile_shadow_top.9.png diff --git a/res/drawable-xhdpi/ic_actionbar_accept.png b/WallpaperPicker/res/drawable-xhdpi/ic_actionbar_accept.png Binary files differindex b52dc3701..b52dc3701 100755 --- a/res/drawable-xhdpi/ic_actionbar_accept.png +++ b/WallpaperPicker/res/drawable-xhdpi/ic_actionbar_accept.png diff --git a/res/drawable-xhdpi/ic_images.png b/WallpaperPicker/res/drawable-xhdpi/ic_images.png Binary files differindex 3f21faf8f..3f21faf8f 100644 --- a/res/drawable-xhdpi/ic_images.png +++ b/WallpaperPicker/res/drawable-xhdpi/ic_images.png diff --git a/res/drawable-xhdpi/tile_picker_focused.9.png b/WallpaperPicker/res/drawable-xhdpi/tile_picker_focused.9.png Binary files differindex 279e85963..279e85963 100644 --- a/res/drawable-xhdpi/tile_picker_focused.9.png +++ b/WallpaperPicker/res/drawable-xhdpi/tile_picker_focused.9.png diff --git a/res/drawable-xhdpi/tile_picker_pressed.9.png b/WallpaperPicker/res/drawable-xhdpi/tile_picker_pressed.9.png Binary files differindex abe0e0080..abe0e0080 100644 --- a/res/drawable-xhdpi/tile_picker_pressed.9.png +++ b/WallpaperPicker/res/drawable-xhdpi/tile_picker_pressed.9.png diff --git a/res/drawable-xhdpi/tile_picker_selected.9.png b/WallpaperPicker/res/drawable-xhdpi/tile_picker_selected.9.png Binary files differindex b047591ac..b047591ac 100644 --- a/res/drawable-xhdpi/tile_picker_selected.9.png +++ b/WallpaperPicker/res/drawable-xhdpi/tile_picker_selected.9.png diff --git a/res/drawable-xhdpi/tile_shadow_bottom.9.png b/WallpaperPicker/res/drawable-xhdpi/tile_shadow_bottom.9.png Binary files differindex 81571f3b7..81571f3b7 100644 --- a/res/drawable-xhdpi/tile_shadow_bottom.9.png +++ b/WallpaperPicker/res/drawable-xhdpi/tile_shadow_bottom.9.png diff --git a/res/drawable-xhdpi/tile_shadow_top.9.png b/WallpaperPicker/res/drawable-xhdpi/tile_shadow_top.9.png Binary files differindex 8503a59fe..8503a59fe 100644 --- a/res/drawable-xhdpi/tile_shadow_top.9.png +++ b/WallpaperPicker/res/drawable-xhdpi/tile_shadow_top.9.png diff --git a/res/drawable-xxhdpi/ic_images.png b/WallpaperPicker/res/drawable-xxhdpi/ic_images.png Binary files differindex d00db9a00..d00db9a00 100644 --- a/res/drawable-xxhdpi/ic_images.png +++ b/WallpaperPicker/res/drawable-xxhdpi/ic_images.png diff --git a/res/drawable-xxhdpi/tile_picker_focused.9.png b/WallpaperPicker/res/drawable-xxhdpi/tile_picker_focused.9.png Binary files differindex 1004c14b8..1004c14b8 100644 --- a/res/drawable-xxhdpi/tile_picker_focused.9.png +++ b/WallpaperPicker/res/drawable-xxhdpi/tile_picker_focused.9.png diff --git a/res/drawable-xxhdpi/tile_picker_pressed.9.png b/WallpaperPicker/res/drawable-xxhdpi/tile_picker_pressed.9.png Binary files differindex 9658444a1..9658444a1 100644 --- a/res/drawable-xxhdpi/tile_picker_pressed.9.png +++ b/WallpaperPicker/res/drawable-xxhdpi/tile_picker_pressed.9.png diff --git a/res/drawable-xxhdpi/tile_picker_selected.9.png b/WallpaperPicker/res/drawable-xxhdpi/tile_picker_selected.9.png Binary files differindex a3cd30369..a3cd30369 100644 --- a/res/drawable-xxhdpi/tile_picker_selected.9.png +++ b/WallpaperPicker/res/drawable-xxhdpi/tile_picker_selected.9.png diff --git a/res/drawable-xxhdpi/tile_shadow_bottom.9.png b/WallpaperPicker/res/drawable-xxhdpi/tile_shadow_bottom.9.png Binary files differindex 55250f041..55250f041 100644 --- a/res/drawable-xxhdpi/tile_shadow_bottom.9.png +++ b/WallpaperPicker/res/drawable-xxhdpi/tile_shadow_bottom.9.png diff --git a/res/drawable-xxhdpi/tile_shadow_top.9.png b/WallpaperPicker/res/drawable-xxhdpi/tile_shadow_top.9.png Binary files differindex 3f2263364..3f2263364 100644 --- a/res/drawable-xxhdpi/tile_shadow_top.9.png +++ b/WallpaperPicker/res/drawable-xxhdpi/tile_shadow_top.9.png diff --git a/res/drawable/wallpaper_tile_fg.xml b/WallpaperPicker/res/drawable/wallpaper_tile_fg.xml index c299f32c6..c299f32c6 100644 --- a/res/drawable/wallpaper_tile_fg.xml +++ b/WallpaperPicker/res/drawable/wallpaper_tile_fg.xml diff --git a/res/layout/actionbar_set_wallpaper.xml b/WallpaperPicker/res/layout/actionbar_set_wallpaper.xml index 1622742a5..8e349b732 100644 --- a/res/layout/actionbar_set_wallpaper.xml +++ b/WallpaperPicker/res/layout/actionbar_set_wallpaper.xml @@ -18,17 +18,15 @@ */ --> -<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" - style="?android:actionButtonStyle" +<com.android.launcher3.AlphaDisableableButton + xmlns:android="http://schemas.android.com/apk/res/android" + style="@style/ActionBarSetWallpaperStyle" + android:id="@+id/set_wallpaper_button" android:layout_width="match_parent" - android:layout_height="match_parent" > - <TextView style="?android:actionBarTabTextStyle" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="start|center_vertical" - android:paddingRight="20dp" - android:drawableLeft="@drawable/ic_actionbar_accept" - android:drawablePadding="8dp" - android:gravity="center_vertical" - android:text="@string/wallpaper_instructions" /> -</FrameLayout> + android:layout_height="match_parent" + android:paddingRight="20dp" + android:drawableLeft="@drawable/ic_actionbar_accept" + android:drawablePadding="8dp" + android:gravity="start|center_vertical" + android:text="@string/wallpaper_instructions"> +</com.android.launcher3.AlphaDisableableButton> diff --git a/res/layout/wallpaper_cropper.xml b/WallpaperPicker/res/layout/wallpaper_cropper.xml index 3a3d98a69..abb860898 100644 --- a/res/layout/wallpaper_cropper.xml +++ b/WallpaperPicker/res/layout/wallpaper_cropper.xml @@ -32,7 +32,7 @@ android:visibility="invisible" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_gravity="center" + android:layout_centerInParent="true" android:indeterminate="true" android:indeterminateOnly="true" android:background="@android:color/transparent" /> diff --git a/res/layout/wallpaper_picker.xml b/WallpaperPicker/res/layout/wallpaper_picker.xml index c91cc7e6a..c36493d2f 100644 --- a/res/layout/wallpaper_picker.xml +++ b/WallpaperPicker/res/layout/wallpaper_picker.xml @@ -33,7 +33,7 @@ android:visibility="invisible" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_gravity="center" + android:layout_centerInParent="true" android:indeterminate="true" android:indeterminateOnly="true" android:background="@android:color/transparent" /> diff --git a/res/layout/wallpaper_picker_image_picker_item.xml b/WallpaperPicker/res/layout/wallpaper_picker_image_picker_item.xml index ae3c43d8e..ae3c43d8e 100644 --- a/res/layout/wallpaper_picker_image_picker_item.xml +++ b/WallpaperPicker/res/layout/wallpaper_picker_image_picker_item.xml diff --git a/res/layout/wallpaper_picker_item.xml b/WallpaperPicker/res/layout/wallpaper_picker_item.xml index 0ac8f97fb..0ac8f97fb 100644 --- a/res/layout/wallpaper_picker_item.xml +++ b/WallpaperPicker/res/layout/wallpaper_picker_item.xml diff --git a/res/layout/wallpaper_picker_live_wallpaper_item.xml b/WallpaperPicker/res/layout/wallpaper_picker_live_wallpaper_item.xml index 29fdb1b82..29fdb1b82 100644 --- a/res/layout/wallpaper_picker_live_wallpaper_item.xml +++ b/WallpaperPicker/res/layout/wallpaper_picker_live_wallpaper_item.xml diff --git a/res/layout/wallpaper_picker_third_party_item.xml b/WallpaperPicker/res/layout/wallpaper_picker_third_party_item.xml index 68661bc00..68661bc00 100644 --- a/res/layout/wallpaper_picker_third_party_item.xml +++ b/WallpaperPicker/res/layout/wallpaper_picker_third_party_item.xml diff --git a/res/menu/cab_delete_wallpapers.xml b/WallpaperPicker/res/menu/cab_delete_wallpapers.xml index 38ac5c4d6..38ac5c4d6 100644 --- a/res/menu/cab_delete_wallpapers.xml +++ b/WallpaperPicker/res/menu/cab_delete_wallpapers.xml diff --git a/res/mipmap-hdpi/ic_launcher_wallpaper.png b/WallpaperPicker/res/mipmap-hdpi/ic_launcher_wallpaper.png Binary files differindex affee851d..affee851d 100644 --- a/res/mipmap-hdpi/ic_launcher_wallpaper.png +++ b/WallpaperPicker/res/mipmap-hdpi/ic_launcher_wallpaper.png diff --git a/res/mipmap-mdpi/ic_launcher_wallpaper.png b/WallpaperPicker/res/mipmap-mdpi/ic_launcher_wallpaper.png Binary files differindex cb4443bdb..cb4443bdb 100644 --- a/res/mipmap-mdpi/ic_launcher_wallpaper.png +++ b/WallpaperPicker/res/mipmap-mdpi/ic_launcher_wallpaper.png diff --git a/res/mipmap-xhdpi/ic_launcher_wallpaper.png b/WallpaperPicker/res/mipmap-xhdpi/ic_launcher_wallpaper.png Binary files differindex 60f8dceec..60f8dceec 100644 --- a/res/mipmap-xhdpi/ic_launcher_wallpaper.png +++ b/WallpaperPicker/res/mipmap-xhdpi/ic_launcher_wallpaper.png diff --git a/res/mipmap-xxhdpi/ic_launcher_wallpaper.png b/WallpaperPicker/res/mipmap-xxhdpi/ic_launcher_wallpaper.png Binary files differindex 023fb5886..023fb5886 100644 --- a/res/mipmap-xxhdpi/ic_launcher_wallpaper.png +++ b/WallpaperPicker/res/mipmap-xxhdpi/ic_launcher_wallpaper.png diff --git a/res/values-nodpi/wallpapers.xml b/WallpaperPicker/res/values-nodpi/wallpapers.xml index 1e340e4b2..1e340e4b2 100644 --- a/res/values-nodpi/wallpapers.xml +++ b/WallpaperPicker/res/values-nodpi/wallpapers.xml diff --git a/WallpaperPicker/res/values-sw600dp/config.xml b/WallpaperPicker/res/values-sw600dp/config.xml new file mode 100644 index 000000000..62342dcc2 --- /dev/null +++ b/WallpaperPicker/res/values-sw600dp/config.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2013 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. +--> +<resources> + <bool name="allow_rotation">true</bool> +</resources> diff --git a/WallpaperPicker/res/values-sw720dp-v19/styles.xml b/WallpaperPicker/res/values-sw720dp-v19/styles.xml new file mode 100644 index 000000000..91078517d --- /dev/null +++ b/WallpaperPicker/res/values-sw720dp-v19/styles.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +* Copyright (C) 2013 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. +*/ +--> + +<resources> + <style name="Theme" parent="android:Theme.Holo.Wallpaper.NoTitleBar"> + <item name="android:windowActionModeOverlay">true</item> + <item name="android:windowTranslucentStatus">true</item> + <item name="android:windowTranslucentNavigation">true</item> + </style> +</resources> diff --git a/WallpaperPicker/res/values-sw720dp/dimens.xml b/WallpaperPicker/res/values-sw720dp/dimens.xml new file mode 100644 index 000000000..9ae155b3c --- /dev/null +++ b/WallpaperPicker/res/values-sw720dp/dimens.xml @@ -0,0 +1,28 @@ +<?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. +--> + +<resources> + <dimen name="app_icon_size">72dp</dimen> + +<!-- QSB --> + <dimen name="toolbar_button_vertical_padding">8dip</dimen> + <dimen name="toolbar_button_horizontal_padding">8dip</dimen> + + <!-- When dragging items on the workspace, the number of dps by which the position of + the drag view should be offset from the position of the original view. --> + <dimen name="dragViewOffsetX">0dp</dimen> + <dimen name="dragViewOffsetY">0dp</dimen> +</resources> diff --git a/WallpaperPicker/res/values-sw720dp/styles.xml b/WallpaperPicker/res/values-sw720dp/styles.xml new file mode 100644 index 000000000..b48909087 --- /dev/null +++ b/WallpaperPicker/res/values-sw720dp/styles.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +* Copyright (C) 2013 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. +*/ +--> + +<resources> + <style name="Theme" parent="android:Theme.Holo.Wallpaper.NoTitleBar"> + <item name="android:windowActionModeOverlay">true</item> + </style> +</resources> diff --git a/WallpaperPicker/res/values-v19/styles.xml b/WallpaperPicker/res/values-v19/styles.xml new file mode 100644 index 000000000..85a989d55 --- /dev/null +++ b/WallpaperPicker/res/values-v19/styles.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +* Copyright (C) 2013 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. +*/ +--> + +<resources> + <style name="Theme.WallpaperCropper" parent="@android:style/Theme.Holo"> + <item name="android:actionBarStyle">@style/WallpaperCropperActionBar</item> + <item name="android:windowFullscreen">true</item> + <item name="android:windowActionBarOverlay">true</item> + <item name="android:windowTranslucentNavigation">true</item> + </style> + + <style name="Theme" parent="@android:style/Theme.Holo.Wallpaper.NoTitleBar"> + <item name="android:windowTranslucentStatus">true</item> + <item name="android:windowTranslucentNavigation">true</item> + </style> +</resources> diff --git a/WallpaperPicker/res/values/colors.xml b/WallpaperPicker/res/values/colors.xml new file mode 100644 index 000000000..adae7cff6 --- /dev/null +++ b/WallpaperPicker/res/values/colors.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/assets/res/any/colors.xml +** +** Copyright 2013, 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. +*/ +--> +<resources> + <color name="wallpaper_picker_translucent_gray">#66000000</color> +</resources> diff --git a/WallpaperPicker/res/values/config.xml b/WallpaperPicker/res/values/config.xml new file mode 100644 index 000000000..71580b5b0 --- /dev/null +++ b/WallpaperPicker/res/values/config.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2013 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. +--> +<resources> + <bool name="allow_rotation">false</bool> + <!-- Specifies whether to expand the cropped area on both sides (rather + than just to one side) --> + <bool name="center_crop">false</bool> +</resources> diff --git a/res/layout/list_item_checkable.xml b/WallpaperPicker/res/values/dimens.xml index 86d6b1a4c..0447c6d1f 100644 --- a/res/layout/list_item_checkable.xml +++ b/WallpaperPicker/res/values/dimens.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2010 The Android Open Source Project +<!-- Copyright (C) 2013 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. @@ -13,14 +13,10 @@ See the License for the specific language governing permissions and limitations under the License. --> -<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:minHeight="?android:attr/listPreferredItemHeightSmall" - android:textAppearance="?android:attr/textAppearanceMedium" - android:textColor="?android:attr/textColorAlertDialogListItem" - android:gravity="center_vertical" - android:paddingStart="16dip" - android:paddingEnd="16dip" - android:checkMark="?android:attr/listChoiceIndicatorSingle" - android:ellipsize="marquee" /> + +<resources> +<!-- Wallpaper picker --> + <dimen name="wallpaperThumbnailWidth">106.5dp</dimen> + <dimen name="wallpaperThumbnailHeight">94.5dp</dimen> + <dimen name="wallpaperItemIconSize">32dp</dimen> +</resources> diff --git a/WallpaperPicker/res/values/strings.xml b/WallpaperPicker/res/values/strings.xml new file mode 100644 index 000000000..1ee3513f9 --- /dev/null +++ b/WallpaperPicker/res/values/strings.xml @@ -0,0 +1,53 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +* Copyright (C) 2013 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. +*/ +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <!-- Button label on Wallpaper picker screen; user selects this button to set a specific wallpaper --> + <string name="wallpaper_instructions">Set wallpaper</string> + <!-- Error message when an image is selected as a wallpaper, + but the wallpaper picker cannot load it --> + <string name="image_load_fail">Coudn\'t load image</string> + <!-- Error message when an image is selected as a wallpaper, + but the wallpaper cropper cannot load it. The user will + usually see this when using another app and trying to set + an image as the wallpaper --> + <string name="wallpaper_load_fail">Couldn\'t load image as wallpaper</string> + <!-- Shown when wallpapers are selected in Wallpaper picker --> + <!-- String indicating how many media item(s) is(are) selected + eg. 1 selected [CHAR LIMIT=30] --> + <plurals name="number_of_items_selected"> + <item quantity="zero">%1$d selected</item> + <item quantity="one">%1$d selected</item> + <item quantity="other">%1$d selected</item> + </plurals> + <!-- Accessibility string used as a label for a particular wallpaper in the Wallpaper Picker list. + e.g. "Wallpaper 3 of 10" --> + <string name="wallpaper_accessibility_name">Wallpaper %1$d of %2$d</string> + <!-- Accessibility string used to announce that a wallpaper has been selected. --> + <string name="announce_selection">Selected <xliff:g id="label" example="Wallpaper 3 of 10">%1$s</xliff:g></string> + + <!-- Label on button to delete wallpaper(s) --> + <string name="wallpaper_delete">Delete</string> + <!-- Label on button in Wallpaper Picker to pick an image --> + <string name="pick_image">Pick image</string> + <!-- Option in "Select wallpaper from" dialog box --> + <string name="pick_wallpaper">Wallpapers</string> + <!-- Title of activity for cropping wallpapers --> + <string name="crop_wallpaper">Crop wallpaper</string> +</resources> diff --git a/WallpaperPicker/res/values/styles.xml b/WallpaperPicker/res/values/styles.xml new file mode 100644 index 000000000..16b11f279 --- /dev/null +++ b/WallpaperPicker/res/values/styles.xml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +* Copyright (C) 2013 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. +*/ +--> + +<resources> + <style name="Theme.WallpaperCropper" parent="@android:style/Theme.Holo"> + <item name="android:actionBarStyle">@style/WallpaperCropperActionBar</item> + <item name="android:windowFullscreen">true</item> + <item name="android:windowActionBarOverlay">true</item> + </style> + + <style name="Theme.WallpaperPicker" parent="Theme.WallpaperCropper"> + <item name="android:windowBackground">@android:color/transparent</item> + <item name="android:colorBackgroundCacheHint">@null</item> + <item name="android:windowShowWallpaper">true</item> + </style> + + <style name="WallpaperCropperActionBar" parent="android:style/Widget.Holo.ActionBar"> + <item name="android:displayOptions">showCustom</item> + <item name="android:background">#88000000</item> + </style> + + <style name="Theme" parent="@android:style/Theme.Holo.Wallpaper.NoTitleBar"> + </style> + + <style name="ActionBarSetWallpaperStyle" parent="@android:style/Widget.Holo.ActionButton"> + <item name="android:textColor">#ffffffff</item> + </style> +</resources> diff --git a/src/com/android/gallery3d/common/BitmapUtils.java b/WallpaperPicker/src/com/android/gallery3d/common/BitmapUtils.java index a671ed2b9..a671ed2b9 100644 --- a/src/com/android/gallery3d/common/BitmapUtils.java +++ b/WallpaperPicker/src/com/android/gallery3d/common/BitmapUtils.java diff --git a/src/com/android/gallery3d/common/Utils.java b/WallpaperPicker/src/com/android/gallery3d/common/Utils.java index 614a081c8..614a081c8 100644 --- a/src/com/android/gallery3d/common/Utils.java +++ b/WallpaperPicker/src/com/android/gallery3d/common/Utils.java diff --git a/src/com/android/gallery3d/exif/ByteBufferInputStream.java b/WallpaperPicker/src/com/android/gallery3d/exif/ByteBufferInputStream.java index 7fb9f22cc..7fb9f22cc 100644 --- a/src/com/android/gallery3d/exif/ByteBufferInputStream.java +++ b/WallpaperPicker/src/com/android/gallery3d/exif/ByteBufferInputStream.java diff --git a/src/com/android/gallery3d/exif/CountedDataInputStream.java b/WallpaperPicker/src/com/android/gallery3d/exif/CountedDataInputStream.java index dfd4a1a10..dfd4a1a10 100644 --- a/src/com/android/gallery3d/exif/CountedDataInputStream.java +++ b/WallpaperPicker/src/com/android/gallery3d/exif/CountedDataInputStream.java diff --git a/src/com/android/gallery3d/exif/ExifData.java b/WallpaperPicker/src/com/android/gallery3d/exif/ExifData.java index 8422382bb..8422382bb 100644 --- a/src/com/android/gallery3d/exif/ExifData.java +++ b/WallpaperPicker/src/com/android/gallery3d/exif/ExifData.java diff --git a/src/com/android/gallery3d/exif/ExifInterface.java b/WallpaperPicker/src/com/android/gallery3d/exif/ExifInterface.java index a1cf0fc85..a1cf0fc85 100644 --- a/src/com/android/gallery3d/exif/ExifInterface.java +++ b/WallpaperPicker/src/com/android/gallery3d/exif/ExifInterface.java diff --git a/src/com/android/gallery3d/exif/ExifInvalidFormatException.java b/WallpaperPicker/src/com/android/gallery3d/exif/ExifInvalidFormatException.java index bf923ec26..bf923ec26 100644 --- a/src/com/android/gallery3d/exif/ExifInvalidFormatException.java +++ b/WallpaperPicker/src/com/android/gallery3d/exif/ExifInvalidFormatException.java diff --git a/src/com/android/gallery3d/exif/ExifModifier.java b/WallpaperPicker/src/com/android/gallery3d/exif/ExifModifier.java index f00362b6b..0531cbad9 100644 --- a/src/com/android/gallery3d/exif/ExifModifier.java +++ b/WallpaperPicker/src/com/android/gallery3d/exif/ExifModifier.java @@ -18,7 +18,6 @@ package com.android.gallery3d.exif; import android.util.Log; -import java.io.Closeable; import java.io.IOException; import java.io.InputStream; import java.nio.ByteBuffer; diff --git a/src/com/android/gallery3d/exif/ExifOutputStream.java b/WallpaperPicker/src/com/android/gallery3d/exif/ExifOutputStream.java index 7ca05f2e0..7ca05f2e0 100644 --- a/src/com/android/gallery3d/exif/ExifOutputStream.java +++ b/WallpaperPicker/src/com/android/gallery3d/exif/ExifOutputStream.java diff --git a/src/com/android/gallery3d/exif/ExifParser.java b/WallpaperPicker/src/com/android/gallery3d/exif/ExifParser.java index 5467d423d..5467d423d 100644 --- a/src/com/android/gallery3d/exif/ExifParser.java +++ b/WallpaperPicker/src/com/android/gallery3d/exif/ExifParser.java diff --git a/src/com/android/gallery3d/exif/ExifReader.java b/WallpaperPicker/src/com/android/gallery3d/exif/ExifReader.java index 68e972fb7..68e972fb7 100644 --- a/src/com/android/gallery3d/exif/ExifReader.java +++ b/WallpaperPicker/src/com/android/gallery3d/exif/ExifReader.java diff --git a/src/com/android/gallery3d/exif/ExifTag.java b/WallpaperPicker/src/com/android/gallery3d/exif/ExifTag.java index b8b387201..b8b387201 100644 --- a/src/com/android/gallery3d/exif/ExifTag.java +++ b/WallpaperPicker/src/com/android/gallery3d/exif/ExifTag.java diff --git a/src/com/android/gallery3d/exif/IfdData.java b/WallpaperPicker/src/com/android/gallery3d/exif/IfdData.java index 093944aec..093944aec 100644 --- a/src/com/android/gallery3d/exif/IfdData.java +++ b/WallpaperPicker/src/com/android/gallery3d/exif/IfdData.java diff --git a/src/com/android/gallery3d/exif/IfdId.java b/WallpaperPicker/src/com/android/gallery3d/exif/IfdId.java index 7842edbd4..7842edbd4 100644 --- a/src/com/android/gallery3d/exif/IfdId.java +++ b/WallpaperPicker/src/com/android/gallery3d/exif/IfdId.java diff --git a/src/com/android/gallery3d/exif/JpegHeader.java b/WallpaperPicker/src/com/android/gallery3d/exif/JpegHeader.java index e3e787eff..e3e787eff 100644 --- a/src/com/android/gallery3d/exif/JpegHeader.java +++ b/WallpaperPicker/src/com/android/gallery3d/exif/JpegHeader.java diff --git a/src/com/android/gallery3d/exif/OrderedDataOutputStream.java b/WallpaperPicker/src/com/android/gallery3d/exif/OrderedDataOutputStream.java index 428e6b9fc..428e6b9fc 100644 --- a/src/com/android/gallery3d/exif/OrderedDataOutputStream.java +++ b/WallpaperPicker/src/com/android/gallery3d/exif/OrderedDataOutputStream.java diff --git a/src/com/android/gallery3d/exif/Rational.java b/WallpaperPicker/src/com/android/gallery3d/exif/Rational.java index 591d63faf..591d63faf 100644 --- a/src/com/android/gallery3d/exif/Rational.java +++ b/WallpaperPicker/src/com/android/gallery3d/exif/Rational.java diff --git a/src/com/android/gallery3d/glrenderer/BasicTexture.java b/WallpaperPicker/src/com/android/gallery3d/glrenderer/BasicTexture.java index 2e77b903f..2e77b903f 100644 --- a/src/com/android/gallery3d/glrenderer/BasicTexture.java +++ b/WallpaperPicker/src/com/android/gallery3d/glrenderer/BasicTexture.java diff --git a/src/com/android/gallery3d/glrenderer/BitmapTexture.java b/WallpaperPicker/src/com/android/gallery3d/glrenderer/BitmapTexture.java index 100b0b3b9..100b0b3b9 100644 --- a/src/com/android/gallery3d/glrenderer/BitmapTexture.java +++ b/WallpaperPicker/src/com/android/gallery3d/glrenderer/BitmapTexture.java diff --git a/src/com/android/gallery3d/glrenderer/GLCanvas.java b/WallpaperPicker/src/com/android/gallery3d/glrenderer/GLCanvas.java index 305e90521..5b0747704 100644 --- a/src/com/android/gallery3d/glrenderer/GLCanvas.java +++ b/WallpaperPicker/src/com/android/gallery3d/glrenderer/GLCanvas.java @@ -20,8 +20,6 @@ import android.graphics.Bitmap; import android.graphics.Rect; import android.graphics.RectF; -import javax.microedition.khronos.opengles.GL11; - // // GLCanvas gives a convenient interface to draw using OpenGL. // diff --git a/src/com/android/gallery3d/glrenderer/GLES20Canvas.java b/WallpaperPicker/src/com/android/gallery3d/glrenderer/GLES20Canvas.java index 4ead1315e..4ead1315e 100644 --- a/src/com/android/gallery3d/glrenderer/GLES20Canvas.java +++ b/WallpaperPicker/src/com/android/gallery3d/glrenderer/GLES20Canvas.java diff --git a/src/com/android/gallery3d/glrenderer/GLES20IdImpl.java b/WallpaperPicker/src/com/android/gallery3d/glrenderer/GLES20IdImpl.java index 6cd7149cb..6cd7149cb 100644 --- a/src/com/android/gallery3d/glrenderer/GLES20IdImpl.java +++ b/WallpaperPicker/src/com/android/gallery3d/glrenderer/GLES20IdImpl.java diff --git a/src/com/android/gallery3d/glrenderer/GLId.java b/WallpaperPicker/src/com/android/gallery3d/glrenderer/GLId.java index 3cec558f6..3cec558f6 100644 --- a/src/com/android/gallery3d/glrenderer/GLId.java +++ b/WallpaperPicker/src/com/android/gallery3d/glrenderer/GLId.java diff --git a/src/com/android/gallery3d/glrenderer/GLPaint.java b/WallpaperPicker/src/com/android/gallery3d/glrenderer/GLPaint.java index 16b220690..16b220690 100644 --- a/src/com/android/gallery3d/glrenderer/GLPaint.java +++ b/WallpaperPicker/src/com/android/gallery3d/glrenderer/GLPaint.java diff --git a/src/com/android/gallery3d/glrenderer/RawTexture.java b/WallpaperPicker/src/com/android/gallery3d/glrenderer/RawTexture.java index 93f0fdff9..93f0fdff9 100644 --- a/src/com/android/gallery3d/glrenderer/RawTexture.java +++ b/WallpaperPicker/src/com/android/gallery3d/glrenderer/RawTexture.java diff --git a/src/com/android/gallery3d/glrenderer/Texture.java b/WallpaperPicker/src/com/android/gallery3d/glrenderer/Texture.java index 3dcae4aec..3dcae4aec 100644 --- a/src/com/android/gallery3d/glrenderer/Texture.java +++ b/WallpaperPicker/src/com/android/gallery3d/glrenderer/Texture.java diff --git a/src/com/android/gallery3d/glrenderer/UploadedTexture.java b/WallpaperPicker/src/com/android/gallery3d/glrenderer/UploadedTexture.java index f41a979b7..f41a979b7 100644 --- a/src/com/android/gallery3d/glrenderer/UploadedTexture.java +++ b/WallpaperPicker/src/com/android/gallery3d/glrenderer/UploadedTexture.java diff --git a/src/com/android/gallery3d/util/IntArray.java b/WallpaperPicker/src/com/android/gallery3d/util/IntArray.java index 2c4dc2c83..2c4dc2c83 100644 --- a/src/com/android/gallery3d/util/IntArray.java +++ b/WallpaperPicker/src/com/android/gallery3d/util/IntArray.java diff --git a/WallpaperPicker/src/com/android/launcher3/AlphaDisableableButton.java b/WallpaperPicker/src/com/android/launcher3/AlphaDisableableButton.java new file mode 100644 index 000000000..f0796c36f --- /dev/null +++ b/WallpaperPicker/src/com/android/launcher3/AlphaDisableableButton.java @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2014 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.android.launcher3; + +import android.content.Context; +import android.util.AttributeSet; +import android.widget.Button; + +/** + * A Button which becomes translucent when it is disabled + */ +public class AlphaDisableableButton extends Button { + public static float DISABLED_ALPHA_VALUE = 0.4f; + public AlphaDisableableButton(Context context) { + this(context, null); + } + + public AlphaDisableableButton(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public AlphaDisableableButton(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + setLayerType(LAYER_TYPE_HARDWARE, null); + } + + @Override + public void setEnabled(boolean enabled) { + super.setEnabled(enabled); + if(enabled) { + setAlpha(1.0f); + } else { + setAlpha(DISABLED_ALPHA_VALUE); + } + } +} diff --git a/src/com/android/launcher3/CheckableFrameLayout.java b/WallpaperPicker/src/com/android/launcher3/CheckableFrameLayout.java index 5b7d82425..5b7d82425 100644 --- a/src/com/android/launcher3/CheckableFrameLayout.java +++ b/WallpaperPicker/src/com/android/launcher3/CheckableFrameLayout.java diff --git a/src/com/android/launcher3/CropView.java b/WallpaperPicker/src/com/android/launcher3/CropView.java index 9224e3bb2..578b8eafd 100644 --- a/src/com/android/launcher3/CropView.java +++ b/WallpaperPicker/src/com/android/launcher3/CropView.java @@ -165,7 +165,8 @@ public class CropView extends TiledImageView implements OnScaleGestureListener { final float imageWidth = imageDims[0]; final float imageHeight = imageDims[1]; mMinScale = Math.max(w / imageWidth, h / imageHeight); - mRenderer.scale = Math.max(mMinScale, mRenderer.scale); + mRenderer.scale = + Math.max(mMinScale, resetScale ? Float.MIN_VALUE : mRenderer.scale); } } } diff --git a/WallpaperPicker/src/com/android/launcher3/DrawableTileSource.java b/WallpaperPicker/src/com/android/launcher3/DrawableTileSource.java new file mode 100644 index 000000000..c1f2eff0f --- /dev/null +++ b/WallpaperPicker/src/com/android/launcher3/DrawableTileSource.java @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2013 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.android.launcher3; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; + +import com.android.gallery3d.glrenderer.BasicTexture; +import com.android.gallery3d.glrenderer.BitmapTexture; +import com.android.photos.views.TiledImageRenderer; + +public class DrawableTileSource implements TiledImageRenderer.TileSource { + private static final int GL_SIZE_LIMIT = 2048; + // This must be no larger than half the size of the GL_SIZE_LIMIT + // due to decodePreview being allowed to be up to 2x the size of the target + public static final int MAX_PREVIEW_SIZE = GL_SIZE_LIMIT / 2; + + private int mTileSize; + private int mPreviewSize; + private Drawable mDrawable; + private BitmapTexture mPreview; + + public DrawableTileSource(Context context, Drawable d, int previewSize) { + mTileSize = TiledImageRenderer.suggestedTileSize(context); + mDrawable = d; + mPreviewSize = Math.min(previewSize, MAX_PREVIEW_SIZE); + } + + @Override + public int getTileSize() { + return mTileSize; + } + + @Override + public int getImageWidth() { + return mDrawable.getIntrinsicWidth(); + } + + @Override + public int getImageHeight() { + return mDrawable.getIntrinsicHeight(); + } + + @Override + public int getRotation() { + return 0; + } + + @Override + public BasicTexture getPreview() { + if (mPreviewSize == 0) { + return null; + } + if (mPreview == null){ + float width = getImageWidth(); + float height = getImageHeight(); + while (width > MAX_PREVIEW_SIZE || height > MAX_PREVIEW_SIZE) { + width /= 2; + height /= 2; + } + Bitmap b = Bitmap.createBitmap((int) width, (int) height, Bitmap.Config.ARGB_8888); + Canvas c = new Canvas(b); + mDrawable.setBounds(new Rect(0, 0, (int) width, (int) height)); + mDrawable.draw(c); + c.setBitmap(null); + mPreview = new BitmapTexture(b); + } + return mPreview; + } + + @Override + public Bitmap getTile(int level, int x, int y, Bitmap bitmap) { + int tileSize = getTileSize(); + if (bitmap == null) { + bitmap = Bitmap.createBitmap(tileSize, tileSize, Bitmap.Config.ARGB_8888); + } + Canvas c = new Canvas(bitmap); + Rect bounds = new Rect(0, 0, getImageWidth(), getImageHeight()); + bounds.offset(-x, -y); + mDrawable.setBounds(bounds); + mDrawable.draw(c); + c.setBitmap(null); + return bitmap; + } +} diff --git a/src/com/android/launcher3/LiveWallpaperListAdapter.java b/WallpaperPicker/src/com/android/launcher3/LiveWallpaperListAdapter.java index 43d8cfe0c..88f4461bf 100644 --- a/src/com/android/launcher3/LiveWallpaperListAdapter.java +++ b/WallpaperPicker/src/com/android/launcher3/LiveWallpaperListAdapter.java @@ -118,13 +118,12 @@ public class LiveWallpaperListAdapter extends BaseAdapter implements ListAdapter mInfo = info; } @Override - public void onClick(WallpaperCropActivity a) { + public void onClick(WallpaperPickerActivity a) { Intent preview = new Intent(WallpaperManager.ACTION_CHANGE_LIVE_WALLPAPER); preview.putExtra(WallpaperManager.EXTRA_LIVE_WALLPAPER_COMPONENT, mInfo.getComponent()); - a.onLiveWallpaperPickerLaunch(); - Utilities.startActivityForResultSafely( - a, preview, WallpaperPickerActivity.PICK_LIVE_WALLPAPER); + a.onLiveWallpaperPickerLaunch(mInfo); + a.startActivityForResultSafely(preview, WallpaperPickerActivity.PICK_LIVE_WALLPAPER); } } @@ -190,7 +189,9 @@ public class LiveWallpaperListAdapter extends BaseAdapter implements ListAdapter LiveWallpaperListAdapter.this.notifyDataSetChanged(); break; } - info.mThumbnail.setDither(true); + if (info.mThumbnail != null) { + info.mThumbnail.setDither(true); + } if (mWallpaperPosition < mWallpapers.size()) { mWallpapers.set(mWallpaperPosition, info); } else { diff --git a/src/com/android/launcher3/SavedWallpaperImages.java b/WallpaperPicker/src/com/android/launcher3/SavedWallpaperImages.java index a418b8f5c..44bfdf1f9 100644 --- a/src/com/android/launcher3/SavedWallpaperImages.java +++ b/WallpaperPicker/src/com/android/launcher3/SavedWallpaperImages.java @@ -49,7 +49,7 @@ public class SavedWallpaperImages extends BaseAdapter implements ListAdapter { Context mContext; LayoutInflater mLayoutInflater; - public static class SavedWallpaperTile extends WallpaperCropActivity.WallpaperTileInfo { + public static class SavedWallpaperTile extends WallpaperPickerActivity.WallpaperTileInfo { private int mDbId; private Drawable mThumb; public SavedWallpaperTile(int dbId, Drawable thumb) { @@ -57,24 +57,21 @@ public class SavedWallpaperImages extends BaseAdapter implements ListAdapter { mThumb = thumb; } @Override - public void onClick(WallpaperCropActivity a) { + public void onClick(WallpaperPickerActivity a) { String imageFilename = a.getSavedImages().getImageFilename(mDbId); File file = new File(a.getFilesDir(), imageFilename); - CropView v = a.getCropView(); - int rotation = WallpaperCropActivity.getRotationFromExif(file.getAbsolutePath()); - v.setTileSource( - new BitmapRegionTileSource(a, file.getAbsolutePath(), 1024, rotation), null); - v.moveToLeft(); - v.setTouchEnabled(false); + BitmapRegionTileSource.FilePathBitmapSource bitmapSource = + new BitmapRegionTileSource.FilePathBitmapSource(file.getAbsolutePath(), 1024); + a.setCropViewTileSource(bitmapSource, false, true, null); } @Override - public void onSave(WallpaperCropActivity a) { + public void onSave(WallpaperPickerActivity a) { boolean finishActivityWhenDone = true; String imageFilename = a.getSavedImages().getImageFilename(mDbId); a.setWallpaper(imageFilename, finishActivityWhenDone); } @Override - public void onDelete(WallpaperCropActivity a) { + public void onDelete(WallpaperPickerActivity a) { a.getSavedImages().deleteImage(mDbId); } @Override @@ -88,6 +85,9 @@ public class SavedWallpaperImages extends BaseAdapter implements ListAdapter { } public SavedWallpaperImages(Activity context) { + // We used to store the saved images in the cache directory, but that meant they'd get + // deleted sometimes-- move them to the data directory + ImageDb.moveFromCacheDirectoryIfNecessary(context); mDb = new ImageDb(context); mContext = context; mLayoutInflater = context.getLayoutInflater(); @@ -218,11 +218,20 @@ public class SavedWallpaperImages extends BaseAdapter implements ListAdapter { Context mContext; public ImageDb(Context context) { - super(context, new File(context.getCacheDir(), DB_NAME).getPath(), null, DB_VERSION); + super(context, context.getDatabasePath(DB_NAME).getPath(), null, DB_VERSION); // Store the context for later use mContext = context; } + public static void moveFromCacheDirectoryIfNecessary(Context context) { + // We used to store the saved images in the cache directory, but that meant they'd get + // deleted sometimes-- move them to the data directory + File oldSavedImagesFile = new File(context.getCacheDir(), ImageDb.DB_NAME); + File savedImagesFile = context.getDatabasePath(ImageDb.DB_NAME); + if (oldSavedImagesFile.exists()) { + oldSavedImagesFile.renameTo(savedImagesFile); + } + } @Override public void onCreate(SQLiteDatabase database) { database.execSQL("CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " (" + diff --git a/src/com/android/launcher3/ThirdPartyWallpaperPickerListAdapter.java b/WallpaperPicker/src/com/android/launcher3/ThirdPartyWallpaperPickerListAdapter.java index 81cd5a0f0..7a4d48ca9 100644 --- a/src/com/android/launcher3/ThirdPartyWallpaperPickerListAdapter.java +++ b/WallpaperPicker/src/com/android/launcher3/ThirdPartyWallpaperPickerListAdapter.java @@ -51,13 +51,13 @@ public class ThirdPartyWallpaperPickerListAdapter extends BaseAdapter implements mResolveInfo = resolveInfo; } @Override - public void onClick(WallpaperCropActivity a) { + public void onClick(WallpaperPickerActivity a) { final ComponentName itemComponentName = new ComponentName( mResolveInfo.activityInfo.packageName, mResolveInfo.activityInfo.name); Intent launchIntent = new Intent(Intent.ACTION_SET_WALLPAPER); launchIntent.setComponent(itemComponentName); - Utilities.startActivityForResultSafely( - a, launchIntent, WallpaperPickerActivity.PICK_WALLPAPER_THIRD_PARTY_ACTIVITY); + a.startActivityForResultSafely( + launchIntent, WallpaperPickerActivity.PICK_WALLPAPER_THIRD_PARTY_ACTIVITY); } } diff --git a/src/com/android/launcher3/WallpaperCropActivity.java b/WallpaperPicker/src/com/android/launcher3/WallpaperCropActivity.java index 5796a5ddd..561c4bb6a 100644 --- a/src/com/android/launcher3/WallpaperCropActivity.java +++ b/WallpaperPicker/src/com/android/launcher3/WallpaperCropActivity.java @@ -37,15 +37,16 @@ import android.graphics.RectF; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; -import android.util.FloatMath; import android.util.Log; import android.view.Display; import android.view.View; import android.view.WindowManager; +import android.widget.Toast; import com.android.gallery3d.common.Utils; import com.android.gallery3d.exif.ExifInterface; import com.android.photos.BitmapRegionTileSource; +import com.android.photos.BitmapRegionTileSource.BitmapSource; import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; @@ -59,7 +60,7 @@ public class WallpaperCropActivity extends Activity { protected static final String WALLPAPER_WIDTH_KEY = "wallpaper.width"; protected static final String WALLPAPER_HEIGHT_KEY = "wallpaper.height"; - protected static final int DEFAULT_COMPRESS_QUALITY = 90; + private static final int DEFAULT_COMPRESS_QUALITY = 90; /** * The maximum bitmap size we allow to be returned through the intent. * Intents have a maximum of 1MB in total size. However, the Bitmap seems to @@ -68,27 +69,13 @@ public class WallpaperCropActivity extends Activity { * array instead of a Bitmap instance to avoid overhead. */ public static final int MAX_BMAP_IN_INTENT = 750000; - protected static final float WALLPAPER_SCREENS_SPAN = 2f; + private static final float WALLPAPER_SCREENS_SPAN = 2f; + + protected static Point sDefaultWallpaperSize; protected CropView mCropView; protected Uri mUri; - - public static abstract class WallpaperTileInfo { - protected View mView; - public void setView(View v) { - mView = v; - } - public void onClick(WallpaperCropActivity a) {} - public void onSave(WallpaperCropActivity a) {} - public void onDelete(WallpaperCropActivity a) {} - public boolean isSelectable() { return false; } - public boolean isNamelessWallpaper() { return false; } - public void onIndexUpdated(CharSequence label) { - if (isNamelessWallpaper()) { - mView.setContentDescription(label); - } - } - } + protected View mSetWallpaperButton; @Override protected void onCreate(Bundle savedInstanceState) { @@ -113,9 +100,6 @@ public class WallpaperCropActivity extends Activity { return; } - int rotation = getRotationFromExif(this, imageUri); - mCropView.setTileSource(new BitmapRegionTileSource(this, imageUri, 1024, rotation), null); - mCropView.setTouchEnabled(true); // Action bar // Show the custom action bar view final ActionBar actionBar = getActionBar(); @@ -128,6 +112,67 @@ public class WallpaperCropActivity extends Activity { cropImageAndSetWallpaper(imageUri, null, finishActivityWhenDone); } }); + mSetWallpaperButton = findViewById(R.id.set_wallpaper_button); + + // Load image in background + final BitmapRegionTileSource.UriBitmapSource bitmapSource = + new BitmapRegionTileSource.UriBitmapSource(this, imageUri, 1024); + mSetWallpaperButton.setEnabled(false); + Runnable onLoad = new Runnable() { + public void run() { + if (bitmapSource.getLoadingState() != BitmapSource.State.LOADED) { + Toast.makeText(WallpaperCropActivity.this, + getString(R.string.wallpaper_load_fail), + Toast.LENGTH_LONG).show(); + finish(); + } else { + mSetWallpaperButton.setEnabled(true); + } + } + }; + setCropViewTileSource(bitmapSource, true, false, onLoad); + } + + public void setCropViewTileSource( + final BitmapRegionTileSource.BitmapSource bitmapSource, final boolean touchEnabled, + final boolean moveToLeft, final Runnable postExecute) { + final Context context = WallpaperCropActivity.this; + final View progressView = findViewById(R.id.loading); + final AsyncTask<Void, Void, Void> loadBitmapTask = new AsyncTask<Void, Void, Void>() { + protected Void doInBackground(Void...args) { + if (!isCancelled()) { + bitmapSource.loadInBackground(); + } + return null; + } + protected void onPostExecute(Void arg) { + if (!isCancelled()) { + progressView.setVisibility(View.INVISIBLE); + if (bitmapSource.getLoadingState() == BitmapSource.State.LOADED) { + mCropView.setTileSource( + new BitmapRegionTileSource(context, bitmapSource), null); + mCropView.setTouchEnabled(touchEnabled); + if (moveToLeft) { + mCropView.moveToLeft(); + } + } + } + if (postExecute != null) { + postExecute.run(); + } + } + }; + // We don't want to show the spinner every time we load an image, because that would be + // annoying; instead, only start showing the spinner if loading the image has taken + // longer than 1 sec (ie 1000 ms) + progressView.postDelayed(new Runnable() { + public void run() { + if (loadBitmapTask.getStatus() != AsyncTask.Status.FINISHED) { + progressView.setVisibility(View.VISIBLE); + } + } + }, 1000); + loadBitmapTask.execute(); } public boolean enableRotation() { @@ -140,7 +185,7 @@ public class WallpaperCropActivity extends Activity { // As a ratio of screen height, the total distance we want the parallax effect to span // horizontally - protected static float wallpaperTravelToScreenWidthRatio(int width, int height) { + private static float wallpaperTravelToScreenWidthRatio(int width, int height) { float aspectRatio = width / (float) height; // At an aspect ratio of 16/10, the wallpaper parallax effect should span 1.5 * screen width @@ -166,32 +211,34 @@ public class WallpaperCropActivity extends Activity { } static protected Point getDefaultWallpaperSize(Resources res, WindowManager windowManager) { - Point minDims = new Point(); - Point maxDims = new Point(); - windowManager.getDefaultDisplay().getCurrentSizeRange(minDims, maxDims); - - int maxDim = Math.max(maxDims.x, maxDims.y); - int minDim = Math.max(minDims.x, minDims.y); - - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) { - Point realSize = new Point(); - windowManager.getDefaultDisplay().getRealSize(realSize); - maxDim = Math.max(realSize.x, realSize.y); - minDim = Math.min(realSize.x, realSize.y); - } + if (sDefaultWallpaperSize == null) { + Point minDims = new Point(); + Point maxDims = new Point(); + windowManager.getDefaultDisplay().getCurrentSizeRange(minDims, maxDims); + + int maxDim = Math.max(maxDims.x, maxDims.y); + int minDim = Math.max(minDims.x, minDims.y); + + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) { + Point realSize = new Point(); + windowManager.getDefaultDisplay().getRealSize(realSize); + maxDim = Math.max(realSize.x, realSize.y); + minDim = Math.min(realSize.x, realSize.y); + } - // We need to ensure that there is enough extra space in the wallpaper - // for the intended - // parallax effects - final int defaultWidth, defaultHeight; - if (isScreenLarge(res)) { - defaultWidth = (int) (maxDim * wallpaperTravelToScreenWidthRatio(maxDim, minDim)); - defaultHeight = maxDim; - } else { - defaultWidth = Math.max((int) (minDim * WALLPAPER_SCREENS_SPAN), maxDim); - defaultHeight = maxDim; + // We need to ensure that there is enough extra space in the wallpaper + // for the intended parallax effects + final int defaultWidth, defaultHeight; + if (isScreenLarge(res)) { + defaultWidth = (int) (maxDim * wallpaperTravelToScreenWidthRatio(maxDim, minDim)); + defaultHeight = maxDim; + } else { + defaultWidth = Math.max((int) (minDim * WALLPAPER_SCREENS_SPAN), maxDim); + defaultHeight = maxDim; + } + sDefaultWallpaperSize = new Point(defaultWidth, defaultHeight); } - return new Point(defaultWidth, defaultHeight); + return sDefaultWallpaperSize; } public static int getRotationFromExif(String path) { @@ -209,16 +256,18 @@ public class WallpaperCropActivity extends Activity { private static int getRotationFromExifHelper( String path, Resources res, int resId, Context context, Uri uri) { ExifInterface ei = new ExifInterface(); + InputStream is = null; + BufferedInputStream bis = null; try { if (path != null) { ei.readExif(path); } else if (uri != null) { - InputStream is = context.getContentResolver().openInputStream(uri); - BufferedInputStream bis = new BufferedInputStream(is); + is = context.getContentResolver().openInputStream(uri); + bis = new BufferedInputStream(is); ei.readExif(bis); } else { - InputStream is = res.openRawResource(resId); - BufferedInputStream bis = new BufferedInputStream(is); + is = res.openRawResource(resId); + bis = new BufferedInputStream(is); ei.readExif(bis); } Integer ori = ei.getTagIntValue(ExifInterface.TAG_ORIENTATION); @@ -228,7 +277,11 @@ public class WallpaperCropActivity extends Activity { } catch (IOException e) { Log.w(LOGTAG, "Getting exif data failed", e); } catch (NullPointerException e) { + // Sometimes the ExifInterface has an internal NPE if Exif data isn't valid Log.w(LOGTAG, "Getting exif data failed", e); + } finally { + Utils.closeSilently(bis); + Utils.closeSilently(is); } return 0; } @@ -278,50 +331,25 @@ public class WallpaperCropActivity extends Activity { cropTask.execute(); } - protected static boolean isScreenLarge(Resources res) { + private static boolean isScreenLarge(Resources res) { Configuration config = res.getConfiguration(); return config.smallestScreenWidthDp >= 720; } protected void cropImageAndSetWallpaper(Uri uri, OnBitmapCroppedHandler onBitmapCroppedHandler, final boolean finishActivityWhenDone) { + boolean centerCrop = getResources().getBoolean(R.bool.center_crop); // Get the crop boolean ltr = mCropView.getLayoutDirection() == View.LAYOUT_DIRECTION_LTR; - Point minDims = new Point(); - Point maxDims = new Point(); Display d = getWindowManager().getDefaultDisplay(); - d.getCurrentSizeRange(minDims, maxDims); Point displaySize = new Point(); d.getSize(displaySize); - - int maxDim = Math.max(maxDims.x, maxDims.y); - final int minDim = Math.min(minDims.x, minDims.y); - int defaultWallpaperWidth; - if (isScreenLarge(getResources())) { - defaultWallpaperWidth = (int) (maxDim * - wallpaperTravelToScreenWidthRatio(maxDim, minDim)); - } else { - defaultWallpaperWidth = Math.max((int) - (minDim * WALLPAPER_SCREENS_SPAN), maxDim); - } - boolean isPortrait = displaySize.x < displaySize.y; - int portraitHeight; - if (isPortrait) { - portraitHeight = mCropView.getHeight(); - } else { - // TODO: how to actually get the proper portrait height? - // This is not quite right: - portraitHeight = Math.max(maxDims.x, maxDims.y); - } - if (android.os.Build.VERSION.SDK_INT >= - android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) { - Point realSize = new Point(); - d.getRealSize(realSize); - portraitHeight = Math.max(realSize.x, realSize.y); - } + + Point defaultWallpaperSize = getDefaultWallpaperSize(getResources(), + getWindowManager()); // Get the crop RectF cropRect = mCropView.getCrop(); int cropRotation = mCropView.getImageRotation(); @@ -338,23 +366,33 @@ public class WallpaperCropActivity extends Activity { // ADJUST CROP WIDTH // Extend the crop all the way to the right, for parallax // (or all the way to the left, in RTL) - float extraSpace = ltr ? rotatedInSize[0] - cropRect.right : cropRect.left; + float extraSpace; + if (centerCrop) { + extraSpace = 2f * Math.min(rotatedInSize[0] - cropRect.right, cropRect.left); + } else { + extraSpace = ltr ? rotatedInSize[0] - cropRect.right : cropRect.left; + } // Cap the amount of extra width - float maxExtraSpace = defaultWallpaperWidth / cropScale - cropRect.width(); + float maxExtraSpace = defaultWallpaperSize.x / cropScale - cropRect.width(); extraSpace = Math.min(extraSpace, maxExtraSpace); - if (ltr) { - cropRect.right += extraSpace; + if (centerCrop) { + cropRect.left -= extraSpace / 2f; + cropRect.right += extraSpace / 2f; } else { - cropRect.left -= extraSpace; + if (ltr) { + cropRect.right += extraSpace; + } else { + cropRect.left -= extraSpace; + } } // ADJUST CROP HEIGHT if (isPortrait) { - cropRect.bottom = cropRect.top + portraitHeight / cropScale; + cropRect.bottom = cropRect.top + defaultWallpaperSize.y / cropScale; } else { // LANDSCAPE float extraPortraitHeight = - portraitHeight / cropScale - cropRect.height(); + defaultWallpaperSize.y / cropScale - cropRect.height(); float expandHeight = Math.min(Math.min(rotatedInSize[1] - cropRect.bottom, cropRect.top), extraPortraitHeight / 2); @@ -391,7 +429,6 @@ public class WallpaperCropActivity extends Activity { String mInFilePath; byte[] mInImageBytes; int mInResId = 0; - InputStream mInStream; RectF mCropBounds = null; int mOutWidth, mOutHeight; int mRotation; @@ -464,37 +501,36 @@ public class WallpaperCropActivity extends Activity { } // Helper to setup input stream - private void regenerateInputStream() { + private InputStream regenerateInputStream() { if (mInUri == null && mInResId == 0 && mInFilePath == null && mInImageBytes == null) { Log.w(LOGTAG, "cannot read original file, no input URI, resource ID, or " + "image byte array given"); } else { - Utils.closeSilently(mInStream); try { if (mInUri != null) { - mInStream = new BufferedInputStream( + return new BufferedInputStream( mContext.getContentResolver().openInputStream(mInUri)); } else if (mInFilePath != null) { - mInStream = mContext.openFileInput(mInFilePath); + return mContext.openFileInput(mInFilePath); } else if (mInImageBytes != null) { - mInStream = new BufferedInputStream( - new ByteArrayInputStream(mInImageBytes)); + return new BufferedInputStream(new ByteArrayInputStream(mInImageBytes)); } else { - mInStream = new BufferedInputStream( - mResources.openRawResource(mInResId)); + return new BufferedInputStream(mResources.openRawResource(mInResId)); } } catch (FileNotFoundException e) { Log.w(LOGTAG, "cannot read file: " + mInUri.toString(), e); } } + return null; } public Point getImageBounds() { - regenerateInputStream(); - if (mInStream != null) { + InputStream is = regenerateInputStream(); + if (is != null) { BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; - BitmapFactory.decodeStream(mInStream, null, options); + BitmapFactory.decodeStream(is, null, options); + Utils.closeSilently(is); if (options.outWidth != 0 && options.outHeight != 0) { return new Point(options.outWidth, options.outHeight); } @@ -512,26 +548,32 @@ public class WallpaperCropActivity extends Activity { public boolean cropBitmap() { boolean failure = false; - regenerateInputStream(); WallpaperManager wallpaperManager = null; if (mSetWallpaper) { wallpaperManager = WallpaperManager.getInstance(mContext.getApplicationContext()); } - if (mSetWallpaper && mNoCrop && mInStream != null) { + + + if (mSetWallpaper && mNoCrop) { try { - wallpaperManager.setStream(mInStream); + InputStream is = regenerateInputStream(); + if (is != null) { + wallpaperManager.setStream(is); + Utils.closeSilently(is); + } } catch (IOException e) { Log.w(LOGTAG, "cannot write stream to wallpaper", e); failure = true; } return !failure; - } - if (mInStream != null) { + } else { // Find crop bounds (scaled to original image size) Rect roundedTrueCrop = new Rect(); Matrix rotateMatrix = new Matrix(); Matrix inverseRotateMatrix = new Matrix(); + + Point bounds = getImageBounds(); if (mRotation > 0) { rotateMatrix.setRotate(mRotation); inverseRotateMatrix.setRotate(-mRotation); @@ -539,7 +581,11 @@ public class WallpaperCropActivity extends Activity { mCropBounds.roundOut(roundedTrueCrop); mCropBounds = new RectF(roundedTrueCrop); - Point bounds = getImageBounds(); + if (bounds == null) { + Log.w(LOGTAG, "cannot get bounds for image"); + failure = true; + return false; + } float[] rotatedBounds = new float[] { bounds.x, bounds.y }; rotateMatrix.mapPoints(rotatedBounds); @@ -550,7 +596,6 @@ public class WallpaperCropActivity extends Activity { inverseRotateMatrix.mapRect(mCropBounds); mCropBounds.offset(bounds.x/2, bounds.y/2); - regenerateInputStream(); } mCropBounds.roundOut(roundedTrueCrop); @@ -562,15 +607,25 @@ public class WallpaperCropActivity extends Activity { } // See how much we're reducing the size of the image - int scaleDownSampleSize = Math.min(roundedTrueCrop.width() / mOutWidth, - roundedTrueCrop.height() / mOutHeight); - + int scaleDownSampleSize = Math.max(1, Math.min(roundedTrueCrop.width() / mOutWidth, + roundedTrueCrop.height() / mOutHeight)); // Attempt to open a region decoder BitmapRegionDecoder decoder = null; + InputStream is = null; try { - decoder = BitmapRegionDecoder.newInstance(mInStream, true); + is = regenerateInputStream(); + if (is == null) { + Log.w(LOGTAG, "cannot get input stream for uri=" + mInUri.toString()); + failure = true; + return false; + } + decoder = BitmapRegionDecoder.newInstance(is, false); + Utils.closeSilently(is); } catch (IOException e) { Log.w(LOGTAG, "cannot open region decoder for file: " + mInUri.toString(), e); + } finally { + Utils.closeSilently(is); + is = null; } Bitmap crop = null; @@ -586,22 +641,49 @@ public class WallpaperCropActivity extends Activity { if (crop == null) { // BitmapRegionDecoder has failed, try to crop in-memory - regenerateInputStream(); + is = regenerateInputStream(); Bitmap fullSize = null; - if (mInStream != null) { + if (is != null) { BitmapFactory.Options options = new BitmapFactory.Options(); if (scaleDownSampleSize > 1) { options.inSampleSize = scaleDownSampleSize; } - fullSize = BitmapFactory.decodeStream(mInStream, null, options); + fullSize = BitmapFactory.decodeStream(is, null, options); + Utils.closeSilently(is); } if (fullSize != null) { + // Find out the true sample size that was used by the decoder + scaleDownSampleSize = bounds.x / fullSize.getWidth(); mCropBounds.left /= scaleDownSampleSize; mCropBounds.top /= scaleDownSampleSize; mCropBounds.bottom /= scaleDownSampleSize; mCropBounds.right /= scaleDownSampleSize; mCropBounds.roundOut(roundedTrueCrop); + // Adjust values to account for issues related to rounding + if (roundedTrueCrop.width() > fullSize.getWidth()) { + // Adjust the width + roundedTrueCrop.right = roundedTrueCrop.left + fullSize.getWidth(); + } + if (roundedTrueCrop.right > fullSize.getWidth()) { + // Adjust the left value + int adjustment = roundedTrueCrop.left - + Math.max(0, roundedTrueCrop.right - roundedTrueCrop.width()); + roundedTrueCrop.left -= adjustment; + roundedTrueCrop.right -= adjustment; + } + if (roundedTrueCrop.height() > fullSize.getHeight()) { + // Adjust the height + roundedTrueCrop.bottom = roundedTrueCrop.top + fullSize.getHeight(); + } + if (roundedTrueCrop.bottom > fullSize.getHeight()) { + // Adjust the top value + int adjustment = roundedTrueCrop.top - + Math.max(0, roundedTrueCrop.bottom - roundedTrueCrop.height()); + roundedTrueCrop.top -= adjustment; + roundedTrueCrop.bottom -= adjustment; + } + crop = Bitmap.createBitmap(fullSize, roundedTrueCrop.left, roundedTrueCrop.top, roundedTrueCrop.width(), roundedTrueCrop.height()); @@ -705,7 +787,7 @@ public class WallpaperCropActivity extends Activity { protected void updateWallpaperDimensions(int width, int height) { String spKey = getSharedPreferencesKey(); - SharedPreferences sp = getSharedPreferences(spKey, Context.MODE_PRIVATE); + SharedPreferences sp = getSharedPreferences(spKey, Context.MODE_MULTI_PROCESS); SharedPreferences.Editor editor = sp.edit(); if (width != 0 && height != 0) { editor.putInt(WALLPAPER_WIDTH_KEY, width); @@ -725,15 +807,13 @@ public class WallpaperCropActivity extends Activity { WindowManager windowManager, final WallpaperManager wallpaperManager) { final Point defaultWallpaperSize = getDefaultWallpaperSize(res, windowManager); - - new Thread("suggestWallpaperDimension") { - public void run() { - // If we have saved a wallpaper width/height, use that instead - int savedWidth = sharedPrefs.getInt(WALLPAPER_WIDTH_KEY, defaultWallpaperSize.x); - int savedHeight = sharedPrefs.getInt(WALLPAPER_HEIGHT_KEY, defaultWallpaperSize.y); - wallpaperManager.suggestDesiredDimensions(savedWidth, savedHeight); - } - }.start(); + // If we have saved a wallpaper width/height, use that instead + int savedWidth = sharedPrefs.getInt(WALLPAPER_WIDTH_KEY, defaultWallpaperSize.x); + int savedHeight = sharedPrefs.getInt(WALLPAPER_HEIGHT_KEY, defaultWallpaperSize.y); + if (savedWidth != wallpaperManager.getDesiredMinimumWidth() || + savedHeight != wallpaperManager.getDesiredMinimumHeight()) { + wallpaperManager.suggestDesiredDimensions(savedWidth, savedHeight); + } } protected static RectF getMaxCropRect( @@ -771,23 +851,4 @@ public class WallpaperCropActivity extends Activity { ? "png" // We don't support gif compression. : "jpg"; } - - protected void setWallpaperStripYOffset(int bottom) { - // - } - - protected SavedWallpaperImages getSavedImages() { - // for subclasses - throw new UnsupportedOperationException("Not implemented for WallpaperCropActivity"); - } - - protected CropView getCropView() { - // for subclasses - throw new UnsupportedOperationException("Not implemented for WallpaperCropActivity"); - } - - protected void onLiveWallpaperPickerLaunch() { - // for subclasses - throw new UnsupportedOperationException("Not implemented for WallpaperCropActivity"); - } } diff --git a/src/com/android/launcher3/WallpaperPickerActivity.java b/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java index f8e5233f7..7f05ef42d 100644 --- a/src/com/android/launcher3/WallpaperPickerActivity.java +++ b/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java @@ -16,7 +16,6 @@ package com.android.launcher3; -import android.animation.Animator; import android.animation.LayoutTransition; import android.app.ActionBar; import android.app.Activity; @@ -31,6 +30,7 @@ import android.database.Cursor; import android.database.DataSetObserver; import android.graphics.Bitmap; import android.graphics.BitmapFactory; +import android.graphics.Canvas; import android.graphics.Matrix; import android.graphics.Point; import android.graphics.PorterDuff; @@ -40,6 +40,8 @@ import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.LevelListDrawable; import android.net.Uri; +import android.os.AsyncTask; +import android.os.Build; import android.os.Bundle; import android.provider.MediaStore; import android.util.Log; @@ -51,10 +53,12 @@ import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; +import android.view.View.OnLayoutChangeListener; import android.view.ViewGroup; +import android.view.ViewPropertyAnimator; import android.view.ViewTreeObserver; import android.view.ViewTreeObserver.OnGlobalLayoutListener; -import android.view.accessibility.AccessibilityEvent; +import android.view.WindowManager; import android.view.animation.AccelerateInterpolator; import android.view.animation.DecelerateInterpolator; import android.widget.BaseAdapter; @@ -63,16 +67,15 @@ import android.widget.HorizontalScrollView; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ListAdapter; +import android.widget.Toast; -import com.android.gallery3d.exif.ExifInterface; import com.android.photos.BitmapRegionTileSource; import com.android.launcher3.settings.SettingsProvider; +import com.android.photos.BitmapRegionTileSource.BitmapSource; -import java.io.BufferedInputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; -import java.io.InputStream; import java.util.ArrayList; public class WallpaperPickerActivity extends WallpaperCropActivity { @@ -82,11 +85,17 @@ public class WallpaperPickerActivity extends WallpaperCropActivity { public static final int PICK_WALLPAPER_THIRD_PARTY_ACTIVITY = 6; public static final int PICK_LIVE_WALLPAPER = 7; private static final String TEMP_WALLPAPER_TILES = "TEMP_WALLPAPER_TILES"; + private static final String SELECTED_INDEX = "SELECTED_INDEX"; + private static final String OLD_DEFAULT_WALLPAPER_THUMBNAIL_FILENAME = "default_thumb.jpg"; + private static final String DEFAULT_WALLPAPER_THUMBNAIL_FILENAME = "default_thumb2.jpg"; + private static final int FLAG_POST_DELAY_MILLIS = 200; private static final int MENU_WALLPAPER_SCROLL = 0; + private View mSelectedTile; + + protected View mSetWallpaperButton; - private View mSelectedThumb; private boolean mIgnoreNextTap; private OnClickListener mThumbnailOnClickListener; @@ -101,30 +110,74 @@ public class WallpaperPickerActivity extends WallpaperCropActivity { ArrayList<Uri> mTempWallpaperTiles = new ArrayList<Uri>(); private SavedWallpaperImages mSavedImages; private WallpaperInfo mLiveWallpaperInfoOnPickerLaunch; + private int mSelectedIndex = -1; + private WallpaperInfo mLastClickedLiveWallpaperInfo; + + public static abstract class WallpaperTileInfo { + protected View mView; + public void setView(View v) { + mView = v; + } + public void onClick(WallpaperPickerActivity a) {} + public void onSave(WallpaperPickerActivity a) {} + public void onDelete(WallpaperPickerActivity a) {} + public boolean isSelectable() { return false; } + public boolean isNamelessWallpaper() { return false; } + public void onIndexUpdated(CharSequence label) { + if (isNamelessWallpaper()) { + mView.setContentDescription(label); + } + } + } public static class PickImageInfo extends WallpaperTileInfo { @Override - public void onClick(WallpaperCropActivity a) { + public void onClick(WallpaperPickerActivity a) { Intent intent = new Intent(Intent.ACTION_GET_CONTENT); intent.setType("image/*"); - Utilities.startActivityForResultSafely(((WallpaperPickerActivity)a), intent, IMAGE_PICK); + a.startActivityForResultSafely(intent, IMAGE_PICK); } } public static class UriWallpaperInfo extends WallpaperTileInfo { private Uri mUri; + private boolean mFirstClick = true; + private BitmapRegionTileSource.UriBitmapSource mBitmapSource; public UriWallpaperInfo(Uri uri) { mUri = uri; } @Override - public void onClick(WallpaperCropActivity a) { - CropView v = a.getCropView(); - int rotation = WallpaperCropActivity.getRotationFromExif(a, mUri); - v.setTileSource(new BitmapRegionTileSource(a, mUri, 1024, rotation), null); - v.setTouchEnabled(true); + public void onClick(final WallpaperPickerActivity a) { + final Runnable onLoad; + if (!mFirstClick) { + onLoad = null; + } else { + mFirstClick = false; + a.mSetWallpaperButton.setEnabled(false); + onLoad = new Runnable() { + public void run() { + if (mBitmapSource != null && + mBitmapSource.getLoadingState() == BitmapSource.State.LOADED) { + a.selectTile(mView); + a.mSetWallpaperButton.setEnabled(true); + } else { + ViewGroup parent = (ViewGroup) mView.getParent(); + if (parent != null) { + parent.removeView(mView); + Toast.makeText(a, + a.getString(R.string.image_load_fail), + Toast.LENGTH_SHORT).show(); + } + } + } + }; + } + mBitmapSource = new BitmapRegionTileSource.UriBitmapSource( + a, mUri, BitmapRegionTileSource.MAX_PREVIEW_SIZE); + a.setCropViewTileSource(mBitmapSource, true, false, onLoad); } @Override - public void onSave(final WallpaperCropActivity a) { + public void onSave(final WallpaperPickerActivity a) { boolean finishActivityWhenDone = true; OnBitmapCroppedHandler h = new OnBitmapCroppedHandler() { public void onBitmapCropped(byte[] imageBytes) { @@ -132,10 +185,10 @@ public class WallpaperPickerActivity extends WallpaperCropActivity { // rotation is set to 0 since imageBytes has already been correctly rotated Bitmap thumb = createThumbnail( thumbSize, null, null, imageBytes, null, 0, 0, true); - ((WallpaperPickerActivity)a).getSavedImages().writeImage(thumb, imageBytes); + a.getSavedImages().writeImage(thumb, imageBytes); } }; - ((WallpaperPickerActivity)a).cropImageAndSetWallpaper(mUri, h, finishActivityWhenDone); + a.cropImageAndSetWallpaper(mUri, h, finishActivityWhenDone); } @Override public boolean isSelectable() { @@ -158,10 +211,12 @@ public class WallpaperPickerActivity extends WallpaperCropActivity { mThumb = thumb; } @Override - public void onClick(WallpaperCropActivity a) { - int rotation = WallpaperCropActivity.getRotationFromExif(mResources, mResId); - BitmapRegionTileSource source = new BitmapRegionTileSource( - mResources, a, mResId, 1024, rotation); + public void onClick(WallpaperPickerActivity a) { + BitmapRegionTileSource.ResourceBitmapSource bitmapSource = + new BitmapRegionTileSource.ResourceBitmapSource( + mResources, mResId, BitmapRegionTileSource.MAX_PREVIEW_SIZE); + bitmapSource.loadInBackground(); + BitmapRegionTileSource source = new BitmapRegionTileSource(a, bitmapSource); CropView v = a.getCropView(); v.setTileSource(source, null); Point wallpaperSize = WallpaperCropActivity.getDefaultWallpaperSize( @@ -171,11 +226,56 @@ public class WallpaperPickerActivity extends WallpaperCropActivity { wallpaperSize.x, wallpaperSize.y, false); v.setScale(wallpaperSize.x / crop.width()); v.setTouchEnabled(false); + a.setSystemWallpaperVisiblity(false); } @Override - public void onSave(WallpaperCropActivity a) { + public void onSave(WallpaperPickerActivity a) { boolean finishActivityWhenDone = true; - ((WallpaperPickerActivity)a).cropImageAndSetWallpaper(mResources, mResId, finishActivityWhenDone); + a.cropImageAndSetWallpaper(mResources, mResId, finishActivityWhenDone); + } + @Override + public boolean isSelectable() { + return true; + } + @Override + public boolean isNamelessWallpaper() { + return true; + } + } + + public static class DefaultWallpaperInfo extends WallpaperTileInfo { + public Drawable mThumb; + public DefaultWallpaperInfo(Drawable thumb) { + mThumb = thumb; + } + @Override + public void onClick(WallpaperPickerActivity a) { + CropView c = a.getCropView(); + + Drawable defaultWallpaper = WallpaperManager.getInstance(a).getBuiltInDrawable( + c.getWidth(), c.getHeight(), false, 0.5f, 0.5f); + + if (defaultWallpaper == null) { + Log.w(TAG, "Null default wallpaper encountered."); + c.setTileSource(null, null); + return; + } + + c.setTileSource( + new DrawableTileSource(a, defaultWallpaper, DrawableTileSource.MAX_PREVIEW_SIZE), null); + c.setScale(1f); + c.setTouchEnabled(false); + a.setSystemWallpaperVisiblity(false); + } + @Override + public void onSave(WallpaperPickerActivity a) { + try { + WallpaperManager.getInstance(a).clear(); + a.setResult(RESULT_OK); + } catch (IOException e) { + Log.w("Setting wallpaper to default threw exception", e); + } + a.finish(); } @Override public boolean isSelectable() { @@ -187,9 +287,65 @@ public class WallpaperPickerActivity extends WallpaperCropActivity { } } + public void setWallpaperStripYOffset(float offset) { + mWallpaperStrip.setPadding(0, 0, 0, (int) offset); + } + + /** + * shows the system wallpaper behind the window and hides the {@link + * #mCropView} if visible + * @param visible should the system wallpaper be shown + */ + protected void setSystemWallpaperVisiblity(final boolean visible) { + // hide our own wallpaper preview if necessary + if(!visible) { + mCropView.setVisibility(View.VISIBLE); + } else { + changeWallpaperFlags(visible); + } + // the change of the flag must be delayed in order to avoid flickering, + // a simple post / double post does not suffice here + mCropView.postDelayed(new Runnable() { + @Override + public void run() { + if(!visible) { + changeWallpaperFlags(visible); + } else { + mCropView.setVisibility(View.INVISIBLE); + } + } + }, FLAG_POST_DELAY_MILLIS); + } + + private void changeWallpaperFlags(boolean visible) { + int desiredWallpaperFlag = visible ? WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER : 0; + int currentWallpaperFlag = getWindow().getAttributes().flags + & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; + if (desiredWallpaperFlag != currentWallpaperFlag) { + getWindow().setFlags(desiredWallpaperFlag, + WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER); + } + } + @Override - protected void setWallpaperStripYOffset(int offset) { - mWallpaperStrip.setPadding(0, 0, 0, offset); + public void setCropViewTileSource(BitmapSource bitmapSource, + boolean touchEnabled, + boolean moveToLeft, + final Runnable postExecute) { + // we also want to show our own wallpaper instead of the one in the background + Runnable showPostExecuteRunnable = new Runnable() { + @Override + public void run() { + if(postExecute != null) { + postExecute.run(); + } + setSystemWallpaperVisiblity(false); + } + }; + super.setCropViewTileSource(bitmapSource, + touchEnabled, + moveToLeft, + showPostExecuteRunnable); } // called by onCreate; this is subclassed to overwrite WallpaperCropActivity @@ -197,9 +353,11 @@ public class WallpaperPickerActivity extends WallpaperCropActivity { setContentView(R.layout.wallpaper_picker); mCropView = (CropView) findViewById(R.id.cropView); + mCropView.setVisibility(View.INVISIBLE); + mWallpaperStrip = findViewById(R.id.wallpaper_strip); mCropView.setTouchCallback(new CropView.TouchCallback() { - LauncherViewPropertyAnimator mAnim; + ViewPropertyAnimator mAnim; @Override public void onTouchDown() { if (mAnim != null) { @@ -208,17 +366,14 @@ public class WallpaperPickerActivity extends WallpaperCropActivity { if (mWallpaperStrip.getAlpha() == 1f) { mIgnoreNextTap = true; } - mAnim = new LauncherViewPropertyAnimator(mWallpaperStrip); + mAnim = mWallpaperStrip.animate(); mAnim.alpha(0f) - .setDuration(150) - .addListener(new Animator.AnimatorListener() { - public void onAnimationStart(Animator animator) { } - public void onAnimationEnd(Animator animator) { - mWallpaperStrip.setVisibility(View.INVISIBLE); - } - public void onAnimationCancel(Animator animator) { } - public void onAnimationRepeat(Animator animator) { } - }); + .setDuration(150) + .withEndAction(new Runnable() { + public void run() { + mWallpaperStrip.setVisibility(View.INVISIBLE); + } + }); mAnim.setInterpolator(new AccelerateInterpolator(0.75f)); mAnim.start(); } @@ -235,7 +390,7 @@ public class WallpaperPickerActivity extends WallpaperCropActivity { mAnim.cancel(); } mWallpaperStrip.setVisibility(View.VISIBLE); - mAnim = new LauncherViewPropertyAnimator(mWallpaperStrip); + mAnim = mWallpaperStrip.animate(); mAnim.alpha(1f) .setDuration(150) .setInterpolator(new DecelerateInterpolator(0.75f)); @@ -253,18 +408,10 @@ public class WallpaperPickerActivity extends WallpaperCropActivity { } return; } + mSetWallpaperButton.setEnabled(true); WallpaperTileInfo info = (WallpaperTileInfo) v.getTag(); - if (info.isSelectable()) { - if (mSelectedThumb != null) { - mSelectedThumb.setSelected(false); - mSelectedThumb = null; - } - mSelectedThumb = v; - v.setSelected(true); - // TODO: Remove this once the accessibility framework and - // services have better support for selection state. - v.announceForAccessibility( - getString(R.string.announce_selection, v.getContentDescription())); + if (info.isSelectable() && v.getVisibility() == View.VISIBLE) { + selectTile(v); } info.onClick(WallpaperPickerActivity.this); } @@ -293,12 +440,12 @@ public class WallpaperPickerActivity extends WallpaperCropActivity { ArrayList<ResourceWallpaperInfo> wallpapers = findBundledWallpapers(); mWallpapersView = (LinearLayout) findViewById(R.id.wallpaper_list); BuiltInWallpapersAdapter ia = new BuiltInWallpapersAdapter(this, wallpapers); - populateWallpapersFromAdapter(mWallpapersView, ia, false, true); + populateWallpapersFromAdapter(mWallpapersView, ia, false); // Populate the saved wallpapers mSavedImages = new SavedWallpaperImages(this); mSavedImages.loadThumbnailsAndImageIdList(); - populateWallpapersFromAdapter(mWallpapersView, mSavedImages, true, true); + populateWallpapersFromAdapter(mWallpapersView, mSavedImages, true); // Populate the live wallpapers final LinearLayout liveWallpapersView = @@ -307,7 +454,7 @@ public class WallpaperPickerActivity extends WallpaperCropActivity { a.registerDataSetObserver(new DataSetObserver() { public void onChanged() { liveWallpapersView.removeAllViews(); - populateWallpapersFromAdapter(liveWallpapersView, a, false, false); + populateWallpapersFromAdapter(liveWallpapersView, a, false); initializeScrollForRtl(); updateTileIndices(); } @@ -318,7 +465,7 @@ public class WallpaperPickerActivity extends WallpaperCropActivity { (LinearLayout) findViewById(R.id.third_party_wallpaper_list); final ThirdPartyWallpaperPickerListAdapter ta = new ThirdPartyWallpaperPickerListAdapter(this); - populateWallpapersFromAdapter(thirdPartyWallpapersView, ta, false, false); + populateWallpapersFromAdapter(thirdPartyWallpapersView, ta, false); // Add a tile for the Gallery LinearLayout masterWallpaperList = (LinearLayout) findViewById(R.id.master_wallpaper_list); @@ -342,7 +489,37 @@ public class WallpaperPickerActivity extends WallpaperCropActivity { pickImageTile.setTag(pickImageInfo); pickImageInfo.setView(pickImageTile); pickImageTile.setOnClickListener(mThumbnailOnClickListener); - pickImageInfo.setView(pickImageTile); + + // Add a tile for the default wallpaper + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + DefaultWallpaperInfo defaultWallpaperInfo = getDefaultWallpaper(); + if (defaultWallpaperInfo != null) { + FrameLayout defaultWallpaperTile = (FrameLayout) createImageTileView( + getLayoutInflater(), 0, null, mWallpapersView, defaultWallpaperInfo.mThumb); + setWallpaperItemPaddingToZero(defaultWallpaperTile); + defaultWallpaperTile.setTag(defaultWallpaperInfo); + mWallpapersView.addView(defaultWallpaperTile, 0); + defaultWallpaperTile.setOnClickListener(mThumbnailOnClickListener); + defaultWallpaperInfo.setView(defaultWallpaperTile); + } + } + + // Select the first item; wait for a layout pass so that we initialize the dimensions of + // cropView or the defaultWallpaperView first + mCropView.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) { + if ((right - left) > 0 && (bottom - top) > 0) { + if (mSelectedIndex >= 0 && mSelectedIndex < mWallpapersView.getChildCount()) { + mThumbnailOnClickListener.onClick( + mWallpapersView.getChildAt(mSelectedIndex)); + setSystemWallpaperVisiblity(false); + } + v.removeOnLayoutChangeListener(this); + } + } + }); updateTileIndices(); @@ -364,12 +541,17 @@ public class WallpaperPickerActivity extends WallpaperCropActivity { new View.OnClickListener() { @Override public void onClick(View v) { - if (mSelectedThumb != null) { - WallpaperTileInfo info = (WallpaperTileInfo) mSelectedThumb.getTag(); + if (mSelectedTile != null) { + WallpaperTileInfo info = (WallpaperTileInfo) mSelectedTile.getTag(); info.onSave(WallpaperPickerActivity.this); + } else { + // no tile was selected, so we just finish the activity and go back + setResult(Activity.RESULT_OK); + finish(); } } }); + mSetWallpaperButton = findViewById(R.id.set_wallpaper_button); // CAB for deleting items mActionModeCallback = new ActionMode.Callback() { @@ -416,6 +598,7 @@ public class WallpaperPickerActivity extends WallpaperCropActivity { if (itemId == R.id.menu_delete) { int childCount = mWallpapersView.getChildCount(); ArrayList<View> viewsToRemove = new ArrayList<View>(); + boolean selectedTileRemoved = false; for (int i = 0; i < childCount; i++) { CheckableFrameLayout c = (CheckableFrameLayout) mWallpapersView.getChildAt(i); @@ -423,11 +606,19 @@ public class WallpaperPickerActivity extends WallpaperCropActivity { WallpaperTileInfo info = (WallpaperTileInfo) c.getTag(); info.onDelete(WallpaperPickerActivity.this); viewsToRemove.add(c); + if (i == mSelectedIndex) { + selectedTileRemoved = true; + } } } for (View v : viewsToRemove) { mWallpapersView.removeView(v); } + if (selectedTileRemoved) { + mSelectedIndex = -1; + mSelectedTile = null; + setSystemWallpaperVisiblity(true); + } updateTileIndices(); mode.finish(); // Action picked, so close the CAB return true; @@ -444,12 +635,28 @@ public class WallpaperPickerActivity extends WallpaperCropActivity { CheckableFrameLayout c = (CheckableFrameLayout) mWallpapersView.getChildAt(i); c.setChecked(false); } - mSelectedThumb.setSelected(true); + if (mSelectedTile != null) { + mSelectedTile.setSelected(true); + } mActionMode = null; } }; } + private void selectTile(View v) { + if (mSelectedTile != null) { + mSelectedTile.setSelected(false); + mSelectedTile = null; + } + mSelectedTile = v; + v.setSelected(true); + mSelectedIndex = mWallpapersView.indexOfChild(v); + // TODO: Remove this once the accessibility framework and + // services have better support for selection state. + v.announceForAccessibility( + getString(R.string.announce_selection, v.getContentDescription())); + } + private void initializeScrollForRtl() { final HorizontalScrollView scroll = (HorizontalScrollView) findViewById(R.id.wallpaper_scroll_container); @@ -467,10 +674,6 @@ public class WallpaperPickerActivity extends WallpaperCropActivity { } } - public boolean enableRotation() { - return super.enableRotation() || Launcher.sForceEnableRotation; - } - protected Bitmap getThumbnailOfLastPhoto() { Cursor cursor = MediaStore.Images.Media.query(getContentResolver(), MediaStore.Images.Media.EXTERNAL_CONTENT_URI, @@ -490,25 +693,6 @@ public class WallpaperPickerActivity extends WallpaperCropActivity { } @Override - public boolean onCreateOptionsMenu(Menu menu) { - menu.add(0, MENU_WALLPAPER_SCROLL, 0, - R.string.wallpaper_scroll).setCheckable(true); - - return super.onCreateOptionsMenu(menu); - } - - @Override - public boolean onPrepareOptionsMenu(Menu menu) { - MenuItem wallpaperScroll = menu.findItem(MENU_WALLPAPER_SCROLL); - - wallpaperScroll.setChecked(SettingsProvider.getBoolean(this, - SettingsProvider.SETTINGS_UI_HOMESCREEN_SCROLLING_WALLPAPER_SCROLL, - R.bool.preferences_interface_homescreen_scrolling_wallpaper_scroll_default)); - - return super.onPrepareOptionsMenu(menu); - } - - @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle presses on the action bar items switch (item.getItemId()) { @@ -534,17 +718,19 @@ public class WallpaperPickerActivity extends WallpaperCropActivity { protected void onSaveInstanceState(Bundle outState) { outState.putParcelableArrayList(TEMP_WALLPAPER_TILES, mTempWallpaperTiles); + outState.putInt(SELECTED_INDEX, mSelectedIndex); } protected void onRestoreInstanceState(Bundle savedInstanceState) { ArrayList<Uri> uris = savedInstanceState.getParcelableArrayList(TEMP_WALLPAPER_TILES); for (Uri uri : uris) { - addTemporaryWallpaperTile(uri); + addTemporaryWallpaperTile(uri, true); } + mSelectedIndex = savedInstanceState.getInt(SELECTED_INDEX, -1); } private void populateWallpapersFromAdapter(ViewGroup parent, BaseAdapter adapter, - boolean addLongPressHandler, boolean selectFirstTile) { + boolean addLongPressHandler) { for (int i = 0; i < adapter.getCount(); i++) { FrameLayout thumbnail = (FrameLayout) adapter.getView(i, null, parent); parent.addView(thumbnail, i); @@ -555,9 +741,6 @@ public class WallpaperPickerActivity extends WallpaperCropActivity { addLongPressHandler(thumbnail); } thumbnail.setOnClickListener(mThumbnailOnClickListener); - if (i == 0 && selectFirstTile) { - mThumbnailOnClickListener.onClick(thumbnail); - } } } @@ -647,26 +830,36 @@ public class WallpaperPickerActivity extends WallpaperCropActivity { } } - private void addTemporaryWallpaperTile(Uri uri) { + private void addTemporaryWallpaperTile(final Uri uri, boolean fromRestore) { mTempWallpaperTiles.add(uri); // Add a tile for the image picked from Gallery - FrameLayout pickedImageThumbnail = (FrameLayout) getLayoutInflater(). + final FrameLayout pickedImageThumbnail = (FrameLayout) getLayoutInflater(). inflate(R.layout.wallpaper_picker_item, mWallpapersView, false); + pickedImageThumbnail.setVisibility(View.GONE); setWallpaperItemPaddingToZero(pickedImageThumbnail); + mWallpapersView.addView(pickedImageThumbnail, 0); // Load the thumbnail - ImageView image = (ImageView) pickedImageThumbnail.findViewById(R.id.wallpaper_image); - Point defaultSize = getDefaultThumbnailSize(this.getResources()); - int rotation = WallpaperCropActivity.getRotationFromExif(this, uri); - Bitmap thumb = createThumbnail(defaultSize, this, uri, null, null, 0, rotation, false); - if (thumb != null) { - image.setImageBitmap(thumb); - Drawable thumbDrawable = image.getDrawable(); - thumbDrawable.setDither(true); - } else { - Log.e(TAG, "Error loading thumbnail for uri=" + uri); - } - mWallpapersView.addView(pickedImageThumbnail, 0); + final ImageView image = (ImageView) pickedImageThumbnail.findViewById(R.id.wallpaper_image); + final Point defaultSize = getDefaultThumbnailSize(this.getResources()); + final Context context = this; + new AsyncTask<Void, Bitmap, Bitmap>() { + protected Bitmap doInBackground(Void...args) { + int rotation = WallpaperCropActivity.getRotationFromExif(context, uri); + return createThumbnail(defaultSize, context, uri, null, null, 0, rotation, false); + + } + protected void onPostExecute(Bitmap thumb) { + if (thumb != null) { + image.setImageBitmap(thumb); + Drawable thumbDrawable = image.getDrawable(); + thumbDrawable.setDither(true); + pickedImageThumbnail.setVisibility(View.VISIBLE); + } else { + Log.e(TAG, "Error loading thumbnail for uri=" + uri); + } + } + }.execute(); UriWallpaperInfo info = new UriWallpaperInfo(uri); pickedImageThumbnail.setTag(info); @@ -674,14 +867,16 @@ public class WallpaperPickerActivity extends WallpaperCropActivity { addLongPressHandler(pickedImageThumbnail); updateTileIndices(); pickedImageThumbnail.setOnClickListener(mThumbnailOnClickListener); - mThumbnailOnClickListener.onClick(pickedImageThumbnail); + if (!fromRestore) { + mThumbnailOnClickListener.onClick(pickedImageThumbnail); + } } protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == IMAGE_PICK && resultCode == RESULT_OK) { if (data != null && data.getData() != null) { Uri uri = data.getData(); - addTemporaryWallpaperTile(uri); + addTemporaryWallpaperTile(uri, false); } } else if (requestCode == PICK_WALLPAPER_THIRD_PARTY_ACTIVITY) { setResult(RESULT_OK); @@ -689,11 +884,15 @@ public class WallpaperPickerActivity extends WallpaperCropActivity { } else if (requestCode == PICK_LIVE_WALLPAPER) { WallpaperManager wm = WallpaperManager.getInstance(this); final WallpaperInfo oldLiveWallpaper = mLiveWallpaperInfoOnPickerLaunch; + final WallpaperInfo clickedWallpaper = mLastClickedLiveWallpaperInfo; WallpaperInfo newLiveWallpaper = wm.getWallpaperInfo(); // Try to figure out if a live wallpaper was set; if (newLiveWallpaper != null && - (oldLiveWallpaper == null || - !oldLiveWallpaper.getComponent().equals(newLiveWallpaper.getComponent()))) { + (oldLiveWallpaper == null + || !oldLiveWallpaper.getComponent() + .equals(newLiveWallpaper.getComponent()) + || clickedWallpaper.getComponent() + .equals(oldLiveWallpaper.getComponent()))) { // Return if a live wallpaper was set setResult(RESULT_OK); finish(); @@ -724,18 +923,35 @@ public class WallpaperPickerActivity extends WallpaperCropActivity { } // Add an entry for the default wallpaper (stored in system resources) - ResourceWallpaperInfo defaultWallpaperInfo = getDefaultWallpaperInfo(); - if (defaultWallpaperInfo != null) { - bundledWallpapers.add(0, defaultWallpaperInfo); + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { + ResourceWallpaperInfo defaultWallpaperInfo = getPreKKDefaultWallpaperInfo(); + if (defaultWallpaperInfo != null) { + bundledWallpapers.add(0, defaultWallpaperInfo); + } } return bundledWallpapers; } - private ResourceWallpaperInfo getDefaultWallpaperInfo() { + private boolean writeImageToFileAsJpeg(File f, Bitmap b) { + try { + f.createNewFile(); + FileOutputStream thumbFileStream = + openFileOutput(f.getName(), Context.MODE_PRIVATE); + b.compress(Bitmap.CompressFormat.JPEG, 95, thumbFileStream); + thumbFileStream.close(); + return true; + } catch (IOException e) { + Log.e(TAG, "Error while writing bitmap to file " + e); + f.delete(); + } + return false; + } + + private ResourceWallpaperInfo getPreKKDefaultWallpaperInfo() { Resources sysRes = Resources.getSystem(); int resId = sysRes.getIdentifier("default_wallpaper", "drawable", "android"); - File defaultThumbFile = new File(getFilesDir(), "default_thumb.jpg"); + File defaultThumbFile = new File(getFilesDir(), DEFAULT_WALLPAPER_THUMBNAIL_FILENAME); Bitmap thumb = null; boolean defaultWallpaperExists = false; if (defaultThumbFile.exists()) { @@ -748,17 +964,7 @@ public class WallpaperPickerActivity extends WallpaperCropActivity { thumb = createThumbnail( defaultThumbSize, this, null, null, sysRes, resId, rotation, false); if (thumb != null) { - try { - defaultThumbFile.createNewFile(); - FileOutputStream thumbFileStream = - openFileOutput(defaultThumbFile.getName(), Context.MODE_PRIVATE); - thumb.compress(Bitmap.CompressFormat.JPEG, 95, thumbFileStream); - thumbFileStream.close(); - defaultWallpaperExists = true; - } catch (IOException e) { - Log.e(TAG, "Error while writing default wallpaper thumbnail to file " + e); - defaultThumbFile.delete(); - } + defaultWallpaperExists = writeImageToFileAsJpeg(defaultThumbFile, thumb); } } if (defaultWallpaperExists) { @@ -767,6 +973,40 @@ public class WallpaperPickerActivity extends WallpaperCropActivity { return null; } + private DefaultWallpaperInfo getDefaultWallpaper() { + File defaultThumbFile = new File(getFilesDir(), DEFAULT_WALLPAPER_THUMBNAIL_FILENAME); + Bitmap thumb = null; + boolean defaultWallpaperExists = false; + if (defaultThumbFile.exists()) { + thumb = BitmapFactory.decodeFile(defaultThumbFile.getAbsolutePath()); + defaultWallpaperExists = true; + } else { + // Delete old thumbnail file, since we had a bug where the thumbnail wasn't being drawn + // before + new File(getFilesDir(), OLD_DEFAULT_WALLPAPER_THUMBNAIL_FILENAME).delete(); + + Resources res = getResources(); + Point defaultThumbSize = getDefaultThumbnailSize(res); + Drawable wallpaperDrawable = WallpaperManager.getInstance(this).getBuiltInDrawable( + defaultThumbSize.x, defaultThumbSize.y, true, 0.5f, 0.5f); + if (wallpaperDrawable != null) { + thumb = Bitmap.createBitmap( + defaultThumbSize.x, defaultThumbSize.y, Bitmap.Config.ARGB_8888); + Canvas c = new Canvas(thumb); + wallpaperDrawable.setBounds(0, 0, defaultThumbSize.x, defaultThumbSize.y); + wallpaperDrawable.draw(c); + c.setBitmap(null); + } + if (thumb != null) { + defaultWallpaperExists = writeImageToFileAsJpeg(defaultThumbFile, thumb); + } + } + if (defaultWallpaperExists) { + return new DefaultWallpaperInfo(new BitmapDrawable(thumb)); + } + return null; + } + public Pair<ApplicationInfo, Integer> getWallpaperArrayResourceId() { // Context.getPackageName() may return the "original" package name, // com.android.launcher3; Resources needs the real package name, @@ -812,7 +1052,8 @@ public class WallpaperPickerActivity extends WallpaperCropActivity { return mSavedImages; } - public void onLiveWallpaperPickerLaunch() { + public void onLiveWallpaperPickerLaunch(WallpaperInfo info) { + mLastClickedLiveWallpaperInfo = info; mLiveWallpaperInfoOnPickerLaunch = WallpaperManager.getInstance(this).getWallpaperInfo(); } @@ -881,4 +1122,10 @@ public class WallpaperPickerActivity extends WallpaperCropActivity { return view; } + + // In Launcher3, we override this with a method that catches exceptions + // from starting activities; didn't want to copy and paste code into here + public void startActivityForResultSafely(Intent intent, int requestCode) { + startActivityForResult(intent, requestCode); + } } diff --git a/src/com/android/launcher3/WallpaperRootView.java b/WallpaperPicker/src/com/android/launcher3/WallpaperRootView.java index 7b0d4f147..ceaa043a7 100644 --- a/src/com/android/launcher3/WallpaperRootView.java +++ b/WallpaperPicker/src/com/android/launcher3/WallpaperRootView.java @@ -22,14 +22,14 @@ import android.util.AttributeSet; import android.widget.RelativeLayout; public class WallpaperRootView extends RelativeLayout { - private final WallpaperCropActivity a; + private final WallpaperPickerActivity a; public WallpaperRootView(Context context, AttributeSet attrs) { super(context, attrs); - a = (WallpaperCropActivity) context; + a = (WallpaperPickerActivity) context; } public WallpaperRootView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); - a = (WallpaperCropActivity) context; + a = (WallpaperPickerActivity) context; } protected boolean fitSystemWindows(Rect insets) { diff --git a/WallpaperPicker/src/com/android/photos/BitmapRegionTileSource.java b/WallpaperPicker/src/com/android/photos/BitmapRegionTileSource.java new file mode 100644 index 000000000..764156de0 --- /dev/null +++ b/WallpaperPicker/src/com/android/photos/BitmapRegionTileSource.java @@ -0,0 +1,528 @@ +/* + * Copyright (C) 2013 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.android.photos; + +import android.annotation.TargetApi; +import android.content.Context; +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.Bitmap.Config; +import android.graphics.BitmapFactory; +import android.graphics.BitmapRegionDecoder; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Rect; +import android.net.Uri; +import android.os.Build; +import android.os.Build.VERSION_CODES; +import android.util.Log; + +import com.android.gallery3d.common.BitmapUtils; +import com.android.gallery3d.common.Utils; +import com.android.gallery3d.exif.ExifInterface; +import com.android.gallery3d.glrenderer.BasicTexture; +import com.android.gallery3d.glrenderer.BitmapTexture; +import com.android.photos.views.TiledImageRenderer; + +import java.io.BufferedInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; + +interface SimpleBitmapRegionDecoder { + int getWidth(); + int getHeight(); + Bitmap decodeRegion(Rect wantRegion, BitmapFactory.Options options); +} + +class SimpleBitmapRegionDecoderWrapper implements SimpleBitmapRegionDecoder { + BitmapRegionDecoder mDecoder; + private SimpleBitmapRegionDecoderWrapper(BitmapRegionDecoder decoder) { + mDecoder = decoder; + } + public static SimpleBitmapRegionDecoderWrapper newInstance( + String pathName, boolean isShareable) { + try { + BitmapRegionDecoder d = BitmapRegionDecoder.newInstance(pathName, isShareable); + if (d != null) { + return new SimpleBitmapRegionDecoderWrapper(d); + } + } catch (IOException e) { + Log.w("BitmapRegionTileSource", "getting decoder failed for path " + pathName, e); + return null; + } + return null; + } + public static SimpleBitmapRegionDecoderWrapper newInstance( + InputStream is, boolean isShareable) { + try { + BitmapRegionDecoder d = BitmapRegionDecoder.newInstance(is, isShareable); + if (d != null) { + return new SimpleBitmapRegionDecoderWrapper(d); + } + } catch (IOException e) { + Log.w("BitmapRegionTileSource", "getting decoder failed", e); + return null; + } + return null; + } + public int getWidth() { + return mDecoder.getWidth(); + } + public int getHeight() { + return mDecoder.getHeight(); + } + public Bitmap decodeRegion(Rect wantRegion, BitmapFactory.Options options) { + return mDecoder.decodeRegion(wantRegion, options); + } +} + +class DumbBitmapRegionDecoder implements SimpleBitmapRegionDecoder { + Bitmap mBuffer; + Canvas mTempCanvas; + Paint mTempPaint; + private DumbBitmapRegionDecoder(Bitmap b) { + mBuffer = b; + } + public static DumbBitmapRegionDecoder newInstance(String pathName) { + Bitmap b = BitmapFactory.decodeFile(pathName); + if (b != null) { + return new DumbBitmapRegionDecoder(b); + } + return null; + } + public static DumbBitmapRegionDecoder newInstance(InputStream is) { + Bitmap b = BitmapFactory.decodeStream(is); + if (b != null) { + return new DumbBitmapRegionDecoder(b); + } + return null; + } + public int getWidth() { + return mBuffer.getWidth(); + } + public int getHeight() { + return mBuffer.getHeight(); + } + public Bitmap decodeRegion(Rect wantRegion, BitmapFactory.Options options) { + if (mTempCanvas == null) { + mTempCanvas = new Canvas(); + mTempPaint = new Paint(); + mTempPaint.setFilterBitmap(true); + } + int sampleSize = Math.max(options.inSampleSize, 1); + Bitmap newBitmap = Bitmap.createBitmap( + wantRegion.width() / sampleSize, + wantRegion.height() / sampleSize, + Bitmap.Config.ARGB_8888); + mTempCanvas.setBitmap(newBitmap); + mTempCanvas.save(); + mTempCanvas.scale(1f / sampleSize, 1f / sampleSize); + mTempCanvas.drawBitmap(mBuffer, -wantRegion.left, -wantRegion.top, mTempPaint); + mTempCanvas.restore(); + mTempCanvas.setBitmap(null); + return newBitmap; + } +} + +/** + * A {@link com.android.photos.views.TiledImageRenderer.TileSource} using + * {@link BitmapRegionDecoder} to wrap a local file + */ +@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) +public class BitmapRegionTileSource implements TiledImageRenderer.TileSource { + + private static final String TAG = "BitmapRegionTileSource"; + + private static final boolean REUSE_BITMAP = + Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN; + private static final int GL_SIZE_LIMIT = 2048; + // This must be no larger than half the size of the GL_SIZE_LIMIT + // due to decodePreview being allowed to be up to 2x the size of the target + public static final int MAX_PREVIEW_SIZE = GL_SIZE_LIMIT / 2; + + public static abstract class BitmapSource { + private SimpleBitmapRegionDecoder mDecoder; + private Bitmap mPreview; + private int mPreviewSize; + private int mRotation; + public enum State { NOT_LOADED, LOADED, ERROR_LOADING }; + private State mState = State.NOT_LOADED; + public BitmapSource(int previewSize) { + mPreviewSize = previewSize; + } + public boolean loadInBackground() { + ExifInterface ei = new ExifInterface(); + if (readExif(ei)) { + Integer ori = ei.getTagIntValue(ExifInterface.TAG_ORIENTATION); + if (ori != null) { + mRotation = ExifInterface.getRotationForOrientationValue(ori.shortValue()); + } + } + mDecoder = loadBitmapRegionDecoder(); + if (mDecoder == null) { + mState = State.ERROR_LOADING; + return false; + } else { + int width = mDecoder.getWidth(); + int height = mDecoder.getHeight(); + if (mPreviewSize != 0) { + int previewSize = Math.min(mPreviewSize, MAX_PREVIEW_SIZE); + BitmapFactory.Options opts = new BitmapFactory.Options(); + opts.inPreferredConfig = Bitmap.Config.ARGB_8888; + opts.inPreferQualityOverSpeed = true; + + float scale = (float) previewSize / Math.max(width, height); + opts.inSampleSize = BitmapUtils.computeSampleSizeLarger(scale); + opts.inJustDecodeBounds = false; + mPreview = loadPreviewBitmap(opts); + } + mState = State.LOADED; + return true; + } + } + + public State getLoadingState() { + return mState; + } + + public SimpleBitmapRegionDecoder getBitmapRegionDecoder() { + return mDecoder; + } + + public Bitmap getPreviewBitmap() { + return mPreview; + } + + public int getPreviewSize() { + return mPreviewSize; + } + + public int getRotation() { + return mRotation; + } + + public abstract boolean readExif(ExifInterface ei); + public abstract SimpleBitmapRegionDecoder loadBitmapRegionDecoder(); + public abstract Bitmap loadPreviewBitmap(BitmapFactory.Options options); + } + + public static class FilePathBitmapSource extends BitmapSource { + private String mPath; + public FilePathBitmapSource(String path, int previewSize) { + super(previewSize); + mPath = path; + } + @Override + public SimpleBitmapRegionDecoder loadBitmapRegionDecoder() { + SimpleBitmapRegionDecoder d; + d = SimpleBitmapRegionDecoderWrapper.newInstance(mPath, true); + if (d == null) { + d = DumbBitmapRegionDecoder.newInstance(mPath); + } + return d; + } + @Override + public Bitmap loadPreviewBitmap(BitmapFactory.Options options) { + return BitmapFactory.decodeFile(mPath, options); + } + @Override + public boolean readExif(ExifInterface ei) { + try { + ei.readExif(mPath); + return true; + } catch (NullPointerException e) { + Log.w("BitmapRegionTileSource", "reading exif failed", e); + return false; + } catch (IOException e) { + Log.w("BitmapRegionTileSource", "getting decoder failed", e); + return false; + } + } + } + + public static class UriBitmapSource extends BitmapSource { + private Context mContext; + private Uri mUri; + public UriBitmapSource(Context context, Uri uri, int previewSize) { + super(previewSize); + mContext = context; + mUri = uri; + } + private InputStream regenerateInputStream() throws FileNotFoundException { + InputStream is = mContext.getContentResolver().openInputStream(mUri); + return new BufferedInputStream(is); + } + @Override + public SimpleBitmapRegionDecoder loadBitmapRegionDecoder() { + try { + InputStream is = regenerateInputStream(); + SimpleBitmapRegionDecoder regionDecoder = + SimpleBitmapRegionDecoderWrapper.newInstance(is, false); + Utils.closeSilently(is); + if (regionDecoder == null) { + is = regenerateInputStream(); + regionDecoder = DumbBitmapRegionDecoder.newInstance(is); + Utils.closeSilently(is); + } + return regionDecoder; + } catch (FileNotFoundException e) { + Log.e("BitmapRegionTileSource", "Failed to load URI " + mUri, e); + return null; + } catch (IOException e) { + Log.e("BitmapRegionTileSource", "Failure while reading URI " + mUri, e); + return null; + } + } + @Override + public Bitmap loadPreviewBitmap(BitmapFactory.Options options) { + try { + InputStream is = regenerateInputStream(); + Bitmap b = BitmapFactory.decodeStream(is, null, options); + Utils.closeSilently(is); + return b; + } catch (FileNotFoundException e) { + Log.e("BitmapRegionTileSource", "Failed to load URI " + mUri, e); + return null; + } + } + @Override + public boolean readExif(ExifInterface ei) { + InputStream is = null; + try { + is = regenerateInputStream(); + ei.readExif(is); + Utils.closeSilently(is); + return true; + } catch (FileNotFoundException e) { + Log.e("BitmapRegionTileSource", "Failed to load URI " + mUri, e); + return false; + } catch (IOException e) { + Log.e("BitmapRegionTileSource", "Failed to load URI " + mUri, e); + return false; + } catch (NullPointerException e) { + Log.e("BitmapRegionTileSource", "Failed to read EXIF for URI " + mUri, e); + return false; + } finally { + Utils.closeSilently(is); + } + } + } + + public static class ResourceBitmapSource extends BitmapSource { + private Resources mRes; + private int mResId; + public ResourceBitmapSource(Resources res, int resId, int previewSize) { + super(previewSize); + mRes = res; + mResId = resId; + } + private InputStream regenerateInputStream() { + InputStream is = mRes.openRawResource(mResId); + return new BufferedInputStream(is); + } + @Override + public SimpleBitmapRegionDecoder loadBitmapRegionDecoder() { + InputStream is = regenerateInputStream(); + SimpleBitmapRegionDecoder regionDecoder = + SimpleBitmapRegionDecoderWrapper.newInstance(is, false); + Utils.closeSilently(is); + if (regionDecoder == null) { + is = regenerateInputStream(); + regionDecoder = DumbBitmapRegionDecoder.newInstance(is); + Utils.closeSilently(is); + } + return regionDecoder; + } + @Override + public Bitmap loadPreviewBitmap(BitmapFactory.Options options) { + return BitmapFactory.decodeResource(mRes, mResId, options); + } + @Override + public boolean readExif(ExifInterface ei) { + try { + InputStream is = regenerateInputStream(); + ei.readExif(is); + Utils.closeSilently(is); + return true; + } catch (IOException e) { + Log.e("BitmapRegionTileSource", "Error reading resource", e); + return false; + } + } + } + + SimpleBitmapRegionDecoder mDecoder; + int mWidth; + int mHeight; + int mTileSize; + private BasicTexture mPreview; + private final int mRotation; + + // For use only by getTile + private Rect mWantRegion = new Rect(); + private Rect mOverlapRegion = new Rect(); + private BitmapFactory.Options mOptions; + private Canvas mCanvas; + + public BitmapRegionTileSource(Context context, BitmapSource source) { + mTileSize = TiledImageRenderer.suggestedTileSize(context); + mRotation = source.getRotation(); + mDecoder = source.getBitmapRegionDecoder(); + if (mDecoder != null) { + mWidth = mDecoder.getWidth(); + mHeight = mDecoder.getHeight(); + mOptions = new BitmapFactory.Options(); + mOptions.inPreferredConfig = Bitmap.Config.ARGB_8888; + mOptions.inPreferQualityOverSpeed = true; + mOptions.inTempStorage = new byte[16 * 1024]; + int previewSize = source.getPreviewSize(); + if (previewSize != 0) { + previewSize = Math.min(previewSize, MAX_PREVIEW_SIZE); + // Although this is the same size as the Bitmap that is likely already + // loaded, the lifecycle is different and interactions are on a different + // thread. Thus to simplify, this source will decode its own bitmap. + Bitmap preview = decodePreview(source, previewSize); + if (preview.getWidth() <= GL_SIZE_LIMIT && preview.getHeight() <= GL_SIZE_LIMIT) { + mPreview = new BitmapTexture(preview); + } else { + Log.w(TAG, String.format( + "Failed to create preview of apropriate size! " + + " in: %dx%d, out: %dx%d", + mWidth, mHeight, + preview.getWidth(), preview.getHeight())); + } + } + } + } + + @Override + public int getTileSize() { + return mTileSize; + } + + @Override + public int getImageWidth() { + return mWidth; + } + + @Override + public int getImageHeight() { + return mHeight; + } + + @Override + public BasicTexture getPreview() { + return mPreview; + } + + @Override + public int getRotation() { + return mRotation; + } + + @Override + public Bitmap getTile(int level, int x, int y, Bitmap bitmap) { + int tileSize = getTileSize(); + if (!REUSE_BITMAP) { + return getTileWithoutReusingBitmap(level, x, y, tileSize); + } + + int t = tileSize << level; + mWantRegion.set(x, y, x + t, y + t); + + if (bitmap == null) { + bitmap = Bitmap.createBitmap(tileSize, tileSize, Bitmap.Config.ARGB_8888); + } + + mOptions.inSampleSize = (1 << level); + mOptions.inBitmap = bitmap; + + try { + bitmap = mDecoder.decodeRegion(mWantRegion, mOptions); + } finally { + if (mOptions.inBitmap != bitmap && mOptions.inBitmap != null) { + mOptions.inBitmap = null; + } + } + + if (bitmap == null) { + Log.w("BitmapRegionTileSource", "fail in decoding region"); + } + return bitmap; + } + + private Bitmap getTileWithoutReusingBitmap( + int level, int x, int y, int tileSize) { + + int t = tileSize << level; + mWantRegion.set(x, y, x + t, y + t); + + mOverlapRegion.set(0, 0, mWidth, mHeight); + + mOptions.inSampleSize = (1 << level); + Bitmap bitmap = mDecoder.decodeRegion(mOverlapRegion, mOptions); + + if (bitmap == null) { + Log.w(TAG, "fail in decoding region"); + } + + if (mWantRegion.equals(mOverlapRegion)) { + return bitmap; + } + + Bitmap result = Bitmap.createBitmap(tileSize, tileSize, Config.ARGB_8888); + if (mCanvas == null) { + mCanvas = new Canvas(); + } + mCanvas.setBitmap(result); + mCanvas.drawBitmap(bitmap, + (mOverlapRegion.left - mWantRegion.left) >> level, + (mOverlapRegion.top - mWantRegion.top) >> level, null); + mCanvas.setBitmap(null); + return result; + } + + /** + * Note that the returned bitmap may have a long edge that's longer + * than the targetSize, but it will always be less than 2x the targetSize + */ + private Bitmap decodePreview(BitmapSource source, int targetSize) { + Bitmap result = source.getPreviewBitmap(); + if (result == null) { + return null; + } + + // We need to resize down if the decoder does not support inSampleSize + // or didn't support the specified inSampleSize (some decoders only do powers of 2) + float scale = (float) targetSize / (float) (Math.max(result.getWidth(), result.getHeight())); + + if (scale <= 0.5) { + result = BitmapUtils.resizeBitmapByScale(result, scale, true); + } + return ensureGLCompatibleBitmap(result); + } + + private static Bitmap ensureGLCompatibleBitmap(Bitmap bitmap) { + if (bitmap == null || bitmap.getConfig() != null) { + return bitmap; + } + Bitmap newBitmap = bitmap.copy(Config.ARGB_8888, false); + bitmap.recycle(); + return newBitmap; + } +} diff --git a/src/com/android/photos/views/BlockingGLTextureView.java b/WallpaperPicker/src/com/android/photos/views/BlockingGLTextureView.java index 8a0505185..8a0505185 100644 --- a/src/com/android/photos/views/BlockingGLTextureView.java +++ b/WallpaperPicker/src/com/android/photos/views/BlockingGLTextureView.java diff --git a/src/com/android/photos/views/TiledImageRenderer.java b/WallpaperPicker/src/com/android/photos/views/TiledImageRenderer.java index c4e493b34..c4e493b34 100644 --- a/src/com/android/photos/views/TiledImageRenderer.java +++ b/WallpaperPicker/src/com/android/photos/views/TiledImageRenderer.java diff --git a/src/com/android/photos/views/TiledImageView.java b/WallpaperPicker/src/com/android/photos/views/TiledImageView.java index af4199c91..94063b027 100644 --- a/src/com/android/photos/views/TiledImageView.java +++ b/WallpaperPicker/src/com/android/photos/views/TiledImageView.java @@ -112,6 +112,18 @@ public class TiledImageView extends FrameLayout { //setTileSource(new ColoredTiles()); } + @Override + public void setVisibility(int visibility) { + super.setVisibility(visibility); + // need to update inner view's visibility because it seems like we're causing it to draw + // from {@link #dispatchDraw} or {@link #invalidate} even if we are invisible. + if (USE_TEXTURE_VIEW) { + mTextureView.setVisibility(visibility); + } else { + mGLSurfaceView.setVisibility(visibility); + } + } + public void destroy() { if (!IS_SUPPORTED) { return; diff --git a/proguard.flags b/proguard.flags index fc511bff4..df4a99687 100644 --- a/proguard.flags +++ b/proguard.flags @@ -8,6 +8,9 @@ public void onClickAllAppsButton(android.view.View); public void onClickAppMarketButton(android.view.View); public void dismissFirstRunCling(android.view.View); + public void dismissMigrationClingCopyApps(android.view.View); + public void dismissMigrationClingUseDefault(android.view.View); + public void dismissMigrationWorkspaceCling(android.view.View); public void dismissWorkspaceCling(android.view.View); public void dismissAllAppsCling(android.view.View); } diff --git a/res/anim/drop_down.xml b/res/anim/drop_down.xml new file mode 100644 index 000000000..49059a048 --- /dev/null +++ b/res/anim/drop_down.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8"?> +<set xmlns:android="http://schemas.android.com/apk/res/android" + android:interpolator="@android:interpolator/accelerate_decelerate"> + <scale + android:fromXScale="1.0" + android:toXScale="1.0" + android:fromYScale="2.5" + android:toYScale="1.0" + android:pivotX="50%" + android:pivotY="50%" + android:duration="300" + android:fillBefore="false" /> +</set> diff --git a/res/anim/enter_from_left.xml b/res/anim/enter_from_left.xml new file mode 100644 index 000000000..e2bdbdda3 --- /dev/null +++ b/res/anim/enter_from_left.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8"?> +<set + xmlns:android="http://schemas.android.com/apk/res/android" > + + <objectAnimator + xmlns:android="http://schemas.android.com/apk/res/android" + android:duration="300" + android:propertyName="x" + android:valueFrom="-1000" + android:valueTo="0" + android:valueType="floatType" /> +</set> diff --git a/res/anim/enter_from_right.xml b/res/anim/enter_from_right.xml new file mode 100644 index 000000000..02a56c7ae --- /dev/null +++ b/res/anim/enter_from_right.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8"?> +<set + xmlns:android="http://schemas.android.com/apk/res/android" > + + <objectAnimator + xmlns:android="http://schemas.android.com/apk/res/android" + android:duration="300" + android:propertyName="x" + android:valueFrom="1000" + android:valueTo="0" + android:valueType="floatType" /> +</set> diff --git a/res/anim/exit_out_left.xml b/res/anim/exit_out_left.xml new file mode 100644 index 000000000..eae925a2a --- /dev/null +++ b/res/anim/exit_out_left.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8"?> +<set + xmlns:android="http://schemas.android.com/apk/res/android" > + + <objectAnimator + xmlns:android="http://schemas.android.com/apk/res/android" + android:duration="300" + android:propertyName="x" + android:valueFrom="0" + android:valueTo="-1000" + android:valueType="floatType" /> +</set> + diff --git a/res/anim/exit_out_right.xml b/res/anim/exit_out_right.xml new file mode 100644 index 000000000..7345c942d --- /dev/null +++ b/res/anim/exit_out_right.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8"?> +<set + xmlns:android="http://schemas.android.com/apk/res/android" > + + <objectAnimator + xmlns:android="http://schemas.android.com/apk/res/android" + android:duration="300" + android:propertyName="x" + android:valueFrom="0" + android:valueTo="1000" + android:valueType="floatType" /> +</set> diff --git a/res/color/listitem_text.xml b/res/color/listitem_text.xml new file mode 100644 index 000000000..c17b8555d --- /dev/null +++ b/res/color/listitem_text.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8"?> +<selector xmlns:android="http://schemas.android.com/apk/res/android" > + <item android:state_enabled="true" + android:state_pressed="true" android:color="@color/settings_bg_color" /> + <item android:color="@android:color/white" /> +</selector> diff --git a/res/drawable-hdpi/folder_lock.png b/res/drawable-hdpi/folder_lock.png Binary files differnew file mode 100644 index 000000000..9d5ac426d --- /dev/null +++ b/res/drawable-hdpi/folder_lock.png diff --git a/res/drawable-hdpi/folder_lock_light.png b/res/drawable-hdpi/folder_lock_light.png Binary files differnew file mode 100644 index 000000000..ca849e8d7 --- /dev/null +++ b/res/drawable-hdpi/folder_lock_light.png diff --git a/res/drawable-hdpi/folder_unlock.png b/res/drawable-hdpi/folder_unlock.png Binary files differnew file mode 100644 index 000000000..58524209c --- /dev/null +++ b/res/drawable-hdpi/folder_unlock.png diff --git a/res/drawable-hdpi/ic_clear.png b/res/drawable-hdpi/ic_clear.png Binary files differdeleted file mode 100644 index 67e0e6695..000000000 --- a/res/drawable-hdpi/ic_clear.png +++ /dev/null diff --git a/res/drawable-hdpi/ic_default_screen.png b/res/drawable-hdpi/ic_default_screen.png Binary files differindex 832fdef35..8a6996340 100644 --- a/res/drawable-hdpi/ic_default_screen.png +++ b/res/drawable-hdpi/ic_default_screen.png diff --git a/res/drawable-hdpi/ic_default_screen_pressed.png b/res/drawable-hdpi/ic_default_screen_pressed.png Binary files differindex 2975c6152..e3a7969e5 100644 --- a/res/drawable-hdpi/ic_default_screen_pressed.png +++ b/res/drawable-hdpi/ic_default_screen_pressed.png diff --git a/res/drawable-hdpi/ic_iconpacks.png b/res/drawable-hdpi/ic_iconpacks.png Binary files differdeleted file mode 100644 index 7985c1847..000000000 --- a/res/drawable-hdpi/ic_iconpacks.png +++ /dev/null diff --git a/res/drawable-hdpi/ic_remove.png b/res/drawable-hdpi/ic_remove.png Binary files differnew file mode 100644 index 000000000..d26b12b8f --- /dev/null +++ b/res/drawable-hdpi/ic_remove.png diff --git a/res/drawable-hdpi/ic_setting.png b/res/drawable-hdpi/ic_setting.png Binary files differdeleted file mode 100644 index c617154f1..000000000 --- a/res/drawable-hdpi/ic_setting.png +++ /dev/null diff --git a/res/drawable-hdpi/ic_setting_pressed.png b/res/drawable-hdpi/ic_setting_pressed.png Binary files differdeleted file mode 100644 index fb58a4b12..000000000 --- a/res/drawable-hdpi/ic_setting_pressed.png +++ /dev/null diff --git a/res/drawable-hdpi/ic_themes.png b/res/drawable-hdpi/ic_themes.png Binary files differnew file mode 100644 index 000000000..d627bcd2a --- /dev/null +++ b/res/drawable-hdpi/ic_themes.png diff --git a/res/drawable-hdpi/ic_themes_pressed.png b/res/drawable-hdpi/ic_themes_pressed.png Binary files differnew file mode 100644 index 000000000..b6f5c2fb9 --- /dev/null +++ b/res/drawable-hdpi/ic_themes_pressed.png diff --git a/res/drawable-hdpi/ic_widget.png b/res/drawable-hdpi/ic_widget.png Binary files differindex e7cc5346a..8c57af0de 100644 --- a/res/drawable-hdpi/ic_widget.png +++ b/res/drawable-hdpi/ic_widget.png diff --git a/res/drawable-hdpi/ic_widget_pressed.png b/res/drawable-hdpi/ic_widget_pressed.png Binary files differindex 4d0a1e43e..081f9f9ce 100644 --- a/res/drawable-hdpi/ic_widget_pressed.png +++ b/res/drawable-hdpi/ic_widget_pressed.png diff --git a/res/drawable-hdpi/on_boarding_welcome.png b/res/drawable-hdpi/on_boarding_welcome.png Binary files differnew file mode 100644 index 000000000..852a0cb13 --- /dev/null +++ b/res/drawable-hdpi/on_boarding_welcome.png diff --git a/res/drawable-hdpi/screenpanel_hover.9.png b/res/drawable-hdpi/screenpanel_hover.9.png Binary files differindex 3321fc925..0fed7c9d8 100644 --- a/res/drawable-hdpi/screenpanel_hover.9.png +++ b/res/drawable-hdpi/screenpanel_hover.9.png diff --git a/res/drawable-hdpi/search_bg.9.png b/res/drawable-hdpi/search_bg.9.png Binary files differnew file mode 100644 index 000000000..798127b50 --- /dev/null +++ b/res/drawable-hdpi/search_bg.9.png diff --git a/res/drawable-mdpi/folder_lock.png b/res/drawable-mdpi/folder_lock.png Binary files differnew file mode 100644 index 000000000..c44921a29 --- /dev/null +++ b/res/drawable-mdpi/folder_lock.png diff --git a/res/drawable-mdpi/folder_lock_light.png b/res/drawable-mdpi/folder_lock_light.png Binary files differnew file mode 100644 index 000000000..293444ec8 --- /dev/null +++ b/res/drawable-mdpi/folder_lock_light.png diff --git a/res/drawable-mdpi/folder_unlock.png b/res/drawable-mdpi/folder_unlock.png Binary files differnew file mode 100644 index 000000000..93e60fc45 --- /dev/null +++ b/res/drawable-mdpi/folder_unlock.png diff --git a/res/drawable-mdpi/ic_clear.png b/res/drawable-mdpi/ic_clear.png Binary files differdeleted file mode 100644 index 9d08a42b7..000000000 --- a/res/drawable-mdpi/ic_clear.png +++ /dev/null diff --git a/res/drawable-mdpi/ic_default_screen.png b/res/drawable-mdpi/ic_default_screen.png Binary files differindex 431b16841..60747a922 100644 --- a/res/drawable-mdpi/ic_default_screen.png +++ b/res/drawable-mdpi/ic_default_screen.png diff --git a/res/drawable-mdpi/ic_default_screen_pressed.png b/res/drawable-mdpi/ic_default_screen_pressed.png Binary files differindex 361f023f8..f18ee2c5f 100644 --- a/res/drawable-mdpi/ic_default_screen_pressed.png +++ b/res/drawable-mdpi/ic_default_screen_pressed.png diff --git a/res/drawable-mdpi/ic_iconpacks.png b/res/drawable-mdpi/ic_iconpacks.png Binary files differdeleted file mode 100644 index 36e35c215..000000000 --- a/res/drawable-mdpi/ic_iconpacks.png +++ /dev/null diff --git a/res/drawable-mdpi/ic_remove.png b/res/drawable-mdpi/ic_remove.png Binary files differnew file mode 100644 index 000000000..48c82fa1c --- /dev/null +++ b/res/drawable-mdpi/ic_remove.png diff --git a/res/drawable-mdpi/ic_setting.png b/res/drawable-mdpi/ic_setting.png Binary files differdeleted file mode 100644 index 0c8ae9d65..000000000 --- a/res/drawable-mdpi/ic_setting.png +++ /dev/null diff --git a/res/drawable-mdpi/ic_setting_pressed.png b/res/drawable-mdpi/ic_setting_pressed.png Binary files differdeleted file mode 100644 index 846091f58..000000000 --- a/res/drawable-mdpi/ic_setting_pressed.png +++ /dev/null diff --git a/res/drawable-mdpi/ic_themes.png b/res/drawable-mdpi/ic_themes.png Binary files differnew file mode 100644 index 000000000..f38a683a8 --- /dev/null +++ b/res/drawable-mdpi/ic_themes.png diff --git a/res/drawable-mdpi/ic_themes_pressed.png b/res/drawable-mdpi/ic_themes_pressed.png Binary files differnew file mode 100644 index 000000000..29b929b7d --- /dev/null +++ b/res/drawable-mdpi/ic_themes_pressed.png diff --git a/res/drawable-mdpi/ic_widget.png b/res/drawable-mdpi/ic_widget.png Binary files differindex 955ebf5b7..5f974c28c 100644 --- a/res/drawable-mdpi/ic_widget.png +++ b/res/drawable-mdpi/ic_widget.png diff --git a/res/drawable-mdpi/ic_widget_pressed.png b/res/drawable-mdpi/ic_widget_pressed.png Binary files differindex f65f49f8a..0a3e8838f 100644 --- a/res/drawable-mdpi/ic_widget_pressed.png +++ b/res/drawable-mdpi/ic_widget_pressed.png diff --git a/res/drawable-mdpi/on_boarding_welcome.png b/res/drawable-mdpi/on_boarding_welcome.png Binary files differnew file mode 100644 index 000000000..1d12e8362 --- /dev/null +++ b/res/drawable-mdpi/on_boarding_welcome.png diff --git a/res/drawable-mdpi/screenpanel_hover.9.png b/res/drawable-mdpi/screenpanel_hover.9.png Binary files differindex dd7740665..7dd885860 100644 --- a/res/drawable-mdpi/screenpanel_hover.9.png +++ b/res/drawable-mdpi/screenpanel_hover.9.png diff --git a/res/drawable-mdpi/search_bg.9.png b/res/drawable-mdpi/search_bg.9.png Binary files differnew file mode 100644 index 000000000..3b259d4fb --- /dev/null +++ b/res/drawable-mdpi/search_bg.9.png diff --git a/res/drawable-sw600dp-hdpi/ic_allapps.png b/res/drawable-sw600dp-hdpi/ic_allapps.png Binary files differindex 8bda43569..4d1aa861b 100644 --- a/res/drawable-sw600dp-hdpi/ic_allapps.png +++ b/res/drawable-sw600dp-hdpi/ic_allapps.png diff --git a/res/drawable-sw600dp-hdpi/ic_allapps_pressed.png b/res/drawable-sw600dp-hdpi/ic_allapps_pressed.png Binary files differindex 07ff33183..fa5f0f8ba 100644 --- a/res/drawable-sw600dp-hdpi/ic_allapps_pressed.png +++ b/res/drawable-sw600dp-hdpi/ic_allapps_pressed.png diff --git a/res/drawable-sw600dp-mdpi/ic_allapps.png b/res/drawable-sw600dp-mdpi/ic_allapps.png Binary files differindex e2afea5f3..20bfb793a 100644 --- a/res/drawable-sw600dp-mdpi/ic_allapps.png +++ b/res/drawable-sw600dp-mdpi/ic_allapps.png diff --git a/res/drawable-sw600dp-mdpi/ic_allapps_pressed.png b/res/drawable-sw600dp-mdpi/ic_allapps_pressed.png Binary files differindex d409c7ed3..cfe8fe80e 100644 --- a/res/drawable-sw600dp-mdpi/ic_allapps_pressed.png +++ b/res/drawable-sw600dp-mdpi/ic_allapps_pressed.png diff --git a/res/drawable-sw600dp-xhdpi/ic_allapps.png b/res/drawable-sw600dp-xhdpi/ic_allapps.png Binary files differindex 8fed2903a..4e4a8bab0 100644 --- a/res/drawable-sw600dp-xhdpi/ic_allapps.png +++ b/res/drawable-sw600dp-xhdpi/ic_allapps.png diff --git a/res/drawable-sw600dp-xhdpi/ic_allapps_pressed.png b/res/drawable-sw600dp-xhdpi/ic_allapps_pressed.png Binary files differindex 786b676ff..a76af1b78 100644 --- a/res/drawable-sw600dp-xhdpi/ic_allapps_pressed.png +++ b/res/drawable-sw600dp-xhdpi/ic_allapps_pressed.png diff --git a/res/drawable-sw600dp-xxhdpi/ic_allapps.png b/res/drawable-sw600dp-xxhdpi/ic_allapps.png Binary files differindex 242965605..96c7e0f27 100644 --- a/res/drawable-sw600dp-xxhdpi/ic_allapps.png +++ b/res/drawable-sw600dp-xxhdpi/ic_allapps.png diff --git a/res/drawable-sw600dp-xxhdpi/ic_allapps_pressed.png b/res/drawable-sw600dp-xxhdpi/ic_allapps_pressed.png Binary files differindex b93a51bea..9992b4644 100644 --- a/res/drawable-sw600dp-xxhdpi/ic_allapps_pressed.png +++ b/res/drawable-sw600dp-xxhdpi/ic_allapps_pressed.png diff --git a/res/drawable-sw720dp-xxhdpi/workspace_bg.9.png b/res/drawable-sw720dp-xxhdpi/workspace_bg.9.png Binary files differnew file mode 100644 index 000000000..efc9b0465 --- /dev/null +++ b/res/drawable-sw720dp-xxhdpi/workspace_bg.9.png diff --git a/res/drawable-xhdpi/folder_lock.png b/res/drawable-xhdpi/folder_lock.png Binary files differnew file mode 100644 index 000000000..5d8610b2f --- /dev/null +++ b/res/drawable-xhdpi/folder_lock.png diff --git a/res/drawable-xhdpi/folder_lock_light.png b/res/drawable-xhdpi/folder_lock_light.png Binary files differnew file mode 100644 index 000000000..4342c50f6 --- /dev/null +++ b/res/drawable-xhdpi/folder_lock_light.png diff --git a/res/drawable-xhdpi/folder_unlock.png b/res/drawable-xhdpi/folder_unlock.png Binary files differnew file mode 100644 index 000000000..a5b99c376 --- /dev/null +++ b/res/drawable-xhdpi/folder_unlock.png diff --git a/res/drawable-xhdpi/ic_clear.png b/res/drawable-xhdpi/ic_clear.png Binary files differdeleted file mode 100644 index d5925c795..000000000 --- a/res/drawable-xhdpi/ic_clear.png +++ /dev/null diff --git a/res/drawable-xhdpi/ic_default_screen.png b/res/drawable-xhdpi/ic_default_screen.png Binary files differindex da1e3a883..fcb9a97ae 100644 --- a/res/drawable-xhdpi/ic_default_screen.png +++ b/res/drawable-xhdpi/ic_default_screen.png diff --git a/res/drawable-xhdpi/ic_default_screen_pressed.png b/res/drawable-xhdpi/ic_default_screen_pressed.png Binary files differindex b8dc28c0c..cb360b20d 100644 --- a/res/drawable-xhdpi/ic_default_screen_pressed.png +++ b/res/drawable-xhdpi/ic_default_screen_pressed.png diff --git a/res/drawable-xhdpi/ic_iconpacks.png b/res/drawable-xhdpi/ic_iconpacks.png Binary files differdeleted file mode 100644 index 207d68a35..000000000 --- a/res/drawable-xhdpi/ic_iconpacks.png +++ /dev/null diff --git a/res/drawable-xhdpi/ic_remove.png b/res/drawable-xhdpi/ic_remove.png Binary files differnew file mode 100644 index 000000000..38a8705ad --- /dev/null +++ b/res/drawable-xhdpi/ic_remove.png diff --git a/res/drawable-xhdpi/ic_setting.png b/res/drawable-xhdpi/ic_setting.png Binary files differdeleted file mode 100644 index 91ba98c55..000000000 --- a/res/drawable-xhdpi/ic_setting.png +++ /dev/null diff --git a/res/drawable-xhdpi/ic_setting_pressed.png b/res/drawable-xhdpi/ic_setting_pressed.png Binary files differdeleted file mode 100644 index 08aafc405..000000000 --- a/res/drawable-xhdpi/ic_setting_pressed.png +++ /dev/null diff --git a/res/drawable-xhdpi/ic_themes.png b/res/drawable-xhdpi/ic_themes.png Binary files differnew file mode 100644 index 000000000..550e5d09b --- /dev/null +++ b/res/drawable-xhdpi/ic_themes.png diff --git a/res/drawable-xhdpi/ic_themes_pressed.png b/res/drawable-xhdpi/ic_themes_pressed.png Binary files differnew file mode 100644 index 000000000..49653566a --- /dev/null +++ b/res/drawable-xhdpi/ic_themes_pressed.png diff --git a/res/drawable-xhdpi/ic_widget.png b/res/drawable-xhdpi/ic_widget.png Binary files differindex fae347ba7..47dcdd14f 100644 --- a/res/drawable-xhdpi/ic_widget.png +++ b/res/drawable-xhdpi/ic_widget.png diff --git a/res/drawable-xhdpi/ic_widget_pressed.png b/res/drawable-xhdpi/ic_widget_pressed.png Binary files differindex eca9bcc26..8bb387b88 100644 --- a/res/drawable-xhdpi/ic_widget_pressed.png +++ b/res/drawable-xhdpi/ic_widget_pressed.png diff --git a/res/drawable-xhdpi/on_boarding_welcome.png b/res/drawable-xhdpi/on_boarding_welcome.png Binary files differnew file mode 100644 index 000000000..8c101e0db --- /dev/null +++ b/res/drawable-xhdpi/on_boarding_welcome.png diff --git a/res/drawable-xhdpi/screenpanel_hover.9.png b/res/drawable-xhdpi/screenpanel_hover.9.png Binary files differindex a44dc113f..251bf2085 100644 --- a/res/drawable-xhdpi/screenpanel_hover.9.png +++ b/res/drawable-xhdpi/screenpanel_hover.9.png diff --git a/res/drawable-xhdpi/search_bg.9.png b/res/drawable-xhdpi/search_bg.9.png Binary files differnew file mode 100644 index 000000000..947fd4de6 --- /dev/null +++ b/res/drawable-xhdpi/search_bg.9.png diff --git a/res/drawable-xxhdpi/folder_lock.png b/res/drawable-xxhdpi/folder_lock.png Binary files differnew file mode 100644 index 000000000..16726d395 --- /dev/null +++ b/res/drawable-xxhdpi/folder_lock.png diff --git a/res/drawable-xxhdpi/folder_lock_light.png b/res/drawable-xxhdpi/folder_lock_light.png Binary files differnew file mode 100644 index 000000000..4226f6af8 --- /dev/null +++ b/res/drawable-xxhdpi/folder_lock_light.png diff --git a/res/drawable-xxhdpi/folder_unlock.png b/res/drawable-xxhdpi/folder_unlock.png Binary files differnew file mode 100644 index 000000000..95c18cbc2 --- /dev/null +++ b/res/drawable-xxhdpi/folder_unlock.png diff --git a/res/drawable-xxhdpi/ic_clear.png b/res/drawable-xxhdpi/ic_clear.png Binary files differdeleted file mode 100644 index 1472e7cc7..000000000 --- a/res/drawable-xxhdpi/ic_clear.png +++ /dev/null diff --git a/res/drawable-xxhdpi/ic_default_screen.png b/res/drawable-xxhdpi/ic_default_screen.png Binary files differindex 4577ad2b5..e0ee77426 100644 --- a/res/drawable-xxhdpi/ic_default_screen.png +++ b/res/drawable-xxhdpi/ic_default_screen.png diff --git a/res/drawable-xxhdpi/ic_default_screen_pressed.png b/res/drawable-xxhdpi/ic_default_screen_pressed.png Binary files differindex cf9cd10e2..fb8c81575 100644 --- a/res/drawable-xxhdpi/ic_default_screen_pressed.png +++ b/res/drawable-xxhdpi/ic_default_screen_pressed.png diff --git a/res/drawable-xxhdpi/ic_iconpacks.png b/res/drawable-xxhdpi/ic_iconpacks.png Binary files differdeleted file mode 100644 index d1aea29da..000000000 --- a/res/drawable-xxhdpi/ic_iconpacks.png +++ /dev/null diff --git a/res/drawable-xxhdpi/ic_remove.png b/res/drawable-xxhdpi/ic_remove.png Binary files differnew file mode 100644 index 000000000..ac36b34c0 --- /dev/null +++ b/res/drawable-xxhdpi/ic_remove.png diff --git a/res/drawable-xxhdpi/ic_setting.png b/res/drawable-xxhdpi/ic_setting.png Binary files differdeleted file mode 100644 index 6e1e6627c..000000000 --- a/res/drawable-xxhdpi/ic_setting.png +++ /dev/null diff --git a/res/drawable-xxhdpi/ic_setting_pressed.png b/res/drawable-xxhdpi/ic_setting_pressed.png Binary files differdeleted file mode 100644 index a202a40fe..000000000 --- a/res/drawable-xxhdpi/ic_setting_pressed.png +++ /dev/null diff --git a/res/drawable-xxhdpi/ic_themes.png b/res/drawable-xxhdpi/ic_themes.png Binary files differnew file mode 100644 index 000000000..1f68ae61f --- /dev/null +++ b/res/drawable-xxhdpi/ic_themes.png diff --git a/res/drawable-xxhdpi/ic_themes_pressed.png b/res/drawable-xxhdpi/ic_themes_pressed.png Binary files differnew file mode 100644 index 000000000..da596ab82 --- /dev/null +++ b/res/drawable-xxhdpi/ic_themes_pressed.png diff --git a/res/drawable-xxhdpi/ic_widget.png b/res/drawable-xxhdpi/ic_widget.png Binary files differindex 3bdb42d5e..fddfecaa3 100644 --- a/res/drawable-xxhdpi/ic_widget.png +++ b/res/drawable-xxhdpi/ic_widget.png diff --git a/res/drawable-xxhdpi/ic_widget_pressed.png b/res/drawable-xxhdpi/ic_widget_pressed.png Binary files differindex db6765f13..3d3670ed4 100644 --- a/res/drawable-xxhdpi/ic_widget_pressed.png +++ b/res/drawable-xxhdpi/ic_widget_pressed.png diff --git a/res/drawable-xxhdpi/screenpanel_hover.9.png b/res/drawable-xxhdpi/screenpanel_hover.9.png Binary files differindex 1ab18da6a..e8b36d8f1 100644 --- a/res/drawable-xxhdpi/screenpanel_hover.9.png +++ b/res/drawable-xxhdpi/screenpanel_hover.9.png diff --git a/res/drawable-xxhdpi/search_bg.9.png b/res/drawable-xxhdpi/search_bg.9.png Binary files differnew file mode 100644 index 000000000..6626cd99b --- /dev/null +++ b/res/drawable-xxhdpi/search_bg.9.png diff --git a/res/drawable/above_shadow.xml b/res/drawable/above_shadow.xml new file mode 100644 index 000000000..5965c971e --- /dev/null +++ b/res/drawable/above_shadow.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8"?> +<shape xmlns:android="http://schemas.android.com/apk/res/android"> + <gradient + android:startColor="#20000000" + android:endColor="@android:color/transparent" + android:angle="90" > + </gradient> +</shape>
\ No newline at end of file diff --git a/res/drawable/acordian_00000.png b/res/drawable/acordian_00000.png Binary files differnew file mode 100644 index 000000000..72bebb4b3 --- /dev/null +++ b/res/drawable/acordian_00000.png diff --git a/res/drawable/acordian_00001.png b/res/drawable/acordian_00001.png Binary files differnew file mode 100644 index 000000000..48f07492b --- /dev/null +++ b/res/drawable/acordian_00001.png diff --git a/res/drawable/acordian_00002.png b/res/drawable/acordian_00002.png Binary files differnew file mode 100644 index 000000000..3ae1b69ca --- /dev/null +++ b/res/drawable/acordian_00002.png diff --git a/res/drawable/acordian_00003.png b/res/drawable/acordian_00003.png Binary files differnew file mode 100644 index 000000000..da2ffe0bf --- /dev/null +++ b/res/drawable/acordian_00003.png diff --git a/res/drawable/acordian_00004.png b/res/drawable/acordian_00004.png Binary files differnew file mode 100644 index 000000000..66f0a26f7 --- /dev/null +++ b/res/drawable/acordian_00004.png diff --git a/res/drawable/acordian_00005.png b/res/drawable/acordian_00005.png Binary files differnew file mode 100644 index 000000000..475060766 --- /dev/null +++ b/res/drawable/acordian_00005.png diff --git a/res/drawable/acordian_00006.png b/res/drawable/acordian_00006.png Binary files differnew file mode 100644 index 000000000..b52388848 --- /dev/null +++ b/res/drawable/acordian_00006.png diff --git a/res/drawable/acordian_00007.png b/res/drawable/acordian_00007.png Binary files differnew file mode 100644 index 000000000..053036747 --- /dev/null +++ b/res/drawable/acordian_00007.png diff --git a/res/drawable/acordian_00008.png b/res/drawable/acordian_00008.png Binary files differnew file mode 100644 index 000000000..11c23fe1f --- /dev/null +++ b/res/drawable/acordian_00008.png diff --git a/res/drawable/acordian_00009.png b/res/drawable/acordian_00009.png Binary files differnew file mode 100644 index 000000000..2fd060a03 --- /dev/null +++ b/res/drawable/acordian_00009.png diff --git a/res/drawable/acordian_00010.png b/res/drawable/acordian_00010.png Binary files differnew file mode 100644 index 000000000..5debae47a --- /dev/null +++ b/res/drawable/acordian_00010.png diff --git a/res/drawable/acordian_00011.png b/res/drawable/acordian_00011.png Binary files differnew file mode 100644 index 000000000..5debae47a --- /dev/null +++ b/res/drawable/acordian_00011.png diff --git a/res/drawable/acordian_00012.png b/res/drawable/acordian_00012.png Binary files differnew file mode 100644 index 000000000..5debae47a --- /dev/null +++ b/res/drawable/acordian_00012.png diff --git a/res/drawable/acordian_00013.png b/res/drawable/acordian_00013.png Binary files differnew file mode 100644 index 000000000..5debae47a --- /dev/null +++ b/res/drawable/acordian_00013.png diff --git a/res/drawable/acordian_00014.png b/res/drawable/acordian_00014.png Binary files differnew file mode 100644 index 000000000..5debae47a --- /dev/null +++ b/res/drawable/acordian_00014.png diff --git a/res/drawable/acordian_00015.png b/res/drawable/acordian_00015.png Binary files differnew file mode 100644 index 000000000..5debae47a --- /dev/null +++ b/res/drawable/acordian_00015.png diff --git a/res/drawable/acordian_00016.png b/res/drawable/acordian_00016.png Binary files differnew file mode 100644 index 000000000..5debae47a --- /dev/null +++ b/res/drawable/acordian_00016.png diff --git a/res/drawable/acordian_00017.png b/res/drawable/acordian_00017.png Binary files differnew file mode 100644 index 000000000..5debae47a --- /dev/null +++ b/res/drawable/acordian_00017.png diff --git a/res/drawable/acordian_00018.png b/res/drawable/acordian_00018.png Binary files differnew file mode 100644 index 000000000..5debae47a --- /dev/null +++ b/res/drawable/acordian_00018.png diff --git a/res/drawable/acordian_00019.png b/res/drawable/acordian_00019.png Binary files differnew file mode 100644 index 000000000..5debae47a --- /dev/null +++ b/res/drawable/acordian_00019.png diff --git a/res/drawable/acordian_00020.png b/res/drawable/acordian_00020.png Binary files differnew file mode 100644 index 000000000..5debae47a --- /dev/null +++ b/res/drawable/acordian_00020.png diff --git a/res/drawable/acordian_00021.png b/res/drawable/acordian_00021.png Binary files differnew file mode 100644 index 000000000..5debae47a --- /dev/null +++ b/res/drawable/acordian_00021.png diff --git a/res/drawable/acordian_00022.png b/res/drawable/acordian_00022.png Binary files differnew file mode 100644 index 000000000..5debae47a --- /dev/null +++ b/res/drawable/acordian_00022.png diff --git a/res/drawable/acordian_00023.png b/res/drawable/acordian_00023.png Binary files differnew file mode 100644 index 000000000..5debae47a --- /dev/null +++ b/res/drawable/acordian_00023.png diff --git a/res/drawable/acordian_00024.png b/res/drawable/acordian_00024.png Binary files differnew file mode 100644 index 000000000..5debae47a --- /dev/null +++ b/res/drawable/acordian_00024.png diff --git a/res/drawable/acordian_00025.png b/res/drawable/acordian_00025.png Binary files differnew file mode 100644 index 000000000..5debae47a --- /dev/null +++ b/res/drawable/acordian_00025.png diff --git a/res/drawable/acordian_00026.png b/res/drawable/acordian_00026.png Binary files differnew file mode 100644 index 000000000..5debae47a --- /dev/null +++ b/res/drawable/acordian_00026.png diff --git a/res/drawable/acordian_00027.png b/res/drawable/acordian_00027.png Binary files differnew file mode 100644 index 000000000..2fd060a03 --- /dev/null +++ b/res/drawable/acordian_00027.png diff --git a/res/drawable/acordian_00028.png b/res/drawable/acordian_00028.png Binary files differnew file mode 100644 index 000000000..11c23fe1f --- /dev/null +++ b/res/drawable/acordian_00028.png diff --git a/res/drawable/acordian_00029.png b/res/drawable/acordian_00029.png Binary files differnew file mode 100644 index 000000000..053036747 --- /dev/null +++ b/res/drawable/acordian_00029.png diff --git a/res/drawable/acordian_00030.png b/res/drawable/acordian_00030.png Binary files differnew file mode 100644 index 000000000..b52388848 --- /dev/null +++ b/res/drawable/acordian_00030.png diff --git a/res/drawable/acordian_00031.png b/res/drawable/acordian_00031.png Binary files differnew file mode 100644 index 000000000..734bb390d --- /dev/null +++ b/res/drawable/acordian_00031.png diff --git a/res/drawable/acordian_00032.png b/res/drawable/acordian_00032.png Binary files differnew file mode 100644 index 000000000..66f0a26f7 --- /dev/null +++ b/res/drawable/acordian_00032.png diff --git a/res/drawable/acordian_00033.png b/res/drawable/acordian_00033.png Binary files differnew file mode 100644 index 000000000..da2ffe0bf --- /dev/null +++ b/res/drawable/acordian_00033.png diff --git a/res/drawable/acordian_00034.png b/res/drawable/acordian_00034.png Binary files differnew file mode 100644 index 000000000..3ae1b69ca --- /dev/null +++ b/res/drawable/acordian_00034.png diff --git a/res/drawable/acordian_00035.png b/res/drawable/acordian_00035.png Binary files differnew file mode 100644 index 000000000..48f07492b --- /dev/null +++ b/res/drawable/acordian_00035.png diff --git a/res/drawable/acordian_00036.png b/res/drawable/acordian_00036.png Binary files differnew file mode 100644 index 000000000..72bebb4b3 --- /dev/null +++ b/res/drawable/acordian_00036.png diff --git a/res/drawable/acordian_00037.png b/res/drawable/acordian_00037.png Binary files differnew file mode 100644 index 000000000..72bebb4b3 --- /dev/null +++ b/res/drawable/acordian_00037.png diff --git a/res/drawable/acordian_00038.png b/res/drawable/acordian_00038.png Binary files differnew file mode 100644 index 000000000..72bebb4b3 --- /dev/null +++ b/res/drawable/acordian_00038.png diff --git a/res/drawable/acordian_00039.png b/res/drawable/acordian_00039.png Binary files differnew file mode 100644 index 000000000..72bebb4b3 --- /dev/null +++ b/res/drawable/acordian_00039.png diff --git a/res/drawable/acordian_00040.png b/res/drawable/acordian_00040.png Binary files differnew file mode 100644 index 000000000..72bebb4b3 --- /dev/null +++ b/res/drawable/acordian_00040.png diff --git a/res/drawable/acordian_00041.png b/res/drawable/acordian_00041.png Binary files differnew file mode 100644 index 000000000..72bebb4b3 --- /dev/null +++ b/res/drawable/acordian_00041.png diff --git a/res/drawable/acordian_00042.png b/res/drawable/acordian_00042.png Binary files differnew file mode 100644 index 000000000..72bebb4b3 --- /dev/null +++ b/res/drawable/acordian_00042.png diff --git a/res/drawable/acordian_00043.png b/res/drawable/acordian_00043.png Binary files differnew file mode 100644 index 000000000..72bebb4b3 --- /dev/null +++ b/res/drawable/acordian_00043.png diff --git a/res/drawable/acordian_00044.png b/res/drawable/acordian_00044.png Binary files differnew file mode 100644 index 000000000..72bebb4b3 --- /dev/null +++ b/res/drawable/acordian_00044.png diff --git a/res/drawable/acordian_00045.png b/res/drawable/acordian_00045.png Binary files differnew file mode 100644 index 000000000..72bebb4b3 --- /dev/null +++ b/res/drawable/acordian_00045.png diff --git a/res/drawable/acordian_00046.png b/res/drawable/acordian_00046.png Binary files differnew file mode 100644 index 000000000..72bebb4b3 --- /dev/null +++ b/res/drawable/acordian_00046.png diff --git a/res/drawable/acordian_00047.png b/res/drawable/acordian_00047.png Binary files differnew file mode 100644 index 000000000..72bebb4b3 --- /dev/null +++ b/res/drawable/acordian_00047.png diff --git a/res/drawable/acordian_00048.png b/res/drawable/acordian_00048.png Binary files differnew file mode 100644 index 000000000..72bebb4b3 --- /dev/null +++ b/res/drawable/acordian_00048.png diff --git a/res/drawable/acordian_00049.png b/res/drawable/acordian_00049.png Binary files differnew file mode 100644 index 000000000..72bebb4b3 --- /dev/null +++ b/res/drawable/acordian_00049.png diff --git a/res/drawable/below_shadow.xml b/res/drawable/below_shadow.xml new file mode 100644 index 000000000..c724e27d3 --- /dev/null +++ b/res/drawable/below_shadow.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8"?> +<shape xmlns:android="http://schemas.android.com/apk/res/android"> + <gradient + android:startColor="#20000000" + android:endColor="@android:color/transparent" + android:angle="270" > + </gradient> +</shape>
\ No newline at end of file diff --git a/res/drawable/carousel_00000.png b/res/drawable/carousel_00000.png Binary files differnew file mode 100644 index 000000000..d444d1318 --- /dev/null +++ b/res/drawable/carousel_00000.png diff --git a/res/drawable/carousel_00001.png b/res/drawable/carousel_00001.png Binary files differnew file mode 100644 index 000000000..ebd6200a4 --- /dev/null +++ b/res/drawable/carousel_00001.png diff --git a/res/drawable/carousel_00002.png b/res/drawable/carousel_00002.png Binary files differnew file mode 100644 index 000000000..121f26fa6 --- /dev/null +++ b/res/drawable/carousel_00002.png diff --git a/res/drawable/carousel_00003.png b/res/drawable/carousel_00003.png Binary files differnew file mode 100644 index 000000000..9a61cb40b --- /dev/null +++ b/res/drawable/carousel_00003.png diff --git a/res/drawable/carousel_00004.png b/res/drawable/carousel_00004.png Binary files differnew file mode 100644 index 000000000..4f9a741cc --- /dev/null +++ b/res/drawable/carousel_00004.png diff --git a/res/drawable/carousel_00005.png b/res/drawable/carousel_00005.png Binary files differnew file mode 100644 index 000000000..32eadfea5 --- /dev/null +++ b/res/drawable/carousel_00005.png diff --git a/res/drawable/carousel_00006.png b/res/drawable/carousel_00006.png Binary files differnew file mode 100644 index 000000000..e9d8cd625 --- /dev/null +++ b/res/drawable/carousel_00006.png diff --git a/res/drawable/carousel_00007.png b/res/drawable/carousel_00007.png Binary files differnew file mode 100644 index 000000000..d4202b14c --- /dev/null +++ b/res/drawable/carousel_00007.png diff --git a/res/drawable/carousel_00008.png b/res/drawable/carousel_00008.png Binary files differnew file mode 100644 index 000000000..88247f836 --- /dev/null +++ b/res/drawable/carousel_00008.png diff --git a/res/drawable/carousel_00009.png b/res/drawable/carousel_00009.png Binary files differnew file mode 100644 index 000000000..503f791fe --- /dev/null +++ b/res/drawable/carousel_00009.png diff --git a/res/drawable/carousel_00010.png b/res/drawable/carousel_00010.png Binary files differnew file mode 100644 index 000000000..b439edc22 --- /dev/null +++ b/res/drawable/carousel_00010.png diff --git a/res/drawable/carousel_00011.png b/res/drawable/carousel_00011.png Binary files differnew file mode 100644 index 000000000..80a7eca42 --- /dev/null +++ b/res/drawable/carousel_00011.png diff --git a/res/drawable/carousel_00012.png b/res/drawable/carousel_00012.png Binary files differnew file mode 100644 index 000000000..57e72b869 --- /dev/null +++ b/res/drawable/carousel_00012.png diff --git a/res/drawable/carousel_00013.png b/res/drawable/carousel_00013.png Binary files differnew file mode 100644 index 000000000..6211a520e --- /dev/null +++ b/res/drawable/carousel_00013.png diff --git a/res/drawable/carousel_00014.png b/res/drawable/carousel_00014.png Binary files differnew file mode 100644 index 000000000..714466bdd --- /dev/null +++ b/res/drawable/carousel_00014.png diff --git a/res/drawable/carousel_00015.png b/res/drawable/carousel_00015.png Binary files differnew file mode 100644 index 000000000..0b34111c4 --- /dev/null +++ b/res/drawable/carousel_00015.png diff --git a/res/drawable/carousel_00016.png b/res/drawable/carousel_00016.png Binary files differnew file mode 100644 index 000000000..a3c08cd13 --- /dev/null +++ b/res/drawable/carousel_00016.png diff --git a/res/drawable/carousel_00017.png b/res/drawable/carousel_00017.png Binary files differnew file mode 100644 index 000000000..5fa15a7cb --- /dev/null +++ b/res/drawable/carousel_00017.png diff --git a/res/drawable/carousel_00018.png b/res/drawable/carousel_00018.png Binary files differnew file mode 100644 index 000000000..e10df7dd0 --- /dev/null +++ b/res/drawable/carousel_00018.png diff --git a/res/drawable/carousel_00019.png b/res/drawable/carousel_00019.png Binary files differnew file mode 100644 index 000000000..4e3765b40 --- /dev/null +++ b/res/drawable/carousel_00019.png diff --git a/res/drawable/carousel_00020.png b/res/drawable/carousel_00020.png Binary files differnew file mode 100644 index 000000000..d444d1318 --- /dev/null +++ b/res/drawable/carousel_00020.png diff --git a/res/drawable/carousel_00021.png b/res/drawable/carousel_00021.png Binary files differnew file mode 100644 index 000000000..d444d1318 --- /dev/null +++ b/res/drawable/carousel_00021.png diff --git a/res/drawable/carousel_00022.png b/res/drawable/carousel_00022.png Binary files differnew file mode 100644 index 000000000..d444d1318 --- /dev/null +++ b/res/drawable/carousel_00022.png diff --git a/res/drawable/carousel_00023.png b/res/drawable/carousel_00023.png Binary files differnew file mode 100644 index 000000000..d444d1318 --- /dev/null +++ b/res/drawable/carousel_00023.png diff --git a/res/drawable/carousel_00024.png b/res/drawable/carousel_00024.png Binary files differnew file mode 100644 index 000000000..d444d1318 --- /dev/null +++ b/res/drawable/carousel_00024.png diff --git a/res/drawable/carousel_00025.png b/res/drawable/carousel_00025.png Binary files differnew file mode 100644 index 000000000..d444d1318 --- /dev/null +++ b/res/drawable/carousel_00025.png diff --git a/res/drawable/carousel_00026.png b/res/drawable/carousel_00026.png Binary files differnew file mode 100644 index 000000000..d444d1318 --- /dev/null +++ b/res/drawable/carousel_00026.png diff --git a/res/drawable/carousel_00027.png b/res/drawable/carousel_00027.png Binary files differnew file mode 100644 index 000000000..d444d1318 --- /dev/null +++ b/res/drawable/carousel_00027.png diff --git a/res/drawable/carousel_00028.png b/res/drawable/carousel_00028.png Binary files differnew file mode 100644 index 000000000..d444d1318 --- /dev/null +++ b/res/drawable/carousel_00028.png diff --git a/res/drawable/carousel_00029.png b/res/drawable/carousel_00029.png Binary files differnew file mode 100644 index 000000000..d444d1318 --- /dev/null +++ b/res/drawable/carousel_00029.png diff --git a/res/drawable/carousel_00030.png b/res/drawable/carousel_00030.png Binary files differnew file mode 100644 index 000000000..d444d1318 --- /dev/null +++ b/res/drawable/carousel_00030.png diff --git a/res/drawable/carousel_00031.png b/res/drawable/carousel_00031.png Binary files differnew file mode 100644 index 000000000..d444d1318 --- /dev/null +++ b/res/drawable/carousel_00031.png diff --git a/res/drawable/carousel_00032.png b/res/drawable/carousel_00032.png Binary files differnew file mode 100644 index 000000000..d444d1318 --- /dev/null +++ b/res/drawable/carousel_00032.png diff --git a/res/drawable/carousel_00033.png b/res/drawable/carousel_00033.png Binary files differnew file mode 100644 index 000000000..d444d1318 --- /dev/null +++ b/res/drawable/carousel_00033.png diff --git a/res/drawable/carousel_00034.png b/res/drawable/carousel_00034.png Binary files differnew file mode 100644 index 000000000..d444d1318 --- /dev/null +++ b/res/drawable/carousel_00034.png diff --git a/res/drawable/carousel_00035.png b/res/drawable/carousel_00035.png Binary files differnew file mode 100644 index 000000000..d444d1318 --- /dev/null +++ b/res/drawable/carousel_00035.png diff --git a/res/drawable/carousel_00036.png b/res/drawable/carousel_00036.png Binary files differnew file mode 100644 index 000000000..d444d1318 --- /dev/null +++ b/res/drawable/carousel_00036.png diff --git a/res/drawable/carousel_00037.png b/res/drawable/carousel_00037.png Binary files differnew file mode 100644 index 000000000..d444d1318 --- /dev/null +++ b/res/drawable/carousel_00037.png diff --git a/res/drawable/carousel_00038.png b/res/drawable/carousel_00038.png Binary files differnew file mode 100644 index 000000000..d444d1318 --- /dev/null +++ b/res/drawable/carousel_00038.png diff --git a/res/drawable/carousel_00039.png b/res/drawable/carousel_00039.png Binary files differnew file mode 100644 index 000000000..d444d1318 --- /dev/null +++ b/res/drawable/carousel_00039.png diff --git a/res/drawable/carousel_00040.png b/res/drawable/carousel_00040.png Binary files differnew file mode 100644 index 000000000..d444d1318 --- /dev/null +++ b/res/drawable/carousel_00040.png diff --git a/res/drawable/carousel_00041.png b/res/drawable/carousel_00041.png Binary files differnew file mode 100644 index 000000000..d444d1318 --- /dev/null +++ b/res/drawable/carousel_00041.png diff --git a/res/drawable/carousel_00042.png b/res/drawable/carousel_00042.png Binary files differnew file mode 100644 index 000000000..d444d1318 --- /dev/null +++ b/res/drawable/carousel_00042.png diff --git a/res/drawable/carousel_00043.png b/res/drawable/carousel_00043.png Binary files differnew file mode 100644 index 000000000..d444d1318 --- /dev/null +++ b/res/drawable/carousel_00043.png diff --git a/res/drawable/carousel_00044.png b/res/drawable/carousel_00044.png Binary files differnew file mode 100644 index 000000000..d444d1318 --- /dev/null +++ b/res/drawable/carousel_00044.png diff --git a/res/drawable/carousel_00045.png b/res/drawable/carousel_00045.png Binary files differnew file mode 100644 index 000000000..d444d1318 --- /dev/null +++ b/res/drawable/carousel_00045.png diff --git a/res/drawable/carousel_00046.png b/res/drawable/carousel_00046.png Binary files differnew file mode 100644 index 000000000..d444d1318 --- /dev/null +++ b/res/drawable/carousel_00046.png diff --git a/res/drawable/carousel_00047.png b/res/drawable/carousel_00047.png Binary files differnew file mode 100644 index 000000000..d444d1318 --- /dev/null +++ b/res/drawable/carousel_00047.png diff --git a/res/drawable/carousel_00048.png b/res/drawable/carousel_00048.png Binary files differnew file mode 100644 index 000000000..d444d1318 --- /dev/null +++ b/res/drawable/carousel_00048.png diff --git a/res/drawable/carousel_00049.png b/res/drawable/carousel_00049.png Binary files differnew file mode 100644 index 000000000..d444d1318 --- /dev/null +++ b/res/drawable/carousel_00049.png diff --git a/res/drawable/cubein_00000.png b/res/drawable/cubein_00000.png Binary files differnew file mode 100644 index 000000000..678a89d23 --- /dev/null +++ b/res/drawable/cubein_00000.png diff --git a/res/drawable/cubein_00001.png b/res/drawable/cubein_00001.png Binary files differnew file mode 100644 index 000000000..322899f46 --- /dev/null +++ b/res/drawable/cubein_00001.png diff --git a/res/drawable/cubein_00002.png b/res/drawable/cubein_00002.png Binary files differnew file mode 100644 index 000000000..3d963c7ee --- /dev/null +++ b/res/drawable/cubein_00002.png diff --git a/res/drawable/cubein_00003.png b/res/drawable/cubein_00003.png Binary files differnew file mode 100644 index 000000000..7dabd0bf3 --- /dev/null +++ b/res/drawable/cubein_00003.png diff --git a/res/drawable/cubein_00004.png b/res/drawable/cubein_00004.png Binary files differnew file mode 100644 index 000000000..b73ce02c8 --- /dev/null +++ b/res/drawable/cubein_00004.png diff --git a/res/drawable/cubein_00005.png b/res/drawable/cubein_00005.png Binary files differnew file mode 100644 index 000000000..d9c7ea1f0 --- /dev/null +++ b/res/drawable/cubein_00005.png diff --git a/res/drawable/cubein_00006.png b/res/drawable/cubein_00006.png Binary files differnew file mode 100644 index 000000000..2b3198bc9 --- /dev/null +++ b/res/drawable/cubein_00006.png diff --git a/res/drawable/cubein_00007.png b/res/drawable/cubein_00007.png Binary files differnew file mode 100644 index 000000000..915fbe71f --- /dev/null +++ b/res/drawable/cubein_00007.png diff --git a/res/drawable/cubein_00008.png b/res/drawable/cubein_00008.png Binary files differnew file mode 100644 index 000000000..4eee981b6 --- /dev/null +++ b/res/drawable/cubein_00008.png diff --git a/res/drawable/cubein_00009.png b/res/drawable/cubein_00009.png Binary files differnew file mode 100644 index 000000000..516661963 --- /dev/null +++ b/res/drawable/cubein_00009.png diff --git a/res/drawable/cubein_00010.png b/res/drawable/cubein_00010.png Binary files differnew file mode 100644 index 000000000..3fdb7af1a --- /dev/null +++ b/res/drawable/cubein_00010.png diff --git a/res/drawable/cubein_00011.png b/res/drawable/cubein_00011.png Binary files differnew file mode 100644 index 000000000..273b70afa --- /dev/null +++ b/res/drawable/cubein_00011.png diff --git a/res/drawable/cubein_00012.png b/res/drawable/cubein_00012.png Binary files differnew file mode 100644 index 000000000..4ed7571c0 --- /dev/null +++ b/res/drawable/cubein_00012.png diff --git a/res/drawable/cubein_00013.png b/res/drawable/cubein_00013.png Binary files differnew file mode 100644 index 000000000..6ec50e73c --- /dev/null +++ b/res/drawable/cubein_00013.png diff --git a/res/drawable/cubein_00014.png b/res/drawable/cubein_00014.png Binary files differnew file mode 100644 index 000000000..78eee8c7f --- /dev/null +++ b/res/drawable/cubein_00014.png diff --git a/res/drawable/cubein_00015.png b/res/drawable/cubein_00015.png Binary files differnew file mode 100644 index 000000000..cbf4bbd53 --- /dev/null +++ b/res/drawable/cubein_00015.png diff --git a/res/drawable/cubein_00016.png b/res/drawable/cubein_00016.png Binary files differnew file mode 100644 index 000000000..3bd56fc2d --- /dev/null +++ b/res/drawable/cubein_00016.png diff --git a/res/drawable/cubein_00017.png b/res/drawable/cubein_00017.png Binary files differnew file mode 100644 index 000000000..2783f73b1 --- /dev/null +++ b/res/drawable/cubein_00017.png diff --git a/res/drawable/cubein_00018.png b/res/drawable/cubein_00018.png Binary files differnew file mode 100644 index 000000000..052c7b22b --- /dev/null +++ b/res/drawable/cubein_00018.png diff --git a/res/drawable/cubein_00019.png b/res/drawable/cubein_00019.png Binary files differnew file mode 100644 index 000000000..7c99a679b --- /dev/null +++ b/res/drawable/cubein_00019.png diff --git a/res/drawable/cubein_00020.png b/res/drawable/cubein_00020.png Binary files differnew file mode 100644 index 000000000..1662df8dc --- /dev/null +++ b/res/drawable/cubein_00020.png diff --git a/res/drawable/cubein_00021.png b/res/drawable/cubein_00021.png Binary files differnew file mode 100644 index 000000000..1662df8dc --- /dev/null +++ b/res/drawable/cubein_00021.png diff --git a/res/drawable/cubein_00022.png b/res/drawable/cubein_00022.png Binary files differnew file mode 100644 index 000000000..1662df8dc --- /dev/null +++ b/res/drawable/cubein_00022.png diff --git a/res/drawable/cubein_00023.png b/res/drawable/cubein_00023.png Binary files differnew file mode 100644 index 000000000..1662df8dc --- /dev/null +++ b/res/drawable/cubein_00023.png diff --git a/res/drawable/cubein_00024.png b/res/drawable/cubein_00024.png Binary files differnew file mode 100644 index 000000000..1662df8dc --- /dev/null +++ b/res/drawable/cubein_00024.png diff --git a/res/drawable/cubein_00025.png b/res/drawable/cubein_00025.png Binary files differnew file mode 100644 index 000000000..1662df8dc --- /dev/null +++ b/res/drawable/cubein_00025.png diff --git a/res/drawable/cubein_00026.png b/res/drawable/cubein_00026.png Binary files differnew file mode 100644 index 000000000..1662df8dc --- /dev/null +++ b/res/drawable/cubein_00026.png diff --git a/res/drawable/cubein_00027.png b/res/drawable/cubein_00027.png Binary files differnew file mode 100644 index 000000000..1662df8dc --- /dev/null +++ b/res/drawable/cubein_00027.png diff --git a/res/drawable/cubein_00028.png b/res/drawable/cubein_00028.png Binary files differnew file mode 100644 index 000000000..1662df8dc --- /dev/null +++ b/res/drawable/cubein_00028.png diff --git a/res/drawable/cubein_00029.png b/res/drawable/cubein_00029.png Binary files differnew file mode 100644 index 000000000..1662df8dc --- /dev/null +++ b/res/drawable/cubein_00029.png diff --git a/res/drawable/cubein_00030.png b/res/drawable/cubein_00030.png Binary files differnew file mode 100644 index 000000000..1662df8dc --- /dev/null +++ b/res/drawable/cubein_00030.png diff --git a/res/drawable/cubein_00031.png b/res/drawable/cubein_00031.png Binary files differnew file mode 100644 index 000000000..1662df8dc --- /dev/null +++ b/res/drawable/cubein_00031.png diff --git a/res/drawable/cubein_00032.png b/res/drawable/cubein_00032.png Binary files differnew file mode 100644 index 000000000..1662df8dc --- /dev/null +++ b/res/drawable/cubein_00032.png diff --git a/res/drawable/cubein_00033.png b/res/drawable/cubein_00033.png Binary files differnew file mode 100644 index 000000000..1662df8dc --- /dev/null +++ b/res/drawable/cubein_00033.png diff --git a/res/drawable/cubein_00034.png b/res/drawable/cubein_00034.png Binary files differnew file mode 100644 index 000000000..1662df8dc --- /dev/null +++ b/res/drawable/cubein_00034.png diff --git a/res/drawable/cubein_00035.png b/res/drawable/cubein_00035.png Binary files differnew file mode 100644 index 000000000..1662df8dc --- /dev/null +++ b/res/drawable/cubein_00035.png diff --git a/res/drawable/cubein_00036.png b/res/drawable/cubein_00036.png Binary files differnew file mode 100644 index 000000000..1662df8dc --- /dev/null +++ b/res/drawable/cubein_00036.png diff --git a/res/drawable/cubein_00037.png b/res/drawable/cubein_00037.png Binary files differnew file mode 100644 index 000000000..1662df8dc --- /dev/null +++ b/res/drawable/cubein_00037.png diff --git a/res/drawable/cubein_00038.png b/res/drawable/cubein_00038.png Binary files differnew file mode 100644 index 000000000..1662df8dc --- /dev/null +++ b/res/drawable/cubein_00038.png diff --git a/res/drawable/cubein_00039.png b/res/drawable/cubein_00039.png Binary files differnew file mode 100644 index 000000000..1662df8dc --- /dev/null +++ b/res/drawable/cubein_00039.png diff --git a/res/drawable/cubein_00040.png b/res/drawable/cubein_00040.png Binary files differnew file mode 100644 index 000000000..1662df8dc --- /dev/null +++ b/res/drawable/cubein_00040.png diff --git a/res/drawable/cubein_00041.png b/res/drawable/cubein_00041.png Binary files differnew file mode 100644 index 000000000..1662df8dc --- /dev/null +++ b/res/drawable/cubein_00041.png diff --git a/res/drawable/cubein_00042.png b/res/drawable/cubein_00042.png Binary files differnew file mode 100644 index 000000000..1662df8dc --- /dev/null +++ b/res/drawable/cubein_00042.png diff --git a/res/drawable/cubein_00043.png b/res/drawable/cubein_00043.png Binary files differnew file mode 100644 index 000000000..1662df8dc --- /dev/null +++ b/res/drawable/cubein_00043.png diff --git a/res/drawable/cubein_00044.png b/res/drawable/cubein_00044.png Binary files differnew file mode 100644 index 000000000..1662df8dc --- /dev/null +++ b/res/drawable/cubein_00044.png diff --git a/res/drawable/cubein_00045.png b/res/drawable/cubein_00045.png Binary files differnew file mode 100644 index 000000000..1662df8dc --- /dev/null +++ b/res/drawable/cubein_00045.png diff --git a/res/drawable/cubein_00046.png b/res/drawable/cubein_00046.png Binary files differnew file mode 100644 index 000000000..1662df8dc --- /dev/null +++ b/res/drawable/cubein_00046.png diff --git a/res/drawable/cubein_00047.png b/res/drawable/cubein_00047.png Binary files differnew file mode 100644 index 000000000..1662df8dc --- /dev/null +++ b/res/drawable/cubein_00047.png diff --git a/res/drawable/cubein_00048.png b/res/drawable/cubein_00048.png Binary files differnew file mode 100644 index 000000000..1662df8dc --- /dev/null +++ b/res/drawable/cubein_00048.png diff --git a/res/drawable/cubein_00049.png b/res/drawable/cubein_00049.png Binary files differnew file mode 100644 index 000000000..1662df8dc --- /dev/null +++ b/res/drawable/cubein_00049.png diff --git a/res/drawable/cubeout_00000.png b/res/drawable/cubeout_00000.png Binary files differnew file mode 100644 index 000000000..d444d1318 --- /dev/null +++ b/res/drawable/cubeout_00000.png diff --git a/res/drawable/cubeout_00001.png b/res/drawable/cubeout_00001.png Binary files differnew file mode 100644 index 000000000..69b57487c --- /dev/null +++ b/res/drawable/cubeout_00001.png diff --git a/res/drawable/cubeout_00002.png b/res/drawable/cubeout_00002.png Binary files differnew file mode 100644 index 000000000..58f4191ae --- /dev/null +++ b/res/drawable/cubeout_00002.png diff --git a/res/drawable/cubeout_00003.png b/res/drawable/cubeout_00003.png Binary files differnew file mode 100644 index 000000000..096771ec5 --- /dev/null +++ b/res/drawable/cubeout_00003.png diff --git a/res/drawable/cubeout_00004.png b/res/drawable/cubeout_00004.png Binary files differnew file mode 100644 index 000000000..2d027ffa5 --- /dev/null +++ b/res/drawable/cubeout_00004.png diff --git a/res/drawable/cubeout_00005.png b/res/drawable/cubeout_00005.png Binary files differnew file mode 100644 index 000000000..bc3876565 --- /dev/null +++ b/res/drawable/cubeout_00005.png diff --git a/res/drawable/cubeout_00006.png b/res/drawable/cubeout_00006.png Binary files differnew file mode 100644 index 000000000..742bebd0e --- /dev/null +++ b/res/drawable/cubeout_00006.png diff --git a/res/drawable/cubeout_00007.png b/res/drawable/cubeout_00007.png Binary files differnew file mode 100644 index 000000000..ec7b63326 --- /dev/null +++ b/res/drawable/cubeout_00007.png diff --git a/res/drawable/cubeout_00008.png b/res/drawable/cubeout_00008.png Binary files differnew file mode 100644 index 000000000..5eb601422 --- /dev/null +++ b/res/drawable/cubeout_00008.png diff --git a/res/drawable/cubeout_00009.png b/res/drawable/cubeout_00009.png Binary files differnew file mode 100644 index 000000000..30559fb95 --- /dev/null +++ b/res/drawable/cubeout_00009.png diff --git a/res/drawable/cubeout_00010.png b/res/drawable/cubeout_00010.png Binary files differnew file mode 100644 index 000000000..fa8b785fd --- /dev/null +++ b/res/drawable/cubeout_00010.png diff --git a/res/drawable/cubeout_00011.png b/res/drawable/cubeout_00011.png Binary files differnew file mode 100644 index 000000000..9de04f3e3 --- /dev/null +++ b/res/drawable/cubeout_00011.png diff --git a/res/drawable/cubeout_00012.png b/res/drawable/cubeout_00012.png Binary files differnew file mode 100644 index 000000000..343901380 --- /dev/null +++ b/res/drawable/cubeout_00012.png diff --git a/res/drawable/cubeout_00013.png b/res/drawable/cubeout_00013.png Binary files differnew file mode 100644 index 000000000..4fcd8444c --- /dev/null +++ b/res/drawable/cubeout_00013.png diff --git a/res/drawable/cubeout_00014.png b/res/drawable/cubeout_00014.png Binary files differnew file mode 100644 index 000000000..df3b99369 --- /dev/null +++ b/res/drawable/cubeout_00014.png diff --git a/res/drawable/cubeout_00015.png b/res/drawable/cubeout_00015.png Binary files differnew file mode 100644 index 000000000..b4f910f3c --- /dev/null +++ b/res/drawable/cubeout_00015.png diff --git a/res/drawable/cubeout_00016.png b/res/drawable/cubeout_00016.png Binary files differnew file mode 100644 index 000000000..262e12942 --- /dev/null +++ b/res/drawable/cubeout_00016.png diff --git a/res/drawable/cubeout_00017.png b/res/drawable/cubeout_00017.png Binary files differnew file mode 100644 index 000000000..873146bc3 --- /dev/null +++ b/res/drawable/cubeout_00017.png diff --git a/res/drawable/cubeout_00018.png b/res/drawable/cubeout_00018.png Binary files differnew file mode 100644 index 000000000..2d52f2343 --- /dev/null +++ b/res/drawable/cubeout_00018.png diff --git a/res/drawable/cubeout_00019.png b/res/drawable/cubeout_00019.png Binary files differnew file mode 100644 index 000000000..1b7bff44a --- /dev/null +++ b/res/drawable/cubeout_00019.png diff --git a/res/drawable/cubeout_00020.png b/res/drawable/cubeout_00020.png Binary files differnew file mode 100644 index 000000000..1662df8dc --- /dev/null +++ b/res/drawable/cubeout_00020.png diff --git a/res/drawable/cubeout_00021.png b/res/drawable/cubeout_00021.png Binary files differnew file mode 100644 index 000000000..1662df8dc --- /dev/null +++ b/res/drawable/cubeout_00021.png diff --git a/res/drawable/cubeout_00022.png b/res/drawable/cubeout_00022.png Binary files differnew file mode 100644 index 000000000..1662df8dc --- /dev/null +++ b/res/drawable/cubeout_00022.png diff --git a/res/drawable/cubeout_00023.png b/res/drawable/cubeout_00023.png Binary files differnew file mode 100644 index 000000000..1662df8dc --- /dev/null +++ b/res/drawable/cubeout_00023.png diff --git a/res/drawable/cubeout_00024.png b/res/drawable/cubeout_00024.png Binary files differnew file mode 100644 index 000000000..1662df8dc --- /dev/null +++ b/res/drawable/cubeout_00024.png diff --git a/res/drawable/cubeout_00025.png b/res/drawable/cubeout_00025.png Binary files differnew file mode 100644 index 000000000..1662df8dc --- /dev/null +++ b/res/drawable/cubeout_00025.png diff --git a/res/drawable/cubeout_00026.png b/res/drawable/cubeout_00026.png Binary files differnew file mode 100644 index 000000000..1662df8dc --- /dev/null +++ b/res/drawable/cubeout_00026.png diff --git a/res/drawable/cubeout_00027.png b/res/drawable/cubeout_00027.png Binary files differnew file mode 100644 index 000000000..1662df8dc --- /dev/null +++ b/res/drawable/cubeout_00027.png diff --git a/res/drawable/cubeout_00028.png b/res/drawable/cubeout_00028.png Binary files differnew file mode 100644 index 000000000..1662df8dc --- /dev/null +++ b/res/drawable/cubeout_00028.png diff --git a/res/drawable/cubeout_00029.png b/res/drawable/cubeout_00029.png Binary files differnew file mode 100644 index 000000000..1662df8dc --- /dev/null +++ b/res/drawable/cubeout_00029.png diff --git a/res/drawable/cubeout_00030.png b/res/drawable/cubeout_00030.png Binary files differnew file mode 100644 index 000000000..1662df8dc --- /dev/null +++ b/res/drawable/cubeout_00030.png diff --git a/res/drawable/cubeout_00031.png b/res/drawable/cubeout_00031.png Binary files differnew file mode 100644 index 000000000..1662df8dc --- /dev/null +++ b/res/drawable/cubeout_00031.png diff --git a/res/drawable/cubeout_00032.png b/res/drawable/cubeout_00032.png Binary files differnew file mode 100644 index 000000000..1662df8dc --- /dev/null +++ b/res/drawable/cubeout_00032.png diff --git a/res/drawable/cubeout_00033.png b/res/drawable/cubeout_00033.png Binary files differnew file mode 100644 index 000000000..1662df8dc --- /dev/null +++ b/res/drawable/cubeout_00033.png diff --git a/res/drawable/cubeout_00034.png b/res/drawable/cubeout_00034.png Binary files differnew file mode 100644 index 000000000..1662df8dc --- /dev/null +++ b/res/drawable/cubeout_00034.png diff --git a/res/drawable/cubeout_00035.png b/res/drawable/cubeout_00035.png Binary files differnew file mode 100644 index 000000000..1662df8dc --- /dev/null +++ b/res/drawable/cubeout_00035.png diff --git a/res/drawable/cubeout_00036.png b/res/drawable/cubeout_00036.png Binary files differnew file mode 100644 index 000000000..1662df8dc --- /dev/null +++ b/res/drawable/cubeout_00036.png diff --git a/res/drawable/cubeout_00037.png b/res/drawable/cubeout_00037.png Binary files differnew file mode 100644 index 000000000..1662df8dc --- /dev/null +++ b/res/drawable/cubeout_00037.png diff --git a/res/drawable/cubeout_00038.png b/res/drawable/cubeout_00038.png Binary files differnew file mode 100644 index 000000000..1662df8dc --- /dev/null +++ b/res/drawable/cubeout_00038.png diff --git a/res/drawable/cubeout_00039.png b/res/drawable/cubeout_00039.png Binary files differnew file mode 100644 index 000000000..1662df8dc --- /dev/null +++ b/res/drawable/cubeout_00039.png diff --git a/res/drawable/cubeout_00040.png b/res/drawable/cubeout_00040.png Binary files differnew file mode 100644 index 000000000..1662df8dc --- /dev/null +++ b/res/drawable/cubeout_00040.png diff --git a/res/drawable/cubeout_00041.png b/res/drawable/cubeout_00041.png Binary files differnew file mode 100644 index 000000000..1662df8dc --- /dev/null +++ b/res/drawable/cubeout_00041.png diff --git a/res/drawable/cubeout_00042.png b/res/drawable/cubeout_00042.png Binary files differnew file mode 100644 index 000000000..1662df8dc --- /dev/null +++ b/res/drawable/cubeout_00042.png diff --git a/res/drawable/cubeout_00043.png b/res/drawable/cubeout_00043.png Binary files differnew file mode 100644 index 000000000..1662df8dc --- /dev/null +++ b/res/drawable/cubeout_00043.png diff --git a/res/drawable/cubeout_00044.png b/res/drawable/cubeout_00044.png Binary files differnew file mode 100644 index 000000000..1662df8dc --- /dev/null +++ b/res/drawable/cubeout_00044.png diff --git a/res/drawable/cubeout_00045.png b/res/drawable/cubeout_00045.png Binary files differnew file mode 100644 index 000000000..1662df8dc --- /dev/null +++ b/res/drawable/cubeout_00045.png diff --git a/res/drawable/cubeout_00046.png b/res/drawable/cubeout_00046.png Binary files differnew file mode 100644 index 000000000..1662df8dc --- /dev/null +++ b/res/drawable/cubeout_00046.png diff --git a/res/drawable/cubeout_00047.png b/res/drawable/cubeout_00047.png Binary files differnew file mode 100644 index 000000000..1662df8dc --- /dev/null +++ b/res/drawable/cubeout_00047.png diff --git a/res/drawable/cubeout_00048.png b/res/drawable/cubeout_00048.png Binary files differnew file mode 100644 index 000000000..1662df8dc --- /dev/null +++ b/res/drawable/cubeout_00048.png diff --git a/res/drawable/cubeout_00049.png b/res/drawable/cubeout_00049.png Binary files differnew file mode 100644 index 000000000..1662df8dc --- /dev/null +++ b/res/drawable/cubeout_00049.png diff --git a/res/drawable/cylinderin_00000.png b/res/drawable/cylinderin_00000.png Binary files differnew file mode 100644 index 000000000..c5eeb55a0 --- /dev/null +++ b/res/drawable/cylinderin_00000.png diff --git a/res/drawable/cylinderin_00001.png b/res/drawable/cylinderin_00001.png Binary files differnew file mode 100644 index 000000000..bfc597a49 --- /dev/null +++ b/res/drawable/cylinderin_00001.png diff --git a/res/drawable/cylinderin_00002.png b/res/drawable/cylinderin_00002.png Binary files differnew file mode 100644 index 000000000..88114b7e2 --- /dev/null +++ b/res/drawable/cylinderin_00002.png diff --git a/res/drawable/cylinderin_00003.png b/res/drawable/cylinderin_00003.png Binary files differnew file mode 100644 index 000000000..fe24f3f22 --- /dev/null +++ b/res/drawable/cylinderin_00003.png diff --git a/res/drawable/cylinderin_00004.png b/res/drawable/cylinderin_00004.png Binary files differnew file mode 100644 index 000000000..c3a655b23 --- /dev/null +++ b/res/drawable/cylinderin_00004.png diff --git a/res/drawable/cylinderin_00005.png b/res/drawable/cylinderin_00005.png Binary files differnew file mode 100644 index 000000000..e34b658e8 --- /dev/null +++ b/res/drawable/cylinderin_00005.png diff --git a/res/drawable/cylinderin_00006.png b/res/drawable/cylinderin_00006.png Binary files differnew file mode 100644 index 000000000..7f4d7b9db --- /dev/null +++ b/res/drawable/cylinderin_00006.png diff --git a/res/drawable/cylinderin_00007.png b/res/drawable/cylinderin_00007.png Binary files differnew file mode 100644 index 000000000..bef4a2d11 --- /dev/null +++ b/res/drawable/cylinderin_00007.png diff --git a/res/drawable/cylinderin_00008.png b/res/drawable/cylinderin_00008.png Binary files differnew file mode 100644 index 000000000..3ed252efa --- /dev/null +++ b/res/drawable/cylinderin_00008.png diff --git a/res/drawable/cylinderin_00009.png b/res/drawable/cylinderin_00009.png Binary files differnew file mode 100644 index 000000000..6b47c400e --- /dev/null +++ b/res/drawable/cylinderin_00009.png diff --git a/res/drawable/cylinderin_00010.png b/res/drawable/cylinderin_00010.png Binary files differnew file mode 100644 index 000000000..5ffd650ed --- /dev/null +++ b/res/drawable/cylinderin_00010.png diff --git a/res/drawable/cylinderin_00011.png b/res/drawable/cylinderin_00011.png Binary files differnew file mode 100644 index 000000000..f6ad8cc80 --- /dev/null +++ b/res/drawable/cylinderin_00011.png diff --git a/res/drawable/cylinderin_00012.png b/res/drawable/cylinderin_00012.png Binary files differnew file mode 100644 index 000000000..27c7d6945 --- /dev/null +++ b/res/drawable/cylinderin_00012.png diff --git a/res/drawable/cylinderin_00013.png b/res/drawable/cylinderin_00013.png Binary files differnew file mode 100644 index 000000000..a78a4359d --- /dev/null +++ b/res/drawable/cylinderin_00013.png diff --git a/res/drawable/cylinderin_00014.png b/res/drawable/cylinderin_00014.png Binary files differnew file mode 100644 index 000000000..4eda97009 --- /dev/null +++ b/res/drawable/cylinderin_00014.png diff --git a/res/drawable/cylinderin_00015.png b/res/drawable/cylinderin_00015.png Binary files differnew file mode 100644 index 000000000..e3ddc7e98 --- /dev/null +++ b/res/drawable/cylinderin_00015.png diff --git a/res/drawable/cylinderin_00016.png b/res/drawable/cylinderin_00016.png Binary files differnew file mode 100644 index 000000000..eb48e294c --- /dev/null +++ b/res/drawable/cylinderin_00016.png diff --git a/res/drawable/cylinderin_00017.png b/res/drawable/cylinderin_00017.png Binary files differnew file mode 100644 index 000000000..fb7b3aff9 --- /dev/null +++ b/res/drawable/cylinderin_00017.png diff --git a/res/drawable/cylinderin_00018.png b/res/drawable/cylinderin_00018.png Binary files differnew file mode 100644 index 000000000..5c73e4d98 --- /dev/null +++ b/res/drawable/cylinderin_00018.png diff --git a/res/drawable/cylinderin_00019.png b/res/drawable/cylinderin_00019.png Binary files differnew file mode 100644 index 000000000..967423915 --- /dev/null +++ b/res/drawable/cylinderin_00019.png diff --git a/res/drawable/cylinderin_00020.png b/res/drawable/cylinderin_00020.png Binary files differnew file mode 100644 index 000000000..c5eeb55a0 --- /dev/null +++ b/res/drawable/cylinderin_00020.png diff --git a/res/drawable/cylinderin_00021.png b/res/drawable/cylinderin_00021.png Binary files differnew file mode 100644 index 000000000..c5eeb55a0 --- /dev/null +++ b/res/drawable/cylinderin_00021.png diff --git a/res/drawable/cylinderin_00022.png b/res/drawable/cylinderin_00022.png Binary files differnew file mode 100644 index 000000000..c5eeb55a0 --- /dev/null +++ b/res/drawable/cylinderin_00022.png diff --git a/res/drawable/cylinderin_00023.png b/res/drawable/cylinderin_00023.png Binary files differnew file mode 100644 index 000000000..c5eeb55a0 --- /dev/null +++ b/res/drawable/cylinderin_00023.png diff --git a/res/drawable/cylinderin_00024.png b/res/drawable/cylinderin_00024.png Binary files differnew file mode 100644 index 000000000..c5eeb55a0 --- /dev/null +++ b/res/drawable/cylinderin_00024.png diff --git a/res/drawable/cylinderin_00025.png b/res/drawable/cylinderin_00025.png Binary files differnew file mode 100644 index 000000000..c5eeb55a0 --- /dev/null +++ b/res/drawable/cylinderin_00025.png diff --git a/res/drawable/cylinderin_00026.png b/res/drawable/cylinderin_00026.png Binary files differnew file mode 100644 index 000000000..c5eeb55a0 --- /dev/null +++ b/res/drawable/cylinderin_00026.png diff --git a/res/drawable/cylinderin_00027.png b/res/drawable/cylinderin_00027.png Binary files differnew file mode 100644 index 000000000..c5eeb55a0 --- /dev/null +++ b/res/drawable/cylinderin_00027.png diff --git a/res/drawable/cylinderin_00028.png b/res/drawable/cylinderin_00028.png Binary files differnew file mode 100644 index 000000000..c5eeb55a0 --- /dev/null +++ b/res/drawable/cylinderin_00028.png diff --git a/res/drawable/cylinderin_00029.png b/res/drawable/cylinderin_00029.png Binary files differnew file mode 100644 index 000000000..c5eeb55a0 --- /dev/null +++ b/res/drawable/cylinderin_00029.png diff --git a/res/drawable/cylinderin_00030.png b/res/drawable/cylinderin_00030.png Binary files differnew file mode 100644 index 000000000..c5eeb55a0 --- /dev/null +++ b/res/drawable/cylinderin_00030.png diff --git a/res/drawable/cylinderin_00031.png b/res/drawable/cylinderin_00031.png Binary files differnew file mode 100644 index 000000000..c5eeb55a0 --- /dev/null +++ b/res/drawable/cylinderin_00031.png diff --git a/res/drawable/cylinderin_00032.png b/res/drawable/cylinderin_00032.png Binary files differnew file mode 100644 index 000000000..c5eeb55a0 --- /dev/null +++ b/res/drawable/cylinderin_00032.png diff --git a/res/drawable/cylinderin_00033.png b/res/drawable/cylinderin_00033.png Binary files differnew file mode 100644 index 000000000..c5eeb55a0 --- /dev/null +++ b/res/drawable/cylinderin_00033.png diff --git a/res/drawable/cylinderin_00034.png b/res/drawable/cylinderin_00034.png Binary files differnew file mode 100644 index 000000000..c5eeb55a0 --- /dev/null +++ b/res/drawable/cylinderin_00034.png diff --git a/res/drawable/cylinderin_00035.png b/res/drawable/cylinderin_00035.png Binary files differnew file mode 100644 index 000000000..c5eeb55a0 --- /dev/null +++ b/res/drawable/cylinderin_00035.png diff --git a/res/drawable/cylinderin_00036.png b/res/drawable/cylinderin_00036.png Binary files differnew file mode 100644 index 000000000..c5eeb55a0 --- /dev/null +++ b/res/drawable/cylinderin_00036.png diff --git a/res/drawable/cylinderin_00037.png b/res/drawable/cylinderin_00037.png Binary files differnew file mode 100644 index 000000000..c5eeb55a0 --- /dev/null +++ b/res/drawable/cylinderin_00037.png diff --git a/res/drawable/cylinderin_00038.png b/res/drawable/cylinderin_00038.png Binary files differnew file mode 100644 index 000000000..c5eeb55a0 --- /dev/null +++ b/res/drawable/cylinderin_00038.png diff --git a/res/drawable/cylinderin_00039.png b/res/drawable/cylinderin_00039.png Binary files differnew file mode 100644 index 000000000..c5eeb55a0 --- /dev/null +++ b/res/drawable/cylinderin_00039.png diff --git a/res/drawable/cylinderin_00040.png b/res/drawable/cylinderin_00040.png Binary files differnew file mode 100644 index 000000000..c5eeb55a0 --- /dev/null +++ b/res/drawable/cylinderin_00040.png diff --git a/res/drawable/cylinderin_00041.png b/res/drawable/cylinderin_00041.png Binary files differnew file mode 100644 index 000000000..c5eeb55a0 --- /dev/null +++ b/res/drawable/cylinderin_00041.png diff --git a/res/drawable/cylinderin_00042.png b/res/drawable/cylinderin_00042.png Binary files differnew file mode 100644 index 000000000..c5eeb55a0 --- /dev/null +++ b/res/drawable/cylinderin_00042.png diff --git a/res/drawable/cylinderin_00043.png b/res/drawable/cylinderin_00043.png Binary files differnew file mode 100644 index 000000000..c5eeb55a0 --- /dev/null +++ b/res/drawable/cylinderin_00043.png diff --git a/res/drawable/cylinderin_00044.png b/res/drawable/cylinderin_00044.png Binary files differnew file mode 100644 index 000000000..c5eeb55a0 --- /dev/null +++ b/res/drawable/cylinderin_00044.png diff --git a/res/drawable/cylinderin_00045.png b/res/drawable/cylinderin_00045.png Binary files differnew file mode 100644 index 000000000..c5eeb55a0 --- /dev/null +++ b/res/drawable/cylinderin_00045.png diff --git a/res/drawable/cylinderin_00046.png b/res/drawable/cylinderin_00046.png Binary files differnew file mode 100644 index 000000000..c5eeb55a0 --- /dev/null +++ b/res/drawable/cylinderin_00046.png diff --git a/res/drawable/cylinderin_00047.png b/res/drawable/cylinderin_00047.png Binary files differnew file mode 100644 index 000000000..c5eeb55a0 --- /dev/null +++ b/res/drawable/cylinderin_00047.png diff --git a/res/drawable/cylinderin_00048.png b/res/drawable/cylinderin_00048.png Binary files differnew file mode 100644 index 000000000..c5eeb55a0 --- /dev/null +++ b/res/drawable/cylinderin_00048.png diff --git a/res/drawable/cylinderin_00049.png b/res/drawable/cylinderin_00049.png Binary files differnew file mode 100644 index 000000000..c5eeb55a0 --- /dev/null +++ b/res/drawable/cylinderin_00049.png diff --git a/res/drawable/cylinderout_00000.png b/res/drawable/cylinderout_00000.png Binary files differnew file mode 100644 index 000000000..d53161c2b --- /dev/null +++ b/res/drawable/cylinderout_00000.png diff --git a/res/drawable/cylinderout_00001.png b/res/drawable/cylinderout_00001.png Binary files differnew file mode 100644 index 000000000..ba768d300 --- /dev/null +++ b/res/drawable/cylinderout_00001.png diff --git a/res/drawable/cylinderout_00002.png b/res/drawable/cylinderout_00002.png Binary files differnew file mode 100644 index 000000000..c753c3b02 --- /dev/null +++ b/res/drawable/cylinderout_00002.png diff --git a/res/drawable/cylinderout_00003.png b/res/drawable/cylinderout_00003.png Binary files differnew file mode 100644 index 000000000..903d16029 --- /dev/null +++ b/res/drawable/cylinderout_00003.png diff --git a/res/drawable/cylinderout_00004.png b/res/drawable/cylinderout_00004.png Binary files differnew file mode 100644 index 000000000..803ba23be --- /dev/null +++ b/res/drawable/cylinderout_00004.png diff --git a/res/drawable/cylinderout_00005.png b/res/drawable/cylinderout_00005.png Binary files differnew file mode 100644 index 000000000..ccfb96d48 --- /dev/null +++ b/res/drawable/cylinderout_00005.png diff --git a/res/drawable/cylinderout_00006.png b/res/drawable/cylinderout_00006.png Binary files differnew file mode 100644 index 000000000..1b7a4c899 --- /dev/null +++ b/res/drawable/cylinderout_00006.png diff --git a/res/drawable/cylinderout_00007.png b/res/drawable/cylinderout_00007.png Binary files differnew file mode 100644 index 000000000..5366845fa --- /dev/null +++ b/res/drawable/cylinderout_00007.png diff --git a/res/drawable/cylinderout_00008.png b/res/drawable/cylinderout_00008.png Binary files differnew file mode 100644 index 000000000..325574a27 --- /dev/null +++ b/res/drawable/cylinderout_00008.png diff --git a/res/drawable/cylinderout_00009.png b/res/drawable/cylinderout_00009.png Binary files differnew file mode 100644 index 000000000..9280ff34b --- /dev/null +++ b/res/drawable/cylinderout_00009.png diff --git a/res/drawable/cylinderout_00010.png b/res/drawable/cylinderout_00010.png Binary files differnew file mode 100644 index 000000000..f667a3261 --- /dev/null +++ b/res/drawable/cylinderout_00010.png diff --git a/res/drawable/cylinderout_00011.png b/res/drawable/cylinderout_00011.png Binary files differnew file mode 100644 index 000000000..8d38ecf7e --- /dev/null +++ b/res/drawable/cylinderout_00011.png diff --git a/res/drawable/cylinderout_00012.png b/res/drawable/cylinderout_00012.png Binary files differnew file mode 100644 index 000000000..80359d12a --- /dev/null +++ b/res/drawable/cylinderout_00012.png diff --git a/res/drawable/cylinderout_00013.png b/res/drawable/cylinderout_00013.png Binary files differnew file mode 100644 index 000000000..087953e6c --- /dev/null +++ b/res/drawable/cylinderout_00013.png diff --git a/res/drawable/cylinderout_00014.png b/res/drawable/cylinderout_00014.png Binary files differnew file mode 100644 index 000000000..083009a08 --- /dev/null +++ b/res/drawable/cylinderout_00014.png diff --git a/res/drawable/cylinderout_00015.png b/res/drawable/cylinderout_00015.png Binary files differnew file mode 100644 index 000000000..c5cfb7eb9 --- /dev/null +++ b/res/drawable/cylinderout_00015.png diff --git a/res/drawable/cylinderout_00016.png b/res/drawable/cylinderout_00016.png Binary files differnew file mode 100644 index 000000000..c1e9eea70 --- /dev/null +++ b/res/drawable/cylinderout_00016.png diff --git a/res/drawable/cylinderout_00017.png b/res/drawable/cylinderout_00017.png Binary files differnew file mode 100644 index 000000000..cca8ec06e --- /dev/null +++ b/res/drawable/cylinderout_00017.png diff --git a/res/drawable/cylinderout_00018.png b/res/drawable/cylinderout_00018.png Binary files differnew file mode 100644 index 000000000..13c2a8ce6 --- /dev/null +++ b/res/drawable/cylinderout_00018.png diff --git a/res/drawable/cylinderout_00019.png b/res/drawable/cylinderout_00019.png Binary files differnew file mode 100644 index 000000000..3e806b910 --- /dev/null +++ b/res/drawable/cylinderout_00019.png diff --git a/res/drawable/cylinderout_00020.png b/res/drawable/cylinderout_00020.png Binary files differnew file mode 100644 index 000000000..d53161c2b --- /dev/null +++ b/res/drawable/cylinderout_00020.png diff --git a/res/drawable/cylinderout_00021.png b/res/drawable/cylinderout_00021.png Binary files differnew file mode 100644 index 000000000..d53161c2b --- /dev/null +++ b/res/drawable/cylinderout_00021.png diff --git a/res/drawable/cylinderout_00022.png b/res/drawable/cylinderout_00022.png Binary files differnew file mode 100644 index 000000000..d53161c2b --- /dev/null +++ b/res/drawable/cylinderout_00022.png diff --git a/res/drawable/cylinderout_00023.png b/res/drawable/cylinderout_00023.png Binary files differnew file mode 100644 index 000000000..d53161c2b --- /dev/null +++ b/res/drawable/cylinderout_00023.png diff --git a/res/drawable/cylinderout_00024.png b/res/drawable/cylinderout_00024.png Binary files differnew file mode 100644 index 000000000..d53161c2b --- /dev/null +++ b/res/drawable/cylinderout_00024.png diff --git a/res/drawable/cylinderout_00025.png b/res/drawable/cylinderout_00025.png Binary files differnew file mode 100644 index 000000000..d53161c2b --- /dev/null +++ b/res/drawable/cylinderout_00025.png diff --git a/res/drawable/cylinderout_00026.png b/res/drawable/cylinderout_00026.png Binary files differnew file mode 100644 index 000000000..d53161c2b --- /dev/null +++ b/res/drawable/cylinderout_00026.png diff --git a/res/drawable/cylinderout_00027.png b/res/drawable/cylinderout_00027.png Binary files differnew file mode 100644 index 000000000..d53161c2b --- /dev/null +++ b/res/drawable/cylinderout_00027.png diff --git a/res/drawable/cylinderout_00028.png b/res/drawable/cylinderout_00028.png Binary files differnew file mode 100644 index 000000000..d53161c2b --- /dev/null +++ b/res/drawable/cylinderout_00028.png diff --git a/res/drawable/cylinderout_00029.png b/res/drawable/cylinderout_00029.png Binary files differnew file mode 100644 index 000000000..d53161c2b --- /dev/null +++ b/res/drawable/cylinderout_00029.png diff --git a/res/drawable/cylinderout_00030.png b/res/drawable/cylinderout_00030.png Binary files differnew file mode 100644 index 000000000..d53161c2b --- /dev/null +++ b/res/drawable/cylinderout_00030.png diff --git a/res/drawable/cylinderout_00031.png b/res/drawable/cylinderout_00031.png Binary files differnew file mode 100644 index 000000000..d53161c2b --- /dev/null +++ b/res/drawable/cylinderout_00031.png diff --git a/res/drawable/cylinderout_00032.png b/res/drawable/cylinderout_00032.png Binary files differnew file mode 100644 index 000000000..d53161c2b --- /dev/null +++ b/res/drawable/cylinderout_00032.png diff --git a/res/drawable/cylinderout_00033.png b/res/drawable/cylinderout_00033.png Binary files differnew file mode 100644 index 000000000..d53161c2b --- /dev/null +++ b/res/drawable/cylinderout_00033.png diff --git a/res/drawable/cylinderout_00034.png b/res/drawable/cylinderout_00034.png Binary files differnew file mode 100644 index 000000000..d53161c2b --- /dev/null +++ b/res/drawable/cylinderout_00034.png diff --git a/res/drawable/cylinderout_00035.png b/res/drawable/cylinderout_00035.png Binary files differnew file mode 100644 index 000000000..d53161c2b --- /dev/null +++ b/res/drawable/cylinderout_00035.png diff --git a/res/drawable/cylinderout_00036.png b/res/drawable/cylinderout_00036.png Binary files differnew file mode 100644 index 000000000..d53161c2b --- /dev/null +++ b/res/drawable/cylinderout_00036.png diff --git a/res/drawable/cylinderout_00037.png b/res/drawable/cylinderout_00037.png Binary files differnew file mode 100644 index 000000000..d53161c2b --- /dev/null +++ b/res/drawable/cylinderout_00037.png diff --git a/res/drawable/cylinderout_00038.png b/res/drawable/cylinderout_00038.png Binary files differnew file mode 100644 index 000000000..d53161c2b --- /dev/null +++ b/res/drawable/cylinderout_00038.png diff --git a/res/drawable/cylinderout_00039.png b/res/drawable/cylinderout_00039.png Binary files differnew file mode 100644 index 000000000..d53161c2b --- /dev/null +++ b/res/drawable/cylinderout_00039.png diff --git a/res/drawable/cylinderout_00040.png b/res/drawable/cylinderout_00040.png Binary files differnew file mode 100644 index 000000000..d53161c2b --- /dev/null +++ b/res/drawable/cylinderout_00040.png diff --git a/res/drawable/cylinderout_00041.png b/res/drawable/cylinderout_00041.png Binary files differnew file mode 100644 index 000000000..d53161c2b --- /dev/null +++ b/res/drawable/cylinderout_00041.png diff --git a/res/drawable/cylinderout_00042.png b/res/drawable/cylinderout_00042.png Binary files differnew file mode 100644 index 000000000..d53161c2b --- /dev/null +++ b/res/drawable/cylinderout_00042.png diff --git a/res/drawable/cylinderout_00043.png b/res/drawable/cylinderout_00043.png Binary files differnew file mode 100644 index 000000000..d53161c2b --- /dev/null +++ b/res/drawable/cylinderout_00043.png diff --git a/res/drawable/cylinderout_00044.png b/res/drawable/cylinderout_00044.png Binary files differnew file mode 100644 index 000000000..d53161c2b --- /dev/null +++ b/res/drawable/cylinderout_00044.png diff --git a/res/drawable/cylinderout_00045.png b/res/drawable/cylinderout_00045.png Binary files differnew file mode 100644 index 000000000..d53161c2b --- /dev/null +++ b/res/drawable/cylinderout_00045.png diff --git a/res/drawable/cylinderout_00046.png b/res/drawable/cylinderout_00046.png Binary files differnew file mode 100644 index 000000000..d53161c2b --- /dev/null +++ b/res/drawable/cylinderout_00046.png diff --git a/res/drawable/cylinderout_00047.png b/res/drawable/cylinderout_00047.png Binary files differnew file mode 100644 index 000000000..d53161c2b --- /dev/null +++ b/res/drawable/cylinderout_00047.png diff --git a/res/drawable/cylinderout_00048.png b/res/drawable/cylinderout_00048.png Binary files differnew file mode 100644 index 000000000..d53161c2b --- /dev/null +++ b/res/drawable/cylinderout_00048.png diff --git a/res/drawable/cylinderout_00049.png b/res/drawable/cylinderout_00049.png Binary files differnew file mode 100644 index 000000000..d53161c2b --- /dev/null +++ b/res/drawable/cylinderout_00049.png diff --git a/res/drawable/flip_00000.png b/res/drawable/flip_00000.png Binary files differnew file mode 100644 index 000000000..cbe7f859b --- /dev/null +++ b/res/drawable/flip_00000.png diff --git a/res/drawable/flip_00001.png b/res/drawable/flip_00001.png Binary files differnew file mode 100644 index 000000000..086511876 --- /dev/null +++ b/res/drawable/flip_00001.png diff --git a/res/drawable/flip_00002.png b/res/drawable/flip_00002.png Binary files differnew file mode 100644 index 000000000..ae9f255f7 --- /dev/null +++ b/res/drawable/flip_00002.png diff --git a/res/drawable/flip_00003.png b/res/drawable/flip_00003.png Binary files differnew file mode 100644 index 000000000..62846c7d1 --- /dev/null +++ b/res/drawable/flip_00003.png diff --git a/res/drawable/flip_00004.png b/res/drawable/flip_00004.png Binary files differnew file mode 100644 index 000000000..ae70cb81b --- /dev/null +++ b/res/drawable/flip_00004.png diff --git a/res/drawable/flip_00005.png b/res/drawable/flip_00005.png Binary files differnew file mode 100644 index 000000000..ccef96be3 --- /dev/null +++ b/res/drawable/flip_00005.png diff --git a/res/drawable/flip_00006.png b/res/drawable/flip_00006.png Binary files differnew file mode 100644 index 000000000..ce8819c6a --- /dev/null +++ b/res/drawable/flip_00006.png diff --git a/res/drawable/flip_00007.png b/res/drawable/flip_00007.png Binary files differnew file mode 100644 index 000000000..b502e2d4a --- /dev/null +++ b/res/drawable/flip_00007.png diff --git a/res/drawable/flip_00008.png b/res/drawable/flip_00008.png Binary files differnew file mode 100644 index 000000000..bfaae1d36 --- /dev/null +++ b/res/drawable/flip_00008.png diff --git a/res/drawable/flip_00009.png b/res/drawable/flip_00009.png Binary files differnew file mode 100644 index 000000000..f974cd4c6 --- /dev/null +++ b/res/drawable/flip_00009.png diff --git a/res/drawable/flip_00010.png b/res/drawable/flip_00010.png Binary files differnew file mode 100644 index 000000000..9b298a83f --- /dev/null +++ b/res/drawable/flip_00010.png diff --git a/res/drawable/flip_00011.png b/res/drawable/flip_00011.png Binary files differnew file mode 100644 index 000000000..27accf584 --- /dev/null +++ b/res/drawable/flip_00011.png diff --git a/res/drawable/flip_00012.png b/res/drawable/flip_00012.png Binary files differnew file mode 100644 index 000000000..48f3d37b4 --- /dev/null +++ b/res/drawable/flip_00012.png diff --git a/res/drawable/flip_00013.png b/res/drawable/flip_00013.png Binary files differnew file mode 100644 index 000000000..ed3273f80 --- /dev/null +++ b/res/drawable/flip_00013.png diff --git a/res/drawable/flip_00014.png b/res/drawable/flip_00014.png Binary files differnew file mode 100644 index 000000000..24cfa1787 --- /dev/null +++ b/res/drawable/flip_00014.png diff --git a/res/drawable/flip_00015.png b/res/drawable/flip_00015.png Binary files differnew file mode 100644 index 000000000..dc8483e48 --- /dev/null +++ b/res/drawable/flip_00015.png diff --git a/res/drawable/flip_00016.png b/res/drawable/flip_00016.png Binary files differnew file mode 100644 index 000000000..c445a5b87 --- /dev/null +++ b/res/drawable/flip_00016.png diff --git a/res/drawable/flip_00017.png b/res/drawable/flip_00017.png Binary files differnew file mode 100644 index 000000000..0d269886a --- /dev/null +++ b/res/drawable/flip_00017.png diff --git a/res/drawable/flip_00018.png b/res/drawable/flip_00018.png Binary files differnew file mode 100644 index 000000000..39762fa11 --- /dev/null +++ b/res/drawable/flip_00018.png diff --git a/res/drawable/flip_00019.png b/res/drawable/flip_00019.png Binary files differnew file mode 100644 index 000000000..02f160ab3 --- /dev/null +++ b/res/drawable/flip_00019.png diff --git a/res/drawable/flip_00020.png b/res/drawable/flip_00020.png Binary files differnew file mode 100644 index 000000000..cbe7f859b --- /dev/null +++ b/res/drawable/flip_00020.png diff --git a/res/drawable/flip_00021.png b/res/drawable/flip_00021.png Binary files differnew file mode 100644 index 000000000..cbe7f859b --- /dev/null +++ b/res/drawable/flip_00021.png diff --git a/res/drawable/flip_00022.png b/res/drawable/flip_00022.png Binary files differnew file mode 100644 index 000000000..cbe7f859b --- /dev/null +++ b/res/drawable/flip_00022.png diff --git a/res/drawable/flip_00023.png b/res/drawable/flip_00023.png Binary files differnew file mode 100644 index 000000000..cbe7f859b --- /dev/null +++ b/res/drawable/flip_00023.png diff --git a/res/drawable/flip_00024.png b/res/drawable/flip_00024.png Binary files differnew file mode 100644 index 000000000..cbe7f859b --- /dev/null +++ b/res/drawable/flip_00024.png diff --git a/res/drawable/flip_00025.png b/res/drawable/flip_00025.png Binary files differnew file mode 100644 index 000000000..cbe7f859b --- /dev/null +++ b/res/drawable/flip_00025.png diff --git a/res/drawable/flip_00026.png b/res/drawable/flip_00026.png Binary files differnew file mode 100644 index 000000000..cbe7f859b --- /dev/null +++ b/res/drawable/flip_00026.png diff --git a/res/drawable/flip_00027.png b/res/drawable/flip_00027.png Binary files differnew file mode 100644 index 000000000..cbe7f859b --- /dev/null +++ b/res/drawable/flip_00027.png diff --git a/res/drawable/flip_00028.png b/res/drawable/flip_00028.png Binary files differnew file mode 100644 index 000000000..cbe7f859b --- /dev/null +++ b/res/drawable/flip_00028.png diff --git a/res/drawable/flip_00029.png b/res/drawable/flip_00029.png Binary files differnew file mode 100644 index 000000000..cbe7f859b --- /dev/null +++ b/res/drawable/flip_00029.png diff --git a/res/drawable/flip_00030.png b/res/drawable/flip_00030.png Binary files differnew file mode 100644 index 000000000..cbe7f859b --- /dev/null +++ b/res/drawable/flip_00030.png diff --git a/res/drawable/flip_00031.png b/res/drawable/flip_00031.png Binary files differnew file mode 100644 index 000000000..cbe7f859b --- /dev/null +++ b/res/drawable/flip_00031.png diff --git a/res/drawable/flip_00032.png b/res/drawable/flip_00032.png Binary files differnew file mode 100644 index 000000000..cbe7f859b --- /dev/null +++ b/res/drawable/flip_00032.png diff --git a/res/drawable/flip_00033.png b/res/drawable/flip_00033.png Binary files differnew file mode 100644 index 000000000..cbe7f859b --- /dev/null +++ b/res/drawable/flip_00033.png diff --git a/res/drawable/flip_00034.png b/res/drawable/flip_00034.png Binary files differnew file mode 100644 index 000000000..cbe7f859b --- /dev/null +++ b/res/drawable/flip_00034.png diff --git a/res/drawable/flip_00035.png b/res/drawable/flip_00035.png Binary files differnew file mode 100644 index 000000000..cbe7f859b --- /dev/null +++ b/res/drawable/flip_00035.png diff --git a/res/drawable/flip_00036.png b/res/drawable/flip_00036.png Binary files differnew file mode 100644 index 000000000..cbe7f859b --- /dev/null +++ b/res/drawable/flip_00036.png diff --git a/res/drawable/flip_00037.png b/res/drawable/flip_00037.png Binary files differnew file mode 100644 index 000000000..cbe7f859b --- /dev/null +++ b/res/drawable/flip_00037.png diff --git a/res/drawable/flip_00038.png b/res/drawable/flip_00038.png Binary files differnew file mode 100644 index 000000000..cbe7f859b --- /dev/null +++ b/res/drawable/flip_00038.png diff --git a/res/drawable/flip_00039.png b/res/drawable/flip_00039.png Binary files differnew file mode 100644 index 000000000..cbe7f859b --- /dev/null +++ b/res/drawable/flip_00039.png diff --git a/res/drawable/flip_00040.png b/res/drawable/flip_00040.png Binary files differnew file mode 100644 index 000000000..cbe7f859b --- /dev/null +++ b/res/drawable/flip_00040.png diff --git a/res/drawable/flip_00041.png b/res/drawable/flip_00041.png Binary files differnew file mode 100644 index 000000000..cbe7f859b --- /dev/null +++ b/res/drawable/flip_00041.png diff --git a/res/drawable/flip_00042.png b/res/drawable/flip_00042.png Binary files differnew file mode 100644 index 000000000..cbe7f859b --- /dev/null +++ b/res/drawable/flip_00042.png diff --git a/res/drawable/flip_00043.png b/res/drawable/flip_00043.png Binary files differnew file mode 100644 index 000000000..cbe7f859b --- /dev/null +++ b/res/drawable/flip_00043.png diff --git a/res/drawable/flip_00044.png b/res/drawable/flip_00044.png Binary files differnew file mode 100644 index 000000000..cbe7f859b --- /dev/null +++ b/res/drawable/flip_00044.png diff --git a/res/drawable/flip_00045.png b/res/drawable/flip_00045.png Binary files differnew file mode 100644 index 000000000..cbe7f859b --- /dev/null +++ b/res/drawable/flip_00045.png diff --git a/res/drawable/flip_00046.png b/res/drawable/flip_00046.png Binary files differnew file mode 100644 index 000000000..cbe7f859b --- /dev/null +++ b/res/drawable/flip_00046.png diff --git a/res/drawable/flip_00047.png b/res/drawable/flip_00047.png Binary files differnew file mode 100644 index 000000000..cbe7f859b --- /dev/null +++ b/res/drawable/flip_00047.png diff --git a/res/drawable/flip_00048.png b/res/drawable/flip_00048.png Binary files differnew file mode 100644 index 000000000..cbe7f859b --- /dev/null +++ b/res/drawable/flip_00048.png diff --git a/res/drawable/flip_00049.png b/res/drawable/flip_00049.png Binary files differnew file mode 100644 index 000000000..cbe7f859b --- /dev/null +++ b/res/drawable/flip_00049.png diff --git a/res/drawable/grid.png b/res/drawable/grid.png Binary files differnew file mode 100644 index 000000000..79fe901d1 --- /dev/null +++ b/res/drawable/grid.png diff --git a/res/drawable/grid_comfortable.png b/res/drawable/grid_comfortable.png Binary files differnew file mode 100644 index 000000000..34e3ef2ee --- /dev/null +++ b/res/drawable/grid_comfortable.png diff --git a/res/drawable/grid_condensed.png b/res/drawable/grid_condensed.png Binary files differnew file mode 100644 index 000000000..ebc9d4e54 --- /dev/null +++ b/res/drawable/grid_condensed.png diff --git a/res/drawable/grid_cozy.png b/res/drawable/grid_cozy.png Binary files differnew file mode 100644 index 000000000..929bcb541 --- /dev/null +++ b/res/drawable/grid_cozy.png diff --git a/res/drawable/handle.png b/res/drawable/handle.png Binary files differnew file mode 100644 index 000000000..6e943f0da --- /dev/null +++ b/res/drawable/handle.png diff --git a/res/drawable/handle_left.png b/res/drawable/handle_left.png Binary files differnew file mode 100644 index 000000000..b78889ec0 --- /dev/null +++ b/res/drawable/handle_left.png diff --git a/res/drawable/handle_reversed.png b/res/drawable/handle_reversed.png Binary files differnew file mode 100644 index 000000000..6e943f0da --- /dev/null +++ b/res/drawable/handle_reversed.png diff --git a/res/drawable/launcheranimatedarrow_00000.png b/res/drawable/launcheranimatedarrow_00000.png Binary files differnew file mode 100644 index 000000000..2ed7fe9a7 --- /dev/null +++ b/res/drawable/launcheranimatedarrow_00000.png diff --git a/res/drawable/launcheranimatedarrow_00001.png b/res/drawable/launcheranimatedarrow_00001.png Binary files differnew file mode 100644 index 000000000..f3707e07c --- /dev/null +++ b/res/drawable/launcheranimatedarrow_00001.png diff --git a/res/drawable/launcheranimatedarrow_00002.png b/res/drawable/launcheranimatedarrow_00002.png Binary files differnew file mode 100644 index 000000000..3549389d0 --- /dev/null +++ b/res/drawable/launcheranimatedarrow_00002.png diff --git a/res/drawable/launcheranimatedarrow_00003.png b/res/drawable/launcheranimatedarrow_00003.png Binary files differnew file mode 100644 index 000000000..891e86c42 --- /dev/null +++ b/res/drawable/launcheranimatedarrow_00003.png diff --git a/res/drawable/launcheranimatedarrow_00004.png b/res/drawable/launcheranimatedarrow_00004.png Binary files differnew file mode 100644 index 000000000..7cfb1ef8c --- /dev/null +++ b/res/drawable/launcheranimatedarrow_00004.png diff --git a/res/drawable/launcheranimatedarrow_00005.png b/res/drawable/launcheranimatedarrow_00005.png Binary files differnew file mode 100644 index 000000000..121f4d516 --- /dev/null +++ b/res/drawable/launcheranimatedarrow_00005.png diff --git a/res/drawable/launcheranimatedarrow_00006.png b/res/drawable/launcheranimatedarrow_00006.png Binary files differnew file mode 100644 index 000000000..3a38e71f7 --- /dev/null +++ b/res/drawable/launcheranimatedarrow_00006.png diff --git a/res/drawable/launcheranimatedarrow_00007.png b/res/drawable/launcheranimatedarrow_00007.png Binary files differnew file mode 100644 index 000000000..e81a719fd --- /dev/null +++ b/res/drawable/launcheranimatedarrow_00007.png diff --git a/res/drawable/launcheranimatedarrow_00008.png b/res/drawable/launcheranimatedarrow_00008.png Binary files differnew file mode 100644 index 000000000..bd6f40981 --- /dev/null +++ b/res/drawable/launcheranimatedarrow_00008.png diff --git a/res/drawable/launcheranimatedarrow_00009.png b/res/drawable/launcheranimatedarrow_00009.png Binary files differnew file mode 100644 index 000000000..c7cb60daf --- /dev/null +++ b/res/drawable/launcheranimatedarrow_00009.png diff --git a/res/drawable/launcheranimatedarrow_00010.png b/res/drawable/launcheranimatedarrow_00010.png Binary files differnew file mode 100644 index 000000000..1bf30dcc3 --- /dev/null +++ b/res/drawable/launcheranimatedarrow_00010.png diff --git a/res/drawable/launcheranimatedarrow_00011.png b/res/drawable/launcheranimatedarrow_00011.png Binary files differnew file mode 100644 index 000000000..3cb598806 --- /dev/null +++ b/res/drawable/launcheranimatedarrow_00011.png diff --git a/res/drawable/launcheranimatedarrow_00012.png b/res/drawable/launcheranimatedarrow_00012.png Binary files differnew file mode 100644 index 000000000..58070de06 --- /dev/null +++ b/res/drawable/launcheranimatedarrow_00012.png diff --git a/res/drawable/launcheranimatedarrow_00013.png b/res/drawable/launcheranimatedarrow_00013.png Binary files differnew file mode 100644 index 000000000..810d0a229 --- /dev/null +++ b/res/drawable/launcheranimatedarrow_00013.png diff --git a/res/drawable/launcheranimatedarrow_00014.png b/res/drawable/launcheranimatedarrow_00014.png Binary files differnew file mode 100644 index 000000000..3f9e51861 --- /dev/null +++ b/res/drawable/launcheranimatedarrow_00014.png diff --git a/res/drawable/launcheranimatedarrow_00015.png b/res/drawable/launcheranimatedarrow_00015.png Binary files differnew file mode 100644 index 000000000..348bfbbc6 --- /dev/null +++ b/res/drawable/launcheranimatedarrow_00015.png diff --git a/res/drawable/launcheranimatedarrow_00016.png b/res/drawable/launcheranimatedarrow_00016.png Binary files differnew file mode 100644 index 000000000..5b0b28649 --- /dev/null +++ b/res/drawable/launcheranimatedarrow_00016.png diff --git a/res/drawable/listitem_bg.xml b/res/drawable/listitem_bg.xml new file mode 100644 index 000000000..b81e995f8 --- /dev/null +++ b/res/drawable/listitem_bg.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8"?> +<selector xmlns:android="http://schemas.android.com/apk/res/android" > + <item android:state_enabled="true" + android:state_pressed="true" android:drawable="@android:color/white" /> + <item android:drawable="@color/settings_bg_color" /> +</selector>
\ No newline at end of file diff --git a/res/drawable/listitem_selector.xml b/res/drawable/listitem_selector.xml new file mode 100644 index 000000000..b81e995f8 --- /dev/null +++ b/res/drawable/listitem_selector.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8"?> +<selector xmlns:android="http://schemas.android.com/apk/res/android" > + <item android:state_enabled="true" + android:state_pressed="true" android:drawable="@android:color/white" /> + <item android:drawable="@color/settings_bg_color" /> +</selector>
\ No newline at end of file diff --git a/res/drawable/none_00000.png b/res/drawable/none_00000.png Binary files differnew file mode 100644 index 000000000..280dbde5c --- /dev/null +++ b/res/drawable/none_00000.png diff --git a/res/drawable/none_00001.png b/res/drawable/none_00001.png Binary files differnew file mode 100644 index 000000000..9318c29d5 --- /dev/null +++ b/res/drawable/none_00001.png diff --git a/res/drawable/none_00002.png b/res/drawable/none_00002.png Binary files differnew file mode 100644 index 000000000..41288e9bf --- /dev/null +++ b/res/drawable/none_00002.png diff --git a/res/drawable/none_00003.png b/res/drawable/none_00003.png Binary files differnew file mode 100644 index 000000000..831375e36 --- /dev/null +++ b/res/drawable/none_00003.png diff --git a/res/drawable/none_00004.png b/res/drawable/none_00004.png Binary files differnew file mode 100644 index 000000000..0ab2c45ac --- /dev/null +++ b/res/drawable/none_00004.png diff --git a/res/drawable/none_00005.png b/res/drawable/none_00005.png Binary files differnew file mode 100644 index 000000000..3a3904cad --- /dev/null +++ b/res/drawable/none_00005.png diff --git a/res/drawable/none_00006.png b/res/drawable/none_00006.png Binary files differnew file mode 100644 index 000000000..012ed8a6a --- /dev/null +++ b/res/drawable/none_00006.png diff --git a/res/drawable/none_00007.png b/res/drawable/none_00007.png Binary files differnew file mode 100644 index 000000000..f72aa33a4 --- /dev/null +++ b/res/drawable/none_00007.png diff --git a/res/drawable/none_00008.png b/res/drawable/none_00008.png Binary files differnew file mode 100644 index 000000000..520df34dc --- /dev/null +++ b/res/drawable/none_00008.png diff --git a/res/drawable/none_00009.png b/res/drawable/none_00009.png Binary files differnew file mode 100644 index 000000000..d8ce1ca76 --- /dev/null +++ b/res/drawable/none_00009.png diff --git a/res/drawable/none_00010.png b/res/drawable/none_00010.png Binary files differnew file mode 100644 index 000000000..50ea44727 --- /dev/null +++ b/res/drawable/none_00010.png diff --git a/res/drawable/none_00011.png b/res/drawable/none_00011.png Binary files differnew file mode 100644 index 000000000..bb664bb06 --- /dev/null +++ b/res/drawable/none_00011.png diff --git a/res/drawable/none_00012.png b/res/drawable/none_00012.png Binary files differnew file mode 100644 index 000000000..ba415ccdb --- /dev/null +++ b/res/drawable/none_00012.png diff --git a/res/drawable/none_00013.png b/res/drawable/none_00013.png Binary files differnew file mode 100644 index 000000000..5727430ea --- /dev/null +++ b/res/drawable/none_00013.png diff --git a/res/drawable/none_00014.png b/res/drawable/none_00014.png Binary files differnew file mode 100644 index 000000000..8791adc7e --- /dev/null +++ b/res/drawable/none_00014.png diff --git a/res/drawable/none_00015.png b/res/drawable/none_00015.png Binary files differnew file mode 100644 index 000000000..07ae898fa --- /dev/null +++ b/res/drawable/none_00015.png diff --git a/res/drawable/none_00016.png b/res/drawable/none_00016.png Binary files differnew file mode 100644 index 000000000..61954a175 --- /dev/null +++ b/res/drawable/none_00016.png diff --git a/res/drawable/none_00017.png b/res/drawable/none_00017.png Binary files differnew file mode 100644 index 000000000..38d3b8c3a --- /dev/null +++ b/res/drawable/none_00017.png diff --git a/res/drawable/none_00018.png b/res/drawable/none_00018.png Binary files differnew file mode 100644 index 000000000..59af03174 --- /dev/null +++ b/res/drawable/none_00018.png diff --git a/res/drawable/none_00019.png b/res/drawable/none_00019.png Binary files differnew file mode 100644 index 000000000..6dbff8983 --- /dev/null +++ b/res/drawable/none_00019.png diff --git a/res/drawable/none_00020.png b/res/drawable/none_00020.png Binary files differnew file mode 100644 index 000000000..cbcff0391 --- /dev/null +++ b/res/drawable/none_00020.png diff --git a/res/drawable/none_00021.png b/res/drawable/none_00021.png Binary files differnew file mode 100644 index 000000000..cbcff0391 --- /dev/null +++ b/res/drawable/none_00021.png diff --git a/res/drawable/none_00022.png b/res/drawable/none_00022.png Binary files differnew file mode 100644 index 000000000..cbcff0391 --- /dev/null +++ b/res/drawable/none_00022.png diff --git a/res/drawable/none_00023.png b/res/drawable/none_00023.png Binary files differnew file mode 100644 index 000000000..cbcff0391 --- /dev/null +++ b/res/drawable/none_00023.png diff --git a/res/drawable/none_00024.png b/res/drawable/none_00024.png Binary files differnew file mode 100644 index 000000000..cbcff0391 --- /dev/null +++ b/res/drawable/none_00024.png diff --git a/res/drawable/none_00025.png b/res/drawable/none_00025.png Binary files differnew file mode 100644 index 000000000..cbcff0391 --- /dev/null +++ b/res/drawable/none_00025.png diff --git a/res/drawable/none_00026.png b/res/drawable/none_00026.png Binary files differnew file mode 100644 index 000000000..cbcff0391 --- /dev/null +++ b/res/drawable/none_00026.png diff --git a/res/drawable/none_00027.png b/res/drawable/none_00027.png Binary files differnew file mode 100644 index 000000000..cbcff0391 --- /dev/null +++ b/res/drawable/none_00027.png diff --git a/res/drawable/none_00028.png b/res/drawable/none_00028.png Binary files differnew file mode 100644 index 000000000..cbcff0391 --- /dev/null +++ b/res/drawable/none_00028.png diff --git a/res/drawable/none_00029.png b/res/drawable/none_00029.png Binary files differnew file mode 100644 index 000000000..cbcff0391 --- /dev/null +++ b/res/drawable/none_00029.png diff --git a/res/drawable/none_00030.png b/res/drawable/none_00030.png Binary files differnew file mode 100644 index 000000000..cbcff0391 --- /dev/null +++ b/res/drawable/none_00030.png diff --git a/res/drawable/none_00031.png b/res/drawable/none_00031.png Binary files differnew file mode 100644 index 000000000..cbcff0391 --- /dev/null +++ b/res/drawable/none_00031.png diff --git a/res/drawable/none_00032.png b/res/drawable/none_00032.png Binary files differnew file mode 100644 index 000000000..cbcff0391 --- /dev/null +++ b/res/drawable/none_00032.png diff --git a/res/drawable/none_00033.png b/res/drawable/none_00033.png Binary files differnew file mode 100644 index 000000000..cbcff0391 --- /dev/null +++ b/res/drawable/none_00033.png diff --git a/res/drawable/none_00034.png b/res/drawable/none_00034.png Binary files differnew file mode 100644 index 000000000..cbcff0391 --- /dev/null +++ b/res/drawable/none_00034.png diff --git a/res/drawable/none_00035.png b/res/drawable/none_00035.png Binary files differnew file mode 100644 index 000000000..cbcff0391 --- /dev/null +++ b/res/drawable/none_00035.png diff --git a/res/drawable/none_00036.png b/res/drawable/none_00036.png Binary files differnew file mode 100644 index 000000000..cbcff0391 --- /dev/null +++ b/res/drawable/none_00036.png diff --git a/res/drawable/none_00037.png b/res/drawable/none_00037.png Binary files differnew file mode 100644 index 000000000..cbcff0391 --- /dev/null +++ b/res/drawable/none_00037.png diff --git a/res/drawable/none_00038.png b/res/drawable/none_00038.png Binary files differnew file mode 100644 index 000000000..cbcff0391 --- /dev/null +++ b/res/drawable/none_00038.png diff --git a/res/drawable/none_00039.png b/res/drawable/none_00039.png Binary files differnew file mode 100644 index 000000000..cbcff0391 --- /dev/null +++ b/res/drawable/none_00039.png diff --git a/res/drawable/none_00040.png b/res/drawable/none_00040.png Binary files differnew file mode 100644 index 000000000..cbcff0391 --- /dev/null +++ b/res/drawable/none_00040.png diff --git a/res/drawable/none_00041.png b/res/drawable/none_00041.png Binary files differnew file mode 100644 index 000000000..cbcff0391 --- /dev/null +++ b/res/drawable/none_00041.png diff --git a/res/drawable/none_00042.png b/res/drawable/none_00042.png Binary files differnew file mode 100644 index 000000000..cbcff0391 --- /dev/null +++ b/res/drawable/none_00042.png diff --git a/res/drawable/none_00043.png b/res/drawable/none_00043.png Binary files differnew file mode 100644 index 000000000..cbcff0391 --- /dev/null +++ b/res/drawable/none_00043.png diff --git a/res/drawable/none_00044.png b/res/drawable/none_00044.png Binary files differnew file mode 100644 index 000000000..cbcff0391 --- /dev/null +++ b/res/drawable/none_00044.png diff --git a/res/drawable/none_00045.png b/res/drawable/none_00045.png Binary files differnew file mode 100644 index 000000000..cbcff0391 --- /dev/null +++ b/res/drawable/none_00045.png diff --git a/res/drawable/none_00046.png b/res/drawable/none_00046.png Binary files differnew file mode 100644 index 000000000..cbcff0391 --- /dev/null +++ b/res/drawable/none_00046.png diff --git a/res/drawable/none_00047.png b/res/drawable/none_00047.png Binary files differnew file mode 100644 index 000000000..cbcff0391 --- /dev/null +++ b/res/drawable/none_00047.png diff --git a/res/drawable/none_00048.png b/res/drawable/none_00048.png Binary files differnew file mode 100644 index 000000000..cbcff0391 --- /dev/null +++ b/res/drawable/none_00048.png diff --git a/res/drawable/none_00049.png b/res/drawable/none_00049.png Binary files differnew file mode 100644 index 000000000..cbcff0391 --- /dev/null +++ b/res/drawable/none_00049.png diff --git a/res/drawable/overview_00000.png b/res/drawable/overview_00000.png Binary files differnew file mode 100644 index 000000000..e000c6108 --- /dev/null +++ b/res/drawable/overview_00000.png diff --git a/res/drawable/overview_00001.png b/res/drawable/overview_00001.png Binary files differnew file mode 100644 index 000000000..ee52cae5e --- /dev/null +++ b/res/drawable/overview_00001.png diff --git a/res/drawable/overview_00002.png b/res/drawable/overview_00002.png Binary files differnew file mode 100644 index 000000000..401629303 --- /dev/null +++ b/res/drawable/overview_00002.png diff --git a/res/drawable/overview_00003.png b/res/drawable/overview_00003.png Binary files differnew file mode 100644 index 000000000..9fce3248f --- /dev/null +++ b/res/drawable/overview_00003.png diff --git a/res/drawable/overview_00004.png b/res/drawable/overview_00004.png Binary files differnew file mode 100644 index 000000000..6089f3611 --- /dev/null +++ b/res/drawable/overview_00004.png diff --git a/res/drawable/overview_00005.png b/res/drawable/overview_00005.png Binary files differnew file mode 100644 index 000000000..0195e61d5 --- /dev/null +++ b/res/drawable/overview_00005.png diff --git a/res/drawable/overview_00006.png b/res/drawable/overview_00006.png Binary files differnew file mode 100644 index 000000000..c91cc1ede --- /dev/null +++ b/res/drawable/overview_00006.png diff --git a/res/drawable/overview_00007.png b/res/drawable/overview_00007.png Binary files differnew file mode 100644 index 000000000..ca57ff22c --- /dev/null +++ b/res/drawable/overview_00007.png diff --git a/res/drawable/overview_00008.png b/res/drawable/overview_00008.png Binary files differnew file mode 100644 index 000000000..c42692f20 --- /dev/null +++ b/res/drawable/overview_00008.png diff --git a/res/drawable/overview_00009.png b/res/drawable/overview_00009.png Binary files differnew file mode 100644 index 000000000..e38b36827 --- /dev/null +++ b/res/drawable/overview_00009.png diff --git a/res/drawable/overview_00010.png b/res/drawable/overview_00010.png Binary files differnew file mode 100644 index 000000000..4416302f8 --- /dev/null +++ b/res/drawable/overview_00010.png diff --git a/res/drawable/overview_00011.png b/res/drawable/overview_00011.png Binary files differnew file mode 100644 index 000000000..013cdec94 --- /dev/null +++ b/res/drawable/overview_00011.png diff --git a/res/drawable/overview_00012.png b/res/drawable/overview_00012.png Binary files differnew file mode 100644 index 000000000..fe08ca75d --- /dev/null +++ b/res/drawable/overview_00012.png diff --git a/res/drawable/overview_00013.png b/res/drawable/overview_00013.png Binary files differnew file mode 100644 index 000000000..4907c3715 --- /dev/null +++ b/res/drawable/overview_00013.png diff --git a/res/drawable/overview_00014.png b/res/drawable/overview_00014.png Binary files differnew file mode 100644 index 000000000..26acf47bc --- /dev/null +++ b/res/drawable/overview_00014.png diff --git a/res/drawable/overview_00015.png b/res/drawable/overview_00015.png Binary files differnew file mode 100644 index 000000000..258059ae2 --- /dev/null +++ b/res/drawable/overview_00015.png diff --git a/res/drawable/overview_00016.png b/res/drawable/overview_00016.png Binary files differnew file mode 100644 index 000000000..8c164c139 --- /dev/null +++ b/res/drawable/overview_00016.png diff --git a/res/drawable/overview_00017.png b/res/drawable/overview_00017.png Binary files differnew file mode 100644 index 000000000..dd1df3330 --- /dev/null +++ b/res/drawable/overview_00017.png diff --git a/res/drawable/overview_00018.png b/res/drawable/overview_00018.png Binary files differnew file mode 100644 index 000000000..b3e54a3e6 --- /dev/null +++ b/res/drawable/overview_00018.png diff --git a/res/drawable/overview_00019.png b/res/drawable/overview_00019.png Binary files differnew file mode 100644 index 000000000..5a0b1cbc1 --- /dev/null +++ b/res/drawable/overview_00019.png diff --git a/res/drawable/overview_00020.png b/res/drawable/overview_00020.png Binary files differnew file mode 100644 index 000000000..a54f07a80 --- /dev/null +++ b/res/drawable/overview_00020.png diff --git a/res/drawable/overview_00021.png b/res/drawable/overview_00021.png Binary files differnew file mode 100644 index 000000000..a54f07a80 --- /dev/null +++ b/res/drawable/overview_00021.png diff --git a/res/drawable/overview_00022.png b/res/drawable/overview_00022.png Binary files differnew file mode 100644 index 000000000..a54f07a80 --- /dev/null +++ b/res/drawable/overview_00022.png diff --git a/res/drawable/overview_00023.png b/res/drawable/overview_00023.png Binary files differnew file mode 100644 index 000000000..a54f07a80 --- /dev/null +++ b/res/drawable/overview_00023.png diff --git a/res/drawable/overview_00024.png b/res/drawable/overview_00024.png Binary files differnew file mode 100644 index 000000000..a54f07a80 --- /dev/null +++ b/res/drawable/overview_00024.png diff --git a/res/drawable/overview_00025.png b/res/drawable/overview_00025.png Binary files differnew file mode 100644 index 000000000..a54f07a80 --- /dev/null +++ b/res/drawable/overview_00025.png diff --git a/res/drawable/overview_00026.png b/res/drawable/overview_00026.png Binary files differnew file mode 100644 index 000000000..a54f07a80 --- /dev/null +++ b/res/drawable/overview_00026.png diff --git a/res/drawable/overview_00027.png b/res/drawable/overview_00027.png Binary files differnew file mode 100644 index 000000000..a54f07a80 --- /dev/null +++ b/res/drawable/overview_00027.png diff --git a/res/drawable/overview_00028.png b/res/drawable/overview_00028.png Binary files differnew file mode 100644 index 000000000..a54f07a80 --- /dev/null +++ b/res/drawable/overview_00028.png diff --git a/res/drawable/overview_00029.png b/res/drawable/overview_00029.png Binary files differnew file mode 100644 index 000000000..a54f07a80 --- /dev/null +++ b/res/drawable/overview_00029.png diff --git a/res/drawable/overview_00030.png b/res/drawable/overview_00030.png Binary files differnew file mode 100644 index 000000000..a54f07a80 --- /dev/null +++ b/res/drawable/overview_00030.png diff --git a/res/drawable/overview_00031.png b/res/drawable/overview_00031.png Binary files differnew file mode 100644 index 000000000..a54f07a80 --- /dev/null +++ b/res/drawable/overview_00031.png diff --git a/res/drawable/overview_00032.png b/res/drawable/overview_00032.png Binary files differnew file mode 100644 index 000000000..a54f07a80 --- /dev/null +++ b/res/drawable/overview_00032.png diff --git a/res/drawable/overview_00033.png b/res/drawable/overview_00033.png Binary files differnew file mode 100644 index 000000000..a54f07a80 --- /dev/null +++ b/res/drawable/overview_00033.png diff --git a/res/drawable/overview_00034.png b/res/drawable/overview_00034.png Binary files differnew file mode 100644 index 000000000..a54f07a80 --- /dev/null +++ b/res/drawable/overview_00034.png diff --git a/res/drawable/overview_00035.png b/res/drawable/overview_00035.png Binary files differnew file mode 100644 index 000000000..a54f07a80 --- /dev/null +++ b/res/drawable/overview_00035.png diff --git a/res/drawable/overview_00036.png b/res/drawable/overview_00036.png Binary files differnew file mode 100644 index 000000000..a54f07a80 --- /dev/null +++ b/res/drawable/overview_00036.png diff --git a/res/drawable/overview_00037.png b/res/drawable/overview_00037.png Binary files differnew file mode 100644 index 000000000..a54f07a80 --- /dev/null +++ b/res/drawable/overview_00037.png diff --git a/res/drawable/overview_00038.png b/res/drawable/overview_00038.png Binary files differnew file mode 100644 index 000000000..a54f07a80 --- /dev/null +++ b/res/drawable/overview_00038.png diff --git a/res/drawable/overview_00039.png b/res/drawable/overview_00039.png Binary files differnew file mode 100644 index 000000000..a54f07a80 --- /dev/null +++ b/res/drawable/overview_00039.png diff --git a/res/drawable/overview_00040.png b/res/drawable/overview_00040.png Binary files differnew file mode 100644 index 000000000..a54f07a80 --- /dev/null +++ b/res/drawable/overview_00040.png diff --git a/res/drawable/overview_00041.png b/res/drawable/overview_00041.png Binary files differnew file mode 100644 index 000000000..a54f07a80 --- /dev/null +++ b/res/drawable/overview_00041.png diff --git a/res/drawable/overview_00042.png b/res/drawable/overview_00042.png Binary files differnew file mode 100644 index 000000000..a54f07a80 --- /dev/null +++ b/res/drawable/overview_00042.png diff --git a/res/drawable/overview_00043.png b/res/drawable/overview_00043.png Binary files differnew file mode 100644 index 000000000..a54f07a80 --- /dev/null +++ b/res/drawable/overview_00043.png diff --git a/res/drawable/overview_00044.png b/res/drawable/overview_00044.png Binary files differnew file mode 100644 index 000000000..a54f07a80 --- /dev/null +++ b/res/drawable/overview_00044.png diff --git a/res/drawable/overview_00045.png b/res/drawable/overview_00045.png Binary files differnew file mode 100644 index 000000000..a54f07a80 --- /dev/null +++ b/res/drawable/overview_00045.png diff --git a/res/drawable/overview_00046.png b/res/drawable/overview_00046.png Binary files differnew file mode 100644 index 000000000..a54f07a80 --- /dev/null +++ b/res/drawable/overview_00046.png diff --git a/res/drawable/overview_00047.png b/res/drawable/overview_00047.png Binary files differnew file mode 100644 index 000000000..a54f07a80 --- /dev/null +++ b/res/drawable/overview_00047.png diff --git a/res/drawable/overview_00048.png b/res/drawable/overview_00048.png Binary files differnew file mode 100644 index 000000000..a54f07a80 --- /dev/null +++ b/res/drawable/overview_00048.png diff --git a/res/drawable/overview_00049.png b/res/drawable/overview_00049.png Binary files differnew file mode 100644 index 000000000..a54f07a80 --- /dev/null +++ b/res/drawable/overview_00049.png diff --git a/res/drawable/rotatedown_00000.png b/res/drawable/rotatedown_00000.png Binary files differnew file mode 100644 index 000000000..07ccb92e0 --- /dev/null +++ b/res/drawable/rotatedown_00000.png diff --git a/res/drawable/rotatedown_00001.png b/res/drawable/rotatedown_00001.png Binary files differnew file mode 100644 index 000000000..98f1b6761 --- /dev/null +++ b/res/drawable/rotatedown_00001.png diff --git a/res/drawable/rotatedown_00002.png b/res/drawable/rotatedown_00002.png Binary files differnew file mode 100644 index 000000000..927f5d1a5 --- /dev/null +++ b/res/drawable/rotatedown_00002.png diff --git a/res/drawable/rotatedown_00003.png b/res/drawable/rotatedown_00003.png Binary files differnew file mode 100644 index 000000000..fcb6f47e3 --- /dev/null +++ b/res/drawable/rotatedown_00003.png diff --git a/res/drawable/rotatedown_00004.png b/res/drawable/rotatedown_00004.png Binary files differnew file mode 100644 index 000000000..16797d611 --- /dev/null +++ b/res/drawable/rotatedown_00004.png diff --git a/res/drawable/rotatedown_00005.png b/res/drawable/rotatedown_00005.png Binary files differnew file mode 100644 index 000000000..4c43eb8b6 --- /dev/null +++ b/res/drawable/rotatedown_00005.png diff --git a/res/drawable/rotatedown_00006.png b/res/drawable/rotatedown_00006.png Binary files differnew file mode 100644 index 000000000..2f03ec42b --- /dev/null +++ b/res/drawable/rotatedown_00006.png diff --git a/res/drawable/rotatedown_00007.png b/res/drawable/rotatedown_00007.png Binary files differnew file mode 100644 index 000000000..6a6d080b8 --- /dev/null +++ b/res/drawable/rotatedown_00007.png diff --git a/res/drawable/rotatedown_00008.png b/res/drawable/rotatedown_00008.png Binary files differnew file mode 100644 index 000000000..bf9f3103f --- /dev/null +++ b/res/drawable/rotatedown_00008.png diff --git a/res/drawable/rotatedown_00009.png b/res/drawable/rotatedown_00009.png Binary files differnew file mode 100644 index 000000000..f911bf4bc --- /dev/null +++ b/res/drawable/rotatedown_00009.png diff --git a/res/drawable/rotatedown_00010.png b/res/drawable/rotatedown_00010.png Binary files differnew file mode 100644 index 000000000..f84dd2051 --- /dev/null +++ b/res/drawable/rotatedown_00010.png diff --git a/res/drawable/rotatedown_00011.png b/res/drawable/rotatedown_00011.png Binary files differnew file mode 100644 index 000000000..7106a7db8 --- /dev/null +++ b/res/drawable/rotatedown_00011.png diff --git a/res/drawable/rotatedown_00012.png b/res/drawable/rotatedown_00012.png Binary files differnew file mode 100644 index 000000000..13cd0b2c6 --- /dev/null +++ b/res/drawable/rotatedown_00012.png diff --git a/res/drawable/rotatedown_00013.png b/res/drawable/rotatedown_00013.png Binary files differnew file mode 100644 index 000000000..4589bf263 --- /dev/null +++ b/res/drawable/rotatedown_00013.png diff --git a/res/drawable/rotatedown_00014.png b/res/drawable/rotatedown_00014.png Binary files differnew file mode 100644 index 000000000..6b59e5d07 --- /dev/null +++ b/res/drawable/rotatedown_00014.png diff --git a/res/drawable/rotatedown_00015.png b/res/drawable/rotatedown_00015.png Binary files differnew file mode 100644 index 000000000..890746b83 --- /dev/null +++ b/res/drawable/rotatedown_00015.png diff --git a/res/drawable/rotatedown_00016.png b/res/drawable/rotatedown_00016.png Binary files differnew file mode 100644 index 000000000..56d9e2343 --- /dev/null +++ b/res/drawable/rotatedown_00016.png diff --git a/res/drawable/rotatedown_00017.png b/res/drawable/rotatedown_00017.png Binary files differnew file mode 100644 index 000000000..d2d80406c --- /dev/null +++ b/res/drawable/rotatedown_00017.png diff --git a/res/drawable/rotatedown_00018.png b/res/drawable/rotatedown_00018.png Binary files differnew file mode 100644 index 000000000..43afa3ed8 --- /dev/null +++ b/res/drawable/rotatedown_00018.png diff --git a/res/drawable/rotatedown_00019.png b/res/drawable/rotatedown_00019.png Binary files differnew file mode 100644 index 000000000..4c6ec9095 --- /dev/null +++ b/res/drawable/rotatedown_00019.png diff --git a/res/drawable/rotatedown_00020.png b/res/drawable/rotatedown_00020.png Binary files differnew file mode 100644 index 000000000..2cfdd90ee --- /dev/null +++ b/res/drawable/rotatedown_00020.png diff --git a/res/drawable/rotatedown_00021.png b/res/drawable/rotatedown_00021.png Binary files differnew file mode 100644 index 000000000..a54e05333 --- /dev/null +++ b/res/drawable/rotatedown_00021.png diff --git a/res/drawable/rotatedown_00022.png b/res/drawable/rotatedown_00022.png Binary files differnew file mode 100644 index 000000000..7f9c0214c --- /dev/null +++ b/res/drawable/rotatedown_00022.png diff --git a/res/drawable/rotatedown_00023.png b/res/drawable/rotatedown_00023.png Binary files differnew file mode 100644 index 000000000..86c20dfbd --- /dev/null +++ b/res/drawable/rotatedown_00023.png diff --git a/res/drawable/rotatedown_00024.png b/res/drawable/rotatedown_00024.png Binary files differnew file mode 100644 index 000000000..cacf6274b --- /dev/null +++ b/res/drawable/rotatedown_00024.png diff --git a/res/drawable/rotatedown_00025.png b/res/drawable/rotatedown_00025.png Binary files differnew file mode 100644 index 000000000..f80765d5b --- /dev/null +++ b/res/drawable/rotatedown_00025.png diff --git a/res/drawable/rotatedown_00026.png b/res/drawable/rotatedown_00026.png Binary files differnew file mode 100644 index 000000000..cb0714379 --- /dev/null +++ b/res/drawable/rotatedown_00026.png diff --git a/res/drawable/rotatedown_00027.png b/res/drawable/rotatedown_00027.png Binary files differnew file mode 100644 index 000000000..4f5639729 --- /dev/null +++ b/res/drawable/rotatedown_00027.png diff --git a/res/drawable/rotatedown_00028.png b/res/drawable/rotatedown_00028.png Binary files differnew file mode 100644 index 000000000..b1b114e5c --- /dev/null +++ b/res/drawable/rotatedown_00028.png diff --git a/res/drawable/rotatedown_00029.png b/res/drawable/rotatedown_00029.png Binary files differnew file mode 100644 index 000000000..b20104e93 --- /dev/null +++ b/res/drawable/rotatedown_00029.png diff --git a/res/drawable/rotatedown_00030.png b/res/drawable/rotatedown_00030.png Binary files differnew file mode 100644 index 000000000..07ccb92e0 --- /dev/null +++ b/res/drawable/rotatedown_00030.png diff --git a/res/drawable/rotatedown_00031.png b/res/drawable/rotatedown_00031.png Binary files differnew file mode 100644 index 000000000..07ccb92e0 --- /dev/null +++ b/res/drawable/rotatedown_00031.png diff --git a/res/drawable/rotatedown_00032.png b/res/drawable/rotatedown_00032.png Binary files differnew file mode 100644 index 000000000..07ccb92e0 --- /dev/null +++ b/res/drawable/rotatedown_00032.png diff --git a/res/drawable/rotatedown_00033.png b/res/drawable/rotatedown_00033.png Binary files differnew file mode 100644 index 000000000..07ccb92e0 --- /dev/null +++ b/res/drawable/rotatedown_00033.png diff --git a/res/drawable/rotatedown_00034.png b/res/drawable/rotatedown_00034.png Binary files differnew file mode 100644 index 000000000..07ccb92e0 --- /dev/null +++ b/res/drawable/rotatedown_00034.png diff --git a/res/drawable/rotatedown_00035.png b/res/drawable/rotatedown_00035.png Binary files differnew file mode 100644 index 000000000..07ccb92e0 --- /dev/null +++ b/res/drawable/rotatedown_00035.png diff --git a/res/drawable/rotatedown_00036.png b/res/drawable/rotatedown_00036.png Binary files differnew file mode 100644 index 000000000..07ccb92e0 --- /dev/null +++ b/res/drawable/rotatedown_00036.png diff --git a/res/drawable/rotatedown_00037.png b/res/drawable/rotatedown_00037.png Binary files differnew file mode 100644 index 000000000..07ccb92e0 --- /dev/null +++ b/res/drawable/rotatedown_00037.png diff --git a/res/drawable/rotatedown_00038.png b/res/drawable/rotatedown_00038.png Binary files differnew file mode 100644 index 000000000..07ccb92e0 --- /dev/null +++ b/res/drawable/rotatedown_00038.png diff --git a/res/drawable/rotatedown_00039.png b/res/drawable/rotatedown_00039.png Binary files differnew file mode 100644 index 000000000..07ccb92e0 --- /dev/null +++ b/res/drawable/rotatedown_00039.png diff --git a/res/drawable/rotatedown_00040.png b/res/drawable/rotatedown_00040.png Binary files differnew file mode 100644 index 000000000..07ccb92e0 --- /dev/null +++ b/res/drawable/rotatedown_00040.png diff --git a/res/drawable/rotatedown_00041.png b/res/drawable/rotatedown_00041.png Binary files differnew file mode 100644 index 000000000..07ccb92e0 --- /dev/null +++ b/res/drawable/rotatedown_00041.png diff --git a/res/drawable/rotatedown_00042.png b/res/drawable/rotatedown_00042.png Binary files differnew file mode 100644 index 000000000..07ccb92e0 --- /dev/null +++ b/res/drawable/rotatedown_00042.png diff --git a/res/drawable/rotatedown_00043.png b/res/drawable/rotatedown_00043.png Binary files differnew file mode 100644 index 000000000..07ccb92e0 --- /dev/null +++ b/res/drawable/rotatedown_00043.png diff --git a/res/drawable/rotatedown_00044.png b/res/drawable/rotatedown_00044.png Binary files differnew file mode 100644 index 000000000..07ccb92e0 --- /dev/null +++ b/res/drawable/rotatedown_00044.png diff --git a/res/drawable/rotatedown_00045.png b/res/drawable/rotatedown_00045.png Binary files differnew file mode 100644 index 000000000..07ccb92e0 --- /dev/null +++ b/res/drawable/rotatedown_00045.png diff --git a/res/drawable/rotatedown_00046.png b/res/drawable/rotatedown_00046.png Binary files differnew file mode 100644 index 000000000..07ccb92e0 --- /dev/null +++ b/res/drawable/rotatedown_00046.png diff --git a/res/drawable/rotatedown_00047.png b/res/drawable/rotatedown_00047.png Binary files differnew file mode 100644 index 000000000..07ccb92e0 --- /dev/null +++ b/res/drawable/rotatedown_00047.png diff --git a/res/drawable/rotatedown_00048.png b/res/drawable/rotatedown_00048.png Binary files differnew file mode 100644 index 000000000..07ccb92e0 --- /dev/null +++ b/res/drawable/rotatedown_00048.png diff --git a/res/drawable/rotatedown_00049.png b/res/drawable/rotatedown_00049.png Binary files differnew file mode 100644 index 000000000..07ccb92e0 --- /dev/null +++ b/res/drawable/rotatedown_00049.png diff --git a/res/drawable/rotateup_00000.png b/res/drawable/rotateup_00000.png Binary files differnew file mode 100644 index 000000000..75e575f94 --- /dev/null +++ b/res/drawable/rotateup_00000.png diff --git a/res/drawable/rotateup_00001.png b/res/drawable/rotateup_00001.png Binary files differnew file mode 100644 index 000000000..d43792b1d --- /dev/null +++ b/res/drawable/rotateup_00001.png diff --git a/res/drawable/rotateup_00002.png b/res/drawable/rotateup_00002.png Binary files differnew file mode 100644 index 000000000..f77000771 --- /dev/null +++ b/res/drawable/rotateup_00002.png diff --git a/res/drawable/rotateup_00003.png b/res/drawable/rotateup_00003.png Binary files differnew file mode 100644 index 000000000..f5c2493b6 --- /dev/null +++ b/res/drawable/rotateup_00003.png diff --git a/res/drawable/rotateup_00004.png b/res/drawable/rotateup_00004.png Binary files differnew file mode 100644 index 000000000..b84318252 --- /dev/null +++ b/res/drawable/rotateup_00004.png diff --git a/res/drawable/rotateup_00005.png b/res/drawable/rotateup_00005.png Binary files differnew file mode 100644 index 000000000..342b3f9ae --- /dev/null +++ b/res/drawable/rotateup_00005.png diff --git a/res/drawable/rotateup_00006.png b/res/drawable/rotateup_00006.png Binary files differnew file mode 100644 index 000000000..cbf69d75e --- /dev/null +++ b/res/drawable/rotateup_00006.png diff --git a/res/drawable/rotateup_00007.png b/res/drawable/rotateup_00007.png Binary files differnew file mode 100644 index 000000000..8826db503 --- /dev/null +++ b/res/drawable/rotateup_00007.png diff --git a/res/drawable/rotateup_00008.png b/res/drawable/rotateup_00008.png Binary files differnew file mode 100644 index 000000000..6c363edaa --- /dev/null +++ b/res/drawable/rotateup_00008.png diff --git a/res/drawable/rotateup_00009.png b/res/drawable/rotateup_00009.png Binary files differnew file mode 100644 index 000000000..48e289034 --- /dev/null +++ b/res/drawable/rotateup_00009.png diff --git a/res/drawable/rotateup_00010.png b/res/drawable/rotateup_00010.png Binary files differnew file mode 100644 index 000000000..5749ccd29 --- /dev/null +++ b/res/drawable/rotateup_00010.png diff --git a/res/drawable/rotateup_00011.png b/res/drawable/rotateup_00011.png Binary files differnew file mode 100644 index 000000000..2a0463c92 --- /dev/null +++ b/res/drawable/rotateup_00011.png diff --git a/res/drawable/rotateup_00012.png b/res/drawable/rotateup_00012.png Binary files differnew file mode 100644 index 000000000..9bcfa09d4 --- /dev/null +++ b/res/drawable/rotateup_00012.png diff --git a/res/drawable/rotateup_00013.png b/res/drawable/rotateup_00013.png Binary files differnew file mode 100644 index 000000000..bc4ebb9db --- /dev/null +++ b/res/drawable/rotateup_00013.png diff --git a/res/drawable/rotateup_00014.png b/res/drawable/rotateup_00014.png Binary files differnew file mode 100644 index 000000000..181456805 --- /dev/null +++ b/res/drawable/rotateup_00014.png diff --git a/res/drawable/rotateup_00015.png b/res/drawable/rotateup_00015.png Binary files differnew file mode 100644 index 000000000..48c34408b --- /dev/null +++ b/res/drawable/rotateup_00015.png diff --git a/res/drawable/rotateup_00016.png b/res/drawable/rotateup_00016.png Binary files differnew file mode 100644 index 000000000..772a31d6a --- /dev/null +++ b/res/drawable/rotateup_00016.png diff --git a/res/drawable/rotateup_00017.png b/res/drawable/rotateup_00017.png Binary files differnew file mode 100644 index 000000000..ddad38c9e --- /dev/null +++ b/res/drawable/rotateup_00017.png diff --git a/res/drawable/rotateup_00018.png b/res/drawable/rotateup_00018.png Binary files differnew file mode 100644 index 000000000..a401751be --- /dev/null +++ b/res/drawable/rotateup_00018.png diff --git a/res/drawable/rotateup_00019.png b/res/drawable/rotateup_00019.png Binary files differnew file mode 100644 index 000000000..2091c5e6e --- /dev/null +++ b/res/drawable/rotateup_00019.png diff --git a/res/drawable/rotateup_00020.png b/res/drawable/rotateup_00020.png Binary files differnew file mode 100644 index 000000000..61ca3b246 --- /dev/null +++ b/res/drawable/rotateup_00020.png diff --git a/res/drawable/rotateup_00021.png b/res/drawable/rotateup_00021.png Binary files differnew file mode 100644 index 000000000..27c4258f3 --- /dev/null +++ b/res/drawable/rotateup_00021.png diff --git a/res/drawable/rotateup_00022.png b/res/drawable/rotateup_00022.png Binary files differnew file mode 100644 index 000000000..6f158ba2f --- /dev/null +++ b/res/drawable/rotateup_00022.png diff --git a/res/drawable/rotateup_00023.png b/res/drawable/rotateup_00023.png Binary files differnew file mode 100644 index 000000000..6a0a4dae0 --- /dev/null +++ b/res/drawable/rotateup_00023.png diff --git a/res/drawable/rotateup_00024.png b/res/drawable/rotateup_00024.png Binary files differnew file mode 100644 index 000000000..cdfde2a76 --- /dev/null +++ b/res/drawable/rotateup_00024.png diff --git a/res/drawable/rotateup_00025.png b/res/drawable/rotateup_00025.png Binary files differnew file mode 100644 index 000000000..2ac9ffa0e --- /dev/null +++ b/res/drawable/rotateup_00025.png diff --git a/res/drawable/rotateup_00026.png b/res/drawable/rotateup_00026.png Binary files differnew file mode 100644 index 000000000..2e41a9719 --- /dev/null +++ b/res/drawable/rotateup_00026.png diff --git a/res/drawable/rotateup_00027.png b/res/drawable/rotateup_00027.png Binary files differnew file mode 100644 index 000000000..fc68c10aa --- /dev/null +++ b/res/drawable/rotateup_00027.png diff --git a/res/drawable/rotateup_00028.png b/res/drawable/rotateup_00028.png Binary files differnew file mode 100644 index 000000000..cc5fb9c28 --- /dev/null +++ b/res/drawable/rotateup_00028.png diff --git a/res/drawable/rotateup_00029.png b/res/drawable/rotateup_00029.png Binary files differnew file mode 100644 index 000000000..43ef7a180 --- /dev/null +++ b/res/drawable/rotateup_00029.png diff --git a/res/drawable/rotateup_00030.png b/res/drawable/rotateup_00030.png Binary files differnew file mode 100644 index 000000000..75e575f94 --- /dev/null +++ b/res/drawable/rotateup_00030.png diff --git a/res/drawable/rotateup_00031.png b/res/drawable/rotateup_00031.png Binary files differnew file mode 100644 index 000000000..75e575f94 --- /dev/null +++ b/res/drawable/rotateup_00031.png diff --git a/res/drawable/rotateup_00032.png b/res/drawable/rotateup_00032.png Binary files differnew file mode 100644 index 000000000..75e575f94 --- /dev/null +++ b/res/drawable/rotateup_00032.png diff --git a/res/drawable/rotateup_00033.png b/res/drawable/rotateup_00033.png Binary files differnew file mode 100644 index 000000000..75e575f94 --- /dev/null +++ b/res/drawable/rotateup_00033.png diff --git a/res/drawable/rotateup_00034.png b/res/drawable/rotateup_00034.png Binary files differnew file mode 100644 index 000000000..75e575f94 --- /dev/null +++ b/res/drawable/rotateup_00034.png diff --git a/res/drawable/rotateup_00035.png b/res/drawable/rotateup_00035.png Binary files differnew file mode 100644 index 000000000..75e575f94 --- /dev/null +++ b/res/drawable/rotateup_00035.png diff --git a/res/drawable/rotateup_00036.png b/res/drawable/rotateup_00036.png Binary files differnew file mode 100644 index 000000000..75e575f94 --- /dev/null +++ b/res/drawable/rotateup_00036.png diff --git a/res/drawable/rotateup_00037.png b/res/drawable/rotateup_00037.png Binary files differnew file mode 100644 index 000000000..75e575f94 --- /dev/null +++ b/res/drawable/rotateup_00037.png diff --git a/res/drawable/rotateup_00038.png b/res/drawable/rotateup_00038.png Binary files differnew file mode 100644 index 000000000..75e575f94 --- /dev/null +++ b/res/drawable/rotateup_00038.png diff --git a/res/drawable/rotateup_00039.png b/res/drawable/rotateup_00039.png Binary files differnew file mode 100644 index 000000000..75e575f94 --- /dev/null +++ b/res/drawable/rotateup_00039.png diff --git a/res/drawable/rotateup_00040.png b/res/drawable/rotateup_00040.png Binary files differnew file mode 100644 index 000000000..75e575f94 --- /dev/null +++ b/res/drawable/rotateup_00040.png diff --git a/res/drawable/rotateup_00041.png b/res/drawable/rotateup_00041.png Binary files differnew file mode 100644 index 000000000..75e575f94 --- /dev/null +++ b/res/drawable/rotateup_00041.png diff --git a/res/drawable/rotateup_00042.png b/res/drawable/rotateup_00042.png Binary files differnew file mode 100644 index 000000000..75e575f94 --- /dev/null +++ b/res/drawable/rotateup_00042.png diff --git a/res/drawable/rotateup_00043.png b/res/drawable/rotateup_00043.png Binary files differnew file mode 100644 index 000000000..75e575f94 --- /dev/null +++ b/res/drawable/rotateup_00043.png diff --git a/res/drawable/rotateup_00044.png b/res/drawable/rotateup_00044.png Binary files differnew file mode 100644 index 000000000..75e575f94 --- /dev/null +++ b/res/drawable/rotateup_00044.png diff --git a/res/drawable/rotateup_00045.png b/res/drawable/rotateup_00045.png Binary files differnew file mode 100644 index 000000000..75e575f94 --- /dev/null +++ b/res/drawable/rotateup_00045.png diff --git a/res/drawable/rotateup_00046.png b/res/drawable/rotateup_00046.png Binary files differnew file mode 100644 index 000000000..75e575f94 --- /dev/null +++ b/res/drawable/rotateup_00046.png diff --git a/res/drawable/rotateup_00047.png b/res/drawable/rotateup_00047.png Binary files differnew file mode 100644 index 000000000..75e575f94 --- /dev/null +++ b/res/drawable/rotateup_00047.png diff --git a/res/drawable/rotateup_00048.png b/res/drawable/rotateup_00048.png Binary files differnew file mode 100644 index 000000000..75e575f94 --- /dev/null +++ b/res/drawable/rotateup_00048.png diff --git a/res/drawable/rotateup_00049.png b/res/drawable/rotateup_00049.png Binary files differnew file mode 100644 index 000000000..75e575f94 --- /dev/null +++ b/res/drawable/rotateup_00049.png diff --git a/res/drawable/stack_00000.png b/res/drawable/stack_00000.png Binary files differnew file mode 100644 index 000000000..b7e7f0bd2 --- /dev/null +++ b/res/drawable/stack_00000.png diff --git a/res/drawable/stack_00001.png b/res/drawable/stack_00001.png Binary files differnew file mode 100644 index 000000000..8b7f3a564 --- /dev/null +++ b/res/drawable/stack_00001.png diff --git a/res/drawable/stack_00002.png b/res/drawable/stack_00002.png Binary files differnew file mode 100644 index 000000000..c9e3aed80 --- /dev/null +++ b/res/drawable/stack_00002.png diff --git a/res/drawable/stack_00003.png b/res/drawable/stack_00003.png Binary files differnew file mode 100644 index 000000000..565f69b99 --- /dev/null +++ b/res/drawable/stack_00003.png diff --git a/res/drawable/stack_00004.png b/res/drawable/stack_00004.png Binary files differnew file mode 100644 index 000000000..2726dacc4 --- /dev/null +++ b/res/drawable/stack_00004.png diff --git a/res/drawable/stack_00005.png b/res/drawable/stack_00005.png Binary files differnew file mode 100644 index 000000000..266f1dcc0 --- /dev/null +++ b/res/drawable/stack_00005.png diff --git a/res/drawable/stack_00006.png b/res/drawable/stack_00006.png Binary files differnew file mode 100644 index 000000000..f26c0d042 --- /dev/null +++ b/res/drawable/stack_00006.png diff --git a/res/drawable/stack_00007.png b/res/drawable/stack_00007.png Binary files differnew file mode 100644 index 000000000..f6bd36217 --- /dev/null +++ b/res/drawable/stack_00007.png diff --git a/res/drawable/stack_00008.png b/res/drawable/stack_00008.png Binary files differnew file mode 100644 index 000000000..d9c20d803 --- /dev/null +++ b/res/drawable/stack_00008.png diff --git a/res/drawable/stack_00009.png b/res/drawable/stack_00009.png Binary files differnew file mode 100644 index 000000000..54620e210 --- /dev/null +++ b/res/drawable/stack_00009.png diff --git a/res/drawable/stack_00010.png b/res/drawable/stack_00010.png Binary files differnew file mode 100644 index 000000000..7ec4b8719 --- /dev/null +++ b/res/drawable/stack_00010.png diff --git a/res/drawable/stack_00011.png b/res/drawable/stack_00011.png Binary files differnew file mode 100644 index 000000000..300b98ac6 --- /dev/null +++ b/res/drawable/stack_00011.png diff --git a/res/drawable/stack_00012.png b/res/drawable/stack_00012.png Binary files differnew file mode 100644 index 000000000..eae0e919a --- /dev/null +++ b/res/drawable/stack_00012.png diff --git a/res/drawable/stack_00013.png b/res/drawable/stack_00013.png Binary files differnew file mode 100644 index 000000000..fa24d7461 --- /dev/null +++ b/res/drawable/stack_00013.png diff --git a/res/drawable/stack_00014.png b/res/drawable/stack_00014.png Binary files differnew file mode 100644 index 000000000..ad0a8108c --- /dev/null +++ b/res/drawable/stack_00014.png diff --git a/res/drawable/stack_00015.png b/res/drawable/stack_00015.png Binary files differnew file mode 100644 index 000000000..125950961 --- /dev/null +++ b/res/drawable/stack_00015.png diff --git a/res/drawable/stack_00016.png b/res/drawable/stack_00016.png Binary files differnew file mode 100644 index 000000000..cc0e9076b --- /dev/null +++ b/res/drawable/stack_00016.png diff --git a/res/drawable/stack_00017.png b/res/drawable/stack_00017.png Binary files differnew file mode 100644 index 000000000..174165b54 --- /dev/null +++ b/res/drawable/stack_00017.png diff --git a/res/drawable/stack_00018.png b/res/drawable/stack_00018.png Binary files differnew file mode 100644 index 000000000..0fb9cea69 --- /dev/null +++ b/res/drawable/stack_00018.png diff --git a/res/drawable/stack_00019.png b/res/drawable/stack_00019.png Binary files differnew file mode 100644 index 000000000..4a66a8fda --- /dev/null +++ b/res/drawable/stack_00019.png diff --git a/res/drawable/stack_00020.png b/res/drawable/stack_00020.png Binary files differnew file mode 100644 index 000000000..ebe970d76 --- /dev/null +++ b/res/drawable/stack_00020.png diff --git a/res/drawable/stack_00021.png b/res/drawable/stack_00021.png Binary files differnew file mode 100644 index 000000000..ebe970d76 --- /dev/null +++ b/res/drawable/stack_00021.png diff --git a/res/drawable/stack_00022.png b/res/drawable/stack_00022.png Binary files differnew file mode 100644 index 000000000..ebe970d76 --- /dev/null +++ b/res/drawable/stack_00022.png diff --git a/res/drawable/stack_00023.png b/res/drawable/stack_00023.png Binary files differnew file mode 100644 index 000000000..ebe970d76 --- /dev/null +++ b/res/drawable/stack_00023.png diff --git a/res/drawable/stack_00024.png b/res/drawable/stack_00024.png Binary files differnew file mode 100644 index 000000000..ebe970d76 --- /dev/null +++ b/res/drawable/stack_00024.png diff --git a/res/drawable/stack_00025.png b/res/drawable/stack_00025.png Binary files differnew file mode 100644 index 000000000..ebe970d76 --- /dev/null +++ b/res/drawable/stack_00025.png diff --git a/res/drawable/stack_00026.png b/res/drawable/stack_00026.png Binary files differnew file mode 100644 index 000000000..ebe970d76 --- /dev/null +++ b/res/drawable/stack_00026.png diff --git a/res/drawable/stack_00027.png b/res/drawable/stack_00027.png Binary files differnew file mode 100644 index 000000000..ebe970d76 --- /dev/null +++ b/res/drawable/stack_00027.png diff --git a/res/drawable/stack_00028.png b/res/drawable/stack_00028.png Binary files differnew file mode 100644 index 000000000..ebe970d76 --- /dev/null +++ b/res/drawable/stack_00028.png diff --git a/res/drawable/stack_00029.png b/res/drawable/stack_00029.png Binary files differnew file mode 100644 index 000000000..ebe970d76 --- /dev/null +++ b/res/drawable/stack_00029.png diff --git a/res/drawable/stack_00030.png b/res/drawable/stack_00030.png Binary files differnew file mode 100644 index 000000000..ebe970d76 --- /dev/null +++ b/res/drawable/stack_00030.png diff --git a/res/drawable/stack_00031.png b/res/drawable/stack_00031.png Binary files differnew file mode 100644 index 000000000..ebe970d76 --- /dev/null +++ b/res/drawable/stack_00031.png diff --git a/res/drawable/stack_00032.png b/res/drawable/stack_00032.png Binary files differnew file mode 100644 index 000000000..ebe970d76 --- /dev/null +++ b/res/drawable/stack_00032.png diff --git a/res/drawable/stack_00033.png b/res/drawable/stack_00033.png Binary files differnew file mode 100644 index 000000000..ebe970d76 --- /dev/null +++ b/res/drawable/stack_00033.png diff --git a/res/drawable/stack_00034.png b/res/drawable/stack_00034.png Binary files differnew file mode 100644 index 000000000..ebe970d76 --- /dev/null +++ b/res/drawable/stack_00034.png diff --git a/res/drawable/stack_00035.png b/res/drawable/stack_00035.png Binary files differnew file mode 100644 index 000000000..ebe970d76 --- /dev/null +++ b/res/drawable/stack_00035.png diff --git a/res/drawable/stack_00036.png b/res/drawable/stack_00036.png Binary files differnew file mode 100644 index 000000000..ebe970d76 --- /dev/null +++ b/res/drawable/stack_00036.png diff --git a/res/drawable/stack_00037.png b/res/drawable/stack_00037.png Binary files differnew file mode 100644 index 000000000..ebe970d76 --- /dev/null +++ b/res/drawable/stack_00037.png diff --git a/res/drawable/stack_00038.png b/res/drawable/stack_00038.png Binary files differnew file mode 100644 index 000000000..ebe970d76 --- /dev/null +++ b/res/drawable/stack_00038.png diff --git a/res/drawable/stack_00039.png b/res/drawable/stack_00039.png Binary files differnew file mode 100644 index 000000000..ebe970d76 --- /dev/null +++ b/res/drawable/stack_00039.png diff --git a/res/drawable/stack_00040.png b/res/drawable/stack_00040.png Binary files differnew file mode 100644 index 000000000..ebe970d76 --- /dev/null +++ b/res/drawable/stack_00040.png diff --git a/res/drawable/stack_00041.png b/res/drawable/stack_00041.png Binary files differnew file mode 100644 index 000000000..ebe970d76 --- /dev/null +++ b/res/drawable/stack_00041.png diff --git a/res/drawable/stack_00042.png b/res/drawable/stack_00042.png Binary files differnew file mode 100644 index 000000000..ebe970d76 --- /dev/null +++ b/res/drawable/stack_00042.png diff --git a/res/drawable/stack_00043.png b/res/drawable/stack_00043.png Binary files differnew file mode 100644 index 000000000..ebe970d76 --- /dev/null +++ b/res/drawable/stack_00043.png diff --git a/res/drawable/stack_00044.png b/res/drawable/stack_00044.png Binary files differnew file mode 100644 index 000000000..ebe970d76 --- /dev/null +++ b/res/drawable/stack_00044.png diff --git a/res/drawable/stack_00045.png b/res/drawable/stack_00045.png Binary files differnew file mode 100644 index 000000000..ebe970d76 --- /dev/null +++ b/res/drawable/stack_00045.png diff --git a/res/drawable/stack_00046.png b/res/drawable/stack_00046.png Binary files differnew file mode 100644 index 000000000..ebe970d76 --- /dev/null +++ b/res/drawable/stack_00046.png diff --git a/res/drawable/stack_00047.png b/res/drawable/stack_00047.png Binary files differnew file mode 100644 index 000000000..ebe970d76 --- /dev/null +++ b/res/drawable/stack_00047.png diff --git a/res/drawable/stack_00048.png b/res/drawable/stack_00048.png Binary files differnew file mode 100644 index 000000000..ebe970d76 --- /dev/null +++ b/res/drawable/stack_00048.png diff --git a/res/drawable/stack_00049.png b/res/drawable/stack_00049.png Binary files differnew file mode 100644 index 000000000..ebe970d76 --- /dev/null +++ b/res/drawable/stack_00049.png diff --git a/res/drawable/setting_button.xml b/res/drawable/themes_button.xml index 4d66a1ac7..3006b9a6e 100644 --- a/res/drawable/setting_button.xml +++ b/res/drawable/themes_button.xml @@ -15,7 +15,7 @@ --> <selector xmlns:android="http://schemas.android.com/apk/res/android"> - <item android:state_focused="true" android:drawable="@drawable/ic_setting_pressed" /> - <item android:state_pressed="true" android:drawable="@drawable/ic_setting_pressed" /> - <item android:drawable="@drawable/ic_setting" /> + <item android:state_focused="true" android:drawable="@drawable/ic_themes_pressed" /> + <item android:state_pressed="true" android:drawable="@drawable/ic_themes_pressed" /> + <item android:drawable="@drawable/ic_themes" /> </selector> diff --git a/res/drawable/transition_accordion.xml b/res/drawable/transition_accordion.xml new file mode 100644 index 000000000..5650ba2e6 --- /dev/null +++ b/res/drawable/transition_accordion.xml @@ -0,0 +1,54 @@ +<animation-list + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/transition_accordian" android:oneshot="false"> + <item android:drawable="@drawable/acordian_00000" android:duration="30" /> + <item android:drawable="@drawable/acordian_00001" android:duration="30" /> + <item android:drawable="@drawable/acordian_00002" android:duration="30" /> + <item android:drawable="@drawable/acordian_00003" android:duration="30" /> + <item android:drawable="@drawable/acordian_00004" android:duration="30" /> + <item android:drawable="@drawable/acordian_00005" android:duration="30" /> + <item android:drawable="@drawable/acordian_00006" android:duration="30" /> + <item android:drawable="@drawable/acordian_00007" android:duration="30" /> + <item android:drawable="@drawable/acordian_00008" android:duration="30" /> + <item android:drawable="@drawable/acordian_00009" android:duration="30" /> + <item android:drawable="@drawable/acordian_00010" android:duration="30" /> + <item android:drawable="@drawable/acordian_00011" android:duration="30" /> + <item android:drawable="@drawable/acordian_00012" android:duration="30" /> + <item android:drawable="@drawable/acordian_00013" android:duration="30" /> + <item android:drawable="@drawable/acordian_00014" android:duration="30" /> + <item android:drawable="@drawable/acordian_00015" android:duration="30" /> + <item android:drawable="@drawable/acordian_00016" android:duration="30" /> + <item android:drawable="@drawable/acordian_00017" android:duration="30" /> + <item android:drawable="@drawable/acordian_00018" android:duration="30" /> + <item android:drawable="@drawable/acordian_00019" android:duration="30" /> + <item android:drawable="@drawable/acordian_00020" android:duration="30" /> + <item android:drawable="@drawable/acordian_00021" android:duration="30" /> + <item android:drawable="@drawable/acordian_00022" android:duration="30" /> + <item android:drawable="@drawable/acordian_00023" android:duration="30" /> + <item android:drawable="@drawable/acordian_00024" android:duration="30" /> + <item android:drawable="@drawable/acordian_00025" android:duration="30" /> + <item android:drawable="@drawable/acordian_00026" android:duration="30" /> + <item android:drawable="@drawable/acordian_00027" android:duration="30" /> + <item android:drawable="@drawable/acordian_00028" android:duration="30" /> + <item android:drawable="@drawable/acordian_00029" android:duration="30" /> + <item android:drawable="@drawable/acordian_00030" android:duration="30" /> + <item android:drawable="@drawable/acordian_00031" android:duration="30" /> + <item android:drawable="@drawable/acordian_00032" android:duration="30" /> + <item android:drawable="@drawable/acordian_00033" android:duration="30" /> + <item android:drawable="@drawable/acordian_00034" android:duration="30" /> + <item android:drawable="@drawable/acordian_00035" android:duration="30" /> + <item android:drawable="@drawable/acordian_00036" android:duration="30" /> + <item android:drawable="@drawable/acordian_00037" android:duration="30" /> + <item android:drawable="@drawable/acordian_00038" android:duration="30" /> + <item android:drawable="@drawable/acordian_00039" android:duration="30" /> + <item android:drawable="@drawable/acordian_00040" android:duration="30" /> + <item android:drawable="@drawable/acordian_00041" android:duration="30" /> + <item android:drawable="@drawable/acordian_00042" android:duration="30" /> + <item android:drawable="@drawable/acordian_00043" android:duration="30" /> + <item android:drawable="@drawable/acordian_00044" android:duration="30" /> + <item android:drawable="@drawable/acordian_00045" android:duration="30" /> + <item android:drawable="@drawable/acordian_00046" android:duration="30" /> + <item android:drawable="@drawable/acordian_00047" android:duration="30" /> + <item android:drawable="@drawable/acordian_00048" android:duration="30" /> + <item android:drawable="@drawable/acordian_00049" android:duration="30" /> +</animation-list> diff --git a/res/drawable/transition_arrow.xml b/res/drawable/transition_arrow.xml new file mode 100644 index 000000000..540db93d8 --- /dev/null +++ b/res/drawable/transition_arrow.xml @@ -0,0 +1,21 @@ +<animation-list + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/transition_arrow" android:oneshot="true"> + <item android:drawable="@drawable/launcheranimatedarrow_00000" android:duration="30" /> + <item android:drawable="@drawable/launcheranimatedarrow_00001" android:duration="30" /> + <item android:drawable="@drawable/launcheranimatedarrow_00002" android:duration="30" /> + <item android:drawable="@drawable/launcheranimatedarrow_00003" android:duration="30" /> + <item android:drawable="@drawable/launcheranimatedarrow_00004" android:duration="30" /> + <item android:drawable="@drawable/launcheranimatedarrow_00005" android:duration="30" /> + <item android:drawable="@drawable/launcheranimatedarrow_00006" android:duration="30" /> + <item android:drawable="@drawable/launcheranimatedarrow_00007" android:duration="30" /> + <item android:drawable="@drawable/launcheranimatedarrow_00008" android:duration="30" /> + <item android:drawable="@drawable/launcheranimatedarrow_00009" android:duration="30" /> + <item android:drawable="@drawable/launcheranimatedarrow_00010" android:duration="30" /> + <item android:drawable="@drawable/launcheranimatedarrow_00011" android:duration="30" /> + <item android:drawable="@drawable/launcheranimatedarrow_00012" android:duration="30" /> + <item android:drawable="@drawable/launcheranimatedarrow_00013" android:duration="30" /> + <item android:drawable="@drawable/launcheranimatedarrow_00014" android:duration="30" /> + <item android:drawable="@drawable/launcheranimatedarrow_00015" android:duration="30" /> + <item android:drawable="@drawable/launcheranimatedarrow_00016" android:duration="30" /> +</animation-list> diff --git a/res/drawable/transition_arrow_reverse.xml b/res/drawable/transition_arrow_reverse.xml new file mode 100644 index 000000000..855f08fb4 --- /dev/null +++ b/res/drawable/transition_arrow_reverse.xml @@ -0,0 +1,21 @@ +<animation-list + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/transition_arrow_reverse" android:oneshot="true"> + <item android:drawable="@drawable/launcheranimatedarrow_00016" android:duration="30" /> + <item android:drawable="@drawable/launcheranimatedarrow_00015" android:duration="30" /> + <item android:drawable="@drawable/launcheranimatedarrow_00014" android:duration="30" /> + <item android:drawable="@drawable/launcheranimatedarrow_00013" android:duration="30" /> + <item android:drawable="@drawable/launcheranimatedarrow_00012" android:duration="30" /> + <item android:drawable="@drawable/launcheranimatedarrow_00011" android:duration="30" /> + <item android:drawable="@drawable/launcheranimatedarrow_00010" android:duration="30" /> + <item android:drawable="@drawable/launcheranimatedarrow_00009" android:duration="30" /> + <item android:drawable="@drawable/launcheranimatedarrow_00008" android:duration="30" /> + <item android:drawable="@drawable/launcheranimatedarrow_00007" android:duration="30" /> + <item android:drawable="@drawable/launcheranimatedarrow_00006" android:duration="30" /> + <item android:drawable="@drawable/launcheranimatedarrow_00005" android:duration="30" /> + <item android:drawable="@drawable/launcheranimatedarrow_00004" android:duration="30" /> + <item android:drawable="@drawable/launcheranimatedarrow_00003" android:duration="30" /> + <item android:drawable="@drawable/launcheranimatedarrow_00002" android:duration="30" /> + <item android:drawable="@drawable/launcheranimatedarrow_00001" android:duration="30" /> + <item android:drawable="@drawable/launcheranimatedarrow_00000" android:duration="30" /> +</animation-list> diff --git a/res/drawable/transition_carousel.xml b/res/drawable/transition_carousel.xml new file mode 100644 index 000000000..bebb5c006 --- /dev/null +++ b/res/drawable/transition_carousel.xml @@ -0,0 +1,55 @@ +<animation-list + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/transition_carousel" android:oneshot="false"> + <item android:drawable="@drawable/carousel_00000" android:duration="30" /> + <item android:drawable="@drawable/carousel_00001" android:duration="30" /> + <item android:drawable="@drawable/carousel_00002" android:duration="30" /> + <item android:drawable="@drawable/carousel_00003" android:duration="30" /> + <item android:drawable="@drawable/carousel_00004" android:duration="30" /> + <item android:drawable="@drawable/carousel_00005" android:duration="30" /> + <item android:drawable="@drawable/carousel_00006" android:duration="30" /> + <item android:drawable="@drawable/carousel_00007" android:duration="30" /> + <item android:drawable="@drawable/carousel_00008" android:duration="30" /> + <item android:drawable="@drawable/carousel_00009" android:duration="30" /> + <item android:drawable="@drawable/carousel_00010" android:duration="30" /> + <item android:drawable="@drawable/carousel_00011" android:duration="30" /> + <item android:drawable="@drawable/carousel_00012" android:duration="30" /> + <item android:drawable="@drawable/carousel_00013" android:duration="30" /> + <item android:drawable="@drawable/carousel_00014" android:duration="30" /> + <item android:drawable="@drawable/carousel_00015" android:duration="30" /> + <item android:drawable="@drawable/carousel_00016" android:duration="30" /> + <item android:drawable="@drawable/carousel_00017" android:duration="30" /> + <item android:drawable="@drawable/carousel_00018" android:duration="30" /> + <item android:drawable="@drawable/carousel_00019" android:duration="30" /> + <item android:drawable="@drawable/carousel_00020" android:duration="30" /> + <item android:drawable="@drawable/carousel_00021" android:duration="30" /> + <item android:drawable="@drawable/carousel_00022" android:duration="30" /> + <item android:drawable="@drawable/carousel_00023" android:duration="30" /> + <item android:drawable="@drawable/carousel_00024" android:duration="30" /> + <item android:drawable="@drawable/carousel_00025" android:duration="30" /> + <item android:drawable="@drawable/carousel_00026" android:duration="30" /> + <item android:drawable="@drawable/carousel_00027" android:duration="30" /> + <item android:drawable="@drawable/carousel_00028" android:duration="30" /> + <item android:drawable="@drawable/carousel_00029" android:duration="30" /> + <item android:drawable="@drawable/carousel_00030" android:duration="30" /> + <item android:drawable="@drawable/carousel_00031" android:duration="30" /> + <item android:drawable="@drawable/carousel_00032" android:duration="30" /> + <item android:drawable="@drawable/carousel_00033" android:duration="30" /> + <item android:drawable="@drawable/carousel_00034" android:duration="30" /> + <item android:drawable="@drawable/carousel_00035" android:duration="30" /> + <item android:drawable="@drawable/carousel_00036" android:duration="30" /> + <item android:drawable="@drawable/carousel_00037" android:duration="30" /> + <item android:drawable="@drawable/carousel_00038" android:duration="30" /> + <item android:drawable="@drawable/carousel_00039" android:duration="30" /> + <item android:drawable="@drawable/carousel_00040" android:duration="30" /> + <item android:drawable="@drawable/carousel_00041" android:duration="30" /> + <item android:drawable="@drawable/carousel_00042" android:duration="30" /> + <item android:drawable="@drawable/carousel_00043" android:duration="30" /> + <item android:drawable="@drawable/carousel_00044" android:duration="30" /> + <item android:drawable="@drawable/carousel_00045" android:duration="30" /> + <item android:drawable="@drawable/carousel_00046" android:duration="30" /> + <item android:drawable="@drawable/carousel_00047" android:duration="30" /> + <item android:drawable="@drawable/carousel_00048" android:duration="30" /> + <item android:drawable="@drawable/carousel_00049" android:duration="30" /> + <item android:drawable="@drawable/carousel_00049" android:duration="30" /> +</animation-list> diff --git a/res/drawable/transition_cubein.xml b/res/drawable/transition_cubein.xml new file mode 100644 index 000000000..b5a9321f3 --- /dev/null +++ b/res/drawable/transition_cubein.xml @@ -0,0 +1,55 @@ +<animation-list + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/transition_cubein" android:oneshot="false"> + <item android:drawable="@drawable/cubein_00000" android:duration="30" /> + <item android:drawable="@drawable/cubein_00001" android:duration="30" /> + <item android:drawable="@drawable/cubein_00002" android:duration="30" /> + <item android:drawable="@drawable/cubein_00003" android:duration="30" /> + <item android:drawable="@drawable/cubein_00004" android:duration="30" /> + <item android:drawable="@drawable/cubein_00005" android:duration="30" /> + <item android:drawable="@drawable/cubein_00006" android:duration="30" /> + <item android:drawable="@drawable/cubein_00007" android:duration="30" /> + <item android:drawable="@drawable/cubein_00008" android:duration="30" /> + <item android:drawable="@drawable/cubein_00009" android:duration="30" /> + <item android:drawable="@drawable/cubein_00010" android:duration="30" /> + <item android:drawable="@drawable/cubein_00011" android:duration="30" /> + <item android:drawable="@drawable/cubein_00012" android:duration="30" /> + <item android:drawable="@drawable/cubein_00013" android:duration="30" /> + <item android:drawable="@drawable/cubein_00014" android:duration="30" /> + <item android:drawable="@drawable/cubein_00015" android:duration="30" /> + <item android:drawable="@drawable/cubein_00016" android:duration="30" /> + <item android:drawable="@drawable/cubein_00017" android:duration="30" /> + <item android:drawable="@drawable/cubein_00018" android:duration="30" /> + <item android:drawable="@drawable/cubein_00019" android:duration="30" /> + <item android:drawable="@drawable/cubein_00020" android:duration="30" /> + <item android:drawable="@drawable/cubein_00021" android:duration="30" /> + <item android:drawable="@drawable/cubein_00022" android:duration="30" /> + <item android:drawable="@drawable/cubein_00023" android:duration="30" /> + <item android:drawable="@drawable/cubein_00024" android:duration="30" /> + <item android:drawable="@drawable/cubein_00025" android:duration="30" /> + <item android:drawable="@drawable/cubein_00026" android:duration="30" /> + <item android:drawable="@drawable/cubein_00027" android:duration="30" /> + <item android:drawable="@drawable/cubein_00028" android:duration="30" /> + <item android:drawable="@drawable/cubein_00029" android:duration="30" /> + <item android:drawable="@drawable/cubein_00030" android:duration="30" /> + <item android:drawable="@drawable/cubein_00031" android:duration="30" /> + <item android:drawable="@drawable/cubein_00032" android:duration="30" /> + <item android:drawable="@drawable/cubein_00033" android:duration="30" /> + <item android:drawable="@drawable/cubein_00034" android:duration="30" /> + <item android:drawable="@drawable/cubein_00035" android:duration="30" /> + <item android:drawable="@drawable/cubein_00036" android:duration="30" /> + <item android:drawable="@drawable/cubein_00037" android:duration="30" /> + <item android:drawable="@drawable/cubein_00038" android:duration="30" /> + <item android:drawable="@drawable/cubein_00039" android:duration="30" /> + <item android:drawable="@drawable/cubein_00040" android:duration="30" /> + <item android:drawable="@drawable/cubein_00041" android:duration="30" /> + <item android:drawable="@drawable/cubein_00042" android:duration="30" /> + <item android:drawable="@drawable/cubein_00043" android:duration="30" /> + <item android:drawable="@drawable/cubein_00044" android:duration="30" /> + <item android:drawable="@drawable/cubein_00045" android:duration="30" /> + <item android:drawable="@drawable/cubein_00046" android:duration="30" /> + <item android:drawable="@drawable/cubein_00047" android:duration="30" /> + <item android:drawable="@drawable/cubein_00048" android:duration="30" /> + <item android:drawable="@drawable/cubein_00049" android:duration="30" /> + <item android:drawable="@drawable/cubein_00049" android:duration="30" /> +</animation-list> diff --git a/res/drawable/transition_cubeout.xml b/res/drawable/transition_cubeout.xml new file mode 100644 index 000000000..c8694bb6f --- /dev/null +++ b/res/drawable/transition_cubeout.xml @@ -0,0 +1,55 @@ +<animation-list + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/transition_cubeout" android:oneshot="false"> + <item android:drawable="@drawable/cubeout_00000" android:duration="30" /> + <item android:drawable="@drawable/cubeout_00001" android:duration="30" /> + <item android:drawable="@drawable/cubeout_00002" android:duration="30" /> + <item android:drawable="@drawable/cubeout_00003" android:duration="30" /> + <item android:drawable="@drawable/cubeout_00004" android:duration="30" /> + <item android:drawable="@drawable/cubeout_00005" android:duration="30" /> + <item android:drawable="@drawable/cubeout_00006" android:duration="30" /> + <item android:drawable="@drawable/cubeout_00007" android:duration="30" /> + <item android:drawable="@drawable/cubeout_00008" android:duration="30" /> + <item android:drawable="@drawable/cubeout_00009" android:duration="30" /> + <item android:drawable="@drawable/cubeout_00010" android:duration="30" /> + <item android:drawable="@drawable/cubeout_00011" android:duration="30" /> + <item android:drawable="@drawable/cubeout_00012" android:duration="30" /> + <item android:drawable="@drawable/cubeout_00013" android:duration="30" /> + <item android:drawable="@drawable/cubeout_00014" android:duration="30" /> + <item android:drawable="@drawable/cubeout_00015" android:duration="30" /> + <item android:drawable="@drawable/cubeout_00016" android:duration="30" /> + <item android:drawable="@drawable/cubeout_00017" android:duration="30" /> + <item android:drawable="@drawable/cubeout_00018" android:duration="30" /> + <item android:drawable="@drawable/cubeout_00019" android:duration="30" /> + <item android:drawable="@drawable/cubeout_00020" android:duration="30" /> + <item android:drawable="@drawable/cubeout_00021" android:duration="30" /> + <item android:drawable="@drawable/cubeout_00022" android:duration="30" /> + <item android:drawable="@drawable/cubeout_00023" android:duration="30" /> + <item android:drawable="@drawable/cubeout_00024" android:duration="30" /> + <item android:drawable="@drawable/cubeout_00025" android:duration="30" /> + <item android:drawable="@drawable/cubeout_00026" android:duration="30" /> + <item android:drawable="@drawable/cubeout_00027" android:duration="30" /> + <item android:drawable="@drawable/cubeout_00028" android:duration="30" /> + <item android:drawable="@drawable/cubeout_00029" android:duration="30" /> + <item android:drawable="@drawable/cubeout_00030" android:duration="30" /> + <item android:drawable="@drawable/cubeout_00031" android:duration="30" /> + <item android:drawable="@drawable/cubeout_00032" android:duration="30" /> + <item android:drawable="@drawable/cubeout_00033" android:duration="30" /> + <item android:drawable="@drawable/cubeout_00034" android:duration="30" /> + <item android:drawable="@drawable/cubeout_00035" android:duration="30" /> + <item android:drawable="@drawable/cubeout_00036" android:duration="30" /> + <item android:drawable="@drawable/cubeout_00037" android:duration="30" /> + <item android:drawable="@drawable/cubeout_00038" android:duration="30" /> + <item android:drawable="@drawable/cubeout_00039" android:duration="30" /> + <item android:drawable="@drawable/cubeout_00040" android:duration="30" /> + <item android:drawable="@drawable/cubeout_00041" android:duration="30" /> + <item android:drawable="@drawable/cubeout_00042" android:duration="30" /> + <item android:drawable="@drawable/cubeout_00043" android:duration="30" /> + <item android:drawable="@drawable/cubeout_00044" android:duration="30" /> + <item android:drawable="@drawable/cubeout_00045" android:duration="30" /> + <item android:drawable="@drawable/cubeout_00046" android:duration="30" /> + <item android:drawable="@drawable/cubeout_00047" android:duration="30" /> + <item android:drawable="@drawable/cubeout_00048" android:duration="30" /> + <item android:drawable="@drawable/cubeout_00049" android:duration="30" /> + <item android:drawable="@drawable/cubeout_00049" android:duration="30" /> +</animation-list> diff --git a/res/drawable/transition_cylinderin.xml b/res/drawable/transition_cylinderin.xml new file mode 100644 index 000000000..e51d32e9c --- /dev/null +++ b/res/drawable/transition_cylinderin.xml @@ -0,0 +1,55 @@ +<animation-list + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/transition_cylinderin" android:oneshot="false"> + <item android:drawable="@drawable/cylinderin_00000" android:duration="30" /> + <item android:drawable="@drawable/cylinderin_00001" android:duration="30" /> + <item android:drawable="@drawable/cylinderin_00002" android:duration="30" /> + <item android:drawable="@drawable/cylinderin_00003" android:duration="30" /> + <item android:drawable="@drawable/cylinderin_00004" android:duration="30" /> + <item android:drawable="@drawable/cylinderin_00005" android:duration="30" /> + <item android:drawable="@drawable/cylinderin_00006" android:duration="30" /> + <item android:drawable="@drawable/cylinderin_00007" android:duration="30" /> + <item android:drawable="@drawable/cylinderin_00008" android:duration="30" /> + <item android:drawable="@drawable/cylinderin_00009" android:duration="30" /> + <item android:drawable="@drawable/cylinderin_00010" android:duration="30" /> + <item android:drawable="@drawable/cylinderin_00011" android:duration="30" /> + <item android:drawable="@drawable/cylinderin_00012" android:duration="30" /> + <item android:drawable="@drawable/cylinderin_00013" android:duration="30" /> + <item android:drawable="@drawable/cylinderin_00014" android:duration="30" /> + <item android:drawable="@drawable/cylinderin_00015" android:duration="30" /> + <item android:drawable="@drawable/cylinderin_00016" android:duration="30" /> + <item android:drawable="@drawable/cylinderin_00017" android:duration="30" /> + <item android:drawable="@drawable/cylinderin_00018" android:duration="30" /> + <item android:drawable="@drawable/cylinderin_00019" android:duration="30" /> + <item android:drawable="@drawable/cylinderin_00020" android:duration="30" /> + <item android:drawable="@drawable/cylinderin_00021" android:duration="30" /> + <item android:drawable="@drawable/cylinderin_00022" android:duration="30" /> + <item android:drawable="@drawable/cylinderin_00023" android:duration="30" /> + <item android:drawable="@drawable/cylinderin_00024" android:duration="30" /> + <item android:drawable="@drawable/cylinderin_00025" android:duration="30" /> + <item android:drawable="@drawable/cylinderin_00026" android:duration="30" /> + <item android:drawable="@drawable/cylinderin_00027" android:duration="30" /> + <item android:drawable="@drawable/cylinderin_00028" android:duration="30" /> + <item android:drawable="@drawable/cylinderin_00029" android:duration="30" /> + <item android:drawable="@drawable/cylinderin_00030" android:duration="30" /> + <item android:drawable="@drawable/cylinderin_00031" android:duration="30" /> + <item android:drawable="@drawable/cylinderin_00032" android:duration="30" /> + <item android:drawable="@drawable/cylinderin_00033" android:duration="30" /> + <item android:drawable="@drawable/cylinderin_00034" android:duration="30" /> + <item android:drawable="@drawable/cylinderin_00035" android:duration="30" /> + <item android:drawable="@drawable/cylinderin_00036" android:duration="30" /> + <item android:drawable="@drawable/cylinderin_00037" android:duration="30" /> + <item android:drawable="@drawable/cylinderin_00038" android:duration="30" /> + <item android:drawable="@drawable/cylinderin_00039" android:duration="30" /> + <item android:drawable="@drawable/cylinderin_00040" android:duration="30" /> + <item android:drawable="@drawable/cylinderin_00041" android:duration="30" /> + <item android:drawable="@drawable/cylinderin_00042" android:duration="30" /> + <item android:drawable="@drawable/cylinderin_00043" android:duration="30" /> + <item android:drawable="@drawable/cylinderin_00044" android:duration="30" /> + <item android:drawable="@drawable/cylinderin_00045" android:duration="30" /> + <item android:drawable="@drawable/cylinderin_00046" android:duration="30" /> + <item android:drawable="@drawable/cylinderin_00047" android:duration="30" /> + <item android:drawable="@drawable/cylinderin_00048" android:duration="30" /> + <item android:drawable="@drawable/cylinderin_00049" android:duration="30" /> + <item android:drawable="@drawable/cylinderin_00049" android:duration="30" /> +</animation-list> diff --git a/res/drawable/transition_cylinderout.xml b/res/drawable/transition_cylinderout.xml new file mode 100644 index 000000000..451964ee2 --- /dev/null +++ b/res/drawable/transition_cylinderout.xml @@ -0,0 +1,55 @@ +<animation-list + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/transition_cylinderout" android:oneshot="false"> + <item android:drawable="@drawable/cylinderout_00000" android:duration="30" /> + <item android:drawable="@drawable/cylinderout_00001" android:duration="30" /> + <item android:drawable="@drawable/cylinderout_00002" android:duration="30" /> + <item android:drawable="@drawable/cylinderout_00003" android:duration="30" /> + <item android:drawable="@drawable/cylinderout_00004" android:duration="30" /> + <item android:drawable="@drawable/cylinderout_00005" android:duration="30" /> + <item android:drawable="@drawable/cylinderout_00006" android:duration="30" /> + <item android:drawable="@drawable/cylinderout_00007" android:duration="30" /> + <item android:drawable="@drawable/cylinderout_00008" android:duration="30" /> + <item android:drawable="@drawable/cylinderout_00009" android:duration="30" /> + <item android:drawable="@drawable/cylinderout_00010" android:duration="30" /> + <item android:drawable="@drawable/cylinderout_00011" android:duration="30" /> + <item android:drawable="@drawable/cylinderout_00012" android:duration="30" /> + <item android:drawable="@drawable/cylinderout_00013" android:duration="30" /> + <item android:drawable="@drawable/cylinderout_00014" android:duration="30" /> + <item android:drawable="@drawable/cylinderout_00015" android:duration="30" /> + <item android:drawable="@drawable/cylinderout_00016" android:duration="30" /> + <item android:drawable="@drawable/cylinderout_00017" android:duration="30" /> + <item android:drawable="@drawable/cylinderout_00018" android:duration="30" /> + <item android:drawable="@drawable/cylinderout_00019" android:duration="30" /> + <item android:drawable="@drawable/cylinderout_00020" android:duration="30" /> + <item android:drawable="@drawable/cylinderout_00021" android:duration="30" /> + <item android:drawable="@drawable/cylinderout_00022" android:duration="30" /> + <item android:drawable="@drawable/cylinderout_00023" android:duration="30" /> + <item android:drawable="@drawable/cylinderout_00024" android:duration="30" /> + <item android:drawable="@drawable/cylinderout_00025" android:duration="30" /> + <item android:drawable="@drawable/cylinderout_00026" android:duration="30" /> + <item android:drawable="@drawable/cylinderout_00027" android:duration="30" /> + <item android:drawable="@drawable/cylinderout_00028" android:duration="30" /> + <item android:drawable="@drawable/cylinderout_00029" android:duration="30" /> + <item android:drawable="@drawable/cylinderout_00030" android:duration="30" /> + <item android:drawable="@drawable/cylinderout_00031" android:duration="30" /> + <item android:drawable="@drawable/cylinderout_00032" android:duration="30" /> + <item android:drawable="@drawable/cylinderout_00033" android:duration="30" /> + <item android:drawable="@drawable/cylinderout_00034" android:duration="30" /> + <item android:drawable="@drawable/cylinderout_00035" android:duration="30" /> + <item android:drawable="@drawable/cylinderout_00036" android:duration="30" /> + <item android:drawable="@drawable/cylinderout_00037" android:duration="30" /> + <item android:drawable="@drawable/cylinderout_00038" android:duration="30" /> + <item android:drawable="@drawable/cylinderout_00039" android:duration="30" /> + <item android:drawable="@drawable/cylinderout_00040" android:duration="30" /> + <item android:drawable="@drawable/cylinderout_00041" android:duration="30" /> + <item android:drawable="@drawable/cylinderout_00042" android:duration="30" /> + <item android:drawable="@drawable/cylinderout_00043" android:duration="30" /> + <item android:drawable="@drawable/cylinderout_00044" android:duration="30" /> + <item android:drawable="@drawable/cylinderout_00045" android:duration="30" /> + <item android:drawable="@drawable/cylinderout_00046" android:duration="30" /> + <item android:drawable="@drawable/cylinderout_00047" android:duration="30" /> + <item android:drawable="@drawable/cylinderout_00048" android:duration="30" /> + <item android:drawable="@drawable/cylinderout_00049" android:duration="30" /> + <item android:drawable="@drawable/cylinderout_00049" android:duration="30" /> +</animation-list> diff --git a/res/drawable/transition_flip.xml b/res/drawable/transition_flip.xml new file mode 100644 index 000000000..30897202e --- /dev/null +++ b/res/drawable/transition_flip.xml @@ -0,0 +1,55 @@ +<animation-list + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/transition_flip" android:oneshot="false"> + <item android:drawable="@drawable/flip_00000" android:duration="30" /> + <item android:drawable="@drawable/flip_00001" android:duration="30" /> + <item android:drawable="@drawable/flip_00002" android:duration="30" /> + <item android:drawable="@drawable/flip_00003" android:duration="30" /> + <item android:drawable="@drawable/flip_00004" android:duration="30" /> + <item android:drawable="@drawable/flip_00005" android:duration="30" /> + <item android:drawable="@drawable/flip_00006" android:duration="30" /> + <item android:drawable="@drawable/flip_00007" android:duration="30" /> + <item android:drawable="@drawable/flip_00008" android:duration="30" /> + <item android:drawable="@drawable/flip_00009" android:duration="30" /> + <item android:drawable="@drawable/flip_00010" android:duration="30" /> + <item android:drawable="@drawable/flip_00011" android:duration="30" /> + <item android:drawable="@drawable/flip_00012" android:duration="30" /> + <item android:drawable="@drawable/flip_00013" android:duration="30" /> + <item android:drawable="@drawable/flip_00014" android:duration="30" /> + <item android:drawable="@drawable/flip_00015" android:duration="30" /> + <item android:drawable="@drawable/flip_00016" android:duration="30" /> + <item android:drawable="@drawable/flip_00017" android:duration="30" /> + <item android:drawable="@drawable/flip_00018" android:duration="30" /> + <item android:drawable="@drawable/flip_00019" android:duration="30" /> + <item android:drawable="@drawable/flip_00020" android:duration="30" /> + <item android:drawable="@drawable/flip_00021" android:duration="30" /> + <item android:drawable="@drawable/flip_00022" android:duration="30" /> + <item android:drawable="@drawable/flip_00023" android:duration="30" /> + <item android:drawable="@drawable/flip_00024" android:duration="30" /> + <item android:drawable="@drawable/flip_00025" android:duration="30" /> + <item android:drawable="@drawable/flip_00026" android:duration="30" /> + <item android:drawable="@drawable/flip_00027" android:duration="30" /> + <item android:drawable="@drawable/flip_00028" android:duration="30" /> + <item android:drawable="@drawable/flip_00029" android:duration="30" /> + <item android:drawable="@drawable/flip_00030" android:duration="30" /> + <item android:drawable="@drawable/flip_00031" android:duration="30" /> + <item android:drawable="@drawable/flip_00032" android:duration="30" /> + <item android:drawable="@drawable/flip_00033" android:duration="30" /> + <item android:drawable="@drawable/flip_00034" android:duration="30" /> + <item android:drawable="@drawable/flip_00035" android:duration="30" /> + <item android:drawable="@drawable/flip_00036" android:duration="30" /> + <item android:drawable="@drawable/flip_00037" android:duration="30" /> + <item android:drawable="@drawable/flip_00038" android:duration="30" /> + <item android:drawable="@drawable/flip_00039" android:duration="30" /> + <item android:drawable="@drawable/flip_00040" android:duration="30" /> + <item android:drawable="@drawable/flip_00041" android:duration="30" /> + <item android:drawable="@drawable/flip_00042" android:duration="30" /> + <item android:drawable="@drawable/flip_00043" android:duration="30" /> + <item android:drawable="@drawable/flip_00044" android:duration="30" /> + <item android:drawable="@drawable/flip_00045" android:duration="30" /> + <item android:drawable="@drawable/flip_00046" android:duration="30" /> + <item android:drawable="@drawable/flip_00047" android:duration="30" /> + <item android:drawable="@drawable/flip_00048" android:duration="30" /> + <item android:drawable="@drawable/flip_00049" android:duration="30" /> + <item android:drawable="@drawable/flip_00049" android:duration="30" /> +</animation-list> diff --git a/res/drawable/transition_none.xml b/res/drawable/transition_none.xml new file mode 100644 index 000000000..e357939b5 --- /dev/null +++ b/res/drawable/transition_none.xml @@ -0,0 +1,55 @@ +<animation-list + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/transition_none" android:oneshot="false"> + <item android:drawable="@drawable/none_00000" android:duration="30" /> + <item android:drawable="@drawable/none_00001" android:duration="30" /> + <item android:drawable="@drawable/none_00002" android:duration="30" /> + <item android:drawable="@drawable/none_00003" android:duration="30" /> + <item android:drawable="@drawable/none_00004" android:duration="30" /> + <item android:drawable="@drawable/none_00005" android:duration="30" /> + <item android:drawable="@drawable/none_00006" android:duration="30" /> + <item android:drawable="@drawable/none_00007" android:duration="30" /> + <item android:drawable="@drawable/none_00008" android:duration="30" /> + <item android:drawable="@drawable/none_00009" android:duration="30" /> + <item android:drawable="@drawable/none_00010" android:duration="30" /> + <item android:drawable="@drawable/none_00011" android:duration="30" /> + <item android:drawable="@drawable/none_00012" android:duration="30" /> + <item android:drawable="@drawable/none_00013" android:duration="30" /> + <item android:drawable="@drawable/none_00014" android:duration="30" /> + <item android:drawable="@drawable/none_00015" android:duration="30" /> + <item android:drawable="@drawable/none_00016" android:duration="30" /> + <item android:drawable="@drawable/none_00017" android:duration="30" /> + <item android:drawable="@drawable/none_00018" android:duration="30" /> + <item android:drawable="@drawable/none_00019" android:duration="30" /> + <item android:drawable="@drawable/none_00020" android:duration="30" /> + <item android:drawable="@drawable/none_00021" android:duration="30" /> + <item android:drawable="@drawable/none_00022" android:duration="30" /> + <item android:drawable="@drawable/none_00023" android:duration="30" /> + <item android:drawable="@drawable/none_00024" android:duration="30" /> + <item android:drawable="@drawable/none_00025" android:duration="30" /> + <item android:drawable="@drawable/none_00026" android:duration="30" /> + <item android:drawable="@drawable/none_00027" android:duration="30" /> + <item android:drawable="@drawable/none_00028" android:duration="30" /> + <item android:drawable="@drawable/none_00029" android:duration="30" /> + <item android:drawable="@drawable/none_00030" android:duration="30" /> + <item android:drawable="@drawable/none_00031" android:duration="30" /> + <item android:drawable="@drawable/none_00032" android:duration="30" /> + <item android:drawable="@drawable/none_00033" android:duration="30" /> + <item android:drawable="@drawable/none_00034" android:duration="30" /> + <item android:drawable="@drawable/none_00035" android:duration="30" /> + <item android:drawable="@drawable/none_00036" android:duration="30" /> + <item android:drawable="@drawable/none_00037" android:duration="30" /> + <item android:drawable="@drawable/none_00038" android:duration="30" /> + <item android:drawable="@drawable/none_00039" android:duration="30" /> + <item android:drawable="@drawable/none_00040" android:duration="30" /> + <item android:drawable="@drawable/none_00041" android:duration="30" /> + <item android:drawable="@drawable/none_00042" android:duration="30" /> + <item android:drawable="@drawable/none_00043" android:duration="30" /> + <item android:drawable="@drawable/none_00044" android:duration="30" /> + <item android:drawable="@drawable/none_00045" android:duration="30" /> + <item android:drawable="@drawable/none_00046" android:duration="30" /> + <item android:drawable="@drawable/none_00047" android:duration="30" /> + <item android:drawable="@drawable/none_00048" android:duration="30" /> + <item android:drawable="@drawable/none_00049" android:duration="30" /> + <item android:drawable="@drawable/none_00049" android:duration="30" /> +</animation-list> diff --git a/res/drawable/transition_overview.xml b/res/drawable/transition_overview.xml new file mode 100644 index 000000000..47dac7d92 --- /dev/null +++ b/res/drawable/transition_overview.xml @@ -0,0 +1,55 @@ +<animation-list + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/transition_overview" android:oneshot="false"> + <item android:drawable="@drawable/overview_00000" android:duration="30" /> + <item android:drawable="@drawable/overview_00001" android:duration="30" /> + <item android:drawable="@drawable/overview_00002" android:duration="30" /> + <item android:drawable="@drawable/overview_00003" android:duration="30" /> + <item android:drawable="@drawable/overview_00004" android:duration="30" /> + <item android:drawable="@drawable/overview_00005" android:duration="30" /> + <item android:drawable="@drawable/overview_00006" android:duration="30" /> + <item android:drawable="@drawable/overview_00007" android:duration="30" /> + <item android:drawable="@drawable/overview_00008" android:duration="30" /> + <item android:drawable="@drawable/overview_00009" android:duration="30" /> + <item android:drawable="@drawable/overview_00010" android:duration="30" /> + <item android:drawable="@drawable/overview_00011" android:duration="30" /> + <item android:drawable="@drawable/overview_00012" android:duration="30" /> + <item android:drawable="@drawable/overview_00013" android:duration="30" /> + <item android:drawable="@drawable/overview_00014" android:duration="30" /> + <item android:drawable="@drawable/overview_00015" android:duration="30" /> + <item android:drawable="@drawable/overview_00016" android:duration="30" /> + <item android:drawable="@drawable/overview_00017" android:duration="30" /> + <item android:drawable="@drawable/overview_00018" android:duration="30" /> + <item android:drawable="@drawable/overview_00019" android:duration="30" /> + <item android:drawable="@drawable/overview_00020" android:duration="30" /> + <item android:drawable="@drawable/overview_00021" android:duration="30" /> + <item android:drawable="@drawable/overview_00022" android:duration="30" /> + <item android:drawable="@drawable/overview_00023" android:duration="30" /> + <item android:drawable="@drawable/overview_00024" android:duration="30" /> + <item android:drawable="@drawable/overview_00025" android:duration="30" /> + <item android:drawable="@drawable/overview_00026" android:duration="30" /> + <item android:drawable="@drawable/overview_00027" android:duration="30" /> + <item android:drawable="@drawable/overview_00028" android:duration="30" /> + <item android:drawable="@drawable/overview_00029" android:duration="30" /> + <item android:drawable="@drawable/overview_00030" android:duration="30" /> + <item android:drawable="@drawable/overview_00031" android:duration="30" /> + <item android:drawable="@drawable/overview_00032" android:duration="30" /> + <item android:drawable="@drawable/overview_00033" android:duration="30" /> + <item android:drawable="@drawable/overview_00034" android:duration="30" /> + <item android:drawable="@drawable/overview_00035" android:duration="30" /> + <item android:drawable="@drawable/overview_00036" android:duration="30" /> + <item android:drawable="@drawable/overview_00037" android:duration="30" /> + <item android:drawable="@drawable/overview_00038" android:duration="30" /> + <item android:drawable="@drawable/overview_00039" android:duration="30" /> + <item android:drawable="@drawable/overview_00040" android:duration="30" /> + <item android:drawable="@drawable/overview_00041" android:duration="30" /> + <item android:drawable="@drawable/overview_00042" android:duration="30" /> + <item android:drawable="@drawable/overview_00043" android:duration="30" /> + <item android:drawable="@drawable/overview_00044" android:duration="30" /> + <item android:drawable="@drawable/overview_00045" android:duration="30" /> + <item android:drawable="@drawable/overview_00046" android:duration="30" /> + <item android:drawable="@drawable/overview_00047" android:duration="30" /> + <item android:drawable="@drawable/overview_00048" android:duration="30" /> + <item android:drawable="@drawable/overview_00049" android:duration="30" /> + <item android:drawable="@drawable/overview_00049" android:duration="30" /> +</animation-list> diff --git a/res/drawable/transition_rotatedown.xml b/res/drawable/transition_rotatedown.xml new file mode 100644 index 000000000..f05f71003 --- /dev/null +++ b/res/drawable/transition_rotatedown.xml @@ -0,0 +1,55 @@ +<animation-list + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/transition_rotatedown" android:oneshot="false"> + <item android:drawable="@drawable/rotatedown_00000" android:duration="30" /> + <item android:drawable="@drawable/rotatedown_00001" android:duration="30" /> + <item android:drawable="@drawable/rotatedown_00002" android:duration="30" /> + <item android:drawable="@drawable/rotatedown_00003" android:duration="30" /> + <item android:drawable="@drawable/rotatedown_00004" android:duration="30" /> + <item android:drawable="@drawable/rotatedown_00005" android:duration="30" /> + <item android:drawable="@drawable/rotatedown_00006" android:duration="30" /> + <item android:drawable="@drawable/rotatedown_00007" android:duration="30" /> + <item android:drawable="@drawable/rotatedown_00008" android:duration="30" /> + <item android:drawable="@drawable/rotatedown_00009" android:duration="30" /> + <item android:drawable="@drawable/rotatedown_00010" android:duration="30" /> + <item android:drawable="@drawable/rotatedown_00011" android:duration="30" /> + <item android:drawable="@drawable/rotatedown_00012" android:duration="30" /> + <item android:drawable="@drawable/rotatedown_00013" android:duration="30" /> + <item android:drawable="@drawable/rotatedown_00014" android:duration="30" /> + <item android:drawable="@drawable/rotatedown_00015" android:duration="30" /> + <item android:drawable="@drawable/rotatedown_00016" android:duration="30" /> + <item android:drawable="@drawable/rotatedown_00017" android:duration="30" /> + <item android:drawable="@drawable/rotatedown_00018" android:duration="30" /> + <item android:drawable="@drawable/rotatedown_00019" android:duration="30" /> + <item android:drawable="@drawable/rotatedown_00020" android:duration="30" /> + <item android:drawable="@drawable/rotatedown_00021" android:duration="30" /> + <item android:drawable="@drawable/rotatedown_00022" android:duration="30" /> + <item android:drawable="@drawable/rotatedown_00023" android:duration="30" /> + <item android:drawable="@drawable/rotatedown_00024" android:duration="30" /> + <item android:drawable="@drawable/rotatedown_00025" android:duration="30" /> + <item android:drawable="@drawable/rotatedown_00026" android:duration="30" /> + <item android:drawable="@drawable/rotatedown_00027" android:duration="30" /> + <item android:drawable="@drawable/rotatedown_00028" android:duration="30" /> + <item android:drawable="@drawable/rotatedown_00029" android:duration="30" /> + <item android:drawable="@drawable/rotatedown_00030" android:duration="30" /> + <item android:drawable="@drawable/rotatedown_00031" android:duration="30" /> + <item android:drawable="@drawable/rotatedown_00032" android:duration="30" /> + <item android:drawable="@drawable/rotatedown_00033" android:duration="30" /> + <item android:drawable="@drawable/rotatedown_00034" android:duration="30" /> + <item android:drawable="@drawable/rotatedown_00035" android:duration="30" /> + <item android:drawable="@drawable/rotatedown_00036" android:duration="30" /> + <item android:drawable="@drawable/rotatedown_00037" android:duration="30" /> + <item android:drawable="@drawable/rotatedown_00038" android:duration="30" /> + <item android:drawable="@drawable/rotatedown_00039" android:duration="30" /> + <item android:drawable="@drawable/rotatedown_00040" android:duration="30" /> + <item android:drawable="@drawable/rotatedown_00041" android:duration="30" /> + <item android:drawable="@drawable/rotatedown_00042" android:duration="30" /> + <item android:drawable="@drawable/rotatedown_00043" android:duration="30" /> + <item android:drawable="@drawable/rotatedown_00044" android:duration="30" /> + <item android:drawable="@drawable/rotatedown_00045" android:duration="30" /> + <item android:drawable="@drawable/rotatedown_00046" android:duration="30" /> + <item android:drawable="@drawable/rotatedown_00047" android:duration="30" /> + <item android:drawable="@drawable/rotatedown_00048" android:duration="30" /> + <item android:drawable="@drawable/rotatedown_00049" android:duration="30" /> + <item android:drawable="@drawable/rotatedown_00049" android:duration="30" /> +</animation-list> diff --git a/res/drawable/transition_rotateup.xml b/res/drawable/transition_rotateup.xml new file mode 100644 index 000000000..3a2e8fa8e --- /dev/null +++ b/res/drawable/transition_rotateup.xml @@ -0,0 +1,55 @@ +<animation-list + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/transition_rotateup" android:oneshot="false"> + <item android:drawable="@drawable/rotateup_00000" android:duration="30" /> + <item android:drawable="@drawable/rotateup_00001" android:duration="30" /> + <item android:drawable="@drawable/rotateup_00002" android:duration="30" /> + <item android:drawable="@drawable/rotateup_00003" android:duration="30" /> + <item android:drawable="@drawable/rotateup_00004" android:duration="30" /> + <item android:drawable="@drawable/rotateup_00005" android:duration="30" /> + <item android:drawable="@drawable/rotateup_00006" android:duration="30" /> + <item android:drawable="@drawable/rotateup_00007" android:duration="30" /> + <item android:drawable="@drawable/rotateup_00008" android:duration="30" /> + <item android:drawable="@drawable/rotateup_00009" android:duration="30" /> + <item android:drawable="@drawable/rotateup_00010" android:duration="30" /> + <item android:drawable="@drawable/rotateup_00011" android:duration="30" /> + <item android:drawable="@drawable/rotateup_00012" android:duration="30" /> + <item android:drawable="@drawable/rotateup_00013" android:duration="30" /> + <item android:drawable="@drawable/rotateup_00014" android:duration="30" /> + <item android:drawable="@drawable/rotateup_00015" android:duration="30" /> + <item android:drawable="@drawable/rotateup_00016" android:duration="30" /> + <item android:drawable="@drawable/rotateup_00017" android:duration="30" /> + <item android:drawable="@drawable/rotateup_00018" android:duration="30" /> + <item android:drawable="@drawable/rotateup_00019" android:duration="30" /> + <item android:drawable="@drawable/rotateup_00020" android:duration="30" /> + <item android:drawable="@drawable/rotateup_00021" android:duration="30" /> + <item android:drawable="@drawable/rotateup_00022" android:duration="30" /> + <item android:drawable="@drawable/rotateup_00023" android:duration="30" /> + <item android:drawable="@drawable/rotateup_00024" android:duration="30" /> + <item android:drawable="@drawable/rotateup_00025" android:duration="30" /> + <item android:drawable="@drawable/rotateup_00026" android:duration="30" /> + <item android:drawable="@drawable/rotateup_00027" android:duration="30" /> + <item android:drawable="@drawable/rotateup_00028" android:duration="30" /> + <item android:drawable="@drawable/rotateup_00029" android:duration="30" /> + <item android:drawable="@drawable/rotateup_00030" android:duration="30" /> + <item android:drawable="@drawable/rotateup_00031" android:duration="30" /> + <item android:drawable="@drawable/rotateup_00032" android:duration="30" /> + <item android:drawable="@drawable/rotateup_00033" android:duration="30" /> + <item android:drawable="@drawable/rotateup_00034" android:duration="30" /> + <item android:drawable="@drawable/rotateup_00035" android:duration="30" /> + <item android:drawable="@drawable/rotateup_00036" android:duration="30" /> + <item android:drawable="@drawable/rotateup_00037" android:duration="30" /> + <item android:drawable="@drawable/rotateup_00038" android:duration="30" /> + <item android:drawable="@drawable/rotateup_00039" android:duration="30" /> + <item android:drawable="@drawable/rotateup_00040" android:duration="30" /> + <item android:drawable="@drawable/rotateup_00041" android:duration="30" /> + <item android:drawable="@drawable/rotateup_00042" android:duration="30" /> + <item android:drawable="@drawable/rotateup_00043" android:duration="30" /> + <item android:drawable="@drawable/rotateup_00044" android:duration="30" /> + <item android:drawable="@drawable/rotateup_00045" android:duration="30" /> + <item android:drawable="@drawable/rotateup_00046" android:duration="30" /> + <item android:drawable="@drawable/rotateup_00047" android:duration="30" /> + <item android:drawable="@drawable/rotateup_00048" android:duration="30" /> + <item android:drawable="@drawable/rotateup_00049" android:duration="30" /> + <item android:drawable="@drawable/rotateup_00049" android:duration="30" /> +</animation-list> diff --git a/res/drawable/transition_stack.xml b/res/drawable/transition_stack.xml new file mode 100644 index 000000000..1483a1bae --- /dev/null +++ b/res/drawable/transition_stack.xml @@ -0,0 +1,55 @@ +<animation-list + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/transition_stack" android:oneshot="false"> + <item android:drawable="@drawable/stack_00000" android:duration="30" /> + <item android:drawable="@drawable/stack_00001" android:duration="30" /> + <item android:drawable="@drawable/stack_00002" android:duration="30" /> + <item android:drawable="@drawable/stack_00003" android:duration="30" /> + <item android:drawable="@drawable/stack_00004" android:duration="30" /> + <item android:drawable="@drawable/stack_00005" android:duration="30" /> + <item android:drawable="@drawable/stack_00006" android:duration="30" /> + <item android:drawable="@drawable/stack_00007" android:duration="30" /> + <item android:drawable="@drawable/stack_00008" android:duration="30" /> + <item android:drawable="@drawable/stack_00009" android:duration="30" /> + <item android:drawable="@drawable/stack_00010" android:duration="30" /> + <item android:drawable="@drawable/stack_00011" android:duration="30" /> + <item android:drawable="@drawable/stack_00012" android:duration="30" /> + <item android:drawable="@drawable/stack_00013" android:duration="30" /> + <item android:drawable="@drawable/stack_00014" android:duration="30" /> + <item android:drawable="@drawable/stack_00015" android:duration="30" /> + <item android:drawable="@drawable/stack_00016" android:duration="30" /> + <item android:drawable="@drawable/stack_00017" android:duration="30" /> + <item android:drawable="@drawable/stack_00018" android:duration="30" /> + <item android:drawable="@drawable/stack_00019" android:duration="30" /> + <item android:drawable="@drawable/stack_00020" android:duration="30" /> + <item android:drawable="@drawable/stack_00021" android:duration="30" /> + <item android:drawable="@drawable/stack_00022" android:duration="30" /> + <item android:drawable="@drawable/stack_00023" android:duration="30" /> + <item android:drawable="@drawable/stack_00024" android:duration="30" /> + <item android:drawable="@drawable/stack_00025" android:duration="30" /> + <item android:drawable="@drawable/stack_00026" android:duration="30" /> + <item android:drawable="@drawable/stack_00027" android:duration="30" /> + <item android:drawable="@drawable/stack_00028" android:duration="30" /> + <item android:drawable="@drawable/stack_00029" android:duration="30" /> + <item android:drawable="@drawable/stack_00030" android:duration="30" /> + <item android:drawable="@drawable/stack_00031" android:duration="30" /> + <item android:drawable="@drawable/stack_00032" android:duration="30" /> + <item android:drawable="@drawable/stack_00033" android:duration="30" /> + <item android:drawable="@drawable/stack_00034" android:duration="30" /> + <item android:drawable="@drawable/stack_00035" android:duration="30" /> + <item android:drawable="@drawable/stack_00036" android:duration="30" /> + <item android:drawable="@drawable/stack_00037" android:duration="30" /> + <item android:drawable="@drawable/stack_00038" android:duration="30" /> + <item android:drawable="@drawable/stack_00039" android:duration="30" /> + <item android:drawable="@drawable/stack_00040" android:duration="30" /> + <item android:drawable="@drawable/stack_00041" android:duration="30" /> + <item android:drawable="@drawable/stack_00042" android:duration="30" /> + <item android:drawable="@drawable/stack_00043" android:duration="30" /> + <item android:drawable="@drawable/stack_00044" android:duration="30" /> + <item android:drawable="@drawable/stack_00045" android:duration="30" /> + <item android:drawable="@drawable/stack_00046" android:duration="30" /> + <item android:drawable="@drawable/stack_00047" android:duration="30" /> + <item android:drawable="@drawable/stack_00048" android:duration="30" /> + <item android:drawable="@drawable/stack_00049" android:duration="30" /> + <item android:drawable="@drawable/stack_00049" android:duration="30" /> +</animation-list> diff --git a/res/drawable/transition_zoomin.xml b/res/drawable/transition_zoomin.xml new file mode 100644 index 000000000..cf76e5312 --- /dev/null +++ b/res/drawable/transition_zoomin.xml @@ -0,0 +1,55 @@ +<animation-list + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/transition_zoomin" android:oneshot="false"> + <item android:drawable="@drawable/zoomin_00000" android:duration="30" /> + <item android:drawable="@drawable/zoomin_00001" android:duration="30" /> + <item android:drawable="@drawable/zoomin_00002" android:duration="30" /> + <item android:drawable="@drawable/zoomin_00003" android:duration="30" /> + <item android:drawable="@drawable/zoomin_00004" android:duration="30" /> + <item android:drawable="@drawable/zoomin_00005" android:duration="30" /> + <item android:drawable="@drawable/zoomin_00006" android:duration="30" /> + <item android:drawable="@drawable/zoomin_00007" android:duration="30" /> + <item android:drawable="@drawable/zoomin_00008" android:duration="30" /> + <item android:drawable="@drawable/zoomin_00009" android:duration="30" /> + <item android:drawable="@drawable/zoomin_00010" android:duration="30" /> + <item android:drawable="@drawable/zoomin_00011" android:duration="30" /> + <item android:drawable="@drawable/zoomin_00012" android:duration="30" /> + <item android:drawable="@drawable/zoomin_00013" android:duration="30" /> + <item android:drawable="@drawable/zoomin_00014" android:duration="30" /> + <item android:drawable="@drawable/zoomin_00015" android:duration="30" /> + <item android:drawable="@drawable/zoomin_00016" android:duration="30" /> + <item android:drawable="@drawable/zoomin_00017" android:duration="30" /> + <item android:drawable="@drawable/zoomin_00018" android:duration="30" /> + <item android:drawable="@drawable/zoomin_00019" android:duration="30" /> + <item android:drawable="@drawable/zoomin_00020" android:duration="30" /> + <item android:drawable="@drawable/zoomin_00021" android:duration="30" /> + <item android:drawable="@drawable/zoomin_00022" android:duration="30" /> + <item android:drawable="@drawable/zoomin_00023" android:duration="30" /> + <item android:drawable="@drawable/zoomin_00024" android:duration="30" /> + <item android:drawable="@drawable/zoomin_00025" android:duration="30" /> + <item android:drawable="@drawable/zoomin_00026" android:duration="30" /> + <item android:drawable="@drawable/zoomin_00027" android:duration="30" /> + <item android:drawable="@drawable/zoomin_00028" android:duration="30" /> + <item android:drawable="@drawable/zoomin_00029" android:duration="30" /> + <item android:drawable="@drawable/zoomin_00030" android:duration="30" /> + <item android:drawable="@drawable/zoomin_00031" android:duration="30" /> + <item android:drawable="@drawable/zoomin_00032" android:duration="30" /> + <item android:drawable="@drawable/zoomin_00033" android:duration="30" /> + <item android:drawable="@drawable/zoomin_00034" android:duration="30" /> + <item android:drawable="@drawable/zoomin_00035" android:duration="30" /> + <item android:drawable="@drawable/zoomin_00036" android:duration="30" /> + <item android:drawable="@drawable/zoomin_00037" android:duration="30" /> + <item android:drawable="@drawable/zoomin_00038" android:duration="30" /> + <item android:drawable="@drawable/zoomin_00039" android:duration="30" /> + <item android:drawable="@drawable/zoomin_00040" android:duration="30" /> + <item android:drawable="@drawable/zoomin_00041" android:duration="30" /> + <item android:drawable="@drawable/zoomin_00042" android:duration="30" /> + <item android:drawable="@drawable/zoomin_00043" android:duration="30" /> + <item android:drawable="@drawable/zoomin_00044" android:duration="30" /> + <item android:drawable="@drawable/zoomin_00045" android:duration="30" /> + <item android:drawable="@drawable/zoomin_00046" android:duration="30" /> + <item android:drawable="@drawable/zoomin_00047" android:duration="30" /> + <item android:drawable="@drawable/zoomin_00048" android:duration="30" /> + <item android:drawable="@drawable/zoomin_00049" android:duration="30" /> + <item android:drawable="@drawable/zoomin_00049" android:duration="30" /> +</animation-list> diff --git a/res/drawable/transition_zoomout.xml b/res/drawable/transition_zoomout.xml new file mode 100644 index 000000000..1acdb0c94 --- /dev/null +++ b/res/drawable/transition_zoomout.xml @@ -0,0 +1,55 @@ +<animation-list + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/transition_zoomout" android:oneshot="false"> + <item android:drawable="@drawable/zoomout_00000" android:duration="30" /> + <item android:drawable="@drawable/zoomout_00001" android:duration="30" /> + <item android:drawable="@drawable/zoomout_00002" android:duration="30" /> + <item android:drawable="@drawable/zoomout_00003" android:duration="30" /> + <item android:drawable="@drawable/zoomout_00004" android:duration="30" /> + <item android:drawable="@drawable/zoomout_00005" android:duration="30" /> + <item android:drawable="@drawable/zoomout_00006" android:duration="30" /> + <item android:drawable="@drawable/zoomout_00007" android:duration="30" /> + <item android:drawable="@drawable/zoomout_00008" android:duration="30" /> + <item android:drawable="@drawable/zoomout_00009" android:duration="30" /> + <item android:drawable="@drawable/zoomout_00010" android:duration="30" /> + <item android:drawable="@drawable/zoomout_00011" android:duration="30" /> + <item android:drawable="@drawable/zoomout_00012" android:duration="30" /> + <item android:drawable="@drawable/zoomout_00013" android:duration="30" /> + <item android:drawable="@drawable/zoomout_00014" android:duration="30" /> + <item android:drawable="@drawable/zoomout_00015" android:duration="30" /> + <item android:drawable="@drawable/zoomout_00016" android:duration="30" /> + <item android:drawable="@drawable/zoomout_00017" android:duration="30" /> + <item android:drawable="@drawable/zoomout_00018" android:duration="30" /> + <item android:drawable="@drawable/zoomout_00019" android:duration="30" /> + <item android:drawable="@drawable/zoomout_00020" android:duration="30" /> + <item android:drawable="@drawable/zoomout_00021" android:duration="30" /> + <item android:drawable="@drawable/zoomout_00022" android:duration="30" /> + <item android:drawable="@drawable/zoomout_00023" android:duration="30" /> + <item android:drawable="@drawable/zoomout_00024" android:duration="30" /> + <item android:drawable="@drawable/zoomout_00025" android:duration="30" /> + <item android:drawable="@drawable/zoomout_00026" android:duration="30" /> + <item android:drawable="@drawable/zoomout_00027" android:duration="30" /> + <item android:drawable="@drawable/zoomout_00028" android:duration="30" /> + <item android:drawable="@drawable/zoomout_00029" android:duration="30" /> + <item android:drawable="@drawable/zoomout_00030" android:duration="30" /> + <item android:drawable="@drawable/zoomout_00031" android:duration="30" /> + <item android:drawable="@drawable/zoomout_00032" android:duration="30" /> + <item android:drawable="@drawable/zoomout_00033" android:duration="30" /> + <item android:drawable="@drawable/zoomout_00034" android:duration="30" /> + <item android:drawable="@drawable/zoomout_00035" android:duration="30" /> + <item android:drawable="@drawable/zoomout_00036" android:duration="30" /> + <item android:drawable="@drawable/zoomout_00037" android:duration="30" /> + <item android:drawable="@drawable/zoomout_00038" android:duration="30" /> + <item android:drawable="@drawable/zoomout_00039" android:duration="30" /> + <item android:drawable="@drawable/zoomout_00040" android:duration="30" /> + <item android:drawable="@drawable/zoomout_00041" android:duration="30" /> + <item android:drawable="@drawable/zoomout_00042" android:duration="30" /> + <item android:drawable="@drawable/zoomout_00043" android:duration="30" /> + <item android:drawable="@drawable/zoomout_00044" android:duration="30" /> + <item android:drawable="@drawable/zoomout_00045" android:duration="30" /> + <item android:drawable="@drawable/zoomout_00046" android:duration="30" /> + <item android:drawable="@drawable/zoomout_00047" android:duration="30" /> + <item android:drawable="@drawable/zoomout_00048" android:duration="30" /> + <item android:drawable="@drawable/zoomout_00049" android:duration="30" /> + <item android:drawable="@drawable/zoomout_00049" android:duration="30" /> +</animation-list> diff --git a/res/drawable/zoomin_00000.png b/res/drawable/zoomin_00000.png Binary files differnew file mode 100644 index 000000000..f48138061 --- /dev/null +++ b/res/drawable/zoomin_00000.png diff --git a/res/drawable/zoomin_00001.png b/res/drawable/zoomin_00001.png Binary files differnew file mode 100644 index 000000000..d2f01b4d5 --- /dev/null +++ b/res/drawable/zoomin_00001.png diff --git a/res/drawable/zoomin_00002.png b/res/drawable/zoomin_00002.png Binary files differnew file mode 100644 index 000000000..f0bea7934 --- /dev/null +++ b/res/drawable/zoomin_00002.png diff --git a/res/drawable/zoomin_00003.png b/res/drawable/zoomin_00003.png Binary files differnew file mode 100644 index 000000000..23bd3d5ff --- /dev/null +++ b/res/drawable/zoomin_00003.png diff --git a/res/drawable/zoomin_00004.png b/res/drawable/zoomin_00004.png Binary files differnew file mode 100644 index 000000000..9f343a2dc --- /dev/null +++ b/res/drawable/zoomin_00004.png diff --git a/res/drawable/zoomin_00005.png b/res/drawable/zoomin_00005.png Binary files differnew file mode 100644 index 000000000..cf7d82ad5 --- /dev/null +++ b/res/drawable/zoomin_00005.png diff --git a/res/drawable/zoomin_00006.png b/res/drawable/zoomin_00006.png Binary files differnew file mode 100644 index 000000000..5043dfdab --- /dev/null +++ b/res/drawable/zoomin_00006.png diff --git a/res/drawable/zoomin_00007.png b/res/drawable/zoomin_00007.png Binary files differnew file mode 100644 index 000000000..013cbbf3c --- /dev/null +++ b/res/drawable/zoomin_00007.png diff --git a/res/drawable/zoomin_00008.png b/res/drawable/zoomin_00008.png Binary files differnew file mode 100644 index 000000000..d8acca68a --- /dev/null +++ b/res/drawable/zoomin_00008.png diff --git a/res/drawable/zoomin_00009.png b/res/drawable/zoomin_00009.png Binary files differnew file mode 100644 index 000000000..982aa00bf --- /dev/null +++ b/res/drawable/zoomin_00009.png diff --git a/res/drawable/zoomin_00010.png b/res/drawable/zoomin_00010.png Binary files differnew file mode 100644 index 000000000..7a5b96457 --- /dev/null +++ b/res/drawable/zoomin_00010.png diff --git a/res/drawable/zoomin_00011.png b/res/drawable/zoomin_00011.png Binary files differnew file mode 100644 index 000000000..94c374b3f --- /dev/null +++ b/res/drawable/zoomin_00011.png diff --git a/res/drawable/zoomin_00012.png b/res/drawable/zoomin_00012.png Binary files differnew file mode 100644 index 000000000..f4ca0cb6a --- /dev/null +++ b/res/drawable/zoomin_00012.png diff --git a/res/drawable/zoomin_00013.png b/res/drawable/zoomin_00013.png Binary files differnew file mode 100644 index 000000000..fbb30e04c --- /dev/null +++ b/res/drawable/zoomin_00013.png diff --git a/res/drawable/zoomin_00014.png b/res/drawable/zoomin_00014.png Binary files differnew file mode 100644 index 000000000..8e93f17c1 --- /dev/null +++ b/res/drawable/zoomin_00014.png diff --git a/res/drawable/zoomin_00015.png b/res/drawable/zoomin_00015.png Binary files differnew file mode 100644 index 000000000..bad7462a6 --- /dev/null +++ b/res/drawable/zoomin_00015.png diff --git a/res/drawable/zoomin_00016.png b/res/drawable/zoomin_00016.png Binary files differnew file mode 100644 index 000000000..282a8073f --- /dev/null +++ b/res/drawable/zoomin_00016.png diff --git a/res/drawable/zoomin_00017.png b/res/drawable/zoomin_00017.png Binary files differnew file mode 100644 index 000000000..ae94999f2 --- /dev/null +++ b/res/drawable/zoomin_00017.png diff --git a/res/drawable/zoomin_00018.png b/res/drawable/zoomin_00018.png Binary files differnew file mode 100644 index 000000000..3fcc59e52 --- /dev/null +++ b/res/drawable/zoomin_00018.png diff --git a/res/drawable/zoomin_00019.png b/res/drawable/zoomin_00019.png Binary files differnew file mode 100644 index 000000000..be9cfcbb3 --- /dev/null +++ b/res/drawable/zoomin_00019.png diff --git a/res/drawable/zoomin_00020.png b/res/drawable/zoomin_00020.png Binary files differnew file mode 100644 index 000000000..303e8f87f --- /dev/null +++ b/res/drawable/zoomin_00020.png diff --git a/res/drawable/zoomin_00021.png b/res/drawable/zoomin_00021.png Binary files differnew file mode 100644 index 000000000..303e8f87f --- /dev/null +++ b/res/drawable/zoomin_00021.png diff --git a/res/drawable/zoomin_00022.png b/res/drawable/zoomin_00022.png Binary files differnew file mode 100644 index 000000000..303e8f87f --- /dev/null +++ b/res/drawable/zoomin_00022.png diff --git a/res/drawable/zoomin_00023.png b/res/drawable/zoomin_00023.png Binary files differnew file mode 100644 index 000000000..303e8f87f --- /dev/null +++ b/res/drawable/zoomin_00023.png diff --git a/res/drawable/zoomin_00024.png b/res/drawable/zoomin_00024.png Binary files differnew file mode 100644 index 000000000..303e8f87f --- /dev/null +++ b/res/drawable/zoomin_00024.png diff --git a/res/drawable/zoomin_00025.png b/res/drawable/zoomin_00025.png Binary files differnew file mode 100644 index 000000000..303e8f87f --- /dev/null +++ b/res/drawable/zoomin_00025.png diff --git a/res/drawable/zoomin_00026.png b/res/drawable/zoomin_00026.png Binary files differnew file mode 100644 index 000000000..303e8f87f --- /dev/null +++ b/res/drawable/zoomin_00026.png diff --git a/res/drawable/zoomin_00027.png b/res/drawable/zoomin_00027.png Binary files differnew file mode 100644 index 000000000..303e8f87f --- /dev/null +++ b/res/drawable/zoomin_00027.png diff --git a/res/drawable/zoomin_00028.png b/res/drawable/zoomin_00028.png Binary files differnew file mode 100644 index 000000000..303e8f87f --- /dev/null +++ b/res/drawable/zoomin_00028.png diff --git a/res/drawable/zoomin_00029.png b/res/drawable/zoomin_00029.png Binary files differnew file mode 100644 index 000000000..303e8f87f --- /dev/null +++ b/res/drawable/zoomin_00029.png diff --git a/res/drawable/zoomin_00030.png b/res/drawable/zoomin_00030.png Binary files differnew file mode 100644 index 000000000..303e8f87f --- /dev/null +++ b/res/drawable/zoomin_00030.png diff --git a/res/drawable/zoomin_00031.png b/res/drawable/zoomin_00031.png Binary files differnew file mode 100644 index 000000000..303e8f87f --- /dev/null +++ b/res/drawable/zoomin_00031.png diff --git a/res/drawable/zoomin_00032.png b/res/drawable/zoomin_00032.png Binary files differnew file mode 100644 index 000000000..303e8f87f --- /dev/null +++ b/res/drawable/zoomin_00032.png diff --git a/res/drawable/zoomin_00033.png b/res/drawable/zoomin_00033.png Binary files differnew file mode 100644 index 000000000..303e8f87f --- /dev/null +++ b/res/drawable/zoomin_00033.png diff --git a/res/drawable/zoomin_00034.png b/res/drawable/zoomin_00034.png Binary files differnew file mode 100644 index 000000000..303e8f87f --- /dev/null +++ b/res/drawable/zoomin_00034.png diff --git a/res/drawable/zoomin_00035.png b/res/drawable/zoomin_00035.png Binary files differnew file mode 100644 index 000000000..303e8f87f --- /dev/null +++ b/res/drawable/zoomin_00035.png diff --git a/res/drawable/zoomin_00036.png b/res/drawable/zoomin_00036.png Binary files differnew file mode 100644 index 000000000..303e8f87f --- /dev/null +++ b/res/drawable/zoomin_00036.png diff --git a/res/drawable/zoomin_00037.png b/res/drawable/zoomin_00037.png Binary files differnew file mode 100644 index 000000000..303e8f87f --- /dev/null +++ b/res/drawable/zoomin_00037.png diff --git a/res/drawable/zoomin_00038.png b/res/drawable/zoomin_00038.png Binary files differnew file mode 100644 index 000000000..303e8f87f --- /dev/null +++ b/res/drawable/zoomin_00038.png diff --git a/res/drawable/zoomin_00039.png b/res/drawable/zoomin_00039.png Binary files differnew file mode 100644 index 000000000..303e8f87f --- /dev/null +++ b/res/drawable/zoomin_00039.png diff --git a/res/drawable/zoomin_00040.png b/res/drawable/zoomin_00040.png Binary files differnew file mode 100644 index 000000000..303e8f87f --- /dev/null +++ b/res/drawable/zoomin_00040.png diff --git a/res/drawable/zoomin_00041.png b/res/drawable/zoomin_00041.png Binary files differnew file mode 100644 index 000000000..303e8f87f --- /dev/null +++ b/res/drawable/zoomin_00041.png diff --git a/res/drawable/zoomin_00042.png b/res/drawable/zoomin_00042.png Binary files differnew file mode 100644 index 000000000..303e8f87f --- /dev/null +++ b/res/drawable/zoomin_00042.png diff --git a/res/drawable/zoomin_00043.png b/res/drawable/zoomin_00043.png Binary files differnew file mode 100644 index 000000000..303e8f87f --- /dev/null +++ b/res/drawable/zoomin_00043.png diff --git a/res/drawable/zoomin_00044.png b/res/drawable/zoomin_00044.png Binary files differnew file mode 100644 index 000000000..303e8f87f --- /dev/null +++ b/res/drawable/zoomin_00044.png diff --git a/res/drawable/zoomin_00045.png b/res/drawable/zoomin_00045.png Binary files differnew file mode 100644 index 000000000..303e8f87f --- /dev/null +++ b/res/drawable/zoomin_00045.png diff --git a/res/drawable/zoomin_00046.png b/res/drawable/zoomin_00046.png Binary files differnew file mode 100644 index 000000000..303e8f87f --- /dev/null +++ b/res/drawable/zoomin_00046.png diff --git a/res/drawable/zoomin_00047.png b/res/drawable/zoomin_00047.png Binary files differnew file mode 100644 index 000000000..303e8f87f --- /dev/null +++ b/res/drawable/zoomin_00047.png diff --git a/res/drawable/zoomin_00048.png b/res/drawable/zoomin_00048.png Binary files differnew file mode 100644 index 000000000..303e8f87f --- /dev/null +++ b/res/drawable/zoomin_00048.png diff --git a/res/drawable/zoomin_00049.png b/res/drawable/zoomin_00049.png Binary files differnew file mode 100644 index 000000000..303e8f87f --- /dev/null +++ b/res/drawable/zoomin_00049.png diff --git a/res/drawable/zoomout_00000.png b/res/drawable/zoomout_00000.png Binary files differnew file mode 100644 index 000000000..94284f9b9 --- /dev/null +++ b/res/drawable/zoomout_00000.png diff --git a/res/drawable/zoomout_00001.png b/res/drawable/zoomout_00001.png Binary files differnew file mode 100644 index 000000000..8c2a2596a --- /dev/null +++ b/res/drawable/zoomout_00001.png diff --git a/res/drawable/zoomout_00002.png b/res/drawable/zoomout_00002.png Binary files differnew file mode 100644 index 000000000..e3c4cb49b --- /dev/null +++ b/res/drawable/zoomout_00002.png diff --git a/res/drawable/zoomout_00003.png b/res/drawable/zoomout_00003.png Binary files differnew file mode 100644 index 000000000..95af18d06 --- /dev/null +++ b/res/drawable/zoomout_00003.png diff --git a/res/drawable/zoomout_00004.png b/res/drawable/zoomout_00004.png Binary files differnew file mode 100644 index 000000000..4d8af9632 --- /dev/null +++ b/res/drawable/zoomout_00004.png diff --git a/res/drawable/zoomout_00005.png b/res/drawable/zoomout_00005.png Binary files differnew file mode 100644 index 000000000..6db1ab05a --- /dev/null +++ b/res/drawable/zoomout_00005.png diff --git a/res/drawable/zoomout_00006.png b/res/drawable/zoomout_00006.png Binary files differnew file mode 100644 index 000000000..277d8c4ac --- /dev/null +++ b/res/drawable/zoomout_00006.png diff --git a/res/drawable/zoomout_00007.png b/res/drawable/zoomout_00007.png Binary files differnew file mode 100644 index 000000000..4fe81f665 --- /dev/null +++ b/res/drawable/zoomout_00007.png diff --git a/res/drawable/zoomout_00008.png b/res/drawable/zoomout_00008.png Binary files differnew file mode 100644 index 000000000..fadd58a14 --- /dev/null +++ b/res/drawable/zoomout_00008.png diff --git a/res/drawable/zoomout_00009.png b/res/drawable/zoomout_00009.png Binary files differnew file mode 100644 index 000000000..5b6003e07 --- /dev/null +++ b/res/drawable/zoomout_00009.png diff --git a/res/drawable/zoomout_00010.png b/res/drawable/zoomout_00010.png Binary files differnew file mode 100644 index 000000000..b77a4f88b --- /dev/null +++ b/res/drawable/zoomout_00010.png diff --git a/res/drawable/zoomout_00011.png b/res/drawable/zoomout_00011.png Binary files differnew file mode 100644 index 000000000..85fbbb831 --- /dev/null +++ b/res/drawable/zoomout_00011.png diff --git a/res/drawable/zoomout_00012.png b/res/drawable/zoomout_00012.png Binary files differnew file mode 100644 index 000000000..eb8acb213 --- /dev/null +++ b/res/drawable/zoomout_00012.png diff --git a/res/drawable/zoomout_00013.png b/res/drawable/zoomout_00013.png Binary files differnew file mode 100644 index 000000000..3501c8514 --- /dev/null +++ b/res/drawable/zoomout_00013.png diff --git a/res/drawable/zoomout_00014.png b/res/drawable/zoomout_00014.png Binary files differnew file mode 100644 index 000000000..fd600be1b --- /dev/null +++ b/res/drawable/zoomout_00014.png diff --git a/res/drawable/zoomout_00015.png b/res/drawable/zoomout_00015.png Binary files differnew file mode 100644 index 000000000..b88c6bcd8 --- /dev/null +++ b/res/drawable/zoomout_00015.png diff --git a/res/drawable/zoomout_00016.png b/res/drawable/zoomout_00016.png Binary files differnew file mode 100644 index 000000000..c618a55fc --- /dev/null +++ b/res/drawable/zoomout_00016.png diff --git a/res/drawable/zoomout_00017.png b/res/drawable/zoomout_00017.png Binary files differnew file mode 100644 index 000000000..c54b0dc8f --- /dev/null +++ b/res/drawable/zoomout_00017.png diff --git a/res/drawable/zoomout_00018.png b/res/drawable/zoomout_00018.png Binary files differnew file mode 100644 index 000000000..8e974a18a --- /dev/null +++ b/res/drawable/zoomout_00018.png diff --git a/res/drawable/zoomout_00019.png b/res/drawable/zoomout_00019.png Binary files differnew file mode 100644 index 000000000..79c6fb0e0 --- /dev/null +++ b/res/drawable/zoomout_00019.png diff --git a/res/drawable/zoomout_00020.png b/res/drawable/zoomout_00020.png Binary files differnew file mode 100644 index 000000000..b4be2aa37 --- /dev/null +++ b/res/drawable/zoomout_00020.png diff --git a/res/drawable/zoomout_00021.png b/res/drawable/zoomout_00021.png Binary files differnew file mode 100644 index 000000000..b4be2aa37 --- /dev/null +++ b/res/drawable/zoomout_00021.png diff --git a/res/drawable/zoomout_00022.png b/res/drawable/zoomout_00022.png Binary files differnew file mode 100644 index 000000000..b4be2aa37 --- /dev/null +++ b/res/drawable/zoomout_00022.png diff --git a/res/drawable/zoomout_00023.png b/res/drawable/zoomout_00023.png Binary files differnew file mode 100644 index 000000000..b4be2aa37 --- /dev/null +++ b/res/drawable/zoomout_00023.png diff --git a/res/drawable/zoomout_00024.png b/res/drawable/zoomout_00024.png Binary files differnew file mode 100644 index 000000000..b4be2aa37 --- /dev/null +++ b/res/drawable/zoomout_00024.png diff --git a/res/drawable/zoomout_00025.png b/res/drawable/zoomout_00025.png Binary files differnew file mode 100644 index 000000000..b4be2aa37 --- /dev/null +++ b/res/drawable/zoomout_00025.png diff --git a/res/drawable/zoomout_00026.png b/res/drawable/zoomout_00026.png Binary files differnew file mode 100644 index 000000000..b4be2aa37 --- /dev/null +++ b/res/drawable/zoomout_00026.png diff --git a/res/drawable/zoomout_00027.png b/res/drawable/zoomout_00027.png Binary files differnew file mode 100644 index 000000000..b4be2aa37 --- /dev/null +++ b/res/drawable/zoomout_00027.png diff --git a/res/drawable/zoomout_00028.png b/res/drawable/zoomout_00028.png Binary files differnew file mode 100644 index 000000000..b4be2aa37 --- /dev/null +++ b/res/drawable/zoomout_00028.png diff --git a/res/drawable/zoomout_00029.png b/res/drawable/zoomout_00029.png Binary files differnew file mode 100644 index 000000000..b4be2aa37 --- /dev/null +++ b/res/drawable/zoomout_00029.png diff --git a/res/drawable/zoomout_00030.png b/res/drawable/zoomout_00030.png Binary files differnew file mode 100644 index 000000000..b4be2aa37 --- /dev/null +++ b/res/drawable/zoomout_00030.png diff --git a/res/drawable/zoomout_00031.png b/res/drawable/zoomout_00031.png Binary files differnew file mode 100644 index 000000000..b4be2aa37 --- /dev/null +++ b/res/drawable/zoomout_00031.png diff --git a/res/drawable/zoomout_00032.png b/res/drawable/zoomout_00032.png Binary files differnew file mode 100644 index 000000000..b4be2aa37 --- /dev/null +++ b/res/drawable/zoomout_00032.png diff --git a/res/drawable/zoomout_00033.png b/res/drawable/zoomout_00033.png Binary files differnew file mode 100644 index 000000000..b4be2aa37 --- /dev/null +++ b/res/drawable/zoomout_00033.png diff --git a/res/drawable/zoomout_00034.png b/res/drawable/zoomout_00034.png Binary files differnew file mode 100644 index 000000000..b4be2aa37 --- /dev/null +++ b/res/drawable/zoomout_00034.png diff --git a/res/drawable/zoomout_00035.png b/res/drawable/zoomout_00035.png Binary files differnew file mode 100644 index 000000000..b4be2aa37 --- /dev/null +++ b/res/drawable/zoomout_00035.png diff --git a/res/drawable/zoomout_00036.png b/res/drawable/zoomout_00036.png Binary files differnew file mode 100644 index 000000000..b4be2aa37 --- /dev/null +++ b/res/drawable/zoomout_00036.png diff --git a/res/drawable/zoomout_00037.png b/res/drawable/zoomout_00037.png Binary files differnew file mode 100644 index 000000000..b4be2aa37 --- /dev/null +++ b/res/drawable/zoomout_00037.png diff --git a/res/drawable/zoomout_00038.png b/res/drawable/zoomout_00038.png Binary files differnew file mode 100644 index 000000000..b4be2aa37 --- /dev/null +++ b/res/drawable/zoomout_00038.png diff --git a/res/drawable/zoomout_00039.png b/res/drawable/zoomout_00039.png Binary files differnew file mode 100644 index 000000000..b4be2aa37 --- /dev/null +++ b/res/drawable/zoomout_00039.png diff --git a/res/drawable/zoomout_00040.png b/res/drawable/zoomout_00040.png Binary files differnew file mode 100644 index 000000000..b4be2aa37 --- /dev/null +++ b/res/drawable/zoomout_00040.png diff --git a/res/drawable/zoomout_00041.png b/res/drawable/zoomout_00041.png Binary files differnew file mode 100644 index 000000000..b4be2aa37 --- /dev/null +++ b/res/drawable/zoomout_00041.png diff --git a/res/drawable/zoomout_00042.png b/res/drawable/zoomout_00042.png Binary files differnew file mode 100644 index 000000000..b4be2aa37 --- /dev/null +++ b/res/drawable/zoomout_00042.png diff --git a/res/drawable/zoomout_00043.png b/res/drawable/zoomout_00043.png Binary files differnew file mode 100644 index 000000000..b4be2aa37 --- /dev/null +++ b/res/drawable/zoomout_00043.png diff --git a/res/drawable/zoomout_00044.png b/res/drawable/zoomout_00044.png Binary files differnew file mode 100644 index 000000000..b4be2aa37 --- /dev/null +++ b/res/drawable/zoomout_00044.png diff --git a/res/drawable/zoomout_00045.png b/res/drawable/zoomout_00045.png Binary files differnew file mode 100644 index 000000000..b4be2aa37 --- /dev/null +++ b/res/drawable/zoomout_00045.png diff --git a/res/drawable/zoomout_00046.png b/res/drawable/zoomout_00046.png Binary files differnew file mode 100644 index 000000000..b4be2aa37 --- /dev/null +++ b/res/drawable/zoomout_00046.png diff --git a/res/drawable/zoomout_00047.png b/res/drawable/zoomout_00047.png Binary files differnew file mode 100644 index 000000000..b4be2aa37 --- /dev/null +++ b/res/drawable/zoomout_00047.png diff --git a/res/drawable/zoomout_00048.png b/res/drawable/zoomout_00048.png Binary files differnew file mode 100644 index 000000000..b4be2aa37 --- /dev/null +++ b/res/drawable/zoomout_00048.png diff --git a/res/drawable/zoomout_00049.png b/res/drawable/zoomout_00049.png Binary files differnew file mode 100644 index 000000000..b4be2aa37 --- /dev/null +++ b/res/drawable/zoomout_00049.png diff --git a/res/layout-land/folder_cling.xml b/res/layout-land/folder_cling.xml index 86286d71b..5dd372973 100644 --- a/res/layout-land/folder_cling.xml +++ b/res/layout-land/folder_cling.xml @@ -16,7 +16,7 @@ <com.android.launcher3.Cling xmlns:android="http://schemas.android.com/apk/res/android" xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3" - launcher:drawIdentifier="folder_portrait"> + launcher:drawIdentifier="folder_landscape"> <FrameLayout android:layout_width="match_parent" android:layout_height="match_parent" @@ -25,6 +25,7 @@ android:layout_marginTop="10dp" android:layout_marginBottom="10dp"> <LinearLayout + android:id="@+id/folder_bubble" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> @@ -59,6 +60,6 @@ android:id="@+id/cling_dismiss" android:layout_marginBottom="15dp" android:layout_marginEnd="20dp" - android:layout_gravity="bottom|end" + android:layout_gravity="bottom|right" android:onClick="dismissFolderCling" /> </com.android.launcher3.Cling> diff --git a/res/layout-land/launcher.xml b/res/layout-land/launcher.xml index 2f64efe39..3e8503a67 100644 --- a/res/layout-land/launcher.xml +++ b/res/layout-land/launcher.xml @@ -36,9 +36,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="center" - launcher:defaultScreen="@integer/config_workspaceDefaultScreen" - launcher:pageSpacing="@dimen/workspace_page_spacing" - launcher:pageIndicator="@id/page_indicator" /> + launcher:defaultScreen="@integer/config_workspaceDefaultScreen" /> <include layout="@layout/hotseat" android:id="@+id/hotseat" @@ -47,8 +45,8 @@ android:layout_gravity="end" /> <include - android:id="@+id/qsb_bar" - layout="@layout/qsb_bar" /> + android:id="@+id/search_drop_target_bar" + layout="@layout/search_drop_target_bar" /> <!-- The Workspace cling must appear under the AppsCustomizePagedView below to ensure that it is still visible during the transition to AllApps and doesn't overlay on @@ -63,43 +61,33 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:visibility="gone" /> + <include layout="@layout/migration_cling" + android:id="@+id/migration_cling" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:visibility="gone" /> + <include layout="@layout/migration_workspace_cling" + android:id="@+id/migration_workspace_cling" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:visibility="gone" /> <include layout="@layout/workspace_cling" android:id="@+id/workspace_cling" android:layout_width="match_parent" android:layout_height="match_parent" android:visibility="gone" /> - <include layout="@layout/folder_cling" android:id="@+id/folder_cling" android:layout_width="match_parent" android:layout_height="match_parent" android:visibility="gone" /> - <!-- TODO: Fix - <com.android.launcher3.DrawableStateProxyView - android:id="@+id/voice_button_proxy" - android:layout_width="0dp" - android:layout_height="0dp" - android:layout_gravity="top|start" - android:layout_marginTop="64dp" - android:clickable="true" - android:onClick="onClickVoiceButton" - android:importantForAccessibility="no" - launcher:sourceViewId="@+id/voice_button" /> - --> - <include layout="@layout/apps_customize_pane" android:id="@+id/apps_customize_pane" android:layout_width="match_parent" android:layout_height="match_parent" android:visibility="invisible" /> - <include layout="@layout/all_apps_cling" - android:id="@+id/all_apps_cling" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:visibility="gone" /> - <include layout="@layout/overview_panel" android:id="@+id/overview_panel" android:visibility="gone" /> diff --git a/res/layout-land/migration_cling.xml b/res/layout-land/migration_cling.xml new file mode 100644 index 000000000..343f43f1f --- /dev/null +++ b/res/layout-land/migration_cling.xml @@ -0,0 +1,100 @@ +<?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. +--> +<com.android.launcher3.Cling + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3" + android:layout_width="match_parent" + android:layout_height="match_parent" + launcher:drawIdentifier="migration_landscape"> + <FrameLayout + android:id="@+id/content" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical"> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="top" + android:orientation="vertical"> + <TextView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="top" + android:gravity="center" + android:text="@string/first_run_cling_title" + android:textSize="42dp" + android:textColor="#FFffffff" /> + <ImageView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="10dp" + android:layout_marginBottom="0dp" + android:layout_gravity="center_horizontal" + android:src="@drawable/on_boarding_welcome" /> + + <ImageView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal" + android:src="@drawable/cling_arrow_up" /> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginLeft="25dp" + android:layout_marginRight="25dp" + android:paddingLeft="25dp" + android:paddingRight="25dp" + android:paddingTop="20dp" + android:paddingBottom="20dp" + android:orientation="vertical" + android:background="@drawable/cling"> + <TextView + style="@style/ClingTitleText" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/migration_cling_title" /> + <TextView + style="@style/ClingText" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/migration_cling_description" /> + </LinearLayout> + </LinearLayout> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="bottom" + android:layout_marginLeft="25dp" + android:layout_marginRight="25dp" + android:layout_marginBottom="25dp" + android:orientation="vertical"> + <Button + style="@style/ClingButton" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/migration_cling_copy_apps" + android:onClick="dismissMigrationClingCopyApps" /> + <Button + style="@style/ClingButton" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/migration_cling_use_default" + android:onClick="dismissMigrationClingUseDefault" /> + </LinearLayout> + </FrameLayout> +</com.android.launcher3.Cling> diff --git a/res/layout-land/migration_workspace_cling.xml b/res/layout-land/migration_workspace_cling.xml new file mode 100644 index 000000000..1148be45f --- /dev/null +++ b/res/layout-land/migration_workspace_cling.xml @@ -0,0 +1,70 @@ +<?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. +--> +<com.android.launcher3.Cling + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3" + android:layout_width="match_parent" + android:layout_height="match_parent" + launcher:drawIdentifier="migration_workspace_landscape"> + <LinearLayout + android:id="@+id/content" + android:layout_width="400dp" + android:layout_height="wrap_content" + android:layout_gravity="end|center_vertical" + android:paddingEnd="60dp" + android:paddingRight="60dp" + android:orientation="vertical"> + <LinearLayout + android:id="@+id/migration_workspace_cling_bubble" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal"> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginRight="4dp" + android:paddingLeft="20dp" + android:paddingRight="20dp" + android:paddingTop="20dp" + android:paddingBottom="20dp" + android:orientation="vertical" + android:background="@drawable/cling"> + <TextView + style="@style/ClingTitleText" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/workspace_cling_title" /> + <TextView + style="@style/ClingText" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/workspace_cling_move_item" /> + </LinearLayout> + <ImageView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical" + android:src="@drawable/cling_arrow_end" /> + </LinearLayout> + <Button + style="@style/ClingButton" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="5dp" + android:layout_gravity="right" + android:onClick="dismissMigrationWorkspaceCling" /> + </LinearLayout> +</com.android.launcher3.Cling> diff --git a/res/layout-land/search_bar.xml b/res/layout-land/qsb.xml index d56e380d0..d56e380d0 100644 --- a/res/layout-land/search_bar.xml +++ b/res/layout-land/qsb.xml diff --git a/res/layout-land/workspace_cling.xml b/res/layout-land/workspace_cling.xml index db33db06f..d3b07d74d 100644 --- a/res/layout-land/workspace_cling.xml +++ b/res/layout-land/workspace_cling.xml @@ -18,24 +18,20 @@ xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3" android:layout_width="match_parent" android:layout_height="match_parent" - launcher:drawIdentifier="workspace_portrait"> + launcher:drawIdentifier="workspace_landscape"> <FrameLayout android:id="@+id/content" android:layout_width="match_parent" - android:layout_height="match_parent" - android:layout_marginStart="25dp" - android:layout_marginEnd="25dp" - android:layout_marginTop="310dp"> + android:layout_height="match_parent"> <LinearLayout + android:id="@+id/workspace_cling_bubble" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="top" + android:layout_marginStart="25dp" + android:layout_marginEnd="25dp" + android:layout_marginTop="30dp" android:orientation="vertical"> - <ImageView - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center_horizontal" - android:src="@drawable/cling_arrow_up" /> <LinearLayout android:paddingLeft="20dp" android:paddingRight="20dp" @@ -56,14 +52,57 @@ android:layout_height="wrap_content" android:text="@string/workspace_cling_move_item" /> </LinearLayout> + <ImageView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal" + android:src="@drawable/cling_arrow_down" /> + </LinearLayout> + + <LinearLayout + android:id="@+id/focused_hotseat_app_bubble" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="bottom|left" + android:layout_marginLeft="25dp" + android:layout_marginBottom="90dp" + android:orientation="vertical" + android:visibility="gone"> + <LinearLayout + android:paddingLeft="20dp" + android:paddingRight="20dp" + android:paddingTop="20dp" + android:paddingBottom="20dp" + android:layout_width="240dp" + android:layout_height="wrap_content" + android:orientation="vertical" + android:background="@drawable/cling"> + <TextView + android:id="@+id/focused_hotseat_app_title" + style="@style/ClingTitleText" + android:layout_width="wrap_content" + android:layout_height="wrap_content" /> + <TextView + android:id="@+id/focused_hotseat_app_description" + style="@style/ClingText" + android:layout_width="match_parent" + android:layout_height="wrap_content" /> + </LinearLayout> + <ImageView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="left" + android:layout_marginLeft="78dp" + android:src="@drawable/cling_arrow_down" /> </LinearLayout> </FrameLayout> + <Button style="@style/ClingButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="15dp" - android:layout_marginEnd="20dp" - android:layout_gravity="bottom|end" + android:layout_marginRight="20dp" + android:layout_gravity="bottom|right" android:onClick="dismissWorkspaceCling" /> </com.android.launcher3.Cling> diff --git a/res/layout-port/first_run_cling.xml b/res/layout-port/first_run_cling.xml index 4830e5df8..ac3939cfd 100644 --- a/res/layout-port/first_run_cling.xml +++ b/res/layout-port/first_run_cling.xml @@ -39,16 +39,14 @@ android:layout_marginBottom="10dp" android:text="@string/first_run_cling_title" android:textColor="#FFFFFFFF" - android:textSize="30sp" android:gravity="center" /> <TextView - style="@style/ClingAltTitleText" + style="@style/ClingAltText" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:text="@string/first_run_cling_description" android:textColor="#80000000" - android:textSize="16sp" android:gravity="center" /> </LinearLayout> <TextView diff --git a/res/layout-port/folder_cling.xml b/res/layout-port/folder_cling.xml index 86286d71b..1a1b11fce 100644 --- a/res/layout-port/folder_cling.xml +++ b/res/layout-port/folder_cling.xml @@ -25,6 +25,7 @@ android:layout_marginTop="10dp" android:layout_marginBottom="10dp"> <LinearLayout + android:id="@+id/folder_bubble" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> @@ -59,6 +60,6 @@ android:id="@+id/cling_dismiss" android:layout_marginBottom="15dp" android:layout_marginEnd="20dp" - android:layout_gravity="bottom|end" + android:layout_gravity="bottom|right" android:onClick="dismissFolderCling" /> </com.android.launcher3.Cling> diff --git a/res/layout-port/launcher.xml b/res/layout-port/launcher.xml index 98cd0f3b6..c55aec867 100644 --- a/res/layout-port/launcher.xml +++ b/res/layout-port/launcher.xml @@ -35,8 +35,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" launcher:defaultScreen="@integer/config_workspaceDefaultScreen" - launcher:pageSpacing="@dimen/workspace_page_spacing" - launcher:pageIndicator="@id/page_indicator"> + launcher:pageIndicator="@+id/page_indicator"> </com.android.launcher3.Workspace> <include layout="@layout/hotseat" @@ -54,8 +53,8 @@ android:layout_gravity="center_horizontal" /> <include - android:id="@+id/qsb_bar" - layout="@layout/qsb_bar" /> + android:id="@+id/search_drop_target_bar" + layout="@layout/search_drop_target_bar" /> <!-- The Workspace cling must appear under the AppsCustomizePagedView below to ensure that it is still visible during the transition to AllApps and doesn't overlay on @@ -70,6 +69,16 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:visibility="gone" /> + <include layout="@layout/migration_cling" + android:id="@+id/migration_cling" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:visibility="gone" /> + <include layout="@layout/migration_workspace_cling" + android:id="@+id/migration_workspace_cling" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:visibility="gone" /> <include layout="@layout/workspace_cling" android:id="@+id/workspace_cling" android:layout_width="match_parent" @@ -99,12 +108,6 @@ android:layout_height="match_parent" android:visibility="invisible" /> - <include layout="@layout/all_apps_cling" - android:id="@+id/all_apps_cling" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:visibility="gone" /> - <include layout="@layout/overview_panel" android:id="@+id/overview_panel" android:visibility="gone" /> diff --git a/res/layout-port/migration_cling.xml b/res/layout-port/migration_cling.xml new file mode 100644 index 000000000..1bffe6c82 --- /dev/null +++ b/res/layout-port/migration_cling.xml @@ -0,0 +1,100 @@ +<?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. +--> +<com.android.launcher3.Cling + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3" + android:layout_width="match_parent" + android:layout_height="match_parent" + launcher:drawIdentifier="migration_portrait"> + <FrameLayout + android:id="@+id/content" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical"> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="top" + android:orientation="vertical"> + <TextView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="top" + android:gravity="center" + android:text="@string/first_run_cling_title" + android:textSize="42dp" + android:textColor="#FFffffff" /> + <ImageView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="10dp" + android:layout_marginBottom="0dp" + android:layout_gravity="center_horizontal" + android:src="@drawable/on_boarding_welcome" /> + + <ImageView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal" + android:src="@drawable/cling_arrow_up" /> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginLeft="25dp" + android:layout_marginRight="25dp" + android:paddingLeft="25dp" + android:paddingRight="25dp" + android:paddingTop="20dp" + android:paddingBottom="20dp" + android:orientation="vertical" + android:background="@drawable/cling"> + <TextView + style="@style/ClingTitleText" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/migration_cling_title" /> + <TextView + style="@style/ClingText" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/migration_cling_description" /> + </LinearLayout> + </LinearLayout> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="bottom" + android:layout_marginLeft="25dp" + android:layout_marginRight="25dp" + android:layout_marginBottom="25dp" + android:orientation="vertical"> + <Button + style="@style/ClingButton" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/migration_cling_copy_apps" + android:onClick="dismissMigrationClingCopyApps" /> + <Button + style="@style/ClingButton" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/migration_cling_use_default" + android:onClick="dismissMigrationClingUseDefault" /> + </LinearLayout> + </FrameLayout> +</com.android.launcher3.Cling> diff --git a/res/layout-port/all_apps_cling.xml b/res/layout-port/migration_workspace_cling.xml index ed99d78a0..576bb41f2 100644 --- a/res/layout-port/all_apps_cling.xml +++ b/res/layout-port/migration_workspace_cling.xml @@ -18,18 +18,18 @@ xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3" android:layout_width="match_parent" android:layout_height="match_parent" - launcher:drawIdentifier="all_apps"> + launcher:drawIdentifier="migration_workspace_portrait"> <FrameLayout android:id="@+id/content" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout + android:id="@+id/migration_workspace_cling_bubble" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_gravity="top" + android:layout_gravity="bottom" android:layout_marginStart="25dp" android:layout_marginEnd="25dp" - android:layout_marginTop="30dp" android:orientation="vertical"> <LinearLayout android:paddingLeft="20dp" @@ -44,22 +44,27 @@ style="@style/ClingTitleText" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="@string/all_apps_cling_cm" /> + android:text="@string/workspace_cling_title" /> <TextView style="@style/ClingText" android:layout_width="match_parent" android:layout_height="wrap_content" - android:text="@string/all_apps_cling_summary" /> + android:text="@string/workspace_cling_move_item" /> </LinearLayout> + <ImageView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal" + android:src="@drawable/cling_arrow_down" /> </LinearLayout> - </FrameLayout> - <Button - style="@style/ClingButton" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginBottom="60dp" - android:layout_marginRight="20dp" - android:layout_gravity="bottom|right" - android:onClick="dismissAllAppsCling" /> + <Button + style="@style/ClingButton" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginBottom="15dp" + android:layout_marginEnd="20dp" + android:layout_gravity="bottom|right" + android:onClick="dismissMigrationWorkspaceCling" /> + </FrameLayout> </com.android.launcher3.Cling> diff --git a/res/layout-sw720dp/search_bar.xml b/res/layout-port/qsb.xml index 1c96ca380..f7a1c8773 100644 --- a/res/layout-sw720dp/search_bar.xml +++ b/res/layout-port/qsb.xml @@ -16,13 +16,12 @@ <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3" - style="@style/SearchDropTargetBar" android:layout_width="match_parent" android:layout_height="match_parent" - android:background="@drawable/search_frame"> + android:background="@drawable/search_bg"> <!-- Global search icon --> <com.android.launcher3.HolographicLinearLayout - style="@style/SearchButton" + style="@style/SearchButton.WithPaddingStart" launcher:sourceImageViewId="@+id/search_button" android:id="@+id/search_button_container" android:layout_width="match_parent" @@ -31,7 +30,6 @@ android:layout_centerVertical="true" android:layout_alignParentStart="true" android:layout_toStartOf="@+id/voice_button_container" - android:paddingStart="8dp" android:onClick="onClickSearchButton" android:focusable="true" android:clickable="true" @@ -57,6 +55,7 @@ android:layout_centerVertical="true" android:layout_alignParentEnd="true" android:paddingEnd="8dp" + android:paddingRight="8dp" android:onClick="onClickVoiceButton" android:focusable="true" android:clickable="true" diff --git a/res/layout-port/workspace_cling.xml b/res/layout-port/workspace_cling.xml index b926ca967..624568668 100644 --- a/res/layout-port/workspace_cling.xml +++ b/res/layout-port/workspace_cling.xml @@ -24,6 +24,7 @@ android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout + android:id="@+id/workspace_cling_bubble" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="top" diff --git a/res/layout-sw600dp-port/first_run_cling.xml b/res/layout-sw600dp-port/first_run_cling.xml new file mode 100644 index 000000000..d80c084ab --- /dev/null +++ b/res/layout-sw600dp-port/first_run_cling.xml @@ -0,0 +1,100 @@ +<?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. +--> +<com.android.launcher3.Cling + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3" + android:layout_width="match_parent" + android:layout_height="match_parent" + launcher:drawIdentifier="first_run_portrait"> + <FrameLayout + android:id="@+id/content" + android:layout_width="match_parent" + android:layout_height="match_parent"> + <LinearLayout + android:id="@+id/bubble_content" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:layout_marginLeft="100dp" + android:layout_marginRight="100dp" + android:orientation="vertical"> + <TextView + style="@style/ClingAltTitleText" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal" + android:layout_marginBottom="10dp" + android:text="@string/first_run_cling_title" + android:textColor="#FFFFFFFF" + android:gravity="center" /> + <TextView + style="@style/ClingAltText" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal" + android:text="@string/first_run_cling_description" + android:textColor="#80000000" + android:gravity="center" /> + </LinearLayout> + <TextView + style="@style/ClingHintText" + android:id="@+id/search_bar_hint" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="top|end" + android:layout_marginEnd="30dp" + android:layout_marginTop="80dp" + android:gravity="center_horizontal" + android:maxWidth="160dp" + android:visibility="gone" + android:drawableTop="@drawable/cling_arrow_up" + android:drawablePadding="10dp" + android:text="@string/first_run_cling_search_bar_hint" /> + <TextView + style="@style/ClingHintText" + android:id="@+id/custom_content_hint" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="top|start" + android:layout_marginStart="30dp" + android:layout_marginTop="120dp" + android:gravity="start" + android:maxWidth="160dp" + android:visibility="gone" + android:drawableStart="@drawable/cling_arrow_start" + android:drawablePadding="10dp" + android:text="@string/first_run_cling_custom_content_hint" /> + <TextView + style="@style/ClingHintText" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="bottom|end" + android:layout_marginEnd="30dp" + android:layout_marginBottom="120dp" + android:maxWidth="180dp" + android:drawableEnd="@drawable/cling_arrow_end" + android:drawablePadding="10dp" + android:text="@string/first_run_cling_create_screens_hint" /> + </FrameLayout> + <Button + style="@style/ClingButton" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginBottom="30dp" + android:layout_marginEnd="30dp" + android:layout_gravity="bottom|end" + android:onClick="dismissFirstRunCling" /> +</com.android.launcher3.Cling> diff --git a/res/layout-sw600dp-port/folder_cling.xml b/res/layout-sw600dp-port/folder_cling.xml deleted file mode 100644 index 87086cb62..000000000 --- a/res/layout-sw600dp-port/folder_cling.xml +++ /dev/null @@ -1,51 +0,0 @@ -<?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. ---> -<com.android.launcher3.Cling - xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3" - launcher:drawIdentifier="folder_portrait"> - <FrameLayout - android:layout_width="match_parent" - android:layout_height="match_parent" - android:layout_marginStart="20dp" - android:layout_marginEnd="10dp" - android:layout_marginTop="@dimen/folderClingMarginTop"> - <LinearLayout - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="vertical"> - <TextView - style="@style/ClingTitleText" - android:id="@+id/folder_cling_title" - android:text="@string/folder_cling_title" /> - <TextView - style="@style/ClingText" - android:id="@+id/folder_cling_create_folder" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:text="@string/folder_cling_create_folder" /> - </LinearLayout> - </FrameLayout> - <Button - style="@style/ClingButton" - android:id="@+id/cling_dismiss" - android:minWidth="168dp" - android:textSize="24sp" - android:layout_marginBottom="27dp" - android:layout_marginEnd="36dp" - android:layout_gravity="bottom|end" - android:onClick="dismissFolderCling" /> -</com.android.launcher3.Cling> diff --git a/res/layout-sw600dp-port/migration_workspace_cling.xml b/res/layout-sw600dp-port/migration_workspace_cling.xml new file mode 100644 index 000000000..eb13137a1 --- /dev/null +++ b/res/layout-sw600dp-port/migration_workspace_cling.xml @@ -0,0 +1,70 @@ +<?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. +--> +<com.android.launcher3.Cling + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3" + android:layout_width="match_parent" + android:layout_height="match_parent" + launcher:drawIdentifier="migration_workspace_large_portrait"> + <FrameLayout + android:id="@+id/content" + android:layout_width="480dp" + android:layout_height="match_parent" + android:layout_gravity="bottom|center_horizontal"> + <LinearLayout + android:id="@+id/migration_workspace_cling_bubble" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="bottom" + android:layout_marginStart="25dp" + android:layout_marginEnd="25dp" + android:orientation="vertical"> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginRight="4dp" + android:paddingLeft="20dp" + android:paddingRight="20dp" + android:paddingTop="20dp" + android:paddingBottom="20dp" + android:orientation="vertical" + android:background="@drawable/cling"> + <TextView + style="@style/ClingTitleText" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/workspace_cling_title" /> + <TextView + style="@style/ClingText" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/workspace_cling_move_item" /> + </LinearLayout> + <ImageView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal" + android:src="@drawable/cling_arrow_down" /> + <Button + style="@style/ClingButton" + android:id="@+id/dismiss_migration_workspace_cling_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="right" + android:onClick="dismissMigrationWorkspaceCling" /> + </LinearLayout> + </FrameLayout> +</com.android.launcher3.Cling> diff --git a/res/layout-sw600dp/first_run_cling.xml b/res/layout-sw600dp/first_run_cling.xml new file mode 100644 index 000000000..295765b6e --- /dev/null +++ b/res/layout-sw600dp/first_run_cling.xml @@ -0,0 +1,100 @@ +<?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. +--> +<com.android.launcher3.Cling + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3" + android:layout_width="match_parent" + android:layout_height="match_parent" + launcher:drawIdentifier="first_run_landscape"> + <FrameLayout + android:id="@+id/content" + android:layout_width="match_parent" + android:layout_height="match_parent"> + <LinearLayout + android:id="@+id/bubble_content" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:layout_marginLeft="100dp" + android:layout_marginRight="100dp" + android:orientation="vertical"> + <TextView + style="@style/ClingAltTitleText" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal" + android:layout_marginBottom="10dp" + android:text="@string/first_run_cling_title" + android:textColor="#FFFFFFFF" + android:gravity="center" /> + <TextView + style="@style/ClingAltText" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal" + android:text="@string/first_run_cling_description" + android:textColor="#80000000" + android:gravity="center" /> + </LinearLayout> + <TextView + style="@style/ClingHintText" + android:id="@+id/search_bar_hint" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="top|start" + android:layout_marginStart="60dp" + android:layout_marginTop="105dp" + android:gravity="start" + android:maxWidth="160dp" + android:visibility="gone" + android:drawableStart="@drawable/cling_arrow_start" + android:drawablePadding="10dp" + android:text="@string/first_run_cling_search_bar_hint" /> + <TextView + style="@style/ClingHintText" + android:id="@+id/custom_content_hint" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="top|start" + android:layout_marginStart="60dp" + android:layout_marginTop="200dp" + android:gravity="start" + android:maxWidth="160dp" + android:visibility="gone" + android:drawableStart="@drawable/cling_arrow_start" + android:drawablePadding="10dp" + android:text="@string/first_run_cling_custom_content_hint" /> + <TextView + style="@style/ClingHintText" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="bottom|end" + android:layout_marginEnd="30dp" + android:layout_marginBottom="120dp" + android:maxWidth="180dp" + android:drawableEnd="@drawable/cling_arrow_end" + android:drawablePadding="10dp" + android:text="@string/first_run_cling_create_screens_hint" /> + </FrameLayout> + <Button + style="@style/ClingButton" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginBottom="30dp" + android:layout_marginEnd="30dp" + android:layout_gravity="bottom|end" + android:onClick="dismissFirstRunCling" /> +</com.android.launcher3.Cling> diff --git a/res/layout-sw600dp/folder_cling.xml b/res/layout-sw600dp/folder_cling.xml new file mode 100644 index 000000000..f21aef4e4 --- /dev/null +++ b/res/layout-sw600dp/folder_cling.xml @@ -0,0 +1,66 @@ +<?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. +--> +<com.android.launcher3.Cling + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3" + launcher:drawIdentifier="folder_large"> + <LinearLayout + android:id="@+id/folder_bubble" + android:layout_width="300dp" + android:layout_height="match_parent" + android:layout_gravity="left|top" + android:paddingTop="28dp" + android:paddingRight="10dp" + android:orientation="vertical"> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal"> + <ImageView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical" + android:src="@drawable/cling_arrow_start" /> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginRight="4dp" + android:paddingLeft="20dp" + android:paddingRight="20dp" + android:paddingTop="20dp" + android:paddingBottom="20dp" + android:orientation="vertical" + android:background="@drawable/cling"> + <TextView + style="@style/ClingTitleText" + android:id="@+id/folder_cling_title" + android:text="@string/folder_cling_title" /> + <TextView + style="@style/ClingText" + android:id="@+id/folder_cling_create_folder" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/folder_cling_create_folder" /> + </LinearLayout> + </LinearLayout> + <Button + style="@style/ClingButton" + android:id="@+id/cling_dismiss" + android:layout_marginTop="5dp" + android:layout_gravity="right" + android:onClick="dismissFolderCling" /> + </LinearLayout> +</com.android.launcher3.Cling> diff --git a/res/layout-sw600dp/migration_cling.xml b/res/layout-sw600dp/migration_cling.xml new file mode 100644 index 000000000..19def6a56 --- /dev/null +++ b/res/layout-sw600dp/migration_cling.xml @@ -0,0 +1,98 @@ +<?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. +--> +<com.android.launcher3.Cling + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3" + android:layout_width="match_parent" + android:layout_height="match_parent" + launcher:drawIdentifier="migration_portrait"> + <LinearLayout + android:id="@+id/content" + android:layout_width="360dp" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:orientation="vertical"> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="top" + android:layout_marginBottom="15dp" + android:orientation="vertical"> + <TextView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:gravity="center" + android:text="@string/first_run_cling_title" + android:textSize="42dp" + android:textColor="#FFffffff" /> + <ImageView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="10dp" + android:layout_marginBottom="0dp" + android:layout_gravity="center_horizontal" + android:src="@drawable/on_boarding_welcome" /> + + <ImageView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal" + android:src="@drawable/cling_arrow_up" /> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginLeft="4dp" + android:layout_marginRight="4dp" + android:paddingLeft="25dp" + android:paddingRight="25dp" + android:paddingTop="20dp" + android:paddingBottom="20dp" + android:orientation="vertical" + android:background="@drawable/cling"> + <TextView + style="@style/ClingTitleText" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/migration_cling_title" /> + <TextView + style="@style/ClingText" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/migration_cling_description" /> + </LinearLayout> + </LinearLayout> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="bottom" + android:orientation="vertical"> + <Button + style="@style/ClingButton" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/migration_cling_copy_apps" + android:onClick="dismissMigrationClingCopyApps" /> + <Button + style="@style/ClingButton" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/migration_cling_use_default" + android:onClick="dismissMigrationClingUseDefault" /> + </LinearLayout> + </LinearLayout> +</com.android.launcher3.Cling> diff --git a/res/layout-land/all_apps_cling.xml b/res/layout-sw600dp/workspace_cling.xml index 19a93a5f3..63b5522ca 100644 --- a/res/layout-land/all_apps_cling.xml +++ b/res/layout-sw600dp/workspace_cling.xml @@ -18,47 +18,48 @@ xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3" android:layout_width="match_parent" android:layout_height="match_parent" - launcher:drawIdentifier="all_apps"> + launcher:drawIdentifier="workspace_large"> <FrameLayout android:id="@+id/content" android:layout_width="match_parent" - android:layout_height="match_parent" - android:layout_marginStart="25dp" - android:layout_marginEnd="25dp" - android:layout_marginTop="310dp"> + android:layout_height="match_parent"> <LinearLayout - android:layout_width="match_parent" + android:id="@+id/workspace_cling_bubble" + android:layout_width="400dp" android:layout_height="wrap_content" - android:layout_gravity="top" + android:layout_gravity="center_horizontal|bottom" android:orientation="vertical"> <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" android:paddingLeft="20dp" android:paddingRight="20dp" android:paddingTop="20dp" android:paddingBottom="20dp" - android:layout_width="match_parent" - android:layout_height="wrap_content" android:orientation="vertical" android:background="@drawable/cling"> <TextView style="@style/ClingTitleText" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="@string/all_apps_cling_cm" /> + android:text="@string/workspace_cling_title" /> <TextView style="@style/ClingText" android:layout_width="match_parent" android:layout_height="wrap_content" - android:text="@string/all_apps_cling_summary" /> + android:text="@string/workspace_cling_move_item" /> </LinearLayout> + <ImageView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal" + android:src="@drawable/cling_arrow_down" /> + <Button + style="@style/ClingButton" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="right" + android:onClick="dismissWorkspaceCling" /> </LinearLayout> </FrameLayout> - <Button - style="@style/ClingButton" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginBottom="15dp" - android:layout_marginEnd="20dp" - android:layout_gravity="bottom|end" - android:onClick="dismissAllAppsCling" /> </com.android.launcher3.Cling> diff --git a/res/layout-sw720dp-port/folder_cling.xml b/res/layout-sw720dp-port/folder_cling.xml deleted file mode 100644 index 40d4e20a5..000000000 --- a/res/layout-sw720dp-port/folder_cling.xml +++ /dev/null @@ -1,46 +0,0 @@ -<?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. ---> -<com.android.launcher3.Cling - xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3" - launcher:drawIdentifier="folder_large"> - <FrameLayout - android:layout_width="match_parent" - android:layout_height="match_parent" - android:layout_marginStart="@dimen/cling_text_block_offset_x" - android:layout_marginTop="@dimen/cling_text_block_offset_y"> - <LinearLayout - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="vertical"> - <TextView - style="@style/ClingTitleText" - android:id="@+id/folder_cling_title" - android:text="@string/folder_cling_title" /> - <TextView - style="@style/ClingText" - android:id="@+id/folder_cling_create_folder" - android:layout_width="480dp" - android:layout_height="wrap_content" - android:text="@string/folder_cling_create_folder" /> - <Button - style="@style/ClingButton" - android:id="@+id/cling_dismiss" - android:layout_marginTop="15dp" - android:onClick="dismissFolderCling" /> - </LinearLayout> - </FrameLayout> -</com.android.launcher3.Cling> diff --git a/res/layout-sw720dp/first_run_cling.xml b/res/layout-sw720dp/first_run_cling.xml new file mode 100644 index 000000000..c43d8d32e --- /dev/null +++ b/res/layout-sw720dp/first_run_cling.xml @@ -0,0 +1,98 @@ +<?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. +--> +<com.android.launcher3.Cling + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3" + android:layout_width="match_parent" + android:layout_height="match_parent" + launcher:drawIdentifier="first_run_portrait"> + <FrameLayout + android:id="@+id/content" + android:layout_width="match_parent" + android:layout_height="match_parent"> + <LinearLayout + android:id="@+id/bubble_content" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:layout_marginLeft="100dp" + android:layout_marginRight="100dp" + android:orientation="vertical"> + <TextView + style="@style/ClingAltTitleText" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal" + android:layout_marginBottom="10dp" + android:text="@string/first_run_cling_title" + android:textColor="#FFFFFFFF" + android:gravity="center" /> + <TextView + style="@style/ClingAltText" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal" + android:text="@string/first_run_cling_description" + android:textColor="#80000000" + android:gravity="center" /> + </LinearLayout> + <TextView + style="@style/ClingHintText" + android:id="@+id/search_bar_hint" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="top|end" + android:layout_marginEnd="120dp" + android:layout_marginTop="80dp" + android:gravity="center_horizontal" + android:maxWidth="160dp" + android:visibility="gone" + android:drawableTop="@drawable/cling_arrow_up" + android:drawablePadding="10dp" + android:text="@string/first_run_cling_search_bar_hint" /> + <TextView + style="@style/ClingHintText" + android:id="@+id/custom_content_hint" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical|start" + android:layout_marginStart="30dp" + android:gravity="start" + android:maxWidth="160dp" + android:visibility="gone" + android:drawableStart="@drawable/cling_arrow_start" + android:drawablePadding="10dp" + android:text="@string/first_run_cling_custom_content_hint" /> + <TextView + style="@style/ClingHintText" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical|end" + android:layout_marginEnd="30dp" + android:maxWidth="180dp" + android:drawableEnd="@drawable/cling_arrow_end" + android:drawablePadding="10dp" + android:text="@string/first_run_cling_create_screens_hint" /> + </FrameLayout> + <Button + style="@style/ClingButton" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginBottom="30dp" + android:layout_marginEnd="40dp" + android:layout_gravity="bottom|end" + android:onClick="dismissFirstRunCling" /> +</com.android.launcher3.Cling> diff --git a/res/layout-sw720dp/launcher.xml b/res/layout-sw720dp/launcher.xml index 7b0d770ec..d7d67cc3f 100644 --- a/res/layout-sw720dp/launcher.xml +++ b/res/layout-sw720dp/launcher.xml @@ -36,7 +36,6 @@ android:layout_width="match_parent" android:layout_height="match_parent" launcher:defaultScreen="@integer/config_workspaceDefaultScreen" - launcher:pageSpacing="@dimen/workspace_page_spacing" launcher:pageIndicator="@id/page_indicator"> </com.android.launcher3.Workspace> @@ -46,8 +45,8 @@ android:layout_height="match_parent" /> <include - android:id="@+id/qsb_bar" - layout="@layout/qsb_bar" /> + android:id="@+id/search_drop_target_bar" + layout="@layout/search_drop_target_bar" /> <!-- Keep these behind the workspace so that they are not visible when we go into AllApps --> @@ -61,17 +60,31 @@ <!-- The Workspace cling must appear under the AppsCustomizePagedView below to ensure that it is still visible during the transition to AllApps and doesn't overlay on top of that view. --> + <com.android.launcher3.ScrimView + android:id="@+id/cling_scrim" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:visibility="gone" /> <include layout="@layout/first_run_cling" android:id="@+id/first_run_cling" android:layout_width="match_parent" android:layout_height="match_parent" android:visibility="gone" /> + <include layout="@layout/migration_cling" + android:id="@+id/migration_cling" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:visibility="gone" /> + <include layout="@layout/migration_workspace_cling" + android:id="@+id/migration_workspace_cling" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:visibility="gone" /> <include layout="@layout/workspace_cling" android:id="@+id/workspace_cling" android:layout_width="match_parent" android:layout_height="match_parent" android:visibility="gone" /> - <include layout="@layout/folder_cling" android:id="@+id/folder_cling" android:layout_width="match_parent" @@ -94,12 +107,6 @@ android:layout_height="match_parent" android:visibility="invisible" /> - <include layout="@layout/all_apps_cling" - android:id="@+id/all_apps_cling" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:visibility="gone" /> - <include layout="@layout/overview_panel" android:id="@+id/overview_panel" android:visibility="gone" /> diff --git a/res/layout-sw720dp/market_button.xml b/res/layout-sw720dp/market_button.xml index f1e99599e..7eaeafac3 100644 --- a/res/layout-sw720dp/market_button.xml +++ b/res/layout-sw720dp/market_button.xml @@ -18,8 +18,8 @@ style="@style/MarketButton" android:onClick="onClickAppMarketButton" android:gravity="center" - android:paddingStart="32dp" - android:paddingEnd="32dp" + android:paddingLeft="32dp" + android:paddingRight="32dp" android:drawablePadding="10dp" android:background="@drawable/tab_widget_indicator_selector" android:text="@string/market" diff --git a/res/layout-sw720dp/migration_workspace_cling.xml b/res/layout-sw720dp/migration_workspace_cling.xml new file mode 100644 index 000000000..eb13137a1 --- /dev/null +++ b/res/layout-sw720dp/migration_workspace_cling.xml @@ -0,0 +1,70 @@ +<?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. +--> +<com.android.launcher3.Cling + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3" + android:layout_width="match_parent" + android:layout_height="match_parent" + launcher:drawIdentifier="migration_workspace_large_portrait"> + <FrameLayout + android:id="@+id/content" + android:layout_width="480dp" + android:layout_height="match_parent" + android:layout_gravity="bottom|center_horizontal"> + <LinearLayout + android:id="@+id/migration_workspace_cling_bubble" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="bottom" + android:layout_marginStart="25dp" + android:layout_marginEnd="25dp" + android:orientation="vertical"> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginRight="4dp" + android:paddingLeft="20dp" + android:paddingRight="20dp" + android:paddingTop="20dp" + android:paddingBottom="20dp" + android:orientation="vertical" + android:background="@drawable/cling"> + <TextView + style="@style/ClingTitleText" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/workspace_cling_title" /> + <TextView + style="@style/ClingText" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/workspace_cling_move_item" /> + </LinearLayout> + <ImageView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal" + android:src="@drawable/cling_arrow_down" /> + <Button + style="@style/ClingButton" + android:id="@+id/dismiss_migration_workspace_cling_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="right" + android:onClick="dismissMigrationWorkspaceCling" /> + </LinearLayout> + </FrameLayout> +</com.android.launcher3.Cling> diff --git a/res/layout-port/search_bar.xml b/res/layout-sw720dp/qsb.xml index 1c96ca380..399666ab0 100644 --- a/res/layout-port/search_bar.xml +++ b/res/layout-sw720dp/qsb.xml @@ -19,10 +19,10 @@ style="@style/SearchDropTargetBar" android:layout_width="match_parent" android:layout_height="match_parent" - android:background="@drawable/search_frame"> + android:background="@drawable/search_bg"> <!-- Global search icon --> <com.android.launcher3.HolographicLinearLayout - style="@style/SearchButton" + style="@style/SearchButton.WithPaddingStart" launcher:sourceImageViewId="@+id/search_button" android:id="@+id/search_button_container" android:layout_width="match_parent" @@ -31,7 +31,6 @@ android:layout_centerVertical="true" android:layout_alignParentStart="true" android:layout_toStartOf="@+id/voice_button_container" - android:paddingStart="8dp" android:onClick="onClickSearchButton" android:focusable="true" android:clickable="true" @@ -57,6 +56,7 @@ android:layout_centerVertical="true" android:layout_alignParentEnd="true" android:paddingEnd="8dp" + android:paddingRight="8dp" android:onClick="onClickVoiceButton" android:focusable="true" android:clickable="true" diff --git a/res/layout/add_list_item.xml b/res/layout/add_list_item.xml index 0ae011330..e937d7bc1 100644 --- a/res/layout/add_list_item.xml +++ b/res/layout/add_list_item.xml @@ -21,5 +21,5 @@ android:textAppearance="?android:attr/textAppearanceLarge" android:gravity="center_vertical" android:drawablePadding="14dip" - android:paddingStart="15dip" - android:paddingEnd="15dip" /> + android:paddingLeft="15dip" + android:paddingRight="15dip" /> diff --git a/res/layout/apps_customize_pane.xml b/res/layout/apps_customize_pane.xml index bc10e708a..1352e1904 100644 --- a/res/layout/apps_customize_pane.xml +++ b/res/layout/apps_customize_pane.xml @@ -27,19 +27,17 @@ android:id="@+id/apps_customize_pane_content" android:layout_width="match_parent" android:layout_height="match_parent" - android:layout_marginBottom="@dimen/apps_customize_page_indicator_offset" launcher:widgetCountX="@integer/apps_customize_widget_cell_count_x" launcher:widgetCountY="@integer/apps_customize_widget_cell_count_y" launcher:clingFocusedX="@integer/apps_customize_cling_focused_x" launcher:clingFocusedY="@integer/apps_customize_cling_focused_y" launcher:maxGap="@dimen/workspace_max_gap" - launcher:pageIndicator="@+id/page_indicator" /> + launcher:pageIndicator="@+id/apps_customize_page_indicator" /> <include - android:id="@+id/page_indicator" + android:id="@+id/apps_customize_page_indicator" layout="@layout/page_indicator" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_gravity="bottom|center_horizontal" - android:layout_marginBottom="@dimen/apps_customize_page_indicator_margin" /> + android:layout_gravity="center_horizontal|bottom" /> </FrameLayout> </com.android.launcher3.AppsCustomizeLayout> diff --git a/res/layout/apps_customize_widget.xml b/res/layout/apps_customize_widget.xml index f2d234266..7c98b4a9b 100644 --- a/res/layout/apps_customize_widget.xml +++ b/res/layout/apps_customize_widget.xml @@ -28,12 +28,13 @@ <!-- The preview of the widget or shortcut. --> <com.android.launcher3.PagedViewWidgetImageView android:id="@+id/widget_preview" + style="@style/PagedViewWidgetImageView" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:paddingTop="@dimen/app_widget_preview_padding_top" - android:paddingStart="@dimen/app_widget_preview_padding_left" android:paddingEnd="@dimen/app_widget_preview_padding_right" + android:paddingRight="@dimen/app_widget_preview_padding_right" android:scaleType="matrix" android:background="@drawable/screenpanel" /> <LinearLayout diff --git a/res/layout/appwidget_error.xml b/res/layout/appwidget_error.xml index f5a914819..03d4ae424 100644 --- a/res/layout/appwidget_error.xml +++ b/res/layout/appwidget_error.xml @@ -19,8 +19,8 @@ android:layout_height="wrap_content" android:paddingTop="10dip" android:paddingBottom="10dip" - android:paddingStart="20dip" - android:paddingEnd="20dip" + android:paddingLeft="20dip" + android:paddingRight="20dip" android:gravity="center" android:background="@drawable/bg_appwidget_error" android:textAppearance="?android:attr/textAppearanceMediumInverse" diff --git a/res/layout/custom_grid_size_dialog.xml b/res/layout/custom_grid_size_dialog.xml new file mode 100644 index 000000000..d7345ee56 --- /dev/null +++ b/res/layout/custom_grid_size_dialog.xml @@ -0,0 +1,33 @@ +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="wrap_content" + android:layout_height="wrap_content" > + + <LinearLayout + android:id="@+id/grid_number_pickers" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_centerHorizontal="true" + android:orientation="horizontal"> + + <NumberPicker + android:id="@+id/custom_rows" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginRight="@dimen/dialog_padding"/> + + <NumberPicker + android:id="@+id/custom_columns" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginLeft="@dimen/dialog_padding"/> + + </LinearLayout> + + <Button + android:id="@+id/dialog_confirm_button" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:text="@string/dialog_confirm" + android:layout_below="@id/grid_number_pickers" + android:layout_marginTop="@dimen/dialog_padding"/> +</RelativeLayout>
\ No newline at end of file diff --git a/res/layout/custom_workspace_cling.xml b/res/layout/custom_workspace_cling.xml deleted file mode 100644 index 3744f2e4b..000000000 --- a/res/layout/custom_workspace_cling.xml +++ /dev/null @@ -1,32 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2012 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. ---> -<!-- dummy layout, to be replaced in overlays --> -<com.android.launcher3.Cling - xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3" - android:layout_width="match_parent" - android:layout_height="match_parent" - launcher:drawIdentifier="workspace_custom"> - <TextView - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:textSize="20dp" - android:textColor="@android:color/holo_blue_light" - android:text="@string/dummy_custom_cling_error_message" - android:gravity="start" - android:layout_gravity="bottom|start" - /> -</com.android.launcher3.Cling> diff --git a/res/layout/dynamic_grid_size_screen.xml b/res/layout/dynamic_grid_size_screen.xml new file mode 100644 index 000000000..38db4b05c --- /dev/null +++ b/res/layout/dynamic_grid_size_screen.xml @@ -0,0 +1,52 @@ +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_gravity="center_horizontal|bottom" + android:background="@color/settings_bg_color" + android:orientation="vertical" + android:paddingBottom="@dimen/overview_panel_bottom_padding" + android:paddingTop="@dimen/overview_panel_bottom_padding" + android:clickable="true" > + + <LinearLayout + android:id="@+id/dynamic_grid_title" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal" + android:background="@drawable/listitem_bg" + android:clickable="true" > + + <ImageView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical" + android:adjustViewBounds="true" + android:src="@drawable/handle_left" /> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/grid_size_text" + android:textAllCaps="true" + android:fontFamily="sans-serif-condensed" + android:textColor="@android:color/white" + android:layout_gravity="center_vertical" + android:textSize="16sp" /> + </LinearLayout> + + <ImageView + android:id="@+id/dynamic_grid_size_image" + android:layout_width="@dimen/dynamic_grid_size_image_width" + android:layout_height="@dimen/dynamic_grid_size_image_height" + android:layout_gravity="center_horizontal" + android:adjustViewBounds="true" + android:layout_marginBottom="@dimen/grid_padding"/> + + <ListView + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/dynamic_grid_list" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:listSelector="@android:color/transparent" + android:splitMotionEvents="false"/> +</LinearLayout> diff --git a/res/layout/folder_icon.xml b/res/layout/folder_icon.xml index 44056828c..5147f9960 100644 --- a/res/layout/folder_icon.xml +++ b/res/layout/folder_icon.xml @@ -30,5 +30,8 @@ android:src="@drawable/portal_ring_inner_holo"/> <com.android.launcher3.BubbleTextView style="@style/WorkspaceIcon" - android:id="@+id/folder_icon_name" /> + android:id="@+id/folder_icon_name" + android:layout_gravity="top" + android:layout_width="match_parent" + android:layout_height="match_parent" /> </com.android.launcher3.FolderIcon> diff --git a/res/layout/hidden_folder.xml b/res/layout/hidden_folder.xml new file mode 100644 index 000000000..ca06f6e48 --- /dev/null +++ b/res/layout/hidden_folder.xml @@ -0,0 +1,51 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:background="@color/settings_bg_color" + android:orientation="vertical" + android:paddingLeft="@dimen/overview_panel_button_spacing" + android:paddingRight="@dimen/overview_panel_button_spacing" + android:paddingTop="@dimen/overview_panel_bottom_padding" + android:focusable="true" + android:focusableInTouchMode="true" + android:clickable="true" > + + <RelativeLayout + android:id="@+id/folder_title_lock" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal" > + <ImageView + android:id="@+id/folder_lock_icon" + android:layout_width="25dp" + android:layout_height="25dp" + android:layout_alignParentRight="true" + android:layout_centerVertical="true" + android:src="@drawable/folder_unlock" + android:background="@drawable/listitem_bg" /> + + <EditText + android:id="@+id/folder_name" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignParentLeft="true" + android:paddingBottom="@dimen/folder_name_padding" + android:paddingTop="@dimen/folder_name_padding" + android:hint="@string/folder_hint_text" + android:textColor="@android:color/white" + android:textSize="20sp" + android:textColorHighlight="#ffCCCCCC" + android:textCursorDrawable="@null" + android:singleLine="true" + android:background="#00000000" /> + </RelativeLayout> + + <ListView + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/hidden_apps_list" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginLeft="5dp" /> + +</LinearLayout> diff --git a/res/layout/hidden_folder_apps_list_item.xml b/res/layout/hidden_folder_apps_list_item.xml new file mode 100644 index 000000000..f3af4ad1d --- /dev/null +++ b/res/layout/hidden_folder_apps_list_item.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:minHeight="48dp" + android:gravity="center_vertical" + android:paddingRight="?android:attr/scrollbarSize" + android:background="?android:attr/selectableItemBackground"> + + <ImageView android:id="@+id/icon" + android:layout_width="40dp" + android:layout_height="40dp" + android:layout_gravity="center" /> + + <TextView android:id="@+id/title" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginLeft="15dip" + android:layout_marginRight="6dip" + android:layout_marginTop="6dip" + android:layout_marginBottom="6dip" + android:layout_weight="1" + android:singleLine="true" + android:textAppearance="?android:attr/textAppearanceMedium" + android:ellipsize="marquee" + android:fadingEdge="horizontal" /> + + <ImageView android:id="@+id/remove" + android:layout_width="40dp" + android:layout_height="40dp" + android:layout_gravity="center" + android:src="@drawable/ic_remove"/> +</LinearLayout>
\ No newline at end of file diff --git a/res/layout/iconpack_chooser.xml b/res/layout/iconpack_chooser.xml deleted file mode 100644 index 105a95969..000000000 --- a/res/layout/iconpack_chooser.xml +++ /dev/null @@ -1,29 +0,0 @@ -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:orientation="horizontal"> - <ImageView - android:id="@+id/icon" - android:layout_gravity="center_vertical" - android:layout_width="@dimen/app_icon_size" - android:layout_height="@dimen/app_icon_size" - android:layout_margin="8dp"/> - <TextView - android:id="@+id/title" - android:layout_width="0dp" - android:layout_height="wrap_content" - android:paddingStart="8dip" - android:paddingEnd="8dip" - android:layout_gravity="center_vertical" - android:layout_weight="1" - android:textAppearance="?android:attr/textAppearanceLarge" - android:textSize="19sp"/> - <RadioButton - android:id="@+id/radio" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center_vertical" - android:focusable="false" - android:clickable="false" - android:duplicateParentState="true" /> -</LinearLayout> diff --git a/res/layout/market_button.xml b/res/layout/market_button.xml index 4a718c3d6..41e6ec7cc 100644 --- a/res/layout/market_button.xml +++ b/res/layout/market_button.xml @@ -18,8 +18,8 @@ style="@style/MarketButton" android:onClick="onClickAppMarketButton" android:gravity="center" - android:paddingStart="16dp" - android:paddingEnd="16dp" + android:paddingLeft="16dp" + android:paddingRight="16dp" android:background="@drawable/tab_widget_indicator_selector" android:contentDescription="@string/market" android:shadowColor="@color/workspace_all_apps_and_delete_zone_text_shadow_color" diff --git a/res/layout/overview_panel.xml b/res/layout/overview_panel.xml index 479b622ec..cf9f616d7 100644 --- a/res/layout/overview_panel.xml +++ b/res/layout/overview_panel.xml @@ -1,7 +1,8 @@ <?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2013 The Android Open Source Project +<!-- + Copyright (C) 2013 The Android Open Source Project - Licensed under the Apache License, Version 2.0 (the "License"); + 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 @@ -13,138 +14,37 @@ See the License for the specific language governing permissions and limitations under the License. --> -<FrameLayout - xmlns:android="http://schemas.android.com/apk/res/android" + +<com.android.launcher3.SlidingUpPanelLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:slidingpanel="http://schemas.android.com/apk/res/com.android.launcher3" + android:id="@+id/sliding_layout" android:layout_width="match_parent" - android:layout_height="match_parent"> + android:layout_height="match_parent" + android:gravity="bottom" + slidingpanel:overlay="false" + slidingpanel:panelHeight="@dimen/sliding_panel_padding" > <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="wrap_content" + android:id="@+id/default_home_screen_panel" + android:layout_width="match_parent" android:layout_height="wrap_content" - android:orientation="horizontal" - android:layout_gravity="center_horizontal|top" - android:paddingTop="@dimen/overview_panel_top_padding"> + android:layout_gravity="center_horizontal" + android:background="@color/settings_bg_color" + android:paddingTop="@dimen/overview_panel_top_padding" > - <TextView + <ImageView android:id="@+id/default_screen_button" + android:layout_width="match_parent" + android:layout_height="@dimen/app_icon_size" android:layout_weight="1" - android:layout_width="0dp" - android:layout_height="wrap_content" + android:src="@drawable/default_screen_button" + android:scaleType="fitCenter" + android:gravity="top" android:paddingLeft="@dimen/overview_panel_button_spacing" - android:paddingRight="@dimen/overview_panel_button_spacing" - android:text="@string/default_screen_button_text" - android:drawablePadding="4dp" - android:drawableTop="@drawable/default_screen_button" - android:gravity="center_horizontal" - android:fontFamily="sans-serif-condensed" - android:textAllCaps="true" - android:textSize="12sp" /> - - <TextView - android:id="@+id/transition_effect_button" - android:layout_weight="1" - android:layout_width="0dp" - android:layout_height="wrap_content" - android:paddingLeft="@dimen/overview_panel_button_spacing" - android:paddingRight="@dimen/overview_panel_button_spacing" - android:text="@string/transition_effect_button_text" - android:drawablePadding="4dp" - android:drawableTop="@drawable/wallpaper_button" - android:gravity="center_horizontal" - android:fontFamily="sans-serif-condensed" - android:textAllCaps="true" - android:textSize="12sp" /> - - <TextView - android:id="@+id/icon_pack_button" - android:layout_weight="1" - android:layout_width="0dp" - android:layout_height="wrap_content" - android:paddingLeft="@dimen/overview_panel_button_spacing" - android:paddingRight="@dimen/overview_panel_button_spacing" - android:text="@string/icon_packs_title" - android:drawablePadding="4dp" - android:drawableTop="@drawable/iconpack_button" - android:gravity="center_horizontal" - android:fontFamily="sans-serif-condensed" - android:textAllCaps="true" - android:textSize="12sp" /> - + android:paddingRight="@dimen/overview_panel_button_spacing"/> </LinearLayout> - <LinearLayout - xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:orientation="horizontal" - android:layout_gravity="center_horizontal|bottom" - android:paddingBottom="@dimen/overview_panel_bottom_padding"> + <include layout="@layout/settings_pane" /> - <TextView - android:id="@+id/wallpaper_button" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:paddingLeft="@dimen/overview_panel_button_spacing" - android:paddingRight="@dimen/overview_panel_button_spacing" - android:text="@string/wallpaper_button_text" - android:drawablePadding="4dp" - android:drawableTop="@drawable/wallpaper_button" - android:gravity="center_horizontal" - android:fontFamily="sans-serif-condensed" - android:textAllCaps="true" - android:textSize="12sp" /> - <TextView - android:id="@+id/sort_button" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:paddingLeft="@dimen/overview_panel_button_spacing" - android:paddingRight="@dimen/overview_panel_button_spacing" - android:text="@string/sort_button_text" - android:drawablePadding="4dp" - android:drawableTop="@drawable/wallpaper_button" - android:gravity="center_horizontal" - android:fontFamily="sans-serif-condensed" - android:textAllCaps="true" - android:textSize="12sp" /> - <TextView - android:id="@+id/widget_button" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:paddingLeft="@dimen/overview_panel_button_spacing" - android:paddingRight="@dimen/overview_panel_button_spacing" - android:text="@string/widget_button_text" - android:drawablePadding="4dp" - android:gravity="center_horizontal" - android:drawableTop="@drawable/widget_button" - android:fontFamily="sans-serif-condensed" - android:textAllCaps="true" - android:textSize="12sp"/> - <TextView - android:id="@+id/filter_button" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:paddingLeft="@dimen/overview_panel_button_spacing" - android:paddingRight="@dimen/overview_panel_button_spacing" - android:text="@string/filter_button_text" - android:drawablePadding="4dp" - android:gravity="center_horizontal" - android:drawableTop="@drawable/widget_button" - android:fontFamily="sans-serif-condensed" - android:textAllCaps="true" - android:textSize="12sp"/> - <TextView - android:id="@+id/settings_button" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:paddingLeft="@dimen/overview_panel_button_spacing" - android:paddingRight="@dimen/overview_panel_button_spacing" - android:text="@string/settings_button_text" - android:drawablePadding="4dp" - android:gravity="center_horizontal" - android:drawableTop="@drawable/setting_button" - android:fontFamily="sans-serif-condensed" - android:textAllCaps="true" - android:textSize="12sp" /> - </LinearLayout> -</FrameLayout> +</com.android.launcher3.SlidingUpPanelLayout> diff --git a/res/layout/qsb_bar.xml b/res/layout/search_drop_target_bar.xml index 030acf6be..2d51b93ab 100644 --- a/res/layout/qsb_bar.xml +++ b/res/layout/search_drop_target_bar.xml @@ -15,14 +15,13 @@ --> <com.android.launcher3.SearchDropTargetBar xmlns:android="http://schemas.android.com/apk/res/android" - style="@style/QSBBar" + android:orientation="horizontal" android:focusable="false" android:layout_width="match_parent" android:layout_height="match_parent"> <!-- Drag specific targets container --> <LinearLayout - style="@style/SearchDropTargetBar" android:id="@+id/drag_target_bar" android:layout_width="match_parent" android:layout_height="match_parent" diff --git a/res/layout/settings_pane.xml b/res/layout/settings_pane.xml new file mode 100644 index 000000000..495d0997d --- /dev/null +++ b/res/layout/settings_pane.xml @@ -0,0 +1,109 @@ +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="match_parent" > + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_gravity="center_horizontal|bottom" + android:background="@color/settings_bg_color" + android:orientation="vertical" + android:paddingBottom="@dimen/overview_panel_bottom_padding" > + + <LinearLayout + android:id="@+id/settings_pane_header" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:paddingTop="@dimen/overview_panel_top_padding" > + + <ImageView + android:id="@+id/settings_drag_arrow" + android:layout_width="@dimen/overview_panel_handle_size" + android:layout_height="@dimen/overview_panel_handle_size" + android:layout_gravity="center_horizontal" + android:adjustViewBounds="true" + android:background="@drawable/launcheranimatedarrow_00000"/> + + <RelativeLayout + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:orientation="horizontal" + android:layout_gravity="center_horizontal|bottom" + android:paddingBottom="@dimen/overview_panel_bottom_padding" + android:paddingTop="@dimen/overview_panel_list_padding" + android:layout_marginLeft="@dimen/overview_panel_button_spacing" + android:layout_marginRight="@dimen/overview_panel_button_spacing"> + + <TextView + android:id="@+id/wallpaper_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:drawablePadding="4dp" + android:drawableTop="@drawable/wallpaper_button" + android:fontFamily="sans-serif-condensed" + android:gravity="center_horizontal" + android:paddingLeft="@dimen/overview_panel_button_spacing" + android:paddingRight="@dimen/overview_panel_button_spacing" + android:text="@string/wallpaper_button_text" + android:textAllCaps="true" + android:textSize="12sp" + android:textColor="@android:color/white" + android:layout_alignParentTop="true" + android:layout_alignParentLeft="true"/> + + <TextView + android:id="@+id/widget_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:drawablePadding="4dp" + android:drawableTop="@drawable/widget_button" + android:fontFamily="sans-serif-condensed" + android:gravity="center_horizontal" + android:paddingLeft="@dimen/overview_panel_button_spacing" + android:paddingRight="@dimen/overview_panel_button_spacing" + android:text="@string/widget_button_text" + android:textAllCaps="true" + android:textSize="12sp" + android:textColor="@android:color/white" + android:layout_alignParentTop="true" + android:layout_centerHorizontal="true" /> + + <TextView + android:id="@+id/themes_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:drawablePadding="4dp" + android:drawableTop="@drawable/themes_button" + android:fontFamily="sans-serif-condensed" + android:gravity="center_horizontal" + android:paddingLeft="@dimen/overview_panel_button_spacing" + android:paddingRight="@dimen/overview_panel_button_spacing" + android:text="@string/themes_button_text" + android:textAllCaps="true" + android:textSize="12sp" + android:textColor="@android:color/white" + android:layout_alignParentTop="true" + android:layout_alignParentRight="true" /> + + </RelativeLayout> + </LinearLayout> + + <view + class="com.android.launcher3.list.PinnedHeaderListView" + android:id="@+id/settings_home_screen_listview" + android:layout_width="match_parent" + android:layout_height="0dip" + android:fastScrollEnabled="true" + android:layout_weight="1" /> + + </LinearLayout> + + <LinearLayout + android:id="@+id/dark_panel" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:background="@android:color/background_dark" + android:visibility="gone" /> +</FrameLayout>
\ No newline at end of file diff --git a/res/layout/settings_pane_list_header.xml b/res/layout/settings_pane_list_header.xml new file mode 100644 index 000000000..700f5e773 --- /dev/null +++ b/res/layout/settings_pane_list_header.xml @@ -0,0 +1,19 @@ +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal|bottom" + android:background="@color/settings_bg_color" + android:paddingLeft="@dimen/overview_panel_list_padding" + android:paddingRight="@dimen/overview_panel_list_padding" + android:orientation="horizontal" > + + <TextView + android:id="@+id/item_name" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:drawablePadding="4dp" + android:fontFamily="sans-serif-condensed" + android:gravity="left" + android:textSize="16sp" + android:textColor="@color/settings_header_text"/> +</RelativeLayout> diff --git a/res/layout/settings_pane_list_item.xml b/res/layout/settings_pane_list_item.xml new file mode 100644 index 000000000..0053f4c73 --- /dev/null +++ b/res/layout/settings_pane_list_item.xml @@ -0,0 +1,44 @@ +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal|bottom" + android:background="@drawable/listitem_bg" + android:paddingLeft="@dimen/overview_panel_list_padding" + android:paddingRight="@dimen/overview_panel_list_padding" + android:orientation="horizontal" > + + <TextView + android:id="@+id/item_name" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:drawablePadding="4dp" + android:fontFamily="sans-serif-condensed" + android:gravity="left" + android:paddingBottom="@dimen/overview_panel_list_padding" + android:paddingTop="@dimen/overview_panel_list_padding" + android:textSize="20sp" + android:textColor="@color/listitem_text" + android:layout_alignParentLeft="true" + android:scrollHorizontally="true" + android:ellipsize="end" + android:maxLines="1"/> + + <TextView + android:id="@+id/item_state" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:drawablePadding="4dp" + android:fontFamily="sans-serif-condensed" + android:gravity="right" + android:paddingBottom="@dimen/overview_panel_list_padding" + android:paddingTop="@dimen/overview_panel_list_padding" + android:textSize="20sp" + android:textAllCaps="true" + android:textColor="@color/listitem_text" + android:layout_alignParentRight="true" + android:layout_toRightOf="@id/item_name" + android:scrollHorizontally="true" + android:ellipsize="end" + android:maxLines="1"/> + +</RelativeLayout>
\ No newline at end of file diff --git a/res/layout/settings_transitions_screen.xml b/res/layout/settings_transitions_screen.xml new file mode 100644 index 000000000..37535e912 --- /dev/null +++ b/res/layout/settings_transitions_screen.xml @@ -0,0 +1,52 @@ +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_gravity="center_horizontal|bottom" + android:background="@color/settings_bg_color" + android:orientation="vertical" + android:paddingBottom="@dimen/overview_panel_bottom_padding" + android:paddingTop="@dimen/overview_panel_bottom_padding" + android:clickable="true" > + + <LinearLayout + android:id="@+id/transition_title" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal" + android:background="@drawable/listitem_bg" + android:clickable="true" > + + <ImageView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical" + android:adjustViewBounds="true" + android:src="@drawable/handle_left" /> + + <TextView + android:id="@+id/transition_effect_title" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/scroll_effect_text" + android:textAllCaps="true" + android:fontFamily="sans-serif-condensed" + android:textColor="@android:color/white" + android:layout_gravity="center_vertical" + android:textSize="16sp" /> + </LinearLayout> + + <ImageView + android:id="@+id/settings_transition_image" + android:layout_width="150dp" + android:layout_height="150dp" + android:layout_gravity="center_horizontal" + android:adjustViewBounds="true" /> + + <ListView + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/settings_transitions_list" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:listSelector="@android:color/transparent" + android:splitMotionEvents="false"/> +</LinearLayout> diff --git a/res/layout/user_folder.xml b/res/layout/user_folder.xml index 5d5f33b1f..28476db69 100644 --- a/res/layout/user_folder.xml +++ b/res/layout/user_folder.xml @@ -34,21 +34,41 @@ android:hapticFeedbackEnabled="false" /> </ScrollView> - <com.android.launcher3.FolderEditText - android:id="@+id/folder_name" + <RelativeLayout + android:id="@+id/folder_title_section" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_centerHorizontal="true" - android:paddingTop="@dimen/folder_name_padding" - android:paddingBottom="@dimen/folder_name_padding" - android:background="#00000000" - android:hint="@string/folder_hint_text" - android:textSize="14sp" - android:textColor="#ff777777" - android:textColorHighlight="#ffCCCCCC" - android:textCursorDrawable="@null" - android:gravity="center_horizontal" - android:singleLine="true" - android:imeOptions="flagNoExtractUi" - android:fontFamily="sans-serif-condensed"/> + android:orientation="horizontal" > + + <ImageView + android:id="@+id/folder_lock" + android:layout_width="@dimen/folder_lock_icon" + android:layout_height="@dimen/folder_lock_icon" + android:paddingBottom="@dimen/folder_name_padding" + android:paddingTop="@dimen/folder_name_padding" + android:adjustViewBounds="true" + android:layout_alignParentRight="true" + android:src="@drawable/folder_unlock" /> + + <com.android.launcher3.FolderEditText + android:id="@+id/folder_name" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_centerHorizontal="true" + android:background="#00000000" + android:fontFamily="sans-serif-condensed" + android:gravity="center_horizontal" + android:hint="@string/folder_hint_text" + android:imeOptions="flagNoExtractUi" + android:paddingBottom="@dimen/folder_name_padding" + android:paddingTop="@dimen/folder_name_padding" + android:singleLine="true" + android:textColor="#ff777777" + android:textColorHighlight="#ffCCCCCC" + android:textCursorDrawable="@null" + android:layout_alignParentLeft="true" + android:layout_toLeftOf="@id/folder_lock" + android:textSize="16sp" /> + </RelativeLayout> + </com.android.launcher3.Folder> diff --git a/res/layout/wallpaper_picker_clear.xml b/res/layout/wallpaper_picker_clear.xml deleted file mode 100644 index 727c3b422..000000000 --- a/res/layout/wallpaper_picker_clear.xml +++ /dev/null @@ -1,42 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2014 The CyanogenMod 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. ---> - -<com.android.launcher3.CheckableFrameLayout - xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="@dimen/wallpaperThumbnailWidth" - android:layout_height="@dimen/wallpaperThumbnailHeight" - android:focusable="true" - android:clickable="true" - android:background="@drawable/wallpaper_tile_fg" - android:foreground="@drawable/wallpaper_tile_fg"> - <ImageView - android:id="@+id/wallpaper_image" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:background="@color/wallpaper_picker_translucent_gray" - android:scaleType="centerCrop" /> - <TextView - android:id="@+id/wallpaper_item_label" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:ellipsize="marquee" - android:gravity="center" - android:layout_gravity="center" - android:text="@string/clear_keyguard_wallpaper" - android:drawableTop="@drawable/ic_clear" - android:drawablePadding="4dp" - android:textColor="@android:color/white"/> -</com.android.launcher3.CheckableFrameLayout> diff --git a/res/mipmap-xxhdpi/on_boarding_welcome.png b/res/mipmap-xxhdpi/on_boarding_welcome.png Binary files differnew file mode 100644 index 000000000..7b11dea0e --- /dev/null +++ b/res/mipmap-xxhdpi/on_boarding_welcome.png diff --git a/res/values-af/cm_arrays.xml b/res/values-af/cm_arrays.xml index 78bfee283..966761f24 100644 --- a/res/values-af/cm_arrays.xml +++ b/res/values-af/cm_arrays.xml @@ -16,19 +16,14 @@ limitations under the License. --> <resources> - <string-array name="preferences_interface_general_icons_text_font_family_entries"> - <item>Gereelde</item> - <item>Lig</item> - <item>Verkorte</item> - </string-array> <string-array name="transition_effect_entries"> <item>Geen</item> - <item>Zoom in</item> - <item>Zoom uit</item> + <item>Vergroot</item> + <item>Verklein</item> <item>Roteer op</item> <item>Roteer af</item> - <item>Kubus in</item> - <item>Kubus uit</item> + <item>Blokkie in</item> + <item>Blokkie uit</item> <item>Stapel</item> <item>Trek klavier</item> <item>Spieël</item> diff --git a/res/values-af/cm_strings.xml b/res/values-af/cm_strings.xml index a501119de..3ef65004b 100644 --- a/res/values-af/cm_strings.xml +++ b/res/values-af/cm_strings.xml @@ -16,49 +16,27 @@ limitations under the License. --> <resources> - <string name="application_copyright">Kopiereg \u00A9 2014 Die CyanogenMod Projek</string> - <string name="sort_button_text">Sorteer</string> - <string name="filter_button_text">Filter</string> - <string name="default_screen_button_text">Verstek skerm</string> - <string name="transition_effect_button_text">Rol effek</string> - <string name="sort_mode_title">Titel</string> - <string name="sort_mode_launch_count">Begin telling</string> - <string name="sort_mode_install_time">Iinstalleer tyd</string> + <string name="launcher_settings">LANSEERDER INSTELLINGS</string> + <string name="home_screen_settings">TUIS SKERM INSTELLINGS</string> + <string name="drawer_settings">LAAI INSTELLINGS</string> + <string name="setting_state_on">AAN</string> + <string name="setting_state_off">AF</string> + <string name="themes_button_text">Temas</string> <string name="scrolling_page_outlines">Bladsy buitelyne</string> <string name="scrolling_fade_adjacent">Vervaag kant bladsye</string> - <string name="wallpaper_scroll">Rol muurpapier</string> - <string name="preferences_title">Instellings</string> - <string name="preferences_application_title">Program</string> - <string name="preferences_interface_homescreen_title">Tuis skerm</string> - <string name="preferences_interface_homescreen_search_title">Soekbalk</string> - <string name="preferences_interface_homescreen_search_summary">Wys soekbalk altyd aan die bokant van die skerm</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_title">Steek ikoon etikette weg</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">Steek ikoon etikette op Tuis Skerm weg</string> - <string name="preferences_interface_drawer_title">Laai</string> - <string name="preferences_interface_drawer_summary">Program en legstuk laai</string> - <string name="preferences_interface_drawer_apps_category">Programme</string> - <string name="preferences_interface_drawer_hidden_apps_title">Versteekte programme</string> - <string name="preferences_interface_drawer_hidden_apps_summary">Steek programme van die laai weg</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">Verwyder kortpaaie</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">Verwyder kortpaaie of versteekte programme van die tuis skerm</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_title">Verwyder legstukke</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_summary">Verwyder legstukke of versteekte programme van die tuis skerm</string> - <string name="preferences_interface_drawer_hide_icon_labels_title">Steek ikoon etikette weg</string> - <string name="preferences_interface_drawer_hide_icon_labels_summary">Steek ikoon etikette weg in die laai</string> - <string name="preferences_interface_dock_title">Dok</string> - <string name="preferences_interface_general_title">Algemeen</string> - <string name="preferences_interface_general_icons_category">Ikone</string> - <string name="preferences_interface_general_icons_large_title">Groter ikone</string> - <string name="preferences_interface_general_icons_large_summary">Gebruik ekstra groot toepassing ikone in tuis skerm en laai</string> - <string name="preferences_interface_general_icons_text_style_title">Teksfont styl</string> - <string name="preferences_interface_general_icons_text_style_summary">Variant en styl van font om te gebruik vir ikoon teks</string> - <string name="dialog_pick_iconpack_title">Kies ikoon stel</string> - <string name="default_iconpack_title">Standaard ikone</string> - <string name="icon_packs_title">Ikoon stelle</string> - <string name="no_iconpacks_summary">Geen ikoon stelle geïnstalleer</string> - <string name="clear_keyguard_wallpaper">Verwyder</string> - <string name="all_apps_cling_cm">Verpersoonlik jou laai</string> - <string name="all_apps_cling_summary">Tik die bladsy aanwyser vir bykomende konfigurasie-instellings</string> - <string name="menu_hidden_apps_delete">Herstel</string> + <string name="scrolling_wallpaper">Rol agtergrond</string> <string name="hidden_apps_title">Versteekte programme</string> + <string name="scroll_effect_text">Rol effek</string> + <string name="drawer_sorting_text">Sorteer metode</string> + <string name="sort_mode_title">Titel</string> + <string name="sort_mode_launch_count">Begin telling</string> + <string name="sort_mode_install_time">Iinstalleer tyd</string> + <string name="home_screen_search_text">Soekbalk</string> + <string name="larger_icons_text">Groter ikone</string> + <string name="icon_labels">Ikoon etikette</string> + <string name="icon_labels_show">Vertoon</string> + <string name="icon_labels_hide">Wegsteek</string> + <string name="protected_app_settings">Beskermde programme</string> + <string name="search_screen_left_text">Soek paneel</string> + <string name="search_screen_left_unsupported_toast">Jy moet \'n ondersteunde soek program hê en CyanogenMod om hierdie funksie te gebruik.</string> </resources> diff --git a/res/values-ar/cm_arrays.xml b/res/values-ar/cm_arrays.xml index 97cd1b0ba..78682bcb6 100644 --- a/res/values-ar/cm_arrays.xml +++ b/res/values-ar/cm_arrays.xml @@ -16,24 +16,19 @@ limitations under the License. --> <resources> - <string-array name="preferences_interface_general_icons_text_font_family_entries"> - <item>العادية</item> - <item>فاتح</item> - <item>مكثف</item> - </string-array> <string-array name="transition_effect_entries"> <item>لا شيء</item> <item>تكبير</item> <item>تصغير</item> <item>تدوير للأعلى</item> - <item>تدوير لأسفل</item> + <item>تدوير للأسفل</item> <item>مكعب لداخل</item> <item>مكعب للخارج</item> <item>جميع</item> <item>Accordion</item> <item>لف</item> - <item>اسطوانة الداخل</item> - <item>اسطوانة الخارج</item> + <item>اسطوانة لداخل</item> + <item>اسطوانة للخارج</item> <item>دائري</item> <item>نظرة عامّة</item> </string-array> diff --git a/res/values-ar/cm_strings.xml b/res/values-ar/cm_strings.xml index d0161cdce..e9fd70329 100644 --- a/res/values-ar/cm_strings.xml +++ b/res/values-ar/cm_strings.xml @@ -16,49 +16,37 @@ limitations under the License. --> <resources> - <string name="application_copyright">حقوق الطبع والنشر \u00A9 2013 لي مشروع CyanogenMod</string> - <string name="sort_button_text">ترتيب</string> - <string name="filter_button_text">التصفية</string> - <string name="default_screen_button_text">الشاشة الافتراضية</string> - <string name="transition_effect_button_text">تأثير التمرير</string> - <string name="sort_mode_title">العنوان</string> - <string name="sort_mode_launch_count">عداد الإنطلاق</string> - <string name="sort_mode_install_time">وقت التثبيت</string> + <string name="launcher_settings">إعدادات اللنشر</string> + <string name="home_screen_settings">إعدادات الشاشة الرئيسية</string> + <string name="drawer_settings">إعدادات الفراغ</string> + <string name="app_settings">إعدادات التطبيق</string> + <string name="setting_state_on">يعمل</string> + <string name="setting_state_off">لايعمل</string> + <string name="themes_button_text">المواضيع</string> <string name="scrolling_page_outlines">الخطوط العريضة لي الصفحة</string> <string name="scrolling_fade_adjacent">تتلاشى الصفحات الجانبية</string> - <string name="wallpaper_scroll">تمرير الخلفية</string> - <string name="preferences_title">إعدادات</string> - <string name="preferences_application_title">التطبيق</string> - <string name="preferences_interface_homescreen_title">الشاشة الرئيسية</string> - <string name="preferences_interface_homescreen_search_title">شريط البحث</string> - <string name="preferences_interface_homescreen_search_summary">إستمرار إظهار شريط البحث في أعلى الشاشة</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_title">إخفاء تسميات الرمز</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">إخفاء تسميات الرموز على الشاشة الرئيسية</string> - <string name="preferences_interface_drawer_title">الفراغ</string> - <string name="preferences_interface_drawer_summary">فراغ التطبيقات والمصغرات</string> - <string name="preferences_interface_drawer_apps_category">تطبيقات</string> - <string name="preferences_interface_drawer_hidden_apps_title">تطبيقات المخفية</string> - <string name="preferences_interface_drawer_hidden_apps_summary">إخفاء تطبيقات من الفراغ</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">إزالة اختصارات</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">إزالة الاختصارات للتطبيقات المخفية من الشاشة الرئيسية</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_title">إزالة المصغرات</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_summary">إزالة مصغرات التطبيقات المخفية من الشاشة الرئيسية</string> - <string name="preferences_interface_drawer_hide_icon_labels_title">إخفاء تسميات الرمز</string> - <string name="preferences_interface_drawer_hide_icon_labels_summary">إخفاء تسميات الرمز في الفراغ</string> - <string name="preferences_interface_dock_title">حوض</string> - <string name="preferences_interface_general_title">عام</string> - <string name="preferences_interface_general_icons_category">أيقونات</string> - <string name="preferences_interface_general_icons_large_title">أيقونات كبيرة</string> - <string name="preferences_interface_general_icons_large_summary">استخدام الرموز إضافية كبيرة لي التطبيق في الشاشة الرئيسية و الفراغ</string> - <string name="preferences_interface_general_icons_text_style_title">نمط خط النص</string> - <string name="preferences_interface_general_icons_text_style_summary">شكل ونمط الخط لاستخدامه لرمز النص</string> - <string name="dialog_pick_iconpack_title">اختر حزمة الأيقونة</string> - <string name="default_iconpack_title">الإيقونات الافتراضية</string> - <string name="icon_packs_title">حزم الإيقونات</string> - <string name="no_iconpacks_summary">لا توجد حزم أيقونات لتثبيت</string> - <string name="clear_keyguard_wallpaper">تصفية</string> - <string name="all_apps_cling_cm">تخصيص الفراغ</string> - <string name="all_apps_cling_summary">انقر فوق مؤشر الصفحة لعرض إعدادات التكوين الإضافي</string> - <string name="menu_hidden_apps_delete">إعادة تعيين</string> + <string name="scrolling_wallpaper">تمرير الخلفية</string> + <string name="grid_size_text">حجم الشبكة</string> + <string name="grid_size_comfortable">مريحة</string> + <string name="grid_size_cozy">مريح</string> + <string name="grid_size_condensed">مكثف</string> + <string name="grid_size_custom">مخصص</string> + <string name="preferences_interface_homescreen_custom">حدد حجم مخصص</string> + <string name="preferences_interface_homescreen_rows_title">عدد الصفوف</string> + <string name="preferences_interface_homescreen_columns_title">عدد الأعمدة</string> <string name="hidden_apps_title">تطبيقات المخفية</string> + <string name="scroll_effect_text">تأثير التمرير</string> + <string name="drawer_sorting_text">وضع الفرز</string> + <string name="sort_mode_title">العنوان</string> + <string name="sort_mode_launch_count">عداد الإنطلاق</string> + <string name="sort_mode_install_time">وقت التثبيت</string> + <string name="home_screen_search_text">شريط البحث</string> + <string name="larger_icons_text">أيقونات كبيرة</string> + <string name="icon_labels">تسميات الرمز</string> + <string name="icon_labels_show">إظهار</string> + <string name="icon_labels_hide">إخفاء</string> + <string name="protected_app_settings">التطبيقات المحمية</string> + <string name="search_screen_left_text">لوحة البحث</string> + <string name="search_screen_left_unsupported_toast">يجب أن يكون تطبيق البحث و CyanogenMod مدعومين لستخدام هذه الميزة.</string> + <string name="dialog_confirm">تأكيد</string> </resources> diff --git a/res/values-ca/cm_arrays.xml b/res/values-ca/cm_arrays.xml index 5dd971cbd..5207e1dfd 100644 --- a/res/values-ca/cm_arrays.xml +++ b/res/values-ca/cm_arrays.xml @@ -16,11 +16,6 @@ limitations under the License. --> <resources> - <string-array name="preferences_interface_general_icons_text_font_family_entries"> - <item>Normal</item> - <item>Fina</item> - <item>Condensada</item> - </string-array> <string-array name="transition_effect_entries"> <item>Cap</item> <item>Amplia</item> diff --git a/res/values-ca/cm_strings.xml b/res/values-ca/cm_strings.xml index ff387a6e1..5c153cc59 100644 --- a/res/values-ca/cm_strings.xml +++ b/res/values-ca/cm_strings.xml @@ -16,49 +16,37 @@ limitations under the License. --> <resources> - <string name="application_copyright">Copyright \u00A9 2014 The CyanogenMod Project</string> - <string name="sort_button_text">Ordena</string> - <string name="filter_button_text">Filtre</string> - <string name="default_screen_button_text">Pantalla predeterminada</string> - <string name="transition_effect_button_text">Efecte desplaçament</string> - <string name="sort_mode_title">Títol</string> - <string name="sort_mode_launch_count">Vegades executat</string> - <string name="sort_mode_install_time">Hora d\'instal·lació</string> + <string name="launcher_settings">CONFIGURACIÓ DEL LLANÇADOR</string> + <string name="home_screen_settings">CONFIGURACIÓ DE LA PANTALLA D\'INICI</string> + <string name="drawer_settings">CONFIGURACIÓ DEL CALAIX</string> + <string name="app_settings">CONFIGURACIÓ DE L\'APP</string> + <string name="setting_state_on">SÍ</string> + <string name="setting_state_off">NO</string> + <string name="themes_button_text">Temes</string> <string name="scrolling_page_outlines">Vores de la pàgina</string> <string name="scrolling_fade_adjacent">Esvaeix els costats de les pàgines</string> - <string name="wallpaper_scroll">Desplaça el fons de pantalla</string> - <string name="preferences_title">Ajustaments</string> - <string name="preferences_application_title">App</string> - <string name="preferences_interface_homescreen_title">Pantalla d\'inici</string> - <string name="preferences_interface_homescreen_search_title">Barra de cerca</string> - <string name="preferences_interface_homescreen_search_summary">Mostra sempre la barra de cerca a la part superior de la pantalla</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_title">Amaga les etiquetes de les icones</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">Amaga les etiquetes de les icones de la pantalla d\'inici</string> - <string name="preferences_interface_drawer_title">Calaix</string> - <string name="preferences_interface_drawer_summary">Calaix d\'apps i widgets</string> - <string name="preferences_interface_drawer_apps_category">Apps</string> - <string name="preferences_interface_drawer_hidden_apps_title">Apps amagades</string> - <string name="preferences_interface_drawer_hidden_apps_summary">Amaga les apps del calaix</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">Treu les dreceres</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">Treu les dreceres de les apps amagades de la pantalla d\'inici</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_title">Treu els widgets</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_summary">Treu els widgets de les apps amagades de la pantalla d\'inici</string> - <string name="preferences_interface_drawer_hide_icon_labels_title">Amaga les etiquetes de les icones</string> - <string name="preferences_interface_drawer_hide_icon_labels_summary">Amaga les etiquetes de les icones al calaix</string> - <string name="preferences_interface_dock_title">Barra d\'aplicacions</string> - <string name="preferences_interface_general_title">General</string> - <string name="preferences_interface_general_icons_category">Icones</string> - <string name="preferences_interface_general_icons_large_title">Icones més grans</string> - <string name="preferences_interface_general_icons_large_summary">Utilitza icones d\'aplicació extra grans a la pantalla d\'inici i al calaix</string> - <string name="preferences_interface_general_icons_text_style_title">Estil del tipus de lletra del text</string> - <string name="preferences_interface_general_icons_text_style_summary">Variant i estil del tipus de lletra pel text de les icones</string> - <string name="dialog_pick_iconpack_title">Escull un paquet d\'icones</string> - <string name="default_iconpack_title">Icones per defecte</string> - <string name="icon_packs_title">Paquets d\'icones</string> - <string name="no_iconpacks_summary">No hi ha paquets d\'icones instal·lats</string> - <string name="clear_keyguard_wallpaper">Neteja</string> - <string name="all_apps_cling_cm">Personalitza el teu calaix</string> - <string name="all_apps_cling_summary">Pica l\'indicador de pàgina per veure les opcions de configuració addicionals</string> - <string name="menu_hidden_apps_delete">Reinicia</string> + <string name="scrolling_wallpaper">Desplaça el fons de pantalla</string> + <string name="grid_size_text">Mida de la graella</string> + <string name="grid_size_comfortable">Còmoda</string> + <string name="grid_size_cozy">Acollidora</string> + <string name="grid_size_condensed">Condensada</string> + <string name="grid_size_custom">Personalitzada</string> + <string name="preferences_interface_homescreen_custom">Selecciona la mida personalitzada</string> + <string name="preferences_interface_homescreen_rows_title">Nombre de files</string> + <string name="preferences_interface_homescreen_columns_title">Nombre de columnes</string> <string name="hidden_apps_title">Apps amagades</string> + <string name="scroll_effect_text">Efecte desplaçament</string> + <string name="drawer_sorting_text">Mode d\'ordenació</string> + <string name="sort_mode_title">Títol</string> + <string name="sort_mode_launch_count">Vegades executat</string> + <string name="sort_mode_install_time">Hora d\'instal·lació</string> + <string name="home_screen_search_text">Barra de cerca</string> + <string name="larger_icons_text">Icones grans</string> + <string name="icon_labels">Etiquetes de les icones</string> + <string name="icon_labels_show">Mostra</string> + <string name="icon_labels_hide">Amaga</string> + <string name="protected_app_settings">Apps protegides</string> + <string name="search_screen_left_text">Quadre de cerca</string> + <string name="search_screen_left_unsupported_toast">Has de tenir una app de cerca suportada i perquè CyanogenMod utilitzi aquesta característica.</string> + <string name="dialog_confirm">Confirma</string> </resources> diff --git a/res/values-cs/cm_arrays.xml b/res/values-cs/cm_arrays.xml index bffc61fef..aa326e178 100644 --- a/res/values-cs/cm_arrays.xml +++ b/res/values-cs/cm_arrays.xml @@ -16,24 +16,19 @@ limitations under the License. --> <resources> - <string-array name="preferences_interface_general_icons_text_font_family_entries"> - <item>Obyčejné</item> - <item>Slabé</item> - <item>Zůžené</item> - </string-array> <string-array name="transition_effect_entries"> <item>Žádný</item> - <item>Přiblížení</item> + <item>Příblížení</item> <item>Oddálení</item> - <item>Rotace nahoru</item> - <item>Rotace dolu</item> + <item>Otočení nahoru</item> + <item>Otočení dolu</item> <item>Uvnitř krychle</item> <item>Vně krychle</item> <item>Vrstvy</item> <item>Harmonika</item> <item>Překlopení</item> <item>Uvnitř válce</item> - <item>Vně válce</item> + <item>Mimo válec</item> <item>Kolotoč</item> <item>Přehled</item> </string-array> diff --git a/res/values-cs/cm_strings.xml b/res/values-cs/cm_strings.xml index 449e1db3a..f5c603f52 100644 --- a/res/values-cs/cm_strings.xml +++ b/res/values-cs/cm_strings.xml @@ -16,49 +16,37 @@ limitations under the License. --> <resources> - <string name="application_copyright">Copyright \u00A9 2014 CyanogenMod projekt</string> - <string name="sort_button_text">Třídit</string> - <string name="filter_button_text">Filtr</string> - <string name="default_screen_button_text">Výchozí obrazovka</string> - <string name="transition_effect_button_text">Efekt přechodu</string> - <string name="sort_mode_title">Název</string> - <string name="sort_mode_launch_count">Počet spuštění</string> - <string name="sort_mode_install_time">Čas instalace</string> + <string name="launcher_settings">NASTAVENÍ SPOUŠTĚČE</string> + <string name="home_screen_settings">NASTAVENÍ DOMOVSKÉ OBRAZOVKY</string> + <string name="drawer_settings">NASTAVENÍ SLOŽKY</string> + <string name="app_settings">NASTAVENÍ APL</string> + <string name="setting_state_on">Zap.</string> + <string name="setting_state_off">Vyp.</string> + <string name="themes_button_text">Motivy</string> <string name="scrolling_page_outlines">Ohraničení stránek</string> <string name="scrolling_fade_adjacent">Prolínat hrany ploch</string> - <string name="wallpaper_scroll">Posouvání tapety</string> - <string name="preferences_title">Nastavení</string> - <string name="preferences_application_title">Aplikace</string> - <string name="preferences_interface_homescreen_title">Domovská plocha</string> - <string name="preferences_interface_homescreen_search_title">Vyhledávací lišta</string> - <string name="preferences_interface_homescreen_search_summary">Trvale zobrazit lištu vyhledávání vždy u horní hrany plochy</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_title">Skrýt popisky ikon</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">Skrýt popisky ikon na domovské ploše</string> - <string name="preferences_interface_drawer_title">Aplikační složka</string> - <string name="preferences_interface_drawer_summary">Složka aplikací a widgetů</string> - <string name="preferences_interface_drawer_apps_category">Aplikace</string> - <string name="preferences_interface_drawer_hidden_apps_title">Skryté aplikace</string> - <string name="preferences_interface_drawer_hidden_apps_summary">Skrýt aplikace ve složce</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">Odebrat zástupce</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">Odebrat zástupce skrytých aplikací z domovské plochy</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_title">Odebrat widgety</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_summary">Odebrat widgety skrytých aplikací z domovské plochy</string> - <string name="preferences_interface_drawer_hide_icon_labels_title">Skrýt popisky ikon</string> - <string name="preferences_interface_drawer_hide_icon_labels_summary">Skrýt popisky ikon ve složce</string> - <string name="preferences_interface_dock_title">Dok</string> - <string name="preferences_interface_general_title">Obecné</string> - <string name="preferences_interface_general_icons_category">Ikony</string> - <string name="preferences_interface_general_icons_large_title">Větší ikony</string> - <string name="preferences_interface_general_icons_large_summary">Použít větší ikony aplikací na plochách a aplikační složce</string> - <string name="preferences_interface_general_icons_text_style_title">Vzhled písma</string> - <string name="preferences_interface_general_icons_text_style_summary">Vzhled a varianta pro popis ikon</string> - <string name="dialog_pick_iconpack_title">Vyberte balíček ikon</string> - <string name="default_iconpack_title">Výchozí ikony</string> - <string name="icon_packs_title">Balíčky ikon</string> - <string name="no_iconpacks_summary">Není nainstalován žádný balíček ikon</string> - <string name="clear_keyguard_wallpaper">Odstranit</string> - <string name="all_apps_cling_cm">Upravit vlastní složku</string> - <string name="all_apps_cling_summary">Dotykem na indikátor stránky zobrazit další možnosti nastavení</string> - <string name="menu_hidden_apps_delete">Obnovit</string> + <string name="scrolling_wallpaper">Posouvání tapety</string> + <string name="grid_size_text">Velikost mřížky</string> + <string name="grid_size_comfortable">Komfortní</string> + <string name="grid_size_cozy">Pohodlná</string> + <string name="grid_size_condensed">Zůžená</string> + <string name="grid_size_custom">Vlastní</string> + <string name="preferences_interface_homescreen_custom">Zvolte vlastní velikost</string> + <string name="preferences_interface_homescreen_rows_title">Počet řádek</string> + <string name="preferences_interface_homescreen_columns_title">Počet sloupců</string> <string name="hidden_apps_title">Skryté aplikace</string> + <string name="scroll_effect_text">Efekt přechodu</string> + <string name="drawer_sorting_text">Režim třídění</string> + <string name="sort_mode_title">Název</string> + <string name="sort_mode_launch_count">Počet spuštění</string> + <string name="sort_mode_install_time">Čas instalace</string> + <string name="home_screen_search_text">Vyhledávací lišta</string> + <string name="larger_icons_text">Větší ikony</string> + <string name="icon_labels">Popisky ikon</string> + <string name="icon_labels_show">Zobrazit</string> + <string name="icon_labels_hide">Skrýt</string> + <string name="protected_app_settings">Chráněné aplikace</string> + <string name="search_screen_left_text">Panel vyhledávání</string> + <string name="search_screen_left_unsupported_toast">Pro použití této funkce musíte mít nainstalovanou podporovanou aplikaci vyhledávání a CyanogenMod.</string> + <string name="dialog_confirm">Potvrdit</string> </resources> diff --git a/res/values-da/cm_arrays.xml b/res/values-da/cm_arrays.xml index dcc77c789..038d014d7 100644 --- a/res/values-da/cm_arrays.xml +++ b/res/values-da/cm_arrays.xml @@ -16,24 +16,19 @@ limitations under the License. --> <resources> - <string-array name="preferences_interface_general_icons_text_font_family_entries"> - <item>Regulær</item> - <item>Lys</item> - <item>Kondenseret</item> - </string-array> <string-array name="transition_effect_entries"> <item>Ingen</item> <item>Zoom ind</item> <item>Zoom ud</item> - <item>Rotér op</item> - <item>Rotér ned</item> - <item>Terning ind</item> - <item>Terning ud</item> + <item>Rotere op</item> + <item>Rotere ned</item> + <item>Indvendig terning</item> + <item>Udvendig terning</item> <item>Stak</item> <item>Harmonika</item> <item>Flip</item> - <item>Cylinder ind</item> - <item>Cylinder ud</item> + <item>Indvendig cylinder</item> + <item>Udvendig cylinder</item> <item>Karrusel</item> <item>Overblik</item> </string-array> diff --git a/res/values-da/cm_strings.xml b/res/values-da/cm_strings.xml index 0149c9c91..5d584f8d6 100644 --- a/res/values-da/cm_strings.xml +++ b/res/values-da/cm_strings.xml @@ -16,49 +16,37 @@ limitations under the License. --> <resources> - <string name="application_copyright">Copyright \u00A9 2014 The CyanogenMod Project</string> - <string name="sort_button_text">Sortér</string> - <string name="filter_button_text">Filtrér</string> - <string name="default_screen_button_text">Standardskærm</string> - <string name="transition_effect_button_text">Rulleeffekt</string> - <string name="sort_mode_title">Titel</string> - <string name="sort_mode_launch_count">Antal gange brugt</string> - <string name="sort_mode_install_time">Installationstidspunkt</string> + <string name="launcher_settings">INDSTILLINGER FOR LAUNCHER</string> + <string name="home_screen_settings">INDSTILLINGER FOR STARTSKÆRM</string> + <string name="drawer_settings">INDSTILLINGER FOR OVERSIGT</string> + <string name="app_settings">APP-INDSTILLINGER</string> + <string name="setting_state_on">TIL</string> + <string name="setting_state_off">FRA</string> + <string name="themes_button_text">Temaer</string> <string name="scrolling_page_outlines">Sideomrids</string> <string name="scrolling_fade_adjacent">Sideovergange</string> - <string name="wallpaper_scroll">Rul baggrund</string> - <string name="preferences_title">Indstillinger</string> - <string name="preferences_application_title">App</string> - <string name="preferences_interface_homescreen_title">Startskærm</string> - <string name="preferences_interface_homescreen_search_title">Søgelinje</string> - <string name="preferences_interface_homescreen_search_summary">Vis permanent søgelinje i toppen af skærmen</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_title">Skjul ikontekster</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">Skjul ikontekster på startskærmen</string> - <string name="preferences_interface_drawer_title">Oversigt</string> - <string name="preferences_interface_drawer_summary">Oversigt over apps og widgets</string> - <string name="preferences_interface_drawer_apps_category">Apps</string> - <string name="preferences_interface_drawer_hidden_apps_title">Skjulte apps</string> - <string name="preferences_interface_drawer_hidden_apps_summary">Skjul apps fra oversigten</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">Fjern genveje</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">Fjern genveje til skjulte apps fra startskærmen</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_title">Fjern widgets</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_summary">Fjern widgets fra skjulte apps fra startskærmen</string> - <string name="preferences_interface_drawer_hide_icon_labels_title">Skjul ikontekster</string> - <string name="preferences_interface_drawer_hide_icon_labels_summary">Skjul ikontekster i oversigten</string> - <string name="preferences_interface_dock_title">Docklinje</string> - <string name="preferences_interface_general_title">Generelt</string> - <string name="preferences_interface_general_icons_category">Ikoner</string> - <string name="preferences_interface_general_icons_large_title">Større ikoner</string> - <string name="preferences_interface_general_icons_large_summary">Brug ekstra store app-ikoner på startskærm og i oversigten</string> - <string name="preferences_interface_general_icons_text_style_title">Font til tekster</string> - <string name="preferences_interface_general_icons_text_style_summary">Fontvariant og -stilart til ikontekster</string> - <string name="dialog_pick_iconpack_title">Vælg ikonpakke</string> - <string name="default_iconpack_title">Standardikoner</string> - <string name="icon_packs_title">Ikonpakker</string> - <string name="no_iconpacks_summary">Ingen ikonpakker installeret</string> - <string name="clear_keyguard_wallpaper">Ryd</string> - <string name="all_apps_cling_cm">Tilpas din oversigt</string> - <string name="all_apps_cling_summary">Tryk på sideindikatoren for at vise yderligere konfigurationsindstillinger</string> - <string name="menu_hidden_apps_delete">Nulstil</string> + <string name="scrolling_wallpaper">Rul baggrund</string> + <string name="grid_size_text">Gitterstørrelse</string> + <string name="grid_size_comfortable">Behageligt</string> + <string name="grid_size_cozy">Hyggeligt</string> + <string name="grid_size_condensed">Sammentrængt</string> + <string name="grid_size_custom">Brugerdefineret</string> + <string name="preferences_interface_homescreen_custom">Vælg brugerdefineret størrelse</string> + <string name="preferences_interface_homescreen_rows_title">Antal rækker</string> + <string name="preferences_interface_homescreen_columns_title">Antal kolonner</string> <string name="hidden_apps_title">Skjulte apps</string> + <string name="scroll_effect_text">Rulleeffekt</string> + <string name="drawer_sorting_text">Sorteringstilstand</string> + <string name="sort_mode_title">Titel</string> + <string name="sort_mode_launch_count">Antal gange brugt</string> + <string name="sort_mode_install_time">Installationstidspunkt</string> + <string name="home_screen_search_text">Søgelinje</string> + <string name="larger_icons_text">Større ikoner</string> + <string name="icon_labels">Ikontekster</string> + <string name="icon_labels_show">Vis</string> + <string name="icon_labels_hide">Skjul</string> + <string name="protected_app_settings">Beskyttede apps</string> + <string name="search_screen_left_text">Søgepanel</string> + <string name="search_screen_left_unsupported_toast">Du skal have en understøttet søge-app og CyanogenMod for at anvende denne funktion.</string> + <string name="dialog_confirm">Bekræft</string> </resources> diff --git a/res/values-de/cm_arrays.xml b/res/values-de/cm_arrays.xml index 6f5eb308f..b1fb3b5f1 100644 --- a/res/values-de/cm_arrays.xml +++ b/res/values-de/cm_arrays.xml @@ -16,11 +16,6 @@ limitations under the License. --> <resources> - <string-array name="preferences_interface_general_icons_text_font_family_entries"> - <item>Normal</item> - <item>Dünn</item> - <item>Schmal</item> - </string-array> <string-array name="transition_effect_entries"> <item>Keine</item> <item>Hineinzoomen</item> diff --git a/res/values-de/cm_strings.xml b/res/values-de/cm_strings.xml index 8e784472e..30b1e5fb8 100644 --- a/res/values-de/cm_strings.xml +++ b/res/values-de/cm_strings.xml @@ -16,49 +16,37 @@ limitations under the License. --> <resources> - <string name="application_copyright">Copyright \u00A9 2014 The CyanogenMod Project</string> - <string name="sort_button_text">Sortieren</string> - <string name="filter_button_text">Filtern</string> - <string name="default_screen_button_text">Standardseite</string> - <string name="transition_effect_button_text">Scroll-Effekt</string> - <string name="sort_mode_title">Titel</string> - <string name="sort_mode_launch_count">Aufrufanzahl</string> - <string name="sort_mode_install_time">Installationsdatum</string> + <string name="launcher_settings">LAUNCHER-EINSTELLUNGEN</string> + <string name="home_screen_settings">STARTBILDSCHIRM-EINSTELLUNGEN</string> + <string name="drawer_settings">APP-ÜBERSICHT-EINSTELLUNGEN</string> + <string name="app_settings">APP-EINSTELLUNGEN</string> + <string name="setting_state_on">AN</string> + <string name="setting_state_off">AUS</string> + <string name="themes_button_text">Designs</string> <string name="scrolling_page_outlines">Seitenumriss anzeigen</string> <string name="scrolling_fade_adjacent">Seiten einblenden</string> - <string name="wallpaper_scroll">Hintergrundbild scrollen</string> - <string name="preferences_title">Einstellungen</string> - <string name="preferences_application_title">App</string> - <string name="preferences_interface_homescreen_title">Startbildschirm</string> - <string name="preferences_interface_homescreen_search_title">Suchleiste</string> - <string name="preferences_interface_homescreen_search_summary">Dauerhafte Anzeige der Suchleiste am oberen Bildschirmrand</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_title">Beschriftung nicht anzeigen</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">Symbolbeschriftungen auf den Startseiten ausblenden</string> - <string name="preferences_interface_drawer_title">App-Übersicht</string> - <string name="preferences_interface_drawer_summary">App- und Widget-Übersicht</string> - <string name="preferences_interface_drawer_apps_category">Apps</string> - <string name="preferences_interface_drawer_hidden_apps_title">Versteckte Apps</string> - <string name="preferences_interface_drawer_hidden_apps_summary">Apps in der App-Übersicht verstecken</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">Verknüpfungen entfernen</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">Verknüpfungen für versteckte Apps vom Startbildschirm entfernen</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_title">Widgets entfernen</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_summary">Widgets von versteckten Apps vom Startbildschirm entfernen</string> - <string name="preferences_interface_drawer_hide_icon_labels_title">Beschriftung nicht anzeigen</string> - <string name="preferences_interface_drawer_hide_icon_labels_summary">Symbolbeschriftungen in der App-Übersicht ausblenden</string> - <string name="preferences_interface_dock_title">Dock</string> - <string name="preferences_interface_general_title">Allgemein</string> - <string name="preferences_interface_general_icons_category">Symbole</string> - <string name="preferences_interface_general_icons_large_title">Große Symbole</string> - <string name="preferences_interface_general_icons_large_summary">Große Symbole für Apps im Startbildschirm und der App-Übersicht verwenden</string> - <string name="preferences_interface_general_icons_text_style_title">Schriftstil</string> - <string name="preferences_interface_general_icons_text_style_summary">Schriftart und Schriftstil der Symbolbeschriftung</string> - <string name="dialog_pick_iconpack_title">Symbolpaket auswählen</string> - <string name="default_iconpack_title">Standardsymbole</string> - <string name="icon_packs_title">Symbolpakete</string> - <string name="no_iconpacks_summary">Es sind keine Symbolpakete installiert</string> - <string name="clear_keyguard_wallpaper">Zurücksetzen</string> - <string name="all_apps_cling_cm">App-Übersicht konfigurieren</string> - <string name="all_apps_cling_summary">Berühren Sie den Seitenindikator, um die erweiterten Einstellungen zu öffnen.</string> - <string name="menu_hidden_apps_delete">Zurücksetzen</string> + <string name="scrolling_wallpaper">Hintergrundbild scrollen</string> + <string name="grid_size_text">Rastergröße</string> + <string name="grid_size_comfortable">Normal</string> + <string name="grid_size_cozy">Mittel</string> + <string name="grid_size_condensed">Klein</string> + <string name="grid_size_custom">Benutzerdefiniert</string> + <string name="preferences_interface_homescreen_custom">Benutzerdefinierte Größe auswählen</string> + <string name="preferences_interface_homescreen_rows_title">Anzahl der Zeilen</string> + <string name="preferences_interface_homescreen_columns_title">Anzahl der Spalten</string> <string name="hidden_apps_title">Versteckte Apps</string> + <string name="scroll_effect_text">Scroll-Effekt</string> + <string name="drawer_sorting_text">Sortiermodus</string> + <string name="sort_mode_title">Titel</string> + <string name="sort_mode_launch_count">Aufrufanzahl</string> + <string name="sort_mode_install_time">Installationsdatum</string> + <string name="home_screen_search_text">Suchleiste</string> + <string name="larger_icons_text">Große Symbole</string> + <string name="icon_labels">Symbol-Beschriftungen</string> + <string name="icon_labels_show">Anzeigen</string> + <string name="icon_labels_hide">Verbergen</string> + <string name="protected_app_settings">Geschützte Apps</string> + <string name="search_screen_left_text">Google Now</string> + <string name="search_screen_left_unsupported_toast">Um diese Funktion nutzen zu können, müssen Sie CyanogenMod und eine unterstützte Such-App installiert haben.</string> + <string name="dialog_confirm">Bestätigen</string> </resources> diff --git a/res/values-el/cm_arrays.xml b/res/values-el/cm_arrays.xml index af43fa119..b37f8c596 100644 --- a/res/values-el/cm_arrays.xml +++ b/res/values-el/cm_arrays.xml @@ -16,11 +16,6 @@ limitations under the License. --> <resources> - <string-array name="preferences_interface_general_icons_text_font_family_entries"> - <item>Κανονική</item> - <item>Λεπτή</item> - <item>Συμπυκνωμένη</item> - </string-array> <string-array name="transition_effect_entries"> <item>Κανένα</item> <item>Μεγέθυνση</item> diff --git a/res/values-el/cm_strings.xml b/res/values-el/cm_strings.xml index df3a2a6bb..b21a14baa 100644 --- a/res/values-el/cm_strings.xml +++ b/res/values-el/cm_strings.xml @@ -16,49 +16,37 @@ limitations under the License. --> <resources> - <string name="application_copyright">Copyright \u00A9 2014 The CyanogenMod Project</string> - <string name="sort_button_text">Ταξινόμηση</string> - <string name="filter_button_text">Φιλτράρισμα</string> - <string name="default_screen_button_text">Προεπιλ. οθόνη</string> - <string name="transition_effect_button_text">Εφέ κύλισης</string> - <string name="sort_mode_title">Τίτλος</string> - <string name="sort_mode_launch_count">Αριθμός εκκινήσεων</string> - <string name="sort_mode_install_time">Χρόνος εγκατάστασης</string> + <string name="launcher_settings">ΓΕΝΙΚΕΣ ΡΥΘΜΙΣΕΙΣ</string> + <string name="home_screen_settings">ΡΥΘΜΙΣΕΙΣ ΑΡΧΙΚΗΣ ΟΘΟΝΗΣ</string> + <string name="drawer_settings">ΡΥΘΜΙΣΕΙΣ ΣΥΡΤΑΡΙΟΥ</string> + <string name="app_settings">ΡΥΘΜΙΣΕΙΣ ΕΦΑΡΜΟΓΩΝ</string> + <string name="setting_state_on">ΕΝΕΡΓΟ</string> + <string name="setting_state_off">ΑΝΕΝΕΡΓΟ</string> + <string name="themes_button_text">Θέματα</string> <string name="scrolling_page_outlines">Περίγραμμα σελιδών</string> <string name="scrolling_fade_adjacent">Ξεθώριασμα πλευρικών σελίδων</string> - <string name="wallpaper_scroll">Κύλιση ταπετσαρίας</string> - <string name="preferences_title">Ρυθμίσεις</string> - <string name="preferences_application_title">Εφαρμογή</string> - <string name="preferences_interface_homescreen_title">Αρχική οθόνη</string> - <string name="preferences_interface_homescreen_search_title">Μπάρα αναζήτησης</string> - <string name="preferences_interface_homescreen_search_summary">Εμφάνιση της μπάρας αναζήτησης στο πάνω μέρος της οθόνης</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_title">Απόκρυψη ετικετών εικονιδίων</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">Απόκρυψη ετικετών εικονιδίων στην αρχική οθόνη</string> - <string name="preferences_interface_drawer_title">Συρτάρι</string> - <string name="preferences_interface_drawer_summary">Συρτάρι εφαρμογών και widget</string> - <string name="preferences_interface_drawer_apps_category">Εφαρμογές</string> - <string name="preferences_interface_drawer_hidden_apps_title">Κρυμμένες εφαρμογές</string> - <string name="preferences_interface_drawer_hidden_apps_summary">Απόκρυψη εφαρμογών από το συρτάρι</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">Αφαίρεση συντομεύσεων</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">Αφαίρεση συντομεύσεων των κρυμμένων εφαρμογών από την αρχική οθόνη</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_title">Αφαίρεση widget</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_summary">Αφαίρεση widget των κρυμμένων εφαρμογών από την αρχική οθόνη</string> - <string name="preferences_interface_drawer_hide_icon_labels_title">Απόκρυψη ετικετών εικονιδίων</string> - <string name="preferences_interface_drawer_hide_icon_labels_summary">Απόκρυψη ετικετών εικονιδίων στο συρτάρι</string> - <string name="preferences_interface_dock_title">Μπάρα εφαρμογών</string> - <string name="preferences_interface_general_title">Γενικά</string> - <string name="preferences_interface_general_icons_category">Εικονίδια</string> - <string name="preferences_interface_general_icons_large_title">Μεγαλύτερα εικονίδια</string> - <string name="preferences_interface_general_icons_large_summary">Χρήση μεγάλων εικονιδίων εφαρμογών στην αρχική οθόνη και το συρτάρι</string> - <string name="preferences_interface_general_icons_text_style_title">Στυλ γραμματοσειράς κειμένου</string> - <string name="preferences_interface_general_icons_text_style_summary">Τύπος και στυλ της γραμματοσειράς που χρησιμοποιείται για το κείμενο των εικονιδίων</string> - <string name="dialog_pick_iconpack_title">Επιλογή πακέτου εικονιδίων</string> - <string name="default_iconpack_title">Προεπιλεγμένα εικονίδια</string> - <string name="icon_packs_title">Πακέτα εικονιδίων</string> - <string name="no_iconpacks_summary">Δεν υπάρχουν εγκατεστημένα πακέτα εικονιδίων</string> - <string name="clear_keyguard_wallpaper">Εκκαθάριση</string> - <string name="all_apps_cling_cm">Προσαρμόστε το συρτάρι σας</string> - <string name="all_apps_cling_summary">Αγγίξτε την ένδειξη σελίδας για προβολή πρόσθετων ρυθμίσεων</string> - <string name="menu_hidden_apps_delete">Επαναφορά</string> + <string name="scrolling_wallpaper">Κύλιση ταπετσαρίας</string> + <string name="grid_size_text">Μέγεθος πλέγματος</string> + <string name="grid_size_comfortable">Άνετο</string> + <string name="grid_size_cozy">Κανονικό</string> + <string name="grid_size_condensed">Συμπυκνωμένο</string> + <string name="grid_size_custom">Προσαρμοσμένο</string> + <string name="preferences_interface_homescreen_custom">Επιλέξτε προσαρμοσμένο μέγεθος</string> + <string name="preferences_interface_homescreen_rows_title">Αριθμός γραμμών</string> + <string name="preferences_interface_homescreen_columns_title">Αριθμός στηλών</string> <string name="hidden_apps_title">Κρυμμένες εφαρμογές</string> + <string name="scroll_effect_text">Εφέ κύλισης</string> + <string name="drawer_sorting_text">Ταξινόμηση</string> + <string name="sort_mode_title">Τίτλος</string> + <string name="sort_mode_launch_count">Αριθμός εκκινήσεων</string> + <string name="sort_mode_install_time">Χρόνος εγκατάστασης</string> + <string name="home_screen_search_text">Μπάρα αναζήτησης</string> + <string name="larger_icons_text">Μεγαλύτερα εικονίδια</string> + <string name="icon_labels">Ετικέτες εικονιδίων</string> + <string name="icon_labels_show">Εμφάνιση</string> + <string name="icon_labels_hide">Απόκρυψη</string> + <string name="protected_app_settings">Προστατευμένες εφαρμογές</string> + <string name="search_screen_left_text">Σελίδα αναζήτησης</string> + <string name="search_screen_left_unsupported_toast">Πρέπει να έχετε μια υποστηριζόμενη εφαρμογή αναζήτησης και CyanogenMod για να χρησιμοποιήσετε αυτήν τη δυνατότητα.</string> + <string name="dialog_confirm">Επιβεβαίωση</string> </resources> diff --git a/res/values-en/dimens.xml b/res/values-en/dimens.xml new file mode 100644 index 000000000..01d4693c7 --- /dev/null +++ b/res/values-en/dimens.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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. +--> + +<resources> +<!-- Cling --> + <dimen name="cling_title_text_size">22sp</dimen> + <dimen name="cling_text_size">16sp</dimen> + <dimen name="cling_alt_title_text_size">30sp</dimen> + <dimen name="cling_alt_text_size">16sp</dimen> + <dimen name="cling_hint_text_size">18sp</dimen> +</resources> diff --git a/res/values-es-rXA/cm_arrays.xml b/res/values-es-rXA/cm_arrays.xml index 530baacc2..8cab04774 100644 --- a/res/values-es-rXA/cm_arrays.xml +++ b/res/values-es-rXA/cm_arrays.xml @@ -16,17 +16,12 @@ limitations under the License. --> <resources> - <string-array name="preferences_interface_general_icons_text_font_family_entries"> - <item>Normal</item> - <item>Fina</item> - <item>Comprimida</item> - </string-array> <string-array name="transition_effect_entries"> <item>Nengún</item> - <item>Zoom entrante</item> - <item>Zoom saliente</item> - <item>Rotar arriba</item> - <item>Rotar abaxo</item> + <item>Acercar</item> + <item>Allonxar</item> + <item>Xirar arriba</item> + <item>Xirar abaxo</item> <item>Cúbicu entrante</item> <item>Cúbicu saliente</item> <item>Empilar</item> diff --git a/res/values-es-rXA/cm_strings.xml b/res/values-es-rXA/cm_strings.xml index df3dedecb..8c6a2e4c1 100644 --- a/res/values-es-rXA/cm_strings.xml +++ b/res/values-es-rXA/cm_strings.xml @@ -16,49 +16,37 @@ limitations under the License. --> <resources> - <string name="application_copyright">Copyright \u00A9 2014 The CyanogenMod Project</string> - <string name="sort_button_text">Ordenar</string> - <string name="filter_button_text">Filtriar</string> - <string name="default_screen_button_text">Pantalla por defeutu</string> - <string name="transition_effect_button_text">Efeutu de desplazamientu</string> - <string name="sort_mode_title">Títulu</string> - <string name="sort_mode_launch_count">Vegaes executáu</string> - <string name="sort_mode_install_time">Data d\'instalación</string> + <string name="launcher_settings">AXUSTES DEL LLANZADOR</string> + <string name="home_screen_settings">AXUSTES DE PANTALLA D\'ANICIU</string> + <string name="drawer_settings">AXUSTES DE LES APLICACIONES</string> + <string name="app_settings">AXUSTES D\'APLICACIÓN</string> + <string name="setting_state_on">SÍ</string> + <string name="setting_state_off">NON</string> + <string name="themes_button_text">Temes</string> <string name="scrolling_page_outlines">Berbesos de pantalla</string> <string name="scrolling_fade_adjacent">Efeutu de dilíu</string> - <string name="wallpaper_scroll">Desplazar fondu</string> - <string name="preferences_title">Axustes</string> - <string name="preferences_application_title">Aplicación</string> - <string name="preferences_interface_homescreen_title">Pantalla d\'aniciu</string> - <string name="preferences_interface_homescreen_search_title">Barra de gueta</string> - <string name="preferences_interface_homescreen_search_summary">Habilitar permantentemente la barra de gueta</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_title">Anubrir etiquetes de los iconos</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">Anubrir les etiquetes de los iconos na pantalla d\'aniciu</string> - <string name="preferences_interface_drawer_title">Aplicaciones</string> - <string name="preferences_interface_drawer_summary">Aplicaciones y widgets</string> - <string name="preferences_interface_drawer_apps_category">Aplicaciones</string> - <string name="preferences_interface_drawer_hidden_apps_title">Aplicaciones anubríes</string> - <string name="preferences_interface_drawer_hidden_apps_summary">Anubrir aplicaciones pa que nun s\'amuesen</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">Desaniciar atayos</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">Desaniciar atayos d\'aplicaciones anubríes de la pantalla d\'aniciu</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_title">Desaniciar widgets</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_summary">Desaniciar widgets d\'aplicaciones anubríes de la pantalla d\'aniciu</string> - <string name="preferences_interface_drawer_hide_icon_labels_title">Anubrir etiquetes de los iconos</string> - <string name="preferences_interface_drawer_hide_icon_labels_summary">Anubrir les etiquetes de los iconos de la pantalla d\'aniciu</string> - <string name="preferences_interface_dock_title">Barra d\'aplicaciones</string> - <string name="preferences_interface_general_title">Xeneral</string> - <string name="preferences_interface_general_icons_category">Iconos</string> - <string name="preferences_interface_general_icons_large_title">Iconos grandes</string> - <string name="preferences_interface_general_icons_large_summary">Usar iconos grandes na pantalla d\'aniciu y d\'aplicaciones</string> - <string name="preferences_interface_general_icons_text_style_title">Estilu\'l testu</string> - <string name="preferences_interface_general_icons_text_style_summary">Camudar l\'estilu\'l testu pa les etiquetes de los iconos</string> - <string name="dialog_pick_iconpack_title">Esbillar paquete d\'iconos</string> - <string name="default_iconpack_title">Iconos por defeutu</string> - <string name="icon_packs_title">Paquetes d\'iconos</string> - <string name="no_iconpacks_summary">Nun hai paquetes d\'iconos instalaos</string> - <string name="clear_keyguard_wallpaper">Llimpiar</string> - <string name="all_apps_cling_cm">Personaliza les tos aplicaciones</string> - <string name="all_apps_cling_summary">Primi l\'indicador de páxina p\'amosar axustes adicionales</string> - <string name="menu_hidden_apps_delete">Restablecer</string> + <string name="scrolling_wallpaper">Desplazar fondu</string> + <string name="grid_size_text">Tamañu del rexáu</string> + <string name="grid_size_comfortable">Confortable</string> + <string name="grid_size_cozy">Acoyedor</string> + <string name="grid_size_condensed">Condensáu</string> + <string name="grid_size_custom">Personalizáu</string> + <string name="preferences_interface_homescreen_custom">Esbilla\'l tamañu personalizáu</string> + <string name="preferences_interface_homescreen_rows_title">Númberu de fileres</string> + <string name="preferences_interface_homescreen_columns_title">Númberu de columnes</string> <string name="hidden_apps_title">Aplicaciones anubríes</string> + <string name="scroll_effect_text">Efeutu de desplazamientu</string> + <string name="drawer_sorting_text">Mou d\'ordenación</string> + <string name="sort_mode_title">Títulu</string> + <string name="sort_mode_launch_count">Vegaes executáu</string> + <string name="sort_mode_install_time">Data d\'instalación</string> + <string name="home_screen_search_text">Barra de gueta</string> + <string name="larger_icons_text">Iconos grandes</string> + <string name="icon_labels">Etiquetes de los iconos</string> + <string name="icon_labels_show">Amosar</string> + <string name="icon_labels_hide">Anubrir</string> + <string name="protected_app_settings">Apps protexíes</string> + <string name="search_screen_left_text">Panel de gueta</string> + <string name="search_screen_left_unsupported_toast">Ye necesario tener una aplicación de gueta y CyanogenMod pa poder usar esta carauterística.</string> + <string name="dialog_confirm">Confirmar</string> </resources> diff --git a/res/values-es/cm_arrays.xml b/res/values-es/cm_arrays.xml index 1f36f82a1..3f1f46dab 100644 --- a/res/values-es/cm_arrays.xml +++ b/res/values-es/cm_arrays.xml @@ -16,11 +16,6 @@ limitations under the License. --> <resources> - <string-array name="preferences_interface_general_icons_text_font_family_entries"> - <item>Normal</item> - <item>Fina</item> - <item>Comprimida</item> - </string-array> <string-array name="transition_effect_entries"> <item>Ninguno</item> <item>Zoom entrante</item> diff --git a/res/values-es/cm_strings.xml b/res/values-es/cm_strings.xml index e0478d8ea..44727d129 100644 --- a/res/values-es/cm_strings.xml +++ b/res/values-es/cm_strings.xml @@ -16,49 +16,37 @@ limitations under the License. --> <resources> - <string name="application_copyright">Copyright \u00A9 2014 The CyanogenMod Project</string> - <string name="sort_button_text">Ordenar</string> - <string name="filter_button_text">Filtrar</string> - <string name="default_screen_button_text">Pantalla por defecto</string> - <string name="transition_effect_button_text">Efecto de desplazamiento</string> - <string name="sort_mode_title">Título</string> - <string name="sort_mode_launch_count">Veces ejecutado</string> - <string name="sort_mode_install_time">Fecha de instalación</string> + <string name="launcher_settings">AJUSTES DEL LANZADOR</string> + <string name="home_screen_settings">AJUSTES DEL INICIO</string> + <string name="drawer_settings">AJUSTES DE LAS APLICACIONES</string> + <string name="app_settings">AJUSTES DE LA APLICACIÓN</string> + <string name="setting_state_on">SÍ</string> + <string name="setting_state_off">NO</string> + <string name="themes_button_text">Temas</string> <string name="scrolling_page_outlines">Bordes de pantalla</string> <string name="scrolling_fade_adjacent">Efecto de fundido</string> - <string name="wallpaper_scroll">Desplazar fondo</string> - <string name="preferences_title">Ajustes</string> - <string name="preferences_application_title">Aplicación</string> - <string name="preferences_interface_homescreen_title">Pantalla de inicio</string> - <string name="preferences_interface_homescreen_search_title">Barra de búsqueda</string> - <string name="preferences_interface_homescreen_search_summary">Habilitar la barra de búsqueda permanentemente</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_title">Ocultar etiquetas</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">Ocultar las etiquetas de los iconos en la pantalla de inicio</string> - <string name="preferences_interface_drawer_title">Aplicaciones</string> - <string name="preferences_interface_drawer_summary">Aplicaciones y widgets</string> - <string name="preferences_interface_drawer_apps_category">Aplicaciones</string> - <string name="preferences_interface_drawer_hidden_apps_title">Ocultar aplicaciones</string> - <string name="preferences_interface_drawer_hidden_apps_summary">Ocultar aplicaciones para que no se muestren</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">Eliminar iconos</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">Eliminar iconos de aplicaciones ocultas de la pantalla de inicio</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_title">Eliminar widgets</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_summary">Eliminar widgets de aplicaciones ocultas de la pantalla de inicio</string> - <string name="preferences_interface_drawer_hide_icon_labels_title">Ocultar etiquetas</string> - <string name="preferences_interface_drawer_hide_icon_labels_summary">Ocultar las etiquetas de los iconos de la pantalla de inicio</string> - <string name="preferences_interface_dock_title">Barra de aplicaciones</string> - <string name="preferences_interface_general_title">General</string> - <string name="preferences_interface_general_icons_category">Iconos</string> - <string name="preferences_interface_general_icons_large_title">Iconos grandes</string> - <string name="preferences_interface_general_icons_large_summary">Usar iconos grandes en la pantalla de inicio y de aplicaciones</string> - <string name="preferences_interface_general_icons_text_style_title">Estilo del texto</string> - <string name="preferences_interface_general_icons_text_style_summary">Cambiar el estilo de texto para las etiquetas de los iconos</string> - <string name="dialog_pick_iconpack_title">Escoger paquete de iconos</string> - <string name="default_iconpack_title">Iconos por defecto</string> - <string name="icon_packs_title">Paquetes de iconos</string> - <string name="no_iconpacks_summary">No hay paquetes de iconos instalados</string> - <string name="clear_keyguard_wallpaper">Limpiar</string> - <string name="all_apps_cling_cm">Personalizar tus aplicaciones</string> - <string name="all_apps_cling_summary">Tocar el indicador de página para mostrar ajustes adicionales</string> - <string name="menu_hidden_apps_delete">Restablecer</string> + <string name="scrolling_wallpaper">Desplazar fondo de pantalla</string> + <string name="grid_size_text">Tamaño de la cuadrícula</string> + <string name="grid_size_comfortable">Normal</string> + <string name="grid_size_cozy">Cómoda</string> + <string name="grid_size_condensed">Comprimida</string> + <string name="grid_size_custom">Personalizada</string> + <string name="preferences_interface_homescreen_custom">Selecciona el tamaño personalizado</string> + <string name="preferences_interface_homescreen_rows_title">Número de filas</string> + <string name="preferences_interface_homescreen_columns_title">Número de columnas</string> <string name="hidden_apps_title">Ocultar aplicaciones</string> + <string name="scroll_effect_text">Efecto de desplazamiento</string> + <string name="drawer_sorting_text">Modo de ordenación</string> + <string name="sort_mode_title">Título</string> + <string name="sort_mode_launch_count">Veces ejecutado</string> + <string name="sort_mode_install_time">Fecha de instalación</string> + <string name="home_screen_search_text">Barra de búsqueda</string> + <string name="larger_icons_text">Iconos grandes</string> + <string name="icon_labels">Etiquetas de iconos</string> + <string name="icon_labels_show">Mostrar</string> + <string name="icon_labels_hide">Ocultar</string> + <string name="protected_app_settings">Aplicaciones protegidas</string> + <string name="search_screen_left_text">Panel de búsqueda</string> + <string name="search_screen_left_unsupported_toast">Debes tener una aplicación de búsqueda y CyanogenMod para poder utilizar esta característica.</string> + <string name="dialog_confirm">Confirmar</string> </resources> diff --git a/res/values-et/cm_arrays.xml b/res/values-et/cm_arrays.xml index c652830e5..0a9de69ed 100644 --- a/res/values-et/cm_arrays.xml +++ b/res/values-et/cm_arrays.xml @@ -16,24 +16,19 @@ limitations under the License. --> <resources> - <string-array name="preferences_interface_general_icons_text_font_family_entries"> - <item>Regulaarne</item> - <item>Kerge</item> - <item>Lühendatud</item> - </string-array> <string-array name="transition_effect_entries"> <item>Puudub</item> - <item>Suumi Sisse</item> - <item>Suumi Välja</item> - <item>Pööra Üles</item> - <item>Pööra Alla</item> - <item>Kuubik Sisse</item> - <item>Kuubik Välja</item> + <item>Suumi sisse</item> + <item>Suumi välja</item> + <item>Pööra üles</item> + <item>Pööra alla</item> + <item>Kuubik sisse</item> + <item>Kuubik välja</item> <item>Kihid</item> <item>Akordion</item> <item>Pööra ümber</item> - <item>Silinder Sisse</item> - <item>Silinder Välja</item> + <item>Silinder sisse</item> + <item>Silinder välja</item> <item>Karussell</item> <item>Ülevaade</item> </string-array> diff --git a/res/values-et/cm_strings.xml b/res/values-et/cm_strings.xml index 3b3ff2b5f..1b97ec2a1 100644 --- a/res/values-et/cm_strings.xml +++ b/res/values-et/cm_strings.xml @@ -16,49 +16,37 @@ limitations under the License. --> <resources> - <string name="application_copyright">Autoriõigus \u00A9 2014 The CyanogenMod Project</string> - <string name="sort_button_text">Sorteeri</string> - <string name="filter_button_text">Filtreeri</string> - <string name="default_screen_button_text">Vaikimisi ekraan</string> - <string name="transition_effect_button_text">Kerimisefekt</string> - <string name="sort_mode_title">Pealkiri</string> - <string name="sort_mode_launch_count">Käivitamiste arv</string> - <string name="sort_mode_install_time">Installeerimise aeg</string> + <string name="launcher_settings">KÄIVITAJA SEADED</string> + <string name="home_screen_settings">KODUEKRAANI SEADED</string> + <string name="drawer_settings">SAHTLI SEADED</string> + <string name="app_settings">RAKENDUSE SEADED</string> + <string name="setting_state_on">SEES</string> + <string name="setting_state_off">VÄLJAS</string> + <string name="themes_button_text">Teemad</string> <string name="scrolling_page_outlines">Lehe äärisjooned</string> <string name="scrolling_fade_adjacent">Sulanda äärislehed</string> - <string name="wallpaper_scroll">Keri taustapilti</string> - <string name="preferences_title">Sätted</string> - <string name="preferences_application_title">Rakendus</string> - <string name="preferences_interface_homescreen_title">Koduekraan</string> - <string name="preferences_interface_homescreen_search_title">Otsinguriba</string> - <string name="preferences_interface_homescreen_search_summary">Näita püsivat otsinguriba ekraani ülaosas</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_title">Peida ikoonide sildid</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">Peida ikoonide sildid koduekraanil</string> - <string name="preferences_interface_drawer_title">Sahtel</string> - <string name="preferences_interface_drawer_summary">Rakenduste ja vidinate sahtel</string> - <string name="preferences_interface_drawer_apps_category">Rakendused</string> - <string name="preferences_interface_drawer_hidden_apps_title">Peidetud rakendused</string> - <string name="preferences_interface_drawer_hidden_apps_summary">Peida rakendusi sahtlist</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">Eemalda otseteed</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">Eemalda peidetud rakenduste otseteed koduekraanilt</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_title">Eemalda vidinad</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_summary">Eemalda peidetud rakenduste vidinad koduekraanilt</string> - <string name="preferences_interface_drawer_hide_icon_labels_title">Peida ikoonide sildid</string> - <string name="preferences_interface_drawer_hide_icon_labels_summary">Peida ikoonide sildid sahtlis</string> - <string name="preferences_interface_dock_title">Dokk</string> - <string name="preferences_interface_general_title">Üldine</string> - <string name="preferences_interface_general_icons_category">Ikoonid</string> - <string name="preferences_interface_general_icons_large_title">Suuremad ikoonid</string> - <string name="preferences_interface_general_icons_large_summary">Kasuta ülisuuri rakenduste ikoone koduekraanil ja sahtlis</string> - <string name="preferences_interface_general_icons_text_style_title">Kirja fondistiil</string> - <string name="preferences_interface_general_icons_text_style_summary">Fondi tüüp ja stiil mida kasutatakse ikoonidel</string> - <string name="dialog_pick_iconpack_title">Vali ikoonipakk</string> - <string name="default_iconpack_title">Vaikimisi ikoonid</string> - <string name="icon_packs_title">Ikoonipakid</string> - <string name="no_iconpacks_summary">Ühtegi ikoonipakki pole installitud</string> - <string name="clear_keyguard_wallpaper">Selge</string> - <string name="all_apps_cling_cm">Kohandage oma sahtlit</string> - <string name="all_apps_cling_summary">Puudutage lehe indikaatoril et näha täiendavaid sätteid</string> - <string name="menu_hidden_apps_delete">Lähtesta</string> + <string name="scrolling_wallpaper">Keri taustapilti</string> + <string name="grid_size_text">Ruudustiku suurus</string> + <string name="grid_size_comfortable">Mugav</string> + <string name="grid_size_cozy">Kodune</string> + <string name="grid_size_condensed">Kärbitud</string> + <string name="grid_size_custom">Isiklik</string> + <string name="preferences_interface_homescreen_custom">Vali sobiv suurus</string> + <string name="preferences_interface_homescreen_rows_title">Ridade arv</string> + <string name="preferences_interface_homescreen_columns_title">Veergude arv</string> <string name="hidden_apps_title">Peidetud rakendused</string> + <string name="scroll_effect_text">Kerimisefekt</string> + <string name="drawer_sorting_text">Sortimisrežiim</string> + <string name="sort_mode_title">Pealkiri</string> + <string name="sort_mode_launch_count">Käivitamiste arv</string> + <string name="sort_mode_install_time">Installeerimise aeg</string> + <string name="home_screen_search_text">Otsinguriba</string> + <string name="larger_icons_text">Suuremad ikoonid</string> + <string name="icon_labels">Ikooni sildid</string> + <string name="icon_labels_show">Näita</string> + <string name="icon_labels_hide">Peida</string> + <string name="protected_app_settings">Kaitstud rakendused</string> + <string name="search_screen_left_text">Otsingupaneel</string> + <string name="search_screen_left_unsupported_toast">Teil peab olema toetatud otsingurakendus ja CyanogenMod et kasutada seda võimalust.</string> + <string name="dialog_confirm">Kinnita</string> </resources> diff --git a/res/values-fi/cm_arrays.xml b/res/values-fi/cm_arrays.xml index b466c383d..9b1d7a28e 100644 --- a/res/values-fi/cm_arrays.xml +++ b/res/values-fi/cm_arrays.xml @@ -16,11 +16,6 @@ limitations under the License. --> <resources> - <string-array name="preferences_interface_general_icons_text_font_family_entries"> - <item>Tavallinen</item> - <item>Ohut</item> - <item>Tiivistetty</item> - </string-array> <string-array name="transition_effect_entries"> <item>Ei mitään</item> <item>Lähennä</item> diff --git a/res/values-fi/cm_strings.xml b/res/values-fi/cm_strings.xml index 679510ca5..a9556788e 100644 --- a/res/values-fi/cm_strings.xml +++ b/res/values-fi/cm_strings.xml @@ -16,49 +16,37 @@ limitations under the License. --> <resources> - <string name="application_copyright">Copyright \u00A9 2014 The CyanogenMod Project</string> - <string name="sort_button_text">Järjestä</string> - <string name="filter_button_text">Suodatin</string> - <string name="default_screen_button_text">Oletusnäyttö</string> - <string name="transition_effect_button_text">Vieritysefekti</string> - <string name="sort_mode_title">Nimi</string> - <string name="sort_mode_launch_count">Käynnistyskerrat</string> - <string name="sort_mode_install_time">Asennuspäivä</string> + <string name="launcher_settings">LAUNCHERIN ASETUKSET</string> + <string name="home_screen_settings">KOTINÄYTÖN ASETUKSET</string> + <string name="drawer_settings">SOVELLUSVALIKON ASETUKSET</string> + <string name="app_settings">SOVELLUKSEN ASETUKSET</string> + <string name="setting_state_on">PÄÄLLÄ</string> + <string name="setting_state_off">POIS</string> + <string name="themes_button_text">Teemat</string> <string name="scrolling_page_outlines">Sivun ulkoreunat</string> <string name="scrolling_fade_adjacent">Häivytä sivun reunat</string> - <string name="wallpaper_scroll">Vieritä taustakuvaa</string> - <string name="preferences_title">Asetukset</string> - <string name="preferences_application_title">Sovellus</string> - <string name="preferences_interface_homescreen_title">Kotinäyttö</string> - <string name="preferences_interface_homescreen_search_title">Hakupalkki</string> - <string name="preferences_interface_homescreen_search_summary">Näytä pysyvä hakupalkki näytön yläreunassa</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_title">Piilota kuvakkeiden tekstit</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">Piilota kuvakkeiden tekstit kotinäytöllä</string> - <string name="preferences_interface_drawer_title">Sovellusvalikko</string> - <string name="preferences_interface_drawer_summary">Sovellus- ja widgetvalikko</string> - <string name="preferences_interface_drawer_apps_category">Sovellukset</string> - <string name="preferences_interface_drawer_hidden_apps_title">Piilotetut sovellukset</string> - <string name="preferences_interface_drawer_hidden_apps_summary">Piilota sovellukset valikosta</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">Poista kuvakkeet</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">Poista piilotettujen sovellusten kuvakkeet kotinäytöltä</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_title">Poista widgetit</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_summary">Poista piilotettujen sovellusten widgetit kotinäytöltä</string> - <string name="preferences_interface_drawer_hide_icon_labels_title">Piilota kuvakkeiden tekstit</string> - <string name="preferences_interface_drawer_hide_icon_labels_summary">Piilota kuvakkeiden tekstit valikossa</string> - <string name="preferences_interface_dock_title">Alapalkki</string> - <string name="preferences_interface_general_title">Yleiset</string> - <string name="preferences_interface_general_icons_category">Kuvakkeet</string> - <string name="preferences_interface_general_icons_large_title">Suuremmat kuvakkeet</string> - <string name="preferences_interface_general_icons_large_summary">Käytä erittäin suuria sovelluskuvakkeita kotinäytöllä ja sovellusvalikossa</string> - <string name="preferences_interface_general_icons_text_style_title">Fonttityyli</string> - <string name="preferences_interface_general_icons_text_style_summary">Muuta kuvakkeiden fonttien tyyliä</string> - <string name="dialog_pick_iconpack_title">Valitse kuvakepaketti</string> - <string name="default_iconpack_title">Oletuskuvakkeet</string> - <string name="icon_packs_title">Kuvakepaketit</string> - <string name="no_iconpacks_summary">Kuvakepaketteja ei asennettu</string> - <string name="clear_keyguard_wallpaper">Tyhjennä</string> - <string name="all_apps_cling_cm">Muokkaa sovellusvalikkoa</string> - <string name="all_apps_cling_summary">Napauta sivun ilmaisinta nähdäksesi lisää asetuksia</string> - <string name="menu_hidden_apps_delete">Nollaa</string> + <string name="scrolling_wallpaper">Vieritä taustakuvaa</string> + <string name="grid_size_text">Ruudukon koko</string> + <string name="grid_size_comfortable">Mukava</string> + <string name="grid_size_cozy">Kodikas</string> + <string name="grid_size_condensed">Tiivistetty</string> + <string name="grid_size_custom">Muokattu</string> + <string name="preferences_interface_homescreen_custom">Valitse mukautettu koko</string> + <string name="preferences_interface_homescreen_rows_title">Rivien määrä</string> + <string name="preferences_interface_homescreen_columns_title">Sarakkeiden määrä</string> <string name="hidden_apps_title">Piilotetut sovellukset</string> + <string name="scroll_effect_text">Vieritysefekti</string> + <string name="drawer_sorting_text">Lajittelu</string> + <string name="sort_mode_title">Nimi</string> + <string name="sort_mode_launch_count">Käynnistyskerrat</string> + <string name="sort_mode_install_time">Asennuspäivä</string> + <string name="home_screen_search_text">Hakupalkki</string> + <string name="larger_icons_text">Suuremmat kuvakkeet</string> + <string name="icon_labels">Kuvakkeiden otsikot</string> + <string name="icon_labels_show">Näytä</string> + <string name="icon_labels_hide">Piilota</string> + <string name="protected_app_settings">Suojatut sovellukset</string> + <string name="search_screen_left_text">Hakupaneeli</string> + <string name="search_screen_left_unsupported_toast">Sinulla tulee olla tuettu hakusovellus ja CyanogenMod käyttääksesi tätä toimintoa.</string> + <string name="dialog_confirm">Vahvista</string> </resources> diff --git a/res/values-fr/cm_arrays.xml b/res/values-fr/cm_arrays.xml index 15ef135ee..46a63a475 100644 --- a/res/values-fr/cm_arrays.xml +++ b/res/values-fr/cm_arrays.xml @@ -16,15 +16,10 @@ limitations under the License. --> <resources> - <string-array name="preferences_interface_general_icons_text_font_family_entries"> - <item>Régulier</item> - <item>Léger</item> - <item>Condensé</item> - </string-array> <string-array name="transition_effect_entries"> <item>Aucun</item> - <item>Zoom avant</item> - <item>Zoom arrière</item> + <item>Zoom</item> + <item>Dézoom</item> <item>Rotation vers le haut</item> <item>Rotation vers le bas</item> <item>Cube intérieur</item> diff --git a/res/values-fr/cm_strings.xml b/res/values-fr/cm_strings.xml index 1ba03261b..5de215d40 100644 --- a/res/values-fr/cm_strings.xml +++ b/res/values-fr/cm_strings.xml @@ -16,49 +16,37 @@ limitations under the License. --> <resources> - <string name="application_copyright">Copyright \u00A9 2014 The CyanogenMod Project</string> - <string name="sort_button_text">Trier</string> - <string name="filter_button_text">Filtre</string> - <string name="default_screen_button_text">Écran par défaut</string> - <string name="transition_effect_button_text">Effet de défilement</string> - <string name="sort_mode_title">Titre</string> - <string name="sort_mode_launch_count">Nombre de lancements</string> - <string name="sort_mode_install_time">Durée d\'installation</string> + <string name="launcher_settings">PARAMÈTRES DU LANCEUR</string> + <string name="home_screen_settings">PARAMÈTRES DE L\'ÉCRAN D\'ACCUEIL</string> + <string name="drawer_settings">PARAMÈTRES DE L\'ÉCRAN DES APPLICATIONS</string> + <string name="app_settings">PARAMÈTRES DE L\'APPLICATION</string> + <string name="setting_state_on">OUI</string> + <string name="setting_state_off">NON</string> + <string name="themes_button_text">Thèmes</string> <string name="scrolling_page_outlines">Espacement des pages</string> <string name="scrolling_fade_adjacent">Estomper les pages adjacentes</string> - <string name="wallpaper_scroll">Défilement du fond d\'écran</string> - <string name="preferences_title">Paramètres</string> - <string name="preferences_application_title">Application</string> - <string name="preferences_interface_homescreen_title">Écran d\'accueil</string> - <string name="preferences_interface_homescreen_search_title">Barre de recherche</string> - <string name="preferences_interface_homescreen_search_summary">Afficher la barre de recherche persistante en haut de l\'écran</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_title">Masquer le nom des icônes</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">Masquer le nom des icônes sur l\'écran d\'accueil</string> - <string name="preferences_interface_drawer_title">Liste d\'applications</string> - <string name="preferences_interface_drawer_summary">Applications et widgets de la liste des applications</string> - <string name="preferences_interface_drawer_apps_category">Applications</string> - <string name="preferences_interface_drawer_hidden_apps_title">Applications masquées</string> - <string name="preferences_interface_drawer_hidden_apps_summary">Masquer les applications de la liste des applications</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">Supprimer les raccourcis</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">Supprimer les raccourcis sur l\'écran d\'accueil des applications masquées</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_title">Supprimer les widgets</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_summary">Supprimer les widgets sur l\'écran d\'accueil des applications masquées</string> - <string name="preferences_interface_drawer_hide_icon_labels_title">Masquer le nom des icônes</string> - <string name="preferences_interface_drawer_hide_icon_labels_summary">Masquer le nom des icônes dans la liste des applications</string> - <string name="preferences_interface_dock_title">Dock</string> - <string name="preferences_interface_general_title">Général</string> - <string name="preferences_interface_general_icons_category">Icônes</string> - <string name="preferences_interface_general_icons_large_title">Grandes icônes</string> - <string name="preferences_interface_general_icons_large_summary">Utiliser des icônes extra-larges dans l\'écran d\'accueil et la liste d\'applications</string> - <string name="preferences_interface_general_icons_text_style_title">Style de police de texte</string> - <string name="preferences_interface_general_icons_text_style_summary">Variante et style de police à utiliser pour le texte des l\'icônes</string> - <string name="dialog_pick_iconpack_title">Choisissez le pack d\'icônes</string> - <string name="default_iconpack_title">Icônes par défaut</string> - <string name="icon_packs_title">Packs d\'icônes</string> - <string name="no_iconpacks_summary">Aucun pack d\'icônes installé</string> - <string name="clear_keyguard_wallpaper">Supprimer</string> - <string name="all_apps_cling_cm">Personnaliser votre affichage</string> - <string name="all_apps_cling_summary">Appuyez sur l\'indicateur de page pour afficher les paramètres de configuration supplémentaires</string> - <string name="menu_hidden_apps_delete">Réinitialiser</string> + <string name="scrolling_wallpaper">Défilement du fond d\'écran</string> + <string name="grid_size_text">Taille de la grille</string> + <string name="grid_size_comfortable">Confortable</string> + <string name="grid_size_cozy">Cosy</string> + <string name="grid_size_condensed">Condensé</string> + <string name="grid_size_custom">Personnalisée</string> + <string name="preferences_interface_homescreen_custom">Sélectionner la taille personnalisée</string> + <string name="preferences_interface_homescreen_rows_title">Nombre de lignes</string> + <string name="preferences_interface_homescreen_columns_title">Nombre de colonnes</string> <string name="hidden_apps_title">Applications masquées</string> + <string name="scroll_effect_text">Effet de défilement</string> + <string name="drawer_sorting_text">Mode de tri</string> + <string name="sort_mode_title">Titre</string> + <string name="sort_mode_launch_count">Nombre de lancements</string> + <string name="sort_mode_install_time">Durée d\'installation</string> + <string name="home_screen_search_text">Barre de recherche</string> + <string name="larger_icons_text">Grandes icônes</string> + <string name="icon_labels">Nom des icônes</string> + <string name="icon_labels_show">Afficher</string> + <string name="icon_labels_hide">Masquer</string> + <string name="protected_app_settings">Applications protégées</string> + <string name="search_screen_left_text">Panneau de recherche</string> + <string name="search_screen_left_unsupported_toast">Vous devez avoir une application de recherche compatible et CyanogenMod pour utiliser cette fonctionnalité.</string> + <string name="dialog_confirm">Confirmer</string> </resources> diff --git a/res/values-hu/cm_arrays.xml b/res/values-hu/cm_arrays.xml index e7b15fe2c..06a15a2fd 100644 --- a/res/values-hu/cm_arrays.xml +++ b/res/values-hu/cm_arrays.xml @@ -16,15 +16,10 @@ limitations under the License. --> <resources> - <string-array name="preferences_interface_general_icons_text_font_family_entries"> - <item>Szokásos</item> - <item>Világos</item> - <item>Tömörített</item> - </string-array> <string-array name="transition_effect_entries"> <item>Nincs</item> - <item>Nagyítás befelé</item> - <item>Nagyítás kifelé</item> + <item>Nagyítás</item> + <item>Kicsinyítés</item> <item>Forgatás felfelé</item> <item>Forgatás lefelé</item> <item>Kocka belül</item> diff --git a/res/values-hu/cm_strings.xml b/res/values-hu/cm_strings.xml index 434fd319e..4dd032e66 100644 --- a/res/values-hu/cm_strings.xml +++ b/res/values-hu/cm_strings.xml @@ -16,49 +16,37 @@ limitations under the License. --> <resources> - <string name="application_copyright">Copyright \u00A9 2014 The CyanogenMod Project</string> - <string name="sort_button_text">Rendezés</string> - <string name="filter_button_text">Szűrő</string> - <string name="default_screen_button_text">Alapértelmezett képernyő</string> - <string name="transition_effect_button_text">Görgetés effekt</string> - <string name="sort_mode_title">Név</string> - <string name="sort_mode_launch_count">Indítások száma</string> - <string name="sort_mode_install_time">Telepítés ideje</string> + <string name="launcher_settings">PROGRAMINDÍTÓ BEÁLLÍTÁSOK</string> + <string name="home_screen_settings">KEZDŐKÉPERNYŐ BEÁLLÍTÁSOK</string> + <string name="drawer_settings">ALKALMAZÁSKÉPERNYŐ BEÁLLÍTÁSOK</string> + <string name="app_settings">ALKALMAZÁS BEÁLLÍTÁSAI</string> + <string name="setting_state_on">BE</string> + <string name="setting_state_off">KI</string> + <string name="themes_button_text">Témák</string> <string name="scrolling_page_outlines">Oldal körvonalak</string> <string name="scrolling_fade_adjacent">Elhalványuló váltás az oldalak közt</string> - <string name="wallpaper_scroll">Háttérkép görgetése</string> - <string name="preferences_title">Beállítások</string> - <string name="preferences_application_title">Alkamazás</string> - <string name="preferences_interface_homescreen_title">Kezdőképernyő</string> - <string name="preferences_interface_homescreen_search_title">Keresési sáv</string> - <string name="preferences_interface_homescreen_search_summary">Állandó keresési sáv megjelenítése a képernyő felső </string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_title">Ikon feliratok elrejtése</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">Elrejti a kezdőképernyőn lévő ikonok neveit</string> - <string name="preferences_interface_drawer_title">Alkalmazásképernyők</string> - <string name="preferences_interface_drawer_summary">Alkalmazások és modulok</string> - <string name="preferences_interface_drawer_apps_category">Alkalmazások</string> - <string name="preferences_interface_drawer_hidden_apps_title">Rejtett alkalmazások</string> - <string name="preferences_interface_drawer_hidden_apps_summary">Alkalmazások elrejtése az alkalmazásképernyőről</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">Rejtett alkalmazások (parancsikonok)</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">Rejtett alkalmazások ikonjainak eltávolítása</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_title">Rejtett alkalmazások (modulok)</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_summary">Rejtett alkalmazás moduljának eltávolítása</string> - <string name="preferences_interface_drawer_hide_icon_labels_title">Ikon feliratok elrejtése</string> - <string name="preferences_interface_drawer_hide_icon_labels_summary">Ikon feliratok elrejtése az alkalmazásképernyőkről</string> - <string name="preferences_interface_dock_title">Dokkoló</string> - <string name="preferences_interface_general_title">Általános</string> - <string name="preferences_interface_general_icons_category">Ikonok</string> - <string name="preferences_interface_general_icons_large_title">Nagyobb ikonok</string> - <string name="preferences_interface_general_icons_large_summary">Extra méretű ikonok a kezdő ill. alkalmazás képernyőkön</string> - <string name="preferences_interface_general_icons_text_style_title">Szöveg betűtípusa</string> - <string name="preferences_interface_general_icons_text_style_summary">Ikon szövegének típusa</string> - <string name="dialog_pick_iconpack_title">Ikoncsomag választása</string> - <string name="default_iconpack_title">Alapértelmezett ikonok</string> - <string name="icon_packs_title">Ikon csomagok</string> - <string name="no_iconpacks_summary">Nincsenek telepítve ikoncsomagok</string> - <string name="clear_keyguard_wallpaper">Törlés</string> - <string name="all_apps_cling_cm">Alkalmazásképernyők testreszabása</string> - <string name="all_apps_cling_summary">Érintse meg az oldaljelölőt a további konfigurációs beállítások megtekintéséhez</string> - <string name="menu_hidden_apps_delete">Visszaállítás</string> + <string name="scrolling_wallpaper">Háttérkép görgetése</string> + <string name="grid_size_text">Rácsméret</string> + <string name="grid_size_comfortable">Kényelmes</string> + <string name="grid_size_cozy">Hangulatos</string> + <string name="grid_size_condensed">Tömörített</string> + <string name="grid_size_custom">Egyéni</string> + <string name="preferences_interface_homescreen_custom">Válassza ki az egyéni méretet</string> + <string name="preferences_interface_homescreen_rows_title">Sorok száma</string> + <string name="preferences_interface_homescreen_columns_title">Oszlopok száma</string> <string name="hidden_apps_title">Rejtett alkalmazások</string> + <string name="scroll_effect_text">Görgetés effekt</string> + <string name="drawer_sorting_text">Rendezési mód</string> + <string name="sort_mode_title">Név</string> + <string name="sort_mode_launch_count">Indítások száma</string> + <string name="sort_mode_install_time">Telepítés ideje</string> + <string name="home_screen_search_text">Keresési sáv</string> + <string name="larger_icons_text">Nagyobb ikonok</string> + <string name="icon_labels">Ikon feliratok</string> + <string name="icon_labels_show">Megjelenítés</string> + <string name="icon_labels_hide">Elrejtés</string> + <string name="protected_app_settings">Védett alkalmazások</string> + <string name="search_screen_left_text">Keresés panel</string> + <string name="search_screen_left_unsupported_toast">Rendelkeznie kell egy támogatott kereső alkalmazással és CyanogenMod-dal, hogy használhassa ezt a funkciót.</string> + <string name="dialog_confirm">Megerősítés</string> </resources> diff --git a/res/values-in/cm_arrays.xml b/res/values-in/cm_arrays.xml index d7c2e6fb6..4e7c2d485 100644 --- a/res/values-in/cm_arrays.xml +++ b/res/values-in/cm_arrays.xml @@ -16,24 +16,19 @@ limitations under the License. --> <resources> - <string-array name="preferences_interface_general_icons_text_font_family_entries"> - <item>Reguler</item> - <item>Terang</item> - <item>Condensed</item> - </string-array> <string-array name="transition_effect_entries"> <item>Tidak Ada</item> - <item>Perkecil</item> - <item>Perbesar</item> - <item>Putar ke Atas</item> - <item>Putar ke Bawah</item> - <item>Kubus Masuk</item> - <item>Kubus Keluar</item> + <item>Memperbesar</item> + <item>Memperkecil</item> + <item>Memutar keatas</item> + <item>Memutar kebawah</item> + <item>Kubus masuk</item> + <item>Kubus keluar</item> <item>Tumpukan</item> - <item>Accordion</item> + <item>Akordion</item> <item>Membalik</item> - <item>Silinder Masuk</item> - <item>Silinder Keluar</item> + <item>Silinder masuk</item> + <item>Silinder keluar</item> <item>Komedi putar</item> <item>Overview</item> </string-array> diff --git a/res/values-in/cm_strings.xml b/res/values-in/cm_strings.xml index 85cd71ba4..3d9070e40 100644 --- a/res/values-in/cm_strings.xml +++ b/res/values-in/cm_strings.xml @@ -16,49 +16,37 @@ limitations under the License. --> <resources> - <string name="application_copyright">Hak cipta \u00A9 2013 The CyanogenMod Project</string> - <string name="sort_button_text">Urutkan</string> - <string name="filter_button_text">Filter</string> - <string name="default_screen_button_text">Layar default</string> - <string name="transition_effect_button_text">Efek scroll</string> - <string name="sort_mode_title">Judul</string> - <string name="sort_mode_launch_count">Hitungan peluncur</string> - <string name="sort_mode_install_time">Waktu pemasangan</string> + <string name="launcher_settings">PENGATURAN PELUNCUR</string> + <string name="home_screen_settings">PENGATURAN LAYAR HOME</string> + <string name="drawer_settings">PENGATURAN DRAWER</string> + <string name="app_settings">PENGATURAN APL</string> + <string name="setting_state_on">ON</string> + <string name="setting_state_off">OFF</string> + <string name="themes_button_text">Tema</string> <string name="scrolling_page_outlines">Garis luar halaman</string> <string name="scrolling_fade_adjacent">Fade side pages</string> - <string name="wallpaper_scroll">Wallpaper gulir</string> - <string name="preferences_title">Pengaturan</string> - <string name="preferences_application_title">App</string> - <string name="preferences_interface_homescreen_title">Layar home</string> - <string name="preferences_interface_homescreen_search_title">Bar pencarian</string> - <string name="preferences_interface_homescreen_search_summary">Tampilkan bar pencarian tetap di atas layar</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_title">Sembunyikan label ikon</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">Sembunyikan label ikon pada homescreen</string> - <string name="preferences_interface_drawer_title">Drawer</string> - <string name="preferences_interface_drawer_summary">Aplikasi dan widgets drawer</string> - <string name="preferences_interface_drawer_apps_category">Aplikasi</string> - <string name="preferences_interface_drawer_hidden_apps_title">Aplikasi tersembunyi</string> - <string name="preferences_interface_drawer_hidden_apps_summary">Sembunyikan aplikasi dari drawer</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">Hapus pintasan</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">Hapus cara pintas apps yang tersembunyi dari homescreen</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_title">Hapus widget</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_summary">Hapus aplikasi widget tersembunyi dari homescreen</string> - <string name="preferences_interface_drawer_hide_icon_labels_title">Sembunyikan label ikon</string> - <string name="preferences_interface_drawer_hide_icon_labels_summary">Sembunyikan label ikon di drawer</string> - <string name="preferences_interface_dock_title">Dock</string> - <string name="preferences_interface_general_title">Umum</string> - <string name="preferences_interface_general_icons_category">Ikon</string> - <string name="preferences_interface_general_icons_large_title">Ikon lebih besar</string> - <string name="preferences_interface_general_icons_large_summary">Gunakan ikon aplikasi lebih besar di homescreen dan drawer</string> - <string name="preferences_interface_general_icons_text_style_title">Gaya teks font</string> - <string name="preferences_interface_general_icons_text_style_summary">Varian dan gaya font untuk menggunakan teks icon</string> - <string name="dialog_pick_iconpack_title">Pilih paket ikon</string> - <string name="default_iconpack_title">Ikon semula</string> - <string name="icon_packs_title">Paket ikon</string> - <string name="no_iconpacks_summary">Tidak ada ikon paket yang diinstal</string> - <string name="clear_keyguard_wallpaper">Bersihkan</string> - <string name="all_apps_cling_cm">Sesuaikan drawer anda</string> - <string name="all_apps_cling_summary">Tap indikator halaman untuk melihat pengaturan konfigurasi tambahan</string> - <string name="menu_hidden_apps_delete">Kembalikan</string> + <string name="scrolling_wallpaper">Gulir wallpaper</string> + <string name="grid_size_text">Ukuran grid</string> + <string name="grid_size_comfortable">Comfortable</string> + <string name="grid_size_cozy">Cozy</string> + <string name="grid_size_condensed">Condensed</string> + <string name="grid_size_custom">Kustom</string> + <string name="preferences_interface_homescreen_custom">Pilih ukuran kustom</string> + <string name="preferences_interface_homescreen_rows_title">Jumlah baris</string> + <string name="preferences_interface_homescreen_columns_title">Jumlah kolom</string> <string name="hidden_apps_title">Aplikasi tersembunyi</string> + <string name="scroll_effect_text">Efek gulir</string> + <string name="drawer_sorting_text">Mode penyortiran</string> + <string name="sort_mode_title">Judul</string> + <string name="sort_mode_launch_count">Hitungan peluncur</string> + <string name="sort_mode_install_time">Waktu pemasangan</string> + <string name="home_screen_search_text">Bar pencarian</string> + <string name="larger_icons_text">Ikon lebih besar</string> + <string name="icon_labels">Label ikon</string> + <string name="icon_labels_show">Tampilkan</string> + <string name="icon_labels_hide">Sembunyikan</string> + <string name="protected_app_settings">Aplikasi yang di lindungi</string> + <string name="search_screen_left_text">Panel pencarian</string> + <string name="search_screen_left_unsupported_toast">Anda harus memiliki apl pencarain yang didukung dan CyanogenMod untuk menggunakan fitur ini.</string> + <string name="dialog_confirm">Konfirmasi</string> </resources> diff --git a/res/values-it/cm_arrays.xml b/res/values-it/cm_arrays.xml index 890b4566a..529ea113b 100644 --- a/res/values-it/cm_arrays.xml +++ b/res/values-it/cm_arrays.xml @@ -16,15 +16,10 @@ limitations under the License. --> <resources> - <string-array name="preferences_interface_general_icons_text_font_family_entries"> - <item>Regolare</item> - <item>Luminoso</item> - <item>Condensato</item> - </string-array> <string-array name="transition_effect_entries"> <item>Nessuno</item> - <item>Riduci</item> <item>Ingrandisci</item> + <item>Riduci</item> <item>Ruota su</item> <item>Ruota giù</item> <item>Cubo interno</item> diff --git a/res/values-it/cm_strings.xml b/res/values-it/cm_strings.xml index 1b1e072a8..a2dba2e78 100644 --- a/res/values-it/cm_strings.xml +++ b/res/values-it/cm_strings.xml @@ -16,49 +16,37 @@ limitations under the License. --> <resources> - <string name="application_copyright">Copyright \u00A9 2014 The CyanogenMod Project</string> - <string name="sort_button_text">Ordina</string> - <string name="filter_button_text">Filtro</string> - <string name="default_screen_button_text">Schermata predefinita</string> - <string name="transition_effect_button_text">Effetto scorrimento</string> - <string name="sort_mode_title">Titolo</string> - <string name="sort_mode_launch_count">Numero avvii</string> - <string name="sort_mode_install_time">Tempo installazione</string> + <string name="launcher_settings">IMPOSTAZIONI LAUNCHER</string> + <string name="home_screen_settings">IMPOSTAZIONI SCHERMATA HOME</string> + <string name="drawer_settings">IMPOSTAZIONI DRAWER</string> + <string name="app_settings">IMPOSTAZIONI APP</string> + <string name="setting_state_on">ON</string> + <string name="setting_state_off">OFF</string> + <string name="themes_button_text">Temi</string> <string name="scrolling_page_outlines">Contorni pagina</string> <string name="scrolling_fade_adjacent">Dissolvenza pagine laterali</string> - <string name="wallpaper_scroll">Scorrimento wallpaper</string> - <string name="preferences_title">Impostazioni</string> - <string name="preferences_application_title">App</string> - <string name="preferences_interface_homescreen_title">Schermata Home</string> - <string name="preferences_interface_homescreen_search_title">Barra di ricerca</string> - <string name="preferences_interface_homescreen_search_summary">Mostra la barra di ricerca persistente nella parte superiore dello schermo</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_title">Nascondi etichette icone</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">Nascondi le etichette delle icone sulla schermata Home</string> - <string name="preferences_interface_drawer_title">Drawer</string> - <string name="preferences_interface_drawer_summary">Drawer app e widget</string> - <string name="preferences_interface_drawer_apps_category">App</string> - <string name="preferences_interface_drawer_hidden_apps_title">App nascoste</string> - <string name="preferences_interface_drawer_hidden_apps_summary">Nascondi le app dal drawer</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">Rimuovi scorciatoie</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">Rimuovi le scorciatoie delle app nascoste dalla schermata Home</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_title">Rimuovi widget</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_summary">Rimuovi i widget delle app nascoste dalla schermata Home</string> - <string name="preferences_interface_drawer_hide_icon_labels_title">Nascondi etichette icone</string> - <string name="preferences_interface_drawer_hide_icon_labels_summary">Nascondi le etichette delle icone nel drawer</string> - <string name="preferences_interface_dock_title">Dock</string> - <string name="preferences_interface_general_title">Generale</string> - <string name="preferences_interface_general_icons_category">Icone</string> - <string name="preferences_interface_general_icons_large_title">Icone grandi</string> - <string name="preferences_interface_general_icons_large_summary">Usa le icone grandi delle app nella schermata Home e nel drawer</string> - <string name="preferences_interface_general_icons_text_style_title">Stile caratteri testo</string> - <string name="preferences_interface_general_icons_text_style_summary">Varianti e stile dei caratteri per il testo dell\'icona</string> - <string name="dialog_pick_iconpack_title">Scegli pacchetto icone</string> - <string name="default_iconpack_title">Icone predefinite</string> - <string name="icon_packs_title">Pacchetti icone</string> - <string name="no_iconpacks_summary">Nessun pacchetto di icone installato</string> - <string name="clear_keyguard_wallpaper">Svuota</string> - <string name="all_apps_cling_cm">Personalizza il drawer</string> - <string name="all_apps_cling_summary">Tocca l\'indicatore della pagina per visualizzare le impostazioni di configurazione aggiuntive</string> - <string name="menu_hidden_apps_delete">Ripristina</string> + <string name="scrolling_wallpaper">Sfondo scorrevole</string> + <string name="grid_size_text">Dimensione griglia</string> + <string name="grid_size_comfortable">Confortevole</string> + <string name="grid_size_cozy">Accogliente</string> + <string name="grid_size_condensed">Condensato</string> + <string name="grid_size_custom">Personalizzata</string> + <string name="preferences_interface_homescreen_custom">Personalizza dimensione</string> + <string name="preferences_interface_homescreen_rows_title">Numero di righe</string> + <string name="preferences_interface_homescreen_columns_title">Numero di colonne</string> <string name="hidden_apps_title">App nascoste</string> + <string name="scroll_effect_text">Effetto scorrimento</string> + <string name="drawer_sorting_text">Modalità ordinamento</string> + <string name="sort_mode_title">Titolo</string> + <string name="sort_mode_launch_count">Numero avvii</string> + <string name="sort_mode_install_time">Tempo installazione</string> + <string name="home_screen_search_text">Barra di ricerca</string> + <string name="larger_icons_text">Icone grandi</string> + <string name="icon_labels">Etichette icone</string> + <string name="icon_labels_show">Visualizza</string> + <string name="icon_labels_hide">Nascondi</string> + <string name="protected_app_settings">App protette</string> + <string name="search_screen_left_text">Pannello ricerca</string> + <string name="search_screen_left_unsupported_toast">È necessario disporre di un app per la ricerca supportata e CyanogenMod per utilizzare questa funzionalità.</string> + <string name="dialog_confirm">Conferma</string> </resources> diff --git a/res/values-iw/cm_arrays.xml b/res/values-iw/cm_arrays.xml index c6d027d04..bc7066482 100644 --- a/res/values-iw/cm_arrays.xml +++ b/res/values-iw/cm_arrays.xml @@ -16,24 +16,19 @@ limitations under the License. --> <resources> - <string-array name="preferences_interface_general_icons_text_font_family_entries"> - <item>רגיל</item> - <item>לבן</item> - <item>מרוכז</item> - </string-array> <string-array name="transition_effect_entries"> <item>ללא</item> <item>התקרבות</item> <item>התרחקות</item> - <item>סובב שמאלה</item> - <item>סובב ימינה</item> - <item>קוביית פנים</item> - <item>קוביית חוץ</item> + <item>סובב למעלה</item> + <item>סובב למטע</item> + <item>קובייה פנימה</item> + <item>קוביה החוצה</item> <item>מחסנית</item> <item>אקורדיון</item> <item>היפוך</item> - <item>גליל פנימי</item> - <item>גליל חיצוני</item> + <item>גליל פנימה</item> + <item>גליל החוצה</item> <item>קרוסלה</item> <item>תקציר</item> </string-array> diff --git a/res/values-iw/cm_strings.xml b/res/values-iw/cm_strings.xml index 05d328735..8bbf211f1 100644 --- a/res/values-iw/cm_strings.xml +++ b/res/values-iw/cm_strings.xml @@ -16,49 +16,37 @@ limitations under the License. --> <resources> - <string name="application_copyright">Copyright \u00A9 2014 The CyanogenMod Project</string> - <string name="sort_button_text">מיין</string> - <string name="filter_button_text">סינון</string> - <string name="default_screen_button_text">מסך ברירת מחדל</string> - <string name="transition_effect_button_text">אפקט גלילה</string> - <string name="sort_mode_title">כותרת</string> - <string name="sort_mode_launch_count">מספר הפעלות</string> - <string name="sort_mode_install_time">זמן התקנה</string> + <string name="launcher_settings">הגדרות מפעיל</string> + <string name="home_screen_settings">הגדרות מסך הבית</string> + <string name="drawer_settings">הגדרות מגירת יישומים</string> + <string name="app_settings">הגדרות יישום</string> + <string name="setting_state_on">מופעל</string> + <string name="setting_state_off">מושבת</string> + <string name="themes_button_text">ערכות עיצוב</string> <string name="scrolling_page_outlines">תיאור דף</string> <string name="scrolling_fade_adjacent">עימום דפים צדדיים</string> - <string name="wallpaper_scroll">גלילת טפט</string> - <string name="preferences_title">העדפות</string> - <string name="preferences_application_title">יישום</string> - <string name="preferences_interface_homescreen_title">מסך הבית</string> - <string name="preferences_interface_homescreen_search_title">סרגל החיפוש</string> - <string name="preferences_interface_homescreen_search_summary">הצג את שורת החיפוש תמיד בחלק העליון של המסך</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_title">הסתר תוויות הסמלים</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">הסתר תוויות הסמלים על מסך הבית</string> - <string name="preferences_interface_drawer_title">מגירה</string> - <string name="preferences_interface_drawer_summary">מגירת הווידג\'טים והיישומים</string> - <string name="preferences_interface_drawer_apps_category">יישומים</string> - <string name="preferences_interface_drawer_hidden_apps_title">יישומים מוסתרים</string> - <string name="preferences_interface_drawer_hidden_apps_summary">הסתר יישומים מהמגירה</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">הסר קיצורי דרך</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">הסר את קיצורי הדרך של היישומים המוסתרים ממסך הבית</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_title">הסר ווידג\'טים</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_summary">הסר את הווידג\'טים של היישומים המוסתרים ממסך הבית</string> - <string name="preferences_interface_drawer_hide_icon_labels_title">הסתר תוויות הסמלים</string> - <string name="preferences_interface_drawer_hide_icon_labels_summary">הסתר תוויות הסמלים במגירה</string> - <string name="preferences_interface_dock_title">עגינה</string> - <string name="preferences_interface_general_title">כללי</string> - <string name="preferences_interface_general_icons_category">סמלים</string> - <string name="preferences_interface_general_icons_large_title">סמלים גדולים יותר</string> - <string name="preferences_interface_general_icons_large_summary">השתמש בצלמיות יישום גדול מאוד במסך הבית ובמגירה</string> - <string name="preferences_interface_general_icons_text_style_title">סגנון הגופן של הטקסט</string> - <string name="preferences_interface_general_icons_text_style_summary">סגנון ועיצוב הגופן עבור טקסט הסמלים</string> - <string name="dialog_pick_iconpack_title">בחר ערכת סמלים</string> - <string name="default_iconpack_title">סמלי ברירת מחדל</string> - <string name="icon_packs_title">אוסף סמלים</string> - <string name="no_iconpacks_summary">לא מותקנות ערכות סמל</string> - <string name="clear_keyguard_wallpaper">נקה</string> - <string name="all_apps_cling_cm">התאמה אישית של מגירת היישומים</string> - <string name="all_apps_cling_summary">הקש על מחוון הדף כדי להציג הגדרות נוספות</string> - <string name="menu_hidden_apps_delete">אפס</string> + <string name="scrolling_wallpaper">גלילת טפט</string> + <string name="grid_size_text">גודל רשת</string> + <string name="grid_size_comfortable">נוח</string> + <string name="grid_size_cozy">נעים</string> + <string name="grid_size_condensed">מרוכז</string> + <string name="grid_size_custom">מותאם אישית</string> + <string name="preferences_interface_homescreen_custom">בחר גודל מותאם אישית</string> + <string name="preferences_interface_homescreen_rows_title">מספר שורות</string> + <string name="preferences_interface_homescreen_columns_title">מספר עמודות</string> <string name="hidden_apps_title">יישומים מוסתרים</string> + <string name="scroll_effect_text">אפקט גלילה</string> + <string name="drawer_sorting_text">מצב המיון</string> + <string name="sort_mode_title">כותרת</string> + <string name="sort_mode_launch_count">מספר הפעלות</string> + <string name="sort_mode_install_time">זמן התקנה</string> + <string name="home_screen_search_text">סרגל החיפוש</string> + <string name="larger_icons_text">סמלים גדולים יותר</string> + <string name="icon_labels">תוויות סמלים</string> + <string name="icon_labels_show">הצג</string> + <string name="icon_labels_hide">הסתר</string> + <string name="protected_app_settings">יישומים מוגנים</string> + <string name="search_screen_left_text">לוח חיפוש</string> + <string name="search_screen_left_unsupported_toast">אתה חייב יישום חיפוש נתמך ו-CyanogenMod כדי להשתמש בתכונה זו.</string> + <string name="dialog_confirm">אשר</string> </resources> diff --git a/res/values-ja/cm_arrays.xml b/res/values-ja/cm_arrays.xml index e78f2b716..b215aa601 100644 --- a/res/values-ja/cm_arrays.xml +++ b/res/values-ja/cm_arrays.xml @@ -16,25 +16,20 @@ limitations under the License. --> <resources> - <string-array name="preferences_interface_general_icons_text_font_family_entries"> - <item>標準</item> - <item>Light</item> - <item>Condensed</item> - </string-array> <string-array name="transition_effect_entries"> <item>なし</item> - <item>ズームイン</item> - <item>ズームアウト</item> - <item>上回転</item> - <item>下回転</item> - <item>キューブイン</item> - <item>キューブアウト</item> - <item>スタック</item> - <item>アコーディオン</item> - <item>フリップ</item> - <item>シリンダーイン</item> - <item>シリンダーアウト</item> - <item>カルーセル</item> - <item>オーバービュー</item> + <item>Zoom in</item> + <item>Zoom out</item> + <item>Rotate up</item> + <item>Rotate down</item> + <item>Cube in</item> + <item>Cube out</item> + <item>Stack</item> + <item>Accordion</item> + <item>Flip</item> + <item>Cylinder in</item> + <item>Cylinder out</item> + <item>Carousel</item> + <item>Overview</item> </string-array> </resources> diff --git a/res/values-ja/cm_strings.xml b/res/values-ja/cm_strings.xml index 3a6bd8644..e127daab2 100644 --- a/res/values-ja/cm_strings.xml +++ b/res/values-ja/cm_strings.xml @@ -16,49 +16,37 @@ limitations under the License. --> <resources> - <string name="application_copyright">Copyright \u00A9 2014 The CyanogenMod Project</string> - <string name="sort_button_text">並べ替え</string> - <string name="filter_button_text">フィルター</string> - <string name="default_screen_button_text">デフォルトの画面</string> - <string name="transition_effect_button_text">スクロール効果</string> - <string name="sort_mode_title">タイトル</string> - <string name="sort_mode_launch_count">起動回数</string> - <string name="sort_mode_install_time">インストール日時</string> + <string name="launcher_settings">ランチャーの設定</string> + <string name="home_screen_settings">ホーム画面の設定</string> + <string name="drawer_settings">ドロワーの設定</string> + <string name="app_settings">アプリの設定</string> + <string name="setting_state_on">ON</string> + <string name="setting_state_off">OFF</string> + <string name="themes_button_text">テーマ</string> <string name="scrolling_page_outlines">ページの外枠を表示</string> <string name="scrolling_fade_adjacent">側面のページをフェード</string> - <string name="wallpaper_scroll">壁紙をスクロール</string> - <string name="preferences_title">設定</string> - <string name="preferences_application_title">アプリ</string> - <string name="preferences_interface_homescreen_title">ホーム画面</string> - <string name="preferences_interface_homescreen_search_title">検索バー</string> - <string name="preferences_interface_homescreen_search_summary">画面の上部に検索バーを常に表示する</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_title">アイコンラベルを非表示にする</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">ホーム画面でアイコンラベルを非表示にする</string> - <string name="preferences_interface_drawer_title">ドロワー</string> - <string name="preferences_interface_drawer_summary">アプリとウィジェットのドロワー</string> - <string name="preferences_interface_drawer_apps_category">アプリ</string> - <string name="preferences_interface_drawer_hidden_apps_title">非表示にするアプリ</string> - <string name="preferences_interface_drawer_hidden_apps_summary">ドロワーからアプリを非表示にする</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">ショートカットを削除</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">ホーム画面から非表示にしたアプリのショートカットを削除する</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_title">ウィジェットを削除</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_summary">ホーム画面から非表示にしたアプリのウィジェットを削除する</string> - <string name="preferences_interface_drawer_hide_icon_labels_title">アイコンラベルを非表示にする</string> - <string name="preferences_interface_drawer_hide_icon_labels_summary">ドロワーでアイコンラベルを非表示にする</string> - <string name="preferences_interface_dock_title">ドック</string> - <string name="preferences_interface_general_title">全般</string> - <string name="preferences_interface_general_icons_category">アイコン</string> - <string name="preferences_interface_general_icons_large_title">大きいアイコン</string> - <string name="preferences_interface_general_icons_large_summary">ホーム画面とドロワーで大きいアイコンを使用する</string> - <string name="preferences_interface_general_icons_text_style_title">テキストのフォントスタイル</string> - <string name="preferences_interface_general_icons_text_style_summary">アイコンテキストに使用するフォントスタイルと種類</string> - <string name="dialog_pick_iconpack_title">アイコンパックを選択</string> - <string name="default_iconpack_title">デフォルトのアイコン</string> - <string name="icon_packs_title">アイコンパック</string> - <string name="no_iconpacks_summary">アイコンパックがインストールされていません</string> - <string name="clear_keyguard_wallpaper">クリア</string> - <string name="all_apps_cling_cm">ドロワーをカスタマイズ</string> - <string name="all_apps_cling_summary">追加の構成設定を表示するには、ページインジケータをタップします。</string> - <string name="menu_hidden_apps_delete">リセット</string> + <string name="scrolling_wallpaper">壁紙のスクロール</string> + <string name="grid_size_text">グリッドサイズ</string> + <string name="grid_size_comfortable">Comfortable</string> + <string name="grid_size_cozy">Cozy</string> + <string name="grid_size_condensed">Condensed</string> + <string name="grid_size_custom">カスタム</string> + <string name="preferences_interface_homescreen_custom">カスタムのサイズを選択</string> + <string name="preferences_interface_homescreen_rows_title">行数</string> + <string name="preferences_interface_homescreen_columns_title">列数</string> <string name="hidden_apps_title">非表示にするアプリ</string> + <string name="scroll_effect_text">スクロール効果</string> + <string name="drawer_sorting_text">並べ替えモード</string> + <string name="sort_mode_title">タイトル</string> + <string name="sort_mode_launch_count">起動回数</string> + <string name="sort_mode_install_time">インストール日時</string> + <string name="home_screen_search_text">検索バー</string> + <string name="larger_icons_text">大きいアイコン</string> + <string name="icon_labels">アイコンラベル</string> + <string name="icon_labels_show">表示</string> + <string name="icon_labels_hide">非表示</string> + <string name="protected_app_settings">アプリの保護</string> + <string name="search_screen_left_text">検索パネル</string> + <string name="search_screen_left_unsupported_toast">この機能を利用するには、サポートされている検索アプリとCyanogenModが必要です。</string> + <string name="dialog_confirm">確認</string> </resources> diff --git a/res/values-ku/cm_arrays.xml b/res/values-ku/cm_arrays.xml new file mode 100644 index 000000000..6770e6dc4 --- /dev/null +++ b/res/values-ku/cm_arrays.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="utf-8"?> +<!--Generated by crowdin.net--> +<!-- + Copyright (C) 2014 The CyanogenMod 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. +--> +<resources> + <string-array name="transition_effect_entries"> + <item>هیچ</item> + <item>زومکردن بۆ ناو</item> + <item>زومکردن بۆ دەرەوە</item> + <item>سوڕانەوە بۆ سەرەوە</item> + <item>سوڕانەوە بۆ خوارەوە</item> + <item>شەشپاڵو بۆ ناو</item> + <item>شەشپاڵو دەرەوە</item> + <item>كەتەكە</item> + <item>ئۆكۆردێون</item> + <item>قاتکردن</item> + <item>لولەک لەناو</item> + <item>لولەک بۆ دەرەوە</item> + <item>غارغارێن</item> + <item>پیشاندانی گشتی</item> + </string-array> +</resources> diff --git a/res/values-ku/cm_strings.xml b/res/values-ku/cm_strings.xml new file mode 100644 index 000000000..449353f02 --- /dev/null +++ b/res/values-ku/cm_strings.xml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="utf-8"?> +<!--Generated by crowdin.net--> +<!-- + Copyright (C) 2014 The CyanogenMod 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. +--> +<resources> + <string name="home_screen_settings">رێکخستنی شاشەی سەرەکی</string> + <string name="setting_state_on">هەڵگیرساو</string> + <string name="setting_state_off">کووژاوە</string> + <string name="themes_button_text">رووکارەکان</string> + <string name="grid_size_custom">دروستکراو</string> + <string name="hidden_apps_title">شاردنەوەی بەرنامەکان</string> + <string name="drawer_sorting_text">جۆری پۆڵێنکردن</string> + <string name="sort_mode_title">ناونیشان</string> + <string name="sort_mode_launch_count">دانانی ههژمار</string> + <string name="sort_mode_install_time">کاتی دامەزراندن</string> + <string name="home_screen_search_text">شریتی گەڕان</string> + <string name="larger_icons_text">وێنۆچکەی گەورەتر</string> + <string name="icon_labels_show">پیشاندان</string> + <string name="icon_labels_hide">شاردنەوە</string> + <string name="protected_app_settings">بەرنامە پارێزراوەکان</string> + <string name="search_screen_left_text">پەرەی گەران</string> + <string name="dialog_confirm">دلنیاکردنەوە</string> +</resources> diff --git a/res/values-land/config.xml b/res/values-land/config.xml index 121bb0c14..31115c9cb 100644 --- a/res/values-land/config.xml +++ b/res/values-land/config.xml @@ -18,6 +18,4 @@ <!-- Workspace --> <!-- Whether or not the drop targets drop down as opposed to fade in --> <bool name="config_useDropTargetDownTransition">false</bool> - <!-- Whether or not to fade the side pages --> - <bool name="config_workspaceFadeAdjacentScreens">false</bool> </resources> diff --git a/res/values-land/dimens.xml b/res/values-land/dimens.xml index 5961b1936..07d92798d 100644 --- a/res/values-land/dimens.xml +++ b/res/values-land/dimens.xml @@ -19,11 +19,6 @@ <dimen name="toolbar_button_vertical_padding">8dip</dimen> <dimen name="toolbar_button_horizontal_padding">0dip</dimen> -<!-- Workspace --> - <!-- We really want the page spacing to be the max of either the button bar - height or the qsb bar height --> - <dimen name="workspace_page_spacing">-1dp</dimen> - <!-- AppsCustomize --> <dimen name="apps_customize_tab_bar_height">42dp</dimen> <integer name="apps_customize_widget_cell_count_x">3</integer> diff --git a/res/values-land/styles.xml b/res/values-land/styles.xml index ccb5fcb06..87a744455 100644 --- a/res/values-land/styles.xml +++ b/res/values-land/styles.xml @@ -19,15 +19,11 @@ <resources> <!-- Search Bar --> - <style name="QSBBar"> - </style> - <style name="SearchDropTargetBar"> - </style> <style name="SearchButton"> </style> <style name="DropTargetButtonContainer"> <item name="android:layout_width">match_parent</item> - <item name="android:layout_height">0dp</item> + <item name="android:layout_height">wrap_content</item> </style> <style name="DropTargetButton"> <item name="android:layout_width">wrap_content</item> @@ -36,8 +32,8 @@ <item name="android:gravity">center</item> <item name="android:paddingTop">@dimen/toolbar_button_vertical_padding</item> <item name="android:paddingBottom">@dimen/toolbar_button_vertical_padding</item> - <item name="android:paddingStart">@dimen/toolbar_button_horizontal_padding</item> - <item name="android:paddingEnd">@dimen/toolbar_button_horizontal_padding</item> + <item name="android:paddingLeft">@dimen/toolbar_button_horizontal_padding</item> + <item name="android:paddingRight">@dimen/toolbar_button_horizontal_padding</item> <item name="android:shadowColor">#DD000000</item> <item name="android:shadowDx">0.0</item> <item name="android:shadowDy">1.0</item> diff --git a/res/values-lb/cm_arrays.xml b/res/values-lb/cm_arrays.xml index 6074c5ac9..5c2e3c8a4 100644 --- a/res/values-lb/cm_arrays.xml +++ b/res/values-lb/cm_arrays.xml @@ -16,24 +16,19 @@ limitations under the License. --> <resources> - <string-array name="preferences_interface_general_icons_text_font_family_entries"> - <item>Normal</item> - <item>Dënn</item> - <item>Schmuel</item> - </string-array> <string-array name="transition_effect_entries"> <item>Keen</item> - <item>Erazoomen</item> - <item>Erauszoomen</item> - <item>Eroprotéieren</item> - <item>Erofrotéieren</item> - <item>Wierfel bannen</item> - <item>Wierfel baussen</item> + <item>Zoom in</item> + <item>Zoom out</item> + <item>Rotate up</item> + <item>Rotate down</item> + <item>Cube in</item> + <item>Cube out</item> <item>Koup</item> <item>Akkordeon</item> <item>Ëmdréinen</item> - <item>Zylinder bannen</item> - <item>Zylinder baussen</item> + <item>Cylinder in</item> + <item>Cylinder out</item> <item>Karussell</item> <item>Iwwersiicht</item> </string-array> diff --git a/res/values-lb/cm_strings.xml b/res/values-lb/cm_strings.xml index 19a760f55..7c98f88d1 100644 --- a/res/values-lb/cm_strings.xml +++ b/res/values-lb/cm_strings.xml @@ -16,38 +16,10 @@ limitations under the License. --> <resources> - <string name="application_copyright">Copyright \u00A9 2014 The CyanogenMod Project</string> - <string name="sort_button_text">Zortéieren</string> - <string name="filter_button_text">Filteren</string> - <string name="default_screen_button_text">Standardsäit</string> - <string name="transition_effect_button_text">Scrolleffekt</string> + <string name="setting_state_on">UN</string> + <string name="scrolling_page_outlines">Säiterummen</string> + <string name="scrolling_fade_adjacent">Säiten um Rand ausblenden</string> <string name="sort_mode_title">Titel</string> <string name="sort_mode_launch_count">Startunzuel</string> <string name="sort_mode_install_time">Installatiounszäit</string> - <string name="scrolling_page_outlines">Säiterummen</string> - <string name="scrolling_fade_adjacent">Säiten um Rand ausblenden</string> - <string name="wallpaper_scroll">Hannergrondbild scrollen</string> - <string name="preferences_title">Astellungen</string> - <string name="preferences_application_title">App</string> - <string name="preferences_interface_homescreen_title">Startschierm</string> - <string name="preferences_interface_homescreen_search_title">Sichkëscht</string> - <string name="preferences_interface_homescreen_search_summary">D\'Sichfeld um ieweschte Bord vum Schierm ëmmer uweisen</string> - <string name="preferences_interface_drawer_title">App-Iwwersiicht</string> - <string name="preferences_interface_drawer_apps_category">Apps</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">Ofkierzungen ewechhuelen</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_title">Widgets ewechhuelen</string> - <string name="preferences_interface_dock_title">Dock</string> - <string name="preferences_interface_general_title">Allgemeng</string> - <string name="preferences_interface_general_icons_category">Symboler</string> - <string name="preferences_interface_general_icons_large_title">Grouss Symboler</string> - <string name="preferences_interface_general_icons_large_summary">Grouss Symboler fir d\'Apps um Startschierm a bei der App-Iwwersiicht benotzen</string> - <string name="preferences_interface_general_icons_text_style_title">Schrëftstil</string> - <string name="preferences_interface_general_icons_text_style_summary">Schrëftaart a -stil vum Text ënner de Symboler</string> - <string name="dialog_pick_iconpack_title">Symbolpak auswielen</string> - <string name="default_iconpack_title">Standardsymboler</string> - <string name="icon_packs_title">Symbolpäck</string> - <string name="no_iconpacks_summary">Keng Symbolpäck installéiert</string> - <string name="all_apps_cling_cm">App-Iwwersiicht konfiguréieren</string> - <string name="all_apps_cling_summary">Dréck de Säitenindikator fir zousätzlech Astellungen ze gesinn</string> - <string name="menu_hidden_apps_delete">Zrécksetzen</string> </resources> diff --git a/res/values-lt/cm_arrays.xml b/res/values-lt/cm_arrays.xml index 47465cbdc..83b8e4562 100644 --- a/res/values-lt/cm_arrays.xml +++ b/res/values-lt/cm_arrays.xml @@ -16,11 +16,6 @@ limitations under the License. --> <resources> - <string-array name="preferences_interface_general_icons_text_font_family_entries"> - <item>Įprastas</item> - <item>Plonas</item> - <item>Suglaustas</item> - </string-array> <string-array name="transition_effect_entries"> <item>Joks</item> <item>Padidinti</item> diff --git a/res/values-lt/cm_strings.xml b/res/values-lt/cm_strings.xml index 116b19e46..271c9a6da 100644 --- a/res/values-lt/cm_strings.xml +++ b/res/values-lt/cm_strings.xml @@ -16,49 +16,37 @@ limitations under the License. --> <resources> - <string name="application_copyright">Autorinės teisės \u00A9 2014 „CyanogenMod“ projektas</string> - <string name="sort_button_text">Rūšiuoti</string> - <string name="filter_button_text">Filtras</string> - <string name="default_screen_button_text">Numatytasis ekranas</string> - <string name="transition_effect_button_text">Slinkimo efektas</string> + <string name="launcher_settings">PALEIDĖJO NUSTATYMAI</string> + <string name="home_screen_settings">PAGRINDINIO EKRANO NUSTATYMAI</string> + <string name="drawer_settings">STALČIAUS NUSTATYMAI</string> + <string name="app_settings">PROGRAMOS NUSTATYMAI</string> + <string name="setting_state_on">ĮJUNGTA</string> + <string name="setting_state_off">IŠJUNGTA</string> + <string name="themes_button_text">Temos</string> + <string name="scrolling_page_outlines">Puslapio kontūrai</string> + <string name="scrolling_fade_adjacent">Išblukinti šoninius puslapius</string> + <string name="scrolling_wallpaper">Slinkti darbalaukio foną</string> + <string name="grid_size_text">Tinklelio dydis</string> + <string name="grid_size_comfortable">Patogus</string> + <string name="grid_size_cozy">Jaukus</string> + <string name="grid_size_condensed">Suglaustas</string> + <string name="grid_size_custom">Individualus</string> + <string name="preferences_interface_homescreen_custom">Pasirinkite individualų dydį</string> + <string name="preferences_interface_homescreen_rows_title">Eilučių skaičius</string> + <string name="preferences_interface_homescreen_columns_title">Stulpelių skaičius</string> + <string name="hidden_apps_title">Paslėptos programos</string> + <string name="scroll_effect_text">Slinkimo efektas</string> + <string name="drawer_sorting_text">Rūšiavimo režimas</string> <string name="sort_mode_title">Pavadinimas</string> <string name="sort_mode_launch_count">Paleidimų kiekis</string> <string name="sort_mode_install_time">Įdiegimo laikas</string> - <string name="scrolling_page_outlines">Puslapio kontūrai</string> - <string name="scrolling_fade_adjacent">Išblukinti šoninius ekranus</string> - <string name="wallpaper_scroll">Slinkti ekrano foną</string> - <string name="preferences_title">Nustatymai</string> - <string name="preferences_application_title">Programa</string> - <string name="preferences_interface_homescreen_title">Pagrindinis ekranas</string> - <string name="preferences_interface_homescreen_search_title">Paieškos juosta</string> - <string name="preferences_interface_homescreen_search_summary">Rodyti nuolatinę paieškos juostą ekrano viršuje</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_title">Paslėpti piktogramų pavadinimus</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">Paslėpti piktogramų pavadinimus pagrindiniame ekrane</string> - <string name="preferences_interface_drawer_title">Stalčius</string> - <string name="preferences_interface_drawer_summary">Programų ir valdiklių stalčius</string> - <string name="preferences_interface_drawer_apps_category">Programos</string> - <string name="preferences_interface_drawer_hidden_apps_title">Paslėptos programos</string> - <string name="preferences_interface_drawer_hidden_apps_summary">Paslėpti programas iš stalčiaus</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">Pašalinti nuorodas</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">Pašalinti paslėptų programų nuorodas iš pagrindinio ekrano</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_title">Pašalinti valdiklius</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_summary">Pašalinti paslėptų programų valdiklius iš pagrindinio ekrano</string> - <string name="preferences_interface_drawer_hide_icon_labels_title">Paslėpti piktogramų pavadinimus</string> - <string name="preferences_interface_drawer_hide_icon_labels_summary">Paslėpti piktogramų pavadinimus iš stalčiaus</string> - <string name="preferences_interface_dock_title">Dokas</string> - <string name="preferences_interface_general_title">Bendra</string> - <string name="preferences_interface_general_icons_category">Piktogramos</string> - <string name="preferences_interface_general_icons_large_title">Didesnės piktogramos</string> - <string name="preferences_interface_general_icons_large_summary">Naudoti didesnes programų piktogramas pagrindiniame ekrane ir stalčiuje</string> - <string name="preferences_interface_general_icons_text_style_title">Teksto šrifto stilius</string> - <string name="preferences_interface_general_icons_text_style_summary">Piktogramos teksto šrifto variantas ir stilius</string> - <string name="dialog_pick_iconpack_title">Pasirinkti piktogramų paketą</string> - <string name="default_iconpack_title">Numatytosios piktogramos</string> - <string name="icon_packs_title">Piktogramų paketai</string> - <string name="no_iconpacks_summary">Piktogramų paketai neįdiegti</string> - <string name="clear_keyguard_wallpaper">Išvalyti</string> - <string name="all_apps_cling_cm">Tinkinti savo stalčių</string> - <string name="all_apps_cling_summary">Bakstelėkite puslapio indikatorių norėdami peržiūrėti papildomus konfigūracijos nustatymus</string> - <string name="menu_hidden_apps_delete">Atkurti</string> - <string name="hidden_apps_title">Paslėptos programos</string> + <string name="home_screen_search_text">Paieškos juosta</string> + <string name="larger_icons_text">Didesnės piktogramos</string> + <string name="icon_labels">Piktogramų pavadinimai</string> + <string name="icon_labels_show">Rodyti</string> + <string name="icon_labels_hide">Paslėpti</string> + <string name="protected_app_settings">Apsaugotos programos</string> + <string name="search_screen_left_text">Paieškos panėlė</string> + <string name="search_screen_left_unsupported_toast">Jūs privalote turėti palaikomą paieškos programą ir „CyanogenMod“ norėdami naudotis šia funkcija.</string> + <string name="dialog_confirm">Patvirtinti</string> </resources> diff --git a/res/values-nb/cm_arrays.xml b/res/values-nb/cm_arrays.xml index ffec66d24..55f4e24f4 100644 --- a/res/values-nb/cm_arrays.xml +++ b/res/values-nb/cm_arrays.xml @@ -16,11 +16,6 @@ limitations under the License. --> <resources> - <string-array name="preferences_interface_general_icons_text_font_family_entries"> - <item>Vanlig</item> - <item>Lys</item> - <item>Kondensert</item> - </string-array> <string-array name="transition_effect_entries"> <item>Ingen</item> <item>Zoome inn</item> diff --git a/res/values-nb/cm_strings.xml b/res/values-nb/cm_strings.xml index ed18d7186..7078b4992 100644 --- a/res/values-nb/cm_strings.xml +++ b/res/values-nb/cm_strings.xml @@ -16,49 +16,37 @@ limitations under the License. --> <resources> - <string name="application_copyright">Copyright \u00A9 2014 The CyanogenMod Project</string> - <string name="sort_button_text">Sorter</string> - <string name="filter_button_text">Filter</string> - <string name="default_screen_button_text">Standardskjermbildet</string> - <string name="transition_effect_button_text">Bla effekt</string> - <string name="sort_mode_title">Tittel</string> - <string name="sort_mode_launch_count">Start teller</string> - <string name="sort_mode_install_time">Installeringstid</string> + <string name="launcher_settings">LAUNCHER INNSTILLINGER</string> + <string name="home_screen_settings">HJEMMESKJERM INNSTILLINGER</string> + <string name="drawer_settings">SKUFF INNSTILLINGER</string> + <string name="app_settings">APP-INNSTILLINGER</string> + <string name="setting_state_on">PÅ</string> + <string name="setting_state_off">AV</string> + <string name="themes_button_text">Temaer</string> <string name="scrolling_page_outlines">Skjermkontur</string> <string name="scrolling_fade_adjacent">Fade skjermsider</string> - <string name="wallpaper_scroll">Bla bakgrunn</string> - <string name="preferences_title">Innstillinger</string> - <string name="preferences_application_title">App</string> - <string name="preferences_interface_homescreen_title">Hjemmeskjerm</string> - <string name="preferences_interface_homescreen_search_title">Søkefeltet</string> - <string name="preferences_interface_homescreen_search_summary">Vis vedvarende søkefeltet øverst på skjermen</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_title">Skjule ikonetiketter</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">Skjule ikonetiketter på hjemmeskjerm</string> - <string name="preferences_interface_drawer_title">Skuff</string> - <string name="preferences_interface_drawer_summary">Programmer og widgets skuff</string> - <string name="preferences_interface_drawer_apps_category">Apps</string> - <string name="preferences_interface_drawer_hidden_apps_title">Skjulte programmer</string> - <string name="preferences_interface_drawer_hidden_apps_summary">Skjul apps fra skuffen</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">Fjern snarveier</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">Fjerne snarveier til skjulte programmer fra hjemmeskjerm</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_title">Fjern widgets</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_summary">Fjerne widgeter av skjulte programmer fra hjemmeskjerm</string> - <string name="preferences_interface_drawer_hide_icon_labels_title">Skjul ikonetiketter</string> - <string name="preferences_interface_drawer_hide_icon_labels_summary">Skjul ikonetiketter i skuffen</string> - <string name="preferences_interface_dock_title">Dock</string> - <string name="preferences_interface_general_title">Generelt</string> - <string name="preferences_interface_general_icons_category">Ikoner</string> - <string name="preferences_interface_general_icons_large_title">Større ikoner</string> - <string name="preferences_interface_general_icons_large_summary">Bruk ekstra store programikoner på hjemmeskjerm og skuff</string> - <string name="preferences_interface_general_icons_text_style_title">Skrifttype</string> - <string name="preferences_interface_general_icons_text_style_summary">Variant og stil på skrift brukt til ikon tekst</string> - <string name="dialog_pick_iconpack_title">Velg ikon pakke</string> - <string name="default_iconpack_title">Standardikoner</string> - <string name="icon_packs_title">Symbol-pakker</string> - <string name="no_iconpacks_summary">Ingen ikon pakker installert</string> - <string name="clear_keyguard_wallpaper">Fjern</string> - <string name="all_apps_cling_cm">Tilpasse din skuff</string> - <string name="all_apps_cling_summary">Trykk på sideindikatoren for å vise flere konfigurasjonsinnstillinger</string> - <string name="menu_hidden_apps_delete">Tilbakestille</string> + <string name="scrolling_wallpaper">Scroll bakgrunn</string> + <string name="grid_size_text">Rutenettstørrelse</string> + <string name="grid_size_comfortable">Komfortabel</string> + <string name="grid_size_cozy">Koselig</string> + <string name="grid_size_condensed">Kondensert</string> + <string name="grid_size_custom">Egendefinert</string> + <string name="preferences_interface_homescreen_custom">Velg egendefinert størrelse</string> + <string name="preferences_interface_homescreen_rows_title">Antall rader</string> + <string name="preferences_interface_homescreen_columns_title">Antall kolonner</string> <string name="hidden_apps_title">Skjulte programmer</string> + <string name="scroll_effect_text">Bla effekt</string> + <string name="drawer_sorting_text">Sorteringsmodus</string> + <string name="sort_mode_title">Tittel</string> + <string name="sort_mode_launch_count">Start teller</string> + <string name="sort_mode_install_time">Installeringstid</string> + <string name="home_screen_search_text">Søkefelt</string> + <string name="larger_icons_text">Større ikoner</string> + <string name="icon_labels">Ikonetiketter</string> + <string name="icon_labels_show">Vis</string> + <string name="icon_labels_hide">Skjul</string> + <string name="protected_app_settings">Beskyttede apps</string> + <string name="search_screen_left_text">Søke-panelet</string> + <string name="search_screen_left_unsupported_toast">Du må ha en støttet søke app og CyanogenMod for å bruke denne funksjonen.</string> + <string name="dialog_confirm">Bekreft</string> </resources> diff --git a/res/values-nl/cm_arrays.xml b/res/values-nl/cm_arrays.xml index 9c2a4e878..55de714b7 100644 --- a/res/values-nl/cm_arrays.xml +++ b/res/values-nl/cm_arrays.xml @@ -16,11 +16,6 @@ limitations under the License. --> <resources> - <string-array name="preferences_interface_general_icons_text_font_family_entries"> - <item>Standaard</item> - <item>Licht</item> - <item>Smal</item> - </string-array> <string-array name="transition_effect_entries"> <item>Geen</item> <item>Inzoomen</item> diff --git a/res/values-nl/cm_strings.xml b/res/values-nl/cm_strings.xml index bf5021141..cdf3e7e4e 100644 --- a/res/values-nl/cm_strings.xml +++ b/res/values-nl/cm_strings.xml @@ -16,49 +16,37 @@ limitations under the License. --> <resources> - <string name="application_copyright">Copyright \u00A9 2014 The CyanogenMod Project</string> - <string name="sort_button_text">Sorteren</string> - <string name="filter_button_text">Filteren</string> - <string name="default_screen_button_text">Standaard\nscherm</string> - <string name="transition_effect_button_text">Overgangs\neffect</string> - <string name="sort_mode_title">Titel</string> - <string name="sort_mode_launch_count">Aantal starts</string> - <string name="sort_mode_install_time">Tijd van installatie</string> + <string name="launcher_settings">INSTELLINGEN STARTPAGINA</string> + <string name="home_screen_settings">INSTELLINGEN THUISSCHERM</string> + <string name="drawer_settings">INSTELLINGEN OVERZICHT</string> + <string name="app_settings">INSTELLINGEN APPS</string> + <string name="setting_state_on">AAN</string> + <string name="setting_state_off">UIT</string> + <string name="themes_button_text">Thema\'s</string> <string name="scrolling_page_outlines">Paginacontouren</string> <string name="scrolling_fade_adjacent">Zijkant pagina\'s vervagen</string> - <string name="wallpaper_scroll">Achtergrond schuiven</string> - <string name="preferences_title">Instellingen</string> - <string name="preferences_application_title">App</string> - <string name="preferences_interface_homescreen_title">Startscherm</string> - <string name="preferences_interface_homescreen_search_title">Zoekbalk</string> - <string name="preferences_interface_homescreen_search_summary">Zoekbalk permanent tonen bovenaan het scherm</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_title">Labels verbergen</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">Labels verbergen onder pictogrammen op het startscherm</string> - <string name="preferences_interface_drawer_title">Overzicht</string> - <string name="preferences_interface_drawer_summary">App- en widgetoverzicht</string> - <string name="preferences_interface_drawer_apps_category">Apps</string> - <string name="preferences_interface_drawer_hidden_apps_title">Verborgen apps</string> - <string name="preferences_interface_drawer_hidden_apps_summary">Apps verbergen in het app-overzicht</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">Snelkoppelingen verbergen</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">Snelkoppelingen van verborgen apps niet weergeven op startscherm</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_title">Widgets verbergen</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_summary">Widgets van verborgen apps niet weergeven op startscherm</string> - <string name="preferences_interface_drawer_hide_icon_labels_title">Labels verbergen</string> - <string name="preferences_interface_drawer_hide_icon_labels_summary">Labels verbergen onder pictogrammen in het appoverzicht</string> - <string name="preferences_interface_dock_title">Dock</string> - <string name="preferences_interface_general_title">Algemeen</string> - <string name="preferences_interface_general_icons_category">Pictogrammen</string> - <string name="preferences_interface_general_icons_large_title">Grote pictogrammen</string> - <string name="preferences_interface_general_icons_large_summary">Extra grote pictogrammen gebruiken voor apps op het startscherm en in het overzicht</string> - <string name="preferences_interface_general_icons_text_style_title">Lettertypestijl</string> - <string name="preferences_interface_general_icons_text_style_summary">Stijl van tekst bij pictogrammen</string> - <string name="dialog_pick_iconpack_title">Pictogrampakket kiezen</string> - <string name="default_iconpack_title">Standaard</string> - <string name="icon_packs_title">Pictogram\npakket</string> - <string name="no_iconpacks_summary">Geen pictogrampakketten geïnstalleerd</string> - <string name="clear_keyguard_wallpaper">Verwijderen</string> - <string name="all_apps_cling_cm">App-overzicht aanpassen</string> - <string name="all_apps_cling_summary">Tik op de pagina-indicator voor extra instellingen</string> - <string name="menu_hidden_apps_delete">Opnieuw instellen</string> + <string name="scrolling_wallpaper">Achtergrond schuiven</string> + <string name="grid_size_text">Rastergrootte</string> + <string name="grid_size_comfortable">Comfortabel</string> + <string name="grid_size_cozy">Knus</string> + <string name="grid_size_condensed">Smal</string> + <string name="grid_size_custom">Aangepast</string> + <string name="preferences_interface_homescreen_custom">Aangepaste grootte</string> + <string name="preferences_interface_homescreen_rows_title">Aantal rijen</string> + <string name="preferences_interface_homescreen_columns_title">Aantal kolommen</string> <string name="hidden_apps_title">Verborgen apps</string> + <string name="scroll_effect_text">Overgangseffect</string> + <string name="drawer_sorting_text">Sorteren op</string> + <string name="sort_mode_title">Titel</string> + <string name="sort_mode_launch_count">Aantal starts</string> + <string name="sort_mode_install_time">Tijd van installatie</string> + <string name="home_screen_search_text">Zoekbalk</string> + <string name="larger_icons_text">Grote pictogrammen</string> + <string name="icon_labels">Pictogramlabels</string> + <string name="icon_labels_show">Aan</string> + <string name="icon_labels_hide">Uit</string> + <string name="protected_app_settings">Beschermde apps</string> + <string name="search_screen_left_text">Zoekscherm</string> + <string name="search_screen_left_unsupported_toast">Een ondersteunde zoek-app en CyanogenMod zijn vereist om deze functie te gebruiken.</string> + <string name="dialog_confirm">Bevestig</string> </resources> diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml index e2a2a0719..3cae98a9d 100644 --- a/res/values-nl/strings.xml +++ b/res/values-nl/strings.xml @@ -119,6 +119,6 @@ <string name="custom_workspace_cling_title_2" msgid="662588444436552198"></string> <string name="custom_workspace_cling_description_2" msgid="8097921091798539310"></string> <string name="widget_button_text" msgid="2880537293434387943">"Widgets"</string> - <string name="wallpaper_button_text" msgid="8404103075899945851">"Achtergronden"</string> + <string name="wallpaper_button_text" msgid="8404103075899945851">"Achtergrond"</string> <string name="settings_button_text" msgid="8119458837558863227">"Instellingen"</string> </resources> diff --git a/res/values-pl/cm_arrays.xml b/res/values-pl/cm_arrays.xml index c5e7253ab..4d6e4626c 100644 --- a/res/values-pl/cm_arrays.xml +++ b/res/values-pl/cm_arrays.xml @@ -16,24 +16,19 @@ limitations under the License. --> <resources> - <string-array name="preferences_interface_general_icons_text_font_family_entries"> - <item>Regularny</item> - <item>Lekki</item> - <item>Skondensowany</item> - </string-array> <string-array name="transition_effect_entries"> <item>Brak</item> - <item>Przybliżenie</item> - <item>Oddalenie</item> - <item>Obrót w górę</item> + <item>Zbliżanie</item> + <item>Oddalanie</item> + <item>Obrót do góry</item> <item>Obrót w dół</item> - <item>Kostka do wewnątrz</item> - <item>Kostka do zewnątrz</item> + <item>Kostka (w środku)</item> + <item>Kostka (na zewnątrz)</item> <item>Stos</item> <item>Akordeon</item> <item>Obrót</item> - <item>Cylinder do wewnątrz</item> - <item>Cylinder do zewnątrz</item> + <item>Cylinder (w środku)</item> + <item>Cylinder (na zewnątrz)</item> <item>Karuzela</item> <item>Przegląd</item> </string-array> diff --git a/res/values-pl/cm_strings.xml b/res/values-pl/cm_strings.xml index 6bf22dc0f..31541d7a7 100644 --- a/res/values-pl/cm_strings.xml +++ b/res/values-pl/cm_strings.xml @@ -16,49 +16,37 @@ limitations under the License. --> <resources> - <string name="application_copyright">Copyright \u00A9 2014 The CyanogenMod Project</string> - <string name="sort_button_text">Sortowanie</string> - <string name="filter_button_text">Filtruj</string> - <string name="default_screen_button_text">Ekran domyślny</string> - <string name="transition_effect_button_text">Efekt przewijania</string> - <string name="sort_mode_title">Tytuł</string> - <string name="sort_mode_launch_count">Liczba uruchomień</string> - <string name="sort_mode_install_time">Data instalacji</string> + <string name="launcher_settings">USTAWIENIA LAUNCHERA</string> + <string name="home_screen_settings">USTAWIENIA EKRANU GŁÓWNEGO</string> + <string name="drawer_settings">USTAWIENIA SZUFLADY APLIKACJI</string> + <string name="app_settings">USTAWIENIA APLIKACJI</string> + <string name="setting_state_on">WŁĄCZONE</string> + <string name="setting_state_off">WYŁĄCZONE</string> + <string name="themes_button_text">Motywy</string> <string name="scrolling_page_outlines">Kontury strony</string> <string name="scrolling_fade_adjacent">Przenikaj strony boczne</string> - <string name="wallpaper_scroll">Przewijaj tapetę</string> - <string name="preferences_title">Ustawienia</string> - <string name="preferences_application_title">Aplikacja</string> - <string name="preferences_interface_homescreen_title">Ekran głowny</string> - <string name="preferences_interface_homescreen_search_title">Pasek wyszukiwania</string> - <string name="preferences_interface_homescreen_search_summary">Pokazuj pasek wyszukiwania na stałe</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_title">Ukryj etykiety ikon</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">Ukrywa etykiety ikon na ekranie głównym</string> - <string name="preferences_interface_drawer_title">Szuflada</string> - <string name="preferences_interface_drawer_summary">Szuflada aplikacji i widżetów</string> - <string name="preferences_interface_drawer_apps_category">Aplikacje</string> - <string name="preferences_interface_drawer_hidden_apps_title">Ukryte aplikacje</string> - <string name="preferences_interface_drawer_hidden_apps_summary">Ukrywanie aplikacji z szuflady</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">Usuń skróty</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">Usuwa skróty ukrytych aplikacji z ekranu głównego</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_title">Usuń widżety</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_summary">Usuwa widżety ukrytych aplikacji z ekranu głównego</string> - <string name="preferences_interface_drawer_hide_icon_labels_title">Ukryj etykiety ikon</string> - <string name="preferences_interface_drawer_hide_icon_labels_summary">Ukryj etykiety ikon w szufladzie</string> - <string name="preferences_interface_dock_title">Dok</string> - <string name="preferences_interface_general_title">Ogólne</string> - <string name="preferences_interface_general_icons_category">Ikony</string> - <string name="preferences_interface_general_icons_large_title">Większe ikony</string> - <string name="preferences_interface_general_icons_large_summary">Użyj ekstra dużych ikon na ekranie głównym i szufladzie</string> - <string name="preferences_interface_general_icons_text_style_title">Styl czcionki tekstu</string> - <string name="preferences_interface_general_icons_text_style_summary">Wariant i styl czcionki używanej do tekstu przy ikonach</string> - <string name="dialog_pick_iconpack_title">Wybierz paczkę ikon</string> - <string name="default_iconpack_title">Domyślne ikony</string> - <string name="icon_packs_title">Paczki ikon</string> - <string name="no_iconpacks_summary">Brak zainstalowanych paczek ikon</string> - <string name="clear_keyguard_wallpaper">Wyczyść</string> - <string name="all_apps_cling_cm">Dostosuj szufladę</string> - <string name="all_apps_cling_summary">Naciśnij na wskaźnik strony by zobaczyć dodatkowe opcje konfiguracji</string> - <string name="menu_hidden_apps_delete">Przywróć domyślne</string> + <string name="scrolling_wallpaper">Przewijanie tapety</string> + <string name="grid_size_text">Rozmiar siatki</string> + <string name="grid_size_comfortable">Wygodny</string> + <string name="grid_size_cozy">Luźny</string> + <string name="grid_size_condensed">Zagęszczony</string> + <string name="grid_size_custom">Własny</string> + <string name="preferences_interface_homescreen_custom">Wybierz własny rozmiar</string> + <string name="preferences_interface_homescreen_rows_title">Liczba wierszy</string> + <string name="preferences_interface_homescreen_columns_title">Liczba kolumn</string> <string name="hidden_apps_title">Ukryte aplikacje</string> + <string name="scroll_effect_text">Efekt przewijania</string> + <string name="drawer_sorting_text">Tryb sortowania</string> + <string name="sort_mode_title">Tytuł</string> + <string name="sort_mode_launch_count">Liczba uruchomień</string> + <string name="sort_mode_install_time">Data instalacji</string> + <string name="home_screen_search_text">Pasek wyszukiwania</string> + <string name="larger_icons_text">Większe ikony</string> + <string name="icon_labels">Etykiety ikon</string> + <string name="icon_labels_show">Pokaż</string> + <string name="icon_labels_hide">Ukryj</string> + <string name="protected_app_settings">Chronione aplikacje</string> + <string name="search_screen_left_text">Pasek wyszukiwania</string> + <string name="search_screen_left_unsupported_toast">Musisz posiadać aplikację wyszukiwania wspieraną przez CyanogenMod by używać tej funkcji.</string> + <string name="dialog_confirm">Potwierdź</string> </resources> diff --git a/res/values-port/dimens.xml b/res/values-port/dimens.xml index 7194a2a77..7753ab318 100644 --- a/res/values-port/dimens.xml +++ b/res/values-port/dimens.xml @@ -15,9 +15,6 @@ --> <resources> -<!-- Workspace --> - <dimen name="workspace_page_spacing">-1dp</dimen> - <!-- AppsCustomize --> <integer name="apps_customize_cling_focused_x">1</integer> <integer name="apps_customize_cling_focused_y">1</integer> diff --git a/res/values-pt-rBR/cm_arrays.xml b/res/values-pt-rBR/cm_arrays.xml index b03d887be..c7bc16cc4 100644 --- a/res/values-pt-rBR/cm_arrays.xml +++ b/res/values-pt-rBR/cm_arrays.xml @@ -16,19 +16,14 @@ limitations under the License. --> <resources> - <string-array name="preferences_interface_general_icons_text_font_family_entries"> - <item>Normal</item> - <item>Leve</item> - <item>Condensado</item> - </string-array> <string-array name="transition_effect_entries"> <item>Nenhum</item> - <item>Dar Zoom</item> - <item>Tirar Zoom</item> - <item>Rotacionar p/ Cima</item> - <item>Rotacionar p/ Baixo</item> - <item>Cubo Interno</item> - <item>Cubo Externo</item> + <item>Aumentar zoom</item> + <item>Diminuir o zoom</item> + <item>Girar para cima</item> + <item>Girar para baixo</item> + <item>Cubo interno</item> + <item>Cubo externo</item> <item>Pilha</item> <item>Acordeão</item> <item>Girar</item> diff --git a/res/values-pt-rBR/cm_strings.xml b/res/values-pt-rBR/cm_strings.xml index 01381a48e..af903e032 100644 --- a/res/values-pt-rBR/cm_strings.xml +++ b/res/values-pt-rBR/cm_strings.xml @@ -16,49 +16,37 @@ limitations under the License. --> <resources> - <string name="application_copyright">Copyright \u00A9 2014 The CyanogenMod Project</string> - <string name="sort_button_text">Ordenar</string> - <string name="filter_button_text">Filtrar</string> - <string name="default_screen_button_text">Tela padrão</string> - <string name="transition_effect_button_text">Efeito de rolagem</string> - <string name="sort_mode_title">Título</string> - <string name="sort_mode_launch_count">Contador de inicialização</string> - <string name="sort_mode_install_time">Hora da instalação</string> + <string name="launcher_settings">CONFIGURAÇÕES DO LAUNCHER</string> + <string name="home_screen_settings">CONFIGURAÇÕES DA TELA DE INÍCIO</string> + <string name="drawer_settings">CONFIGURAÇÕES DA GAVETA APLICAÇÕES</string> + <string name="app_settings">CONFIGURAÇÕES DE APLICATIVO</string> + <string name="setting_state_on">LIG</string> + <string name="setting_state_off">DESL</string> + <string name="themes_button_text">Temas</string> <string name="scrolling_page_outlines">Contorno de página</string> <string name="scrolling_fade_adjacent">Esmaecer páginas laterais</string> - <string name="wallpaper_scroll">Rolar papel de parede</string> - <string name="preferences_title">Preferências</string> - <string name="preferences_application_title">Aplicação</string> - <string name="preferences_interface_homescreen_title">Tela Inicial</string> - <string name="preferences_interface_homescreen_search_title">Barra de pesquisa</string> - <string name="preferences_interface_homescreen_search_summary">Exibir barra de pesquisa persistente no topo da tela</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_title">Ocultar as legendas dos ícones</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">Oculta as legendas dos ícones na tela inicial</string> - <string name="preferences_interface_drawer_title">Gaveta de apps</string> - <string name="preferences_interface_drawer_summary">Gaveta de aplicativos e widgets</string> - <string name="preferences_interface_drawer_apps_category">Aplicativos</string> - <string name="preferences_interface_drawer_hidden_apps_title">Aplicativos ocultos</string> - <string name="preferences_interface_drawer_hidden_apps_summary">Ocultar aplicativos da gaveta</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">Remover atalhos</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">Remover os atalhos de aplicativos ocultos da tela inicial</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_title">Remover widgets</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_summary">Remover os widgets dos aplicativos ocultos da tela inicial</string> - <string name="preferences_interface_drawer_hide_icon_labels_title">Ocultar as legendas dos ícones</string> - <string name="preferences_interface_drawer_hide_icon_labels_summary">Ocultar as legendas dos ícones na gaveta</string> - <string name="preferences_interface_dock_title">Dock</string> - <string name="preferences_interface_general_title">Geral</string> - <string name="preferences_interface_general_icons_category">Ícones</string> - <string name="preferences_interface_general_icons_large_title">Ícones grandes</string> - <string name="preferences_interface_general_icons_large_summary">Usar ícones de aplicação extra grandes na tela inicial e gaveta de aplicativos</string> - <string name="preferences_interface_general_icons_text_style_title">Estilo da fonte</string> - <string name="preferences_interface_general_icons_text_style_summary">Estilo da fonte para usar nos textos dos ícones</string> - <string name="dialog_pick_iconpack_title">Escolher o pacote de ícones</string> - <string name="default_iconpack_title">Ícones padrão</string> - <string name="icon_packs_title">Pacote de ícones</string> - <string name="no_iconpacks_summary">Nenhum pacote de ícones instalado</string> - <string name="clear_keyguard_wallpaper">Limpar</string> - <string name="all_apps_cling_cm">Personalizar sua gaveta de aplicativos</string> - <string name="all_apps_cling_summary">Toque o indicador desta página para visualizar configurações adicionais</string> - <string name="menu_hidden_apps_delete">Redefinir</string> + <string name="scrolling_wallpaper">Rolar papel de parede</string> + <string name="grid_size_text">Tamanho da grade</string> + <string name="grid_size_comfortable">Confortável</string> + <string name="grid_size_cozy">Aconchegante</string> + <string name="grid_size_condensed">Condensado</string> + <string name="grid_size_custom">Personalizado</string> + <string name="preferences_interface_homescreen_custom">Selecione tamanho personalizado</string> + <string name="preferences_interface_homescreen_rows_title">Número de linhas</string> + <string name="preferences_interface_homescreen_columns_title">Número de colunas</string> <string name="hidden_apps_title">Aplicativos ocultos</string> + <string name="scroll_effect_text">Efeito de rolagem</string> + <string name="drawer_sorting_text">Modo de ordenação</string> + <string name="sort_mode_title">Título</string> + <string name="sort_mode_launch_count">Contador de inicialização</string> + <string name="sort_mode_install_time">Hora da instalação</string> + <string name="home_screen_search_text">Barra de pesquisa</string> + <string name="larger_icons_text">Ícones grandes</string> + <string name="icon_labels">Etiquetas de ícones</string> + <string name="icon_labels_show">Mostrar</string> + <string name="icon_labels_hide">Ocultar</string> + <string name="protected_app_settings">Aplicativos protegidos</string> + <string name="search_screen_left_text">Painel de pesquisa</string> + <string name="search_screen_left_unsupported_toast">Você precisa ter instalado um aplicativo de pesquisa suportado e o CyanogenMod para utilizar este recurso.</string> + <string name="dialog_confirm">Confirmar</string> </resources> diff --git a/res/values-pt-rPT/cm_arrays.xml b/res/values-pt-rPT/cm_arrays.xml index c720a9ef3..ed3ede04b 100644 --- a/res/values-pt-rPT/cm_arrays.xml +++ b/res/values-pt-rPT/cm_arrays.xml @@ -16,23 +16,18 @@ limitations under the License. --> <resources> - <string-array name="preferences_interface_general_icons_text_font_family_entries"> - <item>Normal</item> - <item>Fino</item> - <item>Condensado</item> - </string-array> <string-array name="transition_effect_entries"> <item>Nenhum</item> - <item>Zoom In</item> - <item>Zoom Out</item> - <item>Rodar para Cima</item> - <item>Rodar para Baixo</item> - <item>Cubo para Dentro</item> - <item>Cubo para Fora</item> + <item>Zoom para dentro</item> + <item>Zoom para fora</item> + <item>Rodar para cima</item> + <item>Rodar para baixo</item> + <item>Cubo para dentro</item> + <item>Cubo para fora</item> <item>Pilha</item> <item>Acordeão</item> <item>Virar</item> - <item>Cilindro para Dentro</item> + <item>Cilindro para dentro</item> <item>Cilindro para Fora</item> <item>Carrossel</item> <item>Vista geral</item> diff --git a/res/values-pt-rPT/cm_strings.xml b/res/values-pt-rPT/cm_strings.xml index 127a341d6..79311bdaa 100644 --- a/res/values-pt-rPT/cm_strings.xml +++ b/res/values-pt-rPT/cm_strings.xml @@ -16,49 +16,37 @@ limitations under the License. --> <resources> - <string name="application_copyright">Copyright \u00A9 2014 The CyanogenMod Project</string> - <string name="sort_button_text">Ordenar</string> - <string name="filter_button_text">Filtrar</string> - <string name="default_screen_button_text">Ecrã Padrão</string> - <string name="transition_effect_button_text">Efeito de transição</string> - <string name="sort_mode_title">Título</string> - <string name="sort_mode_launch_count">Contagem de inicializações</string> - <string name="sort_mode_install_time">Data de instalação</string> + <string name="launcher_settings">DEFINIÇÕES DO LANÇADOR</string> + <string name="home_screen_settings">DEFINIÇÕES DO ECRÃ INICIAL</string> + <string name="drawer_settings">DEFINIÇÕES DA GAVETA APLICAÇÕES</string> + <string name="app_settings">DEFINIÇÕES DA APLICAÇÃO</string> + <string name="setting_state_on">LIG.</string> + <string name="setting_state_off">DESL.</string> + <string name="themes_button_text">Temas</string> <string name="scrolling_page_outlines">Contorno das páginas</string> <string name="scrolling_fade_adjacent">Desvanecer as páginas laterais</string> - <string name="wallpaper_scroll">Deslizar papel de parede</string> - <string name="preferences_title">Definições</string> - <string name="preferences_application_title">Aplicação</string> - <string name="preferences_interface_homescreen_title">Ecrã inicial</string> - <string name="preferences_interface_homescreen_search_title">Barra de pesquisa</string> - <string name="preferences_interface_homescreen_search_summary">Mostrar barra de pesquisa persistente no topo do ecrã</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_title">Ocultar as legendas dos ícones</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">Oculta as legendas dos ícones no ambiente de trabalho</string> - <string name="preferences_interface_drawer_title">Gaveta de aplicações</string> - <string name="preferences_interface_drawer_summary">Gaveta de aplicações e widgets</string> - <string name="preferences_interface_drawer_apps_category">Aplicações</string> - <string name="preferences_interface_drawer_hidden_apps_title">Aplicações ocultas</string> - <string name="preferences_interface_drawer_hidden_apps_summary">Ocultar aplicações da gaveta</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">Remover atalhos</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">Remover os atalhos de aplicações ocultas do ambiente de trabalho</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_title">Remover widgets</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_summary">Remover os widgets das aplicações ocultas do ambiente de trabalho</string> - <string name="preferences_interface_drawer_hide_icon_labels_title">Ocultar as legendas dos ícones</string> - <string name="preferences_interface_drawer_hide_icon_labels_summary">Ocultar as legendas dos ícones na gaveta de aplicações</string> - <string name="preferences_interface_dock_title">Dock</string> - <string name="preferences_interface_general_title">Geral</string> - <string name="preferences_interface_general_icons_category">Ícones</string> - <string name="preferences_interface_general_icons_large_title">Ícones grandes</string> - <string name="preferences_interface_general_icons_large_summary">Usar ícones de aplicação extra grandes no ecrã inicial e na gaveta de aplicações</string> - <string name="preferences_interface_general_icons_text_style_title">Estilo de tipo de letra</string> - <string name="preferences_interface_general_icons_text_style_summary">Variante e estilo do tipo de letra a usar para o texto dos ícones</string> - <string name="dialog_pick_iconpack_title">Escolher pacote de ícones</string> - <string name="default_iconpack_title">Ícones padrão</string> - <string name="icon_packs_title">Pacotes de Ícones</string> - <string name="no_iconpacks_summary">Nenhum pacote de ícones instalado</string> - <string name="clear_keyguard_wallpaper">Limpar</string> - <string name="all_apps_cling_cm">Personalize a sua gaveta de aplicações</string> - <string name="all_apps_cling_summary">Toque no indicador de página para ver definições adicionais</string> - <string name="menu_hidden_apps_delete">Restaurar</string> + <string name="scrolling_wallpaper">Deslizar imagem de fundo</string> + <string name="grid_size_text">Tamanho da grelha</string> + <string name="grid_size_comfortable">Confortável</string> + <string name="grid_size_cozy">Cómodo</string> + <string name="grid_size_condensed">Condensado</string> + <string name="grid_size_custom">Personalizado</string> + <string name="preferences_interface_homescreen_custom">Selecionar o tamanho personalizado</string> + <string name="preferences_interface_homescreen_rows_title">Número de linhas</string> + <string name="preferences_interface_homescreen_columns_title">Número de colunas</string> <string name="hidden_apps_title">Aplicações ocultas</string> + <string name="scroll_effect_text">Efeito de transição</string> + <string name="drawer_sorting_text">Ordenar por</string> + <string name="sort_mode_title">Título</string> + <string name="sort_mode_launch_count">Contagem de inicializações</string> + <string name="sort_mode_install_time">Data de instalação</string> + <string name="home_screen_search_text">Barra de pesquisa</string> + <string name="larger_icons_text">Ícones grandes</string> + <string name="icon_labels">Legendas dos ícones</string> + <string name="icon_labels_show">Mostrar</string> + <string name="icon_labels_hide">Ocultar</string> + <string name="protected_app_settings">Aplicações protegidas</string> + <string name="search_screen_left_text">Painel de pesquisa</string> + <string name="search_screen_left_unsupported_toast">Deve ter instalada uma aplicação de pesquisa suportada e a CyanogenMod para utilizar este recurso.</string> + <string name="dialog_confirm">Confirmar</string> </resources> diff --git a/res/values-ro/cm_arrays.xml b/res/values-ro/cm_arrays.xml new file mode 100644 index 000000000..a8fbba5d0 --- /dev/null +++ b/res/values-ro/cm_arrays.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="utf-8"?> +<!--Generated by crowdin.net--> +<!-- + Copyright (C) 2014 The CyanogenMod 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. +--> +<resources> + <string-array name="transition_effect_entries"> + <item>Nimic</item> + <item>Zoom in</item> + <item>Zoom out</item> + <item>Rotire în sus</item> + <item>Rotire în jos</item> + <item>Cub interior</item> + <item>Cub exterior</item> + <item>Stivă</item> + <item>Acordeon</item> + <item>Flip</item> + <item>Cilindru interor</item> + <item>Cilindru exterior</item> + <item>Carusel</item> + <item>Privire de ansamblu</item> + </string-array> +</resources> diff --git a/res/values-ro/cm_strings.xml b/res/values-ro/cm_strings.xml new file mode 100644 index 000000000..a38b471b2 --- /dev/null +++ b/res/values-ro/cm_strings.xml @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="utf-8"?> +<!--Generated by crowdin.net--> +<!-- + Copyright (C) 2014 The CyanogenMod 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. +--> +<resources> + <string name="launcher_settings">SETĂRI LAUNCHER</string> + <string name="home_screen_settings">SETĂRI ECRAN PRINCIPAL</string> + <string name="drawer_settings">SETĂRI ECRAN APLICAȚII</string> + <string name="app_settings">SETĂRI APLICAȚIE</string> + <string name="setting_state_on">ACTIV</string> + <string name="setting_state_off">INACTIV</string> + <string name="themes_button_text">Teme</string> + <string name="scrolling_page_outlines">Contururi pagină</string> + <string name="scrolling_fade_adjacent">Estompează paginile secundare</string> + <string name="scrolling_wallpaper">Scroll-ează fundal</string> + <string name="grid_size_text">Dimensiune grilă</string> + <string name="grid_size_comfortable">Confortabil</string> + <string name="grid_size_cozy">Comod</string> + <string name="grid_size_condensed">Condensat</string> + <string name="grid_size_custom">Particularizat</string> + <string name="preferences_interface_homescreen_custom">Selectare dimensiune particularizată</string> + <string name="preferences_interface_homescreen_rows_title">Numărul de rânduri</string> + <string name="preferences_interface_homescreen_columns_title">Numărul de coloane</string> + <string name="hidden_apps_title">Aplicații ascunse</string> + <string name="scroll_effect_text">Efect scroll</string> + <string name="drawer_sorting_text">Mod sortare</string> + <string name="sort_mode_title">Titlu</string> + <string name="sort_mode_launch_count">Numărare lansare</string> + <string name="sort_mode_install_time">Timp de instalare</string> + <string name="home_screen_search_text">Bară de căutare</string> + <string name="larger_icons_text">Icon-uri mai mari</string> + <string name="icon_labels">Etichete icon-uri</string> + <string name="icon_labels_show">Arată</string> + <string name="icon_labels_hide">Ascunde</string> + <string name="protected_app_settings">Aplicații protejate</string> + <string name="search_screen_left_text">Panou de căutare</string> + <string name="search_screen_left_unsupported_toast">Trebuie să ai o aplicație de căutare suportată și CyanogenMod să folosească această caracteristică.</string> + <string name="dialog_confirm">Confirmă</string> +</resources> diff --git a/res/values-ru/cm_arrays.xml b/res/values-ru/cm_arrays.xml index 8d6d774e1..903c4747c 100644 --- a/res/values-ru/cm_arrays.xml +++ b/res/values-ru/cm_arrays.xml @@ -16,11 +16,6 @@ limitations under the License. --> <resources> - <string-array name="preferences_interface_general_icons_text_font_family_entries"> - <item>Обычный</item> - <item>Облегчённый</item> - <item>Сжатый</item> - </string-array> <string-array name="transition_effect_entries"> <item>Нет</item> <item>Увеличение</item> diff --git a/res/values-ru/cm_strings.xml b/res/values-ru/cm_strings.xml index af3f3baa0..be4dcdc16 100644 --- a/res/values-ru/cm_strings.xml +++ b/res/values-ru/cm_strings.xml @@ -16,49 +16,37 @@ limitations under the License. --> <resources> - <string name="application_copyright">\u00A9 Проект CyanogenMod, 2014</string> - <string name="sort_button_text">Сортировка</string> - <string name="filter_button_text">Фильтрация</string> - <string name="default_screen_button_text">Экран по умолчанию</string> - <string name="transition_effect_button_text">Эффект прокрутки</string> - <string name="sort_mode_title">По названию</string> - <string name="sort_mode_launch_count">По частоте использования</string> - <string name="sort_mode_install_time">По времени установки</string> + <string name="launcher_settings">НАСТРОЙКИ ЛАУНЧЕРА</string> + <string name="home_screen_settings">ДОМАШНИЙ ЭКРАН</string> + <string name="drawer_settings">МЕНЮ ПРИЛОЖЕНИЙ</string> + <string name="app_settings">НАСТРОЙКИ ПРИЛОЖЕНИЯ</string> + <string name="setting_state_on">ВКЛ.</string> + <string name="setting_state_off">ВЫКЛ.</string> + <string name="themes_button_text">Темы</string> <string name="scrolling_page_outlines">Границы страниц</string> <string name="scrolling_fade_adjacent">Затемнять края при переходе</string> - <string name="wallpaper_scroll">Прокрутка обоев</string> - <string name="preferences_title">Настройки</string> - <string name="preferences_application_title">Приложение</string> - <string name="preferences_interface_homescreen_title">Домашний экран</string> - <string name="preferences_interface_homescreen_search_title">Строка поиска</string> - <string name="preferences_interface_homescreen_search_summary">Показывать постоянную строку поиска вверху экрана</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_title">Скрывать подписи значков</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">Не отображать текст у ярлыков на домашнем экране</string> - <string name="preferences_interface_drawer_title">Меню приложений</string> - <string name="preferences_interface_drawer_summary">Список приложений и виджетов</string> - <string name="preferences_interface_drawer_apps_category">Приложения</string> - <string name="preferences_interface_drawer_hidden_apps_title">Скрытые приложения</string> - <string name="preferences_interface_drawer_hidden_apps_summary">Выбрать приложения, которые не будут отображаться в меню</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">Удалять ярлыки</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">Убирать ярлыки скрытых приложений с домашнего экрана</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_title">Удалять виджеты</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_summary">Убирать виджеты скрытых приложений с домашнего экрана</string> - <string name="preferences_interface_drawer_hide_icon_labels_title">Скрывать подписи значков</string> - <string name="preferences_interface_drawer_hide_icon_labels_summary">Не отображать текст у ярлыков в меню приложений</string> - <string name="preferences_interface_dock_title">Нижняя панель</string> - <string name="preferences_interface_general_title">Общие</string> - <string name="preferences_interface_general_icons_category">Значки</string> - <string name="preferences_interface_general_icons_large_title">Крупные значки</string> - <string name="preferences_interface_general_icons_large_summary">Использовать крупные значки приложений на домашнем экране и в меню приложений</string> - <string name="preferences_interface_general_icons_text_style_title">Тип шрифта</string> - <string name="preferences_interface_general_icons_text_style_summary">Выбор стиля шрифта для подписей значков</string> - <string name="dialog_pick_iconpack_title">Выберите набор значков</string> - <string name="default_iconpack_title">Значки по умолчанию</string> - <string name="icon_packs_title">Наборы значков</string> - <string name="no_iconpacks_summary">Наборы значков не установлены</string> - <string name="clear_keyguard_wallpaper">Очистить</string> - <string name="all_apps_cling_cm">Настройте меню приложений по своему вкусу</string> - <string name="all_apps_cling_summary">Коснитесь индикатора страницы внизу для перехода к настройкам.</string> - <string name="menu_hidden_apps_delete">Сброс</string> + <string name="scrolling_wallpaper">Прокрутка обоев</string> + <string name="grid_size_text">Размер сетки</string> + <string name="grid_size_comfortable">Комфортная</string> + <string name="grid_size_cozy">Удобная</string> + <string name="grid_size_condensed">Сжатая</string> + <string name="grid_size_custom">Настраиваемая</string> + <string name="preferences_interface_homescreen_custom">Выберите размер сетки</string> + <string name="preferences_interface_homescreen_rows_title">Количество строк</string> + <string name="preferences_interface_homescreen_columns_title">Количество столбцов</string> <string name="hidden_apps_title">Скрытые приложения</string> + <string name="scroll_effect_text">Эффект прокрутки</string> + <string name="drawer_sorting_text">Режим сортировки</string> + <string name="sort_mode_title">По назв.</string> + <string name="sort_mode_launch_count">По частоте исп.</string> + <string name="sort_mode_install_time">По врем. устан.</string> + <string name="home_screen_search_text">Строка поиска</string> + <string name="larger_icons_text">Крупные значки</string> + <string name="icon_labels">Подписи значков</string> + <string name="icon_labels_show">Показ.</string> + <string name="icon_labels_hide">Скрывать</string> + <string name="protected_app_settings">Заблокированные приложения</string> + <string name="search_screen_left_text">Поисковый экран слева</string> + <string name="search_screen_left_unsupported_toast">Для использования этой функции необходимо наличие поддерживаемого приложения поиска и CyanogenMod.</string> + <string name="dialog_confirm">Подтвердить</string> </resources> diff --git a/res/values-si/cm_arrays.xml b/res/values-si/cm_arrays.xml index 3ff25c0b8..0cb9638aa 100644 --- a/res/values-si/cm_arrays.xml +++ b/res/values-si/cm_arrays.xml @@ -16,11 +16,6 @@ limitations under the License. --> <resources> - <string-array name="preferences_interface_general_icons_text_font_family_entries"> - <item>විධිමත්</item> - <item>සැහැල්ලු</item> - <item>ඝනීභූත</item> - </string-array> <string-array name="transition_effect_entries"> <item>කිසිවක් නැත</item> <item>ඇතුලට විශාලනය</item> diff --git a/res/values-si/cm_strings.xml b/res/values-si/cm_strings.xml index 9804bb914..49ad20a95 100644 --- a/res/values-si/cm_strings.xml +++ b/res/values-si/cm_strings.xml @@ -16,49 +16,37 @@ limitations under the License. --> <resources> - <string name="application_copyright">ප්රකාශන අයිතිය \u00A9 2014 CyanogenMod ව්යාපෘතිය</string> - <string name="sort_button_text">සුබෙදන්න</string> - <string name="filter_button_text">පෙරහන</string> - <string name="default_screen_button_text">පෙරනිමි තිරය</string> - <string name="transition_effect_button_text">අනුචලන ආටෝපය</string> - <string name="sort_mode_title">පටබැඳිනාමය</string> - <string name="sort_mode_launch_count">දියත් කල වාර ගණන</string> - <string name="sort_mode_install_time">ස්ථාපිත වේලාව</string> + <string name="launcher_settings">දියත් කරකයේ සැකසීම්</string> + <string name="home_screen_settings">මුල් තිරයේ සැකසීම්</string> + <string name="drawer_settings">ලාච්චුවේ සැකසීම්</string> + <string name="app_settings">යෙදුම් සැකසීම්</string> + <string name="setting_state_on">සක්රීයයි</string> + <string name="setting_state_off">අක්රීයයි</string> + <string name="themes_button_text">තේමා</string> <string name="scrolling_page_outlines">පිටුවේ පිට මායිම්</string> <string name="scrolling_fade_adjacent">පැති පිටු අවපැහැ කරන්න</string> - <string name="wallpaper_scroll">වෝල්පේපරය අනුචලනය කරන්න</string> - <string name="preferences_title">සැකසීම්</string> - <string name="preferences_application_title">යෙදුම</string> - <string name="preferences_interface_homescreen_title">මුල් තිරය</string> - <string name="preferences_interface_homescreen_search_title">සෙවුම් තීරුව</string> - <string name="preferences_interface_homescreen_search_summary">තිරය මුදුනෙහි අප්රතිහත සෙවුම් තීරුව පෙන්වන්න</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_title">අයිකන ලේබල සඟවන්න</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">මුල් තිරයේ අයිකන ලේබල සඟවන්න</string> - <string name="preferences_interface_drawer_title">ලාච්චුව</string> - <string name="preferences_interface_drawer_summary">යෙදුම් සහ විජට ලාච්චුව</string> - <string name="preferences_interface_drawer_apps_category">යෙදුම්</string> - <string name="preferences_interface_drawer_hidden_apps_title">සැඟවුණු යෙදුම්</string> - <string name="preferences_interface_drawer_hidden_apps_summary">යෙදුම් ලාච්චුවේ නොපෙන්වන්න</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">කෙටිමං ඉවත් කරන්න</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">සැඟවුණු යෙදුම්හි කෙටිමං මුල් තිරයෙන් ඉවත් කරන්න</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_title">විජට ඉවත් කරන්න</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_summary">සැඟවුණු යෙදුම්හි විජට මුල් තිරයෙන් ඉවත් කරන්න</string> - <string name="preferences_interface_drawer_hide_icon_labels_title">අයිකන ලේබල සඟවන්න</string> - <string name="preferences_interface_drawer_hide_icon_labels_summary">ලාච්චුව තුල අයිකන ලේබල සඟවන්න</string> - <string name="preferences_interface_dock_title">ඈඳීම</string> - <string name="preferences_interface_general_title">ප්රධාන</string> - <string name="preferences_interface_general_icons_category">අයිකන</string> - <string name="preferences_interface_general_icons_large_title">විශාල අයිකන</string> - <string name="preferences_interface_general_icons_large_summary">මුල් තිරයේ හා ලාච්චුවේ අති විශාල යෙදුම් අයිකන භාවිතා කරන්න</string> - <string name="preferences_interface_general_icons_text_style_title">පෙළ ෆොන්ට විලාසය</string> - <string name="preferences_interface_general_icons_text_style_summary">අයිකන පෙළ සඳහා භාවිතයට ෆොන්ටයේ ප්රභේදය සහ විලාසය</string> - <string name="dialog_pick_iconpack_title">අයිකන පොදිය තෝරන්න</string> - <string name="default_iconpack_title">පෙරනිමි අයිකන</string> - <string name="icon_packs_title">අයිකන පොදි</string> - <string name="no_iconpacks_summary">අයිකන පොදි කිසිවක් පිහිටුවා නැත</string> - <string name="clear_keyguard_wallpaper">හිස් කරන්න</string> - <string name="all_apps_cling_cm">ඔබගේ ලාච්චුව රිසිකරණය කරන්න</string> - <string name="all_apps_cling_summary">අතිරේක වින්යාසන සැකසීම් බැලීමට පිටු දර්ශකය මත තට්ටු කරන්න</string> - <string name="menu_hidden_apps_delete">ප්රත්යාරම්භනය</string> + <string name="scrolling_wallpaper">වෝල්පේපරය අනුචලනය කරන්න</string> + <string name="grid_size_text">කොටු සැලැස්මේ ප්රමාණය</string> + <string name="grid_size_comfortable">සැපපහසු</string> + <string name="grid_size_cozy">ප්රියජනක</string> + <string name="grid_size_condensed">ඝනීභූත</string> + <string name="grid_size_custom">රිසිවූ</string> + <string name="preferences_interface_homescreen_custom">රිසිකළ ප්රමාණය තෝරන්න</string> + <string name="preferences_interface_homescreen_rows_title">පේළි ගණන</string> + <string name="preferences_interface_homescreen_columns_title">තීරු ගණන</string> <string name="hidden_apps_title">සැඟවුණු යෙදුම්</string> + <string name="scroll_effect_text">අනුචලන ආටෝපය</string> + <string name="drawer_sorting_text">සුබෙදීමේ ප්රකාරය</string> + <string name="sort_mode_title">පටබැඳිනාමය</string> + <string name="sort_mode_launch_count">දියත් කල වාර ගණන</string> + <string name="sort_mode_install_time">ස්ථාපිත වේලාව</string> + <string name="home_screen_search_text">සෙවුම් තීරුව</string> + <string name="larger_icons_text">විශාල අයිකන</string> + <string name="icon_labels">අයිකන ලේබල</string> + <string name="icon_labels_show">පෙන්වන්න</string> + <string name="icon_labels_hide">සඟවන්න</string> + <string name="protected_app_settings">ආරක්ෂිත යෙදුම්</string> + <string name="search_screen_left_text">සෙවීම් පුවරුව</string> + <string name="search_screen_left_unsupported_toast">මෙම විශේෂාංගය භාවිතාකිරීම සඳහා, ඔබ සතුව, සහාය දක්වන සෙවීම් යෙදුමක් සහ CyanogenMod තිබිය යුතුමය.</string> + <string name="dialog_confirm">තහවුරු කරන්න</string> </resources> diff --git a/res/values-sk/cm_arrays.xml b/res/values-sk/cm_arrays.xml index 10b82522c..baa3dd8a5 100644 --- a/res/values-sk/cm_arrays.xml +++ b/res/values-sk/cm_arrays.xml @@ -16,15 +16,10 @@ limitations under the License. --> <resources> - <string-array name="preferences_interface_general_icons_text_font_family_entries"> - <item>Pravidelný</item> - <item>Svetlý</item> - <item>Zhustený</item> - </string-array> <string-array name="transition_effect_entries"> <item>Žiadny</item> - <item>Priblíženie</item> - <item>Oddialenie</item> + <item>Priblížiť</item> + <item>Oddialiť</item> <item>Otočenie hore</item> <item>Otočenie dolu</item> <item>Kocka zvnútra</item> diff --git a/res/values-sk/cm_strings.xml b/res/values-sk/cm_strings.xml index 6a78d0a7d..cbfff3a91 100644 --- a/res/values-sk/cm_strings.xml +++ b/res/values-sk/cm_strings.xml @@ -16,49 +16,37 @@ limitations under the License. --> <resources> - <string name="application_copyright">Autorské práva \u00A9 2014 Projekt CyanogenMod</string> - <string name="sort_button_text">Zoradiť</string> - <string name="filter_button_text">Filtrovať</string> - <string name="default_screen_button_text">Predvolená obrazovka</string> - <string name="transition_effect_button_text">Efekt posunu</string> - <string name="sort_mode_title">Názov</string> - <string name="sort_mode_launch_count">Počet spustení</string> - <string name="sort_mode_install_time">Čas inštalácie</string> + <string name="launcher_settings">NASTAVENIA SPÚŠŤAČA</string> + <string name="home_screen_settings">NASTAVENIA DOMOVSKEJ OBRAZOVKY</string> + <string name="drawer_settings">NASTAVENIA PONUKY</string> + <string name="app_settings">NASTAVENIA APLIKÁCIÍ</string> + <string name="setting_state_on">Zapnuté</string> + <string name="setting_state_off">VYPNUTÉ</string> + <string name="themes_button_text">Témy</string> <string name="scrolling_page_outlines">Obrysy stránky</string> <string name="scrolling_fade_adjacent">Stmavnuté bočné strany</string> - <string name="wallpaper_scroll">Posun tapety</string> - <string name="preferences_title">Nastavenia</string> - <string name="preferences_application_title">Aplikácia</string> - <string name="preferences_interface_homescreen_title">Domovská obrazovka</string> - <string name="preferences_interface_homescreen_search_title">Vyhľadávací panel</string> - <string name="preferences_interface_homescreen_search_summary">Zobraziť pretrvávajúci vyhľadávací panel v hornej časti obrazovky</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_title">Skryť menovky ikon</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">Skryť menovky ikon z domovskej obrazovky</string> - <string name="preferences_interface_drawer_title">Ponuka aplikácií</string> - <string name="preferences_interface_drawer_summary">Aplikácie a miniaplikácie ponuky</string> - <string name="preferences_interface_drawer_apps_category">Aplikácie</string> - <string name="preferences_interface_drawer_hidden_apps_title">Skryté aplikácie</string> - <string name="preferences_interface_drawer_hidden_apps_summary">Skryť aplikácie zo zoznamu aplikácií</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">Vymazať odkazy</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">Vymazať odkazy skrytých aplikácií z domovskej obrazovky</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_title">Vymazať miniaplikácie</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_summary">Vymazať miniaplikácie skrytých aplikácií z domovskej obrazovky</string> - <string name="preferences_interface_drawer_hide_icon_labels_title">Skryť menovky ikon</string> - <string name="preferences_interface_drawer_hide_icon_labels_summary">Skryť menovky ikon v ponuke aplikácií</string> - <string name="preferences_interface_dock_title">Dok</string> - <string name="preferences_interface_general_title">Všeobecné</string> - <string name="preferences_interface_general_icons_category">Ikony</string> - <string name="preferences_interface_general_icons_large_title">Väčšie ikony</string> - <string name="preferences_interface_general_icons_large_summary">Použiť extra veľké ikony aplikácií na domovskej obrazovke a v ponuke aplikácií</string> - <string name="preferences_interface_general_icons_text_style_title">Štýl písma textu</string> - <string name="preferences_interface_general_icons_text_style_summary">Variant a štýl písma na použitie pre text ikony</string> - <string name="dialog_pick_iconpack_title">Vyberte balík ikon</string> - <string name="default_iconpack_title">Predvolené ikony</string> - <string name="icon_packs_title">Balíky ikon</string> - <string name="no_iconpacks_summary">Žiadne balíky ikon nie sú nainštalované</string> - <string name="clear_keyguard_wallpaper">Vymazať</string> - <string name="all_apps_cling_cm">Prispôsobte si vašu ponuku</string> - <string name="all_apps_cling_summary">Kliknite na ukazovateľ stránky pre zobrazenie ďalších nastavení</string> - <string name="menu_hidden_apps_delete">Obnoviť</string> + <string name="scrolling_wallpaper">Posun tapety</string> + <string name="grid_size_text">Veľkosť mriežky</string> + <string name="grid_size_comfortable">Pohodlná</string> + <string name="grid_size_cozy">Útulná</string> + <string name="grid_size_condensed">Zhustená</string> + <string name="grid_size_custom">Vlastná</string> + <string name="preferences_interface_homescreen_custom">Vyberte vlastnú veľkosť</string> + <string name="preferences_interface_homescreen_rows_title">Počet riadkov</string> + <string name="preferences_interface_homescreen_columns_title">Počet stĺpcov</string> <string name="hidden_apps_title">Skryté aplikácie</string> + <string name="scroll_effect_text">Efekt posunu</string> + <string name="drawer_sorting_text">Režim triedenia</string> + <string name="sort_mode_title">Názov</string> + <string name="sort_mode_launch_count">Počet spustení</string> + <string name="sort_mode_install_time">Čas inštalácie</string> + <string name="home_screen_search_text">Vyhľadávací panel</string> + <string name="larger_icons_text">Väčšie ikony</string> + <string name="icon_labels">Menovky ikon</string> + <string name="icon_labels_show">Zobraziť</string> + <string name="icon_labels_hide">Skryť</string> + <string name="protected_app_settings">Chránené aplikácie</string> + <string name="search_screen_left_text">Panel vyhľadávania</string> + <string name="search_screen_left_unsupported_toast">Musíte mať podporovaný vyhľadávač a CyanogenMod pre použitie tejto funkcie.</string> + <string name="dialog_confirm">Potvrdiť</string> </resources> diff --git a/res/values-sr/cm_arrays.xml b/res/values-sr/cm_arrays.xml index 54f520e01..6a4f6cc49 100644 --- a/res/values-sr/cm_arrays.xml +++ b/res/values-sr/cm_arrays.xml @@ -16,22 +16,17 @@ limitations under the License. --> <resources> - <string-array name="preferences_interface_general_icons_text_font_family_entries"> - <item>Обично</item> - <item>Светло</item> - <item>Кондензовано</item> - </string-array> <string-array name="transition_effect_entries"> - <item>Без ефекта</item> - <item>Увећај</item> - <item>Умањи</item> - <item>Ротирај нагоре</item> - <item>Ротирај надоле</item> + <item>Ниједан</item> + <item>Увећавање</item> + <item>Умањивање</item> + <item>Ротирање нагоре</item> + <item>Ротирање надоле</item> <item>Коцка унутра</item> <item>Коцка споља</item> <item>Листање карата</item> - <item>Хармонијски</item> - <item>Флип</item> + <item>Хармоника</item> + <item>Окрет</item> <item>Цилиндар унутра</item> <item>Цилиндар споља</item> <item>Рингишпил</item> diff --git a/res/values-sr/cm_strings.xml b/res/values-sr/cm_strings.xml index 4c4eaf47b..6d22910fd 100644 --- a/res/values-sr/cm_strings.xml +++ b/res/values-sr/cm_strings.xml @@ -16,49 +16,37 @@ limitations under the License. --> <resources> - <string name="application_copyright">Copyright \u00A9 2014 The CyanogenMod Project</string> - <string name="sort_button_text">Приказ</string> - <string name="filter_button_text">Филтер</string> - <string name="default_screen_button_text">Подразумевани екран</string> - <string name="transition_effect_button_text">Ефекат скроловања</string> + <string name="launcher_settings">ПОДЕШАВАЊА ПОКРЕТАЧА</string> + <string name="home_screen_settings">ПОДЕШАВАЊА ПОЧЕТНОГ ЕКРАНА</string> + <string name="drawer_settings">ПОДЕШАВАЊА ФИОКЕ</string> + <string name="app_settings">ПОДЕШАВАЊА АПЛИКАЦИЈА</string> + <string name="setting_state_on">ДА</string> + <string name="setting_state_off">НЕ</string> + <string name="themes_button_text">Теме</string> + <string name="scrolling_page_outlines">Контура странице</string> + <string name="scrolling_fade_adjacent">Замагљени крајеви страница</string> + <string name="scrolling_wallpaper">Скроловање позадине</string> + <string name="grid_size_text">Величина мреже</string> + <string name="grid_size_comfortable">Комфорно</string> + <string name="grid_size_cozy">Удобно</string> + <string name="grid_size_condensed">Кондензовано</string> + <string name="grid_size_custom">Прилагођено</string> + <string name="preferences_interface_homescreen_custom">Изабери прилагођену величину</string> + <string name="preferences_interface_homescreen_rows_title">Број редова</string> + <string name="preferences_interface_homescreen_columns_title">Број колона</string> + <string name="hidden_apps_title">Сакривене апликације</string> + <string name="scroll_effect_text">Ефекат</string> + <string name="drawer_sorting_text">Сортирање</string> <string name="sort_mode_title">Наслов</string> <string name="sort_mode_launch_count">Број покретања</string> <string name="sort_mode_install_time">Време инсталирања</string> - <string name="scrolling_page_outlines">Контура странице</string> - <string name="scrolling_fade_adjacent">Замагљени крајеви страница</string> - <string name="wallpaper_scroll">Скроловање позадине</string> - <string name="preferences_title">Подешавања</string> - <string name="preferences_application_title">Апликације</string> - <string name="preferences_interface_homescreen_title">Почетни екран</string> - <string name="preferences_interface_homescreen_search_title">Табла за претрагу</string> - <string name="preferences_interface_homescreen_search_summary">Прикажи упорну таблу за претрагу на врху екрана</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_title">Сакриј етикете икона</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">Сакријте етикете икона на почетном екрану</string> - <string name="preferences_interface_drawer_title">Фиока</string> - <string name="preferences_interface_drawer_summary">Фиока за апликације и виџете</string> - <string name="preferences_interface_drawer_apps_category">Апликације</string> - <string name="preferences_interface_drawer_hidden_apps_title">Скривене апликације</string> - <string name="preferences_interface_drawer_hidden_apps_summary">Сакријте апликације из фиоке</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">Уклони пречице</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">Уклоните пречице скривених апликација са почетног екрана</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_title">Уклони виџете</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_summary">Уклоните виџете скривених апликација са почетног екрана</string> - <string name="preferences_interface_drawer_hide_icon_labels_title">Сакриј етикете икона</string> - <string name="preferences_interface_drawer_hide_icon_labels_summary">Сакријте етикете икона у фиоци</string> - <string name="preferences_interface_dock_title">Док</string> - <string name="preferences_interface_general_title">Oпште</string> - <string name="preferences_interface_general_icons_category">Иконе</string> - <string name="preferences_interface_general_icons_large_title">Веће иконе</string> - <string name="preferences_interface_general_icons_large_summary">Користите екстра велике апликационе иконе на почетном екрану и фиоци</string> - <string name="preferences_interface_general_icons_text_style_title">Стил фонта текста</string> - <string name="preferences_interface_general_icons_text_style_summary">Варијанту и стил фонта користити за текст на иконама</string> - <string name="dialog_pick_iconpack_title">Одаберите пакет икона</string> - <string name="default_iconpack_title">Подразумеване иконе</string> - <string name="icon_packs_title">Пакети икона</string> - <string name="no_iconpacks_summary">Нема инсталираних пакета са иконама</string> - <string name="clear_keyguard_wallpaper">Чисто</string> - <string name="all_apps_cling_cm">Прилагодите фиоку</string> - <string name="all_apps_cling_summary">Додирните индикатор странице да би сте видели додатна подешавања</string> - <string name="menu_hidden_apps_delete">Ресетовање</string> - <string name="hidden_apps_title">Скривене апликације</string> + <string name="home_screen_search_text">Трака за претрагу</string> + <string name="larger_icons_text">Веће иконе</string> + <string name="icon_labels">Ознаке икона</string> + <string name="icon_labels_show">Прикажи</string> + <string name="icon_labels_hide">Сакриј</string> + <string name="protected_app_settings">Заштићене апликације</string> + <string name="search_screen_left_text">Панел за претрагу</string> + <string name="search_screen_left_unsupported_toast">Мораш да имаш подржану апликацију за претрагу и CyanogenMod да би користио ову функцију.</string> + <string name="dialog_confirm">Потврди</string> </resources> diff --git a/res/values-sv/cm_arrays.xml b/res/values-sv/cm_arrays.xml index 82f1a1f1e..96f037287 100644 --- a/res/values-sv/cm_arrays.xml +++ b/res/values-sv/cm_arrays.xml @@ -16,24 +16,19 @@ limitations under the License. --> <resources> - <string-array name="preferences_interface_general_icons_text_font_family_entries"> - <item>Vanlig</item> - <item>Ljus</item> - <item>Kondenserad</item> - </string-array> <string-array name="transition_effect_entries"> <item>Ingen</item> - <item>Zooma In</item> + <item>Zooma in</item> <item>Zooma ut</item> - <item>Rotera upp</item> - <item>Rotera ner</item> - <item>Kub in</item> - <item>Kub ut</item> + <item>Rotera uppåt</item> + <item>Rotera nedåt</item> + <item>Kub inåt</item> + <item>Kub utåt</item> <item>Stack</item> <item>Dragspel</item> <item>Vänd</item> - <item>Cylinder in</item> - <item>Cylinder ut</item> + <item>Cylinder inåt</item> + <item>Cylinder utåt</item> <item>Karusell</item> <item>Översikt</item> </string-array> diff --git a/res/values-sv/cm_strings.xml b/res/values-sv/cm_strings.xml index 530ebab3a..417a2d842 100644 --- a/res/values-sv/cm_strings.xml +++ b/res/values-sv/cm_strings.xml @@ -16,49 +16,24 @@ limitations under the License. --> <resources> - <string name="application_copyright">Copyright \u00A9 2014 The CyanogenMod Project</string> - <string name="sort_button_text">Sortera</string> - <string name="filter_button_text">Filtrera</string> - <string name="default_screen_button_text">Standardskärm</string> - <string name="transition_effect_button_text">Rullningseffekt</string> - <string name="sort_mode_title">Titel</string> - <string name="sort_mode_launch_count">Startantal</string> - <string name="sort_mode_install_time">Installationstillfälle</string> + <string name="launcher_settings">LAUNCHERINSTÄLLNINGAR</string> + <string name="home_screen_settings">HEMSKÄRMSINSTÄLLNINGAR</string> + <string name="drawer_settings">APPMENYINSTÄLLNINGAR</string> + <string name="setting_state_on">PÅ</string> + <string name="setting_state_off">AV</string> + <string name="themes_button_text">Teman</string> <string name="scrolling_page_outlines">Skärmkonturer</string> <string name="scrolling_fade_adjacent">Tona skärmsidor</string> - <string name="wallpaper_scroll">Rulla bakgrundsbild</string> - <string name="preferences_title">Inställningar</string> - <string name="preferences_application_title">App</string> - <string name="preferences_interface_homescreen_title">Hemskärm</string> - <string name="preferences_interface_homescreen_search_title">Sökfält</string> - <string name="preferences_interface_homescreen_search_summary">Visa beständigt sökfält längst upp på skärmen</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_title">Dölj ikonetiketter</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">Dölj ikonetiketter på hemskärmen</string> - <string name="preferences_interface_drawer_title">Appmeny</string> - <string name="preferences_interface_drawer_summary">App- och widgetmeny</string> - <string name="preferences_interface_drawer_apps_category">Appar</string> - <string name="preferences_interface_drawer_hidden_apps_title">Gömda appar</string> - <string name="preferences_interface_drawer_hidden_apps_summary">Göm appar från menyn</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">Ta bort genvägar</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">Ta bort genvägarna till gömda appar från hemskärmen</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_title">Ta bort widgetar</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_summary">Ta bort widgetarna från gömda appar från hemskärmen</string> - <string name="preferences_interface_drawer_hide_icon_labels_title">Göm ikonetiketter</string> - <string name="preferences_interface_drawer_hide_icon_labels_summary">Göm ikonetiketter i appmenyn</string> - <string name="preferences_interface_dock_title">Docka</string> - <string name="preferences_interface_general_title">Allmänt</string> - <string name="preferences_interface_general_icons_category">Ikoner</string> - <string name="preferences_interface_general_icons_large_title">Större ikoner</string> - <string name="preferences_interface_general_icons_large_summary">Använda extra stora appikoner på hemskärmen och appmenyn</string> - <string name="preferences_interface_general_icons_text_style_title">Typsnitt</string> - <string name="preferences_interface_general_icons_text_style_summary">Variant och stil på typsnitt som används för ikontext</string> - <string name="dialog_pick_iconpack_title">Välj ikonpaket</string> - <string name="default_iconpack_title">Standardikoner</string> - <string name="icon_packs_title">Ikonpaket</string> - <string name="no_iconpacks_summary">Inga ikonpaket installerade</string> - <string name="clear_keyguard_wallpaper">Ta bort</string> - <string name="all_apps_cling_cm">Anpassa din appmeny</string> - <string name="all_apps_cling_summary">Tryck på sidindikatorn för att se ytterligare inställningar</string> - <string name="menu_hidden_apps_delete">Återställ</string> + <string name="scrolling_wallpaper">Rulla bakgrundsbild</string> <string name="hidden_apps_title">Gömda appar</string> + <string name="scroll_effect_text">Rullningseffekt</string> + <string name="drawer_sorting_text">Sorteringsläge</string> + <string name="sort_mode_title">Titel</string> + <string name="sort_mode_launch_count">Startantal</string> + <string name="sort_mode_install_time">Installationstillfälle</string> + <string name="home_screen_search_text">Sökfält</string> + <string name="larger_icons_text">Större ikoner</string> + <string name="protected_app_settings">Skyddade appar</string> + <string name="search_screen_left_text">Sökpanel</string> + <string name="search_screen_left_unsupported_toast">Du måste ha en stödd sökapp och CyanogenMod för att använda denna funktion.</string> </resources> diff --git a/res/values-sw320dp/dimens.xml b/res/values-sw320dp/dimens.xml index bcc465e94..93fb82130 100644 --- a/res/values-sw320dp/dimens.xml +++ b/res/values-sw320dp/dimens.xml @@ -16,6 +16,8 @@ <resources> <!-- Workspace --> - <dimen name="overview_panel_bottom_padding">35dp</dimen> - <dimen name="overview_panel_button_spacing">15dp</dimen> + <dimen name="overview_panel_bottom_padding">50dp</dimen> + <dimen name="overview_panel_button_spacing">17dp</dimen> + <dimen name="overview_panel_side_padding">28dp</dimen> + <dimen name="overview_panel_list_padding">16dp</dimen> </resources> diff --git a/res/values-sw340dp-port/config.xml b/res/values-sw340dp-port/config.xml index d31ee5969..5f71077c7 100644 --- a/res/values-sw340dp-port/config.xml +++ b/res/values-sw340dp-port/config.xml @@ -15,7 +15,4 @@ --> <resources> -<!-- Workspace --> - <!-- Whether or not to fade the side pages --> - <bool name="config_workspaceFadeAdjacentScreens">false</bool> </resources> diff --git a/res/values-sw340dp/dimens.xml b/res/values-sw340dp/dimens.xml index 69d6e58a3..56b9a3b04 100644 --- a/res/values-sw340dp/dimens.xml +++ b/res/values-sw340dp/dimens.xml @@ -17,4 +17,6 @@ <resources> <!-- Drag padding to add to the bottom of drop targets --> <dimen name="drop_target_drag_padding">20dp</dimen> + + <dimen name="overview_panel_button_spacing">22dp</dimen> </resources> diff --git a/res/values-sw600dp-land/dimens.xml b/res/values-sw600dp-land/dimens.xml index 7f5594de3..f9ca01bee 100644 --- a/res/values-sw600dp-land/dimens.xml +++ b/res/values-sw600dp-land/dimens.xml @@ -15,12 +15,6 @@ --> <resources> -<!-- AppsCustomize --> - <dimen name="apps_customize_pageLayoutWidthGap">36dp</dimen> - <dimen name="apps_customize_pageLayoutHeightGap">8dp</dimen> - <dimen name="apps_customize_pageLayoutPaddingTop">20dp</dimen> - <dimen name="apps_customize_pageLayoutPaddingBottom">14dp</dimen> - <!-- QSB --> <dimen name="toolbar_button_vertical_padding">12dip</dimen> <dimen name="toolbar_button_horizontal_padding">20dip</dimen> diff --git a/res/values-sw600dp/dimens.xml b/res/values-sw600dp/dimens.xml index 8d6c7f4e3..3360d302c 100644 --- a/res/values-sw600dp/dimens.xml +++ b/res/values-sw600dp/dimens.xml @@ -23,4 +23,11 @@ <dimen name="app_widget_preview_label_margin_top">8dp</dimen> <dimen name="app_widget_preview_label_margin_left">@dimen/app_widget_preview_padding_left</dimen> <dimen name="app_widget_preview_label_margin_right">@dimen/app_widget_preview_padding_right</dimen> + + <dimen name="sliding_panel_padding">180dp</dimen> + <dimen name="overview_panel_button_spacing">32dp</dimen> + + <!-- Dynamic Grid settings --> + <dimen name="dynamic_grid_size_image_width">300dp</dimen> + <dimen name="dynamic_grid_size_image_height">300dp</dimen> </resources> diff --git a/res/values-sw600dp/styles.xml b/res/values-sw600dp/styles.xml index 375430417..bcbbafdbb 100644 --- a/res/values-sw600dp/styles.xml +++ b/res/values-sw600dp/styles.xml @@ -18,33 +18,4 @@ --> <resources> - <style name="ClingButton"> - <item name="android:layout_width">wrap_content</item> - <item name="android:layout_height">wrap_content</item> - <item name="android:paddingTop">10dp</item> - <item name="android:paddingBottom">15dp</item> - <item name="android:paddingStart">35dp</item> - <item name="android:paddingEnd">35dp</item> - <item name="android:text">@string/cling_dismiss</item> - <item name="android:textStyle">bold</item> - <item name="android:background">@drawable/cling_button_bg</item> - </style> - <style name="ClingTitleText"> - <item name="android:layout_width">wrap_content</item> - <item name="android:layout_height">wrap_content</item> - <item name="android:layout_marginBottom">5dp</item> - <item name="android:textSize">30sp</item> - <item name="android:textColor">#33B5E5</item> - <item name="android:shadowColor">#000000</item> - <item name="android:shadowDy">2</item> - <item name="android:shadowRadius">2.0</item> - </style> - <style name="ClingText"> - <item name="android:textSize">22sp</item> - <item name="android:textColor">#FFFFFF</item> - <item name="android:shadowColor">#000000</item> - <item name="android:shadowDy">2</item> - <item name="android:shadowRadius">2.0</item> - <item name="android:lineSpacingMultiplier">1.1</item> - </style> </resources> diff --git a/res/values-sw720dp-land/dimens.xml b/res/values-sw720dp-land/dimens.xml index eb8f83c43..433a5d40d 100644 --- a/res/values-sw720dp-land/dimens.xml +++ b/res/values-sw720dp-land/dimens.xml @@ -21,9 +21,6 @@ <integer name="apps_customize_cling_focused_x">4</integer> <integer name="apps_customize_cling_focused_y">2</integer> -<!-- Workspace --> - <dimen name="workspace_page_spacing">50dp</dimen> - <!-- the area at the edge of the screen that makes the workspace go left or right while you're dragging. --> <dimen name="scroll_zone">100dip</dimen> diff --git a/res/values-sw720dp-port/dimens.xml b/res/values-sw720dp-port/dimens.xml index 62bdaaa97..9fe312bfe 100644 --- a/res/values-sw720dp-port/dimens.xml +++ b/res/values-sw720dp-port/dimens.xml @@ -19,7 +19,6 @@ <!-- the area at the edge of the screen that makes the workspace go left or right while you're dragging. --> <dimen name="scroll_zone">40dp</dimen> - <dimen name="workspace_page_spacing">24dp</dimen> <integer name="apps_customize_cling_focused_x">2</integer> <integer name="apps_customize_cling_focused_y">2</integer> diff --git a/res/values-sw720dp/dimens.xml b/res/values-sw720dp/dimens.xml index 01227e147..6a57e4374 100644 --- a/res/values-sw720dp/dimens.xml +++ b/res/values-sw720dp/dimens.xml @@ -21,12 +21,10 @@ <dimen name="toolbar_button_vertical_padding">8dip</dimen> <dimen name="toolbar_button_horizontal_padding">8dip</dimen> - <!-- dimensions for the wallpaper picker wallpaper thumbnail width --> - <dimen name="wallpaper_chooser_grid_width">196dp</dimen> - <dimen name="wallpaper_chooser_grid_height">140dp</dimen> - <!-- When dragging items on the workspace, the number of dps by which the position of the drag view should be offset from the position of the original view. --> <dimen name="dragViewOffsetX">0dp</dimen> <dimen name="dragViewOffsetY">0dp</dimen> + + <dimen name="overview_panel_button_spacing">35dp</dimen> </resources> diff --git a/res/values-sw720dp/styles.xml b/res/values-sw720dp/styles.xml index 9738a124b..71f030400 100644 --- a/res/values-sw720dp/styles.xml +++ b/res/values-sw720dp/styles.xml @@ -18,57 +18,14 @@ --> <resources> -<!-- Clings --> - <style name="ClingButton"> - <item name="android:layout_width">wrap_content</item> - <item name="android:layout_height">wrap_content</item> - <item name="android:paddingTop">10dp</item> - <item name="android:paddingBottom">15dp</item> - <item name="android:paddingStart">35dp</item> - <item name="android:paddingEnd">35dp</item> - <item name="android:text">@string/cling_dismiss</item> - <item name="android:textSize">20sp</item> - <item name="android:textStyle">bold</item> - <item name="android:background">@drawable/cling_button_bg</item> - </style> - <style name="ClingTitleText"> - <item name="android:layout_width">wrap_content</item> - <item name="android:layout_height">wrap_content</item> - <item name="android:layout_marginBottom">5dp</item> - <item name="android:textSize">32sp</item> - <item name="android:textColor">#49C0EC</item> - <item name="android:shadowColor">#000000</item> - <item name="android:shadowDy">2</item> - <item name="android:shadowRadius">2.0</item> - </style> - <style name="ClingText"> - <item name="android:textSize">22sp</item> - <item name="android:textColor">#FFFFFF</item> - <item name="android:shadowColor">#000000</item> - <item name="android:shadowDy">2</item> - <item name="android:shadowRadius">2.0</item> - <item name="android:lineSpacingMultiplier">1.1</item> - </style> - <!-- Workspace --> - <style name="Theme" parent="android:Theme.Holo.Wallpaper.NoTitleBar"> - <item name="android:windowActionModeOverlay">true</item> - <item name="android:windowTranslucentStatus">true</item> - <item name="android:windowTranslucentNavigation">true</item> - </style> - <style name="TabIndicator.AppsCustomize"> - <item name="android:paddingStart">32dp</item> - <item name="android:paddingEnd">32dp</item> + <item name="android:paddingLeft">32dp</item> + <item name="android:paddingRight">32dp</item> <item name="android:textSize">14sp</item> <item name="android:maxWidth">240dp</item> </style> - <!-- QSB Search / Drop Target bar --> - <style name="QSBBar"> - </style> - <style name="SearchDropTargetBar"> - </style> <style name="SearchButton"> </style> <style name="DropTargetButtonContainer"> @@ -81,8 +38,8 @@ <item name="android:layout_gravity">center</item> <item name="android:gravity">center_vertical</item> <item name="android:drawablePadding">7.5dp</item> - <item name="android:paddingStart">60dp</item> - <item name="android:paddingEnd">60dp</item> + <item name="android:paddingLeft">60dp</item> + <item name="android:paddingRight">60dp</item> <item name="android:textColor">#FFFFFFFF</item> <item name="android:textSize">16sp</item> <item name="android:shadowColor">#393939</item> diff --git a/res/values-th/cm_arrays.xml b/res/values-th/cm_arrays.xml index 1f612140a..1fdc6cf54 100644 --- a/res/values-th/cm_arrays.xml +++ b/res/values-th/cm_arrays.xml @@ -16,15 +16,10 @@ limitations under the License. --> <resources> - <string-array name="preferences_interface_general_icons_text_font_family_entries"> - <item>ปกติ</item> - <item>บาง</item> - <item>บีบ</item> - </string-array> <string-array name="transition_effect_entries"> <item>ไม่มี</item> - <item>ขยาย</item> - <item>ย่อ</item> + <item>ซูมเข้า</item> + <item>ซูมออก</item> <item>หมุนขึ้น</item> <item>หมุนลง</item> <item>เข้าลูกบาศก์</item> diff --git a/res/values-th/cm_strings.xml b/res/values-th/cm_strings.xml index 8fc18cb92..a3ecfdf3c 100644 --- a/res/values-th/cm_strings.xml +++ b/res/values-th/cm_strings.xml @@ -16,49 +16,37 @@ limitations under the License. --> <resources> - <string name="application_copyright">สงวนลิขสิทธิ์ \u00A9 2014 The CyanogenMod Project</string> - <string name="sort_button_text">เรียงลำดับ</string> - <string name="filter_button_text">ตัวกรอง</string> - <string name="default_screen_button_text">หน้าจอเริ่มต้น</string> - <string name="transition_effect_button_text">เอฟเฟกต์เลื่อน</string> - <string name="sort_mode_title">ชื่อเรื่อง</string> - <string name="sort_mode_launch_count">ตัวนับครั้งการเปิด</string> - <string name="sort_mode_install_time">เวลาติดตั้ง</string> + <string name="launcher_settings">ตั้งค่าหน้าตัวเรียกใช้งาน</string> + <string name="home_screen_settings">ตั้งค่าหน้าจอหลัก</string> + <string name="drawer_settings">ตั้งค่าแผงแสดงแอป</string> + <string name="app_settings">ตั้งค่าแอป</string> + <string name="setting_state_on">เปิด</string> + <string name="setting_state_off">ปิด</string> + <string name="themes_button_text">ชุดรูปแบบ</string> <string name="scrolling_page_outlines">โครงร่างหน้า</string> <string name="scrolling_fade_adjacent">จากหน้าด้านข้าง</string> - <string name="wallpaper_scroll">เลื่อนภาพพื้นหลัง</string> - <string name="preferences_title">ตั้งค่า</string> - <string name="preferences_application_title">แอป</string> - <string name="preferences_interface_homescreen_title">หน้าจอหลัก</string> - <string name="preferences_interface_homescreen_search_title">แถบค้นหา</string> - <string name="preferences_interface_homescreen_search_summary">แสดงแถบค้นหาแบบคงที่ด้านบนของหน้าจอ</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_title">ซ่อนป้ายชื่อไอคอน</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">ซ่อนป้ายชื่อบนหน้าจอหลัก</string> - <string name="preferences_interface_drawer_title">พื้นที่วาง</string> - <string name="preferences_interface_drawer_summary">พื้นที่วางแอป และ วิดเจ็ท</string> - <string name="preferences_interface_drawer_apps_category">แอป</string> - <string name="preferences_interface_drawer_hidden_apps_title">ซ่อนแอป</string> - <string name="preferences_interface_drawer_hidden_apps_summary">ซ่อนแอปจากพื้นที่วางแอป</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">เอาทางลัดออก</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">เอาทางลัดของแอปที่ซ่อนออกจากหน้าจอหลัก</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_title">นำวิดเจ็ดออก</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_summary">นำวิดเจ็ทของแอปที่ถูกซ่อนออกจากจอหลัก</string> - <string name="preferences_interface_drawer_hide_icon_labels_title">ซ่อนป้ายชื่อไอคอน</string> - <string name="preferences_interface_drawer_hide_icon_labels_summary">ซ่อนป้ายชื่อไอคอนในที่วางแอป</string> - <string name="preferences_interface_dock_title">แถบวาง</string> - <string name="preferences_interface_general_title">ทั่วไป</string> - <string name="preferences_interface_general_icons_category">ไอคอน</string> - <string name="preferences_interface_general_icons_large_title">ไอคอนขนาดใหญ่</string> - <string name="preferences_interface_general_icons_large_summary">ใช้ไอคอนแอปพิเคชันขนาดใหญ่มากในจอหลักและที่วางแอป</string> - <string name="preferences_interface_general_icons_text_style_title">รูปแบบข้อความ</string> - <string name="preferences_interface_general_icons_text_style_summary">ลักษณะของแบบอักษรที่จะใช้สำหรับป้ายชื่อไอคอน</string> - <string name="dialog_pick_iconpack_title">เลือกชุดไอคอน</string> - <string name="default_iconpack_title">ไอคอนเริ่มต้น</string> - <string name="icon_packs_title">ชุดไอคอน</string> - <string name="no_iconpacks_summary">ไม่มีชุดไอคอนที่ติดตั้งอยู่</string> - <string name="clear_keyguard_wallpaper">ล้าง</string> - <string name="all_apps_cling_cm">กำหนดที่วางแอปของคุณ</string> - <string name="all_apps_cling_summary">แตะตัวแบ่งหน้าเพื่อดูการตั้งค่าเพิ่มเติม</string> - <string name="menu_hidden_apps_delete">ล้างค่า</string> + <string name="scrolling_wallpaper">เลื่อนภาพพื้นหลัง</string> + <string name="grid_size_text">ขนาดกริด</string> + <string name="grid_size_comfortable">สะดวกสบาย</string> + <string name="grid_size_cozy">โคซี่</string> + <string name="grid_size_condensed">บีบ</string> + <string name="grid_size_custom">กำหนดเอง</string> + <string name="preferences_interface_homescreen_custom">เลือกขนาดกำหนดเอง</string> + <string name="preferences_interface_homescreen_rows_title">จำนวนแถว</string> + <string name="preferences_interface_homescreen_columns_title">จำนวนคอลัมน์</string> <string name="hidden_apps_title">ซ่อนแอป</string> + <string name="scroll_effect_text">เอฟเฟกต์เลื่อน</string> + <string name="drawer_sorting_text">วิธีการเรียง</string> + <string name="sort_mode_title">ชื่อเรื่อง</string> + <string name="sort_mode_launch_count">ตัวนับครั้งการเปิด</string> + <string name="sort_mode_install_time">เวลาติดตั้ง</string> + <string name="home_screen_search_text">แถบค้นหา</string> + <string name="larger_icons_text">ไอคอนขนาดใหญ่</string> + <string name="icon_labels">ป้ายชื่อไอคอน</string> + <string name="icon_labels_show">แสดง</string> + <string name="icon_labels_hide">ซ่อน</string> + <string name="protected_app_settings">แอปที่ป้องกัน</string> + <string name="search_screen_left_text">แผงค้นหา</string> + <string name="search_screen_left_unsupported_toast">คุณต้องมีแอปที่รองรับการค้นหากับ CyanogenMod เพื่อใช้ความสามารถนี้</string> + <string name="dialog_confirm">Google</string> </resources> diff --git a/res/values-tr/cm_arrays.xml b/res/values-tr/cm_arrays.xml index 6631a719b..bfe889901 100644 --- a/res/values-tr/cm_arrays.xml +++ b/res/values-tr/cm_arrays.xml @@ -16,24 +16,19 @@ limitations under the License. --> <resources> - <string-array name="preferences_interface_general_icons_text_font_family_entries"> - <item>Normal</item> - <item>İnce</item> - <item>Kalın</item> - </string-array> <string-array name="transition_effect_entries"> <item>Hiçbiri</item> <item>Yakınlaştır</item> <item>Uzaklaştır</item> - <item>Yukarı Döndür</item> - <item>Aşağı Döndür</item> - <item>Kübün İçi</item> - <item>Kübün dışı</item> + <item>Yukarı döndür</item> + <item>Aşağı döndür</item> + <item>Küp içi</item> + <item>Küp dışı</item> <item>Yığın</item> <item>Akordiyon</item> <item>Çevir</item> - <item>Silindirin İçi</item> - <item>Silindirin Dışı</item> + <item>Silindir içi</item> + <item>Silindir dışı</item> <item>Karusel</item> <item>Genel Görünüm</item> </string-array> diff --git a/res/values-tr/cm_strings.xml b/res/values-tr/cm_strings.xml index 529b76b03..4a7db9ca2 100644 --- a/res/values-tr/cm_strings.xml +++ b/res/values-tr/cm_strings.xml @@ -16,49 +16,37 @@ limitations under the License. --> <resources> - <string name="application_copyright">Telif Hakkı \u00A9 2014 CyanogenMod Projesi</string> - <string name="sort_button_text">Sırala</string> - <string name="filter_button_text">Filtrele</string> - <string name="default_screen_button_text">Varsayılan ekran</string> - <string name="transition_effect_button_text">Kaydırma efekti</string> - <string name="sort_mode_title">Başlık</string> - <string name="sort_mode_launch_count">Çalıştırma sayısı</string> - <string name="sort_mode_install_time">Kurulum zamanı</string> + <string name="launcher_settings">BAŞLATICI AYARLARI</string> + <string name="home_screen_settings">ANA EKRAN AYARLARI</string> + <string name="drawer_settings">ÇEKMECE AYARLARI</string> + <string name="app_settings">UYGULAMA AYARLARI</string> + <string name="setting_state_on">AÇIK</string> + <string name="setting_state_off">KAPALI</string> + <string name="themes_button_text">Temalar</string> <string name="scrolling_page_outlines">Sayfa anahatları</string> <string name="scrolling_fade_adjacent">Yan sayfaları soldur</string> - <string name="wallpaper_scroll">Duvarkağıdını kaydır</string> - <string name="preferences_title">Ayarlar</string> - <string name="preferences_application_title">Uygulama</string> - <string name="preferences_interface_homescreen_title">Ana Ekran</string> - <string name="preferences_interface_homescreen_search_title">Arama çubuğu</string> - <string name="preferences_interface_homescreen_search_summary">Ekranın üstünde kalıcı arama çubuğu göster</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_title">Simge etiketlerini gizle</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">Ana ekranda simge etiketlerini gizle</string> - <string name="preferences_interface_drawer_title">Uygulama çekmecesi</string> - <string name="preferences_interface_drawer_summary">Uygulama ve widget çekmecesi</string> - <string name="preferences_interface_drawer_apps_category">Uygulamalar</string> - <string name="preferences_interface_drawer_hidden_apps_title">Gizli uygulamalar</string> - <string name="preferences_interface_drawer_hidden_apps_summary">Uygulamaları menüden gizle</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">Kısayolları kaldır</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">Ana ekrandan gizli uygulamaların kısayollarını kaldır</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_title">Widgetları kaldır</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_summary">Ana ekrandan gizli uygulamaların widgetlarını kaldır</string> - <string name="preferences_interface_drawer_hide_icon_labels_title">Simge etiketlerini gizle</string> - <string name="preferences_interface_drawer_hide_icon_labels_summary">Çekmecedeki simge etiketlerini gizle</string> - <string name="preferences_interface_dock_title">Ünite</string> - <string name="preferences_interface_general_title">Genel</string> - <string name="preferences_interface_general_icons_category">Simgeler</string> - <string name="preferences_interface_general_icons_large_title">Büyük simgeler</string> - <string name="preferences_interface_general_icons_large_summary">Ana ekranda ve uygulama çekmecesinde çok büyük uyg. simgeleri kullan</string> - <string name="preferences_interface_general_icons_text_style_title">Yazı tipi stili</string> - <string name="preferences_interface_general_icons_text_style_summary">Simge yazısı için yazı tipi</string> - <string name="dialog_pick_iconpack_title">Simge paketi seç</string> - <string name="default_iconpack_title">Varsayılan simgeler</string> - <string name="icon_packs_title">Simge paketleri</string> - <string name="no_iconpacks_summary">Yüklü simge paketi yok</string> - <string name="clear_keyguard_wallpaper">Temizle</string> - <string name="all_apps_cling_cm">Uygulama çekmecesini özelleştir</string> - <string name="all_apps_cling_summary">Ek ayarlara bakmak için sayfa göstergesine dokun</string> - <string name="menu_hidden_apps_delete">Sıfırla</string> + <string name="scrolling_wallpaper">Duvarkağıdını kaydır</string> + <string name="grid_size_text">Izgara boyutu</string> + <string name="grid_size_comfortable">Rahat</string> + <string name="grid_size_cozy">Rahat</string> + <string name="grid_size_condensed">Kalın</string> + <string name="grid_size_custom">Özel</string> + <string name="preferences_interface_homescreen_custom">Özel boyut seçin</string> + <string name="preferences_interface_homescreen_rows_title">Satır sayısı</string> + <string name="preferences_interface_homescreen_columns_title">Sütun sayısı</string> <string name="hidden_apps_title">Gizli uygulamalar</string> + <string name="scroll_effect_text">Kaydırma efekti</string> + <string name="drawer_sorting_text">Sıralama modu</string> + <string name="sort_mode_title">Başlık</string> + <string name="sort_mode_launch_count">Çalıştırma sayısı</string> + <string name="sort_mode_install_time">Kurulum zamanı</string> + <string name="home_screen_search_text">Arama çubuğu</string> + <string name="larger_icons_text">Daha büyük simgeler</string> + <string name="icon_labels">Simge etiketleri</string> + <string name="icon_labels_show">Göster</string> + <string name="icon_labels_hide">Gizle</string> + <string name="protected_app_settings">Korunan uygulamalar</string> + <string name="search_screen_left_text">Arama paneli</string> + <string name="search_screen_left_unsupported_toast">Bu özelliği kullanabilmeniz için desteklenen bir arama uygulaması ve CyanogenMod\'a sahip olmanız gerekiyor.</string> + <string name="dialog_confirm">Onayla</string> </resources> diff --git a/res/values-uk/cm_arrays.xml b/res/values-uk/cm_arrays.xml index 69fc3dfe5..63cab2291 100644 --- a/res/values-uk/cm_arrays.xml +++ b/res/values-uk/cm_arrays.xml @@ -16,24 +16,19 @@ limitations under the License. --> <resources> - <string-array name="preferences_interface_general_icons_text_font_family_entries"> - <item>Звичайний</item> - <item>Легкий</item> - <item>Стиснутий</item> - </string-array> <string-array name="transition_effect_entries"> <item>Немає</item> - <item>Збільшення</item> - <item>Зменшення</item> - <item>Поворот вверх</item> - <item>Поворот вниз</item> - <item>В середині куба</item> - <item>Ззовні куба</item> + <item>Zoom in</item> + <item>Zoom out</item> + <item>Rotate up</item> + <item>Rotate down</item> + <item>Cube in</item> + <item>Cube out</item> <item>Стек</item> <item>Гармошка</item> <item>Переворот</item> - <item>В середині циліндра</item> - <item>Ззовні циліндра</item> + <item>Cylinder in</item> + <item>Cylinder out</item> <item>Карусель</item> <item>Огляд</item> </string-array> diff --git a/res/values-uk/cm_strings.xml b/res/values-uk/cm_strings.xml index 005ef45e7..1c975b681 100644 --- a/res/values-uk/cm_strings.xml +++ b/res/values-uk/cm_strings.xml @@ -16,49 +16,10 @@ limitations under the License. --> <resources> - <string name="application_copyright">Всі права захищені \u00A9 2014 The CyanogenMod Project</string> - <string name="sort_button_text">Сортувати</string> - <string name="filter_button_text">Фільтр</string> - <string name="default_screen_button_text">Екран за замовчуванням</string> - <string name="transition_effect_button_text">Ефект гортання</string> - <string name="sort_mode_title">По назві</string> - <string name="sort_mode_launch_count">По частоті використання</string> - <string name="sort_mode_install_time">По часу встановлення</string> <string name="scrolling_page_outlines">Межі сторінок</string> <string name="scrolling_fade_adjacent">Затемняти краї при гортанні</string> - <string name="wallpaper_scroll">Прокручувати шпалери</string> - <string name="preferences_title">Налаштування</string> - <string name="preferences_application_title">Програма</string> - <string name="preferences_interface_homescreen_title">Домашній екран</string> - <string name="preferences_interface_homescreen_search_title">Рядок пошуку</string> - <string name="preferences_interface_homescreen_search_summary">Завжди показувати рядок пошуку зверху екрану</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_title">Приховувати підписи значків</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">Не відображати текст ярликів на домашньому екрані</string> - <string name="preferences_interface_drawer_title">Меню програм</string> - <string name="preferences_interface_drawer_summary">Список програм і віджетів</string> - <string name="preferences_interface_drawer_apps_category">Програми</string> - <string name="preferences_interface_drawer_hidden_apps_title">Приховані програми</string> - <string name="preferences_interface_drawer_hidden_apps_summary">Приховати програми з меню програм</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">Видаляти ярлики</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">Прибирати ярлики прихованих програм з домашнього екрану</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_title">Видаляти віджети</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_summary">Прибирати віджети прихованих програм з домашнього екрану</string> - <string name="preferences_interface_drawer_hide_icon_labels_title">Приховувати підписи значків</string> - <string name="preferences_interface_drawer_hide_icon_labels_summary">Не відображати текст ярликів в меню програм</string> - <string name="preferences_interface_dock_title">Нижня панель</string> - <string name="preferences_interface_general_title">Загальні</string> - <string name="preferences_interface_general_icons_category">Значки</string> - <string name="preferences_interface_general_icons_large_title">Великі значки</string> - <string name="preferences_interface_general_icons_large_summary">Використовувати великі значки на домашньому екрані та меню програм</string> - <string name="preferences_interface_general_icons_text_style_title">Стиль шрифту</string> - <string name="preferences_interface_general_icons_text_style_summary">Стиль та варіант шрифту для тексту під значками</string> - <string name="dialog_pick_iconpack_title">Вибрати набір значків</string> - <string name="default_iconpack_title">Типові значки</string> - <string name="icon_packs_title">Набори значків</string> - <string name="no_iconpacks_summary">Жодного набору значків не встановлено</string> - <string name="clear_keyguard_wallpaper">Очистити</string> - <string name="all_apps_cling_cm">Налаштуйте меню програм</string> - <string name="all_apps_cling_summary">Торкніться індикатора сторінки знизу, щоб перейти до налаштувань</string> - <string name="menu_hidden_apps_delete">Скидання</string> <string name="hidden_apps_title">Приховані програми</string> + <string name="sort_mode_title">По назві</string> + <string name="sort_mode_launch_count">По частоті використання</string> + <string name="sort_mode_install_time">По часу встановлення</string> </resources> diff --git a/res/values-v17/styles.xml b/res/values-v17/styles.xml new file mode 100644 index 000000000..71c4bfa66 --- /dev/null +++ b/res/values-v17/styles.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <style name="PagedViewWidgetImageView"> + <item name="android:paddingStart">@dimen/app_widget_preview_padding_left</item> + </style> + <style name="SearchButton.WithPaddingStart"> + <item name="android:paddingStart">8dp</item> + </style> +</resources> diff --git a/res/values-zh-rCN/cm_arrays.xml b/res/values-zh-rCN/cm_arrays.xml index 0e02c2853..0c16fd116 100644 --- a/res/values-zh-rCN/cm_arrays.xml +++ b/res/values-zh-rCN/cm_arrays.xml @@ -16,11 +16,6 @@ limitations under the License. --> <resources> - <string-array name="preferences_interface_general_icons_text_font_family_entries"> - <item>常规</item> - <item>Light</item> - <item>Condensed</item> - </string-array> <string-array name="transition_effect_entries"> <item>无</item> <item>放大</item> diff --git a/res/values-zh-rCN/cm_strings.xml b/res/values-zh-rCN/cm_strings.xml index 408769dac..2c617d8e2 100644 --- a/res/values-zh-rCN/cm_strings.xml +++ b/res/values-zh-rCN/cm_strings.xml @@ -16,49 +16,38 @@ limitations under the License. --> <resources> - <string name="application_copyright">版权所有 \u00A9 2014 CyanogenMod 项目</string> - <string name="sort_button_text">排序</string> - <string name="filter_button_text">过滤器</string> - <string name="default_screen_button_text">默认屏幕</string> - <string name="transition_effect_button_text">滚动特效</string> - <string name="sort_mode_title">标题</string> - <string name="sort_mode_launch_count">启动次数</string> - <string name="sort_mode_install_time">安装时间</string> + <string name="launcher_settings">启动器设置</string> + <string name="home_screen_settings">主屏幕设置</string> + <string name="drawer_settings">抽屉设置</string> + <string name="app_settings">应用设置</string> + <string name="setting_state_on">打开</string> + <string name="setting_state_off">关闭</string> + <string name="themes_button_text">主题</string> <string name="scrolling_page_outlines">页概述</string> <string name="scrolling_fade_adjacent">边页淡出</string> - <string name="wallpaper_scroll">滚动壁纸</string> - <string name="preferences_title">设置</string> - <string name="preferences_application_title">应用程序</string> - <string name="preferences_interface_homescreen_title">主屏</string> - <string name="preferences_interface_homescreen_search_title">搜索栏</string> - <string name="preferences_interface_homescreen_search_summary">在屏幕上方始终显示搜索栏</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_title">隐藏图标标签</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">在主屏幕上隐藏图标标签</string> - <string name="preferences_interface_drawer_title">抽屉</string> - <string name="preferences_interface_drawer_summary">应用和小部件抽屉</string> - <string name="preferences_interface_drawer_apps_category">应用</string> - <string name="preferences_interface_drawer_hidden_apps_title">隐藏的应用</string> - <string name="preferences_interface_drawer_hidden_apps_summary">从抽屉隐藏应用</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">移除快捷方式</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">从主屏幕移除已隐藏应用的快捷方式</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_title">移除小部件</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_summary">从主屏幕移除已隐藏应用的小部件</string> - <string name="preferences_interface_drawer_hide_icon_labels_title">隐藏图标标签</string> - <string name="preferences_interface_drawer_hide_icon_labels_summary">在抽屉里隐藏图标标签</string> - <string name="preferences_interface_dock_title">基座</string> - <string name="preferences_interface_general_title">通用</string> - <string name="preferences_interface_general_icons_category">图标</string> - <string name="preferences_interface_general_icons_large_title">大图标</string> - <string name="preferences_interface_general_icons_large_summary">显示大图标</string> - <string name="preferences_interface_general_icons_text_style_title">字体样式</string> - <string name="preferences_interface_general_icons_text_style_summary">图标字体样式</string> - <string name="dialog_pick_iconpack_title">选择图标包</string> - <string name="default_iconpack_title">默认图标</string> - <string name="icon_packs_title">图标包</string> - <string name="no_iconpacks_summary">没有安装的图标包</string> - <string name="clear_keyguard_wallpaper">清除</string> - <string name="all_apps_cling_cm">自定义抽屉</string> - <string name="all_apps_cling_summary">点击页面指示器以查看其他设置</string> - <string name="menu_hidden_apps_delete">重置</string> + <string name="scrolling_wallpaper">滚动壁纸</string> + <string name="grid_size_text">网格大小</string> + <string name="grid_size_comfortable">宽松</string> + <string name="grid_size_cozy">合适</string> + <string name="grid_size_condensed">紧凑</string> + <string name="grid_size_custom">自定义 +</string> + <string name="preferences_interface_homescreen_custom">选择自定义尺寸</string> + <string name="preferences_interface_homescreen_rows_title">行数</string> + <string name="preferences_interface_homescreen_columns_title">列数</string> <string name="hidden_apps_title">隐藏的应用</string> + <string name="scroll_effect_text">滚动特效</string> + <string name="drawer_sorting_text">排序模式</string> + <string name="sort_mode_title">标题</string> + <string name="sort_mode_launch_count">启动次数</string> + <string name="sort_mode_install_time">安装时间</string> + <string name="home_screen_search_text">搜索栏</string> + <string name="larger_icons_text">大图标</string> + <string name="icon_labels">图标标签</string> + <string name="icon_labels_show">显示</string> + <string name="icon_labels_hide">隐藏</string> + <string name="protected_app_settings">受保护的应用</string> + <string name="search_screen_left_text">搜索面板</string> + <string name="search_screen_left_unsupported_toast">您必须有一个受支持的搜索应用和 CyanogenMod 以使用此功能。</string> + <string name="dialog_confirm">确认</string> </resources> diff --git a/res/values-zh-rHK/cm_arrays.xml b/res/values-zh-rHK/cm_arrays.xml index b589a80ea..9c806f151 100644 --- a/res/values-zh-rHK/cm_arrays.xml +++ b/res/values-zh-rHK/cm_arrays.xml @@ -16,24 +16,19 @@ limitations under the License. --> <resources> - <string-array name="preferences_interface_general_icons_text_font_family_entries"> - <item>正常</item> - <item>明亮</item> - <item>簡明</item> - </string-array> <string-array name="transition_effect_entries"> <item>無</item> <item>放大</item> <item>縮小</item> <item>向上旋轉</item> - <item>向下旋轉</item> - <item>Cube In</item> - <item>Cube Out</item> + <item>Rotate down</item> + <item>Cube in</item> + <item>Cube out</item> <item>堆疊</item> <item>手風琴</item> <item>翻轉</item> - <item>膛入</item> - <item>膛出</item> + <item>Cylinder in</item> + <item>Cylinder out</item> <item>幻燈片 </item> <item>概述</item> </string-array> diff --git a/res/values-zh-rHK/cm_strings.xml b/res/values-zh-rHK/cm_strings.xml index ce4bfcf4f..0b720c055 100644 --- a/res/values-zh-rHK/cm_strings.xml +++ b/res/values-zh-rHK/cm_strings.xml @@ -16,49 +16,20 @@ limitations under the License. --> <resources> - <string name="application_copyright">版權所有 \u00A9 2013年 CyanogenMod 計畫</string> - <string name="sort_button_text">排序</string> - <string name="filter_button_text">篩選過濾</string> - <string name="default_screen_button_text">預設螢幕</string> - <string name="transition_effect_button_text">滾動效果</string> - <string name="sort_mode_title">標題</string> - <string name="sort_mode_launch_count">啟動次數</string> - <string name="sort_mode_install_time">安裝時間</string> + <string name="launcher_settings">啟動器設定</string> + <string name="home_screen_settings">主螢幕設定</string> + <string name="drawer_settings">抽屜設定</string> + <string name="setting_state_on">開啟</string> + <string name="setting_state_off">關閉</string> + <string name="themes_button_text">主題</string> <string name="scrolling_page_outlines">頁面輪廓</string> <string name="scrolling_fade_adjacent">邊頁淡出</string> - <string name="wallpaper_scroll">滾動牆紙</string> - <string name="preferences_title">設定</string> - <string name="preferences_application_title">應用程式</string> - <string name="preferences_interface_homescreen_title">主螢幕</string> - <string name="preferences_interface_homescreen_search_title">搜尋欄</string> - <string name="preferences_interface_homescreen_search_summary">在螢幕上方顯示搜尋欄</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_title">隱藏圖示標籤</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">隱藏主螢幕的圖示標籤</string> - <string name="preferences_interface_drawer_title">抽屜</string> - <string name="preferences_interface_drawer_summary">應用程式和小工具的抽屜</string> - <string name="preferences_interface_drawer_apps_category">應用程式</string> - <string name="preferences_interface_drawer_hidden_apps_title">隱藏的應用程式</string> - <string name="preferences_interface_drawer_hidden_apps_summary">隱藏從抽屜的應用程式</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">移除捷徑</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">從主螢幕移除已隱藏的應用程式捷徑</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_title">移除小工具</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_summary">從主螢幕移除已隱藏的應用程式小工具</string> - <string name="preferences_interface_drawer_hide_icon_labels_title">隱藏圖示標籤</string> - <string name="preferences_interface_drawer_hide_icon_labels_summary">隱藏在抽屜裡的圖示標籤</string> - <string name="preferences_interface_dock_title">基座</string> - <string name="preferences_interface_general_title">一般</string> - <string name="preferences_interface_general_icons_category">圖示</string> - <string name="preferences_interface_general_icons_large_title">大圖示</string> - <string name="preferences_interface_general_icons_large_summary">使用超大的應用程序圖標於主螢幕和抽屜</string> - <string name="preferences_interface_general_icons_text_style_title">字體風格</string> - <string name="preferences_interface_general_icons_text_style_summary">變體和字體風格用來應用於圖示的文本上</string> - <string name="dialog_pick_iconpack_title">選擇圖示包</string> - <string name="default_iconpack_title">預設圖示</string> - <string name="icon_packs_title">圖示包</string> - <string name="no_iconpacks_summary">沒有安裝圖示包</string> - <string name="clear_keyguard_wallpaper">清除</string> - <string name="all_apps_cling_cm">自訂您的抽屜</string> - <string name="all_apps_cling_summary">點擊頁面指標來查看其他配置設定</string> - <string name="menu_hidden_apps_delete">重設</string> <string name="hidden_apps_title">隱藏的應用程式</string> + <string name="scroll_effect_text">滾動效果</string> + <string name="drawer_sorting_text">排序模式</string> + <string name="sort_mode_title">標題</string> + <string name="sort_mode_launch_count">啟動次數</string> + <string name="sort_mode_install_time">安裝時間</string> + <string name="home_screen_search_text">搜尋列</string> + <string name="larger_icons_text">大圖示</string> </resources> diff --git a/res/values-zh-rTW/cm_arrays.xml b/res/values-zh-rTW/cm_arrays.xml new file mode 100644 index 000000000..a5b57d64c --- /dev/null +++ b/res/values-zh-rTW/cm_arrays.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="utf-8"?> +<!--Generated by crowdin.net--> +<!-- + Copyright (C) 2014 The CyanogenMod 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. +--> +<resources> + <string-array name="transition_effect_entries"> + <item>無</item> + <item>Zoom in</item> + <item>Zoom out</item> + <item>Rotate up</item> + <item>Rotate down</item> + <item>Cube in</item> + <item>Cube out</item> + <item>Stack</item> + <item>手風琴</item> + <item>Flip</item> + <item>Cylinder in</item> + <item>Cylinder out</item> + <item>Carousel</item> + <item>概述</item> + </string-array> +</resources> diff --git a/res/values-zh-rTW/cm_strings.xml b/res/values-zh-rTW/cm_strings.xml new file mode 100644 index 000000000..acec787c7 --- /dev/null +++ b/res/values-zh-rTW/cm_strings.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="utf-8"?> +<!--Generated by crowdin.net--> +<!-- + Copyright (C) 2014 The CyanogenMod 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. +--> +<resources> + <string name="setting_state_on">開啟</string> + <string name="setting_state_off">關閉</string> + <string name="themes_button_text">主題</string> + <string name="scrolling_fade_adjacent">邊頁淡出</string> + <string name="hidden_apps_title">隱藏的應用程式</string> + <string name="sort_mode_title">標題</string> + <string name="sort_mode_launch_count">啟動次數</string> + <string name="sort_mode_install_time">安裝時間</string> + <string name="home_screen_search_text">搜尋列</string> + <string name="larger_icons_text">大圖示</string> +</resources> diff --git a/res/values/attrs.xml b/res/values/attrs.xml index a2d3a83e0..c64b4f9ec 100644 --- a/res/values/attrs.xml +++ b/res/values/attrs.xml @@ -103,8 +103,7 @@ <attr name="pageLayoutPaddingBottom" format="dimension" /> <attr name="pageLayoutPaddingLeft" format="dimension" /> <attr name="pageLayoutPaddingRight" format="dimension" /> - <!-- The space between adjacent pages of the PagedView. --> - <attr name="pageSpacing" format="dimension" /> + <!-- The page indicator for this workspace --> <attr name="pageIndicator" format="reference" /> </declare-styleable> @@ -157,4 +156,15 @@ </declare-styleable> <declare-styleable name="CustomClingText"> </declare-styleable> + + <declare-styleable name="SlidingUpPanelLayout"> + <attr name="panelHeight" format="dimension" /> + <attr name="shadowHeight" format="dimension" /> + <attr name="paralaxOffset" format="dimension" /> + <attr name="fadeColor" format="color" /> + <attr name="flingVelocity" format="integer" /> + <attr name="dragView" format="reference" /> + <attr name="overlay" format="boolean"/> + </declare-styleable> + </resources> diff --git a/res/values/cm_arrays.xml b/res/values/cm_arrays.xml index 502b7a65c..e8b02dbcb 100644 --- a/res/values/cm_arrays.xml +++ b/res/values/cm_arrays.xml @@ -15,30 +15,19 @@ limitations under the License. --> <resources> - <string-array name="preferences_interface_general_icons_text_font_family_entries"> - <item>Regular</item> - <item>Light</item> - <item>Condensed</item> - </string-array> - <string-array name="preferences_interface_general_icons_text_font_family_values" translatable="false"> - <item>sans-serif</item> - <item>sans-serif-light</item> - <item>sans-serif-condensed</item> - </string-array> - <string-array name="transition_effect_entries"> <item>None</item> - <item>Zoom In</item> - <item>Zoom Out</item> - <item>Rotate Up</item> - <item>Rotate Down</item> - <item>Cube In</item> - <item>Cube Out</item> + <item>Zoom in</item> + <item>Zoom out</item> + <item>Rotate up</item> + <item>Rotate down</item> + <item>Cube in</item> + <item>Cube out</item> <item>Stack</item> <item>Accordion</item> <item>Flip</item> - <item>Cylinder In</item> - <item>Cylinder Out</item> + <item>Cylinder in</item> + <item>Cylinder out</item> <item>Carousel</item> <item>Overview</item> </string-array> @@ -58,4 +47,20 @@ <item>carousel</item> <item>overview</item> </string-array> + <string-array name="transition_effect_drawables" translatable="false"> + <item>@drawable/transition_none</item> + <item>@drawable/transition_zoomin</item> + <item>@drawable/transition_zoomout</item> + <item>@drawable/transition_rotateup</item> + <item>@drawable/transition_rotatedown</item> + <item>@drawable/transition_cubein</item> + <item>@drawable/transition_cubeout</item> + <item>@drawable/transition_stack</item> + <item>@drawable/transition_accordion</item> + <item>@drawable/transition_flip</item> + <item>@drawable/transition_cylinderin</item> + <item>@drawable/transition_cylinderout</item> + <item>@drawable/transition_carousel</item> + <item>@drawable/transition_overview</item> + </string-array> </resources> diff --git a/res/values/cm_integers.xml b/res/values/cm_integers.xml new file mode 100644 index 000000000..f3b0464ef --- /dev/null +++ b/res/values/cm_integers.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2014 The CyanogenMod 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. +--> +<resources> + <integer name="qsb_initial_alpha_state">55</integer> + <integer name="qsb_end_alpha_state">220</integer> + <integer name="qsb_buttons_end_colorfilter">120</integer> +</resources> diff --git a/res/values/cm_strings.xml b/res/values/cm_strings.xml index d4effcc40..b924922fb 100644 --- a/res/values/cm_strings.xml +++ b/res/values/cm_strings.xml @@ -17,86 +17,74 @@ <resources> <!-- Application name --> <string name="cm_application_name" translatable="false">Trebuchet</string> - <!-- App copyright --> - <string name="application_copyright">Copyright \u00A9 2014 The CyanogenMod Project</string> <!-- App version --> <string name="application_version" translatable="false">1.0</string> - <!-- Strings for the customization mode --> - <!-- Text for sorting mode button --> - <string name="sort_button_text">Sort</string> - <!-- Text for filter button --> - <string name="filter_button_text">Filter</string> - <!-- Text for default screen button --> - <string name="default_screen_button_text">Default screen</string> - <!-- Text for transition effect button --> - <string name="transition_effect_button_text">Scroll effect</string> + <string name="launcher_settings">LAUNCHER SETTINGS</string> + <string name="home_screen_settings">HOME SCREEN SETTINGS</string> + <string name="drawer_settings">DRAWER SETTINGS</string> + <string name="app_settings">APP SETTINGS</string> - <string name="sort_mode_title">Title</string> - <string name="sort_mode_launch_count">Launch count</string> - <string name="sort_mode_install_time">Install time</string> + <!-- Settings states --> + <string name="setting_state_on">ON</string> + <string name="setting_state_off">OFF</string> + + <!-- Themes button --> + <string name="themes_button_text">Themes</string> <string name="scrolling_page_outlines">Page outlines</string> <string name="scrolling_fade_adjacent">Fade side pages</string> + <!-- Wallpaper scroll effect --> + <string name="scrolling_wallpaper">Scroll wallpaper</string> - <string name="wallpaper_scroll">Scroll wallpaper</string> - - <!-- Settings --> - <string name="preferences_title">Settings</string> - <!-- Application --> - <string name="preferences_application_title">App</string> - - <!-- UI --> - <!-- Homescreen --> - <string name="preferences_interface_homescreen_title">Homescreen</string> - <string name="preferences_interface_homescreen_search_title">Search bar</string> - <string name="preferences_interface_homescreen_search_summary">Show persistent search bar at top of screen</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_title">Hide icon labels</string> - <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">Hide icon labels on homescreen</string> - - <!-- Drawer --> - <string name="preferences_interface_drawer_title">Drawer</string> - <string name="preferences_interface_drawer_summary">Apps and widgets drawer</string> - <string name="preferences_interface_drawer_apps_category">Apps</string> - <string name="preferences_interface_drawer_hidden_apps_title">Hidden apps</string> - <string name="preferences_interface_drawer_hidden_apps_summary">Hide apps from the drawer</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">Remove shortcuts</string> - <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">Remove the shortcuts of hidden apps from the homescreen</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_title">Remove widgets</string> - <string name="preferences_interface_drawer_hidden_apps_widgets_summary">Remove the widgets of hidden apps from the homescreen</string> - <string name="preferences_interface_drawer_hide_icon_labels_title">Hide icon labels</string> - <string name="preferences_interface_drawer_hide_icon_labels_summary">Hide icon labels in drawer</string> - - <!-- Dock --> - <string name="preferences_interface_dock_title">Dock</string> - - <!-- General --> - <string name="preferences_interface_general_title">General</string> - <string name="preferences_interface_general_icons_category">Icons</string> - <string name="preferences_interface_general_icons_large_title">Larger icons</string> - <string name="preferences_interface_general_icons_large_summary">Use extra large application icons in homescreen and drawer</string> - <string name="preferences_interface_general_icons_text_style_title">Text font style</string> - <string name="preferences_interface_general_icons_text_style_summary">Variant and style of font to use for icon text</string> - <string name="dialog_pick_iconpack_title">Pick icon pack</string> - <string name="default_iconpack_title">Default icons</string> - <string name="icon_packs_title">Icon packs</string> - <string name="no_iconpacks_summary">No icon packs installed</string> + <!-- Dynamic Grid --> + <string name="grid_size_text">Grid size</string> + <string name="grid_size_comfortable">Comfortable</string> + <string name="grid_size_cozy">Cozy</string> + <string name="grid_size_condensed">Condensed</string> + <string name="grid_size_custom">Custom</string> + <string name="preferences_interface_homescreen_custom">Select custom size</string> + <string name="preferences_interface_homescreen_rows_title">Number of rows</string> + <string name="preferences_interface_homescreen_columns_title">Number of columns</string> <!-- Folder titles --> <string name="google_title" translatable="false">Google</string> - <!-- Clear keyguard wallpaper tile text --> - <string name="clear_keyguard_wallpaper">Clear</string> + <!-- Hidden apps --> + <string name="hidden_apps_title">Hidden apps</string> - <!-- The title text for the all apps cling [CHAR_LIMIT=60] --> - <string name="all_apps_cling_cm">Customize your drawer</string> - <!-- The description of how to access Trebuchet settings [CHAR_LIMIT=160] --> - <string name="all_apps_cling_summary">Tap the page indicator to view additional configuration settings</string> + <!-- Scroll effect --> + <string name="scroll_effect_text">Scroll effect</string> - <!-- Noun, menu item used to reset hidden apps list --> - <string name="menu_hidden_apps_delete">Reset</string> + <!-- Drawer sorting mode --> + <string name="drawer_sorting_text">Sorting mode</string> + + <string name="sort_mode_title">Title</string> + <string name="sort_mode_launch_count">Launch count</string> + <string name="sort_mode_install_time">Install time</string> + + <!-- Home screen search bar --> + <string name="home_screen_search_text">Search bar</string> + + <!-- Larger icons --> + <string name="larger_icons_text">Larger icons</string> + + <!-- Icon labels --> + <string name="icon_labels">Icon labels</string> + <string name="icon_labels_show">Show</string> + <string name="icon_labels_hide">Hide</string> + + <!-- Protected apps --> + <string name="protected_app_settings">Protected apps</string> + + <!-- Text for hiding/showing search screen on left (if installed) --> + <string name="search_screen_left_text">Search panel</string> + + <!-- Toast message when search screen on left is not supported --> + <string name="search_screen_left_unsupported_toast">You must have a supported search app and CyanogenMod to use this feature.</string> + + <!-- Dialog --> + <string name="dialog_confirm">Confirm</string> - <!-- Hidden apps --> - <string name="hidden_apps_title">Hidden apps</string> </resources> diff --git a/res/values/colors.xml b/res/values/colors.xml index dc35a3f68..434cdf9e5 100644 --- a/res/values/colors.xml +++ b/res/values/colors.xml @@ -32,9 +32,15 @@ <color name="workspace_icon_text_color">#FFF</color> <color name="apps_customize_icon_text_color">#FFF</color> - <color name="wallpaper_picker_translucent_gray">#66000000</color> <color name="folder_items_text_color">#FF333333</color> + <color name="folder_items_glow_color">#FFCCCCCC</color> <color name="outline_color">#FFFFFFFF</color> - + <color name="first_run_cling_circle_background_color">#64b1ea</color> + + <color name="settings_header_text">#FF6cd2ea</color> + <color name="settings_bg_color">#FF485459</color> + <color name="settings_bg_header_color">#FFb2b0ab</color> + <color name="settings_bg_selected_color">#26000000</color> + <color name="settings_transition_selected_color">#50000000</color> </resources> diff --git a/res/values/config.xml b/res/values/config.xml index b7880fe1f..003de5ae5 100644 --- a/res/values/config.xml +++ b/res/values/config.xml @@ -1,4 +1,14 @@ <resources> +<!-- Dynamic Grid --> + <integer name="config_dynamic_grid_max_long_edge_cell_count">6</integer> + <integer name="config_dynamic_grid_max_short_edge_cell_count">5</integer> + <integer name="config_dynamic_grid_min_edge_cell_count">3</integer> + <!-- Out of 100, the percent of space the overview bar should try and take vertically. --> + <integer name="config_dynamic_grid_overview_icon_zone_percentage">20</integer> + <!-- Out of 100, the percent to shrink the workspace during overview mode. --> + <integer name="config_dynamic_grid_overview_scale_percentage">80</integer> + +<!-- Miscellaneous --> <bool name="config_largeHeap">false</bool> <bool name="is_tablet">false</bool> <bool name="is_large_tablet">false</bool> @@ -19,8 +29,9 @@ <!-- Out of 100, the percent to shrink the workspace during spring loaded mode. --> <integer name="config_workspaceSpringLoadShrinkPercentage">80</integer> + <!-- Out of 100, the percent to shrink the workspace during overview mode. --> - <integer name="config_workspaceOverviewShrinkPercentage">58</integer> + <integer name="config_workspaceOverviewShrinkPercentage">90</integer> <!-- Fade/zoom in/out duration & scale in the AllApps transition. Note: This should be less than the workspaceShrinkTime as they happen together. --> @@ -91,4 +102,7 @@ filter the activities shown in the launcher. Can be empty. --> <string name="app_filter_class" translatable="false"></string> + <!-- Name of a subclass of com.android.launcher3.BuildInfo used to + get build information. Can be empty. --> + <string name="build_info_class" translatable="false"></string> </resources> diff --git a/res/values/dimens.xml b/res/values/dimens.xml index 3b692a1d1..9641269aa 100644 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -20,11 +20,13 @@ <dimen name="dynamic_grid_search_bar_max_width">500dp</dimen> <dimen name="dynamic_grid_search_bar_height">48dp</dimen> <dimen name="dynamic_grid_page_indicator_height">24dp</dimen> - -<!-- Wallpaper picker --> - <dimen name="wallpaperThumbnailWidth">106.5dp</dimen> - <dimen name="wallpaperThumbnailHeight">94.5dp</dimen> - <dimen name="wallpaperItemIconSize">32dp</dimen> + <dimen name="dynamic_grid_icon_drawable_padding">4dp</dimen> + <dimen name="dynamic_grid_all_apps_cell_padding">18dp</dimen> + <dimen name="dynamic_grid_workspace_page_spacing">8dp</dimen> + <dimen name="dynamic_grid_overview_min_icon_zone_height">80dp</dimen> + <dimen name="dynamic_grid_overview_max_icon_zone_height">120dp</dimen> + <dimen name="dynamic_grid_overview_bar_item_width">48dp</dimen> + <dimen name="dynamic_grid_overview_bar_spacer_width">68dp</dimen> <!-- Cling --> <dimen name="clingPunchThroughGraphicCenterRadius">94dp</dimen> @@ -36,15 +38,23 @@ <add-resource type="dimen" name="custom_cling_margin_top" /> <add-resource type="dimen" name="custom_cling_margin_right" /> <add-resource type="dimen" name="custom_cling_margin_left" /> + + <dimen name="cling_title_text_size">20sp</dimen> + <dimen name="cling_text_size">14sp</dimen> + <dimen name="cling_alt_title_text_size">24sp</dimen> + <dimen name="cling_alt_text_size">16sp</dimen> + <dimen name="cling_hint_text_size">14sp</dimen> <!-- Workspace --> <dimen name="workspace_max_gap">16dp</dimen> <dimen name="workspace_overscroll_drawable_padding">0dp</dimen> - <dimen name="workspace_spring_loaded_page_spacing">15dp</dimen> <dimen name="overview_panel_top_padding">20dp</dimen> <dimen name="overview_panel_bottom_padding">50dp</dimen> <dimen name="overview_panel_button_spacing">30dp</dimen> - <dimen name="overview_mode_page_offset">130dp</dimen> + <dimen name="overview_panel_handle_size">30dp</dimen> + <dimen name="overview_mode_page_offset">60dp</dimen> + <dimen name="sliding_panel_padding">175dp</dimen> + <dimen name="overview_scaling_padding">50dp</dimen> <!-- QSB --> <dimen name="toolbar_button_vertical_padding">4dip</dimen> @@ -98,4 +108,17 @@ <!-- The amount that the preview contents are inset from the preview background --> <dimen name="folder_preview_padding">4dp</dimen> <dimen name="folder_name_padding">10dp</dimen> + <dimen name="folder_lock_icon">50dp</dimen> + + <!-- Settings Pane dimen --> + <dimen name="settings_pane_handle">48dp</dimen> + + <!-- Dynamic Grid settings --> + <dimen name="dialog_padding">10dp</dimen> + + <dimen name="grid_padding">15dp</dimen> + <dimen name="grid_custom_text">50dp</dimen> + + <dimen name="dynamic_grid_size_image_width">150dp</dimen> + <dimen name="dynamic_grid_size_image_height">150dp</dimen> </resources> diff --git a/res/values/preferences_defaults.xml b/res/values/preferences_defaults.xml index 98d8bb7a8..64d904a0f 100644 --- a/res/values/preferences_defaults.xml +++ b/res/values/preferences_defaults.xml @@ -1,6 +1,7 @@ <?xml version="1.0" encoding="utf-8"?> <resources> <bool name="preferences_interface_homescreen_search_default">true</bool> + <bool name="preferences_interface_homescreen_search_screen_left_default">false</bool> <string name="preferences_interface_homescreen_scrolling_transition_effect">none</string> <bool name="preferences_interface_homescreen_scrolling_wallpaper_scroll_default">true</bool> <bool name="preferences_interface_homescreen_scrolling_page_outlines_default">@bool/config_workspaceDefaultShowOutlines</bool> @@ -8,10 +9,8 @@ <bool name="preferences_interface_homescreen_hide_icon_labels_default">false</bool> <string name="preferences_interface_drawer_scrolling_transition_effect">stack</string> <bool name="preferences_interface_drawer_scrolling_fade_adjacent_default">false</bool> - <bool name="preferences_interface_drawer_remove_hidden_apps_shortcuts_default">false</bool> - <bool name="preferences_interface_drawer_remove_hidden_apps_widgets_default">false</bool> + <bool name="preferences_interface_drawer_remove_hidden_apps_shortcuts_default">true</bool> + <bool name="preferences_interface_drawer_remove_hidden_apps_widgets_default">true</bool> <bool name="preferences_interface_drawer_hide_icon_labels_default">false</bool> <bool name="preferences_interface_general_icons_large_default">@bool/config_largeIcons</bool> - <string name="preferences_interface_general_icons_text_font_family_default">sans-serif-condensed</string> - <integer name="preferences_interface_general_icons_text_font_style_default">0</integer> </resources> diff --git a/res/values/strings.xml b/res/values/strings.xml index cafa42442..9cb6c293b 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -28,30 +28,6 @@ <string name="uid_name">Android Core Apps</string> <!-- Default folder name --> <string name="folder_name"></string> - <!-- Button label on Wallpaper picker screen; user selects this button to set a specific wallpaper --> - <string name="wallpaper_instructions">Set wallpaper</string> - <!-- Shown when wallpapers are selected in Wallpaper picker --> - <!-- String indicating how many media item(s) is(are) selected - eg. 1 selected [CHAR LIMIT=30] --> - <plurals name="number_of_items_selected"> - <item quantity="zero">%1$d selected</item> - <item quantity="one">%1$d selected</item> - <item quantity="other">%1$d selected</item> - </plurals> - <!-- Accessibility string used as a label for a particular wallpaper in the Wallpaper Picker list. - e.g. "Wallpaper 3 of 10" --> - <string name="wallpaper_accessibility_name">Wallpaper %1$d of %2$d</string> - <!-- Accessibility string used to announce that a wallpaper has been selected. --> - <string name="announce_selection">Selected <xliff:g id="label" example="Wallpaper 3 of 10">%1$s</xliff:g></string> - - <!-- Label on button to delete wallpaper(s) --> - <string name="wallpaper_delete">Delete</string> - <!-- Label on button in Wallpaper Picker to pick an image --> - <string name="pick_image">Pick image</string> - <!-- Option in "Select wallpaper from" dialog box --> - <string name="pick_wallpaper">Wallpapers</string> - <!-- Title of activity for cropping wallpapers --> - <string name="crop_wallpaper">Crop wallpaper</string> <!-- Displayed when user selects a shortcut for an app that was uninstalled [CHAR_LIMIT=none]--> <string name="activity_not_found">App isn\'t installed.</string> <!-- Labels for the tabs in the customize drawer --> @@ -109,9 +85,9 @@ s --> <!-- Error message when user has filled a home screen --> <string name="out_of_space">No more room on this Home screen.</string> <!-- Error message when user has filled the hotseat --> - <string name="hotseat_out_of_space">No more room on the hotseat.</string> + <string name="hotseat_out_of_space">No more room in the Favorites tray</string> <!-- Error message when user tries to drop an invalid item on the hotseat --> - <string name="invalid_hotseat_item">This widget is too large for the hotseat.</string> + <string name="invalid_hotseat_item">This widget is too large for the Favorites tray</string> <!-- Message displayed when a shortcut is created by an external application --> <string name="shortcut_installed">Shortcut \"<xliff:g id="name" example="Browser">%s</xliff:g>\" created.</string> <!-- Message displayed when a shortcut is uninstalled by an external application --> @@ -230,8 +206,8 @@ s --> <string name="apps_customize_widgets_scroll_format">Widgets page %1$d of %2$d</string> <!-- Clings --> - <!-- The title text for the workspace cling [CHAR_LIMIT=60] --> - <string name="first_run_cling_title">Welcome!</string> + <!-- The title text for the workspace cling [CHAR_LIMIT=30] --> + <string name="first_run_cling_title">Welcome</string> <!-- The description of how to use the workspace [CHAR_LIMIT=60] --> <string name="first_run_cling_description">Make yourself at home.</string> <!-- The description of how to use the workspace [CHAR_LIMIT=60] --> @@ -240,17 +216,21 @@ s --> <string name="first_run_cling_search_bar_hint"></string> <!-- The description of how to use the workspace [CHAR_LIMIT=60] --> <string name="first_run_cling_create_screens_hint">Create more screens for apps and folders</string> - <!-- The title text for the workspace cling [CHAR_LIMIT=60] --> + <!-- The title text for the migration cling [CHAR_LIMIT=30] --> + <string name="migration_cling_title">Copy your app icons</string> + <!-- The description of what migration does [CHAR_LIMIT=70] --> + <string name="migration_cling_description">Import icons and folders from your old Home screens?</string> + <!-- The description of the button to migrate apps from another launcher [CHAR_LIMIT=30] --> + <string name="migration_cling_copy_apps">COPY ICONS</string> + <!-- The description of the button to use the default launcher layout [CHAR_LIMIT=30] --> + <string name="migration_cling_use_default">START FRESH</string> + <!-- The title text for the workspace cling [CHAR_LIMIT=30] --> <string name="workspace_cling_title">Organize your space</string> - <!-- The description of how to use the workspace [CHAR_LIMIT=160] --> + <!-- The description of how to use the workspace [CHAR_LIMIT=70] --> <string name="workspace_cling_move_item">Touch & hold background to manage wallpaper, widgets and settings.</string> - <!-- The title text for the All Apps cling [CHAR_LIMIT=60] --> - <string name="all_apps_cling_title">Choose some apps</string> - <!-- The description of how to pick up and add an item to the workspace [CHAR_LIMIT=160] --> - <string name="all_apps_cling_add_item">To add an app to your Home screen, touch & hold it.</string> - <!-- The title text for the Folder cling [CHAR_LIMIT=60] --> + <!-- The title text for the Folder cling [CHAR_LIMIT=30] --> <string name="folder_cling_title">Here\'s a folder</string> - <!-- The description of how to create a folder [CHAR_LIMIT=160] --> + <!-- The description of how to create a folder [CHAR_LIMIT=70] --> <string name="folder_cling_create_folder">To create one like this, touch & hold an app, then move it over another.</string> <!-- The text on the button to dismiss a cling [CHAR_LIMIT=30] --> <string name="cling_dismiss">OK</string> @@ -272,18 +252,6 @@ s --> <!-- Folder name format --> <string name="folder_name_format">Folder: <xliff:g id="name" example="Games">%1$s</xliff:g></string> - <!-- Strings used in device overlays --> - - <!-- Clings --> - <!-- Dummy string [CHAR_LIMIT=40] --> - <string name="custom_workspace_cling_title_1"></string> - <!-- Dummy string [CHAR_LIMIT=60] --> - <string name="custom_workspace_cling_description_1"></string> - <!-- Dummy string [CHAR_LIMIT=40] --> - <string name="custom_workspace_cling_title_2"></string> - <!-- Dummy string [CHAR_LIMIT=60] --> - <string name="custom_workspace_cling_description_2"></string> - <!-- Debug-only activity name. [DO NOT TRANSLATE] --> <string name="debug_memory_activity">* HPROF</string> diff --git a/res/values/styles.xml b/res/values/styles.xml index a1d2c5ccf..c18dccbab 100644 --- a/res/values/styles.xml +++ b/res/values/styles.xml @@ -18,30 +18,13 @@ --> <resources> - <style name="Theme.WallpaperCropper" parent="@android:style/Theme.Holo"> - <item name="android:actionBarStyle">@style/WallpaperCropperActionBar</item> - <item name="android:windowFullscreen">true</item> - <item name="android:windowActionBarOverlay">true</item> - <item name="android:windowTranslucentNavigation">true</item> - </style> - - <style name="WallpaperCropperActionBar" parent="android:style/Widget.Holo.ActionBar"> - <item name="android:displayOptions">showCustom</item> - <item name="android:background">#88000000</item> - </style> - - <style name="Theme" parent="@android:style/Theme.Holo.Wallpaper.NoTitleBar"> - <item name="android:windowTranslucentStatus">true</item> - <item name="android:windowTranslucentNavigation">true</item> - </style> - <style name="ClingButton"> <item name="android:layout_width">wrap_content</item> <item name="android:layout_height">wrap_content</item> <item name="android:paddingTop">15dp</item> <item name="android:paddingBottom">15dp</item> - <item name="android:paddingStart">50dp</item> - <item name="android:paddingEnd">50dp</item> + <item name="android:paddingLeft">50dp</item> + <item name="android:paddingRight">50dp</item> <item name="android:text">@string/cling_dismiss</item> <item name="android:textColor">#ffffff</item> <item name="android:textStyle">bold</item> @@ -52,27 +35,33 @@ <item name="android:layout_width">wrap_content</item> <item name="android:layout_height">wrap_content</item> <item name="android:layout_marginBottom">5dp</item> - <item name="android:textSize">22sp</item> + <item name="android:textSize">@dimen/cling_title_text_size</item> <item name="android:textColor">#ffffff</item> <item name="android:fontFamily">sans-serif-condensed</item> </style> + <style name="ClingText"> + <item name="android:layout_width">wrap_content</item> + <item name="android:layout_height">wrap_content</item> + <item name="android:textSize">@dimen/cling_text_size</item> + <item name="android:textColor">#80000000</item> + <item name="android:lineSpacingMultiplier">1.1</item> + </style> <style name="ClingAltTitleText"> <item name="android:layout_width">wrap_content</item> <item name="android:layout_height">wrap_content</item> - <item name="android:textSize">24sp</item> + <item name="android:textSize">@dimen/cling_alt_title_text_size</item> <item name="android:textColor">#49C0EC</item> </style> - <style name="ClingText"> + <style name="ClingAltText"> <item name="android:layout_width">wrap_content</item> <item name="android:layout_height">wrap_content</item> - <item name="android:textSize">16sp</item> - <item name="android:textColor">#80000000</item> - <item name="android:lineSpacingMultiplier">1.1</item> + <item name="android:textSize">@dimen/cling_alt_text_size</item> + <item name="android:textColor">#49C0EC</item> </style> <style name="ClingHintText"> <item name="android:layout_width">wrap_content</item> <item name="android:layout_height">wrap_content</item> - <item name="android:textSize">18sp</item> + <item name="android:textSize">@dimen/cling_hint_text_size</item> <item name="android:textColor">#80ffffff</item> <item name="android:fontFamily">sans-serif-condensed</item> </style> @@ -98,14 +87,10 @@ <style name="WorkspaceIcon.AppsCustomize"> <item name="android:background">@null</item> <item name="android:textColor">@color/apps_customize_icon_text_color</item> - <item name="android:drawablePadding">4dp</item> + <item name="android:drawablePadding">@dimen/dynamic_grid_icon_drawable_padding</item> <item name="android:shadowRadius">4.0</item> <item name="android:shadowColor">#FF000000</item> </style> - - <style name="QSBBar"> - <item name="android:orientation">horizontal</item> - </style> <style name="SearchDropTargetBar"> </style> <style name="SearchButton"> @@ -120,8 +105,8 @@ <item name="android:layout_gravity">center</item> <item name="android:gravity">center_vertical</item> <item name="android:drawablePadding">7.5dp</item> - <item name="android:paddingStart">25dp</item> - <item name="android:paddingEnd">25dp</item> + <item name="android:paddingLeft">25dp</item> + <item name="android:paddingRight">25dp</item> <item name="android:textColor">#FFFFFFFF</item> <item name="android:textSize">16sp</item> <item name="android:singleLine">true</item> @@ -136,8 +121,8 @@ <item name="android:layout_width">wrap_content</item> <item name="android:layout_height">match_parent</item> <item name="android:gravity">center</item> - <item name="android:paddingStart">20dp</item> - <item name="android:paddingEnd">20dp</item> + <item name="android:paddingLeft">20dp</item> + <item name="android:paddingRight">20dp</item> <item name="android:background">@drawable/tab_widget_indicator_selector</item> <item name="android:textColor">?android:attr/textColorPrimary</item> <item name="android:textSize">12sp</item> @@ -151,8 +136,8 @@ </style> <style name="MarketButton"> - <item name="android:paddingStart">5dp</item> - <item name="android:paddingEnd">5dp</item> + <item name="android:paddingLeft">5dp</item> + <item name="android:paddingRight">5dp</item> <item name="android:textColor">@color/workspace_all_apps_and_delete_zone_text_color</item> <item name="android:textSize">18sp</item> <item name="android:shadowColor">@color/workspace_all_apps_and_delete_zone_text_shadow_color</item> @@ -166,4 +151,10 @@ </style> <style name="CustomClingText"> </style> + <style name="PagedViewWidgetImageView"> + <item name="android:paddingLeft">@dimen/app_widget_preview_padding_left</item> + </style> + <style name="SearchButton.WithPaddingStart"> + <item name="android:paddingLeft">8dp</item> + </style> </resources> diff --git a/res/xml-sw600dp/default_workspace.xml b/res/xml-sw600dp/default_workspace.xml index 64896f245..b8034e320 100644 --- a/res/xml-sw600dp/default_workspace.xml +++ b/res/xml-sw600dp/default_workspace.xml @@ -26,37 +26,6 @@ launcher:spanX="5" launcher:spanY="3" /> <favorite - launcher:packageName="com.android.vending" - launcher:className="com.android.vending.AssetBrowserActivity" - launcher:container="-100" - launcher:screen="1" - launcher:x="4" - launcher:y="4" /> - <folder - launcher:screen="1" - launcher:x="0" - launcher:y="4" - launcher:title="@string/google_title"> - <favorite - launcher:className="com.google.android.maps.MapsActivity" - launcher:packageName="com.google.android.apps.maps" /> - <favorite - launcher:className="com.google.android.gm.GmailActivity" - launcher:packageName="com.google.android.gm" /> - <favorite - launcher:className="com.google.android.apps.plus.phone.HomeActivity" - launcher:packageName="com.google.android.apps.plus" /> - <favorite - launcher:className="com.android.calendar.AllInOneActivity" - launcher:packageName="com.google.android.calendar" /> - <favorite - launcher:className="com.google.android.maps.driveabout.app.DestinationActivity" - launcher:packageName="com.google.android.apps.maps" /> - <favorite - launcher:className="com.google.android.apps.plus.phone.ConversationListActivity" - launcher:packageName="com.google.android.apps.plus" /> - </folder> - <favorite launcher:packageName="com.andrew.apollo" launcher:className="com.andrew.apollo.ui.activities.HomeActivity" launcher:screen="1" @@ -71,13 +40,6 @@ <!-- Screen [2] --> <favorite - launcher:packageName="com.cyanogenmod.gallerynext" - launcher:className="com.cyanogenmod.gallerynext.app.GalleryActivity" - launcher:container="-100" - launcher:screen="2" - launcher:x="0" - launcher:y="4" /> - <favorite launcher:packageName="com.android.gallery3d" launcher:className="com.android.gallery3d.app.Gallery" launcher:container="-100" @@ -92,15 +54,6 @@ launcher:x="4" launcher:y="4" /> <appwidget - launcher:packageName="com.android.vending" - launcher:className="com.google.android.finsky.widget.consumption.NowPlayingWidgetProvider" - launcher:container="-100" - launcher:screen="2" - launcher:x="0" - launcher:y="0" - launcher:spanX="5" - launcher:spanY="4" /> - <appwidget launcher:packageName="com.android.mms" launcher:className="com.android.mms.widget.MmsWidgetProvider" launcher:container="-100" @@ -112,13 +65,6 @@ <!-- Hotseat --> <favorite - launcher:packageName="com.google.android.talk" - launcher:className="com.google.android.talk.SigningInActivity" - launcher:container="-101" - launcher:screen="4" - launcher:x="4" - launcher:y="0" /> - <favorite launcher:packageName="com.android.mms" launcher:className="com.android.mms.ui.ConversationList" launcher:container="-101" @@ -126,13 +72,6 @@ launcher:x="4" launcher:y="0" /> <favorite - launcher:packageName="com.android.chrome" - launcher:className="com.google.android.apps.chrome.Main" - launcher:container="-101" - launcher:screen="5" - launcher:x="5" - launcher:y="0" /> - <favorite launcher:packageName="com.android.browser" launcher:className="com.android.browser.BrowserActivity" launcher:container="-101" @@ -140,13 +79,6 @@ launcher:x="5" launcher:y="0" /> <favorite - launcher:packageName="com.google.android.music" - launcher:className="com.android.music.activitymanagement.TopLevelActivity" - launcher:container="-101" - launcher:screen="2" - launcher:x="2" - launcher:y="0" /> - <favorite launcher:packageName="com.android.camera2" launcher:className="com.android.camera.CameraLauncher" launcher:container="-101" @@ -154,13 +86,6 @@ launcher:x="2" launcher:y="0" /> <favorite - launcher:packageName="com.google.android.youtube" - launcher:className="com.google.android.youtube.app.honeycomb.Shell$HomeActivity" - launcher:container="-101" - launcher:screen="1" - launcher:x="1" - launcher:y="0" /> - <favorite launcher:packageName="com.android.contacts" launcher:className="com.android.contacts.activities.PeopleActivity" launcher:container="-101" diff --git a/res/xml-sw600dp/default_workspace_gapps.xml b/res/xml-sw600dp/default_workspace_gapps.xml new file mode 100644 index 000000000..8be9f421d --- /dev/null +++ b/res/xml-sw600dp/default_workspace_gapps.xml @@ -0,0 +1,171 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2013-2014 The CyanogenMod 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. +--> +<favorites xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher3"> + <!-- Screen [1] --> + <appwidget + launcher:packageName="com.cyanogenmod.lockclock" + launcher:className="com.cyanogenmod.lockclock.ClockWidgetProvider" + launcher:container="-100" + launcher:screen="1" + launcher:x="0" + launcher:y="0" + launcher:spanX="5" + launcher:spanY="3" /> + <favorite + launcher:packageName="com.android.vending" + launcher:className="com.android.vending.AssetBrowserActivity" + launcher:container="-100" + launcher:screen="1" + launcher:x="4" + launcher:y="4" /> + <folder + launcher:screen="1" + launcher:x="0" + launcher:y="4" + launcher:title="@string/google_title"> + <favorite + launcher:className="com.google.android.maps.MapsActivity" + launcher:packageName="com.google.android.apps.maps" /> + <favorite + launcher:className="com.google.android.gm.ConversationListActivityGmail" + launcher:packageName="com.google.android.gm" /> + <favorite + launcher:className="com.google.android.apps.plus.phone.HomeActivity" + launcher:packageName="com.google.android.apps.plus" /> + <favorite + launcher:className="com.android.calendar.AllInOneActivity" + launcher:packageName="com.google.android.calendar" /> + <favorite + launcher:className="com.google.android.maps.driveabout.app.DestinationActivity" + launcher:packageName="com.google.android.apps.maps" /> + <favorite + launcher:className="com.google.android.apps.plus.phone.ConversationListActivity" + launcher:packageName="com.google.android.apps.plus" /> + </folder> + <favorite + launcher:packageName="com.andrew.apollo" + launcher:className="com.andrew.apollo.ui.activities.HomeActivity" + launcher:screen="1" + launcher:x="0" + launcher:y="4" /> + <favorite + launcher:packageName="com.bel.android.dspmanager" + launcher:className="com.bel.android.dspmanager.activity.DSPManager" + launcher:screen="1" + launcher:x="4" + launcher:y="4" /> + + <!-- Screen [2] --> + <favorite + launcher:packageName="com.cyngn.gallerynext" + launcher:className="com.cyngn.gallerynext.app.GalleryActivity" + launcher:container="-100" + launcher:screen="2" + launcher:x="0" + launcher:y="4" /> + <favorite + launcher:packageName="com.android.gallery3d" + launcher:className="com.android.gallery3d.app.Gallery" + launcher:container="-100" + launcher:screen="2" + launcher:x="0" + launcher:y="4" /> + <favorite + launcher:packageName="com.android.settings" + launcher:className="com.android.settings.Settings" + launcher:container="-100" + launcher:screen="2" + launcher:x="4" + launcher:y="4" /> + <appwidget + launcher:packageName="com.android.vending" + launcher:className="com.google.android.finsky.widget.consumption.NowPlayingWidgetProvider" + launcher:container="-100" + launcher:screen="2" + launcher:x="0" + launcher:y="0" + launcher:spanX="5" + launcher:spanY="4" /> + <appwidget + launcher:packageName="com.android.mms" + launcher:className="com.android.mms.widget.MmsWidgetProvider" + launcher:container="-100" + launcher:screen="2" + launcher:x="0" + launcher:y="0" + launcher:spanX="5" + launcher:spanY="2" /> + + <!-- Hotseat --> + <favorite + launcher:packageName="com.google.android.talk" + launcher:className="com.google.android.talk.SigningInActivity" + launcher:container="-101" + launcher:screen="4" + launcher:x="4" + launcher:y="0" /> + <favorite + launcher:packageName="com.android.mms" + launcher:className="com.android.mms.ui.ConversationList" + launcher:container="-101" + launcher:screen="4" + launcher:x="4" + launcher:y="0" /> + <favorite + launcher:packageName="com.android.chrome" + launcher:className="com.google.android.apps.chrome.Main" + launcher:container="-101" + launcher:screen="5" + launcher:x="5" + launcher:y="0" /> + <favorite + launcher:packageName="com.android.browser" + launcher:className="com.android.browser.BrowserActivity" + launcher:container="-101" + launcher:screen="5" + launcher:x="5" + launcher:y="0" /> + <favorite + launcher:packageName="com.google.android.music" + launcher:className="com.android.music.activitymanagement.TopLevelActivity" + launcher:container="-101" + launcher:screen="2" + launcher:x="2" + launcher:y="0" /> + <favorite + launcher:packageName="com.android.camera2" + launcher:className="com.android.camera.CameraLauncher" + launcher:container="-101" + launcher:screen="2" + launcher:x="2" + launcher:y="0" /> + <favorite + launcher:packageName="com.google.android.youtube" + launcher:className="com.google.android.youtube.app.honeycomb.Shell$HomeActivity" + launcher:container="-101" + launcher:screen="1" + launcher:x="1" + launcher:y="0" /> + <favorite + launcher:packageName="com.android.contacts" + launcher:className="com.android.contacts.activities.PeopleActivity" + launcher:container="-101" + launcher:screen="1" + launcher:x="1" + launcher:y="0" /> + +</favorites> diff --git a/res/xml-sw600dp/default_workspace_no_telephony.xml b/res/xml-sw600dp/default_workspace_no_telephony.xml index fb81f178b..522640a4d 100644 --- a/res/xml-sw600dp/default_workspace_no_telephony.xml +++ b/res/xml-sw600dp/default_workspace_no_telephony.xml @@ -26,37 +26,6 @@ launcher:spanX="5" launcher:spanY="3" /> <favorite - launcher:packageName="com.android.vending" - launcher:className="com.android.vending.AssetBrowserActivity" - launcher:container="-100" - launcher:screen="1" - launcher:x="4" - launcher:y="4" /> - <folder - launcher:screen="1" - launcher:x="0" - launcher:y="4" - launcher:title="@string/google_title"> - <favorite - launcher:className="com.google.android.maps.MapsActivity" - launcher:packageName="com.google.android.apps.maps" /> - <favorite - launcher:className="com.google.android.gm.GmailActivity" - launcher:packageName="com.google.android.gm" /> - <favorite - launcher:className="com.google.android.apps.plus.phone.HomeActivity" - launcher:packageName="com.google.android.apps.plus" /> - <favorite - launcher:className="com.android.calendar.AllInOneActivity" - launcher:packageName="com.google.android.calendar" /> - <favorite - launcher:className="com.google.android.maps.driveabout.app.DestinationActivity" - launcher:packageName="com.google.android.apps.maps" /> - <favorite - launcher:className="com.google.android.apps.plus.phone.ConversationListActivity" - launcher:packageName="com.google.android.apps.plus" /> - </folder> - <favorite launcher:packageName="com.andrew.apollo" launcher:className="com.andrew.apollo.ui.activities.HomeActivity" launcher:screen="1" @@ -71,13 +40,6 @@ <!-- Screen [2] --> <favorite - launcher:packageName="com.cyanogenmod.gallerynext" - launcher:className="com.cyanogenmod.gallerynext.app.GalleryActivity" - launcher:container="-100" - launcher:screen="2" - launcher:x="0" - launcher:y="4" /> - <favorite launcher:packageName="com.android.gallery3d" launcher:className="com.android.gallery3d.app.Gallery" launcher:container="-100" @@ -92,15 +54,6 @@ launcher:x="4" launcher:y="4" /> <appwidget - launcher:packageName="com.android.vending" - launcher:className="com.google.android.finsky.widget.consumption.NowPlayingWidgetProvider" - launcher:container="-100" - launcher:screen="2" - launcher:x="0" - launcher:y="0" - launcher:spanX="5" - launcher:spanY="4"/> - <appwidget launcher:packageName="com.android.settings" launcher:className="com.android.settings.widget.SettingsAppWidgetProvider" launcher:container="-100" @@ -112,13 +65,6 @@ <!-- Hotseat --> <favorite - launcher:packageName="com.google.android.talk" - launcher:className="com.google.android.talk.SigningInActivity" - launcher:container="-101" - launcher:screen="4" - launcher:x="4" - launcher:y="0" /> - <favorite launcher:packageName="com.android.email" launcher:className="com.android.email.activity.Welcome" launcher:container="-101" @@ -126,13 +72,6 @@ launcher:x="4" launcher:y="0" /> <favorite - launcher:packageName="com.android.chrome" - launcher:className="com.google.android.apps.chrome.Main" - launcher:container="-101" - launcher:screen="5" - launcher:x="5" - launcher:y="0" /> - <favorite launcher:packageName="com.android.browser" launcher:className="com.android.browser.BrowserActivity" launcher:container="-101" @@ -140,13 +79,6 @@ launcher:x="5" launcher:y="0" /> <favorite - launcher:packageName="com.google.android.music" - launcher:className="com.android.music.activitymanagement.TopLevelActivity" - launcher:container="-101" - launcher:screen="2" - launcher:x="2" - launcher:y="0" /> - <favorite launcher:packageName="com.android.camera2" launcher:className="com.android.camera.CameraLauncher" launcher:container="-101" @@ -154,13 +86,6 @@ launcher:x="2" launcher:y="0" /> <favorite - launcher:packageName="com.google.android.youtube" - launcher:className="com.google.android.youtube.app.honeycomb.Shell$HomeActivity" - launcher:container="-101" - launcher:screen="1" - launcher:x="1" - launcher:y="0" /> - <favorite launcher:packageName="com.android.contacts" launcher:className="com.android.contacts.activities.PeopleActivity" launcher:container="-101" diff --git a/res/xml-sw600dp/default_workspace_no_telephony_gapps.xml b/res/xml-sw600dp/default_workspace_no_telephony_gapps.xml new file mode 100644 index 000000000..ba1dfbc86 --- /dev/null +++ b/res/xml-sw600dp/default_workspace_no_telephony_gapps.xml @@ -0,0 +1,171 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2013-2014 The CyanogenMod 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. +--> +<favorites xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher3"> + <!-- Screen [1] --> + <appwidget + launcher:packageName="com.cyanogenmod.lockclock" + launcher:className="com.cyanogenmod.lockclock.ClockWidgetProvider" + launcher:container="-100" + launcher:screen="1" + launcher:x="0" + launcher:y="0" + launcher:spanX="5" + launcher:spanY="3" /> + <favorite + launcher:packageName="com.android.vending" + launcher:className="com.android.vending.AssetBrowserActivity" + launcher:container="-100" + launcher:screen="1" + launcher:x="4" + launcher:y="4" /> + <folder + launcher:screen="1" + launcher:x="0" + launcher:y="4" + launcher:title="@string/google_title"> + <favorite + launcher:className="com.google.android.maps.MapsActivity" + launcher:packageName="com.google.android.apps.maps" /> + <favorite + launcher:className="com.google.android.gm.ConversationListActivityGmail" + launcher:packageName="com.google.android.gm" /> + <favorite + launcher:className="com.google.android.apps.plus.phone.HomeActivity" + launcher:packageName="com.google.android.apps.plus" /> + <favorite + launcher:className="com.android.calendar.AllInOneActivity" + launcher:packageName="com.google.android.calendar" /> + <favorite + launcher:className="com.google.android.maps.driveabout.app.DestinationActivity" + launcher:packageName="com.google.android.apps.maps" /> + <favorite + launcher:className="com.google.android.apps.plus.phone.ConversationListActivity" + launcher:packageName="com.google.android.apps.plus" /> + </folder> + <favorite + launcher:packageName="com.andrew.apollo" + launcher:className="com.andrew.apollo.ui.activities.HomeActivity" + launcher:screen="1" + launcher:x="0" + launcher:y="4" /> + <favorite + launcher:packageName="com.bel.android.dspmanager" + launcher:className="com.bel.android.dspmanager.activity.DSPManager" + launcher:screen="1" + launcher:x="4" + launcher:y="4" /> + + <!-- Screen [2] --> + <favorite + launcher:packageName="com.cyngn.gallerynext" + launcher:className="com.cyngn.gallerynext.app.GalleryActivity" + launcher:container="-100" + launcher:screen="2" + launcher:x="0" + launcher:y="4" /> + <favorite + launcher:packageName="com.android.gallery3d" + launcher:className="com.android.gallery3d.app.Gallery" + launcher:container="-100" + launcher:screen="2" + launcher:x="0" + launcher:y="4" /> + <favorite + launcher:packageName="com.android.settings" + launcher:className="com.android.settings.Settings" + launcher:container="-100" + launcher:screen="2" + launcher:x="4" + launcher:y="4" /> + <appwidget + launcher:packageName="com.android.vending" + launcher:className="com.google.android.finsky.widget.consumption.NowPlayingWidgetProvider" + launcher:container="-100" + launcher:screen="2" + launcher:x="0" + launcher:y="0" + launcher:spanX="5" + launcher:spanY="4"/> + <appwidget + launcher:packageName="com.android.settings" + launcher:className="com.android.settings.widget.SettingsAppWidgetProvider" + launcher:container="-100" + launcher:screen="2" + launcher:x="0" + launcher:y="0" + launcher:spanX="5" + launcher:spanY="1" /> + + <!-- Hotseat --> + <favorite + launcher:packageName="com.google.android.talk" + launcher:className="com.google.android.talk.SigningInActivity" + launcher:container="-101" + launcher:screen="4" + launcher:x="4" + launcher:y="0" /> + <favorite + launcher:packageName="com.android.email" + launcher:className="com.android.email.activity.Welcome" + launcher:container="-101" + launcher:screen="4" + launcher:x="4" + launcher:y="0" /> + <favorite + launcher:packageName="com.android.chrome" + launcher:className="com.google.android.apps.chrome.Main" + launcher:container="-101" + launcher:screen="5" + launcher:x="5" + launcher:y="0" /> + <favorite + launcher:packageName="com.android.browser" + launcher:className="com.android.browser.BrowserActivity" + launcher:container="-101" + launcher:screen="5" + launcher:x="5" + launcher:y="0" /> + <favorite + launcher:packageName="com.google.android.music" + launcher:className="com.android.music.activitymanagement.TopLevelActivity" + launcher:container="-101" + launcher:screen="2" + launcher:x="2" + launcher:y="0" /> + <favorite + launcher:packageName="com.android.camera2" + launcher:className="com.android.camera.CameraLauncher" + launcher:container="-101" + launcher:screen="2" + launcher:x="2" + launcher:y="0" /> + <favorite + launcher:packageName="com.google.android.youtube" + launcher:className="com.google.android.youtube.app.honeycomb.Shell$HomeActivity" + launcher:container="-101" + launcher:screen="1" + launcher:x="1" + launcher:y="0" /> + <favorite + launcher:packageName="com.android.contacts" + launcher:className="com.android.contacts.activities.PeopleActivity" + launcher:container="-101" + launcher:screen="1" + launcher:x="1" + launcher:y="0" /> + +</favorites> diff --git a/res/xml-sw720dp/default_workspace.xml b/res/xml-sw720dp/default_workspace.xml index e9231cc37..85920d732 100644 --- a/res/xml-sw720dp/default_workspace.xml +++ b/res/xml-sw720dp/default_workspace.xml @@ -26,37 +26,6 @@ launcher:spanX="6" launcher:spanY="3" /> <favorite - launcher:packageName="com.android.vending" - launcher:className="com.android.vending.AssetBrowserActivity" - launcher:container="-100" - launcher:screen="1" - launcher:x="7" - launcher:y="4" /> - <folder - launcher:screen="1" - launcher:x="0" - launcher:y="4" - launcher:title="@string/google_title"> - <favorite - launcher:className="com.google.android.maps.MapsActivity" - launcher:packageName="com.google.android.apps.maps" /> - <favorite - launcher:className="com.google.android.gm.GmailActivity" - launcher:packageName="com.google.android.gm" /> - <favorite - launcher:className="com.google.android.apps.plus.phone.HomeActivity" - launcher:packageName="com.google.android.apps.plus" /> - <favorite - launcher:className="com.android.calendar.AllInOneActivity" - launcher:packageName="com.google.android.calendar" /> - <favorite - launcher:className="com.google.android.maps.driveabout.app.DestinationActivity" - launcher:packageName="com.google.android.apps.maps" /> - <favorite - launcher:className="com.google.android.apps.plus.phone.ConversationListActivity" - launcher:packageName="com.google.android.apps.plus" /> - </folder> - <favorite launcher:packageName="com.bel.android.dspmanager" launcher:className="com.bel.android.dspmanager.activity.DSPManager" launcher:screen="1" @@ -71,13 +40,6 @@ <!-- Screen [2] --> <favorite - launcher:packageName="com.cyanogenmod.gallerynext" - launcher:className="com.cyanogenmod.gallerynext.app.GalleryActivity" - launcher:container="-100" - launcher:screen="2" - launcher:x="0" - launcher:y="4" /> - <favorite launcher:packageName="com.android.gallery3d" launcher:className="com.android.gallery3d.app.Gallery" launcher:container="-100" @@ -92,15 +54,6 @@ launcher:x="7" launcher:y="4" /> <appwidget - launcher:packageName="com.android.vending" - launcher:className="com.google.android.finsky.widget.consumption.NowPlayingWidgetProvider" - launcher:container="-100" - launcher:screen="2" - launcher:x="1" - launcher:y="0" - launcher:spanX="6" - launcher:spanY="4"/> - <appwidget launcher:packageName="com.android.mms" launcher:className="com.android.mms.widget.MmsWidgetProvider" launcher:screen="2" @@ -111,13 +64,6 @@ <!-- Hotseat --> <favorite - launcher:packageName="com.google.android.talk" - launcher:className="com.google.android.talk.SigningInActivity" - launcher:container="-101" - launcher:screen="5" - launcher:x="5" - launcher:y="0" /> - <favorite launcher:packageName="com.android.mms" launcher:className="com.android.mms.ui.ConversationList" launcher:container="-101" @@ -125,13 +71,6 @@ launcher:x="5" launcher:y="0" /> <favorite - launcher:packageName="com.android.chrome" - launcher:className="com.google.android.apps.chrome.Main" - launcher:container="-101" - launcher:screen="6" - launcher:x="6" - launcher:y="0" /> - <favorite launcher:packageName="com.android.browser" launcher:className="com.android.browser.BrowserActivity" launcher:container="-101" @@ -139,13 +78,6 @@ launcher:x="6" launcher:y="0" /> <favorite - launcher:packageName="com.google.android.music" - launcher:className="com.android.music.activitymanagement.TopLevelActivity" - launcher:container="-101" - launcher:screen="3" - launcher:x="3" - launcher:y="0" /> - <favorite launcher:packageName="com.android.camera2" launcher:className="com.android.camera.CameraLauncher" launcher:container="-101" @@ -153,13 +85,6 @@ launcher:x="3" launcher:y="0" /> <favorite - launcher:packageName="com.google.android.youtube" - launcher:className="com.google.android.youtube.app.honeycomb.Shell$HomeActivity" - launcher:container="-101" - launcher:screen="2" - launcher:x="2" - launcher:y="0" /> - <favorite launcher:packageName="com.android.contacts" launcher:className="com.android.contacts.activities.PeopleActivity" launcher:container="-101" diff --git a/res/xml-sw720dp/default_workspace_gapps.xml b/res/xml-sw720dp/default_workspace_gapps.xml new file mode 100644 index 000000000..2a65712cc --- /dev/null +++ b/res/xml-sw720dp/default_workspace_gapps.xml @@ -0,0 +1,170 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2013-2014 The CyanogenMod 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. +--> +<favorites xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher3"> + <!-- Screen [1] --> + <appwidget + launcher:packageName="com.cyanogenmod.lockclock" + launcher:className="com.cyanogenmod.lockclock.ClockWidgetProvider" + launcher:container="-100" + launcher:screen="1" + launcher:x="1" + launcher:y="0" + launcher:spanX="6" + launcher:spanY="3" /> + <favorite + launcher:packageName="com.android.vending" + launcher:className="com.android.vending.AssetBrowserActivity" + launcher:container="-100" + launcher:screen="1" + launcher:x="7" + launcher:y="4" /> + <folder + launcher:screen="1" + launcher:x="0" + launcher:y="4" + launcher:title="@string/google_title"> + <favorite + launcher:className="com.google.android.maps.MapsActivity" + launcher:packageName="com.google.android.apps.maps" /> + <favorite + launcher:className="com.google.android.gm.ConversationListActivityGmail" + launcher:packageName="com.google.android.gm" /> + <favorite + launcher:className="com.google.android.apps.plus.phone.HomeActivity" + launcher:packageName="com.google.android.apps.plus" /> + <favorite + launcher:className="com.android.calendar.AllInOneActivity" + launcher:packageName="com.google.android.calendar" /> + <favorite + launcher:className="com.google.android.maps.driveabout.app.DestinationActivity" + launcher:packageName="com.google.android.apps.maps" /> + <favorite + launcher:className="com.google.android.apps.plus.phone.ConversationListActivity" + launcher:packageName="com.google.android.apps.plus" /> + </folder> + <favorite + launcher:packageName="com.bel.android.dspmanager" + launcher:className="com.bel.android.dspmanager.activity.DSPManager" + launcher:screen="1" + launcher:x="7" + launcher:y="4" /> + <favorite + launcher:packageName="com.andrew.apollo" + launcher:className="com.andrew.apollo.ui.activities.HomeActivity" + launcher:screen="1" + launcher:x="0" + launcher:y="4" /> + + <!-- Screen [2] --> + <favorite + launcher:packageName="com.cyngn.gallerynext" + launcher:className="com.cyngn.gallerynext.app.GalleryActivity" + launcher:container="-100" + launcher:screen="2" + launcher:x="0" + launcher:y="4" /> + <favorite + launcher:packageName="com.android.gallery3d" + launcher:className="com.android.gallery3d.app.Gallery" + launcher:container="-100" + launcher:screen="2" + launcher:x="0" + launcher:y="4" /> + <favorite + launcher:packageName="com.android.settings" + launcher:className="com.android.settings.Settings" + launcher:container="-100" + launcher:screen="2" + launcher:x="7" + launcher:y="4" /> + <appwidget + launcher:packageName="com.android.vending" + launcher:className="com.google.android.finsky.widget.consumption.NowPlayingWidgetProvider" + launcher:container="-100" + launcher:screen="2" + launcher:x="1" + launcher:y="0" + launcher:spanX="6" + launcher:spanY="4"/> + <appwidget + launcher:packageName="com.android.mms" + launcher:className="com.android.mms.widget.MmsWidgetProvider" + launcher:screen="2" + launcher:x="2" + launcher:y="0" + launcher:spanX="4" + launcher:spanY="2" /> + + <!-- Hotseat --> + <favorite + launcher:packageName="com.google.android.talk" + launcher:className="com.google.android.talk.SigningInActivity" + launcher:container="-101" + launcher:screen="5" + launcher:x="5" + launcher:y="0" /> + <favorite + launcher:packageName="com.android.mms" + launcher:className="com.android.mms.ui.ConversationList" + launcher:container="-101" + launcher:screen="5" + launcher:x="5" + launcher:y="0" /> + <favorite + launcher:packageName="com.android.chrome" + launcher:className="com.google.android.apps.chrome.Main" + launcher:container="-101" + launcher:screen="6" + launcher:x="6" + launcher:y="0" /> + <favorite + launcher:packageName="com.android.browser" + launcher:className="com.android.browser.BrowserActivity" + launcher:container="-101" + launcher:screen="6" + launcher:x="6" + launcher:y="0" /> + <favorite + launcher:packageName="com.google.android.music" + launcher:className="com.android.music.activitymanagement.TopLevelActivity" + launcher:container="-101" + launcher:screen="3" + launcher:x="3" + launcher:y="0" /> + <favorite + launcher:packageName="com.android.camera2" + launcher:className="com.android.camera.CameraLauncher" + launcher:container="-101" + launcher:screen="3" + launcher:x="3" + launcher:y="0" /> + <favorite + launcher:packageName="com.google.android.youtube" + launcher:className="com.google.android.youtube.app.honeycomb.Shell$HomeActivity" + launcher:container="-101" + launcher:screen="2" + launcher:x="2" + launcher:y="0" /> + <favorite + launcher:packageName="com.android.contacts" + launcher:className="com.android.contacts.activities.PeopleActivity" + launcher:container="-101" + launcher:screen="2" + launcher:x="2" + launcher:y="0" /> + +</favorites> diff --git a/res/xml-sw720dp/default_workspace_no_telephony.xml b/res/xml-sw720dp/default_workspace_no_telephony.xml index b15cebbb4..df557bff9 100644 --- a/res/xml-sw720dp/default_workspace_no_telephony.xml +++ b/res/xml-sw720dp/default_workspace_no_telephony.xml @@ -26,37 +26,6 @@ launcher:spanX="6" launcher:spanY="3"/> <favorite - launcher:packageName="com.android.vending" - launcher:className="com.android.vending.AssetBrowserActivity" - launcher:container="-100" - launcher:screen="1" - launcher:x="7" - launcher:y="4" /> - <folder - launcher:screen="1" - launcher:x="0" - launcher:y="4" - launcher:title="@string/google_title"> - <favorite - launcher:className="com.google.android.maps.MapsActivity" - launcher:packageName="com.google.android.apps.maps" /> - <favorite - launcher:className="com.google.android.gm.GmailActivity" - launcher:packageName="com.google.android.gm" /> - <favorite - launcher:className="com.google.android.apps.plus.phone.HomeActivity" - launcher:packageName="com.google.android.apps.plus" /> - <favorite - launcher:className="com.android.calendar.AllInOneActivity" - launcher:packageName="com.google.android.calendar" /> - <favorite - launcher:className="com.google.android.maps.driveabout.app.DestinationActivity" - launcher:packageName="com.google.android.apps.maps" /> - <favorite - launcher:className="com.google.android.apps.plus.phone.ConversationListActivity" - launcher:packageName="com.google.android.apps.plus" /> - </folder> - <favorite launcher:packageName="com.bel.android.dspmanager" launcher:className="com.bel.android.dspmanager.activity.DSPManager" launcher:screen="1" @@ -71,13 +40,6 @@ <!-- Screen [2] --> <favorite - launcher:packageName="com.cyanogenmod.gallerynext" - launcher:className="com.cyanogenmod.gallerynext.app.GalleryActivity" - launcher:container="-100" - launcher:screen="2" - launcher:x="0" - launcher:y="4" /> - <favorite launcher:packageName="com.android.gallery3d" launcher:className="com.android.gallery3d.app.Gallery" launcher:container="-100" @@ -92,15 +54,6 @@ launcher:x="7" launcher:y="4" /> <appwidget - launcher:packageName="com.android.vending" - launcher:className="com.google.android.finsky.widget.consumption.NowPlayingWidgetProvider" - launcher:container="-100" - launcher:screen="2" - launcher:x="1" - launcher:y="0" - launcher:spanX="6" - launcher:spanY="4"/> - <appwidget launcher:packageName="com.android.settings" launcher:className="com.android.settings.widget.SettingsAppWidgetProvider" launcher:container="-100" @@ -112,13 +65,6 @@ <!-- Hotseat --> <favorite - launcher:packageName="com.google.android.talk" - launcher:className="com.google.android.talk.SigningInActivity" - launcher:container="-101" - launcher:screen="5" - launcher:x="5" - launcher:y="0" /> - <favorite launcher:packageName="com.android.email" launcher:className="com.android.email.activity.Welcome" launcher:container="-101" @@ -126,13 +72,6 @@ launcher:x="5" launcher:y="0" /> <favorite - launcher:packageName="com.android.chrome" - launcher:className="com.google.android.apps.chrome.Main" - launcher:container="-101" - launcher:screen="6" - launcher:x="6" - launcher:y="0" /> - <favorite launcher:packageName="com.android.browser" launcher:className="com.android.browser.BrowserActivity" launcher:container="-101" @@ -140,13 +79,6 @@ launcher:x="6" launcher:y="0" /> <favorite - launcher:packageName="com.google.android.music" - launcher:className="com.android.music.activitymanagement.TopLevelActivity" - launcher:container="-101" - launcher:screen="3" - launcher:x="3" - launcher:y="0" /> - <favorite launcher:packageName="com.android.camera2" launcher:className="com.android.camera.CameraLauncher" launcher:container="-101" @@ -154,13 +86,6 @@ launcher:x="3" launcher:y="0" /> <favorite - launcher:packageName="com.google.android.youtube" - launcher:className="com.google.android.youtube.app.honeycomb.Shell$HomeActivity" - launcher:container="-101" - launcher:screen="2" - launcher:x="2" - launcher:y="0" /> - <favorite launcher:packageName="com.android.contacts" launcher:className="com.android.contacts.activities.PeopleActivity" launcher:container="-101" diff --git a/res/xml-sw720dp/default_workspace_no_telephony_gapps.xml b/res/xml-sw720dp/default_workspace_no_telephony_gapps.xml new file mode 100644 index 000000000..2deae95e4 --- /dev/null +++ b/res/xml-sw720dp/default_workspace_no_telephony_gapps.xml @@ -0,0 +1,171 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2013-2014 The CyanogenMod 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. +--> +<favorites xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher3"> + <!-- Screen [1] --> + <appwidget + launcher:packageName="com.cyanogenmod.lockclock" + launcher:className="com.cyanogenmod.lockclock.ClockWidgetProvider" + launcher:container="-100" + launcher:screen="1" + launcher:x="1" + launcher:y="0" + launcher:spanX="6" + launcher:spanY="3"/> + <favorite + launcher:packageName="com.android.vending" + launcher:className="com.android.vending.AssetBrowserActivity" + launcher:container="-100" + launcher:screen="1" + launcher:x="7" + launcher:y="4" /> + <folder + launcher:screen="1" + launcher:x="0" + launcher:y="4" + launcher:title="@string/google_title"> + <favorite + launcher:className="com.google.android.maps.MapsActivity" + launcher:packageName="com.google.android.apps.maps" /> + <favorite + launcher:className="com.google.android.gm.ConversationListActivityGmail" + launcher:packageName="com.google.android.gm" /> + <favorite + launcher:className="com.google.android.apps.plus.phone.HomeActivity" + launcher:packageName="com.google.android.apps.plus" /> + <favorite + launcher:className="com.android.calendar.AllInOneActivity" + launcher:packageName="com.google.android.calendar" /> + <favorite + launcher:className="com.google.android.maps.driveabout.app.DestinationActivity" + launcher:packageName="com.google.android.apps.maps" /> + <favorite + launcher:className="com.google.android.apps.plus.phone.ConversationListActivity" + launcher:packageName="com.google.android.apps.plus" /> + </folder> + <favorite + launcher:packageName="com.bel.android.dspmanager" + launcher:className="com.bel.android.dspmanager.activity.DSPManager" + launcher:screen="1" + launcher:x="7" + launcher:y="4" /> + <favorite + launcher:packageName="com.andrew.apollo" + launcher:className="com.andrew.apollo.ui.activities.HomeActivity" + launcher:screen="1" + launcher:x="0" + launcher:y="4" /> + + <!-- Screen [2] --> + <favorite + launcher:packageName="com.cyngn.gallerynext" + launcher:className="com.cyngn.gallerynext.app.GalleryActivity" + launcher:container="-100" + launcher:screen="2" + launcher:x="0" + launcher:y="4" /> + <favorite + launcher:packageName="com.android.gallery3d" + launcher:className="com.android.gallery3d.app.Gallery" + launcher:container="-100" + launcher:screen="2" + launcher:x="0" + launcher:y="4" /> + <favorite + launcher:packageName="com.android.settings" + launcher:className="com.android.settings.Settings" + launcher:container="-100" + launcher:screen="2" + launcher:x="7" + launcher:y="4" /> + <appwidget + launcher:packageName="com.android.vending" + launcher:className="com.google.android.finsky.widget.consumption.NowPlayingWidgetProvider" + launcher:container="-100" + launcher:screen="2" + launcher:x="1" + launcher:y="0" + launcher:spanX="6" + launcher:spanY="4"/> + <appwidget + launcher:packageName="com.android.settings" + launcher:className="com.android.settings.widget.SettingsAppWidgetProvider" + launcher:container="-100" + launcher:screen="2" + launcher:x="2" + launcher:y="0" + launcher:spanX="4" + launcher:spanY="1" /> + + <!-- Hotseat --> + <favorite + launcher:packageName="com.google.android.talk" + launcher:className="com.google.android.talk.SigningInActivity" + launcher:container="-101" + launcher:screen="5" + launcher:x="5" + launcher:y="0" /> + <favorite + launcher:packageName="com.android.email" + launcher:className="com.android.email.activity.Welcome" + launcher:container="-101" + launcher:screen="5" + launcher:x="5" + launcher:y="0" /> + <favorite + launcher:packageName="com.android.chrome" + launcher:className="com.google.android.apps.chrome.Main" + launcher:container="-101" + launcher:screen="6" + launcher:x="6" + launcher:y="0" /> + <favorite + launcher:packageName="com.android.browser" + launcher:className="com.android.browser.BrowserActivity" + launcher:container="-101" + launcher:screen="6" + launcher:x="6" + launcher:y="0" /> + <favorite + launcher:packageName="com.google.android.music" + launcher:className="com.android.music.activitymanagement.TopLevelActivity" + launcher:container="-101" + launcher:screen="3" + launcher:x="3" + launcher:y="0" /> + <favorite + launcher:packageName="com.android.camera2" + launcher:className="com.android.camera.CameraLauncher" + launcher:container="-101" + launcher:screen="3" + launcher:x="3" + launcher:y="0" /> + <favorite + launcher:packageName="com.google.android.youtube" + launcher:className="com.google.android.youtube.app.honeycomb.Shell$HomeActivity" + launcher:container="-101" + launcher:screen="2" + launcher:x="2" + launcher:y="0" /> + <favorite + launcher:packageName="com.android.contacts" + launcher:className="com.android.contacts.activities.PeopleActivity" + launcher:container="-101" + launcher:screen="2" + launcher:x="2" + launcher:y="0" /> + +</favorites> diff --git a/res/xml/default_workspace.xml b/res/xml/default_workspace.xml index 37676ff43..4174bc818 100644 --- a/res/xml/default_workspace.xml +++ b/res/xml/default_workspace.xml @@ -24,44 +24,6 @@ launcher:y="0" launcher:spanX="4" launcher:spanY="2" /> - <folder launcher:screen="1" launcher:x="0" launcher:y="3" launcher:title="@string/google_title"> - <favorite - launcher:className="com.google.android.gm.GmailActivity" - launcher:packageName="com.google.android.gm" /> - <favorite - launcher:className="com.google.android.apps.plus.phone.HomeActivity" - launcher:packageName="com.google.android.apps.plus" /> - <favorite - launcher:className="com.google.android.maps.MapsActivity" - launcher:packageName="com.google.android.apps.maps" /> - <favorite - launcher:className="com.android.music.activitymanagement.TopLevelActivity" - launcher:packageName="com.google.android.music" /> - <favorite - launcher:className="com.google.android.youtube.videos.EntryPoint" - launcher:packageName="com.google.android.videos" /> - <favorite - launcher:className="com.google.android.apps.books.app.BooksActivity" - launcher:packageName="com.google.android.apps.books" /> - <favorite - launcher:className="com.google.apps.dots.android.app.activity.CurrentsStartActivity" - launcher:packageName="com.google.android.apps.magazines" /> - <favorite - launcher:className="com.google.android.gms.games.ui.destination.main.MainActivity" - launcher:packageName="com.google.android.play.games" /> - <favorite - launcher:className="com.google.android.apps.docs.app.NewMainProxyActivity" - launcher:packageName="com.google.android.apps.docs" /> - <favorite - launcher:className="com.google.android.youtube.app.honeycomb.Shell$HomeActivity" - launcher:packageName="com.google.android.youtube" /> - <favorite - launcher:className="com.google.android.apps.plus.phone.ConversationListActivity" - launcher:packageName="com.google.android.apps.plus" /> - <favorite - launcher:className="com.google.android.talk.SigningInActivity" - launcher:packageName="com.google.android.talk" /> - </folder> <favorite launcher:packageName="com.andrew.apollo" launcher:className="com.andrew.apollo.ui.activities.HomeActivity" @@ -83,14 +45,6 @@ <!-- Screen [2] --> <appwidget - launcher:packageName="com.android.vending" - launcher:className="com.google.android.finsky.widget.consumption.NowPlayingWidgetProvider" - launcher:screen="2" - launcher:x="0" - launcher:y="0" - launcher:spanX="4" - launcher:spanY="2" /> - <appwidget launcher:packageName="com.android.mms" launcher:className="com.android.mms.widget.MmsWidgetProvider" launcher:screen="2" @@ -99,12 +53,6 @@ launcher:spanX="4" launcher:spanY="2" /> <favorite - launcher:packageName="com.cyanogenmod.gallerynext" - launcher:className="com.cyanogenmod.gallerynext.app.GalleryActivity" - launcher:screen="2" - launcher:x="0" - launcher:y="3" /> - <favorite launcher:packageName="com.android.gallery3d" launcher:className="com.android.gallery3d.app.Gallery" launcher:screen="2" @@ -133,13 +81,6 @@ launcher:x="1" launcher:y="0" /> <favorite - launcher:packageName="com.android.chrome" - launcher:className="com.google.android.apps.chrome.Main" - launcher:container="-101" - launcher:screen="3" - launcher:x="3" - launcher:y="0" /> - <favorite launcher:packageName="com.android.browser" launcher:className="com.android.browser.BrowserActivity" launcher:container="-101" @@ -147,13 +88,6 @@ launcher:x="3" launcher:y="0" /> <favorite - launcher:packageName="com.cyngn.cameranext" - launcher:className="com.android.camera.CameraLauncher" - launcher:container="-101" - launcher:screen="4" - launcher:x="4" - launcher:y="0" /> - <favorite launcher:packageName="com.android.camera2" launcher:className="com.android.camera.CameraLauncher" launcher:container="-101" diff --git a/res/xml/default_workspace_gapps.xml b/res/xml/default_workspace_gapps.xml new file mode 100644 index 000000000..b2b6cfc7f --- /dev/null +++ b/res/xml/default_workspace_gapps.xml @@ -0,0 +1,163 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2013-2014 The CyanogenMod 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. +--> +<favorites xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher3"> + <!-- Screen [1] --> + <appwidget + launcher:packageName="com.cyanogenmod.lockclock" + launcher:className="com.cyanogenmod.lockclock.ClockWidgetProvider" + launcher:screen="1" + launcher:x="0" + launcher:y="0" + launcher:spanX="4" + launcher:spanY="2" /> + <folder launcher:screen="1" launcher:x="0" launcher:y="3" launcher:title="@string/google_title"> + <favorite + launcher:className="com.google.android.gm.ConversationListActivityGmail" + launcher:packageName="com.google.android.gm" /> + <favorite + launcher:className="com.google.android.apps.plus.phone.HomeActivity" + launcher:packageName="com.google.android.apps.plus" /> + <favorite + launcher:className="com.google.android.maps.MapsActivity" + launcher:packageName="com.google.android.apps.maps" /> + <favorite + launcher:className="com.android.music.activitymanagement.TopLevelActivity" + launcher:packageName="com.google.android.music" /> + <favorite + launcher:className="com.google.android.youtube.videos.EntryPoint" + launcher:packageName="com.google.android.videos" /> + <favorite + launcher:className="com.google.android.apps.books.app.BooksActivity" + launcher:packageName="com.google.android.apps.books" /> + <favorite + launcher:className="com.google.apps.dots.android.app.activity.CurrentsStartActivity" + launcher:packageName="com.google.android.apps.magazines" /> + <favorite + launcher:className="com.google.android.gms.games.ui.destination.main.MainActivity" + launcher:packageName="com.google.android.play.games" /> + <favorite + launcher:className="com.google.android.apps.docs.app.NewMainProxyActivity" + launcher:packageName="com.google.android.apps.docs" /> + <favorite + launcher:className="com.google.android.youtube.app.honeycomb.Shell$HomeActivity" + launcher:packageName="com.google.android.youtube" /> + <favorite + launcher:className="com.google.android.apps.plus.phone.ConversationListActivity" + launcher:packageName="com.google.android.apps.plus" /> + <favorite + launcher:className="com.google.android.talk.SigningInActivity" + launcher:packageName="com.google.android.talk" /> + </folder> + <favorite + launcher:packageName="com.andrew.apollo" + launcher:className="com.andrew.apollo.ui.activities.HomeActivity" + launcher:screen="1" + launcher:x="0" + launcher:y="3" /> + <favorite + launcher:packageName="com.android.vending" + launcher:className="com.android.vending.AssetBrowserActivity" + launcher:screen="1" + launcher:x="3" + launcher:y="3" /> + <favorite + launcher:packageName="com.bel.android.dspmanager" + launcher:className="com.bel.android.dspmanager.activity.DSPManager" + launcher:screen="1" + launcher:x="3" + launcher:y="3" /> + + <!-- Screen [2] --> + <appwidget + launcher:packageName="com.android.vending" + launcher:className="com.google.android.finsky.widget.consumption.NowPlayingWidgetProvider" + launcher:screen="2" + launcher:x="0" + launcher:y="0" + launcher:spanX="4" + launcher:spanY="2" /> + <appwidget + launcher:packageName="com.android.mms" + launcher:className="com.android.mms.widget.MmsWidgetProvider" + launcher:screen="2" + launcher:x="0" + launcher:y="0" + launcher:spanX="4" + launcher:spanY="2" /> + <favorite + launcher:packageName="com.cyngn.gallerynext" + launcher:className="com.cyngn.gallerynext.app.GalleryActivity" + launcher:screen="2" + launcher:x="0" + launcher:y="3" /> + <favorite + launcher:packageName="com.android.gallery3d" + launcher:className="com.android.gallery3d.app.Gallery" + launcher:screen="2" + launcher:x="0" + launcher:y="3" /> + <favorite + launcher:packageName="com.android.settings" + launcher:className="com.android.settings.Settings" + launcher:screen="2" + launcher:x="3" + launcher:y="3" /> + + <!-- Hotseat (We use the screen as the position of the item in the hotseat) --> + <favorite + launcher:packageName="com.android.dialer" + launcher:className="com.android.dialer.DialtactsActivity" + launcher:container="-101" + launcher:screen="0" + launcher:x="0" + launcher:y="0" /> + <favorite + launcher:packageName="com.android.mms" + launcher:className="com.android.mms.ui.ConversationList" + launcher:container="-101" + launcher:screen="1" + launcher:x="1" + launcher:y="0" /> + <favorite + launcher:packageName="com.android.chrome" + launcher:className="com.google.android.apps.chrome.Main" + launcher:container="-101" + launcher:screen="3" + launcher:x="3" + launcher:y="0" /> + <favorite + launcher:packageName="com.android.browser" + launcher:className="com.android.browser.BrowserActivity" + launcher:container="-101" + launcher:screen="3" + launcher:x="3" + launcher:y="0" /> + <favorite + launcher:packageName="com.cyngn.cameranext" + launcher:className="com.android.camera.CameraLauncher" + launcher:container="-101" + launcher:screen="4" + launcher:x="4" + launcher:y="0" /> + <favorite + launcher:packageName="com.android.camera2" + launcher:className="com.android.camera.CameraLauncher" + launcher:container="-101" + launcher:screen="4" + launcher:x="4" + launcher:y="0" /> +</favorites> diff --git a/res/drawable/iconpack_button.xml b/res/xml/default_workspace_no_all_apps.xml index fedfb7a8e..9a46908d9 100644 --- a/res/drawable/iconpack_button.xml +++ b/res/xml/default_workspace_no_all_apps.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2011 The Android Open Source Project +<!-- Copyright (C) 2013 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. @@ -14,8 +14,8 @@ limitations under the License. --> -<selector xmlns:android="http://schemas.android.com/apk/res/android"> - <item android:state_focused="true" android:drawable="@drawable/ic_iconpacks_pressed" /> - <item android:state_pressed="true" android:drawable="@drawable/ic_iconpacks_pressed" /> - <item android:drawable="@drawable/ic_iconpacks" /> -</selector> +<favorites xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3"> + <!-- Hotseat (We use the screen as the position of the item in the hotseat) --> + <!-- Dialer Hangouts Maps Chrome Camera --> +</favorites> + diff --git a/res/xml/default_workspace_no_all_apps_gapps.xml b/res/xml/default_workspace_no_all_apps_gapps.xml new file mode 100644 index 000000000..7e1301cef --- /dev/null +++ b/res/xml/default_workspace_no_all_apps_gapps.xml @@ -0,0 +1,56 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2013 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. +--> + +<favorites xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3"> + <!-- Hotseat (We use the screen as the position of the item in the hotseat) --> + <!-- Dialer Hangouts Maps Chrome Camera --> + <favorite + launcher:packageName="com.google.android.dialer" + launcher:className="com.google.android.dialer.extensions.GoogleDialtactsActivity" + launcher:container="-101" + launcher:screen="0" + launcher:x="0" + launcher:y="0" /> + <favorite + launcher:packageName="com.google.android.talk" + launcher:className="com.google.android.talk.SigningInActivity" + launcher:container="-101" + launcher:screen="1" + launcher:x="1" + launcher:y="0" /> + <favorite + launcher:packageName="com.google.android.apps.maps" + launcher:className="com.google.android.maps.MapsActivity" + launcher:container="-101" + launcher:screen="2" + launcher:x="2" + launcher:y="0"/> + <favorite + launcher:packageName="com.android.chrome" + launcher:className="com.google.android.apps.chrome.Main" + launcher:container="-101" + launcher:screen="3" + launcher:x="3" + launcher:y="0" /> + <favorite + launcher:packageName="com.google.android.GoogleCamera" + launcher:className="com.android.camera.CameraLauncher" + launcher:container="-101" + launcher:screen="4" + launcher:x="4" + launcher:y="0" /> +</favorites> + diff --git a/res/xml/default_workspace_no_telephony.xml b/res/xml/default_workspace_no_telephony.xml index ce11edd35..868ffbece 100644 --- a/res/xml/default_workspace_no_telephony.xml +++ b/res/xml/default_workspace_no_telephony.xml @@ -24,35 +24,6 @@ launcher:y="0" launcher:spanX="4" launcher:spanY="2" /> - <folder launcher:screen="1" launcher:x="0" launcher:y="3" launcher:title="@string/google_title"> - <favorite - launcher:className="com.google.android.maps.MapsActivity" - launcher:packageName="com.google.android.apps.maps" /> - <favorite - launcher:className="com.google.android.gm.GmailActivity" - launcher:packageName="com.google.android.gm" /> - <favorite - launcher:className="com.google.android.apps.plus.phone.HomeActivity" - launcher:packageName="com.google.android.apps.plus" /> - <favorite - launcher:className="com.android.music.activitymanagement.TopLevelActivity" - launcher:packageName="com.google.android.music" /> - <favorite - launcher:className="com.google.android.youtube.app.honeycomb.Shell$HomeActivity" - launcher:packageName="com.google.android.youtube" /> - <favorite - launcher:className="com.google.android.talk.SigningInActivity" - launcher:packageName="com.google.android.talk" /> - <favorite - launcher:className="com.android.calendar.AllInOneActivity" - launcher:packageName="com.google.android.calendar" /> - <favorite - launcher:className="com.google.android.maps.driveabout.app.DestinationActivity" - launcher:packageName="com.google.android.apps.maps" /> - <favorite - launcher:className="com.google.android.apps.plus.phone.ConversationListActivity" - launcher:packageName="com.google.android.apps.plus" /> - </folder> <favorite launcher:packageName="com.andrew.apollo" launcher:className="com.andrew.apollo.ui.activities.HomeActivity" @@ -60,12 +31,6 @@ launcher:x="0" launcher:y="3" /> <favorite - launcher:packageName="com.android.vending" - launcher:className="com.android.vending.AssetBrowserActivity" - launcher:screen="1" - launcher:x="3" - launcher:y="3" /> - <favorite launcher:packageName="com.bel.android.dspmanager" launcher:className="com.bel.android.dspmanager.activity.DSPManager" launcher:screen="1" @@ -74,14 +39,6 @@ <!-- Screen [2] --> <appwidget - launcher:packageName="com.android.vending" - launcher:className="com.google.android.finsky.widget.consumption.NowPlayingWidgetProvider" - launcher:screen="2" - launcher:x="0" - launcher:y="0" - launcher:spanX="4" - launcher:spanY="2" /> - <appwidget launcher:packageName="com.android.settings" launcher:className="com.android.settings.widget.SettingsAppWidgetProvider" launcher:screen="2" @@ -90,12 +47,6 @@ launcher:spanX="4" launcher:spanY="1" /> <favorite - launcher:packageName="com.cyanogenmod.gallerynext" - launcher:className="com.cyanogenmod.gallerynext.app.GalleryActivity" - launcher:screen="2" - launcher:x="0" - launcher:y="3" /> - <favorite launcher:packageName="com.android.gallery3d" launcher:className="com.android.gallery3d.app.Gallery" launcher:screen="2" @@ -117,13 +68,6 @@ launcher:x="0" launcher:y="0" /> <favorite - launcher:packageName="com.google.android.gm" - launcher:className="com.google.android.gm.ConversationListActivityGmail" - launcher:container="-101" - launcher:screen="1" - launcher:x="1" - launcher:y="0" /> - <favorite launcher:packageName="com.android.email" launcher:className="com.android.email.activity.Welcome" launcher:container="-101" @@ -131,13 +75,6 @@ launcher:x="1" launcher:y="0" /> <favorite - launcher:packageName="com.android.chrome" - launcher:className="com.google.android.apps.chrome.Main" - launcher:container="-101" - launcher:screen="3" - launcher:x="3" - launcher:y="0" /> - <favorite launcher:packageName="com.android.browser" launcher:className="com.android.browser.BrowserActivity" launcher:container="-101" diff --git a/res/xml/default_workspace_no_telephony_gapps.xml b/res/xml/default_workspace_no_telephony_gapps.xml new file mode 100644 index 000000000..f23d12bf4 --- /dev/null +++ b/res/xml/default_workspace_no_telephony_gapps.xml @@ -0,0 +1,154 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2013-2014 The CyanogenMod 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. +--> +<favorites xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher3"> + <!-- Screen [1] --> + <appwidget + launcher:packageName="com.cyanogenmod.lockclock" + launcher:className="com.cyanogenmod.lockclock.ClockWidgetProvider" + launcher:screen="1" + launcher:x="0" + launcher:y="0" + launcher:spanX="4" + launcher:spanY="2" /> + <folder launcher:screen="1" launcher:x="0" launcher:y="3" launcher:title="@string/google_title"> + <favorite + launcher:className="com.google.android.maps.MapsActivity" + launcher:packageName="com.google.android.apps.maps" /> + <favorite + launcher:className="com.google.android.gm.ConversationListActivityGmail" + launcher:packageName="com.google.android.gm" /> + <favorite + launcher:className="com.google.android.apps.plus.phone.HomeActivity" + launcher:packageName="com.google.android.apps.plus" /> + <favorite + launcher:className="com.android.music.activitymanagement.TopLevelActivity" + launcher:packageName="com.google.android.music" /> + <favorite + launcher:className="com.google.android.youtube.app.honeycomb.Shell$HomeActivity" + launcher:packageName="com.google.android.youtube" /> + <favorite + launcher:className="com.google.android.talk.SigningInActivity" + launcher:packageName="com.google.android.talk" /> + <favorite + launcher:className="com.android.calendar.AllInOneActivity" + launcher:packageName="com.google.android.calendar" /> + <favorite + launcher:className="com.google.android.maps.driveabout.app.DestinationActivity" + launcher:packageName="com.google.android.apps.maps" /> + <favorite + launcher:className="com.google.android.apps.plus.phone.ConversationListActivity" + launcher:packageName="com.google.android.apps.plus" /> + </folder> + <favorite + launcher:packageName="com.andrew.apollo" + launcher:className="com.andrew.apollo.ui.activities.HomeActivity" + launcher:screen="1" + launcher:x="0" + launcher:y="3" /> + <favorite + launcher:packageName="com.android.vending" + launcher:className="com.android.vending.AssetBrowserActivity" + launcher:screen="1" + launcher:x="3" + launcher:y="3" /> + <favorite + launcher:packageName="com.bel.android.dspmanager" + launcher:className="com.bel.android.dspmanager.activity.DSPManager" + launcher:screen="1" + launcher:x="3" + launcher:y="3" /> + + <!-- Screen [2] --> + <appwidget + launcher:packageName="com.android.vending" + launcher:className="com.google.android.finsky.widget.consumption.NowPlayingWidgetProvider" + launcher:screen="2" + launcher:x="0" + launcher:y="0" + launcher:spanX="4" + launcher:spanY="2" /> + <appwidget + launcher:packageName="com.android.settings" + launcher:className="com.android.settings.widget.SettingsAppWidgetProvider" + launcher:screen="2" + launcher:x="0" + launcher:y="0" + launcher:spanX="4" + launcher:spanY="1" /> + <favorite + launcher:packageName="com.cyngn.gallerynext" + launcher:className="com.cyngn.gallerynext.app.GalleryActivity" + launcher:screen="2" + launcher:x="0" + launcher:y="3" /> + <favorite + launcher:packageName="com.android.gallery3d" + launcher:className="com.android.gallery3d.app.Gallery" + launcher:screen="2" + launcher:x="0" + launcher:y="3" /> + <favorite + launcher:packageName="com.android.settings" + launcher:className="com.android.settings.Settings" + launcher:screen="2" + launcher:x="3" + launcher:y="3" /> + + <!-- Hotseat (We use the screen as the position of the item in the hotseat) --> + <favorite + launcher:packageName="com.android.contacts" + launcher:className="com.android.contacts.activities.PeopleActivity" + launcher:container="-101" + launcher:screen="0" + launcher:x="0" + launcher:y="0" /> + <favorite + launcher:packageName="com.google.android.gm" + launcher:className="com.google.android.gm.ConversationListActivityGmail" + launcher:container="-101" + launcher:screen="1" + launcher:x="1" + launcher:y="0" /> + <favorite + launcher:packageName="com.android.email" + launcher:className="com.android.email.activity.Welcome" + launcher:container="-101" + launcher:screen="1" + launcher:x="1" + launcher:y="0" /> + <favorite + launcher:packageName="com.android.chrome" + launcher:className="com.google.android.apps.chrome.Main" + launcher:container="-101" + launcher:screen="3" + launcher:x="3" + launcher:y="0" /> + <favorite + launcher:packageName="com.android.browser" + launcher:className="com.android.browser.BrowserActivity" + launcher:container="-101" + launcher:screen="3" + launcher:x="3" + launcher:y="0" /> + <favorite + launcher:packageName="com.android.camera2" + launcher:className="com.android.camera.CameraLauncher" + launcher:container="-101" + launcher:screen="4" + launcher:x="4" + launcher:y="0" /> +</favorites> diff --git a/res/xml/preferences_drawer.xml b/res/xml/preferences_drawer.xml deleted file mode 100644 index b22597516..000000000 --- a/res/xml/preferences_drawer.xml +++ /dev/null @@ -1,42 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- 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. ---> - -<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher3" - android:key="ui_drawer" - android:title="@string/preferences_interface_drawer_title"> - <PreferenceCategory android:title="@string/preferences_interface_drawer_apps_category"> - <Preference android:key="ui_drawer_hidden_apps" - android:title="@string/preferences_interface_drawer_hidden_apps_title" - android:summary="@string/preferences_interface_drawer_hidden_apps_summary"> - <intent android:action=".settings.HiddenAppsActivity"/> - </Preference> - <CheckBoxPreference android:key="ui_drawer_remove_hidden_apps_shortcuts" - android:title="@string/preferences_interface_drawer_hidden_apps_shortcuts_title" - android:summary="@string/preferences_interface_drawer_hidden_apps_shortcuts_summary" - android:defaultValue="@bool/preferences_interface_drawer_remove_hidden_apps_shortcuts_default" /> - <CheckBoxPreference android:key="ui_drawer_remove_hidden_apps_widgets" - android:title="@string/preferences_interface_drawer_hidden_apps_widgets_title" - android:summary="@string/preferences_interface_drawer_hidden_apps_widgets_summary" - android:defaultValue="@bool/preferences_interface_drawer_remove_hidden_apps_widgets_default" /> - </PreferenceCategory> - <PreferenceCategory android:title="@string/preferences_interface_general_icons_category"> - <CheckBoxPreference android:key="ui_drawer_hide_icon_labels" - android:title="@string/preferences_interface_drawer_hide_icon_labels_title" - android:summary="@string/preferences_interface_drawer_hide_icon_labels_summary" - android:defaultValue="@bool/preferences_interface_drawer_hide_icon_labels_default" /> - </PreferenceCategory> -</PreferenceScreen>
\ No newline at end of file diff --git a/res/xml/preferences_general.xml b/res/xml/preferences_general.xml deleted file mode 100644 index 96b93ec44..000000000 --- a/res/xml/preferences_general.xml +++ /dev/null @@ -1,34 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- 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. ---> - -<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher3" - android:key="ui_general" - android:title="@string/preferences_interface_general_title"> - <PreferenceCategory android:title="@string/preferences_interface_general_icons_category"> - <CheckBoxPreference android:key="ui_general_icons_large" - android:title="@string/preferences_interface_general_icons_large_title" - android:summary="@string/preferences_interface_general_icons_large_summary" - android:defaultValue="@bool/preferences_interface_general_icons_large_default" /> - <com.android.launcher3.settings.FontStylePreference android:key="ui_general_icons_text_font" - android:title="@string/preferences_interface_general_icons_text_style_title" - android:summary="@string/preferences_interface_general_icons_text_style_summary" - android:entries="@array/preferences_interface_general_icons_text_font_family_entries" - android:entryValues="@array/preferences_interface_general_icons_text_font_family_values" - android:defaultValue="@string/preferences_interface_general_icons_text_font_family_default" /> - </PreferenceCategory> - -</PreferenceScreen> diff --git a/res/xml/preferences_headers.xml b/res/xml/preferences_headers.xml deleted file mode 100644 index 42a08a9bd..000000000 --- a/res/xml/preferences_headers.xml +++ /dev/null @@ -1,41 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - Copyright (C) 2014 The CyanogenMod 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. ---> -<preference-headers xmlns:android="http://schemas.android.com/apk/res/android"> - - <header android:id="@+id/preferences_homescreen_section" - android:fragment="com.android.launcher3.settings.SettingsActivity$HomescreenFragment" - android:title="@string/preferences_interface_homescreen_title" /> - - <header android:id="@+id/preferences_drawer_section" - android:fragment="com.android.launcher3.settings.SettingsActivity$DrawerFragment" - android:title="@string/preferences_interface_drawer_title" - android:summary="@string/preferences_interface_drawer_summary" /> - - <!--<header android:id="@+id/preferences_dock_section" - android:title="@string/preferences_interface_dock_title" />--> - - <header android:id="@+id/preferences_general_section" - android:fragment="com.android.launcher3.settings.SettingsActivity$GeneralFragment" - android:title="@string/preferences_interface_general_title" /> - - <header android:id="@+id/preferences_application_section" - android:title="@string/preferences_application_title" /> - - <header android:id="@+id/preferences_application_version" - android:summary="@string/application_copyright" /> - -</preference-headers> diff --git a/res/xml/preferences_homescreen.xml b/res/xml/preferences_homescreen.xml deleted file mode 100644 index 1754cfa02..000000000 --- a/res/xml/preferences_homescreen.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- 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. ---> - -<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher3" - android:key="ui_homescreen" - android:title="@string/preferences_interface_homescreen_title"> - <CheckBoxPreference android:key="ui_homescreen_search" - android:title="@string/preferences_interface_homescreen_search_title" - android:summary="@string/preferences_interface_homescreen_search_summary" - android:defaultValue="@bool/preferences_interface_homescreen_search_default" /> - <CheckBoxPreference android:key="ui_homescreen_general_hide_icon_labels" - android:title="@string/preferences_interface_homescreen_general_hide_icon_labels_title" - android:summary="@string/preferences_interface_homescreen_general_hide_icon_labels_summary" - android:defaultValue="@bool/preferences_interface_homescreen_hide_icon_labels_default" /> -</PreferenceScreen> diff --git a/src/com/android/launcher/home/Home.java b/src/com/android/launcher/home/Home.java new file mode 100644 index 000000000..5dce71e86 --- /dev/null +++ b/src/com/android/launcher/home/Home.java @@ -0,0 +1,201 @@ +/* + * Copyright (C) 2014 The CyanogenMod 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.android.launcher.home; + +import android.content.Context; +import android.view.View; +import android.view.ViewGroup.LayoutParams; + +/** + * The generic contract that should supports a <code>Home</code> app to could + * be invoked and registered by an Android launcher.<br/> + * <br/> + * This interface contains the version 1 of the <code>Home Host App</code> protocol.<br/> + * <br/> + * <br/> + * A <code>Home</code> app should: + * <ul> + * <li> + * should have at least a constructor with no arguments + * </li> + * <li> + * declares inside its manifest a <code>com.android.launcher.home</code> metadata with the + * full qualified that contains this interface<br/> + * <pre> + * <meta-data android:name="com.android.launcher.home" value="org.cyanogenmod.launcher.home.HomeStub"/> + * </pre> + * </li> + * <li> + * define the "com.android.launcher.home.permissions.HOME_APP" permission<br/> + * <pre> + * <uses-permission android:name="com.android.launcher.home.permissions.HOME_APP"/> + * </pre> + * </li> + * <li> + * implements the contract defined by this protocol. + * </li> + * </ul> + * <br/> + * Implementors classes of this protocol should be aware that all the {@link Context} references + * passed to this class owns to the host launcher app. This means that you cannot access + * to settings defined by the <code>Home</code> app inside its shared context. + */ +public interface Home { + + /** + * A SHA-1 hash of all declared method of this interface. Home apps should compute as:<br/> + * <br/> + * <pre> + * for method in Home.class.getDeclaredMehod + * sha1.update method.toString.bytes + * </pre><br/> + * DO NOT MODIFY! + */ + public static final String SIGNATURE = "5/A6Mxkz8gHHzzVf4qZR+hiSOAw="; + + /** + * Defines the name of the metadata used to declared the full qualified Home stub class + * that implements this protocol. + */ + public static final String METADATA_HOME_STUB = "com.android.launcher.home"; + + /** + * Defines the name of the permission that the Home app should explicitly declare. + */ + public static final String PERMISSION_HOME_APP = "com.android.launcher.home.permissions.HOME_APP"; + + // Notification flags + public static final int FLAG_NOTIFY_MASK = 0x0000; + public static final int FLAG_NOTIFY_ON_RESUME = FLAG_NOTIFY_MASK + 0x0002; + public static final int FLAG_NOTIFY_ON_PAUSE = FLAG_NOTIFY_MASK + 0x0004; + public static final int FLAG_NOTIFY_ON_SHOW = FLAG_NOTIFY_MASK + 0x0008; + public static final int FLAG_NOTIFY_ON_SCROLL_PROGRESS_CHANGED = FLAG_NOTIFY_MASK + 0x0010; + public static final int FLAG_NOTIFY_ON_HIDE = FLAG_NOTIFY_MASK + 0x0020; + public static final int FLAG_NOTIFY_ALL = FLAG_NOTIFY_ON_RESUME | FLAG_NOTIFY_ON_PAUSE | + FLAG_NOTIFY_ON_SHOW | FLAG_NOTIFY_ON_SCROLL_PROGRESS_CHANGED | FLAG_NOTIFY_ON_HIDE; + + // Operation support flags + public static final int FLAG_OP_MASK = 0x1000; + public static final int FLAG_OP_CUSTOM_SEARCH = FLAG_OP_MASK + 0x0002; + public static final int FLAG_OP_ALL = FLAG_OP_CUSTOM_SEARCH; + + // Search modes + public static final int MODE_SEARCH_TEXT = 0x0000; + public static final int MODE_SEARCH_VOICE = 0x0001; + + /** + * Invoked the first time the <code>Home</code> app is created.<br/> + * This method should be used by implementors classes of this protocol to load the needed + * resources. + * @param context the current {@link Context} of the host launcher. + */ + void onStart(Context context); + + /** + * Invoked when the <code>Home</code> app should be destroy.<br/> + * This method should be used by implementors classes of this protocol to unload all unneeded + * resources. + * @param context the current {@link Context} of the host launcher. + */ + void onDestroy(Context context); + + /** + * Invoked when the host launcher enters in resume mode. + * @param context the current {@link Context} of the host launcher. + */ + void onResume(Context context); + + /** + * Invoked when the host launcher enters in pause mode. + * @param context the current {@link Context} of the host launcher. + */ + void onPause(Context context); + + /** + * Invoked when the custom content page is totally displayed. + * @param context the current {@link Context} of the host launcher. + */ + void onShow(Context context); + + /** + * Invoked when the custom content page is scrolled. + * @param context the current {@link Context} of the host launcher. + * @param progress the current scroll progress. + */ + void onScrollProgressChanged(Context context, float progress); + + /** + * Invoked when the custom content page is totally hidden. + * @param context the current {@link Context} of the host launcher. + */ + void onHide(Context context); + + /** + * Invoked by the host launcher to request an invalidation of the ui elements and data used by + * the <code>Home</code> implementation class. + * @param context the current {@link Context} of the host launcher. + */ + void onInvalidate(Context context); + + /** + * Invoked when the host launcher request enter in search mode. + * @param context the current {@link Context} of the host launcher. + * @param mode the requested search mode. Must be one of: + * <ul> + * <li>{@link #MODE_SEARCH_TEXT}: Textual mode</li> + * <li>{@link #MODE_SEARCH_VOICE}: Voice mode</li> + * </ul> + */ + void onRequestSearch(Context context, int mode); + + /** + * Returns an instance of a {@link View} that holds the custom content to be displayed + * by this <code>Home</code> app. + * @param context the current {@link Context} of the host launcher. + * @return View The custom content view that will be enclosed inside a + * <code>com.android.launcher3.Launcher.QSBScroller</code>.<br/> + * Be aware the the height layout of the returned should be defined as + * {link {@link LayoutParams#WRAP_CONTENT}, so the view could be scrolled inside the + * custom content page. + */ + View createCustomView(Context context); + + /** + * Returns the name of the Home app (LIMIT: 30 characters). + * @param context the current {@link Context} of the host launcher. + */ + String getName(Context context); + + /** + * Implementations should return the combination of notification flags that want to listen to. + * @see #FLAG_NOTIFY_ON_RESUME + * @see #FLAG_NOTIFY_ON_PAUSE + * @see #FLAG_NOTIFY_ON_SHOW + * @see #FLAG_NOTIFY_ON_SCROLL_PROGRESS_CHANGED + * @see #FLAG_NOTIFY_ON_HIDE + * @see #FLAG_NOTIFY_ALL + */ + int getNotificationFlags(); + + /** + * Implementations should return the combination of operation flags that want they want + * to support to. + * @see #FLAG_OP_CUSTOM_SEARCH + * @see #FLAG_OP_ALL + */ + int getOperationFlags(); +} diff --git a/src/com/android/launcher3/AddAdapter.java b/src/com/android/launcher3/AddAdapter.java index ad15e75c6..5308a3de4 100644 --- a/src/com/android/launcher3/AddAdapter.java +++ b/src/com/android/launcher3/AddAdapter.java @@ -27,8 +27,6 @@ import android.widget.TextView; import java.util.ArrayList; -import com.android.launcher3.R; - /** * Adapter showing the types of items that can be added to a {@link Workspace}. */ diff --git a/src/com/android/launcher3/Alarm.java b/src/com/android/launcher3/Alarm.java index 91f9bd091..e9f1fd963 100644 --- a/src/com/android/launcher3/Alarm.java +++ b/src/com/android/launcher3/Alarm.java @@ -78,7 +78,3 @@ public class Alarm implements Runnable{ return mAlarmPending; } } - -interface OnAlarmListener { - public void onAlarm(Alarm alarm); -} diff --git a/src/com/android/launcher3/AllAppsList.java b/src/com/android/launcher3/AllAppsList.java index d955e4eae..89b291f28 100644 --- a/src/com/android/launcher3/AllAppsList.java +++ b/src/com/android/launcher3/AllAppsList.java @@ -16,9 +16,6 @@ package com.android.launcher3; -import java.util.ArrayList; -import java.util.List; - import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -26,13 +23,16 @@ import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; +import java.util.ArrayList; +import java.util.List; + /** * Stores the list of all applications for the all apps view. */ class AllAppsList { public static final int DEFAULT_APPLICATIONS_NUMBER = 42; - + /** The list off all apps. */ public ArrayList<AppInfo> data = new ArrayList<AppInfo>(DEFAULT_APPLICATIONS_NUMBER); @@ -115,8 +115,7 @@ class AllAppsList { data.remove(i); } } - // This is more aggressive than it needs to be. - mIconCache.flush(); + mIconCache.remove(packageName); } /** diff --git a/src/com/android/launcher3/AppInfo.java b/src/com/android/launcher3/AppInfo.java index 53f81bb1c..da222f11f 100644 --- a/src/com/android/launcher3/AppInfo.java +++ b/src/com/android/launcher3/AppInfo.java @@ -18,9 +18,9 @@ package com.android.launcher3; import android.content.ComponentName; import android.content.Intent; +import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; -import android.content.pm.PackageInfo; import android.content.pm.ResolveInfo; import android.graphics.Bitmap; import android.util.Log; @@ -64,6 +64,10 @@ class AppInfo extends ItemInfo { return intent; } + protected Intent getRestoredIntent() { + return null; + } + /** * Must not hold the Context. */ diff --git a/src/com/android/launcher3/AppWidgetResizeFrame.java b/src/com/android/launcher3/AppWidgetResizeFrame.java index ba31621f1..c2125b796 100644 --- a/src/com/android/launcher3/AppWidgetResizeFrame.java +++ b/src/com/android/launcher3/AppWidgetResizeFrame.java @@ -13,8 +13,6 @@ import android.view.Gravity; import android.widget.FrameLayout; import android.widget.ImageView; -import com.android.launcher3.R; - public class AppWidgetResizeFrame extends FrameLayout { private LauncherAppWidgetHostView mWidgetView; private CellLayout mCellLayout; diff --git a/src/com/android/launcher3/AppsCustomizeLayout.java b/src/com/android/launcher3/AppsCustomizeLayout.java index ea1c36a9c..16e5449e6 100644 --- a/src/com/android/launcher3/AppsCustomizeLayout.java +++ b/src/com/android/launcher3/AppsCustomizeLayout.java @@ -67,12 +67,12 @@ public class AppsCustomizeLayout extends FrameLayout implements LauncherTransiti mContent = (FrameLayout) findViewById(R.id.apps_customize_content); if (mAppsCustomizePane == null) throw new Resources.NotFoundException(); - findViewById(R.id.page_indicator).setOnClickListener(new OnClickListener() { + /*findViewById(R.id.page_indicator).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { mAppsCustomizePane.enterOverviewMode(); } - }); + });*/ } public boolean onInterceptTouchEvent(MotionEvent ev) { @@ -136,6 +136,10 @@ public class AppsCustomizeLayout extends FrameLayout implements LauncherTransiti @Override public View getContent() { + View appsCustomizeContent = mAppsCustomizePane.getContent(); + if (appsCustomizeContent != null) { + return appsCustomizeContent; + } return mContent; } @@ -171,12 +175,12 @@ public class AppsCustomizeLayout extends FrameLayout implements LauncherTransiti } // Dismiss the workspace cling - l.dismissWorkspaceCling(null); + l.getLauncherClings().dismissWorkspaceCling(null); } @Override public void onLauncherTransitionStep(Launcher l, float t) { - // Do nothing + mAppsCustomizePane.onLauncherTransitionStep(l, t); } @Override diff --git a/src/com/android/launcher3/AppsCustomizePagedView.java b/src/com/android/launcher3/AppsCustomizePagedView.java index ed504cf2e..f2c08a3e1 100644 --- a/src/com/android/launcher3/AppsCustomizePagedView.java +++ b/src/com/android/launcher3/AppsCustomizePagedView.java @@ -40,6 +40,7 @@ import android.os.AsyncTask; import android.os.Build; import android.os.Bundle; import android.os.Process; +import android.provider.Settings; import android.support.v4.view.ViewCompat; import android.util.AttributeSet; import android.util.Log; @@ -170,9 +171,29 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen * The different sort modes than can be used to order items. */ public enum SortMode { - Title, - LaunchCount, - InstallTime + Title(0), + LaunchCount(1), + InstallTime(2); + + private final int mValue; + private SortMode(int value) { + mValue = value; + } + + public int getValue() { + return mValue; + } + + public static SortMode getModeForValue(int value) { + switch (value) { + case 1: + return LaunchCount; + case 2: + return InstallTime; + default : + return Title; + } + } } private SortMode mSortMode = SortMode.Title; @@ -197,8 +218,8 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen private ArrayList<AppInfo> mFilteredApps; private ArrayList<Object> mFilteredWidgets; - private ArrayList<ComponentName> mHiddenApps; - private ArrayList<String> mHiddenPackages; + private ArrayList<ComponentName> mProtectedApps; + private ArrayList<String> mProtectedPackages; // Cling private boolean mHasShownAllAppsCling; @@ -216,6 +237,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen private PagedViewCellLayout mWidgetSpacingLayout; private int mNumAppsPages; private int mNumWidgetPages; + private Rect mAllAppsPadding = new Rect(); // Animation states enum State { NORMAL, OVERVIEW}; @@ -236,8 +258,6 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen private boolean mOverscrollTransformsSet; private float mLastOverscrollPivotX; - public static boolean DISABLE_ALL_APPS = false; - // Previews & outlines ArrayList<AppsCustomizeAsyncTask> mRunningTasks; private static final int sPageSleepDelay = 200; @@ -323,17 +343,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES); } - String[] flattened = SettingsProvider.getStringCustomDefault(context, - SettingsProvider.SETTINGS_UI_DRAWER_HIDDEN_APPS, "").split("\\|"); - mHiddenApps = new ArrayList<ComponentName>(flattened.length); - mHiddenPackages = new ArrayList<String>(flattened.length); - for (String flat : flattened) { - ComponentName cmp = ComponentName.unflattenFromString(flat); - if (cmp != null) { - mHiddenApps.add(cmp); - mHiddenPackages.add(cmp.getPackageName()); - } - } + updateProtectedAppsList(context); } @Override @@ -361,6 +371,20 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen grid.edgeMarginPx, 2 * grid.edgeMarginPx); } + void setAllAppsPadding(Rect r) { + mAllAppsPadding.set(r); + } + void setWidgetsPageIndicatorPadding(int pageIndicatorHeight) { + mPageLayoutPaddingBottom = pageIndicatorHeight; + } + + WidgetPreviewLoader getWidgetPreviewLoader() { + if (mWidgetPreviewLoader == null) { + mWidgetPreviewLoader = new WidgetPreviewLoader(mLauncher); + } + return mWidgetPreviewLoader; + } + /** Returns the item index of the center item on this page so that we can restore to this * item index when we rotate. */ private int getMiddleComponentIndexOnCurrentPage() { @@ -426,10 +450,6 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen } protected void onDataReady(int width, int height) { - if (mWidgetPreviewLoader == null) { - mWidgetPreviewLoader = new WidgetPreviewLoader(mLauncher); - } - // Now that the data is ready, we can calculate the content width, the number of cells to // use for each page LauncherAppState app = LauncherAppState.getInstance(); @@ -487,7 +507,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen int width = MeasureSpec.getSize(widthMeasureSpec); int height = MeasureSpec.getSize(heightMeasureSpec); if (!isDataReady()) { - if ((DISABLE_ALL_APPS || !mFilteredApps.isEmpty()) && !mFilteredWidgets.isEmpty()) { + if (((LauncherAppState.isDisableAllApps() || !mFilteredApps.isEmpty()) && !mFilteredWidgets.isEmpty())) { setDataIsReady(); setMeasuredDimension(width, height); onDataReady(width, height); @@ -801,13 +821,13 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen int[] previewSizeBeforeScale = new int[1]; - preview = mWidgetPreviewLoader.generateWidgetPreview(createWidgetInfo.componentName, + preview = getWidgetPreviewLoader().generateWidgetPreview(createWidgetInfo.componentName, createWidgetInfo.previewImage, createWidgetInfo.icon, spanX, spanY, maxWidth, maxHeight, null, previewSizeBeforeScale); // Compare the size of the drag preview to the preview in the AppsCustomize tray int previewWidthInAppsCustomize = Math.min(previewSizeBeforeScale[0], - mWidgetPreviewLoader.maxWidthForWidgetPreview(spanX)); + getWidgetPreviewLoader().maxWidthForWidgetPreview(spanX)); scale = previewWidthInAppsCustomize / (float) preview.getWidth(); // The bitmap in the AppsCustomize tray is always the the same size, so there @@ -888,16 +908,26 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen */ private void endDragging(View target, boolean isFlingToDelete, boolean success) { if (isFlingToDelete || !success || (target != mLauncher.getWorkspace() && - !(target instanceof DeleteDropTarget))) { + !(target instanceof DeleteDropTarget) && !(target instanceof Folder))) { // Exit spring loaded mode if we have not successfully dropped or have not handled the // drop in Workspace - mLauncher.exitSpringLoadedDragMode(); + mLauncher.getWorkspace().removeExtraEmptyScreen(true, new Runnable() { + @Override + public void run() { + mLauncher.exitSpringLoadedDragMode(); + mLauncher.unlockScreenOrientation(false); + } + }); + } else { + mLauncher.unlockScreenOrientation(false); } - mLauncher.unlockScreenOrientation(false); } @Override public View getContent() { + if (getChildCount() > 0) { + return getChildAt(0); + } return null; } @@ -921,7 +951,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen public void onLauncherTransitionEnd(Launcher l, boolean animated, boolean toWorkspace) { mInTransition = false; for (AsyncTaskPageData d : mDeferredSyncWidgetPageItems) { - onSyncWidgetPageItems(d); + onSyncWidgetPageItems(d, false); } mDeferredSyncWidgetPageItems.clear(); for (Runnable r : mDeferredPrepareLoadWidgetPreviewsTasks) { @@ -978,6 +1008,23 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen } @Override + public boolean supportsAppInfoDropTarget() { + return true; + } + + @Override + public boolean supportsDeleteDropTarget() { + return false; + } + + @Override + public float getIntrinsicIconScaleFactor() { + LauncherAppState app = LauncherAppState.getInstance(); + DeviceProfile grid = app.getDynamicGrid().getDeviceProfile(); + return (float) grid.allAppsIconSizePx / grid.iconSizePx; + } + + @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); cancelAllTasks(); @@ -1021,12 +1068,12 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen } public void setContentType(ContentType type) { - int page = getCurrentPage(); - if (mContentType != type) { - page = 0; + // Widgets appear to be cleared every time you leave, always force invalidate for them + if (mContentType != type || type == ContentType.Widgets) { + int page = (mContentType != type) ? 0 : getCurrentPage(); + mContentType = type; + invalidatePageData(page, true); } - mContentType = type; - invalidatePageData(page, true); } public ContentType getContentType() { @@ -1073,6 +1120,8 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen int heightSpec = MeasureSpec.makeMeasureSpec(mContentHeight, MeasureSpec.AT_MOST); layout.setMinimumWidth(getPageContentWidth()); layout.measure(widthSpec, heightSpec); + layout.setPadding(mAllAppsPadding.left, mAllAppsPadding.top, mAllAppsPadding.right, + mAllAppsPadding.bottom); setVisibilityOnChildren(layout, View.VISIBLE); } @@ -1127,7 +1176,6 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen icon.setOnLongClickListener(this); icon.setOnTouchListener(this); icon.setOnKeyListener(this); - Utilities.applyTypeface(icon); int index = i - startIndex; int x = index % mCellCountX; @@ -1230,9 +1278,9 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen mRunningTasks.remove(task); if (task.isCancelled()) return; // do cleanup inside onSyncWidgetPageItems - onSyncWidgetPageItems(data); + onSyncWidgetPageItems(data, false); } - }, mWidgetPreviewLoader); + }, getWidgetPreviewLoader()); // Ensure that the task is appropriately prioritized and runs in parallel AppsCustomizeAsyncTask t = new AppsCustomizeAsyncTask(page, @@ -1293,7 +1341,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen createItemInfo.minSpanX = minSpanXY[0]; createItemInfo.minSpanY = minSpanXY[1]; - widget.applyFromAppWidgetProviderInfo(info, -1, spanXY, mWidgetPreviewLoader); + widget.applyFromAppWidgetProviderInfo(info, -1, spanXY, getWidgetPreviewLoader()); widget.setTag(createItemInfo); widget.setShortPressListener(this); } else if (rawInfo instanceof ResolveInfo) { @@ -1303,7 +1351,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen createItemInfo.itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT; createItemInfo.componentName = new ComponentName(info.activityInfo.packageName, info.activityInfo.name); - widget.applyFromResolveInfo(mPackageManager, info, mWidgetPreviewLoader); + widget.applyFromResolveInfo(mPackageManager, info, getWidgetPreviewLoader()); widget.setTag(createItemInfo); } widget.setOnClickListener(this); @@ -1340,13 +1388,13 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen maxPreviewHeight = maxSize[1]; } - mWidgetPreviewLoader.setPreviewSize( + getWidgetPreviewLoader().setPreviewSize( maxPreviewWidth, maxPreviewHeight, mWidgetSpacingLayout); if (immediate) { AsyncTaskPageData data = new AsyncTaskPageData(page, items, - maxPreviewWidth, maxPreviewHeight, null, null, mWidgetPreviewLoader); + maxPreviewWidth, maxPreviewHeight, null, null, getWidgetPreviewLoader()); loadWidgetPreviewsInBackground(null, data); - onSyncWidgetPageItems(data); + onSyncWidgetPageItems(data, immediate); } else { if (mInTransition) { mDeferredPrepareLoadWidgetPreviewsTasks.add(this); @@ -1381,12 +1429,12 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen task.syncThreadPriority(); } - images.add(mWidgetPreviewLoader.getPreview(items.get(i))); + images.add(getWidgetPreviewLoader().getPreview(items.get(i))); } } - private void onSyncWidgetPageItems(AsyncTaskPageData data) { - if (mInTransition) { + private void onSyncWidgetPageItems(AsyncTaskPageData data, boolean immediatelySyncItems) { + if (!immediatelySyncItems && mInTransition) { mDeferredSyncWidgetPageItems.add(data); return; } @@ -1908,6 +1956,10 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen public void setup(Launcher launcher, DragController dragController) { mLauncher = launcher; mDragController = dragController; + int sortMode = SettingsProvider.getIntCustomDefault(mLauncher, SettingsProvider.SETTINGS_UI_DRAWER_SORT_MODE, -1); + if (sortMode != -1) { + setSortMode(SortMode.getModeForValue(sortMode)); + } } /** @@ -1954,7 +2006,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen } public void setApps(ArrayList<AppInfo> list) { - if (!DISABLE_ALL_APPS) { + if (!LauncherAppState.isDisableAllApps()) { mApps = list; filterAppsWithoutInvalidate(); updatePageCountsAndInvalidateData(); @@ -1974,7 +2026,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen } public void addApps(ArrayList<AppInfo> list) { - if (!DISABLE_ALL_APPS) { + if (!LauncherAppState.isDisableAllApps()) { addAppsWithoutInvalidate(list); filterAppsWithoutInvalidate(); updatePageCountsAndInvalidateData(); @@ -2006,7 +2058,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen } public void removeApps(ArrayList<AppInfo> appInfos) { - if (!DISABLE_ALL_APPS) { + if (!LauncherAppState.isDisableAllApps()) { removeAppsWithoutInvalidate(appInfos); filterAppsWithoutInvalidate(); updatePageCountsAndInvalidateData(); @@ -2017,7 +2069,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen // We remove and re-add the updated applications list because it's properties may have // changed (ie. the title), and this will ensure that the items will be in their proper // place in the list. - if (!DISABLE_ALL_APPS) { + if (!LauncherAppState.isDisableAllApps()) { removeAppsWithoutInvalidate(list); addAppsWithoutInvalidate(list); filterAppsWithoutInvalidate(); @@ -2025,13 +2077,31 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen } } + private void updateProtectedAppsList(Context context) { + String protectedComponents = Settings.Secure.getString(context.getContentResolver(), + LauncherModel.SETTINGS_PROTECTED_COMPONENTS); + protectedComponents = protectedComponents == null ? "" : protectedComponents; + String [] flattened = protectedComponents.split("\\|"); + mProtectedApps = new ArrayList<ComponentName>(flattened.length); + mProtectedPackages = new ArrayList<String>(flattened.length); + for (String flat : flattened) { + ComponentName cmp = ComponentName.unflattenFromString(flat); + if (cmp != null) { + mProtectedApps.add(cmp); + mProtectedPackages.add(cmp.getPackageName()); + } + } + } + public void filterAppsWithoutInvalidate() { + updateProtectedAppsList(mLauncher); + mFilteredApps = new ArrayList<AppInfo>(mApps); Iterator<AppInfo> iterator = mFilteredApps.iterator(); while (iterator.hasNext()) { AppInfo appInfo = iterator.next(); boolean system = (appInfo.flags & AppInfo.DOWNLOADED_FLAG) == 0; - if (mHiddenApps.contains(appInfo.componentName) || + if (mProtectedApps.contains(appInfo.componentName) || (system && !getShowSystemApps()) || (!system && !getShowDownloadedApps())) { iterator.remove(); @@ -2046,6 +2116,8 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen } public void filterWidgetsWithoutInvalidate() { + updateProtectedAppsList(mLauncher); + mFilteredWidgets = new ArrayList<Object>(mWidgets); Iterator<Object> iterator = mFilteredWidgets.iterator(); @@ -2074,7 +2146,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen flags = 0; } boolean system = (flags & AppInfo.DOWNLOADED_FLAG) == 0; - if (mHiddenPackages.contains(packageName) || + if (mProtectedPackages.contains(packageName) || (system && !getShowSystemApps()) || (!system && !getShowDownloadedApps())) { iterator.remove(); diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java index 659b2b9d9..c9448850e 100644 --- a/src/com/android/launcher3/BubbleTextView.java +++ b/src/com/android/launcher3/BubbleTextView.java @@ -20,7 +20,6 @@ import android.content.Context; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.Canvas; -import android.graphics.Color; import android.graphics.Rect; import android.graphics.Region; import android.graphics.Region.Op; @@ -87,7 +86,7 @@ public class BubbleTextView extends TextView { // Ensure we are using the right text size LauncherAppState app = LauncherAppState.getInstance(); DeviceProfile grid = app.getDynamicGrid().getDeviceProfile(); - setTextSize(TypedValue.COMPLEX_UNIT_SP, grid.iconTextSize); + setTextSize(TypedValue.COMPLEX_UNIT_PX, grid.iconTextSizePx); setTextColor(getResources().getColor(R.color.workspace_icon_text_color)); } @@ -111,7 +110,7 @@ public class BubbleTextView extends TextView { Bitmap b = info.getIcon(iconCache); setCompoundDrawables(null, Utilities.createIconDrawable(b), null, null); - setCompoundDrawablePadding((int) ((grid.folderIconSizePx - grid.iconSizePx) / 2f)); + setCompoundDrawablePadding(grid.iconDrawablePaddingPx); setText(info.title); setTag(info); } @@ -203,6 +202,10 @@ public class BubbleTextView extends TextView { destCanvas.restore(); } + public void setGlowColor(int color) { + mFocusedOutlineColor = mFocusedGlowColor = mPressedOutlineColor = mPressedGlowColor = color; + } + /** * Returns a new bitmap to be used as the object outline, e.g. to visualize the drop location. * Responsibility for the bitmap is transferred to the caller. diff --git a/src/com/android/launcher3/BuildInfo.java b/src/com/android/launcher3/BuildInfo.java new file mode 100644 index 000000000..b49ee0d9b --- /dev/null +++ b/src/com/android/launcher3/BuildInfo.java @@ -0,0 +1,32 @@ +package com.android.launcher3; + +import android.text.TextUtils; +import android.util.Log; + +public class BuildInfo { + private static final boolean DBG = false; + private static final String TAG = "BuildInfo"; + + public boolean isDogfoodBuild() { + return false; + } + + public static BuildInfo loadByName(String className) { + if (TextUtils.isEmpty(className)) return new BuildInfo(); + + if (DBG) Log.d(TAG, "Loading BuildInfo: " + className); + try { + Class<?> cls = Class.forName(className); + return (BuildInfo) cls.newInstance(); + } catch (ClassNotFoundException e) { + Log.e(TAG, "Bad BuildInfo class", e); + } catch (InstantiationException e) { + Log.e(TAG, "Bad BuildInfo class", e); + } catch (IllegalAccessException e) { + Log.e(TAG, "Bad BuildInfo class", e); + } catch (ClassCastException e) { + Log.e(TAG, "Bad BuildInfo class", e); + } + return new BuildInfo(); + } +} diff --git a/src/com/android/launcher3/ButtonDropTarget.java b/src/com/android/launcher3/ButtonDropTarget.java index d51ae46e8..019f86c21 100644 --- a/src/com/android/launcher3/ButtonDropTarget.java +++ b/src/com/android/launcher3/ButtonDropTarget.java @@ -25,8 +25,6 @@ import android.util.AttributeSet; import android.view.View; import android.widget.TextView; -import com.android.launcher3.R; - /** * Implements a DropTarget. diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java index dc2db8773..373617145 100644 --- a/src/com/android/launcher3/CellLayout.java +++ b/src/com/android/launcher3/CellLayout.java @@ -74,6 +74,7 @@ public class CellLayout extends ViewGroup { private int mHeightGap; private int mMaxGap; private boolean mScrollingTransformsDirty = false; + private boolean mDropPending = false; private final Rect mRect = new Rect(); private final CellInfo mCellInfo = new CellInfo(); @@ -97,6 +98,7 @@ public class CellLayout extends ViewGroup { private int mForegroundAlpha = 0; private float mBackgroundAlpha; private float mBackgroundAlphaMultiplier = 1.0f; + private boolean mDrawBackground = true; private Drawable mNormalBackground; private Drawable mActiveGlowBackground; @@ -130,8 +132,8 @@ public class CellLayout extends ViewGroup { private HashMap<CellLayout.LayoutParams, Animator> mReorderAnimators = new HashMap<CellLayout.LayoutParams, Animator>(); - private HashMap<View, ReorderHintAnimation> - mShakeAnimators = new HashMap<View, ReorderHintAnimation>(); + private HashMap<View, ReorderPreviewAnimation> + mShakeAnimators = new HashMap<View, ReorderPreviewAnimation>(); private boolean mItemPlacementDirty = false; @@ -146,19 +148,20 @@ public class CellLayout extends ViewGroup { private boolean mIsHotseat = false; private float mHotseatScale = 1f; - public static final int MODE_DRAG_OVER = 0; - public static final int MODE_ON_DROP = 1; - public static final int MODE_ON_DROP_EXTERNAL = 2; - public static final int MODE_ACCEPT_DROP = 3; + public static final int MODE_SHOW_REORDER_HINT = 0; + public static final int MODE_DRAG_OVER = 1; + public static final int MODE_ON_DROP = 2; + public static final int MODE_ON_DROP_EXTERNAL = 3; + public static final int MODE_ACCEPT_DROP = 4; private static final boolean DESTRUCTIVE_REORDER = false; private static final boolean DEBUG_VISUALIZE_OCCUPIED = false; static final int LANDSCAPE = 0; static final int PORTRAIT = 1; - private static final float REORDER_HINT_MAGNITUDE = 0.12f; + private static final float REORDER_PREVIEW_MAGNITUDE = 0.12f; private static final int REORDER_ANIMATION_DURATION = 150; - private float mReorderHintAnimationMagnitude; + private float mReorderPreviewAnimationMagnitude; private ArrayList<View> mIntersectingViews = new ArrayList<View>(); private Rect mOccupiedRect = new Rect(); @@ -212,7 +215,7 @@ public class CellLayout extends ViewGroup { setAlwaysDrawnWithCacheEnabled(false); final Resources res = getResources(); - mHotseatScale = (float) grid.hotseatIconSize / grid.iconSize; + mHotseatScale = (float) grid.hotseatIconSizePx / grid.iconSizePx; mNormalBackground = res.getDrawable(R.drawable.screenpanel); mActiveGlowBackground = res.getDrawable(R.drawable.screenpanel_hover); @@ -222,7 +225,7 @@ public class CellLayout extends ViewGroup { mForegroundPadding = res.getDimensionPixelSize(R.dimen.workspace_overscroll_drawable_padding); - mReorderHintAnimationMagnitude = (REORDER_HINT_MAGNITUDE * + mReorderPreviewAnimationMagnitude = (REORDER_PREVIEW_MAGNITUDE * grid.iconSizePx); mNormalBackground.setFilterBitmap(true); @@ -330,6 +333,14 @@ public class CellLayout extends ViewGroup { mShortcutsAndWidgets.setInvertIfRtl(invert); } + public void setDropPending(boolean pending) { + mDropPending = pending; + } + + public boolean isDropPending() { + return mDropPending; + } + private void invalidateBubbleTextView(BubbleTextView icon) { final int padding = icon.getPressedOrFocusedBackgroundPadding(); invalidate(icon.getLeft() + getPaddingLeft() - padding, @@ -376,6 +387,10 @@ public class CellLayout extends ViewGroup { mUseActiveGlowBackground = use; } + void disableBackground() { + mDrawBackground = false; + } + boolean getIsDragOverlapping() { return mIsDragOverlapping; } @@ -404,7 +419,7 @@ public class CellLayout extends ViewGroup { // When we're small, we are either drawn normally or in the "accepts drops" state (during // a drag). However, we also drag the mini hover background *over* one of those two // backgrounds - if (mBackgroundAlpha > 0.0f) { + if (mDrawBackground && mBackgroundAlpha > 0.0f) { Drawable bg; if (mUseActiveGlowBackground) { @@ -2076,6 +2091,8 @@ public class CellLayout extends ViewGroup { } } + solution.intersectingViews = new ArrayList<View>(mIntersectingViews); + // First we try to find a solution which respects the push mechanic. That is, // we try to find a solution such that no displaced item travels through another item // without also displacing that item. @@ -2124,8 +2141,9 @@ public class CellLayout extends ViewGroup { } } - ItemConfiguration simpleSwap(int pixelX, int pixelY, int minSpanX, int minSpanY, int spanX, - int spanY, int[] direction, View dragView, boolean decX, ItemConfiguration solution) { + ItemConfiguration findReorderSolution(int pixelX, int pixelY, int minSpanX, int minSpanY, + int spanX, int spanY, int[] direction, View dragView, boolean decX, + ItemConfiguration solution) { // Copy the current state into the solution. This solution will be manipulated as necessary. copyCurrentStateToSolution(solution, false); // Copy the current occupied array into the temporary occupied array. This array will be @@ -2147,11 +2165,11 @@ public class CellLayout extends ViewGroup { // We try shrinking the widget down to size in an alternating pattern, shrink 1 in // x, then 1 in y etc. if (spanX > minSpanX && (minSpanY == spanY || decX)) { - return simpleSwap(pixelX, pixelY, minSpanX, minSpanY, spanX - 1, spanY, direction, - dragView, false, solution); + return findReorderSolution(pixelX, pixelY, minSpanX, minSpanY, spanX - 1, spanY, + direction, dragView, false, solution); } else if (spanY > minSpanY) { - return simpleSwap(pixelX, pixelY, minSpanX, minSpanY, spanX, spanY - 1, direction, - dragView, true, solution); + return findReorderSolution(pixelX, pixelY, minSpanX, minSpanY, spanX, spanY - 1, + direction, dragView, true, solution); } solution.isSolution = false; } else { @@ -2231,25 +2249,30 @@ public class CellLayout extends ViewGroup { } } - // This method starts or changes the reorder hint animations - private void beginOrAdjustHintAnimations(ItemConfiguration solution, View dragView, int delay) { + + // This method starts or changes the reorder preview animations + private void beginOrAdjustReorderPreviewAnimations(ItemConfiguration solution, + View dragView, int delay, int mode) { int childCount = mShortcutsAndWidgets.getChildCount(); for (int i = 0; i < childCount; i++) { View child = mShortcutsAndWidgets.getChildAt(i); if (child == dragView) continue; CellAndSpan c = solution.map.get(child); + boolean skip = mode == ReorderPreviewAnimation.MODE_HINT && solution.intersectingViews + != null && !solution.intersectingViews.contains(child); + LayoutParams lp = (LayoutParams) child.getLayoutParams(); - if (c != null) { - ReorderHintAnimation rha = new ReorderHintAnimation(child, lp.cellX, lp.cellY, - c.x, c.y, c.spanX, c.spanY); + if (c != null && !skip) { + ReorderPreviewAnimation rha = new ReorderPreviewAnimation(child, mode, lp.cellX, + lp.cellY, c.x, c.y, c.spanX, c.spanY); rha.animate(); } } } - // Class which represents the reorder hint animations. These animations show that an item is + // Class which represents the reorder preview animations. These animations show that an item is // in a temporary state, and hint at where the item will return to. - class ReorderHintAnimation { + class ReorderPreviewAnimation { View child; float finalDeltaX; float finalDeltaY; @@ -2257,11 +2280,18 @@ public class CellLayout extends ViewGroup { float initDeltaY; float finalScale; float initScale; - private static final int DURATION = 300; + int mode; + boolean repeating = false; + private static final int PREVIEW_DURATION = 300; + private static final int HINT_DURATION = Workspace.REORDER_TIMEOUT; + + public static final int MODE_HINT = 0; + public static final int MODE_PREVIEW = 1; + Animator a; - public ReorderHintAnimation(View child, int cellX0, int cellY0, int cellX1, int cellY1, - int spanX, int spanY) { + public ReorderPreviewAnimation(View child, int mode, int cellX0, int cellY0, int cellX1, + int cellY1, int spanX, int spanY) { regionToCenterPoint(cellX0, cellY0, spanX, spanY, mTmpPoint); final int x0 = mTmpPoint[0]; final int y0 = mTmpPoint[1]; @@ -2272,20 +2302,22 @@ public class CellLayout extends ViewGroup { final int dY = y1 - y0; finalDeltaX = 0; finalDeltaY = 0; + int dir = mode == MODE_HINT ? -1 : 1; if (dX == dY && dX == 0) { } else { if (dY == 0) { - finalDeltaX = - Math.signum(dX) * mReorderHintAnimationMagnitude; + finalDeltaX = - dir * Math.signum(dX) * mReorderPreviewAnimationMagnitude; } else if (dX == 0) { - finalDeltaY = - Math.signum(dY) * mReorderHintAnimationMagnitude; + finalDeltaY = - dir * Math.signum(dY) * mReorderPreviewAnimationMagnitude; } else { double angle = Math.atan( (float) (dY) / dX); - finalDeltaX = (int) (- Math.signum(dX) * - Math.abs(Math.cos(angle) * mReorderHintAnimationMagnitude)); - finalDeltaY = (int) (- Math.signum(dY) * - Math.abs(Math.sin(angle) * mReorderHintAnimationMagnitude)); + finalDeltaX = (int) (- dir * Math.signum(dX) * + Math.abs(Math.cos(angle) * mReorderPreviewAnimationMagnitude)); + finalDeltaY = (int) (- dir * Math.signum(dY) * + Math.abs(Math.sin(angle) * mReorderPreviewAnimationMagnitude)); } } + this.mode = mode; initDeltaX = child.getTranslationX(); initDeltaY = child.getTranslationY(); finalScale = getChildrenScale() - 4.0f / child.getWidth(); @@ -2295,7 +2327,7 @@ public class CellLayout extends ViewGroup { void animate() { if (mShakeAnimators.containsKey(child)) { - ReorderHintAnimation oldAnimation = mShakeAnimators.get(child); + ReorderPreviewAnimation oldAnimation = mShakeAnimators.get(child); oldAnimation.cancel(); mShakeAnimators.remove(child); if (finalDeltaX == 0 && finalDeltaY == 0) { @@ -2310,14 +2342,15 @@ public class CellLayout extends ViewGroup { a = va; va.setRepeatMode(ValueAnimator.REVERSE); va.setRepeatCount(ValueAnimator.INFINITE); - va.setDuration(DURATION); + va.setDuration(mode == MODE_HINT ? HINT_DURATION : PREVIEW_DURATION); va.setStartDelay((int) (Math.random() * 60)); va.addUpdateListener(new AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float r = ((Float) animation.getAnimatedValue()).floatValue(); - float x = r * finalDeltaX + (1 - r) * initDeltaX; - float y = r * finalDeltaY + (1 - r) * initDeltaY; + float r1 = (mode == MODE_HINT && repeating) ? 1.0f : r; + float x = r1 * finalDeltaX + (1 - r1) * initDeltaX; + float y = r1 * finalDeltaY + (1 - r1) * initDeltaY; child.setTranslationX(x); child.setTranslationY(y); float s = r * finalScale + (1 - r) * initScale; @@ -2331,6 +2364,7 @@ public class CellLayout extends ViewGroup { initDeltaX = 0; initDeltaY = 0; initScale = getChildrenScale(); + repeating = true; } }); mShakeAnimators.put(child, this); @@ -2362,8 +2396,8 @@ public class CellLayout extends ViewGroup { } } - private void completeAndClearReorderHintAnimations() { - for (ReorderHintAnimation a: mShakeAnimators.values()) { + private void completeAndClearReorderPreviewAnimations() { + for (ReorderPreviewAnimation a: mShakeAnimators.values()) { a.completeAnimationImmediately(); } mShakeAnimators.clear(); @@ -2506,20 +2540,21 @@ public class CellLayout extends ViewGroup { } void revertTempState() { - if (!isItemPlacementDirty() || DESTRUCTIVE_REORDER) return; - final int count = mShortcutsAndWidgets.getChildCount(); - for (int i = 0; i < count; i++) { - View child = mShortcutsAndWidgets.getChildAt(i); - LayoutParams lp = (LayoutParams) child.getLayoutParams(); - if (lp.tmpCellX != lp.cellX || lp.tmpCellY != lp.cellY) { - lp.tmpCellX = lp.cellX; - lp.tmpCellY = lp.cellY; - animateChildToPosition(child, lp.cellX, lp.cellY, REORDER_ANIMATION_DURATION, - 0, false, false); + completeAndClearReorderPreviewAnimations(); + if (isItemPlacementDirty() && !DESTRUCTIVE_REORDER) { + final int count = mShortcutsAndWidgets.getChildCount(); + for (int i = 0; i < count; i++) { + View child = mShortcutsAndWidgets.getChildAt(i); + LayoutParams lp = (LayoutParams) child.getLayoutParams(); + if (lp.tmpCellX != lp.cellX || lp.tmpCellY != lp.cellY) { + lp.tmpCellX = lp.cellX; + lp.tmpCellY = lp.cellY; + animateChildToPosition(child, lp.cellX, lp.cellY, REORDER_ANIMATION_DURATION, + 0, false, false); + } } + setItemPlacementDirty(false); } - completeAndClearReorderHintAnimations(); - setItemPlacementDirty(false); } boolean createAreaForResize(int cellX, int cellY, int spanX, int spanY, @@ -2528,7 +2563,7 @@ public class CellLayout extends ViewGroup { regionToCenterPoint(cellX, cellY, spanX, spanY, pixelXY); // First we determine if things have moved enough to cause a different layout - ItemConfiguration swapSolution = simpleSwap(pixelXY[0], pixelXY[1], spanX, spanY, + ItemConfiguration swapSolution = findReorderSolution(pixelXY[0], pixelXY[1], spanX, spanY, spanX, spanY, direction, dragView, true, new ItemConfiguration()); setUseTempCoords(true); @@ -2542,18 +2577,18 @@ public class CellLayout extends ViewGroup { if (commit) { commitTempPlacement(); - completeAndClearReorderHintAnimations(); + completeAndClearReorderPreviewAnimations(); setItemPlacementDirty(false); } else { - beginOrAdjustHintAnimations(swapSolution, dragView, - REORDER_ANIMATION_DURATION); + beginOrAdjustReorderPreviewAnimations(swapSolution, dragView, + REORDER_ANIMATION_DURATION, ReorderPreviewAnimation.MODE_PREVIEW); } mShortcutsAndWidgets.requestLayout(); } return swapSolution.isSolution; } - int[] createArea(int pixelX, int pixelY, int minSpanX, int minSpanY, int spanX, int spanY, + int[] performReorder(int pixelX, int pixelY, int minSpanX, int minSpanY, int spanX, int spanY, View dragView, int[] result, int resultSpan[], int mode) { // First we determine if things have moved enough to cause a different layout result = findNearestArea(pixelX, pixelY, spanX, spanY, result); @@ -2580,7 +2615,8 @@ public class CellLayout extends ViewGroup { mPreviousReorderDirection[1] = mDirectionVector[1]; } - ItemConfiguration swapSolution = simpleSwap(pixelX, pixelY, minSpanX, minSpanY, + // Find a solution involving pushing / displacing any items in the way + ItemConfiguration swapSolution = findReorderSolution(pixelX, pixelY, minSpanX, minSpanY, spanX, spanY, mDirectionVector, dragView, true, new ItemConfiguration()); // We attempt the approach which doesn't shuffle views at all @@ -2588,12 +2624,29 @@ public class CellLayout extends ViewGroup { minSpanY, spanX, spanY, dragView, new ItemConfiguration()); ItemConfiguration finalSolution = null; + + // If the reorder solution requires resizing (shrinking) the item being dropped, we instead + // favor a solution in which the item is not resized, but if (swapSolution.isSolution && swapSolution.area() >= noShuffleSolution.area()) { finalSolution = swapSolution; } else if (noShuffleSolution.isSolution) { finalSolution = noShuffleSolution; } + if (mode == MODE_SHOW_REORDER_HINT) { + if (finalSolution != null) { + beginOrAdjustReorderPreviewAnimations(finalSolution, dragView, 0, + ReorderPreviewAnimation.MODE_HINT); + result[0] = finalSolution.dragViewX; + result[1] = finalSolution.dragViewY; + resultSpan[0] = finalSolution.dragViewSpanX; + resultSpan[1] = finalSolution.dragViewSpanY; + } else { + result[0] = result[1] = resultSpan[0] = resultSpan[1] = -1; + } + return result; + } + boolean foundSolution = true; if (!DESTRUCTIVE_REORDER) { setUseTempCoords(true); @@ -2618,11 +2671,11 @@ public class CellLayout extends ViewGroup { if (!DESTRUCTIVE_REORDER && (mode == MODE_ON_DROP || mode == MODE_ON_DROP_EXTERNAL)) { commitTempPlacement(); - completeAndClearReorderHintAnimations(); + completeAndClearReorderPreviewAnimations(); setItemPlacementDirty(false); } else { - beginOrAdjustHintAnimations(finalSolution, dragView, - REORDER_ANIMATION_DURATION); + beginOrAdjustReorderPreviewAnimations(finalSolution, dragView, + REORDER_ANIMATION_DURATION, ReorderPreviewAnimation.MODE_PREVIEW); } } } else { @@ -2649,6 +2702,7 @@ public class CellLayout extends ViewGroup { HashMap<View, CellAndSpan> map = new HashMap<View, CellAndSpan>(); private HashMap<View, CellAndSpan> savedMap = new HashMap<View, CellAndSpan>(); ArrayList<View> sortedViews = new ArrayList<View>(); + ArrayList<View> intersectingViews; boolean isSolution = false; int dragViewX, dragViewY, dragViewSpanX, dragViewSpanY; @@ -3108,7 +3162,8 @@ out: for (int i = x; i < x + spanX - 1 && x < xCount; i++) { if (x < mCountX && y < mCountY) { return mOccupied[x][y]; } else { - throw new RuntimeException("Position exceeds the bound of this CellLayout"); + Log.w(TAG, "Position exceeds the bound of this CellLayout"); + return false; } } diff --git a/src/com/android/launcher3/Cling.java b/src/com/android/launcher3/Cling.java index 01a54b4e1..a6139ccbc 100644 --- a/src/com/android/launcher3/Cling.java +++ b/src/com/android/launcher3/Cling.java @@ -18,8 +18,8 @@ package com.android.launcher3; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; -import android.content.Context; import android.content.ComponentName; +import android.content.Context; import android.content.Intent; import android.content.res.Resources; import android.content.res.TypedArray; @@ -30,6 +30,7 @@ import android.util.DisplayMetrics; import android.view.FocusFinder; import android.view.MotionEvent; import android.view.View; +import android.view.ViewGroup; import android.view.animation.AccelerateInterpolator; import android.widget.FrameLayout; import android.widget.TextView; @@ -37,11 +38,6 @@ import android.widget.TextView; public class Cling extends FrameLayout implements Insettable, View.OnClickListener, View.OnLongClickListener, View.OnTouchListener { - static final String FIRST_RUN_CLING_DISMISSED_KEY = "cling_gel.first_run.dismissed"; - static final String WORKSPACE_CLING_DISMISSED_KEY = "cling_gel.workspace.dismissed"; - static final String FOLDER_CLING_DISMISSED_KEY = "cling_gel.folder.dismissed"; - static final String ALL_APPS_CLING_DISMISSED_KEY = "cling_gel.all_apps.dismissed"; - private static String FIRST_RUN_PORTRAIT = "first_run_portrait"; private static String FIRST_RUN_LANDSCAPE = "first_run_landscape"; @@ -50,16 +46,24 @@ public class Cling extends FrameLayout implements Insettable, View.OnClickListen private static String WORKSPACE_LARGE = "workspace_large"; private static String WORKSPACE_CUSTOM = "workspace_custom"; + private static String MIGRATION_PORTRAIT = "migration_portrait"; + private static String MIGRATION_LANDSCAPE = "migration_landscape"; + + private static String MIGRATION_WORKSPACE_PORTRAIT = "migration_workspace_portrait"; + private static String MIGRATION_WORKSPACE_LARGE_PORTRAIT = "migration_workspace_large_portrait"; + private static String MIGRATION_WORKSPACE_LANDSCAPE = "migration_workspace_landscape"; + private static String FOLDER_PORTRAIT = "folder_portrait"; private static String FOLDER_LANDSCAPE = "folder_landscape"; private static String FOLDER_LARGE = "folder_large"; - private static String ALL_APPS = "all_apps"; - private static float FIRST_RUN_CIRCLE_BUFFER_DPS = 60; + private static float FIRST_RUN_MAX_CIRCLE_RADIUS_DPS = 180; private static float WORKSPACE_INNER_CIRCLE_RADIUS_DPS = 50; private static float WORKSPACE_OUTER_CIRCLE_RADIUS_DPS = 60; private static float WORKSPACE_CIRCLE_Y_OFFSET_DPS = 30; + private static float MIGRATION_WORKSPACE_INNER_CIRCLE_RADIUS_DPS = 42; + private static float MIGRATION_WORKSPACE_OUTER_CIRCLE_RADIUS_DPS = 46; private Launcher mLauncher; private boolean mIsInitialized; @@ -73,6 +77,7 @@ public class Cling extends FrameLayout implements Insettable, View.OnClickListen private Rect mFocusedHotseatAppBounds; private Paint mErasePaint; + private Paint mBorderPaint; private Paint mBubblePaint; private Paint mDotPaint; @@ -80,7 +85,6 @@ public class Cling extends FrameLayout implements Insettable, View.OnClickListen private int mBackgroundColor; private final Rect mInsets = new Rect(); - private int[] mPosition; public Cling(Context context) { this(context, null, 0); @@ -105,7 +109,7 @@ public class Cling extends FrameLayout implements Insettable, View.OnClickListen if (!mIsInitialized) { mLauncher = l; mScrimView = scrim; - mBackgroundColor = 0xdd000000; + mBackgroundColor = 0xcc000000; setOnLongClickListener(this); setOnClickListener(this); setOnTouchListener(this); @@ -116,6 +120,10 @@ public class Cling extends FrameLayout implements Insettable, View.OnClickListen mErasePaint.setAlpha(0); mErasePaint.setAntiAlias(true); + mBorderPaint = new Paint(); + mBorderPaint.setColor(0xFFFFFFFF); + mBorderPaint.setAntiAlias(true); + int circleColor = getResources().getColor( R.color.first_run_cling_circle_background_color); mBubblePaint = new Paint(); @@ -130,20 +138,15 @@ public class Cling extends FrameLayout implements Insettable, View.OnClickListen } } - void setPunchThroughForView(View view) { - mPosition = new int[2]; - view.getLocationOnScreen(mPosition); - mPosition[0] += view.getWidth() / 2; - mPosition[1] += view.getHeight() / 2; - } - void setFocusedHotseatApp(int drawableId, int appRank, ComponentName cn, String title, String description) { // Get the app to draw Resources r = getResources(); int appIconId = drawableId; Hotseat hotseat = mLauncher.getHotseat(); - if (hotseat != null && appIconId > -1 && appRank > -1 && !title.isEmpty() && + // Skip the focused app in the large layouts + if (!mDrawIdentifier.equals(WORKSPACE_LARGE) && + hotseat != null && appIconId > -1 && appRank > -1 && !title.isEmpty() && !description.isEmpty()) { // Set the app bounds int x = hotseat.getCellXFromOrder(appRank); @@ -157,7 +160,7 @@ public class Cling extends FrameLayout implements Insettable, View.OnClickListen pos.left + Utilities.sIconTextureWidth, pos.top + Utilities.sIconTextureHeight); Utilities.scaleRectAboutCenter(mFocusedHotseatAppBounds, - (grid.hotseatIconSize / grid.iconSize)); + ((float) grid.hotseatIconSizePx / grid.iconSizePx)); // Set the title TextView v = (TextView) findViewById(R.id.focused_hotseat_app_title); @@ -177,6 +180,82 @@ public class Cling extends FrameLayout implements Insettable, View.OnClickListen } } + void setOpenFolderRect(Rect r) { + if (mDrawIdentifier.equals(FOLDER_LANDSCAPE) || + mDrawIdentifier.equals(FOLDER_LARGE)) { + ViewGroup vg = (ViewGroup) findViewById(R.id.folder_bubble); + ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) vg.getLayoutParams(); + lp.topMargin = r.top - mInsets.bottom; + lp.leftMargin = r.right; + vg.setLayoutDirection(View.LAYOUT_DIRECTION_LTR); + vg.requestLayout(); + } + } + + void updateMigrationWorkspaceBubblePosition() { + DisplayMetrics metrics = new DisplayMetrics(); + mLauncher.getWindowManager().getDefaultDisplay().getMetrics(metrics); + + // Get the page indicator bounds + LauncherAppState app = LauncherAppState.getInstance(); + DeviceProfile grid = app.getDynamicGrid().getDeviceProfile(); + Rect pageIndicatorBounds = grid.getWorkspacePageIndicatorBounds(mInsets); + + if (mDrawIdentifier.equals(MIGRATION_WORKSPACE_PORTRAIT)) { + View bubble = findViewById(R.id.migration_workspace_cling_bubble); + ViewGroup.MarginLayoutParams lp = + (ViewGroup.MarginLayoutParams) bubble.getLayoutParams(); + lp.bottomMargin = grid.heightPx - pageIndicatorBounds.top; + bubble.requestLayout(); + } else if (mDrawIdentifier.equals(MIGRATION_WORKSPACE_LARGE_PORTRAIT)) { + View bubble = findViewById(R.id.content); + ViewGroup.MarginLayoutParams lp = + (ViewGroup.MarginLayoutParams) bubble.getLayoutParams(); + lp.bottomMargin = grid.heightPx - pageIndicatorBounds.top; + bubble.requestLayout(); + } else if (mDrawIdentifier.equals(MIGRATION_WORKSPACE_LANDSCAPE)) { + View bubble = findViewById(R.id.content); + ViewGroup.MarginLayoutParams lp = + (ViewGroup.MarginLayoutParams) bubble.getLayoutParams(); + if (grid.isLayoutRtl) { + lp.leftMargin = pageIndicatorBounds.right; + } else { + lp.rightMargin = (grid.widthPx - pageIndicatorBounds.left); + } + bubble.requestLayout(); + } + } + + void updateWorkspaceBubblePosition() { + DisplayMetrics metrics = new DisplayMetrics(); + mLauncher.getWindowManager().getDefaultDisplay().getMetrics(metrics); + + // Get the cut-out bounds + LauncherAppState app = LauncherAppState.getInstance(); + DeviceProfile grid = app.getDynamicGrid().getDeviceProfile(); + Rect cutOutBounds = getWorkspaceCutOutBounds(metrics); + + if (mDrawIdentifier.equals(WORKSPACE_LARGE)) { + View bubble = findViewById(R.id.workspace_cling_bubble); + ViewGroup.MarginLayoutParams lp = + (ViewGroup.MarginLayoutParams) bubble.getLayoutParams(); + lp.bottomMargin = grid.heightPx - cutOutBounds.top - mInsets.bottom; + bubble.requestLayout(); + } + } + + private Rect getWorkspaceCutOutBounds(DisplayMetrics metrics) { + int halfWidth = metrics.widthPixels / 2; + int halfHeight = metrics.heightPixels / 2; + int yOffset = DynamicGrid.pxFromDp(WORKSPACE_CIRCLE_Y_OFFSET_DPS, metrics); + if (mDrawIdentifier.equals(WORKSPACE_LARGE)) { + yOffset = 0; + } + int radius = DynamicGrid.pxFromDp(WORKSPACE_OUTER_CIRCLE_RADIUS_DPS, metrics); + return new Rect(halfWidth - radius, halfHeight - yOffset - radius, halfWidth + radius, + halfHeight - yOffset + radius); + } + void show(boolean animate, int duration) { setVisibility(View.VISIBLE); setLayerType(View.LAYER_TYPE_HARDWARE, null); @@ -184,7 +263,9 @@ public class Cling extends FrameLayout implements Insettable, View.OnClickListen mDrawIdentifier.equals(WORKSPACE_LANDSCAPE) || mDrawIdentifier.equals(WORKSPACE_LARGE) || mDrawIdentifier.equals(WORKSPACE_CUSTOM) || - mDrawIdentifier.equals(ALL_APPS)) { + mDrawIdentifier.equals(MIGRATION_WORKSPACE_PORTRAIT) || + mDrawIdentifier.equals(MIGRATION_WORKSPACE_LARGE_PORTRAIT) || + mDrawIdentifier.equals(MIGRATION_WORKSPACE_LANDSCAPE)) { View content = getContent(); content.setAlpha(0f); content.animate() @@ -230,7 +311,9 @@ public class Cling extends FrameLayout implements Insettable, View.OnClickListen void hide(final int duration, final Runnable postCb) { if (mDrawIdentifier.equals(FIRST_RUN_PORTRAIT) || - mDrawIdentifier.equals(FIRST_RUN_LANDSCAPE)) { + mDrawIdentifier.equals(FIRST_RUN_LANDSCAPE) || + mDrawIdentifier.equals(MIGRATION_PORTRAIT) || + mDrawIdentifier.equals(MIGRATION_LANDSCAPE)) { View content = getContent(); content.animate() .alpha(0f) @@ -311,8 +394,7 @@ public class Cling extends FrameLayout implements Insettable, View.OnClickListen return (mDrawIdentifier.equals(WORKSPACE_PORTRAIT) || mDrawIdentifier.equals(WORKSPACE_LANDSCAPE) || mDrawIdentifier.equals(WORKSPACE_LARGE) - || mDrawIdentifier.equals(WORKSPACE_CUSTOM) - || mDrawIdentifier.equals(ALL_APPS)); + || mDrawIdentifier.equals(WORKSPACE_CUSTOM)); } @Override @@ -353,7 +435,7 @@ public class Cling extends FrameLayout implements Insettable, View.OnClickListen intent.setComponent(mFocusedHotseatAppComponent); intent.addCategory(Intent.CATEGORY_LAUNCHER); mLauncher.startActivity(intent, null); - mLauncher.dismissWorkspaceCling(this); + mLauncher.getLauncherClings().dismissWorkspaceCling(this); } } } @@ -363,10 +445,12 @@ public class Cling extends FrameLayout implements Insettable, View.OnClickListen if (mDrawIdentifier.equals(WORKSPACE_PORTRAIT) || mDrawIdentifier.equals(WORKSPACE_LANDSCAPE) || mDrawIdentifier.equals(WORKSPACE_LARGE)) { - mLauncher.dismissWorkspaceCling(null); + mLauncher.getLauncherClings().dismissWorkspaceCling(null); return true; - } else if (mDrawIdentifier.equals(ALL_APPS)) { - mLauncher.dismissAllAppsCling(null); + } else if (mDrawIdentifier.equals(MIGRATION_WORKSPACE_PORTRAIT) || + mDrawIdentifier.equals(MIGRATION_WORKSPACE_LARGE_PORTRAIT) || + mDrawIdentifier.equals(MIGRATION_WORKSPACE_LANDSCAPE)) { + mLauncher.getLauncherClings().dismissMigrationWorkspaceCling(null); return true; } return false; @@ -377,6 +461,11 @@ public class Cling extends FrameLayout implements Insettable, View.OnClickListen if (mIsInitialized) { canvas.save(); + // Get the page indicator bounds + LauncherAppState app = LauncherAppState.getInstance(); + DeviceProfile grid = app.getDynamicGrid().getDeviceProfile(); + Rect pageIndicatorBounds = grid.getWorkspacePageIndicatorBounds(mInsets); + // Get the background override if there is one if (mBackground == null) { if (mDrawIdentifier.equals(WORKSPACE_CUSTOM)) { @@ -395,7 +484,9 @@ public class Cling extends FrameLayout implements Insettable, View.OnClickListen } else if (mDrawIdentifier.equals(WORKSPACE_PORTRAIT) || mDrawIdentifier.equals(WORKSPACE_LANDSCAPE) || mDrawIdentifier.equals(WORKSPACE_LARGE) || - mDrawIdentifier.equals(ALL_APPS)) { + mDrawIdentifier.equals(MIGRATION_WORKSPACE_PORTRAIT) || + mDrawIdentifier.equals(MIGRATION_WORKSPACE_LARGE_PORTRAIT) || + mDrawIdentifier.equals(MIGRATION_WORKSPACE_LANDSCAPE)) { // Initialize the draw buffer (to allow punching through) eraseBg = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(), Bitmap.Config.ARGB_8888); @@ -421,29 +512,23 @@ public class Cling extends FrameLayout implements Insettable, View.OnClickListen bubbleContent.getGlobalVisibleRect(bubbleRect); mBubblePaint.setAlpha((int) (255 * alpha)); float buffer = DynamicGrid.pxFromDp(FIRST_RUN_CIRCLE_BUFFER_DPS, metrics); + float maxRadius = DynamicGrid.pxFromDp(FIRST_RUN_MAX_CIRCLE_RADIUS_DPS, metrics); + float radius = Math.min(maxRadius, (bubbleContent.getMeasuredWidth() + buffer) / 2); canvas.drawCircle(metrics.widthPixels / 2, - bubbleRect.centerY(), - (bubbleContent.getMeasuredWidth() + buffer) / 2, + bubbleRect.centerY(), radius, mBubblePaint); } else if (mDrawIdentifier.equals(WORKSPACE_PORTRAIT) || mDrawIdentifier.equals(WORKSPACE_LANDSCAPE) || - mDrawIdentifier.equals(WORKSPACE_LARGE) || - mDrawIdentifier.equals(ALL_APPS)) { - int offset = DynamicGrid.pxFromDp(WORKSPACE_CIRCLE_Y_OFFSET_DPS, metrics); - mErasePaint.setAlpha((int) (128)); - int punchX = metrics.widthPixels / 2; - int punchY = metrics.heightPixels / 2 - offset; - if (mPosition != null) { - punchX = mPosition[0]; - punchY = mPosition[1]; - } - eraseCanvas.drawCircle(punchX, - punchY, + mDrawIdentifier.equals(WORKSPACE_LARGE)) { + Rect cutOutBounds = getWorkspaceCutOutBounds(metrics); + // Draw the outer circle + mErasePaint.setAlpha(128); + eraseCanvas.drawCircle(cutOutBounds.centerX(), cutOutBounds.centerY(), DynamicGrid.pxFromDp(WORKSPACE_OUTER_CIRCLE_RADIUS_DPS, metrics), mErasePaint); + // Draw the inner circle mErasePaint.setAlpha(0); - eraseCanvas.drawCircle(punchX, - punchY, + eraseCanvas.drawCircle(cutOutBounds.centerX(), cutOutBounds.centerY(), DynamicGrid.pxFromDp(WORKSPACE_INNER_CIRCLE_RADIUS_DPS, metrics), mErasePaint); canvas.drawBitmap(eraseBg, 0, 0, null); @@ -458,8 +543,25 @@ public class Cling extends FrameLayout implements Insettable, View.OnClickListen mFocusedHotseatApp.setAlpha((int) (255 * alpha)); mFocusedHotseatApp.draw(canvas); } + } else if (mDrawIdentifier.equals(MIGRATION_WORKSPACE_PORTRAIT) || + mDrawIdentifier.equals(MIGRATION_WORKSPACE_LARGE_PORTRAIT) || + mDrawIdentifier.equals(MIGRATION_WORKSPACE_LANDSCAPE)) { + int offset = DynamicGrid.pxFromDp(WORKSPACE_CIRCLE_Y_OFFSET_DPS, metrics); + // Draw the outer circle + eraseCanvas.drawCircle(pageIndicatorBounds.centerX(), + pageIndicatorBounds.centerY(), + DynamicGrid.pxFromDp(MIGRATION_WORKSPACE_OUTER_CIRCLE_RADIUS_DPS, metrics), + mBorderPaint); + // Draw the inner circle + mErasePaint.setAlpha(0); + eraseCanvas.drawCircle(pageIndicatorBounds.centerX(), + pageIndicatorBounds.centerY(), + DynamicGrid.pxFromDp(MIGRATION_WORKSPACE_INNER_CIRCLE_RADIUS_DPS, metrics), + mErasePaint); + canvas.drawBitmap(eraseBg, 0, 0, null); + eraseCanvas.setBitmap(null); + eraseBg = null; } - canvas.restore(); } diff --git a/src/com/android/launcher3/DeferredHandler.java b/src/com/android/launcher3/DeferredHandler.java index 92ecf9643..a2d121d63 100644 --- a/src/com/android/launcher3/DeferredHandler.java +++ b/src/com/android/launcher3/DeferredHandler.java @@ -21,6 +21,7 @@ import android.os.Looper; import android.os.Message; import android.os.MessageQueue; import android.util.Pair; + import java.util.LinkedList; import java.util.ListIterator; diff --git a/src/com/android/launcher3/DeleteDropTarget.java b/src/com/android/launcher3/DeleteDropTarget.java index 150d958a8..94a335f5d 100644 --- a/src/com/android/launcher3/DeleteDropTarget.java +++ b/src/com/android/launcher3/DeleteDropTarget.java @@ -29,6 +29,7 @@ import android.content.res.Resources; import android.graphics.PointF; import android.graphics.Rect; import android.graphics.drawable.TransitionDrawable; +import android.os.AsyncTask; import android.util.AttributeSet; import android.view.View; import android.view.ViewConfiguration; @@ -95,7 +96,7 @@ public class DeleteDropTarget extends ButtonDropTarget { } private boolean isAllAppsApplication(DragSource source, Object info) { - return (source instanceof AppsCustomizePagedView) && (info instanceof AppInfo); + return source.supportsAppInfoDropTarget() && (info instanceof AppInfo); } private boolean isAllAppsWidget(DragSource source, Object info) { if (source instanceof AppsCustomizePagedView) { @@ -151,12 +152,12 @@ public class DeleteDropTarget extends ButtonDropTarget { return true; } - if (!AppsCustomizePagedView.DISABLE_ALL_APPS && + if (!LauncherAppState.isDisableAllApps() && item.itemType == LauncherSettings.Favorites.ITEM_TYPE_FOLDER) { return true; } - if (!AppsCustomizePagedView.DISABLE_ALL_APPS && + if (!LauncherAppState.isDisableAllApps() && item.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION && item instanceof AppInfo) { AppInfo appInfo = (AppInfo) info; @@ -165,7 +166,7 @@ public class DeleteDropTarget extends ButtonDropTarget { if (item.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION && item instanceof ShortcutInfo) { - if (AppsCustomizePagedView.DISABLE_ALL_APPS) { + if (LauncherAppState.isDisableAllApps()) { ShortcutInfo shortcutInfo = (ShortcutInfo) info; return (shortcutInfo.flags & AppInfo.DOWNLOADED_FLAG) != 0; } else { @@ -179,8 +180,9 @@ public class DeleteDropTarget extends ButtonDropTarget { @Override public void onDragStart(DragSource source, Object info, int dragAction) { boolean isVisible = true; - boolean useUninstallLabel = !AppsCustomizePagedView.DISABLE_ALL_APPS && + boolean useUninstallLabel = !LauncherAppState.isDisableAllApps() && isAllAppsApplication(source, info); + boolean useDeleteLabel = !useUninstallLabel && source.supportsDeleteDropTarget(); // If we are dragging an application from AppsCustomize, only show the control if we can // delete the app (it was downloaded), and rename the string to "uninstall" in such a case. @@ -191,15 +193,17 @@ public class DeleteDropTarget extends ButtonDropTarget { if (useUninstallLabel) { setCompoundDrawablesRelativeWithIntrinsicBounds(mUninstallDrawable, null, null, null); - } else { + } else if (useDeleteLabel) { setCompoundDrawablesRelativeWithIntrinsicBounds(mRemoveDrawable, null, null, null); + } else { + isVisible = false; } mCurrentDrawable = (TransitionDrawable) getCurrentDrawable(); mActive = isVisible; resetHoverColor(); ((ViewGroup) getParent()).setVisibility(isVisible ? View.VISIBLE : View.GONE); - if (getText().length() > 0) { + if (isVisible && getText().length() > 0) { setText(useUninstallLabel ? R.string.delete_target_uninstall_label : R.string.delete_target_label); } @@ -266,21 +270,10 @@ public class DeleteDropTarget extends ButtonDropTarget { } private boolean isUninstallFromWorkspace(DragObject d) { - if (AppsCustomizePagedView.DISABLE_ALL_APPS && isWorkspaceOrFolderApplication(d)) { + if (LauncherAppState.isDisableAllApps() && isWorkspaceOrFolderApplication(d)) { ShortcutInfo shortcut = (ShortcutInfo) d.dragInfo; - if (shortcut.intent != null && shortcut.intent.getComponent() != null) { - Set<String> categories = shortcut.intent.getCategories(); - boolean includesLauncherCategory = false; - if (categories != null) { - for (String category : categories) { - if (category.equals(Intent.CATEGORY_LAUNCHER)) { - includesLauncherCategory = true; - break; - } - } - } - return includesLauncherCategory; - } + // Only allow manifest shortcuts to initiate an un-install. + return !InstallShortcutReceiver.isValidShortcutLaunchIntent(shortcut.intent); } return false; } @@ -340,11 +333,12 @@ public class DeleteDropTarget extends ButtonDropTarget { if (appWidgetHost != null) { // Deleting an app widget ID is a void call but writes to disk before returning // to the caller... - new Thread("deleteAppWidgetId") { - public void run() { + new AsyncTask<Void, Void, Void>() { + public Void doInBackground(Void ... args) { appWidgetHost.deleteAppWidgetId(launcherAppWidgetInfo.appWidgetId); + return null; } - }.start(); + }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void) null); } } if (wasWaitingForUninstall && !mWaitingForUninstall) { diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java new file mode 100644 index 000000000..99819caf3 --- /dev/null +++ b/src/com/android/launcher3/DeviceProfile.java @@ -0,0 +1,886 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.launcher3; + +import android.appwidget.AppWidgetHostView; +import android.content.ComponentName; +import android.content.Context; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.graphics.Paint; +import android.graphics.Paint.FontMetrics; +import android.graphics.Point; +import android.graphics.PointF; +import android.graphics.Rect; +import android.util.DisplayMetrics; +import android.view.Display; +import android.view.Gravity; +import android.view.Surface; +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewGroup.LayoutParams; +import android.view.WindowManager; +import android.widget.FrameLayout; +import android.widget.LinearLayout; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; + +import com.android.launcher3.settings.SettingsProvider; + +class DeviceProfileQuery { + float widthDps; + float heightDps; + float value; + PointF dimens; + + DeviceProfileQuery(float w, float h, float v) { + widthDps = w; + heightDps = h; + value = v; + dimens = new PointF(w, h); + } +} + +public class DeviceProfile { + public static interface DeviceProfileCallbacks { + public void onAvailableSizeChanged(DeviceProfile grid); + } + + public final static int GRID_SIZE_MAX = 3; + public final static int GRID_SIZE_MIN = 2; + + public enum GridSize { + Comfortable(0), + Cozy(1), + Condensed(2), + Custom(3); + + private final int mValue; + private GridSize(int value) { + mValue = value; + } + + public int getValue() { + return mValue; + } + + public static GridSize getModeForValue(int value) { + switch (value) { + case 1: + return Cozy; + case 2: + return Condensed; + case 3: + return Custom; + default : + return Comfortable; + } + } + } + + String name; + float minWidthDps; + float minHeightDps; + float numRows; + float numColumns; + int numRowsBase; + int numColumnsBase; + float numHotseatIcons; + private float iconSize; + private float iconTextSize; + private int iconDrawablePaddingOriginalPx; + private float hotseatIconSize; + + boolean isLandscape; + boolean isTablet; + boolean isLargeTablet; + boolean isLayoutRtl; + boolean transposeLayoutWithOrientation; + + int desiredWorkspaceLeftRightMarginPx; + int edgeMarginPx; + Rect defaultWidgetPadding; + + int widthPx; + int heightPx; + int availableWidthPx; + int availableHeightPx; + int defaultPageSpacingPx; + + int overviewModeMinIconZoneHeightPx; + int overviewModeMaxIconZoneHeightPx; + int overviewModeBarItemWidthPx; + int overviewModeBarSpacerWidthPx; + float overviewModeIconZoneRatio; + float overviewModeScaleFactor; + + int iconSizePx; + int iconTextSizePx; + int iconDrawablePaddingPx; + int cellWidthPx; + int cellHeightPx; + int allAppsIconSizePx; + int allAppsIconTextSizePx; + int allAppsCellWidthPx; + int allAppsCellHeightPx; + int allAppsCellPaddingPx; + int folderBackgroundOffset; + int folderIconSizePx; + int folderCellWidthPx; + int folderCellHeightPx; + int hotseatCellWidthPx; + int hotseatCellHeightPx; + int hotseatIconSizePx; + int hotseatBarHeightPx; + int hotseatAllAppsRank; + int allAppsNumRows; + int allAppsNumCols; + int searchBarSpaceWidthPx; + int searchBarSpaceMaxWidthPx; + int searchBarSpaceHeightPx; + int searchBarHeightPx; + int pageIndicatorHeightPx; + + + boolean searchBarVisible; + + float dragViewScale; + + private ArrayList<DeviceProfileCallbacks> mCallbacks = new ArrayList<DeviceProfileCallbacks>(); + + DeviceProfile(String n, float w, float h, float r, float c, + float is, float its, float hs, float his) { + // Ensure that we have an odd number of hotseat items (since we need to place all apps) + if (!LauncherAppState.isDisableAllApps() && hs % 2 == 0) { + throw new RuntimeException("All Device Profiles must have an odd number of hotseat spaces"); + } + + name = n; + minWidthDps = w; + minHeightDps = h; + numRows = r; + numColumns = c; + iconSize = is; + iconTextSize = its; + numHotseatIcons = hs; + hotseatIconSize = his; + } + + DeviceProfile(Context context, + ArrayList<DeviceProfile> profiles, + float minWidth, float minHeight, + int wPx, int hPx, + int awPx, int ahPx, + Resources res) { + DisplayMetrics dm = res.getDisplayMetrics(); + ArrayList<DeviceProfileQuery> points = + new ArrayList<DeviceProfileQuery>(); + transposeLayoutWithOrientation = + res.getBoolean(R.bool.hotseat_transpose_layout_with_orientation); + minWidthDps = minWidth; + minHeightDps = minHeight; + + ComponentName cn = new ComponentName(context.getPackageName(), + this.getClass().getName()); + defaultWidgetPadding = AppWidgetHostView.getDefaultPaddingForWidget(context, cn, null); + edgeMarginPx = res.getDimensionPixelSize(R.dimen.dynamic_grid_edge_margin); + desiredWorkspaceLeftRightMarginPx = 2 * edgeMarginPx; + pageIndicatorHeightPx = + res.getDimensionPixelSize(R.dimen.dynamic_grid_page_indicator_height); + defaultPageSpacingPx = + res.getDimensionPixelSize(R.dimen.dynamic_grid_workspace_page_spacing); + allAppsCellPaddingPx = + res.getDimensionPixelSize(R.dimen.dynamic_grid_all_apps_cell_padding); + overviewModeMinIconZoneHeightPx = + res.getDimensionPixelSize(R.dimen.dynamic_grid_overview_min_icon_zone_height); + overviewModeMaxIconZoneHeightPx = + res.getDimensionPixelSize(R.dimen.dynamic_grid_overview_max_icon_zone_height); + overviewModeBarItemWidthPx = + res.getDimensionPixelSize(R.dimen.dynamic_grid_overview_bar_item_width); + overviewModeBarSpacerWidthPx = + res.getDimensionPixelSize(R.dimen.dynamic_grid_overview_bar_spacer_width); + overviewModeIconZoneRatio = + res.getInteger(R.integer.config_dynamic_grid_overview_icon_zone_percentage) / 100f; + overviewModeScaleFactor = + res.getInteger(R.integer.config_dynamic_grid_overview_scale_percentage) / 100f; + + // Interpolate the rows + for (DeviceProfile p : profiles) { + points.add(new DeviceProfileQuery(p.minWidthDps, p.minHeightDps, p.numRows)); + } + numRows = Math.round(invDistWeightedInterpolate(minWidth, minHeight, points)); + numRowsBase = (int) numRows; + int gridResize = SettingsProvider.getIntCustomDefault(context, + SettingsProvider.SETTINGS_UI_DYNAMIC_GRID_SIZE, 0); + if (GridSize.getModeForValue(gridResize) != GridSize.Custom) { + numRows += gridResize; + } else { + int iTempNumberOfRows = SettingsProvider.getIntCustomDefault(context, + SettingsProvider.SETTINGS_UI_HOMESCREEN_ROWS, (int)numRows); + if (iTempNumberOfRows > 0) { + numRows = iTempNumberOfRows; + } + } + // Interpolate the columns + points.clear(); + for (DeviceProfile p : profiles) { + points.add(new DeviceProfileQuery(p.minWidthDps, p.minHeightDps, p.numColumns)); + } + numColumns = Math.round(invDistWeightedInterpolate(minWidth, minHeight, points)); + numColumnsBase = (int) numColumns; + if (GridSize.getModeForValue(gridResize) != GridSize.Custom) { + numColumns += gridResize; + } else { + int iTempNumberOfColumns = SettingsProvider.getIntCustomDefault(context, + SettingsProvider.SETTINGS_UI_HOMESCREEN_COLUMNS, (int)numColumns); + if (iTempNumberOfColumns > 0) { + numColumns = iTempNumberOfColumns; + } + } + // Interpolate the hotseat length + points.clear(); + for (DeviceProfile p : profiles) { + points.add(new DeviceProfileQuery(p.minWidthDps, p.minHeightDps, p.numHotseatIcons)); + } + numHotseatIcons = Math.round(invDistWeightedInterpolate(minWidth, minHeight, points)); + hotseatAllAppsRank = (int) (numHotseatIcons / 2); + + // Interpolate the icon size + points.clear(); + for (DeviceProfile p : profiles) { + points.add(new DeviceProfileQuery(p.minWidthDps, p.minHeightDps, p.iconSize)); + } + iconSize = invDistWeightedInterpolate(minWidth, minHeight, points); + // AllApps uses the original non-scaled icon size + allAppsIconSizePx = DynamicGrid.pxFromDp(iconSize, dm); + + // Interpolate the icon text size + points.clear(); + for (DeviceProfile p : profiles) { + points.add(new DeviceProfileQuery(p.minWidthDps, p.minHeightDps, p.iconTextSize)); + } + iconTextSize = invDistWeightedInterpolate(minWidth, minHeight, points); + iconDrawablePaddingOriginalPx = + res.getDimensionPixelSize(R.dimen.dynamic_grid_icon_drawable_padding); + // AllApps uses the original non-scaled icon text size + allAppsIconTextSizePx = DynamicGrid.pxFromDp(iconTextSize, dm); + + // Interpolate the hotseat icon size + points.clear(); + for (DeviceProfile p : profiles) { + points.add(new DeviceProfileQuery(p.minWidthDps, p.minHeightDps, p.hotseatIconSize)); + } + // Hotseat + hotseatIconSize = invDistWeightedInterpolate(minWidth, minHeight, points); + + // Calculate the remaining vars + updateFromConfiguration(context, res, wPx, hPx, awPx, ahPx); + updateAvailableDimensions(context); + + // Search Bar + searchBarVisible = SettingsProvider.getBoolean(context, SettingsProvider.SETTINGS_UI_HOMESCREEN_SEARCH, + R.bool.preferences_interface_homescreen_search_default); + searchBarSpaceWidthPx = Math.min(searchBarSpaceMaxWidthPx, widthPx); + searchBarSpaceHeightPx = 2 * edgeMarginPx + (searchBarVisible ? searchBarHeightPx : 2 * edgeMarginPx); + } + + void addCallback(DeviceProfileCallbacks cb) { + mCallbacks.add(cb); + cb.onAvailableSizeChanged(this); + } + void removeCallback(DeviceProfileCallbacks cb) { + mCallbacks.remove(cb); + } + + private int getDeviceOrientation(Context context) { + WindowManager windowManager = (WindowManager) + context.getSystemService(Context.WINDOW_SERVICE); + Resources resources = context.getResources(); + DisplayMetrics dm = resources.getDisplayMetrics(); + Configuration config = resources.getConfiguration(); + int rotation = windowManager.getDefaultDisplay().getRotation(); + + boolean isLandscape = (config.orientation == Configuration.ORIENTATION_LANDSCAPE) && + (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180); + boolean isRotatedPortrait = (config.orientation == Configuration.ORIENTATION_PORTRAIT) && + (rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270); + if (isLandscape || isRotatedPortrait) { + return CellLayout.LANDSCAPE; + } else { + return CellLayout.PORTRAIT; + } + } + + private void updateAvailableDimensions(Context context) { + WindowManager windowManager = (WindowManager) + context.getSystemService(Context.WINDOW_SERVICE); + Display display = windowManager.getDefaultDisplay(); + Resources resources = context.getResources(); + DisplayMetrics dm = resources.getDisplayMetrics(); + Configuration config = resources.getConfiguration(); + + // There are three possible configurations that the dynamic grid accounts for, portrait, + // landscape with the nav bar at the bottom, and landscape with the nav bar at the side. + // To prevent waiting for fitSystemWindows(), we make the observation that in landscape, + // the height is the smallest height (either with the nav bar at the bottom or to the + // side) and otherwise, the height is simply the largest possible height for a portrait + // device. + Point size = new Point(); + Point smallestSize = new Point(); + Point largestSize = new Point(); + display.getSize(size); + display.getCurrentSizeRange(smallestSize, largestSize); + availableWidthPx = size.x; + if (config.orientation == Configuration.ORIENTATION_LANDSCAPE) { + availableHeightPx = smallestSize.y; + } else { + availableHeightPx = largestSize.y; + } + + // Check to see if the icons fit in the new available height. If not, then we need to + // shrink the icon size. + float scale = 1f; + int drawablePadding = iconDrawablePaddingOriginalPx; + updateIconSize(1f, drawablePadding, resources, dm); + float usedHeight = (cellHeightPx * numRows); + + Rect workspacePadding = getWorkspacePadding(); + int maxHeight = (availableHeightPx - workspacePadding.top - workspacePadding.bottom); + if (usedHeight > maxHeight) { + scale = maxHeight / usedHeight; + drawablePadding = 0; + } + updateIconSize(scale, drawablePadding, resources, dm); + + // Make the callbacks + for (DeviceProfileCallbacks cb : mCallbacks) { + cb.onAvailableSizeChanged(this); + } + } + + private void updateIconSize(float scale, int drawablePadding, Resources resources, + DisplayMetrics dm) { + iconSizePx = (int) (DynamicGrid.pxFromDp(iconSize, dm) * scale); + iconTextSizePx = (int) (DynamicGrid.pxFromSp(iconTextSize, dm) * scale); + iconDrawablePaddingPx = drawablePadding; + hotseatIconSizePx = (int) (DynamicGrid.pxFromDp(hotseatIconSize, dm) * scale); + + // Search Bar + searchBarSpaceWidthPx = Math.min(searchBarSpaceMaxWidthPx, widthPx); + searchBarSpaceMaxWidthPx = resources.getDimensionPixelSize(R.dimen.dynamic_grid_search_bar_max_width); + searchBarHeightPx = resources.getDimensionPixelSize(R.dimen.dynamic_grid_search_bar_height); + searchBarSpaceHeightPx = searchBarHeightPx + getSearchBarTopOffset(); + + // Calculate the actual text height + Paint textPaint = new Paint(); + textPaint.setTextSize(iconTextSizePx); + FontMetrics fm = textPaint.getFontMetrics(); + cellWidthPx = iconSizePx; + cellHeightPx = iconSizePx + iconDrawablePaddingPx + (int) Math.ceil(fm.bottom - fm.top); + final float scaleDps = resources.getDimensionPixelSize(R.dimen.dragViewScale); + dragViewScale = (iconSizePx + scaleDps) / iconSizePx; + + // Hotseat + hotseatBarHeightPx = iconSizePx + 4 * edgeMarginPx; + hotseatCellWidthPx = iconSizePx; + hotseatCellHeightPx = iconSizePx; + + // Folder + folderCellWidthPx = cellWidthPx + 3 * edgeMarginPx; + folderCellHeightPx = cellHeightPx + edgeMarginPx; + folderBackgroundOffset = -edgeMarginPx; + folderIconSizePx = iconSizePx + 2 * -folderBackgroundOffset; + + // All Apps + Rect padding = getWorkspacePadding(isLandscape ? + CellLayout.LANDSCAPE : CellLayout.PORTRAIT); + int pageIndicatorOffset = + resources.getDimensionPixelSize(R.dimen.apps_customize_page_indicator_offset); + + if (isPhone()) { + searchBarSpaceWidthPx = Math.min(searchBarSpaceMaxWidthPx, widthPx); + } else { + searchBarSpaceWidthPx = widthPx - (isLandscape ? 3 : 1) * iconSizePx; + } + + allAppsCellWidthPx = allAppsIconSizePx; + allAppsCellHeightPx = allAppsIconSizePx + drawablePadding + iconTextSizePx; + int maxLongEdgeCellCount = + resources.getInteger(R.integer.config_dynamic_grid_max_long_edge_cell_count); + int maxShortEdgeCellCount = + resources.getInteger(R.integer.config_dynamic_grid_max_short_edge_cell_count); + int minEdgeCellCount = + resources.getInteger(R.integer.config_dynamic_grid_min_edge_cell_count); + int maxRows = (isLandscape ? maxShortEdgeCellCount : maxLongEdgeCellCount); + int maxCols = (isLandscape ? maxLongEdgeCellCount : maxShortEdgeCellCount); + + allAppsNumRows = (availableHeightPx - pageIndicatorHeightPx) / + (allAppsCellHeightPx + allAppsCellPaddingPx); + allAppsNumRows = Math.max(minEdgeCellCount, Math.min(maxRows, allAppsNumRows)); + allAppsNumCols = (availableWidthPx) / + (allAppsCellWidthPx + allAppsCellPaddingPx); + allAppsNumCols = Math.max(minEdgeCellCount, Math.min(maxCols, allAppsNumCols)); + } + + void updateFromConfiguration(Context context, Resources resources, int wPx, int hPx, + int awPx, int ahPx) { + Configuration configuration = resources.getConfiguration(); + isLandscape = (configuration.orientation == Configuration.ORIENTATION_LANDSCAPE); + isTablet = resources.getBoolean(R.bool.is_tablet); + isLargeTablet = resources.getBoolean(R.bool.is_large_tablet); + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) { + isLayoutRtl = (configuration.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL); + } else { + isLayoutRtl = false; + } + widthPx = wPx; + heightPx = hPx; + availableWidthPx = awPx; + availableHeightPx = ahPx; + + updateAvailableDimensions(context); + } + + private float dist(PointF p0, PointF p1) { + return (float) Math.sqrt((p1.x - p0.x)*(p1.x-p0.x) + + (p1.y-p0.y)*(p1.y-p0.y)); + } + + private float weight(PointF a, PointF b, + float pow) { + float d = dist(a, b); + if (d == 0f) { + return Float.POSITIVE_INFINITY; + } + return (float) (1f / Math.pow(d, pow)); + } + + private float invDistWeightedInterpolate(float width, float height, + ArrayList<DeviceProfileQuery> points) { + float sum = 0; + float weights = 0; + float pow = 5; + float kNearestNeighbors = 3; + final PointF xy = new PointF(width, height); + + ArrayList<DeviceProfileQuery> pointsByNearness = points; + Collections.sort(pointsByNearness, new Comparator<DeviceProfileQuery>() { + public int compare(DeviceProfileQuery a, DeviceProfileQuery b) { + return (int) (dist(xy, a.dimens) - dist(xy, b.dimens)); + } + }); + + for (int i = 0; i < pointsByNearness.size(); ++i) { + DeviceProfileQuery p = pointsByNearness.get(i); + if (i < kNearestNeighbors) { + float w = weight(xy, p.dimens, pow); + if (w == Float.POSITIVE_INFINITY) { + return p.value; + } + weights += w; + } + } + + for (int i = 0; i < pointsByNearness.size(); ++i) { + DeviceProfileQuery p = pointsByNearness.get(i); + if (i < kNearestNeighbors) { + float w = weight(xy, p.dimens, pow); + sum += w * p.value / weights; + } + } + + return sum; + } + + /** Returns the search bar top offset */ + int getSearchBarTopOffset() { + if (isTablet() && !isVerticalBarLayout()) { + return searchBarVisible ? 4 * edgeMarginPx : 0; + } else { + return searchBarVisible ? 2 * edgeMarginPx : 0; + } + } + + /** Returns the search bar bounds in the current orientation */ + Rect getSearchBarBounds() { + return getSearchBarBounds(isLandscape ? CellLayout.LANDSCAPE : CellLayout.PORTRAIT); + } + /** Returns the search bar bounds in the specified orientation */ + Rect getSearchBarBounds(int orientation) { + Rect bounds = new Rect(); + if (orientation == CellLayout.LANDSCAPE && + transposeLayoutWithOrientation) { + if (isLayoutRtl) { + bounds.set(availableWidthPx - searchBarSpaceHeightPx, edgeMarginPx, + availableWidthPx, availableHeightPx - edgeMarginPx); + } else { + bounds.set(0, edgeMarginPx, searchBarSpaceHeightPx, + availableHeightPx - edgeMarginPx); + } + } else { + if (isTablet()) { + // Pad the left and right of the workspace to ensure consistent spacing + // between all icons + int width = (orientation == CellLayout.LANDSCAPE) + ? Math.max(widthPx, heightPx) + : Math.min(widthPx, heightPx); + // XXX: If the icon size changes across orientations, we will have to take + // that into account here too. + int gap = (int) ((width - 2 * edgeMarginPx - + (numColumns * cellWidthPx)) / (2 * (numColumns + 1))); + bounds.set(edgeMarginPx + gap, getSearchBarTopOffset(), + availableWidthPx - (edgeMarginPx + gap), + searchBarVisible ? searchBarSpaceHeightPx : edgeMarginPx); + } else { + bounds.set(desiredWorkspaceLeftRightMarginPx - defaultWidgetPadding.left, + getSearchBarTopOffset(), + availableWidthPx - (desiredWorkspaceLeftRightMarginPx - + defaultWidgetPadding.right), searchBarVisible ? searchBarSpaceHeightPx : edgeMarginPx); + } + } + return bounds; + } + + /** Returns the bounds of the workspace page indicators. */ + Rect getWorkspacePageIndicatorBounds(Rect insets) { + Rect workspacePadding = getWorkspacePadding(); + if (isLandscape && transposeLayoutWithOrientation) { + if (isLayoutRtl) { + return new Rect(workspacePadding.left, workspacePadding.top, + workspacePadding.left + pageIndicatorHeightPx, + heightPx - workspacePadding.bottom - insets.bottom); + } else { + int pageIndicatorLeft = widthPx - workspacePadding.right; + return new Rect(pageIndicatorLeft, workspacePadding.top, + pageIndicatorLeft + pageIndicatorHeightPx, + heightPx - workspacePadding.bottom - insets.bottom); + } + } else { + int pageIndicatorTop = heightPx - insets.bottom - workspacePadding.bottom; + return new Rect(workspacePadding.left, pageIndicatorTop, + widthPx - workspacePadding.right, pageIndicatorTop + pageIndicatorHeightPx); + } + } + + /** Returns the workspace padding in the specified orientation */ + Rect getWorkspacePadding() { + return getWorkspacePadding(isLandscape ? CellLayout.LANDSCAPE : CellLayout.PORTRAIT); + } + Rect getWorkspacePadding(int orientation) { + Rect searchBarBounds = getSearchBarBounds(orientation); + Rect padding = new Rect(); + if (orientation == CellLayout.LANDSCAPE && + transposeLayoutWithOrientation) { + // Pad the left and right of the workspace with search/hotseat bar sizes + if (isLayoutRtl) { + padding.set(hotseatBarHeightPx, edgeMarginPx, + searchBarBounds.width(), edgeMarginPx); + } else { + padding.set(searchBarBounds.width(), edgeMarginPx, + hotseatBarHeightPx, edgeMarginPx); + } + } else { + if (isTablet()) { + // Pad the left and right of the workspace to ensure consistent spacing + // between all icons + float gapScale = 1f + (dragViewScale - 1f) / 2f; + int width = (orientation == CellLayout.LANDSCAPE) + ? Math.max(widthPx, heightPx) + : Math.min(widthPx, heightPx); + int height = (orientation != CellLayout.LANDSCAPE) + ? Math.max(widthPx, heightPx) + : Math.min(widthPx, heightPx); + int paddingTop = searchBarBounds.bottom; + int paddingBottom = hotseatBarHeightPx + pageIndicatorHeightPx; + int availableWidth = Math.max(0, width - (int) ((numColumns * cellWidthPx) + + (numColumns * gapScale * cellWidthPx))); + int availableHeight = Math.max(0, height - paddingTop - paddingBottom + - (int) (2 * numRows * cellHeightPx)); + padding.set(availableWidth / 2, paddingTop + availableHeight / 2, + availableWidth / 2, paddingBottom + availableHeight / 2); + } else { + // Pad the top and bottom of the workspace with search/hotseat bar sizes + padding.set(desiredWorkspaceLeftRightMarginPx - defaultWidgetPadding.left, + searchBarBounds.bottom, + desiredWorkspaceLeftRightMarginPx - defaultWidgetPadding.right, + hotseatBarHeightPx + pageIndicatorHeightPx); + } + } + return padding; + } + + int getWorkspacePageSpacing(int orientation) { + if ((orientation == CellLayout.LANDSCAPE && + transposeLayoutWithOrientation) || isLargeTablet()) { + // In landscape mode the page spacing is set to the default. + return defaultPageSpacingPx; + } else { + // In portrait, we want the pages spaced such that there is no + // overhang of the previous / next page into the current page viewport. + // We assume symmetrical padding in portrait mode. + return Math.max(defaultPageSpacingPx, 2 * getWorkspacePadding().left); + } + } + + Rect getOverviewModeButtonBarRect() { + int zoneHeight = (int) (overviewModeIconZoneRatio * availableHeightPx); + zoneHeight = Math.min(overviewModeMaxIconZoneHeightPx, + Math.max(overviewModeMinIconZoneHeightPx, zoneHeight)); + return new Rect(0, availableHeightPx - zoneHeight, 0, availableHeightPx); + } + + float getOverviewModeScale() { + Rect workspacePadding = getWorkspacePadding(); + Rect overviewBar = getOverviewModeButtonBarRect(); + int pageSpace = availableHeightPx - workspacePadding.top - workspacePadding.bottom; + return (overviewModeScaleFactor * (pageSpace - overviewBar.height())) / pageSpace; + } + + // The rect returned will be extended to below the system ui that covers the workspace + Rect getHotseatRect() { + if (isVerticalBarLayout()) { + return new Rect(availableWidthPx - hotseatBarHeightPx, 0, + Integer.MAX_VALUE, availableHeightPx); + } else { + return new Rect(0, availableHeightPx - hotseatBarHeightPx, + availableWidthPx, Integer.MAX_VALUE); + } + } + + int calculateCellWidth(int width, int countX) { + return width / countX; + } + int calculateCellHeight(int height, int countY) { + return height / countY; + } + + boolean isPhone() { + return !isTablet && !isLargeTablet; + } + boolean isTablet() { + return isTablet; + } + boolean isLargeTablet() { + return isLargeTablet; + } + + boolean isVerticalBarLayout() { + return isLandscape && transposeLayoutWithOrientation; + } + + boolean shouldFadeAdjacentWorkspaceScreens() { + return isVerticalBarLayout() || isLargeTablet(); + } + + int getVisibleChildCount(ViewGroup parent) { + int visibleChildren = 0; + for (int i = 0; i < parent.getChildCount(); i++) { + if (parent.getChildAt(i).getVisibility() != View.GONE) { + visibleChildren++; + } + } + return visibleChildren; + } + + int calculateOverviewModeWidth(int visibleChildCount) { + return visibleChildCount * overviewModeBarItemWidthPx + + (visibleChildCount-1) * overviewModeBarSpacerWidthPx; + } + + public void layout(Launcher launcher) { + // Update search bar for live settings + searchBarVisible = SettingsProvider.getBoolean(launcher, SettingsProvider.SETTINGS_UI_HOMESCREEN_SEARCH, + R.bool.preferences_interface_homescreen_search_default); + searchBarSpaceHeightPx = 2 * edgeMarginPx + (searchBarVisible ? searchBarHeightPx : 2 * edgeMarginPx); + FrameLayout.LayoutParams lp; + Resources res = launcher.getResources(); + boolean hasVerticalBarLayout = isVerticalBarLayout(); + + // Layout the search bar space + View searchBar = launcher.getSearchBar(); + lp = (FrameLayout.LayoutParams) searchBar.getLayoutParams(); + if (hasVerticalBarLayout) { + // Vertical search bar space + lp.gravity = Gravity.TOP | Gravity.LEFT; + lp.width = searchBarSpaceHeightPx; + lp.height = LayoutParams.WRAP_CONTENT; + searchBar.setPadding( + 0, 2 * edgeMarginPx, 0, + 2 * edgeMarginPx); + + searchBar.setVisibility(searchBarVisible ? View.VISIBLE : View.GONE); + LinearLayout targets = (LinearLayout) searchBar.findViewById(R.id.drag_target_bar); + targets.setOrientation(LinearLayout.VERTICAL); + } else { + // Horizontal search bar space + lp.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL; + lp.width = searchBarSpaceWidthPx; + lp.height = searchBarSpaceHeightPx; + searchBar.setPadding( + 2 * edgeMarginPx, + getSearchBarTopOffset(), + 2 * edgeMarginPx, 0); + } + searchBar.setLayoutParams(lp); + + // Layout the drop target icons + LinearLayout dropTargetBar = (LinearLayout) launcher.getSearchBar().getDropTargetBar(); + if (hasVerticalBarLayout) { + dropTargetBar.setOrientation(LinearLayout.VERTICAL); + } else { + dropTargetBar.setOrientation(LinearLayout.HORIZONTAL); + } + + // Layout the search bar + View qsbBar = launcher.getQsbBar(); + qsbBar.setVisibility(searchBarVisible ? View.VISIBLE : View.GONE); + LayoutParams vglp = qsbBar.getLayoutParams(); + vglp.width = LayoutParams.MATCH_PARENT; + vglp.height = LayoutParams.MATCH_PARENT; + qsbBar.setLayoutParams(vglp); + + // Layout the voice proxy + View voiceButtonProxy = launcher.findViewById(R.id.voice_button_proxy); + if (voiceButtonProxy != null) { + if (hasVerticalBarLayout) { + // TODO: MOVE THIS INTO SEARCH BAR MEASURE + } else { + lp = (FrameLayout.LayoutParams) voiceButtonProxy.getLayoutParams(); + lp.gravity = Gravity.TOP | Gravity.END; + lp.width = (widthPx - searchBarSpaceWidthPx) / 2 + + 2 * iconSizePx; + lp.height = searchBarSpaceHeightPx; + } + } + + // Layout the workspace + PagedView workspace = (PagedView) launcher.findViewById(R.id.workspace); + lp = (FrameLayout.LayoutParams) workspace.getLayoutParams(); + lp.gravity = Gravity.CENTER; + int orientation = isLandscape ? CellLayout.LANDSCAPE : CellLayout.PORTRAIT; + Rect padding = getWorkspacePadding(orientation); + workspace.setLayoutParams(lp); + workspace.setPadding(padding.left, padding.top, padding.right, padding.bottom); + workspace.setPageSpacing(getWorkspacePageSpacing(orientation)); + + // Layout the hotseat + View hotseat = launcher.findViewById(R.id.hotseat); + lp = (FrameLayout.LayoutParams) hotseat.getLayoutParams(); + if (hasVerticalBarLayout) { + // Vertical hotseat + lp.gravity = Gravity.END; + lp.width = hotseatBarHeightPx; + lp.height = LayoutParams.MATCH_PARENT; + hotseat.findViewById(R.id.layout).setPadding(0, 2 * edgeMarginPx, 0, 2 * edgeMarginPx); + } else if (isTablet()) { + // Pad the hotseat with the workspace padding calculated above + lp.gravity = Gravity.BOTTOM; + lp.width = LayoutParams.MATCH_PARENT; + lp.height = hotseatBarHeightPx; + hotseat.setPadding(edgeMarginPx + padding.left, 0, + edgeMarginPx + padding.right, + 2 * edgeMarginPx); + } else { + // For phones, layout the hotseat without any bottom margin + // to ensure that we have space for the folders + lp.gravity = Gravity.BOTTOM; + lp.width = LayoutParams.MATCH_PARENT; + lp.height = hotseatBarHeightPx; + hotseat.findViewById(R.id.layout).setPadding(2 * edgeMarginPx, 0, + 2 * edgeMarginPx, 0); + } + hotseat.setLayoutParams(lp); + + // Layout the page indicators + View pageIndicator = launcher.findViewById(R.id.page_indicator); + if (pageIndicator != null) { + if (hasVerticalBarLayout) { + // Hide the page indicators when we have vertical search/hotseat + pageIndicator.setVisibility(View.GONE); + } else { + // Put the page indicators above the hotseat + lp = (FrameLayout.LayoutParams) pageIndicator.getLayoutParams(); + lp.gravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; + lp.width = LayoutParams.WRAP_CONTENT; + lp.height = LayoutParams.WRAP_CONTENT; + lp.bottomMargin = Math.max(hotseatBarHeightPx, lp.bottomMargin); + pageIndicator.setLayoutParams(lp); + } + } + + // Layout the apps customize + View appsCustomize = launcher.findViewById(R.id.apps_customize_pane_content); + lp = (FrameLayout.LayoutParams) appsCustomize.getLayoutParams(); + lp.gravity = Gravity.CENTER; + appsCustomize.setLayoutParams(lp); + + // Layout AllApps + AppsCustomizeLayout host = (AppsCustomizeLayout) + launcher.findViewById(R.id.apps_customize_pane); + if (host != null) { + // Center the all apps page indicator + int pageIndicatorHeight = (int) (pageIndicatorHeightPx * Math.min(1f, + (allAppsIconSizePx / DynamicGrid.DEFAULT_ICON_SIZE_PX))); + pageIndicator = host.findViewById(R.id.apps_customize_page_indicator); + if (pageIndicator != null) { + lp = (FrameLayout.LayoutParams) pageIndicator.getLayoutParams(); + lp.gravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; + lp.width = LayoutParams.WRAP_CONTENT; + lp.height = pageIndicatorHeight; + pageIndicator.setLayoutParams(lp); + } + + AppsCustomizePagedView pagedView = (AppsCustomizePagedView) + host.findViewById(R.id.apps_customize_pane_content); + padding = new Rect(); + if (pagedView != null) { + // Constrain the dimensions of all apps so that it does not span the full width + int paddingLR = (availableWidthPx - (allAppsCellWidthPx * allAppsNumCols)) / + (2 * (allAppsNumCols + 1)); + int paddingTB = (availableHeightPx - (allAppsCellHeightPx * allAppsNumRows)) / + (2 * (allAppsNumRows + 1)); + paddingLR = Math.min(paddingLR, (int)((paddingLR + paddingTB) * 0.75f)); + paddingTB = Math.min(paddingTB, (int)((paddingLR + paddingTB) * 0.75f)); + int maxAllAppsWidth = (allAppsNumCols * (allAppsCellWidthPx + 2 * paddingLR)); + int gridPaddingLR = (availableWidthPx - maxAllAppsWidth) / 2; + // Only adjust the side paddings on landscape phones, or tablets + if ((isTablet() || isLandscape) && gridPaddingLR > (allAppsCellWidthPx / 4)) { + padding.left = padding.right = gridPaddingLR; + } + // The icons are centered, so we can't just offset by the page indicator height + // because the empty space will actually be pageIndicatorHeight + paddingTB + padding.bottom = Math.max(0, pageIndicatorHeight - paddingTB); + pagedView.setAllAppsPadding(padding); + pagedView.setWidgetsPageIndicatorPadding(pageIndicatorHeight); + } + } + + // Layout the Overview Mode +// ViewGroup overviewMode = launcher.getOverviewPanel(); +// if (overviewMode != null) { +// Rect r = getOverviewModeButtonBarRect(); +// lp = (FrameLayout.LayoutParams) overviewMode.getLayoutParams(); +// lp.gravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; +// lp.width = Math.min(availableWidthPx, +// calculateOverviewModeWidth(getVisibleChildCount(overviewMode))); +// lp.height = r.height(); +// overviewMode.setLayoutParams(lp); +// } + } +} diff --git a/src/com/android/launcher3/DragController.java b/src/com/android/launcher3/DragController.java index 5b5c35c5a..4c3ea2a0a 100644 --- a/src/com/android/launcher3/DragController.java +++ b/src/com/android/launcher3/DragController.java @@ -16,6 +16,7 @@ package com.android.launcher3; +import android.content.ComponentName; import android.content.Context; import android.content.res.Resources; import android.graphics.Bitmap; @@ -25,16 +26,9 @@ import android.graphics.Rect; import android.os.Handler; import android.os.IBinder; import android.util.Log; -import android.view.HapticFeedbackConstants; -import android.view.KeyEvent; -import android.view.MotionEvent; -import android.view.VelocityTracker; -import android.view.View; -import android.view.ViewConfiguration; +import android.view.*; import android.view.inputmethod.InputMethodManager; -import com.android.launcher3.R; - import java.util.ArrayList; /** @@ -203,7 +197,7 @@ public class DragController { * @param dragRegion Coordinates within the bitmap b for the position of item being dragged. * Makes dragging feel more precise, e.g. you can clip out a transparent border */ - public void startDrag(Bitmap b, int dragLayerX, int dragLayerY, + public DragView startDrag(Bitmap b, int dragLayerX, int dragLayerY, DragSource source, Object dragInfo, int dragAction, Point dragOffset, Rect dragRegion, float initialDragViewScale) { if (PROFILE_DRAWING_DURING_DRAG) { @@ -250,6 +244,7 @@ public class DragController { mLauncher.getDragLayer().performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); dragView.show(mMotionDownX, mMotionDownY); handleMoveEvent(mMotionDownX, mMotionDownY); + return dragView; } /** @@ -323,7 +318,7 @@ public class DragController { } endDrag(); } - public void onAppsRemoved(ArrayList<AppInfo> appInfos, Context context) { + public void onAppsRemoved(final ArrayList<String> packageNames, ArrayList<AppInfo> appInfos) { // Cancel the current drag if we are removing an app that we are dragging if (mDragObject != null) { Object rawDragInfo = mDragObject.dragInfo; @@ -332,9 +327,10 @@ public class DragController { for (AppInfo info : appInfos) { // Added null checks to prevent NPE we've seen in the wild if (dragInfo != null && - dragInfo.intent != null) { - boolean isSameComponent = - dragInfo.intent.getComponent().equals(info.componentName); + dragInfo.intent != null && info != null) { + ComponentName cn = dragInfo.intent.getComponent(); + boolean isSameComponent = cn.equals(info.componentName) || + packageNames.contains(cn.getPackageName()); if (isSameComponent) { cancelDrag(); return; diff --git a/src/com/android/launcher3/DragLayer.java b/src/com/android/launcher3/DragLayer.java index 401f4ed52..3ff4293af 100644 --- a/src/com/android/launcher3/DragLayer.java +++ b/src/com/android/launcher3/DragLayer.java @@ -24,11 +24,13 @@ import android.animation.ValueAnimator.AnimatorUpdateListener; import android.content.Context; import android.content.res.Resources; import android.graphics.Canvas; -import android.graphics.Matrix; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.util.AttributeSet; -import android.view.*; +import android.view.KeyEvent; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; import android.view.animation.DecelerateInterpolator; @@ -63,8 +65,6 @@ public class DragLayer extends FrameLayout implements ViewGroup.OnHierarchyChang private boolean mHoverPointClosesFolder = false; private Rect mHitRect = new Rect(); - private int mWorkspaceIndex = -1; - private int mQsbIndex = -1; public static final int ANIMATION_END_DISAPPEAR = 0; public static final int ANIMATION_END_FADE_OUT = 1; public static final int ANIMATION_END_REMAIN_VISIBLE = 2; @@ -73,6 +73,8 @@ public class DragLayer extends FrameLayout implements ViewGroup.OnHierarchyChang private final Rect mInsets = new Rect(); + private int mDragViewIndex; + /** * Used to create a new DragLayer from XML. * @@ -106,21 +108,34 @@ public class DragLayer extends FrameLayout implements ViewGroup.OnHierarchyChang final int n = getChildCount(); for (int i = 0; i < n; i++) { final View child = getChildAt(i); - final FrameLayout.LayoutParams flp = (FrameLayout.LayoutParams) child.getLayoutParams(); - if (child instanceof Insettable) { - ((Insettable)child).setInsets(insets); - } else { - flp.topMargin += (insets.top - mInsets.top); - flp.leftMargin += (insets.left - mInsets.left); - flp.rightMargin += (insets.right - mInsets.right); - flp.bottomMargin += (insets.bottom - mInsets.bottom); + if (child.getId() == R.id.overview_panel) { + continue; } - child.setLayoutParams(flp); + setInsets(child, insets, mInsets); } mInsets.set(insets); return true; // I'll take it from here } + @Override + public void addView(View child, int index, android.view.ViewGroup.LayoutParams params) { + super.addView(child, index, params); + setInsets(child, mInsets, new Rect()); + } + + private void setInsets(View child, Rect newInsets, Rect oldInsets) { + final FrameLayout.LayoutParams flp = (FrameLayout.LayoutParams) child.getLayoutParams(); + if (child instanceof Insettable) { + ((Insettable) child).setInsets(newInsets); + } else { + flp.topMargin += (newInsets.top - oldInsets.top); + flp.leftMargin += (newInsets.left - oldInsets.left); + flp.rightMargin += (newInsets.right - oldInsets.right); + flp.bottomMargin += (newInsets.bottom - oldInsets.bottom); + } + child.setLayoutParams(flp); + } + private boolean isEventOverFolderTextRegion(Folder folder, MotionEvent ev) { getDescendantRectRelativeToSelf(folder.getEditTextRegion(), mHitRect); if (mHitRect.contains((int) ev.getX(), (int) ev.getY())) { @@ -156,7 +171,8 @@ public class DragLayer extends FrameLayout implements ViewGroup.OnHierarchyChang } Folder currentFolder = mLauncher.getWorkspace().getOpenFolder(); - if (currentFolder != null && !mLauncher.isFolderClingVisible() && intercept) { + if (currentFolder != null && !mLauncher.getLauncherClings().isFolderClingVisible() && + intercept) { if (currentFolder.isEditingName()) { if (!isEventOverFolderTextRegion(currentFolder, ev)) { currentFolder.dismissEditingName(); @@ -212,22 +228,19 @@ public class DragLayer extends FrameLayout implements ViewGroup.OnHierarchyChang sendTapOutsideFolderAccessibilityEvent(currentFolder.isEditingName()); mHoverPointClosesFolder = true; return true; - } else if (isOverFolder) { - mHoverPointClosesFolder = false; - } else { - return true; } + mHoverPointClosesFolder = false; + break; case MotionEvent.ACTION_HOVER_MOVE: isOverFolder = isEventOverFolder(currentFolder, ev); if (!isOverFolder && !mHoverPointClosesFolder) { sendTapOutsideFolderAccessibilityEvent(currentFolder.isEditingName()); mHoverPointClosesFolder = true; return true; - } else if (isOverFolder) { - mHoverPointClosesFolder = false; - } else { + } else if (!isOverFolder) { return true; } + mHoverPointClosesFolder = false; } } } @@ -480,7 +493,7 @@ public class DragLayer extends FrameLayout implements ViewGroup.OnHierarchyChang } public void animateViewIntoPosition(DragView dragView, final View child) { - animateViewIntoPosition(dragView, child, null); + animateViewIntoPosition(dragView, child, null, null); } public void animateViewIntoPosition(DragView dragView, final int[] pos, float alpha, @@ -496,8 +509,8 @@ public class DragLayer extends FrameLayout implements ViewGroup.OnHierarchyChang } public void animateViewIntoPosition(DragView dragView, final View child, - final Runnable onFinishAnimationRunnable) { - animateViewIntoPosition(dragView, child, -1, onFinishAnimationRunnable, null); + final Runnable onFinishAnimationRunnable, View anchorView) { + animateViewIntoPosition(dragView, child, -1, onFinishAnimationRunnable, anchorView); } public void animateViewIntoPosition(DragView dragView, final View child, int duration, @@ -522,14 +535,18 @@ public class DragLayer extends FrameLayout implements ViewGroup.OnHierarchyChang scale *= childScale; int toX = coord[0]; int toY = coord[1]; + float toScale = scale; if (child instanceof TextView) { TextView tv = (TextView) child; + // Account for the source scale of the icon (ie. from AllApps to Workspace, in which + // the workspace may have smaller icon bounds). + toScale = scale / dragView.getIntrinsicIconScaleFactor(); // The child may be scaled (always about the center of the view) so to account for it, // we have to offset the position by the scaled size. Once we do that, we can center // the drag view about the scaled child view. - toY += Math.round(scale * tv.getPaddingTop()); - toY -= dragView.getMeasuredHeight() * (1 - scale) / 2; + toY += Math.round(toScale * tv.getPaddingTop()); + toY -= dragView.getMeasuredHeight() * (1 - toScale) / 2; toX -= (dragView.getMeasuredWidth() - Math.round(scale * child.getMeasuredWidth())) / 2; } else if (child instanceof FolderIcon) { // Account for holographic blur padding on the drag view @@ -555,7 +572,7 @@ public class DragLayer extends FrameLayout implements ViewGroup.OnHierarchyChang } } }; - animateViewIntoPosition(dragView, fromX, fromY, toX, toY, 1, 1, 1, scale, scale, + animateViewIntoPosition(dragView, fromX, fromY, toX, toY, 1, 1, 1, toScale, toScale, onCompleteRunnable, ANIMATION_END_DISAPPEAR, duration, anchorView); } @@ -645,8 +662,10 @@ public class DragLayer extends FrameLayout implements ViewGroup.OnHierarchyChang int x = (int) (fromLeft + Math.round(((to.left - fromLeft) * motionPercent))); int y = (int) (fromTop + Math.round(((to.top - fromTop) * motionPercent))); - int xPos = x - mDropView.getScrollX() + (mAnchorView != null - ? (mAnchorViewInitialScrollX - mAnchorView.getScrollX()) : 0); + int anchorAdjust = mAnchorView == null ? 0 : (int) (mAnchorView.getScaleX() * + (mAnchorViewInitialScrollX - mAnchorView.getScrollX())); + + int xPos = x - mDropView.getScrollX() + anchorAdjust; int yPos = y - mDropView.getScrollY(); mDropView.setTranslationX(xPos); @@ -755,31 +774,26 @@ public class DragLayer extends FrameLayout implements ViewGroup.OnHierarchyChang } private void updateChildIndices() { - if (mLauncher != null) { - mWorkspaceIndex = indexOfChild(mLauncher.getWorkspace()); - mQsbIndex = indexOfChild(mLauncher.getSearchBar()); + mDragViewIndex = -1; + int childCount = getChildCount(); + for (int i = 0; i < childCount; i++) { + if (getChildAt(i) instanceof DragView) { + mDragViewIndex = i; + } } } @Override protected int getChildDrawingOrder(int childCount, int i) { - // TODO: We have turned off this custom drawing order because it now effects touch - // dispatch order. We need to sort that issue out and then decide how to go about this. - if (true || LauncherAppState.isScreenLandscape(getContext()) || - mWorkspaceIndex == -1 || mQsbIndex == -1 || - mLauncher.getWorkspace().isDrawingBackgroundGradient()) { + if (mDragViewIndex == -1) { return i; - } - - // This ensures that the workspace is drawn above the hotseat and qsb, - // except when the workspace is drawing a background gradient, in which - // case we want the workspace to stay behind these elements. - if (i == mQsbIndex) { - return mWorkspaceIndex; - } else if (i == mWorkspaceIndex) { - return mQsbIndex; - } else { + } else if (i == mDragViewIndex) { + return getChildCount()-1; + } else if (i < mDragViewIndex) { return i; + } else { + // i > mDragViewIndex + return i-1; } } @@ -800,7 +814,6 @@ public class DragLayer extends FrameLayout implements ViewGroup.OnHierarchyChang /** * Note: this is a reimplementation of View.isLayoutRtl() since that is currently hidden api. */ - @Override public boolean isLayoutRtl() { return (getLayoutDirection() == LAYOUT_DIRECTION_RTL); } diff --git a/src/com/android/launcher3/DragSource.java b/src/com/android/launcher3/DragSource.java index 2ef99ae08..7369eeac2 100644 --- a/src/com/android/launcher3/DragSource.java +++ b/src/com/android/launcher3/DragSource.java @@ -31,6 +31,22 @@ public interface DragSource { boolean supportsFlingToDelete(); /** + * @return whether items dragged from this source supports 'App Info' + */ + boolean supportsAppInfoDropTarget(); + + /** + * @return whether items dragged from this source supports 'Delete' drop target (e.g. to remove + * a shortcut. + */ + boolean supportsDeleteDropTarget(); + + /* + * @return the scale of the icons over the workspace icon size + */ + float getIntrinsicIconScaleFactor(); + + /** * A callback specifically made back to the source after an item from this source has been flung * to be deleted on a DropTarget. In such a situation, this method will be called after * onDropCompleted, and more importantly, after the fling animation has completed. diff --git a/src/com/android/launcher3/DragView.java b/src/com/android/launcher3/DragView.java index 686cf62ff..ea34e46f9 100644 --- a/src/com/android/launcher3/DragView.java +++ b/src/com/android/launcher3/DragView.java @@ -14,7 +14,6 @@ * limitations under the License. */ - package com.android.launcher3; import android.animation.ValueAnimator; @@ -30,8 +29,6 @@ import android.graphics.Rect; import android.view.View; import android.view.animation.DecelerateInterpolator; -import com.android.launcher3.R; - public class DragView extends View { private static float sDragAlpha = 1f; @@ -51,6 +48,9 @@ public class DragView extends View { private float mOffsetX = 0.0f; private float mOffsetY = 0.0f; private float mInitialScale = 1f; + // The intrinsic icon scale factor is the scale factor for a drag icon over the workspace + // size. This is ignored for non-icons. + private float mIntrinsicIconScale = 1f; /** * Construct the drag view. @@ -120,6 +120,15 @@ public class DragView extends View { mPaint = new Paint(Paint.FILTER_BITMAP_FLAG); } + /** Sets the scale of the view over the normal workspace icon size. */ + public void setIntrinsicIconScaleFactor(float scale) { + mIntrinsicIconScale = scale; + } + + public float getIntrinsicIconScaleFactor() { + return mIntrinsicIconScale; + } + public float getOffsetY() { return mOffsetY; } diff --git a/src/com/android/launcher3/DrawableStateProxyView.java b/src/com/android/launcher3/DrawableStateProxyView.java index 0758de1f7..c83659ad5 100644 --- a/src/com/android/launcher3/DrawableStateProxyView.java +++ b/src/com/android/launcher3/DrawableStateProxyView.java @@ -23,8 +23,6 @@ import android.view.MotionEvent; import android.view.View; import android.widget.LinearLayout; -import com.android.launcher3.R; - public class DrawableStateProxyView extends LinearLayout { private View mView; diff --git a/src/com/android/launcher3/DynamicGrid.java b/src/com/android/launcher3/DynamicGrid.java index 6457fdc31..9be377e8e 100644 --- a/src/com/android/launcher3/DynamicGrid.java +++ b/src/com/android/launcher3/DynamicGrid.java @@ -16,495 +16,14 @@ package com.android.launcher3; -import android.appwidget.AppWidgetHostView; -import android.content.ComponentName; import android.content.Context; -import android.content.res.Configuration; import android.content.res.Resources; -import android.graphics.Paint; -import android.graphics.Paint.FontMetrics; -import android.graphics.PointF; -import android.graphics.Rect; import android.util.DisplayMetrics; import android.util.TypedValue; -import android.view.Gravity; -import android.view.View; -import android.view.ViewGroup.LayoutParams; -import android.widget.FrameLayout; -import android.widget.LinearLayout; import com.android.launcher3.settings.SettingsProvider; import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; - - -class DeviceProfileQuery { - float widthDps; - float heightDps; - float value; - PointF dimens; - - DeviceProfileQuery(float w, float h, float v) { - widthDps = w; - heightDps = h; - value = v; - dimens = new PointF(w, h); - } -} - -class DeviceProfile { - String name; - float minWidthDps; - float minHeightDps; - float numRows; - float numColumns; - float iconSize; - float iconTextSize; - float numHotseatIcons; - float hotseatIconSize; - - boolean isLandscape; - boolean isTablet; - boolean isLargeTablet; - boolean transposeLayoutWithOrientation; - - int desiredWorkspaceLeftRightMarginPx; - int edgeMarginPx; - Rect defaultWidgetPadding; - - int widthPx; - int heightPx; - int availableWidthPx; - int availableHeightPx; - int iconSizePx; - int iconTextSizePx; - int cellWidthPx; - int cellHeightPx; - int folderBackgroundOffset; - int folderIconSizePx; - int folderCellWidthPx; - int folderCellHeightPx; - int hotseatCellWidthPx; - int hotseatCellHeightPx; - int hotseatIconSizePx; - int hotseatBarHeightPx; - int hotseatAllAppsRank; - int allAppsNumRows; - int allAppsNumCols; - boolean searchBarVisible; - int searchBarSpaceWidthPx; - int searchBarSpaceMaxWidthPx; - int searchBarSpaceHeightPx; - int searchBarHeightPx; - int pageIndicatorHeightPx; - - DeviceProfile(String n, float w, float h, float r, float c, - float is, float its, float hs, float his) { - // Ensure that we have an odd number of hotseat items (since we need to place all apps) - if (!AppsCustomizePagedView.DISABLE_ALL_APPS && hs % 2 == 0) { - throw new RuntimeException("All Device Profiles must have an odd number of hotseat spaces"); - } - - name = n; - minWidthDps = w; - minHeightDps = h; - numRows = r; - numColumns = c; - iconSize = is; - iconTextSize = its; - numHotseatIcons = hs; - hotseatIconSize = his; - } - - DeviceProfile(Context context, - ArrayList<DeviceProfile> profiles, - float minWidth, float minHeight, - int wPx, int hPx, - int awPx, int ahPx, - Resources resources) { - DisplayMetrics dm = resources.getDisplayMetrics(); - ArrayList<DeviceProfileQuery> points = - new ArrayList<DeviceProfileQuery>(); - transposeLayoutWithOrientation = - resources.getBoolean(R.bool.hotseat_transpose_layout_with_orientation); - minWidthDps = minWidth; - minHeightDps = minHeight; - - ComponentName cn = new ComponentName(context.getPackageName(), - this.getClass().getName()); - defaultWidgetPadding = AppWidgetHostView.getDefaultPaddingForWidget(context, cn, null); - edgeMarginPx = resources.getDimensionPixelSize(R.dimen.dynamic_grid_edge_margin); - desiredWorkspaceLeftRightMarginPx = 2 * edgeMarginPx; - pageIndicatorHeightPx = resources.getDimensionPixelSize(R.dimen.dynamic_grid_page_indicator_height); - - // Interpolate the rows - for (DeviceProfile p : profiles) { - points.add(new DeviceProfileQuery(p.minWidthDps, p.minHeightDps, p.numRows)); - } - numRows = Math.round(invDistWeightedInterpolate(minWidth, minHeight, points)); - // Interpolate the columns - points.clear(); - for (DeviceProfile p : profiles) { - points.add(new DeviceProfileQuery(p.minWidthDps, p.minHeightDps, p.numColumns)); - } - numColumns = Math.round(invDistWeightedInterpolate(minWidth, minHeight, points)); - // Interpolate the icon size - points.clear(); - for (DeviceProfile p : profiles) { - points.add(new DeviceProfileQuery(p.minWidthDps, p.minHeightDps, p.iconSize)); - } - iconSize = invDistWeightedInterpolate(minWidth, minHeight, points); - iconSizePx = DynamicGrid.pxFromDp(iconSize, dm); - - // Interpolate the icon text size - points.clear(); - for (DeviceProfile p : profiles) { - points.add(new DeviceProfileQuery(p.minWidthDps, p.minHeightDps, p.iconTextSize)); - } - iconTextSize = invDistWeightedInterpolate(minWidth, minHeight, points); - iconTextSizePx = DynamicGrid.pxFromSp(iconTextSize, dm); - - // Interpolate the hotseat size - points.clear(); - for (DeviceProfile p : profiles) { - points.add(new DeviceProfileQuery(p.minWidthDps, p.minHeightDps, p.numHotseatIcons)); - } - numHotseatIcons = Math.round(invDistWeightedInterpolate(minWidth, minHeight, points)); - // Interpolate the hotseat icon size - points.clear(); - for (DeviceProfile p : profiles) { - points.add(new DeviceProfileQuery(p.minWidthDps, p.minHeightDps, p.hotseatIconSize)); - } - // Hotseat - hotseatIconSize = invDistWeightedInterpolate(minWidth, minHeight, points); - hotseatIconSizePx = DynamicGrid.pxFromDp(hotseatIconSize, dm); - hotseatAllAppsRank = (int) Math.ceil(numColumns / 2); - - // Calculate other vars based on Configuration - updateFromConfiguration(resources, wPx, hPx, awPx, ahPx); - - // Search Bar - searchBarVisible = SettingsProvider.getBoolean(context, SettingsProvider.SETTINGS_UI_HOMESCREEN_SEARCH, - R.bool.preferences_interface_homescreen_search_default); - searchBarSpaceMaxWidthPx = resources.getDimensionPixelSize(R.dimen.dynamic_grid_search_bar_max_width); - searchBarHeightPx = resources.getDimensionPixelSize(R.dimen.dynamic_grid_search_bar_height); - - searchBarSpaceHeightPx = searchBarHeightPx + (searchBarVisible ? 2 * edgeMarginPx : 0); - - // Calculate the actual text height - Paint textPaint = new Paint(); - textPaint.setTextSize(iconTextSizePx); - FontMetrics fm = textPaint.getFontMetrics(); - cellWidthPx = iconSizePx; - cellHeightPx = iconSizePx + (int) Math.ceil(fm.bottom - fm.top); - - // At this point, if the cells do not fit into the available height, then we need - // to shrink the icon size - /* - Rect padding = getWorkspacePadding(isLandscape ? - CellLayout.LANDSCAPE : CellLayout.PORTRAIT); - int h = (int) (numRows * cellHeightPx) + padding.top + padding.bottom; - if (h > availableHeightPx) { - float delta = h - availableHeightPx; - int deltaPx = (int) Math.ceil(delta / numRows); - iconSizePx -= deltaPx; - iconSize = DynamicGrid.dpiFromPx(iconSizePx, dm); - cellWidthPx = iconSizePx; - cellHeightPx = iconSizePx + (int) Math.ceil(fm.bottom - fm.top); - } - */ - - // Hotseat - hotseatBarHeightPx = iconSizePx + 4 * edgeMarginPx; - hotseatCellWidthPx = iconSizePx; - hotseatCellHeightPx = iconSizePx; - - // Folder - folderCellWidthPx = cellWidthPx + 3 * edgeMarginPx; - folderCellHeightPx = cellHeightPx + (int) ((3f/2f) * edgeMarginPx); - folderBackgroundOffset = -edgeMarginPx; - folderIconSizePx = iconSizePx + 2 * -folderBackgroundOffset; - } - - void updateFromConfiguration(Resources resources, int wPx, int hPx, - int awPx, int ahPx) { - isLandscape = (resources.getConfiguration().orientation == - Configuration.ORIENTATION_LANDSCAPE); - isTablet = resources.getBoolean(R.bool.is_tablet); - isLargeTablet = resources.getBoolean(R.bool.is_large_tablet); - widthPx = wPx; - heightPx = hPx; - availableWidthPx = awPx; - availableHeightPx = ahPx; - - Rect padding = getWorkspacePadding(isLandscape ? - CellLayout.LANDSCAPE : CellLayout.PORTRAIT); - int pageIndicatorOffset = - resources.getDimensionPixelSize(R.dimen.apps_customize_page_indicator_offset); - if (isLandscape) { - allAppsNumRows = (availableHeightPx - pageIndicatorOffset - 4 * edgeMarginPx) / - (iconSizePx + iconTextSizePx + 2 * edgeMarginPx); - } else { - allAppsNumRows = (int) numRows + 1; - } - allAppsNumCols = (availableWidthPx - padding.left - padding.right - 2 * edgeMarginPx) / - (iconSizePx + 2 * edgeMarginPx); - allAppsNumCols = (int) Math.min(numColumns, allAppsNumCols); - - if (isPhone()) { - searchBarSpaceWidthPx = Math.min(searchBarSpaceMaxWidthPx, widthPx); - } else { - searchBarSpaceWidthPx = wPx - (isLandscape ? 3 : 1) * iconSizePx; - } - } - - private float dist(PointF p0, PointF p1) { - return (float) Math.sqrt((p1.x - p0.x)*(p1.x-p0.x) + - (p1.y-p0.y)*(p1.y-p0.y)); - } - - private float weight(PointF a, PointF b, - float pow) { - float d = dist(a, b); - if (d == 0f) { - return Float.POSITIVE_INFINITY; - } - return (float) (1f / Math.pow(d, pow)); - } - - private float invDistWeightedInterpolate(float width, float height, - ArrayList<DeviceProfileQuery> points) { - float sum = 0; - float weights = 0; - float pow = 5; - float kNearestNeighbors = 3; - final PointF xy = new PointF(width, height); - - ArrayList<DeviceProfileQuery> pointsByNearness = points; - Collections.sort(pointsByNearness, new Comparator<DeviceProfileQuery>() { - public int compare(DeviceProfileQuery a, DeviceProfileQuery b) { - return (int) (dist(xy, a.dimens) - dist(xy, b.dimens)); - } - }); - - for (int i = 0; i < pointsByNearness.size(); ++i) { - DeviceProfileQuery p = pointsByNearness.get(i); - if (i < kNearestNeighbors) { - float w = weight(xy, p.dimens, pow); - if (w == Float.POSITIVE_INFINITY) { - return p.value; - } - weights += w; - } - } - - for (int i = 0; i < pointsByNearness.size(); ++i) { - DeviceProfileQuery p = pointsByNearness.get(i); - if (i < kNearestNeighbors) { - float w = weight(xy, p.dimens, pow); - sum += w * p.value / weights; - } - } - - return sum; - } - - Rect getWorkspacePadding(int orientation) { - Rect padding = new Rect(); - if (orientation == CellLayout.LANDSCAPE && - transposeLayoutWithOrientation) { - // Pad the left and right of the workspace with search/hotseat bar sizes - padding.set(searchBarVisible ? searchBarSpaceHeightPx : edgeMarginPx, edgeMarginPx, - hotseatBarHeightPx, edgeMarginPx); - } else { - if (isTablet()) { - // Pad the left and right of the workspace to ensure consistent spacing - // between all icons - int width = (orientation == CellLayout.LANDSCAPE) - ? Math.max(widthPx, heightPx) - : Math.min(widthPx, heightPx); - // XXX: If the icon size changes across orientations, we will have to take - // that into account here too. - int gap = (int) ((width - 2 * edgeMarginPx - - (numColumns * cellWidthPx)) / (2 * (numColumns + 1))); - padding.set(edgeMarginPx + gap, - searchBarVisible ? searchBarSpaceHeightPx : edgeMarginPx, - edgeMarginPx + gap, - hotseatBarHeightPx + pageIndicatorHeightPx); - } else { - // Pad the top and bottom of the workspace with search/hotseat bar sizes - padding.set(desiredWorkspaceLeftRightMarginPx - defaultWidgetPadding.left, - searchBarVisible ? searchBarSpaceHeightPx : edgeMarginPx, - desiredWorkspaceLeftRightMarginPx - defaultWidgetPadding.right, - hotseatBarHeightPx + pageIndicatorHeightPx); - } - } - return padding; - } - - // The rect returned will be extended to below the system ui that covers the workspace - Rect getHotseatRect() { - if (isVerticalBarLayout()) { - return new Rect(availableWidthPx - hotseatBarHeightPx, 0, - Integer.MAX_VALUE, availableHeightPx); - } else { - return new Rect(0, availableHeightPx - hotseatBarHeightPx, - availableWidthPx, Integer.MAX_VALUE); - } - } - - int calculateCellWidth(int width, int countX) { - return width / countX; - } - int calculateCellHeight(int height, int countY) { - return height / countY; - } - - boolean isPhone() { - return !isTablet && !isLargeTablet; - } - boolean isTablet() { - return isTablet; - } - boolean isLargeTablet() { - return isLargeTablet; - } - - boolean isVerticalBarLayout() { - return isLandscape && transposeLayoutWithOrientation; - } - - public void layout(Launcher launcher) { - FrameLayout.LayoutParams lp; - Resources res = launcher.getResources(); - boolean hasVerticalBarLayout = isVerticalBarLayout(); - - // Layout the search bar space - View searchBar = launcher.getSearchBar(); - lp = (FrameLayout.LayoutParams) searchBar.getLayoutParams(); - if (hasVerticalBarLayout) { - // Vertical search bar - lp.gravity = Gravity.TOP | Gravity.LEFT; - lp.width = searchBarSpaceHeightPx; - lp.height = LayoutParams.MATCH_PARENT; - searchBar.setPadding( - 0, 2 * edgeMarginPx, 0, - 2 * edgeMarginPx); - } else { - // Horizontal search bar - lp.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL; - lp.width = searchBarSpaceWidthPx; - lp.height = searchBarSpaceHeightPx; - searchBar.setPadding( - 2 * edgeMarginPx, - 2 * edgeMarginPx, - 2 * edgeMarginPx, 0); - } - searchBar.setLayoutParams(lp); - - // Layout the drop target icons - LinearLayout dropTargetBar = (LinearLayout) launcher.getSearchBar().getDropTargetBar(); - if (hasVerticalBarLayout) { - dropTargetBar.setOrientation(LinearLayout.VERTICAL); - } else { - dropTargetBar.setOrientation(LinearLayout.HORIZONTAL); - } - - // Layout the search bar - View qsbBar = launcher.getQsbBar(); - qsbBar.setVisibility(searchBarVisible ? View.VISIBLE : View.GONE); - LayoutParams vglp = qsbBar.getLayoutParams(); - vglp.width = LayoutParams.MATCH_PARENT; - vglp.height = LayoutParams.MATCH_PARENT; - qsbBar.setLayoutParams(vglp); - - // Layout the voice proxy - View voiceButtonProxy = launcher.findViewById(R.id.voice_button_proxy); - if (voiceButtonProxy != null) { - if (hasVerticalBarLayout) { - // TODO: MOVE THIS INTO SEARCH BAR MEASURE - } else { - lp = (FrameLayout.LayoutParams) voiceButtonProxy.getLayoutParams(); - lp.gravity = Gravity.TOP | Gravity.END; - lp.width = (widthPx - searchBarSpaceWidthPx) / 2 + - 2 * iconSizePx; - lp.height = searchBarSpaceHeightPx; - } - } - - // Layout the workspace - View workspace = launcher.findViewById(R.id.workspace); - lp = (FrameLayout.LayoutParams) workspace.getLayoutParams(); - lp.gravity = Gravity.CENTER; - Rect padding = getWorkspacePadding(isLandscape - ? CellLayout.LANDSCAPE - : CellLayout.PORTRAIT); - workspace.setPadding(padding.left, padding.top, - padding.right, padding.bottom); - workspace.setLayoutParams(lp); - - // Layout the hotseat - View hotseat = launcher.findViewById(R.id.hotseat); - lp = (FrameLayout.LayoutParams) hotseat.getLayoutParams(); - if (hasVerticalBarLayout) { - // Vertical hotseat - lp.gravity = Gravity.RIGHT; - lp.width = hotseatBarHeightPx; - lp.height = LayoutParams.MATCH_PARENT; - hotseat.setPadding(0, 2 * edgeMarginPx, - 2 * edgeMarginPx, 2 * edgeMarginPx); - } else if (isTablet()) { - // Pad the hotseat with the grid gap calculated above - int gridGap = (int) ((widthPx - 2 * edgeMarginPx - - (numColumns * cellWidthPx)) / (2 * (numColumns + 1))); - int gridWidth = (int) ((numColumns * cellWidthPx) + - ((numColumns - 1) * gridGap)); - int hotseatGap = (int) Math.max(0, - (gridWidth - (numHotseatIcons * hotseatCellWidthPx)) - / (numHotseatIcons - 1)); - lp.gravity = Gravity.BOTTOM; - lp.width = LayoutParams.MATCH_PARENT; - lp.height = hotseatBarHeightPx; - hotseat.setPadding(2 * edgeMarginPx + gridGap + hotseatGap, 0, - 2 * edgeMarginPx + gridGap + hotseatGap, - 2 * edgeMarginPx); - } else { - // For phones, layout the hotseat without any bottom margin - // to ensure that we have space for the folders - lp.gravity = Gravity.BOTTOM; - lp.width = LayoutParams.MATCH_PARENT; - lp.height = hotseatBarHeightPx; - hotseat.findViewById(R.id.layout).setPadding(2 * edgeMarginPx, 0, - 2 * edgeMarginPx, 0); - } - hotseat.setLayoutParams(lp); - - // Layout the page indicators - View pageIndicator = launcher.findViewById(R.id.page_indicator); - if (pageIndicator != null) { - if (hasVerticalBarLayout) { - // Hide the page indicators when we have vertical search/hotseat - pageIndicator.setVisibility(View.GONE); - } else { - // Put the page indicators above the hotseat - lp = (FrameLayout.LayoutParams) pageIndicator.getLayoutParams(); - lp.gravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; - lp.width = LayoutParams.WRAP_CONTENT; - lp.height = LayoutParams.WRAP_CONTENT; - lp.bottomMargin = hotseatBarHeightPx; - pageIndicator.setLayoutParams(lp); - } - } - - // Layout the apps customize - View appsCustomize = launcher.findViewById(R.id.apps_customize_pane_content); - lp = (FrameLayout.LayoutParams) appsCustomize.getLayoutParams(); - lp.gravity = Gravity.CENTER; - appsCustomize.setLayoutParams(lp); - } -} public class DynamicGrid { @SuppressWarnings("unused") @@ -514,6 +33,10 @@ public class DynamicGrid { private float mMinWidth; private float mMinHeight; + // This is a static that we use for the default icon size on a 4/5-inch phone + static float DEFAULT_ICON_SIZE_DP = 60; + static float DEFAULT_ICON_SIZE_PX = 0; + public static float dpiFromPx(int size, DisplayMetrics metrics){ float densityRatio = (float) metrics.densityDpi / DisplayMetrics.DENSITY_DEFAULT; return (size / densityRatio); @@ -534,29 +57,34 @@ public class DynamicGrid { DisplayMetrics dm = resources.getDisplayMetrics(); ArrayList<DeviceProfile> deviceProfiles = new ArrayList<DeviceProfile>(); - boolean hasAA = !AppsCustomizePagedView.DISABLE_ALL_APPS; + boolean hasAA = !LauncherAppState.isDisableAllApps(); boolean useLargeIcons = SettingsProvider.getBoolean(context, SettingsProvider.SETTINGS_UI_GENERAL_ICONS_LARGE, R.bool.preferences_interface_general_icons_large_default); + DEFAULT_ICON_SIZE_PX = pxFromDp(DEFAULT_ICON_SIZE_DP, dm); // Our phone profiles include the bar sizes in each orientation deviceProfiles.add(new DeviceProfile("Super Short Stubby", - 255, 300, 2, 3, (useLargeIcons ? 54 : 48), 13, (hasAA ? 5 : 4), (useLargeIcons ? 54 : 48))); + 255, 300, 2, 3, (useLargeIcons ? 54 : 48), 13, (hasAA ? 5 : 5), (useLargeIcons ? 54 : 48))); deviceProfiles.add(new DeviceProfile("Shorter Stubby", - 255, 400, 3, 3, (useLargeIcons ? 54 : 48), 13, (hasAA ? 5 : 4), (useLargeIcons ? 54 : 48))); + 255, 400, 3, 3, (useLargeIcons ? 54 : 48), 13, (hasAA ? 5 : 5), (useLargeIcons ? 54 : 48))); deviceProfiles.add(new DeviceProfile("Short Stubby", - 275, 420, 3, 4, (useLargeIcons ? 54 : 48), 13, (hasAA ? 5 : 4), (useLargeIcons ? 54 : 48))); + 275, 420, 3, 4, (useLargeIcons ? 54 : 48), 13, (hasAA ? 5 : 5), (useLargeIcons ? 54 : 48))); deviceProfiles.add(new DeviceProfile("Stubby", - 255, 450, 3, 4, (useLargeIcons ? 54 : 48), 13, (hasAA ? 5 : 4), (useLargeIcons ? 54 : 48))); - deviceProfiles.add(new DeviceProfile("Nexus S", - 296, 491.33f, 4, 4, (useLargeIcons ? 56 : 48), 13, (hasAA ? 5 : 4), (useLargeIcons ? 56 : 48))); + 255, 450, 3, 4, (useLargeIcons ? 54 : 48), 13, (hasAA ? 5 : 5), (useLargeIcons ? 54 : 48))); + deviceProfiles.add(new DeviceProfile("Nexus 5", + 359, 567, 4, 4, (useLargeIcons ? DEFAULT_ICON_SIZE_DP : 56), 13, (hasAA ? 5 : 5), 56)); deviceProfiles.add(new DeviceProfile("Nexus 4", - 359, 518, 4, 4, (useLargeIcons ? 60 : 52), 13, (hasAA ? 5 : 4), (useLargeIcons ? 56 : 48))); + 359, 518, 4, 4, (useLargeIcons ? DEFAULT_ICON_SIZE_DP : 52), 13, (hasAA ? 5 : 5), (useLargeIcons ? 56 : 48))); + deviceProfiles.add(new DeviceProfile("Large Phone", + 335, 567, 4, 4, (useLargeIcons ? DEFAULT_ICON_SIZE_DP : 56), 13, (hasAA ? 5 : 5), 56)); + deviceProfiles.add(new DeviceProfile("Large Phone", + 406, 694, 5, 5, (useLargeIcons ? 64 : 56), 14.4f, 5, 56)); // The tablet profile is odd in that the landscape orientation // also includes the nav bar on the side deviceProfiles.add(new DeviceProfile("Nexus 7", 575, 904, 5, 5, (useLargeIcons ? 72 : 60), 14.4f, 7, (useLargeIcons ? 60 : 52))); // Larger tablet profiles always have system bars on the top & bottom deviceProfiles.add(new DeviceProfile("Nexus 10", - 727, 1207, 5, 8, (useLargeIcons ? 80 : 64), 14.4f, 9, (useLargeIcons ? 64 : 56))); + 727, 1207, 5, 8, (useLargeIcons ? 76 : 64), 14.4f, 9, (useLargeIcons ? 64 : 56))); /* deviceProfiles.add(new DeviceProfile("Nexus 7", 600, 960, 5, 5, 72, 14.4f, 5, 60)); @@ -574,7 +102,7 @@ public class DynamicGrid { resources); } - DeviceProfile getDeviceProfile() { + public DeviceProfile getDeviceProfile() { return mProfile; } @@ -583,7 +111,7 @@ public class DynamicGrid { "Wd: " + mProfile.minWidthDps + ", Hd: " + mProfile.minHeightDps + ", W: " + mProfile.widthPx + ", H: " + mProfile.heightPx + " [r: " + mProfile.numRows + ", c: " + mProfile.numColumns + - ", is: " + mProfile.iconSizePx + ", its: " + mProfile.iconTextSize + + ", is: " + mProfile.iconSizePx + ", its: " + mProfile.iconTextSizePx + ", cw: " + mProfile.cellWidthPx + ", ch: " + mProfile.cellHeightPx + ", hc: " + mProfile.numHotseatIcons + ", his: " + mProfile.hotseatIconSizePx + "]"; } diff --git a/src/com/android/launcher3/DynamicGridSizeFragment.java b/src/com/android/launcher3/DynamicGridSizeFragment.java new file mode 100644 index 000000000..586c2bd49 --- /dev/null +++ b/src/com/android/launcher3/DynamicGridSizeFragment.java @@ -0,0 +1,331 @@ +package com.android.launcher3; + +import android.animation.Animator; +import android.animation.ObjectAnimator; +import android.app.Dialog; +import android.app.Fragment; +import android.content.Context; +import android.content.DialogInterface; +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.util.DisplayMetrics; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.NumberPicker; +import android.widget.TextView; +import com.android.launcher3.settings.SettingsProvider; + +public class DynamicGridSizeFragment extends Fragment implements NumberPicker.OnValueChangeListener, Dialog.OnDismissListener{ + public static final String DYNAMIC_GRID_SIZE_FRAGMENT = "dynamicGridSizeFragment"; + public static final int MIN_DYNAMIC_GRID_ROWS = 2; + public static final int MIN_DYNAMIC_GRID_COLUMNS = 3; + ImageView mDynamicGridImage; + ListView mListView; + View mCurrentSelection; + GridSizeArrayAdapter mAdapter; + DeviceProfile.GridSize mCurrentSize; + + Dialog mDialog; + + int mCustomGridRows = 0; + int mCustomGridColumns = 0; + + View.OnClickListener mSettingsItemListener = new View.OnClickListener() { + + @Override + public void onClick(View v) { + mCurrentSize = DeviceProfile.GridSize + .getModeForValue((Integer) v.getTag()); + + setCleared(mCurrentSelection); + setSelected(v); + mCurrentSelection = v; + + if (mCurrentSize == DeviceProfile.GridSize.Custom) { + showNumberPicker(); + } + + ((GridSizeArrayAdapter) mListView.getAdapter()).notifyDataSetChanged(); + + mAdapter.notifyDataSetInvalidated(); + setCurrentImage(); + } + }; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View v = inflater.inflate(R.layout.dynamic_grid_size_screen, container, false); + mDynamicGridImage = (ImageView) v.findViewById(R.id.dynamic_grid_size_image); + mDynamicGridImage.setBackground(getResources().getDrawable(R.drawable.grid)); + + LinearLayout titleLayout = (LinearLayout) v.findViewById(R.id.dynamic_grid_title); + titleLayout.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + setSize(); + } + }); + + mCurrentSize = DeviceProfile.GridSize.getModeForValue( + SettingsProvider.getIntCustomDefault(getActivity(), + SettingsProvider.SETTINGS_UI_DYNAMIC_GRID_SIZE, 0)); + + setCurrentImage(); + + mListView = (ListView) v.findViewById(R.id.dynamic_grid_list); + Resources res = getResources(); + String [] values = { + res.getString(R.string.grid_size_comfortable), + res.getString(R.string.grid_size_cozy), + res.getString(R.string.grid_size_condensed), + res.getString(R.string.grid_size_custom)}; + mAdapter = new GridSizeArrayAdapter(getActivity(), + R.layout.settings_pane_list_item, values); + mListView.setAdapter(mAdapter); + + return v; + } + + private void setCurrentImage() { + Drawable d = null; + boolean custom = false; + + switch (mCurrentSize) { + case Comfortable: + d = getResources().getDrawable(R.drawable.grid_comfortable); + break; + case Cozy: + d = getResources().getDrawable(R.drawable.grid_cozy); + break; + case Condensed: + d = getResources().getDrawable(R.drawable.grid_condensed); + break; + default: + + custom = true; + break; + } + + if (d != null && !custom) { + mDynamicGridImage.setImageBitmap(null); + mDynamicGridImage.setBackground(d); + } else if (custom) { + mDynamicGridImage.setBackground(null); + mDynamicGridImage.setImageBitmap(writeOnDrawable(R.drawable.grid)); + } + } + + public Bitmap writeOnDrawable(int drawableId){ + LauncherAppState app = LauncherAppState.getInstance(); + DeviceProfile grid = app.getDynamicGrid().getDeviceProfile(); + + int rows = mCustomGridRows == 0 ? (int) grid.numRows : mCustomGridRows; + int columns = mCustomGridColumns == 0 ? (int) grid.numColumns : mCustomGridColumns; + + String text = rows + " " + "\u00d7" + " " + columns; + + Bitmap bm = BitmapFactory.decodeResource(getResources(), + drawableId).copy(Bitmap.Config.ARGB_8888, true); + + Paint paint = new Paint(); + paint.setStyle(Paint.Style.FILL); + paint.setColor(Color.BLACK); + int px = getResources().getDimensionPixelOffset(R.dimen.grid_custom_text); + paint.setTextSize(px); + + Canvas canvas = new Canvas(bm); + + float canvasWidth = canvas.getWidth(); + float sentenceWidth = paint.measureText(text); + float startPositionX = (canvasWidth - sentenceWidth) / 2; + + canvas.drawText(text, startPositionX, bm.getHeight()/2, paint); + + return bm; + } + + @Override + public Animator onCreateAnimator(int transit, boolean enter, int nextAnim) { + if (enter) { + DisplayMetrics displaymetrics = new DisplayMetrics(); + getActivity().getWindowManager().getDefaultDisplay().getMetrics(displaymetrics); + int width = displaymetrics.widthPixels; + final ObjectAnimator anim = ObjectAnimator.ofFloat(this, "translationX", width, 0); + + final View darkPanel = ((Launcher) getActivity()).getDarkPanel(); + darkPanel.setVisibility(View.VISIBLE); + ObjectAnimator anim2 = ObjectAnimator.ofFloat( + darkPanel , "alpha", 0.0f, 0.3f); + anim2.start(); + + anim.addListener(new Animator.AnimatorListener() { + @Override + public void onAnimationStart(Animator arg0) {} + @Override + public void onAnimationRepeat(Animator arg0) {} + @Override + public void onAnimationEnd(Animator arg0) { + darkPanel.setVisibility(View.GONE); + } + @Override + public void onAnimationCancel(Animator arg0) {} + }); + + return anim; + } else { + return super.onCreateAnimator(transit, enter, nextAnim); + } + } + + public void setSize() { + ((Launcher) getActivity()).setDynamicGridSize(mCurrentSize); + } + + private void setSelected(View v) { + v.setBackgroundColor(Color.WHITE); + TextView t = (TextView) v.findViewById(R.id.item_name); + t.setTextColor(getResources().getColor(R.color.settings_bg_color)); + } + + private void setCleared(View v) { + v.setBackgroundColor(getResources().getColor(R.color.settings_bg_color)); + TextView t = (TextView) v.findViewById(R.id.item_name); + t.setTextColor(Color.WHITE); + } + + private void showNumberPicker() { + mDialog = new Dialog(getActivity()); + mDialog.setTitle(getResources().getString(R.string.preferences_interface_homescreen_custom)); + mDialog.setContentView(R.layout.custom_grid_size_dialog); + + NumberPicker nPRows= (NumberPicker) mDialog.findViewById(R.id.custom_rows); + NumberPicker nPColumns = (NumberPicker) mDialog.findViewById(R.id.custom_columns); + + LauncherAppState app = LauncherAppState.getInstance(); + DeviceProfile grid = app.getDynamicGrid().getDeviceProfile(); + + int rows = grid.numRowsBase; + int columns = grid.numColumnsBase; + if (mCustomGridColumns == 0) { + mCustomGridColumns = (int) grid.numColumns; + } + if (mCustomGridRows == 0) { + mCustomGridRows = (int) grid.numRows; + } + + nPRows.setMinValue(Math.max(MIN_DYNAMIC_GRID_ROWS, rows - DeviceProfile.GRID_SIZE_MIN)); + nPRows.setMaxValue(rows + DeviceProfile.GRID_SIZE_MAX); + nPRows.setValue(mCustomGridRows); + nPRows.setWrapSelectorWheel(false); + nPRows.setOnValueChangedListener(this); + nPRows.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS); + + nPColumns.setMinValue(Math.max(MIN_DYNAMIC_GRID_COLUMNS, columns - DeviceProfile.GRID_SIZE_MIN)); + nPColumns.setMaxValue(columns + DeviceProfile.GRID_SIZE_MAX); + nPColumns.setValue(mCustomGridColumns); + nPColumns.setWrapSelectorWheel(false); + nPColumns.setOnValueChangedListener(this); + nPColumns.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS); + + Button b = (Button) mDialog.findViewById(R.id.dialog_confirm_button); + b.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (mDialog != null) { + mDialog.dismiss(); + } + } + }); + mDialog.setOnDismissListener(this); + mDialog.show(); + } + + @Override + public void onPause() { + super.onPause(); + if (mDialog != null) { + mDialog.dismiss(); + } + } + + @Override + public void onValueChange(NumberPicker picker, int oldVal, int newVal) { + if (picker.getId() == R.id.custom_rows) { + mCustomGridRows = newVal; + } else if (picker.getId() == R.id.custom_columns) { + mCustomGridColumns = newVal; + } + } + + @Override + public void onDismiss(DialogInterface dialog) { + SettingsProvider.putInt(getActivity(), + SettingsProvider.SETTINGS_UI_HOMESCREEN_ROWS, mCustomGridRows); + SettingsProvider.putInt(getActivity(), + SettingsProvider.SETTINGS_UI_HOMESCREEN_COLUMNS, mCustomGridColumns); + + mAdapter.notifyDataSetInvalidated(); + + setCurrentImage(); + } + + private class GridSizeArrayAdapter extends ArrayAdapter<String> { + Context mContext; + String[] mTitles; + + public GridSizeArrayAdapter(Context context, int textViewResourceId, + String[] objects) { + super(context, textViewResourceId, objects); + + mContext = context; + mTitles = objects; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + LayoutInflater inflater = (LayoutInflater) mContext + .getSystemService(Context.LAYOUT_INFLATER_SERVICE); + convertView = inflater.inflate(R.layout.settings_pane_list_item, + parent, false); + TextView textView = (TextView) convertView + .findViewById(R.id.item_name); + textView.setText(mTitles[position]); + // Set Selected State + if (position == mCurrentSize.getValue()) { + mCurrentSelection = convertView; + setSelected(mCurrentSelection); + } + + if (position == DeviceProfile.GridSize.Custom.getValue()) { + LauncherAppState app = LauncherAppState.getInstance(); + DeviceProfile grid = app.getDynamicGrid().getDeviceProfile(); + + String state = mTitles[position]; + int rows = SettingsProvider.getIntCustomDefault(getActivity(), + SettingsProvider.SETTINGS_UI_HOMESCREEN_ROWS, grid.numRowsBase); + int columns = SettingsProvider.getIntCustomDefault(getActivity(), + SettingsProvider.SETTINGS_UI_HOMESCREEN_COLUMNS, grid.numColumnsBase); + state += " " + "(" + rows + " " + "\u00d7" + " " + columns + ")"; + + textView.setText(state); + } + + convertView.setOnClickListener(mSettingsItemListener); + convertView.setTag(position); + return convertView; + } + } +} diff --git a/src/com/android/launcher3/FastBitmapDrawable.java b/src/com/android/launcher3/FastBitmapDrawable.java index 8061c619d..847a8e1bc 100644 --- a/src/com/android/launcher3/FastBitmapDrawable.java +++ b/src/com/android/launcher3/FastBitmapDrawable.java @@ -35,8 +35,7 @@ class FastBitmapDrawable extends Drawable { mAlpha = 255; mBitmap = b; if (b != null) { - mWidth = mBitmap.getWidth(); - mHeight = mBitmap.getHeight(); + setBounds(0, 0, b.getWidth(), b.getHeight()); } else { mWidth = mHeight = 0; } @@ -67,6 +66,7 @@ class FastBitmapDrawable extends Drawable { public void setFilterBitmap(boolean filterBitmap) { mPaint.setFilterBitmap(filterBitmap); + mPaint.setAntiAlias(filterBitmap); } public int getAlpha() { @@ -75,32 +75,30 @@ class FastBitmapDrawable extends Drawable { @Override public int getIntrinsicWidth() { - return mWidth; + int width = getBounds().width(); + if (width == 0) { + width = mBitmap.getWidth(); + } + return width; } @Override public int getIntrinsicHeight() { - return mHeight; + int height = getBounds().height(); + if (height == 0) { + height = mBitmap.getHeight(); + } + return height; } @Override public int getMinimumWidth() { - return mWidth; + return getBounds().width(); } @Override public int getMinimumHeight() { - return mHeight; - } - - public void setBitmap(Bitmap b) { - mBitmap = b; - if (b != null) { - mWidth = mBitmap.getWidth(); - mHeight = mBitmap.getHeight(); - } else { - mWidth = mHeight = 0; - } + return getBounds().height(); } public Bitmap getBitmap() { diff --git a/src/com/android/launcher3/FirstFrameAnimatorHelper.java b/src/com/android/launcher3/FirstFrameAnimatorHelper.java index 78fdadd4f..f4c49d77a 100644 --- a/src/com/android/launcher3/FirstFrameAnimatorHelper.java +++ b/src/com/android/launcher3/FirstFrameAnimatorHelper.java @@ -91,29 +91,30 @@ public class FirstFrameAnimatorHelper extends AnimatorListenerAdapter mStartTime = currentTime; } + final long currentPlayTime = animation.getCurrentPlayTime(); if (!mHandlingOnAnimationUpdate && sVisible && // If the current play time exceeds the duration, the animation // will get finished, even if we call setCurrentPlayTime -- therefore // don't adjust the animation in that case - animation.getCurrentPlayTime() < animation.getDuration()) { + currentPlayTime < animation.getDuration()) { mHandlingOnAnimationUpdate = true; long frameNum = sGlobalFrameCounter - mStartFrame; // If we haven't drawn our first frame, reset the time to t = 0 // (give up after MAX_DELAY ms of waiting though - might happen, for example, if we // are no longer in the foreground and no frames are being rendered ever) - if (frameNum == 0 && currentTime < mStartTime + MAX_DELAY) { + if (frameNum == 0 && currentTime < mStartTime + MAX_DELAY && currentPlayTime > 0) { // The first frame on animations doesn't always trigger an invalidate... // force an invalidate here to make sure the animation continues to advance mTarget.getRootView().invalidate(); animation.setCurrentPlayTime(0); - // For the second frame, if the first frame took more than 16ms, // adjust the start time and pretend it took only 16ms anyway. This // prevents a large jump in the animation due to an expensive first frame } else if (frameNum == 1 && currentTime < mStartTime + MAX_DELAY && !mAdjustedSecondFrameTime && - currentTime > mStartTime + IDEAL_FRAME_DURATION) { + currentTime > mStartTime + IDEAL_FRAME_DURATION && + currentPlayTime > IDEAL_FRAME_DURATION) { animation.setCurrentPlayTime(IDEAL_FRAME_DURATION); mAdjustedSecondFrameTime = true; } else { diff --git a/src/com/android/launcher3/FocusHelper.java b/src/com/android/launcher3/FocusHelper.java index 357af49f6..b92b17f22 100644 --- a/src/com/android/launcher3/FocusHelper.java +++ b/src/com/android/launcher3/FocusHelper.java @@ -548,7 +548,7 @@ public class FocusHelper { final CellLayout layout = (CellLayout) parent.getParent(); final Workspace workspace = (Workspace) layout.getParent(); final ViewGroup launcher = (ViewGroup) workspace.getParent(); - final ViewGroup tabs = (ViewGroup) launcher.findViewById(R.id.qsb_bar); + final ViewGroup tabs = (ViewGroup) launcher.findViewById(R.id.search_drop_target_bar); final ViewGroup hotseat = (ViewGroup) launcher.findViewById(R.id.hotseat); int pageIndex = workspace.indexOfChild(layout); int pageCount = workspace.getChildCount(); diff --git a/src/com/android/launcher3/Folder.java b/src/com/android/launcher3/Folder.java index a00f3c1da..71183c342 100644 --- a/src/com/android/launcher3/Folder.java +++ b/src/com/android/launcher3/Folder.java @@ -20,11 +20,13 @@ import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ObjectAnimator; import android.animation.PropertyValuesHolder; +import android.content.ComponentName; import android.content.Context; +import android.content.Intent; import android.content.res.Resources; import android.graphics.PointF; import android.graphics.Rect; -import android.graphics.drawable.Drawable; +import android.os.Bundle; import android.os.SystemClock; import android.support.v4.widget.AutoScrollHelper; import android.text.InputType; @@ -43,7 +45,9 @@ import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputMethodManager; +import android.widget.ImageView; import android.widget.LinearLayout; +import android.widget.RelativeLayout; import android.widget.ScrollView; import android.widget.TextView; @@ -62,6 +66,12 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList View.OnFocusChangeListener { private static final String TAG = "Launcher.Folder"; + private static final String PROTECTED_ACTION = "cyanogenmod.intent.action.PACKAGE_PROTECTED"; + private static final String PROTECTED_STATE = + "cyanogenmod.intent.action.PACKAGE_PROTECTED_STATE"; + private static final String PROTECTED_COMPONENT = + "cyanogenmod.intent.action.PACKAGE_PROTECTED_COMPONENT"; + protected DragController mDragController; protected Launcher mLauncher; protected FolderInfo mInfo; @@ -71,6 +81,8 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList static final int STATE_ANIMATING = 1; static final int STATE_OPEN = 2; + private static final int CLOSE_FOLDER_DELAY_MS = 150; + private int mExpandDuration; protected CellLayout mContent; private ScrollView mScrollView; @@ -79,17 +91,17 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList private int mState = STATE_NONE; private static final int REORDER_ANIMATION_DURATION = 230; private static final int REORDER_DELAY = 250; - private static final int ON_EXIT_CLOSE_DELAY = 800; + private static final int ON_EXIT_CLOSE_DELAY = 400; private boolean mRearrangeOnClose = false; private FolderIcon mFolderIcon; private int mMaxCountX; private int mMaxCountY; private int mMaxNumItems; private ArrayList<View> mItemsInReadingOrder = new ArrayList<View>(); - private Drawable mIconDrawable; boolean mItemsInvalidated = false; private ShortcutInfo mCurrentDragInfo; private View mCurrentDragView; + private boolean mIsExternalDrag; boolean mSuppressOnAdd = false; private int[] mTargetCell = new int[2]; private int[] mPreviousTargetCell = new int[2]; @@ -103,6 +115,8 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList private boolean mSuppressFolderDeletion = false; private boolean mItemAddedBackToSelfViaIcon = false; FolderEditText mFolderName; + ImageView mFolderLock; + RelativeLayout mFolderTitleSection; private float mFolderIconPivotX; private float mFolderIconPivotY; @@ -116,6 +130,11 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList private int DRAG_MODE_REORDER = 1; private int mDragMode = DRAG_MODE_NONE; + // We avoid measuring the scroll view with a 0 width or height, as this + // results in CellLayout being measured as UNSPECIFIED, which it does + // not support. + private static final int MIN_CONTENT_DIMEN = 5; + private boolean mDestroyed; private AutoScrollHelper mAutoScrollHelper; @@ -124,6 +143,8 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList private boolean mDeferDropAfterUninstall; private boolean mUninstallSuccessful; + private boolean mHiddenFolder = false; + /** * Used to inflate the Workspace from XML. * @@ -141,8 +162,13 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList Resources res = getResources(); mMaxCountX = (int) grid.numColumns; - mMaxCountY = (int) grid.numRows; - mMaxNumItems = mMaxCountX * mMaxCountY; + // Allow scrolling folders when DISABLE_ALL_APPS is true. + if (LauncherAppState.isDisableAllApps()) { + mMaxCountY = mMaxNumItems = Integer.MAX_VALUE; + } else { + mMaxCountY = (int) grid.numRows; + mMaxNumItems = mMaxCountX * mMaxCountY; + } mInputMethodManager = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE); @@ -167,6 +193,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList super.onFinishInflate(); mScrollView = (ScrollView) findViewById(R.id.scroll_view); mContent = (CellLayout) findViewById(R.id.folder_content); + int measureSpec = MeasureSpec.UNSPECIFIED; LauncherAppState app = LauncherAppState.getInstance(); DeviceProfile grid = app.getDynamicGrid().getDeviceProfile(); @@ -181,7 +208,6 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList // We find out how tall the text view wants to be (it is set to wrap_content), so that // we can allocate the appropriate amount of space for it. - int measureSpec = MeasureSpec.UNSPECIFIED; mFolderName.measure(measureSpec, measureSpec); mFolderNameHeight = mFolderName.getMeasuredHeight(); @@ -199,6 +225,12 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList mFolderName.setVisibility(View.GONE); mFolderNameHeight = getPaddingBottom(); } + + mFolderLock = (ImageView) findViewById(R.id.folder_lock); + mFolderTitleSection = (RelativeLayout) findViewById(R.id.folder_title_section); + mFolderLock.measure(measureSpec, measureSpec); + mFolderLock.setOnClickListener(this); + mFolderTitleSection.measure(measureSpec, measureSpec); } private ActionMode.Callback mActionModeCallback = new ActionMode.Callback() { @@ -223,6 +255,60 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList if (tag instanceof ShortcutInfo) { mLauncher.onClick(v); } + + if (v.getId() == R.id.folder_lock) { + startHiddenFolderManager(); + } + } + + public void startHiddenFolderManager() { + Bundle bundle = new Bundle(); + bundle.putBoolean(HiddenFolderFragment.HIDDEN_FOLDER_STATUS, mInfo.hidden); + mLauncher.validateLockForHiddenFolders(bundle, mFolderIcon); + } + + public String[] getComponentTitles() { + int size = mItemsInReadingOrder.size(); + String[] componentsTitles = new String[size]; + for (int i = 0; i < size; i++) { + View v = mItemsInReadingOrder.get(i); + Object tag = v.getTag(); + if (tag instanceof ShortcutInfo) { + componentsTitles[i] = ((ShortcutInfo) tag).title.toString(); + } + } + return componentsTitles; + } + + public String[] getComponents() { + String components = getComponentString(); + return components.split("\\|"); + } + + public void modifyProtectedApps(boolean protect) { + String components = getComponentString(); + + Intent intent = new Intent(); + intent.setAction(PROTECTED_ACTION); + intent.putExtra(PROTECTED_STATE, protect); + intent.putExtra(PROTECTED_COMPONENT, components); + + mLauncher.sendBroadcast(intent); + } + + private String getComponentString() { + int size = mItemsInReadingOrder.size(); + String components = ""; + for (int i = 0; i < size; i++) { + View v = mItemsInReadingOrder.get(i); + Object tag = v.getTag(); + if (tag instanceof ShortcutInfo) { + ComponentName componentName = ((ShortcutInfo) tag).getIntent().getComponent(); + components += componentName.flattenToString() + "|"; + } + } + + return components; } public boolean onLongClick(View v) { @@ -236,11 +322,10 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList return false; } - mLauncher.dismissFolderCling(null); + mLauncher.getLauncherClings().dismissFolderCling(null); mLauncher.getWorkspace().onDragStartedWithItem(v); mLauncher.getWorkspace().beginDragShared(v, this); - mIconDrawable = ((TextView) v).getCompoundDrawables()[1]; mCurrentDragInfo = item; mEmptyCell[0] = item.cellX; @@ -262,6 +347,8 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList public void startEditingFolderName() { mFolderName.setHint(""); mIsEditingName = true; + + mInputMethodManager.showSoftInput(mFolderName, 0); } public void dismissEditingName() { @@ -305,10 +392,6 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList return mFolderName; } - public Drawable getDragDrawable() { - return mIconDrawable; - } - /** * We need to handle touch events to prevent them from falling through to the workspace below. */ @@ -383,7 +466,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList int count = 0; for (int i = 0; i < children.size(); i++) { ShortcutInfo child = (ShortcutInfo) children.get(i); - if (!createAndAddShortcut(child)) { + if (createAndAddShortcut(child) == null) { overflow.add(child); } else { count++; @@ -405,12 +488,26 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList updateTextViewFocus(); mInfo.addListener(this); + setFolderName(); + updateItemLocationsInDatabase(); + } + + public void setFolderName() { if (!sDefaultFolderName.contentEquals(mInfo.title)) { mFolderName.setText(mInfo.title); } else { mFolderName.setText(""); } updateItemLocationsInDatabase(); + + // In case any children didn't come across during loading, clean up the folder accordingly + mFolderIcon.post(new Runnable() { + public void run() { + if (getItemCount() <= 1) { + replaceFolderWithFinalItem(); + } + } + }); } /** @@ -459,11 +556,15 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList public void onAnimationEnd(Animator animation) { mState = STATE_OPEN; setLayerType(LAYER_TYPE_NONE, null); - Cling cling = mLauncher.showFirstRunFoldersCling(); - if (cling != null) { - cling.bringScrimToFront(); - bringToFront(); - cling.bringToFront(); + + // Only show cling if we are not in the middle of a drag - this would be quite jarring. + if (!mDragController.isDragging()) { + Cling cling = mLauncher.getLauncherClings().showFoldersCling(); + if (cling != null) { + cling.bringScrimToFront(); + bringToFront(); + cling.bringToFront(); + } } setFocusOnFirstChild(); } @@ -471,6 +572,23 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList oa.setDuration(mExpandDuration); setLayerType(LAYER_TYPE_HARDWARE, null); oa.start(); + + // Make sure the folder picks up the last drag move even if the finger doesn't move. + if (mDragController.isDragging()) { + mDragController.forceTouchMove(); + } + } + + public void beginExternalDrag(ShortcutInfo item) { + setupContentForNumItems(getItemCount() + 1); + findAndSetEmptyCells(item); + + mCurrentDragInfo = item; + mEmptyCell[0] = item.cellX; + mEmptyCell[1] = item.cellY; + mIsExternalDrag = true; + + mDragInProgress = true; } private void sendCustomAccessibilityEvent(int type, String text) { @@ -537,7 +655,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList } } - protected boolean createAndAddShortcut(ShortcutInfo item) { + protected View createAndAddShortcut(ShortcutInfo item) { final BubbleTextView textView = (BubbleTextView) mInflater.inflate(R.layout.application, this, false); textView.setCompoundDrawables(null, @@ -546,7 +664,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList textView.setTag(item); textView.setTextColor(getResources().getColor(R.color.folder_items_text_color)); textView.setShadowsEnabled(false); - Utilities.applyTypeface(textView); + textView.setGlowColor(getResources().getColor(R.color.folder_items_glow_color)); textView.setOnClickListener(this); textView.setOnLongClickListener(this); @@ -558,7 +676,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList // This shouldn't happen, log it. Log.e(TAG, "Folder order not properly persisted during bind"); if (!findAndSetEmptyCells(item)) { - return false; + return null; } } @@ -567,7 +685,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList boolean insert = false; textView.setOnKeyListener(new FolderKeyEventListener()); mContent.addViewToCellLayout(textView, insert ? 0 : -1, (int)item.id, lp, true); - return true; + return textView; } public void onDragEnter(DragObject d) { @@ -716,6 +834,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList mCurrentDragView = null; mSuppressOnAdd = false; mRearrangeOnClose = true; + mIsExternalDrag = false; } public void onDragExit(DragObject d) { @@ -749,7 +868,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList success && (!beingCalledAfterUninstall || mUninstallSuccessful); if (successfulDrop) { - if (mDeleteFolderOnDropCompleted && !mItemAddedBackToSelfViaIcon) { + if (mDeleteFolderOnDropCompleted && !mItemAddedBackToSelfViaIcon && target != this) { replaceFolderWithFinalItem(); } } else { @@ -768,6 +887,12 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList } } + // This is kind of hacky, but in general, dropping on the workspace handles removing + // the extra screen, but dropping elsewhere (back to self, or onto delete) doesn't. + if (target != mLauncher.getWorkspace()) { + mLauncher.getWorkspace().removeExtraEmptyScreen(true, null); + } + mDeleteFolderOnDropCompleted = false; mDragInProgress = false; mItemAddedBackToSelfViaIcon = false; @@ -793,10 +918,25 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList } @Override + public float getIntrinsicIconScaleFactor() { + return 1f; + } + + @Override public boolean supportsFlingToDelete() { return true; } + @Override + public boolean supportsAppInfoDropTarget() { + return false; + } + + @Override + public boolean supportsDeleteDropTarget() { + return true; + } + public void onFlingToDelete(DragObject d, int x, int y, PointF vec) { // Do nothing } @@ -812,7 +952,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList View v = list.get(i); ItemInfo info = (ItemInfo) v.getTag(); LauncherModel.moveItemInDatabase(mLauncher, info, mInfo.id, 0, - info.cellX, info.cellY); + info.cellX, info.cellY); } } @@ -965,31 +1105,48 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList Rect workspacePadding = grid.getWorkspacePadding(grid.isLandscape ? CellLayout.LANDSCAPE : CellLayout.PORTRAIT); int maxContentAreaHeight = grid.availableHeightPx - - 4 * grid.edgeMarginPx - workspacePadding.top - workspacePadding.bottom - - getPaddingTop() - getPaddingBottom() - mFolderNameHeight; - return Math.min(maxContentAreaHeight, + int height = Math.min(maxContentAreaHeight, mContent.getDesiredHeight()); + return Math.max(height, MIN_CONTENT_DIMEN); + } + + private int getContentAreaWidth() { + return Math.max(mContent.getDesiredWidth(), MIN_CONTENT_DIMEN); } private int getFolderHeight() { - int height = getPaddingTop() + getPaddingBottom() - + getContentAreaHeight() + mFolderNameHeight; + int height = getPaddingTop() + getPaddingBottom() + mFolderNameHeight + + getContentAreaHeight(); return height; } protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - int width = getPaddingLeft() + getPaddingRight() + mContent.getDesiredWidth(); + int width = getPaddingLeft() + + getPaddingRight() + + Math.max(mContent.getDesiredWidth(), + mFolderTitleSection.getMeasuredWidth()); int height = getFolderHeight(); - int contentAreaWidthSpec = MeasureSpec.makeMeasureSpec(mContent.getDesiredWidth(), + int contentAreaWidthSpec = MeasureSpec.makeMeasureSpec(getContentAreaWidth(), MeasureSpec.EXACTLY); int contentAreaHeightSpec = MeasureSpec.makeMeasureSpec(getContentAreaHeight(), MeasureSpec.EXACTLY); - mContent.setFixedSize(mContent.getDesiredWidth(), mContent.getDesiredHeight()); + + if (LauncherAppState.isDisableAllApps()) { + // Don't cap the height of the content to allow scrolling. + mContent.setFixedSize(getContentAreaWidth(), mContent.getDesiredHeight()); + } else { + mContent.setFixedSize(getContentAreaWidth(), getContentAreaHeight()); + } + mScrollView.measure(contentAreaWidthSpec, contentAreaHeightSpec); - mFolderName.measure(contentAreaWidthSpec, - MeasureSpec.makeMeasureSpec(mFolderNameHeight, MeasureSpec.EXACTLY)); + mFolderName.measure(contentAreaWidthSpec, MeasureSpec.makeMeasureSpec( + mFolderNameHeight, MeasureSpec.EXACTLY)); + mFolderLock.measure(contentAreaWidthSpec, MeasureSpec.makeMeasureSpec( + mFolderNameHeight, MeasureSpec.EXACTLY)); + mFolderTitleSection.measure(contentAreaWidthSpec, MeasureSpec + .makeMeasureSpec(mFolderNameHeight, MeasureSpec.EXACTLY)); setMeasuredDimension(width, height); } @@ -1051,13 +1208,16 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList } private void replaceFolderWithFinalItem() { + if (mInfo.hidden) { + return; + } // Add the last remaining child to the workspace in place of the folder Runnable onCompleteRunnable = new Runnable() { @Override public void run() { CellLayout cellLayout = mLauncher.getCellLayout(mInfo.container, mInfo.screenId); - View child = null; + View child = null; // Move the item from the folder to the workspace, in the position of the folder if (getItemCount() == 1) { ShortcutInfo finalItem = mInfo.contents.get(0); @@ -1069,7 +1229,10 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList if (getItemCount() <= 1) { // Remove the folder LauncherModel.deleteItemFromDatabase(mLauncher, mInfo); - cellLayout.removeView(mFolderIcon); + if (cellLayout != null) { + // b/12446428 -- sometimes the cell layout has already gone away? + cellLayout.removeView(mFolderIcon); + } if (mFolderIcon instanceof DropTarget) { mDragController.removeDropTarget((DropTarget) mFolderIcon); } @@ -1087,6 +1250,8 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList View finalChild = getItemAt(0); if (finalChild != null) { mFolderIcon.performDestroyAnimation(finalChild, onCompleteRunnable); + } else { + onCompleteRunnable.run(); } mDestroyed = true; } @@ -1109,34 +1274,75 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList } public void onDrop(DragObject d) { - ShortcutInfo item; - if (d.dragInfo instanceof AppInfo) { - // Came from all apps -- make a copy - item = ((AppInfo) d.dragInfo).makeShortcut(); - item.spanX = 1; - item.spanY = 1; - } else { - item = (ShortcutInfo) d.dragInfo; + Runnable cleanUpRunnable = null; + + // If we are coming from All Apps space, we need to remove the extra empty screen (which is + // normally done in Workspace#onDropExternal, as well zoom back in and close the folder. + if (d.dragSource != mLauncher.getWorkspace() && !(d.dragSource instanceof Folder)) { + cleanUpRunnable = new Runnable() { + @Override + public void run() { + mLauncher.getWorkspace().removeExtraEmptyScreen(false, new Runnable() { + @Override + public void run() { + mLauncher.closeFolder(); + mLauncher.exitSpringLoadedDragModeDelayed(true, + Launcher.EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT_FOLDER_CLOSE, + null); + } + }, CLOSE_FOLDER_DELAY_MS, false); + } + }; } - // Dragged from self onto self, currently this is the only path possible, however - // we keep this as a distinct code path. - if (item == mCurrentDragInfo) { - ShortcutInfo si = (ShortcutInfo) mCurrentDragView.getTag(); - CellLayout.LayoutParams lp = (CellLayout.LayoutParams) mCurrentDragView.getLayoutParams(); + + View currentDragView; + ShortcutInfo si = mCurrentDragInfo; + if (mIsExternalDrag) { + si.cellX = mEmptyCell[0]; + si.cellY = mEmptyCell[1]; + currentDragView = createAndAddShortcut(si); + } else { + currentDragView = mCurrentDragView; + CellLayout.LayoutParams lp = (CellLayout.LayoutParams) currentDragView.getLayoutParams(); si.cellX = lp.cellX = mEmptyCell[0]; si.cellX = lp.cellY = mEmptyCell[1]; - mContent.addViewToCellLayout(mCurrentDragView, -1, (int)item.id, lp, true); - if (d.dragView.hasDrawn()) { - mLauncher.getDragLayer().animateViewIntoPosition(d.dragView, mCurrentDragView); - } else { - d.deferDragViewCleanupPostAnimation = false; - mCurrentDragView.setVisibility(VISIBLE); + mContent.addViewToCellLayout(currentDragView, -1, (int) si.id, lp, true); + } + + if (d.dragView.hasDrawn()) { + + // Temporarily reset the scale such that the animation target gets calculated correctly. + float scaleX = getScaleX(); + float scaleY = getScaleY(); + setScaleX(1.0f); + setScaleY(1.0f); + mLauncher.getDragLayer().animateViewIntoPosition(d.dragView, currentDragView, + cleanUpRunnable, null); + setScaleX(scaleX); + setScaleY(scaleY); + } else { + d.deferDragViewCleanupPostAnimation = false; + currentDragView.setVisibility(VISIBLE); + } + mItemsInvalidated = true; + setupContentDimensions(getItemCount()); + + // Actually move the item in the database if it was an external drag. + if (mIsExternalDrag) { + LauncherModel.addOrMoveItemInDatabase( + mLauncher, si, mInfo.id, 0, si.cellX, si.cellY); + + // We only need to update the locations if it doesn't get handled in #onDropCompleted. + if (d.dragSource != this) { + updateItemLocationsInDatabaseBatch(); } - mItemsInvalidated = true; - setupContentDimensions(getItemCount()); - mSuppressOnAdd = true; + mIsExternalDrag = false; } - mInfo.add(item); + + // Temporarily suppress the listener, as we did all the work already here. + mSuppressOnAdd = true; + mInfo.add(si); + mSuppressOnAdd = false; } // This is used so the item doesn't immediately appear in the folder when added. In one case @@ -1218,6 +1424,20 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList return mItemsInReadingOrder; } + public ShortcutInfo getShortcutForComponent(ComponentName componentName) { + for (View v : mItemsInReadingOrder) { + Object tag = v.getTag(); + if (tag instanceof ShortcutInfo) { + ComponentName cName = ((ShortcutInfo) tag).getIntent().getComponent(); + if (cName.equals(componentName)) { + return (ShortcutInfo) tag; + } + } + } + + return null; + } + public void getLocationInDragLayer(int[] loc) { mLauncher.getDragLayer().getLocationInDragLayer(this, loc); } @@ -1232,4 +1452,8 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList public void getHitRectRelativeToDragLayer(Rect outRect) { getHitRect(outRect); } + + public View getViewFromPosition(int position) { + return mItemsInReadingOrder.get(position); + } } diff --git a/src/com/android/launcher3/FolderIcon.java b/src/com/android/launcher3/FolderIcon.java index 9b7919b42..464b35da9 100644 --- a/src/com/android/launcher3/FolderIcon.java +++ b/src/com/android/launcher3/FolderIcon.java @@ -36,11 +36,10 @@ import android.view.View; import android.view.ViewGroup; import android.view.animation.AccelerateInterpolator; import android.view.animation.DecelerateInterpolator; +import android.widget.FrameLayout; import android.widget.ImageView; -import android.widget.LinearLayout; import android.widget.TextView; -import com.android.launcher3.R; import com.android.launcher3.DropTarget.DragObject; import com.android.launcher3.FolderInfo.FolderListener; @@ -49,7 +48,7 @@ import java.util.ArrayList; /** * An icon that can appear on in the workspace representing an {@link UserFolder}. */ -public class FolderIcon extends LinearLayout implements FolderListener { +public class FolderIcon extends FrameLayout implements FolderListener { private Launcher mLauncher; private Folder mFolder; private FolderInfo mInfo; @@ -76,10 +75,16 @@ public class FolderIcon extends LinearLayout implements FolderListener { // Flag as to whether or not to draw an outer ring. Currently none is designed. public static final boolean HAS_OUTER_RING = true; + // Flag whether the folder should open itself when an item is dragged over is enabled. + public static final boolean SPRING_LOADING_ENABLED = true; + // The degree to which the item in the back of the stack is scaled [0...1] // (0 means it's not scaled at all, 1 means it's scaled to nothing) private static final float PERSPECTIVE_SCALE_FACTOR = 0.35f; + // Delay when drag enters until the folder opens, in miliseconds. + private static final int ON_OPEN_DELAY = 800; + public static Drawable sSharedFolderLeaveBehind = null; private ImageView mPreviewBackground; @@ -104,6 +109,9 @@ public class FolderIcon extends LinearLayout implements FolderListener { private PreviewItemDrawingParams mAnimParams = new PreviewItemDrawingParams(0, 0, 0, 0); private ArrayList<ShortcutInfo> mHiddenItems = new ArrayList<ShortcutInfo>(); + private Alarm mOpenAlarm = new Alarm(); + private ItemInfo mDragInfo; + public FolderIcon(Context context, AttributeSet attrs) { super(context, attrs); init(); @@ -134,18 +142,20 @@ public class FolderIcon extends LinearLayout implements FolderListener { "INITIAL_ITEM_ANIMATION_DURATION, as sequencing of adding first two items " + "is dependent on this"); } + LauncherAppState app = LauncherAppState.getInstance(); + DeviceProfile grid = app.getDynamicGrid().getDeviceProfile(); FolderIcon icon = (FolderIcon) LayoutInflater.from(launcher).inflate(resId, group, false); icon.setClipToPadding(false); icon.mFolderName = (BubbleTextView) icon.findViewById(R.id.folder_icon_name); icon.mFolderName.setText(folderInfo.title); - Utilities.applyTypeface(icon.mFolderName); - icon.mPreviewBackground = (ImageView) icon.findViewById(R.id.preview_background); - LauncherAppState app = LauncherAppState.getInstance(); - DeviceProfile grid = app.getDynamicGrid().getDeviceProfile(); + icon.mFolderName.setCompoundDrawablePadding(0); + FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) icon.mFolderName.getLayoutParams(); + lp.topMargin = grid.iconSizePx + grid.iconDrawablePaddingPx; + // Offset the preview background to center this view accordingly - LinearLayout.LayoutParams lp = - (LinearLayout.LayoutParams) icon.mPreviewBackground.getLayoutParams(); + icon.mPreviewBackground = (ImageView) icon.findViewById(R.id.preview_background); + lp = (FrameLayout.LayoutParams) icon.mPreviewBackground.getLayoutParams(); lp.topMargin = grid.folderBackgroundOffset; lp.width = grid.folderIconSizePx; lp.height = grid.folderIconSizePx; @@ -308,14 +318,23 @@ public class FolderIcon extends LinearLayout implements FolderListener { private boolean willAcceptItem(ItemInfo item) { final int itemType = item.itemType; + + boolean hidden = false; + if (item instanceof FolderInfo){ + hidden = ((FolderInfo) item).hidden; + } return ((itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION || itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT || itemType == LauncherSettings.Favorites.ITEM_TYPE_FOLDER) && - !mFolder.isFull() && item != mInfo && !mInfo.opened); + !mFolder.isFull() && item != mInfo && !mInfo.opened && + !hidden); } public boolean acceptDrop(Object dragInfo) { final ItemInfo item = (ItemInfo) dragInfo; + if (mInfo.hidden) { + return false; + } return !mFolder.isDestroyed() && willAcceptItem(item); } @@ -331,11 +350,32 @@ public class FolderIcon extends LinearLayout implements FolderListener { mFolderRingAnimator.setCellLayout(layout); mFolderRingAnimator.animateToAcceptState(); layout.showFolderAccept(mFolderRingAnimator); + mOpenAlarm.setOnAlarmListener(mOnOpenListener); + if (SPRING_LOADING_ENABLED) { + mOpenAlarm.setAlarm(ON_OPEN_DELAY); + } + mDragInfo = (ItemInfo) dragInfo; } public void onDragOver(Object dragInfo) { } + OnAlarmListener mOnOpenListener = new OnAlarmListener() { + public void onAlarm(Alarm alarm) { + ShortcutInfo item; + if (mDragInfo instanceof AppInfo) { + // Came from all apps -- make a copy. + item = ((AppInfo) mDragInfo).makeShortcut(); + item.spanX = 1; + item.spanY = 1; + } else { + item = (ShortcutInfo) mDragInfo; + } + mFolder.beginExternalDrag(item); + mLauncher.openFolder(FolderIcon.this); + } + }; + public void performCreateAnimation(final ShortcutInfo destInfo, final View destView, final ShortcutInfo srcInfo, final DragView srcView, Rect dstRect, float scaleRelativeToDragLayer, Runnable postAnimationRunnable) { @@ -371,6 +411,7 @@ public class FolderIcon extends LinearLayout implements FolderListener { public void onDragExit() { mFolderRingAnimator.animateToNaturalState(); + mOpenAlarm.cancelAlarm(); } private void onDrop(final ShortcutInfo item, DragView animateView, Rect finalRect, @@ -548,12 +589,10 @@ public class FolderIcon extends LinearLayout implements FolderListener { if (d != null) { mOldBounds.set(d.getBounds()); d.setBounds(0, 0, mIntrinsicIconSize, mIntrinsicIconSize); - d.setFilterBitmap(true); d.setColorFilter(Color.argb(params.overlayAlpha, 255, 255, 255), PorterDuff.Mode.SRC_ATOP); d.draw(canvas); d.clearColorFilter(); - d.setFilterBitmap(false); d.setBounds(mOldBounds); } canvas.restore(); @@ -580,6 +619,20 @@ public class FolderIcon extends LinearLayout implements FolderListener { } int nItemsInPreview = Math.min(items.size(), NUM_ITEMS_IN_PREVIEW); + + // Hidden folder - don't display Preview + if (mInfo.hidden) { + mParams = computePreviewItemDrawingParams(NUM_ITEMS_IN_PREVIEW/2, mParams); + canvas.save(); + canvas.translate(mParams.transX + mPreviewOffsetX, mParams.transY + mPreviewOffsetY); + canvas.scale(mParams.scale, mParams.scale); + Drawable lock = getResources().getDrawable(R.drawable.folder_lock); + lock.setBounds(0, 0, mIntrinsicIconSize, mIntrinsicIconSize); + lock.draw(canvas); + canvas.restore(); + return; + } + if (!mAnimating) { for (int i = nItemsInPreview - 1; i >= 0; i--) { v = (TextView) items.get(i); diff --git a/src/com/android/launcher3/FolderInfo.java b/src/com/android/launcher3/FolderInfo.java index bb5ae8200..133bfd089 100644 --- a/src/com/android/launcher3/FolderInfo.java +++ b/src/com/android/launcher3/FolderInfo.java @@ -16,10 +16,10 @@ package com.android.launcher3; -import java.util.ArrayList; - import android.content.ContentValues; +import java.util.ArrayList; + /** * Represents a folder containing shortcuts or apps. */ @@ -31,9 +31,10 @@ class FolderInfo extends ItemInfo { boolean opened; /** - * The apps and shortcuts + * The apps and shortcuts and hidden status */ ArrayList<ShortcutInfo> contents = new ArrayList<ShortcutInfo>(); + Boolean hidden = false; ArrayList<FolderListener> listeners = new ArrayList<FolderListener>(); @@ -78,6 +79,7 @@ class FolderInfo extends ItemInfo { void onAddToDatabase(ContentValues values) { super.onAddToDatabase(values); values.put(LauncherSettings.Favorites.TITLE, title.toString()); + values.put(LauncherSettings.Favorites.HIDDEN, hidden ? 1 : 0); } void addListener(FolderListener listener) { diff --git a/src/com/android/launcher3/GelIntegrationHelper.java b/src/com/android/launcher3/GelIntegrationHelper.java new file mode 100644 index 000000000..f43e7e6a0 --- /dev/null +++ b/src/com/android/launcher3/GelIntegrationHelper.java @@ -0,0 +1,102 @@ +package com.android.launcher3; + +import android.app.Activity; +import android.app.ActivityManager; +import android.content.ComponentName; +import android.content.Intent; +import android.service.gesture.EdgeGestureManager; +import com.android.internal.util.gesture.EdgeGesturePosition; + +import java.util.List; + +/** + * A singleton wrapper class for GEL Integration. + * Requires EdgeGestureManager functionality that is only available + * in CyanogenMod. + */ +public class GelIntegrationHelper { + // The Intent for the search activity (resolves to Google Now when installed) + public final static String INTENT_ACTION_ASSIST = "android.intent.action.ASSIST"; + + private static final String GEL_ACTIVITY = "com.google.android.velvet.ui.VelvetActivity"; + private static final String GEL_PACKAGE_NAME = "com.google.android.googlequicksearchbox"; + + private static final int EDGE_GESTURE_SERVICE_RIGHT_EDGE = 4; + private static final int EDGE_GESTURE_SERVICE_LEFT_EDGE = 1; + private static final int EDGE_GESTURE_SERVICE_NO_EDGE = -1; + + private EdgeGestureManager.EdgeGestureActivationListener mEdgeGestureActivationListener = null; + private static GelIntegrationHelper sInstance; + + private GelIntegrationHelper() {} + + public static GelIntegrationHelper getInstance() { + if(sInstance == null) { + sInstance = new GelIntegrationHelper(); + } + return sInstance; + } + + /** + * 1. Registers an EdgeGestureActivationListener with the EdgeGestureManager so that + * the user can return to Trebuchet when they swipe from the right edge of the device. + * 2. Starts the Google Now Activity with an exit_out_right transition animation so that + * the new Activity appears to slide in as another screen (similar to GEL). + */ + public void registerSwipeBackGestureListenerAndStartGel(final Activity launcherActivity, boolean isLayoutRtl) { + EdgeGestureManager edgeGestureManager = EdgeGestureManager.getInstance(); + if(mEdgeGestureActivationListener == null) { + mEdgeGestureActivationListener = new EdgeGestureManager.EdgeGestureActivationListener() { + ActivityManager mAm = (ActivityManager) + launcherActivity.getSystemService(Activity.ACTIVITY_SERVICE); + + @Override + public void onEdgeGestureActivation(int touchX, int touchY, + EdgeGesturePosition position, int flags) { + // Retrieve the top level activity information + List< ActivityManager.RunningTaskInfo > taskInfo = mAm.getRunningTasks(1); + ComponentName topActivityComponentInfo = taskInfo.get(0).topActivity; + String topActivityClassName = topActivityComponentInfo.getClassName(); + String topActivityPackageName = topActivityComponentInfo.getPackageName(); + + // If the top level activity is Google Now, return to home. + // Otherwise, do nothing. + if(GEL_ACTIVITY.equals(topActivityClassName) + && GEL_PACKAGE_NAME.equals(topActivityPackageName)) { + Intent homeIntent = new Intent(Intent.ACTION_MAIN); + homeIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NO_ANIMATION); + homeIntent.addCategory(Intent.CATEGORY_HOME); + launcherActivity.startActivity(homeIntent); + launcherActivity.overridePendingTransition(0, 0); + dropEventsUntilLift(); + } + } + }; + edgeGestureManager.setEdgeGestureActivationListener(mEdgeGestureActivationListener); + } + mEdgeGestureActivationListener.restoreListenerState(); + int edge = isLayoutRtl ? EDGE_GESTURE_SERVICE_LEFT_EDGE : EDGE_GESTURE_SERVICE_RIGHT_EDGE; + edgeGestureManager.updateEdgeGestureActivationListener(mEdgeGestureActivationListener, + edge); + + // Start the Google Now Activity + Intent i = new Intent(INTENT_ACTION_ASSIST); + launcherActivity.startActivity(i); + launcherActivity.overridePendingTransition(0, R.anim.exit_out_right); + } + + /** + * Handle necessary cleanup and reset tasks for GEL integration, to be called from onResume. + */ + public void handleGelResume() { + // If there is an active EdgeGestureActivationListener for GEL integration, + // it should stop listening when we have resumed the launcher. + if(mEdgeGestureActivationListener != null) { + EdgeGestureManager edgeGestureManager = EdgeGestureManager.getInstance(); + // Update the listener so it is not listening to any postions (-1) + edgeGestureManager.updateEdgeGestureActivationListener(mEdgeGestureActivationListener, + EDGE_GESTURE_SERVICE_NO_EDGE); + } + } + +} diff --git a/src/com/android/launcher3/HiddenFolderFragment.java b/src/com/android/launcher3/HiddenFolderFragment.java new file mode 100644 index 000000000..07b0e4a8a --- /dev/null +++ b/src/com/android/launcher3/HiddenFolderFragment.java @@ -0,0 +1,343 @@ +package com.android.launcher3; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; + +import android.app.Fragment; +import android.app.FragmentTransaction; +import android.media.Image; +import android.text.InputType; +import android.view.KeyEvent; +import android.view.MenuItem; +import android.view.inputmethod.EditorInfo; +import android.view.inputmethod.InputMethodManager; +import android.widget.*; +import com.android.launcher3.settings.SettingsProvider; + +import android.app.Activity; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.graphics.drawable.Drawable; +import android.os.AsyncTask; +import android.os.Bundle; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; + +public class HiddenFolderFragment extends Fragment { + public static final String HIDDEN_FOLDER_FRAGMENT = "hiddenFolderFragment"; + public static final String HIDDEN_FOLDER_NAME = "hiddenFolderName"; + public static final String HIDDEN_FOLDER_STATUS = "hiddenFolderStatus"; + public static final String HIDDEN_FOLDER_INFO = "hiddenFolderInfo"; + public static final String HIDDEN_FOLDER_INFO_TITLES = "hiddenFolderInfoTitles"; + public static final String HIDDEN_FOLDER_LAUNCH = "hiddenFolderLaunchPosition"; + + private static final int REQ_LOCK_PATTERN = 1; + + private String[] mComponentInfo; + private String[] mComponentTitles; + private boolean mHidden; + private PackageManager mPackageManager; + private AppsAdapter mAppsAdapter; + private ArrayList<AppEntry> mAppEntries; + + private EditText mFolderName; + private ListView mListView; + + private Launcher mLauncher; + + private boolean mAuth = false; + private boolean mSent = false; + + private OnClickListener mClicklistener = new OnClickListener() { + @Override + public void onClick(View v) { + mHidden = !mHidden; + + ImageView mLock = (ImageView) v; + Drawable mLockIcon = mHidden ? getResources().getDrawable(R.drawable.folder_lock_light) + : getResources().getDrawable(R.drawable.folder_unlock); + mLock.setImageDrawable(mLockIcon); + } + }; + + @Override + public View onCreateView (LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View v = inflater.inflate(R.layout.hidden_folder, container, false); + + mLauncher = (Launcher) getActivity(); + mPackageManager = mLauncher.getPackageManager(); + + mHidden = getArguments().getBoolean(HIDDEN_FOLDER_STATUS); + Folder folder = mLauncher.mHiddenFolderIcon.getFolder(); + mComponentInfo = folder.getComponents(); + mComponentTitles = folder.getComponentTitles(); + String title = mLauncher.mHiddenFolderIcon.getFolderInfo().title.toString(); + + mFolderName = (EditText) v.findViewById(R.id.folder_name); + mFolderName.setText(title); + mFolderName.setSelectAllOnFocus(true); + mFolderName.setInputType(mFolderName.getInputType() | + InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS | InputType.TYPE_TEXT_FLAG_CAP_WORDS); + mFolderName.setImeOptions(EditorInfo.IME_ACTION_DONE); + mFolderName.setOnEditorActionListener(new TextView.OnEditorActionListener() { + @Override + public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { + if (actionId == EditorInfo.IME_ACTION_DONE) { + doneEditingText(v); + return true; + } + return false; + } + }); + mFolderName.setOnFocusChangeListener(new View.OnFocusChangeListener() { + @Override + public void onFocusChange(View v, boolean hasFocus) { + if (!hasFocus) { + doneEditingText(v); + } + } + }); + + ImageView mLock = (ImageView) v.findViewById(R.id.folder_lock_icon); + Drawable mLockIcon = mHidden ? getResources().getDrawable(R.drawable.folder_lock_light) + : getResources().getDrawable(R.drawable.folder_unlock); + mLock.setImageDrawable(mLockIcon); + mLock.setOnClickListener(mClicklistener); + + mAppsAdapter = new AppsAdapter(mLauncher, R.layout.hidden_apps_list_item); + mAppsAdapter.setNotifyOnChange(true); + mAppEntries = loadApps(); + mAppsAdapter.clear(); + mAppsAdapter.addAll(mAppEntries); + + mListView = (ListView) v.findViewById(R.id.hidden_apps_list); + mListView.setAdapter(mAppsAdapter); + + return v; + } + + private void doneEditingText(View v) { + InputMethodManager mInputMethodManager = (InputMethodManager) + mLauncher.getSystemService(Context.INPUT_METHOD_SERVICE); + mInputMethodManager.hideSoftInputFromWindow(v.getWindowToken(), 0); + + mListView.requestFocus(); + } + + private ArrayList<AppEntry> loadApps() { + ArrayList<AppEntry> apps = new ArrayList<AppEntry>(); + int size = mComponentInfo.length; + for (int i = 0; i < size; i++) { + apps.add(new AppEntry(mComponentInfo[i], mComponentTitles[i])); + } + return apps; + } + + private void removeComponentFromFolder(AppEntry app) { + mLauncher.mHiddenFolderIcon.getFolderInfo().remove( + mLauncher.mHiddenFolderIcon.getFolder() + .getShortcutForComponent(app.componentName)); + + mAppEntries.remove(app); + mAppsAdapter.remove(app); + mAppsAdapter.notifyDataSetInvalidated(); + } + + public void saveHiddenFolderStatus(int position) { + String newTitle = mFolderName.getText().toString(); + if (mLauncher.mHiddenFolderIcon != null) { + if (position != -1) { + Folder folder = mLauncher.mHiddenFolderIcon.getFolder(); + View v = folder.getViewFromPosition(position); + Object tag = v.getTag(); + if (tag instanceof ShortcutInfo) { + mLauncher.startActivitySafely(v, + ((ShortcutInfo) tag).getIntent(), + v.getTag()); + + return; + } + } + + // Folder name + FolderInfo info = mLauncher.mHiddenFolderIcon.getFolderInfo(); + if (!info.title.equals(newTitle)) { + info.setTitle(newTitle); + mLauncher.mHiddenFolderIcon.getFolder().setFolderName(); + LauncherModel.updateItemInDatabase(mLauncher, info); + } + + // Folder hidden status + if (info.hidden == mHidden) { + return; + } else { + info.hidden = mHidden; + // flip the boolean value to accomodate framework + // in framework "false" is "protected" and "true" is "visible" + mLauncher.mHiddenFolderIcon.getFolder().modifyProtectedApps(!info.hidden); + + LauncherModel.updateItemInDatabase(mLauncher, info); + // We need to make sure this change gets written to the DB before + // OnResume restarts the process + mLauncher.mModel.flushWorkerThread(); + } + } + + FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction(); + fragmentTransaction + .remove(mLauncher.mHiddenFolderFragment).commit(); + } + + public class AppsAdapter extends ArrayAdapter<AppEntry> { + + private final LayoutInflater mInflator; + + private ConcurrentHashMap<String, Drawable> mIcons; + private Drawable mDefaultImg; + private List<AppEntry> mApps; + + public AppsAdapter(Context context, int textViewResourceId) { + super(context, textViewResourceId); + + mApps = new ArrayList<AppEntry>(); + + mInflator = LayoutInflater.from(context); + + // set the default icon till the actual app icon is loaded in async + // task + mDefaultImg = context.getResources().getDrawable( + android.R.mipmap.sym_def_app_icon); + mIcons = new ConcurrentHashMap<String, Drawable>(); + } + + @Override + public View getView(final int position, View convertView, + ViewGroup parent) { + final AppViewHolder viewHolder; + + if (convertView == null) { + convertView = mInflator.inflate( + R.layout.hidden_folder_apps_list_item, parent, false); + viewHolder = new AppViewHolder(convertView, position); + convertView.setTag(viewHolder); + } else { + viewHolder = (AppViewHolder) convertView.getTag(); + } + + final AppEntry app = getItem(position); + + viewHolder.title.setText(app.title); + + Drawable icon = mIcons.get(app.componentName.getPackageName()); + viewHolder.icon.setImageDrawable(icon != null ? icon : mDefaultImg); + viewHolder.remove.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + removeComponentFromFolder(app); + } + }); + + convertView.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + saveHiddenFolderStatus(viewHolder.position); + } + }); + + return convertView; + } + + @Override + public boolean hasStableIds() { + return true; + } + + @Override + public void notifyDataSetChanged() { + super.notifyDataSetChanged(); + // If we have new items, we have to load their icons + // If items were deleted, remove them from our mApps + List<AppEntry> newApps = new ArrayList<AppEntry>(getCount()); + List<AppEntry> oldApps = new ArrayList<AppEntry>(getCount()); + for (int i = 0; i < getCount(); i++) { + AppEntry app = getItem(i); + if (mApps.contains(app)) { + oldApps.add(app); + } else { + newApps.add(app); + } + } + + if (newApps.size() > 0) { + new LoadIconsTask().execute(newApps.toArray(new AppEntry[] {})); + newApps.addAll(oldApps); + mApps = newApps; + } else { + mApps = oldApps; + } + } + + /** + * An asynchronous task to load the icons of the installed applications. + */ + private class LoadIconsTask extends AsyncTask<AppEntry, Void, Void> { + @Override + protected Void doInBackground(AppEntry... apps) { + for (AppEntry app : apps) { + try { + if (mIcons.containsKey(app.componentName + .getPackageName())) { + continue; + } + Drawable icon = mPackageManager + .getApplicationIcon(app.componentName + .getPackageName()); + mIcons.put(app.componentName.getPackageName(), icon); + publishProgress(); + } catch (PackageManager.NameNotFoundException e) { + // ignored; app will show up with default image + } + } + + return null; + } + + @Override + protected void onProgressUpdate(Void... progress) { + notifyDataSetChanged(); + } + } + } + + private final class AppEntry { + + public final ComponentName componentName; + public final String title; + + public AppEntry(String component, String title) { + componentName = ComponentName.unflattenFromString(component); + this.title = title; + } + } + + private static class AppViewHolder { + public final TextView title; + public final ImageView icon; + public final ImageView remove; + public final int position; + + public AppViewHolder(View parentView, int position) { + icon = (ImageView) parentView.findViewById(R.id.icon); + remove = (ImageView) parentView.findViewById(R.id.remove); + title = (TextView) parentView.findViewById(R.id.title); + this.position = position; + } + } +} diff --git a/src/com/android/launcher3/Hotseat.java b/src/com/android/launcher3/Hotseat.java index 2812b4129..0cca03b8c 100644 --- a/src/com/android/launcher3/Hotseat.java +++ b/src/com/android/launcher3/Hotseat.java @@ -149,7 +149,7 @@ public class Hotseat extends FrameLayout { void addAllAppsFolder(IconCache iconCache, ArrayList<AppInfo> allApps, ArrayList<ComponentName> onWorkspace, Launcher launcher, Workspace workspace) { - if (AppsCustomizePagedView.DISABLE_ALL_APPS) { + if (LauncherAppState.isDisableAllApps()) { FolderInfo fi = new FolderInfo(); fi.cellX = getCellXFromOrder(mAllAppsButtonRank); @@ -179,7 +179,7 @@ public class Hotseat extends FrameLayout { } void addAppsToAllAppsFolder(ArrayList<AppInfo> apps) { - if (AppsCustomizePagedView.DISABLE_ALL_APPS) { + if (LauncherAppState.isDisableAllApps()) { View v = mContent.getChildAt(getCellXFromOrder(mAllAppsButtonRank), getCellYFromOrder(mAllAppsButtonRank)); FolderIcon fi = null; diff --git a/src/com/android/launcher3/IconCache.java b/src/com/android/launcher3/IconCache.java index e1659e795..1dade8027 100644 --- a/src/com/android/launcher3/IconCache.java +++ b/src/com/android/launcher3/IconCache.java @@ -16,6 +16,8 @@ package com.android.launcher3; +import com.android.launcher3.backup.BackupProtos; + import android.app.ActivityManager; import android.content.ComponentName; import android.content.Context; @@ -25,16 +27,24 @@ import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.res.Resources; import android.graphics.Bitmap; +import android.graphics.BitmapFactory; import android.graphics.Canvas; +import android.graphics.Paint; import android.graphics.drawable.Drawable; import android.text.TextUtils; - +import android.util.Log; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.Map.Entry; -import com.android.launcher3.settings.SettingsProvider; - /** * Cache of application icons. Icons can be made from any thread. */ @@ -43,7 +53,9 @@ public class IconCache { private static final String TAG = "Launcher.IconCache"; private static final int INITIAL_ICON_CACHE_CAPACITY = 50; - private IconPackHelper mIconPackHelper; + private static final String RESOURCE_FILE_PREFIX = "icon_"; + + private static final boolean DEBUG = true; private static class CacheEntry { public Bitmap icon; @@ -67,9 +79,6 @@ public class IconCache { // need to set mIconDpi before getting default icon mDefaultIcon = makeDefaultIcon(); - - mIconPackHelper = new IconPackHelper(context); - loadIconPack(); } public Drawable getFullResDefaultActivityIcon() { @@ -117,18 +126,12 @@ public class IconCache { resources = null; } if (resources != null) { - int iconId = 0; - if (mIconPackHelper != null && mIconPackHelper.isIconPackLoaded()) { - iconId = mIconPackHelper.getResourceIdForActivityIcon(info); - if (iconId != 0) { - return getFullResIcon(mIconPackHelper.getIconPackResources(), iconId); - } - } - iconId = info.getIconResource(); + int iconId = info.getIconResource(); if (iconId != 0) { return getFullResIcon(resources, iconId); } } + return getFullResDefaultActivityIcon(); } @@ -144,16 +147,6 @@ public class IconCache { return b; } - private void loadIconPack() { - mIconPackHelper.unloadIconPack(); - String iconPack = SettingsProvider.getStringCustomDefault(mContext, - SettingsProvider.SETTINGS_UI_GENERAL_ICONS_ICON_PACK, ""); - if (!TextUtils.isEmpty(iconPack) && !mIconPackHelper.loadIconPack(iconPack)) { - SettingsProvider.putString(mContext, - SettingsProvider.SETTINGS_UI_GENERAL_ICONS_ICON_PACK, ""); - } - } - /** * Remove any records for the supplied ComponentName. */ @@ -164,13 +157,27 @@ public class IconCache { } /** + * Remove any records for the supplied package name. + */ + public void remove(String packageName) { + HashSet<ComponentName> forDeletion = new HashSet<ComponentName>(); + for (ComponentName componentName: mCache.keySet()) { + if (componentName.getPackageName().equals(packageName)) { + forDeletion.add(componentName); + } + } + for (ComponentName condemned: forDeletion) { + remove(condemned); + } + } + + /** * Empty out the cache. */ public void flush() { synchronized (mCache) { mCache.clear(); } - loadIconPack(); } /** @@ -181,7 +188,7 @@ public class IconCache { Iterator<Entry<ComponentName, CacheEntry>> it = mCache.entrySet().iterator(); while (it.hasNext()) { final CacheEntry e = it.next().getValue(); - if (e.icon.getWidth() != grid.iconSizePx || e.icon.getHeight() != grid.iconSizePx) { + if (e.icon.getWidth() < grid.iconSizePx || e.icon.getHeight() < grid.iconSizePx) { it.remove(); } } @@ -202,15 +209,22 @@ public class IconCache { } public Bitmap getIcon(Intent intent) { + return getIcon(intent, null); + } + + public Bitmap getIcon(Intent intent, String title) { synchronized (mCache) { final ResolveInfo resolveInfo = mPackageManager.resolveActivity(intent, 0); ComponentName component = intent.getComponent(); - if (resolveInfo == null || component == null) { + if (component == null) { return mDefaultIcon; } CacheEntry entry = cacheLocked(component, resolveInfo, null); + if (title != null) { + entry.title = title; + } return entry.icon; } } @@ -239,28 +253,34 @@ public class IconCache { mCache.put(componentName, entry); - ComponentName key = LauncherModel.getComponentNameFromResolveInfo(info); - if (labelCache != null && labelCache.containsKey(key)) { - entry.title = labelCache.get(key).toString(); - } else { - entry.title = info.loadLabel(mPackageManager).toString(); - if (labelCache != null) { - labelCache.put(key, entry.title); + if (info != null) { + ComponentName key = LauncherModel.getComponentNameFromResolveInfo(info); + if (labelCache != null && labelCache.containsKey(key)) { + entry.title = labelCache.get(key).toString(); + } else { + entry.title = info.loadLabel(mPackageManager).toString(); + if (labelCache != null) { + labelCache.put(key, entry.title); + } + } + if (entry.title == null) { + entry.title = info.activityInfo.name; } - } - if (entry.title == null) { - entry.title = info.activityInfo.name; - } - Drawable icon = getFullResIcon(info); - if (mIconPackHelper.isIconPackLoaded() && (mIconPackHelper - .getResourceIdForActivityIcon(info.activityInfo) == 0)) { entry.icon = Utilities.createIconBitmap( - icon, mContext, mIconPackHelper.getIconBack(), - mIconPackHelper.getIconMask(), mIconPackHelper.getIconUpon(), mIconPackHelper.getIconScale()); + getFullResIcon(info), mContext); } else { - entry.icon = Utilities.createIconBitmap( - icon, mContext); + entry.title = ""; + Bitmap preloaded = getPreloadedIcon(componentName); + if (preloaded != null) { + if (DEBUG) Log.d(TAG, "using preloaded icon for " + + componentName.toShortString()); + entry.icon = preloaded; + } else { + if (DEBUG) Log.d(TAG, "using default icon for " + + componentName.toShortString()); + entry.icon = mDefaultIcon; + } } } return entry; @@ -276,4 +296,137 @@ public class IconCache { return set; } } + + /** + * Pre-load an icon into the persistent cache. + * + * <P>Queries for a component that does not exist in the package manager + * will be answered by the persistent cache. + * + * @param context application context + * @param componentName the icon should be returned for this component + * @param icon the icon to be persisted + * @param dpi the native density of the icon + */ + public static void preloadIcon(Context context, ComponentName componentName, Bitmap icon, + int dpi) { + // TODO rescale to the correct native DPI + try { + PackageManager packageManager = context.getPackageManager(); + packageManager.getActivityIcon(componentName); + // component is present on the system already, do nothing + return; + } catch (PackageManager.NameNotFoundException e) { + // pass + } + + final String key = componentName.flattenToString(); + FileOutputStream resourceFile = null; + try { + resourceFile = context.openFileOutput(getResourceFilename(componentName), + Context.MODE_PRIVATE); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + if (icon.compress(android.graphics.Bitmap.CompressFormat.PNG, 75, os)) { + byte[] buffer = os.toByteArray(); + resourceFile.write(buffer, 0, buffer.length); + } else { + Log.w(TAG, "failed to encode cache for " + key); + return; + } + } catch (FileNotFoundException e) { + Log.w(TAG, "failed to pre-load cache for " + key, e); + } catch (IOException e) { + Log.w(TAG, "failed to pre-load cache for " + key, e); + } finally { + if (resourceFile != null) { + try { + resourceFile.close(); + } catch (IOException e) { + Log.d(TAG, "failed to save restored icon for: " + key, e); + } + } + } + } + + /** + * Read a pre-loaded icon from the persistent icon cache. + * + * @param componentName the component that should own the icon + * @returns a bitmap if one is cached, or null. + */ + private Bitmap getPreloadedIcon(ComponentName componentName) { + final String key = componentName.flattenToShortString(); + + if (DEBUG) Log.v(TAG, "looking for pre-load icon for " + key); + Bitmap icon = null; + FileInputStream resourceFile = null; + try { + resourceFile = mContext.openFileInput(getResourceFilename(componentName)); + byte[] buffer = new byte[1024]; + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + int bytesRead = 0; + while(bytesRead >= 0) { + bytes.write(buffer, 0, bytesRead); + bytesRead = resourceFile.read(buffer, 0, buffer.length); + } + if (DEBUG) Log.d(TAG, "read " + bytes.size()); + icon = BitmapFactory.decodeByteArray(bytes.toByteArray(), 0, bytes.size()); + if (icon == null) { + Log.w(TAG, "failed to decode pre-load icon for " + key); + } + } catch (FileNotFoundException e) { + if (DEBUG) Log.d(TAG, "there is no restored icon for: " + key, e); + } catch (IOException e) { + Log.w(TAG, "failed to read pre-load icon for: " + key, e); + } finally { + if(resourceFile != null) { + try { + resourceFile.close(); + } catch (IOException e) { + Log.d(TAG, "failed to manage pre-load icon file: " + key, e); + } + } + } + + if (icon != null) { + // TODO: handle alpha mask in the view layer + Bitmap b = Bitmap.createBitmap(Math.max(icon.getWidth(), 1), + Math.max(icon.getHeight(), 1), + Bitmap.Config.ARGB_8888); + Canvas c = new Canvas(b); + Paint paint = new Paint(); + paint.setAlpha(127); + c.drawBitmap(icon, 0, 0, paint); + c.setBitmap(null); + icon.recycle(); + icon = b; + } + + return icon; + } + + /** + * Remove a pre-loaded icon from the persistent icon cache. + * + * @param componentName the component that should own the icon + * @returns true on success + */ + public boolean deletePreloadedIcon(ComponentName componentName) { + if (componentName == null) { + return false; + } + if (mCache.remove(componentName) != null) { + if (DEBUG) Log.d(TAG, "removed pre-loaded icon from the in-memory cache"); + } + boolean success = mContext.deleteFile(getResourceFilename(componentName)); + if (DEBUG && success) Log.d(TAG, "removed pre-loaded icon from persistent cache"); + + return success; + } + + private static String getResourceFilename(ComponentName component) { + String resourceName = component.flattenToShortString(); + String filename = resourceName.replace(File.separatorChar, '_'); + return RESOURCE_FILE_PREFIX + filename; + } } diff --git a/src/com/android/launcher3/IconPackHelper.java b/src/com/android/launcher3/IconPackHelper.java deleted file mode 100644 index 69fadd965..000000000 --- a/src/com/android/launcher3/IconPackHelper.java +++ /dev/null @@ -1,517 +0,0 @@ -package com.android.launcher3; - -import java.io.IOException; -import java.io.InputStream; -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.Map; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; -import org.xmlpull.v1.XmlPullParserFactory; - -import android.app.Activity; -import android.app.AlertDialog; -import android.content.ComponentName; -import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; -import android.content.pm.ActivityInfo; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import android.content.res.Resources; -import android.content.res.XmlResourceParser; -import android.graphics.drawable.Drawable; -import android.text.TextUtils; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.BaseAdapter; -import android.widget.ImageView; -import android.widget.RadioButton; -import android.widget.TextView; -import android.widget.Toast; - -import com.android.launcher3.Launcher; -import com.android.launcher3.settings.SettingsProvider; - -public class IconPackHelper { - - static final String ICON_MASK_TAG = "iconmask"; - static final String ICON_BACK_TAG = "iconback"; - static final String ICON_UPON_TAG = "iconupon"; - static final String ICON_SCALE_TAG = "scale"; - - public final static String[] sSupportedActions = new String[] { - "org.adw.launcher.THEMES", - "com.gau.go.launcherex.theme" - }; - - public static final String[] sSupportedCategories = new String[] { - "com.fede.launcher.THEME_ICONPACK", - "com.anddoes.launcher.THEME", - "com.teslacoilsw.launcher.THEME" - }; - - // Holds package/class -> drawable - private Map<String, String> mIconPackResources; - private final Context mContext; - private String mLoadedIconPackName; - private Resources mLoadedIconPackResource; - private Drawable mIconBack, mIconUpon, mIconMask; - private float mIconScale; - - public Drawable getIconBack() { - return mIconBack; - } - - public Drawable getIconMask() { - return mIconMask; - } - - public Drawable getIconUpon() { - return mIconUpon; - } - - public float getIconScale() { - return mIconScale; - } - - IconPackHelper(Context context) { - mContext = context; - mIconPackResources = new HashMap<String, String>(); - } - - private Drawable getDrawableForName(String name) { - if (isIconPackLoaded()) { - String item = mIconPackResources.get(name); - if (!TextUtils.isEmpty(item)) { - int id = getResourceIdForDrawable(item); - if (id != 0) { - return mLoadedIconPackResource.getDrawable(id); - } - } - } - return null; - } - - public static Map<String, IconPackInfo> getSupportedPackages(Context context) { - Intent i = new Intent(); - Map<String, IconPackInfo> packages = new HashMap<String, IconPackInfo>(); - PackageManager packageManager = context.getPackageManager(); - for (String action : sSupportedActions) { - i.setAction(action); - for (ResolveInfo r : packageManager.queryIntentActivities(i, 0)) { - IconPackInfo info = new IconPackInfo(r, packageManager); - packages.put(r.activityInfo.packageName, info); - } - } - i = new Intent(Intent.ACTION_MAIN); - for (String category : sSupportedCategories) { - i.addCategory(category); - for (ResolveInfo r : packageManager.queryIntentActivities(i, 0)) { - IconPackInfo info = new IconPackInfo(r, packageManager); - packages.put(r.activityInfo.packageName, info); - } - i.removeCategory(category); - } - return packages; - } - - private static void loadResourcesFromXmlParser(XmlPullParser parser, - Map<String, String> iconPackResources) throws XmlPullParserException, IOException { - int eventType = parser.getEventType(); - do { - - if (eventType != XmlPullParser.START_TAG) { - continue; - } - - if (parser.getName().equalsIgnoreCase(ICON_MASK_TAG) || - parser.getName().equalsIgnoreCase(ICON_BACK_TAG) || - parser.getName().equalsIgnoreCase(ICON_UPON_TAG)) { - String icon = parser.getAttributeValue(null, "img"); - if (icon == null) { - if (parser.getAttributeCount() == 1) { - icon = parser.getAttributeValue(0); - } - } - iconPackResources.put(parser.getName().toLowerCase(), icon); - continue; - } - - if (parser.getName().equalsIgnoreCase(ICON_SCALE_TAG)) { - String factor = parser.getAttributeValue(null, "factor"); - if (factor == null) { - if (parser.getAttributeCount() == 1) { - factor = parser.getAttributeValue(0); - } - } - iconPackResources.put(parser.getName().toLowerCase(), factor); - continue; - } - - if (!parser.getName().equalsIgnoreCase("item")) { - continue; - } - - String component = parser.getAttributeValue(null, "component"); - String drawable = parser.getAttributeValue(null, "drawable"); - - // Validate component/drawable exist - if (TextUtils.isEmpty(component) || TextUtils.isEmpty(drawable)) { - continue; - } - - // Validate format/length of component - if (!component.startsWith("ComponentInfo{") || !component.endsWith("}") - || component.length() < 16) { - continue; - } - - // Sanitize stored value - component = component.substring(14, component.length() - 1).toLowerCase(); - - ComponentName name = null; - if (!component.contains("/")) { - // Package icon reference - iconPackResources.put(component, drawable); - } else { - name = ComponentName.unflattenFromString(component); - if (name != null) { - iconPackResources.put(name.getPackageName(), drawable); - iconPackResources.put(name.getPackageName() + "." + name.getClassName(), drawable); - } - } - } while ((eventType = parser.next()) != XmlPullParser.END_DOCUMENT); - } - - private static void loadApplicationResources(Context context, - Map<String, String> iconPackResources, String packageName) { - Field[] drawableItems = null; - try { - Context appContext = context.createPackageContext(packageName, - Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY); - drawableItems = Class.forName(packageName+".R$drawable", - true, appContext.getClassLoader()).getFields(); - } catch (Exception e){ - return; - } - - for (Field f : drawableItems) { - String name = f.getName(); - - String icon = name.toLowerCase(); - name = name.replaceAll("_", "."); - - iconPackResources.put(name, icon); - - int activityIndex = name.lastIndexOf("."); - if (activityIndex <= 0 || activityIndex == name.length() - 1) { - continue; - } - - String iconPackage = name.substring(0, activityIndex); - if (TextUtils.isEmpty(iconPackage)) { - continue; - } - iconPackResources.put(iconPackage, icon); - - String iconActivity = name.substring(activityIndex + 1); - if (TextUtils.isEmpty(iconActivity)) { - continue; - } - iconPackResources.put(iconPackage + "." + iconActivity, icon); - } - } - - public boolean loadIconPack(String packageName) { - mIconPackResources = getIconPackResources(mContext, packageName); - Resources res = null; - try { - res = mContext.getPackageManager().getResourcesForApplication(packageName); - } catch (PackageManager.NameNotFoundException e) { - e.printStackTrace(); - return false; - } - mLoadedIconPackResource = res; - mLoadedIconPackName = packageName; - mIconBack = getDrawableForName(ICON_BACK_TAG); - mIconMask = getDrawableForName(ICON_MASK_TAG); - mIconUpon = getDrawableForName(ICON_UPON_TAG); - String scale = mIconPackResources.get(ICON_SCALE_TAG); - if (scale != null) { - try { - mIconScale = Float.valueOf(scale); - } catch (NumberFormatException e) { - } - } - return true; - } - - public static Map<String, String> getIconPackResources(Context context, String packageName) { - if (TextUtils.isEmpty(packageName)) { - return null; - } - - Resources res = null; - try { - res = context.getPackageManager().getResourcesForApplication(packageName); - } catch (PackageManager.NameNotFoundException e) { - e.printStackTrace(); - return null; - } - - XmlPullParser parser = null; - InputStream inputStream = null; - Map<String, String> iconPackResources = new HashMap<String, String>(); - - try { - inputStream = res.getAssets().open("appfilter.xml"); - XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); - parser = factory.newPullParser(); - parser.setInput(inputStream, "UTF-8"); - } catch (Exception e) { - // Catch any exception since we want to fall back to parsing the xml/ - // resource in all cases - int resId = res.getIdentifier("appfilter", "xml", packageName); - if (resId != 0) { - parser = res.getXml(resId); - } - } - - if (parser != null) { - try { - loadResourcesFromXmlParser(parser, iconPackResources); - return iconPackResources; - } catch (XmlPullParserException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } finally { - // Cleanup resources - if (parser instanceof XmlResourceParser) { - ((XmlResourceParser) parser).close(); - } - if (inputStream != null) { - try { - inputStream.close(); - } catch (IOException e) { - } - } - } - } - - // Application uses a different theme format (most likely launcher pro) - int arrayId = res.getIdentifier("theme_iconpack", "array", packageName); - if (arrayId == 0) { - arrayId = res.getIdentifier("icon_pack", "array", packageName); - } - - if (arrayId != 0) { - String[] iconPack = res.getStringArray(arrayId); - for (String entry : iconPack) { - - if (TextUtils.isEmpty(entry)) { - continue; - } - - String icon = entry.toLowerCase(); - entry = entry.replaceAll("_", "."); - - iconPackResources.put(entry, icon); - - int activityIndex = entry.lastIndexOf("."); - if (activityIndex <= 0 || activityIndex == entry.length() - 1) { - continue; - } - - String iconPackage = entry.substring(0, activityIndex); - if (TextUtils.isEmpty(iconPackage)) { - continue; - } - iconPackResources.put(iconPackage, icon); - - String iconActivity = entry.substring(activityIndex + 1); - if (TextUtils.isEmpty(iconActivity)) { - continue; - } - iconPackResources.put(iconPackage + "." + iconActivity, icon); - } - } else { - loadApplicationResources(context, iconPackResources, packageName); - } - return iconPackResources; - } - - public void unloadIconPack() { - mLoadedIconPackResource = null; - mLoadedIconPackName = null; - mIconPackResources = null; - mIconMask = null; - mIconBack = null; - mIconUpon = null; - mIconScale = 1f; - } - - public static void pickIconPack(final Context context, final boolean pickIcon) { - Map<String, IconPackInfo> supportedPackages = getSupportedPackages(context); - if (supportedPackages.isEmpty()) { - Toast.makeText(context, R.string.no_iconpacks_summary, Toast.LENGTH_SHORT).show(); - return; - } - - final IconAdapter adapter = new IconAdapter(context, supportedPackages); - AlertDialog.Builder builder = new AlertDialog.Builder(context); - builder.setTitle(R.string.dialog_pick_iconpack_title); - if (!pickIcon) { - builder.setAdapter(adapter, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int position) { - if (adapter.isCurrentIconPack(position)) { - ((Launcher) context).getWorkspace().exitOverviewMode(true); - return; - } - String selectedPackage = adapter.getItem(position); - SettingsProvider.putString(context, - SettingsProvider.SETTINGS_UI_GENERAL_ICONS_ICON_PACK, selectedPackage); - LauncherAppState.getInstance().getIconCache().flush(); - LauncherAppState.getInstance().getModel().forceReload(); - ((Launcher) context).getWorkspace().exitOverviewMode(true); - } - }); - } else { - builder.setAdapter(adapter, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - String selectedPackage = adapter.getItem(which); - Launcher launcherActivity = (Launcher) context; - if (TextUtils.isEmpty(selectedPackage)) { - launcherActivity.onActivityResult(Launcher.REQUEST_PICK_ICON, Activity.RESULT_OK, null); - } else { - Intent i = new Intent(); - i.setClass(context, IconPickerActivity.class); - i.putExtra(IconPickerActivity.PACKAGE_NAME_EXTRA, selectedPackage); - launcherActivity.startActivityForResult(i, Launcher.REQUEST_PICK_ICON); - } - } - }); - } - builder.show().getWindow().getDecorView().setAlpha(0.8f); - } - - boolean isIconPackLoaded() { - return mLoadedIconPackResource != null && - mLoadedIconPackName != null && - mIconPackResources != null; - } - - private int getResourceIdForDrawable(String resource) { - int resId = mLoadedIconPackResource.getIdentifier(resource, "drawable", mLoadedIconPackName); - return resId; - } - - public Resources getIconPackResources() { - return mLoadedIconPackResource; - } - - public int getResourceIdForActivityIcon(ActivityInfo info) { - String drawable = mIconPackResources.get(info.packageName.toLowerCase() - + "." + info.name.toLowerCase()); - if (drawable == null) { - // Icon pack doesn't have an icon for the activity, fallback to package icon - drawable = mIconPackResources.get(info.packageName.toLowerCase()); - if (drawable == null) { - return 0; - } - } - return getResourceIdForDrawable(drawable); - } - - static class IconPackInfo { - String packageName; - CharSequence label; - Drawable icon; - - IconPackInfo(ResolveInfo r, PackageManager packageManager) { - packageName = r.activityInfo.packageName; - icon = r.loadIcon(packageManager); - label = r.loadLabel(packageManager); - } - - IconPackInfo(){ - } - - public IconPackInfo(String label, Drawable icon, String packageName) { - this.label = label; - this.icon = icon; - this.packageName = packageName; - } - } - - private static class IconAdapter extends BaseAdapter { - ArrayList<IconPackInfo> mSupportedPackages; - LayoutInflater mLayoutInflater; - String mCurrentIconPack; - int mCurrentIconPackPosition = -1; - - IconAdapter(Context ctx, Map<String, IconPackInfo> supportedPackages) { - mLayoutInflater = LayoutInflater.from(ctx); - mSupportedPackages = new ArrayList<IconPackInfo>(supportedPackages.values()); - Collections.sort(mSupportedPackages, new Comparator<IconPackInfo>() { - @Override - public int compare(IconPackInfo lhs, IconPackInfo rhs) { - return lhs.label.toString().compareToIgnoreCase(rhs.label.toString()); - } - }); - - Resources res = ctx.getResources(); - String defaultLabel = res.getString(R.string.default_iconpack_title); - Drawable icon = res.getDrawable(R.mipmap.ic_launcher_home); - mSupportedPackages.add(0, new IconPackInfo(defaultLabel, icon, "")); - - mCurrentIconPack = SettingsProvider.getStringCustomDefault(ctx, - SettingsProvider.SETTINGS_UI_GENERAL_ICONS_ICON_PACK, ""); - } - - @Override - public int getCount() { - return mSupportedPackages.size(); - } - - @Override - public String getItem(int position) { - return (String) mSupportedPackages.get(position).packageName; - } - - @Override - public long getItemId(int position) { - return 0; - } - - public boolean isCurrentIconPack(int position) { - return mCurrentIconPackPosition == position; - } - - @Override - public View getView(int position, View convertView, ViewGroup parent) { - if (convertView == null) { - convertView = mLayoutInflater.inflate(R.layout.iconpack_chooser, null); - } - IconPackInfo info = mSupportedPackages.get(position); - TextView txtView = (TextView) convertView.findViewById(R.id.title); - txtView.setText(info.label); - ImageView imgView = (ImageView) convertView.findViewById(R.id.icon); - imgView.setImageDrawable(info.icon); - RadioButton radioButton = (RadioButton) convertView.findViewById(R.id.radio); - boolean isCurrentIconPack = info.packageName.equals(mCurrentIconPack); - radioButton.setChecked(isCurrentIconPack); - if (isCurrentIconPack) { - mCurrentIconPackPosition = position; - } - return convertView; - } - } - -}
\ No newline at end of file diff --git a/src/com/android/launcher3/IconPickerActivity.java b/src/com/android/launcher3/IconPickerActivity.java deleted file mode 100644 index 5f08eda68..000000000 --- a/src/com/android/launcher3/IconPickerActivity.java +++ /dev/null @@ -1,152 +0,0 @@ -package com.android.launcher3; - -import java.lang.ref.WeakReference; -import java.util.ArrayList; -import java.util.LinkedHashSet; -import java.util.Map; - -import android.app.Activity; -import android.app.ActivityManager; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.pm.PackageManager.NameNotFoundException; -import android.content.res.Resources; -import android.graphics.drawable.BitmapDrawable; -import android.graphics.drawable.Drawable; -import android.os.AsyncTask; -import android.os.Bundle; -import android.view.View; -import android.view.ViewGroup; -import android.widget.AdapterView; -import android.widget.BaseAdapter; -import android.widget.GridView; -import android.widget.ImageView; - -public class IconPickerActivity extends Activity { - - public static final String SELECTED_RESOURCE_EXTRA = "selected_resource"; - public static final String SELECTED_BITMAP_EXTRA = "bitmap"; - public static final String PACKAGE_NAME_EXTRA = "package"; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - ActivityManager activityManager = - (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); - int iconSize = activityManager.getLauncherLargeIconSize(); - final String pkgName = getIntent().getStringExtra(PACKAGE_NAME_EXTRA); - - GridView gridview = new GridView(this); - gridview.setNumColumns(GridView.AUTO_FIT); - gridview.setHorizontalSpacing(40); - gridview.setVerticalSpacing(40); - gridview.setPadding(20, 20, 20, 0); - gridview.setFastScrollEnabled(true); - gridview.setColumnWidth(iconSize); - gridview.setStretchMode(GridView.STRETCH_COLUMN_WIDTH); - - gridview.setAdapter(new ImageAdapter(this, pkgName)); - gridview.setOnItemClickListener(new AdapterView.OnItemClickListener() { - @Override - public void onItemClick(AdapterView<?> adapterView, View v, int position, long id) { - Intent in = new Intent(); - DrawableInfo d = (DrawableInfo) adapterView.getAdapter().getItem(position); - in.putExtra(SELECTED_RESOURCE_EXTRA, pkgName + "|" + d.resource_name); - in.putExtra(SELECTED_BITMAP_EXTRA, ((BitmapDrawable)d.drawable.get()).getBitmap()); - setResult(Activity.RESULT_OK, in); - finish(); - } - }); - setContentView(gridview); - } - - public class ImageAdapter extends BaseAdapter { - private Context mContext; - private Resources mResources; - private ArrayList<DrawableInfo> mDrawables = new ArrayList<DrawableInfo>(); - - public class FetchDrawable extends AsyncTask<Integer, Void, Drawable> { - WeakReference<ImageView> mImageView; - - FetchDrawable(ImageView imgView) { - mImageView = new WeakReference<ImageView>(imgView); - } - - @Override - protected Drawable doInBackground(Integer... position) { - DrawableInfo info = getItem(position[0]); - int itemId = info.resource_id; - Drawable d = mResources.getDrawable(itemId); - info.drawable = new WeakReference<Drawable>(d); - return d; - } - - @Override - public void onPostExecute(Drawable result) { - if (mImageView.get() != null) { - mImageView.get().setImageDrawable(result); - } - } - } - - public ImageAdapter(Context c, String pkgName) { - mContext = c; - Map<String, String> resources = IconPackHelper.getIconPackResources(c, pkgName); - try { - mResources = c.getPackageManager().getResourcesForApplication(pkgName); - LinkedHashSet<String> drawables = new LinkedHashSet<String>(resources.values()); - for (String s : drawables) { - int id = mResources.getIdentifier(s, "drawable", pkgName); - if (id != 0) { - mDrawables.add(new DrawableInfo(s, id)); - } - } - } catch (NameNotFoundException e) { - } - } - - public int getCount() { - return mDrawables.size(); - } - - public DrawableInfo getItem(int position) { - return mDrawables.get(position); - } - - public long getItemId(int position) { - return 0; - } - - public View getView(final int position, View convertView, ViewGroup parent) { - final ImageView imageView; - if (convertView == null) { - imageView = new ImageView(mContext); - imageView.setLayoutParams(new GridView.LayoutParams( - GridView.LayoutParams.WRAP_CONTENT, GridView.LayoutParams.WRAP_CONTENT)); - imageView.setScaleType(ImageView.ScaleType.FIT_CENTER); - } else { - imageView = (ImageView) convertView; - Object tag = imageView.getTag(); - if (tag != null && tag instanceof FetchDrawable) { - ((FetchDrawable) tag).cancel(true); - } - } - FetchDrawable req = new FetchDrawable(imageView); - imageView.setTag(req); - req.execute(position); - return imageView; - } - } - - private class DrawableInfo { - WeakReference<Drawable> drawable; - final String resource_name; - final int resource_id; - DrawableInfo(String n, int i) { - resource_name = n; - resource_id = i; - } - } -} diff --git a/src/com/android/launcher3/InstallShortcutReceiver.java b/src/com/android/launcher3/InstallShortcutReceiver.java index 7df73b1f6..28cef1346 100644 --- a/src/com/android/launcher3/InstallShortcutReceiver.java +++ b/src/com/android/launcher3/InstallShortcutReceiver.java @@ -24,17 +24,20 @@ import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.graphics.Bitmap; import android.graphics.BitmapFactory; +import android.text.TextUtils; import android.util.Base64; import android.util.Log; import android.widget.Toast; +import org.json.JSONObject; +import org.json.JSONStringer; +import org.json.JSONTokener; + import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.Set; -import org.json.*; - public class InstallShortcutReceiver extends BroadcastReceiver { private static final String TAG = "InstallShortcutReceiver"; private static final boolean DBG = false; @@ -108,6 +111,9 @@ public class InstallShortcutReceiver extends BroadcastReceiver { public static void removeFromInstallQueue(SharedPreferences sharedPrefs, ArrayList<String> packageNames) { + if (packageNames.isEmpty()) { + return; + } synchronized(sLock) { Set<String> strings = sharedPrefs.getStringSet(APPS_PENDING_INSTALL, null); if (DBG) { @@ -218,18 +224,11 @@ public class InstallShortcutReceiver extends BroadcastReceiver { if (intent == null) { return; } + // This name is only used for comparisons and notifications, so fall back to activity name // if not supplied - String name = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME); - if (name == null) { - try { - PackageManager pm = context.getPackageManager(); - ActivityInfo info = pm.getActivityInfo(intent.getComponent(), 0); - name = info.loadLabel(pm).toString(); - } catch (PackageManager.NameNotFoundException nnfe) { - return; - } - } + String name = ensureValidName(context, intent, + data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME)).toString(); Bitmap icon = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON); Intent.ShortcutIconResource iconResource = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE); @@ -272,6 +271,12 @@ public class InstallShortcutReceiver extends BroadcastReceiver { //final Intent data = pendingInfo.data; final Intent intent = pendingInfo.launchIntent; final String name = pendingInfo.name; + + if (LauncherAppState.isDisableAllApps() && !isValidShortcutLaunchIntent(intent)) { + if (DBG) Log.d(TAG, "Ignoring shortcut with launchIntent:" + intent); + continue; + } + final boolean exists = LauncherModel.shortcutExists(context, name, intent); //final boolean allowDuplicate = data.getBooleanExtra(Launcher.EXTRA_SHORTCUT_DUPLICATE, true); @@ -299,11 +304,35 @@ public class InstallShortcutReceiver extends BroadcastReceiver { // Add the new apps to the model and bind them if (!addShortcuts.isEmpty()) { LauncherAppState app = LauncherAppState.getInstance(); - app.getModel().addAndBindAddedApps(context, addShortcuts, null); + app.getModel().addAndBindAddedWorkspaceApps(context, addShortcuts); } } } + /** + * Returns true if the intent is a valid launch intent for a shortcut. + * This is used to identify shortcuts which are different from the ones exposed by the + * applications' manifest file. + * + * When DISABLE_ALL_APPS is true, shortcuts exposed via the app's manifest should never be + * duplicated or removed(unless the app is un-installed). + * + * @param launchIntent The intent that will be launched when the shortcut is clicked. + */ + static boolean isValidShortcutLaunchIntent(Intent launchIntent) { + if (launchIntent != null + && Intent.ACTION_MAIN.equals(launchIntent.getAction()) + && launchIntent.getComponent() != null + && launchIntent.getCategories() != null + && launchIntent.getCategories().size() == 1 + && launchIntent.hasCategory(Intent.CATEGORY_LAUNCHER) + && launchIntent.getExtras() == null + && TextUtils.isEmpty(launchIntent.getDataString())) { + return false; + } + return true; + } + private static ShortcutInfo getShortcutInfo(Context context, Intent data, Intent launchIntent) { if (launchIntent.getAction() == null) { @@ -315,6 +344,25 @@ public class InstallShortcutReceiver extends BroadcastReceiver { Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); } LauncherAppState app = LauncherAppState.getInstance(); - return app.getModel().infoFromShortcutIntent(context, data, null); + ShortcutInfo info = app.getModel().infoFromShortcutIntent(context, data, null); + info.title = ensureValidName(context, launchIntent, info.title); + return info; + } + + /** + * Ensures that we have a valid, non-null name. If the provided name is null, we will return + * the application name instead. + */ + private static CharSequence ensureValidName(Context context, Intent intent, CharSequence name) { + if (name == null) { + try { + PackageManager pm = context.getPackageManager(); + ActivityInfo info = pm.getActivityInfo(intent.getComponent(), 0); + name = info.loadLabel(pm).toString(); + } catch (PackageManager.NameNotFoundException nnfe) { + return ""; + } + } + return name; } } diff --git a/src/com/android/launcher3/InstallWidgetReceiver.java b/src/com/android/launcher3/InstallWidgetReceiver.java index 0ef478074..74b9e3d99 100644 --- a/src/com/android/launcher3/InstallWidgetReceiver.java +++ b/src/com/android/launcher3/InstallWidgetReceiver.java @@ -16,8 +16,6 @@ package com.android.launcher3; -import java.util.List; - import android.appwidget.AppWidgetProviderInfo; import android.content.ClipData; import android.content.Context; @@ -33,7 +31,7 @@ import android.widget.ImageView; import android.widget.ListAdapter; import android.widget.TextView; -import com.android.launcher3.R; +import java.util.List; /** diff --git a/src/com/android/launcher3/ItemInfo.java b/src/com/android/launcher3/ItemInfo.java index 8c4cefd5f..3dc92c9c2 100644 --- a/src/com/android/launcher3/ItemInfo.java +++ b/src/com/android/launcher3/ItemInfo.java @@ -27,7 +27,7 @@ import java.io.IOException; /** * Represents an item in the launcher. */ -class ItemInfo { +public class ItemInfo { static final int NO_ID = -1; @@ -122,6 +122,10 @@ class ItemInfo { throw new RuntimeException("Unexpected Intent"); } + protected Intent getRestoredIntent() { + throw new RuntimeException("Unexpected Intent"); + } + /** * Write the fields of this item to the DB * diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 416c80641..ab3f1daa0 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -17,8 +17,6 @@ package com.android.launcher3; -import android.accounts.Account; -import android.accounts.AccountManager; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; @@ -29,8 +27,10 @@ import android.animation.ValueAnimator.AnimatorUpdateListener; import android.app.Activity; import android.app.ActivityManager; import android.app.ActivityOptions; -import android.app.AlertDialog; import android.app.Dialog; +import android.app.Fragment; +import android.app.FragmentManager; +import android.app.FragmentTransaction; import android.app.SearchManager; import android.appwidget.AppWidgetHostView; import android.appwidget.AppWidgetManager; @@ -41,13 +41,14 @@ import android.content.ComponentCallbacks2; import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; -import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; import android.content.pm.ActivityInfo; +import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; +import android.content.pm.ResolveInfo; import android.content.res.Configuration; import android.content.res.Resources; import android.database.ContentObserver; @@ -55,6 +56,7 @@ import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Point; import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.net.Uri; @@ -65,7 +67,6 @@ import android.os.Handler; import android.os.Message; import android.os.StrictMode; import android.os.SystemClock; -import android.provider.Settings; import android.speech.RecognizerIntent; import android.text.Selection; import android.text.SpannableStringBuilder; @@ -83,14 +84,12 @@ import android.view.MenuItem; import android.view.MotionEvent; import android.view.Surface; import android.view.View; -import android.view.View.OnClickListener; import android.view.View.OnLongClickListener; import android.view.ViewGroup; import android.view.ViewTreeObserver; import android.view.ViewTreeObserver.OnGlobalLayoutListener; import android.view.WindowManager; import android.view.accessibility.AccessibilityEvent; -import android.view.accessibility.AccessibilityManager; import android.view.animation.AccelerateDecelerateInterpolator; import android.view.animation.DecelerateInterpolator; import android.view.inputmethod.InputMethodManager; @@ -101,8 +100,9 @@ import android.widget.PopupMenu; import android.widget.TextView; import android.widget.Toast; +import com.android.launcher.home.Home; import com.android.launcher3.DropTarget.DragObject; -import com.android.launcher3.settings.SettingsActivity; +import com.android.launcher3.PagedView.TransitionEffect; import com.android.launcher3.settings.SettingsProvider; import java.io.DataInputStream; @@ -119,6 +119,8 @@ import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; + /** * Default launcher application. @@ -129,12 +131,16 @@ public class Launcher extends Activity static final String TAG = "Launcher"; static final boolean LOGD = false; + DeviceProfile mGrid; + static final boolean PROFILE_STARTUP = false; static final boolean DEBUG_WIDGETS = false; static final boolean DEBUG_STRICT_MODE = false; static final boolean DEBUG_RESUME_TIME = false; static final boolean DEBUG_DUMP_LOG = false; + static final boolean ENABLE_DEBUG_INTENTS = false; // allow DebugIntents to run + private static final int REQUEST_CREATE_SHORTCUT = 1; private static final int REQUEST_CREATE_APPWIDGET = 5; private static final int REQUEST_PICK_APPLICATION = 6; @@ -143,8 +149,11 @@ public class Launcher extends Activity private static final int REQUEST_PICK_WALLPAPER = 10; private static final int REQUEST_BIND_APPWIDGET = 11; + static final int REQUEST_PICK_ICON = 13; + private static final int REQUEST_LOCK_PATTERN = 14; + /** * IntentStarter uses request codes starting with this. This must be greater than all activity * request codes used internally. @@ -161,6 +170,7 @@ public class Launcher extends Activity // adb shell setprop log.tag.PROPERTY_NAME [VERBOSE | SUPPRESS] static final String FORCE_ENABLE_ROTATION_PROPERTY = "launcher_force_rotate"; static final String DUMP_STATE_PROPERTY = "launcher_dump_state"; + static final String DISABLE_ALL_APPS_PROPERTY = "launcher_noallapps"; // The Intent extra that defines whether to ignore the launch animation static final String INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION = @@ -188,6 +198,13 @@ public class Launcher extends Activity private static final String RUNTIME_STATE_PENDING_ADD_SPAN_Y = "launcher.add_span_y"; // Type: parcelable private static final String RUNTIME_STATE_PENDING_ADD_WIDGET_INFO = "launcher.add_widget_info"; + // Type: parcelable + private static final String RUNTIME_STATE_PENDING_ADD_WIDGET_ID = "launcher.add_widget_id"; + // Type: int[] + private static final String RUNTIME_STATE_VIEW_IDS = "launcher.view_ids"; + + + static final String FIRST_RUN_ACTIVITY_DISPLAYED = "launcher.first_run_activity_displayed"; private static final String TOOLBAR_ICON_METADATA_NAME = "com.android.launcher.toolbar_icon"; private static final String TOOLBAR_SEARCH_ICON_METADATA_NAME = @@ -203,25 +220,31 @@ public class Launcher extends Activity public static final String SHOW_WEIGHT_WATCHER = "debug.show_mem"; public static final boolean SHOW_WEIGHT_WATCHER_DEFAULT = false; + public static final String USER_HAS_MIGRATED = "launcher.user_migrated_from_old_data"; + /** The different states that Launcher can be in. */ private enum State { NONE, WORKSPACE, APPS_CUSTOMIZE, APPS_CUSTOMIZE_SPRING_LOADED }; private State mState = State.WORKSPACE; private AnimatorSet mStateAnimation; static final int APPWIDGET_HOST_ID = 1024; - private static final int EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT = 300; - private static final int EXIT_SPRINGLOADED_MODE_LONG_TIMEOUT = 600; - private static final int SHOW_CLING_DURATION = 250; - private static final int DISMISS_CLING_DURATION = 200; + public static final int EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT = 300; + public static final int EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT_FOLDER_CLOSE = 400; + private static final int ON_ACTIVITY_RESULT_ANIMATION_DELAY = 500; private static final Object sLock = new Object(); private static int sScreen = DEFAULT_SCREEN; + private HashMap<Integer, Integer> mItemIdToViewId = new HashMap<Integer, Integer>(); + private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1); + // How long to wait before the new-shortcut animation automatically pans the workspace private static int NEW_APPS_PAGE_MOVE_DELAY = 500; private static int NEW_APPS_ANIMATION_INACTIVE_TIMEOUT_SECONDS = 5; private static int NEW_APPS_ANIMATION_DELAY = 500; + private boolean mGelIntegrationEnabled = false; + private final BroadcastReceiver mCloseSystemDialogsReceiver = new CloseSystemDialogsIntentReceiver(); private final ContentObserver mWidgetObserver = new AppWidgetResetObserver(); @@ -230,22 +253,37 @@ public class Launcher extends Activity private Workspace mWorkspace; private View mLauncherView; + private View mPageIndicators; private DragLayer mDragLayer; private DragController mDragController; private View mWeightWatcher; + private TransitionEffectsFragment mTransitionEffectsFragment; + private DynamicGridSizeFragment mDynamicGridSizeFragment; + private LauncherClings mLauncherClings; + protected HiddenFolderFragment mHiddenFolderFragment; + private AppWidgetManager mAppWidgetManager; private LauncherAppWidgetHost mAppWidgetHost; private ItemInfo mPendingAddInfo = new ItemInfo(); private AppWidgetProviderInfo mPendingAddWidgetInfo; + private int mPendingAddWidgetId = -1; private int[] mTmpAddItemCellCoordinates = new int[2]; private FolderInfo mFolderInfo; + protected FolderIcon mHiddenFolderIcon; + private boolean mHiddenFolderAuth = false; + private Hotseat mHotseat; + private View mOverviewPanel; + private View mDarkPanel; + OverviewSettingsPanel mOverviewSettingsPanel; + +// private ViewGroup mOverviewPanel; private View mAllAppsButton; @@ -253,7 +291,10 @@ public class Launcher extends Activity private AppsCustomizeLayout mAppsCustomizeLayout; private AppsCustomizePagedView mAppsCustomizeContent; private boolean mAutoAdvanceRunning = false; + private View mQsb; private View mQsbBar; + private ImageView mQsbBarSearch; + private ImageView mQsbBarVoice; private Bundle mSavedState; // We set the state in both onCreate and then onNewIntent in some cases, which causes both @@ -280,14 +321,12 @@ public class Launcher extends Activity private Dialog mTransitionEffectDialog; - private LauncherModel mModel; + protected LauncherModel mModel; private IconCache mIconCache; private boolean mUserPresent = true; private boolean mVisible = false; private boolean mHasFocus = false; private boolean mAttached = false; - private static final boolean DISABLE_CLINGS = false; - private static final boolean DISABLE_CUSTOM_CLINGS = true; private static LocaleConfiguration sLocaleConfiguration = null; @@ -315,6 +354,7 @@ public class Launcher extends Activity private Drawable mWorkspaceBackgroundDrawable; private final ArrayList<Integer> mSynchronouslyBoundPages = new ArrayList<Integer>(); + private static final boolean DISABLE_SYNCHRONOUS_BINDING_CURRENT_PAGE = false; static final ArrayList<String> sDumpLogs = new ArrayList<String>(); static Date sDateStamp = new Date(); @@ -338,9 +378,6 @@ public class Launcher extends Activity private BubbleTextView mWaitingForResume; - private HideFromAccessibilityHelper mHideFromAccessibilityHelper - = new HideFromAccessibilityHelper(); - // Preferences private boolean mHideIconLabels; @@ -368,10 +405,33 @@ public class Launcher extends Activity private Stats mStats; - private static boolean isPropertyEnabled(String propertyName) { + public Animator.AnimatorListener mAnimatorListener = new Animator.AnimatorListener() { + @Override + public void onAnimationStart(Animator arg0) {} + @Override + public void onAnimationRepeat(Animator arg0) {} + @Override + public void onAnimationEnd(Animator arg0) { + mDarkPanel.setVisibility(View.GONE); + } + @Override + public void onAnimationCancel(Animator arg0) {} + }; + + static boolean isPropertyEnabled(String propertyName) { return Log.isLoggable(propertyName, Log.VERBOSE); } + private BroadcastReceiver protectedAppsChangedReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + // Update the workspace + updateDynamicGrid(); + mWorkspace.hideOutlines(); + mSearchDropTargetBar.showSearchBar(false); + } + }; + @Override protected void onCreate(Bundle savedInstanceState) { if (DEBUG_STRICT_MODE) { @@ -391,36 +451,14 @@ public class Launcher extends Activity super.onCreate(savedInstanceState); - LauncherAppState.setApplicationContext(getApplicationContext()); - LauncherAppState app = LauncherAppState.getInstance(); - - mHideIconLabels = SettingsProvider.getBoolean(this, - SettingsProvider.SETTINGS_UI_HOMESCREEN_HIDE_ICON_LABELS, - R.bool.preferences_interface_homescreen_hide_icon_labels_default); - - // Determine the dynamic grid properties - Point smallestSize = new Point(); - Point largestSize = new Point(); - Point realSize = new Point(); - Display display = getWindowManager().getDefaultDisplay(); - display.getCurrentSizeRange(smallestSize, largestSize); - display.getRealSize(realSize); - DisplayMetrics dm = new DisplayMetrics(); - display.getMetrics(dm); - // Lazy-initialize the dynamic grid - DeviceProfile grid = app.initDynamicGrid(this, - Math.min(smallestSize.x, smallestSize.y), - Math.min(largestSize.x, largestSize.y), - realSize.x, realSize.y, - dm.widthPixels, dm.heightPixels); + initializeDynamicGrid(); // the LauncherApplication should call this, but in case of Instrumentation it might not be present yet mSharedPrefs = getSharedPreferences(LauncherAppState.getSharedPreferencesKey(), Context.MODE_PRIVATE); - mModel = app.setLauncher(this); - mIconCache = app.getIconCache(); - mIconCache.flushInvalidIcons(grid); + mDragController = new DragController(this); + mLauncherClings = new LauncherClings(this); mInflater = getLayoutInflater(); mStats = new Stats(this); @@ -445,7 +483,7 @@ public class Launcher extends Activity setContentView(R.layout.launcher); setupViews(); - grid.layout(this); + mGrid.layout(this); registerContentObservers(); @@ -454,25 +492,21 @@ public class Launcher extends Activity mSavedState = savedInstanceState; restoreState(mSavedState); - // Update customization drawer _after_ restoring the states - if (mAppsCustomizeContent != null) { - mAppsCustomizeContent.onPackagesUpdated( - LauncherModel.getSortedWidgetsAndShortcuts(this)); - } + restoreGelSetting(); if (PROFILE_STARTUP) { android.os.Debug.stopMethodTracing(); } if (!mRestoring) { - if (sPausedFromUserAction) { + if (DISABLE_SYNCHRONOUS_BINDING_CURRENT_PAGE || sPausedFromUserAction) { // If the user leaves launcher, then we should just load items asynchronously when // they return. - mModel.startLoader(true, -1); + mModel.startLoader(true, PagedView.INVALID_RESTORE_PAGE); } else { // We only load the page synchronously if the user rotates (or triggers a // configuration change) while launcher is in the foreground - mModel.startLoader(true, mWorkspace.getCurrentPage()); + mModel.startLoader(true, mWorkspace.getRestorePage()); } } @@ -488,7 +522,60 @@ public class Launcher extends Activity // On large interfaces, we want the screen to auto-rotate based on the current orientation unlockScreenOrientation(true); - showFirstRunCling(); + // The two first run cling paths are mutually exclusive, if the launcher is preinstalled + // on the device, then we always show the first run cling experience (or if there is no + // launcher2). Otherwise, we prompt the user upon started for migration + showFirstRunActivity(); + if (mLauncherClings.shouldShowFirstRunOrMigrationClings()) { + if (mModel.canMigrateFromOldLauncherDb(this)) { + mLauncherClings.showMigrationCling(); + } else { + mLauncherClings.showFirstRunCling(); + } + } else { + mLauncherClings.removeFirstRunAndMigrationClings(); + } + IntentFilter protectedAppsFilter = new IntentFilter( + "cyanogenmod.intent.action.PROTECTED_COMPONENT_UPDATE"); + registerReceiver(protectedAppsChangedReceiver, protectedAppsFilter, + "cyanogenmod.permission.PROTECTED_APP", null); + } + + public void restoreGelSetting() { + mGelIntegrationEnabled = SettingsProvider.getBoolean(this, + SettingsProvider.SETTINGS_UI_HOMESCREEN_SEARCH_SCREEN_LEFT, + R.bool.preferences_interface_homescreen_search_screen_left_default); + } + + void initializeDynamicGrid() { + LauncherAppState.setApplicationContext(getApplicationContext()); + LauncherAppState app = LauncherAppState.getInstance(); + + mHideIconLabels = SettingsProvider.getBoolean(this, + SettingsProvider.SETTINGS_UI_HOMESCREEN_HIDE_ICON_LABELS, + R.bool.preferences_interface_homescreen_hide_icon_labels_default); + + restoreGelSetting(); + + // Determine the dynamic grid properties + Point smallestSize = new Point(); + Point largestSize = new Point(); + Point realSize = new Point(); + Display display = getWindowManager().getDefaultDisplay(); + display.getCurrentSizeRange(smallestSize, largestSize); + display.getRealSize(realSize); + DisplayMetrics dm = new DisplayMetrics(); + display.getMetrics(dm); + // Lazy-initialize the dynamic grid + mGrid = app.initDynamicGrid(this, + Math.min(smallestSize.x, smallestSize.y), + Math.min(largestSize.x, largestSize.y), + realSize.x, realSize.y, + dm.widthPixels, dm.heightPixels); + + mModel = app.setLauncher(this); + mIconCache = app.getIconCache(); + mIconCache.flushInvalidIcons(mGrid); } protected void onUserLeaveHint() { @@ -496,17 +583,64 @@ public class Launcher extends Activity sPausedFromUserAction = true; } - /** To be overriden by subclasses to hint to Launcher that we have custom content */ - protected boolean hasCustomContentToLeft() { + /** To be overridden by subclasses to hint to Launcher that we have custom content */ + protected boolean hasCustomSearchSupport() { return false; } + protected boolean hasCustomContentToLeft() { + return isGelIntegrationSupported() && isGelIntegrationEnabled(); + } + + public boolean isGelIntegrationSupported() { + final SearchManager searchManager = + (SearchManager) getSystemService(Context.SEARCH_SERVICE); + ComponentName globalSearchActivity = searchManager.getGlobalSearchActivity(); + + // Currently the only custom content available is the GEL launcher integration, + // only supported on CyanogenMod. + return globalSearchActivity != null && isCM(); + } + + public boolean isGelIntegrationEnabled() { + return mGelIntegrationEnabled; + } + + public void onCustomContentLaunch() { + if(isGelIntegrationEnabled() && isGelIntegrationSupported()) { + GelIntegrationHelper.getInstance().registerSwipeBackGestureListenerAndStartGel(this, mWorkspace.isLayoutRtl()); + } + } + + /** + * Check if the device running this application is running CyanogenMod. + * @return true if this device is running CM. + */ + protected boolean isCM() { + return getPackageManager().hasSystemFeature("com.cyanogenmod.android"); + } + /** * To be overridden by subclasses to create the custom content and call * {@link #addToCustomContentPage}. This will only be invoked if * {@link #hasCustomContentToLeft()} is {@code true}. */ - protected void addCustomContentToLeft() { + protected void populateCustomContentContainer() { + } + + /** + * To be overridden by subclasses to indicate that there is an activity to launch + * before showing the standard launcher experience. + */ + protected boolean hasFirstRunActivity() { + return false; + } + + /** + * To be overridden by subclasses to launch any first run activity + */ + protected Intent getFirstRunActivity() { + return null; } /** @@ -521,13 +655,22 @@ public class Launcher extends Activity if (!mWorkspace.hasCustomContent() && hasCustomContentToLeft()) { // Create the custom content page and call the subclass to populate it. - mWorkspace.createCustomContentPage(); - addCustomContentToLeft(); + mWorkspace.createCustomContentContainer(); + populateCustomContentContainer(); } else if (mWorkspace.hasCustomContent() && !hasCustomContentToLeft()) { mWorkspace.removeCustomContentPage(); } } + /** To be overriden by subclasses to hint to Launcher that we have custom content and + * support {@link #hasCustomSearchSupport()} + * @see com.android.launcher.home.Home#MODE_SEARCH_TEXT + * @see com.android.launcher.home.Home#MODE_SEARCH_VOICE + * */ + protected void requestSearch(int mode) { + // To be implemented + } + private void updateGlobalIcons() { boolean searchVisible = false; boolean voiceVisible = false; @@ -590,12 +733,12 @@ public class Launcher extends Activity mIconCache.flush(); final LocaleConfiguration localeConfiguration = sLocaleConfiguration; - new Thread("WriteLocaleConfiguration") { - @Override - public void run() { + new AsyncTask<Void, Void, Void>() { + public Void doInBackground(Void ... args) { writeConfiguration(Launcher.this, localeConfiguration); + return null; } - }.start(); + }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void) null); } } @@ -659,10 +802,6 @@ public class Launcher extends Activity return mInflater; } - public DragLayer getDragLayer() { - return mDragLayer; - } - boolean isDraggingEnabled() { // We prevent dragging when we are loading the workspace as it is possible to pick up a view // that is subsequently removed from the workspace in startBinding(). @@ -682,6 +821,34 @@ public class Launcher extends Activity } /** + * Copied from View -- the View version of the method isn't called + * anywhere else in our process and only exists for API level 17+, + * so it's ok to keep our own version with no API requirement. + */ + public static int generateViewId() { + for (;;) { + final int result = sNextGeneratedId.get(); + // aapt-generated IDs have the high byte nonzero; clamp to the range under that. + int newValue = result + 1; + if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0. + if (sNextGeneratedId.compareAndSet(result, newValue)) { + return result; + } + } + } + + public int getViewIdForItem(ItemInfo info) { + // This cast is safe given the > 2B range for int. + int itemId = (int) info.id; + if (mItemIdToViewId.containsKey(itemId)) { + return mItemIdToViewId.get(itemId); + } + int viewId = generateViewId(); + mItemIdToViewId.put(itemId, viewId); + return viewId; + } + + /** * Returns whether we should delay spring loaded mode -- for shortcuts and widgets that have * a configuration step, this allows the proper animations to run after other transitions. */ @@ -718,14 +885,27 @@ public class Launcher extends Activity final int requestCode, final int resultCode, final Intent data) { // Reset the startActivity waiting flag mWaitingForResult = false; + int pendingAddWidgetId = mPendingAddWidgetId; + mPendingAddWidgetId = -1; + + Runnable exitSpringLoaded = new Runnable() { + @Override + public void run() { + exitSpringLoadedDragModeDelayed((resultCode != RESULT_CANCELED), + EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT, null); + } + }; if (requestCode == REQUEST_BIND_APPWIDGET) { - int appWidgetId = data != null ? + final int appWidgetId = data != null ? data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1) : -1; if (resultCode == RESULT_CANCELED) { completeTwoStageWidgetDrop(RESULT_CANCELED, appWidgetId); + mWorkspace.removeExtraEmptyScreen(true, exitSpringLoaded, + ON_ACTIVITY_RESULT_ANIMATION_DELAY, false); } else if (resultCode == RESULT_OK) { - addAppWidgetImpl(appWidgetId, mPendingAddInfo, null, mPendingAddWidgetInfo); + addAppWidgetImpl(appWidgetId, mPendingAddInfo, null, + mPendingAddWidgetInfo, ON_ACTIVITY_RESULT_ANIMATION_DELAY); } return; } else if (requestCode == REQUEST_PICK_WALLPAPER) { @@ -733,24 +913,67 @@ public class Launcher extends Activity mWorkspace.exitOverviewMode(false); } return; + } else if (requestCode == REQUEST_LOCK_PATTERN) { + mHiddenFolderAuth = true; + switch (resultCode) { + case RESULT_OK: + FragmentManager fragmentManager = getFragmentManager(); + FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); + + fragmentTransaction.setCustomAnimations(0, 0); + fragmentTransaction.replace(R.id.launcher, mHiddenFolderFragment, + HiddenFolderFragment.HIDDEN_FOLDER_FRAGMENT); + fragmentTransaction.commit(); + break; + case RESULT_CANCELED: + // User failed to enter/confirm a lock pattern, back out + break; + } + return; } - boolean delayExitSpringLoadedMode = false; boolean isWidgetDrop = (requestCode == REQUEST_PICK_APPWIDGET || requestCode == REQUEST_CREATE_APPWIDGET); // We have special handling for widgets if (isWidgetDrop) { - int appWidgetId = data != null ? - data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1) : -1; - if (appWidgetId < 0) { + final int appWidgetId; + int widgetId = data != null ? data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1) + : -1; + if (widgetId < 0) { + appWidgetId = pendingAddWidgetId; + } else { + appWidgetId = widgetId; + } + + final int result; + final Runnable onComplete; + if (appWidgetId < 0 || resultCode == RESULT_CANCELED) { Log.e(TAG, "Error: appWidgetId (EXTRA_APPWIDGET_ID) was not returned from the \\" + "widget configuration activity."); - completeTwoStageWidgetDrop(RESULT_CANCELED, appWidgetId); - mWorkspace.stripEmptyScreens(); + result = RESULT_CANCELED; + completeTwoStageWidgetDrop(result, appWidgetId); + onComplete = new Runnable() { + @Override + public void run() { + exitSpringLoadedDragModeDelayed(false, 0, null); + } + }; } else { - completeTwoStageWidgetDrop(resultCode, appWidgetId); + result = resultCode; + final CellLayout dropLayout = + (CellLayout) mWorkspace.getScreenWithId(mPendingAddInfo.screenId); + dropLayout.setDropPending(true); + onComplete = new Runnable() { + @Override + public void run() { + completeTwoStageWidgetDrop(result, appWidgetId); + dropLayout.setDropPending(false); + } + }; } + mWorkspace.removeExtraEmptyScreen(true, onComplete, ON_ACTIVITY_RESULT_ANIMATION_DELAY, + false); return; } @@ -770,15 +993,15 @@ public class Launcher extends Activity if (isWorkspaceLocked()) { sPendingAddList.add(args); } else { - delayExitSpringLoadedMode = completeAdd(args); + completeAdd(args); } + mWorkspace.removeExtraEmptyScreen(true, exitSpringLoaded, + ON_ACTIVITY_RESULT_ANIMATION_DELAY, false); } else if (resultCode == RESULT_CANCELED) { - mWorkspace.stripEmptyScreens(); + mWorkspace.removeExtraEmptyScreen(true, exitSpringLoaded, + ON_ACTIVITY_RESULT_ANIMATION_DELAY, false); } mDragLayer.clearAnimatedView(); - // Exit spring loaded mode if necessary after cancelling the configuration of a widget - exitSpringLoadedDragModeDelayed((resultCode != RESULT_CANCELED), delayExitSpringLoadedMode, - null); } private void completeTwoStageWidgetDrop(final int resultCode, final int appWidgetId) { @@ -798,25 +1021,19 @@ public class Launcher extends Activity public void run() { completeAddAppWidget(appWidgetId, mPendingAddInfo.container, mPendingAddInfo.screenId, layout, null); - exitSpringLoadedDragModeDelayed((resultCode != RESULT_CANCELED), false, - null); + exitSpringLoadedDragModeDelayed((resultCode != RESULT_CANCELED), + EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT, null); } }; } else if (resultCode == RESULT_CANCELED) { + mAppWidgetHost.deleteAppWidgetId(appWidgetId); animationType = Workspace.CANCEL_TWO_STAGE_WIDGET_DROP_ANIMATION; - onCompleteRunnable = new Runnable() { - @Override - public void run() { - exitSpringLoadedDragModeDelayed((resultCode != RESULT_CANCELED), false, - null); - } - }; } if (mDragLayer.getAnimatedView() != null) { mWorkspace.animateWidgetDrop(mPendingAddInfo, cellLayout, (DragView) mDragLayer.getAnimatedView(), onCompleteRunnable, animationType, boundWidget, true); - } else { + } else if (onCompleteRunnable != null) { // The animated view may be null in the case of a rotation during widget configuration onCompleteRunnable.run(); } @@ -843,15 +1060,15 @@ public class Launcher extends Activity } super.onResume(); - if (settingsChanged()) { - android.os.Process.killProcess(android.os.Process.myPid()); + if(isGelIntegrationEnabled() && isGelIntegrationSupported()) { + GelIntegrationHelper.getInstance().handleGelResume(); } // Restore the previous launcher state if (mOnResumeState == State.WORKSPACE) { showWorkspace(false); } else if (mOnResumeState == State.APPS_CUSTOMIZE) { - showAllApps(false, AppsCustomizePagedView.ContentType.Applications, false); + showAllApps(false, mAppsCustomizeContent.getContentType(), false); } mOnResumeState = State.NONE; @@ -862,7 +1079,7 @@ public class Launcher extends Activity sPausedFromUserAction = false; if (mRestoring || mOnResumeNeedsLoad) { mWorkspaceLoading = true; - mModel.startLoader(true, -1); + mModel.startLoader(true, PagedView.INVALID_RESTORE_PAGE); mRestoring = false; mOnResumeNeedsLoad = false; } @@ -937,6 +1154,29 @@ public class Launcher extends Activity mWorkspace.updateInteractionForState(); mWorkspace.onResume(); mAppsCustomizeContent.onResume(); + + //Close out Fragments + Fragment f = getFragmentManager().findFragmentByTag( + TransitionEffectsFragment.TRANSITION_EFFECTS_FRAGMENT); + if (f != null) { + mTransitionEffectsFragment.setEffect(); + } + f = getFragmentManager().findFragmentByTag( + DynamicGridSizeFragment.DYNAMIC_GRID_SIZE_FRAGMENT); + if (f != null) { + mDynamicGridSizeFragment.setSize(); + mWorkspace.hideOutlines(); + } + Fragment f1 = getFragmentManager().findFragmentByTag( + HiddenFolderFragment.HIDDEN_FOLDER_FRAGMENT); + if (f1 != null && !mHiddenFolderAuth) { + mHiddenFolderFragment.saveHiddenFolderStatus(-1); + FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction(); + fragmentTransaction + .remove(mHiddenFolderFragment).commit(); + } else { + mHiddenFolderAuth = false; + } } @Override @@ -954,12 +1194,9 @@ public class Launcher extends Activity if (mWorkspace.getCustomContentCallbacks() != null) { mWorkspace.getCustomContentCallbacks().onHide(); } - } - protected void onFinishBindingItems() { - if (mWorkspace != null && hasCustomContentToLeft() && mWorkspace.hasCustomContent()) { - addCustomContentToLeft(); - } + //Reset the OverviewPanel position + ((SlidingUpPanelLayout) mOverviewPanel).collapsePane(); } QSBScroller mQsbScroller = new QSBScroller() { @@ -969,6 +1206,7 @@ public class Launcher extends Activity public void setScrollY(int scroll) { scrollY = scroll; + // Be careful of feature check isSearchBarEnabled if (mWorkspace.isOnOrMovingToCustomContent()) { mSearchDropTargetBar.setTranslationY(- scrollY); getQsbBar().setTranslationY(-scrollY); @@ -978,7 +1216,9 @@ public class Launcher extends Activity public void resetQSBScroll() { mSearchDropTargetBar.animate().translationY(0).start(); - getQsbBar().animate().translationY(0).start(); + if (isSearchBarEnabled()) { + getQsbBar().animate().translationY(0).start(); + } } public interface CustomContentCallbacks { @@ -992,17 +1232,11 @@ public class Launcher extends Activity public void onScrollProgressChanged(float progress); } - protected void startSettings() { - Intent settings; - // If we are on CyanogenMod the launcher settings are accessed from system settings. - if (!getPackageManager().hasSystemFeature("com.cyanogenmod.android")) { - settings = new Intent().setClass(this, SettingsActivity.class); - settings.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK - | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); - } else { - settings = new Intent(android.provider.Settings.ACTION_SETTINGS); - } + protected void startThemeSettings() { + Intent settings = new Intent().setClassName(OverviewSettingsPanel.ANDROID_SETTINGS, + OverviewSettingsPanel.THEME_SETTINGS); startActivity(settings); + if (mWorkspace.isInOverviewMode()) { mWorkspace.exitOverviewMode(false); } else if (mAppsCustomizeContent.isInOverviewMode()) { @@ -1038,89 +1272,88 @@ public class Launcher extends Activity mAppsCustomizeContent.setSortMode(AppsCustomizePagedView.SortMode.LaunchCount); break; } + mOverviewSettingsPanel.notifyDataSetInvalidated(); + SettingsProvider.putInt(getBaseContext(), SettingsProvider.SETTINGS_UI_DRAWER_SORT_MODE, + mAppsCustomizeContent.getSortMode().getValue()); return true; } }); popupMenu.show(); } - public void onClickTransitionEffectButton(View v) { - AlertDialog.Builder builder = new AlertDialog.Builder(this); + public void onClickDynamicGridSizeButton() { + FragmentManager fragmentManager = getFragmentManager(); + FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); - // Load values - final PagedView pagedView = isAllAppsVisible() ? mAppsCustomizeContent : mWorkspace; - final PagedView.TransitionEffect oldEffect = pagedView.getTransitionEffect(); - final String oldEffectName = oldEffect != null ? oldEffect.getName() : - PagedView.TransitionEffect.TRANSITION_EFFECT_NONE; + mDynamicGridSizeFragment = new DynamicGridSizeFragment(); + fragmentTransaction.replace(R.id.launcher, mDynamicGridSizeFragment, + DynamicGridSizeFragment.DYNAMIC_GRID_SIZE_FRAGMENT); + fragmentTransaction.commit(); + } - final String[] titles = getResources().getStringArray(R.array.transition_effect_entries); - final String[] values = getResources().getStringArray(R.array.transition_effect_values); + public void setDynamicGridSize(DeviceProfile.GridSize size) { + SettingsProvider.putInt(this, + SettingsProvider.SETTINGS_UI_DYNAMIC_GRID_SIZE, size.getValue()); - int selected = -1; - for (int i = values.length - 1; i >= 0; i--) { - if (values[i].equals(oldEffectName)) { - selected = i; - break; - } - } + updateDynamicGrid(); - // Create title view with overflow menu - View customTitle = getLayoutInflater().inflate(R.layout.dialog_title_overflow_menu, null); - TextView title = (TextView) customTitle.findViewById(android.R.id.title); - title.setText(R.string.transition_effect_button_text); + mOverviewSettingsPanel.notifyDataSetInvalidated(); - View overflowMenu = customTitle.findViewById(R.id.overflow_menu_button); - overflowMenu.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - onClickTransitionEffectOverflowMenuButton(v); - } - }); + FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction(); + fragmentTransaction + .setCustomAnimations(0, R.anim.exit_out_right); + fragmentTransaction + .remove(mDynamicGridSizeFragment).commit(); - builder.setCustomTitle(customTitle); + mDarkPanel.setVisibility(View.VISIBLE); + ObjectAnimator anim = ObjectAnimator.ofFloat( + mDarkPanel, "alpha", 0.3f, 0.0f); + anim.start(); + anim.addListener(mAnimatorListener); - builder.setSingleChoiceItems(titles, selected, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - String effect = values[which]; - PagedView.TransitionEffect.setFromString(pagedView, effect); - - // Show the changes immediately - final int currentPage = pagedView.getNextPage(); - final int nextPage = currentPage + (currentPage != pagedView.getPageCount() - 1 ? 1 : -1); - pagedView.snapToPageImmediately(currentPage); - pagedView.snapToPage(nextPage, new Runnable() { - @Override - public void run() { - pagedView.snapToPage(currentPage); - } - }); + } - SettingsProvider.get(Launcher.this).edit() - .putString(!isAllAppsVisible() ? - SettingsProvider.SETTINGS_UI_HOMESCREEN_SCROLLING_TRANSITION_EFFECT : - SettingsProvider.SETTINGS_UI_DRAWER_SCROLLING_TRANSITION_EFFECT, effect) - .commit(); - } - }); + public void onClickTransitionEffectButton(View v, final boolean pageOrDrawer) { + Bundle bundle = new Bundle(); + bundle.putBoolean(TransitionEffectsFragment.PAGE_OR_DRAWER_SCROLL_SELECT, + pageOrDrawer); + FragmentManager fragmentManager = getFragmentManager(); + FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); - if (isAllAppsVisible()) { - mAppsCustomizeContent.exitOverviewMode(true); - } else { - mWorkspace.exitOverviewMode(true); - } + mTransitionEffectsFragment = new TransitionEffectsFragment(); + mTransitionEffectsFragment.setArguments(bundle); + fragmentTransaction.setCustomAnimations(0, 0); + fragmentTransaction.replace(R.id.launcher, mTransitionEffectsFragment, + TransitionEffectsFragment.TRANSITION_EFFECTS_FRAGMENT); + fragmentTransaction.commit(); + } - builder.setPositiveButton(android.R.string.ok, null) - .setOnDismissListener(new DialogInterface.OnDismissListener() { - @Override - public void onDismiss(DialogInterface dialog) { - mTransitionEffectDialog = null; - } - }); - mTransitionEffectDialog = builder.create(); - mTransitionEffectDialog.show(); - mTransitionEffectDialog.setCanceledOnTouchOutside(true); - mTransitionEffectDialog.getWindow().getDecorView().setAlpha(0.6f); + public void setTransitionEffect(boolean pageOrDrawer, String newTransitionEffect) { + String mSettingsProviderValue = pageOrDrawer ? + SettingsProvider.SETTINGS_UI_DRAWER_SCROLLING_TRANSITION_EFFECT + : SettingsProvider.SETTINGS_UI_HOMESCREEN_SCROLLING_TRANSITION_EFFECT; + PagedView pagedView = pageOrDrawer ? mAppsCustomizeContent : mWorkspace; + + SettingsProvider + .get(getApplicationContext()) + .edit() + .putString(mSettingsProviderValue, + newTransitionEffect).commit(); + TransitionEffect.setFromString(pagedView, newTransitionEffect); + + mOverviewSettingsPanel.notifyDataSetInvalidated(); + + FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction(); + fragmentTransaction + .setCustomAnimations(0, R.anim.exit_out_right); + fragmentTransaction + .remove(mTransitionEffectsFragment).commit(); + + mDarkPanel.setVisibility(View.VISIBLE); + ObjectAnimator anim = ObjectAnimator.ofFloat( + mDarkPanel, "alpha", 0.3f, 0.0f); + anim.start(); + anim.addListener(mAnimatorListener); } public void onClickTransitionEffectOverflowMenuButton(View v) { @@ -1175,6 +1408,13 @@ public class Launcher extends Activity popupMenu.show(); } + protected boolean hasSettings() { + return false; + } + + protected void startSettings() { + } + public interface QSBScroller { public void setScrollY(int scrollY); } @@ -1271,6 +1511,7 @@ public class Launcher extends Activity * * @param savedState The previous state. */ + @SuppressWarnings("unchecked") private void restoreState(Bundle savedState) { if (savedState == null) { return; @@ -1298,6 +1539,7 @@ public class Launcher extends Activity mPendingAddInfo.spanX = savedState.getInt(RUNTIME_STATE_PENDING_ADD_SPAN_X); mPendingAddInfo.spanY = savedState.getInt(RUNTIME_STATE_PENDING_ADD_SPAN_Y); mPendingAddWidgetInfo = savedState.getParcelable(RUNTIME_STATE_PENDING_ADD_WIDGET_INFO); + mPendingAddWidgetId = savedState.getInt(RUNTIME_STATE_PENDING_ADD_WIDGET_ID); mWaitingForResult = true; mRestoring = true; } @@ -1321,6 +1563,8 @@ public class Launcher extends Activity int currentIndex = savedState.getInt("apps_customize_currentIndex"); mAppsCustomizeContent.restorePageForIndex(currentIndex); } + mItemIdToViewId = (HashMap<Integer, Integer>) + savedState.getSerializable(RUNTIME_STATE_VIEW_IDS); } /** @@ -1332,6 +1576,7 @@ public class Launcher extends Activity mLauncherView = findViewById(R.id.launcher); mDragLayer = (DragLayer) findViewById(R.id.drag_layer); mWorkspace = (Workspace) mDragLayer.findViewById(R.id.workspace); + mPageIndicators = mDragLayer.findViewById(R.id.page_indicator); mLauncherView.setSystemUiVisibility( View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION); @@ -1348,78 +1593,11 @@ public class Launcher extends Activity } mOverviewPanel = findViewById(R.id.overview_panel); - mOverviewPanel.setAlpha(0f); - View widgetButton = findViewById(R.id.widget_button); - widgetButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View arg0) { - showAllApps(true, AppsCustomizePagedView.ContentType.Widgets, true); - } - }); - widgetButton.setOnTouchListener(getHapticFeedbackTouchListener()); - - View wallpaperButton = findViewById(R.id.wallpaper_button); - wallpaperButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View arg0) { - startWallpaper(); - } - }); - wallpaperButton.setOnTouchListener(getHapticFeedbackTouchListener()); - - View settingsButton = findViewById(R.id.settings_button); - settingsButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View arg0) { - startSettings(); - } - }); - settingsButton.setOnTouchListener(getHapticFeedbackTouchListener()); - - View defaultScreenButton = findViewById(R.id.default_screen_button); - defaultScreenButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View arg0) { - mWorkspace.onClickDefaultScreenButton(); - } - }); - defaultScreenButton.setOnTouchListener(getHapticFeedbackTouchListener()); - - View transitionEffectButton = findViewById(R.id.transition_effect_button); - transitionEffectButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View arg0) { - onClickTransitionEffectButton(arg0); - } - }); - transitionEffectButton.setOnTouchListener(getHapticFeedbackTouchListener()); - - View iconPackButton = findViewById(R.id.icon_pack_button); - iconPackButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View arg0) { - IconPackHelper.pickIconPack(Launcher.this, false); - } - }); - iconPackButton.setOnTouchListener(getHapticFeedbackTouchListener()); - - View sortButton = findViewById(R.id.sort_button); - sortButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View arg0) { - onClickSortModeButton(arg0); - } - }); - sortButton.setOnTouchListener(getHapticFeedbackTouchListener()); - - View filterButton = findViewById(R.id.filter_button); - filterButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - - } - }); - filterButton.setOnTouchListener(getHapticFeedbackTouchListener()); + mOverviewSettingsPanel = new OverviewSettingsPanel( + this, mOverviewPanel); + mOverviewSettingsPanel.initializeAdapter(); + mOverviewSettingsPanel.initializeViews(); + mDarkPanel = ((SlidingUpPanelLayout) mOverviewPanel).findViewById(R.id.dark_panel); // Setup the workspace mWorkspace.setHapticFeedbackEnabled(false); @@ -1428,7 +1606,8 @@ public class Launcher extends Activity dragController.addDragListener(mWorkspace); // Get the search/delete bar - mSearchDropTargetBar = (SearchDropTargetBar) mDragLayer.findViewById(R.id.qsb_bar); + mSearchDropTargetBar = (SearchDropTargetBar) + mDragLayer.findViewById(R.id.search_drop_target_bar); // Setup AppsCustomize mAppsCustomizeLayout = (AppsCustomizeLayout) findViewById(R.id.apps_customize_pane); @@ -1494,7 +1673,6 @@ public class Launcher extends Activity favorite.setCompoundDrawables(null, d, null, null); favorite.setOnTouchListener(getHapticFeedbackTouchListener()); } - Utilities.applyTypeface(favorite); return favorite; } @@ -1662,11 +1840,12 @@ public class Launcher extends Activity if (appWidgetId != -1) { // Deleting an app widget ID is a void call but writes to disk before returning // to the caller... - new Thread("deleteAppWidgetId") { - public void run() { + new AsyncTask<Void, Void, Void>() { + public Void doInBackground(Void ... args) { mAppWidgetHost.deleteAppWidgetId(appWidgetId); + return null; } - }.start(); + }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void) null); } showOutOfSpaceMessage(isHotseatLayout(layout)); return; @@ -1722,6 +1901,15 @@ public class Launcher extends Activity } else if (Intent.ACTION_USER_PRESENT.equals(action)) { mUserPresent = true; updateRunning(); + } else if (ENABLE_DEBUG_INTENTS && DebugIntents.DELETE_DATABASE.equals(action)) { + mModel.resetLoadedState(false, true); + mModel.startLoader(false, PagedView.INVALID_RESTORE_PAGE, + LauncherModel.LOADER_FLAG_CLEAR_WORKSPACE); + } else if (ENABLE_DEBUG_INTENTS && DebugIntents.MIGRATE_DATABASE.equals(action)) { + mModel.resetLoadedState(false, true); + mModel.startLoader(false, PagedView.INVALID_RESTORE_PAGE, + LauncherModel.LOADER_FLAG_CLEAR_WORKSPACE + | LauncherModel.LOADER_FLAG_MIGRATE_SHORTCUTS); } } }; @@ -1734,6 +1922,10 @@ public class Launcher extends Activity final IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_SCREEN_OFF); filter.addAction(Intent.ACTION_USER_PRESENT); + if (ENABLE_DEBUG_INTENTS) { + filter.addAction(DebugIntents.DELETE_DATABASE); + filter.addAction(DebugIntents.MIGRATE_DATABASE); + } registerReceiver(mReceiver, filter); FirstFrameAnimatorHelper.initializeDrawListener(getWindow().getDecorView()); mAttached = true; @@ -1869,6 +2061,30 @@ public class Launcher extends Activity Toast.makeText(this, getString(strId), Toast.LENGTH_SHORT).show(); } + public DragLayer getDragLayer() { + return mDragLayer; + } + + public Workspace getWorkspace() { + return mWorkspace; + } + + public Hotseat getHotseat() { + return mHotseat; + } + + public View getDarkPanel() { + return mDarkPanel; + } + + public View getOverviewPanel() { + return mOverviewPanel; + } + + public SearchDropTargetBar getSearchBar() { + return mSearchDropTargetBar; + } + public LauncherAppWidgetHost getAppWidgetHost() { return mAppWidgetHost; } @@ -1877,6 +2093,14 @@ public class Launcher extends Activity return mModel; } + public LauncherClings getLauncherClings() { + return mLauncherClings; + } + + protected SharedPreferences getSharedPrefs() { + return mSharedPrefs; + } + public void closeSystemDialogs() { getWindow().closeAllPanels(); @@ -1913,7 +2137,7 @@ public class Launcher extends Activity // In all these cases, only animate if we're already on home mWorkspace.exitWidgetResizeMode(); if (alreadyOnHome && mState == State.WORKSPACE && !mWorkspace.isTouchActive() && - openFolder == null) { + openFolder == null && shouldMoveToDefaultScreenOnHomeIntent()) { mWorkspace.moveToDefaultScreen(true); } @@ -1936,9 +2160,11 @@ public class Launcher extends Activity } // Reset the apps customize page - if (mAppsCustomizeLayout != null) { + if (!alreadyOnHome && mAppsCustomizeLayout != null) { mAppsCustomizeLayout.reset(); } + + onHomeIntent(); } if (DEBUG_RESUME_TIME) { @@ -1946,6 +2172,21 @@ public class Launcher extends Activity } } + /** + * Override point for subclasses to prevent movement to the default screen when the home + * button is pressed. Used (for example) in GEL, to prevent movement during a search. + */ + protected boolean shouldMoveToDefaultScreenOnHomeIntent() { + return true; + } + + /** + * Override point for subclasses to provide custom behaviour for when a home intent is fired. + */ + protected void onHomeIntent() { + // Do nothing + } + @Override public void onRestoreInstanceState(Bundle state) { super.onRestoreInstanceState(state); @@ -1957,7 +2198,8 @@ public class Launcher extends Activity @Override protected void onSaveInstanceState(Bundle outState) { if (mWorkspace.getChildCount() > 0) { - outState.putInt(RUNTIME_STATE_CURRENT_SCREEN, mWorkspace.getRestorePage()); + outState.putInt(RUNTIME_STATE_CURRENT_SCREEN, + mWorkspace.getCurrentPageOffsetFromCustomContent()); } super.onSaveInstanceState(outState); @@ -1975,6 +2217,7 @@ public class Launcher extends Activity outState.putInt(RUNTIME_STATE_PENDING_ADD_SPAN_X, mPendingAddInfo.spanX); outState.putInt(RUNTIME_STATE_PENDING_ADD_SPAN_Y, mPendingAddInfo.spanY); outState.putParcelable(RUNTIME_STATE_PENDING_ADD_WIDGET_INFO, mPendingAddWidgetInfo); + outState.putInt(RUNTIME_STATE_PENDING_ADD_WIDGET_ID, mPendingAddWidgetId); } if (mFolderInfo != null && mWaitingForResult) { @@ -1984,6 +2227,7 @@ public class Launcher extends Activity // Save the current AppsCustomize tab if (mAppsCustomizeLayout != null) { + AppsCustomizePagedView.ContentType type = mAppsCustomizeContent.getContentType(); String currentTabTag = mAppsCustomizeContent.getContentType().name(); if (currentTabTag != null) { outState.putString("apps_customize_currentContentType", currentTabTag); @@ -1991,6 +2235,7 @@ public class Launcher extends Activity int currentIndex = mAppsCustomizeContent.getSaveInstanceStateIndex(); outState.putInt("apps_customize_currentIndex", currentIndex); } + outState.putSerializable(RUNTIME_STATE_VIEW_IDS, mItemIdToViewId); } @Override @@ -2029,17 +2274,33 @@ public class Launcher extends Activity mDragLayer.clearAllResizeFrames(); ((ViewGroup) mWorkspace.getParent()).removeAllViews(); - mWorkspace.removeAllViews(); + mWorkspace.removeAllWorkspaceScreens(); mWorkspace = null; mDragController = null; LauncherAnimUtils.onDestroyActivity(); + + unregisterReceiver(protectedAppsChangedReceiver); } public DragController getDragController() { return mDragController; } + public void validateLockForHiddenFolders(Bundle bundle, FolderIcon info) { + // Validate Lock Pattern + Intent lockPatternActivity = new Intent(); + lockPatternActivity.setClassName( + "com.android.settings", + "com.android.settings.applications.LockPatternActivity"); + startActivityForResult(lockPatternActivity, REQUEST_LOCK_PATTERN); + mHiddenFolderAuth = false; + + mHiddenFolderIcon = info; + mHiddenFolderFragment = new HiddenFolderFragment(); + mHiddenFolderFragment.setArguments(bundle); + } + @Override public void startActivityForResult(Intent intent, int requestCode) { if (requestCode >= 0) mWaitingForResult = true; @@ -2119,29 +2380,28 @@ public class Launcher extends Activity } } + public boolean isOnCustomContent() { + return mWorkspace.isOnOrMovingToCustomContent(); + } + @Override public boolean onPrepareOptionsMenu(Menu menu) { super.onPrepareOptionsMenu(menu); - if (!isAllAppsVisible()) { + if (!isOnCustomContent()) { + // Close any open folders + closeFolder(); + // Stop resizing any widgets + mWorkspace.exitWidgetResizeMode(); if (!mWorkspace.isInOverviewMode()) { - mWorkspace.enterOverviewMode(); - } else { - mWorkspace.exitOverviewMode(true); - } - } else { - if (!mAppsCustomizeContent.isInOverviewMode()) { - mAppsCustomizeContent.enterOverviewMode(); + // Show the overview mode + showOverviewMode(true); } else { - mAppsCustomizeContent.exitOverviewMode(true); + showWorkspace(true); } } return false; } - void enterAllAppsOverviewMode() { - mAppsCustomizeContent.enterOverviewMode(); - } - @Override public boolean onSearchRequested() { startSearch(null, false, null, true); @@ -2153,6 +2413,10 @@ public class Launcher extends Activity return mWorkspaceLoading || mWaitingForResult; } + public boolean isWorkspaceLoading() { + return mWorkspaceLoading; + } + private void resetAddInfo() { mPendingAddInfo.container = ItemInfo.NO_ID; mPendingAddInfo.screenId = -1; @@ -2162,10 +2426,17 @@ public class Launcher extends Activity mPendingAddInfo.dropPos = null; } - void addAppWidgetImpl(final int appWidgetId, ItemInfo info, AppWidgetHostView boundWidget, - AppWidgetProviderInfo appWidgetInfo) { + void addAppWidgetImpl(final int appWidgetId, final ItemInfo info, + final AppWidgetHostView boundWidget, final AppWidgetProviderInfo appWidgetInfo) { + addAppWidgetImpl(appWidgetId, info, boundWidget, appWidgetInfo, 0); + } + + void addAppWidgetImpl(final int appWidgetId, final ItemInfo info, + final AppWidgetHostView boundWidget, final AppWidgetProviderInfo appWidgetInfo, int + delay) { if (appWidgetInfo.configure != null) { mPendingAddWidgetInfo = appWidgetInfo; + mPendingAddWidgetId = appWidgetId; // Launch over to configure widget, if needed Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE); @@ -2174,10 +2445,17 @@ public class Launcher extends Activity Utilities.startActivityForResultSafely(this, intent, REQUEST_CREATE_APPWIDGET); } else { // Otherwise just add it + Runnable onComplete = new Runnable() { + @Override + public void run() { + // Exit spring loaded mode if necessary after adding the widget + exitSpringLoadedDragModeDelayed(true, EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT, + null); + } + }; completeAddAppWidget(appWidgetId, info.container, info.screenId, boundWidget, appWidgetInfo); - // Exit spring loaded mode if necessary after adding the widget - exitSpringLoadedDragModeDelayed(true, false, null); + mWorkspace.removeExtraEmptyScreen(true, onComplete, delay, false); } } @@ -2327,7 +2605,7 @@ public class Launcher extends Activity } protected ComponentName getWallpaperPickerComponent() { - return new ComponentName(WALLPAPER_PICKER_PACKAGE, WALLPAPER_PICKER_ACTIVITY); + return new ComponentName(getPackageName(), LauncherWallpaperPickerActivity.class.getName()); } /** @@ -2365,10 +2643,15 @@ public class Launcher extends Activity @Override public void onBackPressed() { + Fragment f1 = getFragmentManager().findFragmentByTag( + HiddenFolderFragment.HIDDEN_FOLDER_FRAGMENT); + if (f1 != null) { + mHiddenFolderFragment.saveHiddenFolderStatus(-1); + FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction(); + fragmentTransaction + .remove(mHiddenFolderFragment).commit(); + } if (isAllAppsVisible()) { - if (isClingsEnabled()) { - dismissAllAppsCling(null); - } if (mAppsCustomizeContent.isInOverviewMode()) { mAppsCustomizeContent.exitOverviewMode(true); } else { @@ -2380,7 +2663,17 @@ public class Launcher extends Activity } } } else if (mWorkspace.isInOverviewMode()) { - mWorkspace.exitOverviewMode(true); + Fragment f = getFragmentManager().findFragmentByTag( + TransitionEffectsFragment.TRANSITION_EFFECTS_FRAGMENT); + Fragment f2 = getFragmentManager().findFragmentByTag( + DynamicGridSizeFragment.DYNAMIC_GRID_SIZE_FRAGMENT); + if (f != null) { + mTransitionEffectsFragment.setEffect(); + } else if (f2 != null) { + mDynamicGridSizeFragment.setSize(); + } else { + mWorkspace.exitOverviewMode(true); + } } else if (mWorkspace.getOpenFolder() != null) { Folder openFolder = mWorkspace.getOpenFolder(); if (openFolder.isEditingName()) { @@ -2454,7 +2747,7 @@ public class Launcher extends Activity final String shortcutClass = intent.getComponent().getClassName(); if (shortcutClass.equals(WidgetAdder.class.getName())) { - showAllApps(true, AppsCustomizePagedView.ContentType.Widgets, true); + onClickAddWidgetButton(); return; } else if (shortcutClass.equals(MemoryDumpActivity.class.getName())) { MemoryDumpActivity.startDump(this); @@ -2504,8 +2797,12 @@ public class Launcher extends Activity * @param v The view that was clicked. */ public void onClickSearchButton(View v) { - v.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY); + if (hasCustomSearchSupport()) { + requestSearch(Home.MODE_SEARCH_TEXT); + return; + } + v.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY); onSearchRequested(); } @@ -2515,8 +2812,12 @@ public class Launcher extends Activity * @param v The view that was clicked. */ public void onClickVoiceButton(View v) { - v.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY); + if (hasCustomSearchSupport()) { + requestSearch(Home.MODE_SEARCH_VOICE); + return; + } + v.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY); startVoice(); } @@ -2545,7 +2846,15 @@ public class Launcher extends Activity * @param v The view that was clicked. */ public void onClickAllAppsButton(View v) { - showAllApps(true, AppsCustomizePagedView.ContentType.Applications, true); + showAllApps(true, AppsCustomizePagedView.ContentType.Applications, false); + } + + /** + * Event handler for the (Add) Widgets button that appears after a long press + * on the home screen. + */ + protected void onClickAddWidgetButton() { + showAllApps(true, AppsCustomizePagedView.ContentType.Widgets, true); } public void onTouchDownAllAppsButton(View v) { @@ -2592,9 +2901,10 @@ public class Launcher extends Activity void startApplicationDetailsActivity(ComponentName componentName) { String packageName = componentName.getPackageName(); - Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, + Intent intent = new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.fromParts("package", packageName, null)); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK | + Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); startActivitySafely(null, intent, "startApplicationDetailsActivity"); } @@ -2804,6 +3114,11 @@ public class Launcher extends Activity Folder folder = folderIcon.getFolder(); FolderInfo info = folder.mInfo; + if (info.hidden) { + folder.startHiddenFolderManager(); + return; + } + info.opened = true; // Just verify that the folder hasn't already been added to the DragLayer. @@ -2825,7 +3140,7 @@ public class Launcher extends Activity } public void closeFolder() { - Folder folder = mWorkspace.getOpenFolder(); + Folder folder = mWorkspace != null ? mWorkspace.getOpenFolder() : null; if (folder != null) { if (folder.isEditingName()) { folder.dismissEditingName(); @@ -2833,7 +3148,7 @@ public class Launcher extends Activity closeFolder(folder); // Dismiss the folder cling - dismissFolderCling(null); + mLauncherClings.dismissFolderCling(null); } } @@ -2883,7 +3198,8 @@ public class Launcher extends Activity // The hotseat touch handling does not go through Workspace, and we always allow long press // on hotseat items. final View itemUnderLongClick = longClickCellInfo.cell; - boolean allowLongPress = isHotseatLayout(v) || mWorkspace.allowLongPress(); + final boolean inHotseat = isHotseatLayout(v); + boolean allowLongPress = inHotseat || mWorkspace.allowLongPress(); if (allowLongPress && !mDragController.isDragging()) { if (itemUnderLongClick == null) { // User long pressed on empty space @@ -2909,15 +3225,6 @@ public class Launcher extends Activity return mHotseat != null && layout != null && (layout instanceof CellLayout) && (layout == mHotseat.getLayout()); } - Hotseat getHotseat() { - return mHotseat; - } - View getOverviewPanel() { - return mOverviewPanel; - } - SearchDropTargetBar getSearchBar() { - return mSearchDropTargetBar; - } /** * Returns the CellLayout of the specified container at the specified screen. @@ -2934,39 +3241,12 @@ public class Launcher extends Activity } } - protected Workspace getWorkspace() { - return mWorkspace; + public AppsCustomizePagedView getAppsCustomizeContent() { + return mAppsCustomizeContent; } public void updateOverviewPanel() { - View defaultScreenButton = mOverviewPanel.findViewById(R.id.default_screen_button); - View transitionEffectButton = mOverviewPanel.findViewById(R.id.transition_effect_button); - View widgetButton = mOverviewPanel.findViewById(R.id.widget_button); - View wallpaperButton = mOverviewPanel.findViewById(R.id.wallpaper_button); - View sortButton = mOverviewPanel.findViewById(R.id.sort_button); - View filterButton = mOverviewPanel.findViewById(R.id.filter_button); - View iconPackButton = findViewById(R.id.icon_pack_button); - - PagedView pagedView = !isAllAppsVisible() ? mWorkspace : mAppsCustomizeContent; - - defaultScreenButton.setVisibility((!isAllAppsVisible() && pagedView.getPageCount() > 1) ? View.VISIBLE : View.GONE); - transitionEffectButton.setVisibility(pagedView.getPageCount() > 1 ? View.VISIBLE : View.GONE); - widgetButton.setVisibility(!isAllAppsVisible() ? View.VISIBLE : View.GONE); - wallpaperButton.setVisibility(!isAllAppsVisible() ? View.VISIBLE : View.GONE); - sortButton.setVisibility(isAllAppsVisible() ? View.VISIBLE : View.GONE); - // TODO: implement filtering - // filterButton.setVisibility(isAllAppsVisible() ? View.VISIBLE : View.GONE); - filterButton.setVisibility(View.GONE); - - boolean isVisible = !isAllAppsVisible(); - if (isVisible) { - int numIconPacks = IconPackHelper.getSupportedPackages(this).size(); - isVisible = numIconPacks > 0; - } - iconPackButton.setVisibility(isVisible ? View.VISIBLE : View.GONE); - - // Make sure overview panel is drawn above apps customize - mOverviewPanel.bringToFront(); + mOverviewSettingsPanel.update(); } public boolean isAllAppsVisible() { @@ -3077,23 +3357,6 @@ public class Launcher extends Activity AppsCustomizePagedView.ContentType contentType = mAppsCustomizeContent.getContentType(); showAppsCustomizeHelper(animated, springLoaded, contentType); } - - public void showAllAppsCling() { - if (isClingsEnabled() && - !mSharedPrefs.getBoolean(Cling.ALL_APPS_CLING_DISMISSED_KEY, false) && - !skipCustomClingIfNoAccounts() ) { - Cling cling = (Cling) findViewById(R.id.all_apps_cling); - View pageIndicator = mAppsCustomizeLayout.findViewById(R.id.page_indicator); - cling.setPunchThroughForView(pageIndicator); - if (cling != null) { - cling.bringToFront(); - } - initCling(R.id.all_apps_cling, 0, true, true); - } else { - removeCling(R.id.all_apps_cling); - } - } - private void showAppsCustomizeHelper(final boolean animated, final boolean springLoaded, final AppsCustomizePagedView.ContentType contentType) { if (mStateAnimation != null) { @@ -3116,8 +3379,9 @@ public class Launcher extends Activity // Shrink workspaces away if going to AppsCustomize from workspace Animator workspaceAnim = mWorkspace.getChangeStateAnimation(Workspace.State.SMALL, animated); - if (!AppsCustomizePagedView.DISABLE_ALL_APPS) { - // Set the content type for the all apps space + if (!LauncherAppState.isDisableAllApps() + || contentType == AppsCustomizePagedView.ContentType.Widgets) { + // Set the content type for the all apps/widgets space mAppsCustomizeContent.setContentType(contentType); } @@ -3173,10 +3437,6 @@ public class Launcher extends Activity if (mSearchDropTargetBar != null) { mSearchDropTargetBar.hideSearchBar(false); } - - if (contentType == AppsCustomizePagedView.ContentType.Applications) { - showAllAppsCling(); - } } }); @@ -3304,7 +3564,7 @@ public class Launcher extends Activity dispatchOnLauncherTransitionPrepare(fromView, animated, true); dispatchOnLauncherTransitionPrepare(toView, animated, true); - mAppsCustomizeContent.pauseScrolling(); + mAppsCustomizeContent.stopScrolling(); mStateAnimation.addListener(new AnimatorListenerAdapter() { @Override @@ -3316,7 +3576,6 @@ public class Launcher extends Activity onCompleteRunnable.run(); } mAppsCustomizeContent.updateCurrentPageScroll(); - mAppsCustomizeContent.resumeScrolling(); } }); @@ -3433,7 +3692,7 @@ public class Launcher extends Activity } } - void exitSpringLoadedDragModeDelayed(final boolean successfulDrop, boolean extendedDelay, + void exitSpringLoadedDragModeDelayed(final boolean successfulDrop, int delay, final Runnable onCompleteRunnable) { if (mState != State.APPS_CUSTOMIZE_SPRING_LOADED) return; @@ -3450,9 +3709,8 @@ public class Launcher extends Activity exitSpringLoadedDragMode(); } } - }, (extendedDelay ? - EXIT_SPRINGLOADED_MODE_LONG_TIMEOUT : - EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT)); + }, delay); + } void exitSpringLoadedDragMode() { @@ -3626,11 +3884,25 @@ public class Launcher extends Activity } public View getQsbBar() { - if (mQsbBar == null) { - mQsbBar = mInflater.inflate(R.layout.search_bar, mSearchDropTargetBar, false); - mSearchDropTargetBar.addView(mQsbBar); + if (mQsb == null) { + mQsb = mInflater.inflate(R.layout.qsb, mSearchDropTargetBar, false); + mSearchDropTargetBar.addView(mQsb); + } + return mQsb; + } + + public ImageView getQsbBarSearchButton() { + if (mQsbBarSearch == null && getQsbBar() != null) { + return (ImageView) getQsbBar().findViewById(R.id.search_button); } - return mQsbBar; + return mQsbBarSearch; + } + + public ImageView getQsbBarVoiceButton() { + if (mQsbBarVoice == null && getQsbBar() != null) { + return (ImageView) getQsbBar().findViewById(R.id.voice_button); + } + return mQsbBarVoice; } protected boolean updateGlobalSearchIcon() { @@ -3887,14 +4159,18 @@ public class Launcher extends Activity // Create the custom content page (this call updates mDefaultScreen which calls // setCurrentPage() so ensure that all pages are added before calling this). - // The actual content of the custom page will be added during onFinishBindingItems(). - if (!mWorkspace.hasCustomContent() && hasCustomContentToLeft()) { - mWorkspace.createCustomContentPage(); + if (hasCustomContentToLeft()) { + mWorkspace.createCustomContentContainer(); + populateCustomContentContainer(); } } @Override public void bindAddScreens(ArrayList<Long> orderedScreenIds) { + // Log to disk + Launcher.addDumpLog(TAG, "11683562 - bindAddScreens()", true); + Launcher.addDumpLog(TAG, "11683562 - orderedScreenIds: " + + TextUtils.join(", ", orderedScreenIds), true); int count = orderedScreenIds.size(); for (int i = 0; i < count; i++) { mWorkspace.insertNewWorkspaceScreenBeforeEmptyScreen(orderedScreenIds.get(i)); @@ -3939,23 +4215,25 @@ public class Launcher extends Activity } // Add the new screens - bindAddScreens(newScreens); + if (newScreens != null) { + bindAddScreens(newScreens); + } // We add the items without animation on non-visible pages, and with // animations on the new page (which we will try and snap to). - if (!addNotAnimated.isEmpty()) { + if (addNotAnimated != null && !addNotAnimated.isEmpty()) { bindItems(addNotAnimated, 0, addNotAnimated.size(), false); } - if (!addAnimated.isEmpty()) { + if (addAnimated != null && !addAnimated.isEmpty()) { bindItems(addAnimated, 0, addAnimated.size(), true); } // Remove the extra empty screen - mWorkspace.removeExtraEmptyScreens(); + mWorkspace.removeExtraEmptyScreen(false, null); - if (!AppsCustomizePagedView.DISABLE_ALL_APPS && + if (!LauncherAppState.isDisableAllApps() && addedApps != null && mAppsCustomizeContent != null) { mAppsCustomizeContent.addApps(addedApps); } @@ -4053,9 +4331,11 @@ public class Launcher extends Activity // when we are loading right after we return to launcher. mWorkspace.postDelayed(new Runnable() { public void run() { - mWorkspace.snapToPage(newScreenIndex); - mWorkspace.postDelayed(startBounceAnimRunnable, - NEW_APPS_ANIMATION_DELAY); + if (mWorkspace != null) { + mWorkspace.snapToPage(newScreenIndex); + mWorkspace.postDelayed(startBounceAnimRunnable, + NEW_APPS_ANIMATION_DELAY); + } } }, NEW_APPS_PAGE_MOVE_DELAY); } else { @@ -4165,13 +4445,6 @@ public class Launcher extends Activity mWorkspace.getUniqueComponents(true, null); mIntentsOnWorkspaceFromUpgradePath = mWorkspace.getUniqueComponents(true, null); } - - mWorkspace.post(new Runnable() { - @Override - public void run() { - onFinishBindingItems(); - } - }); } private boolean canRunNewAppsAnimation() { @@ -4190,6 +4463,16 @@ public class Launcher extends Activity return bounceAnim; } + public boolean useVerticalBarLayout() { + return LauncherAppState.getInstance().getDynamicGrid(). + getDeviceProfile().isVerticalBarLayout(); + } + + protected Rect getSearchBarBounds() { + return LauncherAppState.getInstance().getDynamicGrid(). + getDeviceProfile().getSearchBarBounds(); + } + @Override public void bindSearchablesChanged() { boolean searchVisible = updateGlobalSearchIcon(); @@ -4205,7 +4488,7 @@ public class Launcher extends Activity * Implementation of the method from LauncherModel.Callbacks. */ public void bindAllApplications(final ArrayList<AppInfo> apps) { - if (AppsCustomizePagedView.DISABLE_ALL_APPS) { + if (LauncherAppState.isDisableAllApps()) { if (mIntentsOnWorkspaceFromUpgradePath != null) { if (LauncherModel.UPGRADE_USE_MORE_APPS_FOLDER) { getHotseat().addAllAppsFolder(mIconCache, apps, @@ -4213,9 +4496,15 @@ public class Launcher extends Activity } mIntentsOnWorkspaceFromUpgradePath = null; } + if (mAppsCustomizeContent != null) { + mAppsCustomizeContent.onPackagesUpdated( + LauncherModel.getSortedWidgetsAndShortcuts(this)); + } } else { if (mAppsCustomizeContent != null) { mAppsCustomizeContent.setApps(apps); + mAppsCustomizeContent.onPackagesUpdated( + LauncherModel.getSortedWidgetsAndShortcuts(this)); } } } @@ -4239,7 +4528,7 @@ public class Launcher extends Activity mWorkspace.updateShortcuts(apps); } - if (!AppsCustomizePagedView.DISABLE_ALL_APPS && + if (!LauncherAppState.isDisableAllApps() && mAppsCustomizeContent != null) { mAppsCustomizeContent.updateApps(apps); } @@ -4255,27 +4544,28 @@ public class Launcher extends Activity * Implementation of the method from LauncherModel.Callbacks. */ public void bindComponentsRemoved(final ArrayList<String> packageNames, - final ArrayList<AppInfo> appInfos, - final boolean packageRemoved) { + final ArrayList<AppInfo> appInfos) { Runnable r = new Runnable() { public void run() { - bindComponentsRemoved(packageNames, appInfos, packageRemoved); + bindComponentsRemoved(packageNames, appInfos); } }; if (waitUntilResume(r)) { return; } - if (packageRemoved) { + if (!packageNames.isEmpty()) { mWorkspace.removeItemsByPackageName(packageNames); - } else { + } + if (!appInfos.isEmpty()) { mWorkspace.removeItemsByApplicationInfo(appInfos); } // Notify the drag controller - mDragController.onAppsRemoved(appInfos, this); + mDragController.onAppsRemoved(packageNames, appInfos); - if (!AppsCustomizePagedView.DISABLE_ALL_APPS && + // Update AllApps + if (!LauncherAppState.isDisableAllApps() && mAppsCustomizeContent != null) { mAppsCustomizeContent.removeApps(appInfos); } @@ -4291,7 +4581,6 @@ public class Launcher extends Activity mWidgetsAndShortcuts = null; } }; - public void bindPackagesUpdated(final ArrayList<Object> widgetsAndShortcuts) { if (waitUntilResume(mBindPackagesUpdatedRunnable, true)) { mWidgetsAndShortcuts = widgetsAndShortcuts; @@ -4299,8 +4588,7 @@ public class Launcher extends Activity } // Update the widgets pane - if (!AppsCustomizePagedView.DISABLE_ALL_APPS && - mAppsCustomizeContent != null) { + if (mAppsCustomizeContent != null) { mAppsCustomizeContent.onPackagesUpdated(widgetsAndShortcuts); } } @@ -4362,202 +4650,27 @@ public class Launcher extends Activity } } - /* Cling related */ - private boolean isClingsEnabled() { - if (DISABLE_CLINGS) { - return false; - } - - // disable clings when running in a test harness - if(ActivityManager.isRunningInTestHarness()) return false; - - // Disable clings for accessibility when explore by touch is enabled - final AccessibilityManager a11yManager = (AccessibilityManager) getSystemService( - ACCESSIBILITY_SERVICE); - if (a11yManager.isTouchExplorationEnabled()) { - return false; - } - - // Restricted secondary users (child mode) will potentially have very few apps - // seeded when they start up for the first time. Clings won't work well with that -// boolean supportsLimitedUsers = -// android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2; -// Account[] accounts = AccountManager.get(this).getAccounts(); -// if (supportsLimitedUsers && accounts.length == 0) { -// UserManager um = (UserManager) getSystemService(Context.USER_SERVICE); -// Bundle restrictions = um.getUserRestrictions(); -// if (restrictions.getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS, false)) { -// return false; -// } -// } - return true; - } - - private Cling initCling(int clingId, int scrimId, boolean animate, - boolean dimNavBarVisibilty) { - Cling cling = (Cling) findViewById(clingId); - View scrim = null; - if (scrimId > 0) { - scrim = findViewById(R.id.cling_scrim); - } - if (cling != null) { - cling.init(this, scrim); - cling.show(animate, SHOW_CLING_DURATION); - - if (dimNavBarVisibilty) { - cling.setSystemUiVisibility(cling.getSystemUiVisibility() | - View.SYSTEM_UI_FLAG_LOW_PROFILE); - } - } - return cling; - } - - private void dismissCling(final Cling cling, final Runnable postAnimationCb, - final String flag, int duration, boolean restoreNavBarVisibilty) { - // To catch cases where siblings of top-level views are made invisible, just check whether - // the cling is directly set to GONE before dismissing it. - if (cling != null && cling.getVisibility() != View.GONE) { - final Runnable cleanUpClingCb = new Runnable() { - public void run() { - cling.cleanup(); - // We should update the shared preferences on a background thread - new Thread("dismissClingThread") { - public void run() { - SharedPreferences.Editor editor = mSharedPrefs.edit(); - editor.putBoolean(flag, true); - editor.commit(); - } - }.start(); - if (postAnimationCb != null) { - postAnimationCb.run(); - } - } - }; - if (duration <= 0) { - cleanUpClingCb.run(); - } else { - cling.hide(duration, cleanUpClingCb); - } - mHideFromAccessibilityHelper.restoreImportantForAccessibility(mDragLayer); - - if (restoreNavBarVisibilty) { - cling.setSystemUiVisibility(cling.getSystemUiVisibility() & - ~View.SYSTEM_UI_FLAG_LOW_PROFILE); - } - } - } - - private void removeCling(int id) { - final View cling = findViewById(id); - if (cling != null) { - final ViewGroup parent = (ViewGroup) cling.getParent(); - parent.post(new Runnable() { - @Override - public void run() { - parent.removeView(cling); - } - }); - mHideFromAccessibilityHelper.restoreImportantForAccessibility(mDragLayer); - } - } - - private boolean skipCustomClingIfNoAccounts() { - Cling cling = (Cling) findViewById(R.id.workspace_cling); - boolean customCling = cling.getDrawIdentifier().equals("workspace_custom"); - if (customCling) { - AccountManager am = AccountManager.get(this); - if (am == null) return false; - Account[] accounts = am.getAccountsByType("com.google"); - return accounts.length == 0; - } - return false; - } - - public void updateCustomContentHintVisibility() { - Cling cling = (Cling) findViewById(R.id.first_run_cling); - String ccHintStr = getFirstRunCustomContentHint(); - - if (mWorkspace.hasCustomContent()) { - // Show the custom content hint if ccHintStr is not empty - if (cling != null) { - setCustomContentHintVisibility(cling, ccHintStr, true, true); - } - } else { - // Hide the custom content hint - if (cling != null) { - setCustomContentHintVisibility(cling, ccHintStr, false, true); - } - } + /** + * Called when the SearchBar hint should be changed. + * + * @param hint the hint to be displayed in the search bar. + */ + protected void onSearchBarHintChanged(String hint) { + mLauncherClings.updateSearchBarHint(hint); } - private void setCustomContentHintVisibility(Cling cling, String ccHintStr, boolean visible, - boolean animate) { - final TextView ccHint = (TextView) cling.findViewById(R.id.custom_content_hint); - if (ccHint != null) { - if (visible && !ccHintStr.isEmpty()) { - ccHint.setText(ccHintStr); - ccHint.setVisibility(View.VISIBLE); - if (animate) { - ccHint.setAlpha(0f); - ccHint.animate().alpha(1f) - .setDuration(SHOW_CLING_DURATION) - .start(); - } else { - ccHint.setAlpha(1f); - } + protected boolean isLauncherPreinstalled() { + PackageManager pm = getPackageManager(); + try { + ApplicationInfo ai = pm.getApplicationInfo(getComponentName().getPackageName(), 0); + if ((ai.flags & ApplicationInfo.FLAG_SYSTEM) != 0) { + return true; } else { - if (animate) { - ccHint.animate().alpha(0f) - .setDuration(SHOW_CLING_DURATION) - .setListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - ccHint.setVisibility(View.GONE); - } - }) - .start(); - } else { - ccHint.setAlpha(0f); - ccHint.setVisibility(View.GONE); - } + return false; } - } - } - - public void showFirstRunCling() { - if (isClingsEnabled() && - !mSharedPrefs.getBoolean(Cling.FIRST_RUN_CLING_DISMISSED_KEY, false) && - !skipCustomClingIfNoAccounts() ) { - // If we're not using the default workspace layout, replace workspace cling - // with a custom workspace cling (usually specified in an overlay) - // For now, only do this on tablets - if (!DISABLE_CUSTOM_CLINGS) { - if (mSharedPrefs.getInt(LauncherProvider.DEFAULT_WORKSPACE_RESOURCE_ID, 0) != 0 && - getResources().getBoolean(R.bool.config_useCustomClings)) { - // Use a custom cling - View cling = findViewById(R.id.workspace_cling); - ViewGroup clingParent = (ViewGroup) cling.getParent(); - int clingIndex = clingParent.indexOfChild(cling); - clingParent.removeViewAt(clingIndex); - View customCling = mInflater.inflate(R.layout.custom_workspace_cling, clingParent, false); - clingParent.addView(customCling, clingIndex); - customCling.setId(R.id.workspace_cling); - } - } - Cling cling = (Cling) findViewById(R.id.first_run_cling); - if (cling != null) { - String sbHintStr = getFirstRunClingSearchBarHint(); - String ccHintStr = getFirstRunCustomContentHint(); - if (!sbHintStr.isEmpty()) { - TextView sbHint = (TextView) cling.findViewById(R.id.search_bar_hint); - sbHint.setText(sbHintStr); - sbHint.setVisibility(View.VISIBLE); - } - setCustomContentHintVisibility(cling, ccHintStr, true, false); - } - initCling(R.id.first_run_cling, 0, false, true); - } else { - removeCling(R.id.first_run_cling); + } catch (NameNotFoundException e) { + e.printStackTrace(); + return false; } } @@ -4583,83 +4696,79 @@ public class Launcher extends Activity return ""; } - public void showFirstRunWorkspaceCling() { - // Enable the clings only if they have not been dismissed before - if (isClingsEnabled() && - !mSharedPrefs.getBoolean(Cling.WORKSPACE_CLING_DISMISSED_KEY, false)) { - Cling c = initCling(R.id.workspace_cling, 0, false, true); + public void dismissFirstRunCling(View v) { + mLauncherClings.dismissFirstRunCling(v); + } + public void dismissMigrationClingCopyApps(View v) { + mLauncherClings.dismissMigrationClingCopyApps(v); + } + public void dismissMigrationClingUseDefault(View v) { + mLauncherClings.dismissMigrationClingUseDefault(v); + } + public void dismissMigrationWorkspaceCling(View v) { + mLauncherClings.dismissMigrationWorkspaceCling(v); + } + public void dismissWorkspaceCling(View v) { + mLauncherClings.dismissWorkspaceCling(v); + } + public void dismissFolderCling(View v) { + mLauncherClings.dismissFolderCling(v); + } - // Set the focused hotseat app if there is one - c.setFocusedHotseatApp(getFirstRunFocusedHotseatAppDrawableId(), - getFirstRunFocusedHotseatAppRank(), - getFirstRunFocusedHotseatAppComponentName(), - getFirstRunFocusedHotseatAppBubbleTitle(), - getFirstRunFocusedHotseatAppBubbleDescription()); - } else { - removeCling(R.id.workspace_cling); - } + private boolean shouldRunFirstRunActivity() { + return !ActivityManager.isRunningInTestHarness() && + !mSharedPrefs.getBoolean(FIRST_RUN_ACTIVITY_DISPLAYED, false); } - public Cling showFirstRunFoldersCling() { - // Enable the clings only if they have not been dismissed before - if (isClingsEnabled() && - !mSharedPrefs.getBoolean(Cling.FOLDER_CLING_DISMISSED_KEY, false)) { - Cling cling = initCling(R.id.folder_cling, R.id.cling_scrim, - true, true); - return cling; - } else { - removeCling(R.id.folder_cling); - return null; + + public void showFirstRunActivity() { + if (shouldRunFirstRunActivity() && + hasFirstRunActivity()) { + Intent firstRunIntent = getFirstRunActivity(); + if (firstRunIntent != null) { + startActivity(firstRunIntent); + markFirstRunActivityShown(); + } } } - protected SharedPreferences getSharedPrefs() { - return mSharedPrefs; + + private void markFirstRunActivityShown() { + SharedPreferences.Editor editor = mSharedPrefs.edit(); + editor.putBoolean(FIRST_RUN_ACTIVITY_DISPLAYED, true); + editor.apply(); } - public boolean isFolderClingVisible() { - Cling cling = (Cling) findViewById(R.id.folder_cling); - if (cling != null) { - return cling.getVisibility() == View.VISIBLE; - } - return false; + + void showWorkspaceSearchAndHotseat() { + if (mWorkspace != null) mWorkspace.setAlpha(1f); + if (mHotseat != null) mHotseat.setAlpha(1f); + if (mPageIndicators != null) mPageIndicators.setAlpha(1f); + if (mSearchDropTargetBar != null) mSearchDropTargetBar.showSearchBar(false); } - public void dismissFirstRunCling(View v) { - Cling cling = (Cling) findViewById(R.id.first_run_cling); - Runnable cb = new Runnable() { - public void run() { - // Show the workspace cling next - showFirstRunWorkspaceCling(); - } - }; - dismissCling(cling, cb, Cling.FIRST_RUN_CLING_DISMISSED_KEY, - DISMISS_CLING_DURATION, false); - // Fade out the search bar for the workspace cling coming up - mSearchDropTargetBar.hideSearchBar(true); + void hideWorkspaceSearchAndHotseat() { + if (mWorkspace != null) mWorkspace.setAlpha(0f); + if (mHotseat != null) mHotseat.setAlpha(0f); + if (mPageIndicators != null) mPageIndicators.setAlpha(0f); + if (mSearchDropTargetBar != null) mSearchDropTargetBar.hideSearchBar(false); } - public void dismissWorkspaceCling(View v) { - Cling cling = (Cling) findViewById(R.id.workspace_cling); - Runnable cb = null; - if (v == null) { - cb = new Runnable() { - public void run() { - mWorkspace.enterOverviewMode(); - } - }; - } - dismissCling(cling, cb, Cling.WORKSPACE_CLING_DISMISSED_KEY, - DISMISS_CLING_DURATION, true); - // Fade in the search bar - mSearchDropTargetBar.showSearchBar(true); + + public ItemInfo createAppDragInfo(Intent appLaunchIntent) { + ResolveInfo ri = getPackageManager().resolveActivity(appLaunchIntent, 0); + if (ri == null) { + return null; + } + return new AppInfo(getPackageManager(), ri, mIconCache, null); } - public void dismissFolderCling(View v) { - Cling cling = (Cling) findViewById(R.id.folder_cling); - dismissCling(cling, null, Cling.FOLDER_CLING_DISMISSED_KEY, - DISMISS_CLING_DURATION, true); + + public ItemInfo createShortcutDragInfo(Intent shortcutIntent, CharSequence caption, + Bitmap icon) { + return new ShortcutInfo(shortcutIntent, caption, icon); } - public void dismissAllAppsCling(View v) { - Cling cling = (Cling) findViewById(R.id.all_apps_cling); - dismissCling(cling, null, Cling.ALL_APPS_CLING_DISMISSED_KEY, - DISMISS_CLING_DURATION, true); + + public void startDrag(View dragView, ItemInfo dragInfo, DragSource source) { + dragView.setTag(dragInfo); + mWorkspace.onDragStartedWithItem(dragView); + mWorkspace.beginDragShared(dragView, source); } /** @@ -4725,22 +4834,30 @@ public class Launcher extends Activity } public static void addDumpLog(String tag, String log, boolean debugLog) { + addDumpLog(tag, log, null, debugLog); + } + + public static void addDumpLog(String tag, String log, Exception e, boolean debugLog) { if (debugLog) { - Log.d(tag, log); + if (e != null) { + Log.d(tag, log, e); + } else { + Log.d(tag, log); + } } if (DEBUG_DUMP_LOG) { sDateStamp.setTime(System.currentTimeMillis()); synchronized (sDumpLogs) { - sDumpLogs.add(sDateFormat.format(sDateStamp) + ": " + tag + ", " + log); + sDumpLogs.add(sDateFormat.format(sDateStamp) + ": " + tag + ", " + log + + (e == null ? "" : (", Exception: " + e))); } } } public void dumpLogsToLocalData() { if (DEBUG_DUMP_LOG) { - new Thread("DumpLogsToLocalData") { - @Override - public void run() { + new AsyncTask<Void, Void, Void>() { + public Void doInBackground(Void ... args) { boolean success = false; sDateStamp.setTime(sRunStart); String FILENAME = sDateStamp.getMonth() + "-" @@ -4778,10 +4895,53 @@ public class Launcher extends Activity } catch (IOException e) { e.printStackTrace(); } + return null; } - }.start(); + }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void) null); } } + + public AppsCustomizePagedView.SortMode getAppsCustomizeContentSortMode () { + return mAppsCustomizeContent.getSortMode(); + } + + public boolean shouldShowSearchBar() { + return mWorkspace.getShowSearchBar(); + } + + public boolean shouldHideWorkspaceIconLables() { + return mWorkspace.getHideIconLables(); + } + + public String getWorkspaceTransitionEffect() { + TransitionEffect effect = mWorkspace.getTransitionEffect(); + return effect == null ? TransitionEffect.TRANSITION_EFFECT_NONE : effect.getName(); + } + + public String getAppsCustomizeTransitionEffect() { + TransitionEffect effect = mAppsCustomizeContent.getTransitionEffect(); + return effect == null ? TransitionEffect.TRANSITION_EFFECT_NONE : effect.getName(); + } + + public void updateDynamicGrid() { + mSearchDropTargetBar.setupQSB(this); + mSearchDropTargetBar.hideSearchBar(false); + + initializeDynamicGrid(); + + mGrid.layout(this); + mWorkspace.showOutlines(); + + // Synchronized reload + mModel.startLoader(true, mWorkspace.getCurrentPage()); + mWorkspace.updateCustomContentVisibility(); + } + + public boolean isSearchBarEnabled() { + return SettingsProvider.getBoolean(this, + SettingsProvider.SETTINGS_UI_HOMESCREEN_SEARCH, + R.bool.preferences_interface_homescreen_search_default); + } } interface LauncherTransitionable { @@ -4791,3 +4951,8 @@ interface LauncherTransitionable { void onLauncherTransitionStep(Launcher l, float t); void onLauncherTransitionEnd(Launcher l, boolean animated, boolean toWorkspace); } + +interface DebugIntents { + static final String DELETE_DATABASE = "com.android.launcher3.action.DELETE_DATABASE"; + static final String MIGRATE_DATABASE = "com.android.launcher3.action.MIGRATE_DATABASE"; +} diff --git a/src/com/android/launcher3/LauncherAnimUtils.java b/src/com/android/launcher3/LauncherAnimUtils.java index 5d4f9c67e..e6c220b2a 100644 --- a/src/com/android/launcher3/LauncherAnimUtils.java +++ b/src/com/android/launcher3/LauncherAnimUtils.java @@ -25,12 +25,13 @@ import android.view.View; import android.view.ViewTreeObserver; import java.util.HashSet; +import java.util.WeakHashMap; public class LauncherAnimUtils { - static HashSet<Animator> sAnimators = new HashSet<Animator>(); + static WeakHashMap<Animator, Object> sAnimators = new WeakHashMap<Animator, Object>(); static Animator.AnimatorListener sEndAnimListener = new Animator.AnimatorListener() { public void onAnimationStart(Animator animation) { - sAnimators.add(animation); + sAnimators.put(animation, null); } public void onAnimationRepeat(Animator animation) { @@ -74,13 +75,12 @@ public class LauncherAnimUtils { } public static void onDestroyActivity() { - HashSet<Animator> animators = new HashSet<Animator>(sAnimators); + HashSet<Animator> animators = new HashSet<Animator>(sAnimators.keySet()); for (Animator a : animators) { if (a.isRunning()) { a.cancel(); - } else { - sAnimators.remove(a); } + sAnimators.remove(a); } } diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java index cba0d61ac..11e18b186 100644 --- a/src/com/android/launcher3/LauncherAppState.java +++ b/src/com/android/launcher3/LauncherAppState.java @@ -22,23 +22,23 @@ import android.content.res.Configuration; import android.content.res.Resources; import android.database.ContentObserver; import android.os.Handler; -import android.provider.Settings; import android.util.Log; -import com.android.launcher3.settings.SettingsProvider; import java.lang.ref.WeakReference; -public class LauncherAppState { +public class LauncherAppState implements DeviceProfile.DeviceProfileCallbacks { private static final String TAG = "LauncherAppState"; private static final String SHARED_PREFERENCES_KEY = "com.android.launcher3.prefs"; + private final AppFilter mAppFilter; + private final BuildInfo mBuildInfo; private LauncherModel mModel; private IconCache mIconCache; - private AppFilter mAppFilter; private WidgetPreviewLoader.CacheDb mWidgetPreviewCacheDb; private boolean mIsScreenLarge; private float mScreenDensity; private int mLongPressTimeout = 300; + private boolean mWallpaperChangedSinceLastCheck; private static WeakReference<LauncherProvider> sLauncherProvider; private static Context sContext; @@ -84,10 +84,11 @@ public class LauncherAppState { mIsScreenLarge = isScreenLarge(sContext.getResources()); mScreenDensity = sContext.getResources().getDisplayMetrics().density; - mWidgetPreviewCacheDb = new WidgetPreviewLoader.CacheDb(sContext); + recreateWidgetPreviewDb(); mIconCache = new IconCache(sContext); mAppFilter = AppFilter.loadByName(sContext.getString(R.string.app_filter_class)); + mBuildInfo = BuildInfo.loadByName(sContext.getString(R.string.build_info_class)); mModel = new LauncherModel(this, mIconCache, mAppFilter); // Register intent receivers @@ -113,18 +114,13 @@ public class LauncherAppState { ContentResolver resolver = sContext.getContentResolver(); resolver.registerContentObserver(LauncherSettings.Favorites.CONTENT_URI, true, mFavoritesObserver); - - // Generate default typeface - String fontFamily = SettingsProvider.getString(sContext, - SettingsProvider.SETTINGS_UI_GENERAL_ICONS_TEXT_FONT_FAMILY, - R.string.preferences_interface_general_icons_text_font_family_default); - - // TODO: Implement font styles - int fontStyle = SettingsProvider.getInt(sContext, - SettingsProvider.SETTINGS_UI_GENERAL_ICONS_TEXT_FONT_STYLE, - R.integer.preferences_interface_general_icons_text_font_style_default); - - Utilities.generateTypeface(fontFamily, fontStyle); + } + + public void recreateWidgetPreviewDb() { + if (mWidgetPreviewCacheDb != null) { + mWidgetPreviewCacheDb.close(); + } + mWidgetPreviewCacheDb = new WidgetPreviewLoader.CacheDb(sContext); } /** @@ -189,21 +185,20 @@ public class LauncherAppState { DeviceProfile initDynamicGrid(Context context, int minWidth, int minHeight, int width, int height, int availableWidth, int availableHeight) { - if (mDynamicGrid == null) { - mDynamicGrid = new DynamicGrid(context, - context.getResources(), - minWidth, minHeight, width, height, - availableWidth, availableHeight); - } + + mDynamicGrid = new DynamicGrid(context, + context.getResources(), + minWidth, minHeight, width, height, + availableWidth, availableHeight); + mDynamicGrid.getDeviceProfile().addCallback(this); // Update the icon size DeviceProfile grid = mDynamicGrid.getDeviceProfile(); - Utilities.setIconSize(grid.iconSizePx); - grid.updateFromConfiguration(context.getResources(), width, height, + grid.updateFromConfiguration(context, context.getResources(), width, height, availableWidth, availableHeight); return grid; } - DynamicGrid getDynamicGrid() { + public DynamicGrid getDynamicGrid() { return mDynamicGrid; } @@ -228,4 +223,29 @@ public class LauncherAppState { public int getLongPressTimeout() { return mLongPressTimeout; } + + public void onWallpaperChanged() { + mWallpaperChangedSinceLastCheck = true; + } + + public boolean hasWallpaperChangedSinceLastCheck() { + boolean result = mWallpaperChangedSinceLastCheck; + mWallpaperChangedSinceLastCheck = false; + return result; + } + + @Override + public void onAvailableSizeChanged(DeviceProfile grid) { + Utilities.setIconSize(grid.iconSizePx); + } + + public static boolean isDisableAllApps() { + // Returns false on non-dogfood builds. + return getInstance().mBuildInfo.isDogfoodBuild() && + Launcher.isPropertyEnabled(Launcher.DISABLE_ALL_APPS_PROPERTY); + } + + public static boolean isDogfoodBuild() { + return getInstance().mBuildInfo.isDogfoodBuild(); + } } diff --git a/src/com/android/launcher3/LauncherAppWidgetHostView.java b/src/com/android/launcher3/LauncherAppWidgetHostView.java index 83aef1a2f..51a649a07 100644 --- a/src/com/android/launcher3/LauncherAppWidgetHostView.java +++ b/src/com/android/launcher3/LauncherAppWidgetHostView.java @@ -65,6 +65,12 @@ public class LauncherAppWidgetHostView extends AppWidgetHostView implements Touc } public boolean onInterceptTouchEvent(MotionEvent ev) { + // Just in case the previous long press hasn't been cleared, we make sure to start fresh + // on touch down. + if (ev.getAction() == MotionEvent.ACTION_DOWN) { + mLongPressHelper.cancelLongPress(); + } + // Consume any touch events for ourselves after longpress is triggered if (mLongPressHelper.hasPerformedLongPress()) { mLongPressHelper.cancelLongPress(); @@ -110,13 +116,15 @@ public class LauncherAppWidgetHostView extends AppWidgetHostView implements Touc @Override public void onTouchComplete() { - mLongPressHelper.cancelLongPress(); + if (!mLongPressHelper.hasPerformedLongPress()) { + // If a long press has been performed, we don't want to clear the record of that since + // we still may be receiving a touch up which we want to intercept + mLongPressHelper.cancelLongPress(); + } } @Override public int getDescendantFocusability() { return ViewGroup.FOCUS_BLOCK_DESCENDANTS; } - - } diff --git a/src/com/android/launcher3/LauncherBackupAgentHelper.java b/src/com/android/launcher3/LauncherBackupAgentHelper.java index 2b5059b72..de6aedddd 100644 --- a/src/com/android/launcher3/LauncherBackupAgentHelper.java +++ b/src/com/android/launcher3/LauncherBackupAgentHelper.java @@ -18,12 +18,22 @@ package com.android.launcher3; import android.app.backup.BackupAgentHelper; import android.app.backup.BackupManager; +import android.app.backup.SharedPreferencesBackupHelper; import android.content.Context; +import android.content.SharedPreferences; +import android.provider.Settings; +import android.util.Log; public class LauncherBackupAgentHelper extends BackupAgentHelper { + private static final String TAG = "LauncherBackupAgentHelper"; + static final boolean VERBOSE = true; + static final boolean DEBUG = false; + private static BackupManager sBackupManager; + protected static final String SETTING_RESTORE_ENABLED = "launcher_restore_enabled"; + /** * Notify the backup manager that out database is dirty. * @@ -38,9 +48,27 @@ public class LauncherBackupAgentHelper extends BackupAgentHelper { sBackupManager.dataChanged(); } + @Override + public void onDestroy() { + // There is only one process accessing this preference file, but the restore + // modifies the file outside the normal codepaths, so it looks like another + // process. This forces a reload of the file, in case this process persists. + String spKey = LauncherAppState.getSharedPreferencesKey(); + SharedPreferences sp = getSharedPreferences(spKey, Context.MODE_MULTI_PROCESS); + super.onDestroy(); + } @Override public void onCreate() { - addHelper(LauncherBackupHelper.LAUNCHER_PREFIX, new LauncherBackupHelper(this)); + boolean restoreEnabled = 0 != Settings.Secure.getInt( + getContentResolver(), SETTING_RESTORE_ENABLED, 0); + if (VERBOSE) Log.v(TAG, "restore is " + (restoreEnabled ? "enabled" : "disabled")); + + addHelper(LauncherBackupHelper.LAUNCHER_PREFS_PREFIX, + new LauncherPreferencesBackupHelper(this, + LauncherAppState.getSharedPreferencesKey(), + restoreEnabled)); + addHelper(LauncherBackupHelper.LAUNCHER_PREFIX, + new LauncherBackupHelper(this, restoreEnabled)); } } diff --git a/src/com/android/launcher3/LauncherBackupHelper.java b/src/com/android/launcher3/LauncherBackupHelper.java index 9b901eea1..62e6f3102 100644 --- a/src/com/android/launcher3/LauncherBackupHelper.java +++ b/src/com/android/launcher3/LauncherBackupHelper.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.android.launcher3; import com.google.protobuf.nano.InvalidProtocolBufferNanoException; @@ -31,14 +30,14 @@ import com.android.launcher3.backup.BackupProtos.Screen; import com.android.launcher3.backup.BackupProtos.Widget; import android.app.backup.BackupDataInputStream; -import android.app.backup.BackupHelper; -import android.app.backup.BackupDataInput; import android.app.backup.BackupDataOutput; +import android.app.backup.BackupHelper; import android.app.backup.BackupManager; import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetProviderInfo; import android.content.ComponentName; import android.content.ContentResolver; +import android.content.ContentValues; import android.content.Context; import android.content.Intent; import android.database.Cursor; @@ -68,7 +67,8 @@ import java.util.zip.CRC32; public class LauncherBackupHelper implements BackupHelper { private static final String TAG = "LauncherBackupHelper"; - private static final boolean DEBUG = false; + private static final boolean VERBOSE = LauncherBackupAgentHelper.VERBOSE; + private static final boolean DEBUG = LauncherBackupAgentHelper.DEBUG; private static final boolean DEBUG_PAYLOAD = false; private static final int MAX_JOURNAL_SIZE = 1000000; @@ -83,6 +83,8 @@ public class LauncherBackupHelper implements BackupHelper { public static final String LAUNCHER_PREFIX = "L"; + public static final String LAUNCHER_PREFS_PREFIX = "LP"; + private static final Bitmap.CompressFormat IMAGE_FORMAT = android.graphics.Bitmap.CompressFormat.PNG; @@ -134,14 +136,19 @@ public class LauncherBackupHelper implements BackupHelper { private static final int SCREEN_RANK_INDEX = 2; + private static IconCache mIconCache; + private final Context mContext; + private final boolean mRestoreEnabled; + private HashMap<ComponentName, AppWidgetProviderInfo> mWidgetMap; private ArrayList<Key> mKeys; - public LauncherBackupHelper(Context context) { + public LauncherBackupHelper(Context context, boolean restoreEnabled) { mContext = context; + mRestoreEnabled = restoreEnabled; } private void dataChanged() { @@ -166,7 +173,7 @@ public class LauncherBackupHelper implements BackupHelper { @Override public void performBackup(ParcelFileDescriptor oldState, BackupDataOutput data, ParcelFileDescriptor newState) { - Log.v(TAG, "onBackup"); + if (VERBOSE) Log.v(TAG, "onBackup"); Journal in = readJournal(oldState); Journal out = new Journal(); @@ -176,19 +183,23 @@ public class LauncherBackupHelper implements BackupHelper { out.rows = 0; out.bytes = 0; - Log.v(TAG, "lastBackupTime=" + lastBackupTime); + Log.v(TAG, "lastBackupTime = " + lastBackupTime); ArrayList<Key> keys = new ArrayList<Key>(); - try { - backupFavorites(in, data, out, keys); - backupScreens(in, data, out, keys); - backupIcons(in, data, out, keys); - backupWidgets(in, data, out, keys); - } catch (IOException e) { - Log.e(TAG, "launcher backup has failed", e); + if (launcherIsReady()) { + try { + backupFavorites(in, data, out, keys); + backupScreens(in, data, out, keys); + backupIcons(in, data, out, keys); + backupWidgets(in, data, out, keys); + } catch (IOException e) { + Log.e(TAG, "launcher backup has failed", e); + } + out.key = keys.toArray(new BackupProtos.Key[keys.size()]); + } else { + out = in; } - out.key = keys.toArray(BackupProtos.Key.EMPTY_ARRAY); writeJournal(newState, out); Log.v(TAG, "onBackup: wrote " + out.bytes + "b in " + out.rows + " rows."); } @@ -202,7 +213,7 @@ public class LauncherBackupHelper implements BackupHelper { */ @Override public void restoreEntity(BackupDataInputStream data) { - Log.v(TAG, "restoreEntity"); + if (VERBOSE) Log.v(TAG, "restoreEntity"); if (mKeys == null) { mKeys = new ArrayList<Key>(); } @@ -218,10 +229,11 @@ public class LauncherBackupHelper implements BackupHelper { bytesRead = data.read(buffer, 0, dataSize); if (DEBUG) Log.d(TAG, "read " + bytesRead + " of " + dataSize + " available"); } catch (IOException e) { - Log.d(TAG, "failed to read entity from restore data", e); + Log.e(TAG, "failed to read entity from restore data", e); } try { key = backupKeyToKey(backupKey); + mKeys.add(key); switch (key.type) { case Key.FAVORITE: restoreFavorite(key, buffer, dataSize, mKeys); @@ -260,7 +272,7 @@ public class LauncherBackupHelper implements BackupHelper { // will catch any changes the restore process might have made Journal out = new Journal(); out.t = 0; - out.key = mKeys.toArray(BackupProtos.Key.EMPTY_ARRAY); + out.key = mKeys.toArray(new BackupProtos.Key[mKeys.size()]); writeJournal(newState, out); Log.v(TAG, "onRestore: read " + mKeys.size() + " rows"); mKeys.clear(); @@ -295,10 +307,13 @@ public class LauncherBackupHelper implements BackupHelper { final long updateTime = cursor.getLong(ID_MODIFIED); Key key = getKey(Key.FAVORITE, id); keys.add(key); - currentIds.add(keyToBackupKey(key)); - if (updateTime > in.t) { + final String backupKey = keyToBackupKey(key); + currentIds.add(backupKey); + if (!savedIds.contains(backupKey) || updateTime >= in.t) { byte[] blob = packFavorite(cursor); writeRowToBackup(key, blob, out, data); + } else { + if (VERBOSE) Log.v(TAG, "favorite " + id + " was too old: " + updateTime); } } } finally { @@ -322,15 +337,21 @@ public class LauncherBackupHelper implements BackupHelper { * @param keys keys to mark as clean in the notes for next backup */ private void restoreFavorite(Key key, byte[] buffer, int dataSize, ArrayList<Key> keys) { - Log.v(TAG, "unpacking favorite " + key.id + " (" + dataSize + " bytes)"); + if (VERBOSE) Log.v(TAG, "unpacking favorite " + key.id); if (DEBUG) Log.d(TAG, "read (" + buffer.length + "): " + Base64.encodeToString(buffer, 0, dataSize, Base64.NO_WRAP)); + if (!mRestoreEnabled) { + if (VERBOSE) Log.v(TAG, "restore not enabled: skipping database mutation"); + return; + } + try { - Favorite favorite = unpackFavorite(buffer, 0, dataSize); - if (DEBUG) Log.d(TAG, "unpacked " + favorite.itemType); + ContentResolver cr = mContext.getContentResolver(); + ContentValues values = unpackFavorite(buffer, 0, dataSize); + cr.insert(Favorites.CONTENT_URI, values); } catch (InvalidProtocolBufferNanoException e) { - Log.w(TAG, "failed to decode proto", e); + Log.e(TAG, "failed to decode favorite", e); } } @@ -358,15 +379,19 @@ public class LauncherBackupHelper implements BackupHelper { Set<String> currentIds = new HashSet<String>(cursor.getCount()); try { cursor.moveToPosition(-1); + if (DEBUG) Log.d(TAG, "dumping screens after: " + in.t); while(cursor.moveToNext()) { final long id = cursor.getLong(ID_INDEX); final long updateTime = cursor.getLong(ID_MODIFIED); Key key = getKey(Key.SCREEN, id); keys.add(key); - currentIds.add(keyToBackupKey(key)); - if (updateTime > in.t) { + final String backupKey = keyToBackupKey(key); + currentIds.add(backupKey); + if (!savedIds.contains(backupKey) || updateTime >= in.t) { byte[] blob = packScreen(cursor); writeRowToBackup(key, blob, out, data); + } else { + if (VERBOSE) Log.v(TAG, "screen " + id + " was too old: " + updateTime); } } } finally { @@ -390,14 +415,22 @@ public class LauncherBackupHelper implements BackupHelper { * @param keys keys to mark as clean in the notes for next backup */ private void restoreScreen(Key key, byte[] buffer, int dataSize, ArrayList<Key> keys) { - Log.v(TAG, "unpacking screen " + key.id); + if (VERBOSE) Log.v(TAG, "unpacking screen " + key.id); if (DEBUG) Log.d(TAG, "read (" + buffer.length + "): " + Base64.encodeToString(buffer, 0, dataSize, Base64.NO_WRAP)); + + if (!mRestoreEnabled) { + if (VERBOSE) Log.v(TAG, "restore not enabled: skipping database mutation"); + return; + } + try { - Screen screen = unpackScreen(buffer, 0, dataSize); - if (DEBUG) Log.d(TAG, "unpacked " + screen.rank); + ContentResolver cr = mContext.getContentResolver(); + ContentValues values = unpackScreen(buffer, 0, dataSize); + cr.insert(WorkspaceScreens.CONTENT_URI, values); + } catch (InvalidProtocolBufferNanoException e) { - Log.w(TAG, "failed to decode proto", e); + Log.e(TAG, "failed to decode screen", e); } } @@ -414,14 +447,12 @@ public class LauncherBackupHelper implements BackupHelper { private void backupIcons(Journal in, BackupDataOutput data, Journal out, ArrayList<Key> keys) throws IOException { // persist icons that haven't been persisted yet - final LauncherAppState appState = LauncherAppState.getInstanceNoCreate(); - if (appState == null) { + if (!initializeIconCache()) { dataChanged(); // try again later if (DEBUG) Log.d(TAG, "Launcher is not initialized, delaying icon backup"); return; } final ContentResolver cr = mContext.getContentResolver(); - final IconCache iconCache = appState.getIconCache(); final int dpi = mContext.getResources().getDisplayMetrics().densityDpi; // read the old ID set @@ -452,30 +483,30 @@ public class LauncherBackupHelper implements BackupHelper { Log.w(TAG, "empty intent on application favorite: " + id); } if (savedIds.contains(backupKey)) { - if (DEBUG) Log.d(TAG, "already saved icon " + backupKey); + if (VERBOSE) Log.v(TAG, "already saved icon " + backupKey); // remember that we already backed this up previously keys.add(key); } else if (backupKey != null) { if (DEBUG) Log.d(TAG, "I can count this high: " + out.rows); if ((out.rows - startRows) < MAX_ICONS_PER_PASS) { - if (DEBUG) Log.d(TAG, "saving icon " + backupKey); - Bitmap icon = iconCache.getIcon(intent); + if (VERBOSE) Log.v(TAG, "saving icon " + backupKey); + Bitmap icon = mIconCache.getIcon(intent); keys.add(key); - if (icon != null && !iconCache.isDefaultIcon(icon)) { + if (icon != null && !mIconCache.isDefaultIcon(icon)) { byte[] blob = packIcon(dpi, icon); writeRowToBackup(key, blob, out, data); } } else { - if (DEBUG) Log.d(TAG, "scheduling another run for icon " + backupKey); + if (VERBOSE) Log.d(TAG, "deferring icon backup " + backupKey); // too many icons for this pass, request another. dataChanged(); } } } catch (URISyntaxException e) { - Log.w(TAG, "invalid URI on application favorite: " + id); + Log.e(TAG, "invalid URI on application favorite: " + id); } catch (IOException e) { - Log.w(TAG, "unable to save application icon for favorite: " + id); + Log.e(TAG, "unable to save application icon for favorite: " + id); } } @@ -500,21 +531,36 @@ public class LauncherBackupHelper implements BackupHelper { * @param keys keys to mark as clean in the notes for next backup */ private void restoreIcon(Key key, byte[] buffer, int dataSize, ArrayList<Key> keys) { - Log.v(TAG, "unpacking icon " + key.id); + if (VERBOSE) Log.v(TAG, "unpacking icon " + key.id); if (DEBUG) Log.d(TAG, "read (" + buffer.length + "): " + Base64.encodeToString(buffer, 0, dataSize, Base64.NO_WRAP)); + try { Resource res = unpackIcon(buffer, 0, dataSize); - if (DEBUG) Log.d(TAG, "unpacked " + res.dpi); - if (DEBUG) Log.d(TAG, "read " + - Base64.encodeToString(res.data, 0, res.data.length, - Base64.NO_WRAP)); + if (DEBUG) { + Log.d(TAG, "unpacked " + res.dpi + " dpi icon"); + } + if (DEBUG_PAYLOAD) { + Log.d(TAG, "read " + + Base64.encodeToString(res.data, 0, res.data.length, + Base64.NO_WRAP)); + } Bitmap icon = BitmapFactory.decodeByteArray(res.data, 0, res.data.length); if (icon == null) { Log.w(TAG, "failed to unpack icon for " + key.name); } - } catch (InvalidProtocolBufferNanoException e) { - Log.w(TAG, "failed to decode proto", e); + + if (!mRestoreEnabled) { + if (VERBOSE) { + Log.v(TAG, "restore not enabled: skipping database mutation"); + } + return; + } else { + IconCache.preloadIcon(mContext, ComponentName.unflattenFromString(key.name), + icon, res.dpi); + } + } catch (IOException e) { + Log.d(TAG, "failed to save restored icon for: " + key.name, e); } } @@ -532,15 +578,13 @@ public class LauncherBackupHelper implements BackupHelper { ArrayList<Key> keys) throws IOException { // persist static widget info that hasn't been persisted yet final LauncherAppState appState = LauncherAppState.getInstanceNoCreate(); - if (appState == null) { - dataChanged(); // try again later - if (DEBUG) Log.d(TAG, "Launcher is not initialized, delaying widget backup"); + if (appState == null || !initializeIconCache()) { + Log.w(TAG, "Failed to get icon cache during restore"); return; } final ContentResolver cr = mContext.getContentResolver(); final WidgetPreviewLoader previewLoader = new WidgetPreviewLoader(mContext); final PagedViewCellLayout widgetSpacingLayout = new PagedViewCellLayout(mContext); - final IconCache iconCache = appState.getIconCache(); final int dpi = mContext.getResources().getDisplayMetrics().densityDpi; final DeviceProfile profile = appState.getDynamicGrid().getDeviceProfile(); if (DEBUG) Log.d(TAG, "cellWidthPx: " + profile.cellWidthPx); @@ -573,22 +617,22 @@ public class LauncherBackupHelper implements BackupHelper { Log.w(TAG, "empty intent on appwidget: " + id); } if (savedIds.contains(backupKey)) { - if (DEBUG) Log.d(TAG, "already saved widget " + backupKey); + if (VERBOSE) Log.v(TAG, "already saved widget " + backupKey); // remember that we already backed this up previously keys.add(key); } else if (backupKey != null) { if (DEBUG) Log.d(TAG, "I can count this high: " + out.rows); if ((out.rows - startRows) < MAX_WIDGETS_PER_PASS) { - if (DEBUG) Log.d(TAG, "saving widget " + backupKey); + if (VERBOSE) Log.v(TAG, "saving widget " + backupKey); previewLoader.setPreviewSize(spanX * profile.cellWidthPx, spanY * profile.cellHeightPx, widgetSpacingLayout); - byte[] blob = packWidget(dpi, previewLoader, iconCache, provider); + byte[] blob = packWidget(dpi, previewLoader, mIconCache, provider); keys.add(key); writeRowToBackup(key, blob, out, data); } else { - if (DEBUG) Log.d(TAG, "scheduling another run for widget " + backupKey); + if (VERBOSE) Log.d(TAG, "deferring widget backup " + backupKey); // too many widgets for this pass, request another. dataChanged(); } @@ -615,7 +659,7 @@ public class LauncherBackupHelper implements BackupHelper { * @param keys keys to mark as clean in the notes for next backup */ private void restoreWidget(Key key, byte[] buffer, int dataSize, ArrayList<Key> keys) { - Log.v(TAG, "unpacking widget " + key.id); + if (VERBOSE) Log.v(TAG, "unpacking widget " + key.id); if (DEBUG) Log.d(TAG, "read (" + buffer.length + "): " + Base64.encodeToString(buffer, 0, dataSize, Base64.NO_WRAP)); try { @@ -628,8 +672,15 @@ public class LauncherBackupHelper implements BackupHelper { Log.w(TAG, "failed to unpack widget icon for " + key.name); } } + + if (!mRestoreEnabled) { + if (VERBOSE) Log.v(TAG, "restore not enabled: skipping database mutation"); + return; + } else { + // future site of widget table mutation + } } catch (InvalidProtocolBufferNanoException e) { - Log.w(TAG, "failed to decode proto", e); + Log.e(TAG, "failed to decode widget", e); } } @@ -764,11 +815,48 @@ public class LauncherBackupHelper implements BackupHelper { } /** Deserialize a Favorite from persistence, after verifying checksum wrapper. */ - private Favorite unpackFavorite(byte[] buffer, int offset, int dataSize) + private ContentValues unpackFavorite(byte[] buffer, int offset, int dataSize) throws InvalidProtocolBufferNanoException { Favorite favorite = new Favorite(); MessageNano.mergeFrom(favorite, readCheckedBytes(buffer, offset, dataSize)); - return favorite; + if (VERBOSE) Log.v(TAG, "unpacked favorite " + favorite.itemType + ", " + + (TextUtils.isEmpty(favorite.title) ? favorite.id : favorite.title)); + ContentValues values = new ContentValues(); + values.put(Favorites._ID, favorite.id); + values.put(Favorites.SCREEN, favorite.screen); + values.put(Favorites.CONTAINER, favorite.container); + values.put(Favorites.CELLX, favorite.cellX); + values.put(Favorites.CELLY, favorite.cellY); + values.put(Favorites.SPANX, favorite.spanX); + values.put(Favorites.SPANY, favorite.spanY); + values.put(Favorites.ICON_TYPE, favorite.iconType); + if (favorite.iconType == Favorites.ICON_TYPE_RESOURCE) { + values.put(Favorites.ICON_PACKAGE, favorite.iconPackage); + values.put(Favorites.ICON_RESOURCE, favorite.iconResource); + } + if (favorite.iconType == Favorites.ICON_TYPE_BITMAP) { + values.put(Favorites.ICON, favorite.icon); + } + if (!TextUtils.isEmpty(favorite.title)) { + values.put(Favorites.TITLE, favorite.title); + } else { + values.put(Favorites.TITLE, ""); + } + if (!TextUtils.isEmpty(favorite.intent)) { + values.put(Favorites.INTENT, favorite.intent); + } + values.put(Favorites.ITEM_TYPE, favorite.itemType); + if (favorite.itemType == Favorites.ITEM_TYPE_APPWIDGET) { + if (!TextUtils.isEmpty(favorite.appWidgetProvider)) { + values.put(Favorites.APPWIDGET_PROVIDER, favorite.appWidgetProvider); + } + values.put(Favorites.APPWIDGET_ID, favorite.appWidgetId); + } + + // Let LauncherModel know we've been here. + values.put(LauncherSettings.Favorites.RESTORED, 1); + + return values; } /** Serialize a Screen for persistence, including a checksum wrapper. */ @@ -781,11 +869,15 @@ public class LauncherBackupHelper implements BackupHelper { } /** Deserialize a Screen from persistence, after verifying checksum wrapper. */ - private Screen unpackScreen(byte[] buffer, int offset, int dataSize) + private ContentValues unpackScreen(byte[] buffer, int offset, int dataSize) throws InvalidProtocolBufferNanoException { Screen screen = new Screen(); MessageNano.mergeFrom(screen, readCheckedBytes(buffer, offset, dataSize)); - return screen; + if (VERBOSE) Log.v(TAG, "unpacked screen " + screen.id + "/" + screen.rank); + ContentValues values = new ContentValues(); + values.put(WorkspaceScreens._ID, screen.id); + values.put(WorkspaceScreens.SCREEN_RANK, screen.rank); + return values; } /** Serialize an icon Resource for persistence, including a checksum wrapper. */ @@ -800,10 +892,11 @@ public class LauncherBackupHelper implements BackupHelper { } /** Deserialize an icon resource from persistence, after verifying checksum wrapper. */ - private Resource unpackIcon(byte[] buffer, int offset, int dataSize) + private static Resource unpackIcon(byte[] buffer, int offset, int dataSize) throws InvalidProtocolBufferNanoException { Resource res = new Resource(); MessageNano.mergeFrom(res, readCheckedBytes(buffer, offset, dataSize)); + if (VERBOSE) Log.v(TAG, "unpacked icon " + res.dpi + "/" + res.data.length); return res; } @@ -842,6 +935,7 @@ public class LauncherBackupHelper implements BackupHelper { throws InvalidProtocolBufferNanoException { Widget widget = new Widget(); MessageNano.mergeFrom(widget, readCheckedBytes(buffer, offset, dataSize)); + if (VERBOSE) Log.v(TAG, "unpacked widget " + widget.provider); return widget; } @@ -852,7 +946,7 @@ public class LauncherBackupHelper implements BackupHelper { * in that case, do a full backup. * * @param oldState the read-0only file descriptor pointing to the old journal - * @return a Journal protocol bugffer + * @return a Journal protocol buffer */ private Journal readJournal(ParcelFileDescriptor oldState) { Journal journal = new Journal(); @@ -861,47 +955,61 @@ public class LauncherBackupHelper implements BackupHelper { } FileInputStream inStream = new FileInputStream(oldState.getFileDescriptor()); try { - int remaining = inStream.available(); - if (DEBUG) Log.d(TAG, "available " + remaining); - if (remaining < MAX_JOURNAL_SIZE) { - byte[] buffer = new byte[remaining]; + int availableBytes = inStream.available(); + if (DEBUG) Log.d(TAG, "available " + availableBytes); + if (availableBytes < MAX_JOURNAL_SIZE) { + byte[] buffer = new byte[availableBytes]; int bytesRead = 0; - while (remaining > 0) { + boolean valid = false; + InvalidProtocolBufferNanoException lastProtoException = null; + while (availableBytes > 0) { try { - int result = inStream.read(buffer, bytesRead, remaining); + // OMG what are you doing? This is crazy inefficient! + // If we read a byte that is not ours, we will cause trouble: b/12491813 + // However, we don't know how many bytes to expect (oops). + // So we have to step through *slowly*, watching for the end. + int result = inStream.read(buffer, bytesRead, 1); if (result > 0) { - if (DEBUG) Log.d(TAG, "read some bytes: " + result); - remaining -= result; + availableBytes -= result; bytesRead += result; + if (DEBUG && (bytesRead % 100 == 0)) { + Log.d(TAG, "read some bytes: " + bytesRead); + } } else { - // stop reading ands see what there is to parse - Log.w(TAG, "read error: " + result); - remaining = 0; + Log.w(TAG, "unexpected end of file while reading journal."); + // stop reading and see what there is to parse + availableBytes = 0; } } catch (IOException e) { - Log.w(TAG, "failed to read the journal", e); buffer = null; - remaining = 0; + availableBytes = 0; } - } - if (DEBUG) Log.d(TAG, "journal bytes read: " + bytesRead); - if (buffer != null) { + // check the buffer to see if we have a valid journal try { MessageNano.mergeFrom(journal, readCheckedBytes(buffer, 0, bytesRead)); + // if we are here, then we have read a valid, checksum-verified journal + valid = true; + availableBytes = 0; + if (VERBOSE) Log.v(TAG, "read " + bytesRead + " bytes of journal"); } catch (InvalidProtocolBufferNanoException e) { - Log.d(TAG, "failed to read the journal", e); + // if we don't have the whole journal yet, mergeFrom will throw. keep going. + lastProtoException = e; journal.clear(); } } + if (DEBUG) Log.d(TAG, "journal bytes read: " + bytesRead); + if (!valid) { + Log.w(TAG, "could not find a valid journal", lastProtoException); + } } } catch (IOException e) { - Log.d(TAG, "failed to close the journal", e); + Log.w(TAG, "failed to close the journal", e); } finally { try { inStream.close(); } catch (IOException e) { - Log.d(TAG, "failed to close the journal", e); + Log.w(TAG, "failed to close the journal", e); } } return journal; @@ -914,7 +1022,7 @@ public class LauncherBackupHelper implements BackupHelper { data.writeEntityData(blob, blob.length); out.rows++; out.bytes += blob.length; - Log.v(TAG, "saving " + geKeyType(key) + " " + backupKey + ": " + + if (VERBOSE) Log.v(TAG, "saving " + geKeyType(key) + " " + backupKey + ": " + getKeyName(key) + "/" + blob.length); if(DEBUG_PAYLOAD) { String encoded = Base64.encodeToString(blob, 0, blob.length, Base64.NO_WRAP); @@ -922,7 +1030,7 @@ public class LauncherBackupHelper implements BackupHelper { for (int offset = 0; offset < encoded.length(); offset += chunkSize) { int end = offset + chunkSize; end = Math.min(end, encoded.length()); - Log.d(TAG, "wrote " + encoded.substring(offset, end)); + Log.w(TAG, "wrote " + encoded.substring(offset, end)); } } } @@ -942,7 +1050,7 @@ public class LauncherBackupHelper implements BackupHelper { throws IOException { int rows = 0; for(String deleted: deletedIds) { - Log.v(TAG, "dropping icon " + deleted); + if (VERBOSE) Log.v(TAG, "dropping deleted item " + deleted); data.writeEntityHeader(deleted, -1); rows++; } @@ -962,10 +1070,12 @@ public class LauncherBackupHelper implements BackupHelper { FileOutputStream outStream = null; try { outStream = new FileOutputStream(newState.getFileDescriptor()); - outStream.write(writeCheckedBytes(journal)); + final byte[] journalBytes = writeCheckedBytes(journal); + outStream.write(journalBytes); outStream.close(); + if (VERBOSE) Log.v(TAG, "wrote " + journalBytes.length + " bytes of journal"); } catch (IOException e) { - Log.d(TAG, "failed to write backup journal", e); + Log.w(TAG, "failed to write backup journal", e); } } @@ -980,7 +1090,7 @@ public class LauncherBackupHelper implements BackupHelper { } /** Unwrap a proto message from a CheckedMessage, verifying the checksum. */ - private byte[] readCheckedBytes(byte[] buffer, int offset, int dataSize) + private static byte[] readCheckedBytes(byte[] buffer, int offset, int dataSize) throws InvalidProtocolBufferNanoException { CheckedMessage wrapper = new CheckedMessage(); MessageNano.mergeFrom(wrapper, buffer, offset, dataSize); @@ -1004,6 +1114,43 @@ public class LauncherBackupHelper implements BackupHelper { return mWidgetMap.get(component); } + + private boolean initializeIconCache() { + if (mIconCache != null) { + return true; + } + + final LauncherAppState appState = LauncherAppState.getInstanceNoCreate(); + if (appState == null) { + Throwable stackTrace = new Throwable(); + stackTrace.fillInStackTrace(); + Log.w(TAG, "Failed to get app state during backup/restore", stackTrace); + return false; + } + mIconCache = appState.getIconCache(); + return mIconCache != null; + } + + + // check if the launcher is in a state to support backup + private boolean launcherIsReady() { + ContentResolver cr = mContext.getContentResolver(); + Cursor cursor = cr.query(Favorites.CONTENT_URI, FAVORITE_PROJECTION, null, null, null); + if (cursor == null) { + // launcher data has been wiped, do nothing + return false; + } + cursor.close(); + + if (!initializeIconCache()) { + // launcher services are unavailable, try again later + dataChanged(); + return false; + } + + return true; + } + private class KeyParsingException extends Throwable { private KeyParsingException(Throwable cause) { super(cause); diff --git a/src/com/android/launcher3/LauncherClings.java b/src/com/android/launcher3/LauncherClings.java new file mode 100644 index 000000000..e5e0c1621 --- /dev/null +++ b/src/com/android/launcher3/LauncherClings.java @@ -0,0 +1,451 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.launcher3; + +import android.accounts.Account; +import android.accounts.AccountManager; +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.app.ActivityManager; +import android.content.Context; +import android.content.SharedPreferences; +import android.graphics.Rect; +import android.os.Bundle; +import android.os.UserManager; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.accessibility.AccessibilityManager; +import android.widget.TextView; + +class LauncherClings { + private static final String FIRST_RUN_CLING_DISMISSED_KEY = "cling_gel.first_run.dismissed"; + private static final String MIGRATION_CLING_DISMISSED_KEY = "cling_gel.migration.dismissed"; + private static final String MIGRATION_WORKSPACE_CLING_DISMISSED_KEY = + "cling_gel.migration_workspace.dismissed"; + private static final String WORKSPACE_CLING_DISMISSED_KEY = "cling_gel.workspace.dismissed"; + private static final String FOLDER_CLING_DISMISSED_KEY = "cling_gel.folder.dismissed"; + + private static final boolean DISABLE_CLINGS = false; + + private static final int SHOW_CLING_DURATION = 250; + private static final int DISMISS_CLING_DURATION = 200; + + private Launcher mLauncher; + private LayoutInflater mInflater; + private HideFromAccessibilityHelper mHideFromAccessibilityHelper + = new HideFromAccessibilityHelper(); + + /** Ctor */ + public LauncherClings(Launcher launcher) { + mLauncher = launcher; + mInflater = mLauncher.getLayoutInflater(); + } + + /** Initializes a cling */ + private Cling initCling(int clingId, int scrimId, boolean animate, + boolean dimNavBarVisibilty) { + Cling cling = (Cling) mLauncher.findViewById(clingId); + View scrim = null; + if (scrimId > 0) { + scrim = mLauncher.findViewById(scrimId); + } + if (cling != null) { + cling.init(mLauncher, scrim); + cling.show(animate, SHOW_CLING_DURATION); + + if (dimNavBarVisibilty) { + cling.setSystemUiVisibility(cling.getSystemUiVisibility() | + View.SYSTEM_UI_FLAG_LOW_PROFILE); + } + } + return cling; + } + + /** Returns whether the clings are enabled or should be shown */ + private boolean areClingsEnabled() { + if (DISABLE_CLINGS) { + return false; + } + + // disable clings when running in a test harness + if(ActivityManager.isRunningInTestHarness()) return false; + + // Disable clings for accessibility when explore by touch is enabled + final AccessibilityManager a11yManager = (AccessibilityManager) mLauncher.getSystemService( + Launcher.ACCESSIBILITY_SERVICE); + if (a11yManager.isTouchExplorationEnabled()) { + return false; + } + + // Restricted secondary users (child mode) will potentially have very few apps + // seeded when they start up for the first time. Clings won't work well with that + boolean supportsLimitedUsers = + android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2; + Account[] accounts = AccountManager.get(mLauncher).getAccounts(); + if (supportsLimitedUsers && accounts.length == 0) { + UserManager um = (UserManager) mLauncher.getSystemService(Context.USER_SERVICE); + Bundle restrictions = um.getUserRestrictions(); + if (restrictions.getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS, false)) { + return false; + } + } + return true; + } + + /** Returns whether the folder cling is visible. */ + public boolean isFolderClingVisible() { + Cling cling = (Cling) mLauncher.findViewById(R.id.folder_cling); + if (cling != null) { + return cling.getVisibility() == View.VISIBLE; + } + return false; + } + + private boolean skipCustomClingIfNoAccounts() { + Cling cling = (Cling) mLauncher.findViewById(R.id.workspace_cling); + boolean customCling = cling.getDrawIdentifier().equals("workspace_custom"); + if (customCling) { + AccountManager am = AccountManager.get(mLauncher); + if (am == null) return false; + Account[] accounts = am.getAccountsByType("com.google"); + return accounts.length == 0; + } + return false; + } + + /** Updates the first run cling custom content hint */ + private void setCustomContentHintVisibility(Cling cling, String ccHintStr, boolean visible, + boolean animate) { + final TextView ccHint = (TextView) cling.findViewById(R.id.custom_content_hint); + if (ccHint != null) { + if (visible && !ccHintStr.isEmpty()) { + ccHint.setText(ccHintStr); + ccHint.setVisibility(View.VISIBLE); + if (animate) { + ccHint.setAlpha(0f); + ccHint.animate().alpha(1f) + .setDuration(SHOW_CLING_DURATION) + .start(); + } else { + ccHint.setAlpha(1f); + } + } else { + if (animate) { + ccHint.animate().alpha(0f) + .setDuration(SHOW_CLING_DURATION) + .setListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + ccHint.setVisibility(View.GONE); + } + }) + .start(); + } else { + ccHint.setAlpha(0f); + ccHint.setVisibility(View.GONE); + } + } + } + } + + /** Updates the first run cling custom content hint */ + public void updateCustomContentHintVisibility() { + Cling cling = (Cling) mLauncher.findViewById(R.id.first_run_cling); + String ccHintStr = mLauncher.getFirstRunCustomContentHint(); + + if (mLauncher.getWorkspace().hasCustomContent()) { + // Show the custom content hint if ccHintStr is not empty + if (cling != null) { + setCustomContentHintVisibility(cling, ccHintStr, true, true); + } + } else { + // Hide the custom content hint + if (cling != null) { + setCustomContentHintVisibility(cling, ccHintStr, false, true); + } + } + } + + /** Updates the first run cling search bar hint. */ + public void updateSearchBarHint(String hint) { + Cling cling = (Cling) mLauncher.findViewById(R.id.first_run_cling); + if (cling != null && cling.getVisibility() == View.VISIBLE && !hint.isEmpty()) { + TextView sbHint = (TextView) cling.findViewById(R.id.search_bar_hint); + sbHint.setText(hint); + sbHint.setVisibility(View.VISIBLE); + } + } + + public boolean shouldShowFirstRunOrMigrationClings() { + SharedPreferences sharedPrefs = mLauncher.getSharedPrefs(); + return areClingsEnabled() && + !sharedPrefs.getBoolean(FIRST_RUN_CLING_DISMISSED_KEY, false) && + !sharedPrefs.getBoolean(MIGRATION_CLING_DISMISSED_KEY, false); + } + + public void removeFirstRunAndMigrationClings() { + removeCling(R.id.first_run_cling); + removeCling(R.id.migration_cling); + } + + /** + * Shows the first run cling. + * + * This flow is mutually exclusive with showMigrationCling, and only runs if this Launcher + * package was preinstalled or there is no db to migrate from. + */ + public void showFirstRunCling() { + if (!skipCustomClingIfNoAccounts()) { + Cling cling = (Cling) mLauncher.findViewById(R.id.first_run_cling); + if (cling != null) { + String sbHintStr = mLauncher.getFirstRunClingSearchBarHint(); + String ccHintStr = mLauncher.getFirstRunCustomContentHint(); + if (!sbHintStr.isEmpty()) { + TextView sbHint = (TextView) cling.findViewById(R.id.search_bar_hint); + sbHint.setText(sbHintStr); + sbHint.setVisibility(View.VISIBLE); + } + setCustomContentHintVisibility(cling, ccHintStr, true, false); + } + initCling(R.id.first_run_cling, 0, false, true); + } else { + removeFirstRunAndMigrationClings(); + } + } + + /** + * Shows the migration cling. + * + * This flow is mutually exclusive with showFirstRunCling, and only runs if this Launcher + * package was not preinstalled and there exists a db to migrate from. + */ + public void showMigrationCling() { + mLauncher.hideWorkspaceSearchAndHotseat(); + + Cling c = initCling(R.id.migration_cling, 0, false, true); + c.bringScrimToFront(); + c.bringToFront(); + } + + public void showMigrationWorkspaceCling() { + // Enable the clings only if they have not been dismissed before + if (areClingsEnabled() && !mLauncher.getSharedPrefs().getBoolean( + MIGRATION_WORKSPACE_CLING_DISMISSED_KEY, false)) { + Cling c = initCling(R.id.migration_workspace_cling, 0, false, true); + c.updateMigrationWorkspaceBubblePosition(); + c.bringScrimToFront(); + c.bringToFront(); + } else { + removeCling(R.id.migration_workspace_cling); + } + } + + public void showWorkspaceCling() { + // Enable the clings only if they have not been dismissed before + if (areClingsEnabled() && !mLauncher.getSharedPrefs().getBoolean( + WORKSPACE_CLING_DISMISSED_KEY, false)) { + Cling c = initCling(R.id.workspace_cling, 0, false, true); + c.updateWorkspaceBubblePosition(); + + // Set the focused hotseat app if there is one + c.setFocusedHotseatApp(mLauncher.getFirstRunFocusedHotseatAppDrawableId(), + mLauncher.getFirstRunFocusedHotseatAppRank(), + mLauncher.getFirstRunFocusedHotseatAppComponentName(), + mLauncher.getFirstRunFocusedHotseatAppBubbleTitle(), + mLauncher.getFirstRunFocusedHotseatAppBubbleDescription()); + } else { + removeCling(R.id.workspace_cling); + } + } + + public Cling showFoldersCling() { + SharedPreferences sharedPrefs = mLauncher.getSharedPrefs(); + // Enable the clings only if they have not been dismissed before + if (areClingsEnabled() && + !sharedPrefs.getBoolean(FOLDER_CLING_DISMISSED_KEY, false) && + !sharedPrefs.getBoolean(Launcher.USER_HAS_MIGRATED, false)) { + Cling cling = initCling(R.id.folder_cling, R.id.cling_scrim, + true, true); + Folder openFolder = mLauncher.getWorkspace().getOpenFolder(); + if (openFolder != null) { + Rect openFolderRect = new Rect(); + openFolder.getHitRect(openFolderRect); + cling.setOpenFolderRect(openFolderRect); + openFolder.bringToFront(); + } + return cling; + } else { + removeCling(R.id.folder_cling); + return null; + } + } + + public static void synchonouslyMarkFirstRunClingDismissed(Context ctx) { + SharedPreferences prefs = ctx.getSharedPreferences( + LauncherAppState.getSharedPreferencesKey(),Context.MODE_PRIVATE); + SharedPreferences.Editor editor = prefs.edit(); + editor.putBoolean(LauncherClings.FIRST_RUN_CLING_DISMISSED_KEY, true); + editor.commit(); + } + + public void markFolderClingDismissed() { + SharedPreferences.Editor editor = mLauncher.getSharedPrefs().edit(); + editor.putBoolean(LauncherClings.FOLDER_CLING_DISMISSED_KEY, true); + editor.apply(); + } + + /** Removes the cling outright from the DragLayer */ + private void removeCling(int id) { + final View cling = mLauncher.findViewById(id); + if (cling != null) { + final ViewGroup parent = (ViewGroup) cling.getParent(); + parent.post(new Runnable() { + @Override + public void run() { + parent.removeView(cling); + } + }); + mHideFromAccessibilityHelper.restoreImportantForAccessibility(mLauncher.getDragLayer()); + } + } + + /** Hides the specified Cling */ + private void dismissCling(final Cling cling, final Runnable postAnimationCb, + final String flag, int duration, boolean restoreNavBarVisibilty) { + // To catch cases where siblings of top-level views are made invisible, just check whether + // the cling is directly set to GONE before dismissing it. + if (cling != null && cling.getVisibility() != View.GONE) { + final Runnable cleanUpClingCb = new Runnable() { + public void run() { + cling.cleanup(); + SharedPreferences.Editor editor = mLauncher.getSharedPrefs().edit(); + editor.putBoolean(flag, true); + editor.apply(); + if (postAnimationCb != null) { + postAnimationCb.run(); + } + } + }; + if (duration <= 0) { + cleanUpClingCb.run(); + } else { + cling.hide(duration, cleanUpClingCb); + } + mHideFromAccessibilityHelper.restoreImportantForAccessibility(mLauncher.getDragLayer()); + + if (restoreNavBarVisibilty) { + cling.setSystemUiVisibility(cling.getSystemUiVisibility() & + ~View.SYSTEM_UI_FLAG_LOW_PROFILE); + } + } + } + + public void dismissFirstRunCling(View v) { + Cling cling = (Cling) mLauncher.findViewById(R.id.first_run_cling); + Runnable cb = new Runnable() { + public void run() { + // Show the workspace cling next + showWorkspaceCling(); + } + }; + dismissCling(cling, cb, FIRST_RUN_CLING_DISMISSED_KEY, + DISMISS_CLING_DURATION, false); + + // Fade out the search bar for the workspace cling coming up + mLauncher.getSearchBar().hideSearchBar(true); + } + + private void dismissMigrationCling() { + mLauncher.showWorkspaceSearchAndHotseat(); + Runnable dismissCb = new Runnable() { + public void run() { + Cling cling = (Cling) mLauncher.findViewById(R.id.migration_cling); + Runnable cb = new Runnable() { + public void run() { + // Show the migration workspace cling next + showMigrationWorkspaceCling(); + } + }; + dismissCling(cling, cb, MIGRATION_CLING_DISMISSED_KEY, + DISMISS_CLING_DURATION, true); + } + }; + mLauncher.getWorkspace().post(dismissCb); + } + + private void dismissAnyWorkspaceCling(Cling cling, String key, View v) { + Runnable cb = null; + if (v == null) { + cb = new Runnable() { + public void run() { + mLauncher.getWorkspace().enterOverviewMode(); + } + }; + } + dismissCling(cling, cb, key, DISMISS_CLING_DURATION, true); + + // Fade in the search bar + mLauncher.getSearchBar().showSearchBar(true); + } + + public void dismissMigrationClingCopyApps(View v) { + // Copy the shortcuts from the old database + LauncherModel model = mLauncher.getModel(); + model.resetLoadedState(false, true); + model.startLoader(false, PagedView.INVALID_RESTORE_PAGE, + LauncherModel.LOADER_FLAG_CLEAR_WORKSPACE + | LauncherModel.LOADER_FLAG_MIGRATE_SHORTCUTS); + + // Set the flag to skip the folder cling + String spKey = LauncherAppState.getSharedPreferencesKey(); + SharedPreferences sp = mLauncher.getSharedPreferences(spKey, Context.MODE_PRIVATE); + SharedPreferences.Editor editor = sp.edit(); + editor.putBoolean(Launcher.USER_HAS_MIGRATED, true); + editor.apply(); + + // Disable the migration cling + dismissMigrationCling(); + } + + public void dismissMigrationClingUseDefault(View v) { + // Clear the workspace + LauncherModel model = mLauncher.getModel(); + model.resetLoadedState(false, true); + model.startLoader(false, PagedView.INVALID_RESTORE_PAGE, + LauncherModel.LOADER_FLAG_CLEAR_WORKSPACE); + + // Disable the migration cling + dismissMigrationCling(); + } + + public void dismissMigrationWorkspaceCling(View v) { + Cling cling = (Cling) mLauncher.findViewById(R.id.migration_workspace_cling); + dismissAnyWorkspaceCling(cling, MIGRATION_WORKSPACE_CLING_DISMISSED_KEY, v); + } + + public void dismissWorkspaceCling(View v) { + Cling cling = (Cling) mLauncher.findViewById(R.id.workspace_cling); + dismissAnyWorkspaceCling(cling, WORKSPACE_CLING_DISMISSED_KEY, v); + } + + public void dismissFolderCling(View v) { + Cling cling = (Cling) mLauncher.findViewById(R.id.folder_cling); + dismissCling(cling, null, FOLDER_CLING_DISMISSED_KEY, + DISMISS_CLING_DURATION, true); + } +} diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java index e06fe5fb3..9fe0bf3a5 100644 --- a/src/com/android/launcher3/LauncherModel.java +++ b/src/com/android/launcher3/LauncherModel.java @@ -48,6 +48,8 @@ import android.os.Process; import android.os.RemoteException; import android.os.SystemClock; import android.provider.BaseColumns; +import android.text.TextUtils; +import android.provider.Settings; import android.util.Log; import android.util.Pair; @@ -78,13 +80,21 @@ import java.util.concurrent.atomic.AtomicBoolean; public class LauncherModel extends BroadcastReceiver { static final boolean DEBUG_LOADERS = false; static final String TAG = "Launcher.Model"; + public static final String SETTINGS_PROTECTED_COMPONENTS = "protected_components"; // true = use a "More Apps" folder for non-workspace apps on upgrade // false = strew non-workspace apps across the workspace on upgrade public static final boolean UPGRADE_USE_MORE_APPS_FOLDER = false; + public static final int LOADER_FLAG_NONE = 0; + public static final int LOADER_FLAG_CLEAR_WORKSPACE = 1 << 0; + public static final int LOADER_FLAG_MIGRATE_SHORTCUTS = 1 << 1; + private static final int ITEMS_CHUNK = 6; // batch size for the workspace icons + private static final long INVALID_SCREEN_ID = -1L; + private final boolean mAppsCanBeOnRemoveableStorage; + private final boolean mOldContentProviderExists; private final LauncherAppState mApp; private final Object mLock = new Object(); @@ -175,8 +185,7 @@ public class LauncherModel extends BroadcastReceiver { ArrayList<AppInfo> addedApps); public void bindAppsUpdated(ArrayList<AppInfo> apps); public void bindComponentsRemoved(ArrayList<String> packageNames, - ArrayList<AppInfo> appInfos, - boolean matchPackageNamesOnly); + ArrayList<AppInfo> appInfos); public void bindPackagesUpdated(ArrayList<Object> widgetsAndShortcuts); public void bindSearchablesChanged(); public void onPageBoundSynchronously(int page); @@ -188,16 +197,16 @@ public class LauncherModel extends BroadcastReceiver { } LauncherModel(LauncherAppState app, IconCache iconCache, AppFilter appFilter) { - final Context context = app.getContext(); + Context context = app.getContext(); + ContentResolver contentResolver = context.getContentResolver(); mAppsCanBeOnRemoveableStorage = Environment.isExternalStorageRemovable(); + mOldContentProviderExists = (contentResolver.acquireContentProviderClient( + LauncherSettings.Favorites.OLD_CONTENT_URI) != null); mApp = app; mBgAllAppsList = new AllAppsList(iconCache, appFilter); mIconCache = iconCache; - mDefaultIcon = Utilities.createIconBitmap( - mIconCache.getFullResDefaultActivityIcon(), context); - final Resources res = context.getResources(); Configuration config = res.getConfiguration(); mPreviousConfigMcc = config.mcc; @@ -228,6 +237,10 @@ public class LauncherModel extends BroadcastReceiver { } } + boolean canMigrateFromOldLauncherDb(Launcher launcher) { + return mOldContentProviderExists && !launcher.isLauncherPreinstalled() ; + } + static boolean findNextAvailableIconSpaceInScreen(ArrayList<ItemInfo> items, int[] xy, long screen) { LauncherAppState app = LauncherAppState.getInstance(); @@ -289,14 +302,58 @@ public class LauncherModel extends BroadcastReceiver { return null; } - public void addAndBindAddedApps(final Context context, final ArrayList<ItemInfo> workspaceApps, - final ArrayList<AppInfo> allAppsApps) { - Callbacks cb = mCallbacks != null ? mCallbacks.get() : null; - addAndBindAddedApps(context, workspaceApps, cb, allAppsApps); + public void addAppsToAllApps(final Context ctx, final ArrayList<AppInfo> allAppsApps) { + final Callbacks callbacks = mCallbacks != null ? mCallbacks.get() : null; + + if (allAppsApps == null) { + throw new RuntimeException("allAppsApps must not be null"); + } + if (allAppsApps.isEmpty()) { + return; + } + + final ArrayList<AppInfo> restoredAppsFinal = new ArrayList<AppInfo>(); + Iterator<AppInfo> iter = allAppsApps.iterator(); + while (iter.hasNext()) { + ItemInfo a = iter.next(); + if (LauncherModel.appWasRestored(ctx, a.getIntent())) { + restoredAppsFinal.add((AppInfo) a); + } + } + + // Process the newly added applications and add them to the database first + Runnable r = new Runnable() { + public void run() { + runOnMainThread(new Runnable() { + public void run() { + Callbacks cb = mCallbacks != null ? mCallbacks.get() : null; + if (callbacks == cb && cb != null) { + if (!restoredAppsFinal.isEmpty()) { + for (AppInfo info : restoredAppsFinal) { + final Intent intent = info.getIntent(); + if (intent != null) { + mIconCache.deletePreloadedIcon(intent.getComponent()); + } + } + callbacks.bindAppsUpdated(restoredAppsFinal); + } + callbacks.bindAppsAdded(null, null, null, allAppsApps); + } + } + }); + } + }; + runOnWorkerThread(r); } - public void addAndBindAddedApps(final Context context, final ArrayList<ItemInfo> workspaceApps, - final Callbacks callbacks, final ArrayList<AppInfo> allAppsApps) { - if (workspaceApps.isEmpty() && allAppsApps.isEmpty()) { + + public void addAndBindAddedWorkspaceApps(final Context context, + final ArrayList<ItemInfo> workspaceApps) { + final Callbacks callbacks = mCallbacks != null ? mCallbacks.get() : null; + + if (workspaceApps == null) { + throw new RuntimeException("workspaceApps and allAppsApps must not be null"); + } + if (workspaceApps.isEmpty()) { return; } // Process the newly added applications and add them to the database first @@ -304,6 +361,7 @@ public class LauncherModel extends BroadcastReceiver { public void run() { final ArrayList<ItemInfo> addedShortcutsFinal = new ArrayList<ItemInfo>(); final ArrayList<Long> addedWorkspaceScreensFinal = new ArrayList<Long>(); + final ArrayList<AppInfo> restoredAppsFinal = new ArrayList<AppInfo>(); // Get the list of workspace screens. We need to append to this list and // can not use sBgWorkspaceScreens because loadWorkspace() may not have been @@ -324,6 +382,11 @@ public class LauncherModel extends BroadcastReceiver { // Short-circuit this logic if the icon exists somewhere on the workspace if (LauncherModel.shortcutExists(context, name, launchIntent)) { + // Only InstallShortcutReceiver sends us shortcutInfos, ignore them + if (a instanceof AppInfo && + LauncherModel.appWasRestored(context, launchIntent)) { + restoredAppsFinal.add((AppInfo) a); + } continue; } @@ -379,7 +442,7 @@ public class LauncherModel extends BroadcastReceiver { // Update the workspace screens updateWorkspaceScreenOrder(context, workspaceScreens); - if (!addedShortcutsFinal.isEmpty() || !allAppsApps.isEmpty()) { + if (!addedShortcutsFinal.isEmpty()) { runOnMainThread(new Runnable() { public void run() { Callbacks cb = mCallbacks != null ? mCallbacks.get() : null; @@ -398,7 +461,10 @@ public class LauncherModel extends BroadcastReceiver { } } callbacks.bindAppsAdded(addedWorkspaceScreensFinal, - addNotAnimated, addAnimated, allAppsApps); + addNotAnimated, addAnimated, null); + if (!restoredAppsFinal.isEmpty()) { + callbacks.bindAppsUpdated(restoredAppsFinal); + } } } }); @@ -409,6 +475,11 @@ public class LauncherModel extends BroadcastReceiver { } public Bitmap getFallbackIcon() { + if (mDefaultIcon == null) { + final Context context = LauncherAppState.getInstance().getContext(); + mDefaultIcon = Utilities.createIconBitmap( + mIconCache.getFullResDefaultActivityIcon(), context); + } return Bitmap.createBitmap(mDefaultIcon); } @@ -504,8 +575,7 @@ public class LauncherModel extends BroadcastReceiver { if (stackTrace != null) { e.setStackTrace(stackTrace); } - // TODO: something breaks this in the upgrade path - //throw e; + throw e; } } @@ -589,8 +659,9 @@ public class LauncherModel extends BroadcastReceiver { // as in Workspace.onDrop. Here, we just add/remove them from the list of items // that are on the desktop, as appropriate ItemInfo modelItem = sBgItemsIdMap.get(itemId); - if (modelItem.container == LauncherSettings.Favorites.CONTAINER_DESKTOP || - modelItem.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) { + if (modelItem != null && + (modelItem.container == LauncherSettings.Favorites.CONTAINER_DESKTOP || + modelItem.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT)) { switch (modelItem.itemType) { case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION: case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT: @@ -760,6 +831,30 @@ public class LauncherModel extends BroadcastReceiver { } /** + * Returns true if the shortcuts already exists in the database. + * we identify a shortcut by the component name of the intent. + */ + static boolean appWasRestored(Context context, Intent intent) { + final ContentResolver cr = context.getContentResolver(); + final ComponentName component = intent.getComponent(); + if (component == null) { + return false; + } + String componentName = component.flattenToString(); + final String where = "intent glob \"*component=" + componentName + "*\" and restored = 1"; + Cursor c = cr.query(LauncherSettings.Favorites.CONTENT_URI, + new String[]{"intent", "restored"}, where, null, null); + boolean result = false; + try { + result = c.moveToFirst(); + } finally { + c.close(); + } + Log.d(TAG, "shortcutWasRestored is " + result + " for " + componentName); + return result; + } + + /** * Returns an ItemInfo array containing all the items in the LauncherModel. * The ItemInfo.id is not set through this function. */ @@ -819,6 +914,7 @@ public class LauncherModel extends BroadcastReceiver { final int screenIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SCREEN); final int cellXIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLX); final int cellYIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLY); + final int hiddenIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.HIDDEN); FolderInfo folderInfo = null; switch (c.getInt(itemTypeIndex)) { @@ -833,6 +929,7 @@ public class LauncherModel extends BroadcastReceiver { folderInfo.screenId = c.getInt(screenIndex); folderInfo.cellX = c.getInt(cellXIndex); folderInfo.cellY = c.getInt(cellYIndex); + folderInfo.hidden = c.getInt(hiddenIndex) > 0; return folderInfo; } @@ -1017,6 +1114,10 @@ public class LauncherModel extends BroadcastReceiver { * a list of screen ids in the order that they should appear. */ void updateWorkspaceScreenOrder(Context context, final ArrayList<Long> screens) { + // Log to disk + Launcher.addDumpLog(TAG, "11683562 - updateWorkspaceScreenOrder()", true); + Launcher.addDumpLog(TAG, "11683562 - screens: " + TextUtils.join(", ", screens), true); + final ArrayList<Long> screensCopy = new ArrayList<Long>(screens); final ContentResolver cr = context.getContentResolver(); final Uri uri = LauncherSettings.WorkspaceScreens.CONTENT_URI; @@ -1033,18 +1134,23 @@ public class LauncherModel extends BroadcastReceiver { Runnable r = new Runnable() { @Override public void run() { + ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>(); // Clear the table - cr.delete(uri, null, null); + ops.add(ContentProviderOperation.newDelete(uri).build()); int count = screensCopy.size(); - ContentValues[] values = new ContentValues[count]; for (int i = 0; i < count; i++) { ContentValues v = new ContentValues(); long screenId = screensCopy.get(i); v.put(LauncherSettings.WorkspaceScreens._ID, screenId); v.put(LauncherSettings.WorkspaceScreens.SCREEN_RANK, i); - values[i] = v; + ops.add(ContentProviderOperation.newInsert(uri).withValues(v).build()); + } + + try { + cr.applyBatch(LauncherProvider.AUTHORITY, ops); + } catch (Exception ex) { + throw new RuntimeException(ex); } - cr.bulkInsert(uri, values); synchronized (sBgLock) { sBgWorkspaceScreens.clear(); @@ -1139,15 +1245,29 @@ public class LauncherModel extends BroadcastReceiver { } } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(action)) { - // First, schedule to add these apps back in. + final boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false); String[] packages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST); - enqueuePackageUpdated(new PackageUpdatedTask(PackageUpdatedTask.OP_ADD, packages)); - // Then, rebind everything. - startLoaderFromBackground(); + if (!replacing) { + enqueuePackageUpdated(new PackageUpdatedTask(PackageUpdatedTask.OP_ADD, packages)); + if (mAppsCanBeOnRemoveableStorage) { + // Only rebind if we support removable storage. It catches the case where + // apps on the external sd card need to be reloaded + startLoaderFromBackground(); + } + } else { + // If we are replacing then just update the packages in the list + enqueuePackageUpdated(new PackageUpdatedTask(PackageUpdatedTask.OP_UPDATE, + packages)); + } } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) { - String[] packages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST); - enqueuePackageUpdated(new PackageUpdatedTask( - PackageUpdatedTask.OP_UNAVAILABLE, packages)); + final boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false); + if (!replacing) { + String[] packages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST); + enqueuePackageUpdated(new PackageUpdatedTask( + PackageUpdatedTask.OP_UNAVAILABLE, packages)); + } + // else, we are replacing the packages, so ignore this event and wait for + // EXTERNAL_APPLICATIONS_AVAILABLE to update the packages at that time } else if (Intent.ACTION_LOCALE_CHANGED.equals(action)) { // If we have changed locale we need to clear out the labels in all apps/workspace. forceReload(); @@ -1211,7 +1331,7 @@ public class LauncherModel extends BroadcastReceiver { } } if (runLoader) { - startLoader(false, -1); + startLoader(false, PagedView.INVALID_RESTORE_PAGE); } } @@ -1230,6 +1350,10 @@ public class LauncherModel extends BroadcastReceiver { } public void startLoader(boolean isLaunching, int synchronousBindPage) { + startLoader(isLaunching, synchronousBindPage, LOADER_FLAG_NONE); + } + + public void startLoader(boolean isLaunching, int synchronousBindPage, int loadFlags) { synchronized (mLock) { if (DEBUG_LOADERS) { Log.d(TAG, "startLoader isLaunching=" + isLaunching); @@ -1244,8 +1368,9 @@ public class LauncherModel extends BroadcastReceiver { // If there is already one running, tell it to stop. // also, don't downgrade isLaunching if we're already running isLaunching = isLaunching || stopLoaderLocked(); - mLoaderTask = new LoaderTask(mApp.getContext(), isLaunching); - if (synchronousBindPage > -1 && mAllAppsLoaded && mWorkspaceLoaded) { + mLoaderTask = new LoaderTask(mApp.getContext(), isLaunching, loadFlags); + if (synchronousBindPage != PagedView.INVALID_RESTORE_PAGE + && mAllAppsLoaded && mWorkspaceLoaded) { mLoaderTask.runBindSynchronousPage(synchronousBindPage); } else { sWorkerThread.setPriority(Thread.NORM_PRIORITY); @@ -1297,6 +1422,15 @@ public class LauncherModel extends BroadcastReceiver { } finally { sc.close(); } + + // Log to disk + Launcher.addDumpLog(TAG, "11683562 - loadWorkspaceScreensDb()", true); + ArrayList<String> orderedScreensPairs= new ArrayList<String>(); + for (Integer i : orderedScreens.keySet()) { + orderedScreensPairs.add("{ " + i + ": " + orderedScreens.get(i) + " }"); + } + Launcher.addDumpLog(TAG, "11683562 - screens: " + + TextUtils.join(", ", orderedScreensPairs), true); return orderedScreens; } @@ -1313,75 +1447,6 @@ public class LauncherModel extends BroadcastReceiver { return false; } - // check & update map of what's occupied; used to discard overlapping/invalid items - public boolean checkItemPlacement(HashMap<Long, ItemInfo[][]> occupied, ItemInfo item, - AtomicBoolean deleteOnItemOverlap) { - LauncherAppState app = LauncherAppState.getInstance(); - DeviceProfile grid = app.getDynamicGrid().getDeviceProfile(); - - long containerIndex = item.screenId; - if (item.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) { - if (occupied.containsKey((long) LauncherSettings.Favorites.CONTAINER_HOTSEAT)) { - if (occupied.get((long) LauncherSettings.Favorites.CONTAINER_HOTSEAT) - [(int) item.screenId][0] != null) { - Log.e(TAG, "Error loading shortcut into hotseat " + item - + " into position (" + item.screenId + ":" + item.cellX + "," - + item.cellY + ") occupied by " - + occupied.get((long) LauncherSettings.Favorites.CONTAINER_HOTSEAT) - [(int) item.screenId][0]); - if (occupied.get((long) LauncherSettings.Favorites.CONTAINER_HOTSEAT) - [(int) item.screenId][0].itemType == LauncherSettings.Favorites.ITEM_TYPE_ALLAPPS) { - deleteOnItemOverlap.set(true); - } - return false; - } else { - ItemInfo[][] hotseatItems = occupied.get( - (long) LauncherSettings.Favorites.CONTAINER_HOTSEAT); - hotseatItems[(int) item.screenId][0] = item; - return true; - } - } else { - ItemInfo[][] items = new ItemInfo[(int) grid.numHotseatIcons][1]; - items[(int) item.screenId][0] = item; - occupied.put((long) LauncherSettings.Favorites.CONTAINER_HOTSEAT, items); - return true; - } - } else if (item.container != LauncherSettings.Favorites.CONTAINER_DESKTOP) { - // Skip further checking if it is not the hotseat or workspace container - return true; - } - - int countX = (int) grid.numColumns; - int countY = (int) grid.numRows; - - if (!occupied.containsKey(item.screenId)) { - ItemInfo[][] items = new ItemInfo[countX + 1][countY + 1]; - occupied.put(item.screenId, items); - } - - ItemInfo[][] screens = occupied.get(item.screenId); - // Check if any workspace icons overlap with each other - for (int x = item.cellX; x < (item.cellX+item.spanX); x++) { - for (int y = item.cellY; y < (item.cellY+item.spanY); y++) { - if (screens[x][y] != null) { - Log.e(TAG, "Error loading shortcut " + item - + " into cell (" + containerIndex + "-" + item.screenId + ":" - + x + "," + y - + ") occupied by " - + screens[x][y]); - return false; - } - } - } - for (int x = item.cellX; x < (item.cellX+item.spanX); x++) { - for (int y = item.cellY; y < (item.cellY+item.spanY); y++) { - screens[x][y] = item; - } - } - - return true; - } - /** * Runnable for the thread that loads the contents of the launcher: * - workspace icons @@ -1394,13 +1459,15 @@ public class LauncherModel extends BroadcastReceiver { private boolean mIsLoadingAndBindingWorkspace; private boolean mStopped; private boolean mLoadAndBindStepFinished; + private int mFlags; private HashMap<Object, CharSequence> mLabelCache; - LoaderTask(Context context, boolean isLaunching) { + LoaderTask(Context context, boolean isLaunching, int flags) { mContext = context; mIsLaunching = isLaunching; mLabelCache = new HashMap<Object, CharSequence>(); + mFlags = flags; } boolean isLaunching() { @@ -1473,7 +1540,7 @@ public class LauncherModel extends BroadcastReceiver { } void runBindSynchronousPage(int synchronousBindPage) { - if (synchronousBindPage < 0) { + if (synchronousBindPage == PagedView.INVALID_RESTORE_PAGE) { // Ensure that we have a valid page index to load synchronously throw new RuntimeException("Should not call runBindSynchronousPage() without " + "valid page index"); @@ -1562,7 +1629,7 @@ public class LauncherModel extends BroadcastReceiver { sBgDbIconCache.clear(); } - if (AppsCustomizePagedView.DISABLE_ALL_APPS) { + if (LauncherAppState.isDisableAllApps()) { // Ensure that all the applications that are in the system are // represented on the home screen. if (!UPGRADE_USE_MORE_APPS_FOLDER || !isUpgrade) { @@ -1638,16 +1705,90 @@ public class LauncherModel extends BroadcastReceiver { } } if (!added.isEmpty()) { - Callbacks cb = mCallbacks != null ? mCallbacks.get() : null; - addAndBindAddedApps(context, added, cb, null); + addAndBindAddedWorkspaceApps(context, added); } } - private boolean checkItemDimensions(ItemInfo info) { + private boolean checkItemPlacement(HashMap<Long, ItemInfo[][]> occupied, ItemInfo item, + AtomicBoolean deleteOnInvalidPlacement) { LauncherAppState app = LauncherAppState.getInstance(); DeviceProfile grid = app.getDynamicGrid().getDeviceProfile(); - return (info.cellX + info.spanX) > (int) grid.numColumns || - (info.cellY + info.spanY) > (int) grid.numRows; + final int countX = (int) grid.numColumns; + final int countY = (int) grid.numRows; + long containerIndex = item.screenId; + if (item.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) { + // Return early if we detect that an item is under the hotseat button + if (mCallbacks == null) { + deleteOnInvalidPlacement.set(true); + Log.e(TAG, "Error loading shortcut into hotseat " + item + + " into position (" + item.screenId + ":" + item.cellX + "," + + item.cellY + ") occupied by all apps"); + return false; + } + final ItemInfo[][] hotseatItems = + occupied.get((long) LauncherSettings.Favorites.CONTAINER_HOTSEAT); + if (item.screenId >= grid.numHotseatIcons) { + Log.e(TAG, "Error loading shortcut " + item + + " into hotseat position " + item.screenId + + ", position out of bounds: (0 to " + (grid.numHotseatIcons - 1) + + ")"); + return false; + } + if (hotseatItems != null) { + if (hotseatItems[(int) item.screenId][0] != null) { + Log.e(TAG, "Error loading shortcut into hotseat " + item + + " into position (" + item.screenId + ":" + item.cellX + "," + + item.cellY + ") occupied by " + + occupied.get(LauncherSettings.Favorites.CONTAINER_HOTSEAT) + [(int) item.screenId][0]); + return false; + } else { + hotseatItems[(int) item.screenId][0] = item; + return true; + } + } else { + final ItemInfo[][] items = new ItemInfo[(int) grid.numHotseatIcons][1]; + items[(int) item.screenId][0] = item; + occupied.put((long) LauncherSettings.Favorites.CONTAINER_HOTSEAT, items); + return true; + } + } else if (item.container != LauncherSettings.Favorites.CONTAINER_DESKTOP) { + // Skip further checking if it is not the hotseat or workspace container + return true; + } + if (!occupied.containsKey(item.screenId)) { + ItemInfo[][] items = new ItemInfo[countX + 1][countY + 1]; + occupied.put(item.screenId, items); + } + final ItemInfo[][] screens = occupied.get(item.screenId); + if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP && + item.cellX < 0 || item.cellY < 0 || + item.cellX + item.spanX > countX || item.cellY + item.spanY > countY) { + Log.e(TAG, "Error loading shortcut " + item + + " into cell (" + containerIndex + "-" + item.screenId + ":" + + item.cellX + "," + item.cellY + + ") out of screen bounds ( " + countX + "x" + countY + ")"); + return false; + } + // Check if any workspace icons overlap with each other + for (int x = item.cellX; x < (item.cellX+item.spanX); x++) { + for (int y = item.cellY; y < (item.cellY+item.spanY); y++) { + if (screens[x][y] != null) { + Log.e(TAG, "Error loading shortcut " + item + + " into cell (" + containerIndex + "-" + item.screenId + ":" + + x + "," + y + + ") occupied by " + + screens[x][y]); + return false; + } + } + } + for (int x = item.cellX; x < (item.cellX+item.spanX); x++) { + for (int y = item.cellY; y < (item.cellY+item.spanY); y++) { + screens[x][y] = item; + } + } + return true; } /** Clears all the sBg data structures */ @@ -1662,8 +1803,11 @@ public class LauncherModel extends BroadcastReceiver { } } - /** Returns whether this is an upgradge path */ + /** Returns whether this is an upgrade path */ private boolean loadWorkspace() { + // Log to disk + Launcher.addDumpLog(TAG, "11683562 - loadWorkspace()", true); + final long t = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0; final Context context = mContext; @@ -1677,16 +1821,33 @@ public class LauncherModel extends BroadcastReceiver { int countX = (int) grid.numColumns; int countY = (int) grid.numRows; - // Make sure the default workspace is loaded, if needed - LauncherAppState.getLauncherProvider().loadDefaultFavoritesIfNecessary(0); + if ((mFlags & LOADER_FLAG_CLEAR_WORKSPACE) != 0) { + Launcher.addDumpLog(TAG, "loadWorkspace: resetting launcher database", true); + LauncherAppState.getLauncherProvider().deleteDatabase(); + } + + if ((mFlags & LOADER_FLAG_MIGRATE_SHORTCUTS) != 0) { + // append the user's Launcher2 shortcuts + Launcher.addDumpLog(TAG, "loadWorkspace: migrating from launcher2", true); + LauncherAppState.getLauncherProvider().migrateLauncher2Shortcuts(); + } else { + // Make sure the default workspace is loaded + Launcher.addDumpLog(TAG, "loadWorkspace: loading default favorites", false); + LauncherAppState.getLauncherProvider().loadDefaultFavoritesIfNecessary(0); + } // Check if we need to do any upgrade-path logic + // (Includes having just imported default favorites) boolean loadedOldDb = LauncherAppState.getLauncherProvider().justLoadedOldDb(); + // Log to disk + Launcher.addDumpLog(TAG, "11683562 - loadedOldDb: " + loadedOldDb, true); + synchronized (sBgLock) { clearSBgDataStructures(); final ArrayList<Long> itemsToRemove = new ArrayList<Long>(); + final ArrayList<Long> restoredRows = new ArrayList<Long>(); final Uri contentUri = LauncherSettings.Favorites.CONTENT_URI; if (DEBUG_LOADERS) Log.d(TAG, "loading model from " + contentUri); final Cursor c = contentResolver.query(contentUri, null, null, null, null); @@ -1727,8 +1888,11 @@ public class LauncherModel extends BroadcastReceiver { (LauncherSettings.Favorites.SPANX); final int spanYIndex = c.getColumnIndexOrThrow( LauncherSettings.Favorites.SPANY); - //final int uriIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.URI); - //final int displayModeIndex = c.getColumnIndexOrThrow( + final int restoredIndex = c.getColumnIndexOrThrow( + LauncherSettings.Favorites.RESTORED); + final int hiddenIndex = c.getColumnIndexOrThrow( + LauncherSettings.Favorites.HIDDEN); + //final int uriIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.URI); //final int displayModeIndex = c.getColumnIndexOrThrow( // LauncherSettings.Favorites.DISPLAY_MODE); ShortcutInfo info; @@ -1739,9 +1903,10 @@ public class LauncherModel extends BroadcastReceiver { Intent intent = null; while (!mStopped && c.moveToNext()) { - AtomicBoolean deleteOnItemOverlap = new AtomicBoolean(false); + AtomicBoolean deleteOnInvalidPlacement = new AtomicBoolean(false); try { int itemType = c.getInt(itemTypeIndex); + boolean restored = 0 != c.getInt(restoredIndex); switch (itemType) { case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION: @@ -1754,25 +1919,45 @@ public class LauncherModel extends BroadcastReceiver { intent = Intent.parseUri(intentDescription, 0); ComponentName cn = intent.getComponent(); if (cn != null && !isValidPackageComponent(manager, cn)) { - if (!mAppsCanBeOnRemoveableStorage) { - // Log the invalid package, and remove it from the db - Launcher.addDumpLog(TAG, "Invalid package removed: " + cn, true); - itemsToRemove.add(id); + if (restored) { + // might be installed later + Launcher.addDumpLog(TAG, + "package not yet restored: " + cn, true); } else { - // If apps can be on external storage, then we just - // leave them for the user to remove (maybe add - // visual treatment to it) - Launcher.addDumpLog(TAG, "Invalid package found: " + cn, true); + if (!mAppsCanBeOnRemoveableStorage) { + // Log the invalid package, and remove it + Launcher.addDumpLog(TAG, + "Invalid package removed: " + cn, true); + itemsToRemove.add(id); + } else { + // If apps can be on external storage, then we just + // leave them for the user to remove (maybe add + // visual treatment to it) + Launcher.addDumpLog(TAG, + "Invalid package found: " + cn, true); + } + continue; } - continue; + } else if (restored) { + // no special handling necessary for this restored item + restoredRows.add(id); + restored = false; } } catch (URISyntaxException e) { - Launcher.addDumpLog(TAG, "Invalid uri: " + intentDescription, true); + Launcher.addDumpLog(TAG, + "Invalid uri: " + intentDescription, true); continue; } } - if (itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) { + if (restored) { + Launcher.addDumpLog(TAG, + "constructing info for partially restored package", + true); + info = getRestoredItemInfo(c, titleIndex, intent); + intent = getRestoredItemIntent(c, context, intent); + } else if (itemType == + LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) { info = getShortcutInfo(manager, intent, context, c, iconIndex, titleIndex, mLabelCache); } else if (itemType == LauncherSettings.Favorites.ITEM_TYPE_ALLAPPS) { @@ -1806,18 +1991,11 @@ public class LauncherModel extends BroadcastReceiver { info.cellY = c.getInt(cellYIndex); info.spanX = 1; info.spanY = 1; - // Skip loading items that are out of bounds - if (container == LauncherSettings.Favorites.CONTAINER_DESKTOP) { - if (checkItemDimensions(info)) { - Launcher.addDumpLog(TAG, "Skipped loading out of bounds shortcut: " - + info + ", " + grid.numColumns + "x" + grid.numRows, true); - continue; - } - } + // check & update map of what's occupied - deleteOnItemOverlap.set(false); - if (!checkItemPlacement(occupied, info, deleteOnItemOverlap)) { - if (deleteOnItemOverlap.get()) { + deleteOnInvalidPlacement.set(false); + if (!checkItemPlacement(occupied, info, deleteOnInvalidPlacement)) { + if (deleteOnInvalidPlacement.get()) { itemsToRemove.add(id); } break; @@ -1858,19 +2036,13 @@ public class LauncherModel extends BroadcastReceiver { folderInfo.cellY = c.getInt(cellYIndex); folderInfo.spanX = 1; folderInfo.spanY = 1; + folderInfo.hidden = c.getInt(hiddenIndex) > 0; - // Skip loading items that are out of bounds - if (container == LauncherSettings.Favorites.CONTAINER_DESKTOP) { - if (checkItemDimensions(folderInfo)) { - Log.d(TAG, "Skipped loading out of bounds folder"); - continue; - } - } // check & update map of what's occupied - deleteOnItemOverlap.set(false); + deleteOnInvalidPlacement.set(false); if (!checkItemPlacement(occupied, folderInfo, - deleteOnItemOverlap)) { - if (deleteOnItemOverlap.get()) { + deleteOnInvalidPlacement)) { + if (deleteOnInvalidPlacement.get()) { itemsToRemove.add(id); } break; @@ -1883,6 +2055,11 @@ public class LauncherModel extends BroadcastReceiver { break; } + if (restored) { + // no special handling required for restored folders + restoredRows.add(id); + } + sBgItemsIdMap.put(folderInfo.id, folderInfo); sBgFolders.put(folderInfo.id, folderInfo); break; @@ -1926,18 +2103,11 @@ public class LauncherModel extends BroadcastReceiver { } appWidgetInfo.container = c.getInt(containerIndex); - // Skip loading items that are out of bounds - if (container == LauncherSettings.Favorites.CONTAINER_DESKTOP) { - if (checkItemDimensions(appWidgetInfo)) { - Log.d(TAG, "Skipped loading out of bounds app widget"); - continue; - } - } // check & update map of what's occupied - deleteOnItemOverlap.set(false); + deleteOnInvalidPlacement.set(false); if (!checkItemPlacement(occupied, appWidgetInfo, - deleteOnItemOverlap)) { - if (deleteOnItemOverlap.get()) { + deleteOnInvalidPlacement)) { + if (deleteOnInvalidPlacement.get()) { itemsToRemove.add(id); } break; @@ -1957,7 +2127,7 @@ public class LauncherModel extends BroadcastReceiver { break; } } catch (Exception e) { - Launcher.addDumpLog(TAG, "Desktop items loading interrupted: " + e, true); + Launcher.addDumpLog(TAG, "Desktop items loading interrupted", e, true); } } } finally { @@ -2003,6 +2173,25 @@ public class LauncherModel extends BroadcastReceiver { } } + if (restoredRows.size() > 0) { + ContentProviderClient updater = contentResolver.acquireContentProviderClient( + LauncherSettings.Favorites.CONTENT_URI); + // Update restored items that no longer require special handling + try { + StringBuilder selectionBuilder = new StringBuilder(); + selectionBuilder.append(LauncherSettings.Favorites._ID); + selectionBuilder.append(" IN ("); + selectionBuilder.append(TextUtils.join(", ", restoredRows)); + selectionBuilder.append(")"); + ContentValues values = new ContentValues(); + values.put(LauncherSettings.Favorites.RESTORED, 0); + updater.update(LauncherSettings.Favorites.CONTENT_URI, + values, selectionBuilder.toString(), null); + } catch (RemoteException e) { + Log.w(TAG, "Could not update restored rows"); + } + } + if (loadedOldDb) { long maxScreenId = 0; // If we're importing we use the old screen order. @@ -2017,6 +2206,10 @@ public class LauncherModel extends BroadcastReceiver { } } Collections.sort(sBgWorkspaceScreens); + // Log to disk + Launcher.addDumpLog(TAG, "11683562 - maxScreenId: " + maxScreenId, true); + Launcher.addDumpLog(TAG, "11683562 - sBgWorkspaceScreens: " + + TextUtils.join(", ", sBgWorkspaceScreens), true); LauncherAppState.getLauncherProvider().updateMaxScreenId(maxScreenId); updateWorkspaceScreenOrder(context, sBgWorkspaceScreens); @@ -2033,6 +2226,9 @@ public class LauncherModel extends BroadcastReceiver { for (Integer i : orderedScreens.keySet()) { sBgWorkspaceScreens.add(orderedScreens.get(i)); } + // Log to disk + Launcher.addDumpLog(TAG, "11683562 - sBgWorkspaceScreens: " + + TextUtils.join(", ", sBgWorkspaceScreens), true); // Remove any empty screens ArrayList<Long> unusedScreens = new ArrayList<Long>(sBgWorkspaceScreens); @@ -2046,6 +2242,10 @@ public class LauncherModel extends BroadcastReceiver { // If there are any empty screens remove them, and update. if (unusedScreens.size() != 0) { + // Log to disk + Launcher.addDumpLog(TAG, "11683562 - unusedScreens (to be removed): " + + TextUtils.join(", ", unusedScreens), true); + sBgWorkspaceScreens.removeAll(unusedScreens); updateWorkspaceScreenOrder(context, sBgWorkspaceScreens); } @@ -2077,7 +2277,7 @@ public class LauncherModel extends BroadcastReceiver { /** Filters the set of items who are directly or indirectly (via another container) on the * specified screen. */ - private void filterCurrentWorkspaceItems(int currentScreen, + private void filterCurrentWorkspaceItems(long currentScreenId, ArrayList<ItemInfo> allWorkspaceItems, ArrayList<ItemInfo> currentScreenItems, ArrayList<ItemInfo> otherScreenItems) { @@ -2090,12 +2290,6 @@ public class LauncherModel extends BroadcastReceiver { } } - // If we aren't filtering on a screen, then the set of items to load is the full set of - // items given. - if (currentScreen < 0) { - currentScreenItems.addAll(allWorkspaceItems); - } - // Order the set of items by their containers first, this allows use to walk through the // list sequentially, build up a list of containers that are in the specified screen, // as well as all items in those containers. @@ -2108,7 +2302,7 @@ public class LauncherModel extends BroadcastReceiver { }); for (ItemInfo info : allWorkspaceItems) { if (info.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) { - if (info.screenId == currentScreen) { + if (info.screenId == currentScreenId) { currentScreenItems.add(info); itemsOnScreen.add(info.id); } else { @@ -2129,20 +2323,15 @@ public class LauncherModel extends BroadcastReceiver { } /** Filters the set of widgets which are on the specified screen. */ - private void filterCurrentAppWidgets(int currentScreen, + private void filterCurrentAppWidgets(long currentScreenId, ArrayList<LauncherAppWidgetInfo> appWidgets, ArrayList<LauncherAppWidgetInfo> currentScreenWidgets, ArrayList<LauncherAppWidgetInfo> otherScreenWidgets) { - // If we aren't filtering on a screen, then the set of items to load is the full set of - // widgets given. - if (currentScreen < 0) { - currentScreenWidgets.addAll(appWidgets); - } for (LauncherAppWidgetInfo widget : appWidgets) { if (widget == null) continue; if (widget.container == LauncherSettings.Favorites.CONTAINER_DESKTOP && - widget.screenId == currentScreen) { + widget.screenId == currentScreenId) { currentScreenWidgets.add(widget); } else { otherScreenWidgets.add(widget); @@ -2151,23 +2340,18 @@ public class LauncherModel extends BroadcastReceiver { } /** Filters the set of folders which are on the specified screen. */ - private void filterCurrentFolders(int currentScreen, + private void filterCurrentFolders(long currentScreenId, HashMap<Long, ItemInfo> itemsIdMap, HashMap<Long, FolderInfo> folders, HashMap<Long, FolderInfo> currentScreenFolders, HashMap<Long, FolderInfo> otherScreenFolders) { - // If we aren't filtering on a screen, then the set of items to load is the full set of - // widgets given. - if (currentScreen < 0) { - currentScreenFolders.putAll(folders); - } for (long id : folders.keySet()) { ItemInfo info = itemsIdMap.get(id); FolderInfo folder = folders.get(id); if (info == null || folder == null) continue; if (info.container == LauncherSettings.Favorites.CONTAINER_DESKTOP && - info.screenId == currentScreen) { + info.screenId == currentScreenId) { currentScreenFolders.put(id, folder); } else { otherScreenFolders.put(id, folder); @@ -2220,8 +2404,11 @@ public class LauncherModel extends BroadcastReceiver { ArrayList<ComponentName> mHiddenApps = new ArrayList<ComponentName>(); ArrayList<String> mHiddenAppsPackages = new ArrayList<String>(); Context context = mApp.getContext(); - String[] flattened = SettingsProvider.getStringCustomDefault(context, - SettingsProvider.SETTINGS_UI_DRAWER_HIDDEN_APPS, "").split("\\|"); + // Since Trebuchet is compiled using the SDK we have to hardcode this string + String protectedComponents = Settings.Secure.getString(context.getContentResolver(), + SETTINGS_PROTECTED_COMPONENTS); + protectedComponents = protectedComponents == null ? "" : protectedComponents; + String[] flattened = protectedComponents.split("\\|"); boolean hideShortcuts = SettingsProvider.getBoolean(context, SettingsProvider.SETTINGS_UI_DRAWER_REMOVE_HIDDEN_APPS_SHORTCUTS, R.bool.preferences_interface_drawer_remove_hidden_apps_shortcuts_default); @@ -2251,20 +2438,30 @@ public class LauncherModel extends BroadcastReceiver { } } } else { + // Only remove items from folders that aren't hidden final FolderInfo folder = (FolderInfo)item; List<ShortcutInfo> shortcuts = folder.contents; + int NN = shortcuts.size() - 1; for (int j = NN; j >= 0; j--) { ShortcutInfo sci = shortcuts.get(j); if (sci.intent != null && sci.intent.getComponent() != null) { - if (mHiddenApps.contains(sci.intent.getComponent())) { - LauncherModel.deleteItemFromDatabase(mContext, sci); - folder.remove(sci); + if (!folder.hidden){ + if (mHiddenApps.contains(sci.intent.getComponent())) { + LauncherModel.deleteItemFromDatabase(mContext, sci); + folder.remove(sci); + } + } else { + if (!mHiddenApps.contains(sci.intent.getComponent())) { + LauncherModel.deleteItemFromDatabase(mContext, sci); + folder.remove(sci); + } } + } } - if (folder.contents.size() == 1 /*&& !(folder instanceof LiveFolderInfo)*/) { + if (folder.contents.size() == 1 && !folder.hidden) { ShortcutInfo finalItem = folder.contents.get(0); finalItem.container = folder.container; LauncherModel.deleteItemFromDatabase(mContext, folder); @@ -2382,13 +2579,7 @@ public class LauncherModel extends BroadcastReceiver { return; } - final boolean isLoadingSynchronously = (synchronizeBindPage > -1); - final int currentScreen = isLoadingSynchronously ? synchronizeBindPage : - oldCallbacks.getCurrentWorkspaceScreen(); - - // Load all the items that are on the current page first (and in the process, unbind - // all the existing workspace items before we call startBinding() below. - unbindWorkspaceItemsOnMainThread(); + // Save a copy of all the bg-thread collections ArrayList<ItemInfo> workspaceItems = new ArrayList<ItemInfo>(); ArrayList<LauncherAppWidgetInfo> appWidgets = new ArrayList<LauncherAppWidgetInfo>(); @@ -2403,6 +2594,23 @@ public class LauncherModel extends BroadcastReceiver { orderedScreenIds.addAll(sBgWorkspaceScreens); } + final boolean isLoadingSynchronously = + synchronizeBindPage != PagedView.INVALID_RESTORE_PAGE; + int currScreen = isLoadingSynchronously ? synchronizeBindPage : + oldCallbacks.getCurrentWorkspaceScreen(); + if (currScreen >= orderedScreenIds.size()) { + // There may be no workspace screens (just hotseat items and an empty page). + currScreen = PagedView.INVALID_RESTORE_PAGE; + } + final int currentScreen = currScreen; + final long currentScreenId = currentScreen < 0 + ? INVALID_SCREEN_ID : orderedScreenIds.get(currentScreen); + + // Load all the items that are on the current page first (and in the process, unbind + // all the existing workspace items before we call startBinding() below. + unbindWorkspaceItemsOnMainThread(); + + // Separate the items that are on the current screen, and all the other remaining items ArrayList<ItemInfo> currentWorkspaceItems = new ArrayList<ItemInfo>(); ArrayList<ItemInfo> otherWorkspaceItems = new ArrayList<ItemInfo>(); ArrayList<LauncherAppWidgetInfo> currentAppWidgets = @@ -2412,12 +2620,11 @@ public class LauncherModel extends BroadcastReceiver { HashMap<Long, FolderInfo> currentFolders = new HashMap<Long, FolderInfo>(); HashMap<Long, FolderInfo> otherFolders = new HashMap<Long, FolderInfo>(); - // Separate the items that are on the current screen, and all the other remaining items - filterCurrentWorkspaceItems(currentScreen, workspaceItems, currentWorkspaceItems, + filterCurrentWorkspaceItems(currentScreenId, workspaceItems, currentWorkspaceItems, otherWorkspaceItems); - filterCurrentAppWidgets(currentScreen, appWidgets, currentAppWidgets, + filterCurrentAppWidgets(currentScreenId, appWidgets, currentAppWidgets, otherAppWidgets); - filterCurrentFolders(currentScreen, itemsIdMap, folders, currentFolders, + filterCurrentFolders(currentScreenId, itemsIdMap, folders, currentFolders, otherFolders); sortWorkspaceItemsSpatially(currentWorkspaceItems); sortWorkspaceItemsSpatially(otherWorkspaceItems); @@ -2442,7 +2649,7 @@ public class LauncherModel extends BroadcastReceiver { r = new Runnable() { public void run() { Callbacks callbacks = tryGetCallbacks(oldCallbacks); - if (callbacks != null) { + if (callbacks != null && currentScreen != PagedView.INVALID_RESTORE_PAGE) { callbacks.onPageBoundSynchronously(currentScreen); } } @@ -2643,6 +2850,7 @@ public class LauncherModel extends BroadcastReceiver { case OP_ADD: for (int i=0; i<N; i++) { if (DEBUG_LOADERS) Log.d(TAG, "mAllAppsList.addPackage " + packages[i]); + mIconCache.remove(packages[i]); mBgAllAppsList.addPackage(context, packages[i]); } break; @@ -2690,14 +2898,14 @@ public class LauncherModel extends BroadcastReceiver { if (added != null) { // Ensure that we add all the workspace applications to the db - Callbacks cb = mCallbacks != null ? mCallbacks.get() : null; - if (!AppsCustomizePagedView.DISABLE_ALL_APPS) { - addAndBindAddedApps(context, new ArrayList<ItemInfo>(), cb, added); - } else { + if (LauncherAppState.isDisableAllApps()) { final ArrayList<ItemInfo> addedInfos = new ArrayList<ItemInfo>(added); - addAndBindAddedApps(context, addedInfos, cb, added); + addAndBindAddedWorkspaceApps(context, addedInfos); + } else { + addAppsToAllApps(context, added); } } + if (modified != null) { final ArrayList<AppInfo> modifiedFinal = modified; @@ -2723,43 +2931,47 @@ public class LauncherModel extends BroadcastReceiver { } }); } - // If a package has been removed, or an app has been removed as a result of - // an update (for example), make the removed callback. - if (mOp == OP_REMOVE || !removedApps.isEmpty()) { - final boolean packageRemoved = (mOp == OP_REMOVE); - final ArrayList<String> removedPackageNames = - new ArrayList<String>(Arrays.asList(packages)); - - // Update the launcher db to reflect the removal of apps - if (packageRemoved) { - for (String pn : removedPackageNames) { - ArrayList<ItemInfo> infos = getItemInfoForPackageName(pn); - for (ItemInfo i : infos) { - deleteItemFromDatabase(context, i); - } - } - // Remove any queued items from the install queue - String spKey = LauncherAppState.getSharedPreferencesKey(); - SharedPreferences sp = - context.getSharedPreferences(spKey, Context.MODE_PRIVATE); - InstallShortcutReceiver.removeFromInstallQueue(sp, removedPackageNames); - } else { - for (AppInfo a : removedApps) { - ArrayList<ItemInfo> infos = - getItemInfoForComponentName(a.componentName); - for (ItemInfo i : infos) { - deleteItemFromDatabase(context, i); - } + final ArrayList<String> removedPackageNames = + new ArrayList<String>(); + if (mOp == OP_REMOVE) { + // Mark all packages in the broadcast to be removed + removedPackageNames.addAll(Arrays.asList(packages)); + } else if (mOp == OP_UPDATE) { + // Mark disabled packages in the broadcast to be removed + final PackageManager pm = context.getPackageManager(); + for (int i=0; i<N; i++) { + if (isPackageDisabled(pm, packages[i])) { + removedPackageNames.add(packages[i]); } } - + } + // Remove all the components associated with this package + for (String pn : removedPackageNames) { + ArrayList<ItemInfo> infos = getItemInfoForPackageName(pn); + for (ItemInfo i : infos) { + deleteItemFromDatabase(context, i); + } + } + // Remove all the specific components + for (AppInfo a : removedApps) { + ArrayList<ItemInfo> infos = getItemInfoForComponentName(a.componentName); + for (ItemInfo i : infos) { + deleteItemFromDatabase(context, i); + } + } + if (!removedPackageNames.isEmpty() || !removedApps.isEmpty()) { + // Remove any queued items from the install queue + String spKey = LauncherAppState.getSharedPreferencesKey(); + SharedPreferences sp = + context.getSharedPreferences(spKey, Context.MODE_PRIVATE); + InstallShortcutReceiver.removeFromInstallQueue(sp, removedPackageNames); + // Call the components-removed callback mHandler.post(new Runnable() { public void run() { Callbacks cb = mCallbacks != null ? mCallbacks.get() : null; if (callbacks == cb && cb != null) { - callbacks.bindComponentsRemoved(removedPackageNames, - removedApps, packageRemoved); + callbacks.bindComponentsRemoved(removedPackageNames, removedApps); } } }); @@ -2801,19 +3013,27 @@ public class LauncherModel extends BroadcastReceiver { return widgetsAndShortcuts; } - private boolean isValidPackageComponent(PackageManager pm, ComponentName cn) { + private static boolean isPackageDisabled(PackageManager pm, String packageName) { + try { + PackageInfo pi = pm.getPackageInfo(packageName, 0); + return !pi.applicationInfo.enabled; + } catch (NameNotFoundException e) { + // Fall through + } + return false; + } + + public static boolean isValidPackageComponent(PackageManager pm, ComponentName cn) { if (cn == null) { return false; } + if (isPackageDisabled(pm, cn.getPackageName())) { + return false; + } try { - // Skip if the application is disabled - PackageInfo pi = pm.getPackageInfo(cn.getPackageName(), 0); - if (!pi.applicationInfo.enabled) { - return false; - } - // Check the activity + PackageInfo pi = pm.getPackageInfo(cn.getPackageName(), 0); return (pm.getActivityInfo(cn, 0) != null); } catch (NameNotFoundException e) { return false; @@ -2821,6 +3041,41 @@ public class LauncherModel extends BroadcastReceiver { } /** + * Make an ShortcutInfo object for a restored application or shortcut item that points + * to a package that is not yet installed on the system. + */ + public ShortcutInfo getRestoredItemInfo(Cursor cursor, int titleIndex, Intent intent) { + final ShortcutInfo info = new ShortcutInfo(); + if (cursor != null) { + info.title = cursor.getString(titleIndex); + } else { + info.title = ""; + } + info.setIcon(mIconCache.getIcon(intent, info.title.toString())); + info.itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT; + info.restoredIntent = intent; + return info; + } + + /** + * Make an Intent object for a restored application or shortcut item that points + * to the market page for the item. + */ + private Intent getRestoredItemIntent(Cursor c, Context context, Intent intent) { + final boolean debug = false; + ComponentName componentName = intent.getComponent(); + Intent marketIntent = new Intent(Intent.ACTION_VIEW); + Uri marketUri = new Uri.Builder() + .scheme("market") + .authority("details") + .appendQueryParameter("id", componentName.getPackageName()) + .build(); + if (debug) Log.d(TAG, "manufactured intent uri: " + marketUri.toString()); + marketIntent.setData(marketUri); + return marketIntent; + } + + /** * This is called from the code that adds shortcuts from the intent receiver. This * doesn't have a Cursor, but */ @@ -2983,6 +3238,10 @@ public class LauncherModel extends BroadcastReceiver { Intent.ACTION_MAIN.equals(intent.getAction()) && name != null) { return true; } + // placeholder shortcuts get special treatment, let them through too. + if (info.getRestoredIntent() != null) { + return true; + } } return false; } diff --git a/src/com/android/launcher3/LauncherPreferencesBackupHelper.java b/src/com/android/launcher3/LauncherPreferencesBackupHelper.java new file mode 100644 index 000000000..6f9c05c88 --- /dev/null +++ b/src/com/android/launcher3/LauncherPreferencesBackupHelper.java @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2014 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.android.launcher3; + +import android.app.backup.BackupDataInputStream; +import android.app.backup.SharedPreferencesBackupHelper; +import android.content.Context; +import android.util.Log; + +public class LauncherPreferencesBackupHelper extends SharedPreferencesBackupHelper { + + private static final String TAG = "LauncherPreferencesBackupHelper"; + private static final boolean VERBOSE = LauncherBackupAgentHelper.VERBOSE; + + private final boolean mRestoreEnabled; + + public LauncherPreferencesBackupHelper(Context context, String sharedPreferencesKey, + boolean restoreEnabled) { + super(context, sharedPreferencesKey); + mRestoreEnabled = restoreEnabled; + } + + @Override + public void restoreEntity(BackupDataInputStream data) { + if (mRestoreEnabled) { + if (VERBOSE) Log.v(TAG, "restoring preferences"); + super.restoreEntity(data); + } + } +} diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java index 359a40323..9a2cb5070 100644 --- a/src/com/android/launcher3/LauncherProvider.java +++ b/src/com/android/launcher3/LauncherProvider.java @@ -22,13 +22,17 @@ import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetProviderInfo; import android.content.ComponentName; import android.content.ContentProvider; +import android.content.ContentProviderOperation; +import android.content.ContentProviderResult; import android.content.ContentResolver; import android.content.ContentUris; import android.content.ContentValues; import android.content.Context; import android.content.Intent; +import android.content.OperationApplicationException; import android.content.SharedPreferences; import android.content.pm.ActivityInfo; +import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.res.Resources; import android.content.res.TypedArray; @@ -48,6 +52,7 @@ import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.AttributeSet; import android.util.Log; +import android.util.SparseArray; import android.util.Xml; import com.android.launcher3.LauncherSettings.Favorites; @@ -56,12 +61,12 @@ import com.android.launcher3.config.ProviderConfig; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; +import java.io.File; import java.io.IOException; import java.net.URISyntaxException; import java.util.ArrayList; -import java.util.HashMap; +import java.util.HashSet; import java.util.List; -import java.util.concurrent.atomic.AtomicBoolean; public class LauncherProvider extends ContentProvider { private static final String TAG = "Launcher.LauncherProvider"; @@ -69,11 +74,14 @@ public class LauncherProvider extends ContentProvider { private static final String DATABASE_NAME = "launcher.db"; - private static final int DATABASE_VERSION = 17; + private static final int DATABASE_VERSION = 20; static final String OLD_AUTHORITY = "com.android.launcher2.settings"; static final String AUTHORITY = ProviderConfig.AUTHORITY; + // Should we attempt to load anything from the com.android.launcher2 provider? + static final boolean IMPORT_LAUNCHER2_DATABASE = false; + static final String TABLE_FAVORITES = "favorites"; static final String TABLE_WORKSPACE_SCREENS = "workspaceScreens"; static final String PARAMETER_NOTIFY = "notify"; @@ -106,6 +114,10 @@ public class LauncherProvider extends ContentProvider { return true; } + public boolean wasNewDbCreated() { + return mOpenHelper.wasNewDbCreated(); + } + @Override public String getType(Uri uri) { SqlArguments args = new SqlArguments(uri, null, null); @@ -133,9 +145,13 @@ public class LauncherProvider extends ContentProvider { private static long dbInsertAndCheck(DatabaseHelper helper, SQLiteDatabase db, String table, String nullColumnHack, ContentValues values) { - if (!values.containsKey(LauncherSettings.Favorites._ID)) { + if (values == null) { + throw new RuntimeException("Error: attempting to insert null values"); + } + if (!values.containsKey(LauncherSettings.BaseLauncherColumns._ID)) { throw new RuntimeException("Error: attempting to add item without specifying an id"); } + helper.checkId(table, values); return db.insert(table, nullColumnHack, values); } @@ -184,6 +200,20 @@ public class LauncherProvider extends ContentProvider { } @Override + public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations) + throws OperationApplicationException { + SQLiteDatabase db = mOpenHelper.getWritableDatabase(); + db.beginTransaction(); + try { + ContentProviderResult[] result = super.applyBatch(operations); + db.setTransactionSuccessful(); + return result; + } finally { + db.endTransaction(); + } + } + + @Override public int delete(Uri uri, String selection, String[] selectionArgs) { SqlArguments args = new SqlArguments(uri, selection, selectionArgs); @@ -266,15 +296,22 @@ public class LauncherProvider extends ContentProvider { SharedPreferences sp = getContext().getSharedPreferences(spKey, Context.MODE_PRIVATE); if (sp.getBoolean(EMPTY_DATABASE_CREATED, false)) { + Log.d(TAG, "loading default workspace"); int workspaceResId = origWorkspaceResId; // Use default workspace resource if none provided if (workspaceResId == 0) { TelephonyManager tm = (TelephonyManager) getContext().getSystemService(Context.TELEPHONY_SERVICE); if (tm.getPhoneType() == TelephonyManager.PHONE_TYPE_NONE) { - workspaceResId = sp.getInt(DEFAULT_WORKSPACE_RESOURCE_ID, R.xml.default_workspace_no_telephony); + if (areGAppsInstalled()) { + workspaceResId = sp.getInt(DEFAULT_WORKSPACE_RESOURCE_ID, + R.xml.default_workspace_no_telephony_gapps); + } else { + workspaceResId = sp.getInt(DEFAULT_WORKSPACE_RESOURCE_ID, + R.xml.default_workspace_no_telephony); + } } else { - workspaceResId = sp.getInt(DEFAULT_WORKSPACE_RESOURCE_ID, R.xml.default_workspace); + workspaceResId = sp.getInt(DEFAULT_WORKSPACE_RESOURCE_ID, getDefaultWorkspaceResourceId()); } } @@ -291,10 +328,59 @@ public class LauncherProvider extends ContentProvider { } } + private boolean areGAppsInstalled() { + PackageManager pm = getContext().getPackageManager(); + try { + PackageInfo info = pm.getPackageInfo("com.google.android.gsf",PackageManager.GET_META_DATA); + } catch (PackageManager.NameNotFoundException e) { + return false; + } + return true; + } + + public void migrateLauncher2Shortcuts() { + mOpenHelper.migrateLauncher2Shortcuts(mOpenHelper.getWritableDatabase(), + LauncherSettings.Favorites.OLD_CONTENT_URI); + } + + private int getDefaultWorkspaceResourceId() { + if (LauncherAppState.isDisableAllApps()) { + if (areGAppsInstalled()){ + return R.xml.default_workspace_no_all_apps_gapps; + } else { + return R.xml.default_workspace_no_all_apps; + } + } else { + if (areGAppsInstalled()){ + return R.xml.default_workspace_gapps; + } else { + return R.xml.default_workspace; + } + } + } + private static interface ContentValuesCallback { public void onRow(ContentValues values); } + private static boolean shouldImportLauncher2Database(Context context) { + boolean isTablet = context.getResources().getBoolean(R.bool.is_tablet); + + // We don't import the old databse for tablets, as the grid size has changed. + return !isTablet && IMPORT_LAUNCHER2_DATABASE; + } + + public void deleteDatabase() { + // Are you sure? (y/n) + final SQLiteDatabase db = mOpenHelper.getWritableDatabase(); + final File dbFile = new File(db.getPath()); + mOpenHelper.close(); + if (dbFile.exists()) { + SQLiteDatabase.deleteDatabase(dbFile); + } + mOpenHelper = new DatabaseHelper(getContext()); + } + private static class DatabaseHelper extends SQLiteOpenHelper { private static final String TAG_FAVORITES = "favorites"; private static final String TAG_FAVORITE = "favorite"; @@ -311,6 +397,8 @@ public class LauncherProvider extends ContentProvider { private long mMaxItemId = -1; private long mMaxScreenId = -1; + private boolean mNewDbCreated = false; + DatabaseHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); mContext = context; @@ -326,6 +414,10 @@ public class LauncherProvider extends ContentProvider { } } + public boolean wasNewDbCreated() { + return mNewDbCreated; + } + /** * Send notification that we've deleted the {@link AppWidgetHost}, * probably as part of the initial database creation. The receiver may @@ -343,6 +435,7 @@ public class LauncherProvider extends ContentProvider { mMaxItemId = 1; mMaxScreenId = 0; + mNewDbCreated = true; db.execSQL("CREATE TABLE favorites (" + "_id INTEGER PRIMARY KEY," + @@ -364,7 +457,9 @@ public class LauncherProvider extends ContentProvider { "uri TEXT," + "displayMode INTEGER," + "appWidgetProvider TEXT," + - "modified INTEGER NOT NULL DEFAULT 0" + + "modified INTEGER NOT NULL DEFAULT 0," + + "restored INTEGER NOT NULL DEFAULT 0," + + "hidden INTEGER DEFAULT 0" + ");"); addWorkspacesTable(db); @@ -374,32 +469,38 @@ public class LauncherProvider extends ContentProvider { sendAppWidgetResetNotify(); } - // Try converting the old database - ContentValuesCallback permuteScreensCb = new ContentValuesCallback() { - public void onRow(ContentValues values) { - int container = values.getAsInteger(LauncherSettings.Favorites.CONTAINER); - if (container == Favorites.CONTAINER_DESKTOP) { - int screen = values.getAsInteger(LauncherSettings.Favorites.SCREEN); - screen = (int) upgradeLauncherDb_permuteScreens(screen); - values.put(LauncherSettings.Favorites.SCREEN, screen); + if (shouldImportLauncher2Database(mContext)) { + // Try converting the old database + ContentValuesCallback permuteScreensCb = new ContentValuesCallback() { + public void onRow(ContentValues values) { + int container = values.getAsInteger(LauncherSettings.Favorites.CONTAINER); + if (container == Favorites.CONTAINER_DESKTOP) { + int screen = values.getAsInteger(LauncherSettings.Favorites.SCREEN); + screen = (int) upgradeLauncherDb_permuteScreens(screen); + values.put(LauncherSettings.Favorites.SCREEN, screen); + } + } + }; + Uri uri = Uri.parse("content://" + Settings.AUTHORITY + + "/old_favorites?notify=true"); + if (!convertDatabase(db, uri, permuteScreensCb, true)) { + // Try and upgrade from the Launcher2 db + uri = LauncherSettings.Favorites.OLD_CONTENT_URI; + if (!convertDatabase(db, uri, permuteScreensCb, false)) { + // If we fail, then set a flag to load the default workspace + setFlagEmptyDbCreated(); + return; } } - }; - Uri uri = Uri.parse("content://" + Settings.AUTHORITY + - "/old_favorites?notify=true"); - if (!convertDatabase(db, uri, permuteScreensCb, true)) { - // Try and upgrade from the Launcher2 db - uri = LauncherSettings.Favorites.OLD_CONTENT_URI; - if (!convertDatabase(db, uri, permuteScreensCb, false)) { - // If we fail, then set a flag to load the default workspace - setFlagEmptyDbCreated(); - return; - } + // Right now, in non-default workspace cases, we want to run the final + // upgrade code (ie. to fix workspace screen indices -> ids, etc.), so + // set that flag too. + setFlagJustLoadedOldDb(); + } else { + // Fresh and clean launcher DB. + mMaxItemId = initializeMaxItemId(db); + setFlagEmptyDbCreated(); } - // Right now, in non-default workspace cases, we want to run the final - // upgrade code (ie. to fix workspace screen indices -> ids, etc.), so - // set that flag too. - setFlagJustLoadedOldDb(); } private void addWorkspacesTable(SQLiteDatabase db) { @@ -670,7 +771,6 @@ public class LauncherProvider extends ContentProvider { } } - if (version < 15) { db.beginTransaction(); try { @@ -747,7 +847,6 @@ public class LauncherProvider extends ContentProvider { } } - // Artificially inflate the version to make sure we're fully up to date // after a possible 10.2-Trebuchet migration @@ -755,6 +854,37 @@ public class LauncherProvider extends ContentProvider { version = 17; } + if (version < 18) { + db.beginTransaction(); + try { + // Insert new column for holding restore status + db.execSQL("ALTER TABLE favorites " + + "ADD COLUMN restored INTEGER NOT NULL DEFAULT 0;"); + db.setTransactionSuccessful(); + version = 18; + } catch (SQLException ex) { + // Old version remains, which means we wipe old data + Log.e(TAG, ex.getMessage(), ex); + } finally { + db.endTransaction(); + } + } + + if (version < 19) { + // We use the db version upgrade here to identify users who may not have seen + // clings yet (because they weren't available), but for whom the clings are now + // available (tablet users). Because one of the possible cling flows (migration) + // is very destructive (wipes out workspaces), we want to prevent this from showing + // until clear data. We do so by marking that the clings have been shown. + LauncherClings.synchonouslyMarkFirstRunClingDismissed(mContext); + version = 19; + } + + if (oldVersion < 20) { + db.execSQL("ALTER TABLE favorites ADD hidden INTEGER DEFAULT 0"); + version = 20; + } + if (version != DATABASE_VERSION) { Log.w(TAG, "Destroying all old data."); db.execSQL("DROP TABLE IF EXISTS " + TABLE_FAVORITES); @@ -917,6 +1047,15 @@ public class LauncherProvider extends ContentProvider { mMaxItemId = id + 1; } + public void checkId(String table, ContentValues values) { + long id = values.getAsLong(LauncherSettings.BaseLauncherColumns._ID); + if (table == LauncherProvider.TABLE_WORKSPACE_SCREENS) { + mMaxScreenId = Math.max(id, mMaxScreenId); + } else { + mMaxItemId = Math.max(id, mMaxItemId); + } + } + private long initializeMaxItemId(SQLiteDatabase db) { Cursor c = db.rawQuery("SELECT MAX(_id) FROM favorites", null); @@ -947,10 +1086,14 @@ public class LauncherProvider extends ContentProvider { throw new RuntimeException("Error: max screen id was not initialized"); } mMaxScreenId += 1; + // Log to disk + Launcher.addDumpLog(TAG, "11683562 - generateNewScreenId(): " + mMaxScreenId, true); return mMaxScreenId; } public void updateMaxScreenId(long maxScreenId) { + // Log to disk + Launcher.addDumpLog(TAG, "11683562 - updateMaxScreenId(): " + maxScreenId, true); mMaxScreenId = maxScreenId; } @@ -971,6 +1114,8 @@ public class LauncherProvider extends ContentProvider { throw new RuntimeException("Error: could not query max screen id"); } + // Log to disk + Launcher.addDumpLog(TAG, "11683562 - initializeMaxScreenId(): " + id, true); return id; } @@ -1102,10 +1247,6 @@ public class LauncherProvider extends ContentProvider { final int depth = parser.getDepth(); - final HashMap<Long, ItemInfo[][]> occupied = new HashMap<Long, ItemInfo[][]>(); - LauncherModel model = LauncherAppState.getInstance().getModel(); - AtomicBoolean deleteItem = new AtomicBoolean(); - int type; while (((type = parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) { @@ -1129,7 +1270,6 @@ public class LauncherProvider extends ContentProvider { // recursively load some more favorites, why not? i += loadFavorites(db, resId); added = false; - mMaxItemId = -1; } else { Log.w(TAG, String.format("Skipping <include workspace=0x%08x>", resId)); } @@ -1158,18 +1298,6 @@ public class LauncherProvider extends ContentProvider { values.put(LauncherSettings.Favorites.CELLX, x); values.put(LauncherSettings.Favorites.CELLY, y); - ItemInfo info = new ItemInfo(); - info.container = container; - info.spanX = a.getInt(R.styleable.Favorite_spanX, 1); - info.spanY = a.getInt(R.styleable.Favorite_spanY, 1); - info.cellX = a.getInt(R.styleable.Favorite_x, 0); - info.cellY = a.getInt(R.styleable.Favorite_y, 0); - info.screenId = a.getInt(R.styleable.Favorite_screen, 0); - - if (!model.checkItemPlacement(occupied, info, deleteItem)) { - continue; - } - if (LOGD) { final String title = a.getString(R.styleable.Favorite_title); final String pkg = a.getString(R.styleable.Favorite_packageName); @@ -1256,22 +1384,7 @@ public class LauncherProvider extends ContentProvider { added = false; } } - if (added) { - i++; - } else { - long containerIndex = info.screenId; - if (info.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) { - occupied.get((long) LauncherSettings.Favorites.CONTAINER_HOTSEAT) - [(int) info.screenId][0] = null; - } else { - ItemInfo[][] screens = occupied.get(info.screenId); - for (int gridX = info.cellX; gridX < (info.cellX+info.spanX); gridX++) { - for (int gridY = info.cellY; gridY < (info.cellY+info.spanY); gridY++) { - screens[gridX][gridY] = null; - } - } - } - } + if (added) i++; a.recycle(); } } catch (XmlPullParserException e) { @@ -1511,6 +1624,273 @@ public class LauncherProvider extends ContentProvider { } return id; } + + public void migrateLauncher2Shortcuts(SQLiteDatabase db, Uri uri) { + final ContentResolver resolver = mContext.getContentResolver(); + Cursor c = null; + int count = 0; + int curScreen = 0; + + try { + c = resolver.query(uri, null, null, null, "title ASC"); + } catch (Exception e) { + // Ignore + } + + // We already have a favorites database in the old provider + if (c != null) { + try { + if (c.getCount() > 0) { + final int idIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites._ID); + final int intentIndex + = c.getColumnIndexOrThrow(LauncherSettings.Favorites.INTENT); + final int titleIndex + = c.getColumnIndexOrThrow(LauncherSettings.Favorites.TITLE); + final int iconTypeIndex + = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON_TYPE); + final int iconIndex + = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON); + final int iconPackageIndex + = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON_PACKAGE); + final int iconResourceIndex + = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON_RESOURCE); + final int containerIndex + = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CONTAINER); + final int itemTypeIndex + = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ITEM_TYPE); + final int screenIndex + = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SCREEN); + final int cellXIndex + = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLX); + final int cellYIndex + = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLY); + final int uriIndex + = c.getColumnIndexOrThrow(LauncherSettings.Favorites.URI); + final int displayModeIndex + = c.getColumnIndexOrThrow(LauncherSettings.Favorites.DISPLAY_MODE); + + int i = 0; + int curX = 0; + int curY = 0; + + final LauncherAppState app = LauncherAppState.getInstance(); + final DeviceProfile grid = app.getDynamicGrid().getDeviceProfile(); + final int width = (int) grid.numColumns; + final int height = (int) grid.numRows; + final int hotseatWidth = (int) grid.numHotseatIcons; + PackageManager pm = mContext.getPackageManager(); + + final HashSet<String> seenIntents = new HashSet<String>(c.getCount()); + + final ArrayList<ContentValues> shortcuts = new ArrayList<ContentValues>(); + final ArrayList<ContentValues> folders = new ArrayList<ContentValues>(); + final SparseArray<ContentValues> hotseat = new SparseArray<ContentValues>(); + + while (c.moveToNext()) { + final int itemType = c.getInt(itemTypeIndex); + if (itemType != Favorites.ITEM_TYPE_APPLICATION + && itemType != Favorites.ITEM_TYPE_SHORTCUT + && itemType != Favorites.ITEM_TYPE_FOLDER) { + continue; + } + + final int cellX = c.getInt(cellXIndex); + final int cellY = c.getInt(cellYIndex); + final int screen = c.getInt(screenIndex); + int container = c.getInt(containerIndex); + final String intentStr = c.getString(intentIndex); + Launcher.addDumpLog(TAG, "migrating \"" + + c.getString(titleIndex) + "\" (" + + cellX + "," + cellY + "@" + + LauncherSettings.Favorites.containerToString(container) + + "/" + screen + + "): " + intentStr, true); + + if (itemType != Favorites.ITEM_TYPE_FOLDER) { + + final Intent intent; + final ComponentName cn; + try { + intent = Intent.parseUri(intentStr, 0); + } catch (URISyntaxException e) { + // bogus intent? + Launcher.addDumpLog(TAG, + "skipping invalid intent uri", true); + continue; + } + + cn = intent.getComponent(); + if (TextUtils.isEmpty(intentStr)) { + // no intent? no icon + Launcher.addDumpLog(TAG, "skipping empty intent", true); + continue; + } else if (cn != null && + !LauncherModel.isValidPackageComponent(pm, cn)) { + // component no longer exists. + Launcher.addDumpLog(TAG, "skipping item whose component " + + "no longer exists.", true); + continue; + } else if (container == + LauncherSettings.Favorites.CONTAINER_DESKTOP) { + // Dedupe icons directly on the workspace + + // Canonicalize + // the Play Store sets the package parameter, but Launcher + // does not, so we clear that out to keep them the same + intent.setPackage(null); + final String key = intent.toUri(0); + if (seenIntents.contains(key)) { + Launcher.addDumpLog(TAG, "skipping duplicate", true); + continue; + } else { + seenIntents.add(key); + } + } + } + + ContentValues values = new ContentValues(c.getColumnCount()); + values.put(LauncherSettings.Favorites._ID, c.getInt(idIndex)); + values.put(LauncherSettings.Favorites.INTENT, intentStr); + values.put(LauncherSettings.Favorites.TITLE, c.getString(titleIndex)); + values.put(LauncherSettings.Favorites.ICON_TYPE, + c.getInt(iconTypeIndex)); + values.put(LauncherSettings.Favorites.ICON, c.getBlob(iconIndex)); + values.put(LauncherSettings.Favorites.ICON_PACKAGE, + c.getString(iconPackageIndex)); + values.put(LauncherSettings.Favorites.ICON_RESOURCE, + c.getString(iconResourceIndex)); + values.put(LauncherSettings.Favorites.ITEM_TYPE, itemType); + values.put(LauncherSettings.Favorites.APPWIDGET_ID, -1); + values.put(LauncherSettings.Favorites.URI, c.getString(uriIndex)); + values.put(LauncherSettings.Favorites.DISPLAY_MODE, + c.getInt(displayModeIndex)); + + if (container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) { + hotseat.put(screen, values); + } + + if (container != LauncherSettings.Favorites.CONTAINER_DESKTOP) { + // In a folder or in the hotseat, preserve position + values.put(LauncherSettings.Favorites.SCREEN, screen); + values.put(LauncherSettings.Favorites.CELLX, cellX); + values.put(LauncherSettings.Favorites.CELLY, cellY); + } else { + // For items contained directly on one of the workspace screen, + // we'll determine their location (screen, x, y) in a second pass. + } + + values.put(LauncherSettings.Favorites.CONTAINER, container); + + if (itemType != Favorites.ITEM_TYPE_FOLDER) { + shortcuts.add(values); + } else { + folders.add(values); + } + } + + // Now that we have all the hotseat icons, let's go through them left-right + // and assign valid locations for them in the new hotseat + final int N = hotseat.size(); + for (int idx=0; idx<N; idx++) { + int hotseatX = hotseat.keyAt(idx); + ContentValues values = hotseat.valueAt(idx); + + if (hotseatX == grid.hotseatAllAppsRank) { + // let's drop this in the next available hole in the hotseat + while (++hotseatX < hotseatWidth) { + if (hotseat.get(hotseatX) == null) { + // found a spot! move it here + values.put(LauncherSettings.Favorites.SCREEN, + hotseatX); + break; + } + } + } + if (hotseatX >= hotseatWidth) { + // no room for you in the hotseat? it's off to the desktop with you + values.put(LauncherSettings.Favorites.CONTAINER, + Favorites.CONTAINER_DESKTOP); + } + } + + final ArrayList<ContentValues> allItems = new ArrayList<ContentValues>(); + // Folders first + allItems.addAll(folders); + // Then shortcuts + allItems.addAll(shortcuts); + + // Layout all the folders + for (ContentValues values: allItems) { + if (values.getAsInteger(LauncherSettings.Favorites.CONTAINER) != + LauncherSettings.Favorites.CONTAINER_DESKTOP) { + // Hotseat items and folder items have already had their + // location information set. Nothing to be done here. + continue; + } + values.put(LauncherSettings.Favorites.SCREEN, curScreen); + values.put(LauncherSettings.Favorites.CELLX, curX); + values.put(LauncherSettings.Favorites.CELLY, curY); + curX = (curX + 1) % width; + if (curX == 0) { + curY = (curY + 1); + } + // Leave the last row of icons blank on every screen + if (curY == height - 1) { + curScreen = (int) generateNewScreenId(); + curY = 0; + } + } + + if (allItems.size() > 0) { + db.beginTransaction(); + try { + for (ContentValues row: allItems) { + if (row == null) continue; + if (dbInsertAndCheck(this, db, TABLE_FAVORITES, null, row) + < 0) { + return; + } else { + count++; + } + } + db.setTransactionSuccessful(); + } finally { + db.endTransaction(); + } + } + + db.beginTransaction(); + try { + for (i=0; i<=curScreen; i++) { + final ContentValues values = new ContentValues(); + values.put(LauncherSettings.WorkspaceScreens._ID, i); + values.put(LauncherSettings.WorkspaceScreens.SCREEN_RANK, i); + if (dbInsertAndCheck(this, db, TABLE_WORKSPACE_SCREENS, null, values) + < 0) { + return; + } + } + db.setTransactionSuccessful(); + } finally { + db.endTransaction(); + } + } + } finally { + c.close(); + } + } + + Launcher.addDumpLog(TAG, "migrated " + count + " icons from Launcher2 into " + + (curScreen+1) + " screens", true); + + // ensure that new screens are created to hold these icons + setFlagJustLoadedOldDb(); + + // Update max IDs; very important since we just grabbed IDs from another database + mMaxItemId = initializeMaxItemId(db); + mMaxScreenId = initializeMaxScreenId(db); + if (LOGD) Log.d(TAG, "mMaxItemId: " + mMaxItemId + " mMaxScreenId: " + mMaxScreenId); + } } /** diff --git a/src/com/android/launcher3/LauncherScroller.java b/src/com/android/launcher3/LauncherScroller.java new file mode 100644 index 000000000..3bd0a78c4 --- /dev/null +++ b/src/com/android/launcher3/LauncherScroller.java @@ -0,0 +1,559 @@ +/* + * Copyright (C) 2006 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.android.launcher3; + +import android.animation.TimeInterpolator; +import android.content.Context; +import android.hardware.SensorManager; +import android.os.Build; +import android.util.FloatMath; +import android.view.ViewConfiguration; +import android.view.animation.AnimationUtils; +import android.view.animation.Interpolator; + +/** + * This class differs from the framework {@link android.widget.Scroller} in that + * you can modify the Interpolator post-construction. + */ +public class LauncherScroller { + private int mMode; + + private int mStartX; + private int mStartY; + private int mFinalX; + private int mFinalY; + + private int mMinX; + private int mMaxX; + private int mMinY; + private int mMaxY; + + private int mCurrX; + private int mCurrY; + private long mStartTime; + private int mDuration; + private float mDurationReciprocal; + private float mDeltaX; + private float mDeltaY; + private boolean mFinished; + private TimeInterpolator mInterpolator; + private boolean mFlywheel; + + private float mVelocity; + private float mCurrVelocity; + private int mDistance; + + private float mFlingFriction = ViewConfiguration.getScrollFriction(); + + private static final int DEFAULT_DURATION = 250; + private static final int SCROLL_MODE = 0; + private static final int FLING_MODE = 1; + + private static float DECELERATION_RATE = (float) (Math.log(0.78) / Math.log(0.9)); + private static final float INFLEXION = 0.35f; // Tension lines cross at (INFLEXION, 1) + private static final float START_TENSION = 0.5f; + private static final float END_TENSION = 1.0f; + private static final float P1 = START_TENSION * INFLEXION; + private static final float P2 = 1.0f - END_TENSION * (1.0f - INFLEXION); + + private static final int NB_SAMPLES = 100; + private static final float[] SPLINE_POSITION = new float[NB_SAMPLES + 1]; + private static final float[] SPLINE_TIME = new float[NB_SAMPLES + 1]; + + private float mDeceleration; + private final float mPpi; + + // A context-specific coefficient adjusted to physical values. + private float mPhysicalCoeff; + + static { + float x_min = 0.0f; + float y_min = 0.0f; + for (int i = 0; i < NB_SAMPLES; i++) { + final float alpha = (float) i / NB_SAMPLES; + + float x_max = 1.0f; + float x, tx, coef; + while (true) { + x = x_min + (x_max - x_min) / 2.0f; + coef = 3.0f * x * (1.0f - x); + tx = coef * ((1.0f - x) * P1 + x * P2) + x * x * x; + if (Math.abs(tx - alpha) < 1E-5) break; + if (tx > alpha) x_max = x; + else x_min = x; + } + SPLINE_POSITION[i] = coef * ((1.0f - x) * START_TENSION + x) + x * x * x; + + float y_max = 1.0f; + float y, dy; + while (true) { + y = y_min + (y_max - y_min) / 2.0f; + coef = 3.0f * y * (1.0f - y); + dy = coef * ((1.0f - y) * START_TENSION + y) + y * y * y; + if (Math.abs(dy - alpha) < 1E-5) break; + if (dy > alpha) y_max = y; + else y_min = y; + } + SPLINE_TIME[i] = coef * ((1.0f - y) * P1 + y * P2) + y * y * y; + } + SPLINE_POSITION[NB_SAMPLES] = SPLINE_TIME[NB_SAMPLES] = 1.0f; + + // This controls the viscous fluid effect (how much of it) + sViscousFluidScale = 8.0f; + // must be set to 1.0 (used in viscousFluid()) + sViscousFluidNormalize = 1.0f; + sViscousFluidNormalize = 1.0f / viscousFluid(1.0f); + + } + + private static float sViscousFluidScale; + private static float sViscousFluidNormalize; + + public void setInterpolator(TimeInterpolator interpolator) { + mInterpolator = interpolator; + } + + /** + * Create a Scroller with the default duration and interpolator. + */ + public LauncherScroller(Context context) { + this(context, null); + } + + /** + * Create a Scroller with the specified interpolator. If the interpolator is + * null, the default (viscous) interpolator will be used. "Flywheel" behavior will + * be in effect for apps targeting Honeycomb or newer. + */ + public LauncherScroller(Context context, Interpolator interpolator) { + this(context, interpolator, + context.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.HONEYCOMB); + } + + /** + * Create a Scroller with the specified interpolator. If the interpolator is + * null, the default (viscous) interpolator will be used. Specify whether or + * not to support progressive "flywheel" behavior in flinging. + */ + public LauncherScroller(Context context, Interpolator interpolator, boolean flywheel) { + mFinished = true; + mInterpolator = interpolator; + mPpi = context.getResources().getDisplayMetrics().density * 160.0f; + mDeceleration = computeDeceleration(ViewConfiguration.getScrollFriction()); + mFlywheel = flywheel; + + mPhysicalCoeff = computeDeceleration(0.84f); // look and feel tuning + } + + /** + * The amount of friction applied to flings. The default value + * is {@link ViewConfiguration#getScrollFriction}. + * + * @param friction A scalar dimension-less value representing the coefficient of + * friction. + */ + public final void setFriction(float friction) { + mDeceleration = computeDeceleration(friction); + mFlingFriction = friction; + } + + private float computeDeceleration(float friction) { + return SensorManager.GRAVITY_EARTH // g (m/s^2) + * 39.37f // inch/meter + * mPpi // pixels per inch + * friction; + } + + /** + * + * Returns whether the scroller has finished scrolling. + * + * @return True if the scroller has finished scrolling, false otherwise. + */ + public final boolean isFinished() { + return mFinished; + } + + /** + * Force the finished field to a particular value. + * + * @param finished The new finished value. + */ + public final void forceFinished(boolean finished) { + mFinished = finished; + } + + /** + * Returns how long the scroll event will take, in milliseconds. + * + * @return The duration of the scroll in milliseconds. + */ + public final int getDuration() { + return mDuration; + } + + /** + * Returns the current X offset in the scroll. + * + * @return The new X offset as an absolute distance from the origin. + */ + public final int getCurrX() { + return mCurrX; + } + + /** + * Returns the current Y offset in the scroll. + * + * @return The new Y offset as an absolute distance from the origin. + */ + public final int getCurrY() { + return mCurrY; + } + + /** + * Returns the current velocity. + * + * @return The original velocity less the deceleration. Result may be + * negative. + */ + public float getCurrVelocity() { + return mMode == FLING_MODE ? + mCurrVelocity : mVelocity - mDeceleration * timePassed() / 2000.0f; + } + + /** + * Returns the start X offset in the scroll. + * + * @return The start X offset as an absolute distance from the origin. + */ + public final int getStartX() { + return mStartX; + } + + /** + * Returns the start Y offset in the scroll. + * + * @return The start Y offset as an absolute distance from the origin. + */ + public final int getStartY() { + return mStartY; + } + + /** + * Returns where the scroll will end. Valid only for "fling" scrolls. + * + * @return The final X offset as an absolute distance from the origin. + */ + public final int getFinalX() { + return mFinalX; + } + + /** + * Returns where the scroll will end. Valid only for "fling" scrolls. + * + * @return The final Y offset as an absolute distance from the origin. + */ + public final int getFinalY() { + return mFinalY; + } + + /** + * Call this when you want to know the new location. If it returns true, + * the animation is not yet finished. + */ + public boolean computeScrollOffset() { + if (mFinished) { + return false; + } + + int timePassed = (int)(AnimationUtils.currentAnimationTimeMillis() - mStartTime); + + if (timePassed < mDuration) { + switch (mMode) { + case SCROLL_MODE: + float x = timePassed * mDurationReciprocal; + + if (mInterpolator == null) + x = viscousFluid(x); + else + x = mInterpolator.getInterpolation(x); + + mCurrX = mStartX + Math.round(x * mDeltaX); + mCurrY = mStartY + Math.round(x * mDeltaY); + break; + case FLING_MODE: + final float t = (float) timePassed / mDuration; + final int index = (int) (NB_SAMPLES * t); + float distanceCoef = 1.f; + float velocityCoef = 0.f; + if (index < NB_SAMPLES) { + final float t_inf = (float) index / NB_SAMPLES; + final float t_sup = (float) (index + 1) / NB_SAMPLES; + final float d_inf = SPLINE_POSITION[index]; + final float d_sup = SPLINE_POSITION[index + 1]; + velocityCoef = (d_sup - d_inf) / (t_sup - t_inf); + distanceCoef = d_inf + (t - t_inf) * velocityCoef; + } + + mCurrVelocity = velocityCoef * mDistance / mDuration * 1000.0f; + + mCurrX = mStartX + Math.round(distanceCoef * (mFinalX - mStartX)); + // Pin to mMinX <= mCurrX <= mMaxX + mCurrX = Math.min(mCurrX, mMaxX); + mCurrX = Math.max(mCurrX, mMinX); + + mCurrY = mStartY + Math.round(distanceCoef * (mFinalY - mStartY)); + // Pin to mMinY <= mCurrY <= mMaxY + mCurrY = Math.min(mCurrY, mMaxY); + mCurrY = Math.max(mCurrY, mMinY); + + if (mCurrX == mFinalX && mCurrY == mFinalY) { + mFinished = true; + } + + break; + } + } + else { + mCurrX = mFinalX; + mCurrY = mFinalY; + mFinished = true; + } + return true; + } + + /** + * Start scrolling by providing a starting point and the distance to travel. + * The scroll will use the default value of 250 milliseconds for the + * duration. + * + * @param startX Starting horizontal scroll offset in pixels. Positive + * numbers will scroll the content to the left. + * @param startY Starting vertical scroll offset in pixels. Positive numbers + * will scroll the content up. + * @param dx Horizontal distance to travel. Positive numbers will scroll the + * content to the left. + * @param dy Vertical distance to travel. Positive numbers will scroll the + * content up. + */ + public void startScroll(int startX, int startY, int dx, int dy) { + startScroll(startX, startY, dx, dy, DEFAULT_DURATION); + } + + /** + * Start scrolling by providing a starting point, the distance to travel, + * and the duration of the scroll. + * + * @param startX Starting horizontal scroll offset in pixels. Positive + * numbers will scroll the content to the left. + * @param startY Starting vertical scroll offset in pixels. Positive numbers + * will scroll the content up. + * @param dx Horizontal distance to travel. Positive numbers will scroll the + * content to the left. + * @param dy Vertical distance to travel. Positive numbers will scroll the + * content up. + * @param duration Duration of the scroll in milliseconds. + */ + public void startScroll(int startX, int startY, int dx, int dy, int duration) { + mMode = SCROLL_MODE; + mFinished = false; + mDuration = duration; + mStartTime = AnimationUtils.currentAnimationTimeMillis(); + mStartX = startX; + mStartY = startY; + mFinalX = startX + dx; + mFinalY = startY + dy; + mDeltaX = dx; + mDeltaY = dy; + mDurationReciprocal = 1.0f / (float) mDuration; + } + + /** + * Start scrolling based on a fling gesture. The distance travelled will + * depend on the initial velocity of the fling. + * + * @param startX Starting point of the scroll (X) + * @param startY Starting point of the scroll (Y) + * @param velocityX Initial velocity of the fling (X) measured in pixels per + * second. + * @param velocityY Initial velocity of the fling (Y) measured in pixels per + * second + * @param minX Minimum X value. The scroller will not scroll past this + * point. + * @param maxX Maximum X value. The scroller will not scroll past this + * point. + * @param minY Minimum Y value. The scroller will not scroll past this + * point. + * @param maxY Maximum Y value. The scroller will not scroll past this + * point. + */ + public void fling(int startX, int startY, int velocityX, int velocityY, + int minX, int maxX, int minY, int maxY) { + // Continue a scroll or fling in progress + if (mFlywheel && !mFinished) { + float oldVel = getCurrVelocity(); + + float dx = (float) (mFinalX - mStartX); + float dy = (float) (mFinalY - mStartY); + float hyp = FloatMath.sqrt(dx * dx + dy * dy); + + float ndx = dx / hyp; + float ndy = dy / hyp; + + float oldVelocityX = ndx * oldVel; + float oldVelocityY = ndy * oldVel; + if (Math.signum(velocityX) == Math.signum(oldVelocityX) && + Math.signum(velocityY) == Math.signum(oldVelocityY)) { + velocityX += oldVelocityX; + velocityY += oldVelocityY; + } + } + + mMode = FLING_MODE; + mFinished = false; + + float velocity = FloatMath.sqrt(velocityX * velocityX + velocityY * velocityY); + + mVelocity = velocity; + mDuration = getSplineFlingDuration(velocity); + mStartTime = AnimationUtils.currentAnimationTimeMillis(); + mStartX = startX; + mStartY = startY; + + float coeffX = velocity == 0 ? 1.0f : velocityX / velocity; + float coeffY = velocity == 0 ? 1.0f : velocityY / velocity; + + double totalDistance = getSplineFlingDistance(velocity); + mDistance = (int) (totalDistance * Math.signum(velocity)); + + mMinX = minX; + mMaxX = maxX; + mMinY = minY; + mMaxY = maxY; + + mFinalX = startX + (int) Math.round(totalDistance * coeffX); + // Pin to mMinX <= mFinalX <= mMaxX + mFinalX = Math.min(mFinalX, mMaxX); + mFinalX = Math.max(mFinalX, mMinX); + + mFinalY = startY + (int) Math.round(totalDistance * coeffY); + // Pin to mMinY <= mFinalY <= mMaxY + mFinalY = Math.min(mFinalY, mMaxY); + mFinalY = Math.max(mFinalY, mMinY); + } + + private double getSplineDeceleration(float velocity) { + return Math.log(INFLEXION * Math.abs(velocity) / (mFlingFriction * mPhysicalCoeff)); + } + + private int getSplineFlingDuration(float velocity) { + final double l = getSplineDeceleration(velocity); + final double decelMinusOne = DECELERATION_RATE - 1.0; + return (int) (1000.0 * Math.exp(l / decelMinusOne)); + } + + private double getSplineFlingDistance(float velocity) { + final double l = getSplineDeceleration(velocity); + final double decelMinusOne = DECELERATION_RATE - 1.0; + return mFlingFriction * mPhysicalCoeff * Math.exp(DECELERATION_RATE / decelMinusOne * l); + } + + static float viscousFluid(float x) + { + x *= sViscousFluidScale; + if (x < 1.0f) { + x -= (1.0f - (float)Math.exp(-x)); + } else { + float start = 0.36787944117f; // 1/e == exp(-1) + x = 1.0f - (float)Math.exp(1.0f - x); + x = start + x * (1.0f - start); + } + x *= sViscousFluidNormalize; + return x; + } + + /** + * Stops the animation. Contrary to {@link #forceFinished(boolean)}, + * aborting the animating cause the scroller to move to the final x and y + * position + * + * @see #forceFinished(boolean) + */ + public void abortAnimation() { + mCurrX = mFinalX; + mCurrY = mFinalY; + mFinished = true; + } + + /** + * Extend the scroll animation. This allows a running animation to scroll + * further and longer, when used with {@link #setFinalX(int)} or {@link #setFinalY(int)}. + * + * @param extend Additional time to scroll in milliseconds. + * @see #setFinalX(int) + * @see #setFinalY(int) + */ + public void extendDuration(int extend) { + int passed = timePassed(); + mDuration = passed + extend; + mDurationReciprocal = 1.0f / mDuration; + mFinished = false; + } + + /** + * Returns the time elapsed since the beginning of the scrolling. + * + * @return The elapsed time in milliseconds. + */ + public int timePassed() { + return (int)(AnimationUtils.currentAnimationTimeMillis() - mStartTime); + } + + /** + * Sets the final position (X) for this scroller. + * + * @param newX The new X offset as an absolute distance from the origin. + * @see #extendDuration(int) + * @see #setFinalY(int) + */ + public void setFinalX(int newX) { + mFinalX = newX; + mDeltaX = mFinalX - mStartX; + mFinished = false; + } + + /** + * Sets the final position (Y) for this scroller. + * + * @param newY The new Y offset as an absolute distance from the origin. + * @see #extendDuration(int) + * @see #setFinalX(int) + */ + public void setFinalY(int newY) { + mFinalY = newY; + mDeltaY = mFinalY - mStartY; + mFinished = false; + } + + /** + * @hide + */ + public boolean isScrollingInDirection(float xvel, float yvel) { + return !mFinished && Math.signum(xvel) == Math.signum(mFinalX - mStartX) && + Math.signum(yvel) == Math.signum(mFinalY - mStartY); + } +} diff --git a/src/com/android/launcher3/LauncherSettings.java b/src/com/android/launcher3/LauncherSettings.java index 1d161d097..034ffbaa3 100644 --- a/src/com/android/launcher3/LauncherSettings.java +++ b/src/com/android/launcher3/LauncherSettings.java @@ -40,6 +40,11 @@ class LauncherSettings { static final String TITLE = "title"; /** + * Folder Hidden status + */ + static final String HIDDEN = "hidden"; + + /** * The Intent URL of the gesture, describing what it points to. This * value is given to {@link android.content.Intent#parseUri(String, int)} to create * an Intent that can be launched. @@ -171,6 +176,14 @@ class LauncherSettings { static final int CONTAINER_DESKTOP = -100; static final int CONTAINER_HOTSEAT = -101; + static final String containerToString(int container) { + switch (container) { + case CONTAINER_DESKTOP: return "desktop"; + case CONTAINER_HOTSEAT: return "hotseat"; + default: return String.valueOf(container); + } + } + /** * The screen holding the favorite (if container is CONTAINER_DESKTOP) * <P>Type: INTEGER</P> @@ -280,5 +293,11 @@ class LauncherSettings { * @see android.provider.LiveFolders#DISPLAY_MODE_LIST */ static final String DISPLAY_MODE = "displayMode"; + + /** + * Boolean indicating that his item was restored and not yet successfully bound. + * <P>Type: INTEGER</P> + */ + static final String RESTORED = "restored"; } } diff --git a/src/com/android/launcher3/LauncherWallpaperPickerActivity.java b/src/com/android/launcher3/LauncherWallpaperPickerActivity.java new file mode 100644 index 000000000..10fe013ee --- /dev/null +++ b/src/com/android/launcher3/LauncherWallpaperPickerActivity.java @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2013 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.android.launcher3; + +import android.content.Intent; + +public class LauncherWallpaperPickerActivity extends WallpaperPickerActivity { + @Override + public void startActivityForResultSafely(Intent intent, int requestCode) { + Utilities.startActivityForResultSafely(this, intent, requestCode); + } + @Override + public boolean enableRotation() { + return Utilities.isRotationEnabled(this); + } +} diff --git a/src/com/android/launcher3/Lists.java b/src/com/android/launcher3/Lists.java new file mode 100644 index 000000000..51f5dc272 --- /dev/null +++ b/src/com/android/launcher3/Lists.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2007 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.android.launcher3; + +import java.util.ArrayList; +import java.util.Collections; + +/** + * Provides static methods for creating {@code List} instances easily, and other + * utility methods for working with lists. + */ +public class Lists { + + /** + * Creates an empty {@code ArrayList} instance. + * + * <p><b>Note:</b> if you only need an <i>immutable</i> empty List, use + * {@link Collections#emptyList} instead. + * + * @return a newly-created, initially-empty {@code ArrayList} + */ + public static <E> ArrayList<E> newArrayList() { + return new ArrayList<E>(); + } + + /** + * Creates a resizable {@code ArrayList} instance containing the given + * elements. + * + * <p><b>Note:</b> due to a bug in javac 1.5.0_06, we cannot support the + * following: + * + * <p>{@code List<Base> list = Lists.newArrayList(sub1, sub2);} + * + * <p>where {@code sub1} and {@code sub2} are references to subtypes of + * {@code Base}, not of {@code Base} itself. To get around this, you must + * use: + * + * <p>{@code List<Base> list = Lists.<Base>newArrayList(sub1, sub2);} + * + * @param elements the elements that the list should contain, in order + * @return a newly-created {@code ArrayList} containing those elements + */ + public static <E> ArrayList<E> newArrayList(E... elements) { + int capacity = (elements.length * 110) / 100 + 5; + ArrayList<E> list = new ArrayList<E>(capacity); + Collections.addAll(list, elements); + return list; + } +} diff --git a/src/com/android/launcher3/LockWallpaperPickerActivity.java b/src/com/android/launcher3/LockWallpaperPickerActivity.java deleted file mode 100644 index 483568480..000000000 --- a/src/com/android/launcher3/LockWallpaperPickerActivity.java +++ /dev/null @@ -1,1600 +0,0 @@ -/* - * Copyright (C) 2014 The CyanogenMod 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.android.launcher3; - -import android.animation.Animator; -import android.animation.LayoutTransition; -import android.app.ActionBar; -import android.app.Activity; -import android.app.WallpaperInfo; -import android.app.WallpaperManager; -import android.content.ContentResolver; -import android.content.Context; -import android.content.Intent; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.content.pm.PackageManager.NameNotFoundException; -import android.content.res.AssetManager; -import android.content.res.Resources; -import android.database.Cursor; -import android.graphics.Bitmap; -import android.graphics.Bitmap.CompressFormat; -import android.graphics.BitmapFactory; -import android.graphics.BitmapRegionDecoder; -import android.graphics.Canvas; -import android.graphics.Matrix; -import android.graphics.Paint; -import android.graphics.Point; -import android.graphics.PorterDuff; -import android.graphics.Rect; -import android.graphics.RectF; -import android.graphics.drawable.BitmapDrawable; -import android.graphics.drawable.Drawable; -import android.graphics.drawable.LevelListDrawable; -import android.net.Uri; -import android.os.AsyncTask; -import android.os.Bundle; -import android.provider.MediaStore; -import android.provider.ThemesContract.ThemesColumns; -import android.util.Log; -import android.util.Pair; -import android.view.ActionMode; -import android.view.Display; -import android.view.LayoutInflater; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.ViewGroup; -import android.view.ViewTreeObserver; -import android.view.ViewTreeObserver.OnGlobalLayoutListener; -import android.view.animation.AccelerateInterpolator; -import android.view.animation.DecelerateInterpolator; -import android.widget.BaseAdapter; -import android.widget.FrameLayout; -import android.widget.HorizontalScrollView; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.ListAdapter; - -import com.android.gallery3d.common.Utils; -import com.android.launcher3.WallpaperCropActivity.BitmapCropTask; -import com.android.launcher3.WallpaperCropActivity.OnBitmapCroppedHandler; -import com.android.photos.BitmapRegionTileSource; - -import java.io.BufferedInputStream; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; - -public class LockWallpaperPickerActivity extends WallpaperCropActivity { - static final String TAG = LockWallpaperPickerActivity.class.getSimpleName(); - - public static final int IMAGE_PICK = 5; - public static final int PICK_WALLPAPER_THIRD_PARTY_ACTIVITY = 6; - public static final int PICK_LIVE_WALLPAPER = 7; - private static final String TEMP_WALLPAPER_TILES = "TEMP_KEYGUARD_WALLPAPER_TILES"; - - private View mSelectedThumb; - private boolean mIgnoreNextTap; - private OnClickListener mThumbnailOnClickListener; - - private LinearLayout mWallpapersView; - private View mWallpaperStrip; - - private ActionMode.Callback mActionModeCallback; - private ActionMode mActionMode; - - private View.OnLongClickListener mLongClickListener; - - ArrayList<Uri> mTempWallpaperTiles = new ArrayList<Uri>(); - private SavedWallpaperImages mSavedImages; - - public static class PickImageInfo extends WallpaperTileInfo { - @Override - public void onClick(WallpaperCropActivity a) { - Intent intent = new Intent(Intent.ACTION_GET_CONTENT); - intent.setType("image/*"); - Utilities.startActivityForResultSafely(((LockWallpaperPickerActivity)a), intent, IMAGE_PICK); - } - } - - public static class UserDesktopWallpaperInfo extends WallpaperTileInfo { - @Override - public void onClick(WallpaperCropActivity a) { - WallpaperManager am = WallpaperManager.getInstance(a); - am.clearKeyguardWallpaper(); - a.setResult(RESULT_OK); - a.finish(); - } - } - - public static class UriWallpaperInfo extends WallpaperTileInfo { - private Uri mUri; - public UriWallpaperInfo(Uri uri) { - mUri = uri; - } - @Override - public void onClick(WallpaperCropActivity a) { - CropView v = a.getCropView(); - int rotation = WallpaperCropActivity.getRotationFromExif(a, mUri); - v.setTileSource(new BitmapRegionTileSource(a, mUri, 1024, rotation), null); - v.setTouchEnabled(true); - } - @Override - public void onSave(final WallpaperCropActivity a) { - boolean finishActivityWhenDone = true; - OnBitmapCroppedHandler h = new OnBitmapCroppedHandler() { - public void onBitmapCropped(byte[] imageBytes) { - Point thumbSize = getDefaultThumbnailSize(a.getResources()); - Bitmap thumb = createThumbnail( - thumbSize, null, null, imageBytes, null, 0, 0, true); - a.getSavedImages().writeImage(thumb, imageBytes); - } - }; - ((LockWallpaperPickerActivity)a).cropImageAndSetWallpaper(mUri, h, finishActivityWhenDone); - } - @Override - public boolean isSelectable() { - return true; - } - @Override - public boolean isNamelessWallpaper() { - return true; - } - } - - /** - * For themes which have regular wallpapers - */ - public static class ThemeWallpaperInfo extends WallpaperTileInfo { - String mPackageName; - boolean mIsLegacy; - Drawable mThumb; - Context mContext; - - public ThemeWallpaperInfo(Context context, String packageName, boolean legacy, Drawable thumb) { - this.mContext = context; - this.mPackageName = packageName; - this.mIsLegacy = legacy; - this.mThumb = thumb; - } - - @Override - public void onClick(WallpaperCropActivity a) { - CropView v = a.getCropView(); - try { - BitmapRegionTileSource source = null; - if (mIsLegacy) { - final PackageManager pm = a.getPackageManager(); - PackageInfo pi = pm.getPackageInfo(mPackageName, 0); - Resources res = a.getPackageManager().getResourcesForApplication(mPackageName); - int resId = pi.legacyThemeInfos[0].wallpaperResourceId; - - int rotation = WallpaperCropActivity.getRotationFromExif(res, resId); - source = new BitmapRegionTileSource( - res, a, resId, 1024, rotation); - } else { - Resources res = a.getPackageManager().getResourcesForApplication(mPackageName); - if (res == null) { - return; - } - - int rotation = 0; - source = new BitmapRegionTileSource( - res, a, "wallpapers", 1024, rotation, true); - } - v.setTileSource(source, null); - v.setTouchEnabled(true); - } catch (NameNotFoundException e) { - } - } - - @Override - public void onSave(WallpaperCropActivity a) { - ((LockWallpaperPickerActivity)a).cropImageAndSetWallpaper( - "wallpapers", - mPackageName, - mIsLegacy, - true); - } - - @Override - public boolean isNamelessWallpaper() { - return true; - } - - @Override - public boolean isSelectable() { - return true; - } - } - - /** - * For themes that have LOCKSCREEN wallpapers - */ - public static class ThemeLockWallpaperInfo extends WallpaperTileInfo { - String mPackageName; - Drawable mThumb; - Context mContext; - - public ThemeLockWallpaperInfo(Context context, String packageName, Drawable thumb) { - this.mContext = context; - this.mPackageName = packageName; - this.mThumb = thumb; - } - - @Override - public void onClick(WallpaperCropActivity a) { - CropView v = a.getCropView(); - try { - BitmapRegionTileSource source = null; - Resources res = a.getPackageManager().getResourcesForApplication(mPackageName); - if (res == null) { - return; - } - - int rotation = 0; - source = new BitmapRegionTileSource( - res, a, "lockscreen", 1024, rotation, true); - v.setTileSource(source, null); - v.setTouchEnabled(true); - } catch (NameNotFoundException e) { - } - } - - @Override - public void onSave(WallpaperCropActivity a) { - ((LockWallpaperPickerActivity)a).cropImageAndSetWallpaper( - "lockscreen", - mPackageName, - false, - true); - } - - @Override - public boolean isNamelessWallpaper() { - return true; - } - - @Override - public boolean isSelectable() { - return true; - } - } - - public static class ResourceWallpaperInfo extends WallpaperTileInfo { - private Resources mResources; - private int mResId; - private Drawable mThumb; - - public ResourceWallpaperInfo(Resources res, int resId, Drawable thumb) { - mResources = res; - mResId = resId; - mThumb = thumb; - } - @Override - public void onClick(WallpaperCropActivity a) { - int rotation = WallpaperCropActivity.getRotationFromExif(mResources, mResId); - BitmapRegionTileSource source = new BitmapRegionTileSource( - mResources, a, mResId, 1024, rotation); - CropView v = a.getCropView(); - v.setTileSource(source, null); - Point wallpaperSize = WallpaperCropActivity.getDefaultWallpaperSize( - a.getResources(), a.getWindowManager()); - RectF crop = WallpaperCropActivity.getMaxCropRect( - source.getImageWidth(), source.getImageHeight(), - wallpaperSize.x, wallpaperSize.y, false); - v.setScale(wallpaperSize.x / crop.width()); - v.setTouchEnabled(false); - } - @Override - public void onSave(WallpaperCropActivity a) { - boolean finishActivityWhenDone = true; - ((LockWallpaperPickerActivity)a).cropImageAndSetWallpaper(mResources, mResId, finishActivityWhenDone); - } - @Override - public boolean isSelectable() { - return true; - } - @Override - public boolean isNamelessWallpaper() { - return true; - } - } - - protected void cropImageAndSetWallpaper(String path, String packageName, final boolean legacy, - final boolean finishActivityWhenDone) { - - Point outSize = new Point(); - getWindowManager().getDefaultDisplay().getSize(outSize); - - final int outWidth = outSize.x; - final int outHeight = outSize.y; - Runnable onEndCrop = new Runnable() { - public void run() { - if (finishActivityWhenDone) { - setResult(Activity.RESULT_OK); - finish(); - } - } - }; - - RectF cropRect = new RectF(mCropView.getCrop()); - BitmapCropTask cropTask = null; - try { - if (legacy) { - final PackageManager pm = getPackageManager(); - PackageInfo pi = pm.getPackageInfo(packageName, 0); - Resources res = getPackageManager().getResourcesForApplication(packageName); - int resId = pi.legacyThemeInfos[0].wallpaperResourceId; - cropTask = new BitmapCropTask(this, res, resId, - cropRect, 0, outWidth, outHeight, true, false, onEndCrop); - } else { - Resources res = getPackageManager().getResourcesForApplication(packageName); - if (res == null) { - return; - } - cropTask = new BitmapCropTask(this, res, path, cropRect, - 0, outWidth, outHeight, true, false, onEndCrop); - } - } catch (NameNotFoundException e) { - return; - } - - if (cropTask != null) { - cropTask.execute(); - } - } - - @Override - protected void cropImageAndSetWallpaper(Uri uri, - OnBitmapCroppedHandler onBitmapCroppedHandler, final boolean finishActivityWhenDone) { - // Get the crop - boolean ltr = mCropView.getLayoutDirection() == View.LAYOUT_DIRECTION_LTR; - - Point minDims = new Point(); - Point maxDims = new Point(); - Display d = getWindowManager().getDefaultDisplay(); - d.getCurrentSizeRange(minDims, maxDims); - - Point displaySize = new Point(); - d.getSize(displaySize); - - int maxDim = Math.max(maxDims.x, maxDims.y); - final int minDim = Math.min(minDims.x, minDims.y); - int defaultWallpaperWidth; - if (isScreenLarge(getResources())) { - defaultWallpaperWidth = (int) (maxDim * - wallpaperTravelToScreenWidthRatio(maxDim, minDim)); - } else { - defaultWallpaperWidth = Math.max((int) - (minDim * WALLPAPER_SCREENS_SPAN), maxDim); - } - - boolean isPortrait = displaySize.x < displaySize.y; - int portraitHeight; - if (isPortrait) { - portraitHeight = mCropView.getHeight(); - } else { - // TODO: how to actually get the proper portrait height? - // This is not quite right: - portraitHeight = Math.max(maxDims.x, maxDims.y); - } - if (android.os.Build.VERSION.SDK_INT >= - android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) { - Point realSize = new Point(); - d.getRealSize(realSize); - portraitHeight = Math.max(realSize.x, realSize.y); - } - // Get the crop - RectF cropRect = mCropView.getCrop(); - int cropRotation = mCropView.getImageRotation(); - float cropScale = mCropView.getWidth() / (float) cropRect.width(); - - Point inSize = mCropView.getSourceDimensions(); - Matrix rotateMatrix = new Matrix(); - rotateMatrix.setRotate(cropRotation); - float[] rotatedInSize = new float[] { inSize.x, inSize.y }; - rotateMatrix.mapPoints(rotatedInSize); - rotatedInSize[0] = Math.abs(rotatedInSize[0]); - rotatedInSize[1] = Math.abs(rotatedInSize[1]); - - // ADJUST CROP WIDTH - // Extend the crop all the way to the right, for parallax - // (or all the way to the left, in RTL) - float extraSpace = ltr ? rotatedInSize[0] - cropRect.right : cropRect.left; - // Cap the amount of extra width - float maxExtraSpace = defaultWallpaperWidth / cropScale - cropRect.width(); - extraSpace = Math.min(extraSpace, maxExtraSpace); - - if (ltr) { - cropRect.right += extraSpace; - } else { - cropRect.left -= extraSpace; - } - - // ADJUST CROP HEIGHT - if (isPortrait) { - cropRect.bottom = cropRect.top + portraitHeight / cropScale; - } else { // LANDSCAPE - float extraPortraitHeight = - portraitHeight / cropScale - cropRect.height(); - float expandHeight = - Math.min(Math.min(rotatedInSize[1] - cropRect.bottom, cropRect.top), - extraPortraitHeight / 2); - cropRect.top -= expandHeight; - cropRect.bottom += expandHeight; - } - final int outWidth = (int) Math.round(cropRect.width() * cropScale); - final int outHeight = (int) Math.round(cropRect.height() * cropScale); - - Runnable onEndCrop = new Runnable() { - public void run() { - updateWallpaperDimensions(outWidth, outHeight); - if (finishActivityWhenDone) { - setResult(Activity.RESULT_OK); - finish(); - } - } - }; - BitmapCropTask cropTask = new BitmapCropTask(this, uri, - cropRect, cropRotation, outWidth, outHeight, true, false, onEndCrop); - if (onBitmapCroppedHandler != null) { - cropTask.setOnBitmapCropped(onBitmapCroppedHandler); - } - cropTask.execute(); - } - - @Override - protected void setWallpaper(String filePath, final boolean finishActivityWhenDone) { - int rotation = getRotationFromExif(filePath); - BitmapCropTask cropTask = new BitmapCropTask( - this, filePath, null, rotation, 0, 0, true, false, null); - final Point bounds = cropTask.getImageBounds(); - Runnable onEndCrop = new Runnable() { - public void run() { - updateWallpaperDimensions(bounds.x, bounds.y); - if (finishActivityWhenDone) { - setResult(Activity.RESULT_OK); - finish(); - } - } - }; - cropTask.setOnEndRunnable(onEndCrop); - cropTask.setNoCrop(true); - cropTask.execute(); - } - - protected static class BitmapCropTask extends AsyncTask<Void, Void, Boolean> { - Uri mInUri = null; - Context mContext; - String mInFilePath; - byte[] mInImageBytes; - int mInResId = 0; - InputStream mInStream; - RectF mCropBounds = null; - int mOutWidth, mOutHeight; - int mRotation; - String mOutputFormat = "jpg"; // for now - boolean mSetWallpaper; - boolean mSaveCroppedBitmap; - Bitmap mCroppedBitmap; - Runnable mOnEndRunnable; - Resources mResources; - OnBitmapCroppedHandler mOnBitmapCroppedHandler; - boolean mNoCrop; - boolean mImageFromAsset; - - public BitmapCropTask(Context c, Resources res , String assetPath, - RectF cropBounds, int rotation, int outWidth, int outHeight, - boolean setWallpaper, boolean saveCroppedBitmap, Runnable onEndRunnable) { - mContext = c; - mResources = res; - mInFilePath = assetPath; - mImageFromAsset = true; - init(cropBounds, rotation, - outWidth, outHeight, setWallpaper, saveCroppedBitmap, onEndRunnable); - } - - public BitmapCropTask(Context c, String filePath, - RectF cropBounds, int rotation, int outWidth, int outHeight, - boolean setWallpaper, boolean saveCroppedBitmap, Runnable onEndRunnable) { - mContext = c; - mInFilePath = filePath; - init(cropBounds, rotation, - outWidth, outHeight, setWallpaper, saveCroppedBitmap, onEndRunnable); - } - - public BitmapCropTask(byte[] imageBytes, - RectF cropBounds, int rotation, int outWidth, int outHeight, - boolean setWallpaper, boolean saveCroppedBitmap, Runnable onEndRunnable) { - mInImageBytes = imageBytes; - init(cropBounds, rotation, - outWidth, outHeight, setWallpaper, saveCroppedBitmap, onEndRunnable); - } - - public BitmapCropTask(Context c, Uri inUri, - RectF cropBounds, int rotation, int outWidth, int outHeight, - boolean setWallpaper, boolean saveCroppedBitmap, Runnable onEndRunnable) { - mContext = c; - mInUri = inUri; - init(cropBounds, rotation, - outWidth, outHeight, setWallpaper, saveCroppedBitmap, onEndRunnable); - } - - public BitmapCropTask(Context c, Resources res, int inResId, - RectF cropBounds, int rotation, int outWidth, int outHeight, - boolean setWallpaper, boolean saveCroppedBitmap, Runnable onEndRunnable) { - mContext = c; - mInResId = inResId; - mResources = res; - init(cropBounds, rotation, - outWidth, outHeight, setWallpaper, saveCroppedBitmap, onEndRunnable); - } - - private void init(RectF cropBounds, int rotation, int outWidth, int outHeight, - boolean setWallpaper, boolean saveCroppedBitmap, Runnable onEndRunnable) { - mCropBounds = cropBounds; - mRotation = rotation; - mOutWidth = outWidth; - mOutHeight = outHeight; - mSetWallpaper = setWallpaper; - mSaveCroppedBitmap = saveCroppedBitmap; - mOnEndRunnable = onEndRunnable; - } - - public void setOnBitmapCropped(OnBitmapCroppedHandler handler) { - mOnBitmapCroppedHandler = handler; - } - - public void setNoCrop(boolean value) { - mNoCrop = value; - } - - public void setOnEndRunnable(Runnable onEndRunnable) { - mOnEndRunnable = onEndRunnable; - } - - // Helper to setup input stream - private void regenerateInputStream() { - if (mInUri == null && mInResId == 0 && mInFilePath == null && mInImageBytes == null && !mImageFromAsset) { - Log.w(TAG, "cannot read original file, no input URI, resource ID, or " + - "image byte array given"); - } else { - Utils.closeSilently(mInStream); - try { - if (mImageFromAsset) { - AssetManager am = mResources.getAssets(); - String[] pathImages = am.list(mInFilePath); - if (pathImages == null || pathImages.length == 0) { - throw new IOException("did not find any images in path: " + mInFilePath); - } - InputStream is = am.open(mInFilePath + File.separator + pathImages[0]); - mInStream = new BufferedInputStream(is); - } else if (mInUri != null) { - mInStream = new BufferedInputStream( - mContext.getContentResolver().openInputStream(mInUri)); - } else if (mInFilePath != null) { - mInStream = mContext.openFileInput(mInFilePath); - } else if (mInImageBytes != null) { - mInStream = new BufferedInputStream( - new ByteArrayInputStream(mInImageBytes)); - } else { - mInStream = new BufferedInputStream( - mResources.openRawResource(mInResId)); - } - } catch (FileNotFoundException e) { - Log.w(TAG, "cannot read file: " + mInUri.toString(), e); - } catch (IOException e) { - Log.w(TAG, "cannot read file: " + mInUri.toString(), e); - } - } - } - - public Point getImageBounds() { - regenerateInputStream(); - if (mInStream != null) { - BitmapFactory.Options options = new BitmapFactory.Options(); - options.inJustDecodeBounds = true; - BitmapFactory.decodeStream(mInStream, null, options); - if (options.outWidth != 0 && options.outHeight != 0) { - return new Point(options.outWidth, options.outHeight); - } - } - return null; - } - - public void setCropBounds(RectF cropBounds) { - mCropBounds = cropBounds; - } - - public Bitmap getCroppedBitmap() { - return mCroppedBitmap; - } - public boolean cropBitmap() { - boolean failure = false; - - regenerateInputStream(); - - WallpaperManager wallpaperManager = null; - if (mSetWallpaper) { - wallpaperManager = WallpaperManager.getInstance(mContext.getApplicationContext()); - } - if (mSetWallpaper && mNoCrop && mInStream != null) { - try { - wallpaperManager.setKeyguardStream(mInStream); - } catch (IOException e) { - Log.w(TAG, "cannot write stream to wallpaper", e); - failure = true; - } - return !failure; - } - if (mInStream != null) { - // Find crop bounds (scaled to original image size) - Rect roundedTrueCrop = new Rect(); - Matrix rotateMatrix = new Matrix(); - Matrix inverseRotateMatrix = new Matrix(); - if (mRotation > 0) { - rotateMatrix.setRotate(mRotation); - inverseRotateMatrix.setRotate(-mRotation); - - mCropBounds.roundOut(roundedTrueCrop); - mCropBounds = new RectF(roundedTrueCrop); - - Point bounds = getImageBounds(); - - float[] rotatedBounds = new float[] { bounds.x, bounds.y }; - rotateMatrix.mapPoints(rotatedBounds); - rotatedBounds[0] = Math.abs(rotatedBounds[0]); - rotatedBounds[1] = Math.abs(rotatedBounds[1]); - - mCropBounds.offset(-rotatedBounds[0]/2, -rotatedBounds[1]/2); - inverseRotateMatrix.mapRect(mCropBounds); - mCropBounds.offset(bounds.x/2, bounds.y/2); - - regenerateInputStream(); - } - - mCropBounds.roundOut(roundedTrueCrop); - - if (roundedTrueCrop.width() <= 0 || roundedTrueCrop.height() <= 0) { - Log.w(TAG, "crop has bad values for full size image"); - failure = true; - return false; - } - - // See how much we're reducing the size of the image - int scaleDownSampleSize = Math.min(roundedTrueCrop.width() / mOutWidth, - roundedTrueCrop.height() / mOutHeight); - - // Attempt to open a region decoder - BitmapRegionDecoder decoder = null; - try { - decoder = BitmapRegionDecoder.newInstance(mInStream, true); - } catch (IOException e) { - Log.w(TAG, "cannot open region decoder for file: " + mInUri.toString(), e); - } - - Bitmap crop = null; - if (decoder != null) { - // Do region decoding to get crop bitmap - BitmapFactory.Options options = new BitmapFactory.Options(); - if (scaleDownSampleSize > 1) { - options.inSampleSize = scaleDownSampleSize; - } - crop = decoder.decodeRegion(roundedTrueCrop, options); - decoder.recycle(); - } - - if (crop == null) { - // BitmapRegionDecoder has failed, try to crop in-memory - regenerateInputStream(); - Bitmap fullSize = null; - if (mInStream != null) { - BitmapFactory.Options options = new BitmapFactory.Options(); - if (scaleDownSampleSize > 1) { - options.inSampleSize = scaleDownSampleSize; - } - fullSize = BitmapFactory.decodeStream(mInStream, null, options); - } - if (fullSize != null) { - mCropBounds.left /= scaleDownSampleSize; - mCropBounds.top /= scaleDownSampleSize; - mCropBounds.bottom /= scaleDownSampleSize; - mCropBounds.right /= scaleDownSampleSize; - mCropBounds.roundOut(roundedTrueCrop); - - crop = Bitmap.createBitmap(fullSize, roundedTrueCrop.left, - roundedTrueCrop.top, roundedTrueCrop.width(), - roundedTrueCrop.height()); - } - } - - if (crop == null) { - Log.w(TAG, "cannot decode file: " + mInUri.toString()); - failure = true; - return false; - } - if (mOutWidth > 0 && mOutHeight > 0 || mRotation > 0) { - float[] dimsAfter = new float[] { crop.getWidth(), crop.getHeight() }; - rotateMatrix.mapPoints(dimsAfter); - dimsAfter[0] = Math.abs(dimsAfter[0]); - dimsAfter[1] = Math.abs(dimsAfter[1]); - - if (!(mOutWidth > 0 && mOutHeight > 0)) { - mOutWidth = Math.round(dimsAfter[0]); - mOutHeight = Math.round(dimsAfter[1]); - } - - RectF cropRect = new RectF(0, 0, dimsAfter[0], dimsAfter[1]); - RectF returnRect = new RectF(0, 0, mOutWidth, mOutHeight); - - Matrix m = new Matrix(); - if (mRotation == 0) { - m.setRectToRect(cropRect, returnRect, Matrix.ScaleToFit.FILL); - } else { - Matrix m1 = new Matrix(); - m1.setTranslate(-crop.getWidth() / 2f, -crop.getHeight() / 2f); - Matrix m2 = new Matrix(); - m2.setRotate(mRotation); - Matrix m3 = new Matrix(); - m3.setTranslate(dimsAfter[0] / 2f, dimsAfter[1] / 2f); - Matrix m4 = new Matrix(); - m4.setRectToRect(cropRect, returnRect, Matrix.ScaleToFit.FILL); - - Matrix c1 = new Matrix(); - c1.setConcat(m2, m1); - Matrix c2 = new Matrix(); - c2.setConcat(m4, m3); - m.setConcat(c2, c1); - } - - Bitmap tmp = Bitmap.createBitmap((int) returnRect.width(), - (int) returnRect.height(), Bitmap.Config.ARGB_8888); - if (tmp != null) { - Canvas c = new Canvas(tmp); - Paint p = new Paint(); - p.setFilterBitmap(true); - c.drawBitmap(crop, m, p); - crop = tmp; - } - } - - if (mSaveCroppedBitmap) { - mCroppedBitmap = crop; - } - - // Get output compression format - CompressFormat cf = - convertExtensionToCompressFormat(getFileExtension(mOutputFormat)); - - // Compress to byte array - ByteArrayOutputStream tmpOut = new ByteArrayOutputStream(2048); - if (crop.compress(cf, DEFAULT_COMPRESS_QUALITY, tmpOut)) { - // If we need to set to the wallpaper, set it - if (mSetWallpaper && wallpaperManager != null) { - try { - byte[] outByteArray = tmpOut.toByteArray(); - wallpaperManager.setKeyguardStream(new ByteArrayInputStream(outByteArray)); - if (mOnBitmapCroppedHandler != null) { - mOnBitmapCroppedHandler.onBitmapCropped(outByteArray); - } - } catch (IOException e) { - Log.w(TAG, "cannot write stream to wallpaper", e); - failure = true; - } - } - } else { - Log.w(TAG, "cannot compress bitmap"); - failure = true; - } - } else { - Log.w(TAG, "could not complete crop task because input stream is null"); - } - return !failure; // True if any of the operations failed - } - - @Override - protected Boolean doInBackground(Void... params) { - return cropBitmap(); - } - - @Override - protected void onPostExecute(Boolean result) { - if (mOnEndRunnable != null) { - mOnEndRunnable.run(); - } - } - } - - @Override - protected void setWallpaperStripYOffset(int offset) { - mWallpaperStrip.setPadding(0, 0, 0, offset); - } - - // called by onCreate; this is subclassed to overwrite WallpaperCropActivity - protected void init() { - setContentView(R.layout.wallpaper_picker); - - mCropView = (CropView) findViewById(R.id.cropView); - mWallpaperStrip = findViewById(R.id.wallpaper_strip); - mCropView.setTouchCallback(new CropView.TouchCallback() { - LauncherViewPropertyAnimator mAnim; - @Override - public void onTouchDown() { - if (mAnim != null) { - mAnim.cancel(); - } - if (mWallpaperStrip.getAlpha() == 1f) { - mIgnoreNextTap = true; - } - mAnim = new LauncherViewPropertyAnimator(mWallpaperStrip); - mAnim.alpha(0f) - .setDuration(150) - .addListener(new Animator.AnimatorListener() { - public void onAnimationStart(Animator animator) { } - public void onAnimationEnd(Animator animator) { - mWallpaperStrip.setVisibility(View.INVISIBLE); - } - public void onAnimationCancel(Animator animator) { } - public void onAnimationRepeat(Animator animator) { } - }); - mAnim.setInterpolator(new AccelerateInterpolator(0.75f)); - mAnim.start(); - } - @Override - public void onTouchUp() { - mIgnoreNextTap = false; - } - @Override - public void onTap() { - boolean ignoreTap = mIgnoreNextTap; - mIgnoreNextTap = false; - if (!ignoreTap) { - if (mAnim != null) { - mAnim.cancel(); - } - mWallpaperStrip.setVisibility(View.VISIBLE); - mAnim = new LauncherViewPropertyAnimator(mWallpaperStrip); - mAnim.alpha(1f) - .setDuration(150) - .setInterpolator(new DecelerateInterpolator(0.75f)); - mAnim.start(); - } - } - }); - - mThumbnailOnClickListener = new OnClickListener() { - public void onClick(View v) { - if (mActionMode != null) { - // When CAB is up, clicking toggles the item instead - if (v.isLongClickable()) { - mLongClickListener.onLongClick(v); - } - return; - } - WallpaperTileInfo info = (WallpaperTileInfo) v.getTag(); - if (info.isSelectable()) { - if (mSelectedThumb != null) { - mSelectedThumb.setSelected(false); - mSelectedThumb = null; - } - mSelectedThumb = v; - v.setSelected(true); - // TODO: Remove this once the accessibility framework and - // services have better support for selection state. - v.announceForAccessibility( - getString(R.string.announce_selection, v.getContentDescription())); - } - info.onClick(LockWallpaperPickerActivity.this); - } - }; - mLongClickListener = new View.OnLongClickListener() { - // Called when the user long-clicks on someView - public boolean onLongClick(View view) { - CheckableFrameLayout c = (CheckableFrameLayout) view; - c.toggle(); - - if (mActionMode != null) { - mActionMode.invalidate(); - } else { - // Start the CAB using the ActionMode.Callback defined below - mActionMode = startActionMode(mActionModeCallback); - int childCount = mWallpapersView.getChildCount(); - for (int i = 0; i < childCount; i++) { - mWallpapersView.getChildAt(i).setSelected(false); - } - } - return true; - } - }; - - mWallpapersView = (LinearLayout) findViewById(R.id.wallpaper_list); - - // Add a tile for the Gallery - LinearLayout masterWallpaperList = (LinearLayout) findViewById(R.id.master_wallpaper_list); - FrameLayout pickImageTile = (FrameLayout) getLayoutInflater(). - inflate(R.layout.wallpaper_picker_image_picker_item, masterWallpaperList, false); - setWallpaperItemPaddingToZero(pickImageTile); - masterWallpaperList.addView(pickImageTile, 0); - - // Add tile for clear image - FrameLayout clearImageTile = (FrameLayout) getLayoutInflater(). - inflate(R.layout.wallpaper_picker_clear, masterWallpaperList, false); - setWallpaperItemPaddingToZero(clearImageTile); - masterWallpaperList.addView(clearImageTile, 0); - - // theme LOCKSCREEN wallpapers - ArrayList<ThemeLockWallpaperInfo> themeLockWallpapers = findThemeLockWallpapers(); - ThemeLockWallpapersAdapter tla = new ThemeLockWallpapersAdapter(this, themeLockWallpapers); - populateWallpapersFromAdapter(mWallpapersView, tla, false, true); - - // theme wallpapers - ArrayList<ThemeWallpaperInfo> themeWallpapers = findThemeWallpapers(); - ThemeWallpapersAdapter ta = new ThemeWallpapersAdapter(this, themeWallpapers); - populateWallpapersFromAdapter(mWallpapersView, ta, false, true); - - // Populate the saved wallpapers - mSavedImages = new SavedWallpaperImages(this); - mSavedImages.loadThumbnailsAndImageIdList(); - populateWallpapersFromAdapter(mWallpapersView, mSavedImages, true, true); - - // Make its background the last photo taken on external storage - Bitmap lastPhoto = getThumbnailOfLastPhoto(); - if (lastPhoto != null) { - ImageView galleryThumbnailBg = - (ImageView) pickImageTile.findViewById(R.id.wallpaper_image); - galleryThumbnailBg.setImageBitmap(getThumbnailOfLastPhoto()); - int colorOverlay = getResources().getColor(R.color.wallpaper_picker_translucent_gray); - galleryThumbnailBg.setColorFilter(colorOverlay, PorterDuff.Mode.SRC_ATOP); - } - - PickImageInfo pickImageInfo = new PickImageInfo(); - pickImageTile.setTag(pickImageInfo); - pickImageInfo.setView(pickImageTile); - pickImageTile.setOnClickListener(mThumbnailOnClickListener); - pickImageInfo.setView(pickImageTile); - - UserDesktopWallpaperInfo clearImageInfo = new UserDesktopWallpaperInfo(); - clearImageTile.setTag(clearImageInfo); - clearImageInfo.setView(clearImageTile); - clearImageTile.setOnClickListener(mThumbnailOnClickListener); - clearImageInfo.setView(clearImageTile); - - updateTileIndices(); - - // Update the scroll for RTL - initializeScrollForRtl(); - - // Create smooth layout transitions for when items are deleted - final LayoutTransition transitioner = new LayoutTransition(); - transitioner.setDuration(200); - transitioner.setStartDelay(LayoutTransition.CHANGE_DISAPPEARING, 0); - transitioner.setAnimator(LayoutTransition.DISAPPEARING, null); - mWallpapersView.setLayoutTransition(transitioner); - - // Action bar - // Show the custom action bar view - final ActionBar actionBar = getActionBar(); - actionBar.setCustomView(R.layout.actionbar_set_wallpaper); - actionBar.getCustomView().setOnClickListener( - new View.OnClickListener() { - @Override - public void onClick(View v) { - if (mSelectedThumb != null) { - WallpaperTileInfo info = (WallpaperTileInfo) mSelectedThumb.getTag(); - info.onSave(LockWallpaperPickerActivity.this); - } - } - }); - - // CAB for deleting items - mActionModeCallback = new ActionMode.Callback() { - // Called when the action mode is created; startActionMode() was called - @Override - public boolean onCreateActionMode(ActionMode mode, Menu menu) { - // Inflate a menu resource providing context menu items - MenuInflater inflater = mode.getMenuInflater(); - inflater.inflate(R.menu.cab_delete_wallpapers, menu); - return true; - } - - private int numCheckedItems() { - int childCount = mWallpapersView.getChildCount(); - int numCheckedItems = 0; - for (int i = 0; i < childCount; i++) { - CheckableFrameLayout c = (CheckableFrameLayout) mWallpapersView.getChildAt(i); - if (c.isChecked()) { - numCheckedItems++; - } - } - return numCheckedItems; - } - - // Called each time the action mode is shown. Always called after onCreateActionMode, - // but may be called multiple times if the mode is invalidated. - @Override - public boolean onPrepareActionMode(ActionMode mode, Menu menu) { - int numCheckedItems = numCheckedItems(); - if (numCheckedItems == 0) { - mode.finish(); - return true; - } else { - mode.setTitle(getResources().getQuantityString( - R.plurals.number_of_items_selected, numCheckedItems, numCheckedItems)); - return true; - } - } - - // Called when the user selects a contextual menu item - @Override - public boolean onActionItemClicked(ActionMode mode, MenuItem item) { - int itemId = item.getItemId(); - if (itemId == R.id.menu_delete) { - int childCount = mWallpapersView.getChildCount(); - ArrayList<View> viewsToRemove = new ArrayList<View>(); - for (int i = 0; i < childCount; i++) { - CheckableFrameLayout c = - (CheckableFrameLayout) mWallpapersView.getChildAt(i); - if (c.isChecked()) { - WallpaperTileInfo info = (WallpaperTileInfo) c.getTag(); - info.onDelete(LockWallpaperPickerActivity.this); - viewsToRemove.add(c); - } - } - for (View v : viewsToRemove) { - mWallpapersView.removeView(v); - } - updateTileIndices(); - mode.finish(); // Action picked, so close the CAB - return true; - } else { - return false; - } - } - - // Called when the user exits the action mode - @Override - public void onDestroyActionMode(ActionMode mode) { - int childCount = mWallpapersView.getChildCount(); - for (int i = 0; i < childCount; i++) { - CheckableFrameLayout c = (CheckableFrameLayout) mWallpapersView.getChildAt(i); - c.setChecked(false); - } - mSelectedThumb.setSelected(true); - mActionMode = null; - } - }; - } - - private void initializeScrollForRtl() { - final HorizontalScrollView scroll = - (HorizontalScrollView) findViewById(R.id.wallpaper_scroll_container); - - if (scroll.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) { - final ViewTreeObserver observer = scroll.getViewTreeObserver(); - observer.addOnGlobalLayoutListener(new OnGlobalLayoutListener() { - public void onGlobalLayout() { - LinearLayout masterWallpaperList = - (LinearLayout) findViewById(R.id.master_wallpaper_list); - scroll.scrollTo(masterWallpaperList.getWidth(), 0); - scroll.getViewTreeObserver().removeOnGlobalLayoutListener(this); - } - }); - } - } - - public boolean enableRotation() { - return super.enableRotation() || Launcher.sForceEnableRotation; - } - - protected Bitmap getThumbnailOfLastPhoto() { - Cursor cursor = MediaStore.Images.Media.query(getContentResolver(), - MediaStore.Images.Media.EXTERNAL_CONTENT_URI, - new String[] { MediaStore.Images.ImageColumns._ID, - MediaStore.Images.ImageColumns.DATE_TAKEN}, - null, null, MediaStore.Images.ImageColumns.DATE_TAKEN + " DESC LIMIT 1"); - Bitmap thumb = null; - if (cursor != null) { - if (cursor.moveToFirst()) { - int id = cursor.getInt(0); - thumb = MediaStore.Images.Thumbnails.getThumbnail(getContentResolver(), - id, MediaStore.Images.Thumbnails.MINI_KIND, null); - } - cursor.close(); - } - return thumb; - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - return super.onCreateOptionsMenu(menu); - } - - @Override - public boolean onPrepareOptionsMenu(Menu menu) { - return super.onPrepareOptionsMenu(menu); - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - // Handle presses on the action bar items - switch (item.getItemId()) { - default: - return super.onOptionsItemSelected(item); - } - } - - protected void onStop() { - super.onStop(); - mWallpaperStrip = findViewById(R.id.wallpaper_strip); - if (mWallpaperStrip.getAlpha() < 1f) { - mWallpaperStrip.setAlpha(1f); - mWallpaperStrip.setVisibility(View.VISIBLE); - } - } - - @Override - protected void onDestroy() { - mWallpapersView.removeAllViews(); - super.onDestroy(); - } - - protected void onSaveInstanceState(Bundle outState) { - outState.putParcelableArrayList(TEMP_WALLPAPER_TILES, mTempWallpaperTiles); - } - - protected void onRestoreInstanceState(Bundle savedInstanceState) { - ArrayList<Uri> uris = savedInstanceState.getParcelableArrayList(TEMP_WALLPAPER_TILES); - for (Uri uri : uris) { - addTemporaryWallpaperTile(uri); - } - } - - private void populateWallpapersFromAdapter(ViewGroup parent, BaseAdapter adapter, - boolean addLongPressHandler, boolean selectFirstTile) { - for (int i = 0; i < adapter.getCount(); i++) { - FrameLayout thumbnail = (FrameLayout) adapter.getView(i, null, parent); - parent.addView(thumbnail, i); - WallpaperTileInfo info = (WallpaperTileInfo) adapter.getItem(i); - thumbnail.setTag(info); - info.setView(thumbnail); - if (addLongPressHandler) { - addLongPressHandler(thumbnail); - } - thumbnail.setOnClickListener(mThumbnailOnClickListener); - if (i == 0 && selectFirstTile) { - mThumbnailOnClickListener.onClick(thumbnail); - } - } - } - - private void updateTileIndices() { - LinearLayout masterWallpaperList = (LinearLayout) findViewById(R.id.master_wallpaper_list); - final int childCount = masterWallpaperList.getChildCount(); - final Resources res = getResources(); - - // Do two passes; the first pass gets the total number of tiles - int numTiles = 0; - for (int passNum = 0; passNum < 2; passNum++) { - int tileIndex = 0; - for (int i = 0; i < childCount; i++) { - View child = masterWallpaperList.getChildAt(i); - LinearLayout subList; - - int subListStart; - int subListEnd; - if (child.getTag() instanceof WallpaperTileInfo) { - subList = masterWallpaperList; - subListStart = i; - subListEnd = i + 1; - } else { // if (child instanceof LinearLayout) { - subList = (LinearLayout) child; - subListStart = 0; - subListEnd = subList.getChildCount(); - } - - for (int j = subListStart; j < subListEnd; j++) { - WallpaperTileInfo info = (WallpaperTileInfo) subList.getChildAt(j).getTag(); - if (info.isNamelessWallpaper()) { - if (passNum == 0) { - numTiles++; - } else { - CharSequence label = res.getString( - R.string.wallpaper_accessibility_name, ++tileIndex, numTiles); - info.onIndexUpdated(label); - } - } - } - } - } - } - - private static Point getDefaultThumbnailSize(Resources res) { - return new Point(res.getDimensionPixelSize(R.dimen.wallpaperThumbnailWidth), - res.getDimensionPixelSize(R.dimen.wallpaperThumbnailHeight)); - } - - private static Bitmap createThumbnail(Point size, Context context, Uri uri, byte[] imageBytes, - Resources res, int resId, int rotation, boolean leftAligned) { - int width = size.x; - int height = size.y; - - BitmapCropTask cropTask; - if (uri != null) { - cropTask = new BitmapCropTask( - context, uri, null, rotation, width, height, false, true, null); - } else if (imageBytes != null) { - cropTask = new BitmapCropTask( - imageBytes, null, rotation, width, height, false, true, null); - } else { - cropTask = new BitmapCropTask( - context, res, resId, null, rotation, width, height, false, true, null); - } - Point bounds = cropTask.getImageBounds(); - if (bounds == null || bounds.x == 0 || bounds.y == 0) { - return null; - } - - Matrix rotateMatrix = new Matrix(); - rotateMatrix.setRotate(rotation); - float[] rotatedBounds = new float[] { bounds.x, bounds.y }; - rotateMatrix.mapPoints(rotatedBounds); - rotatedBounds[0] = Math.abs(rotatedBounds[0]); - rotatedBounds[1] = Math.abs(rotatedBounds[1]); - - RectF cropRect = WallpaperCropActivity.getMaxCropRect( - (int) rotatedBounds[0], (int) rotatedBounds[1], width, height, leftAligned); - cropTask.setCropBounds(cropRect); - - if (cropTask.cropBitmap()) { - return cropTask.getCroppedBitmap(); - } else { - return null; - } - } - - private void addTemporaryWallpaperTile(Uri uri) { - mTempWallpaperTiles.add(uri); - // Add a tile for the image picked from Gallery - FrameLayout pickedImageThumbnail = (FrameLayout) getLayoutInflater(). - inflate(R.layout.wallpaper_picker_item, mWallpapersView, false); - setWallpaperItemPaddingToZero(pickedImageThumbnail); - - // Load the thumbnail - ImageView image = (ImageView) pickedImageThumbnail.findViewById(R.id.wallpaper_image); - Point defaultSize = getDefaultThumbnailSize(this.getResources()); - int rotation = WallpaperCropActivity.getRotationFromExif(this, uri); - Bitmap thumb = createThumbnail(defaultSize, this, uri, null, null, 0, rotation, false); - if (thumb != null) { - image.setImageBitmap(thumb); - Drawable thumbDrawable = image.getDrawable(); - thumbDrawable.setDither(true); - } else { - Log.e(TAG, "Error loading thumbnail for uri=" + uri); - } - mWallpapersView.addView(pickedImageThumbnail, 0); - - UriWallpaperInfo info = new UriWallpaperInfo(uri); - pickedImageThumbnail.setTag(info); - info.setView(pickedImageThumbnail); - addLongPressHandler(pickedImageThumbnail); - updateTileIndices(); - pickedImageThumbnail.setOnClickListener(mThumbnailOnClickListener); - mThumbnailOnClickListener.onClick(pickedImageThumbnail); - } - - protected void onActivityResult(int requestCode, int resultCode, Intent data) { - if (requestCode == IMAGE_PICK && resultCode == RESULT_OK) { - if (data != null && data.getData() != null) { - Uri uri = data.getData(); - addTemporaryWallpaperTile(uri); - } - } else if (requestCode == PICK_WALLPAPER_THIRD_PARTY_ACTIVITY) { - setResult(RESULT_OK); - finish(); - } - } - - static void setWallpaperItemPaddingToZero(FrameLayout frameLayout) { - frameLayout.setPadding(0, 0, 0, 0); - frameLayout.setForeground(new ZeroPaddingDrawable(frameLayout.getForeground())); - } - - private void addLongPressHandler(View v) { - v.setOnLongClickListener(mLongClickListener); - } - - private ArrayList<ThemeWallpaperInfo> findThemeWallpapers() { - ArrayList<ThemeWallpaperInfo> themeWallpapers = - new ArrayList<ThemeWallpaperInfo>(); - ContentResolver cr = getContentResolver(); - String[] projection = { ThemesColumns.PKG_NAME, ThemesColumns.IS_LEGACY_THEME }; - String selection = ThemesColumns.MODIFIES_LAUNCHER + "=? AND " + - ThemesColumns.PKG_NAME + "!=?"; - String[] selectoinArgs = {"1", "default"}; - String sortOrder = null; - Cursor c = cr.query(ThemesColumns.CONTENT_URI, projection, selection, - selectoinArgs, sortOrder); - if (c != null) { - Bitmap bmp; - while (c.moveToNext()) { - String pkgName = c.getString(c.getColumnIndexOrThrow(ThemesColumns.PKG_NAME)); - boolean isLegacy = c.getInt(c.getColumnIndexOrThrow( - ThemesColumns.IS_LEGACY_THEME)) == 1; - bmp = getThemeWallpaper(this, "wallpapers", pkgName, isLegacy, true /* thumb*/); - themeWallpapers.add( - new ThemeWallpaperInfo(this, pkgName, isLegacy, - new BitmapDrawable(getResources(), bmp))); - if (bmp != null) { - Log.d("", String.format("Loaded bitmap of size %dx%d for %s", - bmp.getWidth(), bmp.getHeight(), pkgName)); - } - } - c.close(); - } - return themeWallpapers; - } - - private ArrayList<ThemeLockWallpaperInfo> findThemeLockWallpapers() { - ArrayList<ThemeLockWallpaperInfo> themeWallpapers = - new ArrayList<ThemeLockWallpaperInfo>(); - ContentResolver cr = getContentResolver(); - String[] projection = { ThemesColumns.PKG_NAME }; - String selection = ThemesColumns.MODIFIES_LOCKSCREEN + "=? AND " + - ThemesColumns.PKG_NAME + "!=?"; - String[] selectoinArgs = {"1", "default"}; - String sortOrder = null; - Cursor c = cr.query(ThemesColumns.CONTENT_URI, projection, selection, - selectoinArgs, sortOrder); - if (c != null) { - Bitmap bmp; - while (c.moveToNext()) { - String pkgName = c.getString(c.getColumnIndexOrThrow(ThemesColumns.PKG_NAME)); - bmp = getThemeWallpaper(this, "lockscreen", pkgName, false, true /* thumb*/); - themeWallpapers.add( - new ThemeLockWallpaperInfo(this, pkgName, - new BitmapDrawable(getResources(), bmp))); - if (bmp != null) { - Log.d("", String.format("Loaded bitmap of size %dx%d for %s", - bmp.getWidth(), bmp.getHeight(), pkgName)); - } - } - c.close(); - } - return themeWallpapers; - } - - public Pair<ApplicationInfo, Integer> getWallpaperArrayResourceId() { - // Context.getPackageName() may return the "original" package name, - // com.android.launcher3; Resources needs the real package name, - // com.android.launcher3. So we ask Resources for what it thinks the - // package name should be. - final String packageName = getResources().getResourcePackageName(R.array.wallpapers); - try { - ApplicationInfo info = getPackageManager().getApplicationInfo(packageName, 0); - return new Pair<ApplicationInfo, Integer>(info, R.array.wallpapers); - } catch (PackageManager.NameNotFoundException e) { - return null; - } - } - - public CropView getCropView() { - return mCropView; - } - - public SavedWallpaperImages getSavedImages() { - return mSavedImages; - } - - static class ZeroPaddingDrawable extends LevelListDrawable { - public ZeroPaddingDrawable(Drawable d) { - super(); - addLevel(0, 0, d); - setLevel(0); - } - - @Override - public boolean getPadding(Rect padding) { - padding.set(0, 0, 0, 0); - return true; - } - } - - private static class ThemeLockWallpapersAdapter extends BaseAdapter implements ListAdapter { - private LayoutInflater mLayoutInflater; - private ArrayList<ThemeLockWallpaperInfo> mWallpapers; - - ThemeLockWallpapersAdapter(Activity activity, ArrayList<ThemeLockWallpaperInfo> wallpapers) { - mLayoutInflater = activity.getLayoutInflater(); - mWallpapers = wallpapers; - } - - public int getCount() { - return mWallpapers.size(); - } - - public ThemeLockWallpaperInfo getItem(int position) { - return mWallpapers.get(position); - } - - public long getItemId(int position) { - return position; - } - - public View getView(int position, View convertView, ViewGroup parent) { - Drawable thumb = mWallpapers.get(position).mThumb; - if (thumb == null) { - Log.e(TAG, "Error decoding thumbnail for wallpaper #" + position); - } - return createImageTileView(mLayoutInflater, position, convertView, parent, thumb); - } - } - - private static class ThemeWallpapersAdapter extends BaseAdapter implements ListAdapter { - private LayoutInflater mLayoutInflater; - private ArrayList<ThemeWallpaperInfo> mWallpapers; - - ThemeWallpapersAdapter(Activity activity, ArrayList<ThemeWallpaperInfo> wallpapers) { - mLayoutInflater = activity.getLayoutInflater(); - mWallpapers = wallpapers; - } - - public int getCount() { - return mWallpapers.size(); - } - - public ThemeWallpaperInfo getItem(int position) { - return mWallpapers.get(position); - } - - public long getItemId(int position) { - return position; - } - - public View getView(int position, View convertView, ViewGroup parent) { - Drawable thumb = mWallpapers.get(position).mThumb; - if (thumb == null) { - Log.e(TAG, "Error decoding thumbnail for wallpaper #" + position); - } - return createImageTileView(mLayoutInflater, position, convertView, parent, thumb); - } - } - - public static View createImageTileView(LayoutInflater layoutInflater, int position, - View convertView, ViewGroup parent, Drawable thumb) { - View view; - - if (convertView == null) { - view = layoutInflater.inflate(R.layout.wallpaper_picker_item, parent, false); - } else { - view = convertView; - } - - setWallpaperItemPaddingToZero((FrameLayout) view); - - ImageView image = (ImageView) view.findViewById(R.id.wallpaper_image); - - if (thumb != null) { - image.setImageDrawable(thumb); - thumb.setDither(true); - } - - return view; - } - - private static Bitmap getThemeWallpaper(Context context, String path, String pkgName, - boolean legacyTheme, boolean thumb) { - if (legacyTheme) { - return getLegacyThemeWallpaper(context, pkgName, thumb); - } - InputStream is = null; - try { - Resources res = context.getPackageManager().getResourcesForApplication(pkgName); - if (res == null) { - return null; - } - - AssetManager am = res.getAssets(); - String[] wallpapers = am.list(path); - if (wallpapers == null || wallpapers.length == 0) { - return null; - } - is = am.open(path + File.separator + wallpapers[0]); - - BitmapFactory.Options bounds = new BitmapFactory.Options(); - bounds.inJustDecodeBounds = true; - BitmapFactory.decodeStream(is, null, bounds); - if ((bounds.outWidth == -1) || (bounds.outHeight == -1)) - return null; - - int originalSize = (bounds.outHeight > bounds.outWidth) ? bounds.outHeight - : bounds.outWidth; - Point outSize; - - if (thumb) { - outSize = getDefaultThumbnailSize(context.getResources()); - } else { - outSize = getDefaultWallpaperSize(res, ((Activity) context).getWindowManager()); - } - int thumbSampleSize = (outSize.y > outSize.x) ? outSize.y : outSize.x; - - BitmapFactory.Options opts = new BitmapFactory.Options(); - opts.inSampleSize = originalSize / thumbSampleSize; - return BitmapFactory.decodeStream(is, null, opts); - } catch (IOException e) { - return null; - } catch (NameNotFoundException e) { - return null; - } catch (OutOfMemoryError e) { - return null; - } finally { - if (is != null) { - try { - is.close(); - } catch (IOException e) { - } - } - } - } - - private static Bitmap getLegacyThemeWallpaper(Context context, String pkgName, boolean thumb) { - try { - final PackageManager pm = context.getPackageManager(); - PackageInfo pi = pm.getPackageInfo(pkgName, 0); - Resources res = context.getPackageManager().getResourcesForApplication(pkgName); - - if (pi == null || res == null) { - return null; - } - int resId = pi.legacyThemeInfos[0].wallpaperResourceId; - - BitmapFactory.Options opts = new BitmapFactory.Options(); - opts.inJustDecodeBounds = true; - BitmapFactory.decodeResource(res, resId, opts); - if ((opts.outWidth == -1) || (opts.outHeight == -1)) - return null; - - int originalSize = (opts.outHeight > opts.outWidth) ? opts.outHeight - : opts.outWidth; - Point outSize; - if (thumb) { - outSize = getDefaultThumbnailSize(context.getResources()); - } else { - outSize = getDefaultWallpaperSize(res, ((Activity) context).getWindowManager()); - } - int thumbSampleSize = (outSize.y > outSize.x) ? outSize.y : outSize.x; - - opts.inJustDecodeBounds = false; - opts.inSampleSize = originalSize / thumbSampleSize; - - return BitmapFactory.decodeResource(res, resId, opts); - } catch (NameNotFoundException e) { - return null; - } catch (OutOfMemoryError e1) { - return null; - } - } -} diff --git a/src/com/android/launcher3/OnAlarmListener.java b/src/com/android/launcher3/OnAlarmListener.java new file mode 100644 index 000000000..b5ef83e83 --- /dev/null +++ b/src/com/android/launcher3/OnAlarmListener.java @@ -0,0 +1,5 @@ +package com.android.launcher3; + +public interface OnAlarmListener { + public void onAlarm(Alarm alarm); +} diff --git a/src/com/android/launcher3/OverviewSettingsPanel.java b/src/com/android/launcher3/OverviewSettingsPanel.java new file mode 100644 index 000000000..4466c15de --- /dev/null +++ b/src/com/android/launcher3/OverviewSettingsPanel.java @@ -0,0 +1,233 @@ +package com.android.launcher3; + +import android.content.res.Resources; +import android.database.Cursor; +import android.database.MatrixCursor; +import android.graphics.drawable.AnimationDrawable; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.ImageView; +import android.widget.ListView; +import com.android.launcher3.list.PinnedHeaderListView; +import com.android.launcher3.list.SettingsPinnedHeaderAdapter; + +public class OverviewSettingsPanel { + public static final String ANDROID_SETTINGS = "com.android.settings"; + public static final String ANDROID_PROTECTED_APPS = + "com.android.settings.applications.ProtectedAppsActivity"; + public static final String THEME_SETTINGS = + "com.android.settings.Settings$ThemeSettingsActivity"; + public static final int HOME_SETTINGS_POSITION = 0; + public static final int DRAWER_SETTINGS_POSITION = 1; + + private Launcher mLauncher; + private View mOverviewPanel; + private SettingsPinnedHeaderAdapter mSettingsAdapter; + private PinnedHeaderListView mListView; + private String[] mValues; + + OverviewSettingsPanel(Launcher launcher, View overviewPanel) { + mLauncher = launcher; + mOverviewPanel = overviewPanel; + } + + // One time initialization of the SettingsPinnedHeaderAdapter + public void initializeAdapter() { + // Settings pane Listview + mListView = (PinnedHeaderListView) mLauncher + .findViewById(R.id.settings_home_screen_listview); + mListView.setOverScrollMode(ListView.OVER_SCROLL_NEVER); + Resources res = mLauncher.getResources(); + String[] headers = new String[] { + res.getString(R.string.home_screen_settings), + res.getString(R.string.drawer_settings), + res.getString(R.string.app_settings)}; + + String[] values; + if(mLauncher.isGelIntegrationSupported()) { + values = new String[]{ + res.getString(R.string.home_screen_search_text), + res.getString(R.string.search_screen_left_text), + res.getString(R.string.scroll_effect_text), + res.getString(R.string.icon_labels), + res.getString(R.string.scrolling_wallpaper), + res.getString(R.string.grid_size_text)}; + } else { + values = new String[]{ + res.getString(R.string.home_screen_search_text), + res.getString(R.string.scroll_effect_text), + res.getString(R.string.icon_labels), + res.getString(R.string.scrolling_wallpaper), + res.getString(R.string.grid_size_text)}; + } + + mValues = values; + + String[] valuesDrawer = new String[] { + res.getString(R.string.scroll_effect_text), + res.getString(R.string.drawer_sorting_text), + res.getString(R.string.icon_labels)}; + + String[] valuesApp = new String[] { + res.getString(R.string.larger_icons_text), + res.getString(R.string.protected_app_settings)}; + + + mSettingsAdapter = new SettingsPinnedHeaderAdapter(mLauncher); + mSettingsAdapter.setHeaders(headers); + mSettingsAdapter.addPartition(false, true); + mSettingsAdapter.addPartition(false, true); + mSettingsAdapter.addPartition(false, true); + mSettingsAdapter.mPinnedHeaderCount = headers.length; + + mSettingsAdapter.changeCursor(0, createCursor(headers[0], values)); + mSettingsAdapter.changeCursor(1, createCursor(headers[1], valuesDrawer)); + mSettingsAdapter.changeCursor(2, createCursor(headers[2], valuesApp)); + mListView.setAdapter(mSettingsAdapter); + } + + private Cursor createCursor(String header, String[] values) { + MatrixCursor cursor = new MatrixCursor(new String[]{"_id", header}); + int count = values.length; + for (int i = 0; i < count; i++) { + cursor.addRow(new Object[]{i, values[i]}); + } + return cursor; + } + + // One time View setup + public void initializeViews() { + mOverviewPanel.setAlpha(0f); + mOverviewPanel + .setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN + | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION); + ((SlidingUpPanelLayout) mOverviewPanel) + .setPanelSlideListener(new SettingsSimplePanelSlideListener()); + + //Quick Settings Buttons + View widgetButton = mLauncher.findViewById(R.id.widget_button); + widgetButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View arg0) { + if (!mLauncher.getWorkspace().isSwitchingState()) { + mLauncher.showAllApps(true, AppsCustomizePagedView.ContentType.Widgets, true); + } + } + }); + widgetButton.setOnTouchListener(mLauncher.getHapticFeedbackTouchListener()); + + View wallpaperButton = mLauncher.findViewById(R.id.wallpaper_button); + wallpaperButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View arg0) { + if (!mLauncher.getWorkspace().isSwitchingState()) { + mLauncher.startWallpaper(); + } + } + }); + wallpaperButton.setOnTouchListener(mLauncher.getHapticFeedbackTouchListener()); + + View themesButton = mLauncher.findViewById(R.id.themes_button); + themesButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View arg0) { + if (!mLauncher.getWorkspace().isSwitchingState()) { + mLauncher.startThemeSettings(); + } + } + }); + themesButton.setOnTouchListener(mLauncher.getHapticFeedbackTouchListener()); + + View defaultScreenButton = mLauncher.findViewById(R.id.default_screen_button); + defaultScreenButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View arg0) { + if (!mLauncher.getWorkspace().isSwitchingState()) { + mLauncher.getWorkspace().onClickDefaultScreenButton(); + } + } + }); + + defaultScreenButton.setOnTouchListener(mLauncher.getHapticFeedbackTouchListener()); + + //Handle + View v = mOverviewPanel.findViewById(R.id.settings_pane_header); + ((SlidingUpPanelLayout) mOverviewPanel).setEnableDragViewTouchEvents(true); + ((SlidingUpPanelLayout) mOverviewPanel).setDragView(v); + v.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + if (((SlidingUpPanelLayout) mOverviewPanel).isExpanded()) { + ((SlidingUpPanelLayout) mOverviewPanel).collapsePane(); + } else { + ((SlidingUpPanelLayout) mOverviewPanel).expandPane(); + } + } + }); + } + + public void update() { + Resources res = mLauncher.getResources(); + View widgetButton = mOverviewPanel.findViewById(R.id.widget_button); + View wallpaperButton = mOverviewPanel + .findViewById(R.id.wallpaper_button); + View themesButton = mOverviewPanel.findViewById(R.id.themes_button); + View defaultHomePanel = mOverviewPanel.findViewById(R.id.default_screen_button); + + boolean isAllAppsVisible = mLauncher.isAllAppsVisible(); + + PagedView pagedView = !isAllAppsVisible ? mLauncher.getWorkspace() + : mLauncher.getAppsCustomizeContent(); + + defaultHomePanel.setVisibility((pagedView.getPageCount() > 1) ? + View.VISIBLE : View.GONE); + + if (mLauncher.isAllAppsVisible()) { + mSettingsAdapter.changeCursor(0, createCursor(res + .getString(R.string.home_screen_settings), new String[]{})); + } else { + mSettingsAdapter.changeCursor(0, createCursor(res + .getString(R.string.home_screen_settings), mValues)); + } + + // Make sure overview panel is drawn above apps customize and collapsed + mOverviewPanel.bringToFront(); + mOverviewPanel.invalidate(); + + ((SlidingUpPanelLayout) mOverviewPanel).setPanelHeight(isAllAppsVisible ? + res.getDimensionPixelSize(R.dimen.settings_pane_handle) + : res.getDimensionPixelSize(R.dimen.sliding_panel_padding)); + + ((SlidingUpPanelLayout) mOverviewPanel).collapsePane(); + } + + public void notifyDataSetInvalidated() { + mSettingsAdapter.notifyDataSetInvalidated(); + } + + + class SettingsSimplePanelSlideListener extends SlidingUpPanelLayout.SimplePanelSlideListener { + ImageView mAnimatedArrow; + + public SettingsSimplePanelSlideListener() { + super(); + mAnimatedArrow = (ImageView) mOverviewPanel.findViewById(R.id.settings_drag_arrow); + } + + @Override + public void onPanelCollapsed(View panel) { + mAnimatedArrow.setBackgroundResource(R.drawable.transition_arrow_reverse); + + AnimationDrawable frameAnimation = (AnimationDrawable) mAnimatedArrow.getBackground(); + frameAnimation.start(); + } + + @Override + public void onPanelExpanded(View panel) { + mAnimatedArrow.setBackgroundResource(R.drawable.transition_arrow); + + AnimationDrawable frameAnimation = (AnimationDrawable) mAnimatedArrow.getBackground(); + frameAnimation.start(); + } + } +} diff --git a/src/com/android/launcher3/PageIndicator.java b/src/com/android/launcher3/PageIndicator.java index 08e5f721a..62ea03bcc 100644 --- a/src/com/android/launcher3/PageIndicator.java +++ b/src/com/android/launcher3/PageIndicator.java @@ -16,22 +16,12 @@ package com.android.launcher3; -import android.animation.Animator; -import android.animation.AnimatorListenerAdapter; import android.animation.LayoutTransition; -import android.animation.TimeInterpolator; -import android.content.ComponentName; import android.content.Context; -import android.content.res.Configuration; -import android.content.res.Resources; import android.content.res.TypedArray; import android.util.AttributeSet; -import android.util.Log; import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; import android.widget.LinearLayout; -import com.android.launcher3.R; import java.util.ArrayList; diff --git a/src/com/android/launcher3/PageIndicatorMarker.java b/src/com/android/launcher3/PageIndicatorMarker.java index b1025d6fe..f012db74b 100644 --- a/src/com/android/launcher3/PageIndicatorMarker.java +++ b/src/com/android/launcher3/PageIndicatorMarker.java @@ -16,17 +16,11 @@ package com.android.launcher3; -import android.animation.AnimatorListenerAdapter; -import android.animation.LayoutTransition; import android.content.Context; import android.content.res.Resources; import android.util.AttributeSet; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ImageView; import android.widget.FrameLayout; -import com.android.launcher3.R; +import android.widget.ImageView; public class PageIndicatorMarker extends FrameLayout { @SuppressWarnings("unused") diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java index 6463e203d..7f145aea2 100644 --- a/src/com/android/launcher3/PagedView.java +++ b/src/com/android/launcher3/PagedView.java @@ -32,7 +32,6 @@ import android.graphics.Rect; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; -import android.support.v4.view.accessibility.AccessibilityEventCompat; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.util.Log; @@ -47,8 +46,13 @@ import android.view.ViewParent; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; import android.view.accessibility.AccessibilityNodeInfo; -import android.view.animation.*; import android.widget.Scroller; +import android.view.animation.AccelerateDecelerateInterpolator; +import android.view.animation.AccelerateInterpolator; +import android.view.animation.AnimationUtils; +import android.view.animation.DecelerateInterpolator; +import android.view.animation.Interpolator; +import android.view.animation.LinearInterpolator; import java.lang.reflect.Array; import java.util.ArrayList; @@ -120,8 +124,10 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc protected int mNextPage = INVALID_PAGE; protected int mMaxScrollX; - protected Scroller mScroller; + protected LauncherScroller mScroller; + private Interpolator mDefaultInterpolator; private VelocityTracker mVelocityTracker; + private int mPageSpacing = 0; private float mParentDownMotionX; private float mParentDownMotionY; @@ -150,12 +156,12 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc protected int mTouchState = TOUCH_STATE_REST; protected boolean mForceScreenScrolled = false; + protected OnLongClickListener mLongClickListener; protected int mTouchSlop; private int mPagingTouchSlop; private int mMaximumVelocity; - protected int mPageSpacing; protected int mPageLayoutPaddingTop; protected int mPageLayoutPaddingBottom; protected int mPageLayoutPaddingLeft; @@ -255,20 +261,16 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc private int DELETE_SLIDE_IN_SIDE_PAGE_DURATION = 250; private int DRAG_TO_DELETE_FADE_OUT_DURATION = 350; + protected boolean mEnforceRealBounds = false; // Drop to delete private View mDeleteDropTarget; - private boolean mAutoComputePageSpacing = false; - private boolean mRecomputePageSpacing = false; - // Bouncer private boolean mTopAlignPageWhenShrinkingForBouncer = false; protected final Rect mInsets = new Rect(); - protected int mFirstChildLeft; - - private Runnable mDelayedSnapToPageRunnable; + protected Runnable mDelayedSnapToPageRunnable; // Relating to the scroll and overscroll effects protected static float CAMERA_DISTANCE = 6500; @@ -296,10 +298,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PagedView, defStyle, 0); - setPageSpacing(a.getDimensionPixelSize(R.styleable.PagedView_pageSpacing, 0)); - if (mPageSpacing < 0) { - mAutoComputePageSpacing = mRecomputePageSpacing = true; - } + mPageLayoutPaddingTop = a.getDimensionPixelSize( R.styleable.PagedView_pageLayoutPaddingTop, 0); mPageLayoutPaddingBottom = a.getDimensionPixelSize( @@ -325,7 +324,8 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc protected void init() { mDirtyPageContent = new ArrayList<Boolean>(); mDirtyPageContent.ensureCapacity(32); - mScroller = new Scroller(getContext(), new ScrollInterpolator()); + mScroller = new LauncherScroller(getContext()); + setDefaultInterpolator(new ScrollInterpolator()); mCurrentPage = 0; mCenterPagesVertically = true; @@ -345,6 +345,11 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc setOnHierarchyChangeListener(this); } + protected void setDefaultInterpolator(Interpolator interpolator) { + mDefaultInterpolator = interpolator; + mScroller.setInterpolator(mDefaultInterpolator); + } + protected void onAttachedToWindow() { super.onAttachedToWindow(); @@ -460,6 +465,10 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc return new PageIndicator.PageMarkerResources(); } + /** + * Add a page change listener which will be called when a page is _finished_ listening. + * + */ public void setPageSwitchListener(PageSwitchListener pageSwitchListener) { mPageSwitchListener = pageSwitchListener; if (mPageSwitchListener != null) { @@ -524,33 +533,42 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc } scrollTo(newX, 0); mScroller.setFinalX(newX); - mScroller.forceFinished(true); + forceFinishScroller(); } /** * Called during AllApps/Home transitions to avoid unnecessary work. When that other animation - * ends, {@link #resumeScrolling()} should be called, along with - * {@link #updateCurrentPageScroll()} to correctly set the final state and re-enable scrolling. + * {@link #updateCurrentPageScroll()} should be called, to correctly set the final state and + * re-enable scrolling. */ - void pauseScrolling() { - mScroller.forceFinished(true); + void stopScrolling() { + mCurrentPage = getNextPage(); + notifyPageSwitchListener(); + forceFinishScroller(); } - /** - * Enables scrolling again. - * @see #pauseScrolling() - */ - void resumeScrolling() { + private void abortScrollerAnimation(boolean resetNextPage) { + mScroller.abortAnimation(); + // We need to clean up the next page here to avoid computeScrollHelper from + // updating current page on the pass. + if (resetNextPage) { + mNextPage = INVALID_PAGE; + } } + + private void forceFinishScroller() { + mScroller.forceFinished(true); + // We need to clean up the next page here to avoid computeScrollHelper from + // updating current page on the pass. + mNextPage = INVALID_PAGE; + } + /** * Sets the current page. */ void setCurrentPage(int currentPage) { if (!mScroller.isFinished()) { - mScroller.abortAnimation(); - // We need to clean up the next page here to avoid computeScrollHelper from - // updating current page on the pass. - mNextPage = INVALID_PAGE; + abortScrollerAnimation(true); } // don't introduce any checks like mCurrentPage == currentPage here-- if we change the // the default @@ -571,12 +589,23 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc void setRestorePage(int restorePage) { mRestorePage = restorePage; } + int getRestorePage() { + return mRestorePage; + } + /** + * Should be called whenever the page changes. In the case of a scroll, we wait until the page + * has settled. + */ protected void notifyPageSwitchListener() { if (mPageSwitchListener != null) { - mPageSwitchListener.onPageSwitch(getPageAt(mCurrentPage), mCurrentPage); + mPageSwitchListener.onPageSwitch(getPageAt(getNextPage()), getNextPage()); } + updatePageIndicator(); + } + + private void updatePageIndicator() { // Update the page indicator (when we aren't reordering) if (mPageIndicator != null && !isReordering(false)) { mPageIndicator.setActiveMarker(getNextPage()); @@ -635,7 +664,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc @Override public void scrollTo(int x, int y) { // In free scroll mode, we clamp the scrollX - if (mFreeScroll) { + if (mFreeScroll || mEnforceRealBounds) { x = Math.min(x, mFreeScrollMaxScrollX); x = Math.max(x, mFreeScrollMinScrollX); } @@ -688,6 +717,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc AccessibilityEvent.obtain(AccessibilityEvent.TYPE_VIEW_SCROLLED); ev.setItemCount(getChildCount()); ev.setFromIndex(mCurrentPage); + ev.setToIndex(getNextPage()); final int action; if (getNextPage() >= mCurrentPage) { @@ -796,16 +826,16 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc int widthSize = MeasureSpec.getSize(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); - // NOTE: We multiply by 1.5f to account for the fact that depending on the offset of the + // NOTE: We multiply by 2f to account for the fact that depending on the offset of the // viewport, we can be at most one and a half screens offset once we scale down DisplayMetrics dm = getResources().getDisplayMetrics(); - int maxSize = Math.max(dm.widthPixels, dm.heightPixels + mInsets.top + mInsets.bottom); + int maxSize = Math.max(dm.widthPixels + mInsets.left + mInsets.right, + dm.heightPixels + mInsets.top + mInsets.bottom); - int parentWidthSize, parentHeightSize; + int parentWidthSize = (int) (2f * maxSize); + int parentHeightSize = (int) (2f * maxSize); int scaledWidthSize, scaledHeightSize; if (mUseMinScale) { - parentWidthSize = (int) (1.5f * maxSize); - parentHeightSize = maxSize; scaledWidthSize = (int) (parentWidthSize / mMinScale); scaledHeightSize = (int) (parentHeightSize / mMinScale); } else { @@ -865,21 +895,17 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc childHeightMode = MeasureSpec.EXACTLY; } - childWidth = widthSize - horizontalPadding; - childHeight = heightSize - verticalPadding - mInsets.top - mInsets.bottom; + childWidth = getViewportWidth() - horizontalPadding + - mInsets.left - mInsets.right; + childHeight = getViewportHeight() - verticalPadding + - mInsets.top - mInsets.bottom; mNormalChildHeight = childHeight; - } else { childWidthMode = MeasureSpec.EXACTLY; childHeightMode = MeasureSpec.EXACTLY; - if (mUseMinScale) { - childWidth = getViewportWidth(); - childHeight = getViewportHeight(); - } else { - childWidth = widthSize - getPaddingLeft() - getPaddingRight(); - childHeight = heightSize - getPaddingTop() - getPaddingBottom(); - } + childWidth = getViewportWidth() - mInsets.left - mInsets.right; + childHeight = getViewportHeight(); } final int childWidthMeasureSpec = @@ -890,30 +916,6 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc } } setMeasuredDimension(scaledWidthSize, scaledHeightSize); - - if (childCount > 0) { - // Calculate the variable page spacing if necessary - if (mAutoComputePageSpacing && mRecomputePageSpacing) { - // The gap between pages in the PagedView should be equal to the gap from the page - // to the edge of the screen (so it is not visible in the current screen). To - // account for unequal padding on each side of the paged view, we take the maximum - // of the left/right gap and use that as the gap between each page. - int offset = (getViewportWidth() - getChildWidth(0)) / 2; - int spacing = Math.max(offset, widthSize - offset - - getChildAt(0).getMeasuredWidth()); - setPageSpacing(spacing); - mRecomputePageSpacing = false; - } - } - } - - public void setPageSpacing(int pageSpacing) { - mPageSpacing = pageSpacing; - requestLayout(); - } - - protected int getFirstChildLeft() { - return mFirstChildLeft; } @Override @@ -941,7 +943,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc int verticalPadding = getPaddingTop() + getPaddingBottom(); - int childLeft = mFirstChildLeft = offsetX + (screenWidth - getChildWidth(startIndex)) / 2; + int childLeft = offsetX + (screenWidth - getChildWidth(startIndex)) / 2; if (mPageScrolls == null || getChildCount() != mChildCountOnLastLayout) { mPageScrolls = new int[getChildCount()]; } @@ -967,14 +969,12 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc child.layout(childLeft, childTop, childLeft + child.getMeasuredWidth(), childTop + childHeight); - // We assume the left and right padding are equal, and hence center the pages - // horizontally int scrollOffset = (getViewportWidth() - childWidth) / 2; mPageScrolls[i] = childLeft - scrollOffset - offsetX; if (i != endIndex - delta) { childLeft += childWidth + scrollOffset; - int nextScrollOffset = (getViewportWidth() - getChildWidth(i + delta)) / 2; + int nextScrollOffset = (getViewportWidth() - getChildWidth(i + delta)) /2; childLeft += nextScrollOffset; } } @@ -1044,6 +1044,11 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc mFadeInAdjacentScreens = fade; } + public void setPageSpacing(int pageSpacing) { + mPageSpacing = pageSpacing; + requestLayout(); + } + protected void screenScrolled(int screenCenter) { boolean isInOverscroll = mOverScrollX < 0 || mOverScrollX > mMaxScrollX; // Apply transition effect and adjacent screen fade if enabled @@ -1136,7 +1141,6 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc // This ensures that when children are added, they get the correct transforms / alphas // in accordance with any scroll effects. mForceScreenScrolled = true; - mRecomputePageSpacing = true; updateFreescrollBounds(); invalidate(); } @@ -1254,22 +1258,22 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc @Override protected void dispatchDraw(Canvas canvas) { - int halfScreenSize = getViewportWidth() / 2; - // mOverScrollX is equal to getScrollX() when we're within the normal scroll range. - // Otherwise it is equal to the scaled overscroll position. - int screenCenter = mOverScrollX + halfScreenSize; - - if (screenCenter != mLastScreenCenter || mForceScreenScrolled) { - // set mForceScreenScrolled before calling screenScrolled so that screenScrolled can - // set it for the next frame - mForceScreenScrolled = false; - screenScrolled(screenCenter); - mLastScreenCenter = screenCenter; - } - // Find out which screens are visible; as an optimization we only call draw on them final int pageCount = getChildCount(); if (pageCount > 0) { + int halfScreenSize = getViewportWidth() / 2; + // mOverScrollX is equal to getScrollX() when we're within the normal scroll range. + // Otherwise it is equal to the scaled overscroll position. + int screenCenter = mOverScrollX + halfScreenSize; + + if (screenCenter != mLastScreenCenter || mForceScreenScrolled) { + // set mForceScreenScrolled before calling screenScrolled so that screenScrolled can + // set it for the next frame + mForceScreenScrolled = false; + screenScrolled(screenCenter); + mLastScreenCenter = screenCenter; + } + getVisiblePages(mTempVisiblePagesRange); final int leftScreen = mTempVisiblePagesRange[0]; final int rightScreen = mTempVisiblePagesRange[1]; @@ -1405,24 +1409,22 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc * Return true if a tap at (x, y) should trigger a flip to the previous page. */ protected boolean hitsPreviousPage(float x, float y) { - int offset = (getViewportWidth() - getChildWidth(mCurrentPage)) / 2; if (isLayoutRtl()) { return (x > (getViewportOffsetX() + getViewportWidth() - - offset + mPageSpacing)); + getPaddingRight() - mPageSpacing)); } - return (x < getViewportOffsetX() + offset - mPageSpacing); + return (x < getViewportOffsetX() + getPaddingLeft() + mPageSpacing); } /** * Return true if a tap at (x, y) should trigger a flip to the next page. */ protected boolean hitsNextPage(float x, float y) { - int offset = (getViewportWidth() - getChildWidth(mCurrentPage)) / 2; if (isLayoutRtl()) { - return (x < getViewportOffsetX() + offset - mPageSpacing); + return (x < getViewportOffsetX() + getPaddingLeft() + mPageSpacing); } return (x > (getViewportOffsetX() + getViewportWidth() - - offset + mPageSpacing)); + getPaddingRight() - mPageSpacing)); } /** Returns whether x and y originated within the buffered viewport */ @@ -1498,10 +1500,14 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc * being flinged. */ final int xDist = Math.abs(mScroller.getFinalX() - mScroller.getCurrX()); - final boolean finishedScrolling = (mScroller.isFinished() || xDist < mTouchSlop); + final boolean finishedScrolling = (mScroller.isFinished() || xDist < mTouchSlop / 3); + if (finishedScrolling) { mTouchState = TOUCH_STATE_REST; - mScroller.abortAnimation(); + if (!mScroller.isFinished() && !mFreeScroll) { + setCurrentPage(getNextPage()); + pageEndMoving(); + } } else { if (isTouchPointInViewportWithBuffer((int) mDownMotionX, (int) mDownMotionY)) { mTouchState = TOUCH_STATE_SCROLLING; @@ -1613,8 +1619,21 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc protected float getScrollProgress(int screenCenter, View v, int page) { final int halfScreenSize = getViewportWidth() / 2; - int totalDistance = v.getMeasuredWidth() + mPageSpacing; int delta = screenCenter - (getScrollForPage(page) + halfScreenSize); + int count = getChildCount(); + + final int totalDistance; + + int adjacentPage = page + 1; + if ((delta < 0 && !isLayoutRtl()) || (delta > 0 && isLayoutRtl())) { + adjacentPage = page - 1; + } + + if (adjacentPage < 0 || adjacentPage > count - 1) { + totalDistance = v.getMeasuredWidth() + mPageSpacing; + } else { + totalDistance = Math.abs(getScrollForPage(adjacentPage) - getScrollForPage(page)); + } float scrollProgress = delta / (totalDistance * 1.0f); scrollProgress = Math.min(scrollProgress, getMaxScrollProgress()); @@ -1637,9 +1656,15 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc return 0; } else { View child = getChildAt(index); - int scrollOffset = (getViewportWidth() - child.getMeasuredWidth()) / 2; + + int scrollOffset = 0; + LayoutParams lp = (LayoutParams) child.getLayoutParams(); + if (!lp.isFullScreenPage) { + scrollOffset = isLayoutRtl() ? getPaddingRight() : getPaddingLeft(); + } + int baselineX = mPageScrolls[index] + scrollOffset + getViewportOffsetX(); - return (int) (child.getX() - baselineX); + return (int) (child.getLeft() - baselineX); } } @@ -1712,11 +1737,11 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc } protected void enableFreeScroll() { - setEnableFreeScroll(true, -1); + setEnableFreeScroll(true); } - protected void disableFreeScroll(int snapPage) { - setEnableFreeScroll(false, snapPage); + protected void disableFreeScroll() { + setEnableFreeScroll(false); } void updateFreescrollBounds() { @@ -1730,16 +1755,10 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc } } - private void setEnableFreeScroll(boolean freeScroll, int snapPage) { + private void setEnableFreeScroll(boolean freeScroll) { mFreeScroll = freeScroll; - if (snapPage == -1) { - snapPage = getPageNearestToCenterOfScreen(); - } - - if (!mFreeScroll) { - snapToPage(snapPage); - } else { + if (mFreeScroll) { updateFreescrollBounds(); getOverviewModePages(mTempVisiblePagesRange); if (getCurrentPage() < mTempVisiblePagesRange[0]) { @@ -1799,7 +1818,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc * will be false if being flinged. */ if (!mScroller.isFinished()) { - mScroller.abortAnimation(); + abortScrollerAnimation(false); } // Remember where the motion event started @@ -1925,7 +1944,9 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc addView(mDragView, pageUnderPointIndex); onAddView(mDragView, pageUnderPointIndex); mSidePageHoverIndex = -1; - mPageIndicator.setActiveMarker(getNextPage()); + if (mPageIndicator != null) { + mPageIndicator.setActiveMarker(getNextPage()); + } } }; postDelayed(mSidePageHoverRunnable, REORDERING_SIDE_PAGE_HOVER_TIMEOUT); @@ -1985,29 +2006,31 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc snapToPageWithVelocity(finalPage, velocityX); } else { snapToDestination(); - } } else if (mTouchState == TOUCH_STATE_PREV_PAGE) { - // at this point we have not moved beyond the touch slop - // (otherwise mTouchState would be TOUCH_STATE_SCROLLING), so - // we can just page - int nextPage = Math.max(0, mCurrentPage - 1); - if (nextPage != mCurrentPage) { - snapToPage(nextPage); - } else { - snapToDestination(); } } else { if (!mScroller.isFinished()) { - mScroller.abortAnimation(); + abortScrollerAnimation(true); } float scaleX = getScaleX(); int vX = (int) (-velocityX * scaleX); int initialScrollX = (int) (getScrollX() * scaleX); + mScroller.setInterpolator(mDefaultInterpolator); mScroller.fling(initialScrollX, getScrollY(), vX, 0, Integer.MIN_VALUE, Integer.MAX_VALUE, 0, 0); invalidate(); } + } else if (mTouchState == TOUCH_STATE_PREV_PAGE) { + // at this point we have not moved beyond the touch slop + // (otherwise mTouchState would be TOUCH_STATE_SCROLLING), so + // we can just page + int nextPage = Math.max(0, mCurrentPage - 1); + if (nextPage != mCurrentPage) { + snapToPage(nextPage); + } else { + snapToDestination(); + } } else if (mTouchState == TOUCH_STATE_NEXT_PAGE) { // at this point we have not moved beyond the touch slop // (otherwise mTouchState would be TOUCH_STATE_SCROLLING), so @@ -2267,27 +2290,33 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc } protected void snapToPageImmediately(int whichPage) { - snapToPage(whichPage, PAGE_SNAP_ANIMATION_DURATION, true); + snapToPage(whichPage, PAGE_SNAP_ANIMATION_DURATION, true, null); } protected void snapToPage(int whichPage, int duration) { - snapToPage(whichPage, duration, false); + snapToPage(whichPage, duration, false, null); } - protected void snapToPage(int whichPage, int duration, boolean immediate) { + protected void snapToPage(int whichPage, int duration, TimeInterpolator interpolator) { + snapToPage(whichPage, duration, false, interpolator); + } + + protected void snapToPage(int whichPage, int duration, boolean immediate, + TimeInterpolator interpolator) { whichPage = Math.max(0, Math.min(whichPage, getPageCount() - 1)); int newX = getScrollForPage(whichPage); final int sX = mUnboundedScrollX; final int delta = newX - sX; - snapToPage(whichPage, delta, duration, immediate); + snapToPage(whichPage, delta, duration, immediate, interpolator); } protected void snapToPage(int whichPage, int delta, int duration) { - snapToPage(whichPage, delta, duration, false); + snapToPage(whichPage, delta, duration, false, null); } - protected void snapToPage(int whichPage, int delta, int duration, boolean immediate) { + protected void snapToPage(int whichPage, int delta, int duration, boolean immediate, + TimeInterpolator interpolator) { mNextPage = whichPage; View focusedChild = getFocusedChild(); if (focusedChild != null && whichPage != mCurrentPage && @@ -2306,11 +2335,18 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc } if (!mScroller.isFinished()) { - mScroller.abortAnimation(); + abortScrollerAnimation(false); } + + if (interpolator != null) { + mScroller.setInterpolator(interpolator); + } else { + mScroller.setInterpolator(mDefaultInterpolator); + } + mScroller.startScroll(mUnboundedScrollX, 0, delta, 0, duration); - notifyPageSwitchListener(); + updatePageIndicator(); // Trigger a compute() to finish switching pages if necessary if (immediate) { @@ -2469,8 +2505,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc if (mContentIsRefreshable) { // Force all scrolling-related behavior to end - mScroller.forceFinished(true); - mNextPage = INVALID_PAGE; + forceFinishScroller(); // Update all the pages syncPages(); @@ -2565,7 +2600,8 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc mDragView = getChildAt(dragViewIndex); mDragView.animate().scaleX(1.15f).scaleY(1.15f).setDuration(100).start(); mDragViewBaselineLeft = mDragView.getLeft(); - disableFreeScroll(-1); + snapToPage(getPageNearestToCenterOfScreen()); + disableFreeScroll(); onStartReordering(); return true; } @@ -2597,7 +2633,6 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc mPostReorderingPreZoomInRunnable = new Runnable() { public void run() { onCompleteRunnable.run(); - enableFreeScroll(); }; }; diff --git a/src/com/android/launcher3/PagedViewIcon.java b/src/com/android/launcher3/PagedViewIcon.java index 785725852..01e41078b 100644 --- a/src/com/android/launcher3/PagedViewIcon.java +++ b/src/com/android/launcher3/PagedViewIcon.java @@ -20,6 +20,7 @@ import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Region; +import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.util.TypedValue; import android.widget.TextView; @@ -64,17 +65,22 @@ public class PagedViewIcon extends TextView { // Ensure we are using the right text size LauncherAppState app = LauncherAppState.getInstance(); DeviceProfile grid = app.getDynamicGrid().getDeviceProfile(); - setTextSize(TypedValue.COMPLEX_UNIT_SP, grid.iconTextSize); + setTextSize(TypedValue.COMPLEX_UNIT_PX, grid.allAppsIconTextSizePx); mTextColor = getCurrentTextColor(); mIsTextVisible = mTextColor != getResources().getColor(android.R.color.transparent); } public void applyFromApplicationInfo(AppInfo info, boolean scaleUp, PagedViewIcon.PressedCallback cb) { + LauncherAppState app = LauncherAppState.getInstance(); + DeviceProfile grid = app.getDynamicGrid().getDeviceProfile(); + mIcon = info.iconBitmap; mPressedCallback = cb; - setCompoundDrawables(null, Utilities.createIconDrawable(mIcon), - null, null); + Drawable icon = Utilities.createIconDrawable(mIcon); + icon.setBounds(0, 0, grid.allAppsIconSizePx, grid.allAppsIconSizePx); + setCompoundDrawables(null, icon, null, null); + setCompoundDrawablePadding(grid.iconDrawablePaddingPx); setText(info.title); setTag(info); } diff --git a/src/com/android/launcher3/PagedViewIconCache.java b/src/com/android/launcher3/PagedViewIconCache.java index 8d8924b7e..93887ea23 100644 --- a/src/com/android/launcher3/PagedViewIconCache.java +++ b/src/com/android/launcher3/PagedViewIconCache.java @@ -16,17 +16,17 @@ package com.android.launcher3; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; - import android.appwidget.AppWidgetProviderInfo; import android.content.ComponentName; import android.content.pm.ComponentInfo; import android.content.pm.ResolveInfo; import android.graphics.Bitmap; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; + /** * Simple cache mechanism for PagedView outlines. */ diff --git a/src/com/android/launcher3/PagedViewWidget.java b/src/com/android/launcher3/PagedViewWidget.java index 45320a484..db4aeb940 100644 --- a/src/com/android/launcher3/PagedViewWidget.java +++ b/src/com/android/launcher3/PagedViewWidget.java @@ -30,8 +30,6 @@ import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; -import com.android.launcher3.R; - /** * The linear layout used strictly for the widget/wallpaper tab of the customization tray */ @@ -84,11 +82,11 @@ public class PagedViewWidget extends LinearLayout { DeviceProfile grid = app.getDynamicGrid().getDeviceProfile(); TextView name = (TextView) findViewById(R.id.widget_name); if (name != null) { - name.setTextSize(TypedValue.COMPLEX_UNIT_SP, grid.iconTextSize); + name.setTextSize(TypedValue.COMPLEX_UNIT_PX, grid.iconTextSizePx); } TextView dims = (TextView) findViewById(R.id.widget_dims); if (dims != null) { - dims.setTextSize(TypedValue.COMPLEX_UNIT_SP, grid.iconTextSize); + dims.setTextSize(TypedValue.COMPLEX_UNIT_PX, grid.iconTextSizePx); } } diff --git a/src/com/android/launcher3/PreloadReceiver.java b/src/com/android/launcher3/PreloadReceiver.java index 75e5c98bc..ca25746eb 100644 --- a/src/com/android/launcher3/PreloadReceiver.java +++ b/src/com/android/launcher3/PreloadReceiver.java @@ -19,6 +19,7 @@ package com.android.launcher3; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; +import android.os.AsyncTask; import android.text.TextUtils; import android.util.Log; @@ -39,12 +40,12 @@ public class PreloadReceiver extends BroadcastReceiver { if (LOGD) { Log.d(TAG, "workspace name: " + name + " id: " + workspaceResId); } - new Thread(new Runnable() { - @Override - public void run() { + new AsyncTask<Void, Void, Void>() { + public Void doInBackground(Void ... args) { provider.loadDefaultFavoritesIfNecessary(workspaceResId); + return null; } - }).start(); + }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void) null); } } } diff --git a/src/com/android/launcher3/RampUpScroller.java b/src/com/android/launcher3/RampUpScroller.java deleted file mode 100644 index 89eb5798e..000000000 --- a/src/com/android/launcher3/RampUpScroller.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (C) 2013 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.android.launcher3; - -import android.view.animation.AccelerateInterpolator; -import android.view.animation.AnimationUtils; -import android.view.animation.Interpolator; - -/** - * Scroller that gradually reaches a target velocity. - */ -class RampUpScroller { - private final Interpolator mInterpolator; - private final long mRampUpTime; - - private long mStartTime; - private long mDeltaTime; - private float mTargetVelocityX; - private float mTargetVelocityY; - private int mDeltaX; - private int mDeltaY; - - /** - * Creates a new ramp-up scroller that reaches full velocity after a - * specified duration. - * - * @param rampUpTime Duration before the scroller reaches target velocity. - */ - public RampUpScroller(long rampUpTime) { - mInterpolator = new AccelerateInterpolator(); - mRampUpTime = rampUpTime; - } - - /** - * Starts the scroller at the current animation time. - */ - public void start() { - mStartTime = AnimationUtils.currentAnimationTimeMillis(); - mDeltaTime = mStartTime; - } - - /** - * Computes the current scroll deltas. This usually only be called after - * starting the scroller with {@link #start()}. - * - * @see #getDeltaX() - * @see #getDeltaY() - */ - public void computeScrollDelta() { - final long currentTime = AnimationUtils.currentAnimationTimeMillis(); - final long elapsedSinceStart = currentTime - mStartTime; - final float scale; - if (elapsedSinceStart < mRampUpTime) { - scale = mInterpolator.getInterpolation((float) elapsedSinceStart / mRampUpTime); - } else { - scale = 1f; - } - - final long elapsedSinceDelta = currentTime - mDeltaTime; - mDeltaTime = currentTime; - - mDeltaX = (int) (elapsedSinceDelta * scale * mTargetVelocityX); - mDeltaY = (int) (elapsedSinceDelta * scale * mTargetVelocityY); - } - - /** - * Sets the target velocity for this scroller. - * - * @param x The target X velocity in pixels per millisecond. - * @param y The target Y velocity in pixels per millisecond. - */ - public void setTargetVelocity(float x, float y) { - mTargetVelocityX = x; - mTargetVelocityY = y; - } - - /** - * @return The target X velocity for this scroller. - */ - public float getTargetVelocityX() { - return mTargetVelocityX; - } - - /** - * @return The target Y velocity for this scroller. - */ - public float getTargetVelocityY() { - return mTargetVelocityY; - } - - /** - * The distance traveled in the X-coordinate computed by the last call to - * {@link #computeScrollDelta()}. - */ - public int getDeltaX() { - return mDeltaX; - } - - /** - * The distance traveled in the Y-coordinate computed by the last call to - * {@link #computeScrollDelta()}. - */ - public int getDeltaY() { - return mDeltaY; - } -} diff --git a/src/com/android/launcher3/ScrimView.java b/src/com/android/launcher3/ScrimView.java index 6831fe3d4..68200fe64 100644 --- a/src/com/android/launcher3/ScrimView.java +++ b/src/com/android/launcher3/ScrimView.java @@ -17,11 +17,8 @@ package com.android.launcher3; import android.content.Context; -import android.content.res.Resources; -import android.content.res.TypedArray; import android.graphics.Rect; import android.util.AttributeSet; -import android.view.View; import android.widget.FrameLayout; public class ScrimView extends FrameLayout implements Insettable { diff --git a/src/com/android/launcher3/SearchDropTargetBar.java b/src/com/android/launcher3/SearchDropTargetBar.java index 15452070c..d38c61209 100644 --- a/src/com/android/launcher3/SearchDropTargetBar.java +++ b/src/com/android/launcher3/SearchDropTargetBar.java @@ -69,6 +69,11 @@ public class SearchDropTargetBar extends FrameLayout implements DragController.D dragController.setFlingToDeleteDropTarget(mDeleteDropTarget); mInfoDropTarget.setLauncher(launcher); mDeleteDropTarget.setLauncher(launcher); + + setupQSB(launcher); + } + + public void setupQSB(Launcher launcher) { mQSBSearchBar = launcher.getQsbBar(); if (mEnableDropDownDropTargets) { mQSBSearchBarAnim = LauncherAnimUtils.ofFloat(mQSBSearchBar, "translationY", 0, @@ -188,7 +193,7 @@ public class SearchDropTargetBar extends FrameLayout implements DragController.D // Animate out the QSB search bar, and animate in the drop target bar prepareStartAnimation(mDropTargetBar); mDropTargetBarAnim.start(); - if (!mIsSearchBarHidden) { + if (!mIsSearchBarHidden || mQSBSearchBar.getAlpha() > 0f) { prepareStartAnimation(mQSBSearchBar); mQSBSearchBarAnim.start(); } @@ -204,7 +209,7 @@ public class SearchDropTargetBar extends FrameLayout implements DragController.D // Restore the QSB search bar, and animate out the drop target bar prepareStartAnimation(mDropTargetBar); mDropTargetBarAnim.reverse(); - if (!mIsSearchBarHidden) { + if (!mIsSearchBarHidden || mQSBSearchBar.getAlpha() < 1f) { prepareStartAnimation(mQSBSearchBar); mQSBSearchBarAnim.reverse(); } diff --git a/src/com/android/launcher3/ShortcutInfo.java b/src/com/android/launcher3/ShortcutInfo.java index 0998eec2b..a13aaa911 100644 --- a/src/com/android/launcher3/ShortcutInfo.java +++ b/src/com/android/launcher3/ShortcutInfo.java @@ -20,9 +20,9 @@ import android.content.ComponentName; import android.content.ContentValues; import android.content.Context; import android.content.Intent; +import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; -import android.content.pm.PackageInfo; import android.graphics.Bitmap; import android.util.Log; @@ -64,6 +64,12 @@ class ShortcutInfo extends ItemInfo { long firstInstallTime; int flags = 0; + /** + * If this shortcut is a placeholder, then intent will be a market intent for the package, and + * this will hold the original intent from the database. Otherwise, null. + */ + Intent restoredIntent; + ShortcutInfo() { itemType = LauncherSettings.BaseLauncherColumns.ITEM_TYPE_SHORTCUT; } @@ -71,7 +77,29 @@ class ShortcutInfo extends ItemInfo { protected Intent getIntent() { return intent; } - + + protected Intent getRestoredIntent() { + return restoredIntent; + } + + /** + * Overwrite placeholder data with restored data, or do nothing if this is not a placeholder. + */ + public void restore() { + if (restoredIntent != null) { + intent = restoredIntent; + restoredIntent = null; + } + } + + + ShortcutInfo(Intent intent, CharSequence title, Bitmap icon) { + this(); + this.intent = intent; + this.title = title; + mIcon = icon; + } + public ShortcutInfo(Context context, ShortcutInfo info) { super(info); title = info.title.toString(); diff --git a/src/com/android/launcher3/SlidingUpPanelLayout.java b/src/com/android/launcher3/SlidingUpPanelLayout.java new file mode 100644 index 000000000..52deeb355 --- /dev/null +++ b/src/com/android/launcher3/SlidingUpPanelLayout.java @@ -0,0 +1,1315 @@ +package com.android.launcher3; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.PixelFormat; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.os.Parcel; +import android.os.Parcelable; +import android.support.v4.view.MotionEventCompat; +import android.support.v4.view.ViewCompat; +import android.support.v4.widget.ViewDragHelper; +import android.util.AttributeSet; +import android.util.Log; +import android.view.Gravity; +import android.view.MotionEvent; +import android.view.SoundEffectConstants; +import android.view.View; +import android.view.ViewConfiguration; +import android.view.ViewGroup; +import android.view.accessibility.AccessibilityEvent; +import android.view.animation.Animation; +import android.view.animation.TranslateAnimation; + +public class SlidingUpPanelLayout extends ViewGroup { + private static final String TAG = SlidingUpPanelLayout.class.getSimpleName(); + + /** + * Default peeking out panel height + */ + private static final int DEFAULT_PANEL_HEIGHT = 68; // dp; + + /** + * Default height of the shadow above the peeking out panel + */ + private static final int DEFAULT_SHADOW_HEIGHT = 4; // dp; + + /** + * If no fade color is given by default it will fade to 80% gray. + */ + private static final int DEFAULT_FADE_COLOR = 0x99000000; + + /** + * Default Minimum velocity that will be detected as a fling + */ + private static final int DEFAULT_MIN_FLING_VELOCITY = 400; // dips per second + /** + * Default is set to false because that is how it was written + */ + private static final boolean DEFAULT_OVERLAY_FLAG = false; + /** + * Default attributes for layout + */ + private static final int[] DEFAULT_ATTRS = new int[] { + android.R.attr.gravity + }; + + /** + * Minimum velocity that will be detected as a fling + */ + private int mMinFlingVelocity = DEFAULT_MIN_FLING_VELOCITY; + + /** + * The fade color used for the panel covered by the slider. 0 = no fading. + */ + private int mCoveredFadeColor = DEFAULT_FADE_COLOR; + + /** + * Default paralax length of the main view + */ + private static final int DEFAULT_PARALAX_OFFSET = 0; + + /** + * The paint used to dim the main layout when sliding + */ + private final Paint mCoveredFadePaint = new Paint(); + + /** + * Drawable used to draw the shadow between panes. + */ + private final Drawable mShadowDrawable; + + /** + * The size of the overhang in pixels. + */ + private int mPanelHeight = -1; + + /** + * The size of the shadow in pixels. + */ + private int mShadowHeight = -1; + + /** + * Paralax offset + */ + private int mParalaxOffset = -1; + + /** + * True if the collapsed panel should be dragged up. + */ + private boolean mIsSlidingUp; + + /** + * True if a panel can slide with the current measurements + */ + private boolean mCanSlide; + + /** + * Panel overlays the windows instead of putting it underneath it. + */ + private boolean mOverlayContent = DEFAULT_OVERLAY_FLAG; + + /** + * If provided, the panel can be dragged by only this view. Otherwise, the entire panel can be + * used for dragging. + */ + private View mDragView; + + /** + * If provided, the panel can be dragged by only this view. Otherwise, the entire panel can be + * used for dragging. + */ + private int mDragViewResId = -1; + + /** + * The child view that can slide, if any. + */ + private View mSlideableView; + + /** + * The main view + */ + private View mMainView; + + /** + * Current state of the slideable view. + */ + private enum SlideState { + EXPANDED, + COLLAPSED, + ANCHORED + } + private SlideState mSlideState = SlideState.COLLAPSED; + + /** + * How far the panel is offset from its expanded position. + * range [0, 1] where 0 = expanded, 1 = collapsed. + */ + private float mSlideOffset; + + /** + * How far in pixels the slideable panel may move. + */ + private int mSlideRange; + + /** + * A panel view is locked into internal scrolling or another condition that + * is preventing a drag. + */ + private boolean mIsUnableToDrag; + + /** + * Flag indicating that sliding feature is enabled\disabled + */ + private boolean mIsSlidingEnabled; + + /** + * Flag indicating if a drag view can have its own touch events. If set + * to true, a drag view can scroll horizontally and have its own click listener. + * + * Default is set to false. + */ + private boolean mIsUsingDragViewTouchEvents; + + /** + * Threshold to tell if there was a scroll touch event. + */ + private final int mScrollTouchSlop; + + private float mInitialMotionX; + private float mInitialMotionY; + private float mAnchorPoint = 0.f; + private TranslateAnimation mAnimation; + + private PanelSlideListener mPanelSlideListener; + + private final ViewDragHelper mDragHelper; + + /** + * Stores whether or not the pane was expanded the last time it was slideable. + * If expand/collapse operations are invoked this state is modified. Used by + * instance state save/restore. + */ + private boolean mFirstLayout = true; + + private final Rect mTmpRect = new Rect(); + + /** + * Listener for monitoring events about sliding panes. + */ + public interface PanelSlideListener { + /** + * Called when a sliding pane's position changes. + * @param panel The child view that was moved + * @param slideOffset The new offset of this sliding pane within its range, from 0-1 + */ + public void onPanelSlide(View panel, float slideOffset); + /** + * Called when a sliding pane becomes slid completely collapsed. The pane may or may not + * be interactive at this point depending on if it's shown or hidden + * @param panel The child view that was slid to an collapsed position, revealing other panes + */ + public void onPanelCollapsed(View panel); + + /** + * Called when a sliding pane becomes slid completely expanded. The pane is now guaranteed + * to be interactive. It may now obscure other views in the layout. + * @param panel The child view that was slid to a expanded position + */ + public void onPanelExpanded(View panel); + + public void onPanelAnchored(View panel); + } + + /** + * No-op stubs for {@link PanelSlideListener}. If you only want to implement a subset + * of the listener methods you can extend this instead of implement the full interface. + */ + public static class SimplePanelSlideListener implements PanelSlideListener { + @Override + public void onPanelSlide(View panel, float slideOffset) { + } + @Override + public void onPanelCollapsed(View panel) { + } + @Override + public void onPanelExpanded(View panel) { + } + @Override + public void onPanelAnchored(View panel) { + } + } + + public SlidingUpPanelLayout(Context context) { + this(context, null); + } + + public SlidingUpPanelLayout(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public SlidingUpPanelLayout(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + if (attrs != null) { + TypedArray defAttrs = context.obtainStyledAttributes(attrs, DEFAULT_ATTRS); + + if (defAttrs != null) { + int gravity = defAttrs.getInt(0, Gravity.NO_GRAVITY); + if (gravity != Gravity.TOP && gravity != Gravity.BOTTOM) { + throw new IllegalArgumentException("gravity must be set to either top or bottom"); + } + mIsSlidingUp = gravity == Gravity.BOTTOM; + } + + defAttrs.recycle(); + + TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SlidingUpPanelLayout); + + if (ta != null) { + mPanelHeight = ta.getDimensionPixelSize(R.styleable.SlidingUpPanelLayout_panelHeight, -1); + mShadowHeight = ta.getDimensionPixelSize(R.styleable.SlidingUpPanelLayout_shadowHeight, -1); + mParalaxOffset = ta.getDimensionPixelSize(R.styleable.SlidingUpPanelLayout_paralaxOffset, -1); + + mMinFlingVelocity = ta.getInt(R.styleable.SlidingUpPanelLayout_flingVelocity, DEFAULT_MIN_FLING_VELOCITY); + mCoveredFadeColor = ta.getColor(R.styleable.SlidingUpPanelLayout_fadeColor, DEFAULT_FADE_COLOR); + + mDragViewResId = ta.getResourceId(R.styleable.SlidingUpPanelLayout_dragView, -1); + + mOverlayContent = ta.getBoolean(R.styleable.SlidingUpPanelLayout_overlay,DEFAULT_OVERLAY_FLAG); + } + + ta.recycle(); + } + + final float density = context.getResources().getDisplayMetrics().density; + if (mPanelHeight == -1) { + mPanelHeight = (int) (DEFAULT_PANEL_HEIGHT * density + 0.5f); + } + if (mShadowHeight == -1) { + mShadowHeight = (int) (DEFAULT_SHADOW_HEIGHT * density + 0.5f); + } + if (mParalaxOffset == -1) { + mParalaxOffset = (int) (DEFAULT_PARALAX_OFFSET * density); + } + // If the shadow height is zero, don't show the shadow + if (mShadowHeight > 0) { + if (mIsSlidingUp) { + mShadowDrawable = getResources().getDrawable(R.drawable.above_shadow); + } else { + mShadowDrawable = getResources().getDrawable(R.drawable.below_shadow); + } + + } else { + mShadowDrawable = null; + } + + setWillNotDraw(false); + + mDragHelper = ViewDragHelper.create(this, 0.5f, new DragHelperCallback()); + mDragHelper.setMinVelocity(mMinFlingVelocity * density); + + mCanSlide = true; + mIsSlidingEnabled = true; + + ViewConfiguration vc = ViewConfiguration.get(context); + mScrollTouchSlop = vc.getScaledTouchSlop(); + } + + /** + * Set the Drag View after the view is inflated + */ + @Override + protected void onFinishInflate() { + super.onFinishInflate(); + if (mDragViewResId != -1) { + mDragView = findViewById(mDragViewResId); + } + } + + /** + * Set the color used to fade the pane covered by the sliding pane out when the pane + * will become fully covered in the expanded state. + * + * @param color An ARGB-packed color value + */ + public void setCoveredFadeColor(int color) { + mCoveredFadeColor = color; + invalidate(); + } + + /** + * @return The ARGB-packed color value used to fade the fixed pane + */ + public int getCoveredFadeColor() { + return mCoveredFadeColor; + } + + /** + * Set sliding enabled flag + * @param enabled flag value + */ + public void setSlidingEnabled(boolean enabled) { + mIsSlidingEnabled = enabled; + } + + /** + * Set the collapsed panel height in pixels + * + * @param val A height in pixels + */ + public void setPanelHeight(int val) { + mPanelHeight = val; + requestLayout(); + } + + /** + * @return The current collapsed panel height + */ + public int getPanelHeight() { + return mPanelHeight; + } + + /** + * @return The current paralax offset + */ + public int getCurrentParalaxOffset() { + int offset = (int)(mParalaxOffset * (1 - mSlideOffset)); + return mIsSlidingUp ? -offset : offset; + } + + /** + * Sets the panel slide listener + * @param listener + */ + public void setPanelSlideListener(PanelSlideListener listener) { + mPanelSlideListener = listener; + } + + /** + * Set the draggable view portion. Use to null, to allow the whole panel to be draggable + * + * @param dragView A view that will be used to drag the panel. + */ + public void setDragView(View dragView) { + mDragView = dragView; + } + + /** + * Set an anchor point where the panel can stop during sliding + * + * @param anchorPoint A value between 0 and 1, determining the position of the anchor point + * starting from the top of the layout. + */ + public void setAnchorPoint(float anchorPoint) { + if (anchorPoint > 0 && anchorPoint < 1) + mAnchorPoint = anchorPoint; + } + + /** + * Sets whether or not the panel overlays the content + * @param overlayed + */ + public void setOverlayed(boolean overlayed) { + mOverlayContent = overlayed; + } + + /** + * Check if the panel is set as an overlay. + */ + public boolean isOverlayed() { + return mOverlayContent; + } + + void dispatchOnPanelSlide(View panel) { + if (mPanelSlideListener != null) { + mPanelSlideListener.onPanelSlide(panel, mSlideOffset); + } + } + + void dispatchOnPanelExpanded(View panel) { + if (mPanelSlideListener != null) { + mPanelSlideListener.onPanelExpanded(panel); + } + sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED); + } + + void dispatchOnPanelCollapsed(View panel) { + if (mPanelSlideListener != null) { + mPanelSlideListener.onPanelCollapsed(panel); + } + sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED); + } + + void dispatchOnPanelAnchored(View panel) { + if (mPanelSlideListener != null) { + mPanelSlideListener.onPanelAnchored(panel); + } + sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED); + } + + void updateObscuredViewVisibility() { + if (getChildCount() == 0) { + return; + } + final int leftBound = getPaddingLeft(); + final int rightBound = getWidth() - getPaddingRight(); + final int topBound = getPaddingTop(); + final int bottomBound = getHeight() - getPaddingBottom(); + final int left; + final int right; + final int top; + final int bottom; + if (mSlideableView != null && hasOpaqueBackground(mSlideableView)) { + left = mSlideableView.getLeft(); + right = mSlideableView.getRight(); + top = mSlideableView.getTop(); + bottom = mSlideableView.getBottom(); + } else { + left = right = top = bottom = 0; + } + View child = getChildAt(0); + final int clampedChildLeft = Math.max(leftBound, child.getLeft()); + final int clampedChildTop = Math.max(topBound, child.getTop()); + final int clampedChildRight = Math.min(rightBound, child.getRight()); + final int clampedChildBottom = Math.min(bottomBound, child.getBottom()); + final int vis; + if (clampedChildLeft >= left && clampedChildTop >= top && + clampedChildRight <= right && clampedChildBottom <= bottom) { + vis = INVISIBLE; + } else { + vis = VISIBLE; + } + child.setVisibility(vis); + } + + void setAllChildrenVisible() { + for (int i = 0, childCount = getChildCount(); i < childCount; i++) { + final View child = getChildAt(i); + if (child.getVisibility() == INVISIBLE) { + child.setVisibility(VISIBLE); + } + } + } + + private static boolean hasOpaqueBackground(View v) { + final Drawable bg = v.getBackground(); + if (bg != null) { + return bg.getOpacity() == PixelFormat.OPAQUE; + } + return false; + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + mFirstLayout = true; + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + mFirstLayout = true; + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + final int widthMode = MeasureSpec.getMode(widthMeasureSpec); + final int widthSize = MeasureSpec.getSize(widthMeasureSpec); + final int heightMode = MeasureSpec.getMode(heightMeasureSpec); + final int heightSize = MeasureSpec.getSize(heightMeasureSpec); + + if (widthMode != MeasureSpec.EXACTLY) { + throw new IllegalStateException("Width must have an exact value or MATCH_PARENT"); + } else if (heightMode != MeasureSpec.EXACTLY) { + throw new IllegalStateException("Height must have an exact value or MATCH_PARENT"); + } + + int layoutHeight = heightSize - getPaddingTop() - getPaddingBottom(); + int panelHeight = mPanelHeight; + + final int childCount = getChildCount(); + + if (childCount > 2) { + Log.e(TAG, "onMeasure: More than two child views are not supported."); + } else if (getChildAt(1).getVisibility() == GONE) { + panelHeight = 0; + } + + // We'll find the current one below. + mSlideableView = null; + mCanSlide = false; + + // First pass. Measure based on child LayoutParams width/height. + for (int i = 0; i < childCount; i++) { + final View child = getChildAt(i); + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + + int height = layoutHeight; + if (child.getVisibility() == GONE) { + lp.dimWhenOffset = false; + continue; + } + + if (i == 1) { + lp.slideable = true; + lp.dimWhenOffset = true; + mSlideableView = child; + mCanSlide = true; + } else { + if (!mOverlayContent) { + height -= panelHeight; + } + mMainView = child; + } + + int childWidthSpec; + if (lp.width == LayoutParams.WRAP_CONTENT) { + childWidthSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.AT_MOST); + } else if (lp.width == LayoutParams.MATCH_PARENT) { + childWidthSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY); + } else { + childWidthSpec = MeasureSpec.makeMeasureSpec(lp.width, MeasureSpec.EXACTLY); + } + + int childHeightSpec; + if (lp.height == LayoutParams.WRAP_CONTENT) { + childHeightSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST); + } else if (lp.height == LayoutParams.MATCH_PARENT) { + childHeightSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY); + } else { + childHeightSpec = MeasureSpec.makeMeasureSpec(lp.height, MeasureSpec.EXACTLY); + } + + child.measure(childWidthSpec, childHeightSpec); + } + + setMeasuredDimension(widthSize, heightSize); + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + final int paddingLeft = getPaddingLeft(); + final int paddingTop = getPaddingTop(); + final int slidingTop = getSlidingTop(); + + final int childCount = getChildCount(); + + if (mFirstLayout) { + switch (mSlideState) { + case EXPANDED: + mSlideOffset = mCanSlide ? 0.f : 1.f; + break; + case ANCHORED: + mSlideOffset = mCanSlide ? mAnchorPoint : 1.f; + break; + default: + mSlideOffset = 1.f; + break; + } + } + + for (int i = 0; i < childCount; i++) { + final View child = getChildAt(i); + + if (child.getVisibility() == GONE) { + continue; + } + + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + final int childHeight = child.getMeasuredHeight(); + + if (lp.slideable) { + mSlideRange = childHeight - mPanelHeight; + } + + int childTop; + if (mIsSlidingUp) { + childTop = lp.slideable ? slidingTop + (int) (mSlideRange * mSlideOffset) : paddingTop; + } else { + childTop = lp.slideable ? slidingTop - (int) (mSlideRange * mSlideOffset) : paddingTop; + if (!lp.slideable && !mOverlayContent) { + childTop += mPanelHeight; + } + } + final int childBottom = childTop + childHeight; + final int childLeft = paddingLeft; + final int childRight = childLeft + child.getMeasuredWidth(); + + child.layout(childLeft, childTop, childRight, childBottom); + } + + if (mFirstLayout) { + updateObscuredViewVisibility(); + } + + mFirstLayout = false; + } + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + // Recalculate sliding panes and their details + if (h != oldh) { + mFirstLayout = true; + } + } + + /** + * Set if the drag view can have its own touch events. If set + * to true, a drag view can scroll horizontally and have its own click listener. + * + * Default is set to false. + */ + public void setEnableDragViewTouchEvents(boolean enabled) { + mIsUsingDragViewTouchEvents = enabled; + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + final int action = MotionEventCompat.getActionMasked(ev); + + if (mAnimation != null || !mCanSlide || !mIsSlidingEnabled || (mIsUnableToDrag && action != MotionEvent.ACTION_DOWN)) { + mDragHelper.cancel(); + return super.onInterceptTouchEvent(ev); + } + + if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) { + mDragHelper.cancel(); + return false; + } + + final float x = ev.getX(); + final float y = ev.getY(); + boolean interceptTap = false; + + switch (action) { + case MotionEvent.ACTION_DOWN: { + mIsUnableToDrag = false; + mInitialMotionX = x; + mInitialMotionY = y; + if (isDragViewUnder((int) x, (int) y) && !mIsUsingDragViewTouchEvents) { + interceptTap = true; + } + break; + } + + case MotionEvent.ACTION_MOVE: { + final float adx = Math.abs(x - mInitialMotionX); + final float ady = Math.abs(y - mInitialMotionY); + final int dragSlop = mDragHelper.getTouchSlop(); + + // Handle any horizontal scrolling on the drag view. + if (mIsUsingDragViewTouchEvents) { + if (adx > mScrollTouchSlop && ady < mScrollTouchSlop) { + return super.onInterceptTouchEvent(ev); + } + // Intercept the touch if the drag view has any vertical scroll. + // onTouchEvent will determine if the view should drag vertically. + else if (ady > mScrollTouchSlop) { + interceptTap = isDragViewUnder((int) x, (int) y); + } + } + + if ((ady > dragSlop && adx > ady) || !isDragViewUnder((int) x, (int) y)) { + mDragHelper.cancel(); + mIsUnableToDrag = true; + return false; + } + break; + } + } + + final boolean interceptForDrag = mDragHelper.shouldInterceptTouchEvent(ev); + + return interceptForDrag; + } + + @Override + public boolean onTouchEvent(MotionEvent ev) { + if (!mCanSlide || !mIsSlidingEnabled || mAnimation != null) { + return super.onTouchEvent(ev); + } + + mDragHelper.processTouchEvent(ev); + + final int action = ev.getAction(); + boolean wantTouchEvents = true; + + switch (action & MotionEventCompat.ACTION_MASK) { + case MotionEvent.ACTION_DOWN: { + final float x = ev.getX(); + final float y = ev.getY(); + + //Fix to allow both SettingPanel Drag and Workspace Drag + if (mSlideState == SlideState.COLLAPSED) { + if (y < mSlideableView.getTop()) { + return false; + } + } + + mInitialMotionX = x; + mInitialMotionY = y; + break; + } + + case MotionEvent.ACTION_UP: { + final float x = ev.getX(); + final float y = ev.getY(); + final float dx = x - mInitialMotionX; + final float dy = y - mInitialMotionY; + final int slop = mDragHelper.getTouchSlop(); + View dragView = mDragView != null ? mDragView : mSlideableView; + if (dx * dx + dy * dy < slop * slop && + isDragViewUnder((int) x, (int) y)) { + dragView.playSoundEffect(SoundEffectConstants.CLICK); + if (!isExpanded() && !isAnchored()) { + expandPane(mAnchorPoint); + } else { + collapsePane(); + } + break; + } + break; + } + } + + return wantTouchEvents; + } + + private boolean isDragViewUnder(int x, int y) { + View dragView = mDragView != null ? mDragView : mSlideableView; + if (dragView == null) return false; + int[] viewLocation = new int[2]; + dragView.getLocationOnScreen(viewLocation); + int[] parentLocation = new int[2]; + this.getLocationOnScreen(parentLocation); + int screenX = parentLocation[0] + x; + int screenY = parentLocation[1] + y; + return screenX >= viewLocation[0] && screenX < viewLocation[0] + dragView.getWidth() && + screenY >= viewLocation[1] && screenY < viewLocation[1] + dragView.getHeight(); + } + + private boolean expandPane(View pane, int initialVelocity, float mSlideOffset) { + if (mFirstLayout || smoothSlideTo(mSlideOffset, initialVelocity)) { + return true; + } + return false; + } + + private boolean collapsePane(View pane, int initialVelocity) { + if (mFirstLayout || smoothSlideTo(1.f, initialVelocity)) { + return true; + } + return false; + } + + private int getSlidingTop() { + if (mSlideableView != null) { + return mIsSlidingUp + ? getMeasuredHeight() - getPaddingBottom() - mSlideableView.getMeasuredHeight() + : getPaddingTop(); + } + + return getMeasuredHeight() - getPaddingBottom(); + } + + /** + * Collapse the sliding pane if it is currently slideable. If first layout + * has already completed this will animate. + * + * @return true if the pane was slideable and is now collapsed/in the process of collapsing + */ + public boolean collapsePane() { + return collapsePane(mSlideableView, 0); + } + + /** + * Expand the sliding pane if it is currently slideable. If first layout + * has already completed this will animate. + * + * @return true if the pane was slideable and is now expanded/in the process of expading + */ + public boolean expandPane() { + return expandPane(0); + } + + /** + * Partially expand the sliding pane up to a specific offset + * + * @param mSlideOffset Value between 0 and 1, where 0 is completely expanded. + * @return true if the pane was slideable and is now expanded/in the process of expading + */ + public boolean expandPane(float mSlideOffset) { + if (!isPaneVisible()) { + showPane(); + } + return expandPane(mSlideableView, 0, mSlideOffset); + } + + /** + * Check if the layout is completely expanded. + * + * @return true if sliding panels are completely expanded + */ + public boolean isExpanded() { + return mSlideState == SlideState.EXPANDED; + } + + /** + * Check if the layout is anchored in an intermediate point. + * + * @return true if sliding panels are anchored + */ + public boolean isAnchored() { + return mSlideState == SlideState.ANCHORED; + } + + /** + * Check if the content in this layout cannot fully fit side by side and therefore + * the content pane can be slid back and forth. + * + * @return true if content in this layout can be expanded + */ + public boolean isSlideable() { + return mCanSlide; + } + + public boolean isPaneVisible() { + if (getChildCount() < 2) { + return false; + } + View slidingPane = getChildAt(1); + return slidingPane.getVisibility() == View.VISIBLE; + } + + public void showPane() { + if (getChildCount() < 2) { + return; + } + final View slidingPane = getChildAt(1); + mAnimation = new TranslateAnimation(0, 0, (mIsSlidingUp ? 1 : -1) * getPanelHeight(), 0); + mAnimation.setDuration(400); + mAnimation.setAnimationListener(new Animation.AnimationListener() { + @Override + public void onAnimationStart(Animation animation) { + slidingPane.setVisibility(View.VISIBLE); + } + + @Override + public void onAnimationEnd(Animation animation) { + requestLayout(); + mAnimation = null; + } + + @Override + public void onAnimationRepeat(Animation animation) { + } + }); + slidingPane.startAnimation(mAnimation); + } + + public void hidePane() { + if (mSlideableView == null) { + return; + } + mAnimation = new TranslateAnimation(0, 0, 0, (mIsSlidingUp ? 1 : -1) * getPanelHeight()); + mAnimation.setDuration(500); + mAnimation.setAnimationListener(new Animation.AnimationListener() { + @Override + public void onAnimationStart(Animation animation) { + + } + + @Override + public void onAnimationEnd(Animation animation) { + mSlideableView.setVisibility(View.GONE); + requestLayout(); + mAnimation = null; + } + + @Override + public void onAnimationRepeat(Animation animation) { + + } + }); + mSlideableView.startAnimation(mAnimation); + } + + private void onPanelDragged(int newTop) { + final int topBound = getSlidingTop(); + mSlideOffset = mIsSlidingUp + ? (float) (newTop - topBound) / mSlideRange + : (float) (topBound - newTop) / mSlideRange; + dispatchOnPanelSlide(mSlideableView); + + if (mParalaxOffset > 0) { + int mainViewOffset = getCurrentParalaxOffset(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + mMainView.setTranslationY(mainViewOffset); + } else { + mMainView.animate().translationY(mainViewOffset); + } + } + } + + @Override + protected boolean drawChild(Canvas canvas, View child, long drawingTime) { + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + boolean result; + final int save = canvas.save(Canvas.CLIP_SAVE_FLAG); + + boolean drawScrim = false; + + if (mCanSlide && !lp.slideable && mSlideableView != null) { + // Clip against the slider; no sense drawing what will immediately be covered, + // Unless the panel is set to overlay content + if (!mOverlayContent) { + canvas.getClipBounds(mTmpRect); + if (mIsSlidingUp) { + mTmpRect.bottom = Math.min(mTmpRect.bottom, mSlideableView.getTop()); + } else { + mTmpRect.top = Math.max(mTmpRect.top, mSlideableView.getBottom()); + } + canvas.clipRect(mTmpRect); + } + if (mSlideOffset < 1) { + drawScrim = true; + } + } + + result = super.drawChild(canvas, child, drawingTime); + canvas.restoreToCount(save); + + if (drawScrim) { + final int baseAlpha = (mCoveredFadeColor & 0xff000000) >>> 24; + final int imag = (int) (baseAlpha * (1 - mSlideOffset)); + final int color = imag << 24 | (mCoveredFadeColor & 0xffffff); + mCoveredFadePaint.setColor(color); + canvas.drawRect(mTmpRect, mCoveredFadePaint); + } + + return result; + } + + /** + * Smoothly animate mDraggingPane to the target X position within its range. + * + * @param slideOffset position to animate to + * @param velocity initial velocity in case of fling, or 0. + */ + boolean smoothSlideTo(float slideOffset, int velocity) { + if (!mCanSlide) { + // Nothing to do. + return false; + } + + final int topBound = getSlidingTop(); + int y = mIsSlidingUp + ? (int) (topBound + slideOffset * mSlideRange) + : (int) (topBound - slideOffset * mSlideRange); + + if (mDragHelper.smoothSlideViewTo(mSlideableView, mSlideableView.getLeft(), y)) { + setAllChildrenVisible(); + ViewCompat.postInvalidateOnAnimation(this); + return true; + } + return false; + } + + @Override + public void computeScroll() { + if (mDragHelper.continueSettling(true)) { + if (!mCanSlide) { + mDragHelper.abort(); + return; + } + + ViewCompat.postInvalidateOnAnimation(this); + } + } + + @Override + public void draw(Canvas c) { + super.draw(c); + + if (mSlideableView == null) { + // No need to draw a shadow if we don't have one. + return; + } + + final int right = mSlideableView.getRight(); + final int top; + final int bottom; + if (mIsSlidingUp) { + top = mSlideableView.getTop() - mShadowHeight; + bottom = mSlideableView.getTop(); + } else { + top = mSlideableView.getBottom(); + bottom = mSlideableView.getBottom() + mShadowHeight; + } + final int left = mSlideableView.getLeft(); + + if (mShadowDrawable != null) { + mShadowDrawable.setBounds(left, top, right, bottom); + mShadowDrawable.draw(c); + } + } + + /** + * Tests scrollability within child views of v given a delta of dx. + * + * @param v View to test for horizontal scrollability + * @param checkV Whether the view v passed should itself be checked for scrollability (true), + * or just its children (false). + * @param dx Delta scrolled in pixels + * @param x X coordinate of the active touch point + * @param y Y coordinate of the active touch point + * @return true if child views of v can be scrolled by delta of dx. + */ + protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) { + if (v instanceof ViewGroup) { + final ViewGroup group = (ViewGroup) v; + final int scrollX = v.getScrollX(); + final int scrollY = v.getScrollY(); + final int count = group.getChildCount(); + // Count backwards - let topmost views consume scroll distance first. + for (int i = count - 1; i >= 0; i--) { + final View child = group.getChildAt(i); + if (x + scrollX >= child.getLeft() && x + scrollX < child.getRight() && + y + scrollY >= child.getTop() && y + scrollY < child.getBottom() && + canScroll(child, true, dx, x + scrollX - child.getLeft(), + y + scrollY - child.getTop())) { + return true; + } + } + } + return checkV && ViewCompat.canScrollHorizontally(v, -dx); + } + + + @Override + protected ViewGroup.LayoutParams generateDefaultLayoutParams() { + return new LayoutParams(); + } + + @Override + protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) { + return p instanceof MarginLayoutParams + ? new LayoutParams((MarginLayoutParams) p) + : new LayoutParams(p); + } + + @Override + protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { + return p instanceof LayoutParams && super.checkLayoutParams(p); + } + + @Override + public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) { + return new LayoutParams(getContext(), attrs); + } + + @Override + protected Parcelable onSaveInstanceState() { + Parcelable superState = super.onSaveInstanceState(); + + SavedState ss = new SavedState(superState); + ss.mSlideState = mSlideState; + + return ss; + } + + @Override + protected void onRestoreInstanceState(Parcelable state) { + SavedState ss = (SavedState) state; + super.onRestoreInstanceState(ss.getSuperState()); + mSlideState = ss.mSlideState; + } + + private class DragHelperCallback extends ViewDragHelper.Callback { + + @Override + public boolean tryCaptureView(View child, int pointerId) { + if (mIsUnableToDrag) { + return false; + } + + return ((LayoutParams) child.getLayoutParams()).slideable; + } + + @Override + public void onViewDragStateChanged(int state) { + int anchoredTop = (int)(mAnchorPoint*mSlideRange); + + if (mDragHelper.getViewDragState() == ViewDragHelper.STATE_IDLE) { + if (mSlideOffset == 0) { + if (mSlideState != SlideState.EXPANDED) { + updateObscuredViewVisibility(); + dispatchOnPanelExpanded(mSlideableView); + mSlideState = SlideState.EXPANDED; + } + } else if (mSlideOffset == (float)anchoredTop/(float)mSlideRange) { + if (mSlideState != SlideState.ANCHORED) { + updateObscuredViewVisibility(); + dispatchOnPanelAnchored(mSlideableView); + mSlideState = SlideState.ANCHORED; + } + } else if (mSlideState != SlideState.COLLAPSED) { + dispatchOnPanelCollapsed(mSlideableView); + mSlideState = SlideState.COLLAPSED; + } + } + } + + @Override + public void onViewCaptured(View capturedChild, int activePointerId) { + // Make all child views visible in preparation for sliding things around + setAllChildrenVisible(); + } + + @Override + public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) { + onPanelDragged(top); + invalidate(); + } + + @Override + public void onViewReleased(View releasedChild, float xvel, float yvel) { + int top = mIsSlidingUp + ? getSlidingTop() + : getSlidingTop() - mSlideRange; + + if (mAnchorPoint != 0) { + int anchoredTop; + float anchorOffset; + if (mIsSlidingUp) { + anchoredTop = (int)(mAnchorPoint*mSlideRange); + anchorOffset = (float)anchoredTop/(float)mSlideRange; + } else { + anchoredTop = mPanelHeight - (int)(mAnchorPoint*mSlideRange); + anchorOffset = (float)(mPanelHeight - anchoredTop)/(float)mSlideRange; + } + + if (yvel > 0 || (yvel == 0 && mSlideOffset >= (1f+anchorOffset)/2)) { + top += mSlideRange; + } else if (yvel == 0 && mSlideOffset < (1f+anchorOffset)/2 + && mSlideOffset >= anchorOffset/2) { + top += mSlideRange * mAnchorPoint; + } + + } else if (yvel > 0 || (yvel == 0 && mSlideOffset > 0.5f)) { + top += mSlideRange; + } + + mDragHelper.settleCapturedViewAt(releasedChild.getLeft(), top); + invalidate(); + } + + @Override + public int getViewVerticalDragRange(View child) { + return mSlideRange; + } + + @Override + public int clampViewPositionVertical(View child, int top, int dy) { + final int topBound; + final int bottomBound; + if (mIsSlidingUp) { + topBound = getSlidingTop(); + bottomBound = topBound + mSlideRange; + } else { + bottomBound = getPaddingTop(); + topBound = bottomBound - mSlideRange; + } + + return Math.min(Math.max(top, topBound), bottomBound); + } + } + + public static class LayoutParams extends ViewGroup.MarginLayoutParams { + private static final int[] ATTRS = new int[] { + android.R.attr.layout_weight + }; + + /** + * True if this pane is the slideable pane in the layout. + */ + boolean slideable; + + /** + * True if this view should be drawn dimmed + * when it's been offset from its default position. + */ + boolean dimWhenOffset; + + Paint dimPaint; + + public LayoutParams() { + super(MATCH_PARENT, MATCH_PARENT); + } + + public LayoutParams(int width, int height) { + super(width, height); + } + + public LayoutParams(android.view.ViewGroup.LayoutParams source) { + super(source); + } + + public LayoutParams(MarginLayoutParams source) { + super(source); + } + + public LayoutParams(LayoutParams source) { + super(source); + } + + public LayoutParams(Context c, AttributeSet attrs) { + super(c, attrs); + + final TypedArray a = c.obtainStyledAttributes(attrs, ATTRS); + a.recycle(); + } + + } + + static class SavedState extends BaseSavedState { + SlideState mSlideState; + + SavedState(Parcelable superState) { + super(superState); + } + + private SavedState(Parcel in) { + super(in); + try { + mSlideState = Enum.valueOf(SlideState.class, in.readString()); + } catch (IllegalArgumentException e) { + mSlideState = SlideState.COLLAPSED; + } + } + + @Override + public void writeToParcel(Parcel out, int flags) { + super.writeToParcel(out, flags); + out.writeString(mSlideState.toString()); + } + + public static final Parcelable.Creator<SavedState> CREATOR = + new Parcelable.Creator<SavedState>() { + @Override + public SavedState createFromParcel(Parcel in) { + return new SavedState(in); + } + + @Override + public SavedState[] newArray(int size) { + return new SavedState[size]; + } + }; + } +} diff --git a/src/com/android/launcher3/SmoothPagedView.java b/src/com/android/launcher3/SmoothPagedView.java index a45dbbf6e..4e331aa2c 100644 --- a/src/com/android/launcher3/SmoothPagedView.java +++ b/src/com/android/launcher3/SmoothPagedView.java @@ -19,7 +19,6 @@ package com.android.launcher3; import android.content.Context; import android.util.AttributeSet; import android.view.animation.Interpolator; -import android.widget.Scroller; public abstract class SmoothPagedView extends PagedView { private static final float SMOOTHING_SPEED = 0.75f; @@ -52,8 +51,6 @@ public abstract class SmoothPagedView extends PagedView { } public float getInterpolation(float t) { - // _o(t) = t * t * ((tension + 1) * t + tension) - // o(t) = _o(t - 1) + 1 t -= 1.0f; return t * t * ((mTension + 1) * t + mTension) + 1.0f; } @@ -102,7 +99,7 @@ public abstract class SmoothPagedView extends PagedView { mBaseLineFlingVelocity = 2500.0f; mFlingVelocityInfluence = 0.4f; mScrollInterpolator = new OvershootInterpolator(); - mScroller = new Scroller(getContext(), mScrollInterpolator); + setDefaultInterpolator(mScrollInterpolator); } } diff --git a/src/com/android/launcher3/ThemeChangedReceiver.java b/src/com/android/launcher3/ThemeChangedReceiver.java new file mode 100644 index 000000000..c7a98c5ab --- /dev/null +++ b/src/com/android/launcher3/ThemeChangedReceiver.java @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2014 The CyanogenMod 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.android.launcher3; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; + +import static com.android.launcher3.WidgetPreviewLoader.CacheDb.DB_NAME; + +import java.io.File; +import java.util.ArrayList; + +public class ThemeChangedReceiver extends BroadcastReceiver { + private static final String EXTRA_COMPONENTS = "components"; + + public static final String MODIFIES_ICONS = "mods_icons"; + public static final String MODIFIES_FONTS = "mods_fonts"; + public static final String MODIFIES_OVERLAYS = "mods_overlays"; + + public void onReceive(Context context, Intent intent) { + // components is a string array of the components that changed + ArrayList<String> components = intent.getStringArrayListExtra(EXTRA_COMPONENTS); + if (isInterestingThemeChange(components)) { + LauncherAppState app = LauncherAppState.getInstance(); + clearWidgetPreviewCache(context); + app.recreateWidgetPreviewDb(); + app.getIconCache().flush(); + app.getModel().forceReload(); + } + } + + /** + * We consider this an "interesting" theme change if it modifies icons, overlays, or fonts. + * @param components + * @return + */ + private boolean isInterestingThemeChange(ArrayList<String> components) { + if (components != null) { + for (String component : components) { + if (component.equals(MODIFIES_ICONS) || + component.equals(MODIFIES_FONTS) || + component.equals(MODIFIES_OVERLAYS)) { + return true; + } + } + } + return false; + } + + + /** + * Normally we could use context.deleteDatabase() but this db is in cache/ so we'll + * manually delete it and the journal ourselves. + * + * @param context + */ + private void clearWidgetPreviewCache(Context context) { + File[] files = context.getCacheDir().listFiles(); + if (files != null) { + for (File f : files) { + if (!f.isDirectory() && f.getName().startsWith(DB_NAME)) f.delete(); + } + } + } +} diff --git a/src/com/android/launcher3/TransitionEffectsFragment.java b/src/com/android/launcher3/TransitionEffectsFragment.java new file mode 100644 index 000000000..88c6481d7 --- /dev/null +++ b/src/com/android/launcher3/TransitionEffectsFragment.java @@ -0,0 +1,220 @@ +package com.android.launcher3; + +import android.animation.Animator; +import android.animation.ObjectAnimator; +import android.animation.ValueAnimator; +import android.app.Fragment; +import android.content.Context; +import android.content.Intent; +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Color; +import android.graphics.drawable.AnimationDrawable; +import android.os.Bundle; +import android.util.DisplayMetrics; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.ScrollView; +import android.widget.TextView; +import com.android.launcher3.settings.SettingsProvider; + +public class TransitionEffectsFragment extends Fragment { + public static final String PAGE_OR_DRAWER_SCROLL_SELECT = "pageOrDrawer"; + public static final String SELECTED_TRANSITION_EFFECT = "selectedTransitionEffect"; + public static final String TRANSITION_EFFECTS_FRAGMENT = "transitionEffectsFragment"; + ImageView mTransitionIcon; + ListView mListView; + View mCurrentSelection; + ScrollView mScrollView; + + String[] mTransitionStates; + TypedArray mTransitionDrawables; + String mCurrentState; + int mCurrentPosition; + boolean mPageOrDrawer; + String mSettingsProviderValue; + int mPreferenceValue; + + OnClickListener mSettingsItemListener = new OnClickListener() { + + @Override + public void onClick(View v) { + if (mCurrentPosition == (Integer) v.getTag()) { + return; + } + mCurrentPosition = (Integer) v.getTag(); + mCurrentState = mTransitionStates[mCurrentPosition]; + + setCleared(mCurrentSelection); + setSelected(v); + mCurrentSelection = v; + + new Thread(new Runnable() { + public void run() { + mTransitionIcon.post(new Runnable() { + public void run() { + setImageViewToEffect(); + } + }); + } + }).start(); + + ((TransitionsArrayAdapter) mListView.getAdapter()).notifyDataSetChanged(); + } + }; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View v = inflater.inflate(R.layout.settings_transitions_screen, container, false); + + mPageOrDrawer = getArguments().getBoolean(PAGE_OR_DRAWER_SCROLL_SELECT); + + mSettingsProviderValue = mPageOrDrawer ? + SettingsProvider.SETTINGS_UI_DRAWER_SCROLLING_TRANSITION_EFFECT + : SettingsProvider.SETTINGS_UI_HOMESCREEN_SCROLLING_TRANSITION_EFFECT; + mPreferenceValue = mPageOrDrawer ? R.string.preferences_interface_drawer_scrolling_transition_effect + : R.string.preferences_interface_homescreen_scrolling_transition_effect; + + mTransitionIcon = (ImageView) v.findViewById(R.id.settings_transition_image); + mListView = (ListView) v.findViewById(R.id.settings_transitions_list); + mScrollView = (ScrollView) v.findViewById(R.id.scroll_view); + TextView title = (TextView) v.findViewById(R.id.transition_effect_title); + title.setText(getResources().getString(R.string.scroll_effect_text)); + LinearLayout titleLayout = (LinearLayout) v.findViewById(R.id.transition_title); + titleLayout.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + setEffect(); + } + }); + + String[] titles = getResources().getStringArray( + R.array.transition_effect_entries); + mListView.setAdapter(new TransitionsArrayAdapter(getActivity(), + R.layout.settings_pane_list_item, titles)); + + mTransitionStates = getResources().getStringArray( + R.array.transition_effect_values); + mTransitionDrawables = getResources().obtainTypedArray( + R.array.transition_effect_drawables); + + mCurrentState = SettingsProvider.getString(getActivity(), + mSettingsProviderValue, mPreferenceValue); + mCurrentPosition = mapEffectToPosition(mCurrentState); + + mListView.setSelection(mCurrentPosition); + + return v; + } + + public void setEffect() { + ((Launcher) getActivity()).setTransitionEffect(mPageOrDrawer, mCurrentState); + } + + private int mapEffectToPosition(String effect) { + int length = mTransitionStates.length; + for (int i = 0; i < length; i++) { + if (effect.equals(mTransitionStates[i])) { + return i; + } + } + return -1; + } + + private void setImageViewToEffect() { + mTransitionIcon.setBackgroundResource(mTransitionDrawables + .getResourceId(mCurrentPosition, R.drawable.transition_none)); + + AnimationDrawable frameAnimation = (AnimationDrawable) mTransitionIcon.getBackground(); + frameAnimation.start(); + } + + private void setSelected(View v) { + v.setBackgroundColor(Color.WHITE); + TextView t = (TextView) v.findViewById(R.id.item_name); + t.setTextColor(getResources().getColor(R.color.settings_bg_color)); + } + + private void setCleared(View v) { + v.setBackgroundColor(getResources().getColor(R.color.settings_bg_color)); + TextView t = (TextView) v.findViewById(R.id.item_name); + t.setTextColor(Color.WHITE); + } + + @Override + public Animator onCreateAnimator(int transit, boolean enter, int nextAnim) { + if (enter) { + DisplayMetrics displaymetrics = new DisplayMetrics(); + getActivity().getWindowManager().getDefaultDisplay().getMetrics(displaymetrics); + int width = displaymetrics.widthPixels; + final ObjectAnimator anim = ObjectAnimator.ofFloat(this, "translationX", width, 0); + + final View darkPanel = ((Launcher) getActivity()).getDarkPanel(); + darkPanel.setVisibility(View.VISIBLE); + ObjectAnimator anim2 = ObjectAnimator.ofFloat( + darkPanel , "alpha", 0.0f, 0.3f); + anim2.start(); + + anim.addListener(new Animator.AnimatorListener() { + @Override + public void onAnimationStart(Animator arg0) {} + @Override + public void onAnimationRepeat(Animator arg0) {} + @Override + public void onAnimationEnd(Animator arg0) { + darkPanel.setVisibility(View.GONE); + setImageViewToEffect(); + } + @Override + public void onAnimationCancel(Animator arg0) {} + }); + + return anim; + } else { + return super.onCreateAnimator(transit, enter, nextAnim); + } + } + + private class TransitionsArrayAdapter extends ArrayAdapter<String> { + Context mContext; + String[] titles; + + public TransitionsArrayAdapter(Context context, int textViewResourceId, + String[] objects) { + super(context, textViewResourceId, objects); + + mContext = context; + titles = objects; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + LayoutInflater inflater = (LayoutInflater) mContext + .getSystemService(Context.LAYOUT_INFLATER_SERVICE); + convertView = inflater.inflate(R.layout.settings_pane_list_item, + parent, false); + TextView textView = (TextView) convertView + .findViewById(R.id.item_name); + textView.setText(titles[position]); + // Set Selected State + if (position == mCurrentPosition) { + mCurrentSelection = convertView; + setSelected(mCurrentSelection); + } + + convertView.setOnClickListener(mSettingsItemListener); + convertView.setTag(position); + return convertView; + } + } +} diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java index 282e47516..cbc978585 100644 --- a/src/com/android/launcher3/Utilities.java +++ b/src/com/android/launcher3/Utilities.java @@ -21,14 +21,21 @@ import android.content.ActivityNotFoundException; import android.content.Context; import android.content.Intent; import android.content.res.Resources; -import android.graphics.*; +import android.graphics.Bitmap; +import android.graphics.BlurMaskFilter; +import android.graphics.Canvas; +import android.graphics.ColorMatrix; +import android.graphics.ColorMatrixColorFilter; +import android.graphics.Matrix; +import android.graphics.Paint; +import android.graphics.PaintFlagsDrawFilter; +import android.graphics.Rect; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.PaintDrawable; import android.util.DisplayMetrics; import android.util.Log; import android.view.View; -import android.widget.TextView; import android.widget.Toast; import java.util.ArrayList; @@ -36,7 +43,7 @@ import java.util.ArrayList; /** * Various utilities shared amongst the Launcher's classes. */ -final class Utilities { +public final class Utilities { private static final String TAG = "Launcher.Utilities"; private static int sIconWidth = -1; @@ -51,8 +58,6 @@ final class Utilities { private static final Rect sOldBounds = new Rect(); private static final Canvas sCanvas = new Canvas(); - private static Typeface sTypeface; - static { sCanvas.setDrawFilter(new PaintFlagsDrawFilter(Paint.DITHER_FLAG, Paint.FILTER_BITMAP_FLAG)); @@ -60,6 +65,12 @@ final class Utilities { static int sColors[] = { 0xffff0000, 0xff00ff00, 0xff0000ff }; static int sColorIndex = 0; + + // To turn on these properties, type + // adb shell setprop log.tag.PROPERTY_NAME [VERBOSE | SUPPRESS] + static final String FORCE_ENABLE_ROTATION_PROPERTY = "launcher_force_rotate"; + public static boolean sForceEnableRotation = isPropertyEnabled(FORCE_ENABLE_ROTATION_PROPERTY); + /** * Returns a FastBitmapDrawable with the icon, accurately sized. */ @@ -77,6 +88,16 @@ final class Utilities { icon.setBounds(0, 0, sIconTextureWidth, sIconTextureHeight); } + private static boolean isPropertyEnabled(String propertyName) { + return Log.isLoggable(propertyName, Log.VERBOSE); + } + + public static boolean isRotationEnabled(Context c) { + boolean enableRotation = sForceEnableRotation || + c.getResources().getBoolean(R.bool.allow_rotation); + return enableRotation; + } + /** * Returns a bitmap suitable for the all apps view. Used to convert pre-ICS * icon bitmaps that are stored in the database (which were 74x74 pixels at hdpi size) @@ -103,15 +124,10 @@ final class Utilities { } } - static Bitmap createIconBitmap(Drawable icon, Context context) { - return createIconBitmap(icon, context, null, null, null, 1f); - } - /** * Returns a bitmap suitable for the all apps view. */ - static Bitmap createIconBitmap(Drawable icon, Context context, Drawable iconBack, - Drawable iconMask, Drawable iconUpon, float scale) { + public static Bitmap createIconBitmap(Drawable icon, Context context) { synchronized (sCanvas) { // we share the statics :-( if (sIconWidth == -1) { initStatics(context); @@ -148,7 +164,7 @@ final class Utilities { int textureWidth = sIconTextureWidth; int textureHeight = sIconTextureHeight; - Bitmap bitmap = Bitmap.createBitmap(textureWidth, textureHeight, + final Bitmap bitmap = Bitmap.createBitmap(textureWidth, textureHeight, Bitmap.Config.ARGB_8888); final Canvas canvas = sCanvas; canvas.setBitmap(bitmap); @@ -169,29 +185,7 @@ final class Utilities { sOldBounds.set(icon.getBounds()); icon.setBounds(left, top, left+width, top+height); - canvas.save(); - canvas.scale(scale, scale, width / 2, height/2); icon.draw(canvas); - canvas.restore(); - if (iconMask != null) { - iconMask.setBounds(icon.getBounds()); - ((BitmapDrawable) iconMask).getPaint().setXfermode( - new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); - iconMask.draw(canvas); - } - if (iconBack != null) { - canvas.setBitmap(null); - Bitmap finalBitmap = Bitmap.createBitmap(textureWidth, textureHeight, - Bitmap.Config.ARGB_8888); - canvas.setBitmap(finalBitmap); - iconBack.setBounds(icon.getBounds()); - iconBack.draw(canvas); - canvas.drawBitmap(bitmap, null, icon.getBounds(), null); - bitmap = finalBitmap; - } - if (iconUpon != null) { - iconUpon.draw(canvas); - } icon.setBounds(sOldBounds); canvas.setBitmap(null); @@ -224,27 +218,6 @@ final class Utilities { } /** - * Generates the default icon typeface for use in icons. - * - * @param familyName May be null. The name of the font family. - * @param style The style (normal, bold, italic) of the typeface. e.g. NORMAL, BOLD, ITALIC, BOLD_ITALIC - */ - static void generateTypeface(String familyName, int style) { - sTypeface = Typeface.create(familyName, style); - } - - /** - * Applies the default icon typeface to a textview. - * - * @param textView View to apply typeface to. - */ - static void applyTypeface(TextView textView) { - if (sTypeface != null) { - textView.setTypeface(sTypeface); - } - } - - /** * Given a coordinate relative to the descendant, find the coordinate in a parent view's * coordinates. * diff --git a/src/com/android/launcher3/WallpaperChangedReceiver.java b/src/com/android/launcher3/WallpaperChangedReceiver.java new file mode 100644 index 000000000..2d5612f12 --- /dev/null +++ b/src/com/android/launcher3/WallpaperChangedReceiver.java @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2013 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.android.launcher3; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; + +public class WallpaperChangedReceiver extends BroadcastReceiver { + public void onReceive(Context context, Intent data) { + LauncherAppState.setApplicationContext(context.getApplicationContext()); + LauncherAppState appState = LauncherAppState.getInstance(); + appState.onWallpaperChanged(); + } +} diff --git a/src/com/android/launcher3/WidgetPreviewLoader.java b/src/com/android/launcher3/WidgetPreviewLoader.java index 07b4f6f0a..3db0b51ad 100644 --- a/src/com/android/launcher3/WidgetPreviewLoader.java +++ b/src/com/android/launcher3/WidgetPreviewLoader.java @@ -4,11 +4,13 @@ import android.appwidget.AppWidgetProviderInfo; import android.content.ComponentName; import android.content.ContentValues; import android.content.Context; +import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.res.Resources; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteDiskIOException; import android.database.sqlite.SQLiteOpenHelper; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; @@ -100,6 +102,7 @@ class BitmapFactoryOptionsCache extends SoftReferenceThreadLocal<BitmapFactory.O public class WidgetPreviewLoader { static final String TAG = "WidgetPreviewLoader"; + static final String ANDROID_INCREMENTAL_VERSION_NAME_KEY = "android.incremental.version"; private int mPreviewBitmapWidth; private int mPreviewBitmapHeight; @@ -147,6 +150,26 @@ public class WidgetPreviewLoader { mDb = app.getWidgetPreviewCacheDb(); mLoadedPreviews = new HashMap<String, WeakReference<Bitmap>>(); mUnusedBitmaps = new ArrayList<SoftReference<Bitmap>>(); + + SharedPreferences sp = context.getSharedPreferences( + LauncherAppState.getSharedPreferencesKey(), Context.MODE_PRIVATE); + final String lastVersionName = sp.getString(ANDROID_INCREMENTAL_VERSION_NAME_KEY, null); + final String versionName = android.os.Build.VERSION.INCREMENTAL; + if (!versionName.equals(lastVersionName)) { + // clear all the previews whenever the system version changes, to ensure that previews + // are up-to-date for any apps that might have been updated with the system + clearDb(); + + SharedPreferences.Editor editor = sp.edit(); + editor.putString(ANDROID_INCREMENTAL_VERSION_NAME_KEY, versionName); + editor.commit(); + } + } + + public void recreateDb() { + LauncherAppState app = LauncherAppState.getInstance(); + app.recreateWidgetPreviewDb(); + mDb = app.getWidgetPreviewCacheDb(); } public void setPreviewSize(int previewWidth, int previewHeight, @@ -331,7 +354,20 @@ public class WidgetPreviewLoader { preview.compress(Bitmap.CompressFormat.PNG, 100, stream); values.put(CacheDb.COLUMN_PREVIEW_BITMAP, stream.toByteArray()); values.put(CacheDb.COLUMN_SIZE, mSize); - db.insert(CacheDb.TABLE_NAME, null, values); + try { + db.insert(CacheDb.TABLE_NAME, null, values); + } catch (SQLiteDiskIOException e) { + recreateDb(); + } + } + + private void clearDb() { + SQLiteDatabase db = mDb.getWritableDatabase(); + // Delete everything + try { + db.delete(CacheDb.TABLE_NAME, null, null); + } catch (SQLiteDiskIOException e) { + } } public static void removePackageFromDb(final CacheDb cacheDb, final String packageName) { @@ -341,13 +377,17 @@ public class WidgetPreviewLoader { new AsyncTask<Void, Void, Void>() { public Void doInBackground(Void ... args) { SQLiteDatabase db = cacheDb.getWritableDatabase(); - db.delete(CacheDb.TABLE_NAME, - CacheDb.COLUMN_NAME + " LIKE ? OR " + - CacheDb.COLUMN_NAME + " LIKE ?", // SELECT query - new String[] { - WIDGET_PREFIX + packageName + "/%", - SHORTCUT_PREFIX + packageName + "/%"} // args to SELECT query - ); + try { + db.delete(CacheDb.TABLE_NAME, + CacheDb.COLUMN_NAME + " LIKE ? OR " + + CacheDb.COLUMN_NAME + " LIKE ?", // SELECT query + new String[] { + WIDGET_PREFIX + packageName + "/%", + SHORTCUT_PREFIX + packageName + "/%" + } // args to SELECT query + ); + } catch (SQLiteDiskIOException e) { + } synchronized(sInvalidPackages) { sInvalidPackages.remove(packageName); } @@ -360,9 +400,12 @@ public class WidgetPreviewLoader { new AsyncTask<Void, Void, Void>() { public Void doInBackground(Void ... args) { SQLiteDatabase db = cacheDb.getWritableDatabase(); - db.delete(CacheDb.TABLE_NAME, - CacheDb.COLUMN_NAME + " = ? ", // SELECT query - new String[] { objectName }); // args to SELECT query + try { + db.delete(CacheDb.TABLE_NAME, + CacheDb.COLUMN_NAME + " = ? ", // SELECT query + new String[] { objectName }); // args to SELECT query + } catch (SQLiteDiskIOException e) { + } return null; } }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void) null); @@ -374,14 +417,20 @@ public class WidgetPreviewLoader { CacheDb.COLUMN_SIZE + " = ?"; } SQLiteDatabase db = mDb.getReadableDatabase(); - Cursor result = db.query(CacheDb.TABLE_NAME, - new String[] { CacheDb.COLUMN_PREVIEW_BITMAP }, // cols to return - mCachedSelectQuery, // select query - new String[] { name, mSize }, // args to select query - null, - null, - null, - null); + Cursor result; + try { + result = db.query(CacheDb.TABLE_NAME, + new String[] { CacheDb.COLUMN_PREVIEW_BITMAP }, // cols to return + mCachedSelectQuery, // select query + new String[] { name, mSize }, // args to select query + null, + null, + null, + null); + } catch (SQLiteDiskIOException e) { + recreateDb(); + return null; + } if (result.getCount() > 0) { result.moveToFirst(); byte[] blob = result.getBlob(0); diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java index 37bd8aa73..7e3584115 100644 --- a/src/com/android/launcher3/Workspace.java +++ b/src/com/android/launcher3/Workspace.java @@ -22,6 +22,7 @@ import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.LayoutTransition; import android.animation.ObjectAnimator; +import android.animation.PropertyValuesHolder; import android.animation.TimeInterpolator; import android.animation.ValueAnimator; import android.animation.ValueAnimator.AnimatorUpdateListener; @@ -30,7 +31,6 @@ import android.appwidget.AppWidgetHostView; import android.appwidget.AppWidgetProviderInfo; import android.content.ComponentName; import android.content.Context; -import android.content.Intent; import android.content.SharedPreferences; import android.content.res.Resources; import android.content.res.TypedArray; @@ -43,6 +43,7 @@ import android.graphics.Rect; import android.graphics.Region.Op; import android.graphics.drawable.Drawable; import android.net.Uri; +import android.os.AsyncTask; import android.os.IBinder; import android.os.Parcelable; import android.support.v4.view.ViewCompat; @@ -55,6 +56,8 @@ import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.accessibility.AccessibilityManager; +import android.view.animation.Animation; +import android.view.animation.AnimationUtils; import android.view.animation.DecelerateInterpolator; import android.view.animation.Interpolator; import android.widget.TextView; @@ -62,6 +65,7 @@ import android.widget.TextView; import com.android.launcher3.FolderIcon.FolderRingAnimator; import com.android.launcher3.Launcher.CustomContentCallbacks; import com.android.launcher3.LauncherSettings.Favorites; +import com.android.launcher3.backup.BackupProtos; import com.android.launcher3.settings.SettingsProvider; import java.util.ArrayList; @@ -87,6 +91,9 @@ public class Workspace extends SmoothPagedView private static final int CHILDREN_OUTLINE_FADE_OUT_DURATION = 375; private static final int CHILDREN_OUTLINE_FADE_IN_DURATION = 100; + protected static final int SNAP_OFF_EMPTY_SCREEN_DURATION = 400; + protected static final int FADE_EMPTY_SCREEN_DURATION = 150; + private static final int BACKGROUND_FADE_OUT_DURATION = 350; private static final int ADJACENT_SCREEN_DROP_DURATION = 300; private static final int FLING_THRESHOLD_VELOCITY = 500; @@ -119,14 +126,15 @@ public class Workspace extends SmoothPagedView private ShortcutAndWidgetContainer mDragSourceInternal; private static boolean sAccessibilityEnabled; - // The screen ids used for the empty screens always present to the left/right. - private final static long EXTRA_EMPTY_SCREEN_LEFT_ID = -201; - private final static long EXTRA_EMPTY_SCREEN_RIGHT_ID = -202; + // The screen id used for the empty screen always present to the right. + private final static long EXTRA_EMPTY_SCREEN_ID = -201; private final static long CUSTOM_CONTENT_SCREEN_ID = -301; private HashMap<Long, CellLayout> mWorkspaceScreens = new HashMap<Long, CellLayout>(); private ArrayList<Long> mScreenOrder = new ArrayList<Long>(); + private Runnable mRemoveEmptyScreenRunnable; + /** * CellInfo for the cell that is currently being dragged */ @@ -177,7 +185,6 @@ public class Workspace extends SmoothPagedView private SpringLoadedDragController mSpringLoadedDragController; private float mSpringLoadedShrinkFactor; private float mOverviewModeShrinkFactor; - private int mOverviewModePageOffset; // State variable that indicates whether the pages are small (ie when you're // in all apps or customize mode) @@ -206,7 +213,12 @@ public class Workspace extends SmoothPagedView private boolean mWorkspaceFadeInAdjacentScreens; WallpaperOffsetInterpolator mWallpaperOffset; + private boolean mScrollWallpaper; + private boolean mWallpaperIsLiveWallpaper; + private int mNumPagesForWallpaperParallax; + private float mLastSetWallpaperOffsetSteps = 0; + private Runnable mDelayedResizeRunnable; private Point mDisplaySize = new Point(); @@ -214,7 +226,7 @@ public class Workspace extends SmoothPagedView // Variables relating to the creation of user folders by hovering shortcuts over shortcuts private static final int FOLDER_CREATION_TIMEOUT = 0; - private static final int REORDER_TIMEOUT = 250; + public static final int REORDER_TIMEOUT = 350; private final Alarm mFolderCreationAlarm = new Alarm(); private final Alarm mReorderAlarm = new Alarm(); private FolderRingAnimator mDragFolderRingAnimator = null; @@ -325,16 +337,17 @@ public class Workspace extends SmoothPagedView mLauncher = (Launcher) context; final Resources res = getResources(); + mFadeInAdjacentScreens = false; mWallpaperManager = WallpaperManager.getInstance(context); + LauncherAppState app = LauncherAppState.getInstance(); + DeviceProfile grid = app.getDynamicGrid().getDeviceProfile(); TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.Workspace, defStyle, 0); mSpringLoadedShrinkFactor = res.getInteger(R.integer.config_workspaceSpringLoadShrinkPercentage) / 100.0f; - mOverviewModeShrinkFactor = - res.getInteger(R.integer.config_workspaceOverviewShrinkPercentage) / 100.0f; - mOverviewModePageOffset = res.getDimensionPixelSize(R.dimen.overview_mode_page_offset); + mOverviewModeShrinkFactor = grid.getOverviewModeScale(); mCameraDistance = res.getInteger(R.integer.config_cameraDistance); mDefaultPage = a.getInt(R.styleable.Workspace_defaultScreen, 1); mDefaultScreenId = SettingsProvider.getLongCustomDefault(context, @@ -354,6 +367,14 @@ public class Workspace extends SmoothPagedView @Override public void setInsets(Rect insets) { mInsets.set(insets); + + CellLayout customScreen = getScreenWithId(CUSTOM_CONTENT_SCREEN_ID); + if (customScreen != null) { + View customContent = customScreen.getShortcutsAndWidgets().getChildAt(0); + if (customContent instanceof Insettable) { + ((Insettable) customContent).setInsets(mInsets); + } + } } // estimate the size of a widget with spans hSpan, vSpan. return MAX_VALUE for each @@ -399,7 +420,7 @@ public class Workspace extends SmoothPagedView @Override public void run() { if (mIsDragOccuring) { - addExtraEmptyScreensOnDrag(); + addExtraEmptyScreenOnDrag(); } } }); @@ -414,11 +435,6 @@ public class Workspace extends SmoothPagedView InstallShortcutReceiver.disableAndFlushInstallQueue(getContext()); UninstallShortcutReceiver.disableAndFlushUninstallQueue(getContext()); - // Disable all layout transitions before removing left extra pages to ensure that we don't get - // the transition animations competing with us changing the scroll when we remove it - disableLayoutTransitions(); - removeExtraEmptyScreens(); - enableLayoutTransitions(); mDragSourceInternal = null; mLauncher.onInteractionEnd(); } @@ -438,9 +454,7 @@ public class Workspace extends SmoothPagedView setClipToPadding(false); setChildrenDrawnWithCacheEnabled(true); - // This is a bit of a hack to account for the fact that we translate the workspace - // up a bit, and still need to draw the background covering the whole screen. - setMinScale(mOverviewModeShrinkFactor - 0.2f); + setMinScale(mOverviewModeShrinkFactor); setupLayoutTransition(); final Resources res = getResources(); @@ -456,6 +470,9 @@ public class Workspace extends SmoothPagedView mMaxDistanceForFolderCreation = (0.55f * grid.iconSizePx); mFlingThresholdVelocity = (int) (FLING_THRESHOLD_VELOCITY * mDensity); + + // Set the wallpaper dimensions when Launcher starts up + setWallpaperDimension(); } private void setupLayoutTransition() { @@ -550,7 +567,7 @@ public class Workspace extends SmoothPagedView public long insertNewWorkspaceScreenBeforeEmptyScreen(long screenId) { // Find the index to insert this view into. If the empty screen exists, then // insert it before that. - int insertIndex = mScreenOrder.indexOf(EXTRA_EMPTY_SCREEN_RIGHT_ID); + int insertIndex = mScreenOrder.indexOf(EXTRA_EMPTY_SCREEN_ID); if (insertIndex < 0) { insertIndex = mScreenOrder.size(); } @@ -562,6 +579,10 @@ public class Workspace extends SmoothPagedView } public long insertNewWorkspaceScreen(long screenId, int insertIndex) { + // Log to disk + Launcher.addDumpLog(TAG, "11683562 - insertNewWorkspaceScreen(): " + screenId + + " at index: " + insertIndex, true); + if (mWorkspaceScreens.containsKey(screenId)) { throw new RuntimeException("Screen id " + screenId + " already exists!"); } @@ -585,9 +606,10 @@ public class Workspace extends SmoothPagedView return screenId; } - public void createCustomContentPage() { + public void createCustomContentContainer() { CellLayout customScreen = (CellLayout) mLauncher.getLayoutInflater().inflate(R.layout.workspace_screen, null); + customScreen.disableBackground(); mWorkspaceScreens.put(CUSTOM_CONTENT_SCREEN_ID, customScreen); mScreenOrder.add(0, CUSTOM_CONTENT_SCREEN_ID); @@ -598,7 +620,7 @@ public class Workspace extends SmoothPagedView addFullScreenPage(customScreen); // Update the custom content hint - mLauncher.updateCustomContentHintVisibility(); + mLauncher.getLauncherClings().updateCustomContentHintVisibility(); if (mRestorePage != INVALID_RESTORE_PAGE) { mRestorePage = mRestorePage + 1; } else { @@ -624,7 +646,7 @@ public class Workspace extends SmoothPagedView mCustomContentCallbacks = null; // Update the custom content hint - mLauncher.updateCustomContentHintVisibility(); + mLauncher.getLauncherClings().updateCustomContentHintVisibility(); if (mRestorePage != INVALID_RESTORE_PAGE) { mRestorePage = mRestorePage - 1; } else { @@ -648,6 +670,12 @@ public class Workspace extends SmoothPagedView if (customContent instanceof Insettable) { ((Insettable)customContent).setInsets(mInsets); } + + // Verify that the child is removed from any existing parent. + if (customContent.getParent() instanceof ViewGroup) { + ViewGroup parent = (ViewGroup) customContent.getParent(); + parent.removeView(customContent); + } customScreen.removeAllViews(); customScreen.addViewToCellLayout(customContent, 0, 0, lp, true); mCustomContentDescription = description; @@ -655,89 +683,172 @@ public class Workspace extends SmoothPagedView mCustomContentCallbacks = callbacks; } - public void addExtraEmptyScreensOnDrag() { - boolean addLeftScreen = true; - boolean addRightScreen = true; + public void addExtraEmptyScreenOnDrag() { + // Log to disk + Launcher.addDumpLog(TAG, "11683562 - addExtraEmptyScreenOnDrag()", true); + + boolean lastChildOnScreen = false; + boolean childOnFinalScreen = false; + + // Cancel any pending removal of empty screen + mRemoveEmptyScreenRunnable = null; if (mDragSourceInternal != null) { if (mDragSourceInternal.getChildCount() == 1) { - CellLayout cl = (CellLayout) mDragSourceInternal.getParent(); - addLeftScreen = indexOfChild(cl) != 0; - addRightScreen = indexOfChild(cl) != getChildCount() - 1; + lastChildOnScreen = true; + } + CellLayout cl = (CellLayout) mDragSourceInternal.getParent(); + if (indexOfChild(cl) == getChildCount() - 1) { + childOnFinalScreen = true; } } - if (addLeftScreen && !mWorkspaceScreens.containsKey(EXTRA_EMPTY_SCREEN_LEFT_ID)) { - insertNewWorkspaceScreen(EXTRA_EMPTY_SCREEN_LEFT_ID, 0); - setCurrentPage(getCurrentPage() + 1); + // If this is the last item on the final screen + if (lastChildOnScreen && childOnFinalScreen) { + return; } - if (addRightScreen && !mWorkspaceScreens.containsKey(EXTRA_EMPTY_SCREEN_RIGHT_ID)) { - insertNewWorkspaceScreen(EXTRA_EMPTY_SCREEN_RIGHT_ID); + if (!mWorkspaceScreens.containsKey(EXTRA_EMPTY_SCREEN_ID)) { + insertNewWorkspaceScreen(EXTRA_EMPTY_SCREEN_ID); } } public boolean addExtraEmptyScreen() { - if (!mWorkspaceScreens.containsKey(EXTRA_EMPTY_SCREEN_RIGHT_ID)) { - insertNewWorkspaceScreen(EXTRA_EMPTY_SCREEN_RIGHT_ID); + // Log to disk + Launcher.addDumpLog(TAG, "11683562 - addExtraEmptyScreen()", true); + + if (!mWorkspaceScreens.containsKey(EXTRA_EMPTY_SCREEN_ID)) { + insertNewWorkspaceScreen(EXTRA_EMPTY_SCREEN_ID); return true; } return false; } - public void removeExtraEmptyScreenLeft() { - if (hasExtraEmptyScreenLeft()) { - CellLayout cl = mWorkspaceScreens.get(EXTRA_EMPTY_SCREEN_LEFT_ID); - mWorkspaceScreens.remove(EXTRA_EMPTY_SCREEN_LEFT_ID); - mScreenOrder.remove(EXTRA_EMPTY_SCREEN_LEFT_ID); - setCurrentPage(mCurrentPage - 1); - removeView(cl); - } - } + private void convertFinalScreenToEmptyScreenIfNecessary() { + // Log to disk + Launcher.addDumpLog(TAG, "11683562 - convertFinalScreenToEmptyScreenIfNecessary()", true); - public void removeExtraEmptyScreenRight() { - if (hasExtraEmptyScreenRight()) { - CellLayout cl = mWorkspaceScreens.get(EXTRA_EMPTY_SCREEN_RIGHT_ID); - mWorkspaceScreens.remove(EXTRA_EMPTY_SCREEN_RIGHT_ID); - mScreenOrder.remove(EXTRA_EMPTY_SCREEN_RIGHT_ID); - removeView(cl); + if (hasExtraEmptyScreen() || mScreenOrder.size() == 0) return; + long finalScreenId = mScreenOrder.get(mScreenOrder.size() - 1); + + if (finalScreenId == CUSTOM_CONTENT_SCREEN_ID) return; + CellLayout finalScreen = mWorkspaceScreens.get(finalScreenId); + + // If the final screen is empty, convert it to the extra empty screen + if (finalScreen.getShortcutsAndWidgets().getChildCount() == 0 && + !finalScreen.isDropPending()) { + mWorkspaceScreens.remove(finalScreenId); + mScreenOrder.remove(finalScreenId); + + // if this is the last non-custom content screen, convert it to the empty screen + mWorkspaceScreens.put(EXTRA_EMPTY_SCREEN_ID, finalScreen); + mScreenOrder.add(EXTRA_EMPTY_SCREEN_ID); + + // Update the model if we have changed any screens + mLauncher.getModel().updateWorkspaceScreenOrder(mLauncher, mScreenOrder); + Launcher.addDumpLog(TAG, "11683562 - extra empty screen: " + finalScreenId, true); } } - public void removeExtraEmptyScreens() { - removeExtraEmptyScreenLeft(); - removeExtraEmptyScreenRight(); + public void removeExtraEmptyScreen(final boolean animate, final Runnable onComplete) { + removeExtraEmptyScreen(animate, onComplete, 0, false); } - public boolean hasExtraEmptyScreenLeft() { - return mWorkspaceScreens.containsKey(EXTRA_EMPTY_SCREEN_LEFT_ID) && getChildCount() - numCustomPages() > 1; - } + public void removeExtraEmptyScreen(final boolean animate, final Runnable onComplete, + final int delay, final boolean stripEmptyScreens) { + // Log to disk + Launcher.addDumpLog(TAG, "11683562 - removeExtraEmptyScreen()", true); + if (delay > 0) { + postDelayed(new Runnable() { + @Override + public void run() { + removeExtraEmptyScreen(animate, onComplete, 0, stripEmptyScreens); + } + + }, delay); + return; + } - public boolean hasExtraEmptyScreenRight() { - return mWorkspaceScreens.containsKey(EXTRA_EMPTY_SCREEN_RIGHT_ID) && getChildCount() - numCustomPages() > 1; + convertFinalScreenToEmptyScreenIfNecessary(); + if (hasExtraEmptyScreen()) { + int emptyIndex = mScreenOrder.indexOf(EXTRA_EMPTY_SCREEN_ID); + if (getNextPage() == emptyIndex) { + snapToPage(getNextPage() - 1, SNAP_OFF_EMPTY_SCREEN_DURATION); + fadeAndRemoveEmptyScreen(SNAP_OFF_EMPTY_SCREEN_DURATION, FADE_EMPTY_SCREEN_DURATION, + onComplete, stripEmptyScreens); + } else { + fadeAndRemoveEmptyScreen(0, FADE_EMPTY_SCREEN_DURATION, + onComplete, stripEmptyScreens); + } + return; + } else if (stripEmptyScreens) { + // If we're not going to strip the empty screens after removing + // the extra empty screen, do it right away. + stripEmptyScreens(); + } + + if (onComplete != null) { + onComplete.run(); + } } - public boolean hasExtraEmptyScreens() { - return hasExtraEmptyScreenLeft() || hasExtraEmptyScreenRight(); + private void fadeAndRemoveEmptyScreen(int delay, int duration, final Runnable onComplete, + final boolean stripEmptyScreens) { + // Log to disk + // XXX: Do we need to update LM workspace screens below? + Launcher.addDumpLog(TAG, "11683562 - fadeAndRemoveEmptyScreen()", true); + PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 0f); + PropertyValuesHolder bgAlpha = PropertyValuesHolder.ofFloat("backgroundAlpha", 0f); + + final CellLayout cl = mWorkspaceScreens.get(EXTRA_EMPTY_SCREEN_ID); + + mRemoveEmptyScreenRunnable = new Runnable() { + @Override + public void run() { + if (hasExtraEmptyScreen()) { + mWorkspaceScreens.remove(EXTRA_EMPTY_SCREEN_ID); + mScreenOrder.remove(EXTRA_EMPTY_SCREEN_ID); + removeView(cl); + if (stripEmptyScreens) { + stripEmptyScreens(); + } + } + } + }; + + ObjectAnimator oa = ObjectAnimator.ofPropertyValuesHolder(cl, alpha, bgAlpha); + oa.setDuration(duration); + oa.setStartDelay(delay); + oa.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + if (mRemoveEmptyScreenRunnable != null) { + mRemoveEmptyScreenRunnable.run(); + } + if (onComplete != null) { + onComplete.run(); + } + } + }); + oa.start(); } - public int numExtraEmptyScreens() { - return (hasExtraEmptyScreenLeft() ? 1 : 0) + (hasExtraEmptyScreenRight() ? 1 : 0); + public boolean hasExtraEmptyScreen() { + int nScreens = getChildCount(); + nScreens = nScreens - numCustomPages(); + return mWorkspaceScreens.containsKey(EXTRA_EMPTY_SCREEN_ID) && nScreens > 1; } - public long commitExtraEmptyScreen(long screenId) { - int index = getPageIndexForScreenId(screenId); - CellLayout cl = mWorkspaceScreens.get(screenId); - mWorkspaceScreens.remove(screenId); - mScreenOrder.remove(screenId); + public long commitExtraEmptyScreen() { + // Log to disk + Launcher.addDumpLog(TAG, "11683562 - commitExtraEmptyScreen()", true); + int index = getPageIndexForScreenId(EXTRA_EMPTY_SCREEN_ID); + CellLayout cl = mWorkspaceScreens.get(EXTRA_EMPTY_SCREEN_ID); + mWorkspaceScreens.remove(EXTRA_EMPTY_SCREEN_ID); + mScreenOrder.remove(EXTRA_EMPTY_SCREEN_ID); long newId = LauncherAppState.getLauncherProvider().generateNewScreenId(); mWorkspaceScreens.put(newId, cl); - - if (screenId == EXTRA_EMPTY_SCREEN_LEFT_ID) { - mScreenOrder.add(numCustomPages(), newId); - } else { - mScreenOrder.add(newId); - } + mScreenOrder.add(newId); // Update the page indicator marker if (getPageIndicator() != null) { @@ -782,6 +893,14 @@ public class Workspace extends SmoothPagedView } public void stripEmptyScreens() { + // Log to disk + Launcher.addDumpLog(TAG, "11683562 - stripEmptyScreens()", true); + + if (mLauncher.isWorkspaceLoading()) { + // Don't strip empty screens if the workspace is still loading + Launcher.addDumpLog(TAG, " - workspace loading, skip", true); + return; + } if (isPageMoving()) { mStripScreensOnPageStopMoving = true; return; @@ -802,6 +921,7 @@ public class Workspace extends SmoothPagedView int pageShift = 0; for (Long id: removeScreens) { + Launcher.addDumpLog(TAG, "11683562 - removing id: " + id, true); CellLayout cl = mWorkspaceScreens.get(id); mWorkspaceScreens.remove(id); mScreenOrder.remove(id); @@ -813,8 +933,9 @@ public class Workspace extends SmoothPagedView removeView(cl); } else { // if this is the last non-custom content screen, convert it to the empty screen - mWorkspaceScreens.put(EXTRA_EMPTY_SCREEN_RIGHT_ID, cl); - mScreenOrder.add(EXTRA_EMPTY_SCREEN_RIGHT_ID); + mRemoveEmptyScreenRunnable = null; + mWorkspaceScreens.put(EXTRA_EMPTY_SCREEN_ID, cl); + mScreenOrder.add(EXTRA_EMPTY_SCREEN_ID); } } @@ -864,6 +985,8 @@ public class Workspace extends SmoothPagedView */ void addInScreen(View child, long container, long screenId, int x, int y, int spanX, int spanY, boolean insert, boolean computeXYFromRank) { + //Reload settings + reloadSettings(); if (container == LauncherSettings.Favorites.CONTAINER_DESKTOP) { if (getScreenWithId(screenId) == null) { Log.e(TAG, "Skipping child, screenId " + screenId + " not found"); @@ -872,7 +995,7 @@ public class Workspace extends SmoothPagedView return; } } - if (screenId == EXTRA_EMPTY_SCREEN_LEFT_ID || screenId == EXTRA_EMPTY_SCREEN_RIGHT_ID) { + if (screenId == EXTRA_EMPTY_SCREEN_ID) { // This should never happen throw new RuntimeException("Screen id should not be EXTRA_EMPTY_SCREEN_ID"); } @@ -921,7 +1044,9 @@ public class Workspace extends SmoothPagedView } // Get the canonical child id to uniquely represent this view in this screen - int childId = LauncherModel.getCellLayoutChildId(container, screenId, x, y, spanX, spanY); + ItemInfo info = (ItemInfo) child.getTag(); + int childId = mLauncher.getViewIdForItem(info); + boolean markCellsAsOccupied = !(child instanceof Folder); if (!layout.addViewToCellLayout(child, insert ? 0 : -1, childId, lp, markCellsAsOccupied)) { // TODO: This branch occurs when the workspace is adding views @@ -1115,6 +1240,10 @@ public class Workspace extends SmoothPagedView mDelayedResizeRunnable = null; } + if (mDelayedSnapToPageRunnable != null) { + mDelayedSnapToPageRunnable.run(); + mDelayedSnapToPageRunnable = null; + } if (mStripScreensOnPageStopMoving) { stripEmptyScreens(); mStripScreensOnPageStopMoving = false; @@ -1124,16 +1253,18 @@ public class Workspace extends SmoothPagedView @Override protected void notifyPageSwitchListener() { super.notifyPageSwitchListener(); - Launcher.setScreen(mCurrentPage); + Launcher.setScreen(getNextPage()); - if (hasCustomContent() && getNextPage() == 0 && !mCustomContentShowing) { + int ccIndex = getPageIndexForScreenId(CUSTOM_CONTENT_SCREEN_ID); + if (hasCustomContent() && getNextPage() == ccIndex && !mCustomContentShowing) { mCustomContentShowing = true; + if (mCustomContentCallbacks != null) { mCustomContentCallbacks.onShow(); mCustomContentShowTime = System.currentTimeMillis(); mLauncher.updateVoiceButtonProxyVisible(false); } - } else if (hasCustomContent() && getNextPage() != 0 && mCustomContentShowing) { + } else if (hasCustomContent() && getNextPage() != ccIndex && mCustomContentShowing) { mCustomContentShowing = false; if (mCustomContentCallbacks != null) { mCustomContentCallbacks.onHide(); @@ -1151,10 +1282,44 @@ public class Workspace extends SmoothPagedView } protected void setWallpaperDimension() { - String spKey = WallpaperCropActivity.getSharedPreferencesKey(); - SharedPreferences sp = mLauncher.getSharedPreferences(spKey, Context.MODE_PRIVATE); - WallpaperPickerActivity.suggestWallpaperDimension(mLauncher.getResources(), - sp, mLauncher.getWindowManager(), mWallpaperManager); + new AsyncTask<Void, Void, Void>() { + public Void doInBackground(Void ... args) { + String spKey = WallpaperCropActivity.getSharedPreferencesKey(); + SharedPreferences sp = + mLauncher.getSharedPreferences(spKey, Context.MODE_MULTI_PROCESS); + LauncherWallpaperPickerActivity.suggestWallpaperDimension(mLauncher.getResources(), + sp, mLauncher.getWindowManager(), mWallpaperManager); + return null; + } + }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void) null); + } + + protected void snapToPage(int whichPage, Runnable r) { + snapToPage(whichPage, SLOW_PAGE_SNAP_ANIMATION_DURATION, r); + } + + @Override + protected void snapToPage(int whichPage, int delta, int duration, boolean immediate, + TimeInterpolator interpolator) { + super.snapToPage(whichPage, delta, duration, immediate, interpolator); + + // Trigger onCustomContentLaunch if we have just snapped to the custom page. + int customPageIndex = getPageIndexForScreenId(CUSTOM_CONTENT_SCREEN_ID); + if (hasCustomContent() && whichPage == customPageIndex && !mCustomContentShowing) { + if(!isInOverviewMode()) { + mCustomContentShowing = true; + // Start Google Now and register the gesture to return to Trebuchet + mLauncher.onCustomContentLaunch(); + } + } + } + + protected void snapToPage(int whichPage, int duration, Runnable r) { + if (mDelayedSnapToPageRunnable != null) { + mDelayedSnapToPageRunnable.run(); + } + mDelayedSnapToPageRunnable = r; + snapToPage(whichPage, duration); } protected void snapToScreenId(long screenId, Runnable r) { @@ -1228,9 +1393,11 @@ public class Workspace extends SmoothPagedView } // Exclude the leftmost page - int firstIndex = numCustomPages() + (hasExtraEmptyScreenLeft() ? 1 : 0); - // Exclude the last extra empty screen - int lastIndex = getChildCount() - 1 - (hasExtraEmptyScreenRight() ? 1 : 0); + int emptyExtraPages = numEmptyScreensToIgnore(); + int firstIndex = numCustomPages(); + // Exclude the last extra empty screen (if we have > MIN_PARALLAX_PAGE_SPAN pages) + int lastIndex = getChildCount() - 1 - emptyExtraPages; + if (isLayoutRtl()) { int temp = firstIndex; firstIndex = lastIndex; @@ -1245,16 +1412,21 @@ public class Workspace extends SmoothPagedView // TODO: do different behavior if it's a live wallpaper? // Sometimes the left parameter of the pages is animated during a layout transition; // this parameter offsets it to keep the wallpaper from animating as well - int offsetForLayoutTransitionAnimation = isLayoutRtl() ? - getPageAt(getChildCount() - 1).getLeft() - getFirstChildLeft() : 0; int adjustedScroll = - getScrollX() - firstPageScrollX - offsetForLayoutTransitionAnimation; + getScrollX() - firstPageScrollX - getLayoutTransitionOffsetForPage(0); float offset = Math.min(1, adjustedScroll / (float) scrollRange); offset = Math.max(0, offset); // Don't use up all the wallpaper parallax until you have at least // MIN_PARALLAX_PAGE_SPAN pages int numScrollingPages = getNumScreensExcludingEmptyAndCustom(); - int parallaxPageSpan = Math.max(MIN_PARALLAX_PAGE_SPAN, numScrollingPages - 1); + int parallaxPageSpan; + if (mWallpaperIsLiveWallpaper) { + parallaxPageSpan = numScrollingPages - 1; + } else { + parallaxPageSpan = Math.max(MIN_PARALLAX_PAGE_SPAN, numScrollingPages - 1); + } + mNumPagesForWallpaperParallax = parallaxPageSpan; + // On RTL devices, push the wallpaper offset to the right if we don't have enough // pages (ie if numScrollingPages < MIN_PARALLAX_PAGE_SPAN) int padding = isLayoutRtl() ? parallaxPageSpan - numScrollingPages + 1 : 0; @@ -1262,8 +1434,17 @@ public class Workspace extends SmoothPagedView } } + private int numEmptyScreensToIgnore() { + int numScrollingPages = getChildCount() - numCustomPages(); + if (numScrollingPages >= MIN_PARALLAX_PAGE_SPAN && hasExtraEmptyScreen()) { + return 1; + } else { + return 0; + } + } + private int getNumScreensExcludingEmptyAndCustom() { - int numScrollingPages = getChildCount() - numExtraEmptyScreens() - numCustomPages(); + int numScrollingPages = getChildCount() - numEmptyScreensToIgnore() - numCustomPages(); return numScrollingPages; } @@ -1289,7 +1470,11 @@ public class Workspace extends SmoothPagedView private void setWallpaperOffsetSteps() { // Set wallpaper offset steps (1 / (number of screens - 1)) - mWallpaperManager.setWallpaperOffsetSteps(1.0f / (getChildCount() - 1), 1.0f); + float xOffset = 1.0f / mNumPagesForWallpaperParallax; + if (xOffset != mLastSetWallpaperOffsetSteps) { + mWallpaperManager.setWallpaperOffsetSteps(xOffset, 1.0f); + mLastSetWallpaperOffsetSteps = xOffset; + } } public void setFinalX(float x) { @@ -1430,18 +1615,12 @@ public class Workspace extends SmoothPagedView mState == State.NORMAL && !mIsSwitchingState && !isInOverscroll) { - for (int i = 0; i < getChildCount(); i++) { + for (int i = numCustomPages(); i < getChildCount(); i++) { CellLayout child = (CellLayout) getChildAt(i); if (child != null) { float scrollProgress = getScrollProgress(screenCenter, child, i); float alpha = 1 - Math.abs(scrollProgress); child.getShortcutsAndWidgets().setAlpha(alpha); - if (!mIsDragOccuring && !mShowOutlines) { - child.setBackgroundAlphaMultiplier( - backgroundAlphaInterpolator(Math.abs(scrollProgress))); - } else { - child.setBackgroundAlphaMultiplier(1f); - } } } } @@ -1584,7 +1763,7 @@ public class Workspace extends SmoothPagedView cl.setOverscrollTransformsDirty(true); } } else { - if (mOverscrollTransformsSet) { + if (mOverscrollTransformsSet && getChildCount() > 0) { mOverscrollTransformsSet = false; ((CellLayout) getChildAt(0)).resetOverscrollTransforms(); ((CellLayout) getChildAt(getChildCount() - 1)).resetOverscrollTransforms(); @@ -1631,6 +1810,31 @@ public class Workspace extends SmoothPagedView } else { mWallpaperOffset.syncWithScroll(); } + + // Update wallpaper dimensions if they were changed since last onResume + // (we also always set the wallpaper dimensions in the constructor) + if (LauncherAppState.getInstance().hasWallpaperChangedSinceLastCheck()) { + setWallpaperDimension(); + } + mWallpaperIsLiveWallpaper = mWallpaperManager.getWallpaperInfo() != null; + // Force the wallpaper offset steps to be set again, because another app might have changed + // them + mLastSetWallpaperOffsetSteps = 0f; + + moveAwayFromCustomContentIfRequired(); + } + + public void moveAwayFromCustomContentIfRequired() { + // Never resume to the custom page if GEL integration is enabled. + int customPageIndex = getPageIndexForScreenId(CUSTOM_CONTENT_SCREEN_ID); + // mCustomContentShowing can be lost if the Activity is recreated, + // So make sure it is set to the right value. + mCustomContentShowing = mCustomContentShowing + || (customPageIndex == getCurrentPage() + && hasCustomContent()); + if (mCustomContentShowing && mLauncher.isGelIntegrationEnabled()) { + moveToScreen((customPageIndex + 1), true); + } } @Override @@ -1640,6 +1844,8 @@ public class Workspace extends SmoothPagedView mWallpaperOffset.jumpToFinal(); } super.onLayout(changed, left, top, right, bottom); + + moveAwayFromCustomContentIfRequired(); } @Override @@ -1900,7 +2106,7 @@ public class Workspace extends SmoothPagedView mDefaultScreenId = getScreenIdForPageIndex(getPageNearestToCenterOfScreen()); - exitOverviewMode(getPageNearestToCenterOfScreen(), true); + updateDefaultScreenButton(); SettingsProvider.get(mLauncher).edit() .putLong(SettingsProvider.SETTINGS_UI_HOMESCREEN_DEFAULT_SCREEN_ID, mDefaultScreenId) @@ -1972,6 +2178,9 @@ public class Workspace extends SmoothPagedView } private void enableOverviewMode(boolean enable, int snapPage, boolean animated) { + //Check to see if Settings need to taken + reloadSettings(); + State finalState = Workspace.State.OVERVIEW; if (!enable) { finalState = Workspace.State.NORMAL; @@ -1993,14 +2202,32 @@ public class Workspace extends SmoothPagedView } int getOverviewModeTranslationY() { - int childHeight = getNormalChildHeight(); + LauncherAppState app = LauncherAppState.getInstance(); + DeviceProfile grid = app.getDynamicGrid().getDeviceProfile(); + Rect overviewBar = grid.getOverviewModeButtonBarRect(); + + int availableHeight = getViewportHeight(); + int scaledHeight = (int) (mOverviewModeShrinkFactor * getNormalChildHeight()); + int offsetFromTopEdge = (availableHeight - scaledHeight) / 2; + int offsetToCenterInOverview = (availableHeight - mInsets.top - overviewBar.height() + - scaledHeight) / 2; + + return -offsetFromTopEdge + mInsets.top + offsetToCenterInOverview; + } + + float getOverviewModeScaleY() { + float childHeight = getNormalChildHeight(); int viewPortHeight = getViewportHeight(); - int scaledChildHeight = (int) (mOverviewModeShrinkFactor * childHeight); - int offset = (viewPortHeight - scaledChildHeight) / 2; - int offsetDelta = mOverviewModePageOffset - offset + mInsets.top; + Resources res = getResources(); + int top = res.getDimensionPixelSize(R.dimen.overview_panel_top_padding); + top += res.getDimensionPixelSize(R.dimen.sliding_panel_padding); + top += res.getDimensionPixelSize(R.dimen.overview_scaling_padding); - return offsetDelta; + float scaledChildHeight = viewPortHeight - top; + + float scale = scaledChildHeight / childHeight; + return scale; } boolean shouldVoiceButtonProxyBeVisible() { @@ -2069,16 +2296,16 @@ public class Workspace extends SmoothPagedView mNewScale = 1.0f; if (oldStateIsOverview) { - disableFreeScroll(snapPage); - } else if (stateIsOverview) { - enableFreeScroll(); + disableFreeScroll(); + } else if (stateIsOverview){ + updateFreescrollBounds(); } if (state != State.NORMAL) { if (stateIsSpringLoaded) { mNewScale = mSpringLoadedShrinkFactor; } else if (stateIsOverview) { - mNewScale = mOverviewModeShrinkFactor; + mNewScale = getOverviewModeScaleY(); } else if (stateIsSmall){ mNewScale = mOverviewModeShrinkFactor - 0.3f; } @@ -2096,11 +2323,23 @@ public class Workspace extends SmoothPagedView duration = getResources().getInteger(R.integer.config_appsCustomizeWorkspaceShrinkTime); } + if (snapPage == -1) { + snapPage = getPageNearestToCenterOfScreen(); + } + snapToPage(snapPage, duration, mZoomInInterpolator); + for (int i = 0; i < getChildCount(); i++) { final CellLayout cl = (CellLayout) getChildAt(i); - boolean isCurrentPage = (i == getNextPage()); + boolean isCurrentPage = (i == snapPage); float initialAlpha = cl.getShortcutsAndWidgets().getAlpha(); - float finalAlpha = stateIsSmall ? 0f : 1f; + float finalAlpha; + if (stateIsSmall) { + finalAlpha = 0f; + } else if (stateIsNormal && mWorkspaceFadeInAdjacentScreens) { + finalAlpha = (i == snapPage || i < numCustomPages()) ? 1f : 0f; + } else { + finalAlpha = 1f; + } if (stateIsOverview) { cl.setVisibility(VISIBLE); @@ -2146,6 +2385,7 @@ public class Workspace extends SmoothPagedView final View searchBar = mLauncher.getQsbBar(); final View overviewPanel = mLauncher.getOverviewPanel(); final View hotseat = mLauncher.getHotseat(); + final View pageIndicator = getPageIndicator(); if (animated) { anim.setDuration(duration); LauncherViewPropertyAnimator scale = new LauncherViewPropertyAnimator(this); @@ -2188,36 +2428,43 @@ public class Workspace extends SmoothPagedView } } } - ObjectAnimator pageIndicatorAlpha = null; - if (getPageIndicator() != null) { - pageIndicatorAlpha = ObjectAnimator.ofFloat(getPageIndicator(), "alpha", - finalHotseatAndPageIndicatorAlpha); - } - ObjectAnimator hotseatAlpha = ObjectAnimator.ofFloat(hotseat, "alpha", - finalHotseatAndPageIndicatorAlpha); - ObjectAnimator searchBarAlpha = null; - if (mShowSearchBar) { - searchBarAlpha = ObjectAnimator.ofFloat(searchBar, - "alpha", finalSearchBarAlpha); + Animator pageIndicatorAlpha = null; + if (pageIndicator != null) { + pageIndicatorAlpha = new LauncherViewPropertyAnimator(pageIndicator) + .alpha(finalHotseatAndPageIndicatorAlpha).withLayer(); + pageIndicatorAlpha.addListener(new AlphaUpdateListener(pageIndicator)); + } else { + // create a dummy animation so we don't need to do null checks later + pageIndicatorAlpha = ValueAnimator.ofFloat(0, 0); } - ObjectAnimator overviewPanelAlpha = ObjectAnimator.ofFloat(overviewPanel, - "alpha", finalOverviewPanelAlpha); - overviewPanelAlpha.addListener(new AlphaUpdateListener(overviewPanel)); + Animator hotseatAlpha = new LauncherViewPropertyAnimator(hotseat) + .alpha(finalHotseatAndPageIndicatorAlpha).withLayer(); hotseatAlpha.addListener(new AlphaUpdateListener(hotseat)); + + Animator searchBarAlpha = new LauncherViewPropertyAnimator(searchBar) + .alpha(finalSearchBarAlpha).withLayer(); if (mShowSearchBar) searchBarAlpha.addListener(new AlphaUpdateListener(searchBar)); + Animator overviewPanelAlpha = new LauncherViewPropertyAnimator(overviewPanel) + .alpha(finalOverviewPanelAlpha).withLayer(); + overviewPanelAlpha.addListener(new AlphaUpdateListener(overviewPanel)); + if (workspaceToOverview) { + pageIndicatorAlpha.setInterpolator(new DecelerateInterpolator(2)); hotseatAlpha.setInterpolator(new DecelerateInterpolator(2)); + overviewPanelAlpha.setInterpolator(null); } else if (overviewToWorkspace) { + pageIndicatorAlpha.setInterpolator(null); + hotseatAlpha.setInterpolator(null); overviewPanelAlpha.setInterpolator(new DecelerateInterpolator(2)); } + searchBarAlpha.setInterpolator(null); - if (getPageIndicator() != null) { - pageIndicatorAlpha.addListener(new AlphaUpdateListener(getPageIndicator())); - } - - anim.play(overviewPanelAlpha); + overviewPanel.setAlpha(finalOverviewPanelAlpha); + AlphaUpdateListener.updateVisibility(overviewPanel); + Animation animation = AnimationUtils.loadAnimation(mLauncher, R.anim.drop_down); + overviewPanel.startAnimation(animation); anim.play(hotseatAlpha); if (mShowSearchBar) anim.play(searchBarAlpha); anim.play(pageIndicatorAlpha); @@ -2227,9 +2474,9 @@ public class Workspace extends SmoothPagedView AlphaUpdateListener.updateVisibility(overviewPanel); hotseat.setAlpha(finalHotseatAndPageIndicatorAlpha); AlphaUpdateListener.updateVisibility(hotseat); - if (getPageIndicator() != null) { - getPageIndicator().setAlpha(finalHotseatAndPageIndicatorAlpha); - AlphaUpdateListener.updateVisibility(getPageIndicator()); + if (pageIndicator != null) { + pageIndicator.setAlpha(finalHotseatAndPageIndicatorAlpha); + AlphaUpdateListener.updateVisibility(pageIndicator); } if (mShowSearchBar) { searchBar.setAlpha(finalSearchBarAlpha); @@ -2347,7 +2594,9 @@ public class Workspace extends SmoothPagedView void hideCustomContentIfNecessary() { boolean hide = mState != Workspace.State.NORMAL; if (hide && hasCustomContent()) { + disableLayoutTransitions(); mWorkspaceScreens.get(CUSTOM_CONTENT_SCREEN_ID).setVisibility(INVISIBLE); + enableLayoutTransitions(); } } @@ -2363,6 +2612,11 @@ public class Workspace extends SmoothPagedView final CellLayout cl = (CellLayout) getChildAt(i); cl.setShortcutAndWidgetAlpha(1f); } + } else { + for (int i = 0; i < numCustomPages(); i++) { + final CellLayout cl = (CellLayout) getChildAt(i); + cl.setShortcutAndWidgetAlpha(1f); + } } showCustomContentIfNecessary(); } @@ -2548,10 +2802,21 @@ public class Workspace extends SmoothPagedView if (child instanceof BubbleTextView) { BubbleTextView icon = (BubbleTextView) child; icon.clearPressedOrFocusedBackground(); + } else if (child instanceof FolderIcon) { + // Dismiss the folder cling if we haven't already + mLauncher.getLauncherClings().markFolderClingDismissed(); } - mDragController.startDrag(b, dragLayerX, dragLayerY, source, child.getTag(), + if (child.getTag() == null || !(child.getTag() instanceof ItemInfo)) { + String msg = "Drag started with a view that has no tag set. This " + + "will cause a crash (issue 11627249) down the line. " + + "View: " + child + " tag: " + child.getTag(); + throw new IllegalStateException(msg); + } + + DragView dv = mDragController.startDrag(b, dragLayerX, dragLayerY, source, child.getTag(), DragController.DRAG_ACTION_MOVE, dragVisualizeOffset, dragRect, scale); + dv.setIntrinsicIconScaleFactor(source.getIntrinsicIconScaleFactor()); if (child.getParent() instanceof ShortcutAndWidgetContainer) { mDragSourceInternal = (ShortcutAndWidgetContainer) child.getParent(); @@ -2623,17 +2888,18 @@ public class Workspace extends SmoothPagedView mTargetCell); float distance = dropTargetLayout.getDistanceFromCell(mDragViewVisualCenter[0], mDragViewVisualCenter[1], mTargetCell); - if (willCreateUserFolder((ItemInfo) d.dragInfo, dropTargetLayout, - mTargetCell, distance, true)) { + if (mCreateUserFolderOnDrop && willCreateUserFolder((ItemInfo) d.dragInfo, + dropTargetLayout, mTargetCell, distance, true)) { return true; } - if (willAddToExistingUserFolder((ItemInfo) d.dragInfo, dropTargetLayout, - mTargetCell, distance)) { + + if (mAddToExistingFolderOnDrop && willAddToExistingUserFolder((ItemInfo) d.dragInfo, + dropTargetLayout, mTargetCell, distance)) { return true; } int[] resultSpan = new int[2]; - mTargetCell = dropTargetLayout.createArea((int) mDragViewVisualCenter[0], + mTargetCell = dropTargetLayout.performReorder((int) mDragViewVisualCenter[0], (int) mDragViewVisualCenter[1], minSpanX, minSpanY, spanX, spanY, null, mTargetCell, resultSpan, CellLayout.MODE_ACCEPT_DROP); boolean foundCell = mTargetCell[0] >= 0 && mTargetCell[1] >= 0; @@ -2648,8 +2914,8 @@ public class Workspace extends SmoothPagedView } long screenId = getIdForScreen(dropTargetLayout); - if (screenId == EXTRA_EMPTY_SCREEN_LEFT_ID || screenId == EXTRA_EMPTY_SCREEN_RIGHT_ID) { - commitExtraEmptyScreen(screenId); + if (screenId == EXTRA_EMPTY_SCREEN_ID) { + commitExtraEmptyScreen(); } return true; @@ -2831,13 +3097,13 @@ public class Workspace extends SmoothPagedView // cell also contains a shortcut, then create a folder with the two shortcuts. if (!mInScrollArea && createUserFolderIfNecessary(cell, container, dropTargetLayout, mTargetCell, distance, false, d.dragView, null)) { - stripEmptyScreens(); + removeExtraEmptyScreen(true, null, 0, true); return; } if (addToExistingFolderIfNecessary(cell, dropTargetLayout, mTargetCell, distance, d, false)) { - stripEmptyScreens(); + removeExtraEmptyScreen(true, null, 0, true); return; } @@ -2852,7 +3118,7 @@ public class Workspace extends SmoothPagedView } int[] resultSpan = new int[2]; - mTargetCell = dropTargetLayout.createArea((int) mDragViewVisualCenter[0], + mTargetCell = dropTargetLayout.performReorder((int) mDragViewVisualCenter[0], (int) mDragViewVisualCenter[1], minSpanX, minSpanY, spanX, spanY, cell, mTargetCell, resultSpan, CellLayout.MODE_ON_DROP); @@ -2892,8 +3158,6 @@ public class Workspace extends SmoothPagedView lp.cellHSpan = item.spanX; lp.cellVSpan = item.spanY; lp.isLockedToGrid = true; - cell.setId(LauncherModel.getCellLayoutChildId(container, mDragInfo.screenId, - mTargetCell[0], mTargetCell[1], mDragInfo.spanX, mDragInfo.spanY)); if (container != LauncherSettings.Favorites.CONTAINER_HOTSEAT && cell instanceof LauncherAppWidgetHostView) { @@ -2946,7 +3210,7 @@ public class Workspace extends SmoothPagedView if (finalResizeRunnable != null) { finalResizeRunnable.run(); } - stripEmptyScreens(); + removeExtraEmptyScreen(true, null, 0, true); } }; mAnimatingViewIntoPlace = true; @@ -3035,13 +3299,11 @@ public class Workspace extends SmoothPagedView display.getCurrentSizeRange(smallestSize, largestSize); int countX = (int) grid.numColumns; int countY = (int) grid.numRows; - int constrainedLongEdge = largestSize.y; - int constrainedShortEdge = smallestSize.y; if (orientation == CellLayout.LANDSCAPE) { if (mLandscapeCellLayoutMetrics == null) { Rect padding = grid.getWorkspacePadding(CellLayout.LANDSCAPE); - int width = constrainedLongEdge - padding.left - padding.right; - int height = constrainedShortEdge - padding.top - padding.bottom; + int width = largestSize.x - padding.left - padding.right; + int height = smallestSize.y - padding.top - padding.bottom; mLandscapeCellLayoutMetrics = new Rect(); mLandscapeCellLayoutMetrics.set( grid.calculateCellWidth(width, countX), @@ -3051,8 +3313,8 @@ public class Workspace extends SmoothPagedView } else if (orientation == CellLayout.PORTRAIT) { if (mPortraitCellLayoutMetrics == null) { Rect padding = grid.getWorkspacePadding(CellLayout.PORTRAIT); - int width = constrainedShortEdge - padding.left - padding.right; - int height = constrainedLongEdge - padding.top - padding.bottom; + int width = smallestSize.x - padding.left - padding.right; + int height = largestSize.y - padding.top - padding.bottom; mPortraitCellLayoutMetrics = new Rect(); mPortraitCellLayoutMetrics.set( grid.calculateCellWidth(width, countX), @@ -3437,6 +3699,11 @@ public class Workspace extends SmoothPagedView && !mReorderAlarm.alarmPending() && (mLastReorderX != reorderX || mLastReorderY != reorderY)) { + int[] resultSpan = new int[2]; + mDragTargetLayout.performReorder((int) mDragViewVisualCenter[0], + (int) mDragViewVisualCenter[1], minSpanX, minSpanY, item.spanX, item.spanY, + child, mTargetCell, resultSpan, CellLayout.MODE_SHOW_REORDER_HINT); + // Otherwise, if we aren't adding to or creating a folder and there's no pending // reorder, then we schedule a reorder ReorderAlarmListener listener = new ReorderAlarmListener(mDragViewVisualCenter, @@ -3541,7 +3808,7 @@ public class Workspace extends SmoothPagedView mLastReorderX = mTargetCell[0]; mLastReorderY = mTargetCell[1]; - mTargetCell = mDragTargetLayout.createArea((int) mDragViewVisualCenter[0], + mTargetCell = mDragTargetLayout.performReorder((int) mDragViewVisualCenter[0], (int) mDragViewVisualCenter[1], minSpanX, minSpanY, spanX, spanY, child, mTargetCell, resultSpan, CellLayout.MODE_DRAG_OVER); @@ -3597,7 +3864,13 @@ public class Workspace extends SmoothPagedView final Runnable exitSpringLoadedRunnable = new Runnable() { @Override public void run() { - mLauncher.exitSpringLoadedDragModeDelayed(true, false, null); + removeExtraEmptyScreen(false, new Runnable() { + @Override + public void run() { + mLauncher.exitSpringLoadedDragModeDelayed(true, + Launcher.EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT, null); + } + }); } }; @@ -3645,7 +3918,7 @@ public class Workspace extends SmoothPagedView minSpanY = item.minSpanY; } int[] resultSpan = new int[2]; - mTargetCell = cellLayout.createArea((int) mDragViewVisualCenter[0], + mTargetCell = cellLayout.performReorder((int) mDragViewVisualCenter[0], (int) mDragViewVisualCenter[1], minSpanX, minSpanY, info.spanX, info.spanY, null, mTargetCell, resultSpan, CellLayout.MODE_ON_DROP_EXTERNAL); @@ -3738,7 +4011,7 @@ public class Workspace extends SmoothPagedView if (touchXY != null) { // when dragging and dropping, just find the closest free spot - mTargetCell = cellLayout.createArea((int) mDragViewVisualCenter[0], + mTargetCell = cellLayout.performReorder((int) mDragViewVisualCenter[0], (int) mDragViewVisualCenter[1], 1, 1, 1, 1, null, mTargetCell, null, CellLayout.MODE_ON_DROP_EXTERNAL); } else { @@ -3759,7 +4032,7 @@ public class Workspace extends SmoothPagedView // the correct final location. setFinalTransitionTransform(cellLayout); mLauncher.getDragLayer().animateViewIntoPosition(d.dragView, view, - exitSpringLoadedRunnable); + exitSpringLoadedRunnable, this); resetTransitionTransform(cellLayout); } } @@ -3834,7 +4107,7 @@ public class Workspace extends SmoothPagedView external, scalePreview); Resources res = mLauncher.getResources(); - int duration = res.getInteger(R.integer.config_dropAnimMaxDuration) - 200; + final int duration = res.getInteger(R.integer.config_dropAnimMaxDuration) - 200; // In the case where we've prebound the widget, we remove it from the DragLayer if (finalView instanceof AppWidgetHostView && external) { @@ -3910,8 +4183,8 @@ public class Workspace extends SmoothPagedView return mDragInfo; } - public int getRestorePage() { - return getNextPage() - numCustomPages() - (hasExtraEmptyScreenLeft() ? 1 : 0); + public int getCurrentPageOffsetFromCustomContent() { + return getNextPage() - numCustomPages(); } /** @@ -3932,7 +4205,6 @@ public class Workspace extends SmoothPagedView // hardware layers on children are enabled on startup, but should be disabled until // needed updateChildrenLayersEnabled(false); - setWallpaperDimension(); } /** @@ -3942,11 +4214,11 @@ public class Workspace extends SmoothPagedView final boolean isFlingToDelete, final boolean success) { if (mDeferDropAfterUninstall) { mDeferredAction = new Runnable() { - public void run() { - onDropCompleted(target, d, isFlingToDelete, success); - mDeferredAction = null; - } - }; + public void run() { + onDropCompleted(target, d, isFlingToDelete, success); + mDeferredAction = null; + } + }; return; } @@ -3964,7 +4236,7 @@ public class Workspace extends SmoothPagedView // If we move the item to anything not on the Workspace, check if any empty // screens need to be removed. If we dropped back on the workspace, this will // be done post drop animation. - stripEmptyScreens(); + removeExtraEmptyScreen(true, null, 0, true); } } else if (mDragInfo != null && target != null && (!(target instanceof InfoDropTarget))) { CellLayout cellLayout; @@ -3973,7 +4245,13 @@ public class Workspace extends SmoothPagedView } else { cellLayout = getScreenWithId(mDragInfo.screenId); } - cellLayout.onDropChild(mDragInfo.cell); + if (cellLayout == null && LauncherAppState.isDogfoodBuild()) { + throw new RuntimeException("Invalid state: cellLayout == null in " + + "Workspace#onDropCompleted. Please file a bug. "); + } + if (cellLayout != null) { + cellLayout.onDropChild(mDragInfo.cell); + } } if ((d.cancelled || target instanceof InfoDropTarget || (beingCalledAfterUninstall && !mUninstallSuccessful)) && mDragInfo.cell != null) { @@ -4144,11 +4422,26 @@ public class Workspace extends SmoothPagedView } @Override + public float getIntrinsicIconScaleFactor() { + return 1f; + } + + @Override public boolean supportsFlingToDelete() { return true; } @Override + public boolean supportsAppInfoDropTarget() { + return false; + } + + @Override + public boolean supportsDeleteDropTarget() { + return true; + } + + @Override public void onFlingToDelete(DragObject d, int x, int y, PointF vec) { // Do nothing } @@ -4491,29 +4784,53 @@ public class Workspace extends SmoothPagedView stripEmptyScreens(); } + private void updateShortcut(HashMap<ComponentName, AppInfo> appsMap, ItemInfo info, + View child) { + if (info.getIntent() == null) { + // it's the all-apps shortcut, don't crash! + return; + } + ComponentName cn = info.getIntent().getComponent(); + if (info.getRestoredIntent() != null) { + cn = info.getRestoredIntent().getComponent(); + } + if (cn != null) { + AppInfo appInfo = appsMap.get(cn); + if ((appInfo != null) && LauncherModel.isShortcutInfoUpdateable(info)) { + ShortcutInfo shortcutInfo = (ShortcutInfo) info; + BubbleTextView shortcut = (BubbleTextView) child; + shortcutInfo.restore(); + shortcutInfo.updateIcon(mIconCache); + shortcutInfo.title = appInfo.title.toString(); + shortcut.applyFromShortcutInfo(shortcutInfo, mIconCache); + } + } + } + void updateShortcuts(ArrayList<AppInfo> apps) { + // Create a map of the apps to test against + final HashMap<ComponentName, AppInfo> appsMap = new HashMap<ComponentName, AppInfo>(); + for (AppInfo ai : apps) { + appsMap.put(ai.componentName, ai); + } + ArrayList<ShortcutAndWidgetContainer> childrenLayouts = getAllShortcutAndWidgetContainers(); for (ShortcutAndWidgetContainer layout: childrenLayouts) { - int childCount = layout.getChildCount(); - for (int j = 0; j < childCount; j++) { - final View view = layout.getChildAt(j); - Object tag = view.getTag(); - - if (LauncherModel.isShortcutInfoUpdateable((ItemInfo) tag)) { - ShortcutInfo info = (ShortcutInfo) tag; - - final Intent intent = info.intent; - final ComponentName name = intent.getComponent(); - final int appCount = apps.size(); - for (int k = 0; k < appCount; k++) { - AppInfo app = apps.get(k); - if (app.componentName.equals(name)) { - BubbleTextView shortcut = (BubbleTextView) view; - info.updateIcon(mIconCache); - info.title = app.title.toString(); - shortcut.applyFromShortcutInfo(info, mIconCache); - } + // Update all the children shortcuts + final HashMap<ItemInfo, View> children = new HashMap<ItemInfo, View>(); + for (int j = 0; j < layout.getChildCount(); j++) { + View v = layout.getChildAt(j); + ItemInfo info = (ItemInfo) v.getTag(); + if (info instanceof FolderInfo && v instanceof FolderIcon) { + FolderIcon folder = (FolderIcon) v; + ArrayList<View> folderChildren = folder.getFolder().getItemsInReadingOrder(); + for (View fv : folderChildren) { + info = (ItemInfo) fv.getTag(); + updateShortcut(appsMap, info, fv); } + folder.invalidate(); + } else if (info instanceof ShortcutInfo) { + updateShortcut(appsMap, info, v); } } } @@ -4534,7 +4851,15 @@ public class Workspace extends SmoothPagedView } void moveToDefaultScreen(boolean animate) { - moveToScreen(getPageIndexForScreenId(mDefaultScreenId), animate); + // Do not use the custom page or index -1 as default, + // if GEL integration is enabled. + int idx = getPageIndexForScreenId(mDefaultScreenId); + int ccIndex = getPageIndexForScreenId(CUSTOM_CONTENT_SCREEN_ID); + if(hasCustomContent() && (idx == ccIndex || idx == -1) + && mLauncher.isGelIntegrationEnabled()) { + idx = 1; + } + moveToScreen(idx, animate); } void moveToCustomContentScreen(boolean animate) { @@ -4550,12 +4875,13 @@ public class Workspace extends SmoothPagedView child.requestFocus(); } } + exitWidgetResizeMode(); } @Override protected PageIndicator.PageMarkerResources getPageIndicatorMarker(int pageIndex) { long screenId = getScreenIdForPageIndex(pageIndex); - if (screenId == EXTRA_EMPTY_SCREEN_LEFT_ID || screenId == EXTRA_EMPTY_SCREEN_RIGHT_ID) { + if (screenId == EXTRA_EMPTY_SCREEN_ID) { int count = mScreenOrder.size() - numCustomPages(); if (count > 1) { return new PageIndicator.PageMarkerResources(R.drawable.ic_pageindicator_current, @@ -4592,4 +4918,45 @@ public class Workspace extends SmoothPagedView public void getLocationInDragLayer(int[] loc) { mLauncher.getDragLayer().getLocationInDragLayer(this, loc); } + + private void reloadSettings() { + mShowSearchBar = SettingsProvider.getBoolean(mLauncher, SettingsProvider.SETTINGS_UI_HOMESCREEN_SEARCH, + R.bool.preferences_interface_homescreen_search_default); + mShowOutlines = SettingsProvider.getBoolean(mLauncher, + SettingsProvider.SETTINGS_UI_HOMESCREEN_SCROLLING_PAGE_OUTLINES, + R.bool.preferences_interface_homescreen_scrolling_page_outlines_default); + mHideIconLabels = SettingsProvider.getBoolean(mLauncher, + SettingsProvider.SETTINGS_UI_HOMESCREEN_HIDE_ICON_LABELS, + R.bool.preferences_interface_homescreen_hide_icon_labels_default); + mWorkspaceFadeInAdjacentScreens = SettingsProvider.getBoolean(mLauncher, + SettingsProvider.SETTINGS_UI_HOMESCREEN_SCROLLING_FADE_ADJACENT, + R.bool.preferences_interface_homescreen_scrolling_fade_adjacent_default); + TransitionEffect.setFromString(this, SettingsProvider.getString(mLauncher, + SettingsProvider.SETTINGS_UI_HOMESCREEN_SCROLLING_TRANSITION_EFFECT, + R.string.preferences_interface_homescreen_scrolling_transition_effect)); + + mScrollWallpaper = SettingsProvider.getBoolean(mLauncher, + SettingsProvider.SETTINGS_UI_HOMESCREEN_SCROLLING_WALLPAPER_SCROLL, + R.bool.preferences_interface_homescreen_scrolling_wallpaper_scroll_default); + + if (!mScrollWallpaper) { + if (mWindowToken != null) mWallpaperManager.setWallpaperOffsets(mWindowToken, 0f, 0.5f); + } else { + mWallpaperOffset.syncWithScroll(); + } + } + + public boolean getShowSearchBar() { + return mShowSearchBar; + } + + public boolean getHideIconLables() { + return mHideIconLabels; + } + + @Override + public void scrollTo(int x, int y) { + mEnforceRealBounds = isInOverviewMode(); + super.scrollTo(x, y); + } } diff --git a/src/com/android/launcher3/list/AutoScrollListView.java b/src/com/android/launcher3/list/AutoScrollListView.java new file mode 100644 index 000000000..66336bc71 --- /dev/null +++ b/src/com/android/launcher3/list/AutoScrollListView.java @@ -0,0 +1,117 @@ +/* + * 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.android.launcher3.list; + +import android.content.Context; +import android.util.AttributeSet; +import android.widget.ListView; + +/** + * A ListView that can be asked to scroll (smoothly or otherwise) to a specific + * position. This class takes advantage of similar functionality that exists + * in {@link ListView} and enhances it. + */ +public class AutoScrollListView extends ListView { + + /** + * Position the element at about 1/3 of the list height + */ + private static final float PREFERRED_SELECTION_OFFSET_FROM_TOP = 0.33f; + + private int mRequestedScrollPosition = -1; + private boolean mSmoothScrollRequested; + + public AutoScrollListView(Context context) { + super(context); + } + + public AutoScrollListView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public AutoScrollListView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + /** + * Brings the specified position to view by optionally performing a jump-scroll maneuver: + * first it jumps to some position near the one requested and then does a smooth + * scroll to the requested position. This creates an impression of full smooth + * scrolling without actually traversing the entire list. If smooth scrolling is + * not requested, instantly positions the requested item at a preferred offset. + */ + public void requestPositionToScreen(int position, boolean smoothScroll) { + mRequestedScrollPosition = position; + mSmoothScrollRequested = smoothScroll; + requestLayout(); + } + + @Override + protected void layoutChildren() { + super.layoutChildren(); + if (mRequestedScrollPosition == -1) { + return; + } + + final int position = mRequestedScrollPosition; + mRequestedScrollPosition = -1; + + int firstPosition = getFirstVisiblePosition() + 1; + int lastPosition = getLastVisiblePosition(); + if (position >= firstPosition && position <= lastPosition) { + return; // Already on screen + } + + final int offset = (int) (getHeight() * PREFERRED_SELECTION_OFFSET_FROM_TOP); + if (!mSmoothScrollRequested) { + setSelectionFromTop(position, offset); + + // Since we have changed the scrolling position, we need to redo child layout + // Calling "requestLayout" in the middle of a layout pass has no effect, + // so we call layoutChildren explicitly + super.layoutChildren(); + + } else { + // We will first position the list a couple of screens before or after + // the new selection and then scroll smoothly to it. + int twoScreens = (lastPosition - firstPosition) * 2; + int preliminaryPosition; + if (position < firstPosition) { + preliminaryPosition = position + twoScreens; + if (preliminaryPosition >= getCount()) { + preliminaryPosition = getCount() - 1; + } + if (preliminaryPosition < firstPosition) { + setSelection(preliminaryPosition); + super.layoutChildren(); + } + } else { + preliminaryPosition = position - twoScreens; + if (preliminaryPosition < 0) { + preliminaryPosition = 0; + } + if (preliminaryPosition > lastPosition) { + setSelection(preliminaryPosition); + super.layoutChildren(); + } + } + + + smoothScrollToPositionFromTop(position, offset); + } + } +} diff --git a/src/com/android/launcher3/list/CompositeCursorAdapter.java b/src/com/android/launcher3/list/CompositeCursorAdapter.java new file mode 100644 index 000000000..b1ddb67fb --- /dev/null +++ b/src/com/android/launcher3/list/CompositeCursorAdapter.java @@ -0,0 +1,532 @@ +/* + * 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.android.launcher3.list; + +import android.content.Context; +import android.database.Cursor; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; + +import java.util.ArrayList; + +/** + * A general purpose adapter that is composed of multiple cursors. It just + * appends them in the order they are added. + */ +public abstract class CompositeCursorAdapter extends BaseAdapter { + + private static final int INITIAL_CAPACITY = 2; + + public static class Partition { + boolean showIfEmpty; + boolean hasHeader; + + Cursor cursor; + int idColumnIndex; + int count; + + public Partition(boolean showIfEmpty, boolean hasHeader) { + this.showIfEmpty = showIfEmpty; + this.hasHeader = hasHeader; + } + + /** + * True if the directory should be shown even if no contacts are found. + */ + public boolean getShowIfEmpty() { + return showIfEmpty; + } + + public boolean getHasHeader() { + return hasHeader; + } + } + + private final Context mContext; + private ArrayList<Partition> mPartitions; + private int mCount = 0; + private boolean mCacheValid = true; + private boolean mNotificationsEnabled = true; + private boolean mNotificationNeeded; + + public CompositeCursorAdapter(Context context) { + this(context, INITIAL_CAPACITY); + } + + public CompositeCursorAdapter(Context context, int initialCapacity) { + mContext = context; + mPartitions = new ArrayList<Partition>(); + } + + public Context getContext() { + return mContext; + } + + /** + * Registers a partition. The cursor for that partition can be set later. + * Partitions should be added in the order they are supposed to appear in the + * list. + */ + public void addPartition(boolean showIfEmpty, boolean hasHeader) { + addPartition(new Partition(showIfEmpty, hasHeader)); + } + + public void addPartition(Partition partition) { + mPartitions.add(partition); + invalidate(); + notifyDataSetChanged(); + } + + public void addPartition(int location, Partition partition) { + mPartitions.add(location, partition); + invalidate(); + notifyDataSetChanged(); + } + + public void removePartition(int partitionIndex) { + Cursor cursor = mPartitions.get(partitionIndex).cursor; + if (cursor != null && !cursor.isClosed()) { + cursor.close(); + } + mPartitions.remove(partitionIndex); + invalidate(); + notifyDataSetChanged(); + } + + /** + * Removes cursors for all partitions. + */ + // TODO: Is this really what this is supposed to do? Just remove the cursors? Not close them? + // Not remove the partitions themselves? Isn't this leaking? + + public void clearPartitions() { + for (Partition partition : mPartitions) { + partition.cursor = null; + } + invalidate(); + notifyDataSetChanged(); + } + + /** + * Closes all cursors and removes all partitions. + */ + public void close() { + for (Partition partition : mPartitions) { + Cursor cursor = partition.cursor; + if (cursor != null && !cursor.isClosed()) { + cursor.close(); + } + } + mPartitions.clear(); + invalidate(); + notifyDataSetChanged(); + } + + public void setHasHeader(int partitionIndex, boolean flag) { + mPartitions.get(partitionIndex).hasHeader = flag; + invalidate(); + } + + public void setShowIfEmpty(int partitionIndex, boolean flag) { + mPartitions.get(partitionIndex).showIfEmpty = flag; + invalidate(); + } + + public Partition getPartition(int partitionIndex) { + return mPartitions.get(partitionIndex); + } + + protected void invalidate() { + mCacheValid = false; + } + + public int getPartitionCount() { + return mPartitions.size(); + } + + protected void ensureCacheValid() { + if (mCacheValid) { + return; + } + + mCount = 0; + for (Partition partition : mPartitions) { + Cursor cursor = partition.cursor; + int count = cursor != null ? cursor.getCount() : 0; + if (partition.hasHeader) { + if (count != 0 || partition.showIfEmpty) { + count++; + } + } + partition.count = count; + mCount += count; + } + + mCacheValid = true; + } + + /** + * Returns true if the specified partition was configured to have a header. + */ + public boolean hasHeader(int partition) { + return mPartitions.get(partition).hasHeader; + } + + /** + * Returns the total number of list items in all partitions. + */ + public int getCount() { + ensureCacheValid(); + return mCount; + } + + /** + * Returns the cursor for the given partition + */ + public Cursor getCursor(int partition) { + return mPartitions.get(partition).cursor; + } + + /** + * Changes the cursor for an individual partition. + */ + public void changeCursor(int partition, Cursor cursor) { + Cursor prevCursor = mPartitions.get(partition).cursor; + if (prevCursor != cursor) { + if (prevCursor != null && !prevCursor.isClosed()) { + prevCursor.close(); + } + mPartitions.get(partition).cursor = cursor; + if (cursor != null) { + mPartitions.get(partition).idColumnIndex = cursor.getColumnIndex("_id"); + } + invalidate(); + notifyDataSetChanged(); + } + } + + /** + * Returns true if the specified partition has no cursor or an empty cursor. + */ + public boolean isPartitionEmpty(int partition) { + Cursor cursor = mPartitions.get(partition).cursor; + return cursor == null || cursor.getCount() == 0; + } + + /** + * Given a list position, returns the index of the corresponding partition. + */ + public int getPartitionForPosition(int position) { + ensureCacheValid(); + int start = 0; + for (int i = 0, n = mPartitions.size(); i < n; i++) { + int end = start + mPartitions.get(i).count; + if (position >= start && position < end) { + return i; + } + start = end; + } + return -1; + } + + /** + * Given a list position, return the offset of the corresponding item in its + * partition. The header, if any, will have offset -1. + */ + public int getOffsetInPartition(int position) { + ensureCacheValid(); + int start = 0; + for (Partition partition : mPartitions) { + int end = start + partition.count; + if (position >= start && position < end) { + int offset = position - start; + if (partition.hasHeader) { + offset--; + } + return offset; + } + start = end; + } + return -1; + } + + /** + * Returns the first list position for the specified partition. + */ + public int getPositionForPartition(int partition) { + ensureCacheValid(); + int position = 0; + for (int i = 0; i < partition; i++) { + position += mPartitions.get(i).count; + } + return position; + } + + @Override + public int getViewTypeCount() { + return getItemViewTypeCount() + 1; + } + + /** + * Returns the overall number of item view types across all partitions. An + * implementation of this method needs to ensure that the returned count is + * consistent with the values returned by {@link #getItemViewType(int,int)}. + */ + public int getItemViewTypeCount() { + return 1; + } + + /** + * Returns the view type for the list item at the specified position in the + * specified partition. + */ + protected int getItemViewType(int partition, int position) { + return 1; + } + + @Override + public int getItemViewType(int position) { + ensureCacheValid(); + int start = 0; + for (int i = 0, n = mPartitions.size(); i < n; i++) { + int end = start + mPartitions.get(i).count; + if (position >= start && position < end) { + int offset = position - start; + if (mPartitions.get(i).hasHeader) { + offset--; + } + if (offset == -1) { + return IGNORE_ITEM_VIEW_TYPE; + } else { + return getItemViewType(i, offset); + } + } + start = end; + } + + throw new ArrayIndexOutOfBoundsException(position); + } + + public View getView(int position, View convertView, ViewGroup parent) { + ensureCacheValid(); + int start = 0; + for (int i = 0, n = mPartitions.size(); i < n; i++) { + int end = start + mPartitions.get(i).count; + if (position >= start && position < end) { + int offset = position - start; + if (mPartitions.get(i).hasHeader) { + offset--; + } + View view; + if (offset == -1) { + view = getHeaderView(i, mPartitions.get(i).cursor, convertView, parent); + } else { + if (!mPartitions.get(i).cursor.moveToPosition(offset)) { + throw new IllegalStateException("Couldn't move cursor to position " + + offset); + } + view = getView(i, mPartitions.get(i).cursor, offset, convertView, parent); + } + if (view == null) { + throw new NullPointerException("View should not be null, partition: " + i + + " position: " + offset); + } + return view; + } + start = end; + } + + throw new ArrayIndexOutOfBoundsException(position); + } + + /** + * Returns the header view for the specified partition, creating one if needed. + */ + protected View getHeaderView(int partition, Cursor cursor, View convertView, + ViewGroup parent) { + View view = convertView != null + ? convertView + : newHeaderView(mContext, partition, cursor, parent); + bindHeaderView(view, partition, cursor); + return view; + } + + /** + * Creates the header view for the specified partition. + */ + protected View newHeaderView(Context context, int partition, Cursor cursor, + ViewGroup parent) { + return null; + } + + /** + * Binds the header view for the specified partition. + */ + protected void bindHeaderView(View view, int partition, Cursor cursor) { + } + + /** + * Returns an item view for the specified partition, creating one if needed. + */ + protected View getView(int partition, Cursor cursor, int position, View convertView, + ViewGroup parent) { + View view; + if (convertView != null) { + view = convertView; + } else { + view = newView(mContext, partition, cursor, position, parent); + } + bindView(view, partition, cursor, position); + return view; + } + + /** + * Creates an item view for the specified partition and position. Position + * corresponds directly to the current cursor position. + */ + protected abstract View newView(Context context, int partition, Cursor cursor, int position, + ViewGroup parent); + + /** + * Binds an item view for the specified partition and position. Position + * corresponds directly to the current cursor position. + */ + protected abstract void bindView(View v, int partition, Cursor cursor, int position); + + /** + * Returns a pre-positioned cursor for the specified list position. + */ + public Object getItem(int position) { + ensureCacheValid(); + int start = 0; + for (Partition mPartition : mPartitions) { + int end = start + mPartition.count; + if (position >= start && position < end) { + int offset = position - start; + if (mPartition.hasHeader) { + offset--; + } + if (offset == -1) { + return null; + } + Cursor cursor = mPartition.cursor; + cursor.moveToPosition(offset); + return cursor; + } + start = end; + } + + return null; + } + + /** + * Returns the item ID for the specified list position. + */ + public long getItemId(int position) { + ensureCacheValid(); + int start = 0; + for (Partition mPartition : mPartitions) { + int end = start + mPartition.count; + if (position >= start && position < end) { + int offset = position - start; + if (mPartition.hasHeader) { + offset--; + } + if (offset == -1) { + return 0; + } + if (mPartition.idColumnIndex == -1) { + return 0; + } + + Cursor cursor = mPartition.cursor; + if (cursor == null || cursor.isClosed() || !cursor.moveToPosition(offset)) { + return 0; + } + return cursor.getLong(mPartition.idColumnIndex); + } + start = end; + } + + return 0; + } + + /** + * Returns false if any partition has a header. + */ + @Override + public boolean areAllItemsEnabled() { + for (Partition mPartition : mPartitions) { + if (mPartition.hasHeader) { + return false; + } + } + return true; + } + + /** + * Returns true for all items except headers. + */ + @Override + public boolean isEnabled(int position) { + ensureCacheValid(); + int start = 0; + for (int i = 0, n = mPartitions.size(); i < n; i++) { + int end = start + mPartitions.get(i).count; + if (position >= start && position < end) { + int offset = position - start; + if (mPartitions.get(i).hasHeader && offset == 0) { + return false; + } else { + return isEnabled(i, offset); + } + } + start = end; + } + + return false; + } + + /** + * Returns true if the item at the specified offset of the specified + * partition is selectable and clickable. + */ + protected boolean isEnabled(int partition, int position) { + return true; + } + + /** + * Enable or disable data change notifications. It may be a good idea to + * disable notifications before making changes to several partitions at once. + */ + public void setNotificationsEnabled(boolean flag) { + mNotificationsEnabled = flag; + if (flag && mNotificationNeeded) { + notifyDataSetChanged(); + } + } + + @Override + public void notifyDataSetChanged() { + if (mNotificationsEnabled) { + mNotificationNeeded = false; + super.notifyDataSetChanged(); + } else { + mNotificationNeeded = true; + } + } +} diff --git a/src/com/android/launcher3/list/PinnedHeaderListAdapter.java b/src/com/android/launcher3/list/PinnedHeaderListAdapter.java new file mode 100644 index 000000000..c15e87a46 --- /dev/null +++ b/src/com/android/launcher3/list/PinnedHeaderListAdapter.java @@ -0,0 +1,172 @@ +/* + * 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.android.launcher3.list; + +import android.content.Context; +import android.util.Log; +import android.view.View; +import android.view.ViewGroup; + +/** + * A subclass of {@link CompositeCursorAdapter} that manages pinned partition headers. + */ +public abstract class PinnedHeaderListAdapter extends CompositeCursorAdapter + implements PinnedHeaderListView.PinnedHeaderAdapter { + + public static final int PARTITION_HEADER_TYPE = 0; + + private boolean mPinnedPartitionHeadersEnabled; + private boolean mHeaderVisibility[]; + + public PinnedHeaderListAdapter(Context context) { + super(context); + } + + public PinnedHeaderListAdapter(Context context, int initialCapacity) { + super(context, initialCapacity); + } + + public boolean getPinnedPartitionHeadersEnabled() { + return mPinnedPartitionHeadersEnabled; + } + + public void setPinnedPartitionHeadersEnabled(boolean flag) { + this.mPinnedPartitionHeadersEnabled = flag; + } + + @Override + public int getPinnedHeaderCount() { + if (mPinnedPartitionHeadersEnabled) { + return getPartitionCount(); + } else { + return 0; + } + } + + protected boolean isPinnedPartitionHeaderVisible(int partition) { + return getPinnedPartitionHeadersEnabled() && hasHeader(partition) + && !isPartitionEmpty(partition); + } + + /** + * The default implementation creates the same type of view as a normal + * partition header. + */ + @Override + public View getPinnedHeaderView(int partition, View convertView, ViewGroup parent) { + if (hasHeader(partition)) { + View view = null; + if (convertView != null) { + Integer headerType = (Integer)convertView.getTag(); + if (headerType != null && headerType == PARTITION_HEADER_TYPE) { + view = convertView; + } + } + if (view == null) { + view = newHeaderView(getContext(), partition, null, parent); + view.setTag(PARTITION_HEADER_TYPE); + view.setFocusable(false); + view.setEnabled(false); + } + bindHeaderView(view, partition, getCursor(partition)); + view.setLayoutDirection(parent.getLayoutDirection()); + return view; + } else { + return null; + } + } + + @Override + public void configurePinnedHeaders(PinnedHeaderListView listView) { + if (!getPinnedPartitionHeadersEnabled()) { + return; + } + + int size = getPartitionCount(); + boolean unCached = false; + // Cache visibility bits, because we will need them several times later on + if (mHeaderVisibility == null || mHeaderVisibility.length != size) { + mHeaderVisibility = new boolean[size]; + unCached = true; + } + for (int i = 0; i < size; i++) { + boolean visible = isPinnedPartitionHeaderVisible(i); + mHeaderVisibility[i] = visible; + if (!visible) { + listView.setHeaderInvisible(i, true); + } + } + + int headerViewsCount = listView.getHeaderViewsCount(); + + // Starting at the top, find and pin headers for partitions preceding the visible one(s) + int maxTopHeader = -1; + int topHeaderHeight = 0; + for (int i = 0; i < size; i++) { + if (mHeaderVisibility[i]) { + int position = listView.getPositionAt(topHeaderHeight) - headerViewsCount; + int partition = getPartitionForPosition(position); + if (i > partition) { + break; + } + + if (!unCached){ + listView.setHeaderPinnedAtTop(i, topHeaderHeight, false); + topHeaderHeight += listView.getPinnedHeaderHeight(i); + maxTopHeader = i; + } + + } + } + + // Starting at the bottom, find and pin headers for partitions following the visible one(s) + /*int maxBottomHeader = size; + int bottomHeaderHeight = 0; + int listHeight = listView.getHeight(); + for (int i = size; --i > maxTopHeader;) { + if (mHeaderVisibility[i]) { + int position = listView.getPositionAt(listHeight - bottomHeaderHeight) + - headerViewsCount; + if (position < 0) { + break; + } + + int partition = getPartitionForPosition(position - 1); + if (partition == -1 || i <= partition) { + break; + } + + int height = listView.getPinnedHeaderHeight(i); + bottomHeaderHeight += height; + + listView.setHeaderPinnedAtBottom(i, listHeight - bottomHeaderHeight, false); + maxBottomHeader = i; + } + } + + // Headers in between the top-pinned and bottom-pinned should be hidden + for (int i = maxTopHeader + 1; i < maxBottomHeader; i++) { + if (mHeaderVisibility[i]) { + listView.setHeaderInvisible(i, isPartitionEmpty(i)); + } + }*/ + } + + @Override + public int getScrollPositionForHeader(int viewIndex) { + return getPositionForPartition(viewIndex); + } +} diff --git a/src/com/android/launcher3/list/PinnedHeaderListView.java b/src/com/android/launcher3/list/PinnedHeaderListView.java new file mode 100644 index 000000000..30688fea3 --- /dev/null +++ b/src/com/android/launcher3/list/PinnedHeaderListView.java @@ -0,0 +1,565 @@ +/* + * 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.android.launcher3.list; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Rect; +import android.graphics.RectF; +import android.util.AttributeSet; +import android.util.Log; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AbsListView; +import android.widget.AbsListView.OnScrollListener; +import android.widget.AdapterView; +import android.widget.AdapterView.OnItemSelectedListener; +import android.widget.ListAdapter; + +/** + * A ListView that maintains a header pinned at the top of the list. The + * pinned header can be pushed up and dissolved as needed. + */ +public class PinnedHeaderListView extends AutoScrollListView + implements OnScrollListener, OnItemSelectedListener { + + /** + * Adapter interface. The list adapter must implement this interface. + */ + public interface PinnedHeaderAdapter { + + /** + * Returns the overall number of pinned headers, visible or not. + */ + int getPinnedHeaderCount(); + + /** + * Creates or updates the pinned header view. + */ + View getPinnedHeaderView(int viewIndex, View convertView, ViewGroup parent); + + /** + * Configures the pinned headers to match the visible list items. The + * adapter should call {@link PinnedHeaderListView#setHeaderPinnedAtTop}, + * {@link PinnedHeaderListView#setHeaderPinnedAtBottom}, + * {@link PinnedHeaderListView#setFadingHeader} or + * {@link PinnedHeaderListView#setHeaderInvisible}, for each header that + * needs to change its position or visibility. + */ + void configurePinnedHeaders(PinnedHeaderListView listView); + + /** + * Returns the list position to scroll to if the pinned header is touched. + * Return -1 if the list does not need to be scrolled. + */ + int getScrollPositionForHeader(int viewIndex); + } + + private static final int MAX_ALPHA = 255; + private static final int TOP = 0; + private static final int BOTTOM = 1; + private static final int FADING = 2; + + private static final int DEFAULT_ANIMATION_DURATION = 20; + + private static final int DEFAULT_SMOOTH_SCROLL_DURATION = 100; + + private static final class PinnedHeader { + View view; + boolean visible; + int y; + int height; + int alpha; + int state; + + boolean animating; + boolean targetVisible; + int sourceY; + int targetY; + long targetTime; + } + + private PinnedHeaderAdapter mAdapter; + private int mSize; + private PinnedHeader[] mHeaders; + private RectF mBounds = new RectF(); + private Rect mClipRect = new Rect(); + private OnScrollListener mOnScrollListener; + private OnItemSelectedListener mOnItemSelectedListener; + private int mScrollState; + + private boolean mScrollToSectionOnHeaderTouch = false; + private boolean mHeaderTouched = false; + + private int mAnimationDuration = DEFAULT_ANIMATION_DURATION; + private boolean mAnimating; + private long mAnimationTargetTime; + private int mHeaderPaddingStart; + private int mHeaderWidth; + + public PinnedHeaderListView(Context context) { + this(context, null, android.R.attr.listViewStyle); + } + + public PinnedHeaderListView(Context context, AttributeSet attrs) { + this(context, attrs, android.R.attr.listViewStyle); + } + + public PinnedHeaderListView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + super.setOnScrollListener(this); + super.setOnItemSelectedListener(this); + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + super.onLayout(changed, l, t, r, b); + mHeaderPaddingStart = getPaddingStart(); + mHeaderWidth = r - l - mHeaderPaddingStart - getPaddingEnd(); + } + + public void setPinnedHeaderAnimationDuration(int duration) { + mAnimationDuration = duration; + } + + @Override + public void setAdapter(ListAdapter adapter) { + mAdapter = (PinnedHeaderAdapter)adapter; + super.setAdapter(adapter); + } + + @Override + public void setOnScrollListener(OnScrollListener onScrollListener) { + mOnScrollListener = onScrollListener; + super.setOnScrollListener(this); + } + + @Override + public void setOnItemSelectedListener(OnItemSelectedListener listener) { + mOnItemSelectedListener = listener; + super.setOnItemSelectedListener(this); + } + + public void setScrollToSectionOnHeaderTouch(boolean value) { + mScrollToSectionOnHeaderTouch = value; + } + + @Override + public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, + int totalItemCount) { + if (mAdapter != null) { + int count = mAdapter.getPinnedHeaderCount(); + if (count != mSize) { + mSize = count; + if (mHeaders == null) { + mHeaders = new PinnedHeader[mSize]; + } else if (mHeaders.length < mSize) { + PinnedHeader[] headers = mHeaders; + mHeaders = new PinnedHeader[mSize]; + System.arraycopy(headers, 0, mHeaders, 0, headers.length); + } + } + + for (int i = 0; i < mSize; i++) { + if (mHeaders[i] == null) { + mHeaders[i] = new PinnedHeader(); + } + mHeaders[i].view = mAdapter.getPinnedHeaderView(i, mHeaders[i].view, this); + } + + mAnimationTargetTime = System.currentTimeMillis() + mAnimationDuration; + mAdapter.configurePinnedHeaders(this); + invalidateIfAnimating(); + + } + if (mOnScrollListener != null) { + mOnScrollListener.onScroll(this, firstVisibleItem, visibleItemCount, totalItemCount); + } + } + + @Override + protected float getTopFadingEdgeStrength() { + // Disable vertical fading at the top when the pinned header is present + return mSize > 0 ? 0 : super.getTopFadingEdgeStrength(); + } + + @Override + public void onScrollStateChanged(AbsListView view, int scrollState) { + mScrollState = scrollState; + if (mOnScrollListener != null) { + mOnScrollListener.onScrollStateChanged(this, scrollState); + } + } + + /** + * Ensures that the selected item is positioned below the top-pinned headers + * and above the bottom-pinned ones. + */ + @Override + public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { + int height = getHeight(); + + int windowTop = 0; + int windowBottom = height; + + for (int i = 0; i < mSize; i++) { + PinnedHeader header = mHeaders[i]; + if (header.visible) { + if (header.state == TOP) { + windowTop = header.y + header.height; + } else if (header.state == BOTTOM) { + windowBottom = header.y; + break; + } + } + } + + View selectedView = getSelectedView(); + if (selectedView != null) { + if (selectedView.getTop() < windowTop) { + setSelectionFromTop(position, windowTop); + } else if (selectedView.getBottom() > windowBottom) { + setSelectionFromTop(position, windowBottom - selectedView.getHeight()); + } + } + + if (mOnItemSelectedListener != null) { + mOnItemSelectedListener.onItemSelected(parent, view, position, id); + } + } + + @Override + public void onNothingSelected(AdapterView<?> parent) { + if (mOnItemSelectedListener != null) { + mOnItemSelectedListener.onNothingSelected(parent); + } + } + + public int getPinnedHeaderHeight(int viewIndex) { + ensurePinnedHeaderLayout(viewIndex); + return mHeaders[viewIndex].view.getHeight(); + } + + /** + * Set header to be pinned at the top. + * + * @param viewIndex index of the header view + * @param y is position of the header in pixels. + * @param animate true if the transition to the new coordinate should be animated + */ + public void setHeaderPinnedAtTop(int viewIndex, int y, boolean animate) { + ensurePinnedHeaderLayout(viewIndex); + PinnedHeader header = mHeaders[viewIndex]; + header.visible = true; + header.y = y; + header.state = TOP; + + // TODO perhaps we should animate at the top as well + header.animating = false; + } + + /** + * Set header to be pinned at the bottom. + * + * @param viewIndex index of the header view + * @param y is position of the header in pixels. + * @param animate true if the transition to the new coordinate should be animated + */ + public void setHeaderPinnedAtBottom(int viewIndex, int y, boolean animate) { + ensurePinnedHeaderLayout(viewIndex); + PinnedHeader header = mHeaders[viewIndex]; + header.state = BOTTOM; + if (header.animating) { + header.targetTime = mAnimationTargetTime; + header.sourceY = header.y; + header.targetY = y; + } else if (animate && (header.y != y || !header.visible)) { + if (header.visible) { + header.sourceY = header.y; + } else { + header.visible = true; + header.sourceY = y + header.height; + } + header.animating = true; + header.targetVisible = true; + header.targetTime = mAnimationTargetTime; + header.targetY = y; + } else { + header.visible = true; + header.y = y; + } + } + + /** + * Set header to be pinned at the top of the first visible item. + * + * @param viewIndex index of the header view + * @param position is position of the header in pixels. + */ + public void setFadingHeader(int viewIndex, int position, boolean fade) { + ensurePinnedHeaderLayout(viewIndex); + + View child = getChildAt(position - getFirstVisiblePosition()); + if (child == null) return; + + PinnedHeader header = mHeaders[viewIndex]; + header.visible = true; + header.state = FADING; + header.alpha = MAX_ALPHA; + header.animating = false; + + int top = getTotalTopPinnedHeaderHeight(); + header.y = top; + if (fade) { + int bottom = child.getBottom() - top; + int headerHeight = header.height; + if (bottom < headerHeight) { + int portion = bottom - headerHeight; + header.alpha = MAX_ALPHA * (headerHeight + portion) / headerHeight; + header.y = top + portion; + } + } + } + + /** + * Makes header invisible. + * + * @param viewIndex index of the header view + * @param animate true if the transition to the new coordinate should be animated + */ + public void setHeaderInvisible(int viewIndex, boolean animate) { + PinnedHeader header = mHeaders[viewIndex]; + if (header.visible && (animate || header.animating) && header.state == BOTTOM) { + header.sourceY = header.y; + if (!header.animating) { + header.visible = true; + header.targetY = getBottom() + header.height; + } + header.animating = true; + header.targetTime = mAnimationTargetTime; + header.targetVisible = false; + } else { + header.visible = false; + } + } + + private void ensurePinnedHeaderLayout(int viewIndex) { + View view = mHeaders[viewIndex].view; + if (view.isLayoutRequested()) { + int widthSpec = View.MeasureSpec.makeMeasureSpec(mHeaderWidth, View.MeasureSpec.EXACTLY); + int heightSpec; + ViewGroup.LayoutParams layoutParams = view.getLayoutParams(); + if (layoutParams != null && layoutParams.height > 0) { + heightSpec = View.MeasureSpec + .makeMeasureSpec(layoutParams.height, View.MeasureSpec.EXACTLY); + } else { + heightSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); + } + view.measure(widthSpec, heightSpec); + int height = view.getMeasuredHeight(); + mHeaders[viewIndex].height = height; + view.layout(0, 0, mHeaderWidth, height); + } + } + + /** + * Returns the sum of heights of headers pinned to the top. + */ + public int getTotalTopPinnedHeaderHeight() { + for (int i = mSize; --i >= 0;) { + PinnedHeader header = mHeaders[i]; + if (header.visible && header.state == TOP) { + return header.y + header.height; + } + } + return 0; + } + + /** + * Returns the list item position at the specified y coordinate. + */ + public int getPositionAt(int y) { + do { + int position = pointToPosition(getPaddingLeft() + 1, y); + if (position != -1) { + return position; + } + // If position == -1, we must have hit a separator. Let's examine + // a nearby pixel + y--; + } while (y > 0); + return 0; + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + mHeaderTouched = false; + if (super.onInterceptTouchEvent(ev)) { + return true; + } + + if (mScrollState == SCROLL_STATE_IDLE) { + final int y = (int)ev.getY(); + final int x = (int)ev.getX(); + for (int i = mSize; --i >= 0;) { + PinnedHeader header = mHeaders[i]; + // For RTL layouts, this also takes into account that the scrollbar is on the left + // side. + final int padding = getPaddingLeft(); + if (header.visible && header.y <= y && header.y + header.height > y && + x >= padding && padding + mHeaderWidth >= x) { + mHeaderTouched = true; + if (mScrollToSectionOnHeaderTouch && + ev.getAction() == MotionEvent.ACTION_DOWN) { + return smoothScrollToPartition(i); + } else { + return true; + } + } + } + } + + return false; + } + + @Override + public boolean onTouchEvent(MotionEvent ev) { + if (mHeaderTouched) { + if (ev.getAction() == MotionEvent.ACTION_UP) { + mHeaderTouched = false; + } + return true; + } + return super.onTouchEvent(ev); + }; + + private boolean smoothScrollToPartition(int partition) { + final int position = mAdapter.getScrollPositionForHeader(partition); + if (position == -1) { + return false; + } + + int offset = 0; + for (int i = 0; i < partition; i++) { + PinnedHeader header = mHeaders[i]; + if (header.visible) { + offset += header.height; + } + } + smoothScrollToPositionFromTop(position + getHeaderViewsCount(), offset, + DEFAULT_SMOOTH_SCROLL_DURATION); + return true; + } + + private void invalidateIfAnimating() { + mAnimating = false; + for (int i = 0; i < mSize; i++) { + if (mHeaders[i].animating) { + mAnimating = true; + invalidate(); + return; + } + } + } + + @Override + protected void dispatchDraw(Canvas canvas) { + long currentTime = mAnimating ? System.currentTimeMillis() : 0; + + int top = 0; + int bottom = getBottom(); + boolean hasVisibleHeaders = false; + for (int i = 0; i < mSize; i++) { + PinnedHeader header = mHeaders[i]; + if (header.visible) { + hasVisibleHeaders = true; + if (header.state == BOTTOM && header.y < bottom) { + bottom = header.y; + } else if (header.state == TOP || header.state == FADING) { + int newTop = header.y + header.height; + if (newTop > top) { + top = newTop; + } + } + } + } + + if (hasVisibleHeaders) { + canvas.save(); + mClipRect.set(0, top, getWidth(), bottom); + canvas.clipRect(mClipRect); + } + + super.dispatchDraw(canvas); + + if (hasVisibleHeaders) { + canvas.restore(); + + // First draw top headers, then the bottom ones to handle the Z axis correctly + for (int i = mSize; --i >= 0;) { + PinnedHeader header = mHeaders[i]; + if (header.visible && (header.state == TOP || header.state == FADING)) { + drawHeader(canvas, header, currentTime); + } + } + + for (int i = 0; i < mSize; i++) { + PinnedHeader header = mHeaders[i]; + if (header.visible && header.state == BOTTOM) { + drawHeader(canvas, header, currentTime); + } + } + } + + invalidateIfAnimating(); + } + + private void drawHeader(Canvas canvas, PinnedHeader header, long currentTime) { + if (header.animating) { + int timeLeft = (int)(header.targetTime - currentTime); + if (timeLeft <= 0) { + header.y = header.targetY; + header.visible = header.targetVisible; + header.animating = false; + } else { + header.y = header.targetY + (header.sourceY - header.targetY) * timeLeft + / mAnimationDuration; + } + } + if (header.visible) { + View view = header.view; + int saveCount = canvas.save(); + canvas.translate(isLayoutRtl() ? + getWidth() - mHeaderPaddingStart - mHeaderWidth : mHeaderPaddingStart, + header.y); + if (header.state == FADING) { + mBounds.set(0, 0, mHeaderWidth, view.getHeight()); + canvas.saveLayerAlpha(mBounds, header.alpha, Canvas.ALL_SAVE_FLAG); + } + view.draw(canvas); + canvas.restoreToCount(saveCount); + } + } + + /** + * Note: this is a reimplementation of View.isLayoutRtl() since that is currently hidden api. + */ + public boolean isLayoutRtl() { + return (getLayoutDirection() == LAYOUT_DIRECTION_RTL); + } +} diff --git a/src/com/android/launcher3/list/SettingsPinnedHeaderAdapter.java b/src/com/android/launcher3/list/SettingsPinnedHeaderAdapter.java new file mode 100644 index 000000000..805b51e37 --- /dev/null +++ b/src/com/android/launcher3/list/SettingsPinnedHeaderAdapter.java @@ -0,0 +1,373 @@ +package com.android.launcher3.list; + +import android.content.Context; +import android.content.Intent; +import android.content.res.Resources; +import android.database.Cursor; +import android.graphics.Typeface; +import android.util.TypedValue; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; +import android.widget.Toast; +import com.android.launcher3.DeviceProfile; +import com.android.launcher3.Launcher; +import com.android.launcher3.OverviewSettingsPanel; +import com.android.launcher3.AppsCustomizePagedView; +import com.android.launcher3.R; + +import com.android.launcher3.settings.SettingsProvider; +import android.view.View.OnClickListener; +import android.content.SharedPreferences; + +public class SettingsPinnedHeaderAdapter extends PinnedHeaderListAdapter { + private Launcher mLauncher; + private Context mContext; + + public SettingsPinnedHeaderAdapter(Context context) { + super(context); + mLauncher = (Launcher) context; + mContext = context; + } + + private String[] mHeaders; + public int mPinnedHeaderCount; + + public void setHeaders(String[] headers) { + this.mHeaders = headers; + } + + @Override + protected View newHeaderView(Context context, int partition, Cursor cursor, + ViewGroup parent) { + LayoutInflater inflater = LayoutInflater.from(context); + return inflater.inflate(R.layout.settings_pane_list_header, null); + } + + @Override + protected void bindHeaderView(View view, int partition, Cursor cursor) { + TextView textView = (TextView) view.findViewById(R.id.item_name); + textView.setText(mHeaders[partition]); + textView.setTypeface(textView.getTypeface(), Typeface.BOLD); + + textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16); + } + + @Override + protected View newView(Context context, int partition, Cursor cursor, int position, + ViewGroup parent) { + LayoutInflater inflater = LayoutInflater.from(context); + return inflater.inflate(R.layout.settings_pane_list_item, null); + } + + @Override + protected void bindView(View v, int partition, Cursor cursor, int position) { + TextView text = (TextView)v.findViewById(R.id.item_name); + String title = cursor.getString(1); + text.setText(title); + + Resources res = mLauncher.getResources(); + + if (title.equals(res + .getString(R.string.home_screen_search_text))) { + boolean current = mLauncher.shouldShowSearchBar(); + String state = current ? res.getString( + R.string.setting_state_on) : res.getString( + R.string.setting_state_off); + ((TextView) v.findViewById(R.id.item_state)).setText(state); + } else if (title.equals(res + .getString(R.string.drawer_sorting_text))) { + updateDrawerSortSettingsItem(v); + } else if (title.equals(res + .getString(R.string.scroll_effect_text)) && + partition == OverviewSettingsPanel.DRAWER_SETTINGS_POSITION) { + String state = mLauncher.getAppsCustomizeTransitionEffect(); + state = mapEffectToValue(state); + ((TextView) v.findViewById(R.id.item_state)).setText(state); + } else if (title.equals(res + .getString(R.string.scroll_effect_text)) && + partition == OverviewSettingsPanel.HOME_SETTINGS_POSITION) { + String state = mLauncher.getWorkspaceTransitionEffect(); + state = mapEffectToValue(state); + ((TextView) v.findViewById(R.id.item_state)).setText(state); + } else if (title.equals(res + .getString(R.string.larger_icons_text))) { + boolean current = SettingsProvider + .getBoolean( + mContext, + SettingsProvider.SETTINGS_UI_GENERAL_ICONS_LARGE, + R.bool.preferences_interface_general_icons_large_default); + String state = current ? res.getString( + R.string.setting_state_on) : res.getString( + R.string.setting_state_off); + ((TextView) v.findViewById(R.id.item_state)).setText(state); + } else if (title.equals(res + .getString(R.string.icon_labels)) && + partition == OverviewSettingsPanel.HOME_SETTINGS_POSITION) { + boolean current = mLauncher.shouldHideWorkspaceIconLables(); + String state = current ? res.getString( + R.string.icon_labels_hide) : res.getString( + R.string.icon_labels_show); + ((TextView) v.findViewById(R.id.item_state)).setText(state); + } else if (title.equals(res + .getString(R.string.icon_labels)) && + partition == OverviewSettingsPanel.DRAWER_SETTINGS_POSITION) { + boolean current = SettingsProvider + .getBoolean( + mContext, + SettingsProvider.SETTINGS_UI_DRAWER_HIDE_ICON_LABELS, + R.bool.preferences_interface_drawer_hide_icon_labels_default); + String state = current ? res.getString( + R.string.icon_labels_hide) : res.getString( + R.string.icon_labels_show); + ((TextView) v.findViewById(R.id.item_state)).setText(state); + } else if (title.equals(res + .getString(R.string.search_screen_left_text))) { + boolean current = SettingsProvider + .getBoolean( + mContext, + SettingsProvider.SETTINGS_UI_HOMESCREEN_SEARCH_SCREEN_LEFT, + R.bool.preferences_interface_homescreen_search_screen_left_default); + String state = current ? res.getString( + R.string.setting_state_on) : res.getString( + R.string.setting_state_off); + ((TextView) v.findViewById(R.id.item_state)).setText(state); + } else if (title.equals(res.getString(R.string.scrolling_wallpaper))) { + boolean current = SettingsProvider + .getBoolean( + mContext, + SettingsProvider.SETTINGS_UI_HOMESCREEN_SCROLLING_WALLPAPER_SCROLL, + R.bool.preferences_interface_homescreen_scrolling_wallpaper_scroll_default); + String state = current ? res.getString( + R.string.setting_state_on) : res.getString( + R.string.setting_state_off); + ((TextView) v.findViewById(R.id.item_state)).setText(state); + } else if (title.equals(res.getString(R.string.grid_size_text))) { + updateDynamicGridSizeSettingsItem(v); + } else { + ((TextView) v.findViewById(R.id.item_state)).setText(""); + } + + v.setTag(partition); + v.setOnClickListener(mSettingsItemListener); + } + + @Override + public View getPinnedHeaderView(int viewIndex, View convertView, ViewGroup parent) { + LayoutInflater inflater = LayoutInflater.from(getContext()); + View view = inflater.inflate(R.layout.settings_pane_list_header, parent, false); + view.setFocusable(false); + view.setEnabled(false); + bindHeaderView(view, viewIndex, null); + return view; + } + + @Override + public int getPinnedHeaderCount() { + return mPinnedHeaderCount; + } + + public void updateDrawerSortSettingsItem(View v) { + String state = ""; + switch (mLauncher.getAppsCustomizeContentSortMode()) { + case Title: + state = mLauncher.getResources().getString(R.string.sort_mode_title); + break; + case LaunchCount: + state = mLauncher.getResources().getString( + R.string.sort_mode_launch_count); + break; + case InstallTime: + state = mLauncher.getResources().getString( + R.string.sort_mode_install_time); + break; + } + ((TextView) v.findViewById(R.id.item_state)).setText(state); + } + + public void updateDynamicGridSizeSettingsItem(View v) { + DeviceProfile.GridSize gridSize = DeviceProfile.GridSize.getModeForValue( + SettingsProvider.getIntCustomDefault(mLauncher, + SettingsProvider.SETTINGS_UI_DYNAMIC_GRID_SIZE, 0)); + String state = ""; + + switch (gridSize) { + case Comfortable: + state = mLauncher.getResources().getString(R.string.grid_size_comfortable); + break; + case Cozy: + state = mLauncher.getResources().getString(R.string.grid_size_cozy); + break; + case Condensed: + state = mLauncher.getResources().getString(R.string.grid_size_condensed); + break; + case Custom: + int rows = SettingsProvider.getIntCustomDefault(mLauncher, + SettingsProvider.SETTINGS_UI_HOMESCREEN_ROWS, 0); + int columns = SettingsProvider.getIntCustomDefault(mLauncher, + SettingsProvider.SETTINGS_UI_HOMESCREEN_COLUMNS, 0); + state = rows + " " + "\u00d7" + " " + columns; + break; + } + ((TextView) v.findViewById(R.id.item_state)).setText(state); + } + + private String mapEffectToValue(String effect) { + final String[] titles = mLauncher.getResources().getStringArray( + R.array.transition_effect_entries); + final String[] values = mLauncher.getResources().getStringArray( + R.array.transition_effect_values); + + int length = values.length; + for (int i = 0; i < length; i++) { + if (effect.equals(values[i])) { + return titles[i]; + } + } + return ""; + } + + OnClickListener mSettingsItemListener = new OnClickListener() { + + @Override + public void onClick(View v) { + // TODO Auto-generated method stub + String value = ((TextView) v.findViewById(R.id.item_name)).getText().toString(); + Resources res = mLauncher.getResources(); + + // Handle toggles or launch pickers + if (value.equals(res + .getString(R.string.home_screen_search_text))) { + onSettingsBooleanChanged( + v, + SettingsProvider.SETTINGS_UI_HOMESCREEN_SEARCH, + R.bool.preferences_interface_homescreen_search_default); + mLauncher.updateDynamicGrid(); + } else if (value.equals(res + .getString(R.string.drawer_sorting_text))) { + onClickTransitionEffectButton(); + } else if (value.equals(res + .getString(R.string.scroll_effect_text)) && + ((Integer)v.getTag() == OverviewSettingsPanel.DRAWER_SETTINGS_POSITION)) { + mLauncher.onClickTransitionEffectButton(v, true); + } else if (value.equals(res + .getString(R.string.scroll_effect_text)) && + ((Integer)v.getTag() == OverviewSettingsPanel.HOME_SETTINGS_POSITION)) { + mLauncher.onClickTransitionEffectButton(v, false); + } else if (value.equals(res + .getString(R.string.larger_icons_text))) { + onSettingsBooleanChanged( + v, + SettingsProvider.SETTINGS_UI_GENERAL_ICONS_LARGE, + R.bool.preferences_interface_general_icons_large_default); + mLauncher.updateDynamicGrid(); + } else if (value.equals(res + .getString(R.string.icon_labels)) && + ((Integer)v.getTag() == OverviewSettingsPanel.HOME_SETTINGS_POSITION)) { + onIconLabelsBooleanChanged( + v, + SettingsProvider.SETTINGS_UI_HOMESCREEN_HIDE_ICON_LABELS, + R.bool.preferences_interface_homescreen_hide_icon_labels_default); + mLauncher.updateDynamicGrid(); + } else if (value.equals(res + .getString(R.string.icon_labels)) && + ((Integer)v.getTag() == OverviewSettingsPanel.DRAWER_SETTINGS_POSITION)) { + onIconLabelsBooleanChanged( + v, + SettingsProvider.SETTINGS_UI_DRAWER_HIDE_ICON_LABELS, + R.bool.preferences_interface_drawer_hide_icon_labels_default); + mLauncher.updateDynamicGrid(); + } else if (value.equals(res.getString(R.string.protected_app_settings))) { + Intent intent = new Intent(); + intent.setClassName(OverviewSettingsPanel.ANDROID_SETTINGS, + OverviewSettingsPanel.ANDROID_PROTECTED_APPS); + mLauncher.startActivity(intent); + } else if (value.equals(res.getString(R.string.protected_app_settings))) { + + } else if (value.equals(res + .getString(R.string.scrolling_wallpaper))) { + onSettingsBooleanChanged( + v, + SettingsProvider.SETTINGS_UI_HOMESCREEN_SCROLLING_WALLPAPER_SCROLL, + R.bool.preferences_interface_homescreen_scrolling_wallpaper_scroll_default); + mLauncher.updateDynamicGrid(); + } else if (value.equals(res + .getString(R.string.search_screen_left_text)) && + ((Integer)v.getTag() == OverviewSettingsPanel.HOME_SETTINGS_POSITION)) { + + boolean current = SettingsProvider.getBoolean(mContext, + SettingsProvider.SETTINGS_UI_HOMESCREEN_SEARCH_SCREEN_LEFT, + R.bool.preferences_interface_homescreen_search_screen_left_default); + + // If GEL integration is not supported, do not allow the user to turn it on. + if(!current && !mLauncher.isGelIntegrationSupported()) { + Toast.makeText(mLauncher.getApplicationContext(), + res.getString(R.string.search_screen_left_unsupported_toast), + Toast.LENGTH_SHORT).show(); + } else { + onSettingsBooleanChanged( + v, + SettingsProvider.SETTINGS_UI_HOMESCREEN_SEARCH_SCREEN_LEFT, + R.bool.preferences_interface_homescreen_search_screen_left_default); + mLauncher.updateDynamicGrid(); + } + } else if (value.equals(res + .getString(R.string.grid_size_text))) { + mLauncher.onClickDynamicGridSizeButton(); + } + + View defaultHome = mLauncher.findViewById(R.id.default_home_screen_panel); + defaultHome.setVisibility(getCursor(0).getCount() > 1 ? View.VISIBLE : View.GONE); + } + }; + + private void onSettingsBooleanChanged(View v, String key, int res) { + boolean current = SettingsProvider.getBoolean( + mContext, key, res); + + // Set new state + SharedPreferences sharedPref = SettingsProvider + .get(mContext); + sharedPref.edit().putBoolean(key, !current).commit(); + sharedPref.edit() + .putBoolean(SettingsProvider.SETTINGS_CHANGED, true) + .commit(); + + String state = current ? mLauncher.getResources().getString( + R.string.setting_state_off) : mLauncher.getResources().getString( + R.string.setting_state_on); + ((TextView) v.findViewById(R.id.item_state)).setText(state); + } + + private void onIconLabelsBooleanChanged(View v, String key, int res) { + boolean current = SettingsProvider.getBoolean( + mContext, key, res); + + // Set new state + SharedPreferences sharedPref = SettingsProvider + .get(mContext); + sharedPref.edit().putBoolean(key, !current).commit(); + sharedPref.edit() + .putBoolean(SettingsProvider.SETTINGS_CHANGED, true) + .commit(); + + String state = current ? mLauncher.getResources().getString( + R.string.icon_labels_show) : mLauncher.getResources().getString( + R.string.icon_labels_hide); + ((TextView) v.findViewById(R.id.item_state)).setText(state); + } + + private void onClickTransitionEffectButton() { + int sort = SettingsProvider.getIntCustomDefault(mLauncher, + SettingsProvider.SETTINGS_UI_DRAWER_SORT_MODE, 0); + + sort = (sort + 1) % AppsCustomizePagedView.SortMode.values().length; + mLauncher.getAppsCustomizeContent().setSortMode( + AppsCustomizePagedView.SortMode.getModeForValue(sort)); + + SettingsProvider.putInt(mLauncher, SettingsProvider.SETTINGS_UI_DRAWER_SORT_MODE, sort); + + notifyDataSetChanged(); + } +} diff --git a/src/com/android/launcher3/settings/FontStylePreference.java b/src/com/android/launcher3/settings/FontStylePreference.java deleted file mode 100644 index 50df4b280..000000000 --- a/src/com/android/launcher3/settings/FontStylePreference.java +++ /dev/null @@ -1,142 +0,0 @@ -package com.android.launcher3.settings; - -import android.app.AlertDialog; -import android.content.Context; -import android.content.DialogInterface; -import android.graphics.Typeface; -import android.preference.ListPreference; -import android.text.TextUtils; -import android.util.AttributeSet; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.*; -import com.android.launcher3.R; - -import java.util.Arrays; -import java.util.List; - -public class FontStylePreference extends ListPreference { - private String mValue; - public int mClickedDialogEntryIndex; - private boolean mValueSet; - - public FontStylePreference(Context context, AttributeSet attrs) { - super(context, attrs); - } - - @Override - protected void onPrepareDialogBuilder(AlertDialog.Builder builder) { - if (getEntries() == null || getEntryValues() == null) { - throw new IllegalStateException( - "ListPreference requires an entries array and an entryValues array."); - } - - mClickedDialogEntryIndex = getValueIndex(); - builder.setSingleChoiceItems(new FontStyleAdapter(getContext()), mClickedDialogEntryIndex, - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - mClickedDialogEntryIndex = which; - - /* - * Clicking on an item simulates the positive button - * click, and dismisses the dialog. - */ - FontStylePreference.this.onClick(dialog, DialogInterface.BUTTON_POSITIVE); - dialog.dismiss(); - } - }); - - /* - * The typical interaction for list-based dialogs is to have - * click-on-an-item dismiss the dialog instead of the user having to - * press 'Ok'. - */ - builder.setPositiveButton(null, null); - } - - @Override - protected void onDialogClosed(boolean positiveResult) { - super.onDialogClosed(positiveResult); - - if (positiveResult && mClickedDialogEntryIndex >= 0 && getEntryValues() != null) { - String value = getEntryValues()[mClickedDialogEntryIndex].toString(); - if (callChangeListener(value)) { - setValue(value); - } - } - } - - @Override - protected void onSetInitialValue(boolean restoreValue, Object defaultValue) { - setValue(restoreValue ? getPersistedString(mValue) : (String) defaultValue); - } - - /** - * Sets the value of the key. This should be one of the entries in - * {@link #getEntryValues()}. - * - * @param value The value to set for the key. - */ - @Override - public void setValue(String value) { - // Always persist/notify the first time. - final boolean changed = !TextUtils.equals(mValue, value); - if (changed || !mValueSet) { - mValue = value; - mValueSet = true; - persistString(value); - if (changed) { - notifyChanged(); - } - } - } - - /** - * Returns the value of the key. This should be one of the entries in - * {@link #getEntryValues()}. - * - * @return The value of the key. - */ - @Override - public String getValue() { - return mValue; - } - - private int getValueIndex() { - return findIndexOfValue(mValue); - } - - private class FontStyleAdapter extends ArrayAdapter<CharSequence> { - private LayoutInflater mInflater; - private List<CharSequence> mEntries; - private List<CharSequence> mValues; - - public FontStyleAdapter(Context context) { - super(context, -1, getEntryValues()); - - mInflater = LayoutInflater.from(context); - mEntries = Arrays.asList(getEntries()); - mValues = Arrays.asList(getEntryValues()); - } - - @Override - public View getView(int position, View convertView, ViewGroup parent) { - CheckedTextView textView; - - if (convertView == null) { - textView = (CheckedTextView) mInflater.inflate(R.layout.list_item_checkable, parent, false); - } else { - textView = (CheckedTextView) convertView; - } - - if (textView != null) { - textView.setText(mEntries.get(position)); - textView.setTag(mValues.get(position)); - textView.setTypeface(Typeface.create((String) mValues.get(position), Typeface.NORMAL)); - } - - return textView; - } - } -} diff --git a/src/com/android/launcher3/settings/HiddenAppsActivity.java b/src/com/android/launcher3/settings/HiddenAppsActivity.java deleted file mode 100644 index 57ea7bc36..000000000 --- a/src/com/android/launcher3/settings/HiddenAppsActivity.java +++ /dev/null @@ -1,302 +0,0 @@ -package com.android.launcher3.settings; - -import android.app.ListActivity; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import android.graphics.drawable.Drawable; -import android.os.AsyncTask; -import android.os.Bundle; -import android.util.Log; -import android.util.SparseBooleanArray; -import android.view.LayoutInflater; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.view.Window; -import android.widget.ArrayAdapter; -import android.widget.ImageView; -import android.widget.ListView; -import android.widget.TextView; - -import com.android.launcher3.R; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.ConcurrentHashMap; - -public class HiddenAppsActivity extends ListActivity { - - private boolean mSaved; - - private static final int MENU_RESET = 0; - - private PackageManager mPackageManager; - - private AppsAdapter mAppsAdapter; - - protected void onCreate(Bundle savedInstanceState) { - requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS); - super.onCreate(savedInstanceState); - - setTitle(R.string.hidden_apps_title); - setContentView(R.layout.hidden_apps_list); - - getActionBar().setDisplayHomeAsUpEnabled(true); - setProgressBarIndeterminateVisibility(true); - setProgressBarIndeterminate(true); - - mPackageManager = getPackageManager(); - mAppsAdapter = new AppsAdapter(this, R.layout.hidden_apps_list_item); - mAppsAdapter.setNotifyOnChange(true); - - setListAdapter(mAppsAdapter); - - AsyncTask<Void, Void, List<AppEntry>> refreshAppsTask = new AsyncTask<Void, Void, List<AppEntry>>() { - - @Override - protected void onPostExecute(List<AppEntry> apps) { - mAppsAdapter.clear(); - mAppsAdapter.addAll(apps); - restoreCheckedItems(); - setProgressBarIndeterminateVisibility(false); - setProgressBarIndeterminate(false); - } - - @Override - protected List<AppEntry> doInBackground(Void... params) { - return refreshApps(); - } - }; - refreshAppsTask.execute(null, null, null); - } - - @Override - public void onPause() { - super.onPause(); - save(); - } - - private void save() { - if (mSaved) { - return; - } - String string = ""; - - SparseBooleanArray checked = getListView().getCheckedItemPositions(); - - AppsAdapter listAdapter = (AppsAdapter) getListAdapter(); - for (int i = 0; i < checked.size(); i++) { - if (checked.valueAt(i)) { - AppEntry app = listAdapter.getItem(checked.keyAt(i)); - if (!string.isEmpty()) - string += "|"; - string += app.componentName.flattenToString(); - } - } - - SharedPreferences.Editor editor = SettingsProvider.get(this).edit(); - editor.putString(SettingsProvider.SETTINGS_UI_DRAWER_HIDDEN_APPS, string); - editor.putBoolean(SettingsProvider.SETTINGS_CHANGED, true); - editor.apply(); - - mSaved = true; - } - - private void restoreCheckedItems() { - List<ComponentName> apps = new ArrayList<ComponentName>(); - String[] flattened = SettingsProvider.getStringCustomDefault(this, - SettingsProvider.SETTINGS_UI_DRAWER_HIDDEN_APPS, "").split("\\|"); - for (String flat : flattened) { - apps.add(ComponentName.unflattenFromString(flat)); - } - - AppsAdapter listAdapter = (AppsAdapter) getListAdapter(); - - for (int i = 0; i < listAdapter.getCount(); i++) { - AppEntry info = listAdapter.getItem(i); - if (apps.contains(info.componentName)) { - getListView().setItemChecked(i, true); - } - } - - mSaved = true; - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - menu.add(0, MENU_RESET, 0, R.string.menu_hidden_apps_delete) - .setShowAsActionFlags(MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_WITH_TEXT); - - return true; - } - - private void reset() { - for (int i = 0; i < getListView().getCount(); i++) { - getListView().setItemChecked(i, false); - } - - mSaved = false; - } - - private List<AppEntry> refreshApps() { - Intent mainIntent = new Intent(Intent.ACTION_MAIN, null); - mainIntent.addCategory(Intent.CATEGORY_LAUNCHER); - List<ResolveInfo> apps = mPackageManager.queryIntentActivities(mainIntent, 0); - Collections.sort(apps, new ResolveInfo.DisplayNameComparator(mPackageManager)); - List<AppEntry> appEntries = new ArrayList<AppEntry>(apps.size()); - for (ResolveInfo info : apps) { - appEntries.add(new AppEntry(info)); - } - return appEntries; - } - - @Override - public boolean onMenuItemSelected(int featureId, MenuItem item) { - if (item.getItemId() == android.R.id.home) { - finish(); - return true; - } else if (item.getItemId() == MENU_RESET) { - reset(); - return true; - } - return super.onMenuItemSelected(featureId, item); - } - - @Override - protected void onListItemClick(ListView l, View v, int position, long id) { - mSaved = false; - } - - private final class AppEntry { - - public final ComponentName componentName; - public final String title; - - public AppEntry(ResolveInfo info) { - componentName = new ComponentName(info.activityInfo.packageName, info.activityInfo.name); - title = info.loadLabel(mPackageManager).toString(); - } - } - - /** - * App view holder used to reuse the views inside the list. - */ - private static class AppViewHolder { - public final TextView title; - public final ImageView icon; - - public AppViewHolder(View parentView) { - icon = (ImageView) parentView.findViewById(R.id.icon); - title = (TextView) parentView.findViewById(R.id.title); - } - } - - public class AppsAdapter extends ArrayAdapter<AppEntry> { - - private final LayoutInflater mInflator; - - private ConcurrentHashMap<String, Drawable> mIcons; - private Drawable mDefaultImg; - private List<AppEntry> mApps; - - public AppsAdapter(Context context, int textViewResourceId) { - super(context, textViewResourceId); - - mApps = new ArrayList<AppEntry>(); - - mInflator = LayoutInflater.from(context); - - // set the default icon till the actual app icon is loaded in async - // task - mDefaultImg = context.getResources().getDrawable(android.R.mipmap.sym_def_app_icon); - mIcons = new ConcurrentHashMap<String, Drawable>(); - } - - @Override - public View getView(final int position, View convertView, ViewGroup parent) { - AppViewHolder viewHolder; - - if (convertView == null) { - convertView = mInflator.inflate(R.layout.hidden_apps_list_item, parent, false); - viewHolder = new AppViewHolder(convertView); - convertView.setTag(viewHolder); - } else { - viewHolder = (AppViewHolder) convertView.getTag(); - } - - AppEntry app = getItem(position); - - viewHolder.title.setText(app.title); - - Drawable icon = mIcons.get(app.componentName.getPackageName()); - viewHolder.icon.setImageDrawable(icon != null ? icon : mDefaultImg); - - return convertView; - } - - @Override - public boolean hasStableIds() { - return true; - } - - @Override - public void notifyDataSetChanged() { - super.notifyDataSetChanged(); - // If we have new items, we have to load their icons - // If items were deleted, remove them from our mApps - List<AppEntry> newApps = new ArrayList<AppEntry>(getCount()); - List<AppEntry> oldApps = new ArrayList<AppEntry>(getCount()); - for (int i = 0; i < getCount(); i++) { - AppEntry app = getItem(i); - if (mApps.contains(app)) { - oldApps.add(app); - } else { - newApps.add(app); - } - } - - if (newApps.size() > 0) { - new LoadIconsTask().execute(newApps.toArray(new AppEntry[] {})); - newApps.addAll(oldApps); - mApps = newApps; - } else { - mApps = oldApps; - } - } - - /** - * An asynchronous task to load the icons of the installed applications. - */ - private class LoadIconsTask extends AsyncTask<AppEntry, Void, Void> { - @Override - protected Void doInBackground(AppEntry... apps) { - for (AppEntry app : apps) { - try { - if (mIcons.containsKey(app.componentName.getPackageName())) { - continue; - } - Drawable icon = mPackageManager.getApplicationIcon(app.componentName - .getPackageName()); - mIcons.put(app.componentName.getPackageName(), icon); - publishProgress(); - } catch (PackageManager.NameNotFoundException e) { - // ignored; app will show up with default image - } - } - - return null; - } - - @Override - protected void onProgressUpdate(Void... progress) { - notifyDataSetChanged(); - } - } - } -} diff --git a/src/com/android/launcher3/settings/SettingsActivity.java b/src/com/android/launcher3/settings/SettingsActivity.java deleted file mode 100644 index dbbf95f52..000000000 --- a/src/com/android/launcher3/settings/SettingsActivity.java +++ /dev/null @@ -1,274 +0,0 @@ -/* - * Copyright (C) 2013 The CyanogenMod 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.android.launcher3.settings; - -import android.content.Context; -import android.content.SharedPreferences; -import android.os.Bundle; -import android.preference.*; -import android.text.TextUtils; -import android.view.MenuItem; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ArrayAdapter; -import android.widget.ImageView; -import android.widget.ListAdapter; -import android.widget.TextView; -import com.android.launcher3.R; - -import java.util.ArrayList; -import java.util.List; - -public class SettingsActivity extends PreferenceActivity - implements SharedPreferences.OnSharedPreferenceChangeListener { - private static final String TAG = "Launcher3.SettingsActivity"; - - private SharedPreferences mSettings; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - mSettings = getSharedPreferences(SettingsProvider.SETTINGS_KEY, - Context.MODE_PRIVATE); - - getActionBar().setDisplayHomeAsUpEnabled(true); - } - - @Override - public SharedPreferences getSharedPreferences(String name, int mode) { - return super.getSharedPreferences(SettingsProvider.SETTINGS_KEY, - Context.MODE_PRIVATE); - } - - @Override - protected void onResume() { - super.onResume(); - mSettings.registerOnSharedPreferenceChangeListener(this); - } - - @Override - protected void onPause() { - super.onPause(); - mSettings.unregisterOnSharedPreferenceChangeListener(this); - } - - @Override - public boolean isValidFragment(String fragmentName) { - return true; - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case android.R.id.home: - onBackPressed(); - finish(); - return true; - default: - break; - } - return super.onOptionsItemSelected(item); - } - - @Override - public void onBuildHeaders(List<Header> target) { - loadHeadersFromResource(R.xml.preferences_headers, target); - updateHeaders(target); - } - - private void updateHeaders(List<Header> headers) { - int i = 0; - while (i < headers.size()) { - Header header = headers.get(i); - - // Version preference - if (header.id == R.id.preferences_application_version) { - header.title = getString(R.string.cm_application_name) + " " + getString(R.string.application_version); - } - - // Increment if not removed - if (headers.get(i) == header) { - i++; - } - } - } - - @Override - public void setListAdapter(ListAdapter adapter) { - if (adapter == null) { - super.setListAdapter(null); - } else { - List<Header> headers = getHeadersFromAdapter(adapter); - super.setListAdapter(new HeaderAdapter(this, headers)); - } - } - - @Override - public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { - SharedPreferences.Editor editor = mSettings.edit(); - editor.putBoolean(SettingsProvider.SETTINGS_CHANGED, true); - editor.commit(); - } - - private List<Header> getHeadersFromAdapter(ListAdapter adapter) { - List<Header> headers = new ArrayList<Header>(); - int count = adapter.getCount(); - for (int i = 0; i < count; i++) { - headers.add((Header)adapter.getItem(i)); - } - return headers; - } - - public static class HomescreenFragment extends PreferenceFragment { - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - addPreferencesFromResource(R.xml.preferences_homescreen); - } - } - - public static class GeneralFragment extends PreferenceFragment { - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - addPreferencesFromResource(R.xml.preferences_general); - } - } - - public static class DrawerFragment extends PreferenceFragment { - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - addPreferencesFromResource(R.xml.preferences_drawer); - } - } - - private static class HeaderAdapter extends ArrayAdapter<Header> { - private static final int HEADER_TYPE_NORMAL = 0; - private static final int HEADER_TYPE_CATEGORY = 1; - - private static final int HEADER_TYPE_COUNT = HEADER_TYPE_CATEGORY + 1; - - private static class HeaderViewHolder { - ImageView icon; - TextView title; - TextView summary; - } - - private LayoutInflater mInflater; - - static int getHeaderType(Header header) { - if (header.id == R.id.preferences_application_section) { - return HEADER_TYPE_CATEGORY; - } else { - return HEADER_TYPE_NORMAL; - } - } - - @Override - public int getItemViewType(int position) { - Header header = getItem(position); - return getHeaderType(header); - } - - @Override - public boolean areAllItemsEnabled() { - return false; // because of categories - } - - @Override - public boolean isEnabled(int position) { - return getItemViewType(position) != HEADER_TYPE_CATEGORY; - } - - @Override - public int getViewTypeCount() { - return HEADER_TYPE_COUNT; - } - - @Override - public boolean hasStableIds() { - return true; - } - - public HeaderAdapter(Context context, List<Header> objects) { - super(context, 0, objects); - - mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - } - - @Override - public View getView(int position, View convertView, ViewGroup parent) { - HeaderViewHolder holder; - Header header = getItem(position); - int headerType = getHeaderType(header); - View view = null; - - if (convertView == null) { - holder = new HeaderViewHolder(); - switch (headerType) { - case HEADER_TYPE_CATEGORY: - view = new TextView(getContext(), null, - android.R.attr.listSeparatorTextViewStyle); - holder.title = (TextView) view; - break; - - case HEADER_TYPE_NORMAL: - view = mInflater.inflate( - R.layout.preference_header_item, parent, - false); - holder.icon = (ImageView) view.findViewById(android.R.id.icon); - holder.title = (TextView) - view.findViewById(android.R.id.title); - holder.summary = (TextView) - view.findViewById(android.R.id.summary); - break; - } - view.setTag(holder); - } else { - view = convertView; - holder = (HeaderViewHolder) view.getTag(); - } - - // All view fields must be updated every time, because the view may be recycled - switch (headerType) { - case HEADER_TYPE_CATEGORY: - holder.title.setText(header.getTitle(getContext().getResources())); - break; - - case HEADER_TYPE_NORMAL: - holder.icon.setImageResource(header.iconRes); - holder.title.setText(header.getTitle(getContext().getResources())); - CharSequence summary = header.getSummary(getContext().getResources()); - if (!TextUtils.isEmpty(summary)) { - holder.summary.setVisibility(View.VISIBLE); - holder.summary.setText(summary); - } else { - holder.summary.setVisibility(View.GONE); - } - break; - } - - return view; - } - } -} diff --git a/src/com/android/launcher3/settings/SettingsProvider.java b/src/com/android/launcher3/settings/SettingsProvider.java index abf4e1b67..32329ab83 100644 --- a/src/com/android/launcher3/settings/SettingsProvider.java +++ b/src/com/android/launcher3/settings/SettingsProvider.java @@ -26,21 +26,24 @@ public final class SettingsProvider { public static final String SETTINGS_UI_HOMESCREEN_DEFAULT_SCREEN_ID = "ui_homescreen_default_screen_id"; public static final String SETTINGS_UI_HOMESCREEN_SEARCH = "ui_homescreen_search"; + public static final String SETTINGS_UI_HOMESCREEN_SEARCH_SCREEN_LEFT = "ui_homescreen_search_screen_left"; public static final String SETTINGS_UI_HOMESCREEN_HIDE_ICON_LABELS = "ui_homescreen_general_hide_icon_labels"; public static final String SETTINGS_UI_HOMESCREEN_SCROLLING_TRANSITION_EFFECT = "ui_homescreen_scrolling_transition_effect"; public static final String SETTINGS_UI_HOMESCREEN_SCROLLING_WALLPAPER_SCROLL = "ui_homescreen_scrolling_wallpaper_scroll"; public static final String SETTINGS_UI_HOMESCREEN_SCROLLING_PAGE_OUTLINES = "ui_homescreen_scrolling_page_outlines"; public static final String SETTINGS_UI_HOMESCREEN_SCROLLING_FADE_ADJACENT = "ui_homescreen_scrolling_fade_adjacent"; + public static final String SETTINGS_UI_DYNAMIC_GRID_SIZE = "ui_dynamic_grid_size"; + public static final String SETTINGS_UI_HOMESCREEN_ROWS = "ui_homescreen_rows"; + public static final String SETTINGS_UI_HOMESCREEN_COLUMNS = "ui_homescreen_columns"; public static final String SETTINGS_UI_DRAWER_SCROLLING_TRANSITION_EFFECT = "ui_drawer_scrolling_transition_effect"; public static final String SETTINGS_UI_DRAWER_SCROLLING_FADE_ADJACENT = "ui_drawer_scrolling_fade_adjacent"; - public static final String SETTINGS_UI_DRAWER_HIDDEN_APPS = "ui_drawer_hidden_apps"; public static final String SETTINGS_UI_DRAWER_REMOVE_HIDDEN_APPS_SHORTCUTS = "ui_drawer_remove_hidden_apps_shortcuts"; public static final String SETTINGS_UI_DRAWER_REMOVE_HIDDEN_APPS_WIDGETS = "ui_drawer_remove_hidden_apps_widgets"; public static final String SETTINGS_UI_DRAWER_HIDE_ICON_LABELS = "ui_drawer_hide_icon_labels"; public static final String SETTINGS_UI_GENERAL_ICONS_LARGE = "ui_general_icons_large"; - public static final String SETTINGS_UI_GENERAL_ICONS_TEXT_FONT_FAMILY = "ui_general_icons_text_font"; - public static final String SETTINGS_UI_GENERAL_ICONS_TEXT_FONT_STYLE = "ui_general_icons_text_font_style"; - public static final String SETTINGS_UI_GENERAL_ICONS_ICON_PACK = "ui_general_iconpack"; + public static final String SETTINGS_UI_DRAWER_SORT_MODE = "ui_drawer_sort_mode"; + + public static final String SETTINGS_HOME_LAST_APP = "home_last_app"; public static SharedPreferences get(Context context) { return context.getSharedPreferences(SETTINGS_KEY, Context.MODE_MULTI_PROCESS); @@ -81,4 +84,8 @@ public final class SettingsProvider { public static void putString(Context context, String key, String value) { get(context).edit().putString(key, value).commit(); } + + public static void putInt(Context context, String key, int value) { + get(context).edit().putInt(key, value).commit(); + } } diff --git a/src/com/android/photos/BitmapRegionTileSource.java b/src/com/android/photos/BitmapRegionTileSource.java deleted file mode 100644 index 4d1a84ed7..000000000 --- a/src/com/android/photos/BitmapRegionTileSource.java +++ /dev/null @@ -1,288 +0,0 @@ -/* - * Copyright (C) 2013 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.android.photos; - -import android.annotation.TargetApi; -import android.content.Context; -import android.content.res.AssetManager; -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.graphics.Bitmap.Config; -import android.graphics.BitmapFactory; -import android.graphics.BitmapRegionDecoder; -import android.graphics.Canvas; -import android.graphics.Rect; -import android.net.Uri; -import android.os.Build; -import android.os.Build.VERSION_CODES; -import android.util.Log; - -import com.android.gallery3d.common.BitmapUtils; -import com.android.gallery3d.glrenderer.BasicTexture; -import com.android.gallery3d.glrenderer.BitmapTexture; -import com.android.photos.views.TiledImageRenderer; - -import java.io.BufferedInputStream; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; - -/** - * A {@link com.android.photos.views.TiledImageRenderer.TileSource} using - * {@link BitmapRegionDecoder} to wrap a local file - */ -@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) -public class BitmapRegionTileSource implements TiledImageRenderer.TileSource { - - private static final String TAG = "BitmapRegionTileSource"; - - private static final boolean REUSE_BITMAP = - Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN; - private static final int GL_SIZE_LIMIT = 2048; - // This must be no larger than half the size of the GL_SIZE_LIMIT - // due to decodePreview being allowed to be up to 2x the size of the target - private static final int MAX_PREVIEW_SIZE = 1024; - - BitmapRegionDecoder mDecoder; - int mWidth; - int mHeight; - int mTileSize; - private BasicTexture mPreview; - private final int mRotation; - - // For use only by getTile - private Rect mWantRegion = new Rect(); - private Rect mOverlapRegion = new Rect(); - private BitmapFactory.Options mOptions; - private Canvas mCanvas; - - public BitmapRegionTileSource(Context context, String path, int previewSize, int rotation) { - this(null, context, path, null, 0, previewSize, rotation, false); - } - - public BitmapRegionTileSource(Resources res, Context context, String path, int previewSize, int rotation, boolean assetPath) { - this(res, context, path, null, 0, previewSize, rotation, assetPath); - } - - public BitmapRegionTileSource(Context context, Uri uri, int previewSize, int rotation) { - this(null, context, null, uri, 0, previewSize, rotation, false); - } - - public BitmapRegionTileSource(Resources res, - Context context, int resId, int previewSize, int rotation) { - this(res, context, null, null, resId, previewSize, rotation, false); - } - - private BitmapRegionTileSource(Resources res, - Context context, String path, Uri uri, int resId, int previewSize, int rotation, boolean assetPath) { - mTileSize = TiledImageRenderer.suggestedTileSize(context); - mRotation = rotation; - try { - if (path != null && !assetPath) { - mDecoder = BitmapRegionDecoder.newInstance(path, true); - } else if (path != null && res != null && assetPath) { - AssetManager am = res.getAssets(); - String[] pathImages = am.list(path); - if (pathImages == null || pathImages.length == 0) { - throw new IOException("did not find any images in path: " + path); - } - InputStream is = am.open(path + File.separator + pathImages[0]); - BufferedInputStream bis = new BufferedInputStream(is); - mDecoder = BitmapRegionDecoder.newInstance(bis, true); - } else if (uri != null) { - InputStream is = context.getContentResolver().openInputStream(uri); - BufferedInputStream bis = new BufferedInputStream(is); - mDecoder = BitmapRegionDecoder.newInstance(bis, true); - } else { - InputStream is = res.openRawResource(resId); - BufferedInputStream bis = new BufferedInputStream(is); - mDecoder = BitmapRegionDecoder.newInstance(bis, true); - } - mWidth = mDecoder.getWidth(); - mHeight = mDecoder.getHeight(); - } catch (IOException e) { - Log.w("BitmapRegionTileSource", "ctor failed", e); - } - mOptions = new BitmapFactory.Options(); - mOptions.inPreferredConfig = Bitmap.Config.ARGB_8888; - mOptions.inPreferQualityOverSpeed = true; - mOptions.inTempStorage = new byte[16 * 1024]; - if (previewSize != 0) { - previewSize = Math.min(previewSize, MAX_PREVIEW_SIZE); - // Although this is the same size as the Bitmap that is likely already - // loaded, the lifecycle is different and interactions are on a different - // thread. Thus to simplify, this source will decode its own bitmap. - Bitmap preview = decodePreview(res, context, path, uri, resId, previewSize, assetPath); - if (preview.getWidth() <= GL_SIZE_LIMIT && preview.getHeight() <= GL_SIZE_LIMIT) { - mPreview = new BitmapTexture(preview); - } else { - Log.w(TAG, String.format( - "Failed to create preview of apropriate size! " - + " in: %dx%d, out: %dx%d", - mWidth, mHeight, - preview.getWidth(), preview.getHeight())); - } - } - } - - @Override - public int getTileSize() { - return mTileSize; - } - - @Override - public int getImageWidth() { - return mWidth; - } - - @Override - public int getImageHeight() { - return mHeight; - } - - @Override - public BasicTexture getPreview() { - return mPreview; - } - - @Override - public int getRotation() { - return mRotation; - } - - @Override - public Bitmap getTile(int level, int x, int y, Bitmap bitmap) { - int tileSize = getTileSize(); - if (!REUSE_BITMAP) { - return getTileWithoutReusingBitmap(level, x, y, tileSize); - } - - int t = tileSize << level; - mWantRegion.set(x, y, x + t, y + t); - - if (bitmap == null) { - bitmap = Bitmap.createBitmap(tileSize, tileSize, Bitmap.Config.ARGB_8888); - } - - mOptions.inSampleSize = (1 << level); - mOptions.inBitmap = bitmap; - - try { - bitmap = mDecoder.decodeRegion(mWantRegion, mOptions); - } finally { - if (mOptions.inBitmap != bitmap && mOptions.inBitmap != null) { - mOptions.inBitmap = null; - } - } - - if (bitmap == null) { - Log.w("BitmapRegionTileSource", "fail in decoding region"); - } - return bitmap; - } - - private Bitmap getTileWithoutReusingBitmap( - int level, int x, int y, int tileSize) { - - int t = tileSize << level; - mWantRegion.set(x, y, x + t, y + t); - - mOverlapRegion.set(0, 0, mWidth, mHeight); - - mOptions.inSampleSize = (1 << level); - Bitmap bitmap = mDecoder.decodeRegion(mOverlapRegion, mOptions); - - if (bitmap == null) { - Log.w(TAG, "fail in decoding region"); - } - - if (mWantRegion.equals(mOverlapRegion)) { - return bitmap; - } - - Bitmap result = Bitmap.createBitmap(tileSize, tileSize, Config.ARGB_8888); - if (mCanvas == null) { - mCanvas = new Canvas(); - } - mCanvas.setBitmap(result); - mCanvas.drawBitmap(bitmap, - (mOverlapRegion.left - mWantRegion.left) >> level, - (mOverlapRegion.top - mWantRegion.top) >> level, null); - mCanvas.setBitmap(null); - return result; - } - - /** - * Note that the returned bitmap may have a long edge that's longer - * than the targetSize, but it will always be less than 2x the targetSize - */ - private Bitmap decodePreview( - Resources res, Context context, String file, Uri uri, int resId, int targetSize, boolean assetPath) { - float scale = (float) targetSize / Math.max(mWidth, mHeight); - mOptions.inSampleSize = BitmapUtils.computeSampleSizeLarger(scale); - mOptions.inJustDecodeBounds = false; - - Bitmap result = null; - if (file != null && res != null && assetPath) { - try { - AssetManager am = res.getAssets(); - String[] pathImages = am.list(file); - if (pathImages == null || pathImages.length == 0) { - throw new IOException("did not find any images in path: " + file); - } - InputStream is = am.open(file + File.separator + pathImages[0]); - BufferedInputStream bis = new BufferedInputStream(is); - result = BitmapFactory.decodeStream(bis, null, mOptions); - } catch (IOException e) { - Log.w("BitmapRegionTileSource", "getting preview failed", e); - } - } else if (file != null) { - result = BitmapFactory.decodeFile(file, mOptions); - } else if (uri != null) { - try { - InputStream is = context.getContentResolver().openInputStream(uri); - BufferedInputStream bis = new BufferedInputStream(is); - result = BitmapFactory.decodeStream(bis, null, mOptions); - } catch (IOException e) { - Log.w("BitmapRegionTileSource", "getting preview failed", e); - } - } else { - result = BitmapFactory.decodeResource(res, resId, mOptions); - } - if (result == null) { - return null; - } - - // We need to resize down if the decoder does not support inSampleSize - // or didn't support the specified inSampleSize (some decoders only do powers of 2) - scale = (float) targetSize / (float) (Math.max(result.getWidth(), result.getHeight())); - - if (scale <= 0.5) { - result = BitmapUtils.resizeBitmapByScale(result, scale, true); - } - return ensureGLCompatibleBitmap(result); - } - - private static Bitmap ensureGLCompatibleBitmap(Bitmap bitmap) { - if (bitmap == null || bitmap.getConfig() != null) { - return bitmap; - } - Bitmap newBitmap = bitmap.copy(Config.ARGB_8888, false); - bitmap.recycle(); - return newBitmap; - } -} diff --git a/src/org/cyanogenmod/trebuchet/TrebuchetLauncher.java b/src/org/cyanogenmod/trebuchet/TrebuchetLauncher.java new file mode 100644 index 000000000..3c5e6a70b --- /dev/null +++ b/src/org/cyanogenmod/trebuchet/TrebuchetLauncher.java @@ -0,0 +1,331 @@ +/* + * Copyright (C) 2014 The CyanogenMod 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 org.cyanogenmod.trebuchet; + +import android.content.BroadcastReceiver; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.res.Resources; +import android.graphics.Color; +import android.graphics.PorterDuff; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.util.Log; +import android.util.SparseArray; +import android.view.animation.AccelerateInterpolator; +import android.widget.ImageView; + +import com.android.launcher.home.Home; +import com.android.launcher3.Launcher; +import com.android.launcher3.R; + +import org.cyanogenmod.trebuchet.home.HomeUtils; +import org.cyanogenmod.trebuchet.home.HomeWrapper; + +import java.lang.Override; + +public class TrebuchetLauncher extends Launcher { + + private static final String TAG = "TrebuchetLauncher"; + + private static final boolean DEBUG = false; + private static final float MIN_PROGRESS = 0; + private static final float MAX_PROGRESS = 1; + + + private static class HomeAppStub { + private final int mUid; + private final ComponentName mComponentName; + private final HomeWrapper mInstance; + + private HomeAppStub(int uid, ComponentName componentName, Context context) + throws SecurityException, ReflectiveOperationException { + super(); + mUid = uid; + mComponentName = componentName; + + // Load a new instance of the Home app + ClassLoader classloader = context.getClassLoader(); + Class<?> homeInterface = classloader.loadClass(Home.class.getName()); + Class<?> homeClazz = classloader.loadClass(mComponentName.getClassName()); + mInstance = new HomeWrapper(context, homeInterface, homeClazz.newInstance()); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((mComponentName == null) ? 0 : mComponentName.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + HomeAppStub other = (HomeAppStub) obj; + if (mComponentName == null) { + if (other.mComponentName != null) + return false; + } else if (!mComponentName.equals(other.mComponentName)) + return false; + return true; + } + } + + private BroadcastReceiver mPackageReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + // Obtain the current instance or a new one if the current instance not exists + boolean invalidate = false; + String action = intent.getAction(); + if (action.equals(Intent.ACTION_PACKAGE_CHANGED) || + action.equals(Intent.ACTION_PACKAGE_REPLACED) || + action.equals(Intent.ACTION_PACKAGE_RESTARTED)) { + if (mCurrentHomeApp != null && intent.getIntExtra(Intent.EXTRA_UID, -1) + == mCurrentHomeApp.mUid) { + // The current Home app has changed or restarted. Invalidate the current + // one to be sure we will get all the new changes (if any) + if (DEBUG) Log.d(TAG, "Home package has changed. Invalidate layout."); + invalidate = true; + } + } + obtainCurrentHomeAppStubLocked(invalidate); + } + }; + + private CustomContentCallbacks mCustomContentCallbacks = new CustomContentCallbacks() { + @Override + public void onShow() { + if (mCurrentHomeApp != null) { + mCurrentHomeApp.mInstance.onShow(); + } + } + + @Override + public void onScrollProgressChanged(float progress) { + updateQsbBarColorState(progress); + if (mCurrentHomeApp != null) { + mCurrentHomeApp.mInstance.onScrollProgressChanged(progress); + } + } + + @Override + public void onHide() { + if (mCurrentHomeApp != null) { + mCurrentHomeApp.mInstance.onHide(); + } + } + }; + + private HomeAppStub mCurrentHomeApp; + private AccelerateInterpolator mQSBAlphaInterpolator; + + private QSBScroller mQsbScroller; + private int mQsbInitialAlphaState; + private int mQsbEndAlphaState; + private int mQsbButtonsEndColorFilter; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mQSBAlphaInterpolator = new AccelerateInterpolator(); + + // Set QsbBar color state + final Resources res = getResources(); + mQsbInitialAlphaState = res.getInteger(R.integer.qsb_initial_alpha_state); + mQsbEndAlphaState = res.getInteger(R.integer.qsb_end_alpha_state); + mQsbButtonsEndColorFilter = res.getInteger(R.integer.qsb_buttons_end_colorfilter); + updateQsbBarColorState(MIN_PROGRESS); + + // Obtain the user-defined Home app or a valid one + obtainCurrentHomeAppStubLocked(true); + + // Register this class to listen for new/deleted packages + IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED); + filter.addAction(Intent.ACTION_PACKAGE_REMOVED); + filter.addAction(Intent.ACTION_PACKAGE_FULLY_REMOVED); + filter.addAction(Intent.ACTION_PACKAGE_CHANGED); + filter.addAction(Intent.ACTION_PACKAGE_REPLACED); + filter.addAction(Intent.ACTION_PACKAGE_RESTARTED); + filter.addDataScheme("package"); + registerReceiver(mPackageReceiver, filter); + } + + @Override + public void onDestroy() { + super.onDestroy(); + + // Unregister services + unregisterReceiver(mPackageReceiver); + } + + @Override + protected void onResume() { + if (mCurrentHomeApp != null) { + mCurrentHomeApp.mInstance.onResume(); + } + super.onResume(); + } + + @Override + protected void onPause() { + if (mCurrentHomeApp != null) { + mCurrentHomeApp.mInstance.onPause(); + } + super.onPause(); + } + + @Override + protected boolean hasCustomContentToLeft() { + return mCurrentHomeApp != null && super.hasCustomContentToLeft(); + } + + @Override + protected void invalidateHasCustomContentToLeft() { + invalidateHomeStub(); + super.invalidateHasCustomContentToLeft(); + } + + @Override + protected void populateCustomContentContainer() { + if (mCurrentHomeApp != null) { + mQsbScroller = addToCustomContentPage(mCurrentHomeApp.mInstance.createCustomView(), + mCustomContentCallbacks, mCurrentHomeApp.mInstance.getName()); + } + } + + @Override + protected boolean hasCustomSearchSupport() { + return hasCustomContentToLeft() && mCurrentHomeApp.mInstance.isOperationSupported( + Home.FLAG_OP_CUSTOM_SEARCH); + } + + @Override + protected void requestSearch(int mode) { + if (!hasCustomSearchSupport()) { + return; + } + mCurrentHomeApp.mInstance.onRequestSearch(mode); + } + + private synchronized void obtainCurrentHomeAppStubLocked(boolean invalidate) { + if (DEBUG) Log.d(TAG, "obtainCurrentHomeAppStubLocked called (" + invalidate + ")"); + + SparseArray<ComponentName> packages = HomeUtils.getInstalledHomePackages(this); + if (!invalidate && mCurrentHomeApp != null && + packages.get(mCurrentHomeApp.mUid) != null) { + // We still have a valid Home app + return; + } + + // We don't have a valid Home app, so we need to destroy the current the custom content + destroyHomeStub(); + + // Return the default valid home app + int size = packages.size(); + for (int i = 0; i < size; i++) { + int key = packages.keyAt(i); + ComponentName pkg = packages.get(key); + String qualifiedPkg = pkg.toShortString(); + Context ctx = HomeUtils.createNewHomePackageContext(this, pkg); + if (ctx == null) { + // We failed to create a valid context. Will try with the next package + continue; + } + try { + mCurrentHomeApp = new HomeAppStub(key, pkg, ctx); + } catch (ReflectiveOperationException ex) { + if (!DEBUG) { + Log.w(TAG, "Cannot instantiate home package: " + qualifiedPkg + ". Ignored."); + } else { + Log.w(TAG, "Cannot instantiate home package: " + qualifiedPkg + + ". Ignored.", ex); + } + } catch (SecurityException ex) { + if (!DEBUG) { + Log.w(TAG, "Home package is insecure: " + qualifiedPkg + ". Ignored."); + } else { + Log.w(TAG, "Home package is insecure: " + qualifiedPkg + ". Ignored.", ex); + } + } + + // Notify home app that is going to be used + if (mCurrentHomeApp != null) { + mCurrentHomeApp.mInstance.onStart(); + } + } + + // Don't have a valid package. Anyway notify the launcher that custom content has changed + invalidateHasCustomContentToLeft(); + } + + private void invalidateHomeStub() { + if (mCurrentHomeApp != null) { + mCurrentHomeApp.mInstance.onInvalidate(); + if (DEBUG) Log.d(TAG, "Home package " + mCurrentHomeApp.mComponentName.toShortString() + + " was invalidated."); + } + } + + private void destroyHomeStub() { + if (mCurrentHomeApp != null) { + mCurrentHomeApp.mInstance.onInvalidate(); + mCurrentHomeApp.mInstance.onDestroy(); + if (DEBUG) Log.d(TAG, "Home package " + mCurrentHomeApp.mComponentName.toShortString() + + " was destroyed."); + } + mQsbScroller = null; + mCurrentHomeApp = null; + } + + private void updateQsbBarColorState(float progress) { + if (getQsbBar() != null) { + float interpolation = mQSBAlphaInterpolator.getInterpolation(progress); + + // Background alpha + int alphaInterpolation = (int)(mQsbInitialAlphaState + + (interpolation * (mQsbEndAlphaState - mQsbInitialAlphaState))); + Drawable background = getQsbBar().getBackground(); + if (background != null) { + background.setAlpha(alphaInterpolation); + } + + // Buttons color filter + int colorInterpolation = (int)(255 - (interpolation * mQsbButtonsEndColorFilter)); + int color = Color.rgb(colorInterpolation, colorInterpolation,colorInterpolation); + ImageView voiceButton = getQsbBarVoiceButton(); + if (voiceButton != null) { + if (progress > 0) { + voiceButton.setColorFilter(color, PorterDuff.Mode.SRC_IN); + } + } + ImageView searchButton = getQsbBarSearchButton(); + if (searchButton != null) { + if (progress > 0) { + searchButton.setColorFilter(color, PorterDuff.Mode.SRC_IN); + } + } + } + } +} diff --git a/src/org/cyanogenmod/trebuchet/home/HomeUtils.java b/src/org/cyanogenmod/trebuchet/home/HomeUtils.java new file mode 100644 index 000000000..63bf5ff60 --- /dev/null +++ b/src/org/cyanogenmod/trebuchet/home/HomeUtils.java @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2014 The CyanogenMod 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 org.cyanogenmod.trebuchet.home; + +import android.content.ComponentName; +import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.content.pm.PackageManager.NameNotFoundException; +import android.os.Bundle; +import android.util.Log; +import android.util.SparseArray; + +import com.android.launcher.home.Home; + +import java.util.List; + +public class HomeUtils { + + private static final String TAG = "HomeUtils"; + + // FIXME For now for security reason we will only support known Home apps + private static final String[] WELL_KNOWN_HOME_APP_PKGS = + { + "org.cyanogenmod.launcher.home" + }; + + + public static final SparseArray<ComponentName> getInstalledHomePackages(Context context) { + // A Home app should: + // - declare the use of Home.PERMISSION_HOME_APP permission. + // - define the home stub class through the Home.METADATA_HOME_STUB metadata + SparseArray<ComponentName> installedHomePackages = new SparseArray<ComponentName>(); + + PackageManager packageManager = context.getPackageManager(); + + List<PackageInfo> installedPackages = packageManager.getInstalledPackages( + PackageManager.GET_PERMISSIONS); + for (PackageInfo pkg : installedPackages) { + boolean hasHomeAppPermission = false; + if (pkg.requestedPermissions != null) { + for (String perm : pkg.requestedPermissions) { + if (perm.equals(Home.PERMISSION_HOME_APP)) { + hasHomeAppPermission = true; + break; + } + } + } + if (hasHomeAppPermission) { + try { + ApplicationInfo appInfo = packageManager.getApplicationInfo(pkg.packageName, + PackageManager.GET_META_DATA); + Bundle metadata = appInfo.metaData; + if (metadata != null && metadata.containsKey(Home.METADATA_HOME_STUB)) { + String homeStub = metadata.getString(Home.METADATA_HOME_STUB); + installedHomePackages.put(appInfo.uid, + new ComponentName(pkg.packageName, homeStub)); + } + } catch (NameNotFoundException ex) { + // Ignored. The package doesn't exists ¿? + } + } + } + + // FIXME For now we only support known Home apps. Remove this checks when + // Trebuchet allows Home apps through the full Home Host Protocol + if (installedHomePackages.size() > 0) { + for (String pkg : WELL_KNOWN_HOME_APP_PKGS) { + int i = installedHomePackages.size() - 1; + boolean isWellKnownPkg = false; + for (; i >= 0; i--) { + int key = installedHomePackages.keyAt(i); + if (installedHomePackages.get(key).getPackageName().equals(pkg)) { + isWellKnownPkg = true; + break; + } + } + if (!isWellKnownPkg) { + installedHomePackages.removeAt(i); + } + } + } + + return installedHomePackages; + } + + public static Context createNewHomePackageContext(Context ctx, ComponentName pkg) { + // Create a new context package for the current user + try { + return ctx.createPackageContext(pkg.getPackageName(), + Context.CONTEXT_IGNORE_SECURITY | Context.CONTEXT_INCLUDE_CODE); + } catch (NameNotFoundException ex) { + Log.e(TAG, "Failed to load a home package context. Package not found.", ex); + } + return null; + } +} diff --git a/src/org/cyanogenmod/trebuchet/home/HomeWrapper.java b/src/org/cyanogenmod/trebuchet/home/HomeWrapper.java new file mode 100644 index 000000000..df8b6cae6 --- /dev/null +++ b/src/org/cyanogenmod/trebuchet/home/HomeWrapper.java @@ -0,0 +1,236 @@ +/* + * Copyright (C) 2014 The CyanogenMod 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 org.cyanogenmod.trebuchet.home; + +import android.content.Context; +import android.util.Base64; +import android.util.SparseArray; +import android.view.View; + +import com.android.launcher.home.Home; + +import java.lang.reflect.Method; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +public class HomeWrapper { + + private static final int M_ID_ONSTART = 0; + private static final int M_ID_ONDESTROY = 1; + private static final int M_ID_ONRESUME = 2; + private static final int M_ID_ONPAUSE = 3; + private static final int M_ID_ONSHOW = 4; + private static final int M_ID_ONSCROLLPROGRESSCHANGED = 5; + private static final int M_ID_ONHIDE = 6; + private static final int M_ID_ONINVALIDATE = 7; + private static final int M_ID_ONREQUESTSEARCH = 8; + private static final int M_ID_CREATECUSTOMVIEW = 9; + private static final int M_ID_GETNAME = 10; + private static final int M_ID_GETNOTIFICATIONFLAGS = 11; + private static final int M_ID_GETOPERATIONFLAGS = 12; + private static final int M_LAST_ID = M_ID_GETOPERATIONFLAGS + 1; + + private final Context mContext; + private final Class<?> mClass; + private final Object mInstance; + + private final SparseArray<Method> cachedMethods; + + private final int mNotificationFlags; + private final int mOperationFlags; + + public HomeWrapper(Context context, Class<?> cls, Object instance) throws SecurityException { + super(); + mContext = context; + mClass = cls; + mInstance = instance; + cachedMethods = new SparseArray<Method>(M_LAST_ID); + + final String sha1 = createDigest(cls); + if (!sha1.equals(Home.SIGNATURE)) { + throw new SecurityException("The remote Home app doesn't implement " + + "the current Home Host Protocol. Signature: " + sha1); + } + + // Obtain the app flags + mNotificationFlags = getNotificationFlags(); + mOperationFlags = getOperationFlags(); + } + + /** @see Home#onStart(Context) **/ + public void onStart() { + invokeVoidContextMethod(M_ID_ONSTART, "onStart"); + } + + /** @see Home#onDestroy(Context) **/ + public void onDestroy() { + invokeVoidContextMethod(M_ID_ONDESTROY, "onDestroy"); + } + + /** @see Home#onResume(Context) **/ + public void onResume() { + if (!isNotificationSupported(Home.FLAG_NOTIFY_ON_RESUME)) { + return; + } + invokeVoidContextMethod(M_ID_ONRESUME, "onResume"); + } + + /** @see Home#onPause(Context) **/ + public void onPause() { + if (!isNotificationSupported(Home.FLAG_NOTIFY_ON_PAUSE)) { + return; + } + invokeVoidContextMethod(M_ID_ONPAUSE, "onPause"); + } + + /** @see Home#onShow(Context) **/ + public void onShow() { + if (!isNotificationSupported(Home.FLAG_NOTIFY_ON_SHOW)) { + return; + } + invokeVoidContextMethod(M_ID_ONSHOW, "onShow"); + } + + /** @see Home#onScrollProgressChanged(Context, float) **/ + public void onScrollProgressChanged(float progress) { + if (!isNotificationSupported(Home.FLAG_NOTIFY_ON_SCROLL_PROGRESS_CHANGED)) { + return; + } + try { + Method method = cachedMethods.get(M_ID_ONSCROLLPROGRESSCHANGED); + if (method == null) { + method = mClass.getMethod("onScrollProgressChanged", Context.class, float.class); + } + method.invoke(mInstance, mContext, progress); + } catch (ReflectiveOperationException ex) { + throw new SecurityException(ex); + } + } + + /** @see Home#onHide(Context) **/ + public void onHide() { + if (!isNotificationSupported(Home.FLAG_NOTIFY_ON_HIDE)) { + return; + } + invokeVoidContextMethod(M_ID_ONHIDE, "onHide"); + } + + /** @see Home#onInvalidate(Context) **/ + public void onInvalidate() { + invokeVoidContextMethod(M_ID_ONINVALIDATE, "onInvalidate"); + } + + /** + * @see Home#onRequestSearch(Context, int) + */ + public void onRequestSearch(int mode) { + try { + Method method = cachedMethods.get(M_ID_ONREQUESTSEARCH); + if (method == null) { + method = mClass.getMethod("onRequestSearch", Context.class, int.class); + } + method.invoke(mInstance, mContext, mode); + } catch (ReflectiveOperationException ex) { + throw new SecurityException(ex); + } + } + + /** @see Home#createCustomView(Context) **/ + public View createCustomView() { + try { + Method method = cachedMethods.get(M_ID_CREATECUSTOMVIEW); + if (method == null) { + method = mClass.getMethod("createCustomView", Context.class); + } + return (View) method.invoke(mInstance, mContext); + } catch (ReflectiveOperationException ex) { + throw new SecurityException(ex); + } + } + + /** @see Home#getName(Context) **/ + public String getName() { + try { + Method method = cachedMethods.get(M_ID_GETNAME); + if (method == null) { + method = mClass.getMethod("getName", Context.class); + } + return (String) method.invoke(mInstance, mContext); + } catch (ReflectiveOperationException ex) { + throw new SecurityException(ex); + } + } + + /** @see Home#getNotificationFlags() **/ + private int getNotificationFlags() { + try { + Method method = cachedMethods.get(M_ID_GETNOTIFICATIONFLAGS); + if (method == null) { + method = mClass.getMethod("getNotificationFlags"); + } + return (Integer) method.invoke(mInstance); + } catch (ReflectiveOperationException ex) { + return 0; + } + } + + /** @see Home#getOperationFlags() **/ + private int getOperationFlags() { + try { + Method method = cachedMethods.get(M_ID_GETOPERATIONFLAGS); + if (method == null) { + method = mClass.getMethod("getOperationFlags"); + } + return (Integer) method.invoke(mInstance); + } catch (ReflectiveOperationException ex) { + return 0; + } + } + + private void invokeVoidContextMethod(int methodId, String methodName) { + try { + Method method = cachedMethods.get(methodId); + if (method == null) { + method = mClass.getMethod(methodName, Context.class); + } + method.invoke(mInstance, mContext); + } catch (ReflectiveOperationException ex) { + throw new SecurityException(ex); + } + } + + private final String createDigest(Class<?> cls) throws SecurityException { + try { + MessageDigest digest = MessageDigest.getInstance("SHA1"); + Method[] methods = cls.getDeclaredMethods(); + for (Method method : methods) { + digest.update(method.toString().getBytes()); + } + return new String(Base64.encode(digest.digest(), Base64.NO_WRAP)); + } catch (NoSuchAlgorithmException ex) { + throw new SecurityException(ex); + } + } + + public boolean isNotificationSupported(int flag) { + return (mNotificationFlags & flag) == flag; + } + + public boolean isOperationSupported(int flag) { + return (mOperationFlags & flag) == flag; + } +} diff --git a/update_gallery_files.py b/update_gallery_files.py index ef4e8c933..738d225eb 100644 --- a/update_gallery_files.py +++ b/update_gallery_files.py @@ -49,6 +49,6 @@ for file_path in files.split(): dir = os.path.dirname(file_path) if file_path.find('exif') != -1 or file_path.find('common') != -1: file_path = 'gallerycommon/' + file_path - cmd = 'cp %s/%s %s/' % (gallery_dir, file_path, dir) + cmd = 'cp %s/%s WallpaperPicker/%s/' % (gallery_dir, file_path, dir) print cmd os.system(cmd) diff --git a/update_system_wallpaper_cropper.py b/update_system_wallpaper_cropper.py new file mode 100644 index 000000000..44cbcc967 --- /dev/null +++ b/update_system_wallpaper_cropper.py @@ -0,0 +1,58 @@ +# This script is used to push the most up-to-date files from +# Launcher into frameworks' version of the WallpaperCropActivity +# (and supporting files) +# The framework versions have some small modifications that are +# necessary so do this with care +import os +import sys +src_dir = "WallpaperPicker/src/" +files = """ +src/android/util/Pools.java +com/android/gallery3d/util/IntArray.java +com/android/gallery3d/common/Utils.java +com/android/gallery3d/exif/ByteBufferInputStream.java +com/android/gallery3d/exif/CountedDataInputStream.java +com/android/gallery3d/exif/ExifData.java +com/android/gallery3d/exif/ExifInterface.java +com/android/gallery3d/exif/ExifInvalidFormatException.java +com/android/gallery3d/exif/ExifModifier.java +com/android/gallery3d/exif/ExifOutputStream.java +com/android/gallery3d/exif/ExifParser.java +com/android/gallery3d/exif/ExifReader.java +com/android/gallery3d/exif/ExifTag.java +com/android/gallery3d/exif/IfdData.java +com/android/gallery3d/exif/IfdId.java +com/android/gallery3d/exif/JpegHeader.java +com/android/gallery3d/exif/OrderedDataOutputStream.java +com/android/gallery3d/exif/Rational.java +com/android/gallery3d/glrenderer/BasicTexture.java +com/android/gallery3d/glrenderer/BitmapTexture.java +com/android/gallery3d/glrenderer/GLCanvas.java +com/android/gallery3d/glrenderer/GLES20Canvas.java +com/android/gallery3d/glrenderer/GLES20IdImpl.java +com/android/gallery3d/glrenderer/GLId.java +com/android/gallery3d/glrenderer/GLPaint.java +com/android/gallery3d/glrenderer/RawTexture.java +com/android/gallery3d/glrenderer/Texture.java +com/android/gallery3d/glrenderer/UploadedTexture.java +com/android/photos/BitmapRegionTileSource.java +com/android/photos/views/BlockingGLTextureView.java +com/android/photos/views/TiledImageRenderer.java +com/android/photos/views/TiledImageView.java +com/android/gallery3d/common/BitmapUtils.java +com/android/launcher3/CropView.java +com/android/launcher3/WallpaperCropActivity.java +""" + +if len(sys.argv) != 2: + print "Usage: python update_sytem_wallpaper_cropper.py <framework_dir>" + exit() +framework_dir = sys.argv[1] + "/packages/WallpaperCropper" +for file_path in files.split(): + file_path = src_dir + file_path + dir = os.path.dirname(file_path) + dir = dir.replace("launcher3", "wallpapercropper") + dir = dir.replace(src_dir, "src/") + cmd = 'cp %s %s/%s' % (file_path, framework_dir, dir) + print cmd + os.system(cmd) diff --git a/util/com/android/launcher3/DecoderRing.java b/util/com/android/launcher3/DecoderRing.java index 1d9e0defb..86431d9b7 100644 --- a/util/com/android/launcher3/DecoderRing.java +++ b/util/com/android/launcher3/DecoderRing.java @@ -34,159 +34,283 @@ import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.lang.System; +import java.util.LinkedList; +import java.util.List; import java.util.zip.CRC32; +import javax.xml.bind.DatatypeConverter; + + /** - * Commandline utility for decoding protos written to the android logs during debugging. + * Commandline utility for decoding Launcher3 backup protocol buffers. * - * base64 -D icon.log > icon.bin - * java -classpath $ANDROID_HOST_OUT/framework/protoutil.jar:$ANDROID_HOST_OUT/../common/obj/JAVA_LIBRARIES/host-libprotobuf-java-2.3.0-nano_intermediates/javalib.jar \ - * com.android.launcher3.DecoderRing -i icon.bin + * <P>When using com.android.internal.backup.LocalTransport, the file names are base64-encoded Key + * protocol buffers with a prefix, that have been base64-encoded again by the transport: + * <pre> + * echo "TDpDQUlnL0pxVTVnOD0=" | launcher_protoutil -k + * </pre> * - * TODO: write a wrapper to setup the classpath + * <P>This tool understands these file names and will use the embedded Key to detect the type and + * extract the payload automatically: + * <pre> + * launcher_protoutil /tmp/TDpDQUlnL0pxVTVnOD0= + * </pre> + * + * <P>With payload debugging enabled, base64-encoded protocol buffers will be written to the logs. + * Copy the encoded snippet from the log, and specify the type explicitly, with the Logs flags: + * <pre> + * echo "CAEYLiCJ9JKsDw==" | launcher_protoutil -L -k + * </pre> + * For backup payloads it is more convenient to copy the log snippet to a file: + * <pre> + * launcher_protoutil -L -f favorite.log + * </pre> */ class DecoderRing { + + public static final String STANDARD_IN = "**stdin**"; + + private static Class[] TYPES = { + Key.class, + Favorite.class, + Screen.class, + Resource.class, + Widget.class + }; + static final int ICON_TYPE_BITMAP = 1; + public static void main(String[ ] args) throws Exception { - File source = null; - Class type = Key.class; + Class defaultType = null; + boolean extractImages = false; + boolean fromLogs = false; int skip = 0; + List<File> files = new LinkedList<File>(); + boolean verbose = false; for (int i = 0; i < args.length; i++) { if ("-k".equals(args[i])) { - type = Key.class; + defaultType = Key.class; } else if ("-f".equals(args[i])) { - type = Favorite.class; + defaultType = Favorite.class; } else if ("-j".equals(args[i])) { - type = Journal.class; + defaultType = Journal.class; } else if ("-i".equals(args[i])) { - type = Resource.class; + defaultType = Resource.class; } else if ("-s".equals(args[i])) { - type = Screen.class; + defaultType = Screen.class; } else if ("-w".equals(args[i])) { - type = Widget.class; + defaultType = Widget.class; } else if ("-S".equals(args[i])) { if ((i + 1) < args.length) { skip = Integer.valueOf(args[++i]); } else { usage(args); } + } else if ("-x".equals(args[i])) { + extractImages = true; + } else if ("-v".equals(args[i])) { + verbose = true; + } else if ("-L".equals(args[i])) { + fromLogs = true; } else if (args[i] != null && !args[i].startsWith("-")) { - source = new File(args[i]); + files.add(new File(args[i])); } else { System.err.println("Unsupported flag: " + args[i]); usage(args); } } + if (defaultType == null && files.isEmpty()) { + // can't infer file type without the key + usage(args); + } - // read in the bytes - ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); - BufferedInputStream input = null; - if (source == null) { - input = new BufferedInputStream(System.in); - } else { - try { - input = new BufferedInputStream(new FileInputStream(source)); - } catch (FileNotFoundException e) { - System.err.println("failed to open file: " + source + ", " + e); - System.exit(1); - } + if (files.size() > 1 && defaultType != null) { + System.err.println("Explicit type ignored for multiple files."); + defaultType = null; } - byte[] buffer = new byte[1024]; - try { - while (input.available() > 0) { - int n = input.read(buffer); - int offset = 0; - if (skip > 0) { - offset = Math.min(skip, n); - n -= offset; - skip -= offset; - } - if (n > 0) { - byteStream.write(buffer, offset, n); + + if (files.isEmpty()) { + files.add(new File(STANDARD_IN)); + } + + for (File source : files) { + Class type = null; + if (defaultType == null) { + Key key = decodeKey(source.getName().getBytes(), fromLogs); + if (key != null) { + type = TYPES[key.type]; + if (verbose) { + System.err.println(source.getName() + " is a " + type.getSimpleName()); + System.out.println(key.toString()); + } } + } else { + type = defaultType; } - } catch (IOException e) { - System.err.println("failed to read input: " + e); - System.exit(1); - } - System.err.println("read this many bytes: " + byteStream.size()); - MessageNano proto = null; - if (type == Key.class) { - Key key = new Key(); + // read in the bytes + ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); + BufferedInputStream input = null; + if (source.getName() == STANDARD_IN) { + input = new BufferedInputStream(System.in); + } else { + try { + input = new BufferedInputStream(new FileInputStream(source)); + } catch (FileNotFoundException e) { + System.err.println("failed to open file: " + source + ", " + e); + System.exit(1); + } + } + byte[] buffer = new byte[1024]; try { - key = Key.parseFrom(byteStream.toByteArray()); - } catch (InvalidProtocolBufferNanoException e) { - System.err.println("failed to parse proto: " + e); + while (input.available() > 0) { + int n = input.read(buffer); + int offset = 0; + if (skip > 0) { + offset = Math.min(skip, n); + n -= offset; + skip -= offset; + } + if (n > 0) { + byteStream.write(buffer, offset, n); + } + } + } catch (IOException e) { + System.err.println("failed to read input: " + e); System.exit(1); } - // keys are self-checked - if (key.checksum != checkKey(key)) { - System.err.println("key ckecksum failed"); - System.exit(1); + + MessageNano proto = null; + byte[] payload = byteStream.toByteArray(); + if (type == Key.class) { + proto = decodeKey(payload, fromLogs); + } else if (type != null) { + proto = decodeBackupData(payload, type, fromLogs); } - proto = key; - } else { - // other types are wrapped in a checksum message - CheckedMessage wrapper = new CheckedMessage(); - try { - MessageNano.mergeFrom(wrapper, byteStream.toByteArray()); - } catch (InvalidProtocolBufferNanoException e) { - System.err.println("failed to parse wrapper: " + e); - System.exit(1); + + // Generic string output + if (proto != null) { + System.out.println(proto.toString()); } - CRC32 checksum = new CRC32(); - checksum.update(wrapper.payload); - if (wrapper.checksum != checksum.getValue()) { - System.err.println("wrapper ckecksum failed"); - System.exit(1); + + if (extractImages) { + String prefix = "stdin"; + if (source != null) { + prefix = source.getName(); + } + // save off the icon bits in a file for inspection + if (proto instanceof Resource) { + Resource icon = (Resource) proto; + writeImageData(icon.data, prefix + ".png"); + } + + // save off the icon bits in a file for inspection + if (proto instanceof Favorite) { + Favorite favorite = (Favorite) proto; + if (favorite.iconType == ICON_TYPE_BITMAP) { + writeImageData(favorite.icon, prefix + ".png"); + } + } + + // save off the widget icon and preview bits in files for inspection + if (proto instanceof Widget) { + Widget widget = (Widget) proto; + if (widget.icon != null) { + writeImageData(widget.icon.data, prefix + "_icon.png"); + } + if (widget.preview != null) { + writeImageData(widget.preview.data, prefix + "_preview.png"); + } + } } - // decode the actual message - proto = (MessageNano) type.newInstance(); - try { - MessageNano.mergeFrom(proto, wrapper.payload); - } catch (InvalidProtocolBufferNanoException e) { - System.err.println("failed to parse proto: " + e); - System.exit(1); + } + System.exit(0); + } + + // In logcat, backup data is base64 encoded, but in localtransport files it is raw + private static MessageNano decodeBackupData(byte[] payload, Class type, boolean fromLogs) + throws InstantiationException, IllegalAccessException { + MessageNano proto;// other types are wrapped in a checksum message + CheckedMessage wrapper = new CheckedMessage(); + try { + if (fromLogs) { + payload = DatatypeConverter.parseBase64Binary(new String(payload)); } + MessageNano.mergeFrom(wrapper, payload); + } catch (InvalidProtocolBufferNanoException e) { + System.err.println("failed to parse wrapper: " + e); + System.exit(1); } - // Generic string output - System.out.println(proto.toString()); + CRC32 checksum = new CRC32(); + checksum.update(wrapper.payload); + if (wrapper.checksum != checksum.getValue()) { + System.err.println("wrapper checksum failed"); + System.exit(1); + } - // save off the icon bits in a file for inspection - if (proto instanceof Resource) { - Resource icon = (Resource) proto; - final String path = "icon.webp"; - FileOutputStream iconFile = new FileOutputStream(path); - iconFile.write(icon.data); - iconFile.close(); - System.err.println("wrote " + path); + // decode the actual message + proto = (MessageNano) type.newInstance(); + try { + MessageNano.mergeFrom(proto, wrapper.payload); + } catch (InvalidProtocolBufferNanoException e) { + System.err.println("failed to parse proto: " + e); + System.exit(1); } + return proto; + } - // save off the widget icon and preview bits in files for inspection - if (proto instanceof Widget) { - Widget widget = (Widget) proto; - if (widget.icon != null) { - final String path = "widget_icon.webp"; - FileOutputStream iconFile = new FileOutputStream(path); - iconFile.write(widget.icon.data); - iconFile.close(); - System.err.println("wrote " + path); - } - if (widget.preview != null) { - final String path = "widget_preview.webp"; - FileOutputStream iconFile = new FileOutputStream(path); - iconFile.write(widget.preview.data); - iconFile.close(); - System.err.println("wrote " + path); + // In logcat, keys are base64 encoded with no prefix. + // The localtransport adds a prefix and the base64 encodes the whole thing again. + private static Key decodeKey(byte[] payload, boolean fromLogs) { + Key key = new Key(); + try { + String encodedKey = new String(payload); + if (!fromLogs) { + byte[] rawKey = DatatypeConverter.parseBase64Binary(encodedKey); + if (rawKey[0] != 'L' || rawKey[1] != ':') { + System.err.println(encodedKey + " is not a launcher backup key."); + return null; + } + encodedKey = new String(rawKey, 2, rawKey.length - 2); } + byte[] keyProtoData = DatatypeConverter.parseBase64Binary(encodedKey); + key = Key.parseFrom(keyProtoData); + } catch (InvalidProtocolBufferNanoException protoException) { + System.err.println("failed to extract key from filename: " + protoException); + return null; + } catch (IllegalArgumentException base64Exception) { + System.err.println("failed to extract key from filename: " + base64Exception); + return null; } - // success - System.exit(0); + // keys are self-checked + if (key.checksum != checkKey(key)) { + System.err.println("key ckecksum failed"); + return null; + } + return key; + } + + private static void writeImageData(byte[] data, String path) { + FileOutputStream iconFile = null; + try { + iconFile = new FileOutputStream(path); + iconFile.write(data); + System.err.println("wrote " + path); + } catch (IOException e) { + System.err.println("failed to write image file: " + e); + } finally { + if (iconFile != null) { + try { + iconFile.close(); + } catch (IOException e) { + System.err.println("failed to close the image file: " + e); + } + } + } } private static long checkKey(Key key) { @@ -201,13 +325,16 @@ class DecoderRing { } private static void usage(String[] args) { - System.err.println("DecoderRing type [input]"); + System.err.println("launcher_protoutil [-x] [-S b] [-k|-f|-i|-s|-w] [filename]"); System.err.println("\t-k\tdecode a key"); System.err.println("\t-f\tdecode a favorite"); System.err.println("\t-i\tdecode a icon"); System.err.println("\t-s\tdecode a screen"); System.err.println("\t-w\tdecode a widget"); - System.err.println("\t-s b\tskip b bytes"); + System.err.println("\t-S b\tskip b bytes"); + System.err.println("\t-x\textract image data to files"); + System.err.println("\t-v\tprint key type data, as well as payload"); + System.err.println("\t-l\texpect data from logcat, instead of the local transport"); System.err.println("\tfilename\tread from filename, not stdin"); System.exit(1); } diff --git a/util/etc/launcher_protoutil b/util/etc/launcher_protoutil new file mode 100644 index 000000000..833b5835e --- /dev/null +++ b/util/etc/launcher_protoutil @@ -0,0 +1,83 @@ +#!/bin/bash +# +# Copyright (C) 2013 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. + +# Set up prog to be the path of this script, including following symlinks, +# and set up progdir to be the fully-qualified pathname of its directory. +prog="$0" +while [ -h "${prog}" ]; do + newProg=`/bin/ls -ld "${prog}"` + newProg=`expr "${newProg}" : ".* -> \(.*\)$"` + if expr "x${newProg}" : 'x/' >/dev/null; then + prog="${newProg}" + else + progdir=`dirname "${prog}"` + prog="${progdir}/${newProg}" + fi +done +oldwd=`pwd` +progdir=`dirname "${prog}"` +cd "${progdir}" +progdir=`pwd` +prog="${progdir}"/`basename "${prog}"` +cd "${oldwd}" + +jarfile=launcher_protoutil_lib.jar +libdir="$progdir" + +if [ ! -r "$libdir/$jarfile" ]; then + # set jar location for the Android tree case + libdir=`dirname "$progdir"`/framework +fi + +if [ ! -r "$libdir/$jarfile" ]; then + echo `basename "$prog"`": can't find $jarfile" + exit 1 +fi + +# By default, give decoder a max heap size of 1 gig. This can be overridden +# by using a "-J" option (see below). +defaultMx="-Xmx1024M" + +# The following will extract any initial parameters of the form +# "-J<stuff>" from the command line and pass them to the Java +# invocation (instead of to the decoder). This makes it possible for +# you to add a command-line parameter such as "-JXmx256M" in your +# scripts, for example. "java" (with no args) and "java -X" give a +# summary of available options. + +javaOpts="" + +while expr "x$1" : 'x-J' >/dev/null; do + opt=`expr "x$1" : 'x-J\(.*\)'` + javaOpts="${javaOpts} -${opt}" + if expr "x${opt}" : "xXmx[0-9]" >/dev/null; then + defaultMx="no" + fi + shift +done + +if [ "${defaultMx}" != "no" ]; then + javaOpts="${javaOpts} ${defaultMx}" +fi + +if [ "$OSTYPE" = "cygwin" ]; then + # For Cygwin, convert the jarfile path into native Windows style. + jarpath=`cygpath -w "$libdir/$jarfile"` +else + jarpath="$libdir/$jarfile" +fi + +exec java $javaOpts -jar "$jarpath" "$@" diff --git a/util/etc/manifest.txt b/util/etc/manifest.txt new file mode 100644 index 000000000..84842ed53 --- /dev/null +++ b/util/etc/manifest.txt @@ -0,0 +1 @@ +Main-Class: com.android.launcher3.DecoderRing |