summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Android.mk7
-rw-r--r--AndroidManifest.xml12
-rw-r--r--CleanSpec.mk4
-rw-r--r--proguard.flags11
-rw-r--r--res/anim/all_apps_2d_fade_in.xml2
-rw-r--r--res/anim/all_apps_2d_fade_out.xml2
-rw-r--r--res/anim/fade_in_slow.xml2
-rw-r--r--res/anim/fade_out_slow.xml2
-rw-r--r--res/drawable-hdpi/all_apps_bg_gradient.9.png (renamed from res/drawable-large-nodpi/all_apps_bg_gradient.9.png)bin2946 -> 2946 bytes
-rw-r--r--res/drawable-hdpi/app_market_generic.pngbin0 -> 3891 bytes
-rw-r--r--res/drawable-hdpi/box_launcher_top_normal.9.pngbin2412 -> 1245 bytes
-rw-r--r--res/drawable-hdpi/box_launcher_top_pressed.9.pngbin3253 -> 1245 bytes
-rw-r--r--res/drawable-hdpi/box_launcher_top_selected.9.pngbin3300 -> 1245 bytes
-rw-r--r--res/drawable-hdpi/divider_launcher_holo.9.pngbin0 -> 199 bytes
-rw-r--r--res/drawable-hdpi/focused_bg.9.pngbin0 -> 2864 bytes
-rw-r--r--res/drawable-hdpi/home_press.9.png (renamed from res/drawable-large-hdpi/home_press.9.png)bin195 -> 195 bytes
-rw-r--r--res/drawable-hdpi/homescreen_large_blue.9.pngbin0 -> 3387 bytes
-rw-r--r--res/drawable-hdpi/homescreen_large_blue_strong.9.pngbin0 -> 4520 bytes
-rw-r--r--res/drawable-hdpi/homescreen_large_green.9.pngbin0 -> 3368 bytes
-rw-r--r--res/drawable-hdpi/homescreen_large_green_strong.9.pngbin0 -> 4499 bytes
-rw-r--r--res/drawable-hdpi/homescreen_small_blue.9.pngbin0 -> 6411 bytes
-rw-r--r--res/drawable-hdpi/homescreen_small_blue_strong.9.pngbin0 -> 5470 bytes
-rw-r--r--res/drawable-hdpi/homescreen_small_green.9.png (renamed from res/drawable-large-hdpi/homescreen_small_green.9.png)bin2578 -> 2578 bytes
-rw-r--r--res/drawable-hdpi/homescreen_small_green_strong.9.pngbin0 -> 5662 bytes
-rw-r--r--res/drawable-hdpi/ic_generic_search.png (renamed from res/drawable-large-hdpi/ic_generic_search.png)bin6099 -> 6099 bytes
-rw-r--r--res/drawable-hdpi/ic_home_all_apps_holo_dark.png (renamed from res/drawable-large-hdpi/ic_home_all_apps_holo_dark.png)bin1676 -> 1676 bytes
-rw-r--r--res/drawable-hdpi/ic_home_delete_holo_dark.png (renamed from res/drawable-large-hdpi/ic_home_delete_holo_dark.png)bin3237 -> 3237 bytes
-rw-r--r--res/drawable-hdpi/ic_home_delete_hover_holo_dark.png (renamed from res/drawable-large-hdpi/ic_home_delete_hover_holo_dark.png)bin3129 -> 3129 bytes
-rw-r--r--res/drawable-hdpi/ic_home_info_holo_dark.pngbin0 -> 5984 bytes
-rw-r--r--res/drawable-hdpi/ic_voice_search.png (renamed from res/drawable-large-hdpi/ic_voice_search.png)bin4969 -> 4969 bytes
-rw-r--r--res/drawable-hdpi/paged_view_indicator.9.pngbin0 -> 358 bytes
-rw-r--r--res/drawable-hdpi/portal_container_holo.9.pngbin0 -> 4410 bytes
-rw-r--r--res/drawable-hdpi/portal_ring_inner_holo.pngbin0 -> 16134 bytes
-rw-r--r--res/drawable-hdpi/portal_ring_outer_holo.pngbin0 -> 38891 bytes
-rw-r--r--res/drawable-hdpi/wallpaper_divider.pngbin0 -> 277 bytes
-rw-r--r--res/drawable-land-hdpi/divider_launcher_holo.9.pngbin0 -> 2886 bytes
-rw-r--r--res/drawable-land-mdpi/divider_launcher_holo.9.pngbin0 -> 2877 bytes
-rw-r--r--res/drawable-large-hdpi/app_market_generic.pngbin924 -> 0 bytes
-rw-r--r--res/drawable-large-hdpi/homescreen_large_blue.9.pngbin895 -> 0 bytes
-rw-r--r--res/drawable-large-hdpi/homescreen_large_blue_strong.9.pngbin2062 -> 0 bytes
-rw-r--r--res/drawable-large-hdpi/homescreen_large_green.9.pngbin877 -> 0 bytes
-rw-r--r--res/drawable-large-hdpi/homescreen_large_green_strong.9.pngbin2036 -> 0 bytes
-rw-r--r--res/drawable-large-hdpi/homescreen_small_blue.9.pngbin4578 -> 0 bytes
-rw-r--r--res/drawable-large-hdpi/homescreen_small_blue_strong.9.pngbin3075 -> 0 bytes
-rw-r--r--res/drawable-large-hdpi/homescreen_small_green_strong.9.pngbin3263 -> 0 bytes
-rw-r--r--res/drawable-large/delete_zone_selector.xml24
-rw-r--r--res/drawable-mdpi/all_apps_bg_gradient.9.pngbin0 -> 2946 bytes
-rw-r--r--res/drawable-mdpi/app_market_generic.png (renamed from res/drawable-large-mdpi/app_market_generic.png)bin3441 -> 3441 bytes
-rw-r--r--res/drawable-mdpi/box_launcher_top_normal.9.pngbin1708 -> 1245 bytes
-rw-r--r--res/drawable-mdpi/box_launcher_top_pressed.9.pngbin2053 -> 1245 bytes
-rw-r--r--res/drawable-mdpi/box_launcher_top_selected.9.pngbin2066 -> 1245 bytes
-rw-r--r--res/drawable-mdpi/divider_launcher_holo.9.pngbin0 -> 1078 bytes
-rw-r--r--res/drawable-mdpi/focused_bg.9.pngbin0 -> 2864 bytes
-rw-r--r--res/drawable-mdpi/home_press.9.png (renamed from res/drawable-large-mdpi/home_press.9.png)bin2846 -> 2846 bytes
-rw-r--r--res/drawable-mdpi/homescreen_large_blue.9.png (renamed from res/drawable-large-mdpi/homescreen_large_blue.9.png)bin647 -> 647 bytes
-rw-r--r--res/drawable-mdpi/homescreen_large_green.9.png (renamed from res/drawable-large-mdpi/homescreen_large_green.9.png)bin645 -> 645 bytes
-rw-r--r--res/drawable-mdpi/homescreen_large_green_strong.9.png (renamed from res/drawable-large-mdpi/homescreen_large_green_strong.9.png)bin1639 -> 1639 bytes
-rw-r--r--res/drawable-mdpi/homescreen_small_blue.9.png (renamed from res/drawable-large-mdpi/homescreen_small_blue.9.png)bin3600 -> 3600 bytes
-rw-r--r--res/drawable-mdpi/homescreen_small_blue_strong.9.png (renamed from res/drawable-large-mdpi/homescreen_small_blue_strong.9.png)bin2446 -> 2446 bytes
-rw-r--r--res/drawable-mdpi/homescreen_small_green.9.png (renamed from res/drawable-large-mdpi/homescreen_small_green.9.png)bin1881 -> 1881 bytes
-rw-r--r--res/drawable-mdpi/homescreen_small_green_strong.9.png (renamed from res/drawable-large-mdpi/homescreen_small_green_strong.9.png)bin2591 -> 2591 bytes
-rw-r--r--res/drawable-mdpi/ic_generic_search.png (renamed from res/drawable-large-mdpi/ic_generic_search.png)bin4885 -> 4885 bytes
-rw-r--r--res/drawable-mdpi/ic_home_all_apps_holo_dark.png (renamed from res/drawable-large-mdpi/ic_home_all_apps_holo_dark.png)bin2478 -> 2478 bytes
-rw-r--r--res/drawable-mdpi/ic_home_delete_holo_dark.png (renamed from res/drawable-large-mdpi/ic_home_delete_holo_dark.png)bin1851 -> 1851 bytes
-rw-r--r--res/drawable-mdpi/ic_home_delete_hover_holo_dark.png (renamed from res/drawable-large-mdpi/ic_home_delete_hover_holo_dark.png)bin2213 -> 2213 bytes
-rw-r--r--res/drawable-mdpi/ic_home_info_holo_dark.png (renamed from res/drawable-large-mdpi/ic_home_info_holo_dark.png)bin2358 -> 2358 bytes
-rw-r--r--res/drawable-mdpi/ic_voice_search.png (renamed from res/drawable-large-mdpi/ic_voice_search.png)bin4171 -> 4171 bytes
-rw-r--r--res/drawable-mdpi/paged_view_indicator.9.pngbin0 -> 358 bytes
-rw-r--r--res/drawable-mdpi/portal_container_holo.9.pngbin0 -> 2548 bytes
-rw-r--r--res/drawable-mdpi/portal_ring_inner_holo.pngbin0 -> 9079 bytes
-rw-r--r--res/drawable-mdpi/portal_ring_outer_holo.pngbin0 -> 20859 bytes
-rw-r--r--res/drawable-mdpi/wallpaper_divider.pngbin0 -> 115 bytes
-rw-r--r--res/drawable-nodpi/all_apps_bg_gradient.9.pngbin0 -> 2946 bytes
-rw-r--r--res/drawable-nodpi/apps_customize_bg_gradient.9.pngbin0 -> 2937 bytes
-rw-r--r--res/drawable/button_bg.xml21
-rw-r--r--res/drawable/delete_zone_selector.xml4
-rw-r--r--res/drawable/flying_icon_bg.xml (renamed from res/drawable-large/button_bg.xml)4
-rw-r--r--res/drawable/focusable_view_bg.xml (renamed from res/layout/all_apps.xml)13
-rw-r--r--res/layout-land/all_apps_2d.xml63
-rw-r--r--res/layout-land/application.xml4
-rw-r--r--res/layout-land/launcher.xml68
-rw-r--r--res/layout-land/user_folder.xml52
-rw-r--r--res/layout-land/workspace_screen.xml4
-rw-r--r--res/layout-large-land/application.xml4
-rw-r--r--res/layout-large/all_apps_no_items_placeholder.xml3
-rw-r--r--res/layout-large/all_apps_paged_view_application.xml5
-rw-r--r--res/layout-large/all_apps_tabbed.xml17
-rw-r--r--res/layout-large/button_bar.xml110
-rw-r--r--res/layout-large/customization_drawer.xml2
-rw-r--r--res/layout-large/customize_paged_view_item.xml5
-rw-r--r--res/layout-large/customize_paged_view_wallpaper.xml5
-rw-r--r--res/layout-large/customize_paged_view_widget.xml5
-rw-r--r--res/layout-large/customize_tab_widget_indicator.xml2
-rw-r--r--res/layout-large/launcher.xml23
-rw-r--r--res/layout-large/qsb_bar.xml131
-rw-r--r--res/layout-large/tab_widget_indicator.xml4
-rw-r--r--res/layout-port/all_apps_2d.xml63
-rw-r--r--res/layout-port/application.xml4
-rw-r--r--res/layout-port/launcher.xml69
-rw-r--r--res/layout-port/user_folder.xml51
-rw-r--r--res/layout-port/workspace_screen.xml2
-rw-r--r--res/layout/add_list_item.xml2
-rw-r--r--res/layout/application_list.xml69
-rw-r--r--res/layout/apps_customize_application.xml (renamed from res/layout/all_apps_3d.xml)29
-rw-r--r--res/layout/apps_customize_pane.xml86
-rw-r--r--res/layout/apps_customize_wallpaper.xml68
-rw-r--r--res/layout/apps_customize_widget.xml85
-rw-r--r--res/layout/qsb_bar.xml94
-rw-r--r--res/layout/tab_widget_indicator.xml (renamed from res/layout-large-port/tab_widget_indicator.xml)6
-rw-r--r--res/layout/user_folder.xml39
-rw-r--r--res/values-af-land/strings.xml25
-rw-r--r--res/values-af/strings.xml163
-rw-r--r--res/values-am-land/strings.xml25
-rw-r--r--res/values-am/strings.xml143
-rw-r--r--res/values-ar-land/strings.xml25
-rw-r--r--res/values-ar/strings.xml13
-rw-r--r--res/values-bg-land/strings.xml25
-rw-r--r--res/values-bg/strings.xml13
-rw-r--r--res/values-ca-land/strings.xml25
-rw-r--r--res/values-ca/strings.xml13
-rw-r--r--res/values-cs-land/strings.xml25
-rw-r--r--res/values-cs/strings.xml13
-rw-r--r--res/values-da-land/strings.xml25
-rw-r--r--res/values-da/strings.xml29
-rw-r--r--res/values-de-land/strings.xml25
-rw-r--r--res/values-de/strings.xml21
-rw-r--r--res/values-el-land/strings.xml25
-rw-r--r--res/values-el/strings.xml13
-rw-r--r--res/values-en-rGB-land/strings.xml25
-rw-r--r--res/values-en-rGB/strings.xml13
-rw-r--r--res/values-es-land/strings.xml25
-rw-r--r--res/values-es-rUS-land/strings.xml25
-rw-r--r--res/values-es-rUS/strings.xml13
-rw-r--r--res/values-es/strings.xml13
-rw-r--r--res/values-fa-land/strings.xml25
-rw-r--r--res/values-fa/strings.xml13
-rw-r--r--res/values-fi-land/strings.xml25
-rw-r--r--res/values-fi/strings.xml13
-rw-r--r--res/values-fr-land/strings.xml25
-rw-r--r--res/values-fr/strings.xml13
-rw-r--r--res/values-hr-land/strings.xml25
-rw-r--r--res/values-hr/strings.xml13
-rw-r--r--res/values-hu-land/strings.xml25
-rw-r--r--res/values-hu/strings.xml13
-rw-r--r--res/values-in-land/strings.xml25
-rw-r--r--res/values-in/strings.xml13
-rw-r--r--res/values-it-land/strings.xml25
-rw-r--r--res/values-it/strings.xml13
-rw-r--r--res/values-iw-land/strings.xml25
-rw-r--r--res/values-iw/strings.xml13
-rw-r--r--res/values-ja-land/strings.xml25
-rw-r--r--res/values-ja/strings.xml13
-rw-r--r--res/values-ko-land/strings.xml25
-rw-r--r--res/values-ko/strings.xml13
-rw-r--r--res/values-land/dimens.xml22
-rw-r--r--res/values-land/strings.xml30
-rw-r--r--res/values-land/styles.xml31
-rw-r--r--res/values-large-port/dimens.xml9
-rw-r--r--res/values-large/config.xml74
-rw-r--r--res/values-large/dimens.xml27
-rw-r--r--res/values-large/strings.xml10
-rw-r--r--res/values-large/styles.xml41
-rw-r--r--res/values-lt-land/strings.xml25
-rw-r--r--res/values-lt/strings.xml13
-rw-r--r--res/values-lv-land/strings.xml25
-rw-r--r--res/values-lv/strings.xml13
-rw-r--r--res/values-ms-land/strings.xml25
-rw-r--r--res/values-ms/strings.xml147
-rw-r--r--res/values-nb-land/strings.xml25
-rw-r--r--res/values-nb/strings.xml13
-rw-r--r--res/values-nl-land/strings.xml25
-rw-r--r--res/values-nl/strings.xml13
-rw-r--r--res/values-pl-land/strings.xml25
-rw-r--r--res/values-pl/strings.xml13
-rw-r--r--res/values-port/dimens.xml18
-rw-r--r--res/values-pt-land/strings.xml25
-rw-r--r--res/values-pt-rPT-land/strings.xml25
-rw-r--r--res/values-pt-rPT/strings.xml13
-rw-r--r--res/values-pt/strings.xml13
-rw-r--r--res/values-rm-land/strings.xml25
-rw-r--r--res/values-rm/strings.xml20
-rw-r--r--res/values-ro-land/strings.xml25
-rw-r--r--res/values-ro/strings.xml13
-rw-r--r--res/values-ru-land/strings.xml25
-rw-r--r--res/values-ru/strings.xml13
-rw-r--r--res/values-sk-land/strings.xml25
-rw-r--r--res/values-sk/strings.xml13
-rw-r--r--res/values-sl-land/strings.xml25
-rw-r--r--res/values-sl/strings.xml13
-rw-r--r--res/values-sr-land/strings.xml25
-rw-r--r--res/values-sr/strings.xml13
-rw-r--r--res/values-sv-land/strings.xml25
-rw-r--r--res/values-sv/strings.xml13
-rw-r--r--res/values-sw-land/strings.xml25
-rw-r--r--res/values-sw/strings.xml143
-rw-r--r--res/values-th-land/strings.xml25
-rw-r--r--res/values-th/strings.xml13
-rw-r--r--res/values-tl-land/strings.xml25
-rw-r--r--res/values-tl/strings.xml13
-rw-r--r--res/values-tr-land/strings.xml25
-rw-r--r--res/values-tr/strings.xml13
-rw-r--r--res/values-uk-land/strings.xml25
-rw-r--r--res/values-uk/strings.xml13
-rw-r--r--res/values-vi-land/strings.xml25
-rw-r--r--res/values-vi/strings.xml13
-rw-r--r--res/values-xlarge-port/dimens.xml26
-rw-r--r--res/values-zh-rCN-land/strings.xml25
-rw-r--r--res/values-zh-rCN/strings.xml13
-rw-r--r--res/values-zh-rTW-land/strings.xml25
-rw-r--r--res/values-zh-rTW/strings.xml13
-rw-r--r--res/values-zu-land/strings.xml25
-rw-r--r--res/values-zu/strings.xml143
-rw-r--r--res/values/attrs.xml14
-rw-r--r--res/values/colors.xml7
-rw-r--r--res/values/config.xml62
-rw-r--r--res/values/dimens.xml62
-rw-r--r--res/values/strings.xml40
-rw-r--r--res/values/styles.xml91
-rw-r--r--res/xml/default_workspace.xml4
-rw-r--r--src/com/android/launcher2/AccessibleTabView.java51
-rw-r--r--src/com/android/launcher2/AddAdapter.java9
-rw-r--r--src/com/android/launcher2/AllApps2D.java26
-rw-r--r--src/com/android/launcher2/AllApps3D.java85
-rw-r--r--src/com/android/launcher2/AllAppsBackground.java4
-rw-r--r--src/com/android/launcher2/AllAppsPagedView.java96
-rw-r--r--src/com/android/launcher2/AllAppsTabbed.java31
-rw-r--r--src/com/android/launcher2/AllAppsView.java7
-rw-r--r--src/com/android/launcher2/AppWidgetResizeFrame.java45
-rw-r--r--src/com/android/launcher2/ApplicationInfoDropTarget.java54
-rw-r--r--src/com/android/launcher2/AppsCustomizePagedView.java884
-rw-r--r--src/com/android/launcher2/AppsCustomizeTabHost.java181
-rw-r--r--src/com/android/launcher2/BubbleTextView.java15
-rw-r--r--src/com/android/launcher2/ButtonDropTarget.java93
-rw-r--r--src/com/android/launcher2/CachedTextView.java15
-rw-r--r--src/com/android/launcher2/CellLayout.java394
-rw-r--r--src/com/android/launcher2/CellLayoutChildren.java143
-rw-r--r--src/com/android/launcher2/CustomizePagedView.java188
-rw-r--r--src/com/android/launcher2/CustomizeTrayTabHost.java18
-rw-r--r--src/com/android/launcher2/DeleteDropTarget.java166
-rw-r--r--src/com/android/launcher2/DeleteZone.java186
-rw-r--r--src/com/android/launcher2/DragController.java94
-rw-r--r--src/com/android/launcher2/DragLayer.java189
-rw-r--r--src/com/android/launcher2/DragSource.java6
-rw-r--r--src/com/android/launcher2/DragView.java35
-rw-r--r--src/com/android/launcher2/DropTarget.java50
-rw-r--r--src/com/android/launcher2/FastBitmapDrawable.java9
-rw-r--r--src/com/android/launcher2/FocusHelper.java938
-rw-r--r--src/com/android/launcher2/FocusOnlyTabWidget.java86
-rw-r--r--src/com/android/launcher2/Folder.java694
-rw-r--r--src/com/android/launcher2/FolderIcon.java332
-rw-r--r--src/com/android/launcher2/FolderInfo.java68
-rw-r--r--src/com/android/launcher2/HolographicPagedViewIcon.java1
-rw-r--r--src/com/android/launcher2/IconCache.java15
-rw-r--r--src/com/android/launcher2/IconDropTarget.java26
-rw-r--r--src/com/android/launcher2/InfoDropTarget.java114
-rw-r--r--src/com/android/launcher2/ItemInfo.java2
-rw-r--r--src/com/android/launcher2/Launcher.java1251
-rw-r--r--src/com/android/launcher2/LauncherAnimatorUpdateListener.java30
-rw-r--r--src/com/android/launcher2/LauncherAppWidgetHostView.java22
-rw-r--r--src/com/android/launcher2/LauncherApplication.java16
-rw-r--r--src/com/android/launcher2/LauncherModel.java224
-rw-r--r--src/com/android/launcher2/LauncherSettings.java12
-rw-r--r--src/com/android/launcher2/LiveFolder.java137
-rw-r--r--src/com/android/launcher2/LiveFolderAdapter.java217
-rw-r--r--src/com/android/launcher2/LiveFolderIcon.java82
-rw-r--r--src/com/android/launcher2/LiveFolderInfo.java70
-rw-r--r--src/com/android/launcher2/PagedView.java200
-rw-r--r--src/com/android/launcher2/PagedViewCellLayout.java93
-rw-r--r--src/com/android/launcher2/PagedViewCellLayoutChildren.java22
-rw-r--r--src/com/android/launcher2/PagedViewExtendedLayout.java67
-rw-r--r--src/com/android/launcher2/PagedViewGridLayout.java121
-rw-r--r--src/com/android/launcher2/PagedViewIcon.java58
-rw-r--r--src/com/android/launcher2/PagedViewWidget.java64
-rw-r--r--src/com/android/launcher2/RocketLauncher.java426
-rw-r--r--src/com/android/launcher2/SearchDropTargetBar.java121
-rw-r--r--src/com/android/launcher2/ShortcutInfo.java6
-rw-r--r--src/com/android/launcher2/ShortcutsAdapter.java58
-rw-r--r--src/com/android/launcher2/SmoothPagedView.java2
-rw-r--r--src/com/android/launcher2/SpringLoadedDragController.java34
-rw-r--r--src/com/android/launcher2/UserFolder.java96
-rw-r--r--src/com/android/launcher2/UserFolderInfo.java59
-rw-r--r--src/com/android/launcher2/Utilities.java30
-rw-r--r--src/com/android/launcher2/Workspace.java1312
-rw-r--r--tests/Android.mk15
-rw-r--r--tests/stress/Android.mk33
-rw-r--r--tests/stress/AndroidManifest.xml31
-rw-r--r--tests/stress/src/com/android/launcher2/stress/LauncherRotationStressTest.java68
287 files changed, 10725 insertions, 3905 deletions
diff --git a/Android.mk b/Android.mk
index 89e626bdd..844f05291 100644
--- a/Android.mk
+++ b/Android.mk
@@ -21,9 +21,10 @@ include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
-LOCAL_STATIC_JAVA_LIBRARIES := android-common
+LOCAL_STATIC_JAVA_LIBRARIES := android-common android-support-v13
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
-LOCAL_SRC_FILES := $(call all-subdir-java-files) $(call all-renderscript-files-under, src)
LOCAL_PACKAGE_NAME := Launcher2
LOCAL_CERTIFICATE := shared
@@ -34,4 +35,6 @@ LOCAL_PROGUARD_FLAG_FILES := proguard.flags
include $(BUILD_PACKAGE)
+include $(call all-subdir-makefiles)
+
endif
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 01e2b77cc..63e3c66ad 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -67,7 +67,7 @@
android:process="@string/process"
android:label="@string/application_name"
android:icon="@drawable/ic_launcher_home"
- android:hardwareAccelerated="true"
+ android:hardwareAccelerated="@bool/config_hardwareAccelerated"
android:largeHeap="true">
<activity
@@ -100,6 +100,16 @@
android:resource="@xml/wallpaper_picker_preview" />
</activity>
+ <activity android:name="com.android.launcher2.RocketLauncher"
+ android:label="@string/dream_name"
+ android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.DREAM" />
+ </intent-filter>
+ </activity>
+
<!-- Intent received used to install shortcuts from other applications -->
<receiver
android:name="com.android.launcher2.InstallShortcutReceiver"
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 444dbd887..f78a1b2a4 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -45,7 +45,9 @@
#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*)
$(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 $(OUT_DIR)/target/common/obj/APPS/Launcher2_intermediates)
# ************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
-# ************************************************ \ No newline at end of file
+# ************************************************
diff --git a/proguard.flags b/proguard.flags
index 19c8fd599..c2b2c65f6 100644
--- a/proguard.flags
+++ b/proguard.flags
@@ -20,6 +20,17 @@
public void setHoverAlpha(float);
}
+-keep class com.android.launcher2.DragLayer$LayoutParams {
+ public void setWidth(int);
+ public int getWidth();
+ public void setHeight(int);
+ public int getHeight();
+ public void setX(int);
+ public int getX();
+ public void setY(int);
+ public int getY();
+}
+
-keep class com.android.launcher2.CellLayout$LayoutParams {
public void setWidth(int);
public int getWidth();
diff --git a/res/anim/all_apps_2d_fade_in.xml b/res/anim/all_apps_2d_fade_in.xml
index 0f1e4f4e1..9d2171ae0 100644
--- a/res/anim/all_apps_2d_fade_in.xml
+++ b/res/anim/all_apps_2d_fade_in.xml
@@ -20,4 +20,4 @@
android:fromAlpha="0.0"
android:toAlpha="1.0"
- android:duration="@integer/config_allAppsFadeInTime" />
+ android:duration="@integer/config_appsCustomizeFadeInTime" />
diff --git a/res/anim/all_apps_2d_fade_out.xml b/res/anim/all_apps_2d_fade_out.xml
index cc4769177..90520c7d1 100644
--- a/res/anim/all_apps_2d_fade_out.xml
+++ b/res/anim/all_apps_2d_fade_out.xml
@@ -20,4 +20,4 @@
android:fromAlpha="1.0"
android:toAlpha="0.0"
- android:duration="@integer/config_allAppsFadeOutTime" />
+ android:duration="@integer/config_appsCustomizeFadeOutTime" />
diff --git a/res/anim/fade_in_slow.xml b/res/anim/fade_in_slow.xml
index 0f1e4f4e1..9d2171ae0 100644
--- a/res/anim/fade_in_slow.xml
+++ b/res/anim/fade_in_slow.xml
@@ -20,4 +20,4 @@
android:fromAlpha="0.0"
android:toAlpha="1.0"
- android:duration="@integer/config_allAppsFadeInTime" />
+ android:duration="@integer/config_appsCustomizeFadeInTime" />
diff --git a/res/anim/fade_out_slow.xml b/res/anim/fade_out_slow.xml
index cc4769177..90520c7d1 100644
--- a/res/anim/fade_out_slow.xml
+++ b/res/anim/fade_out_slow.xml
@@ -20,4 +20,4 @@
android:fromAlpha="1.0"
android:toAlpha="0.0"
- android:duration="@integer/config_allAppsFadeOutTime" />
+ android:duration="@integer/config_appsCustomizeFadeOutTime" />
diff --git a/res/drawable-large-nodpi/all_apps_bg_gradient.9.png b/res/drawable-hdpi/all_apps_bg_gradient.9.png
index 3f4b5b58c..3f4b5b58c 100644
--- a/res/drawable-large-nodpi/all_apps_bg_gradient.9.png
+++ b/res/drawable-hdpi/all_apps_bg_gradient.9.png
Binary files differ
diff --git a/res/drawable-hdpi/app_market_generic.png b/res/drawable-hdpi/app_market_generic.png
new file mode 100644
index 000000000..117453c20
--- /dev/null
+++ b/res/drawable-hdpi/app_market_generic.png
Binary files differ
diff --git a/res/drawable-hdpi/box_launcher_top_normal.9.png b/res/drawable-hdpi/box_launcher_top_normal.9.png
index 98997ad28..af04b076a 100644
--- a/res/drawable-hdpi/box_launcher_top_normal.9.png
+++ b/res/drawable-hdpi/box_launcher_top_normal.9.png
Binary files differ
diff --git a/res/drawable-hdpi/box_launcher_top_pressed.9.png b/res/drawable-hdpi/box_launcher_top_pressed.9.png
index f52fd4805..af04b076a 100644
--- a/res/drawable-hdpi/box_launcher_top_pressed.9.png
+++ b/res/drawable-hdpi/box_launcher_top_pressed.9.png
Binary files differ
diff --git a/res/drawable-hdpi/box_launcher_top_selected.9.png b/res/drawable-hdpi/box_launcher_top_selected.9.png
index 8cacf0e09..af04b076a 100644
--- a/res/drawable-hdpi/box_launcher_top_selected.9.png
+++ b/res/drawable-hdpi/box_launcher_top_selected.9.png
Binary files differ
diff --git a/res/drawable-hdpi/divider_launcher_holo.9.png b/res/drawable-hdpi/divider_launcher_holo.9.png
new file mode 100644
index 000000000..0a1bd2a26
--- /dev/null
+++ b/res/drawable-hdpi/divider_launcher_holo.9.png
Binary files differ
diff --git a/res/drawable-hdpi/focused_bg.9.png b/res/drawable-hdpi/focused_bg.9.png
new file mode 100644
index 000000000..1b0d3fa40
--- /dev/null
+++ b/res/drawable-hdpi/focused_bg.9.png
Binary files differ
diff --git a/res/drawable-large-hdpi/home_press.9.png b/res/drawable-hdpi/home_press.9.png
index 743880b0a..743880b0a 100644
--- a/res/drawable-large-hdpi/home_press.9.png
+++ b/res/drawable-hdpi/home_press.9.png
Binary files differ
diff --git a/res/drawable-hdpi/homescreen_large_blue.9.png b/res/drawable-hdpi/homescreen_large_blue.9.png
new file mode 100644
index 000000000..416514dbe
--- /dev/null
+++ b/res/drawable-hdpi/homescreen_large_blue.9.png
Binary files differ
diff --git a/res/drawable-hdpi/homescreen_large_blue_strong.9.png b/res/drawable-hdpi/homescreen_large_blue_strong.9.png
new file mode 100644
index 000000000..d7e32e796
--- /dev/null
+++ b/res/drawable-hdpi/homescreen_large_blue_strong.9.png
Binary files differ
diff --git a/res/drawable-hdpi/homescreen_large_green.9.png b/res/drawable-hdpi/homescreen_large_green.9.png
new file mode 100644
index 000000000..60042c2dd
--- /dev/null
+++ b/res/drawable-hdpi/homescreen_large_green.9.png
Binary files differ
diff --git a/res/drawable-hdpi/homescreen_large_green_strong.9.png b/res/drawable-hdpi/homescreen_large_green_strong.9.png
new file mode 100644
index 000000000..c40b98ee2
--- /dev/null
+++ b/res/drawable-hdpi/homescreen_large_green_strong.9.png
Binary files differ
diff --git a/res/drawable-hdpi/homescreen_small_blue.9.png b/res/drawable-hdpi/homescreen_small_blue.9.png
new file mode 100644
index 000000000..ddc458ba2
--- /dev/null
+++ b/res/drawable-hdpi/homescreen_small_blue.9.png
Binary files differ
diff --git a/res/drawable-hdpi/homescreen_small_blue_strong.9.png b/res/drawable-hdpi/homescreen_small_blue_strong.9.png
new file mode 100644
index 000000000..8f5a74efc
--- /dev/null
+++ b/res/drawable-hdpi/homescreen_small_blue_strong.9.png
Binary files differ
diff --git a/res/drawable-large-hdpi/homescreen_small_green.9.png b/res/drawable-hdpi/homescreen_small_green.9.png
index 00baae948..00baae948 100644
--- a/res/drawable-large-hdpi/homescreen_small_green.9.png
+++ b/res/drawable-hdpi/homescreen_small_green.9.png
Binary files differ
diff --git a/res/drawable-hdpi/homescreen_small_green_strong.9.png b/res/drawable-hdpi/homescreen_small_green_strong.9.png
new file mode 100644
index 000000000..77baa5296
--- /dev/null
+++ b/res/drawable-hdpi/homescreen_small_green_strong.9.png
Binary files differ
diff --git a/res/drawable-large-hdpi/ic_generic_search.png b/res/drawable-hdpi/ic_generic_search.png
index 67bac5cc8..67bac5cc8 100644
--- a/res/drawable-large-hdpi/ic_generic_search.png
+++ b/res/drawable-hdpi/ic_generic_search.png
Binary files differ
diff --git a/res/drawable-large-hdpi/ic_home_all_apps_holo_dark.png b/res/drawable-hdpi/ic_home_all_apps_holo_dark.png
index 3c7930f10..3c7930f10 100644
--- a/res/drawable-large-hdpi/ic_home_all_apps_holo_dark.png
+++ b/res/drawable-hdpi/ic_home_all_apps_holo_dark.png
Binary files differ
diff --git a/res/drawable-large-hdpi/ic_home_delete_holo_dark.png b/res/drawable-hdpi/ic_home_delete_holo_dark.png
index 9d642786f..9d642786f 100644
--- a/res/drawable-large-hdpi/ic_home_delete_holo_dark.png
+++ b/res/drawable-hdpi/ic_home_delete_holo_dark.png
Binary files differ
diff --git a/res/drawable-large-hdpi/ic_home_delete_hover_holo_dark.png b/res/drawable-hdpi/ic_home_delete_hover_holo_dark.png
index 60d5b15df..60d5b15df 100644
--- a/res/drawable-large-hdpi/ic_home_delete_hover_holo_dark.png
+++ b/res/drawable-hdpi/ic_home_delete_hover_holo_dark.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_home_info_holo_dark.png b/res/drawable-hdpi/ic_home_info_holo_dark.png
new file mode 100644
index 000000000..02df4e1cf
--- /dev/null
+++ b/res/drawable-hdpi/ic_home_info_holo_dark.png
Binary files differ
diff --git a/res/drawable-large-hdpi/ic_voice_search.png b/res/drawable-hdpi/ic_voice_search.png
index 5d2f341ea..5d2f341ea 100644
--- a/res/drawable-large-hdpi/ic_voice_search.png
+++ b/res/drawable-hdpi/ic_voice_search.png
Binary files differ
diff --git a/res/drawable-hdpi/paged_view_indicator.9.png b/res/drawable-hdpi/paged_view_indicator.9.png
new file mode 100644
index 000000000..9fd357a88
--- /dev/null
+++ b/res/drawable-hdpi/paged_view_indicator.9.png
Binary files differ
diff --git a/res/drawable-hdpi/portal_container_holo.9.png b/res/drawable-hdpi/portal_container_holo.9.png
new file mode 100644
index 000000000..af2fa98d7
--- /dev/null
+++ b/res/drawable-hdpi/portal_container_holo.9.png
Binary files differ
diff --git a/res/drawable-hdpi/portal_ring_inner_holo.png b/res/drawable-hdpi/portal_ring_inner_holo.png
new file mode 100644
index 000000000..8a9e85b7f
--- /dev/null
+++ b/res/drawable-hdpi/portal_ring_inner_holo.png
Binary files differ
diff --git a/res/drawable-hdpi/portal_ring_outer_holo.png b/res/drawable-hdpi/portal_ring_outer_holo.png
new file mode 100644
index 000000000..5b4641946
--- /dev/null
+++ b/res/drawable-hdpi/portal_ring_outer_holo.png
Binary files differ
diff --git a/res/drawable-hdpi/wallpaper_divider.png b/res/drawable-hdpi/wallpaper_divider.png
new file mode 100644
index 000000000..2f92d6004
--- /dev/null
+++ b/res/drawable-hdpi/wallpaper_divider.png
Binary files differ
diff --git a/res/drawable-land-hdpi/divider_launcher_holo.9.png b/res/drawable-land-hdpi/divider_launcher_holo.9.png
new file mode 100644
index 000000000..f07f6c4b9
--- /dev/null
+++ b/res/drawable-land-hdpi/divider_launcher_holo.9.png
Binary files differ
diff --git a/res/drawable-land-mdpi/divider_launcher_holo.9.png b/res/drawable-land-mdpi/divider_launcher_holo.9.png
new file mode 100644
index 000000000..ae7734045
--- /dev/null
+++ b/res/drawable-land-mdpi/divider_launcher_holo.9.png
Binary files differ
diff --git a/res/drawable-large-hdpi/app_market_generic.png b/res/drawable-large-hdpi/app_market_generic.png
deleted file mode 100644
index 2a2381f3c..000000000
--- a/res/drawable-large-hdpi/app_market_generic.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-large-hdpi/homescreen_large_blue.9.png b/res/drawable-large-hdpi/homescreen_large_blue.9.png
deleted file mode 100644
index 6ce3d29fb..000000000
--- a/res/drawable-large-hdpi/homescreen_large_blue.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-large-hdpi/homescreen_large_blue_strong.9.png b/res/drawable-large-hdpi/homescreen_large_blue_strong.9.png
deleted file mode 100644
index 811014826..000000000
--- a/res/drawable-large-hdpi/homescreen_large_blue_strong.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-large-hdpi/homescreen_large_green.9.png b/res/drawable-large-hdpi/homescreen_large_green.9.png
deleted file mode 100644
index 4a6546ee4..000000000
--- a/res/drawable-large-hdpi/homescreen_large_green.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-large-hdpi/homescreen_large_green_strong.9.png b/res/drawable-large-hdpi/homescreen_large_green_strong.9.png
deleted file mode 100644
index 5ba9ebe79..000000000
--- a/res/drawable-large-hdpi/homescreen_large_green_strong.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-large-hdpi/homescreen_small_blue.9.png b/res/drawable-large-hdpi/homescreen_small_blue.9.png
deleted file mode 100644
index db93b3ccd..000000000
--- a/res/drawable-large-hdpi/homescreen_small_blue.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-large-hdpi/homescreen_small_blue_strong.9.png b/res/drawable-large-hdpi/homescreen_small_blue_strong.9.png
deleted file mode 100644
index 32bd857d3..000000000
--- a/res/drawable-large-hdpi/homescreen_small_blue_strong.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-large-hdpi/homescreen_small_green_strong.9.png b/res/drawable-large-hdpi/homescreen_small_green_strong.9.png
deleted file mode 100644
index e1e64c57a..000000000
--- a/res/drawable-large-hdpi/homescreen_small_green_strong.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-large/delete_zone_selector.xml b/res/drawable-large/delete_zone_selector.xml
deleted file mode 100644
index e2b37f4dc..000000000
--- a/res/drawable-large/delete_zone_selector.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 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.
-*/
--->
-
-<transition xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:drawable="@drawable/ic_home_delete_holo_dark" />
- <item android:drawable="@drawable/ic_home_delete_hover_holo_dark" />
-</transition>
diff --git a/res/drawable-mdpi/all_apps_bg_gradient.9.png b/res/drawable-mdpi/all_apps_bg_gradient.9.png
new file mode 100644
index 000000000..3f4b5b58c
--- /dev/null
+++ b/res/drawable-mdpi/all_apps_bg_gradient.9.png
Binary files differ
diff --git a/res/drawable-large-mdpi/app_market_generic.png b/res/drawable-mdpi/app_market_generic.png
index 6eb549703..6eb549703 100644
--- a/res/drawable-large-mdpi/app_market_generic.png
+++ b/res/drawable-mdpi/app_market_generic.png
Binary files differ
diff --git a/res/drawable-mdpi/box_launcher_top_normal.9.png b/res/drawable-mdpi/box_launcher_top_normal.9.png
index 8adf2cfe7..af04b076a 100644
--- a/res/drawable-mdpi/box_launcher_top_normal.9.png
+++ b/res/drawable-mdpi/box_launcher_top_normal.9.png
Binary files differ
diff --git a/res/drawable-mdpi/box_launcher_top_pressed.9.png b/res/drawable-mdpi/box_launcher_top_pressed.9.png
index 7a20c547f..af04b076a 100644
--- a/res/drawable-mdpi/box_launcher_top_pressed.9.png
+++ b/res/drawable-mdpi/box_launcher_top_pressed.9.png
Binary files differ
diff --git a/res/drawable-mdpi/box_launcher_top_selected.9.png b/res/drawable-mdpi/box_launcher_top_selected.9.png
index 9e636f03e..af04b076a 100644
--- a/res/drawable-mdpi/box_launcher_top_selected.9.png
+++ b/res/drawable-mdpi/box_launcher_top_selected.9.png
Binary files differ
diff --git a/res/drawable-mdpi/divider_launcher_holo.9.png b/res/drawable-mdpi/divider_launcher_holo.9.png
new file mode 100644
index 000000000..6d101f4ce
--- /dev/null
+++ b/res/drawable-mdpi/divider_launcher_holo.9.png
Binary files differ
diff --git a/res/drawable-mdpi/focused_bg.9.png b/res/drawable-mdpi/focused_bg.9.png
new file mode 100644
index 000000000..1b0d3fa40
--- /dev/null
+++ b/res/drawable-mdpi/focused_bg.9.png
Binary files differ
diff --git a/res/drawable-large-mdpi/home_press.9.png b/res/drawable-mdpi/home_press.9.png
index ff841c397..ff841c397 100644
--- a/res/drawable-large-mdpi/home_press.9.png
+++ b/res/drawable-mdpi/home_press.9.png
Binary files differ
diff --git a/res/drawable-large-mdpi/homescreen_large_blue.9.png b/res/drawable-mdpi/homescreen_large_blue.9.png
index 5e7e61f27..5e7e61f27 100644
--- a/res/drawable-large-mdpi/homescreen_large_blue.9.png
+++ b/res/drawable-mdpi/homescreen_large_blue.9.png
Binary files differ
diff --git a/res/drawable-large-mdpi/homescreen_large_green.9.png b/res/drawable-mdpi/homescreen_large_green.9.png
index 2f83bac7d..2f83bac7d 100644
--- a/res/drawable-large-mdpi/homescreen_large_green.9.png
+++ b/res/drawable-mdpi/homescreen_large_green.9.png
Binary files differ
diff --git a/res/drawable-large-mdpi/homescreen_large_green_strong.9.png b/res/drawable-mdpi/homescreen_large_green_strong.9.png
index 1e145029b..1e145029b 100644
--- a/res/drawable-large-mdpi/homescreen_large_green_strong.9.png
+++ b/res/drawable-mdpi/homescreen_large_green_strong.9.png
Binary files differ
diff --git a/res/drawable-large-mdpi/homescreen_small_blue.9.png b/res/drawable-mdpi/homescreen_small_blue.9.png
index 28bc33b18..28bc33b18 100644
--- a/res/drawable-large-mdpi/homescreen_small_blue.9.png
+++ b/res/drawable-mdpi/homescreen_small_blue.9.png
Binary files differ
diff --git a/res/drawable-large-mdpi/homescreen_small_blue_strong.9.png b/res/drawable-mdpi/homescreen_small_blue_strong.9.png
index f286de9fe..f286de9fe 100644
--- a/res/drawable-large-mdpi/homescreen_small_blue_strong.9.png
+++ b/res/drawable-mdpi/homescreen_small_blue_strong.9.png
Binary files differ
diff --git a/res/drawable-large-mdpi/homescreen_small_green.9.png b/res/drawable-mdpi/homescreen_small_green.9.png
index 58698ea8d..58698ea8d 100644
--- a/res/drawable-large-mdpi/homescreen_small_green.9.png
+++ b/res/drawable-mdpi/homescreen_small_green.9.png
Binary files differ
diff --git a/res/drawable-large-mdpi/homescreen_small_green_strong.9.png b/res/drawable-mdpi/homescreen_small_green_strong.9.png
index 977308579..977308579 100644
--- a/res/drawable-large-mdpi/homescreen_small_green_strong.9.png
+++ b/res/drawable-mdpi/homescreen_small_green_strong.9.png
Binary files differ
diff --git a/res/drawable-large-mdpi/ic_generic_search.png b/res/drawable-mdpi/ic_generic_search.png
index e3fd5a266..e3fd5a266 100644
--- a/res/drawable-large-mdpi/ic_generic_search.png
+++ b/res/drawable-mdpi/ic_generic_search.png
Binary files differ
diff --git a/res/drawable-large-mdpi/ic_home_all_apps_holo_dark.png b/res/drawable-mdpi/ic_home_all_apps_holo_dark.png
index 04749e6f4..04749e6f4 100644
--- a/res/drawable-large-mdpi/ic_home_all_apps_holo_dark.png
+++ b/res/drawable-mdpi/ic_home_all_apps_holo_dark.png
Binary files differ
diff --git a/res/drawable-large-mdpi/ic_home_delete_holo_dark.png b/res/drawable-mdpi/ic_home_delete_holo_dark.png
index 647fd8088..647fd8088 100644
--- a/res/drawable-large-mdpi/ic_home_delete_holo_dark.png
+++ b/res/drawable-mdpi/ic_home_delete_holo_dark.png
Binary files differ
diff --git a/res/drawable-large-mdpi/ic_home_delete_hover_holo_dark.png b/res/drawable-mdpi/ic_home_delete_hover_holo_dark.png
index 06b62e2f2..06b62e2f2 100644
--- a/res/drawable-large-mdpi/ic_home_delete_hover_holo_dark.png
+++ b/res/drawable-mdpi/ic_home_delete_hover_holo_dark.png
Binary files differ
diff --git a/res/drawable-large-mdpi/ic_home_info_holo_dark.png b/res/drawable-mdpi/ic_home_info_holo_dark.png
index c34f443bc..c34f443bc 100644
--- a/res/drawable-large-mdpi/ic_home_info_holo_dark.png
+++ b/res/drawable-mdpi/ic_home_info_holo_dark.png
Binary files differ
diff --git a/res/drawable-large-mdpi/ic_voice_search.png b/res/drawable-mdpi/ic_voice_search.png
index 3c52e2ad8..3c52e2ad8 100644
--- a/res/drawable-large-mdpi/ic_voice_search.png
+++ b/res/drawable-mdpi/ic_voice_search.png
Binary files differ
diff --git a/res/drawable-mdpi/paged_view_indicator.9.png b/res/drawable-mdpi/paged_view_indicator.9.png
new file mode 100644
index 000000000..9fd357a88
--- /dev/null
+++ b/res/drawable-mdpi/paged_view_indicator.9.png
Binary files differ
diff --git a/res/drawable-mdpi/portal_container_holo.9.png b/res/drawable-mdpi/portal_container_holo.9.png
new file mode 100644
index 000000000..42aca5f51
--- /dev/null
+++ b/res/drawable-mdpi/portal_container_holo.9.png
Binary files differ
diff --git a/res/drawable-mdpi/portal_ring_inner_holo.png b/res/drawable-mdpi/portal_ring_inner_holo.png
new file mode 100644
index 000000000..4a6469488
--- /dev/null
+++ b/res/drawable-mdpi/portal_ring_inner_holo.png
Binary files differ
diff --git a/res/drawable-mdpi/portal_ring_outer_holo.png b/res/drawable-mdpi/portal_ring_outer_holo.png
new file mode 100644
index 000000000..90cf77fa8
--- /dev/null
+++ b/res/drawable-mdpi/portal_ring_outer_holo.png
Binary files differ
diff --git a/res/drawable-mdpi/wallpaper_divider.png b/res/drawable-mdpi/wallpaper_divider.png
new file mode 100644
index 000000000..1b453c5fa
--- /dev/null
+++ b/res/drawable-mdpi/wallpaper_divider.png
Binary files differ
diff --git a/res/drawable-nodpi/all_apps_bg_gradient.9.png b/res/drawable-nodpi/all_apps_bg_gradient.9.png
new file mode 100644
index 000000000..3f4b5b58c
--- /dev/null
+++ b/res/drawable-nodpi/all_apps_bg_gradient.9.png
Binary files differ
diff --git a/res/drawable-nodpi/apps_customize_bg_gradient.9.png b/res/drawable-nodpi/apps_customize_bg_gradient.9.png
new file mode 100644
index 000000000..e766bd65a
--- /dev/null
+++ b/res/drawable-nodpi/apps_customize_bg_gradient.9.png
Binary files differ
diff --git a/res/drawable/button_bg.xml b/res/drawable/button_bg.xml
new file mode 100644
index 000000000..a830594ea
--- /dev/null
+++ b/res/drawable/button_bg.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_focused="true" android:drawable="@drawable/focused_bg" />
+ <item android:state_pressed="true" android:drawable="@drawable/home_press" />
+ <item android:drawable="@android:color/transparent" />
+</selector>
diff --git a/res/drawable/delete_zone_selector.xml b/res/drawable/delete_zone_selector.xml
index 0c54b1d74..e2b37f4dc 100644
--- a/res/drawable/delete_zone_selector.xml
+++ b/res/drawable/delete_zone_selector.xml
@@ -19,6 +19,6 @@
-->
<transition xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:drawable="@drawable/trashcan" />
- <item android:drawable="@drawable/trashcan_hover" />
+ <item android:drawable="@drawable/ic_home_delete_holo_dark" />
+ <item android:drawable="@drawable/ic_home_delete_hover_holo_dark" />
</transition>
diff --git a/res/drawable-large/button_bg.xml b/res/drawable/flying_icon_bg.xml
index 9e6e1ff23..affd975bc 100644
--- a/res/drawable-large/button_bg.xml
+++ b/res/drawable/flying_icon_bg.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 The Android Open Source Project
+<!-- 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.
@@ -15,6 +15,6 @@
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_pressed="true" android:drawable="@drawable/home_press" />
+ <item android:state_pressed="true" android:drawable="@drawable/homescreen_small_green" />
<item android:drawable="@android:color/transparent" />
</selector>
diff --git a/res/layout/all_apps.xml b/res/drawable/focusable_view_bg.xml
index fadf736a6..66661e28b 100644
--- a/res/layout/all_apps.xml
+++ b/res/drawable/focusable_view_bg.xml
@@ -1,12 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 The Android Open Source Project
+<!-- 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.
@@ -14,7 +14,6 @@
limitations under the License.
-->
-<!-- switch to all_apps_3d on devices that support RenderScript -->
-<merge xmlns:android="http://schemas.android.com/apk/res/android">
- <include layout="@layout/all_apps_2d" />
-</merge>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_focused="true" android:drawable="@drawable/focused_bg" />
+</selector>
diff --git a/res/layout-land/all_apps_2d.xml b/res/layout-land/all_apps_2d.xml
deleted file mode 100644
index b7fcd4585..000000000
--- a/res/layout-land/all_apps_2d.xml
+++ /dev/null
@@ -1,63 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<!-- Sapphire gets 2D all apps view -->
-<com.android.launcher2.AllApps2D
- xmlns:android="http://schemas.android.com/apk/res/android"
-
- android:id="@+id/all_apps_view"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:padding="2dip"
- android:background="#FF000000">
-
- <GridView android:id="@+id/all_apps_2d_grid"
- android:tag="all_apps_2d_grid"
- android:scrollbars="none"
- android:drawSelectorOnTop="false"
- android:listSelector="@drawable/grid_selector"
- android:verticalSpacing="10dip"
- android:numColumns="6"
- android:fadingEdgeLength="48dip"
- android:cacheColorHint="#FF000000"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_alignParentRight="true"
- android:layout_marginRight="@dimen/button_bar_height_portrait"
- android:nextFocusRight="@+id/all_apps_2d_home"
- android:nextFocusUp="@null"
- android:nextFocusLeft="@null"
- android:nextFocusDown="@null"
- />
-
- <view
- class="com.android.launcher2.AllApps2D$HomeButton"
- android:id="@+id/all_apps_2d_home"
- android:tag="all_apps_2d_home"
- android:src="@drawable/home_button"
- android:background="#FF000000"
- android:layout_alignParentRight="true"
- android:layout_centerVertical="true"
- android:layout_height="wrap_content"
- android:layout_width="@dimen/button_bar_height_portrait"
- android:paddingBottom="@dimen/status_bar_height"
- android:nextFocusLeft="@+id/all_apps_2d_grid"
- android:nextFocusDown="@null"
- android:nextFocusUp="@null"
- android:nextFocusRight="@null"
- />
-
-</com.android.launcher2.AllApps2D>
diff --git a/res/layout-land/application.xml b/res/layout-land/application.xml
index 6e8c31e11..9ed1fa115 100644
--- a/res/layout-land/application.xml
+++ b/res/layout-land/application.xml
@@ -15,4 +15,6 @@
-->
<com.android.launcher2.BubbleTextView xmlns:android="http://schemas.android.com/apk/res/android"
- style="@style/WorkspaceIcon.Landscape" />
+ style="@style/WorkspaceIcon.Landscape"
+ android:focusable="true"
+ android:background="@drawable/focusable_view_bg" />
diff --git a/res/layout-land/launcher.xml b/res/layout-land/launcher.xml
index 6e797f8eb..3e557af0d 100644
--- a/res/layout-land/launcher.xml
+++ b/res/layout-land/launcher.xml
@@ -22,8 +22,6 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
- <include layout="@layout/all_apps" />
-
<!-- The workspace contains 5 screens of cells -->
<com.android.launcher2.Workspace
android:id="@+id/workspace"
@@ -40,8 +38,28 @@
<include android:id="@+id/cell3" layout="@layout/workspace_screen" />
<include android:id="@+id/cell4" layout="@layout/workspace_screen" />
<include android:id="@+id/cell5" layout="@layout/workspace_screen" />
-
</com.android.launcher2.Workspace>
+ <ImageView
+ android:id="@+id/paged_view_indicator"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="bottom"
+ android:visibility="gone"
+ android:alpha="0"
+ android:scaleType="fitXY"
+ android:src="@drawable/paged_view_indicator" />
+
+ <include layout="@layout/qsb_bar"
+ android:id="@+id/qsb_bar"
+ android:layout_width="@dimen/qsb_bar_height"
+ android:layout_height="match_parent"
+ android:layout_gravity="left" />
+
+ <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" />
<com.android.launcher2.ClippedImageView
android:id="@+id/previous_screen"
@@ -77,57 +95,31 @@
android:focusable="true"
android:clickable="true" />
- <com.android.launcher2.DeleteZone
- android:id="@+id/delete_zone"
- android:layout_width="@dimen/delete_zone_size"
- android:layout_height="@dimen/delete_zone_size"
- android:paddingLeft="@dimen/delete_zone_padding"
- android:layout_marginBottom="@dimen/half_status_bar_height"
- android:layout_gravity="right|center_vertical"
-
- android:scaleType="center"
- android:drawableLeft="@drawable/delete_zone_selector"
- android:visibility="invisible"
- launcher:direction="vertical"
- />
-
<RelativeLayout
android:id="@+id/all_apps_button_cluster"
android:layout_height="fill_parent"
android:layout_width="@dimen/button_bar_height_portrait"
android:layout_gravity="right|center_vertical"
- android:layout_marginBottom="@dimen/half_status_bar_height"
- >
-
+ android:layout_marginBottom="@dimen/half_status_bar_height">
+ <ImageView
+ android:id="@+id/hotseat_left"
+ style="@style/HotseatButton.Left"
+ android:layout_below="@id/all_apps_button"
+ android:src="@drawable/hotseat_phone"
+ android:onClick="launchHotSeat" />
<com.android.launcher2.HandleView
style="@style/HotseatButton"
android:id="@+id/all_apps_button"
android:layout_centerVertical="true"
android:layout_alignParentRight="true"
-
android:src="@drawable/all_apps_button"
- launcher:direction="vertical"
- />
-
- <ImageView
- android:id="@+id/hotseat_left"
- style="@style/HotseatButton.Left"
- android:layout_below="@id/all_apps_button"
-
- android:src="@drawable/hotseat_phone"
-
- android:onClick="launchHotSeat"
- />
-
+ launcher:direction="vertical" />
<ImageView
android:id="@+id/hotseat_right"
style="@style/HotseatButton.Right"
android:layout_above="@id/all_apps_button"
-
android:src="@drawable/hotseat_browser"
-
- android:onClick="launchHotSeat"
- />
+ android:onClick="launchHotSeat" />
</RelativeLayout>
</com.android.launcher2.DragLayer>
diff --git a/res/layout-land/user_folder.xml b/res/layout-land/user_folder.xml
deleted file mode 100644
index 5da4aa57e..000000000
--- a/res/layout-land/user_folder.xml
+++ /dev/null
@@ -1,52 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<com.android.launcher2.UserFolder xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical">
-
- <Button
- android:id="@+id/folder_close"
- android:background="@drawable/box_launcher_top"
- android:gravity="left|center_vertical"
- android:textSize="14sp"
- android:textColor="#404040"
- android:textStyle="bold"
- android:layout_width="match_parent"
- android:layout_height="wrap_content" />
-
- <FrameLayout
- android:layout_width="match_parent"
- android:layout_height="0dip"
- android:layout_weight="1"
- android:background="@drawable/box_launcher_bottom">
-
- <GridView
- android:id="@id/folder_content"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
-
- android:cacheColorHint="#ff333333"
-
- android:scrollbarAlwaysDrawVerticalTrack="true"
- android:scrollbarStyle="insideInset"
- android:drawSelectorOnTop="false"
- android:listSelector="@drawable/grid_selector"
-
- android:verticalSpacing="10dip"
- android:numColumns="5" />
- </FrameLayout>
-
-</com.android.launcher2.UserFolder>
diff --git a/res/layout-land/workspace_screen.xml b/res/layout-land/workspace_screen.xml
index 9323f58ac..a9faf892f 100644
--- a/res/layout-land/workspace_screen.xml
+++ b/res/layout-land/workspace_screen.xml
@@ -24,7 +24,7 @@
launcher:cellWidth="@dimen/workspace_cell_width"
launcher:cellHeight="@dimen/workspace_cell_height"
- launcher:xAxisStartPadding="65dip"
- launcher:xAxisEndPadding="65dip"
+ launcher:xAxisStartPadding="@dimen/qsb_bar_height"
+ launcher:xAxisEndPadding="0dip"
launcher:yAxisStartPadding="0dip"
launcher:yAxisEndPadding="0dip"/>
diff --git a/res/layout-large-land/application.xml b/res/layout-large-land/application.xml
index 2598e5a03..9393f7e40 100644
--- a/res/layout-large-land/application.xml
+++ b/res/layout-large-land/application.xml
@@ -15,4 +15,6 @@
-->
<com.android.launcher2.BubbleTextView xmlns:android="http://schemas.android.com/apk/res/android"
- style="@style/WorkspaceIcon.Landscape" />
+ style="@style/WorkspaceIcon.Landscape"
+ android:focusable="true"
+ android:background="@drawable/focusable_view_bg" />
diff --git a/res/layout-large/all_apps_no_items_placeholder.xml b/res/layout-large/all_apps_no_items_placeholder.xml
index 247870cd3..b766df1b8 100644
--- a/res/layout-large/all_apps_no_items_placeholder.xml
+++ b/res/layout-large/all_apps_no_items_placeholder.xml
@@ -32,4 +32,5 @@
android:drawablePadding="0dip"
android:maxLines="2"
- android:fadingEdge="horizontal" />
+ android:fadingEdge="horizontal"
+ android:focusable="false" />
diff --git a/res/layout-large/all_apps_paged_view_application.xml b/res/layout-large/all_apps_paged_view_application.xml
index e5f07bf44..16e5d82b7 100644
--- a/res/layout-large/all_apps_paged_view_application.xml
+++ b/res/layout-large/all_apps_paged_view_application.xml
@@ -21,9 +21,12 @@
launcher:blurColor="#FF6B8CF0"
launcher:outlineColor="#FF8CD2FF"
+ style="@style/WorkspaceIcon.AllApps"
+
android:id="@+id/application_icon"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
- style="@style/WorkspaceIcon.AllApps" />
+ android:focusable="true"
+ android:background="@drawable/focusable_view_bg" />
diff --git a/res/layout-large/all_apps_tabbed.xml b/res/layout-large/all_apps_tabbed.xml
index 9064101fc..41940690c 100644
--- a/res/layout-large/all_apps_tabbed.xml
+++ b/res/layout-large/all_apps_tabbed.xml
@@ -32,7 +32,7 @@
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:background="@drawable/tab_unselected_holo">
- <TabWidget
+ <com.android.launcher2.FocusOnlyTabWidget
android:id="@android:id/tabs"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -50,9 +50,12 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
- android:visibility="invisible"/>
+ android:visibility="invisible"
+ android:background="@drawable/focusable_view_bg"
+ android:focusable="true" />
<TextView
android:id="@+id/market_button"
+ android:onClick="onClickAppMarketButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
@@ -64,7 +67,10 @@
android:shadowColor="@color/workspace_all_apps_and_delete_zone_text_shadow_color"
android:shadowDx="0.0"
android:shadowDy="0.0"
- android:shadowRadius="2.0" />
+ android:shadowRadius="2.0"
+ android:background="@drawable/focusable_view_bg"
+ android:focusable="true"
+ android:clickable="true" />
</FrameLayout>
<com.android.launcher2.DeleteZone
android:id="@+id/all_apps_delete_zone"
@@ -84,7 +90,10 @@
android:shadowColor="@color/workspace_all_apps_and_delete_zone_text_shadow_color"
android:shadowDx="0.0"
android:shadowDy="0.0"
- android:shadowRadius="2.0" />
+ android:shadowRadius="2.0"
+
+ android:background="@drawable/focusable_view_bg"
+ android:focusable="true" />
</RelativeLayout>
<FrameLayout
android:id="@android:id/tabcontent"
diff --git a/res/layout-large/button_bar.xml b/res/layout-large/button_bar.xml
index 5c96c5ced..a06076162 100644
--- a/res/layout-large/button_bar.xml
+++ b/res/layout-large/button_bar.xml
@@ -15,31 +15,34 @@
-->
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher">
+ xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"
+ android:focusable="false">
<!-- Global search icon -->
<ImageView
- android:id="@+id/search_button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentTop="true"
- android:layout_alignParentLeft="true"
- android:paddingLeft="@dimen/toolbar_button_horizontal_padding"
- android:paddingRight="@dimen/toolbar_button_horizontal_padding"
- android:paddingTop="@dimen/toolbar_button_vertical_padding"
- android:paddingBottom="@dimen/toolbar_button_vertical_padding"
- android:src="@drawable/ic_generic_search"
- android:background="@drawable/button_bg"
- android:onClick="onClickSearchButton"
- android:focusable="true"
- android:clickable="true" />
+ android:id="@+id/search_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentTop="true"
+ android:layout_alignParentLeft="true"
+ android:paddingLeft="@dimen/toolbar_button_horizontal_padding"
+ android:paddingRight="@dimen/toolbar_button_horizontal_padding"
+ android:paddingTop="@dimen/toolbar_button_vertical_padding"
+ android:paddingBottom="@dimen/toolbar_button_vertical_padding"
+ android:src="@drawable/ic_generic_search"
+ android:background="@drawable/button_bg"
+ android:onClick="onClickSearchButton"
+
+ android:focusable="true"
+ android:clickable="true"
+ android:contentDescription="@string/accessibility_search_button" />
<ImageView
android:id="@+id/search_divider"
android:src="@drawable/divider_launcher_holo"
android:layout_width="wrap_content"
android:layout_height="match_parent"
- android:layout_toRightOf="@id/search_button"
+ android:layout_toRightOf="@+id/search_button"
android:paddingTop="@dimen/toolbar_button_vertical_padding"
android:paddingBottom="@dimen/toolbar_button_vertical_padding"
@@ -52,7 +55,7 @@
android:id="@+id/voice_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_toRightOf="@id/search_divider"
+ android:layout_toRightOf="@+id/search_divider"
android:paddingLeft="@dimen/toolbar_button_horizontal_padding"
android:paddingRight="@dimen/toolbar_button_horizontal_padding"
android:paddingTop="@dimen/toolbar_button_vertical_padding"
@@ -60,43 +63,21 @@
android:src="@drawable/ic_voice_search"
android:background="@drawable/button_bg"
android:onClick="onClickVoiceButton"
- android:focusable="true"
- android:clickable="true"/>
-
- <ImageView
- android:id="@+id/configure_button"
- android:src="@drawable/ic_home_add_holo_dark"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentTop="true"
- android:layout_alignParentRight="true"
- android:paddingLeft="@dimen/toolbar_button_horizontal_padding"
- android:paddingRight="@dimen/toolbar_button_horizontal_padding"
- android:paddingTop="@dimen/toolbar_button_vertical_padding"
- android:paddingBottom="@dimen/toolbar_button_vertical_padding"
- android:background="@drawable/button_bg"
android:focusable="true"
- android:clickable="true" />
- <ImageView
- android:id="@+id/divider"
- android:src="@drawable/divider_launcher_holo"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:layout_toLeftOf="@id/configure_button"
- android:paddingTop="@dimen/toolbar_button_vertical_padding"
- android:paddingBottom="@dimen/toolbar_button_vertical_padding"
+ android:clickable="true"
+ android:contentDescription="@string/accessibility_voice_search_button" />
- android:focusable="false"
- android:clickable="true" />
+ <!-- AllApps icon -->
<com.android.launcher2.StrokedTextView
android:id="@+id/all_apps_button"
+ android:onClick="onClickAllAppsButton"
android:text="@string/all_apps_button_label"
android:drawablePadding="@dimen/all_apps_button_drawable_padding"
android:drawableLeft="@drawable/ic_home_all_apps_holo_dark"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_toLeftOf="@id/divider"
+ android:layout_toLeftOf="@+id/all_apps_divider"
android:paddingLeft="@dimen/toolbar_button_horizontal_padding"
android:paddingRight="@dimen/toolbar_button_horizontal_padding"
android:paddingTop="@dimen/all_apps_button_vertical_padding"
@@ -117,16 +98,40 @@
android:shadowRadius="2.5"
android:focusable="true"
- android:clickable="true" />
+ android:clickable="true"
+ android:contentDescription="@string/accessibility_all_apps_button" />
+
<ImageView
- android:id="@+id/divider_during_drag"
+ android:id="@+id/all_apps_divider"
android:src="@drawable/divider_launcher_holo"
+ android:onClick="onClickAllAppsButton"
android:layout_width="wrap_content"
android:layout_height="match_parent"
- android:layout_toLeftOf="@id/configure_button"
+ android:layout_toLeftOf="@+id/configure_button"
+ android:paddingTop="@dimen/toolbar_button_vertical_padding"
+ android:paddingBottom="@dimen/toolbar_button_vertical_padding"
+
+ android:focusable="false"
+ android:clickable="true" />
+
+ <!-- Customize icon -->
+ <ImageView
+ android:id="@+id/configure_button"
+ android:src="@drawable/ic_home_add_holo_dark"
+ android:onClick="onClickConfigureButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentTop="true"
+ android:layout_alignParentRight="true"
+ android:paddingLeft="@dimen/toolbar_button_horizontal_padding"
+ android:paddingRight="@dimen/toolbar_button_horizontal_padding"
android:paddingTop="@dimen/toolbar_button_vertical_padding"
android:paddingBottom="@dimen/toolbar_button_vertical_padding"
- android:visibility="gone" />
+ android:background="@drawable/button_bg"
+ android:focusable="true"
+ android:contentDescription="@string/accessibility_customize_button" />
+
+ <!-- Delete icon -->
<com.android.launcher2.DeleteZone
android:id="@+id/delete_zone"
android:text="@string/delete_zone_label_workspace"
@@ -134,7 +139,7 @@
android:drawableLeft="@drawable/delete_zone_selector"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_alignRight="@id/configure_button"
+ android:layout_alignRight="@+id/configure_button"
android:paddingLeft="@dimen/toolbar_button_horizontal_padding"
android:paddingRight="@dimen/toolbar_button_horizontal_padding"
android:paddingTop="@dimen/toolbar_button_vertical_padding"
@@ -150,5 +155,8 @@
android:shadowRadius="2.0"
android:visibility="gone"
- launcher:direction="horizontal" />
-</RelativeLayout> \ No newline at end of file
+ launcher:direction="horizontal"
+
+ android:focusable="true"
+ android:contentDescription="@string/accessibility_delete_button" />
+</RelativeLayout>
diff --git a/res/layout-large/customization_drawer.xml b/res/layout-large/customization_drawer.xml
index 2009117b9..0c59a3f96 100644
--- a/res/layout-large/customization_drawer.xml
+++ b/res/layout-large/customization_drawer.xml
@@ -22,7 +22,7 @@
android:layout_height="match_parent">
<!-- The layout_width of this RelativeLayout gets overwritten in
CustomizeTrayTabHost.onFinishInflate -->
- <TabWidget
+ <com.android.launcher2.FocusOnlyTabWidget
android:id="@android:id/tabs"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
diff --git a/res/layout-large/customize_paged_view_item.xml b/res/layout-large/customize_paged_view_item.xml
index b2e5f08b3..80d678e84 100644
--- a/res/layout-large/customize_paged_view_item.xml
+++ b/res/layout-large/customize_paged_view_item.xml
@@ -25,4 +25,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
- style="@style/WorkspaceIcon.Landscape" />
+ style="@style/WorkspaceIcon.Landscape"
+
+ android:background="@drawable/focusable_view_bg"
+ android:focusable="true" />
diff --git a/res/layout-large/customize_paged_view_wallpaper.xml b/res/layout-large/customize_paged_view_wallpaper.xml
index 8c5abc8d9..d6284c26f 100644
--- a/res/layout-large/customize_paged_view_wallpaper.xml
+++ b/res/layout-large/customize_paged_view_wallpaper.xml
@@ -25,7 +25,10 @@
android:paddingBottom="50dp"
launcher:blurColor="#FF6B8CF0"
- launcher:outlineColor="#FF8CD2FF">
+ launcher:outlineColor="#FF8CD2FF"
+
+ android:background="@drawable/focusable_view_bg"
+ android:focusable="true">
<!-- The preview image for the wallpaper. -->
<ImageView
diff --git a/res/layout-large/customize_paged_view_widget.xml b/res/layout-large/customize_paged_view_widget.xml
index c0b455251..35791f5d5 100644
--- a/res/layout-large/customize_paged_view_widget.xml
+++ b/res/layout-large/customize_paged_view_widget.xml
@@ -25,7 +25,10 @@
android:paddingBottom="50dp"
launcher:blurColor="#FF6B8CF0"
- launcher:outlineColor="#FF8CD2FF">
+ launcher:outlineColor="#FF8CD2FF"
+
+ android:background="@drawable/focusable_view_bg"
+ android:focusable="true">
<!-- The icon of the widget. -->
<ImageView
diff --git a/res/layout-large/customize_tab_widget_indicator.xml b/res/layout-large/customize_tab_widget_indicator.xml
index 39f0867e1..186a34294 100644
--- a/res/layout-large/customize_tab_widget_indicator.xml
+++ b/res/layout-large/customize_tab_widget_indicator.xml
@@ -14,6 +14,6 @@
limitations under the License.
-->
-<TextView
+<com.android.launcher2.AccessibleTabView
xmlns:android="http://schemas.android.com/apk/res/android"
style="@style/CustomizeTabIndicator.Wide" />
diff --git a/res/layout-large/launcher.xml b/res/layout-large/launcher.xml
index f95dd4e97..cb84b5a2a 100644
--- a/res/layout-large/launcher.xml
+++ b/res/layout-large/launcher.xml
@@ -20,28 +20,23 @@
android:id="@+id/drag_layer"
android:layout_width="match_parent"
- android:layout_height="match_parent">
+ android:layout_height="match_parent"
+ android:focusable="false">
<include layout="@layout/workspace"
android:id="@+id/workspace"
android:layout_width="match_parent"
android:layout_height="match_parent" />
- <include layout="@layout/button_bar"
- android:id="@+id/all_apps_button_cluster"
- android:layout_width="fill_parent"
- android:layout_height="?android:attr/actionBarSize"
- android:layout_gravity="top" />
-
- <include layout="@layout/all_apps_tabbed"
- android:id="@+id/all_apps_view"
+ <include layout="@layout/qsb_bar"
+ android:id="@+id/qsb_bar"
android:layout_width="match_parent"
- android:layout_height="match_parent"
+ android:layout_height="@dimen/qsb_bar_height"
android:layout_gravity="top" />
- <include layout="@layout/customization_drawer"
- android:id="@+id/customization_drawer"
+ <include layout="@layout/apps_customize_pane"
+ android:id="@+id/apps_customize_pane"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_gravity="bottom" />
+ android:layout_height="match_parent"
+ android:visibility="invisible" />
</com.android.launcher2.DragLayer>
diff --git a/res/layout-large/qsb_bar.xml b/res/layout-large/qsb_bar.xml
new file mode 100644
index 000000000..421ace2e1
--- /dev/null
+++ b/res/layout-large/qsb_bar.xml
@@ -0,0 +1,131 @@
+<?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.launcher2.SearchDropTargetBar
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"
+ android:focusable="false">
+
+ <!-- Search buttons container -->
+ <RelativeLayout
+ style="@style/SearchDropTargetBar"
+ android:id="@+id/qsb_search_bar"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <!-- Global search icon -->
+ <ImageView
+ style="@style/SearchButton"
+ android:id="@+id/search_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentTop="true"
+ android:src="@drawable/ic_generic_search"
+ android:background="@drawable/button_bg"
+ android:onClick="onClickSearchButton"
+ android:focusable="true"
+ android:clickable="true"
+ android:contentDescription="@string/accessibility_search_button" />
+
+ <ImageView
+ style="@style/SearchButtonDivider"
+ android:id="@+id/search_divider"
+ android:layout_toRightOf="@+id/search_button"
+ android:src="@drawable/divider_launcher_holo"
+ android:onClick="onClickSearchButton"
+ android:focusable="false"
+ android:clickable="true" />
+
+ <!-- Voice search icon -->
+ <ImageView
+ style="@style/SearchButton"
+ android:id="@+id/voice_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_toRightOf="@+id/search_divider"
+ android:src="@drawable/ic_voice_search"
+ android:background="@drawable/button_bg"
+ android:onClick="onClickVoiceButton"
+ android:focusable="true"
+ android:clickable="true"
+ android:contentDescription="@string/accessibility_voice_search_button" />
+
+ <!-- AppsCustomize icon -->
+ <com.android.launcher2.StrokedTextView
+ android:id="@+id/all_apps_button"
+ android:onClick="onClickAllAppsButton"
+ android:drawableLeft="@drawable/ic_home_all_apps_holo_dark"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentRight="true"
+ android:layout_alignParentTop="true"
+ android:layout_toLeftOf="@+id/all_apps_divider"
+ android:paddingLeft="@dimen/toolbar_button_horizontal_padding"
+ android:paddingRight="@dimen/toolbar_button_horizontal_padding"
+ android:paddingTop="@dimen/all_apps_button_vertical_padding"
+ android:paddingBottom="@dimen/all_apps_button_vertical_padding"
+ android:background="@drawable/button_bg"
+
+ android:gravity="center"
+ android:textColor="#CCFFFFFF"
+ android:textSize="18sp"
+
+ launcher:strokeColor="#991e3157"
+ launcher:strokeTextColor="#DDFFFFFF"
+ launcher:strokeWidth="2.5"
+
+ android:shadowColor="#DA000000"
+ android:shadowDx="0.0"
+ android:shadowDy="0.0"
+ android:shadowRadius="2.5"
+
+ android:focusable="true"
+ android:clickable="true"
+ android:contentDescription="@string/accessibility_all_apps_button" />
+ </RelativeLayout>
+
+ <!-- Drag specific targets container -->
+ <LinearLayout
+ style="@style/SearchDropTargetBar"
+ android:id="@+id/drag_target_bar"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:alpha="0">
+
+ <com.android.launcher2.DeleteDropTarget
+ style="@style/DropTargetButtonContainer"
+ android:id="@+id/delete_target"
+ android:layout_weight="1">
+ <!-- Delete target -->
+ <TextView
+ style="@style/DropTargetButton"
+ android:id="@+id/delete_target_text"
+ android:text="@string/delete_zone_label_workspace"
+ android:drawableLeft="@drawable/delete_zone_selector" />
+ </com.android.launcher2.DeleteDropTarget>
+
+ <com.android.launcher2.InfoDropTarget
+ style="@style/DropTargetButtonContainer"
+ android:id="@+id/info_target"
+ android:layout_weight="1">
+ <!-- Info target -->
+ <TextView
+ style="@style/DropTargetButton"
+ android:id="@+id/info_target_text"
+ android:text="@string/info_target_label"
+ android:drawableLeft="@drawable/ic_home_info_holo_dark" />
+ </com.android.launcher2.InfoDropTarget>
+ </LinearLayout>
+</com.android.launcher2.SearchDropTargetBar>
diff --git a/res/layout-large/tab_widget_indicator.xml b/res/layout-large/tab_widget_indicator.xml
index 7794e2903..c09c8534c 100644
--- a/res/layout-large/tab_widget_indicator.xml
+++ b/res/layout-large/tab_widget_indicator.xml
@@ -14,6 +14,6 @@
limitations under the License.
-->
-<TextView
+<com.android.launcher2.AccessibleTabView
xmlns:android="http://schemas.android.com/apk/res/android"
- style="@style/TabIndicator" />
+ style="@style/TabIndicator.Wide" />
diff --git a/res/layout-port/all_apps_2d.xml b/res/layout-port/all_apps_2d.xml
deleted file mode 100644
index 081cba292..000000000
--- a/res/layout-port/all_apps_2d.xml
+++ /dev/null
@@ -1,63 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<!-- Sapphire gets 2D all apps view -->
-<com.android.launcher2.AllApps2D
- xmlns:android="http://schemas.android.com/apk/res/android"
-
- android:id="@+id/all_apps_view"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:padding="2dip"
- android:background="#FF000000">
-
- <GridView android:id="@+id/all_apps_2d_grid"
- android:tag="all_apps_2d_grid"
- android:scrollbars="none"
- android:drawSelectorOnTop="false"
- android:listSelector="@drawable/grid_selector"
- android:verticalSpacing="10dip"
- android:numColumns="4"
- android:fadingEdgeLength="48dip"
- android:cacheColorHint="#FF000000"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_alignParentBottom="true"
- android:layout_marginBottom="@dimen/button_bar_height"
- android:layout_marginTop="8dip"
- android:nextFocusDown="@+id/all_apps_2d_home"
- android:nextFocusUp="@null"
- android:nextFocusLeft="@null"
- android:nextFocusRight="@null"
- />
-
- <view
- class="com.android.launcher2.AllApps2D$HomeButton"
- android:id="@+id/all_apps_2d_home"
- android:tag="all_apps_2d_home"
- android:src="@drawable/home_button"
- android:background="#FF000000"
- android:layout_centerHorizontal="true"
- android:layout_alignParentBottom="true"
- android:layout_width="wrap_content"
- android:layout_height="@dimen/button_bar_height"
- android:nextFocusUp="@+id/all_apps_2d_grid"
- android:nextFocusDown="@null"
- android:nextFocusLeft="@null"
- android:nextFocusRight="@null"
- />
-
-</com.android.launcher2.AllApps2D>
diff --git a/res/layout-port/application.xml b/res/layout-port/application.xml
index 32c1510d9..ddc835420 100644
--- a/res/layout-port/application.xml
+++ b/res/layout-port/application.xml
@@ -15,4 +15,6 @@
-->
<com.android.launcher2.BubbleTextView xmlns:android="http://schemas.android.com/apk/res/android"
- style="@style/WorkspaceIcon.Portrait" />
+ style="@style/WorkspaceIcon.Portrait"
+ android:focusable="true"
+ android:background="@drawable/focusable_view_bg" />
diff --git a/res/layout-port/launcher.xml b/res/layout-port/launcher.xml
index b7c61d8fa..323350653 100644
--- a/res/layout-port/launcher.xml
+++ b/res/layout-port/launcher.xml
@@ -22,8 +22,6 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
- <include layout="@layout/all_apps" />
-
<!-- The workspace contains 5 screens of cells -->
<com.android.launcher2.Workspace
android:id="@+id/workspace"
@@ -38,8 +36,29 @@
<include android:id="@+id/cell3" layout="@layout/workspace_screen" />
<include android:id="@+id/cell4" layout="@layout/workspace_screen" />
<include android:id="@+id/cell5" layout="@layout/workspace_screen" />
-
</com.android.launcher2.Workspace>
+ <ImageView
+ android:id="@+id/paged_view_indicator"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="bottom"
+ android:visibility="gone"
+ android:paddingBottom="@dimen/button_bar_height"
+ android:alpha="0"
+ android:scaleType="fitXY"
+ android:src="@drawable/paged_view_indicator" />
+
+ <include layout="@layout/qsb_bar"
+ android:id="@+id/qsb_bar"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/qsb_bar_height"
+ android:layout_gravity="top" />
+
+ <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" />
<ImageView
android:id="@+id/previous_screen"
@@ -71,57 +90,31 @@
android:focusable="true"
android:clickable="true" />
- <com.android.launcher2.DeleteZone
- android:id="@+id/delete_zone"
- android:layout_width="@dimen/delete_zone_size"
- android:layout_height="@dimen/delete_zone_size"
- android:paddingTop="@dimen/delete_zone_padding"
- android:layout_gravity="bottom|center_horizontal"
-
- android:scaleType="center"
- android:drawableLeft="@drawable/delete_zone_selector"
- android:visibility="invisible"
- launcher:direction="horizontal"
- />
-
<RelativeLayout
android:id="@+id/all_apps_button_cluster"
android:layout_width="fill_parent"
android:layout_height="@dimen/button_bar_height"
android:layout_gravity="bottom|center_horizontal"
- android:paddingTop="2dip"
- >
-
+ android:paddingTop="2dip">
+ <ImageView
+ android:id="@+id/hotseat_left"
+ style="@style/HotseatButton.Left"
+ android:layout_toLeftOf="@id/all_apps_button"
+ android:src="@drawable/hotseat_phone"
+ android:onClick="launchHotSeat" />
<com.android.launcher2.HandleView
style="@style/HotseatButton"
android:id="@+id/all_apps_button"
android:layout_centerHorizontal="true"
android:layout_alignParentBottom="true"
-
android:src="@drawable/all_apps_button"
- launcher:direction="horizontal"
- />
-
- <ImageView
- android:id="@+id/hotseat_left"
- style="@style/HotseatButton.Left"
- android:layout_toLeftOf="@id/all_apps_button"
-
- android:src="@drawable/hotseat_phone"
-
- android:onClick="launchHotSeat"
- />
-
+ launcher:direction="horizontal" />
<ImageView
android:id="@+id/hotseat_right"
style="@style/HotseatButton.Right"
android:layout_toRightOf="@id/all_apps_button"
-
android:src="@drawable/hotseat_browser"
-
- android:onClick="launchHotSeat"
- />
-
+ android:onClick="launchHotSeat" />
</RelativeLayout>
</com.android.launcher2.DragLayer>
diff --git a/res/layout-port/user_folder.xml b/res/layout-port/user_folder.xml
deleted file mode 100644
index 0e6df66c6..000000000
--- a/res/layout-port/user_folder.xml
+++ /dev/null
@@ -1,51 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<com.android.launcher2.UserFolder xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical">
-
- <Button
- android:id="@+id/folder_close"
- android:background="@drawable/box_launcher_top"
- android:gravity="left|center_vertical"
- android:textSize="14sp"
- android:textColor="#404040"
- android:textStyle="bold"
- android:layout_width="match_parent"
- android:layout_height="wrap_content" />
-
- <FrameLayout
- android:layout_width="match_parent"
- android:layout_height="0dip"
- android:layout_weight="1"
- android:background="@drawable/box_launcher_bottom">
- <GridView
- android:id="@id/folder_content"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
-
- android:cacheColorHint="#ff333333"
-
- android:scrollbarAlwaysDrawVerticalTrack="true"
- android:scrollbarStyle="insideInset"
- android:drawSelectorOnTop="false"
- android:listSelector="@drawable/grid_selector"
-
- android:verticalSpacing="10dip"
- android:numColumns="4" />
- </FrameLayout>
-
-</com.android.launcher2.UserFolder>
diff --git a/res/layout-port/workspace_screen.xml b/res/layout-port/workspace_screen.xml
index f400c40b1..7a6714fe0 100644
--- a/res/layout-port/workspace_screen.xml
+++ b/res/layout-port/workspace_screen.xml
@@ -24,7 +24,7 @@
launcher:cellWidth="@dimen/workspace_cell_width"
launcher:cellHeight="@dimen/workspace_cell_height"
- launcher:yAxisStartPadding="8dip"
+ launcher:yAxisStartPadding="@dimen/qsb_bar_height"
launcher:yAxisEndPadding="@dimen/button_bar_height"
launcher:xAxisStartPadding="0dip"
launcher:xAxisEndPadding="0dip" />
diff --git a/res/layout/add_list_item.xml b/res/layout/add_list_item.xml
index 62fc4f481..e937d7bc1 100644
--- a/res/layout/add_list_item.xml
+++ b/res/layout/add_list_item.xml
@@ -18,7 +18,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?android:attr/listPreferredItemHeight"
- android:textAppearance="?android:attr/textAppearanceLargeInverse"
+ android:textAppearance="?android:attr/textAppearanceLarge"
android:gravity="center_vertical"
android:drawablePadding="14dip"
android:paddingLeft="15dip"
diff --git a/res/layout/application_list.xml b/res/layout/application_list.xml
deleted file mode 100644
index b515c9e59..000000000
--- a/res/layout/application_list.xml
+++ /dev/null
@@ -1,69 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/**
- * Copyright (c) 2008, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="?android:attr/listPreferredItemHeight"
-
- android:paddingLeft="10dip"
-
- android:orientation="horizontal">
-
- <ImageView android:id="@+id/icon"
- android:layout_width="@android:dimen/app_icon_size"
- android:layout_height="@android:dimen/app_icon_size"
- android:layout_gravity="center_vertical"
- android:scaleType="fitCenter" />
-
- <LinearLayout
- android:layout_width="0dip"
- android:layout_weight="1.0"
- android:layout_height="match_parent"
-
- android:paddingLeft="8dip"
- android:paddingRight="8dip"
-
- android:orientation="vertical"
- android:gravity="center_vertical">
-
- <TextView android:id="@+id/name"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
-
- android:singleLine="true"
- android:ellipsize="end"
-
- android:textAppearance="?android:attr/textAppearanceLarge" />
-
- <TextView android:id="@+id/description"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
-
- android:layout_below="@id/name"
- android:layout_alignLeft="@id/name"
-
- android:singleLine="true"
- android:ellipsize="end"
-
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="?android:attr/textColorSecondary" />
-
- </LinearLayout>
-
-</LinearLayout>
diff --git a/res/layout/all_apps_3d.xml b/res/layout/apps_customize_application.xml
index 7975df40a..4f3632632 100644
--- a/res/layout/all_apps_3d.xml
+++ b/res/layout/apps_customize_application.xml
@@ -1,12 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 The Android Open Source Project
+<!-- 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.
@@ -14,20 +14,19 @@
limitations under the License.
-->
-<!-- Replace with AllAppsView to use 2D version -->
-<com.android.launcher2.AllApps3D
+<com.android.launcher2.PagedViewIcon
xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"
- android:id="@+id/all_apps_view"
+ style="@style/WorkspaceIcon.AllApps"
+
+ android:id="@+id/application_icon"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:gravity="center_horizontal"
+
+ launcher:blurColor="#FF6B8CF0"
+ launcher:outlineColor="#FF8CD2FF"
- android:scrollbarStyle="outsideInset"
- android:drawSelectorOnTop="false"
- android:listSelector="@drawable/grid_selector"
- android:verticalSpacing="10dip"
- android:numColumns="4"
- android:fadingEdgeLength="20dip"
- android:padding="2dip"
- android:cacheColorHint="#FF000000"
- />
+ android:focusable="true"
+ android:background="@drawable/focusable_view_bg" />
diff --git a/res/layout/apps_customize_pane.xml b/res/layout/apps_customize_pane.xml
new file mode 100644
index 000000000..1b8be80a8
--- /dev/null
+++ b/res/layout/apps_customize_pane.xml
@@ -0,0 +1,86 @@
+<?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.launcher2.AppsCustomizeTabHost
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher">
+ <LinearLayout
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <!-- The layout_width of the tab bar gets overriden to align the content
+ with the text in the tabs in AppsCustomizeTabHost. -->
+ <FrameLayout
+ android:layout_width="wrap_content"
+ android:layout_height="@dimen/qsb_bar_height"
+ android:layout_gravity="center_horizontal">
+ <com.android.launcher2.FocusOnlyTabWidget
+ android:id="@android:id/tabs"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_gravity="left"
+ android:background="@drawable/tab_unselected_holo"
+ android:tabStripEnabled="false" />
+ <TextView
+ style="@style/MarketButton"
+ android:id="@+id/market_button"
+ android:onClick="onClickAppMarketButton"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_gravity="right"
+ android:gravity="center"
+ android:text="@string/market"
+ android:textColor="@color/workspace_all_apps_and_delete_zone_text_color"
+ android:textSize="18sp"
+ android:shadowColor="@color/workspace_all_apps_and_delete_zone_text_shadow_color"
+ android:shadowDx="0.0"
+ android:shadowDy="0.0"
+ android:shadowRadius="2.0"
+ android:background="@drawable/tab_widget_indicator_selector"
+ android:focusable="true"
+ android:clickable="true" />
+ </FrameLayout>
+ <FrameLayout
+ android:id="@android:id/tabcontent"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <com.android.launcher2.AppsCustomizePagedView
+ android:id="@+id/apps_customize_pane_content"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ launcher:cellCountX="@integer/all_apps_view_cellCountX"
+ launcher:cellCountY="@integer/all_apps_view_cellCountY"
+ launcher:pageLayoutWidthGap="@dimen/all_apps_view_pageLayoutWidthGap"
+ launcher:pageLayoutHeightGap="@dimen/all_apps_view_pageLayoutHeightGap"
+ launcher:pageLayoutPaddingTop="@dimen/all_apps_view_pageLayoutPaddingTop"
+ launcher:pageLayoutPaddingBottom="@dimen/all_apps_view_pageLayoutPaddingBottom"
+ launcher:pageLayoutPaddingLeft="@dimen/all_apps_view_pageLayoutPaddingLeft"
+ launcher:pageLayoutPaddingRight="@dimen/all_apps_view_pageLayoutPaddingRight"
+ launcher:widgetCellWidthGap="@dimen/apps_customize_widget_cell_width_gap"
+ launcher:widgetCellHeightGap="@dimen/apps_customize_widget_cell_height_gap"
+ launcher:widgetCountX="@integer/apps_customize_widget_cell_count_x"
+ launcher:widgetCountY="@integer/apps_customize_widget_cell_count_y" />
+ <ImageView
+ android:id="@+id/paged_view_indicator"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="bottom"
+ android:visibility="gone"
+ android:alpha="0"
+ android:scaleType="fitXY"
+ android:src="@drawable/paged_view_indicator" />
+ </FrameLayout>
+ </LinearLayout>
+</com.android.launcher2.AppsCustomizeTabHost>
diff --git a/res/layout/apps_customize_wallpaper.xml b/res/layout/apps_customize_wallpaper.xml
new file mode 100644
index 000000000..d93825f8c
--- /dev/null
+++ b/res/layout/apps_customize_wallpaper.xml
@@ -0,0 +1,68 @@
+<?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.launcher2.PagedViewWidget
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"
+
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:orientation="vertical"
+
+ launcher:blurColor="#FF6B8CF0"
+ launcher:outlineColor="#FF8CD2FF"
+
+ android:background="@drawable/focusable_view_bg"
+ android:focusable="true">
+
+ <!-- The wallpaper preview. -->
+ <ImageView
+ android:id="@+id/widget_preview"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:paddingBottom="10dp"
+ android:adjustViewBounds="true"
+ android:scaleType="fitStart" />
+
+ <!-- The divider image. -->
+ <ImageView
+ android:id="@+id/divider"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="0"
+ android:paddingTop="10dp"
+ android:paddingBottom="10dp"
+ android:src="@drawable/widget_divider" />
+
+ <!-- The name of the wallpaper. -->
+ <TextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/widget_name"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="0"
+ android:gravity="left|bottom"
+
+ android:textColor="#FFFFFFFF"
+ android:textSize="14sp"
+ android:shadowColor="#FF000000"
+ android:shadowDx="0.0"
+ android:shadowDy="1.0"
+ android:shadowRadius="1.0"
+
+ android:maxLines="2"
+ android:fadingEdge="horizontal" />
+</com.android.launcher2.PagedViewWidget>
diff --git a/res/layout/apps_customize_widget.xml b/res/layout/apps_customize_widget.xml
new file mode 100644
index 000000000..53643b40a
--- /dev/null
+++ b/res/layout/apps_customize_widget.xml
@@ -0,0 +1,85 @@
+<?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.launcher2.PagedViewWidget
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"
+
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:orientation="vertical"
+
+ launcher:blurColor="#FF6B8CF0"
+ launcher:outlineColor="#FF8CD2FF"
+
+ android:background="@drawable/focusable_view_bg"
+ android:focusable="true">
+
+ <!-- The icon of the widget. -->
+ <ImageView
+ android:id="@+id/widget_preview"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:paddingBottom="5dp"
+ android:adjustViewBounds="true"
+ android:scaleType="fitStart" />
+
+ <!-- The divider image. -->
+ <ImageView
+ style="WidgetDivider"
+ android:id="@+id/divider"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="0"
+ android:paddingTop="10dp"
+ android:paddingBottom="10dp"
+ android:src="@drawable/widget_divider" />
+
+ <!-- The name of the widget. -->
+ <TextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/widget_name"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="0"
+ android:gravity="left|bottom"
+
+ android:textColor="#FFFFFFFF"
+ android:textSize="14sp"
+ android:shadowColor="#FF000000"
+ android:shadowDx="0.0"
+ android:shadowDy="1.0"
+ android:shadowRadius="1.0"
+
+ android:maxLines="2"
+ android:fadingEdge="horizontal" />
+
+ <!-- The original dimensions of the widget (can't be the same text as above due to different
+ style. -->
+ <TextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/widget_dims"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="0"
+ android:gravity="left|bottom"
+
+ android:textColor="#FF999999"
+ android:textSize="14sp"
+ android:shadowColor="#99000000"
+ android:shadowDx="0.0"
+ android:shadowDy="1.0"
+ android:shadowRadius="1.0" />
+</com.android.launcher2.PagedViewWidget>
diff --git a/res/layout/qsb_bar.xml b/res/layout/qsb_bar.xml
new file mode 100644
index 000000000..68ee8b6d5
--- /dev/null
+++ b/res/layout/qsb_bar.xml
@@ -0,0 +1,94 @@
+<?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.launcher2.SearchDropTargetBar
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"
+ android:focusable="false">
+
+ <!-- Search buttons container -->
+ <LinearLayout
+ style="@style/SearchDropTargetBar"
+ android:id="@+id/qsb_search_bar"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <!-- Global search icon -->
+ <ImageView
+ style="@style/SearchButton"
+ android:id="@+id/search_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/ic_generic_search"
+ android:background="@drawable/button_bg"
+ android:onClick="onClickSearchButton"
+ android:focusable="true"
+ android:clickable="true"
+ android:contentDescription="@string/accessibility_search_button" />
+
+ <ImageView
+ style="@style/SearchButtonDivider"
+ android:id="@+id/search_divider"
+ android:src="@drawable/divider_launcher_holo"
+ android:onClick="onClickSearchButton"
+ android:focusable="false"
+ android:clickable="true" />
+
+ <!-- Voice search icon -->
+ <ImageView
+ style="@style/SearchButton"
+ android:id="@+id/voice_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/ic_voice_search"
+ android:background="@drawable/button_bg"
+ android:onClick="onClickVoiceButton"
+ android:focusable="true"
+ android:clickable="true"
+ android:contentDescription="@string/accessibility_voice_search_button" />
+ </LinearLayout>
+
+ <!-- Drag specific targets container -->
+ <LinearLayout
+ style="@style/SearchDropTargetBar"
+ android:id="@+id/drag_target_bar"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:alpha="0">
+
+ <com.android.launcher2.DeleteDropTarget
+ style="@style/DropTargetButtonContainer"
+ android:id="@+id/delete_target"
+ android:layout_weight="1">
+ <!-- Delete target -->
+ <TextView
+ style="@style/DropTargetButton"
+ android:id="@+id/delete_target_text"
+ android:text="@string/delete_zone_label_workspace"
+ android:drawableLeft="@drawable/delete_zone_selector" />
+ </com.android.launcher2.DeleteDropTarget>
+
+ <com.android.launcher2.InfoDropTarget
+ style="@style/DropTargetButtonContainer"
+ android:id="@+id/info_target"
+ android:layout_weight="1">
+ <!-- Info target -->
+ <TextView
+ style="@style/DropTargetButton"
+ android:id="@+id/info_target_text"
+ android:text="@string/info_target_label"
+ android:drawableLeft="@drawable/ic_home_info_holo_dark" />
+ </com.android.launcher2.InfoDropTarget>
+ </LinearLayout>
+</com.android.launcher2.SearchDropTargetBar>
diff --git a/res/layout-large-port/tab_widget_indicator.xml b/res/layout/tab_widget_indicator.xml
index b113b7b3f..b3694febc 100644
--- a/res/layout-large-port/tab_widget_indicator.xml
+++ b/res/layout/tab_widget_indicator.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 The Android Open Source Project
+<!-- 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.
@@ -14,6 +14,6 @@
limitations under the License.
-->
-<TextView
+<com.android.launcher2.AccessibleTabView
xmlns:android="http://schemas.android.com/apk/res/android"
- style="@style/TabIndicator.Portrait" />
+ style="@style/TabIndicator" />
diff --git a/res/layout/user_folder.xml b/res/layout/user_folder.xml
new file mode 100644
index 000000000..5ef959d71
--- /dev/null
+++ b/res/layout/user_folder.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<com.android.launcher2.Folder
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"
+ android:orientation="vertical"
+ android:background="@drawable/portal_container_holo">
+
+ <com.android.launcher2.CellLayout
+ android:id="@id/folder_content"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+
+ android:cacheColorHint="#ff333333"
+
+ android:hapticFeedbackEnabled="false"
+ launcher:widthGap="@dimen/workspace_width_gap"
+ launcher:heightGap="@dimen/workspace_height_gap"
+ launcher:cellWidth="@dimen/workspace_cell_width"
+ launcher:cellHeight="@dimen/workspace_cell_height"
+ launcher:xAxisStartPadding="0dip"
+ launcher:xAxisEndPadding="0dip"
+ launcher:yAxisStartPadding="8dip"
+ launcher:yAxisEndPadding="8dip"/>
+</com.android.launcher2.Folder>
diff --git a/res/values-af-land/strings.xml b/res/values-af-land/strings.xml
new file mode 100644
index 000000000..b976926f0
--- /dev/null
+++ b/res/values-af-land/strings.xml
@@ -0,0 +1,25 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="delete_target_label" msgid="4155210680095864979"></string>
+ <string name="delete_target_uninstall_label" msgid="1839407506844917298"></string>
+ <string name="info_target_label" msgid="1424400595004570393"></string>
+</resources>
diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml
new file mode 100644
index 000000000..006e3ae76
--- /dev/null
+++ b/res/values-af/strings.xml
@@ -0,0 +1,163 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2008 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- no translation found for application_name (8424725141379931883) -->
+ <skip />
+ <string name="uid_name" msgid="3371120195364560632">"Android Kernprogramme"</string>
+ <!-- no translation found for folder_name (4588446541914685904) -->
+ <skip />
+ <!-- no translation found for chooser_wallpaper (5988031014201479733) -->
+ <skip />
+ <!-- no translation found for wallpaper_instructions (4215640646180727542) -->
+ <skip />
+ <!-- no translation found for pick_wallpaper (5630222540525626723) -->
+ <skip />
+ <!-- no translation found for activity_not_found (5591731020063337696) -->
+ <skip />
+ <string name="configure_wallpaper" msgid="2820186271419674623">"Stel op..."</string>
+ <!-- no translation found for widgets_tab_label (9145860100000983599) -->
+ <skip />
+ <!-- no translation found for folders_tab_label (1145293785541489736) -->
+ <skip />
+ <!-- no translation found for shortcuts_tab_label (8640731503933155644) -->
+ <skip />
+ <!-- no translation found for wallpapers_tab_label (1617804870364119879) -->
+ <skip />
+ <!-- no translation found for applications_tab_label (2991364240020736760) -->
+ <skip />
+ <!-- no translation found for wallpapers_temp_tab_text (1660218201190495279) -->
+ <skip />
+ <!-- no translation found for all_apps_tab_all (2942727589595027258) -->
+ <skip />
+ <!-- no translation found for all_apps_tab_apps (5468972551904071712) -->
+ <skip />
+ <!-- no translation found for all_apps_tab_games (1855736784923494918) -->
+ <skip />
+ <!-- no translation found for all_apps_tab_downloaded (1488049110598641387) -->
+ <skip />
+ <!-- no translation found for long_press_widget_to_add (4307462194057715796) -->
+ <skip />
+ <!-- no translation found for all_apps_no_games (5293893733372793696) -->
+ <skip />
+ <!-- no translation found for all_apps_no_downloads (2284720393234453761) -->
+ <skip />
+ <!-- no translation found for market (2652226429823445833) -->
+ <skip />
+ <!-- no translation found for external_drop_widget_error (4976816434597126575) -->
+ <skip />
+ <!-- no translation found for external_drop_widget_pick_title (4481311720134376218) -->
+ <skip />
+ <string name="rename_folder_label" msgid="5646236631298452787">"Vouernaam"</string>
+ <!-- no translation found for rename_folder_title (4544573104191526550) -->
+ <skip />
+ <!-- no translation found for rename_action (6016003384693240896) -->
+ <skip />
+ <!-- no translation found for cancel_action (3811860427489435048) -->
+ <skip />
+ <string name="menu_item_add_item" msgid="6233177331075781114">"Voeg by Tuis-skerm"</string>
+ <string name="group_applications" msgid="4118484163419674240">"Programme"</string>
+ <string name="group_shortcuts" msgid="9133529424900391877">"Kortpaaie"</string>
+ <string name="group_folder" msgid="5143593791798929193">"Nuwe vouer"</string>
+ <string name="group_live_folders" msgid="2664945399140647217">"Vouers"</string>
+ <string name="group_widgets" msgid="6704978494073105844">"Legstukke"</string>
+ <string name="group_wallpapers" msgid="1568191644272224858">"Muurpapier"</string>
+ <!-- no translation found for add_folder (3521088587367839879) -->
+ <skip />
+ <!-- no translation found for add_clock (2337943840175865746) -->
+ <skip />
+ <!-- no translation found for add_photo_frame (3154058437359487954) -->
+ <skip />
+ <!-- no translation found for out_of_space (8365249326091984698) -->
+ <skip />
+ <string name="shortcut_installed" msgid="7071557296331322355">"Kortpad \"<xliff:g id="NAME">%s</xliff:g>\" is geskep."</string>
+ <string name="shortcut_uninstalled" msgid="2129499669449749995">"Kortpad \"<xliff:g id="NAME">%s</xliff:g>\" is verwyder."</string>
+ <string name="shortcut_duplicate" msgid="4757756326465060694">"Kortpad \"<xliff:g id="NAME">%s</xliff:g>\" bestaan reeds."</string>
+ <string name="title_select_shortcut" msgid="2858897527672831763">"Kies kortpad"</string>
+ <!-- no translation found for title_select_application (8031072293115454221) -->
+ <skip />
+ <string name="title_select_live_folder" msgid="3753447798805166749">"Kies vouer"</string>
+ <!-- no translation found for all_apps_button_label (2578400570124163469) -->
+ <skip />
+ <!-- no translation found for all_apps_home_button_label (1022222300329398558) -->
+ <skip />
+ <!-- no translation found for delete_zone_label_workspace (7153615831493049150) -->
+ <skip />
+ <!-- no translation found for delete_zone_label_all_apps (6664588234817475108) -->
+ <skip />
+ <!-- no translation found for delete_target_label (665300185123139530) -->
+ <skip />
+ <!-- no translation found for delete_target_uninstall_label (748894921183769150) -->
+ <skip />
+ <!-- no translation found for info_target_label (6175926565900432067) -->
+ <skip />
+ <!-- no translation found for accessibility_search_button (816822994629942611) -->
+ <skip />
+ <!-- no translation found for accessibility_voice_search_button (3938249215065842475) -->
+ <skip />
+ <!-- no translation found for accessibility_all_apps_button (1595097919145716305) -->
+ <skip />
+ <!-- no translation found for accessibility_customize_button (585539669413531163) -->
+ <skip />
+ <!-- no translation found for accessibility_delete_button (3628162007991023603) -->
+ <skip />
+ <!-- no translation found for delete_zone_label_all_apps_system_app (3683920959591819044) -->
+ <skip />
+ <!-- no translation found for menu_add (3065046628354640854) -->
+ <skip />
+ <!-- no translation found for menu_manage_apps (2308685199463588895) -->
+ <skip />
+ <!-- no translation found for menu_wallpaper (5837429080911269832) -->
+ <skip />
+ <!-- no translation found for menu_search (4826514464423239041) -->
+ <skip />
+ <!-- no translation found for menu_notifications (6424587053194766192) -->
+ <skip />
+ <string name="menu_gestures" msgid="514678675575912237">"Handgebare"</string>
+ <!-- no translation found for menu_settings (6233960148378443661) -->
+ <skip />
+ <!-- no translation found for cab_menu_delete_app (1242619904941293871) -->
+ <skip />
+ <!-- no translation found for cab_menu_app_info (5180426909324882018) -->
+ <skip />
+ <!-- no translation found for cab_app_selection_text (606113924828167756) -->
+ <skip />
+ <!-- no translation found for cab_widget_selection_text (962527270506951955) -->
+ <skip />
+ <!-- no translation found for cab_folder_selection_text (8916111874189565067) -->
+ <skip />
+ <!-- no translation found for cab_shortcut_selection_text (8115847384500412878) -->
+ <skip />
+ <!-- no translation found for permlab_install_shortcut (1201690825493376489) -->
+ <skip />
+ <string name="permdesc_install_shortcut" msgid="7429365847558984148">"Stel \'n program in staat om kortpaaie by te voeg sonder gebruikerhandeling."</string>
+ <!-- no translation found for permlab_uninstall_shortcut (7696645932555926449) -->
+ <skip />
+ <string name="permdesc_uninstall_shortcut" msgid="959972195916090900">"Stel \'n program in staat om kortpaaie te verwyder sonder gebruikerhandeling."</string>
+ <string name="permlab_read_settings" msgid="3452408290738106747">"lees Tuis-instellings en -kortpaaie"</string>
+ <string name="permdesc_read_settings" msgid="8377434937176025492">"Stel \'n program in staat om die instellings en kortpaaie in Tuis te lees."</string>
+ <string name="permlab_write_settings" msgid="1360567537236705628">"skryf Tuis-instellings en -kortpaaie"</string>
+ <string name="permdesc_write_settings" msgid="1098648778383349818">"Stel program in staat om die instellings en kortpaaie in Tuis te verander."</string>
+ <string name="gadget_error_text" msgid="8359351016167075858">"Kon nie legstuk laai nie"</string>
+ <!-- no translation found for uninstall_system_app_text (7488523163288397451) -->
+ <skip />
+ <!-- no translation found for dream_name (2847171357608437154) -->
+ <skip />
+</resources>
diff --git a/res/values-am-land/strings.xml b/res/values-am-land/strings.xml
new file mode 100644
index 000000000..b976926f0
--- /dev/null
+++ b/res/values-am-land/strings.xml
@@ -0,0 +1,25 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="delete_target_label" msgid="4155210680095864979"></string>
+ <string name="delete_target_uninstall_label" msgid="1839407506844917298"></string>
+ <string name="info_target_label" msgid="1424400595004570393"></string>
+</resources>
diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml
new file mode 100644
index 000000000..50a351138
--- /dev/null
+++ b/res/values-am/strings.xml
@@ -0,0 +1,143 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2008 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="application_name" msgid="8424725141379931883">"አስነሺ"</string>
+ <string name="uid_name" msgid="3371120195364560632">"የAndroid ኮር ትግበራዎች"</string>
+ <!-- no translation found for folder_name (4588446541914685904) -->
+ <skip />
+ <!-- no translation found for chooser_wallpaper (5988031014201479733) -->
+ <skip />
+ <!-- no translation found for wallpaper_instructions (4215640646180727542) -->
+ <skip />
+ <string name="pick_wallpaper" msgid="5630222540525626723">"ልጥፎች"</string>
+ <!-- no translation found for activity_not_found (5591731020063337696) -->
+ <skip />
+ <string name="configure_wallpaper" msgid="2820186271419674623">"አዋቅር..."</string>
+ <string name="widgets_tab_label" msgid="9145860100000983599">" ፍርግሞች"</string>
+ <string name="folders_tab_label" msgid="1145293785541489736">"አቃፊዎች"</string>
+ <string name="shortcuts_tab_label" msgid="8640731503933155644">"ተጨማሪ"</string>
+ <string name="wallpapers_tab_label" msgid="1617804870364119879">"ልጥፎች"</string>
+ <!-- no translation found for applications_tab_label (2991364240020736760) -->
+ <skip />
+ <string name="wallpapers_temp_tab_text" msgid="1660218201190495279">"ይህ የልጥፎች ትር ይሆናል"</string>
+ <string name="all_apps_tab_all" msgid="2942727589595027258">"ሁሉም"</string>
+ <string name="all_apps_tab_apps" msgid="5468972551904071712">"ትግበራ"</string>
+ <string name="all_apps_tab_games" msgid="1855736784923494918">"ጨዋታዎች"</string>
+ <!-- no translation found for all_apps_tab_downloaded (1488049110598641387) -->
+ <skip />
+ <!-- no translation found for long_press_widget_to_add (4307462194057715796) -->
+ <skip />
+ <!-- no translation found for all_apps_no_games (5293893733372793696) -->
+ <skip />
+ <!-- no translation found for all_apps_no_downloads (2284720393234453761) -->
+ <skip />
+ <!-- no translation found for market (2652226429823445833) -->
+ <skip />
+ <!-- no translation found for external_drop_widget_error (4976816434597126575) -->
+ <skip />
+ <!-- no translation found for external_drop_widget_pick_title (4481311720134376218) -->
+ <skip />
+ <string name="rename_folder_label" msgid="5646236631298452787">"አቃፊ ስም"</string>
+ <!-- no translation found for rename_folder_title (4544573104191526550) -->
+ <skip />
+ <!-- no translation found for rename_action (6016003384693240896) -->
+ <skip />
+ <!-- no translation found for cancel_action (3811860427489435048) -->
+ <skip />
+ <string name="menu_item_add_item" msgid="6233177331075781114">"ወደ መነሻ ማያ አክል"</string>
+ <string name="group_applications" msgid="4118484163419674240">"መተግበሪያዎች"</string>
+ <string name="group_shortcuts" msgid="9133529424900391877">"አቋራጮች"</string>
+ <string name="group_folder" msgid="5143593791798929193">"አዲስ አቃፊ"</string>
+ <string name="group_live_folders" msgid="2664945399140647217">"አቃፊዎች"</string>
+ <string name="group_widgets" msgid="6704978494073105844">"ፍርግሞች"</string>
+ <string name="group_wallpapers" msgid="1568191644272224858">"ልጣፍ"</string>
+ <!-- no translation found for add_folder (3521088587367839879) -->
+ <skip />
+ <!-- no translation found for add_clock (2337943840175865746) -->
+ <skip />
+ <!-- no translation found for add_photo_frame (3154058437359487954) -->
+ <skip />
+ <!-- no translation found for out_of_space (8365249326091984698) -->
+ <skip />
+ <string name="shortcut_installed" msgid="7071557296331322355">"አቋራጭ\"<xliff:g id="NAME">%s</xliff:g> \"ተፈጥሯል።"</string>
+ <string name="shortcut_uninstalled" msgid="2129499669449749995">"አቋራጭ \"<xliff:g id="NAME">%s</xliff:g>\" ተወግዶ ነበር።"</string>
+ <string name="shortcut_duplicate" msgid="4757756326465060694">"አቋራጭ \"<xliff:g id="NAME">%s</xliff:g>\" አስቀድሞ አለ።"</string>
+ <string name="title_select_shortcut" msgid="2858897527672831763">"አቋራጭ ምረጥ"</string>
+ <string name="title_select_application" msgid="8031072293115454221">"ትግበራ ይምረጡ"</string>
+ <string name="title_select_live_folder" msgid="3753447798805166749">"አቃፊ ምረጥ"</string>
+ <string name="all_apps_button_label" msgid="2578400570124163469">"ትግበራ"</string>
+ <string name="all_apps_home_button_label" msgid="1022222300329398558">"መነሻ"</string>
+ <!-- no translation found for delete_zone_label_workspace (7153615831493049150) -->
+ <skip />
+ <!-- no translation found for delete_zone_label_all_apps (6664588234817475108) -->
+ <skip />
+ <!-- no translation found for delete_target_label (665300185123139530) -->
+ <skip />
+ <!-- no translation found for delete_target_uninstall_label (748894921183769150) -->
+ <skip />
+ <!-- no translation found for info_target_label (6175926565900432067) -->
+ <skip />
+ <!-- no translation found for accessibility_search_button (816822994629942611) -->
+ <skip />
+ <!-- no translation found for accessibility_voice_search_button (3938249215065842475) -->
+ <skip />
+ <!-- no translation found for accessibility_all_apps_button (1595097919145716305) -->
+ <skip />
+ <!-- no translation found for accessibility_customize_button (585539669413531163) -->
+ <skip />
+ <!-- no translation found for accessibility_delete_button (3628162007991023603) -->
+ <skip />
+ <!-- no translation found for delete_zone_label_all_apps_system_app (3683920959591819044) -->
+ <skip />
+ <!-- no translation found for menu_add (3065046628354640854) -->
+ <skip />
+ <!-- no translation found for menu_manage_apps (2308685199463588895) -->
+ <skip />
+ <!-- no translation found for menu_wallpaper (5837429080911269832) -->
+ <skip />
+ <!-- no translation found for menu_search (4826514464423239041) -->
+ <skip />
+ <!-- no translation found for menu_notifications (6424587053194766192) -->
+ <skip />
+ <string name="menu_gestures" msgid="514678675575912237">"የሰውነትእንቅስቃሴዎች"</string>
+ <!-- no translation found for menu_settings (6233960148378443661) -->
+ <skip />
+ <string name="cab_menu_delete_app" msgid="1242619904941293871">"ትግበራ አራግፍ"</string>
+ <string name="cab_menu_app_info" msgid="5180426909324882018">"የትግበራ ዝርዝሮች"</string>
+ <string name="cab_app_selection_text" msgid="606113924828167756">"1 ትግበራ ተመርጧል"</string>
+ <string name="cab_widget_selection_text" msgid="962527270506951955">"1 ዊድጌት ተመርጧል"</string>
+ <string name="cab_folder_selection_text" msgid="8916111874189565067">"1 አቃፊ ተመርጧል"</string>
+ <string name="cab_shortcut_selection_text" msgid="8115847384500412878">"1 አቋራጭ ተመርጧል"</string>
+ <!-- no translation found for permlab_install_shortcut (1201690825493376489) -->
+ <skip />
+ <string name="permdesc_install_shortcut" msgid="7429365847558984148">"ያለተጠቃሚ ጣልቃገብነት ትግበራአቋራጭ ለማከል ይፈቅዳል።"</string>
+ <!-- no translation found for permlab_uninstall_shortcut (7696645932555926449) -->
+ <skip />
+ <string name="permdesc_uninstall_shortcut" msgid="959972195916090900">"ያለተጠቃሚ ጣልቃገብነት ትግበራአቋራጭ ለማስወገድ ይፈቅዳል።"</string>
+ <string name="permlab_read_settings" msgid="3452408290738106747">"የመነሻቅንብሮች እና አቋራጮችን አንብብ"</string>
+ <string name="permdesc_read_settings" msgid="8377434937176025492">"ቅንብሮችን እና አቋራጮችን በመነሻለማንበብ ትግበራ ይፈቅዳል።"</string>
+ <string name="permlab_write_settings" msgid="1360567537236705628">"መነሻ ቅንብሮች እና አቋራጮች ፃፍ"</string>
+ <string name="permdesc_write_settings" msgid="1098648778383349818">"ቅንብሮችን እና አቋራጮችን በመነሻለመለወጥ ትግበራ ይፈቅዳል።"</string>
+ <string name="gadget_error_text" msgid="8359351016167075858">"ፍርግም የመጫን ችግር"</string>
+ <string name="uninstall_system_app_text" msgid="7488523163288397451">"ይህ የስርዓት ትግበራ ነው እና አለማራገፍ አይቻልም።"</string>
+ <!-- no translation found for dream_name (2847171357608437154) -->
+ <skip />
+</resources>
diff --git a/res/values-ar-land/strings.xml b/res/values-ar-land/strings.xml
new file mode 100644
index 000000000..b976926f0
--- /dev/null
+++ b/res/values-ar-land/strings.xml
@@ -0,0 +1,25 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="delete_target_label" msgid="4155210680095864979"></string>
+ <string name="delete_target_uninstall_label" msgid="1839407506844917298"></string>
+ <string name="info_target_label" msgid="1424400595004570393"></string>
+</resources>
diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml
index df0a21089..9caf56bfe 100644
--- a/res/values-ar/strings.xml
+++ b/res/values-ar/strings.xml
@@ -37,6 +37,7 @@
<string name="all_apps_tab_apps" msgid="5468972551904071712">"التطبيقات"</string>
<string name="all_apps_tab_games" msgid="1855736784923494918">"الألعاب"</string>
<string name="all_apps_tab_downloaded" msgid="1488049110598641387">"تطبيقاتي"</string>
+ <string name="long_press_widget_to_add" msgid="4307462194057715796">"اضغط مع الاستمرار لاختيار إحدى الأدوات"</string>
<string name="all_apps_no_games" msgid="5293893733372793696">"لم يتم العثور على ألعاب"</string>
<string name="all_apps_no_downloads" msgid="2284720393234453761">"ليس لديك أي تطبيقات تم تنزيلها."</string>
<string name="market" msgid="2652226429823445833">"تسوق"</string>
@@ -67,6 +68,17 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"الرئيسية"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"إزالة"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"إزالة"</string>
+ <!-- no translation found for delete_target_label (665300185123139530) -->
+ <skip />
+ <!-- no translation found for delete_target_uninstall_label (748894921183769150) -->
+ <skip />
+ <!-- no translation found for info_target_label (6175926565900432067) -->
+ <skip />
+ <string name="accessibility_search_button" msgid="816822994629942611">"بحث"</string>
+ <string name="accessibility_voice_search_button" msgid="3938249215065842475">"البحث الصوتي"</string>
+ <string name="accessibility_all_apps_button" msgid="1595097919145716305">"التطبيقات"</string>
+ <string name="accessibility_customize_button" msgid="585539669413531163">"تخصيص"</string>
+ <string name="accessibility_delete_button" msgid="3628162007991023603">"إزالة"</string>
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"إزالة التحديث"</string>
<string name="menu_add" msgid="3065046628354640854">"إضافة"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"إدارة التطبيقات"</string>
@@ -91,4 +103,5 @@
<string name="permdesc_write_settings" msgid="1098648778383349818">"للسماح لتطبيق ما بتغيير الإعدادات والاختصارات في الشاشة الرئيسية."</string>
<string name="gadget_error_text" msgid="8359351016167075858">"حدثت مشكلة أثناء تحميل الأداة"</string>
<string name="uninstall_system_app_text" msgid="7488523163288397451">"هذا تطبيق نظام وتتعذر إزالته."</string>
+ <string name="dream_name" msgid="2847171357608437154">"راجمة"</string>
</resources>
diff --git a/res/values-bg-land/strings.xml b/res/values-bg-land/strings.xml
new file mode 100644
index 000000000..b976926f0
--- /dev/null
+++ b/res/values-bg-land/strings.xml
@@ -0,0 +1,25 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="delete_target_label" msgid="4155210680095864979"></string>
+ <string name="delete_target_uninstall_label" msgid="1839407506844917298"></string>
+ <string name="info_target_label" msgid="1424400595004570393"></string>
+</resources>
diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml
index 5be82f164..eb409f1aa 100644
--- a/res/values-bg/strings.xml
+++ b/res/values-bg/strings.xml
@@ -37,6 +37,7 @@
<string name="all_apps_tab_apps" msgid="5468972551904071712">"Приложения"</string>
<string name="all_apps_tab_games" msgid="1855736784923494918">"Игри"</string>
<string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Моите приложения"</string>
+ <string name="long_press_widget_to_add" msgid="4307462194057715796">"Натиснете дълго за избор на приспособление"</string>
<string name="all_apps_no_games" msgid="5293893733372793696">"Няма намерени игри."</string>
<string name="all_apps_no_downloads" msgid="2284720393234453761">"Нямате изтеглени приложения."</string>
<string name="market" msgid="2652226429823445833">"Магазин"</string>
@@ -67,6 +68,17 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Начало"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Премахване"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Деинсталиране"</string>
+ <!-- no translation found for delete_target_label (665300185123139530) -->
+ <skip />
+ <!-- no translation found for delete_target_uninstall_label (748894921183769150) -->
+ <skip />
+ <!-- no translation found for info_target_label (6175926565900432067) -->
+ <skip />
+ <string name="accessibility_search_button" msgid="816822994629942611">"Търсене"</string>
+ <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Гласово търсене"</string>
+ <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Приложения"</string>
+ <string name="accessibility_customize_button" msgid="585539669413531163">"Персонализиране"</string>
+ <string name="accessibility_delete_button" msgid="3628162007991023603">"Премахване"</string>
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Деинстал. на актуализацията"</string>
<string name="menu_add" msgid="3065046628354640854">"Добавяне"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Управление на приложенията"</string>
@@ -91,4 +103,5 @@
<string name="permdesc_write_settings" msgid="1098648778383349818">"Разрешава на приложение да промени настройките и преките пътища в „Начало“."</string>
<string name="gadget_error_text" msgid="8359351016167075858">"Проблем при зареждане на приспособление"</string>
<string name="uninstall_system_app_text" msgid="7488523163288397451">"Това е системно приложение и не може да се деинсталира."</string>
+ <string name="dream_name" msgid="2847171357608437154">"Ракетна площадка"</string>
</resources>
diff --git a/res/values-ca-land/strings.xml b/res/values-ca-land/strings.xml
new file mode 100644
index 000000000..b976926f0
--- /dev/null
+++ b/res/values-ca-land/strings.xml
@@ -0,0 +1,25 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="delete_target_label" msgid="4155210680095864979"></string>
+ <string name="delete_target_uninstall_label" msgid="1839407506844917298"></string>
+ <string name="info_target_label" msgid="1424400595004570393"></string>
+</resources>
diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml
index 56ada67fa..c778b6cfb 100644
--- a/res/values-ca/strings.xml
+++ b/res/values-ca/strings.xml
@@ -37,6 +37,7 @@
<string name="all_apps_tab_apps" msgid="5468972551904071712">"Aplicacions"</string>
<string name="all_apps_tab_games" msgid="1855736784923494918">"Jocs"</string>
<string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Les meves aplicacions"</string>
+ <string name="long_press_widget_to_add" msgid="4307462194057715796">"Mantén premut un widget per triar-lo"</string>
<string name="all_apps_no_games" msgid="5293893733372793696">"No s\'ha trobat cap joc."</string>
<string name="all_apps_no_downloads" msgid="2284720393234453761">"No has baixat cap aplicació."</string>
<string name="market" msgid="2652226429823445833">"Botiga"</string>
@@ -67,6 +68,17 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Pàgina d\'inici"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Elimina"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Desinstal·la"</string>
+ <!-- no translation found for delete_target_label (665300185123139530) -->
+ <skip />
+ <!-- no translation found for delete_target_uninstall_label (748894921183769150) -->
+ <skip />
+ <!-- no translation found for info_target_label (6175926565900432067) -->
+ <skip />
+ <string name="accessibility_search_button" msgid="816822994629942611">"Cerca"</string>
+ <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Cerca per veu"</string>
+ <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Aplicacions"</string>
+ <string name="accessibility_customize_button" msgid="585539669413531163">"Personalitza"</string>
+ <string name="accessibility_delete_button" msgid="3628162007991023603">"Elimina"</string>
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Desinstal·la l\'actualització"</string>
<string name="menu_add" msgid="3065046628354640854">"Afegeix"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Gestiona les aplicacions"</string>
@@ -91,4 +103,5 @@
<string name="permdesc_write_settings" msgid="1098648778383349818">"Permet que una aplicació canviï la configuració i les dreceres de la pantalla Inici."</string>
<string name="gadget_error_text" msgid="8359351016167075858">"S\'ha produït un problema en carregar el widget"</string>
<string name="uninstall_system_app_text" msgid="7488523163288397451">"Això és una aplicació del sistema i no es pot desinstal·lar."</string>
+ <string name="dream_name" msgid="2847171357608437154">"Llançamíssils"</string>
</resources>
diff --git a/res/values-cs-land/strings.xml b/res/values-cs-land/strings.xml
new file mode 100644
index 000000000..b976926f0
--- /dev/null
+++ b/res/values-cs-land/strings.xml
@@ -0,0 +1,25 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="delete_target_label" msgid="4155210680095864979"></string>
+ <string name="delete_target_uninstall_label" msgid="1839407506844917298"></string>
+ <string name="info_target_label" msgid="1424400595004570393"></string>
+</resources>
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index 47fb726cb..fefd5d5ee 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -37,6 +37,7 @@
<string name="all_apps_tab_apps" msgid="5468972551904071712">"Aplikace"</string>
<string name="all_apps_tab_games" msgid="1855736784923494918">"Hry"</string>
<string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Moje aplikace"</string>
+ <string name="long_press_widget_to_add" msgid="4307462194057715796">"Widget přidáte dlouhým stisknutím tlačítka"</string>
<string name="all_apps_no_games" msgid="5293893733372793696">"Nenalezeny žádné hry."</string>
<string name="all_apps_no_downloads" msgid="2284720393234453761">"Nemáte žádné stažené aplikace."</string>
<string name="market" msgid="2652226429823445833">"Obchod"</string>
@@ -67,6 +68,17 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Plocha"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Odebrat"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Odinstalovat"</string>
+ <!-- no translation found for delete_target_label (665300185123139530) -->
+ <skip />
+ <!-- no translation found for delete_target_uninstall_label (748894921183769150) -->
+ <skip />
+ <!-- no translation found for info_target_label (6175926565900432067) -->
+ <skip />
+ <string name="accessibility_search_button" msgid="816822994629942611">"Hledat"</string>
+ <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Hlasové vyhledávání"</string>
+ <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Aplikace"</string>
+ <string name="accessibility_customize_button" msgid="585539669413531163">"Personalizovat"</string>
+ <string name="accessibility_delete_button" msgid="3628162007991023603">"Odebrat"</string>
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Odinstalovat aktualizaci"</string>
<string name="menu_add" msgid="3065046628354640854">"Přidat"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Spravovat aplikace"</string>
@@ -91,4 +103,5 @@
<string name="permdesc_write_settings" msgid="1098648778383349818">"Povoluje aplikaci změnit nastavení a odkazy plochy."</string>
<string name="gadget_error_text" msgid="8359351016167075858">"Problém s načtením widgetu"</string>
<string name="uninstall_system_app_text" msgid="7488523163288397451">"Toto je systémová aplikace a nelze ji odinstalovat."</string>
+ <string name="dream_name" msgid="2847171357608437154">"Raketomet"</string>
</resources>
diff --git a/res/values-da-land/strings.xml b/res/values-da-land/strings.xml
new file mode 100644
index 000000000..b976926f0
--- /dev/null
+++ b/res/values-da-land/strings.xml
@@ -0,0 +1,25 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="delete_target_label" msgid="4155210680095864979"></string>
+ <string name="delete_target_uninstall_label" msgid="1839407506844917298"></string>
+ <string name="info_target_label" msgid="1424400595004570393"></string>
+</resources>
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
index 889b9b3e3..ab7378177 100644
--- a/res/values-da/strings.xml
+++ b/res/values-da/strings.xml
@@ -37,6 +37,7 @@
<string name="all_apps_tab_apps" msgid="5468972551904071712">"Programmer"</string>
<string name="all_apps_tab_games" msgid="1855736784923494918">"Spil"</string>
<string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Mine apps"</string>
+ <string name="long_press_widget_to_add" msgid="4307462194057715796">"Tryk længe for at tilføje en widget"</string>
<string name="all_apps_no_games" msgid="5293893733372793696">"Ingen spil."</string>
<string name="all_apps_no_downloads" msgid="2284720393234453761">"Du har ingen downloadede applikationer."</string>
<string name="market" msgid="2652226429823445833">"Butik"</string>
@@ -61,34 +62,46 @@
<string name="shortcut_uninstalled" msgid="2129499669449749995">"Genvejen \"<xliff:g id="NAME">%s</xliff:g>\" blev fjernet."</string>
<string name="shortcut_duplicate" msgid="4757756326465060694">"Genvejen \"<xliff:g id="NAME">%s</xliff:g>\" findes allerede."</string>
<string name="title_select_shortcut" msgid="2858897527672831763">"Vælg genvej"</string>
- <string name="title_select_application" msgid="8031072293115454221">"Vælg applikation"</string>
+ <string name="title_select_application" msgid="8031072293115454221">"Vælg program"</string>
<string name="title_select_live_folder" msgid="3753447798805166749">"Vælg mappe"</string>
<string name="all_apps_button_label" msgid="2578400570124163469">"Programmer"</string>
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Start"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Fjern"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Afinstaller"</string>
+ <!-- no translation found for delete_target_label (665300185123139530) -->
+ <skip />
+ <!-- no translation found for delete_target_uninstall_label (748894921183769150) -->
+ <skip />
+ <!-- no translation found for info_target_label (6175926565900432067) -->
+ <skip />
+ <string name="accessibility_search_button" msgid="816822994629942611">"Søg"</string>
+ <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Stemmesøgning"</string>
+ <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Programmer"</string>
+ <string name="accessibility_customize_button" msgid="585539669413531163">"Tilpas"</string>
+ <string name="accessibility_delete_button" msgid="3628162007991023603">"Fjern"</string>
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Afinstaller opdatering"</string>
<string name="menu_add" msgid="3065046628354640854">"Tilføj"</string>
- <string name="menu_manage_apps" msgid="2308685199463588895">"Administrer apps"</string>
+ <string name="menu_manage_apps" msgid="2308685199463588895">"Administrer programmer"</string>
<string name="menu_wallpaper" msgid="5837429080911269832">"Tapet"</string>
<string name="menu_search" msgid="4826514464423239041">"Søg"</string>
<string name="menu_notifications" msgid="6424587053194766192">"Meddelelser"</string>
<string name="menu_gestures" msgid="514678675575912237">"Gestus"</string>
<string name="menu_settings" msgid="6233960148378443661">"Indstillinger"</string>
- <string name="cab_menu_delete_app" msgid="1242619904941293871">"Afinstaller applikation"</string>
+ <string name="cab_menu_delete_app" msgid="1242619904941293871">"Afinstaller program"</string>
<string name="cab_menu_app_info" msgid="5180426909324882018">"Programoplysninger"</string>
- <string name="cab_app_selection_text" msgid="606113924828167756">"1 applikation er valgt"</string>
+ <string name="cab_app_selection_text" msgid="606113924828167756">"1 program er valgt"</string>
<string name="cab_widget_selection_text" msgid="962527270506951955">"1 widget er valgt"</string>
<string name="cab_folder_selection_text" msgid="8916111874189565067">"1 mappe er valgt"</string>
<string name="cab_shortcut_selection_text" msgid="8115847384500412878">"1 genvej er valgt"</string>
<string name="permlab_install_shortcut" msgid="1201690825493376489">"installer genveje"</string>
- <string name="permdesc_install_shortcut" msgid="7429365847558984148">"Tillader, at en applikation tilføjer genveje uden brugerindgriben."</string>
+ <string name="permdesc_install_shortcut" msgid="7429365847558984148">"Tillader, at et program tilføjer genveje uden brugerindgriben."</string>
<string name="permlab_uninstall_shortcut" msgid="7696645932555926449">"afinstaller genveje"</string>
- <string name="permdesc_uninstall_shortcut" msgid="959972195916090900">"Tillader, at en applikation fjerner genveje uden brugerindgriben."</string>
+ <string name="permdesc_uninstall_shortcut" msgid="959972195916090900">"Tillader, at et program fjerner genveje uden brugerindgriben."</string>
<string name="permlab_read_settings" msgid="3452408290738106747">"læs indstillinger og genveje for Start"</string>
- <string name="permdesc_read_settings" msgid="8377434937176025492">"Tillader, at en applikation læser indstillingerne og genvejene i Start."</string>
+ <string name="permdesc_read_settings" msgid="8377434937176025492">"Tillader, at et program læser indstillingerne og genvejene i Start."</string>
<string name="permlab_write_settings" msgid="1360567537236705628">"skriv indstillinger og genveje for Start"</string>
- <string name="permdesc_write_settings" msgid="1098648778383349818">"Tillader, at en applikation ændrer indstillingerne og genvejene i Start."</string>
+ <string name="permdesc_write_settings" msgid="1098648778383349818">"Tillader, at et program ændrer indstillingerne og genvejene i Start."</string>
<string name="gadget_error_text" msgid="8359351016167075858">"Der er problemer med indlæsning af widget"</string>
<string name="uninstall_system_app_text" msgid="7488523163288397451">"Dette er et systemprogram, som ikke kan afinstalleres."</string>
+ <string name="dream_name" msgid="2847171357608437154">"Rocket Launcher"</string>
</resources>
diff --git a/res/values-de-land/strings.xml b/res/values-de-land/strings.xml
new file mode 100644
index 000000000..b976926f0
--- /dev/null
+++ b/res/values-de-land/strings.xml
@@ -0,0 +1,25 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="delete_target_label" msgid="4155210680095864979"></string>
+ <string name="delete_target_uninstall_label" msgid="1839407506844917298"></string>
+ <string name="info_target_label" msgid="1424400595004570393"></string>
+</resources>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index 7ade81f2a..cbd24f175 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -37,6 +37,7 @@
<string name="all_apps_tab_apps" msgid="5468972551904071712">"Apps"</string>
<string name="all_apps_tab_games" msgid="1855736784923494918">"Spiele"</string>
<string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Meine Apps"</string>
+ <string name="long_press_widget_to_add" msgid="4307462194057715796">"Zum Hinzufügen eines Widgets lange drücken"</string>
<string name="all_apps_no_games" msgid="5293893733372793696">"Keine Spiele gefunden."</string>
<string name="all_apps_no_downloads" msgid="2284720393234453761">"Keine heruntergeladenen Anwendungen vorhanden"</string>
<string name="market" msgid="2652226429823445833">"Shop"</string>
@@ -67,6 +68,17 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Startseite"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Entfernen"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Deinstallieren"</string>
+ <!-- no translation found for delete_target_label (665300185123139530) -->
+ <skip />
+ <!-- no translation found for delete_target_uninstall_label (748894921183769150) -->
+ <skip />
+ <!-- no translation found for info_target_label (6175926565900432067) -->
+ <skip />
+ <string name="accessibility_search_button" msgid="816822994629942611">"Suchen"</string>
+ <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Sprachsuche"</string>
+ <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Apps"</string>
+ <string name="accessibility_customize_button" msgid="585539669413531163">"Anpassen"</string>
+ <string name="accessibility_delete_button" msgid="3628162007991023603">"Entfernen"</string>
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Update deinstallieren"</string>
<string name="menu_add" msgid="3065046628354640854">"Hinzufügen"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Apps verwalten"</string>
@@ -82,13 +94,14 @@
<string name="cab_folder_selection_text" msgid="8916111874189565067">"1 Ordner ausgewählt"</string>
<string name="cab_shortcut_selection_text" msgid="8115847384500412878">"1 Verknüpfung ausgewählt"</string>
<string name="permlab_install_shortcut" msgid="1201690825493376489">"Verknüpfungen installieren"</string>
- <string name="permdesc_install_shortcut" msgid="7429365847558984148">"Ermöglicht einer App das Hinzufügen von Verknüpfungen ohne Eingriff des Nutzers."</string>
+ <string name="permdesc_install_shortcut" msgid="7429365847558984148">"Ermöglicht einer Anwendung das Hinzufügen von Verknüpfungen ohne Eingriff des Nutzers."</string>
<string name="permlab_uninstall_shortcut" msgid="7696645932555926449">"Verknüpfungen deinstallieren"</string>
- <string name="permdesc_uninstall_shortcut" msgid="959972195916090900">"Ermöglicht einer App das Entfernen von Verknüpfungen ohne Eingriff des Nutzers."</string>
+ <string name="permdesc_uninstall_shortcut" msgid="959972195916090900">"Ermöglicht einer Anwendung das Entfernen von Verknüpfungen ohne Eingriff des Nutzers."</string>
<string name="permlab_read_settings" msgid="3452408290738106747">"Einstellungen und Shortcuts für Startseite lesen"</string>
- <string name="permdesc_read_settings" msgid="8377434937176025492">"Ermöglicht einer App, die Einstellungen und Shortcuts auf der Startseite zu lesen."</string>
+ <string name="permdesc_read_settings" msgid="8377434937176025492">"Ermöglicht einer Anwendung, die Einstellungen und Shortcuts auf der Startseite zu lesen."</string>
<string name="permlab_write_settings" msgid="1360567537236705628">"Einstellungen und Shortcuts für Startseite schreiben"</string>
- <string name="permdesc_write_settings" msgid="1098648778383349818">"Ermöglicht einer App, die Einstellungen und Shortcuts auf der Startseite zu ändern."</string>
+ <string name="permdesc_write_settings" msgid="1098648778383349818">"Ermöglicht einer Anwendung, die Einstellungen und Shortcuts auf der Startseite zu ändern."</string>
<string name="gadget_error_text" msgid="8359351016167075858">"Problem beim Laden des Widgets"</string>
<string name="uninstall_system_app_text" msgid="7488523163288397451">"Dies ist eine Systemanwendung, die nicht deinstalliert werden kann."</string>
+ <string name="dream_name" msgid="2847171357608437154">"Raketenstartgerät"</string>
</resources>
diff --git a/res/values-el-land/strings.xml b/res/values-el-land/strings.xml
new file mode 100644
index 000000000..b976926f0
--- /dev/null
+++ b/res/values-el-land/strings.xml
@@ -0,0 +1,25 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="delete_target_label" msgid="4155210680095864979"></string>
+ <string name="delete_target_uninstall_label" msgid="1839407506844917298"></string>
+ <string name="info_target_label" msgid="1424400595004570393"></string>
+</resources>
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
index 5e9b64492..7e981912e 100644
--- a/res/values-el/strings.xml
+++ b/res/values-el/strings.xml
@@ -37,6 +37,7 @@
<string name="all_apps_tab_apps" msgid="5468972551904071712">"Εφαρμογές"</string>
<string name="all_apps_tab_games" msgid="1855736784923494918">"Παιχνίδια"</string>
<string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Οι εφαρμογές μου"</string>
+ <string name="long_press_widget_to_add" msgid="4307462194057715796">"Πατήστε παρατεταμένα για επιλογή γραφικού στοιχείου"</string>
<string name="all_apps_no_games" msgid="5293893733372793696">"Δεν βρέθηκαν παιχνίδια."</string>
<string name="all_apps_no_downloads" msgid="2284720393234453761">"Δεν υπάρχουν εφαρμογές από λήψη."</string>
<string name="market" msgid="2652226429823445833">"Αγορές"</string>
@@ -67,6 +68,17 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Αρχική σελίδα"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Κατάργηση"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Κατάργηση εγκατάστασης"</string>
+ <!-- no translation found for delete_target_label (665300185123139530) -->
+ <skip />
+ <!-- no translation found for delete_target_uninstall_label (748894921183769150) -->
+ <skip />
+ <!-- no translation found for info_target_label (6175926565900432067) -->
+ <skip />
+ <string name="accessibility_search_button" msgid="816822994629942611">"Αναζήτηση"</string>
+ <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Φωνητική αναζήτηση"</string>
+ <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Εφαρμογές"</string>
+ <string name="accessibility_customize_button" msgid="585539669413531163">"Προσαρμογή"</string>
+ <string name="accessibility_delete_button" msgid="3628162007991023603">"Κατάργηση"</string>
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Κατάργηση εγκατάστασης ενημέρωσης"</string>
<string name="menu_add" msgid="3065046628354640854">"Προσθήκη"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Διαχείριση εφαρμογών"</string>
@@ -91,4 +103,5 @@
<string name="permdesc_write_settings" msgid="1098648778383349818">"Επιτρέπει σε μια εφαρμογή την αλλαγή των ρυθμίσεων και των συντομεύσεων στην αρχική οθόνη."</string>
<string name="gadget_error_text" msgid="8359351016167075858">"Παρουσιάστηκε πρόβλημα στη φόρτωση του γραφικού στοιχείου"</string>
<string name="uninstall_system_app_text" msgid="7488523163288397451">"Αυτή είναι εφαρμογή του συστήματος και δεν είναι δυνατή η κατάργηση της εγκατάστασής της."</string>
+ <string name="dream_name" msgid="2847171357608437154">"Rocket Launcher"</string>
</resources>
diff --git a/res/values-en-rGB-land/strings.xml b/res/values-en-rGB-land/strings.xml
new file mode 100644
index 000000000..b976926f0
--- /dev/null
+++ b/res/values-en-rGB-land/strings.xml
@@ -0,0 +1,25 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="delete_target_label" msgid="4155210680095864979"></string>
+ <string name="delete_target_uninstall_label" msgid="1839407506844917298"></string>
+ <string name="info_target_label" msgid="1424400595004570393"></string>
+</resources>
diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml
index 733413327..ff226f1b3 100644
--- a/res/values-en-rGB/strings.xml
+++ b/res/values-en-rGB/strings.xml
@@ -37,6 +37,7 @@
<string name="all_apps_tab_apps" msgid="5468972551904071712">"Apps"</string>
<string name="all_apps_tab_games" msgid="1855736784923494918">"Games"</string>
<string name="all_apps_tab_downloaded" msgid="1488049110598641387">"My apps"</string>
+ <string name="long_press_widget_to_add" msgid="4307462194057715796">"Long-press to pick up a widget"</string>
<string name="all_apps_no_games" msgid="5293893733372793696">"No games found."</string>
<string name="all_apps_no_downloads" msgid="2284720393234453761">"You have no downloaded applications."</string>
<string name="market" msgid="2652226429823445833">"Shop"</string>
@@ -67,6 +68,17 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Home"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Remove"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Uninstall"</string>
+ <!-- no translation found for delete_target_label (665300185123139530) -->
+ <skip />
+ <!-- no translation found for delete_target_uninstall_label (748894921183769150) -->
+ <skip />
+ <!-- no translation found for info_target_label (6175926565900432067) -->
+ <skip />
+ <string name="accessibility_search_button" msgid="816822994629942611">"Search"</string>
+ <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Voice Search"</string>
+ <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Applications"</string>
+ <string name="accessibility_customize_button" msgid="585539669413531163">"Customise"</string>
+ <string name="accessibility_delete_button" msgid="3628162007991023603">"Remove"</string>
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Uninstall update"</string>
<string name="menu_add" msgid="3065046628354640854">"Add"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Manage apps"</string>
@@ -91,4 +103,5 @@
<string name="permdesc_write_settings" msgid="1098648778383349818">"Allows an application to change the settings and shortcuts in Home."</string>
<string name="gadget_error_text" msgid="8359351016167075858">"Problem loading widget"</string>
<string name="uninstall_system_app_text" msgid="7488523163288397451">"This is a system application and cannot be uninstalled."</string>
+ <string name="dream_name" msgid="2847171357608437154">"Rocket Launcher"</string>
</resources>
diff --git a/res/values-es-land/strings.xml b/res/values-es-land/strings.xml
new file mode 100644
index 000000000..b976926f0
--- /dev/null
+++ b/res/values-es-land/strings.xml
@@ -0,0 +1,25 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="delete_target_label" msgid="4155210680095864979"></string>
+ <string name="delete_target_uninstall_label" msgid="1839407506844917298"></string>
+ <string name="info_target_label" msgid="1424400595004570393"></string>
+</resources>
diff --git a/res/values-es-rUS-land/strings.xml b/res/values-es-rUS-land/strings.xml
new file mode 100644
index 000000000..b976926f0
--- /dev/null
+++ b/res/values-es-rUS-land/strings.xml
@@ -0,0 +1,25 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="delete_target_label" msgid="4155210680095864979"></string>
+ <string name="delete_target_uninstall_label" msgid="1839407506844917298"></string>
+ <string name="info_target_label" msgid="1424400595004570393"></string>
+</resources>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
index eadcbaef4..ee79c4aef 100644
--- a/res/values-es-rUS/strings.xml
+++ b/res/values-es-rUS/strings.xml
@@ -37,6 +37,7 @@
<string name="all_apps_tab_apps" msgid="5468972551904071712">"Aplicaciones"</string>
<string name="all_apps_tab_games" msgid="1855736784923494918">"Juegos"</string>
<string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Mis aplicaciones"</string>
+ <string name="long_press_widget_to_add" msgid="4307462194057715796">"Realiza una pulsación larga para tomar un widget"</string>
<string name="all_apps_no_games" msgid="5293893733372793696">"No se encontraron juegos."</string>
<string name="all_apps_no_downloads" msgid="2284720393234453761">"No has descargado ninguna aplicación."</string>
<string name="market" msgid="2652226429823445833">"Comprar"</string>
@@ -67,6 +68,17 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Página principal"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Quitar"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Desinstalar"</string>
+ <!-- no translation found for delete_target_label (665300185123139530) -->
+ <skip />
+ <!-- no translation found for delete_target_uninstall_label (748894921183769150) -->
+ <skip />
+ <!-- no translation found for info_target_label (6175926565900432067) -->
+ <skip />
+ <string name="accessibility_search_button" msgid="816822994629942611">"Buscar"</string>
+ <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Búsqueda por voz"</string>
+ <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Aplicaciones"</string>
+ <string name="accessibility_customize_button" msgid="585539669413531163">"Personalizar"</string>
+ <string name="accessibility_delete_button" msgid="3628162007991023603">"Eliminar"</string>
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Desinstalar la actualización"</string>
<string name="menu_add" msgid="3065046628354640854">"Agregar"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Administrar aplicaciones"</string>
@@ -91,4 +103,5 @@
<string name="permdesc_write_settings" msgid="1098648778383349818">"Permite a una aplicación cambiar la configuración y los accesos directos de la página principal."</string>
<string name="gadget_error_text" msgid="8359351016167075858">"Problema al cargar el widget"</string>
<string name="uninstall_system_app_text" msgid="7488523163288397451">"Esta es una aplicación de sistema y no puede desinstalarse."</string>
+ <string name="dream_name" msgid="2847171357608437154">"Lanzacohetes"</string>
</resources>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index 90b4e1d7d..0e500e722 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -37,6 +37,7 @@
<string name="all_apps_tab_apps" msgid="5468972551904071712">"Aplicaciones"</string>
<string name="all_apps_tab_games" msgid="1855736784923494918">"Juegos"</string>
<string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Mis aplicaciones"</string>
+ <string name="long_press_widget_to_add" msgid="4307462194057715796">"Mantener pulsado para seleccionar un widget"</string>
<string name="all_apps_no_games" msgid="5293893733372793696">"No hay juegos."</string>
<string name="all_apps_no_downloads" msgid="2284720393234453761">"No tienes aplicaciones descargadas."</string>
<string name="market" msgid="2652226429823445833">"Tienda"</string>
@@ -67,6 +68,17 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Inicio"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Eliminar del escritorio"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Desinstalar"</string>
+ <!-- no translation found for delete_target_label (665300185123139530) -->
+ <skip />
+ <!-- no translation found for delete_target_uninstall_label (748894921183769150) -->
+ <skip />
+ <!-- no translation found for info_target_label (6175926565900432067) -->
+ <skip />
+ <string name="accessibility_search_button" msgid="816822994629942611">"Buscar"</string>
+ <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Búsqueda por voz"</string>
+ <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Aplicaciones"</string>
+ <string name="accessibility_customize_button" msgid="585539669413531163">"Personalizar"</string>
+ <string name="accessibility_delete_button" msgid="3628162007991023603">"Eliminar"</string>
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Desinstalar actualización"</string>
<string name="menu_add" msgid="3065046628354640854">"Añadir"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Administrar aplicaciones"</string>
@@ -91,4 +103,5 @@
<string name="permdesc_write_settings" msgid="1098648778383349818">"Permite que una aplicación modifique la configuración y los accesos directos de la página de inicio."</string>
<string name="gadget_error_text" msgid="8359351016167075858">"Problema al cargar el widget"</string>
<string name="uninstall_system_app_text" msgid="7488523163288397451">"Se trata de una aplicación del sistema y no se puede desinstalar."</string>
+ <string name="dream_name" msgid="2847171357608437154">"Rocket Launcher"</string>
</resources>
diff --git a/res/values-fa-land/strings.xml b/res/values-fa-land/strings.xml
new file mode 100644
index 000000000..b976926f0
--- /dev/null
+++ b/res/values-fa-land/strings.xml
@@ -0,0 +1,25 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="delete_target_label" msgid="4155210680095864979"></string>
+ <string name="delete_target_uninstall_label" msgid="1839407506844917298"></string>
+ <string name="info_target_label" msgid="1424400595004570393"></string>
+</resources>
diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml
index 0d53ea5f0..90824b1fe 100644
--- a/res/values-fa/strings.xml
+++ b/res/values-fa/strings.xml
@@ -37,6 +37,7 @@
<string name="all_apps_tab_apps" msgid="5468972551904071712">"برنامه های کاربردی"</string>
<string name="all_apps_tab_games" msgid="1855736784923494918">"بازی ها"</string>
<string name="all_apps_tab_downloaded" msgid="1488049110598641387">"برنامه های من"</string>
+ <string name="long_press_widget_to_add" msgid="4307462194057715796">"برای انتخاب ابزارک، برای مدت طولانی فشار دهید"</string>
<string name="all_apps_no_games" msgid="5293893733372793696">"هیچ بازی پیدا نشد."</string>
<string name="all_apps_no_downloads" msgid="2284720393234453761">"شما هیچ برنامه کاربردی دانلود شده ای ندارید."</string>
<string name="market" msgid="2652226429823445833">"فروشگاه"</string>
@@ -67,6 +68,17 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"صفحه اصلی"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"حذف"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"حذف نصب"</string>
+ <!-- no translation found for delete_target_label (665300185123139530) -->
+ <skip />
+ <!-- no translation found for delete_target_uninstall_label (748894921183769150) -->
+ <skip />
+ <!-- no translation found for info_target_label (6175926565900432067) -->
+ <skip />
+ <string name="accessibility_search_button" msgid="816822994629942611">"جستجو"</string>
+ <string name="accessibility_voice_search_button" msgid="3938249215065842475">"جستجوی صوتی"</string>
+ <string name="accessibility_all_apps_button" msgid="1595097919145716305">"برنامه های کاربردی"</string>
+ <string name="accessibility_customize_button" msgid="585539669413531163">"سفارشی کردن"</string>
+ <string name="accessibility_delete_button" msgid="3628162007991023603">"حذف"</string>
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"حذف نصب به روزرسانی"</string>
<string name="menu_add" msgid="3065046628354640854">"افزودن"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"مدیریت برنامه ها"</string>
@@ -91,4 +103,5 @@
<string name="permdesc_write_settings" msgid="1098648778383349818">"به برنامه کاربردی اجازه می دهد تنظیمات و میانبرها را در صفحه اصلی تغییر دهد."</string>
<string name="gadget_error_text" msgid="8359351016167075858">"مشکل در بارگیری ابزارک"</string>
<string name="uninstall_system_app_text" msgid="7488523163288397451">"این یک برنامه سیستمی است و لغو نصب نمی شود."</string>
+ <string name="dream_name" msgid="2847171357608437154">"پرتاب کننده موشک"</string>
</resources>
diff --git a/res/values-fi-land/strings.xml b/res/values-fi-land/strings.xml
new file mode 100644
index 000000000..b976926f0
--- /dev/null
+++ b/res/values-fi-land/strings.xml
@@ -0,0 +1,25 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="delete_target_label" msgid="4155210680095864979"></string>
+ <string name="delete_target_uninstall_label" msgid="1839407506844917298"></string>
+ <string name="info_target_label" msgid="1424400595004570393"></string>
+</resources>
diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml
index 7b02c8ddb..4a7fc67fd 100644
--- a/res/values-fi/strings.xml
+++ b/res/values-fi/strings.xml
@@ -37,6 +37,7 @@
<string name="all_apps_tab_apps" msgid="5468972551904071712">"Sovellukset"</string>
<string name="all_apps_tab_games" msgid="1855736784923494918">"Pelit"</string>
<string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Omat sovellukset"</string>
+ <string name="long_press_widget_to_add" msgid="4307462194057715796">"Valitse widget painamalla sitä pitkään"</string>
<string name="all_apps_no_games" msgid="5293893733372793696">"Ei pelejä."</string>
<string name="all_apps_no_downloads" msgid="2284720393234453761">"Ei ladattuja sovelluksia."</string>
<string name="market" msgid="2652226429823445833">"Myymälä"</string>
@@ -67,6 +68,17 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Etusivu"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Poista"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Poista"</string>
+ <!-- no translation found for delete_target_label (665300185123139530) -->
+ <skip />
+ <!-- no translation found for delete_target_uninstall_label (748894921183769150) -->
+ <skip />
+ <!-- no translation found for info_target_label (6175926565900432067) -->
+ <skip />
+ <string name="accessibility_search_button" msgid="816822994629942611">"Haku"</string>
+ <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Äänihaku"</string>
+ <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Sovellukset"</string>
+ <string name="accessibility_customize_button" msgid="585539669413531163">"Muokkaa"</string>
+ <string name="accessibility_delete_button" msgid="3628162007991023603">"Poista"</string>
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Poista päivitys"</string>
<string name="menu_add" msgid="3065046628354640854">"Lisää"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Hallinnoi sovelluksia"</string>
@@ -91,4 +103,5 @@
<string name="permdesc_write_settings" msgid="1098648778383349818">"Antaa sovelluksen muuttaa etusivun asetuksia ja pikakuvakkeita."</string>
<string name="gadget_error_text" msgid="8359351016167075858">"Ongelma ladattaessa widgetiä"</string>
<string name="uninstall_system_app_text" msgid="7488523163288397451">"Tämä on järjestelmäsovellus, eikä sitä voi poistaa."</string>
+ <string name="dream_name" msgid="2847171357608437154">"Sinko"</string>
</resources>
diff --git a/res/values-fr-land/strings.xml b/res/values-fr-land/strings.xml
new file mode 100644
index 000000000..b976926f0
--- /dev/null
+++ b/res/values-fr-land/strings.xml
@@ -0,0 +1,25 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="delete_target_label" msgid="4155210680095864979"></string>
+ <string name="delete_target_uninstall_label" msgid="1839407506844917298"></string>
+ <string name="info_target_label" msgid="1424400595004570393"></string>
+</resources>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index 7ff39d77c..fce065899 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -37,6 +37,7 @@
<string name="all_apps_tab_apps" msgid="5468972551904071712">"Applications"</string>
<string name="all_apps_tab_games" msgid="1855736784923494918">"Jeux"</string>
<string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Mes applications"</string>
+ <string name="long_press_widget_to_add" msgid="4307462194057715796">"Appuyer de manière prolongée pour ajouter un widget"</string>
<string name="all_apps_no_games" msgid="5293893733372793696">"Aucun jeu n\'a été trouvé."</string>
<string name="all_apps_no_downloads" msgid="2284720393234453761">"Vous n\'avez téléchargé aucune application."</string>
<string name="market" msgid="2652226429823445833">"Acheter"</string>
@@ -67,6 +68,17 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Page d\'accueil"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Supprimer"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Désinstaller"</string>
+ <!-- no translation found for delete_target_label (665300185123139530) -->
+ <skip />
+ <!-- no translation found for delete_target_uninstall_label (748894921183769150) -->
+ <skip />
+ <!-- no translation found for info_target_label (6175926565900432067) -->
+ <skip />
+ <string name="accessibility_search_button" msgid="816822994629942611">"Rechercher"</string>
+ <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Recherche vocale"</string>
+ <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Applications"</string>
+ <string name="accessibility_customize_button" msgid="585539669413531163">"Personnaliser"</string>
+ <string name="accessibility_delete_button" msgid="3628162007991023603">"Supprimer"</string>
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Désinstaller la mise à jour"</string>
<string name="menu_add" msgid="3065046628354640854">"Ajouter"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Gérer les applications"</string>
@@ -91,4 +103,5 @@
<string name="permdesc_write_settings" msgid="1098648778383349818">"Permet à une application de modifier les paramètres et les raccourcis de la page d\'accueil."</string>
<string name="gadget_error_text" msgid="8359351016167075858">"Problème lors du chargement du widget"</string>
<string name="uninstall_system_app_text" msgid="7488523163288397451">"Il s\'agit d\'une application système que vous ne pouvez pas désinstaller."</string>
+ <string name="dream_name" msgid="2847171357608437154">"Lance-missile"</string>
</resources>
diff --git a/res/values-hr-land/strings.xml b/res/values-hr-land/strings.xml
new file mode 100644
index 000000000..b976926f0
--- /dev/null
+++ b/res/values-hr-land/strings.xml
@@ -0,0 +1,25 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="delete_target_label" msgid="4155210680095864979"></string>
+ <string name="delete_target_uninstall_label" msgid="1839407506844917298"></string>
+ <string name="info_target_label" msgid="1424400595004570393"></string>
+</resources>
diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml
index ea09db0f4..1ae9210bf 100644
--- a/res/values-hr/strings.xml
+++ b/res/values-hr/strings.xml
@@ -37,6 +37,7 @@
<string name="all_apps_tab_apps" msgid="5468972551904071712">"Aplikacije"</string>
<string name="all_apps_tab_games" msgid="1855736784923494918">"Igre"</string>
<string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Moje aplikacije"</string>
+ <string name="long_press_widget_to_add" msgid="4307462194057715796">"Pritisnite dugo da biste podignuli widget"</string>
<string name="all_apps_no_games" msgid="5293893733372793696">"Igre nisu pronađene."</string>
<string name="all_apps_no_downloads" msgid="2284720393234453761">"Nemate preuzetih aplikacija"</string>
<string name="market" msgid="2652226429823445833">"Trgovina"</string>
@@ -67,6 +68,17 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Početna"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Ukloni"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Deinstaliraj"</string>
+ <!-- no translation found for delete_target_label (665300185123139530) -->
+ <skip />
+ <!-- no translation found for delete_target_uninstall_label (748894921183769150) -->
+ <skip />
+ <!-- no translation found for info_target_label (6175926565900432067) -->
+ <skip />
+ <string name="accessibility_search_button" msgid="816822994629942611">"Pretraži"</string>
+ <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Glasovno pretraživanje"</string>
+ <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Aplikacije"</string>
+ <string name="accessibility_customize_button" msgid="585539669413531163">"Prilagodi"</string>
+ <string name="accessibility_delete_button" msgid="3628162007991023603">"Ukloni"</string>
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Deinstalacija ažuriranja"</string>
<string name="menu_add" msgid="3065046628354640854">"Dodaj"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Upravljaj aplikacijama"</string>
@@ -91,4 +103,5 @@
<string name="permdesc_write_settings" msgid="1098648778383349818">"Dopušta aplikaciji promjenu postavki i prečaca na početnom zaslonu."</string>
<string name="gadget_error_text" msgid="8359351016167075858">"Problem pri učitavanju widgeta"</string>
<string name="uninstall_system_app_text" msgid="7488523163288397451">"Ovo je aplikacija sustava i ne može se ukloniti."</string>
+ <string name="dream_name" msgid="2847171357608437154">"Rocket Launcher"</string>
</resources>
diff --git a/res/values-hu-land/strings.xml b/res/values-hu-land/strings.xml
new file mode 100644
index 000000000..b976926f0
--- /dev/null
+++ b/res/values-hu-land/strings.xml
@@ -0,0 +1,25 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="delete_target_label" msgid="4155210680095864979"></string>
+ <string name="delete_target_uninstall_label" msgid="1839407506844917298"></string>
+ <string name="info_target_label" msgid="1424400595004570393"></string>
+</resources>
diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml
index 77d9dda2f..76b9e5b09 100644
--- a/res/values-hu/strings.xml
+++ b/res/values-hu/strings.xml
@@ -37,6 +37,7 @@
<string name="all_apps_tab_apps" msgid="5468972551904071712">"Alkalmazások"</string>
<string name="all_apps_tab_games" msgid="1855736784923494918">"Játékok"</string>
<string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Saját alkalmazások"</string>
+ <string name="long_press_widget_to_add" msgid="4307462194057715796">"Nyomja meg hosszan a modul felvételéhez"</string>
<string name="all_apps_no_games" msgid="5293893733372793696">"Nincsenek játékok."</string>
<string name="all_apps_no_downloads" msgid="2284720393234453761">"Nincsenek letöltött alkalmazásai."</string>
<string name="market" msgid="2652226429823445833">"Bolt"</string>
@@ -67,6 +68,17 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Főoldal"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Eltávolítás"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Eltávolítás"</string>
+ <!-- no translation found for delete_target_label (665300185123139530) -->
+ <skip />
+ <!-- no translation found for delete_target_uninstall_label (748894921183769150) -->
+ <skip />
+ <!-- no translation found for info_target_label (6175926565900432067) -->
+ <skip />
+ <string name="accessibility_search_button" msgid="816822994629942611">"Keresés"</string>
+ <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Hangalapú keresés"</string>
+ <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Alkalmazások"</string>
+ <string name="accessibility_customize_button" msgid="585539669413531163">"Személyre szabás"</string>
+ <string name="accessibility_delete_button" msgid="3628162007991023603">"Törlés"</string>
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Eltávolítja a frissítést"</string>
<string name="menu_add" msgid="3065046628354640854">"Hozzáadás"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Alkalmazások kezelése"</string>
@@ -91,4 +103,5 @@
<string name="permdesc_write_settings" msgid="1098648778383349818">"Lehetővé teszi egy alkalmazás számára, hogy módosítsa a Főoldal beállításait és parancsikonjait."</string>
<string name="gadget_error_text" msgid="8359351016167075858">"Probléma történt a modul betöltésekor"</string>
<string name="uninstall_system_app_text" msgid="7488523163288397451">"Ez egy rendszeralkalmazás, ezért nem lehet eltávolítani."</string>
+ <string name="dream_name" msgid="2847171357608437154">"Aknavető"</string>
</resources>
diff --git a/res/values-in-land/strings.xml b/res/values-in-land/strings.xml
new file mode 100644
index 000000000..b976926f0
--- /dev/null
+++ b/res/values-in-land/strings.xml
@@ -0,0 +1,25 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="delete_target_label" msgid="4155210680095864979"></string>
+ <string name="delete_target_uninstall_label" msgid="1839407506844917298"></string>
+ <string name="info_target_label" msgid="1424400595004570393"></string>
+</resources>
diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml
index a7ed85641..8ff09d91f 100644
--- a/res/values-in/strings.xml
+++ b/res/values-in/strings.xml
@@ -37,6 +37,7 @@
<string name="all_apps_tab_apps" msgid="5468972551904071712">"Apps"</string>
<string name="all_apps_tab_games" msgid="1855736784923494918">"Permainan"</string>
<string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Apl saya"</string>
+ <string name="long_press_widget_to_add" msgid="4307462194057715796">"Tekan lama untuk memilih gawit"</string>
<string name="all_apps_no_games" msgid="5293893733372793696">"Tidak ditemukan permainan."</string>
<string name="all_apps_no_downloads" msgid="2284720393234453761">"Anda tidak memiliki aplikasi yang diunduh."</string>
<string name="market" msgid="2652226429823445833">"Belanja"</string>
@@ -67,6 +68,17 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Rumah"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Hapus"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Copot pemasangan"</string>
+ <!-- no translation found for delete_target_label (665300185123139530) -->
+ <skip />
+ <!-- no translation found for delete_target_uninstall_label (748894921183769150) -->
+ <skip />
+ <!-- no translation found for info_target_label (6175926565900432067) -->
+ <skip />
+ <string name="accessibility_search_button" msgid="816822994629942611">"Telusuri"</string>
+ <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Penelusuran Suara"</string>
+ <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Aplikasi"</string>
+ <string name="accessibility_customize_button" msgid="585539669413531163">"Ubahsuaikan"</string>
+ <string name="accessibility_delete_button" msgid="3628162007991023603">"Hapus"</string>
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Copot pemasangan pemutakhiran"</string>
<string name="menu_add" msgid="3065046628354640854">"Tambahkan"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Mengelola aplikasi"</string>
@@ -91,4 +103,5 @@
<string name="permdesc_write_settings" msgid="1098648778383349818">"Mengizinkan aplikasi mengubah setelan dan pintasan dalam Beranda."</string>
<string name="gadget_error_text" msgid="8359351016167075858">"Masalah memuat widget"</string>
<string name="uninstall_system_app_text" msgid="7488523163288397451">"Ini adalah aplikasi sistem dan tidak dapat diunduh."</string>
+ <string name="dream_name" msgid="2847171357608437154">"Rocket Launcher"</string>
</resources>
diff --git a/res/values-it-land/strings.xml b/res/values-it-land/strings.xml
new file mode 100644
index 000000000..b976926f0
--- /dev/null
+++ b/res/values-it-land/strings.xml
@@ -0,0 +1,25 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="delete_target_label" msgid="4155210680095864979"></string>
+ <string name="delete_target_uninstall_label" msgid="1839407506844917298"></string>
+ <string name="info_target_label" msgid="1424400595004570393"></string>
+</resources>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index 003db6f3c..f7d471b76 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -37,6 +37,7 @@
<string name="all_apps_tab_apps" msgid="5468972551904071712">"Applicazioni"</string>
<string name="all_apps_tab_games" msgid="1855736784923494918">"Giochi"</string>
<string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Le mie applicazioni"</string>
+ <string name="long_press_widget_to_add" msgid="4307462194057715796">"Premi a lungo per selezionare un widget"</string>
<string name="all_apps_no_games" msgid="5293893733372793696">"Nessun gioco trovato."</string>
<string name="all_apps_no_downloads" msgid="2284720393234453761">"Non hai applicazioni scaricate."</string>
<string name="market" msgid="2652226429823445833">"Acquista"</string>
@@ -67,6 +68,17 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Home"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Rimuovi"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Disinstalla"</string>
+ <!-- no translation found for delete_target_label (665300185123139530) -->
+ <skip />
+ <!-- no translation found for delete_target_uninstall_label (748894921183769150) -->
+ <skip />
+ <!-- no translation found for info_target_label (6175926565900432067) -->
+ <skip />
+ <string name="accessibility_search_button" msgid="816822994629942611">"Cerca"</string>
+ <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Ricerca vocale"</string>
+ <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Applicazioni"</string>
+ <string name="accessibility_customize_button" msgid="585539669413531163">"Personalizza"</string>
+ <string name="accessibility_delete_button" msgid="3628162007991023603">"Rimuovi"</string>
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Disinstalla aggiornamento"</string>
<string name="menu_add" msgid="3065046628354640854">"Aggiungi"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Gestisci applicazioni"</string>
@@ -91,4 +103,5 @@
<string name="permdesc_write_settings" msgid="1098648778383349818">"Consente a un\'applicazione di modificare le impostazioni e le scorciatoie in Home."</string>
<string name="gadget_error_text" msgid="8359351016167075858">"Errore durante il caricamento del widget"</string>
<string name="uninstall_system_app_text" msgid="7488523163288397451">"Questa è un\'applicazione di sistema e non può essere disinstallata."</string>
+ <string name="dream_name" msgid="2847171357608437154">"Lanciamissili"</string>
</resources>
diff --git a/res/values-iw-land/strings.xml b/res/values-iw-land/strings.xml
new file mode 100644
index 000000000..b976926f0
--- /dev/null
+++ b/res/values-iw-land/strings.xml
@@ -0,0 +1,25 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="delete_target_label" msgid="4155210680095864979"></string>
+ <string name="delete_target_uninstall_label" msgid="1839407506844917298"></string>
+ <string name="info_target_label" msgid="1424400595004570393"></string>
+</resources>
diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml
index 75df2457c..3bbd1c6c5 100644
--- a/res/values-iw/strings.xml
+++ b/res/values-iw/strings.xml
@@ -37,6 +37,7 @@
<string name="all_apps_tab_apps" msgid="5468972551904071712">"יישומים"</string>
<string name="all_apps_tab_games" msgid="1855736784923494918">"משחקים"</string>
<string name="all_apps_tab_downloaded" msgid="1488049110598641387">"היישומים שלי"</string>
+ <string name="long_press_widget_to_add" msgid="4307462194057715796">"לחץ לחיצה ארוכה כדי לאסוף widget"</string>
<string name="all_apps_no_games" msgid="5293893733372793696">"לא נמצאו משחקים."</string>
<string name="all_apps_no_downloads" msgid="2284720393234453761">"לא הורדת יישומים."</string>
<string name="market" msgid="2652226429823445833">"קנה"</string>
@@ -67,6 +68,17 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"דף הבית"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"הסר"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"הסר התקנה"</string>
+ <!-- no translation found for delete_target_label (665300185123139530) -->
+ <skip />
+ <!-- no translation found for delete_target_uninstall_label (748894921183769150) -->
+ <skip />
+ <!-- no translation found for info_target_label (6175926565900432067) -->
+ <skip />
+ <string name="accessibility_search_button" msgid="816822994629942611">"חפש"</string>
+ <string name="accessibility_voice_search_button" msgid="3938249215065842475">"חיפוש קולי"</string>
+ <string name="accessibility_all_apps_button" msgid="1595097919145716305">"יישומים"</string>
+ <string name="accessibility_customize_button" msgid="585539669413531163">"התאם אישית"</string>
+ <string name="accessibility_delete_button" msgid="3628162007991023603">"הסר"</string>
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"הסר את התקנת העדכון"</string>
<string name="menu_add" msgid="3065046628354640854">"הוסף"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"נהל יישומים"</string>
@@ -91,4 +103,5 @@
<string name="permdesc_write_settings" msgid="1098648778383349818">"מאפשר ליישום לשנות את ההגדרות וקיצורי הדרך בדף הבית."</string>
<string name="gadget_error_text" msgid="8359351016167075858">"בעיה בטעינת widget"</string>
<string name="uninstall_system_app_text" msgid="7488523163288397451">"זהו יישום מערכת ואין אפשרות להסיר את התקנתו."</string>
+ <string name="dream_name" msgid="2847171357608437154">"Rocket Launcher"</string>
</resources>
diff --git a/res/values-ja-land/strings.xml b/res/values-ja-land/strings.xml
new file mode 100644
index 000000000..b976926f0
--- /dev/null
+++ b/res/values-ja-land/strings.xml
@@ -0,0 +1,25 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="delete_target_label" msgid="4155210680095864979"></string>
+ <string name="delete_target_uninstall_label" msgid="1839407506844917298"></string>
+ <string name="info_target_label" msgid="1424400595004570393"></string>
+</resources>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index ee6ab8326..6693568df 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -37,6 +37,7 @@
<string name="all_apps_tab_apps" msgid="5468972551904071712">"アプリ"</string>
<string name="all_apps_tab_games" msgid="1855736784923494918">"ゲーム"</string>
<string name="all_apps_tab_downloaded" msgid="1488049110598641387">"マイアプリ"</string>
+ <string name="long_press_widget_to_add" msgid="4307462194057715796">"ウィジェットを追加するには押し続けます"</string>
<string name="all_apps_no_games" msgid="5293893733372793696">"ゲームなし"</string>
<string name="all_apps_no_downloads" msgid="2284720393234453761">"ダウンロードしたアプリケーションはありません。"</string>
<string name="market" msgid="2652226429823445833">"ショップ"</string>
@@ -67,6 +68,17 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"ホーム"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"削除"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"アンインストール"</string>
+ <!-- no translation found for delete_target_label (665300185123139530) -->
+ <skip />
+ <!-- no translation found for delete_target_uninstall_label (748894921183769150) -->
+ <skip />
+ <!-- no translation found for info_target_label (6175926565900432067) -->
+ <skip />
+ <string name="accessibility_search_button" msgid="816822994629942611">"検索"</string>
+ <string name="accessibility_voice_search_button" msgid="3938249215065842475">"音声検索"</string>
+ <string name="accessibility_all_apps_button" msgid="1595097919145716305">"アプリケーション"</string>
+ <string name="accessibility_customize_button" msgid="585539669413531163">"カスタマイズ"</string>
+ <string name="accessibility_delete_button" msgid="3628162007991023603">"削除"</string>
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"アップデートをアンインストール"</string>
<string name="menu_add" msgid="3065046628354640854">"追加"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"アプリの管理"</string>
@@ -91,4 +103,5 @@
<string name="permdesc_write_settings" msgid="1098648778383349818">"ホームの設定とショートカットの変更をアプリケーションに許可します。"</string>
<string name="gadget_error_text" msgid="8359351016167075858">"ウィジェットを表示できません"</string>
<string name="uninstall_system_app_text" msgid="7488523163288397451">"このシステムアプリケーションはアンインストールできません。"</string>
+ <string name="dream_name" msgid="2847171357608437154">"Rocket Launcher"</string>
</resources>
diff --git a/res/values-ko-land/strings.xml b/res/values-ko-land/strings.xml
new file mode 100644
index 000000000..b976926f0
--- /dev/null
+++ b/res/values-ko-land/strings.xml
@@ -0,0 +1,25 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="delete_target_label" msgid="4155210680095864979"></string>
+ <string name="delete_target_uninstall_label" msgid="1839407506844917298"></string>
+ <string name="info_target_label" msgid="1424400595004570393"></string>
+</resources>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
index f2b8b0c10..3ff663ac8 100644
--- a/res/values-ko/strings.xml
+++ b/res/values-ko/strings.xml
@@ -37,6 +37,7 @@
<string name="all_apps_tab_apps" msgid="5468972551904071712">"애플리케이션"</string>
<string name="all_apps_tab_games" msgid="1855736784923494918">"게임"</string>
<string name="all_apps_tab_downloaded" msgid="1488049110598641387">"내 애플리케이션"</string>
+ <string name="long_press_widget_to_add" msgid="4307462194057715796">"위젯을 선택하려면 길게 누르세요."</string>
<string name="all_apps_no_games" msgid="5293893733372793696">"게임이 없습니다."</string>
<string name="all_apps_no_downloads" msgid="2284720393234453761">"다운로드한 애플리케이션이 없습니다."</string>
<string name="market" msgid="2652226429823445833">"쇼핑"</string>
@@ -67,6 +68,17 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"홈"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"삭제"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"제거"</string>
+ <!-- no translation found for delete_target_label (665300185123139530) -->
+ <skip />
+ <!-- no translation found for delete_target_uninstall_label (748894921183769150) -->
+ <skip />
+ <!-- no translation found for info_target_label (6175926565900432067) -->
+ <skip />
+ <string name="accessibility_search_button" msgid="816822994629942611">"검색"</string>
+ <string name="accessibility_voice_search_button" msgid="3938249215065842475">"음성 검색"</string>
+ <string name="accessibility_all_apps_button" msgid="1595097919145716305">"애플리케이션"</string>
+ <string name="accessibility_customize_button" msgid="585539669413531163">"맞춤설정"</string>
+ <string name="accessibility_delete_button" msgid="3628162007991023603">"삭제"</string>
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"업데이트 제거"</string>
<string name="menu_add" msgid="3065046628354640854">"추가"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"애플리케이션 관리"</string>
@@ -91,4 +103,5 @@
<string name="permdesc_write_settings" msgid="1098648778383349818">"애플리케이션이 홈에 있는 설정 및 바로가기를 변경할 수 있도록 합니다."</string>
<string name="gadget_error_text" msgid="8359351016167075858">"위젯을 로드하는 중 문제가 발생했습니다."</string>
<string name="uninstall_system_app_text" msgid="7488523163288397451">"시스템 애플리케이션은 제거할 수 없습니다."</string>
+ <string name="dream_name" msgid="2847171357608437154">"로켓 실행기"</string>
</resources>
diff --git a/res/values-land/dimens.xml b/res/values-land/dimens.xml
index 159cbb49e..13519e568 100644
--- a/res/values-land/dimens.xml
+++ b/res/values-land/dimens.xml
@@ -15,7 +15,29 @@
-->
<resources>
+<!-- QSB -->
+ <dimen name="toolbar_button_vertical_padding">12dip</dimen>
+ <dimen name="toolbar_button_horizontal_padding">12dip</dimen>
+
<dimen name="workspace_cell_width">106dip</dimen>
<dimen name="workspace_cell_height">74dip</dimen>
+ <dimen name="folder_cell_width">100dip</dimen>
+ <dimen name="folder_cell_height">74dip</dimen>
<dimen name="button_bar_height">62dip</dimen>
+
+ <integer name="all_apps_view_cellCountX">6</integer>
+ <integer name="all_apps_view_cellCountY">3</integer>
+ <dimen name="all_apps_view_pageLayoutWidthGap">10dp</dimen>
+ <dimen name="all_apps_view_pageLayoutHeightGap">5dp</dimen>
+ <dimen name="all_apps_view_pageLayoutPaddingTop">10dp</dimen>
+ <dimen name="all_apps_view_pageLayoutPaddingBottom">10dp</dimen>
+ <dimen name="all_apps_view_pageLayoutPaddingLeft">2dp</dimen>
+ <dimen name="all_apps_view_pageLayoutPaddingRight">2dp</dimen>
+
+ <dimen name="apps_customize_widget_cell_width_gap">30dp</dimen>
+ <dimen name="apps_customize_widget_cell_height_gap">0dp</dimen>
+ <integer name="apps_customize_widget_cell_count_x">3</integer>
+ <integer name="apps_customize_widget_cell_count_y">1</integer>
+ <integer name="apps_customize_wallpaper_cell_count_x">3</integer>
+ <integer name="apps_customize_wallpaper_cell_count_y">1</integer>
</resources>
diff --git a/res/values-land/strings.xml b/res/values-land/strings.xml
new file mode 100644
index 000000000..bbe8ff21f
--- /dev/null
+++ b/res/values-land/strings.xml
@@ -0,0 +1,30 @@
+<?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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Manifest configuration. -->
+ <skip />
+
+ <!-- Label for delete drop target. [CHAR_LIMIT=30] -->
+ <string name="delete_target_label"></string>
+ <!-- Label for uninstall drop target. [CHAR_LIMIT=30]-->
+ <string name="delete_target_uninstall_label"></string>
+ <!-- Label for the info icon. [CHAR_LIMIT=30] -->
+ <string name="info_target_label"></string>
+</resources>
diff --git a/res/values-land/styles.xml b/res/values-land/styles.xml
index 251c717e1..4daaeccac 100644
--- a/res/values-land/styles.xml
+++ b/res/values-land/styles.xml
@@ -18,6 +18,37 @@
-->
<resources>
+<!-- Search Bar -->
+ <style name="SearchDropTargetBar">
+ <item name="android:orientation">vertical</item>
+ </style>
+ <style name="SearchButton">
+ <item name="android:layout_gravity">center_horizontal</item>
+ <item name="android:paddingTop">@dimen/toolbar_button_vertical_padding</item>
+ <item name="android:paddingBottom">@dimen/toolbar_button_vertical_padding</item>
+ <item name="android:paddingLeft">@dimen/toolbar_button_horizontal_padding</item>
+ <item name="android:paddingRight">@dimen/toolbar_button_horizontal_padding</item>
+ </style>
+ <style name="SearchButtonDivider">
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:layout_gravity">center_horizontal</item>
+ </style>
+ <style name="DropTargetButtonContainer">
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">0dp</item>
+ </style>
+ <style name="DropTargetButton">
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:layout_gravity">center_vertical</item>
+ <item name="android:gravity">center_horizontal</item>
+ <item name="android:paddingTop">@dimen/toolbar_button_vertical_padding</item>
+ <item name="android:paddingBottom">@dimen/toolbar_button_vertical_padding</item>
+ <item name="android:paddingLeft">@dimen/toolbar_button_horizontal_padding</item>
+ <item name="android:paddingRight">@dimen/toolbar_button_horizontal_padding</item>
+ </style>
+
<style name="HotseatButton">
<item name="android:paddingTop">12dip</item>
<item name="android:paddingBottom">12dip</item>
diff --git a/res/values-large-port/dimens.xml b/res/values-large-port/dimens.xml
index 89f86053e..86bd03d24 100644
--- a/res/values-large-port/dimens.xml
+++ b/res/values-large-port/dimens.xml
@@ -15,11 +15,18 @@
-->
<resources>
+ <dimen name="apps_customize_cell_width">96dp</dimen>
+ <dimen name="apps_customize_cell_height">96dp</dimen>
+ <!-- The amount of space to account for the next/prev pages when
+ calculating the number of columns to fit a page.
+ In portrait/large we use apps_customize_cell_width / 8. -->
+ <dimen name="apps_customize_peek_width">12dp</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">40dp</dimen>
- <dimen name="all_apps_view_pageLayoutWidthGap">36dp</dimen>
+ <dimen name="all_apps_view_pageLayoutWidthGap">24dp</dimen>
<dimen name="all_apps_view_pageLayoutHeightGap">36dp</dimen>
<dimen name="all_apps_view_pageLayoutPaddingTop">25dp</dimen>
<dimen name="all_apps_view_pageLayoutPaddingBottom">10dp</dimen>
diff --git a/res/values-large/config.xml b/res/values-large/config.xml
index 4b0c8206f..2a5266415 100644
--- a/res/values-large/config.xml
+++ b/res/values-large/config.xml
@@ -1,81 +1,29 @@
<resources>
- <!-- NOTE: Many of the all apps values here are also used for the customization drawer -->
-
- <!-- Duration in milliseconds of the fade-in/out of the icons as they are being dragged
- from the AllApps or Customization trays -->
- <integer name="icon_allAppsCustomizeFadeInTime">150</integer>
- <integer name="icon_allAppsCustomizeFadeOutTime">200</integer>
- <integer name="icon_allAppsCustomizeFadeAlpha">102</integer>
-
- <!-- Duration in milliseconds of the all apps / configuration zoom-in animation. -->
- <!-- NB: This should be less than the workspaceShrinkTime as they happen together. -->
- <integer name="config_allAppsZoomInTime">1000</integer>
- <integer name="config_allAppsFadeInTime">250</integer>
-
- <!-- Duration in milliseconds of the transition between tabs in the all apps/customize
- tray -->
- <integer name="config_tabTransitionTime">100</integer>
-
- <!-- Duration in milliseconds of the all apps zoom-out animation -->
- <!-- NB: This should be less than the workspaceUnshrinkTime as they happen together. -->
- <integer name="config_allAppsZoomOutTime">1200</integer>
-
- <!-- Scaling factor used in the all apps zooming animations -->
- <integer name="config_allAppsZoomScaleFactor">20</integer>
-
- <!-- Duration in milliseconds of the all apps / configuration zoom-in animation. -->
- <!-- NB: This should be less than the workspaceShrinkTime as they happen together. -->
+<!-- AllApps/Customize/AppsCustomize -->
+ <!-- Fade/zoom in/out duration & scale in the Customize transition.
+ Note: This should be less than the workspaceShrinkTime as they happen together. -->
<integer name="config_customizeZoomInTime">800</integer>
- <integer name="config_customizeFadeInTime">800</integer>
-
- <!-- Duration in milliseconds of the all apps zoom-out animation -->
- <!-- NB: This should be less than the workspaceUnshrinkTime as they happen together. -->
<integer name="config_customizeZoomOutTime">600</integer>
-
- <!-- Scaling factor used in the all apps zooming animations -->
<integer name="config_customizeZoomScaleFactor">7</integer>
+ <integer name="config_customizeFadeInTime">800</integer>
+ <!-- Out of 100, the percent to shrink the workspace during spring loaded mode. -->
+ <integer name="config_workspaceSpringLoadShrinkPercentage">90</integer>
+
+ <!-- The slope, in percent, of the drag movement needed to drag an item out of
+ Customize (y / x * 100%) -->
+ <integer name="config_customizationDrawerDragSlopeThreshold">150</integer>
<!-- Duration in milliseconds of the animations between all apps, customize, & home.
NOTE: If these are changed, the toolbar animation times below should also be. -->
- <integer name="config_allAppsFadeOutTime">500</integer>
<integer name="config_customizeWorkspaceShrinkTime">800</integer>
- <integer name="config_allAppsWorkspaceShrinkTime">1000</integer>
- <integer name="config_workspaceUnshrinkTime">650</integer>
-
- <!-- Duration in milliseconds toolbar fade in and fade out animations.
- NOTE: Fade in and fade out time should together be less the transition
- animations between all apps, customize, & the workspace. -->
- <integer name="config_toolbarButtonFadeInTime">350</integer>
- <integer name="config_toolbarButtonFadeOutTime">200</integer>
+<!-- Workspace -->
<!-- When dragging items on the workspace, how much bigger (in pixels) the dragged view
should be, as compared to the original view. If 0, it will not be scaled at all.
Should be an even number, for pixel alignment. -->
<integer name="config_dragViewExtraPixels">0</integer>
- <!-- When dragging items on the workspace, the number of pixels by which the position of
- the drag view should be offset from the position of the original view. -->
- <integer name="config_dragViewOffsetX">0</integer>
- <integer name="config_dragViewOffsetY">-12</integer>
-
<!-- When shrinking the workspace, this is the percentage of its original size. -->
<integer name="config_workspaceShrinkPercent">17</integer>
- <!-- When items are dropped on the mini screens in customize mode, we have a bounce animation
- of the bright green hover outline, and then fade out the outline at the end. These are
- the values used in that animation -->
- <integer name="config_screenOnDropScalePercent">120</integer>
- <integer name="config_screenOnDropScaleUpDuration">200</integer>
- <integer name="config_screenOnDropScaleDownDuration">200</integer>
- <integer name="config_screenOnDropAlphaFadeDelay">350</integer>
- <integer name="config_screenOnDropAlphaFadeDuration">50</integer>
-
- <!-- The slope, in percent, of the drag movement needed to drag an item out of the customization
- drawer (y / x * 100%) -->
- <integer name="config_customizationDrawerDragSlopeThreshold">150</integer>
- <integer name="config_allAppsDrawerDragSlopeThreshold">150</integer>
-
- <style name="config_orientation">
- <item name="@android:screenOrientation">unspecified</item>
- </style>
</resources>
diff --git a/res/values-large/dimens.xml b/res/values-large/dimens.xml
index 7bc8ec0fa..924832a55 100644
--- a/res/values-large/dimens.xml
+++ b/res/values-large/dimens.xml
@@ -15,6 +15,18 @@
-->
<resources>
+<!-- Workspace -->
+ <dimen name="qsb_bar_height">56dp</dimen>
+
+ <dimen name="apps_customize_cell_width">96dp</dimen>
+ <dimen name="apps_customize_cell_height">96dp</dimen>
+ <!-- The amount of space to account for the next/prev pages when
+ calculating the number of columns to fit a page.
+ In landscape/large we use apps_customize_cell_width / 4. -->
+ <dimen name="apps_customize_peek_width">48dp</dimen>
+ <dimen name="apps_customize_widget_cell_width_gap">36dp</dimen>
+ <dimen name="apps_customize_widget_cell_height_gap">36dp</dimen>
+
<dimen name="workspace_cell_width">96dip</dimen>
<dimen name="workspace_cell_height">96dip</dimen>
@@ -54,16 +66,12 @@
<dimen name="allAppsSmallScreenVerticalMarginLandscape">30dip</dimen>
<dimen name="allAppsSmallScreenVerticalMarginPortrait">60dip</dimen>
- <dimen name="delete_zone_drawable_padding">8dip</dimen>
<dimen name="all_apps_button_drawable_padding">0dip</dimen>
<dimen name="all_apps_button_vertical_padding">4dip</dimen>
<integer name="land_all_apps_view_cellCountX">7</integer>
<integer name="land_all_apps_view_cellCountY">5</integer>
- <dimen name="toolbar_button_vertical_padding">12dip</dimen>
- <dimen name="toolbar_button_horizontal_padding">16dip</dimen>
-
<!-- height & width of the drop rectangle for the trash icon -->
<dimen name="delete_zone_vertical_drag_padding">20dip</dimen>
<dimen name="delete_zone_horizontal_drag_padding">20dip</dimen>
@@ -83,6 +91,11 @@
for the WallpaperChooser in XLarge mode) -->
<dimen name="alert_dialog_content_inset">0dp</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">-12dp</dimen>
+
<!-- The actual number of rows/columns will be determined dynamically based on the screen
size, but in portrait we want to cap the rows at 3, otherwise it looks weird. -->
<integer name="customization_drawer_contents_maxCellCountY">3</integer>
@@ -92,4 +105,10 @@
<!-- Max number of rows in all apps, because too many looks weird. -->
<integer name="all_apps_view_maxCellCountY">6</integer>
+
+ <!-- Padding applied to AppWidgets -->
+ <dimen name="app_widget_padding_left">12dp</dimen>
+ <dimen name="app_widget_padding_right">12dp</dimen>
+ <dimen name="app_widget_padding_top">4dp</dimen>
+ <dimen name="app_widget_padding_bottom">20dp</dimen>
</resources>
diff --git a/res/values-large/strings.xml b/res/values-large/strings.xml
index 75a22a2c5..97024fa5c 100644
--- a/res/values-large/strings.xml
+++ b/res/values-large/strings.xml
@@ -26,4 +26,14 @@
<!-- Negative button text for the wallpaper selection dialog [CHAR_LIMIT=40]-->
<string name="wallpaper_cancel">Cancel</string>
+
+ <!-- Label for delete drop target. [CHAR_LIMIT=30] -->
+ <string name="delete_target_label">Remove</string>
+ <!-- Label for uninstall drop target. [CHAR_LIMIT=30]-->
+ <string name="delete_target_uninstall_label">Uninstall</string>
+ <!-- Label for the info icon. [CHAR_LIMIT=30] -->
+ <string name="info_target_label">Manage</string>
+
+ <!-- Market button text [CHAR LIMIT=32] -->
+ <string name="market">Shop</string>
</resources> \ No newline at end of file
diff --git a/res/values-large/styles.xml b/res/values-large/styles.xml
index 858a63a27..9c1532aa0 100644
--- a/res/values-large/styles.xml
+++ b/res/values-large/styles.xml
@@ -42,14 +42,53 @@
<item name="android:includeFontPadding">false</item>
</style>
+ <style name="WidgetDivider">
+ <item name="android:visibility">visible</item>
+ </style>
+
<style name="TabIndicator.Wide">
<item name="android:paddingLeft">40dp</item>
<item name="android:paddingRight">40dp</item>
- <item name="android:paddingTop">15dp</item>
+ <item name="android:paddingTop">10dp</item>
<item name="android:paddingBottom">20dp</item>
<item name="android:textSize">20sp</item>
</style>
<style name="CustomizeTabIndicator.Wide" parent="TabIndicator.Wide">
</style>
+
+
+ <!-- QSB Search / Drop Target bar -->
+ <style name="SearchDropTargetBar">
+ <item name="android:orientation">horizontal</item>
+ </style>
+ <style name="SearchButton">
+ <item name="android:layout_gravity">center_vertical</item>
+ <item name="android:paddingTop">@dimen/toolbar_button_vertical_padding</item>
+ <item name="android:paddingBottom">@dimen/toolbar_button_vertical_padding</item>
+ <item name="android:paddingLeft">@dimen/toolbar_button_horizontal_padding</item>
+ <item name="android:paddingRight">@dimen/toolbar_button_horizontal_padding</item>
+ </style>
+ <style name="SearchButtonDivider">
+ <item name="android:layout_width">wrap_content</item>
+ <item name="android:layout_height">match_parent</item>
+ <item name="android:layout_gravity">center_vertical</item>
+ </style>
+ <style name="DropTargetButtonContainer">
+ <item name="android:layout_width">0dp</item>
+ <item name="android:layout_height">match_parent</item>
+ </style>
+ <style name="DropTargetButton">
+ <item name="android:layout_width">wrap_content</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:layout_gravity">center</item>
+ <item name="android:gravity">center_vertical</item>
+ <item name="android:drawablePadding">7.5dp</item>
+ <item name="android:textColor">#FFFFFFFF</item>
+ <item name="android:textSize">16sp</item>
+ </style>
+
+ <style name="config_orientation">
+ <item name="@android:screenOrientation">unspecified</item>
+ </style>
</resources>
diff --git a/res/values-lt-land/strings.xml b/res/values-lt-land/strings.xml
new file mode 100644
index 000000000..b976926f0
--- /dev/null
+++ b/res/values-lt-land/strings.xml
@@ -0,0 +1,25 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="delete_target_label" msgid="4155210680095864979"></string>
+ <string name="delete_target_uninstall_label" msgid="1839407506844917298"></string>
+ <string name="info_target_label" msgid="1424400595004570393"></string>
+</resources>
diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml
index acf0e2786..becd96c2a 100644
--- a/res/values-lt/strings.xml
+++ b/res/values-lt/strings.xml
@@ -37,6 +37,7 @@
<string name="all_apps_tab_apps" msgid="5468972551904071712">"Apps"</string>
<string name="all_apps_tab_games" msgid="1855736784923494918">"Žaidimai"</string>
<string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Mano programos"</string>
+ <string name="long_press_widget_to_add" msgid="4307462194057715796">"Kad pasirinkt. valdiklį, ilgai laikykite nuspaudę"</string>
<string name="all_apps_no_games" msgid="5293893733372793696">"Nerasta žaidimų."</string>
<string name="all_apps_no_downloads" msgid="2284720393234453761">"Neturite atsisiųstų programų."</string>
<string name="market" msgid="2652226429823445833">"Parduotuvė"</string>
@@ -67,6 +68,17 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Pagrindinis"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Pašalinti"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Pašalinti"</string>
+ <!-- no translation found for delete_target_label (665300185123139530) -->
+ <skip />
+ <!-- no translation found for delete_target_uninstall_label (748894921183769150) -->
+ <skip />
+ <!-- no translation found for info_target_label (6175926565900432067) -->
+ <skip />
+ <string name="accessibility_search_button" msgid="816822994629942611">"Ieškoti"</string>
+ <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Balso paieška"</string>
+ <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Programos"</string>
+ <string name="accessibility_customize_button" msgid="585539669413531163">"Tinkinti"</string>
+ <string name="accessibility_delete_button" msgid="3628162007991023603">"Pašalinti"</string>
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Pašalinti naujinį"</string>
<string name="menu_add" msgid="3065046628354640854">"Pridėti"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Valdyti programas"</string>
@@ -91,4 +103,5 @@
<string name="permdesc_write_settings" msgid="1098648778383349818">"Leidžia programai keisti pagrindinio puslapio nustatymus ir sparčiuosius klavišus."</string>
<string name="gadget_error_text" msgid="8359351016167075858">"Problema įkeliant valdiklį"</string>
<string name="uninstall_system_app_text" msgid="7488523163288397451">"Tai sistemos programa ir jos negalima pašalinti."</string>
+ <string name="dream_name" msgid="2847171357608437154">"Raketinis prieštankinis šautuvas"</string>
</resources>
diff --git a/res/values-lv-land/strings.xml b/res/values-lv-land/strings.xml
new file mode 100644
index 000000000..b976926f0
--- /dev/null
+++ b/res/values-lv-land/strings.xml
@@ -0,0 +1,25 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="delete_target_label" msgid="4155210680095864979"></string>
+ <string name="delete_target_uninstall_label" msgid="1839407506844917298"></string>
+ <string name="info_target_label" msgid="1424400595004570393"></string>
+</resources>
diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml
index 9c1b389dd..391ecabda 100644
--- a/res/values-lv/strings.xml
+++ b/res/values-lv/strings.xml
@@ -37,6 +37,7 @@
<string name="all_apps_tab_apps" msgid="5468972551904071712">"Lietotnes"</string>
<string name="all_apps_tab_games" msgid="1855736784923494918">"Spēles"</string>
<string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Manas lietotnes"</string>
+ <string name="long_press_widget_to_add" msgid="4307462194057715796">"Lai izvēlētos logrīku, turiet to nospiestu."</string>
<string name="all_apps_no_games" msgid="5293893733372793696">"Nav nevienas spēles."</string>
<string name="all_apps_no_downloads" msgid="2284720393234453761">"Nav ielādēta neviena lietojumprogramma."</string>
<string name="market" msgid="2652226429823445833">"Iepirkties"</string>
@@ -67,6 +68,17 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Sākums"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Noņemt"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Atinstalēt"</string>
+ <!-- no translation found for delete_target_label (665300185123139530) -->
+ <skip />
+ <!-- no translation found for delete_target_uninstall_label (748894921183769150) -->
+ <skip />
+ <!-- no translation found for info_target_label (6175926565900432067) -->
+ <skip />
+ <string name="accessibility_search_button" msgid="816822994629942611">"Meklēt"</string>
+ <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Balss meklēšana"</string>
+ <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Lietojumprogrammas"</string>
+ <string name="accessibility_customize_button" msgid="585539669413531163">"Pielāgot"</string>
+ <string name="accessibility_delete_button" msgid="3628162007991023603">"Noņemt"</string>
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Atinstalēt atjauninājumu"</string>
<string name="menu_add" msgid="3065046628354640854">"Pievienot"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Lietotņu pārvaldība"</string>
@@ -91,4 +103,5 @@
<string name="permdesc_write_settings" msgid="1098648778383349818">"Ļauj lietojumprogrammai mainīt iestatījumus un saīsnes sākuma ekrānā."</string>
<string name="gadget_error_text" msgid="8359351016167075858">"Radās problēma, ielādējot logrīku"</string>
<string name="uninstall_system_app_text" msgid="7488523163288397451">"Šī ir sistēmas lietojumprogramma un to nevar atinstalēt."</string>
+ <string name="dream_name" msgid="2847171357608437154">"Rocket Launcher"</string>
</resources>
diff --git a/res/values-ms-land/strings.xml b/res/values-ms-land/strings.xml
new file mode 100644
index 000000000..b976926f0
--- /dev/null
+++ b/res/values-ms-land/strings.xml
@@ -0,0 +1,25 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="delete_target_label" msgid="4155210680095864979"></string>
+ <string name="delete_target_uninstall_label" msgid="1839407506844917298"></string>
+ <string name="info_target_label" msgid="1424400595004570393"></string>
+</resources>
diff --git a/res/values-ms/strings.xml b/res/values-ms/strings.xml
new file mode 100644
index 000000000..247bb25e4
--- /dev/null
+++ b/res/values-ms/strings.xml
@@ -0,0 +1,147 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2008 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- outdated translation 5865630159700533006 --> <string name="application_name" msgid="8424725141379931883">"Laman Utama"</string>
+ <string name="uid_name" msgid="3371120195364560632">"Apl Teras Android"</string>
+ <string name="folder_name" msgid="4588446541914685904">"Folder"</string>
+ <string name="chooser_wallpaper" msgid="5988031014201479733">"Pilih kertas dinding daripada"</string>
+ <string name="wallpaper_instructions" msgid="4215640646180727542">"Tetapkan kertas dinding"</string>
+ <!-- outdated translation 2674908923379130941 --> <string name="pick_wallpaper" msgid="5630222540525626723">"Galeri Kertas Dinding"</string>
+ <!-- outdated translation 3571057450431950427 --> <string name="activity_not_found" msgid="5591731020063337696">"Aplikasi tidak dipasang pada telefon anda."</string>
+ <!-- no translation found for configure_wallpaper (2820186271419674623) -->
+ <skip />
+ <!-- no translation found for widgets_tab_label (9145860100000983599) -->
+ <skip />
+ <!-- no translation found for folders_tab_label (1145293785541489736) -->
+ <skip />
+ <!-- no translation found for shortcuts_tab_label (8640731503933155644) -->
+ <skip />
+ <!-- no translation found for wallpapers_tab_label (1617804870364119879) -->
+ <skip />
+ <!-- no translation found for applications_tab_label (2991364240020736760) -->
+ <skip />
+ <!-- no translation found for wallpapers_temp_tab_text (1660218201190495279) -->
+ <skip />
+ <!-- no translation found for all_apps_tab_all (2942727589595027258) -->
+ <skip />
+ <!-- no translation found for all_apps_tab_apps (5468972551904071712) -->
+ <skip />
+ <!-- no translation found for all_apps_tab_games (1855736784923494918) -->
+ <skip />
+ <!-- no translation found for all_apps_tab_downloaded (1488049110598641387) -->
+ <skip />
+ <!-- no translation found for long_press_widget_to_add (4307462194057715796) -->
+ <skip />
+ <!-- no translation found for all_apps_no_games (5293893733372793696) -->
+ <skip />
+ <!-- no translation found for all_apps_no_downloads (2284720393234453761) -->
+ <skip />
+ <!-- no translation found for market (2652226429823445833) -->
+ <skip />
+ <!-- no translation found for external_drop_widget_error (4976816434597126575) -->
+ <skip />
+ <!-- no translation found for external_drop_widget_pick_title (4481311720134376218) -->
+ <skip />
+ <string name="rename_folder_label" msgid="5646236631298452787">"Nama folder"</string>
+ <string name="rename_folder_title" msgid="4544573104191526550">"Namakan semula folder"</string>
+ <string name="rename_action" msgid="6016003384693240896">"OK"</string>
+ <string name="cancel_action" msgid="3811860427489435048">"Batal"</string>
+ <string name="menu_item_add_item" msgid="6233177331075781114">"Tambah ke Skrin utama"</string>
+ <string name="group_applications" msgid="4118484163419674240">"Aplikasi"</string>
+ <string name="group_shortcuts" msgid="9133529424900391877">"Pintasan"</string>
+ <string name="group_folder" msgid="5143593791798929193">"Folder baru"</string>
+ <string name="group_live_folders" msgid="2664945399140647217">"Folder"</string>
+ <string name="group_widgets" msgid="6704978494073105844">"Widget"</string>
+ <string name="group_wallpapers" msgid="1568191644272224858">"Kertas dinding"</string>
+ <string name="add_folder" msgid="3521088587367839879">"Folder"</string>
+ <string name="add_clock" msgid="2337943840175865746">"Jam"</string>
+ <string name="add_photo_frame" msgid="3154058437359487954">"Bingkai gambar"</string>
+ <string name="out_of_space" msgid="8365249326091984698">"Tiada lagi ruang pada skrin Utama ini"</string>
+ <!-- no translation found for shortcut_installed (7071557296331322355) -->
+ <skip />
+ <!-- no translation found for shortcut_uninstalled (2129499669449749995) -->
+ <skip />
+ <!-- no translation found for shortcut_duplicate (4757756326465060694) -->
+ <skip />
+ <string name="title_select_shortcut" msgid="2858897527672831763">"Pilih pintasan"</string>
+ <!-- no translation found for title_select_application (8031072293115454221) -->
+ <skip />
+ <string name="title_select_live_folder" msgid="3753447798805166749">"Pilih folder"</string>
+ <!-- no translation found for all_apps_button_label (2578400570124163469) -->
+ <skip />
+ <!-- no translation found for all_apps_home_button_label (1022222300329398558) -->
+ <skip />
+ <!-- no translation found for delete_zone_label_workspace (7153615831493049150) -->
+ <skip />
+ <!-- no translation found for delete_zone_label_all_apps (6664588234817475108) -->
+ <skip />
+ <!-- no translation found for delete_target_label (665300185123139530) -->
+ <skip />
+ <!-- no translation found for delete_target_uninstall_label (748894921183769150) -->
+ <skip />
+ <!-- no translation found for info_target_label (6175926565900432067) -->
+ <skip />
+ <!-- no translation found for accessibility_search_button (816822994629942611) -->
+ <skip />
+ <!-- no translation found for accessibility_voice_search_button (3938249215065842475) -->
+ <skip />
+ <!-- no translation found for accessibility_all_apps_button (1595097919145716305) -->
+ <skip />
+ <!-- no translation found for accessibility_customize_button (585539669413531163) -->
+ <skip />
+ <!-- no translation found for accessibility_delete_button (3628162007991023603) -->
+ <skip />
+ <!-- no translation found for delete_zone_label_all_apps_system_app (3683920959591819044) -->
+ <skip />
+ <string name="menu_add" msgid="3065046628354640854">"Tambah"</string>
+ <!-- no translation found for menu_manage_apps (2308685199463588895) -->
+ <skip />
+ <string name="menu_wallpaper" msgid="5837429080911269832">"Kertas dinding"</string>
+ <string name="menu_search" msgid="4826514464423239041">"Cari"</string>
+ <string name="menu_notifications" msgid="6424587053194766192">"Pemberitahuan"</string>
+ <string name="menu_gestures" msgid="514678675575912237">"Gerak isyarat"</string>
+ <string name="menu_settings" msgid="6233960148378443661">"Tetapan"</string>
+ <!-- no translation found for cab_menu_delete_app (1242619904941293871) -->
+ <skip />
+ <!-- no translation found for cab_menu_app_info (5180426909324882018) -->
+ <skip />
+ <!-- no translation found for cab_app_selection_text (606113924828167756) -->
+ <skip />
+ <!-- no translation found for cab_widget_selection_text (962527270506951955) -->
+ <skip />
+ <!-- no translation found for cab_folder_selection_text (8916111874189565067) -->
+ <skip />
+ <!-- no translation found for cab_shortcut_selection_text (8115847384500412878) -->
+ <skip />
+ <string name="permlab_install_shortcut" msgid="1201690825493376489">"pasang pintasan"</string>
+ <string name="permdesc_install_shortcut" msgid="7429365847558984148">"Membenarkan aplikasi menambah pintasan tanpa campur tangan pengguna."</string>
+ <string name="permlab_uninstall_shortcut" msgid="7696645932555926449">"nyahpasang pintasan"</string>
+ <string name="permdesc_uninstall_shortcut" msgid="959972195916090900">"Membenarkan aplikasi mengalih keluar pintasan tanpa campur tangan pengguna."</string>
+ <string name="permlab_read_settings" msgid="3452408290738106747">"membaca tetapan dan pintasan Laman Utama"</string>
+ <string name="permdesc_read_settings" msgid="8377434937176025492">"Membenarkan aplikasi untuk membaca tetapan dan pintasan di Laman Utama."</string>
+ <string name="permlab_write_settings" msgid="1360567537236705628">"menulis tetapan dan pintasan Laman Utama"</string>
+ <string name="permdesc_write_settings" msgid="1098648778383349818">"Membenarkan aplikasi untuk menukar tetapan dan pintasan di Laman Utama."</string>
+ <string name="gadget_error_text" msgid="8359351016167075858">"Masalah memuatkan widget"</string>
+ <!-- no translation found for uninstall_system_app_text (7488523163288397451) -->
+ <skip />
+ <!-- no translation found for dream_name (2847171357608437154) -->
+ <skip />
+</resources>
diff --git a/res/values-nb-land/strings.xml b/res/values-nb-land/strings.xml
new file mode 100644
index 000000000..b976926f0
--- /dev/null
+++ b/res/values-nb-land/strings.xml
@@ -0,0 +1,25 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="delete_target_label" msgid="4155210680095864979"></string>
+ <string name="delete_target_uninstall_label" msgid="1839407506844917298"></string>
+ <string name="info_target_label" msgid="1424400595004570393"></string>
+</resources>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
index ccdab7e82..e81f8c8a1 100644
--- a/res/values-nb/strings.xml
+++ b/res/values-nb/strings.xml
@@ -37,6 +37,7 @@
<string name="all_apps_tab_apps" msgid="5468972551904071712">"Programmer"</string>
<string name="all_apps_tab_games" msgid="1855736784923494918">"Spill"</string>
<string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Mine programmer"</string>
+ <string name="long_press_widget_to_add" msgid="4307462194057715796">"Trykk og hold inne for å plukke opp en modul"</string>
<string name="all_apps_no_games" msgid="5293893733372793696">"Finner ingen spill."</string>
<string name="all_apps_no_downloads" msgid="2284720393234453761">"Du har ingen nedlastede programmer."</string>
<string name="market" msgid="2652226429823445833">"Butikk"</string>
@@ -67,6 +68,17 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Startsiden"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Fjern"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Avinstaller"</string>
+ <!-- no translation found for delete_target_label (665300185123139530) -->
+ <skip />
+ <!-- no translation found for delete_target_uninstall_label (748894921183769150) -->
+ <skip />
+ <!-- no translation found for info_target_label (6175926565900432067) -->
+ <skip />
+ <string name="accessibility_search_button" msgid="816822994629942611">"Søk"</string>
+ <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Talesøk"</string>
+ <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Applikasjoner"</string>
+ <string name="accessibility_customize_button" msgid="585539669413531163">"Tilpass"</string>
+ <string name="accessibility_delete_button" msgid="3628162007991023603">"Fjern"</string>
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Avinstaller oppdateringen"</string>
<string name="menu_add" msgid="3065046628354640854">"Legg til"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Administrer programmer"</string>
@@ -91,4 +103,5 @@
<string name="permdesc_write_settings" msgid="1098648778383349818">"Lar applikasjonen endre innstillinger og snarveier på skrivebordet."</string>
<string name="gadget_error_text" msgid="8359351016167075858">"Problem under lasting av gadget"</string>
<string name="uninstall_system_app_text" msgid="7488523163288397451">"Dette er et systemprogram og kan ikke avinstalleres."</string>
+ <string name="dream_name" msgid="2847171357608437154">"Rocket Launcher"</string>
</resources>
diff --git a/res/values-nl-land/strings.xml b/res/values-nl-land/strings.xml
new file mode 100644
index 000000000..b976926f0
--- /dev/null
+++ b/res/values-nl-land/strings.xml
@@ -0,0 +1,25 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="delete_target_label" msgid="4155210680095864979"></string>
+ <string name="delete_target_uninstall_label" msgid="1839407506844917298"></string>
+ <string name="info_target_label" msgid="1424400595004570393"></string>
+</resources>
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index 3d7c7ac10..af2844fd7 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -37,6 +37,7 @@
<string name="all_apps_tab_apps" msgid="5468972551904071712">"Apps"</string>
<string name="all_apps_tab_games" msgid="1855736784923494918">"Games"</string>
<string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Mijn apps"</string>
+ <string name="long_press_widget_to_add" msgid="4307462194057715796">"Druk lang om een widget op te halen"</string>
<string name="all_apps_no_games" msgid="5293893733372793696">"Geen games gevonden."</string>
<string name="all_apps_no_downloads" msgid="2284720393234453761">"U heeft geen gedownloade apps."</string>
<string name="market" msgid="2652226429823445833">"Winkel"</string>
@@ -67,6 +68,17 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Startpagina"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Verwijderen"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Verwijderen"</string>
+ <!-- no translation found for delete_target_label (665300185123139530) -->
+ <skip />
+ <!-- no translation found for delete_target_uninstall_label (748894921183769150) -->
+ <skip />
+ <!-- no translation found for info_target_label (6175926565900432067) -->
+ <skip />
+ <string name="accessibility_search_button" msgid="816822994629942611">"Zoeken"</string>
+ <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Spraakgestuurd zoeken"</string>
+ <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Apps"</string>
+ <string name="accessibility_customize_button" msgid="585539669413531163">"Aanpassen"</string>
+ <string name="accessibility_delete_button" msgid="3628162007991023603">"Verwijderen"</string>
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Update verwijderen"</string>
<string name="menu_add" msgid="3065046628354640854">"Toevoegen"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Apps beheren"</string>
@@ -91,4 +103,5 @@
<string name="permdesc_write_settings" msgid="1098648778383349818">"Hiermee kan een app de instellingen en snelkoppelingen op de startpagina wijzigen."</string>
<string name="gadget_error_text" msgid="8359351016167075858">"Probleem bij het laden van widget"</string>
<string name="uninstall_system_app_text" msgid="7488523163288397451">"Dit is een systeemtoepassing die niet kan worden verwijderd."</string>
+ <string name="dream_name" msgid="2847171357608437154">"Rocket Launcher"</string>
</resources>
diff --git a/res/values-pl-land/strings.xml b/res/values-pl-land/strings.xml
new file mode 100644
index 000000000..b976926f0
--- /dev/null
+++ b/res/values-pl-land/strings.xml
@@ -0,0 +1,25 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="delete_target_label" msgid="4155210680095864979"></string>
+ <string name="delete_target_uninstall_label" msgid="1839407506844917298"></string>
+ <string name="info_target_label" msgid="1424400595004570393"></string>
+</resources>
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
index f1161652a..e0dc88036 100644
--- a/res/values-pl/strings.xml
+++ b/res/values-pl/strings.xml
@@ -37,6 +37,7 @@
<string name="all_apps_tab_apps" msgid="5468972551904071712">"Aplikacje"</string>
<string name="all_apps_tab_games" msgid="1855736784923494918">"Gry"</string>
<string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Moje aplikacje"</string>
+ <string name="long_press_widget_to_add" msgid="4307462194057715796">"Naciśnij i przytrzymaj widżet, aby go dodać"</string>
<string name="all_apps_no_games" msgid="5293893733372793696">"Nie znaleziono gier."</string>
<string name="all_apps_no_downloads" msgid="2284720393234453761">"Nie masz żadnych pobranych aplikacji."</string>
<string name="market" msgid="2652226429823445833">"Sklep"</string>
@@ -67,6 +68,17 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Ekran główny"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Usuń"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Odinstaluj"</string>
+ <!-- no translation found for delete_target_label (665300185123139530) -->
+ <skip />
+ <!-- no translation found for delete_target_uninstall_label (748894921183769150) -->
+ <skip />
+ <!-- no translation found for info_target_label (6175926565900432067) -->
+ <skip />
+ <string name="accessibility_search_button" msgid="816822994629942611">"Szukaj"</string>
+ <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Wyszukiwanie głosowe"</string>
+ <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Aplikacje"</string>
+ <string name="accessibility_customize_button" msgid="585539669413531163">"Dostosuj"</string>
+ <string name="accessibility_delete_button" msgid="3628162007991023603">"Usuń"</string>
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Odinstaluj aktualizację"</string>
<string name="menu_add" msgid="3065046628354640854">"Dodaj"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Zarządzaj aplikacjami"</string>
@@ -91,4 +103,5 @@
<string name="permdesc_write_settings" msgid="1098648778383349818">"Umożliwia aplikacji zmianę ustawień i skrótów strony głównej."</string>
<string name="gadget_error_text" msgid="8359351016167075858">"Problem podczas ładowania widżetu"</string>
<string name="uninstall_system_app_text" msgid="7488523163288397451">"To jest aplikacja systemowa i nie można jej odinstalować."</string>
+ <string name="dream_name" msgid="2847171357608437154">"Wyrzutnia rakiet"</string>
</resources>
diff --git a/res/values-port/dimens.xml b/res/values-port/dimens.xml
index 65a3fd3e4..7d50c1a0c 100644
--- a/res/values-port/dimens.xml
+++ b/res/values-port/dimens.xml
@@ -17,4 +17,22 @@
<resources>
<dimen name="workspace_cell_width">80dip</dimen>
<dimen name="workspace_cell_height">100dip</dimen>
+ <dimen name="folder_cell_width">74dip</dimen>
+ <dimen name="folder_cell_height">86dip</dimen>
+
+ <integer name="all_apps_view_cellCountX">4</integer>
+ <integer name="all_apps_view_cellCountY">5</integer>
+ <dimen name="all_apps_view_pageLayoutWidthGap">3dp</dimen>
+ <dimen name="all_apps_view_pageLayoutHeightGap">12dp</dimen>
+ <dimen name="all_apps_view_pageLayoutPaddingTop">15dp</dimen>
+ <dimen name="all_apps_view_pageLayoutPaddingBottom">15dp</dimen>
+ <dimen name="all_apps_view_pageLayoutPaddingLeft">0dp</dimen>
+ <dimen name="all_apps_view_pageLayoutPaddingRight">0dp</dimen>
+
+ <dimen name="apps_customize_widget_cell_width_gap">20dp</dimen>
+ <dimen name="apps_customize_widget_cell_height_gap">40dp</dimen>
+ <integer name="apps_customize_widget_cell_count_x">2</integer>
+ <integer name="apps_customize_widget_cell_count_y">2</integer>
+ <integer name="apps_customize_wallpaper_cell_count_x">1</integer>
+ <integer name="apps_customize_wallpaper_cell_count_y">1</integer>
</resources>
diff --git a/res/values-pt-land/strings.xml b/res/values-pt-land/strings.xml
new file mode 100644
index 000000000..b976926f0
--- /dev/null
+++ b/res/values-pt-land/strings.xml
@@ -0,0 +1,25 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="delete_target_label" msgid="4155210680095864979"></string>
+ <string name="delete_target_uninstall_label" msgid="1839407506844917298"></string>
+ <string name="info_target_label" msgid="1424400595004570393"></string>
+</resources>
diff --git a/res/values-pt-rPT-land/strings.xml b/res/values-pt-rPT-land/strings.xml
new file mode 100644
index 000000000..b976926f0
--- /dev/null
+++ b/res/values-pt-rPT-land/strings.xml
@@ -0,0 +1,25 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="delete_target_label" msgid="4155210680095864979"></string>
+ <string name="delete_target_uninstall_label" msgid="1839407506844917298"></string>
+ <string name="info_target_label" msgid="1424400595004570393"></string>
+</resources>
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
index a3a5a8dd7..65d84a23f 100644
--- a/res/values-pt-rPT/strings.xml
+++ b/res/values-pt-rPT/strings.xml
@@ -37,6 +37,7 @@
<string name="all_apps_tab_apps" msgid="5468972551904071712">"Aplicações"</string>
<string name="all_apps_tab_games" msgid="1855736784923494918">"Jogos"</string>
<string name="all_apps_tab_downloaded" msgid="1488049110598641387">"As minhas aplicações"</string>
+ <string name="long_press_widget_to_add" msgid="4307462194057715796">"Prima por mais tempo para escolher um widget"</string>
<string name="all_apps_no_games" msgid="5293893733372793696">"Sem jogos."</string>
<string name="all_apps_no_downloads" msgid="2284720393234453761">"Não existem aplicações transferidas."</string>
<string name="market" msgid="2652226429823445833">"Loja"</string>
@@ -67,6 +68,17 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Página inicial"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Remover"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Desinstalar"</string>
+ <!-- no translation found for delete_target_label (665300185123139530) -->
+ <skip />
+ <!-- no translation found for delete_target_uninstall_label (748894921183769150) -->
+ <skip />
+ <!-- no translation found for info_target_label (6175926565900432067) -->
+ <skip />
+ <string name="accessibility_search_button" msgid="816822994629942611">"Pesquisar"</string>
+ <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Pesquisa por Voz"</string>
+ <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Aplicações"</string>
+ <string name="accessibility_customize_button" msgid="585539669413531163">"Personalizar"</string>
+ <string name="accessibility_delete_button" msgid="3628162007991023603">"Remover"</string>
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Desinstalar atualização"</string>
<string name="menu_add" msgid="3065046628354640854">"Adicionar"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Gerir aplicações"</string>
@@ -91,4 +103,5 @@
<string name="permdesc_write_settings" msgid="1098648778383349818">"Permite que uma aplicação altere as definições e os atalhos do ecrã principal."</string>
<string name="gadget_error_text" msgid="8359351016167075858">"Erro ao carregar o widget"</string>
<string name="uninstall_system_app_text" msgid="7488523163288397451">"É uma aplicação de sistema e não pode ser desinstalada."</string>
+ <string name="dream_name" msgid="2847171357608437154">"Lança-mísseis"</string>
</resources>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index 55deb9439..9aedab078 100644
--- a/res/values-pt/strings.xml
+++ b/res/values-pt/strings.xml
@@ -37,6 +37,7 @@
<string name="all_apps_tab_apps" msgid="5468972551904071712">"Aplicativos"</string>
<string name="all_apps_tab_games" msgid="1855736784923494918">"Jogos"</string>
<string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Meus aplicativos"</string>
+ <string name="long_press_widget_to_add" msgid="4307462194057715796">"Mantenha pressionado para adicionar um widget"</string>
<string name="all_apps_no_games" msgid="5293893733372793696">"Nenhum jogo encontrado."</string>
<string name="all_apps_no_downloads" msgid="2284720393234453761">"Você não tem nenhum aplicativo transferido."</string>
<string name="market" msgid="2652226429823445833">"Comprar"</string>
@@ -67,6 +68,17 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Página inicial"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Remover"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Desinstalar"</string>
+ <!-- no translation found for delete_target_label (665300185123139530) -->
+ <skip />
+ <!-- no translation found for delete_target_uninstall_label (748894921183769150) -->
+ <skip />
+ <!-- no translation found for info_target_label (6175926565900432067) -->
+ <skip />
+ <string name="accessibility_search_button" msgid="816822994629942611">"Pesquisar"</string>
+ <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Pesquisa por voz"</string>
+ <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Aplicativos"</string>
+ <string name="accessibility_customize_button" msgid="585539669413531163">"Personalizar"</string>
+ <string name="accessibility_delete_button" msgid="3628162007991023603">"Remover"</string>
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Desinstalar atualização"</string>
<string name="menu_add" msgid="3065046628354640854">"Adicionar"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Gerenciar aplicativos"</string>
@@ -91,4 +103,5 @@
<string name="permdesc_write_settings" msgid="1098648778383349818">"Permite que um aplicativo altere as configurações e atalhos na Página inicial."</string>
<string name="gadget_error_text" msgid="8359351016167075858">"Problema ao carregar o widget"</string>
<string name="uninstall_system_app_text" msgid="7488523163288397451">"Este é um aplicativo do sistema e não pode ser desinstalado."</string>
+ <string name="dream_name" msgid="2847171357608437154">"Rocket Launcher"</string>
</resources>
diff --git a/res/values-rm-land/strings.xml b/res/values-rm-land/strings.xml
new file mode 100644
index 000000000..b976926f0
--- /dev/null
+++ b/res/values-rm-land/strings.xml
@@ -0,0 +1,25 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="delete_target_label" msgid="4155210680095864979"></string>
+ <string name="delete_target_uninstall_label" msgid="1839407506844917298"></string>
+ <string name="info_target_label" msgid="1424400595004570393"></string>
+</resources>
diff --git a/res/values-rm/strings.xml b/res/values-rm/strings.xml
index 1b5729b7e..86c5ad348 100644
--- a/res/values-rm/strings.xml
+++ b/res/values-rm/strings.xml
@@ -47,6 +47,8 @@
<skip />
<!-- no translation found for all_apps_tab_downloaded (1488049110598641387) -->
<skip />
+ <!-- no translation found for long_press_widget_to_add (4307462194057715796) -->
+ <skip />
<!-- no translation found for all_apps_no_games (5293893733372793696) -->
<skip />
<!-- no translation found for all_apps_no_downloads (2284720393234453761) -->
@@ -85,6 +87,22 @@
<skip />
<!-- no translation found for delete_zone_label_all_apps (6664588234817475108) -->
<skip />
+ <!-- no translation found for delete_target_label (665300185123139530) -->
+ <skip />
+ <!-- no translation found for delete_target_uninstall_label (748894921183769150) -->
+ <skip />
+ <!-- no translation found for info_target_label (6175926565900432067) -->
+ <skip />
+ <!-- no translation found for accessibility_search_button (816822994629942611) -->
+ <skip />
+ <!-- no translation found for accessibility_voice_search_button (3938249215065842475) -->
+ <skip />
+ <!-- no translation found for accessibility_all_apps_button (1595097919145716305) -->
+ <skip />
+ <!-- no translation found for accessibility_customize_button (585539669413531163) -->
+ <skip />
+ <!-- no translation found for accessibility_delete_button (3628162007991023603) -->
+ <skip />
<!-- no translation found for delete_zone_label_all_apps_system_app (3683920959591819044) -->
<skip />
<string name="menu_add" msgid="3065046628354640854">"Agiuntar"</string>
@@ -118,4 +136,6 @@
<string name="gadget_error_text" msgid="8359351016167075858">"Problems cun chargiar il widget"</string>
<!-- no translation found for uninstall_system_app_text (7488523163288397451) -->
<skip />
+ <!-- no translation found for dream_name (2847171357608437154) -->
+ <skip />
</resources>
diff --git a/res/values-ro-land/strings.xml b/res/values-ro-land/strings.xml
new file mode 100644
index 000000000..b976926f0
--- /dev/null
+++ b/res/values-ro-land/strings.xml
@@ -0,0 +1,25 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="delete_target_label" msgid="4155210680095864979"></string>
+ <string name="delete_target_uninstall_label" msgid="1839407506844917298"></string>
+ <string name="info_target_label" msgid="1424400595004570393"></string>
+</resources>
diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml
index 3a72c51b1..59be591e0 100644
--- a/res/values-ro/strings.xml
+++ b/res/values-ro/strings.xml
@@ -37,6 +37,7 @@
<string name="all_apps_tab_apps" msgid="5468972551904071712">"Aplicaţii"</string>
<string name="all_apps_tab_games" msgid="1855736784923494918">"Jocuri"</string>
<string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Aplicaţiile mele"</string>
+ <string name="long_press_widget_to_add" msgid="4307462194057715796">"Apăsaţi lung pentru a alege un widget"</string>
<string name="all_apps_no_games" msgid="5293893733372793696">"Nu s-au găsit jocuri."</string>
<string name="all_apps_no_downloads" msgid="2284720393234453761">"Nu aveţi aplicaţii descărcate."</string>
<string name="market" msgid="2652226429823445833">"Cumpăraţi"</string>
@@ -67,6 +68,17 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Domiciliu"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Eliminaţi"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Dezinstalaţi"</string>
+ <!-- no translation found for delete_target_label (665300185123139530) -->
+ <skip />
+ <!-- no translation found for delete_target_uninstall_label (748894921183769150) -->
+ <skip />
+ <!-- no translation found for info_target_label (6175926565900432067) -->
+ <skip />
+ <string name="accessibility_search_button" msgid="816822994629942611">"Căutaţi"</string>
+ <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Căutare vocală"</string>
+ <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Aplicaţii"</string>
+ <string name="accessibility_customize_button" msgid="585539669413531163">"Personalizaţi"</string>
+ <string name="accessibility_delete_button" msgid="3628162007991023603">"Eliminaţi"</string>
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Dezinstalaţi actualizarea"</string>
<string name="menu_add" msgid="3065046628354640854">"Adăugaţi"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Gestionaţi aplicaţii"</string>
@@ -91,4 +103,5 @@
<string name="permdesc_write_settings" msgid="1098648778383349818">"Permite unei aplicaţii să modifice setările şi comenzile rapide pentru Ecranul de pornire."</string>
<string name="gadget_error_text" msgid="8359351016167075858">"Probleme la încărcarea obiectului widget"</string>
<string name="uninstall_system_app_text" msgid="7488523163288397451">"Aceasta este o aplicaţie a sistemului şi nu se poate dezinstala."</string>
+ <string name="dream_name" msgid="2847171357608437154">"Rocket Launcher"</string>
</resources>
diff --git a/res/values-ru-land/strings.xml b/res/values-ru-land/strings.xml
new file mode 100644
index 000000000..b976926f0
--- /dev/null
+++ b/res/values-ru-land/strings.xml
@@ -0,0 +1,25 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="delete_target_label" msgid="4155210680095864979"></string>
+ <string name="delete_target_uninstall_label" msgid="1839407506844917298"></string>
+ <string name="info_target_label" msgid="1424400595004570393"></string>
+</resources>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index 912c3f42f..6df1a8175 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -37,6 +37,7 @@
<string name="all_apps_tab_apps" msgid="5468972551904071712">"Приложения"</string>
<string name="all_apps_tab_games" msgid="1855736784923494918">"Игры"</string>
<string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Мои приложения"</string>
+ <string name="long_press_widget_to_add" msgid="4307462194057715796">"Нажмите и удерживайте, чтобы выбрать виджет"</string>
<string name="all_apps_no_games" msgid="5293893733372793696">"Игр не найдено."</string>
<string name="all_apps_no_downloads" msgid="2284720393234453761">"У вас нет загруженных приложений."</string>
<string name="market" msgid="2652226429823445833">"Маркет"</string>
@@ -67,6 +68,17 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Главная"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Удалить"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Удалить"</string>
+ <!-- no translation found for delete_target_label (665300185123139530) -->
+ <skip />
+ <!-- no translation found for delete_target_uninstall_label (748894921183769150) -->
+ <skip />
+ <!-- no translation found for info_target_label (6175926565900432067) -->
+ <skip />
+ <string name="accessibility_search_button" msgid="816822994629942611">"Поиск"</string>
+ <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Голосовой поиск"</string>
+ <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Приложения"</string>
+ <string name="accessibility_customize_button" msgid="585539669413531163">"Настроить"</string>
+ <string name="accessibility_delete_button" msgid="3628162007991023603">"Удалить"</string>
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Удалить обновление"</string>
<string name="menu_add" msgid="3065046628354640854">"Добавить"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Приложения"</string>
@@ -91,4 +103,5 @@
<string name="permdesc_write_settings" msgid="1098648778383349818">"Позволяет приложению изменять настройки и ярлыки на главном экране."</string>
<string name="gadget_error_text" msgid="8359351016167075858">"Не удалось загрузить виджет"</string>
<string name="uninstall_system_app_text" msgid="7488523163288397451">"Это системное приложение. Удалить его невозможно."</string>
+ <string name="dream_name" msgid="2847171357608437154">"Фейерверк"</string>
</resources>
diff --git a/res/values-sk-land/strings.xml b/res/values-sk-land/strings.xml
new file mode 100644
index 000000000..b976926f0
--- /dev/null
+++ b/res/values-sk-land/strings.xml
@@ -0,0 +1,25 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="delete_target_label" msgid="4155210680095864979"></string>
+ <string name="delete_target_uninstall_label" msgid="1839407506844917298"></string>
+ <string name="info_target_label" msgid="1424400595004570393"></string>
+</resources>
diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml
index 3cadf3b56..d533fb5c9 100644
--- a/res/values-sk/strings.xml
+++ b/res/values-sk/strings.xml
@@ -37,6 +37,7 @@
<string name="all_apps_tab_apps" msgid="5468972551904071712">"Aplikácie"</string>
<string name="all_apps_tab_games" msgid="1855736784923494918">"Hry"</string>
<string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Moje aplikácie"</string>
+ <string name="long_press_widget_to_add" msgid="4307462194057715796">"Miniaplikáciu pridáte dlhým stlačením"</string>
<string name="all_apps_no_games" msgid="5293893733372793696">"Nenašli sa žiadne hry."</string>
<string name="all_apps_no_downloads" msgid="2284720393234453761">"Nemáte žiadne prevzaté aplikácie."</string>
<string name="market" msgid="2652226429823445833">"Obchod"</string>
@@ -67,6 +68,17 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Domovská stránka"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Odstrániť"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Odinštalovať"</string>
+ <!-- no translation found for delete_target_label (665300185123139530) -->
+ <skip />
+ <!-- no translation found for delete_target_uninstall_label (748894921183769150) -->
+ <skip />
+ <!-- no translation found for info_target_label (6175926565900432067) -->
+ <skip />
+ <string name="accessibility_search_button" msgid="816822994629942611">"Hľadať"</string>
+ <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Hlasové vyhľadávanie"</string>
+ <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Aplikácie"</string>
+ <string name="accessibility_customize_button" msgid="585539669413531163">"Prispôsobiť"</string>
+ <string name="accessibility_delete_button" msgid="3628162007991023603">"Odstrániť"</string>
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Odinštalovať aktualizáciu"</string>
<string name="menu_add" msgid="3065046628354640854">"Pridať"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Spravovať aplikácie"</string>
@@ -91,4 +103,5 @@
<string name="permdesc_write_settings" msgid="1098648778383349818">"Povoľuje aplikácii zmeniť nastavenia a odkazy plochy."</string>
<string name="gadget_error_text" msgid="8359351016167075858">"Problém s načítaním miniaplikácií"</string>
<string name="uninstall_system_app_text" msgid="7488523163288397451">"Toto je systémová aplikácia a nie je možné ju odinštalovať."</string>
+ <string name="dream_name" msgid="2847171357608437154">"Raketomet"</string>
</resources>
diff --git a/res/values-sl-land/strings.xml b/res/values-sl-land/strings.xml
new file mode 100644
index 000000000..b976926f0
--- /dev/null
+++ b/res/values-sl-land/strings.xml
@@ -0,0 +1,25 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="delete_target_label" msgid="4155210680095864979"></string>
+ <string name="delete_target_uninstall_label" msgid="1839407506844917298"></string>
+ <string name="info_target_label" msgid="1424400595004570393"></string>
+</resources>
diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml
index daf089931..4d844357a 100644
--- a/res/values-sl/strings.xml
+++ b/res/values-sl/strings.xml
@@ -37,6 +37,7 @@
<string name="all_apps_tab_apps" msgid="5468972551904071712">"Programi"</string>
<string name="all_apps_tab_games" msgid="1855736784923494918">"Igre"</string>
<string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Moji programi"</string>
+ <string name="long_press_widget_to_add" msgid="4307462194057715796">"Pritisnite za daljši čas, da poberete pripomoček"</string>
<string name="all_apps_no_games" msgid="5293893733372793696">"Ni najdenih iger."</string>
<string name="all_apps_no_downloads" msgid="2284720393234453761">"Ni prenesenih programov."</string>
<string name="market" msgid="2652226429823445833">"Nakup"</string>
@@ -67,6 +68,17 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Začetni zaslon"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Odstrani"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Odstrani"</string>
+ <!-- no translation found for delete_target_label (665300185123139530) -->
+ <skip />
+ <!-- no translation found for delete_target_uninstall_label (748894921183769150) -->
+ <skip />
+ <!-- no translation found for info_target_label (6175926565900432067) -->
+ <skip />
+ <string name="accessibility_search_button" msgid="816822994629942611">"Išči"</string>
+ <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Glasovno iskanje"</string>
+ <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Programi"</string>
+ <string name="accessibility_customize_button" msgid="585539669413531163">"Prilagodi"</string>
+ <string name="accessibility_delete_button" msgid="3628162007991023603">"Odstrani"</string>
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Odstrani posodobitev"</string>
<string name="menu_add" msgid="3065046628354640854">"Dodaj"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Upravljaj programe"</string>
@@ -91,4 +103,5 @@
<string name="permdesc_write_settings" msgid="1098648778383349818">"Omogoča programu spreminjanje nastavitev in bližnjic na začetnem zaslonu."</string>
<string name="gadget_error_text" msgid="8359351016167075858">"Težave pri nalaganju pripomočka"</string>
<string name="uninstall_system_app_text" msgid="7488523163288397451">"To je sistemski program in ga ni mogoče odstraniti."</string>
+ <string name="dream_name" msgid="2847171357608437154">"Raketno izstrelišče"</string>
</resources>
diff --git a/res/values-sr-land/strings.xml b/res/values-sr-land/strings.xml
new file mode 100644
index 000000000..b976926f0
--- /dev/null
+++ b/res/values-sr-land/strings.xml
@@ -0,0 +1,25 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="delete_target_label" msgid="4155210680095864979"></string>
+ <string name="delete_target_uninstall_label" msgid="1839407506844917298"></string>
+ <string name="info_target_label" msgid="1424400595004570393"></string>
+</resources>
diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml
index 1d920807e..2cd051a52 100644
--- a/res/values-sr/strings.xml
+++ b/res/values-sr/strings.xml
@@ -37,6 +37,7 @@
<string name="all_apps_tab_apps" msgid="5468972551904071712">"Apps"</string>
<string name="all_apps_tab_games" msgid="1855736784923494918">"Игре"</string>
<string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Моје апликације"</string>
+ <string name="long_press_widget_to_add" msgid="4307462194057715796">"Притисните и задржите да бисте додали виџет"</string>
<string name="all_apps_no_games" msgid="5293893733372793696">"Нису пронађене игре."</string>
<string name="all_apps_no_downloads" msgid="2284720393234453761">"Немате ниједну преузету апликацију."</string>
<string name="market" msgid="2652226429823445833">"Куповина"</string>
@@ -67,6 +68,17 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Почетна"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Уклони"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Деинсталирај"</string>
+ <!-- no translation found for delete_target_label (665300185123139530) -->
+ <skip />
+ <!-- no translation found for delete_target_uninstall_label (748894921183769150) -->
+ <skip />
+ <!-- no translation found for info_target_label (6175926565900432067) -->
+ <skip />
+ <string name="accessibility_search_button" msgid="816822994629942611">"Претражи"</string>
+ <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Гласовна претрага"</string>
+ <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Апликације"</string>
+ <string name="accessibility_customize_button" msgid="585539669413531163">"Прилагоди"</string>
+ <string name="accessibility_delete_button" msgid="3628162007991023603">"Уклони"</string>
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Деинсталирај ажурирања"</string>
<string name="menu_add" msgid="3065046628354640854">"Додај"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Управљање апликацијама"</string>
@@ -91,4 +103,5 @@
<string name="permdesc_write_settings" msgid="1098648778383349818">"Омогућава апликацији да промени подешавања и пречице на почетном екрану."</string>
<string name="gadget_error_text" msgid="8359351016167075858">"Проблем приликом учитавања виџета"</string>
<string name="uninstall_system_app_text" msgid="7488523163288397451">"Ово је системска апликација и не може да се деинсталира."</string>
+ <string name="dream_name" msgid="2847171357608437154">"Rocket Launcher"</string>
</resources>
diff --git a/res/values-sv-land/strings.xml b/res/values-sv-land/strings.xml
new file mode 100644
index 000000000..b976926f0
--- /dev/null
+++ b/res/values-sv-land/strings.xml
@@ -0,0 +1,25 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="delete_target_label" msgid="4155210680095864979"></string>
+ <string name="delete_target_uninstall_label" msgid="1839407506844917298"></string>
+ <string name="info_target_label" msgid="1424400595004570393"></string>
+</resources>
diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml
index 8094f05b5..1f00f4dc0 100644
--- a/res/values-sv/strings.xml
+++ b/res/values-sv/strings.xml
@@ -37,6 +37,7 @@
<string name="all_apps_tab_apps" msgid="5468972551904071712">"Appar"</string>
<string name="all_apps_tab_games" msgid="1855736784923494918">"Spel"</string>
<string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Mina appar"</string>
+ <string name="long_press_widget_to_add" msgid="4307462194057715796">"Tryck länge om du vill plocka upp en widget"</string>
<string name="all_apps_no_games" msgid="5293893733372793696">"Inga spel hittades."</string>
<string name="all_apps_no_downloads" msgid="2284720393234453761">"Du har inte hämtat några appar."</string>
<string name="market" msgid="2652226429823445833">"Butik"</string>
@@ -67,6 +68,17 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Startsida"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Ta bort"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Avinstallera"</string>
+ <!-- no translation found for delete_target_label (665300185123139530) -->
+ <skip />
+ <!-- no translation found for delete_target_uninstall_label (748894921183769150) -->
+ <skip />
+ <!-- no translation found for info_target_label (6175926565900432067) -->
+ <skip />
+ <string name="accessibility_search_button" msgid="816822994629942611">"Sök"</string>
+ <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Röstsökning"</string>
+ <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Appar"</string>
+ <string name="accessibility_customize_button" msgid="585539669413531163">"Anpassa"</string>
+ <string name="accessibility_delete_button" msgid="3628162007991023603">"Ta bort"</string>
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Avinstallera uppdatering"</string>
<string name="menu_add" msgid="3065046628354640854">"Lägg till"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Hantera appar"</string>
@@ -91,4 +103,5 @@
<string name="permdesc_write_settings" msgid="1098648778383349818">"Tillåter att ett program ändrar inställningar och genvägar på startsidan."</string>
<string name="gadget_error_text" msgid="8359351016167075858">"Det gick inte att läsa in widgeten"</string>
<string name="uninstall_system_app_text" msgid="7488523163288397451">"Det här är ett systemprogram och kan inte avinstalleras."</string>
+ <string name="dream_name" msgid="2847171357608437154">"Raketavfyringsramp"</string>
</resources>
diff --git a/res/values-sw-land/strings.xml b/res/values-sw-land/strings.xml
new file mode 100644
index 000000000..b976926f0
--- /dev/null
+++ b/res/values-sw-land/strings.xml
@@ -0,0 +1,25 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="delete_target_label" msgid="4155210680095864979"></string>
+ <string name="delete_target_uninstall_label" msgid="1839407506844917298"></string>
+ <string name="info_target_label" msgid="1424400595004570393"></string>
+</resources>
diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml
new file mode 100644
index 000000000..be8d6f950
--- /dev/null
+++ b/res/values-sw/strings.xml
@@ -0,0 +1,143 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2008 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="application_name" msgid="8424725141379931883">"Kizinduzi"</string>
+ <string name="uid_name" msgid="3371120195364560632">"Programu Kuu za Android"</string>
+ <!-- no translation found for folder_name (4588446541914685904) -->
+ <skip />
+ <!-- no translation found for chooser_wallpaper (5988031014201479733) -->
+ <skip />
+ <!-- no translation found for wallpaper_instructions (4215640646180727542) -->
+ <skip />
+ <string name="pick_wallpaper" msgid="5630222540525626723">"Taswira"</string>
+ <!-- no translation found for activity_not_found (5591731020063337696) -->
+ <skip />
+ <string name="configure_wallpaper" msgid="2820186271419674623">"Weka mipangilio.."</string>
+ <string name="widgets_tab_label" msgid="9145860100000983599">"Wijeti"</string>
+ <string name="folders_tab_label" msgid="1145293785541489736">"Mafolda"</string>
+ <string name="shortcuts_tab_label" msgid="8640731503933155644">"Zaidi"</string>
+ <string name="wallpapers_tab_label" msgid="1617804870364119879">"Taswira"</string>
+ <!-- no translation found for applications_tab_label (2991364240020736760) -->
+ <skip />
+ <string name="wallpapers_temp_tab_text" msgid="1660218201190495279">"Hiki kitakuwa kichupo cha taswira"</string>
+ <string name="all_apps_tab_all" msgid="2942727589595027258">"Zote"</string>
+ <string name="all_apps_tab_apps" msgid="5468972551904071712">"Programu"</string>
+ <string name="all_apps_tab_games" msgid="1855736784923494918">"Michezo"</string>
+ <!-- no translation found for all_apps_tab_downloaded (1488049110598641387) -->
+ <skip />
+ <!-- no translation found for long_press_widget_to_add (4307462194057715796) -->
+ <skip />
+ <!-- no translation found for all_apps_no_games (5293893733372793696) -->
+ <skip />
+ <!-- no translation found for all_apps_no_downloads (2284720393234453761) -->
+ <skip />
+ <!-- no translation found for market (2652226429823445833) -->
+ <skip />
+ <!-- no translation found for external_drop_widget_error (4976816434597126575) -->
+ <skip />
+ <!-- no translation found for external_drop_widget_pick_title (4481311720134376218) -->
+ <skip />
+ <string name="rename_folder_label" msgid="5646236631298452787">"Jina la folda"</string>
+ <!-- no translation found for rename_folder_title (4544573104191526550) -->
+ <skip />
+ <!-- no translation found for rename_action (6016003384693240896) -->
+ <skip />
+ <!-- no translation found for cancel_action (3811860427489435048) -->
+ <skip />
+ <string name="menu_item_add_item" msgid="6233177331075781114">"Ongeza kwa skrini ya Nyumbani"</string>
+ <string name="group_applications" msgid="4118484163419674240">"Programu"</string>
+ <string name="group_shortcuts" msgid="9133529424900391877">"Njia za mkato"</string>
+ <string name="group_folder" msgid="5143593791798929193">"Folda mpya"</string>
+ <string name="group_live_folders" msgid="2664945399140647217">"Mafolda"</string>
+ <string name="group_widgets" msgid="6704978494073105844">"Wijeti"</string>
+ <string name="group_wallpapers" msgid="1568191644272224858">"Pazia"</string>
+ <!-- no translation found for add_folder (3521088587367839879) -->
+ <skip />
+ <!-- no translation found for add_clock (2337943840175865746) -->
+ <skip />
+ <!-- no translation found for add_photo_frame (3154058437359487954) -->
+ <skip />
+ <!-- no translation found for out_of_space (8365249326091984698) -->
+ <skip />
+ <string name="shortcut_installed" msgid="7071557296331322355">"Njia ya mkato ya \"<xliff:g id="NAME">%s</xliff:g>\" imeundwa."</string>
+ <string name="shortcut_uninstalled" msgid="2129499669449749995">"Njia ya mkato ya \"<xliff:g id="NAME">%s</xliff:g>\" iliondolewa."</string>
+ <string name="shortcut_duplicate" msgid="4757756326465060694">"Njia ya mkato ya \"<xliff:g id="NAME">%s</xliff:g>\" tayari ipo."</string>
+ <string name="title_select_shortcut" msgid="2858897527672831763">"Chagua njia ya mkato"</string>
+ <string name="title_select_application" msgid="8031072293115454221">"Chagua programu"</string>
+ <string name="title_select_live_folder" msgid="3753447798805166749">"Chagua folda"</string>
+ <string name="all_apps_button_label" msgid="2578400570124163469">"Programu"</string>
+ <string name="all_apps_home_button_label" msgid="1022222300329398558">"Nyumbani"</string>
+ <!-- no translation found for delete_zone_label_workspace (7153615831493049150) -->
+ <skip />
+ <!-- no translation found for delete_zone_label_all_apps (6664588234817475108) -->
+ <skip />
+ <!-- no translation found for delete_target_label (665300185123139530) -->
+ <skip />
+ <!-- no translation found for delete_target_uninstall_label (748894921183769150) -->
+ <skip />
+ <!-- no translation found for info_target_label (6175926565900432067) -->
+ <skip />
+ <!-- no translation found for accessibility_search_button (816822994629942611) -->
+ <skip />
+ <!-- no translation found for accessibility_voice_search_button (3938249215065842475) -->
+ <skip />
+ <!-- no translation found for accessibility_all_apps_button (1595097919145716305) -->
+ <skip />
+ <!-- no translation found for accessibility_customize_button (585539669413531163) -->
+ <skip />
+ <!-- no translation found for accessibility_delete_button (3628162007991023603) -->
+ <skip />
+ <!-- no translation found for delete_zone_label_all_apps_system_app (3683920959591819044) -->
+ <skip />
+ <!-- no translation found for menu_add (3065046628354640854) -->
+ <skip />
+ <!-- no translation found for menu_manage_apps (2308685199463588895) -->
+ <skip />
+ <!-- no translation found for menu_wallpaper (5837429080911269832) -->
+ <skip />
+ <!-- no translation found for menu_search (4826514464423239041) -->
+ <skip />
+ <!-- no translation found for menu_notifications (6424587053194766192) -->
+ <skip />
+ <string name="menu_gestures" msgid="514678675575912237">"Ishara"</string>
+ <!-- no translation found for menu_settings (6233960148378443661) -->
+ <skip />
+ <string name="cab_menu_delete_app" msgid="1242619904941293871">"Ondoa programu"</string>
+ <string name="cab_menu_app_info" msgid="5180426909324882018">"Maelezo ya programu"</string>
+ <string name="cab_app_selection_text" msgid="606113924828167756">"Programu 1 imechaguliwa"</string>
+ <string name="cab_widget_selection_text" msgid="962527270506951955">"Wijeti 1 imechaguliwa"</string>
+ <string name="cab_folder_selection_text" msgid="8916111874189565067">"Folda 1 limechaguliwa"</string>
+ <string name="cab_shortcut_selection_text" msgid="8115847384500412878">" Njia 1 ya mkato imechaguliwa"</string>
+ <!-- no translation found for permlab_install_shortcut (1201690825493376489) -->
+ <skip />
+ <string name="permdesc_install_shortcut" msgid="7429365847558984148">"Huruhusu programu kuongeza njia za mkato bila mtumiaji kuhusika."</string>
+ <!-- no translation found for permlab_uninstall_shortcut (7696645932555926449) -->
+ <skip />
+ <string name="permdesc_uninstall_shortcut" msgid="959972195916090900">"Huruhusu programu kuondoa njia za mkato bila mtumiaji kuhusika."</string>
+ <string name="permlab_read_settings" msgid="3452408290738106747">"soma mipangilio ya Nyumbani na njia za mkato"</string>
+ <string name="permdesc_read_settings" msgid="8377434937176025492">"Huruhusu programu kusoma mipangilio na njia za mkato katika Nyumbani."</string>
+ <string name="permlab_write_settings" msgid="1360567537236705628">"andika mipangilio ya Nyumbani na njia za mkato"</string>
+ <string name="permdesc_write_settings" msgid="1098648778383349818">"Huruhusu programu kubadilisha mipangilio na njia za mkato Nyumbani."</string>
+ <string name="gadget_error_text" msgid="8359351016167075858">"Tatizo la kupakia wijeti"</string>
+ <string name="uninstall_system_app_text" msgid="7488523163288397451">"Hii ni programu ya mfumo na haiwezi kuondolewa."</string>
+ <!-- no translation found for dream_name (2847171357608437154) -->
+ <skip />
+</resources>
diff --git a/res/values-th-land/strings.xml b/res/values-th-land/strings.xml
new file mode 100644
index 000000000..b976926f0
--- /dev/null
+++ b/res/values-th-land/strings.xml
@@ -0,0 +1,25 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="delete_target_label" msgid="4155210680095864979"></string>
+ <string name="delete_target_uninstall_label" msgid="1839407506844917298"></string>
+ <string name="info_target_label" msgid="1424400595004570393"></string>
+</resources>
diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml
index 26c33c915..fc3c68a8a 100644
--- a/res/values-th/strings.xml
+++ b/res/values-th/strings.xml
@@ -37,6 +37,7 @@
<string name="all_apps_tab_apps" msgid="5468972551904071712">"แอปพลิเคชัน"</string>
<string name="all_apps_tab_games" msgid="1855736784923494918">"เกม"</string>
<string name="all_apps_tab_downloaded" msgid="1488049110598641387">"แอปพลิเคชันของฉัน"</string>
+ <string name="long_press_widget_to_add" msgid="4307462194057715796">"กดค้างเพื่อรับวิดเจ็ต"</string>
<string name="all_apps_no_games" msgid="5293893733372793696">"ไม่พบเกม"</string>
<string name="all_apps_no_downloads" msgid="2284720393234453761">"คุณไม่ได้ดาวน์โหลดแอปพลิเคชันไว้"</string>
<string name="market" msgid="2652226429823445833">"ร้าน"</string>
@@ -67,6 +68,17 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"บ้าน"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"นำออก"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"ถอนการติดตั้ง"</string>
+ <!-- no translation found for delete_target_label (665300185123139530) -->
+ <skip />
+ <!-- no translation found for delete_target_uninstall_label (748894921183769150) -->
+ <skip />
+ <!-- no translation found for info_target_label (6175926565900432067) -->
+ <skip />
+ <string name="accessibility_search_button" msgid="816822994629942611">"ค้นหา"</string>
+ <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Voice Search"</string>
+ <string name="accessibility_all_apps_button" msgid="1595097919145716305">"แอปพลิเคชัน"</string>
+ <string name="accessibility_customize_button" msgid="585539669413531163">"กำหนดค่า"</string>
+ <string name="accessibility_delete_button" msgid="3628162007991023603">"ลบ"</string>
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"ถอนการติดตั้งการอัปเดต"</string>
<string name="menu_add" msgid="3065046628354640854">"เพิ่ม"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"จัดการแอปพลิเคชัน"</string>
@@ -91,4 +103,5 @@
<string name="permdesc_write_settings" msgid="1098648778383349818">"อนุญาตให้แอปพลิเคชันเปลี่ยนการตั้งค่าและทางลัดในหน้าแรก"</string>
<string name="gadget_error_text" msgid="8359351016167075858">"มีปัญหาขณะโหลดวิดเจ็ต"</string>
<string name="uninstall_system_app_text" msgid="7488523163288397451">"นี่เป็นแอปพลิเคชันระบบและไม่สามารถถอนการติดตั้งได้"</string>
+ <string name="dream_name" msgid="2847171357608437154">"Rocket Launcher"</string>
</resources>
diff --git a/res/values-tl-land/strings.xml b/res/values-tl-land/strings.xml
new file mode 100644
index 000000000..b976926f0
--- /dev/null
+++ b/res/values-tl-land/strings.xml
@@ -0,0 +1,25 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="delete_target_label" msgid="4155210680095864979"></string>
+ <string name="delete_target_uninstall_label" msgid="1839407506844917298"></string>
+ <string name="info_target_label" msgid="1424400595004570393"></string>
+</resources>
diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml
index f21dc3c66..8f87c6ab3 100644
--- a/res/values-tl/strings.xml
+++ b/res/values-tl/strings.xml
@@ -37,6 +37,7 @@
<string name="all_apps_tab_apps" msgid="5468972551904071712">"Apps"</string>
<string name="all_apps_tab_games" msgid="1855736784923494918">"Mga Laro"</string>
<string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Aking mga app"</string>
+ <string name="long_press_widget_to_add" msgid="4307462194057715796">"Pindutin nang matagal upang kumuha ng widget"</string>
<string name="all_apps_no_games" msgid="5293893733372793696">"Walang nakitang mga laro."</string>
<string name="all_apps_no_downloads" msgid="2284720393234453761">"Wala kang mga na-download na application."</string>
<string name="market" msgid="2652226429823445833">"Mamili"</string>
@@ -67,6 +68,17 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Home"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Alisin"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"I-uninstall"</string>
+ <!-- no translation found for delete_target_label (665300185123139530) -->
+ <skip />
+ <!-- no translation found for delete_target_uninstall_label (748894921183769150) -->
+ <skip />
+ <!-- no translation found for info_target_label (6175926565900432067) -->
+ <skip />
+ <string name="accessibility_search_button" msgid="816822994629942611">"Maghanap"</string>
+ <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Paghahanap gamit ang Boses"</string>
+ <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Mga Application"</string>
+ <string name="accessibility_customize_button" msgid="585539669413531163">"I-customize"</string>
+ <string name="accessibility_delete_button" msgid="3628162007991023603">"Alisin"</string>
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"I-uninstall ang update"</string>
<string name="menu_add" msgid="3065046628354640854">"Idagdag"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Pamahalaan ang apps"</string>
@@ -91,4 +103,5 @@
<string name="permdesc_write_settings" msgid="1098648778383349818">"Pinapayagan ang isang application na baguhin ang mga setting at shortcut sa Home."</string>
<string name="gadget_error_text" msgid="8359351016167075858">"Problema sa pag-load ng widget"</string>
<string name="uninstall_system_app_text" msgid="7488523163288397451">"Isa itong system application at hindi maaaring i-install."</string>
+ <string name="dream_name" msgid="2847171357608437154">"Rocket Launcher"</string>
</resources>
diff --git a/res/values-tr-land/strings.xml b/res/values-tr-land/strings.xml
new file mode 100644
index 000000000..b976926f0
--- /dev/null
+++ b/res/values-tr-land/strings.xml
@@ -0,0 +1,25 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="delete_target_label" msgid="4155210680095864979"></string>
+ <string name="delete_target_uninstall_label" msgid="1839407506844917298"></string>
+ <string name="info_target_label" msgid="1424400595004570393"></string>
+</resources>
diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml
index bf80bf52b..f9d220d44 100644
--- a/res/values-tr/strings.xml
+++ b/res/values-tr/strings.xml
@@ -37,6 +37,7 @@
<string name="all_apps_tab_apps" msgid="5468972551904071712">"Uygulamalar"</string>
<string name="all_apps_tab_games" msgid="1855736784923494918">"Oyunlar"</string>
<string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Uygulamalarım"</string>
+ <string name="long_press_widget_to_add" msgid="4307462194057715796">"Widget seçmek için uzun basın"</string>
<string name="all_apps_no_games" msgid="5293893733372793696">"Oyun bulunamadı."</string>
<string name="all_apps_no_downloads" msgid="2284720393234453761">"İndirilmiş uygulamanız yok."</string>
<string name="market" msgid="2652226429823445833">"Alışveriş"</string>
@@ -67,6 +68,17 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Ana Sayfa"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Kaldır"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Yüklemeyi Kaldır"</string>
+ <!-- no translation found for delete_target_label (665300185123139530) -->
+ <skip />
+ <!-- no translation found for delete_target_uninstall_label (748894921183769150) -->
+ <skip />
+ <!-- no translation found for info_target_label (6175926565900432067) -->
+ <skip />
+ <string name="accessibility_search_button" msgid="816822994629942611">"Ara"</string>
+ <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Sesli Arama"</string>
+ <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Uygulamalar"</string>
+ <string name="accessibility_customize_button" msgid="585539669413531163">"Özelleştir"</string>
+ <string name="accessibility_delete_button" msgid="3628162007991023603">"Kaldır"</string>
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Güncelleme kaldırılsın mı?"</string>
<string name="menu_add" msgid="3065046628354640854">"Ekle"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Uyglm yönet"</string>
@@ -91,4 +103,5 @@
<string name="permdesc_write_settings" msgid="1098648778383349818">"Bir uygulamaya Ana Sayfadaki ayarları ve kısayolları değiştirme izni verir."</string>
<string name="gadget_error_text" msgid="8359351016167075858">"Widget yüklenirken sorun oluştu"</string>
<string name="uninstall_system_app_text" msgid="7488523163288397451">"Bu bir sistem uygulamasıdır ve kaldırılamaz."</string>
+ <string name="dream_name" msgid="2847171357608437154">"Roket Fırlatıcı"</string>
</resources>
diff --git a/res/values-uk-land/strings.xml b/res/values-uk-land/strings.xml
new file mode 100644
index 000000000..b976926f0
--- /dev/null
+++ b/res/values-uk-land/strings.xml
@@ -0,0 +1,25 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="delete_target_label" msgid="4155210680095864979"></string>
+ <string name="delete_target_uninstall_label" msgid="1839407506844917298"></string>
+ <string name="info_target_label" msgid="1424400595004570393"></string>
+</resources>
diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml
index 267ca882f..cdc648f83 100644
--- a/res/values-uk/strings.xml
+++ b/res/values-uk/strings.xml
@@ -37,6 +37,7 @@
<string name="all_apps_tab_apps" msgid="5468972551904071712">"Програми"</string>
<string name="all_apps_tab_games" msgid="1855736784923494918">"Ігри"</string>
<string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Мої програми"</string>
+ <string name="long_press_widget_to_add" msgid="4307462194057715796">"Натисніть і тримайте, щоб вибрати віджет"</string>
<string name="all_apps_no_games" msgid="5293893733372793696">"Ігор не знайдено."</string>
<string name="all_apps_no_downloads" msgid="2284720393234453761">"У вас немає завантажених програм."</string>
<string name="market" msgid="2652226429823445833">"Магазин"</string>
@@ -67,6 +68,17 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Головна"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Видалити"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Видалити"</string>
+ <!-- no translation found for delete_target_label (665300185123139530) -->
+ <skip />
+ <!-- no translation found for delete_target_uninstall_label (748894921183769150) -->
+ <skip />
+ <!-- no translation found for info_target_label (6175926565900432067) -->
+ <skip />
+ <string name="accessibility_search_button" msgid="816822994629942611">"Пошук"</string>
+ <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Голосовий пошук"</string>
+ <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Програми"</string>
+ <string name="accessibility_customize_button" msgid="585539669413531163">"Налаштувати"</string>
+ <string name="accessibility_delete_button" msgid="3628162007991023603">"Видалити"</string>
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Видалити оновлення"</string>
<string name="menu_add" msgid="3065046628354640854">"Додати"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Керув. прогр."</string>
@@ -91,4 +103,5 @@
<string name="permdesc_write_settings" msgid="1098648778383349818">"Дозволяє програмі змінювати налаштування та ярлики на Головній."</string>
<string name="gadget_error_text" msgid="8359351016167075858">"Пробл із завантаж. віджета"</string>
<string name="uninstall_system_app_text" msgid="7488523163288397451">"Це системна програма, її неможливо видалити."</string>
+ <string name="dream_name" msgid="2847171357608437154">"Rocket Launcher"</string>
</resources>
diff --git a/res/values-vi-land/strings.xml b/res/values-vi-land/strings.xml
new file mode 100644
index 000000000..b976926f0
--- /dev/null
+++ b/res/values-vi-land/strings.xml
@@ -0,0 +1,25 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="delete_target_label" msgid="4155210680095864979"></string>
+ <string name="delete_target_uninstall_label" msgid="1839407506844917298"></string>
+ <string name="info_target_label" msgid="1424400595004570393"></string>
+</resources>
diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml
index d3f549f92..57a164c01 100644
--- a/res/values-vi/strings.xml
+++ b/res/values-vi/strings.xml
@@ -37,6 +37,7 @@
<string name="all_apps_tab_apps" msgid="5468972551904071712">"Ứng dụng"</string>
<string name="all_apps_tab_games" msgid="1855736784923494918">"Trò chơi"</string>
<string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Ứng dụng của tôi"</string>
+ <string name="long_press_widget_to_add" msgid="4307462194057715796">"Nhấn và giữ để chọn tiện ích con"</string>
<string name="all_apps_no_games" msgid="5293893733372793696">"Không tìm thấy trò chơi."</string>
<string name="all_apps_no_downloads" msgid="2284720393234453761">"Bạn không có ứng dụng nào được tải xuống."</string>
<string name="market" msgid="2652226429823445833">"Mua hàng"</string>
@@ -67,6 +68,17 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Màn hình trang chủ"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"Xóa"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Gỡ cài đặt"</string>
+ <!-- no translation found for delete_target_label (665300185123139530) -->
+ <skip />
+ <!-- no translation found for delete_target_uninstall_label (748894921183769150) -->
+ <skip />
+ <!-- no translation found for info_target_label (6175926565900432067) -->
+ <skip />
+ <string name="accessibility_search_button" msgid="816822994629942611">"Tìm kiếm"</string>
+ <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Tìm kiếm bằng giọng nói"</string>
+ <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Ứng dụng"</string>
+ <string name="accessibility_customize_button" msgid="585539669413531163">"Tùy chỉnh"</string>
+ <string name="accessibility_delete_button" msgid="3628162007991023603">"Xóa"</string>
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Gỡ cài đặt cập nhật"</string>
<string name="menu_add" msgid="3065046628354640854">"Thêm"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"Quản lý ứng dụng"</string>
@@ -91,4 +103,5 @@
<string name="permdesc_write_settings" msgid="1098648778383349818">"Cho phép ứng dụng thay đổi cài đặt và lối tắt trên Màn hình trang chủ."</string>
<string name="gadget_error_text" msgid="8359351016167075858">"Sự cố khi tải tiện ích"</string>
<string name="uninstall_system_app_text" msgid="7488523163288397451">"Đây là ứng dụng hệ thống và không thể gỡ cài đặt."</string>
+ <string name="dream_name" msgid="2847171357608437154">"Rocket Launcher"</string>
</resources>
diff --git a/res/values-xlarge-port/dimens.xml b/res/values-xlarge-port/dimens.xml
new file mode 100644
index 000000000..31db0b352
--- /dev/null
+++ b/res/values-xlarge-port/dimens.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resources>
+ <!-- The amount of space to account for the next/prev pages when
+ calculating the number of columns to fit a page.
+ In portrait/xlarge we use apps_customize_cell_width / 4. -->
+ <dimen name="apps_customize_peek_width">48dp</dimen>
+
+ <!-- We can also afford to have a slightly wider portrait layout in
+ xlarge -->
+ <dimen name="all_apps_view_pageLayoutWidthGap">36dp</dimen>
+</resources> \ No newline at end of file
diff --git a/res/values-zh-rCN-land/strings.xml b/res/values-zh-rCN-land/strings.xml
new file mode 100644
index 000000000..b976926f0
--- /dev/null
+++ b/res/values-zh-rCN-land/strings.xml
@@ -0,0 +1,25 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="delete_target_label" msgid="4155210680095864979"></string>
+ <string name="delete_target_uninstall_label" msgid="1839407506844917298"></string>
+ <string name="info_target_label" msgid="1424400595004570393"></string>
+</resources>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index a3dc212bd..39da9e3f3 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -37,6 +37,7 @@
<string name="all_apps_tab_apps" msgid="5468972551904071712">"应用程序"</string>
<string name="all_apps_tab_games" msgid="1855736784923494918">"游戏"</string>
<string name="all_apps_tab_downloaded" msgid="1488049110598641387">"我的应用程序"</string>
+ <string name="long_press_widget_to_add" msgid="4307462194057715796">"长按可选取一个窗口小部件"</string>
<string name="all_apps_no_games" msgid="5293893733372793696">"未找到游戏。"</string>
<string name="all_apps_no_downloads" msgid="2284720393234453761">"您没有下载任何应用程序。"</string>
<string name="market" msgid="2652226429823445833">"购买"</string>
@@ -67,6 +68,17 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"主屏幕"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"删除"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"卸载"</string>
+ <!-- no translation found for delete_target_label (665300185123139530) -->
+ <skip />
+ <!-- no translation found for delete_target_uninstall_label (748894921183769150) -->
+ <skip />
+ <!-- no translation found for info_target_label (6175926565900432067) -->
+ <skip />
+ <string name="accessibility_search_button" msgid="816822994629942611">"搜索"</string>
+ <string name="accessibility_voice_search_button" msgid="3938249215065842475">"语音搜索"</string>
+ <string name="accessibility_all_apps_button" msgid="1595097919145716305">"应用程序"</string>
+ <string name="accessibility_customize_button" msgid="585539669413531163">"自定义"</string>
+ <string name="accessibility_delete_button" msgid="3628162007991023603">"删除"</string>
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"卸载更新"</string>
<string name="menu_add" msgid="3065046628354640854">"添加"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"管理应用程序"</string>
@@ -91,4 +103,5 @@
<string name="permdesc_write_settings" msgid="1098648778383349818">"允许应用程序更改主屏幕的设置和快捷方式。"</string>
<string name="gadget_error_text" msgid="8359351016167075858">"载入窗口小部件时出现问题"</string>
<string name="uninstall_system_app_text" msgid="7488523163288397451">"这是系统应用程序,无法卸载。"</string>
+ <string name="dream_name" msgid="2847171357608437154">"Rocket Launcher"</string>
</resources>
diff --git a/res/values-zh-rTW-land/strings.xml b/res/values-zh-rTW-land/strings.xml
new file mode 100644
index 000000000..b976926f0
--- /dev/null
+++ b/res/values-zh-rTW-land/strings.xml
@@ -0,0 +1,25 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="delete_target_label" msgid="4155210680095864979"></string>
+ <string name="delete_target_uninstall_label" msgid="1839407506844917298"></string>
+ <string name="info_target_label" msgid="1424400595004570393"></string>
+</resources>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index 2274274f8..05cc25171 100644
--- a/res/values-zh-rTW/strings.xml
+++ b/res/values-zh-rTW/strings.xml
@@ -37,6 +37,7 @@
<string name="all_apps_tab_apps" msgid="5468972551904071712">"應用程式"</string>
<string name="all_apps_tab_games" msgid="1855736784923494918">"遊戲"</string>
<string name="all_apps_tab_downloaded" msgid="1488049110598641387">"我的應用程式"</string>
+ <string name="long_press_widget_to_add" msgid="4307462194057715796">"持續按住小工具即可選取"</string>
<string name="all_apps_no_games" msgid="5293893733372793696">"找不到遊戲。"</string>
<string name="all_apps_no_downloads" msgid="2284720393234453761">"您沒有下載任何應用程式。"</string>
<string name="market" msgid="2652226429823445833">"商店"</string>
@@ -67,6 +68,17 @@
<string name="all_apps_home_button_label" msgid="1022222300329398558">"主螢幕"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"移除"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"解除安裝"</string>
+ <!-- no translation found for delete_target_label (665300185123139530) -->
+ <skip />
+ <!-- no translation found for delete_target_uninstall_label (748894921183769150) -->
+ <skip />
+ <!-- no translation found for info_target_label (6175926565900432067) -->
+ <skip />
+ <string name="accessibility_search_button" msgid="816822994629942611">"搜尋"</string>
+ <string name="accessibility_voice_search_button" msgid="3938249215065842475">"語音搜尋"</string>
+ <string name="accessibility_all_apps_button" msgid="1595097919145716305">"應用程式"</string>
+ <string name="accessibility_customize_button" msgid="585539669413531163">"自訂"</string>
+ <string name="accessibility_delete_button" msgid="3628162007991023603">"移除"</string>
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"解除安裝更新"</string>
<string name="menu_add" msgid="3065046628354640854">"新增"</string>
<string name="menu_manage_apps" msgid="2308685199463588895">"管理應用程式"</string>
@@ -91,4 +103,5 @@
<string name="permdesc_write_settings" msgid="1098648778383349818">"允許應用程式變更主螢幕中的設定和捷徑。"</string>
<string name="gadget_error_text" msgid="8359351016167075858">"載入小工具時發生問題"</string>
<string name="uninstall_system_app_text" msgid="7488523163288397451">"這是系統應用程式,無法將其解除安裝。"</string>
+ <string name="dream_name" msgid="2847171357608437154">"Rocket Launcher"</string>
</resources>
diff --git a/res/values-zu-land/strings.xml b/res/values-zu-land/strings.xml
new file mode 100644
index 000000000..b976926f0
--- /dev/null
+++ b/res/values-zu-land/strings.xml
@@ -0,0 +1,25 @@
+<?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 xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="delete_target_label" msgid="4155210680095864979"></string>
+ <string name="delete_target_uninstall_label" msgid="1839407506844917298"></string>
+ <string name="info_target_label" msgid="1424400595004570393"></string>
+</resources>
diff --git a/res/values-zu/strings.xml b/res/values-zu/strings.xml
new file mode 100644
index 000000000..25a7bb6c5
--- /dev/null
+++ b/res/values-zu/strings.xml
@@ -0,0 +1,143 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (C) 2008 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="application_name" msgid="8424725141379931883">"Isiqalisi"</string>
+ <string name="uid_name" msgid="3371120195364560632">"I-Android Core Apps"</string>
+ <!-- no translation found for folder_name (4588446541914685904) -->
+ <skip />
+ <!-- no translation found for chooser_wallpaper (5988031014201479733) -->
+ <skip />
+ <!-- no translation found for wallpaper_instructions (4215640646180727542) -->
+ <skip />
+ <string name="pick_wallpaper" msgid="5630222540525626723">"Amaphephadonga"</string>
+ <!-- no translation found for activity_not_found (5591731020063337696) -->
+ <skip />
+ <string name="configure_wallpaper" msgid="2820186271419674623">"Misa..."</string>
+ <string name="widgets_tab_label" msgid="9145860100000983599">"Amawijethi"</string>
+ <string name="folders_tab_label" msgid="1145293785541489736">"Amafolda"</string>
+ <string name="shortcuts_tab_label" msgid="8640731503933155644">"Okungaphezulu"</string>
+ <string name="wallpapers_tab_label" msgid="1617804870364119879">"Amaphephadonga"</string>
+ <!-- no translation found for applications_tab_label (2991364240020736760) -->
+ <skip />
+ <string name="wallpapers_temp_tab_text" msgid="1660218201190495279">"Lokhu kuzoba isithikithana samaphephadonga"</string>
+ <string name="all_apps_tab_all" msgid="2942727589595027258">"Konke"</string>
+ <string name="all_apps_tab_apps" msgid="5468972551904071712">"Izinhlelo Zokusebenza"</string>
+ <string name="all_apps_tab_games" msgid="1855736784923494918">"Imidlalo"</string>
+ <!-- no translation found for all_apps_tab_downloaded (1488049110598641387) -->
+ <skip />
+ <!-- no translation found for long_press_widget_to_add (4307462194057715796) -->
+ <skip />
+ <!-- no translation found for all_apps_no_games (5293893733372793696) -->
+ <skip />
+ <!-- no translation found for all_apps_no_downloads (2284720393234453761) -->
+ <skip />
+ <!-- no translation found for market (2652226429823445833) -->
+ <skip />
+ <!-- no translation found for external_drop_widget_error (4976816434597126575) -->
+ <skip />
+ <!-- no translation found for external_drop_widget_pick_title (4481311720134376218) -->
+ <skip />
+ <string name="rename_folder_label" msgid="5646236631298452787">"Igama lefolda"</string>
+ <!-- no translation found for rename_folder_title (4544573104191526550) -->
+ <skip />
+ <!-- no translation found for rename_action (6016003384693240896) -->
+ <skip />
+ <!-- no translation found for cancel_action (3811860427489435048) -->
+ <skip />
+ <string name="menu_item_add_item" msgid="6233177331075781114">"Faka kwisikrini saseKhaya"</string>
+ <string name="group_applications" msgid="4118484163419674240">"Izinhlelo zokusebenza"</string>
+ <string name="group_shortcuts" msgid="9133529424900391877">"Izinqamuleli"</string>
+ <string name="group_folder" msgid="5143593791798929193">"Ifolda entsha"</string>
+ <string name="group_live_folders" msgid="2664945399140647217">"Amafolda"</string>
+ <string name="group_widgets" msgid="6704978494073105844">"Izinqunjwana"</string>
+ <string name="group_wallpapers" msgid="1568191644272224858">"Amaphephadonga"</string>
+ <!-- no translation found for add_folder (3521088587367839879) -->
+ <skip />
+ <!-- no translation found for add_clock (2337943840175865746) -->
+ <skip />
+ <!-- no translation found for add_photo_frame (3154058437359487954) -->
+ <skip />
+ <!-- no translation found for out_of_space (8365249326091984698) -->
+ <skip />
+ <string name="shortcut_installed" msgid="7071557296331322355">"Isinqamuleli \"<xliff:g id="NAME">%s</xliff:g>\" senziwe"</string>
+ <string name="shortcut_uninstalled" msgid="2129499669449749995">"Isinqamuleli \"<xliff:g id="NAME">%s</xliff:g>\" sikhishiwe."</string>
+ <string name="shortcut_duplicate" msgid="4757756326465060694">"Isinqamuleli \"<xliff:g id="NAME">%s</xliff:g>\" sivele sikhona"</string>
+ <string name="title_select_shortcut" msgid="2858897527672831763">"Khetha isinqamuleli"</string>
+ <string name="title_select_application" msgid="8031072293115454221">"Khetha uhlelo lokusebenza"</string>
+ <string name="title_select_live_folder" msgid="3753447798805166749">"Khetha ifolda"</string>
+ <string name="all_apps_button_label" msgid="2578400570124163469">"Izinhlelo zokusebenza"</string>
+ <string name="all_apps_home_button_label" msgid="1022222300329398558">"Ekhaya"</string>
+ <!-- no translation found for delete_zone_label_workspace (7153615831493049150) -->
+ <skip />
+ <!-- no translation found for delete_zone_label_all_apps (6664588234817475108) -->
+ <skip />
+ <!-- no translation found for delete_target_label (665300185123139530) -->
+ <skip />
+ <!-- no translation found for delete_target_uninstall_label (748894921183769150) -->
+ <skip />
+ <!-- no translation found for info_target_label (6175926565900432067) -->
+ <skip />
+ <!-- no translation found for accessibility_search_button (816822994629942611) -->
+ <skip />
+ <!-- no translation found for accessibility_voice_search_button (3938249215065842475) -->
+ <skip />
+ <!-- no translation found for accessibility_all_apps_button (1595097919145716305) -->
+ <skip />
+ <!-- no translation found for accessibility_customize_button (585539669413531163) -->
+ <skip />
+ <!-- no translation found for accessibility_delete_button (3628162007991023603) -->
+ <skip />
+ <!-- no translation found for delete_zone_label_all_apps_system_app (3683920959591819044) -->
+ <skip />
+ <!-- no translation found for menu_add (3065046628354640854) -->
+ <skip />
+ <!-- no translation found for menu_manage_apps (2308685199463588895) -->
+ <skip />
+ <!-- no translation found for menu_wallpaper (5837429080911269832) -->
+ <skip />
+ <!-- no translation found for menu_search (4826514464423239041) -->
+ <skip />
+ <!-- no translation found for menu_notifications (6424587053194766192) -->
+ <skip />
+ <string name="menu_gestures" msgid="514678675575912237">"Izimpawu"</string>
+ <!-- no translation found for menu_settings (6233960148378443661) -->
+ <skip />
+ <string name="cab_menu_delete_app" msgid="1242619904941293871">"Khipha uhlelo lokusebenza"</string>
+ <string name="cab_menu_app_info" msgid="5180426909324882018">"Imininingwane yohlelo lokusebenza"</string>
+ <string name="cab_app_selection_text" msgid="606113924828167756">"Kukhethwe uhlelo lokusebenza olungu-1"</string>
+ <string name="cab_widget_selection_text" msgid="962527270506951955">"kukhethwe iwijethi engu-1"</string>
+ <string name="cab_folder_selection_text" msgid="8916111874189565067">"kukhethwe ifolda engu-1"</string>
+ <string name="cab_shortcut_selection_text" msgid="8115847384500412878">"kukhethwe isinqamuleli esingu-1"</string>
+ <!-- no translation found for permlab_install_shortcut (1201690825493376489) -->
+ <skip />
+ <string name="permdesc_install_shortcut" msgid="7429365847558984148">"Ivumela uhlelo lokusebenza ukufaka izinqamuleli ngaphandle kokungenela komsebenzisi."</string>
+ <!-- no translation found for permlab_uninstall_shortcut (7696645932555926449) -->
+ <skip />
+ <string name="permdesc_uninstall_shortcut" msgid="959972195916090900">"Ivumela uhlelo lokusebenza ukukhipha izinqamuleli ngaphandle kokungenela komsebenzisi."</string>
+ <string name="permlab_read_settings" msgid="3452408290738106747">"funda izilungiselelo zaseKhaya nezinqamuleli"</string>
+ <string name="permdesc_read_settings" msgid="8377434937176025492">"Ivumela uhlelo lokusebenza ukufunda izilungiselelo nezinqamuleli Ekhaya."</string>
+ <string name="permlab_write_settings" msgid="1360567537236705628">"bhala izilungiselelo zaseKhaya nezinqamuleli"</string>
+ <string name="permdesc_write_settings" msgid="1098648778383349818">"Ivumela izinhlelo ukushintsha izilungiselelo nezinqamuleli Ekhaya."</string>
+ <string name="gadget_error_text" msgid="8359351016167075858">"Inkinga yokulayisha isinqunjwana"</string>
+ <string name="uninstall_system_app_text" msgid="7488523163288397451">"Lolu uhlelo lokusebenza lwesistimu futhi alikwazi ukukhishwa."</string>
+ <!-- no translation found for dream_name (2847171357608437154) -->
+ <skip />
+</resources>
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index 4f4425311..ee48aa7a0 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -104,11 +104,23 @@
<attr name="pageLayoutPaddingBottom" format="dimension" />
<attr name="pageLayoutPaddingLeft" format="dimension" />
<attr name="pageLayoutPaddingRight" format="dimension" />
- <attr name="pageLayoutMaxHeight" format="dimension" />
<!-- The space between adjacent pages of the PagedView. -->
<attr name="pageSpacing" format="dimension" />
</declare-styleable>
+ <!-- AppsCustomizePagedView specific attributes. These attributes are used to
+ customize an AppsCustomizePagedView in xml files. -->
+ <declare-styleable name="AppsCustomizePagedView">
+ <!-- Horizontal spacing between widgets and wallpapers -->
+ <attr name="widgetCellWidthGap" format="dimension" />
+ <!-- Vertical spacing between widgets -->
+ <attr name="widgetCellHeightGap" format="dimension" />
+ <!-- Number of widgets horizontally -->
+ <attr name="widgetCountX" format="integer" />
+ <!-- Number of widgets vertically -->
+ <attr name="widgetCountY" format="integer" />
+ </declare-styleable>
+
<!-- CustomizePagedView specific attributes. These attributes are used to customize
a CustomizePagedView view in XML files. -->
<declare-styleable name="CustomizePagedView">
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 6c372e356..fd7b21c35 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -18,10 +18,14 @@
*/
-->
<resources>
+ <!-- The color tints to apply to the text and drag view when hovering
+ over the delete target or the info target -->
+ <color name="delete_target_hover_tint">#D4FF3600</color>
+ <color name="info_target_hover_tint">#D40078FF</color>
+
<color name="window_background">#FF191919</color>
<color name="grid_dark_background">#EB191919</color>
<color name="bubble_dark_background">#20000000</color>
- <color name="delete_color_filter">#A5FF0000</color>
<color name="appwidget_error_color">#FCCC</color>
<color name="snag_callout_color">#F444</color>
@@ -29,7 +33,6 @@
<color name="gesture_color">#ff0563c1</color>
<color name="uncertain_gesture_color">#ff848484</color>
- <color name="app_info_filter">#A50000FE</color>
<color name="dimmed_view_color">#FF7F7F7F</color>
<color name="drag_outline_color">#6595f9</color>
diff --git a/res/values/config.xml b/res/values/config.xml
index c56a8cec2..70ee42361 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -1,9 +1,51 @@
<resources>
- <integer name="config_allAppsFadeInTime">700</integer>
- <integer name="config_allAppsFadeOutTime">700</integer>
+ <bool name="config_hardwareAccelerated">true</bool>
+<!-- AllApps/Customize/AppsCustomize -->
+ <!-- Fade in/out duration of icons being dragged from the trays -->
+ <integer name="config_dragAppsCustomizeIconFadeInDuration">150</integer>
+ <integer name="config_dragAppsCustomizeIconFadeOutDuration">200</integer>
+ <integer name="config_dragAppsCustomizeIconFadeAlpha">100</integer>
+ <integer name="config_workspaceUnshrinkTime">650</integer>
+ <!-- Out of 100, the percent to shrink the workspace during spring loaded mode. -->
+ <integer name="config_workspaceSpringLoadShrinkPercentage">80</integer>
+ <!-- When items are dropped on the mini screens in customize mode, we have a bounce animation
+ of the bright green hover outline, and then fade out the outline at the end. These are
+ the values used in that animation -->
+ <integer name="config_screenOnDropScalePercent">120</integer>
+ <integer name="config_screenOnDropScaleUpDuration">200</integer>
+ <integer name="config_screenOnDropScaleDownDuration">200</integer>
+ <integer name="config_screenOnDropAlphaFadeDelay">350</integer>
+ <integer name="config_screenOnDropAlphaFadeDuration">50</integer>
+
+ <!-- Fade/zoom in/out duration & scale in the AllApps transition.
+ Note: This should be less than the workspaceShrinkTime as they happen together. -->
+ <integer name="config_appsCustomizeZoomInTime">1000</integer>
+ <integer name="config_appsCustomizeZoomOutTime">1200</integer>
+ <integer name="config_appsCustomizeZoomScaleFactor">20</integer>
+ <integer name="config_appsCustomizeFadeInTime">250</integer>
+ <integer name="config_appsCustomizeFadeOutTime">500</integer>
+ <integer name="config_appsCustomizeWorkspaceShrinkTime">1000</integer>
+
+ <!-- Tab transition animation duration -->
+ <integer name="config_tabTransitionDuration">100</integer>
+
+ <!-- The slope, in percent, of the drag movement needed to drag an item out of
+ AppsCustomize (y / x * 100%) -->
+ <integer name="config_appsCustomizeDragSlopeThreshold">150</integer>
+
+ <!-- Fade in/out duration of toolbar/button bar icons.
+ Note: In + Out duration together should be less the duration of the transition
+ between AllApps, Customize & the Workspace. -->
+ <integer name="config_toolbarButtonFadeInTime">350</integer>
+ <integer name="config_toolbarButtonFadeOutTime">200</integer>
+
+ <!-- Batch loading for loading in LauncherModel -->
<integer name="config_allAppsBatchLoadDelay">0</integer>
<integer name="config_allAppsBatchSize">0</integer>
- <bool name="config_hardwareAccelerated">false</bool>
+
+<!-- Workspace -->
+ <!-- The transition duration for the background of the drop targets -->
+ <integer name="config_dropTargetBgTransitionDuration">100</integer>
<integer name="config_crosshairsFadeInTime">600</integer>
@@ -12,12 +54,6 @@
Should be an even number, for pixel alignment. -->
<integer name="config_dragViewExtraPixels">40</integer>
- <!-- When dragging items on the workspace, the number of pixels by which the position of
- the drag view should be offset from the position of the original view.
- Setting to 1/2 of config_dragViewExtraPixels keeps it centered on its old position. -->
- <integer name="config_dragViewOffsetX">20</integer>
- <integer name="config_dragViewOffsetY">20</integer>
-
<!-- The duration (in ms) of the fade animation on the object outlines, used when
we are dragging objects around on the home screen. -->
<integer name="config_dragOutlineFadeTime">900</integer>
@@ -30,6 +66,9 @@
<integer name="config_dropAnimMaxDuration">400</integer>
+ <!-- The duration of the UserFolder opening and closing animation -->
+ <integer name="config_folderAnimDuration">100</integer>
+
<!-- The distance at which the animation should take the max duration -->
<integer name="config_dropAnimMaxDist">800</integer>
@@ -39,7 +78,6 @@
<integer name="config_workspaceScreenBitmapCacheScale">20</integer>
<integer name="config_maxScaleForUsingWorkspaceScreenBitmapCache">50</integer>
- <style name="config_orientation">
- <item name="@android:screenOrientation">nosensor</item>
- </style>
+ <!-- When shrinking the workspace, this is the percentage of its original size. -->
+ <integer name="config_workspaceShrinkPercent">17</integer>
</resources>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index d6cd3eeb0..15dbc3ab6 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -15,8 +15,27 @@
-->
<resources>
+<!-- Workspace -->
+ <dimen name="qsb_bar_height">56dp</dimen>
+
+<!-- QSB -->
+ <dimen name="toolbar_button_vertical_padding">12dip</dimen>
+ <dimen name="toolbar_button_horizontal_padding">16dip</dimen>
+
+<!-- AllApps/Customize/AppsCustomize -->
+ <!-- Size of icons in Workspace/AppsCustomize -->
+ <dimen name="app_icon_size">50dp</dimen>
+ <dimen name="apps_customize_cell_width">68dp</dimen>
+ <dimen name="apps_customize_cell_height">68dp</dimen>
+ <!-- In portrat/normal, we peek only 1/8th the app cell width -->
+ <dimen name="apps_customize_peek_width">9dp</dimen>
+ <dimen name="apps_customize_widget_cell_width_gap">10dp</dimen>
+ <dimen name="apps_customize_widget_cell_height_gap">10dp</dimen>
<dimen name="title_texture_width">120px</dimen>
+ <!-- height of the tab bar in AppsCustomize -->
+ <dimen name="apps_customize_tab_bar_height">56dp</dimen>
+
<!-- height of the bottom row of controls -->
<dimen name="button_bar_height">56dip</dimen>
@@ -24,6 +43,24 @@
button_bar_height changes -->
<dimen name="button_bar_height_portrait">56dip</dimen>
+ <!-- extra horizontal spacing between mini screen thumbnails ie. in all
+ apps and in customization mode -->
+ <dimen name="smallScreenExtraSpacing">0dip</dimen>
+
+ <!-- Vertical spacing between edge of screen and mini cell layouts when they
+ are minimized to the bottom in all apps -->
+ <dimen name="allAppsSmallScreenVerticalMarginLandscape">30dip</dimen>
+ <dimen name="allAppsSmallScreenVerticalMarginPortrait">60dip</dimen>
+
+ <!-- height & width of the drop rectangle for the trash icon -->
+ <dimen name="delete_zone_size">70dip</dimen>
+
+ <!-- delete_zone_size_full - button_bar_height_portrait -->
+ <dimen name="delete_zone_padding">14dip</dimen>
+
+ <!-- padding between the delete zone drawable and text -->
+ <dimen name="delete_zone_drawable_padding">8dip</dimen>
+
<!-- roughly a status bar (for vertically centering the all apps
home icon in landscape) -->
<dimen name="status_bar_height">25dip</dimen>
@@ -32,16 +69,23 @@
button cluster in landscape) -->
<dimen name="half_status_bar_height">12dip</dimen>
- <!-- Size of icons in workspace -->
- <dimen name="app_icon_size">50dp</dimen>
-
- <!-- height & width of the drop rectangle for the trash icon -->
- <dimen name="delete_zone_size">70dip</dimen>
-
- <!-- delete_zone_size_full - button_bar_height_portrait -->
- <dimen name="delete_zone_padding">14dip</dimen>
-
+<!-- Dragging -->
<!-- the area at the edge of the screen that makes the workspace go left
or right while you're dragging. -->
<dimen name="scroll_zone">20dp</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">-8dp</dimen>
+
+ <!-- Width/height gap overrides for the workspace -->
+ <dimen name="workspace_width_gap">-1dp</dimen>
+ <dimen name="workspace_height_gap">-1dp</dimen>
+
+ <!-- Padding applied to AppWidgets -->
+ <dimen name="app_widget_padding_left">0dp</dimen>
+ <dimen name="app_widget_padding_right">0dp</dimen>
+ <dimen name="app_widget_padding_top">0dp</dimen>
+ <dimen name="app_widget_padding_bottom">0dp</dimen>
</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index eedbd6a9e..b3c6000b5 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -21,10 +21,17 @@
<!-- Manifest configuration. -->
<skip />
<!-- Do not translate. android:sharedUserId of this application. -->
- <string name="sharedUserId" translate="false"><xliff:g id="x"></xliff:g></string>
+ <string name="sharedUserId" translatable="false"><xliff:g id="x"></xliff:g></string>
<!-- Do not translate. android:process of this application. -->
- <string name="process" translate="false"><xliff:g id="x"></xliff:g></string>
+ <string name="process" translatable="false"><xliff:g id="x"></xliff:g></string>
+ <!-- Do not translate. We wish to prioritize the Wallpaper and Live Wallpaper pickers,
+ but because they are in a different package, we need to reference the component in
+ a non language-dependent way. If the Live Wallpaper picker component name changes
+ this will have to be updated as well. -->
+ <string name="live_wallpaper_picker_package_name" translatable="false">com.android.wallpaper.livepicker</string>
+ <string name="live_wallpaper_picker_class_name" translatable="false">com.android.wallpaper.livepicker.LiveWallpaperActivity</string>
+
<!-- General -->
<skip />
<!-- Application name -->
@@ -67,13 +74,17 @@
<!-- Tile of the tab for applications that were downloaded from market [CHAR_LIMIT=24] -->
<string name="all_apps_tab_downloaded">My apps</string>
+ <!-- AppsCustomize pane -->
+ <!-- Message to tell the user to long-press on a widget to add it [CHAR_LIMIT=50] -->
+ <string name="long_press_widget_to_add">Long-press to pick up a widget</string>
+
<!-- All Apps pane -->
<!-- Message to show when there are no games [CHAR_LIMIT=25] -->
<string name="all_apps_no_games">No games found.</string>
<!-- Message to show when there are no downloaded apps [CHAR_LIMIT=50] -->
<string name="all_apps_no_downloads">You have no downloaded applications.</string>
- <!-- Market button text [CHAR LIMIT=32] -->
- <string name="market">Shop</string>
+ <!-- Market button text. The market button has no text in the Phone UI. [CHAR LIMIT=32] -->
+ <string name="market"></string>
<!-- Customization Drawer -->
<!-- The format string for the dimensions of a widget in the drawer -->
@@ -151,6 +162,24 @@
device. [CHAR_LIMIT=30]-->
<string name="delete_zone_label_all_apps">Uninstall</string>
+ <!-- Label for delete drop target. [CHAR_LIMIT=30] -->
+ <string name="delete_target_label">Remove</string>
+ <!-- Label for uninstall drop target. [CHAR_LIMIT=30]-->
+ <string name="delete_target_uninstall_label">Uninstall</string>
+ <!-- Label for the info icon. [CHAR_LIMIT=30] -->
+ <string name="info_target_label">Manage</string>
+
+ <!-- Accessibility: Search button -->
+ <string name="accessibility_search_button">Search</string>
+ <!-- Accessibility: Voice Search button -->
+ <string name="accessibility_voice_search_button">Voice Search</string>
+ <!-- Accessibility: AllApps button -->
+ <string name="accessibility_all_apps_button">Applications</string>
+ <!-- Accessibility: Customize button -->
+ <string name="accessibility_customize_button">Customize</string>
+ <!-- Accessibility: Delete button -->
+ <string name="accessibility_delete_button">Remove</string>
+
<!-- Label for trash icon in All Apps, when an updated system app is selected. The update will
be uninstalled. [CHAR_LIMIT=30] -->
<string name="delete_zone_label_all_apps_system_app">Uninstall update</string>
@@ -226,4 +255,7 @@
<!-- Text to inform the user that they can't uninstall a system application -->
<string name="uninstall_system_app_text">This is a system application and cannot be uninstalled.</string>
+
+ <!-- Title of the Android Dreams (screensaver) module -->
+ <string name="dream_name">Rocket Launcher</string>
</resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 0c74a6a2e..5c458b408 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -35,17 +35,17 @@
</style>
<style name="WorkspaceIcon">
- <item name="android:textSize">13dip</item>
- <item name="android:singleLine">true</item>
- <item name="android:ellipsize">marquee</item>
- <item name="android:shadowColor">#B0000000</item>
- <item name="android:shadowRadius">2.0</item>
- <item name="android:textColor">#FFF</item>
- <item name="android:gravity">center_horizontal</item>
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">match_parent</item>
<item name="android:paddingLeft">5dip</item>
<item name="android:paddingRight">5dip</item>
+ <item name="android:gravity">center_horizontal</item>
+ <item name="android:singleLine">true</item>
+ <item name="android:ellipsize">marquee</item>
+ <item name="android:textSize">13dip</item>
+ <item name="android:textColor">#FFF</item>
+ <item name="android:shadowRadius">2.0</item>
+ <item name="android:shadowColor">#B0000000</item>
</style>
<style name="WorkspaceIcon.AllApps">
@@ -54,7 +54,7 @@
<style name="WorkspaceIcon.Portrait">
<item name="android:drawablePadding">5dip</item>
- <item name="android:paddingTop">4dip</item>
+ <item name="android:paddingTop">0dip</item>
<item name="android:layout_marginLeft">3dip</item>
<item name="android:layout_marginRight">3dip</item>
<item name="android:layout_marginTop">13dip</item>
@@ -68,33 +68,77 @@
<item name="android:layout_marginRight">10dip</item>
</style>
+ <style name="WidgetDivider">
+ <item name="android:visibility">gone</item>
+ </style>
+
+ <style name="SearchDropTargetBar">
+ <item name="android:orientation">horizontal</item>
+ </style>
+ <style name="SearchButton">
+ <item name="android:layout_gravity">center_vertical</item>
+ <item name="android:paddingTop">@dimen/toolbar_button_vertical_padding</item>
+ <item name="android:paddingBottom">@dimen/toolbar_button_vertical_padding</item>
+ <item name="android:paddingLeft">@dimen/toolbar_button_horizontal_padding</item>
+ <item name="android:paddingRight">@dimen/toolbar_button_horizontal_padding</item>
+ </style>
+ <style name="SearchButtonDivider">
+ <item name="android:layout_width">wrap_content</item>
+ <item name="android:layout_height">match_parent</item>
+ <item name="android:layout_gravity">center_vertical</item>
+ </style>
+ <style name="DropTargetButtonContainer">
+ <item name="android:layout_width">0dp</item>
+ <item name="android:layout_height">match_parent</item>
+ </style>
+ <style name="DropTargetButton">
+ <item name="android:layout_width">wrap_content</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:layout_gravity">center</item>
+ <item name="android:gravity">center_vertical</item>
+ <item name="android:drawablePadding">7.5dp</item>
+ <item name="android:textColor">#FFFFFFFF</item>
+ <item name="android:textSize">16sp</item>
+ </style>
+
<style name="TabIndicator">
<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:paddingLeft">40dp</item>
- <item name="android:paddingRight">40dp</item>
- <item name="android:paddingTop">15dp</item>
- <item name="android:paddingBottom">20dp</item>
- <item name="android:textColor">@color/tab_widget_indicator_color</item>
+ <item name="android:paddingLeft">15dp</item>
+ <item name="android:paddingRight">15dp</item>
+ <item name="android:paddingTop">10dp</item>
+ <item name="android:paddingBottom">15dp</item>
<item name="android:background">@drawable/tab_widget_indicator_selector</item>
- <item name="android:textSize">20sp</item>
+ <item name="android:textColor">@color/tab_widget_indicator_color</item>
+ <item name="android:textSize">16sp</item>
<item name="android:shadowColor">#393939</item>
<item name="android:shadowDx">0.0</item>
<item name="android:shadowDy">1.0</item>
<item name="android:shadowRadius">1.0</item>
</style>
- <style name="TabIndicator.Portrait">
- <item name="android:paddingLeft">20dp</item>
- <item name="android:paddingRight">20dp</item>
+ <style name="MarketButton">
+ <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>
+ <item name="android:shadowDx">0.0</item>
+ <item name="android:shadowDy">0.0</item>
+ <item name="android:shadowRadius">2.0</item>
</style>
- <style name="SearchButton" parent="@android:style/Widget.Button.Small">
- <item name="android:paddingTop">7dip</item>
- <item name="android:paddingBottom">9dip</item>
- <item name="android:paddingLeft">10dip</item>
- <item name="android:paddingRight">10dip</item>
+ <style name="DeleteZone">
+ <item name="android:drawableLeft">@drawable/delete_zone_selector</item>
+ <item name="android:drawablePadding">@dimen/delete_zone_drawable_padding</item>
+ <item name="android:paddingRight">20dp</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>
+ <item name="android:shadowDx">0.0</item>
+ <item name="android:shadowDy">0.0</item>
+ <item name="android:shadowRadius">2.0</item>
</style>
<style name="HotseatButton">
@@ -116,4 +160,7 @@
<item name="android:background">@drawable/hotseat_bg_right</item>
</style>
+ <style name="config_orientation">
+ <item name="@android:screenOrientation">nosensor</item>
+ </style>
</resources>
diff --git a/res/xml/default_workspace.xml b/res/xml/default_workspace.xml
index 0519a489a..0d4212cfa 100644
--- a/res/xml/default_workspace.xml
+++ b/res/xml/default_workspace.xml
@@ -28,10 +28,6 @@
launcher:spanY="1" />
<!-- Middle screen [2] -->
- <search
- launcher:screen="2"
- launcher:x="0"
- launcher:y="0" />
<!-- Right screen [3] -->
<appwidget
diff --git a/src/com/android/launcher2/AccessibleTabView.java b/src/com/android/launcher2/AccessibleTabView.java
new file mode 100644
index 000000000..101f139e7
--- /dev/null
+++ b/src/com/android/launcher2/AccessibleTabView.java
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+
+package com.android.launcher2;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.KeyEvent;
+import android.widget.TextView;
+
+/**
+ * We use a custom tab view to process our own focus traversals.
+ */
+public class AccessibleTabView extends TextView {
+ public AccessibleTabView(Context context) {
+ super(context);
+ }
+
+ public AccessibleTabView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public AccessibleTabView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ return FocusHelper.handleTabKeyEvent(this, keyCode, event)
+ || super.onKeyDown(keyCode, event);
+ }
+
+ @Override
+ public boolean onKeyUp(int keyCode, KeyEvent event) {
+ return FocusHelper.handleTabKeyEvent(this, keyCode, event)
+ || super.onKeyUp(keyCode, event);
+ }
+}
diff --git a/src/com/android/launcher2/AddAdapter.java b/src/com/android/launcher2/AddAdapter.java
index 24c31ffcd..d1076b16b 100644
--- a/src/com/android/launcher2/AddAdapter.java
+++ b/src/com/android/launcher2/AddAdapter.java
@@ -40,7 +40,7 @@ public class AddAdapter extends BaseAdapter {
public static final int ITEM_SHORTCUT = 0;
public static final int ITEM_APPWIDGET = 1;
- public static final int ITEM_LIVE_FOLDER = 2;
+ public static final int ITEM_APPLICATION = 2;
public static final int ITEM_WALLPAPER = 3;
/**
@@ -70,15 +70,12 @@ public class AddAdapter extends BaseAdapter {
// Create default actions
Resources res = launcher.getResources();
- mItems.add(new ListItem(res, R.string.group_shortcuts,
- R.drawable.ic_launcher_shortcut, ITEM_SHORTCUT));
+ mItems.add(new ListItem(res, R.string.group_applications,
+ R.drawable.ic_launcher_application, ITEM_APPLICATION));
mItems.add(new ListItem(res, R.string.group_widgets,
R.drawable.ic_launcher_appwidget, ITEM_APPWIDGET));
- mItems.add(new ListItem(res, R.string.group_live_folders,
- R.drawable.ic_launcher_folder, ITEM_LIVE_FOLDER));
-
mItems.add(new ListItem(res, R.string.group_wallpapers,
R.drawable.ic_launcher_wallpaper, ITEM_WALLPAPER));
diff --git a/src/com/android/launcher2/AllApps2D.java b/src/com/android/launcher2/AllApps2D.java
index 1cbb99994..4547f54b3 100644
--- a/src/com/android/launcher2/AllApps2D.java
+++ b/src/com/android/launcher2/AllApps2D.java
@@ -16,8 +16,6 @@
package com.android.launcher2;
-import com.android.launcher.R;
-
import android.content.ComponentName;
import android.content.Context;
import android.content.res.Resources;
@@ -37,6 +35,9 @@ import android.widget.ImageButton;
import android.widget.RelativeLayout;
import android.widget.TextView;
+import com.android.launcher.R;
+import com.android.launcher2.DropTarget.DragObject;
+
import java.util.ArrayList;
import java.util.Collections;
@@ -143,7 +144,7 @@ public class AllApps2D
homeButton.setOnClickListener(
new View.OnClickListener() {
public void onClick(View v) {
- mLauncher.closeAllApps(true);
+ mLauncher.showWorkspace(true);
}
});
}
@@ -158,8 +159,10 @@ public class AllApps2D
this(context, attrs);
}
- public void setLauncher(Launcher launcher) {
+ @Override
+ public void setup(Launcher launcher, DragController dragController) {
mLauncher = launcher;
+ mDragController = dragController;
}
public boolean onKey(View v, int keyCode, KeyEvent event) {
@@ -167,7 +170,7 @@ public class AllApps2D
switch (keyCode) {
case KeyEvent.KEYCODE_BACK:
- mLauncher.closeAllApps(true);
+ mLauncher.showWorkspace(true);
break;
default:
return false;
@@ -190,7 +193,7 @@ public class AllApps2D
app = new ApplicationInfo(app);
mDragController.startDrag(view, this, app, DragController.DRAG_ACTION_COPY);
- mLauncher.closeAllApps(true);
+ mLauncher.showWorkspace(true);
return true;
}
@@ -202,16 +205,11 @@ public class AllApps2D
}
@Override
- public void setDragController(DragController dragger) {
- mDragController = dragger;
- }
-
- @Override
public void onDragViewVisible() {
}
@Override
- public void onDropCompleted(View target, Object dragInfo, boolean success) {
+ public void onDropCompleted(View target, DragObject d, boolean success) {
}
/**
@@ -341,6 +339,10 @@ public class AllApps2D
public void surrender() {
}
+
+ public void reset() {
+ // Do nothing
+ }
}
diff --git a/src/com/android/launcher2/AllApps3D.java b/src/com/android/launcher2/AllApps3D.java
index 29f49afc2..837ddbbab 100644
--- a/src/com/android/launcher2/AllApps3D.java
+++ b/src/com/android/launcher2/AllApps3D.java
@@ -16,12 +16,6 @@
package com.android.launcher2;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-
-import com.android.launcher.R;
-
import android.content.ComponentName;
import android.content.Context;
import android.content.res.Resources;
@@ -29,9 +23,20 @@ import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.PixelFormat;
import android.graphics.Rect;
-import android.renderscript.*;
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.Matrix4f;
+import android.renderscript.Mesh;
+import android.renderscript.ProgramFragment;
+import android.renderscript.ProgramFragmentFixedFunction;
+import android.renderscript.ProgramStore;
+import android.renderscript.ProgramVertex;
+import android.renderscript.ProgramVertexFixedFunction;
+import android.renderscript.RSSurfaceView;
+import android.renderscript.RenderScript;
+import android.renderscript.RenderScriptGL;
+import android.renderscript.Sampler;
import android.util.AttributeSet;
-import android.util.DisplayMetrics;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
@@ -42,6 +47,13 @@ import android.view.View;
import android.view.ViewConfiguration;
import android.view.accessibility.AccessibilityEvent;
+import com.android.launcher.R;
+import com.android.launcher2.DropTarget.DragObject;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+
public class AllApps3D extends RSSurfaceView
implements AllAppsView, View.OnClickListener, View.OnLongClickListener, DragSource {
private static final String TAG = "Launcher.AllApps3D";
@@ -155,13 +167,6 @@ public class AllApps3D extends RSSurfaceView
setRenderScriptGL(sRS);
}
- final DisplayMetrics metrics = getResources().getDisplayMetrics();
- final boolean isPortrait = metrics.widthPixels < metrics.heightPixels;
- mColumnsPerPage = isPortrait ? Defines.COLUMNS_PER_PAGE_PORTRAIT :
- Defines.COLUMNS_PER_PAGE_LANDSCAPE;
- mRowsPerPage = isPortrait ? Defines.ROWS_PER_PAGE_PORTRAIT :
- Defines.ROWS_PER_PAGE_LANDSCAPE;
-
if (sRollo != null) {
sRollo.mAllApps = this;
sRollo.mRes = getResources();
@@ -208,8 +213,10 @@ public class AllApps3D extends RSSurfaceView
setSoundEffectsEnabled(old);
}
- public void setLauncher(Launcher launcher) {
+ @Override
+ public void setup(Launcher launcher, DragController dragController) {
mLauncher = launcher;
+ mDragController = dragController;
}
@Override
@@ -231,6 +238,12 @@ public class AllApps3D extends RSSurfaceView
super.surfaceChanged(holder, format, w, h);
+ final boolean isPortrait = w < h;
+ mColumnsPerPage = isPortrait ? Defines.COLUMNS_PER_PAGE_PORTRAIT :
+ Defines.COLUMNS_PER_PAGE_LANDSCAPE;
+ mRowsPerPage = isPortrait ? Defines.ROWS_PER_PAGE_PORTRAIT :
+ Defines.ROWS_PER_PAGE_LANDSCAPE;
+
if (mSurrendered) return;
mHaveSurface = true;
@@ -350,7 +363,7 @@ public class AllApps3D extends RSSurfaceView
if (mArrowNavigation) {
if (mLastSelection == SELECTION_HOME) {
reallyPlaySoundEffect(SoundEffectConstants.CLICK);
- mLauncher.closeAllApps(true);
+ mLauncher.showWorkspace(true);
} else {
int whichApp = sRollo.mScript.get_gSelectedIconIndex();
if (whichApp >= 0) {
@@ -637,7 +650,7 @@ public class AllApps3D extends RSSurfaceView
if ((isPortrait && y > mTouchYBorders[mTouchYBorders.length-1]) ||
(!isPortrait && x > mTouchXBorders[mTouchXBorders.length-1])) {
reallyPlaySoundEffect(SoundEffectConstants.CLICK);
- mLauncher.closeAllApps(true);
+ mLauncher.showWorkspace(true);
}
sRollo.setHomeSelected(SELECTED_NONE);
}
@@ -691,10 +704,12 @@ public class AllApps3D extends RSSurfaceView
int screenX = mMotionDownRawX - (bmp.getWidth() / 2);
int screenY = mMotionDownRawY - bmp.getHeight();
+ mLauncher.lockScreenOrientation();
+ mLauncher.getWorkspace().onDragStartedWithItemSpans(1, 1, bmp);
mDragController.startDrag(
bmp, screenX, screenY, this, app, DragController.DRAG_ACTION_COPY);
- mLauncher.closeAllApps(true);
+ mLauncher.showWorkspace(true);
}
return true;
}
@@ -737,16 +752,13 @@ public class AllApps3D extends RSSurfaceView
}
@Override
- public void setDragController(DragController dragger) {
- mDragController = dragger;
- }
-
- @Override
public void onDragViewVisible() {
}
@Override
- public void onDropCompleted(View target, Object dragInfo, boolean success) {
+ public void onDropCompleted(View target, DragObject d, boolean success) {
+ mLauncher.getWorkspace().onDragStopped(success);
+ mLauncher.unlockScreenOrientation();
}
/**
@@ -1045,13 +1057,16 @@ public class AllApps3D extends RSSurfaceView
i.ScaleOffset.x = (2.f / 480.f);
i.ScaleOffset.y = 0;
i.ScaleOffset.z = -((float)w / 2) - 0.25f;
- i.ScaleOffset.w = -380.25f;
- i.BendPos.x = 120.f;
- i.BendPos.y = 680.f;
- if (w > h) {
- i.ScaleOffset.z = 40.f;
- i.ScaleOffset.w = h - 40.f;
- i.BendPos.y = 1.f;
+ if (w < h) {
+ // portrait
+ i.ScaleOffset.w = -380.25f;
+ i.BendPos.x = 120.f; // bottom of screen
+ i.BendPos.y = h - 82.f; // top of screen
+ } else {
+ // landscape
+ i.ScaleOffset.w = -206.25f;
+ i.BendPos.x = 50.f;
+ i.BendPos.y = h - 30.f;
}
mUniformAlloc.set(i, 0, true);
}
@@ -1091,7 +1106,7 @@ public class AllApps3D extends RSSurfaceView
" float aDy = cos(bendAngle);\n" +
" float aDz = sin(bendAngle);\n" +
- " float scale = (2.0 / 480.0);\n" +
+ " float scale = (2.0 / " + mWidth + ".0);\n" +
" float x = UNI_Position.x + UNI_ImgSize.x * (1.0 - ani) * (ATTRIB_position.x - 0.5);\n" +
" float ys= UNI_Position.y + UNI_ImgSize.y * (1.0 - ani) * ATTRIB_position.y;\n" +
" float y = 0.0;\n" +
@@ -1466,4 +1481,8 @@ public class AllApps3D extends RSSurfaceView
sRS.contextDump();
}
}
+
+ public void reset() {
+ // Do nothing
+ }
}
diff --git a/src/com/android/launcher2/AllAppsBackground.java b/src/com/android/launcher2/AllAppsBackground.java
index 5292d0ad3..51e1ee472 100644
--- a/src/com/android/launcher2/AllAppsBackground.java
+++ b/src/com/android/launcher2/AllAppsBackground.java
@@ -25,8 +25,8 @@ import android.util.AttributeSet;
import android.view.View;
/**
- * An implementation of PagedView that populates the pages of the workspace
- * with all of the user's applications.
+ * The background for AllApps which moves independently of the AllApps tray (for example, when we
+ * transition between AllApps and the Workspace while in spring-loaded mode).
*/
public class AllAppsBackground extends View {
private Drawable mBackground;
diff --git a/src/com/android/launcher2/AllAppsPagedView.java b/src/com/android/launcher2/AllAppsPagedView.java
index b4c4f3e78..5c8812df3 100644
--- a/src/com/android/launcher2/AllAppsPagedView.java
+++ b/src/com/android/launcher2/AllAppsPagedView.java
@@ -16,14 +16,13 @@
package com.android.launcher2;
-import com.android.launcher.R;
-
import android.content.ComponentName;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
+import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.LayoutInflater;
@@ -32,6 +31,8 @@ import android.view.animation.AnimationUtils;
import android.widget.Checkable;
import android.widget.TextView;
+import com.android.launcher.R;
+
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
@@ -66,11 +67,11 @@ public class AllAppsPagedView extends PagedViewWithDraggableItems implements All
private boolean mAllowHardwareLayerCreation;
private int mPageContentWidth;
+ private boolean mHasMadeSuccessfulDrop;
private int mLastMeasureWidth = -1;
private int mLastMeasureHeight = -1;
private boolean mWaitingToInitPages = true;
- private boolean mWaitingToDetermineRowsAndColumns = true;
private int mMaxCellCountY;
@@ -93,12 +94,7 @@ public class AllAppsPagedView extends PagedViewWithDraggableItems implements All
final Resources r = context.getResources();
setDragSlopeThreshold(
- r.getInteger(R.integer.config_allAppsDrawerDragSlopeThreshold) / 100.0f);
-
- // Create a dummy page and set it up to find out the content width (used by our parent)
- PagedViewCellLayout layout = new PagedViewCellLayout(getContext());
- setupPage(layout);
- mPageContentWidth = layout.getContentWidth();
+ r.getInteger(R.integer.config_appsCustomizeDragSlopeThreshold) / 100.0f);
mMaxCellCountY = r.getInteger(R.integer.all_apps_view_maxCellCountY);
}
@@ -130,8 +126,8 @@ public class AllAppsPagedView extends PagedViewWithDraggableItems implements All
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- if (mWaitingToDetermineRowsAndColumns) {
- mWaitingToDetermineRowsAndColumns = false;
+ if (mWaitingToInitPages) {
+ mWaitingToInitPages = false;
postInvalidatePageData(false);
}
super.onLayout(changed, left, top, right, bottom);
@@ -176,7 +172,7 @@ public class AllAppsPagedView extends PagedViewWithDraggableItems implements All
availableHeight -= mPageLayoutPaddingTop + mPageLayoutPaddingBottom;
availableHeight -= cellHeight; // Assume at least one row
Resources r = getContext().getResources();
- float scaleFactor = r.getInteger(R.integer.config_allAppsZoomScaleFactor) / 100f;
+ float scaleFactor = r.getInteger(R.integer.config_appsCustomizeZoomScaleFactor) / 100f;
availableHeight -= screenHeight * scaleFactor;
if (availableHeight > 0) {
return Math.min(mMaxCellCountY,
@@ -210,14 +206,9 @@ public class AllAppsPagedView extends PagedViewWithDraggableItems implements All
}
@Override
- public void setLauncher(Launcher launcher) {
+ public void setup(Launcher launcher, DragController dragController) {
mLauncher = launcher;
- mLauncher.setAllAppsPagedView(this);
- }
-
- @Override
- public void setDragController(DragController dragger) {
- mDragController = dragger;
+ mDragController = dragController;
}
public void setAppFilter(int filterType) {
@@ -229,6 +220,10 @@ public class AllAppsPagedView extends PagedViewWithDraggableItems implements All
}
}
+ void resetSuccessfulDropFlag() {
+ mHasMadeSuccessfulDrop = false;
+ }
+
@Override
public void zoom(float zoom, boolean animate) {
mZoom = zoom;
@@ -376,6 +371,16 @@ public class AllAppsPagedView extends PagedViewWithDraggableItems implements All
c.translate((v.getWidth() - icon.getIntrinsicWidth()) / 2, v.getPaddingTop());
icon.draw(c);
+ Rect dragRect = null;
+ if (v instanceof TextView) {
+ int iconSize = getResources().getDimensionPixelSize(R.dimen.app_icon_size);
+ int top = v.getPaddingTop();
+ int left = (b.getWidth() - iconSize) / 2;
+ int right = left + iconSize;
+ int bottom = top + iconSize;
+ dragRect = new Rect(left, top, right, bottom);
+ }
+
// We toggle the checked state _after_ we create the view for the drag in case toggling the
// checked state changes the view's look
if (v instanceof Checkable) {
@@ -395,7 +400,7 @@ public class AllAppsPagedView extends PagedViewWithDraggableItems implements All
// Start the drag
mLauncher.lockScreenOrientation();
mLauncher.getWorkspace().onDragStartedWithItemSpans(1, 1, b);
- mDragController.startDrag(v, b, this, app, DragController.DRAG_ACTION_COPY, null);
+ mDragController.startDrag(v, b, this, app, DragController.DRAG_ACTION_COPY, dragRect);
b.recycle();
return true;
}
@@ -405,7 +410,7 @@ public class AllAppsPagedView extends PagedViewWithDraggableItems implements All
}
@Override
- public void onDropCompleted(View target, Object dragInfo, boolean success) {
+ public void onDropCompleted(View target, DragObject d, boolean success) {
// close the choice action mode if we have a proper drop
if (target != this) {
endChoiceMode();
@@ -413,6 +418,12 @@ public class AllAppsPagedView extends PagedViewWithDraggableItems implements All
tearDownDragMode();
mLauncher.getWorkspace().onDragStopped(success);
mLauncher.unlockScreenOrientation();
+
+ if (!success && !mHasMadeSuccessfulDrop) {
+ mLauncher.getWorkspace().shrink(Workspace.ShrinkState.BOTTOM_HIDDEN);
+ } else {
+ mHasMadeSuccessfulDrop |= success;
+ }
}
int getPageContentWidth() {
@@ -452,7 +463,6 @@ public class AllAppsPagedView extends PagedViewWithDraggableItems implements All
Collections.sort(mApps, LauncherModel.APP_NAME_COMPARATOR);
mFilteredApps = rebuildFilteredApps(mApps);
mPageViewIconCache.retainAllApps(list);
- mWaitingToInitPages = false;
invalidatePageData();
}
@@ -542,6 +552,11 @@ public class AllAppsPagedView extends PagedViewWithDraggableItems implements All
// do nothing?
}
+ public void reset() {
+ setCurrentPage(0);
+ invalidatePageData();
+ }
+
private void setupPage(PagedViewCellLayout layout) {
layout.setCellCount(mCellCountX, mCellCountY);
layout.setPadding(mPageLayoutPaddingLeft, mPageLayoutPaddingTop, mPageLayoutPaddingRight,
@@ -551,8 +566,7 @@ public class AllAppsPagedView extends PagedViewWithDraggableItems implements All
@Override
protected void invalidatePageData() {
- if (mWaitingToDetermineRowsAndColumns ||
- mWaitingToInitPages || mCellCountX <= 0 || mCellCountY <= 0) {
+ if (mWaitingToInitPages || mCellCountX <= 0 || mCellCountY <= 0) {
// We don't know our size yet, which means we haven't calculated cell count x/y;
// onMeasure will call us once we figure out our size
return;
@@ -588,6 +602,7 @@ public class AllAppsPagedView extends PagedViewWithDraggableItems implements All
@Override
public void syncPageItems(int page) {
// Ensure that we have the right number of items on the pages
+ final int numPages = getPageCount();
final int cellsPerPage = mCellCountX * mCellCountY;
final int startIndex = page * cellsPerPage;
final int endIndex = Math.min(startIndex + cellsPerPage, mFilteredApps.size());
@@ -596,6 +611,7 @@ public class AllAppsPagedView extends PagedViewWithDraggableItems implements All
if (!mFilteredApps.isEmpty()) {
int curNumPageItems = layout.getPageChildCount();
int numPageItems = endIndex - startIndex;
+ boolean createHolographicOutlines = (numPages > 1);
// If we were previously an empty page, then restart anew
boolean wasEmptyPage = false;
@@ -631,12 +647,12 @@ public class AllAppsPagedView extends PagedViewWithDraggableItems implements All
}
// Actually reapply to the existing text views
- final int numPages = getPageCount();
for (int i = startIndex; i < endIndex; ++i) {
final int index = i - startIndex;
final ApplicationInfo info = mFilteredApps.get(i);
PagedViewIcon icon = (PagedViewIcon) layout.getChildOnPageAt(index);
- icon.applyFromApplicationInfo(info, mPageViewIconCache, true, (numPages > 1));
+ icon.applyFromApplicationInfo(
+ info, mPageViewIconCache, true, createHolographicOutlines);
PagedViewCellLayout.LayoutParams params =
(PagedViewCellLayout.LayoutParams) icon.getLayoutParams();
@@ -644,6 +660,9 @@ public class AllAppsPagedView extends PagedViewWithDraggableItems implements All
params.cellY = index / mCellCountX;
}
+ // We should try and sync all the holographic icons after adding/removing new items
+ layout.reloadHolographicIcons(createHolographicOutlines);
+
// Default to left-aligned icons
layout.enableCenteredContent(false);
} else {
@@ -658,6 +677,7 @@ public class AllAppsPagedView extends PagedViewWithDraggableItems implements All
}
// Center-align the message
+ final boolean createHolographicOutlines = (numPages > 1);
layout.enableCenteredContent(true);
layout.removeAllViewsOnPage();
layout.addViewToCellLayout(icon, -1, 0,
@@ -670,28 +690,16 @@ public class AllAppsPagedView extends PagedViewWithDraggableItems implements All
* We don't actually use AllAppsPagedView as a drop target... it's only used to intercept a drop
* to the workspace.
*/
- @Override
- public boolean acceptDrop(DragSource source, int x, int y, int xOffset, int yOffset,
- DragView dragView, Object dragInfo) {
+ public boolean acceptDrop(DragObject d) {
return false;
}
- @Override
- public DropTarget getDropTargetDelegate(DragSource source, int x, int y, int xOffset,
- int yOffset, DragView dragView, Object dragInfo) {
+ public DropTarget getDropTargetDelegate(DragObject d) {
return null;
}
- @Override
- public void onDragEnter(DragSource source, int x, int y, int xOffset, int yOffset,
- DragView dragView, Object dragInfo) {}
- @Override
- public void onDragExit(DragSource source, int x, int y, int xOffset, int yOffset,
- DragView dragView, Object dragInfo) {}
- @Override
- public void onDragOver(DragSource source, int x, int y, int xOffset, int yOffset,
- DragView dragView, Object dragInfo) {}
- @Override
- public void onDrop(DragSource source, int x, int y, int xOffset, int yOffset,
- DragView dragView, Object dragInfo) {}
+ public void onDragEnter(DragObject d) {}
+ public void onDragExit(DragObject d) {}
+ public void onDragOver(DragObject d) {}
+ public void onDrop(DragObject d) {}
public boolean isDropEnabled() {
return true;
diff --git a/src/com/android/launcher2/AllAppsTabbed.java b/src/com/android/launcher2/AllAppsTabbed.java
index 27e78d831..b765e1778 100644
--- a/src/com/android/launcher2/AllAppsTabbed.java
+++ b/src/com/android/launcher2/AllAppsTabbed.java
@@ -29,6 +29,7 @@ import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
+import android.view.ViewGroup;
import android.widget.TabHost;
import android.widget.TabWidget;
import android.widget.TextView;
@@ -80,6 +81,7 @@ public class AllAppsTabbed extends TabHost implements AllAppsView, LauncherTrans
};
// Create the tabs and wire them up properly
+ AppsCustomizeTabKeyEventListener keyListener = new AppsCustomizeTabKeyEventListener();
TextView tabView;
TabWidget tabWidget = (TabWidget) findViewById(com.android.internal.R.id.tabs);
tabView = (TextView) mInflater.inflate(R.layout.tab_widget_indicator, tabWidget, false);
@@ -90,11 +92,17 @@ public class AllAppsTabbed extends TabHost implements AllAppsView, LauncherTrans
tabView.setText(mContext.getString(R.string.all_apps_tab_downloaded));
addTab(newTabSpec(TAG_DOWNLOADED).setIndicator(tabView).setContent(contentFactory));
+ // Setup the key listener to jump between the last tab view and the market icon
+ View lastTab = tabWidget.getChildTabViewAt(tabWidget.getTabCount() - 1);
+ lastTab.setOnKeyListener(keyListener);
+ View shopButton = findViewById(R.id.market_button);
+ shopButton.setOnKeyListener(keyListener);
+
setOnTabChangedListener(new OnTabChangeListener() {
public void onTabChanged(String tabId) {
// animate the changing of the tab content by fading pages in and out
final Resources res = getResources();
- final int duration = res.getInteger(R.integer.config_tabTransitionTime);
+ final int duration = res.getInteger(R.integer.config_tabTransitionDuration);
final float alpha = mAllApps.getAlpha();
ValueAnimator alphaAnim = ObjectAnimator.ofFloat(mAllApps, "alpha", alpha, 0.0f).
setDuration(duration);
@@ -124,14 +132,9 @@ public class AllAppsTabbed extends TabHost implements AllAppsView, LauncherTrans
}
@Override
- public void setLauncher(Launcher launcher) {
- mAllApps.setLauncher(launcher);
+ public void setup(Launcher launcher, DragController dragController) {
mLauncher = launcher;
- }
-
- @Override
- public void setDragController(DragController dragger) {
- mAllApps.setDragController(dragger);
+ mAllApps.setup(launcher, dragController);
}
@Override
@@ -261,6 +264,10 @@ public class AllAppsTabbed extends TabHost implements AllAppsView, LauncherTrans
mAllApps.surrender();
}
+ public void reset() {
+ mAllApps.reset();
+ }
+
@Override
public boolean onTouchEvent(MotionEvent ev) {
if (ev.getY() > mAllApps.getBottom()) {
@@ -268,4 +275,12 @@ public class AllAppsTabbed extends TabHost implements AllAppsView, LauncherTrans
}
return true;
}
+
+ @Override
+ public int getDescendantFocusability() {
+ if (getVisibility() != View.VISIBLE) {
+ return ViewGroup.FOCUS_BLOCK_DESCENDANTS;
+ }
+ return super.getDescendantFocusability();
+ }
}
diff --git a/src/com/android/launcher2/AllAppsView.java b/src/com/android/launcher2/AllAppsView.java
index 007ecf8d6..e8ca61fb3 100644
--- a/src/com/android/launcher2/AllAppsView.java
+++ b/src/com/android/launcher2/AllAppsView.java
@@ -23,9 +23,7 @@ public interface AllAppsView {
public void zoomed(float zoom);
}
- public void setLauncher(Launcher launcher);
-
- public void setDragController(DragController dragger);
+ public void setup(Launcher launcher, DragController dragController);
public void zoom(float zoom, boolean animate);
@@ -41,6 +39,9 @@ public interface AllAppsView {
public void updateApps(ArrayList<ApplicationInfo> list);
+ // Resets the AllApps page to the front
+ public void reset();
+
public void dumpState();
public void surrender();
diff --git a/src/com/android/launcher2/AppWidgetResizeFrame.java b/src/com/android/launcher2/AppWidgetResizeFrame.java
index 2b2662f42..eca5ad7c4 100644
--- a/src/com/android/launcher2/AppWidgetResizeFrame.java
+++ b/src/com/android/launcher2/AppWidgetResizeFrame.java
@@ -7,6 +7,7 @@ import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.appwidget.AppWidgetProviderInfo;
import android.content.Context;
+import android.content.res.Resources;
import android.view.Gravity;
import android.widget.FrameLayout;
import android.widget.ImageView;
@@ -18,6 +19,8 @@ public class AppWidgetResizeFrame extends FrameLayout {
private ItemInfo mItemInfo;
private LauncherAppWidgetHostView mWidgetView;
private CellLayout mCellLayout;
+ private DragLayer mDragLayer;
+ private Workspace mWorkspace;
private ImageView mLeftHandle;
private ImageView mRightHandle;
private ImageView mTopHandle;
@@ -28,6 +31,11 @@ public class AppWidgetResizeFrame extends FrameLayout {
private boolean mTopBorderActive;
private boolean mBottomBorderActive;
+ private int mWidgetPaddingLeft;
+ private int mWidgetPaddingRight;
+ private int mWidgetPaddingTop;
+ private int mWidgetPaddingBottom;
+
private int mBaselineWidth;
private int mBaselineHeight;
private int mBaselineX;
@@ -57,7 +65,7 @@ public class AppWidgetResizeFrame extends FrameLayout {
public static final int BOTTOM = 3;
public AppWidgetResizeFrame(Context context, ItemInfo itemInfo,
- LauncherAppWidgetHostView widgetView, CellLayout cellLayout) {
+ LauncherAppWidgetHostView widgetView, CellLayout cellLayout, DragLayer dragLayer) {
super(context);
mContext = context;
@@ -65,6 +73,8 @@ public class AppWidgetResizeFrame extends FrameLayout {
mCellLayout = cellLayout;
mWidgetView = widgetView;
mResizeMode = widgetView.getAppWidgetInfo().resizeMode;
+ mDragLayer = dragLayer;
+ mWorkspace = (Workspace) dragLayer.findViewById(R.id.workspace);
final AppWidgetProviderInfo info = widgetView.getAppWidgetInfo();
int[] result = mCellLayout.rectToCell(info.minWidth, info.minHeight, null);
@@ -99,6 +109,12 @@ public class AppWidgetResizeFrame extends FrameLayout {
Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM);
addView(mBottomHandle, lp);
+ Resources r = context.getResources();
+ mWidgetPaddingLeft = r.getDimensionPixelSize(R.dimen.app_widget_padding_left);
+ mWidgetPaddingTop = r.getDimensionPixelSize(R.dimen.app_widget_padding_top);
+ mWidgetPaddingRight = r.getDimensionPixelSize(R.dimen.app_widget_padding_right);
+ mWidgetPaddingBottom = r.getDimensionPixelSize(R.dimen.app_widget_padding_bottom);
+
if (mResizeMode == AppWidgetProviderInfo.RESIZE_HORIZONTAL) {
mTopHandle.setVisibility(GONE);
mBottomHandle.setVisibility(GONE);
@@ -150,7 +166,7 @@ public class AppWidgetResizeFrame extends FrameLayout {
mDeltaX = Math.max(-mBaselineX, deltaX);
mDeltaX = Math.min(mBaselineWidth - 2 * mTouchTargetWidth, mDeltaX);
} else if (mRightBorderActive) {
- mDeltaX = Math.min(mCellLayout.getWidth() - (mBaselineX + mBaselineWidth), deltaX);
+ mDeltaX = Math.min(mDragLayer.getWidth() - (mBaselineX + mBaselineWidth), deltaX);
mDeltaX = Math.max(-mBaselineWidth + 2 * mTouchTargetWidth, mDeltaX);
}
@@ -158,7 +174,7 @@ public class AppWidgetResizeFrame extends FrameLayout {
mDeltaY = Math.max(-mBaselineY, deltaY);
mDeltaY = Math.min(mBaselineHeight - 2 * mTouchTargetWidth, mDeltaY);
} else if (mBottomBorderActive) {
- mDeltaY = Math.min(mCellLayout.getHeight() - (mBaselineY + mBaselineHeight), deltaY);
+ mDeltaY = Math.min(mDragLayer.getHeight() - (mBaselineY + mBaselineHeight), deltaY);
mDeltaY = Math.max(-mBaselineHeight + 2 * mTouchTargetWidth, mDeltaY);
}
}
@@ -168,7 +184,8 @@ public class AppWidgetResizeFrame extends FrameLayout {
*/
public void visualizeResizeForDelta(int deltaX, int deltaY) {
updateDeltas(deltaX, deltaY);
- CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams();
+ DragLayer.LayoutParams lp = (DragLayer.LayoutParams) getLayoutParams();
+
if (mLeftBorderActive) {
lp.x = mBaselineX + mDeltaX;
lp.width = mBaselineWidth - mDeltaX;
@@ -261,6 +278,7 @@ public class AppWidgetResizeFrame extends FrameLayout {
// Update the cells occupied by this widget
mCellLayout.markCellsAsOccupiedForView(mWidgetView);
+ mWidgetView.requestLayout();
}
/**
@@ -284,20 +302,25 @@ public class AppWidgetResizeFrame extends FrameLayout {
}
public void snapToWidget(boolean animate) {
- final CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams();
+ final DragLayer.LayoutParams lp = (DragLayer.LayoutParams) getLayoutParams();
+ int xOffset = mCellLayout.getLeft() + mCellLayout.getLeftPadding() - mWorkspace.getScrollX();
+ int yOffset = mCellLayout.getTop() + mCellLayout.getTopPadding() - mWorkspace.getScrollY();
+
+ int newWidth = mWidgetView.getWidth() + 2 * mBackgroundPadding - mWidgetPaddingLeft -
+ mWidgetPaddingRight;
+ int newHeight = mWidgetView.getHeight() + 2 * mBackgroundPadding - mWidgetPaddingTop -
+ mWidgetPaddingBottom;
- int newWidth = mWidgetView.getWidth() + 2 * mBackgroundPadding;
- int newHeight = mWidgetView.getHeight() + 2 * mBackgroundPadding;
- int newX = mWidgetView.getLeft() - mBackgroundPadding;
- int newY = mWidgetView.getTop() - mBackgroundPadding;
+ int newX = mWidgetView.getLeft() - mBackgroundPadding + xOffset + mWidgetPaddingLeft;
+ int newY = mWidgetView.getTop() - mBackgroundPadding + yOffset + mWidgetPaddingTop;
// We need to make sure the frame stays within the bounds of the CellLayout
if (newY < 0) {
newHeight -= -newY;
newY = 0;
}
- if (newY + newHeight > mCellLayout.getHeight()) {
- newHeight -= newY + newHeight - mCellLayout.getHeight();
+ if (newY + newHeight > mDragLayer.getHeight()) {
+ newHeight -= newY + newHeight - mDragLayer.getHeight();
}
if (!animate) {
diff --git a/src/com/android/launcher2/ApplicationInfoDropTarget.java b/src/com/android/launcher2/ApplicationInfoDropTarget.java
index 78a9d2dcc..4a9727dd5 100644
--- a/src/com/android/launcher2/ApplicationInfoDropTarget.java
+++ b/src/com/android/launcher2/ApplicationInfoDropTarget.java
@@ -16,8 +16,6 @@
package com.android.launcher2;
-import com.android.launcher.R;
-
import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
@@ -29,6 +27,8 @@ import android.graphics.PorterDuffColorFilter;
import android.util.AttributeSet;
import android.view.View;
+import com.android.launcher.R;
+
/**
* Implements a DropTarget which allows applications to be dropped on it,
* in order to launch the application info for that app.
@@ -47,47 +47,42 @@ public class ApplicationInfoDropTarget extends IconDropTarget {
super(context, attrs, defStyle);
// Set the hover paint colour
- int colour = getContext().getResources().getColor(R.color.app_info_filter);
+ int colour = getContext().getResources().getColor(R.color.info_target_hover_tint);
mHoverPaint.setColorFilter(new PorterDuffColorFilter(colour, PorterDuff.Mode.SRC_ATOP));
- if (LauncherApplication.isScreenXLarge()) {
- // For the application info drop target, we just ignore the left padding since we don't want
- // to overlap with the delete zone padding
- int tb = getResources().getDimensionPixelSize(
- R.dimen.delete_zone_vertical_drag_padding);
- int lr = getResources().getDimensionPixelSize(
- R.dimen.delete_zone_horizontal_drag_padding);
- setDragPadding(tb, lr, tb, 0);
- }
+ // For the application info drop target, we just ignore the left padding since we don't want
+ // to overlap with the delete zone padding
+ int tb = getResources().getDimensionPixelSize(
+ R.dimen.delete_zone_vertical_drag_padding);
+ int lr = getResources().getDimensionPixelSize(
+ R.dimen.delete_zone_horizontal_drag_padding);
+ setDragPadding(tb, lr, tb, 0);
}
- public boolean acceptDrop(DragSource source, int x, int y, int xOffset, int yOffset,
- DragView dragView, Object dragInfo) {
+ public boolean acceptDrop(DragObject d) {
// acceptDrop is called just before onDrop. We do the work here, rather than
// in onDrop, because it allows us to reject the drop (by returning false)
// so that the object being dragged isn't removed from the home screen.
if (getVisibility() != VISIBLE) return false;
ComponentName componentName = null;
- if (dragInfo instanceof ApplicationInfo) {
- componentName = ((ApplicationInfo)dragInfo).componentName;
- } else if (dragInfo instanceof ShortcutInfo) {
- componentName = ((ShortcutInfo)dragInfo).intent.getComponent();
+ if (d.dragInfo instanceof ApplicationInfo) {
+ componentName = ((ApplicationInfo) d.dragInfo).componentName;
+ } else if (d.dragInfo instanceof ShortcutInfo) {
+ componentName = ((ShortcutInfo) d.dragInfo).intent.getComponent();
}
mLauncher.startApplicationDetailsActivity(componentName);
return false;
}
- public void onDragEnter(DragSource source, int x, int y, int xOffset, int yOffset,
- DragView dragView, Object dragInfo) {
+ public void onDragEnter(DragObject d) {
if (!mDragAndDropEnabled) return;
- dragView.setPaint(mHoverPaint);
+ d.dragView.setPaint(mHoverPaint);
}
- public void onDragExit(DragSource source, int x, int y, int xOffset, int yOffset,
- DragView dragView, Object dragInfo) {
+ public void onDragExit(DragObject d) {
if (!mDragAndDropEnabled) return;
- dragView.setPaint(null);
+ d.dragView.setPaint(null);
}
public void onDragStart(DragSource source, Object info, int dragAction) {
@@ -162,10 +157,13 @@ public class ApplicationInfoDropTarget extends IconDropTarget {
// Fade in the overlapping views
if (mOverlappingViews != null) {
for (View view : mOverlappingViews) {
- ObjectAnimator oa = ObjectAnimator.ofFloat(view, "alpha", 1.0f);
- oa.setDuration(sFadeInAnimationDuration);
- mFadeAnimator.play(oa);
- view.setVisibility(VISIBLE);
+ // Check whether the views are enabled first, before trying to fade them in
+ if (view.isEnabled()) {
+ ObjectAnimator oa = ObjectAnimator.ofFloat(view, "alpha", 1.0f);
+ oa.setDuration(sFadeInAnimationDuration);
+ mFadeAnimator.play(oa);
+ view.setVisibility(VISIBLE);
+ }
}
}
mFadeAnimator.start();
diff --git a/src/com/android/launcher2/AppsCustomizePagedView.java b/src/com/android/launcher2/AppsCustomizePagedView.java
new file mode 100644
index 000000000..5b4f15062
--- /dev/null
+++ b/src/com/android/launcher2/AppsCustomizePagedView.java
@@ -0,0 +1,884 @@
+/*
+ * 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.
+ */
+
+package com.android.launcher2;
+
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
+import android.appwidget.AppWidgetManager;
+import android.appwidget.AppWidgetProviderInfo;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.Config;
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.LruCache;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.animation.AccelerateInterpolator;
+import android.widget.ImageView;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.android.launcher.R;
+import com.android.launcher2.DropTarget.DragObject;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+public class AppsCustomizePagedView extends PagedViewWithDraggableItems implements
+ AllAppsView, View.OnClickListener, DragSource {
+ static final String LOG_TAG = "AppsCustomizePagedView";
+
+ /**
+ * The different content types that this paged view can show.
+ */
+ public enum ContentType {
+ Applications,
+ Widgets
+ }
+
+ // Refs
+ private Launcher mLauncher;
+ private DragController mDragController;
+ private final LayoutInflater mLayoutInflater;
+ private final PackageManager mPackageManager;
+
+ // Content
+ private ContentType mContentType;
+ private ArrayList<ApplicationInfo> mApps;
+ private List<Object> mWidgets;
+
+ // Caching
+ private Drawable mDefaultWidgetBackground;
+ private final int sWidgetPreviewCacheSize = 1 * 1024 * 1024; // 1 MiB
+ private LruCache<Object, Bitmap> mWidgetPreviewCache;
+ private IconCache mIconCache;
+
+ // Dimens
+ private int mContentWidth;
+ private int mMaxWidgetSpan, mMinWidgetSpan;
+ private int mWidgetWidthGap, mWidgetHeightGap;
+ private int mWidgetCountX, mWidgetCountY;
+ private final int mWidgetPreviewIconPaddedDimension;
+ private final float sWidgetPreviewIconPaddingPercentage = 0.25f;
+ private PagedViewCellLayout mWidgetSpacingLayout;
+
+ // Animations
+ private final float ANIMATION_SCALE = 0.5f;
+ private final int TRANSLATE_ANIM_DURATION = 400;
+ private final int DROP_ANIM_DURATION = 200;
+
+ public AppsCustomizePagedView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ mLayoutInflater = LayoutInflater.from(context);
+ mPackageManager = context.getPackageManager();
+ mContentType = ContentType.Applications;
+ mApps = new ArrayList<ApplicationInfo>();
+ mWidgets = new ArrayList<Object>();
+ mIconCache = ((LauncherApplication) context.getApplicationContext()).getIconCache();
+ mWidgetPreviewCache = new LruCache<Object, Bitmap>(sWidgetPreviewCacheSize) {
+ protected int sizeOf(Object key, Bitmap value) {
+ return value.getByteCount();
+ }
+ };
+
+ // Save the default widget preview background
+ Resources resources = context.getResources();
+ mDefaultWidgetBackground = resources.getDrawable(R.drawable.default_widget_preview);
+
+ TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PagedView, 0, 0);
+ // TODO-APPS_CUSTOMIZE: remove these unnecessary attrs after
+ mCellCountX = a.getInt(R.styleable.PagedView_cellCountX, 6);
+ mCellCountY = a.getInt(R.styleable.PagedView_cellCountY, 4);
+ a.recycle();
+ a = context.obtainStyledAttributes(attrs, R.styleable.AppsCustomizePagedView, 0, 0);
+ mWidgetWidthGap =
+ a.getDimensionPixelSize(R.styleable.AppsCustomizePagedView_widgetCellWidthGap, 0);
+ mWidgetHeightGap =
+ a.getDimensionPixelSize(R.styleable.AppsCustomizePagedView_widgetCellHeightGap, 0);
+ mWidgetCountX = a.getInt(R.styleable.AppsCustomizePagedView_widgetCountX, 2);
+ mWidgetCountY = a.getInt(R.styleable.AppsCustomizePagedView_widgetCountY, 2);
+ a.recycle();
+ mWidgetSpacingLayout = new PagedViewCellLayout(getContext());
+
+ // The max widget span is the length N, such that NxN is the largest bounds that the widget
+ // preview can be before applying the widget scaling
+ mMinWidgetSpan = 1;
+ mMaxWidgetSpan = 3;
+
+ // The padding on the non-matched dimension for the default widget preview icons
+ // (top + bottom)
+ int iconSize = resources.getDimensionPixelSize(R.dimen.app_icon_size);
+ mWidgetPreviewIconPaddedDimension =
+ (int) (iconSize * (1 + (2 * sWidgetPreviewIconPaddingPercentage)));
+ }
+
+ @Override
+ protected void init() {
+ super.init();
+ mCenterPagesVertically = false;
+
+ Context context = getContext();
+ Resources r = context.getResources();
+ setDragSlopeThreshold(r.getInteger(R.integer.config_appsCustomizeDragSlopeThreshold)/100f);
+ }
+
+ @Override
+ protected void onWallpaperTap(android.view.MotionEvent ev) {
+ mLauncher.showWorkspace(true);
+ }
+
+ /**
+ * This differs from isDataReady as this is the test done if isDataReady is not set.
+ */
+ private boolean testDataReady() {
+ return !mApps.isEmpty() && !mWidgets.isEmpty();
+ }
+
+ protected void onDataReady(int width, int height) {
+ // Note that we transpose the counts in portrait so that we get a similar layout
+ boolean isLandscape = getResources().getConfiguration().orientation ==
+ Configuration.ORIENTATION_LANDSCAPE;
+ int maxCellCountX = Integer.MAX_VALUE;
+ int maxCellCountY = Integer.MAX_VALUE;
+ if (LauncherApplication.isScreenLarge()) {
+ maxCellCountX = (isLandscape ? LauncherModel.getCellCountX() :
+ LauncherModel.getCellCountY());
+ maxCellCountY = (isLandscape ? LauncherModel.getCellCountY() :
+ LauncherModel.getCellCountX());
+ }
+
+ // Now that the data is ready, we can calculate the content width, the number of cells to
+ // use for each page
+ mWidgetSpacingLayout.setGap(mPageLayoutWidthGap, mPageLayoutHeightGap);
+ mWidgetSpacingLayout.setPadding(mPageLayoutPaddingLeft, mPageLayoutPaddingTop,
+ mPageLayoutPaddingRight, mPageLayoutPaddingBottom);
+ mWidgetSpacingLayout.calculateCellCount(width, height, maxCellCountX, maxCellCountY);
+ mCellCountX = mWidgetSpacingLayout.getCellCountX();
+ mCellCountY = mWidgetSpacingLayout.getCellCountY();
+ mWidgetCountX = Math.max(1, (int) Math.round(mCellCountX / 2f));
+ mWidgetCountY = Math.max(1, (int) Math.round(mCellCountY / 3f));
+ mContentWidth = mWidgetSpacingLayout.getContentWidth();
+
+ invalidatePageData();
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ int width = MeasureSpec.getSize(widthMeasureSpec);
+ int height = MeasureSpec.getSize(heightMeasureSpec);
+ if (!isDataReady()) {
+ if (testDataReady()) {
+ setDataIsReady();
+ setMeasuredDimension(width, height);
+ onDataReady(width, height);
+ }
+ }
+
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ }
+
+ /** Removes and returns the ResolveInfo with the specified ComponentName */
+ private ResolveInfo removeResolveInfoWithComponentName(List<ResolveInfo> list,
+ ComponentName cn) {
+ Iterator<ResolveInfo> iter = list.iterator();
+ while (iter.hasNext()) {
+ ResolveInfo rinfo = iter.next();
+ ActivityInfo info = rinfo.activityInfo;
+ ComponentName c = new ComponentName(info.packageName, info.name);
+ if (c.equals(cn)) {
+ iter.remove();
+ return rinfo;
+ }
+ }
+ return null;
+ }
+
+ public void onPackagesUpdated() {
+ // Get the list of widgets and shortcuts
+ mWidgets.clear();
+ List<AppWidgetProviderInfo> widgets =
+ AppWidgetManager.getInstance(mLauncher).getInstalledProviders();
+ Collections.sort(widgets,
+ new LauncherModel.WidgetAndShortcutNameComparator(mPackageManager));
+ Intent shortcutsIntent = new Intent(Intent.ACTION_CREATE_SHORTCUT);
+ List<ResolveInfo> shortcuts = mPackageManager.queryIntentActivities(shortcutsIntent, 0);
+ Collections.sort(shortcuts,
+ new LauncherModel.WidgetAndShortcutNameComparator(mPackageManager));
+ mWidgets.addAll(widgets);
+ mWidgets.addAll(shortcuts);
+
+ // The next layout pass will trigger data-ready if both widgets and apps are set, so request
+ // a layout to do this test and invalidate the page data when ready.
+ if (testDataReady()) requestLayout();
+ }
+
+ @Override
+ public void onClick(View v) {
+ if (v instanceof PagedViewIcon) {
+ // Animate some feedback to the click
+ final ApplicationInfo appInfo = (ApplicationInfo) v.getTag();
+ animateClickFeedback(v, new Runnable() {
+ @Override
+ public void run() {
+ mLauncher.startActivitySafely(appInfo.intent, appInfo);
+ }
+ });
+ } else if (v instanceof PagedViewWidget) {
+ // Let the user know that they have to long press to add a widget
+ Toast.makeText(getContext(), R.string.long_press_widget_to_add,
+ Toast.LENGTH_SHORT).show();
+
+ // Create a little animation to show that the widget can move
+ float offsetY = getResources().getDimensionPixelSize(R.dimen.dragViewOffsetY);
+ final ImageView p = (ImageView) v.findViewById(R.id.widget_preview);
+ AnimatorSet bounce = new AnimatorSet();
+ ValueAnimator tyuAnim = ObjectAnimator.ofFloat(p, "translationY", offsetY);
+ tyuAnim.setDuration(125);
+ ValueAnimator tydAnim = ObjectAnimator.ofFloat(p, "translationY", 0f);
+ tydAnim.setDuration(100);
+ bounce.play(tyuAnim).before(tydAnim);
+ bounce.setInterpolator(new AccelerateInterpolator());
+ bounce.start();
+ }
+ }
+
+ /*
+ * PagedViewWithDraggableItems implementation
+ */
+ @Override
+ protected void determineDraggingStart(android.view.MotionEvent ev) {
+ // Disable dragging by pulling an app down for now.
+ }
+ private void beginDraggingApplication(View v) {
+ // Make a copy of the ApplicationInfo
+ ApplicationInfo appInfo = new ApplicationInfo((ApplicationInfo) v.getTag());
+
+ // Compose the drag image (top compound drawable, index is 1)
+ final TextView tv = (TextView) v;
+ final Drawable icon = tv.getCompoundDrawables()[1];
+ Bitmap b = Bitmap.createBitmap(v.getWidth(), v.getHeight(),
+ Bitmap.Config.ARGB_8888);
+ Canvas c = new Canvas(b);
+ c.translate((v.getWidth() - icon.getIntrinsicWidth()) / 2, v.getPaddingTop());
+ icon.draw(c);
+
+ // Compose the visible rect of the drag image
+ Rect dragRect = null;
+ if (v instanceof TextView) {
+ int iconSize = getResources().getDimensionPixelSize(R.dimen.app_icon_size);
+ int top = v.getPaddingTop();
+ int left = (b.getWidth() - iconSize) / 2;
+ int right = left + iconSize;
+ int bottom = top + iconSize;
+ dragRect = new Rect(left, top, right, bottom);
+ }
+
+ // Start the drag
+ mLauncher.lockScreenOrientation();
+ mLauncher.getWorkspace().onDragStartedWithItemSpans(1, 1, b);
+ mDragController.startDrag(v, b, this, appInfo, DragController.DRAG_ACTION_COPY, dragRect);
+ b.recycle();
+ }
+ private void beginDraggingWidget(View v) {
+ // Get the widget preview as the drag representation
+ ImageView image = (ImageView) v.findViewById(R.id.widget_preview);
+ PendingAddItemInfo createItemInfo = (PendingAddItemInfo) v.getTag();
+
+ // Compose the drag image
+ Bitmap b;
+ Drawable preview = image.getDrawable();
+ int w = preview.getIntrinsicWidth();
+ int h = preview.getIntrinsicHeight();
+ if (createItemInfo instanceof PendingAddWidgetInfo) {
+ PendingAddWidgetInfo createWidgetInfo = (PendingAddWidgetInfo) createItemInfo;
+ int[] spanXY = CellLayout.rectToCell(getResources(),
+ createWidgetInfo.minWidth, createWidgetInfo.minHeight, null);
+ createItemInfo.spanX = spanXY[0];
+ createItemInfo.spanY = spanXY[1];
+
+ b = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
+ renderDrawableToBitmap(preview, b, 0, 0, w, h, 1, 1);
+ } else {
+ // Workaround for the fact that we don't keep the original ResolveInfo associated with
+ // the shortcut around. To get the icon, we just render the preview image (which has
+ // the shortcut icon) to a new drag bitmap that clips the non-icon space.
+ b = Bitmap.createBitmap(mWidgetPreviewIconPaddedDimension,
+ mWidgetPreviewIconPaddedDimension, Bitmap.Config.ARGB_8888);
+ Canvas c = new Canvas(b);
+ preview.draw(c);
+ createItemInfo.spanX = createItemInfo.spanY = 1;
+ }
+
+ // Start the drag
+ mLauncher.lockScreenOrientation();
+ mLauncher.getWorkspace().onDragStartedWithItemSpans(createItemInfo.spanX,
+ createItemInfo.spanY, b);
+ mDragController.startDrag(image, b, this, createItemInfo,
+ DragController.DRAG_ACTION_COPY, null);
+ b.recycle();
+ }
+ @Override
+ protected boolean beginDragging(View v) {
+ if (!super.beginDragging(v)) return false;
+
+
+ if (v instanceof PagedViewIcon) {
+ beginDraggingApplication(v);
+ } else if (v instanceof PagedViewWidget) {
+ beginDraggingWidget(v);
+ }
+
+ // Go into spring loaded mode
+ int currentPageIndex = mLauncher.getWorkspace().getCurrentPage();
+ CellLayout currentPage = (CellLayout) mLauncher.getWorkspace().getChildAt(currentPageIndex);
+ mLauncher.enterSpringLoadedDragMode(currentPage);
+ return true;
+ }
+ private void endDragging(boolean success) {
+ post(new Runnable() {
+ // Once the drag operation has fully completed, hence the post, we want to disable the
+ // deleteZone and the appInfoButton in all apps, and re-enable the instance which
+ // live in the workspace
+ public void run() {
+ // if onDestroy was called on Launcher, we might have already deleted the
+ // all apps delete zone / info button, so check if they are null
+ DeleteZone allAppsDeleteZone =
+ (DeleteZone) mLauncher.findViewById(R.id.all_apps_delete_zone);
+ ApplicationInfoDropTarget allAppsInfoButton =
+ (ApplicationInfoDropTarget) mLauncher.findViewById(R.id.all_apps_info_target);
+
+ if (allAppsDeleteZone != null) allAppsDeleteZone.setDragAndDropEnabled(false);
+ if (allAppsInfoButton != null) allAppsInfoButton.setDragAndDropEnabled(false);
+ }
+ });
+ mLauncher.exitSpringLoadedDragMode();
+ mLauncher.getWorkspace().onDragStopped(success);
+ mLauncher.unlockScreenOrientation();
+
+ }
+
+ /*
+ * DragSource implementation
+ */
+ @Override
+ public void onDragViewVisible() {}
+ @Override
+ public void onDropCompleted(View target, DragObject d, boolean success) {
+ endDragging(success);
+
+ // Display an error message if the drag failed due to there not being enough space on the
+ // target layout we were dropping on.
+ if (!success) {
+ boolean showOutOfSpaceMessage = false;
+ if (target instanceof Workspace) {
+ int currentScreen = mLauncher.getCurrentWorkspaceScreen();
+ Workspace workspace = (Workspace) target;
+ CellLayout layout = (CellLayout) workspace.getChildAt(currentScreen);
+ ItemInfo itemInfo = (ItemInfo) d.dragInfo;
+ if (layout != null) {
+ layout.calculateSpans(itemInfo);
+ showOutOfSpaceMessage =
+ !layout.findCellForSpan(null, itemInfo.spanX, itemInfo.spanY);
+ }
+ }
+ // TODO-APPS_CUSTOMIZE: We need to handle this for folders as well later.
+ if (showOutOfSpaceMessage) {
+ mLauncher.showOutOfSpaceMessage();
+ }
+ }
+ }
+
+ public void setContentType(ContentType type) {
+ mContentType = type;
+ setCurrentPage(0);
+ invalidatePageData();
+ }
+
+ /*
+ * Apps PagedView implementation
+ */
+ private void setVisibilityOnChildren(ViewGroup layout, int visibility) {
+ int childCount = layout.getChildCount();
+ for (int i = 0; i < childCount; ++i) {
+ layout.getChildAt(i).setVisibility(visibility);
+ }
+ }
+ private void setupPage(PagedViewCellLayout layout) {
+ layout.setCellCount(mCellCountX, mCellCountY);
+ layout.setGap(mPageLayoutWidthGap, mPageLayoutHeightGap);
+ layout.setPadding(mPageLayoutPaddingLeft, mPageLayoutPaddingTop,
+ mPageLayoutPaddingRight, mPageLayoutPaddingBottom);
+
+ // Note: We force a measure here to get around the fact that when we do layout calculations
+ // immediately after syncing, we don't have a proper width. That said, we already know the
+ // expected page width, so we can actually optimize by hiding all the TextView-based
+ // children that are expensive to measure, and let that happen naturally later.
+ setVisibilityOnChildren(layout, View.GONE);
+ int widthSpec = MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.AT_MOST);
+ int heightSpec = MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.AT_MOST);
+ layout.setMinimumWidth(getPageContentWidth());
+ layout.measure(widthSpec, heightSpec);
+ setVisibilityOnChildren(layout, View.VISIBLE);
+ }
+ public void syncAppsPages() {
+ // Ensure that we have the right number of pages
+ Context context = getContext();
+ int numPages = (int) Math.ceil((float) mApps.size() / (mCellCountX * mCellCountY));
+ for (int i = 0; i < numPages; ++i) {
+ PagedViewCellLayout layout = new PagedViewCellLayout(context);
+ setupPage(layout);
+ addView(layout);
+ }
+ }
+ public void syncAppsPageItems(int page) {
+ // ensure that we have the right number of items on the pages
+ int numPages = getPageCount();
+ int numCells = mCellCountX * mCellCountY;
+ int startIndex = page * numCells;
+ int endIndex = Math.min(startIndex + numCells, mApps.size());
+ PagedViewCellLayout layout = (PagedViewCellLayout) getChildAt(page);
+ layout.removeAllViewsOnPage();
+ for (int i = startIndex; i < endIndex; ++i) {
+ ApplicationInfo info = mApps.get(i);
+ PagedViewIcon icon = (PagedViewIcon) mLayoutInflater.inflate(
+ R.layout.apps_customize_application, layout, false);
+ icon.applyFromApplicationInfo(
+ info, mPageViewIconCache, true, (numPages > 1));
+ icon.setOnClickListener(this);
+ icon.setOnLongClickListener(this);
+ icon.setOnTouchListener(this);
+
+ int index = i - startIndex;
+ int x = index % mCellCountX;
+ int y = index / mCellCountX;
+ layout.addViewToCellLayout(icon, -1, i, new PagedViewCellLayout.LayoutParams(x,y, 1,1));
+ }
+
+ // Create the hardware layers
+ layout.allowHardwareLayerCreation();
+ layout.createHardwareLayers();
+ }
+ /*
+ * Widgets PagedView implementation
+ */
+ private void setupPage(PagedViewGridLayout layout) {
+ layout.setPadding(mPageLayoutPaddingLeft, mPageLayoutPaddingTop,
+ mPageLayoutPaddingRight, mPageLayoutPaddingBottom);
+
+ // Note: We force a measure here to get around the fact that when we do layout calculations
+ // immediately after syncing, we don't have a proper width. That said, we already know the
+ // expected page width, so we can actually optimize by hiding all the TextView-based
+ // children that are expensive to measure, and let that happen naturally later.
+ setVisibilityOnChildren(layout, View.GONE);
+ int widthSpec = MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.AT_MOST);
+ int heightSpec = MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.AT_MOST);
+ layout.setMinimumWidth(getPageContentWidth());
+ layout.measure(widthSpec, heightSpec);
+ setVisibilityOnChildren(layout, View.VISIBLE);
+ }
+ private void renderDrawableToBitmap(Drawable d, Bitmap bitmap, int x, int y, int w, int h,
+ float scaleX, float scaleY) {
+ Canvas c = new Canvas();
+ if (bitmap != null) c.setBitmap(bitmap);
+ c.save();
+ c.scale(scaleX, scaleY);
+ Rect oldBounds = d.copyBounds();
+ d.setBounds(x, y, x + w, y + h);
+ d.draw(c);
+ d.setBounds(oldBounds); // Restore the bounds
+ c.restore();
+ }
+ private FastBitmapDrawable getShortcutPreview(ResolveInfo info, int cellWidth, int cellHeight) {
+ // Return the cached version if necessary
+ Bitmap cachedBitmap = mWidgetPreviewCache.get(info);
+ if (cachedBitmap != null) {
+ return new FastBitmapDrawable(cachedBitmap);
+ }
+
+ Resources resources = mLauncher.getResources();
+ int iconSize = resources.getDimensionPixelSize(R.dimen.app_icon_size);
+ // We only need to make it wide enough so as not allow the preview to be scaled
+ int expectedWidth = cellWidth;
+ int expectedHeight = mWidgetPreviewIconPaddedDimension;
+
+ // Render the icon
+ Bitmap preview = Bitmap.createBitmap(expectedWidth, expectedHeight, Config.ARGB_8888);
+ Drawable icon = mIconCache.getFullResIcon(info, mPackageManager);
+ renderDrawableToBitmap(icon, preview, 0, 0, iconSize, iconSize, 1f, 1f);
+ FastBitmapDrawable iconDrawable = new FastBitmapDrawable(preview);
+ iconDrawable.setBounds(0, 0, expectedWidth, expectedHeight);
+ mWidgetPreviewCache.put(info, preview);
+ return iconDrawable;
+ }
+ private FastBitmapDrawable getWidgetPreview(AppWidgetProviderInfo info, int cellHSpan,
+ int cellVSpan, int cellWidth, int cellHeight) {
+ // Return the cached version if necessary
+ Bitmap cachedBitmap = mWidgetPreviewCache.get(info);
+ if (cachedBitmap != null) {
+ return new FastBitmapDrawable(cachedBitmap);
+ }
+
+ // Calculate the size of the drawable
+ cellHSpan = Math.max(mMinWidgetSpan, Math.min(mMaxWidgetSpan, cellHSpan));
+ cellVSpan = Math.max(mMinWidgetSpan, Math.min(mMaxWidgetSpan, cellVSpan));
+ int expectedWidth = mWidgetSpacingLayout.estimateCellWidth(cellHSpan);
+ int expectedHeight = mWidgetSpacingLayout.estimateCellHeight(cellVSpan);
+
+ // Scale down the bitmap to fit the space
+ float widgetPreviewScale = (float) cellWidth / expectedWidth;
+ expectedWidth = (int) (widgetPreviewScale * expectedWidth);
+ expectedHeight = (int) (widgetPreviewScale * expectedHeight);
+
+ // Load the preview image if possible
+ String packageName = info.provider.getPackageName();
+ Drawable drawable = null;
+ FastBitmapDrawable newDrawable = null;
+ if (info.previewImage != 0) {
+ drawable = mPackageManager.getDrawable(packageName, info.previewImage, null);
+ if (drawable == null) {
+ Log.w(LOG_TAG, "Can't load icon drawable 0x" + Integer.toHexString(info.icon)
+ + " for provider: " + info.provider);
+ } else {
+ // Scale down the preview to the dimensions we want
+ int imageWidth = drawable.getIntrinsicWidth();
+ int imageHeight = drawable.getIntrinsicHeight();
+ float aspect = (float) imageWidth / imageHeight;
+ int newWidth = imageWidth;
+ int newHeight = imageHeight;
+ if (aspect > 1f) {
+ newWidth = expectedWidth;
+ newHeight = (int) (imageHeight * ((float) expectedWidth / imageWidth));
+ } else {
+ newHeight = expectedHeight;
+ newWidth = (int) (imageWidth * ((float) expectedHeight / imageHeight));
+ }
+
+ Bitmap preview = Bitmap.createBitmap(newWidth, newHeight, Config.ARGB_8888);
+ renderDrawableToBitmap(drawable, preview, 0, 0, newWidth, newHeight, 1f, 1f);
+ newDrawable = new FastBitmapDrawable(preview);
+ newDrawable.setBounds(0, 0, newWidth, newHeight);
+ mWidgetPreviewCache.put(info, preview);
+ }
+ }
+
+ // Generate a preview image if we couldn't load one
+ if (drawable == null) {
+ Resources resources = mLauncher.getResources();
+ int iconSize = resources.getDimensionPixelSize(R.dimen.app_icon_size);
+
+ // Specify the dimensions of the bitmap
+ if (info.minWidth >= info.minHeight) {
+ expectedWidth = cellWidth;
+ expectedHeight = mWidgetPreviewIconPaddedDimension;
+ } else {
+ // Note that in vertical widgets, we might not have enough space due to the text
+ // label, so be conservative and use the width as a height bound
+ expectedWidth = mWidgetPreviewIconPaddedDimension;
+ expectedHeight = cellWidth;
+ }
+
+ Bitmap preview = Bitmap.createBitmap(expectedWidth, expectedHeight, Config.ARGB_8888);
+ renderDrawableToBitmap(mDefaultWidgetBackground, preview, 0, 0, expectedWidth,
+ expectedHeight, 1f,1f);
+
+ // Draw the icon in the top left corner
+ try {
+ Drawable icon = null;
+ if (info.icon > 0) icon = mPackageManager.getDrawable(packageName, info.icon, null);
+ if (icon == null) icon = resources.getDrawable(R.drawable.ic_launcher_application);
+
+ int offset = (int) (iconSize * sWidgetPreviewIconPaddingPercentage);
+ renderDrawableToBitmap(icon, preview, offset, offset, iconSize, iconSize, 1f, 1f);
+ } catch (Resources.NotFoundException e) {}
+
+ newDrawable = new FastBitmapDrawable(preview);
+ newDrawable.setBounds(0, 0, expectedWidth, expectedHeight);
+ mWidgetPreviewCache.put(info, preview);
+ }
+ return newDrawable;
+ }
+ public void syncWidgetPages() {
+ // Ensure that we have the right number of pages
+ Context context = getContext();
+ int numWidgetsPerPage = mWidgetCountX * mWidgetCountY;
+ int numPages = (int) Math.ceil(mWidgets.size() / (float) numWidgetsPerPage);
+ for (int i = 0; i < numPages; ++i) {
+ PagedViewGridLayout layout = new PagedViewGridLayout(context, mWidgetCountX,
+ mWidgetCountY);
+ setupPage(layout);
+ addView(layout);
+ }
+ }
+ public void syncWidgetPageItems(int page) {
+ PagedViewGridLayout layout = (PagedViewGridLayout) getChildAt(page);
+ layout.removeAllViews();
+
+ // Calculate the dimensions of each cell we are giving to each widget
+ int numWidgetsPerPage = mWidgetCountX * mWidgetCountY;
+ int numPages = (int) Math.ceil(mWidgets.size() / (float) numWidgetsPerPage);
+ int offset = page * numWidgetsPerPage;
+ int cellWidth = ((mWidgetSpacingLayout.getContentWidth() - mPageLayoutWidthGap
+ - ((mWidgetCountX - 1) * mWidgetWidthGap)) / mWidgetCountX);
+ int cellHeight = ((mWidgetSpacingLayout.getContentHeight() - mPageLayoutHeightGap
+ - ((mWidgetCountY - 1) * mWidgetHeightGap)) / mWidgetCountY);
+ for (int i = 0; i < Math.min(numWidgetsPerPage, mWidgets.size() - offset); ++i) {
+ Object rawInfo = mWidgets.get(offset + i);
+ PendingAddItemInfo createItemInfo = null;
+ PagedViewWidget widget = (PagedViewWidget) mLayoutInflater.inflate(
+ R.layout.apps_customize_widget, layout, false);
+ if (rawInfo instanceof AppWidgetProviderInfo) {
+ // Fill in the widget information
+ AppWidgetProviderInfo info = (AppWidgetProviderInfo) rawInfo;
+ createItemInfo = new PendingAddWidgetInfo(info, null, null);
+ final int[] cellSpans = CellLayout.rectToCell(getResources(), info.minWidth,
+ info.minHeight, null);
+ FastBitmapDrawable preview = getWidgetPreview(info, cellSpans[0], cellSpans[1],
+ cellWidth, cellHeight);
+ widget.applyFromAppWidgetProviderInfo(info, preview, -1, cellSpans,
+ mPageViewIconCache, (numPages > 1));
+ widget.setTag(createItemInfo);
+ } else if (rawInfo instanceof ResolveInfo) {
+ // Fill in the shortcuts information
+ ResolveInfo info = (ResolveInfo) rawInfo;
+ createItemInfo = new PendingAddItemInfo();
+ createItemInfo.itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
+ createItemInfo.componentName = new ComponentName(info.activityInfo.packageName,
+ info.activityInfo.name);
+ FastBitmapDrawable preview = getShortcutPreview(info, cellWidth, cellHeight);
+ widget.applyFromResolveInfo(mPackageManager, info, preview, mPageViewIconCache,
+ (numPages > 1));
+ widget.setTag(createItemInfo);
+ }
+ widget.setOnClickListener(this);
+ widget.setOnLongClickListener(this);
+ widget.setOnTouchListener(this);
+
+ // Layout each widget
+ int ix = i % mWidgetCountX;
+ int iy = i / mWidgetCountX;
+ PagedViewGridLayout.LayoutParams lp = new PagedViewGridLayout.LayoutParams(cellWidth,
+ cellHeight);
+ lp.leftMargin = (ix * cellWidth) + (ix * mWidgetWidthGap);
+ lp.topMargin = (iy * cellHeight) + (iy * mWidgetHeightGap);
+ layout.addView(widget, lp);
+ }
+ }
+
+ @Override
+ public void syncPages() {
+ removeAllViews();
+ switch (mContentType) {
+ case Applications:
+ syncAppsPages();
+ break;
+ case Widgets:
+ syncWidgetPages();
+ break;
+ }
+ }
+ @Override
+ public void syncPageItems(int page) {
+ switch (mContentType) {
+ case Applications:
+ syncAppsPageItems(page);
+ break;
+ case Widgets:
+ syncWidgetPageItems(page);
+ break;
+ }
+ }
+
+ /**
+ * Used by the parent to get the content width to set the tab bar to
+ * @return
+ */
+ public int getPageContentWidth() {
+ return mContentWidth;
+ }
+
+ @Override
+ protected void onPageBeginMoving() {
+ /* TO BE ENABLED LATER
+ setChildrenDrawnWithCacheEnabled(true);
+ for (int i = 0; i < getChildCount(); ++i) {
+ View v = getChildAt(i);
+ if (v instanceof PagedViewCellLayout) {
+ ((PagedViewCellLayout) v).setChildrenDrawingCacheEnabled(true);
+ }
+ }
+ */
+ super.onPageBeginMoving();
+ }
+
+ @Override
+ protected void onPageEndMoving() {
+ /* TO BE ENABLED LATER
+ for (int i = 0; i < getChildCount(); ++i) {
+ View v = getChildAt(i);
+ if (v instanceof PagedViewCellLayout) {
+ ((PagedViewCellLayout) v).setChildrenDrawingCacheEnabled(false);
+ }
+ }
+ setChildrenDrawnWithCacheEnabled(false);
+ */
+ super.onPageEndMoving();
+ }
+
+ /*
+ * AllAppsView implementation
+ */
+ @Override
+ public void setup(Launcher launcher, DragController dragController) {
+ mLauncher = launcher;
+ mDragController = dragController;
+ }
+ @Override
+ public void zoom(float zoom, boolean animate) {
+ // TODO-APPS_CUSTOMIZE: Call back to mLauncher.zoomed()
+ }
+ @Override
+ public boolean isVisible() {
+ return (getVisibility() == VISIBLE);
+ }
+ @Override
+ public boolean isAnimating() {
+ return false;
+ }
+ @Override
+ public void setApps(ArrayList<ApplicationInfo> list) {
+ mApps = list;
+ Collections.sort(mApps, LauncherModel.APP_NAME_COMPARATOR);
+
+ // The next layout pass will trigger data-ready if both widgets and apps are set, so request
+ // a layout to do this test and invalidate the page data when ready.
+ if (testDataReady()) requestLayout();
+ }
+ private void addAppsWithoutInvalidate(ArrayList<ApplicationInfo> list) {
+ // We add it in place, in alphabetical order
+ int count = list.size();
+ for (int i = 0; i < count; ++i) {
+ ApplicationInfo info = list.get(i);
+ int index = Collections.binarySearch(mApps, info, LauncherModel.APP_NAME_COMPARATOR);
+ if (index < 0) {
+ mApps.add(-(index + 1), info);
+ }
+ }
+ }
+ @Override
+ public void addApps(ArrayList<ApplicationInfo> list) {
+ addAppsWithoutInvalidate(list);
+ invalidatePageData();
+ }
+ private int findAppByComponent(List<ApplicationInfo> list, ApplicationInfo item) {
+ ComponentName removeComponent = item.intent.getComponent();
+ int length = list.size();
+ for (int i = 0; i < length; ++i) {
+ ApplicationInfo info = list.get(i);
+ if (info.intent.getComponent().equals(removeComponent)) {
+ return i;
+ }
+ }
+ return -1;
+ }
+ private void removeAppsWithoutInvalidate(ArrayList<ApplicationInfo> list) {
+ // loop through all the apps and remove apps that have the same component
+ int length = list.size();
+ for (int i = 0; i < length; ++i) {
+ ApplicationInfo info = list.get(i);
+ int removeIndex = findAppByComponent(mApps, info);
+ if (removeIndex > -1) {
+ mApps.remove(removeIndex);
+ mPageViewIconCache.removeOutline(new PagedViewIconCache.Key(info));
+ }
+ }
+ }
+ @Override
+ public void removeApps(ArrayList<ApplicationInfo> list) {
+ removeAppsWithoutInvalidate(list);
+ invalidatePageData();
+ }
+ @Override
+ public void updateApps(ArrayList<ApplicationInfo> list) {
+ // 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.
+ removeAppsWithoutInvalidate(list);
+ addAppsWithoutInvalidate(list);
+ invalidatePageData();
+ }
+ @Override
+ public void reset() {
+ if (mContentType != ContentType.Applications) {
+ // Reset to the first page of the Apps pane
+ AppsCustomizeTabHost tabs = (AppsCustomizeTabHost)
+ mLauncher.findViewById(R.id.apps_customize_pane);
+ tabs.setCurrentTabByTag(tabs.getTabTagForContentType(ContentType.Applications));
+ } else {
+ setCurrentPage(0);
+ invalidatePageData();
+ }
+ }
+ @Override
+ public void dumpState() {
+ // TODO: Dump information related to current list of Applications, Widgets, etc.
+ ApplicationInfo.dumpApplicationInfoList(LOG_TAG, "mApps", mApps);
+ dumpAppWidgetProviderInfoList(LOG_TAG, "mWidgets", mWidgets);
+ }
+ private void dumpAppWidgetProviderInfoList(String tag, String label,
+ List<Object> list) {
+ Log.d(tag, label + " size=" + list.size());
+ for (Object i: list) {
+ if (i instanceof AppWidgetProviderInfo) {
+ AppWidgetProviderInfo info = (AppWidgetProviderInfo) i;
+ Log.d(tag, " label=\"" + info.label + "\" previewImage=" + info.previewImage
+ + " resizeMode=" + info.resizeMode + " configure=" + info.configure
+ + " initialLayout=" + info.initialLayout
+ + " minWidth=" + info.minWidth + " minHeight=" + info.minHeight);
+ } else if (i instanceof ResolveInfo) {
+ ResolveInfo info = (ResolveInfo) i;
+ Log.d(tag, " label=\"" + info.loadLabel(mPackageManager) + "\" icon="
+ + info.icon);
+ }
+ }
+ }
+ @Override
+ public void surrender() {
+ // TODO: If we are in the middle of any process (ie. for holographic outlines, etc) we
+ // should stop this now.
+ }
+
+ @Override
+ protected int getPageWidthForScrollingIndicator() {
+ return getPageContentWidth();
+ }
+}
diff --git a/src/com/android/launcher2/AppsCustomizeTabHost.java b/src/com/android/launcher2/AppsCustomizeTabHost.java
new file mode 100644
index 000000000..51db66c73
--- /dev/null
+++ b/src/com/android/launcher2/AppsCustomizeTabHost.java
@@ -0,0 +1,181 @@
+/*
+ * 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.
+ */
+
+package com.android.launcher2;
+
+import android.animation.Animator;
+import android.content.Context;
+import android.content.res.Resources;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TabHost;
+import android.widget.TabWidget;
+import android.widget.TextView;
+
+import com.android.launcher.R;
+
+public class AppsCustomizeTabHost extends TabHost implements LauncherTransitionable,
+ TabHost.OnTabChangeListener {
+ static final String LOG_TAG = "AppsCustomizeTabHost";
+
+ private static final String APPS_TAB_TAG = "APPS";
+ private static final String WIDGETS_TAB_TAG = "WIDGETS";
+
+ private final LayoutInflater mLayoutInflater;
+ private ViewGroup mTabs;
+ private AppsCustomizePagedView mAppsCustomizePane;
+
+ public AppsCustomizeTabHost(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ mLayoutInflater = LayoutInflater.from(context);
+ }
+
+ /**
+ * Convenience methods to select specific tabs
+ */
+ void selectAppsTab() {
+ setCurrentTabByTag(APPS_TAB_TAG);
+ }
+ void selectWidgetsTab() {
+ setCurrentTabByTag(WIDGETS_TAB_TAG);
+ }
+
+ /**
+ * Setup the tab host and create all necessary tabs.
+ */
+ @Override
+ protected void onFinishInflate() {
+ // Setup the tab host
+ setup();
+
+ final TabWidget tabs = (TabWidget) findViewById(com.android.internal.R.id.tabs);
+ final AppsCustomizePagedView appsCustomizePane = (AppsCustomizePagedView)
+ findViewById(R.id.apps_customize_pane_content);
+ mTabs = tabs;
+ mAppsCustomizePane = appsCustomizePane;
+ if (tabs == null || mAppsCustomizePane == null) throw new Resources.NotFoundException();
+
+ // Configure the tabs content factory to return the same paged view (that we change the
+ // content filter on)
+ TabContentFactory contentFactory = new TabContentFactory() {
+ public View createTabContent(String tag) {
+ return appsCustomizePane;
+ }
+ };
+
+ // Create the tabs
+ TextView tabView;
+ tabView = (TextView) mLayoutInflater.inflate(R.layout.tab_widget_indicator, tabs, false);
+ tabView.setText(mContext.getString(R.string.all_apps_button_label));
+ addTab(newTabSpec(APPS_TAB_TAG).setIndicator(tabView).setContent(contentFactory));
+ tabView = (TextView) mLayoutInflater.inflate(R.layout.tab_widget_indicator, tabs, false);
+ tabView.setText(mContext.getString(R.string.widgets_tab_label));
+ addTab(newTabSpec(WIDGETS_TAB_TAG).setIndicator(tabView).setContent(contentFactory));
+ setOnTabChangedListener(this);
+
+ // Setup the key listener to jump between the last tab view and the market icon
+ AppsCustomizeTabKeyEventListener keyListener = new AppsCustomizeTabKeyEventListener();
+ View lastTab = tabs.getChildTabViewAt(tabs.getTabCount() - 1);
+ lastTab.setOnKeyListener(keyListener);
+ View shopButton = findViewById(R.id.market_button);
+ shopButton.setOnKeyListener(keyListener);
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ boolean remeasureTabWidth = (mTabs.getLayoutParams().width <= 0);
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+
+ // Set the width of the tab list to the content width
+ if (remeasureTabWidth) {
+ mTabs.getLayoutParams().width = mAppsCustomizePane.getPageContentWidth();
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ }
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ // Intercept all touch events up to the bottom of the AppsCustomizePane so they do not fall
+ // through to the workspace and trigger showWorkspace()
+ if (event.getY() < mAppsCustomizePane.getBottom()) {
+ return true;
+ }
+ return super.onTouchEvent(event);
+ }
+
+ @Override
+ public void onTabChanged(String tabId) {
+ mAppsCustomizePane.setContentType(getContentTypeForTabTag(tabId));
+ }
+
+ /**
+ * Returns the content type for the specified tab tag.
+ */
+ public AppsCustomizePagedView.ContentType getContentTypeForTabTag(String tag) {
+ if (tag.equals(APPS_TAB_TAG)) {
+ return AppsCustomizePagedView.ContentType.Applications;
+ } else if (tag.equals(WIDGETS_TAB_TAG)) {
+ return AppsCustomizePagedView.ContentType.Widgets;
+ }
+ return AppsCustomizePagedView.ContentType.Applications;
+ }
+
+ /**
+ * Returns the tab tag for a given content type.
+ */
+ public String getTabTagForContentType(AppsCustomizePagedView.ContentType type) {
+ if (type == AppsCustomizePagedView.ContentType.Applications) {
+ return APPS_TAB_TAG;
+ } else if (type == AppsCustomizePagedView.ContentType.Widgets) {
+ return WIDGETS_TAB_TAG;
+ }
+ return APPS_TAB_TAG;
+ }
+
+ /**
+ * Disable focus on anything under this view in the hierarchy if we are not visible.
+ */
+ @Override
+ public int getDescendantFocusability() {
+ if (getVisibility() != View.VISIBLE) {
+ return ViewGroup.FOCUS_BLOCK_DESCENDANTS;
+ }
+ return super.getDescendantFocusability();
+ }
+
+ /* LauncherTransitionable overrides */
+ @Override
+ public void onLauncherTransitionStart(Animator animation) {
+ if (animation != null) {
+ // Turn on hardware layers for performance
+ setLayerType(LAYER_TYPE_HARDWARE, null);
+
+ // force building the layer at the beginning of the animation, so you don't get a
+ // blip early in the animation
+ buildLayer();
+ }
+ }
+
+ @Override
+ public void onLauncherTransitionEnd(Animator animation) {
+ if (animation != null) {
+ setLayerType(LAYER_TYPE_NONE, null);
+ }
+ }
+}
diff --git a/src/com/android/launcher2/BubbleTextView.java b/src/com/android/launcher2/BubbleTextView.java
index 146485489..703b3a8cb 100644
--- a/src/com/android/launcher2/BubbleTextView.java
+++ b/src/com/android/launcher2/BubbleTextView.java
@@ -29,6 +29,7 @@ import android.graphics.Region;
import android.graphics.Region.Op;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
+import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.widget.TextView;
@@ -87,8 +88,6 @@ public class BubbleTextView extends TextView implements VisibilityChangedBroadca
private void init() {
mBackground = getBackground();
- setFocusable(true);
- setBackgroundDrawable(null);
final Resources res = getContext().getResources();
int bubbleColor = res.getColor(R.color.bubble_dark_background);
@@ -330,4 +329,16 @@ public class BubbleTextView extends TextView implements VisibilityChangedBroadca
}
return true;
}
+
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ return FocusHelper.handleBubbleTextViewKeyEvent(this, keyCode, event)
+ || super.onKeyDown(keyCode, event);
+ }
+
+ @Override
+ public boolean onKeyUp(int keyCode, KeyEvent event) {
+ return FocusHelper.handleBubbleTextViewKeyEvent(this, keyCode, event)
+ || super.onKeyUp(keyCode, event);
+ }
}
diff --git a/src/com/android/launcher2/ButtonDropTarget.java b/src/com/android/launcher2/ButtonDropTarget.java
new file mode 100644
index 000000000..e3da860cc
--- /dev/null
+++ b/src/com/android/launcher2/ButtonDropTarget.java
@@ -0,0 +1,93 @@
+/*
+ * 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.launcher2;
+
+import android.content.Context;
+import android.graphics.Paint;
+import android.util.AttributeSet;
+import android.widget.FrameLayout;
+
+import com.android.launcher.R;
+
+
+/**
+ * Implements a DropTarget.
+ */
+public class ButtonDropTarget extends FrameLayout implements DropTarget, DragController.DragListener {
+
+ protected final int mTransitionDuration;
+
+ protected Launcher mLauncher;
+
+ /** Whether this drop target is active for the current drag */
+ protected boolean mActive;
+
+ /** The paint applied to the drag view on hover */
+ protected final Paint mHoverPaint = new Paint();
+
+ public ButtonDropTarget(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public ButtonDropTarget(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+
+ mTransitionDuration =
+ context.getResources().getInteger(R.integer.config_dropTargetBgTransitionDuration);
+ }
+
+ void setLauncher(Launcher launcher) {
+ mLauncher = launcher;
+ }
+
+ public boolean acceptDrop(DragObject d) {
+ return false;
+ }
+
+ public void onDrop(DragObject d) {
+ // Do nothing
+ }
+
+ public void onDragEnter(DragObject d) {
+ d.dragView.setPaint(mHoverPaint);
+ }
+
+ public void onDragOver(DragObject d) {
+ // Do nothing
+ }
+
+ public void onDragExit(DragObject d) {
+ d.dragView.setPaint(null);
+ }
+
+ public void onDragStart(DragSource source, Object info, int dragAction) {
+ // Do nothing
+ }
+
+ public boolean isDropEnabled() {
+ return mActive;
+ }
+
+ public void onDragEnd() {
+ // Do nothing
+ }
+
+ @Override
+ public DropTarget getDropTargetDelegate(DragObject d) {
+ return null;
+ }
+}
diff --git a/src/com/android/launcher2/CachedTextView.java b/src/com/android/launcher2/CachedTextView.java
index 403d856c0..ac2cc3b5c 100644
--- a/src/com/android/launcher2/CachedTextView.java
+++ b/src/com/android/launcher2/CachedTextView.java
@@ -18,10 +18,11 @@ package com.android.launcher2;
import android.content.Context;
import android.graphics.Bitmap;
+import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Paint;
-import android.graphics.Bitmap.Config;
import android.graphics.PorterDuff.Mode;
+import android.graphics.drawable.Drawable;
import android.text.Layout;
import android.util.AttributeSet;
import android.widget.TextView;
@@ -106,7 +107,7 @@ public class CachedTextView extends TextView {
int width = (int) (textCacheRight - mTextCacheLeft + (2 * xCharWidth));
int height = (int) (textCacheBottom - mTextCacheTop);
- if (width != 0 && height != 0) {
+ if (width > 0 && height > 0) {
if (mCache != null) {
if (mCache.getWidth() != width || mCache.getHeight() != height) {
mCache.recycle();
@@ -163,6 +164,16 @@ public class CachedTextView extends TextView {
if (mPrevAlpha != alpha) {
mPrevAlpha = alpha;
mCachePaint.setAlpha(alpha);
+
+ // We manually update the drawables alpha since the default TextView implementation may
+ // not do this if there is a background set (which we may due to the focus bg)
+ final Drawable[] dr = getCompoundDrawables();
+ for (int i = 0; i < dr.length; ++i) {
+ if (dr[i] != null) {
+ dr[i].mutate().setAlpha(alpha);
+ }
+ }
+
super.onSetAlpha(alpha);
}
return true;
diff --git a/src/com/android/launcher2/CellLayout.java b/src/com/android/launcher2/CellLayout.java
index 4a82799de..a9ba88d94 100644
--- a/src/com/android/launcher2/CellLayout.java
+++ b/src/com/android/launcher2/CellLayout.java
@@ -16,12 +16,11 @@
package com.android.launcher2;
-import com.android.launcher.R;
-
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
+import android.animation.PropertyValuesHolder;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
@@ -39,7 +38,6 @@ import android.graphics.Region;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Log;
-import android.view.ContextMenu;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewDebug;
@@ -48,7 +46,10 @@ import android.view.animation.Animation;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.LayoutAnimationController;
+import com.android.launcher.R;
+
import java.util.Arrays;
+import java.util.HashMap;
public class CellLayout extends ViewGroup {
static final String TAG = "CellLayout";
@@ -72,7 +73,7 @@ public class CellLayout extends ViewGroup {
// These are temporary variables to prevent having to allocate a new object just to
// return an (x, y) value from helper functions. Do NOT use them to maintain other state.
- private final int[] mTmpCellXY = new int[2];
+ private final int[] mTmpXY = new int[2];
private final int[] mTmpPoint = new int[2];
private final PointF mTmpPointF = new PointF();
@@ -95,7 +96,7 @@ public class CellLayout extends ViewGroup {
private float mGlowBackgroundScale;
private float mGlowBackgroundAlpha;
- private boolean mAcceptsDrops = false;
+ private boolean mAcceptsDrops = true;
// If we're actively dragging something over this screen, mIsDragOverlapping is true
private boolean mIsDragOverlapping = false;
private boolean mIsDragOccuring = false;
@@ -104,7 +105,7 @@ public class CellLayout extends ViewGroup {
// These arrays are used to implement the drag visualization on x-large screens.
// They are used as circular arrays, indexed by mDragOutlineCurrent.
- private Point[] mDragOutlines = new Point[8];
+ private Point[] mDragOutlines = new Point[4];
private float[] mDragOutlineAlphas = new float[mDragOutlines.length];
private InterruptibleInOutAnimator[] mDragOutlineAnims =
new InterruptibleInOutAnimator[mDragOutlines.length];
@@ -119,6 +120,9 @@ public class CellLayout extends ViewGroup {
private InterruptibleInOutAnimator mCrosshairsAnimator = null;
private float mCrosshairsVisibility = 0.0f;
+ private HashMap<CellLayout.LayoutParams, ObjectAnimator> mReorderAnimators = new
+ HashMap<CellLayout.LayoutParams, ObjectAnimator>();
+
// When a drag operation is in progress, holds the nearest cell to the touch point
private final int[] mDragCell = new int[2];
@@ -168,24 +172,22 @@ public class CellLayout extends ViewGroup {
final Resources res = getResources();
- if (LauncherApplication.isScreenXLarge()) {
- mNormalBackground = res.getDrawable(R.drawable.homescreen_large_blue);
- mActiveBackground = res.getDrawable(R.drawable.homescreen_large_green);
- mActiveGlowBackground = res.getDrawable(R.drawable.homescreen_large_green_strong);
+ mNormalBackground = res.getDrawable(R.drawable.homescreen_large_blue);
+ mActiveBackground = res.getDrawable(R.drawable.homescreen_large_green);
+ mActiveGlowBackground = res.getDrawable(R.drawable.homescreen_large_green_strong);
- mNormalBackgroundMini = res.getDrawable(R.drawable.homescreen_small_blue);
- mNormalGlowBackgroundMini = res.getDrawable(R.drawable.homescreen_small_blue_strong);
- mActiveBackgroundMini = res.getDrawable(R.drawable.homescreen_small_green);
- mActiveGlowBackgroundMini = res.getDrawable(R.drawable.homescreen_small_green_strong);
+ mNormalBackgroundMini = res.getDrawable(R.drawable.homescreen_small_blue);
+ mNormalGlowBackgroundMini = res.getDrawable(R.drawable.homescreen_small_blue_strong);
+ mActiveBackgroundMini = res.getDrawable(R.drawable.homescreen_small_green);
+ mActiveGlowBackgroundMini = res.getDrawable(R.drawable.homescreen_small_green_strong);
- mNormalBackground.setFilterBitmap(true);
- mActiveBackground.setFilterBitmap(true);
- mActiveGlowBackground.setFilterBitmap(true);
- mNormalBackgroundMini.setFilterBitmap(true);
- mNormalGlowBackgroundMini.setFilterBitmap(true);
- mActiveBackgroundMini.setFilterBitmap(true);
- mActiveGlowBackgroundMini.setFilterBitmap(true);
- }
+ mNormalBackground.setFilterBitmap(true);
+ mActiveBackground.setFilterBitmap(true);
+ mActiveGlowBackground.setFilterBitmap(true);
+ mNormalBackgroundMini.setFilterBitmap(true);
+ mNormalGlowBackgroundMini.setFilterBitmap(true);
+ mActiveBackgroundMini.setFilterBitmap(true);
+ mActiveGlowBackgroundMini.setFilterBitmap(true);
// Initialize the data structures used for the drag visualization.
@@ -264,8 +266,7 @@ public class CellLayout extends ViewGroup {
setHoverAlpha(1.0f);
mChildren = new CellLayoutChildren(context);
- mChildren.setCellDimensions(
- mCellWidth, mCellHeight, mLeftPadding, mTopPadding, mWidthGap, mHeightGap);
+ mChildren.setCellDimensions(mCellWidth, mCellHeight, mWidthGap, mHeightGap);
addView(mChildren);
}
@@ -289,12 +290,22 @@ public class CellLayout extends ViewGroup {
return heightGap * (numCells - 1) + cellHeight * numCells;
}
+ public void enableHardwareLayers() {
+ mChildren.enableHardwareLayers();
+ }
+
+ public void setGridSize(int x, int y) {
+ mCountX = x;
+ mCountY = y;
+ mOccupied = new boolean[mCountX][mCountY];
+ }
+
private void invalidateBubbleTextView(BubbleTextView icon) {
final int padding = icon.getPressedOrFocusedBackgroundPadding();
- invalidate(icon.getLeft() - padding,
- icon.getTop() - padding,
- icon.getRight() + padding,
- icon.getBottom() + padding);
+ invalidate(icon.getLeft() + getLeftPadding() - padding,
+ icon.getTop() + getTopPadding() - padding,
+ icon.getRight() + getLeftPadding() + padding,
+ icon.getBottom() + getTopPadding() + padding);
}
void setPressedOrFocusedIcon(BubbleTextView icon) {
@@ -375,35 +386,33 @@ public class CellLayout extends ViewGroup {
}
void animateDrop() {
- if (LauncherApplication.isScreenXLarge()) {
- Resources res = getResources();
- float onDropScale = res.getInteger(R.integer.config_screenOnDropScalePercent) / 100.0f;
- ObjectAnimator scaleUp = ObjectAnimator.ofFloat(this, "hoverScale", onDropScale);
- scaleUp.setDuration(res.getInteger(R.integer.config_screenOnDropScaleUpDuration));
- ObjectAnimator scaleDown = ObjectAnimator.ofFloat(this, "hoverScale", 1.0f);
- scaleDown.setDuration(res.getInteger(R.integer.config_screenOnDropScaleDownDuration));
- ObjectAnimator alphaFadeOut = ObjectAnimator.ofFloat(this, "hoverAlpha", 0.0f);
-
- alphaFadeOut.setStartDelay(res.getInteger(R.integer.config_screenOnDropAlphaFadeDelay));
- alphaFadeOut.setDuration(res.getInteger(R.integer.config_screenOnDropAlphaFadeDelay));
-
- AnimatorSet bouncer = new AnimatorSet();
- bouncer.play(scaleUp).before(scaleDown);
- bouncer.play(scaleUp).with(alphaFadeOut);
- bouncer.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationStart(Animator animation) {
- setIsDragOverlapping(true);
- }
- @Override
- public void onAnimationEnd(Animator animation) {
- setIsDragOverlapping(false);
- setHoverScale(1.0f);
- setHoverAlpha(1.0f);
- }
- });
- bouncer.start();
- }
+ Resources res = getResources();
+ float onDropScale = res.getInteger(R.integer.config_screenOnDropScalePercent) / 100.0f;
+ ObjectAnimator scaleUp = ObjectAnimator.ofFloat(this, "hoverScale", onDropScale);
+ scaleUp.setDuration(res.getInteger(R.integer.config_screenOnDropScaleUpDuration));
+ ObjectAnimator scaleDown = ObjectAnimator.ofFloat(this, "hoverScale", 1.0f);
+ scaleDown.setDuration(res.getInteger(R.integer.config_screenOnDropScaleDownDuration));
+ ObjectAnimator alphaFadeOut = ObjectAnimator.ofFloat(this, "hoverAlpha", 0.0f);
+
+ alphaFadeOut.setStartDelay(res.getInteger(R.integer.config_screenOnDropAlphaFadeDelay));
+ alphaFadeOut.setDuration(res.getInteger(R.integer.config_screenOnDropAlphaFadeDuration));
+
+ AnimatorSet bouncer = new AnimatorSet();
+ bouncer.play(scaleUp).before(scaleDown);
+ bouncer.play(scaleUp).with(alphaFadeOut);
+ bouncer.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ setIsDragOverlapping(true);
+ }
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ setIsDragOverlapping(false);
+ setHoverScale(1.0f);
+ setHoverAlpha(1.0f);
+ }
+ });
+ bouncer.start();
}
@Override
@@ -413,7 +422,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 (LauncherApplication.isScreenXLarge() && mBackgroundAlpha > 0.0f) {
+ if (mBackgroundAlpha > 0.0f) {
Drawable bg;
boolean mini = getScaleX() < 0.5f;
@@ -508,8 +517,8 @@ public class CellLayout extends ViewGroup {
final Bitmap b = mPressedOrFocusedIcon.getPressedOrFocusedBackground();
if (b != null) {
canvas.drawBitmap(b,
- mPressedOrFocusedIcon.getLeft() - padding,
- mPressedOrFocusedIcon.getTop() - padding,
+ mPressedOrFocusedIcon.getLeft() + getLeftPadding() - padding,
+ mPressedOrFocusedIcon.getTop() + getTopPadding() - padding,
null);
}
}
@@ -652,6 +661,14 @@ public class CellLayout extends ViewGroup {
if ((child.getVisibility() == VISIBLE || child.getAnimation() != null) &&
lp.isLockedToGrid) {
child.getHitRect(frame);
+
+ // The child hit rect is relative to the CellLayoutChildren parent, so we need to
+ // offset that by this CellLayout's padding to test an (x,y) point that is relative
+ // to this view.
+ final int tmpXY[] = mTmpXY;
+ child.getLocationOnScreen(tmpXY);
+ frame.offset(mLeftPadding, mTopPadding);
+
if (frame.contains(x, y)) {
cellInfo.cell = child;
cellInfo.cellX = lp.cellX;
@@ -666,7 +683,7 @@ public class CellLayout extends ViewGroup {
}
if (!found) {
- final int cellXY[] = mTmpCellXY;
+ final int cellXY[] = mTmpXY;
pointToCellExact(x, y, cellXY);
cellInfo.cell = null;
@@ -756,6 +773,22 @@ public class CellLayout extends ViewGroup {
result[1] = vStartPadding + cellY * (mCellHeight + mHeightGap);
}
+ /**
+ * Given a cell coordinate, return the point that represents the upper left corner of that cell
+ *
+ * @param cellX X coordinate of the cell
+ * @param cellY Y coordinate of the cell
+ *
+ * @param result Array of 2 ints to hold the x and y coordinate of the point
+ */
+ void cellToCenterPoint(int cellX, int cellY, int[] result) {
+ final int hStartPadding = getLeftPadding();
+ final int vStartPadding = getTopPadding();
+
+ result[0] = hStartPadding + cellX * (mCellWidth + mWidthGap) + mCellWidth / 2;
+ result[1] = vStartPadding + cellY * (mCellHeight + mHeightGap) + mCellHeight / 2;
+ }
+
int getCellWidth() {
return mCellWidth;
}
@@ -788,6 +821,18 @@ public class CellLayout extends ViewGroup {
return mBottomPadding;
}
+ Rect getContentRect(Rect r) {
+ if (r == null) {
+ r = new Rect();
+ }
+ int left = getPaddingLeft();
+ int top = getPaddingTop();
+ int right = left + getWidth() - mLeftPadding - mRightPadding;
+ int bottom = top + getHeight() - mTopPadding - mBottomPadding;
+ r.set(left, top, right, bottom);
+ return r;
+ }
+
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// TODO: currently ignoring padding
@@ -810,10 +855,10 @@ public class CellLayout extends ViewGroup {
if (mWidthGap < 0 || mHeightGap < 0) {
int vSpaceLeft = heightSpecSize - mTopPadding - mBottomPadding - (cellHeight * mCountY);
- mHeightGap = vSpaceLeft / numHeightGaps;
+ mHeightGap = numHeightGaps > 0 ? vSpaceLeft / numHeightGaps : 0;
int hSpaceLeft = widthSpecSize - mLeftPadding - mRightPadding - (cellWidth * mCountX);
- mWidthGap = hSpaceLeft / numWidthGaps;
+ mWidthGap = numWidthGaps > 0 ? hSpaceLeft / numWidthGaps : 0;
// center it around the min gaps
int minGap = Math.min(mWidthGap, mHeightGap);
@@ -834,9 +879,10 @@ public class CellLayout extends ViewGroup {
int count = getChildCount();
for (int i = 0; i < count; i++) {
View child = getChildAt(i);
- int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(newWidth, MeasureSpec.EXACTLY);
- int childheightMeasureSpec = MeasureSpec.makeMeasureSpec(newHeight,
- MeasureSpec.EXACTLY);
+ int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(newWidth - mLeftPadding -
+ mRightPadding, MeasureSpec.EXACTLY);
+ int childheightMeasureSpec = MeasureSpec.makeMeasureSpec(newHeight - mTopPadding -
+ mBottomPadding, MeasureSpec.EXACTLY);
child.measure(childWidthMeasureSpec, childheightMeasureSpec);
}
setMeasuredDimension(newWidth, newHeight);
@@ -847,7 +893,7 @@ public class CellLayout extends ViewGroup {
int count = getChildCount();
for (int i = 0; i < count; i++) {
View child = getChildAt(i);
- child.layout(0, 0, r - l, b - t);
+ child.layout(mLeftPadding, mTopPadding, r - l - mRightPadding , b - t - mBottomPadding);
}
}
@@ -925,6 +971,64 @@ public class CellLayout extends ViewGroup {
return mChildren.getChildAt(x, y);
}
+ public boolean animateChildToPosition(final View child, int cellX, int cellY, int duration) {
+ CellLayoutChildren clc = getChildrenLayout();
+ if (clc.indexOfChild(child) != -1 && !mOccupied[cellX][cellY]) {
+ final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+ final ItemInfo info = (ItemInfo) child.getTag();
+
+ // We cancel any existing animations
+ if (mReorderAnimators.containsKey(lp)) {
+ mReorderAnimators.get(lp).cancel();
+ mReorderAnimators.remove(lp);
+ }
+
+ int oldX = lp.x;
+ int oldY = lp.y;
+ mOccupied[lp.cellX][lp.cellY] = false;
+ mOccupied[cellX][cellY] = true;
+
+ lp.isLockedToGrid = true;
+ lp.cellX = info.cellX = cellX;
+ lp.cellY = info.cellY = cellY;
+ clc.setupLp(lp);
+ lp.isLockedToGrid = false;
+ int newX = lp.x;
+ int newY = lp.y;
+
+ PropertyValuesHolder x = PropertyValuesHolder.ofInt("x", oldX, newX);
+ PropertyValuesHolder y = PropertyValuesHolder.ofInt("y", oldY, newY);
+ ObjectAnimator oa = ObjectAnimator.ofPropertyValuesHolder(lp, x, y);
+ oa.setDuration(duration);
+ mReorderAnimators.put(lp, oa);
+ oa.addUpdateListener(new AnimatorUpdateListener() {
+ public void onAnimationUpdate(ValueAnimator animation) {
+ child.requestLayout();
+ }
+ });
+ oa.addListener(new AnimatorListenerAdapter() {
+ boolean cancelled = false;
+ public void onAnimationEnd(Animator animation) {
+ // If the animation was cancelled, it means that another animation
+ // has interrupted this one, and we don't want to lock the item into
+ // place just yet.
+ if (!cancelled) {
+ lp.isLockedToGrid = true;
+ }
+ if (mReorderAnimators.containsKey(lp)) {
+ mReorderAnimators.remove(lp);
+ }
+ }
+ public void onAnimationCancel(Animator animation) {
+ cancelled = true;
+ }
+ });
+ oa.start();
+ return true;
+ }
+ return false;
+ }
+
/**
* Estimate where the top left cell of the dragged item will land if it is dropped.
*
@@ -967,6 +1071,13 @@ public class CellLayout extends ViewGroup {
mDragCenter.set(originX, originY);
}
+ if (dragOutline == null && v == null) {
+ if (mCrosshairsDrawable != null) {
+ invalidate();
+ }
+ return;
+ }
+
if (nearest != null && (nearest[0] != oldDragCellX || nearest[1] != oldDragCellY)) {
// Find the top left corner of the rect the object will occupy
final int[] topLeft = mTmpPoint;
@@ -976,15 +1087,23 @@ public class CellLayout extends ViewGroup {
int top = topLeft[1];
if (v != null) {
- if (v.getParent() instanceof CellLayout) {
- LayoutParams lp = (LayoutParams) v.getLayoutParams();
- left += lp.leftMargin;
- top += lp.topMargin;
- }
-
- // Offsets due to the size difference between the View and the dragOutline
+ // When drawing the drag outline, it did not account for margin offsets
+ // added by the view's parent.
+ MarginLayoutParams lp = (MarginLayoutParams) v.getLayoutParams();
+ left += lp.leftMargin;
+ top += lp.topMargin;
+
+ // Offsets due to the size difference between the View and the dragOutline.
+ // There is a size difference to account for the outer blur, which may lie
+ // outside the bounds of the view.
left += (v.getWidth() - dragOutline.getWidth()) / 2;
top += (v.getHeight() - dragOutline.getHeight()) / 2;
+ } else {
+ // Center the drag outline in the cell
+ left += ((mCellWidth * spanX) + ((spanX - 1) * mWidthGap)
+ - dragOutline.getWidth()) / 2;
+ top += ((mCellHeight * spanY) + ((spanY - 1) * mHeightGap)
+ - dragOutline.getHeight()) / 2;
}
final int oldIndex = mDragOutlineCurrent;
@@ -1002,6 +1121,13 @@ public class CellLayout extends ViewGroup {
}
}
+ public void clearDragOutlines() {
+ final int oldIndex = mDragOutlineCurrent;
+ mDragOutlineAnims[oldIndex].animateOut();
+ mDragCell[0] = -1;
+ mDragCell[1] = -1;
+ }
+
/**
* Find a vacant area that will fit the given bounds nearest the requested
* cell location. Uses Euclidean distance to score multiple vacant areas.
@@ -1028,16 +1154,23 @@ public class CellLayout extends ViewGroup {
* @param pixelY The Y location at which you want to search for a vacant area.
* @param spanX Horizontal span of the object.
* @param spanY Vertical span of the object.
- * @param ignoreView Considers space occupied by this view as unoccupied
- * @param result Previously returned value to possibly recycle.
+ * @param ignoreOccupied If true, the result can be an occupied cell
+ * @param result Array in which to place the result, or null (in which case a new array will
+ * be allocated)
* @return The X, Y cell of a vacant area that can contain this object,
* nearest the requested location.
*/
- int[] findNearestVacantArea(
- int pixelX, int pixelY, int spanX, int spanY, View ignoreView, int[] result) {
+ int[] findNearestArea(int pixelX, int pixelY, int spanX, int spanY, View ignoreView,
+ boolean ignoreOccupied, int[] result) {
// mark space take by ignoreView as available (method checks if ignoreView is null)
markCellsAsUnoccupiedForView(ignoreView);
+ // For items with a spanX / spanY > 1, the passed in point (pixelX, pixelY) corresponds
+ // to the center of the item, but we are searching based on the top-left cell, so
+ // we translate the point over to correspond to the top-left.
+ pixelX -= (mCellWidth + mWidthGap) * (spanX - 1) / 2f;
+ pixelY -= (mCellHeight + mHeightGap) * (spanY - 1) / 2f;
+
// Keep track of best-scoring drop area
final int[] bestXY = result != null ? result : new int[2];
double bestDistance = Double.MAX_VALUE;
@@ -1049,18 +1182,20 @@ public class CellLayout extends ViewGroup {
for (int y = 0; y < countY - (spanY - 1); y++) {
inner:
for (int x = 0; x < countX - (spanX - 1); x++) {
- for (int i = 0; i < spanX; i++) {
- for (int j = 0; j < spanY; j++) {
- if (occupied[x + i][y + j]) {
- // small optimization: we can skip to after the column we just found
- // an occupied cell
- x += i;
- continue inner;
+ if (ignoreOccupied) {
+ for (int i = 0; i < spanX; i++) {
+ for (int j = 0; j < spanY; j++) {
+ if (occupied[x + i][y + j]) {
+ // small optimization: we can skip to after the column we
+ // just found an occupied cell
+ x += i;
+ continue inner;
+ }
}
}
}
- final int[] cellXY = mTmpCellXY;
- cellToPoint(x, y, cellXY);
+ final int[] cellXY = mTmpXY;
+ cellToCenterPoint(x, y, cellXY);
double distance = Math.sqrt(Math.pow(cellXY[0] - pixelX, 2)
+ Math.pow(cellXY[1] - pixelY, 2));
@@ -1074,12 +1209,48 @@ public class CellLayout extends ViewGroup {
// re-mark space taken by ignoreView as occupied
markCellsAsOccupiedForView(ignoreView);
- // Return null if no suitable location found
- if (bestDistance < Double.MAX_VALUE) {
- return bestXY;
- } else {
- return null;
+ // Return -1, -1 if no suitable location found
+ if (bestDistance == Double.MAX_VALUE) {
+ bestXY[0] = -1;
+ bestXY[1] = -1;
}
+ return bestXY;
+ }
+
+ /**
+ * Find a vacant area that will fit the given bounds nearest the requested
+ * cell location. Uses Euclidean distance to score multiple vacant areas.
+ *
+ * @param pixelX The X location at which you want to search for a vacant area.
+ * @param pixelY The Y location at which you want to search for a vacant area.
+ * @param spanX Horizontal span of the object.
+ * @param spanY Vertical span of the object.
+ * @param ignoreView Considers space occupied by this view as unoccupied
+ * @param result Previously returned value to possibly recycle.
+ * @return The X, Y cell of a vacant area that can contain this object,
+ * nearest the requested location.
+ */
+ int[] findNearestVacantArea(
+ int pixelX, int pixelY, int spanX, int spanY, View ignoreView, int[] result) {
+ return findNearestArea(pixelX, pixelY, spanX, spanY, ignoreView, true, result);
+ }
+
+ /**
+ * Find a starting cell position that will fit the given bounds nearest the requested
+ * cell location. Uses Euclidean distance to score multiple vacant areas.
+ *
+ * @param pixelX The X location at which you want to search for a vacant area.
+ * @param pixelY The Y location at which you want to search for a vacant area.
+ * @param spanX Horizontal span of the object.
+ * @param spanY Vertical span of the object.
+ * @param ignoreView Considers space occupied by this view as unoccupied
+ * @param result Previously returned value to possibly recycle.
+ * @return The X, Y cell of a vacant area that can contain this object,
+ * nearest the requested location.
+ */
+ int[] findNearestArea(
+ int pixelX, int pixelY, int spanX, int spanY, int[] result) {
+ return findNearestArea(pixelX, pixelY, spanX, spanY, null, false, result);
}
boolean existsEmptyCell() {
@@ -1372,8 +1543,8 @@ public class CellLayout extends ViewGroup {
static boolean findVacantCell(int[] vacant, int spanX, int spanY,
int xCount, int yCount, boolean[][] occupied) {
- for (int x = 0; x < xCount; x++) {
- for (int y = 0; y < yCount; y++) {
+ for (int y = 0; y < yCount; y++) {
+ for (int x = 0; x < xCount; x++) {
boolean available = !occupied[x][y];
out: for (int i = x; i < x + spanX - 1 && x < xCount; i++) {
for (int j = y; j < y + spanY - 1 && y < yCount; j++) {
@@ -1477,6 +1648,24 @@ out: for (int i = x; i < x + spanX - 1 && x < xCount; i++) {
}
}
+ public int getDesiredWidth() {
+ return mLeftPadding + mRightPadding + (mCountX * mCellWidth) +
+ (Math.max((mCountX - 1), 0) * mWidthGap);
+ }
+
+ public int getDesiredHeight() {
+ return mTopPadding + mBottomPadding + (mCountY * mCellHeight) +
+ (Math.max((mCountY - 1), 0) * mHeightGap);
+ }
+
+ public boolean isOccupied(int x, int y) {
+ if (x < mCountX && y < mCountY) {
+ return mOccupied[x][y];
+ } else {
+ throw new RuntimeException("Position exceeds the bound of this CellLayout");
+ }
+ }
+
@Override
public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
return new CellLayout.LayoutParams(getContext(), attrs);
@@ -1590,8 +1779,7 @@ out: for (int i = x; i < x + spanX - 1 && x < xCount; i++) {
this.cellVSpan = cellVSpan;
}
- public void setup(int cellWidth, int cellHeight, int widthGap, int heightGap,
- int hStartPadding, int vStartPadding) {
+ public void setup(int cellWidth, int cellHeight, int widthGap, int heightGap) {
if (isLockedToGrid) {
final int myCellHSpan = cellHSpan;
final int myCellVSpan = cellVSpan;
@@ -1602,11 +1790,15 @@ out: for (int i = x; i < x + spanX - 1 && x < xCount; i++) {
leftMargin - rightMargin;
height = myCellVSpan * cellHeight + ((myCellVSpan - 1) * heightGap) -
topMargin - bottomMargin;
- x = hStartPadding + myCellX * (cellWidth + widthGap) + leftMargin;
- y = vStartPadding + myCellY * (cellHeight + heightGap) + topMargin;
+ x = myCellX * (cellWidth + widthGap) + leftMargin;
+ y = myCellY * (cellHeight + heightGap) + topMargin;
}
}
+ public String toString() {
+ return "(" + this.cellX + ", " + this.cellY + ")";
+ }
+
public void setWidth(int width) {
this.width = width;
}
@@ -1638,10 +1830,6 @@ out: for (int i = x; i < x + spanX - 1 && x < xCount; i++) {
public int getY() {
return y;
}
-
- public String toString() {
- return "(" + this.cellX + ", " + this.cellY + ")";
- }
}
// This class stores info for two purposes:
@@ -1650,7 +1838,7 @@ out: for (int i = x; i < x + spanX - 1 && x < xCount; i++) {
// 2. When long clicking on an empty cell in a CellLayout, we save information about the
// cellX and cellY coordinates and which page was clicked. We then set this as a tag on
// the CellLayout that was long clicked
- static final class CellInfo implements ContextMenu.ContextMenuInfo {
+ static final class CellInfo {
View cell;
int cellX = -1;
int cellY = -1;
diff --git a/src/com/android/launcher2/CellLayoutChildren.java b/src/com/android/launcher2/CellLayoutChildren.java
index 04996f359..6e78885de 100644
--- a/src/com/android/launcher2/CellLayoutChildren.java
+++ b/src/com/android/launcher2/CellLayoutChildren.java
@@ -16,12 +16,9 @@
package com.android.launcher2;
-import java.util.ArrayList;
-
import android.app.WallpaperManager;
import android.content.Context;
import android.graphics.Rect;
-import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
@@ -34,33 +31,24 @@ public class CellLayoutChildren extends ViewGroup {
private final WallpaperManager mWallpaperManager;
- private int mLeftPadding;
- private int mTopPadding;
-
private int mCellWidth;
private int mCellHeight;
private int mWidthGap;
private int mHeightGap;
- // Variables relating to resizing widgets
- private final ArrayList<AppWidgetResizeFrame> mResizeFrames =
- new ArrayList<AppWidgetResizeFrame>();
- private AppWidgetResizeFrame mCurrentResizeFrame;
- private int mXDown, mYDown;
-
public CellLayoutChildren(Context context) {
super(context);
mWallpaperManager = WallpaperManager.getInstance(context);
+ }
+
+ public void enableHardwareLayers() {
setLayerType(LAYER_TYPE_HARDWARE, null);
}
- public void setCellDimensions(int cellWidth, int cellHeight,
- int leftPadding, int topPadding, int widthGap, int heightGap ) {
+ public void setCellDimensions(int cellWidth, int cellHeight, int widthGap, int heightGap ) {
mCellWidth = cellWidth;
mCellHeight = cellHeight;
- mLeftPadding = leftPadding;
- mTopPadding = topPadding;
mWidthGap = widthGap;
mHeightGap = heightGap;
}
@@ -72,7 +60,7 @@ public class CellLayoutChildren extends ViewGroup {
CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
if ((lp.cellX <= x) && (x < lp.cellX + lp.cellHSpan) &&
- (lp.cellY <= y) && (y < lp.cellY + lp.cellHSpan)) {
+ (lp.cellY <= y) && (y < lp.cellY + lp.cellVSpan)) {
return child;
}
}
@@ -81,27 +69,33 @@ public class CellLayoutChildren extends ViewGroup {
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- final int cellWidth = mCellWidth;
- final int cellHeight = mCellHeight;
int count = getChildCount();
for (int i = 0; i < count; i++) {
View child = getChildAt(i);
- CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
-
- lp.setup(cellWidth, cellHeight, mWidthGap, mHeightGap,
- mLeftPadding, mTopPadding);
-
- int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(lp.width, MeasureSpec.EXACTLY);
- int childheightMeasureSpec = MeasureSpec.makeMeasureSpec(lp.height,
- MeasureSpec.EXACTLY);
-
- child.measure(childWidthMeasureSpec, childheightMeasureSpec);
+ measureChild(child);
}
int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(widthSpecSize, heightSpecSize);
}
+ public void setupLp(CellLayout.LayoutParams lp) {
+ lp.setup(mCellWidth, mCellHeight, mWidthGap, mHeightGap);
+ }
+
+ public void measureChild(View child) {
+ final int cellWidth = mCellWidth;
+ final int cellHeight = mCellHeight;
+ CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
+
+ lp.setup(cellWidth, cellHeight, mWidthGap, mHeightGap);
+ int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(lp.width, MeasureSpec.EXACTLY);
+ int childheightMeasureSpec = MeasureSpec.makeMeasureSpec(lp.height,
+ MeasureSpec.EXACTLY);
+
+ child.measure(childWidthMeasureSpec, childheightMeasureSpec);
+ }
+
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int count = getChildCount();
@@ -176,95 +170,4 @@ public class CellLayoutChildren extends ViewGroup {
protected void setChildrenDrawnWithCacheEnabled(boolean enabled) {
super.setChildrenDrawnWithCacheEnabled(enabled);
}
-
- public void clearAllResizeFrames() {
- for (AppWidgetResizeFrame frame: mResizeFrames) {
- removeView(frame);
- }
- mResizeFrames.clear();
- }
-
- public boolean hasResizeFrames() {
- return mResizeFrames.size() > 0;
- }
-
- public boolean isWidgetBeingResized() {
- return mCurrentResizeFrame != null;
- }
-
- private boolean handleTouchDown(MotionEvent ev) {
- Rect hitRect = new Rect();
-
- int x = (int) ev.getX();
- int y = (int) ev.getY();
-
- for (AppWidgetResizeFrame child: mResizeFrames) {
- child.getHitRect(hitRect);
- if (hitRect.contains(x, y)) {
- if (child.beginResizeIfPointInRegion(x - child.getLeft(), y - child.getTop())) {
- mCurrentResizeFrame = child;
- mXDown = x;
- mYDown = y;
- requestDisallowInterceptTouchEvent(true);
- return true;
- }
- }
- }
- return false;
- }
-
- @Override
- public boolean onInterceptTouchEvent(MotionEvent ev) {
- if (ev.getAction() == MotionEvent.ACTION_DOWN) {
- if (handleTouchDown(ev)) {
- return true;
- }
- }
- return false;
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent ev) {
- boolean handled = false;
- int action = ev.getAction();
-
- int x = (int) ev.getX();
- int y = (int) ev.getY();
-
- if (ev.getAction() == MotionEvent.ACTION_DOWN) {
- if (ev.getAction() == MotionEvent.ACTION_DOWN) {
- if (handleTouchDown(ev)) {
- return true;
- }
- }
- }
-
- if (mCurrentResizeFrame != null) {
- handled = true;
- switch (action) {
- case MotionEvent.ACTION_MOVE:
- mCurrentResizeFrame.visualizeResizeForDelta(x - mXDown, y - mYDown);
- break;
- case MotionEvent.ACTION_CANCEL:
- case MotionEvent.ACTION_UP:
- mCurrentResizeFrame.commitResizeForDelta(x - mXDown, y - mYDown);
- mCurrentResizeFrame = null;
- }
- }
- return handled;
- }
-
- public void addResizeFrame(ItemInfo itemInfo, LauncherAppWidgetHostView widget,
- CellLayout cellLayout) {
- AppWidgetResizeFrame resizeFrame = new AppWidgetResizeFrame(getContext(),
- itemInfo, widget, cellLayout);
-
- CellLayout.LayoutParams lp = new CellLayout.LayoutParams(-1, -1, -1, -1);
- lp.isLockedToGrid = false;
-
- addView(resizeFrame, lp);
- mResizeFrames.add(resizeFrame);
-
- resizeFrame.snapToWidget(false);
- }
}
diff --git a/src/com/android/launcher2/CustomizePagedView.java b/src/com/android/launcher2/CustomizePagedView.java
index 6aa4c7230..b2a7603b5 100644
--- a/src/com/android/launcher2/CustomizePagedView.java
+++ b/src/com/android/launcher2/CustomizePagedView.java
@@ -16,10 +16,6 @@
package com.android.launcher2;
-import com.android.launcher.R;
-
-import org.xmlpull.v1.XmlPullParser;
-
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
@@ -43,7 +39,6 @@ import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Bitmap.Config;
import android.graphics.drawable.Drawable;
-import android.os.AsyncTask;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Slog;
@@ -55,7 +50,6 @@ import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
-import android.view.View.MeasureSpec;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.LinearInterpolator;
import android.widget.Checkable;
@@ -63,6 +57,11 @@ import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
+import com.android.launcher.R;
+import com.android.launcher2.DropTarget.DragObject;
+
+import org.xmlpull.v1.XmlPullParser;
+
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@@ -100,10 +99,6 @@ public class CustomizePagedView extends PagedViewWithDraggableItems
// The max dimensions for the ImageView we use for displaying a widget
private int mMaxWidgetWidth;
- // The min and max dimensions for the bitmap that is used for a widget preview
- private int mMinWidgetPreviewDim;
- private int mMaxWidgetPreviewDim;
-
// The max number of widget cells to take a "page" of widgets
private int mMaxWidgetsCellHSpan;
@@ -157,7 +152,6 @@ public class CustomizePagedView extends PagedViewWithDraggableItems
private AllAppsPagedView mAllAppsPagedView;
private boolean mWaitingToInitPages = true;
- private boolean mWaitingToDetermineRowsAndColumns = true;
public CustomizePagedView(Context context) {
this(context, null, 0);
@@ -229,8 +223,8 @@ public class CustomizePagedView extends PagedViewWithDraggableItems
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- if (mWaitingToDetermineRowsAndColumns) {
- mWaitingToDetermineRowsAndColumns = false;
+ if (mWaitingToInitPages) {
+ mWaitingToInitPages = false;
postInvalidatePageData(false);
}
super.onLayout(changed, left, top, right, bottom);
@@ -256,7 +250,6 @@ public class CustomizePagedView extends PagedViewWithDraggableItems
// Update the widgets/shortcuts to reflect changes in the set of available apps
mPageViewIconCache.retainAllApps(list);
- mWaitingToInitPages = false;
invalidatePageData();
}
@@ -353,13 +346,8 @@ public class CustomizePagedView extends PagedViewWithDraggableItems
}
});
- Comparator<ResolveInfo> resolveInfoComparator = new Comparator<ResolveInfo>() {
- @Override
- public int compare(ResolveInfo object1, ResolveInfo object2) {
- return object1.loadLabel(mPackageManager).toString().compareTo(
- object2.loadLabel(mPackageManager).toString());
- }
- };
+ LauncherModel.ShortcutNameComparator resolveInfoComparator =
+ new LauncherModel.ShortcutNameComparator(mPackageManager);
// get the list of shortcuts
Intent shortcutsIntent = new Intent(Intent.ACTION_CREATE_SHORTCUT);
@@ -414,7 +402,7 @@ public class CustomizePagedView extends PagedViewWithDraggableItems
}
}
- public void onDropCompleted(View target, Object dragInfo, boolean success) {
+ public void onDropCompleted(View target, DragObject d, boolean success) {
final DragLayer dragLayer = (DragLayer) mLauncher.findViewById(R.id.drag_layer);
// Create a view, identical to the drag view, that is only used for animating the
@@ -425,7 +413,7 @@ public class CustomizePagedView extends PagedViewWithDraggableItems
if (success) {
resetCheckedItem(true);
- animateDropOntoScreen(animView, (ItemInfo) dragInfo, DROP_ANIM_DURATION, 0);
+ animateDropOntoScreen(animView, (ItemInfo) d.dragInfo, DROP_ANIM_DURATION, 0);
} else {
// Animate the icon/widget back to its original position
animateIntoPosition(animView, mDragViewOrigin[0], mDragViewOrigin[1], new Runnable() {
@@ -540,8 +528,6 @@ public class CustomizePagedView extends PagedViewWithDraggableItems
@Override
public void onClick(final View v) {
- // Return early if this is not initiated from a touch
- if (!v.isInTouchMode()) return;
// Return early if we are still animating the pages
if (mNextPage != INVALID_PAGE) return;
@@ -868,14 +854,13 @@ public class CustomizePagedView extends PagedViewWithDraggableItems
/**
* This method will extract the preview image specified by the widget developer (if it exists),
* otherwise, it will try to generate a default image preview with the widget's package icon.
- * This method must be safe to call from a background thread
- * @return the Bitmap that will be wrapped in a FastBitmapDrawable and used and sized in the
- * ImageView to represent the widget
+ * @return the drawable that will be used and sized in the ImageView to represent the widget
*/
- private Bitmap getWidgetPreview(AppWidgetProviderInfo info) {
+ private FastBitmapDrawable getWidgetPreview(AppWidgetProviderInfo info) {
final PackageManager packageManager = mPackageManager;
String packageName = info.provider.getPackageName();
Drawable drawable = null;
+ FastBitmapDrawable newDrawable = null;
if (info.previewImage != 0) {
drawable = packageManager.getDrawable(packageName, info.previewImage, null);
if (drawable == null) {
@@ -885,14 +870,14 @@ public class CustomizePagedView extends PagedViewWithDraggableItems
}
// If we don't have a preview image, create a default one
+ final int minDim = mWorkspaceWidgetLayout.estimateCellWidth(1);
+ final int maxDim = mWorkspaceWidgetLayout.estimateCellWidth(3);
if (drawable == null) {
Resources resources = mLauncher.getResources();
// Create a new bitmap to hold the widget preview
- int width = (int) (Math.max(mMinWidgetPreviewDim,
- Math.min(mMaxWidgetPreviewDim, info.minWidth)) * sScaleFactor);
- int height = (int) (Math.max(mMinWidgetPreviewDim,
- Math.min(mMaxWidgetPreviewDim, info.minHeight)) * sScaleFactor);
+ int width = (int) (Math.max(minDim, Math.min(maxDim, info.minWidth)) * sScaleFactor);
+ int height = (int) (Math.max(minDim, Math.min(maxDim, info.minHeight)) * sScaleFactor);
final Bitmap bitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);
final Drawable background = resources.getDrawable(R.drawable.default_widget_preview);
renderDrawableToBitmap(background, bitmap, 0, 0, width, height, 1.0f, 1.0f);
@@ -907,23 +892,23 @@ public class CustomizePagedView extends PagedViewWithDraggableItems
icon = resources.getDrawable(R.drawable.ic_launcher_application);
}
- final int iconSize = mMinWidgetPreviewDim / 2;
+ final int iconSize = minDim / 2;
final int offset = iconSize / 4;
renderDrawableToBitmap(icon, null, offset, offset, iconSize, iconSize, 1.0f, 1.0f);
} catch (Resources.NotFoundException e) {
// if we can't find the icon, then just don't draw it
}
- return bitmap;
+ newDrawable = new FastBitmapDrawable(bitmap);
} else {
// Scale down the preview if necessary
final float imageWidth = drawable.getIntrinsicWidth();
final float imageHeight = drawable.getIntrinsicHeight();
final float aspect = (float) imageWidth / imageHeight;
- final int scaledWidth = (int) (Math.max(mMinWidgetPreviewDim,
- Math.min(mMaxWidgetPreviewDim, imageWidth)) * sScaleFactor);
- final int scaledHeight = (int) (Math.max(mMinWidgetPreviewDim,
- Math.min(mMaxWidgetPreviewDim, imageHeight)) * sScaleFactor);
+ final int scaledWidth =
+ (int) (Math.max(minDim, Math.min(maxDim, imageWidth)) * sScaleFactor);
+ final int scaledHeight =
+ (int) (Math.max(minDim, Math.min(maxDim, imageHeight)) * sScaleFactor);
int width;
int height;
if (aspect >= 1.0f) {
@@ -937,8 +922,11 @@ public class CustomizePagedView extends PagedViewWithDraggableItems
final Bitmap bitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);
renderDrawableToBitmap(drawable, bitmap, 0, 0, width, height, 1.0f, 1.0f);
- return bitmap;
+ newDrawable = new FastBitmapDrawable(bitmap);
}
+ newDrawable.setBounds(0, 0, newDrawable.getIntrinsicWidth(),
+ newDrawable.getIntrinsicHeight());
+ return newDrawable;
}
private void setupPage(PagedViewCellLayout layout) {
@@ -953,8 +941,6 @@ public class CustomizePagedView extends PagedViewWithDraggableItems
mWorkspaceWidgetLayout.setPadding(20, 10, 20, 0);
mMaxWidgetWidth = mWorkspaceWidgetLayout.estimateCellWidth(sMaxWidgetCellHSpan);
- mMinWidgetPreviewDim = mWorkspaceWidgetLayout.estimateCellWidth(1);
- mMaxWidgetPreviewDim = mWorkspaceWidgetLayout.estimateCellWidth(3);
}
private void syncWidgetPages() {
@@ -964,90 +950,43 @@ public class CustomizePagedView extends PagedViewWithDraggableItems
removeAllViews();
int numPages = relayoutWidgets();
for (int i = 0; i < numPages; ++i) {
- PagedViewExtendedLayout layout = new PagedViewExtendedLayout(getContext());
+ LinearLayout layout = new PagedViewExtendedLayout(getContext());
layout.setGravity(Gravity.CENTER_HORIZONTAL);
layout.setPadding(mPageLayoutPaddingLeft, mPageLayoutPaddingTop,
mPageLayoutPaddingRight, mPageLayoutPaddingBottom);
- if (i < (numPages - 1)) {
- layout.setHasFixedWidth(true);
- layout.setMinimumWidth(mMinPageWidth);
- }
+
addView(layout, new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.MATCH_PARENT));
}
}
- private static class AppWidgetsPageToSync {
- public AppWidgetsPageToSync(
- LinearLayout layout, ArrayList<AppWidgetProviderInfo> appWidgets) {
- mLayout = layout;
- mAppWidgets = (ArrayList<AppWidgetProviderInfo>) appWidgets.clone();
- mAppWidgetBitmaps = new ArrayList<Bitmap>(appWidgets.size());
- }
- public int mPage;
- public LinearLayout mLayout;
- public ArrayList<AppWidgetProviderInfo> mAppWidgets;
- public ArrayList<Bitmap> mAppWidgetBitmaps;
- }
-
private void syncWidgetPageItems(int page) {
+ // ensure that we have the right number of items on the pages
LinearLayout layout = (LinearLayout) getChildAt(page);
+ final ArrayList<AppWidgetProviderInfo> list = mWidgetPages.get(page);
+ final int count = list.size();
+ final int numPages = getPageCount();
layout.removeAllViews();
- AppWidgetsPageToSync pageToSync =
- new AppWidgetsPageToSync(layout, mWidgetPages.get(page));
-
- // Load the widget previews in the bcakground
- new SyncWidgetPageItemsTask().execute(pageToSync);
- }
-
- private class SyncWidgetPageItemsTask extends
- AsyncTask<AppWidgetsPageToSync, Void, AppWidgetsPageToSync> {
- protected AppWidgetsPageToSync doInBackground(AppWidgetsPageToSync... args) {
- if (args.length != 1) {
- throw new RuntimeException("Wrong number of args to SyncWidgetPageItemsTask");
- }
- AppWidgetsPageToSync pageToSync = args[0];
-
- // generating widgetPreviews on more than one thread at a time causes a crash
- synchronized(CustomizePagedView.this) {
- // Load whatever was not in the cache
- int numWidgets = pageToSync.mAppWidgets.size();
- for (int i = 0; i < numWidgets; i++) {
- AppWidgetProviderInfo info = pageToSync.mAppWidgets.get(i);
- pageToSync.mAppWidgetBitmaps.add(getWidgetPreview(info));
- }
- }
- return pageToSync;
- }
+ for (int i = 0; i < count; ++i) {
+ final AppWidgetProviderInfo info = (AppWidgetProviderInfo) list.get(i);
+ final PendingAddWidgetInfo createItemInfo = new PendingAddWidgetInfo(info, null, null);
+ final int[] cellSpans = CellLayout.rectToCell(getResources(), info.minWidth,
+ info.minHeight, null);
+ final FastBitmapDrawable icon = getWidgetPreview(info);
+ final boolean createHolographicOutlines = (numPages > 1);
- protected void onPostExecute(AppWidgetsPageToSync pageToSync) {
- LinearLayout layout = (LinearLayout) pageToSync.mLayout;
- final int numPages = getPageCount();
- final int numWidgets = pageToSync.mAppWidgets.size();
- for (int i = 0; i < numWidgets; ++i) {
- final AppWidgetProviderInfo info = pageToSync.mAppWidgets.get(i);
- final PendingAddWidgetInfo createItemInfo =
- new PendingAddWidgetInfo(info, null, null);
- final int[] cellSpans = CellLayout.rectToCell(getResources(), info.minWidth,
- info.minHeight, null);
-
- FastBitmapDrawable icon
- = new FastBitmapDrawable(pageToSync.mAppWidgetBitmaps.get(i));
- icon.setBounds(0, 0, icon.getIntrinsicWidth(), icon.getIntrinsicHeight());
-
- PagedViewWidget l = (PagedViewWidget) mInflater.inflate(
+ PagedViewWidget l = (PagedViewWidget) mInflater.inflate(
R.layout.customize_paged_view_widget, layout, false);
- l.applyFromAppWidgetProviderInfo(info, icon, mMaxWidgetWidth, cellSpans,
- mPageViewIconCache, (numPages > 1));
- l.setTag(createItemInfo);
- l.setOnClickListener(CustomizePagedView.this);
- l.setOnTouchListener(CustomizePagedView.this);
- l.setOnLongClickListener(CustomizePagedView.this);
+ l.applyFromAppWidgetProviderInfo(info, icon, mMaxWidgetWidth, cellSpans,
+ mPageViewIconCache, createHolographicOutlines);
+ l.setTag(createItemInfo);
+ l.setOnClickListener(this);
+ l.setOnTouchListener(this);
+ l.setOnLongClickListener(this);
- layout.addView(l);
- }
+ layout.addView(l);
}
}
@@ -1059,14 +998,11 @@ public class CustomizePagedView extends PagedViewWithDraggableItems
int numPages = (int) Math.ceil((float) (mWallpaperList.size() * mWallpaperCellHSpan) /
mMaxWallpaperCellHSpan);
for (int i = 0; i < numPages; ++i) {
- PagedViewExtendedLayout layout = new PagedViewExtendedLayout(getContext());
+ LinearLayout layout = new PagedViewExtendedLayout(getContext());
layout.setGravity(Gravity.CENTER_HORIZONTAL);
layout.setPadding(mPageLayoutPaddingLeft, mPageLayoutPaddingTop,
mPageLayoutPaddingRight, mPageLayoutPaddingBottom);
- if (i < (numPages - 1)) {
- layout.setHasFixedWidth(true);
- layout.setMinimumWidth(mMinPageWidth);
- }
+
addView(layout, new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.MATCH_PARENT));
@@ -1085,11 +1021,12 @@ public class CustomizePagedView extends PagedViewWithDraggableItems
for (int i = startIndex; i < endIndex; ++i) {
final ResolveInfo info = mWallpaperList.get(i);
final FastBitmapDrawable icon = getWallpaperPreview(info);
+ final boolean createHolographicOutlines = (numPages > 1);
PagedViewWidget l = (PagedViewWidget) mInflater.inflate(
R.layout.customize_paged_view_wallpaper, layout, false);
l.applyFromWallpaperInfo(info, mPackageManager, icon, mMaxWidgetWidth,
- mPageViewIconCache, (numPages > 1));
+ mPageViewIconCache, createHolographicOutlines);
l.setTag(info);
l.setOnClickListener(this);
@@ -1122,12 +1059,13 @@ public class CustomizePagedView extends PagedViewWithDraggableItems
for (int i = startIndex; i < endIndex; ++i) {
ResolveInfo info = list.get(i);
PendingAddItemInfo createItemInfo = new PendingAddItemInfo();
+ final boolean createHolographicOutlines = (numPages > 1);
PagedViewIcon icon = (PagedViewIcon) mInflater.inflate(
R.layout.customize_paged_view_item, layout, false);
icon.applyFromResolveInfo(info, mPackageManager, mPageViewIconCache,
((LauncherApplication) mLauncher.getApplication()).getIconCache(),
- (numPages > 1));
+ createHolographicOutlines);
switch (mCustomizationType) {
case WallpaperCustomization:
icon.setOnClickListener(this);
@@ -1181,9 +1119,11 @@ public class CustomizePagedView extends PagedViewWithDraggableItems
layout.removeAllViewsOnPage();
for (int i = startIndex; i < endIndex; ++i) {
final ApplicationInfo info = mApps.get(i);
+ final boolean createHolographicOutlines = (numPages > 1);
PagedViewIcon icon = (PagedViewIcon) mInflater.inflate(
R.layout.all_apps_paged_view_application, layout, false);
- icon.applyFromApplicationInfo(info, mPageViewIconCache, true, (numPages > 1));
+ icon.applyFromApplicationInfo(
+ info, mPageViewIconCache, true, createHolographicOutlines);
icon.setOnClickListener(this);
icon.setOnTouchListener(this);
icon.setOnLongClickListener(this);
@@ -1198,7 +1138,7 @@ public class CustomizePagedView extends PagedViewWithDraggableItems
@Override
protected void invalidatePageData() {
- if (mWaitingToDetermineRowsAndColumns || mWaitingToInitPages || mCellCountX <= 0 || mCellCountY <= 0) {
+ if (mWaitingToInitPages || mCellCountX <= 0 || mCellCountY <= 0) {
// We don't know our size yet, which means we haven't calculated cell count x/y;
// onMeasure will call us once we figure out our size
return;
@@ -1248,8 +1188,10 @@ public class CustomizePagedView extends PagedViewWithDraggableItems
}
// Set a min page width for PagedView layout if we have more than a single page
- if (enforceMinimumPagedWidths) {
- setMinimumWidthOverride((childCount > 1) ? mMinPageWidth : 0);
+ if (enforceMinimumPagedWidths && childCount > 1) {
+ setMinimumWidthOverride(mMinPageWidth);
+ } else {
+ resetMinimumWidthOverride();
}
// Bound the current page index
@@ -1287,11 +1229,11 @@ public class CustomizePagedView extends PagedViewWithDraggableItems
@Override
protected int getAssociatedLowerPageBound(int page) {
- return Math.max(0, page - 2);
+ return 0;
}
@Override
protected int getAssociatedUpperPageBound(int page) {
- return Math.min(page + 2, getChildCount() - 1);
+ return getChildCount();
}
@Override
diff --git a/src/com/android/launcher2/CustomizeTrayTabHost.java b/src/com/android/launcher2/CustomizeTrayTabHost.java
index c261bfb9c..578081859 100644
--- a/src/com/android/launcher2/CustomizeTrayTabHost.java
+++ b/src/com/android/launcher2/CustomizeTrayTabHost.java
@@ -16,8 +16,7 @@
package com.android.launcher2;
-import com.android.launcher.R;
-import com.android.launcher2.CustomizePagedView.CustomizationType;
+import java.util.Random;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -28,10 +27,14 @@ import android.content.res.Resources;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
+import android.view.ViewGroup;
import android.widget.TabHost;
import android.widget.TabWidget;
import android.widget.TextView;
+import com.android.launcher.R;
+import com.android.launcher2.CustomizePagedView.CustomizationType;
+
public class CustomizeTrayTabHost extends TabHost implements LauncherTransitionable {
// tags for the customization tabs
private static final String WIDGETS_TAG = "widgets";
@@ -104,8 +107,7 @@ public class CustomizeTrayTabHost extends TabHost implements LauncherTransitiona
getCustomizeFilterForTabTag(tabId);
if (newType != mCustomizePagedView.getCustomizationFilter()) {
// animate the changing of the tab content by fading pages in and out
- final Resources res = getResources();
- final int duration = res.getInteger(R.integer.config_tabTransitionTime);
+ final int duration = res.getInteger(R.integer.config_tabTransitionDuration);
final float alpha = mCustomizePagedView.getAlpha();
ValueAnimator alphaAnim = ObjectAnimator.ofFloat(mCustomizePagedView,
"alpha", alpha, 0.0f);
@@ -186,6 +188,14 @@ public class CustomizeTrayTabHost extends TabHost implements LauncherTransitiona
super.onLayout(changed, l, t, r, b);
}
+ @Override
+ public int getDescendantFocusability() {
+ if (getVisibility() != View.VISIBLE) {
+ return ViewGroup.FOCUS_BLOCK_DESCENDANTS;
+ }
+ return super.getDescendantFocusability();
+ }
+
CustomizationType getCustomizeFilterForTabTag(String tag) {
if (tag.equals(WIDGETS_TAG)) {
return CustomizationType.WidgetCustomization;
diff --git a/src/com/android/launcher2/DeleteDropTarget.java b/src/com/android/launcher2/DeleteDropTarget.java
new file mode 100644
index 000000000..5b3fd1e16
--- /dev/null
+++ b/src/com/android/launcher2/DeleteDropTarget.java
@@ -0,0 +1,166 @@
+/*
+ * 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.
+ */
+
+package com.android.launcher2;
+
+import android.animation.ObjectAnimator;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Color;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffColorFilter;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import com.android.launcher.R;
+
+public class DeleteDropTarget extends ButtonDropTarget {
+
+ private TextView mText;
+ private int mHoverColor = 0xFFFF0000;
+
+ public DeleteDropTarget(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public DeleteDropTarget(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+
+ // Get the drawable
+ mText = (TextView) findViewById(R.id.delete_target_text);
+
+ // Get the hover color
+ Resources r = getResources();
+ mHoverColor = r.getColor(R.color.delete_target_hover_tint);
+ mHoverPaint.setColorFilter(new PorterDuffColorFilter(
+ mHoverColor, PorterDuff.Mode.SRC_ATOP));
+ setBackgroundColor(mHoverColor);
+ getBackground().setAlpha(0);
+ }
+
+ private boolean isAllAppsApplication(DragSource source, Object info) {
+ return (source instanceof AppsCustomizePagedView) && (info instanceof ApplicationInfo);
+ }
+ private boolean isAllAppsWidget(DragSource source, Object info) {
+ return (source instanceof AppsCustomizePagedView) && (info instanceof PendingAddWidgetInfo);
+ }
+ private boolean isWorkspaceApplication(DragObject d) {
+ return (d.dragSource instanceof Workspace) && (d.dragInfo instanceof ShortcutInfo);
+ }
+ private boolean isWorkspaceWidget(DragObject d) {
+ return (d.dragSource instanceof Workspace) && (d.dragInfo instanceof LauncherAppWidgetInfo);
+ }
+ private boolean isWorkspaceFolder(DragObject d) {
+ return (d.dragSource instanceof Workspace) && (d.dragInfo instanceof FolderInfo);
+ }
+
+ @Override
+ public boolean acceptDrop(DragObject d) {
+ // We can remove everything including App shortcuts, folders, widgets, etc.
+ return true;
+ }
+
+ @Override
+ public void onDragStart(DragSource source, Object info, int dragAction) {
+ boolean isVisible = true;
+ boolean isUninstall = false;
+
+ // If we are dragging a widget from AppsCustomize, hide the delete target
+ if (isAllAppsWidget(source, info)) {
+ isVisible = false;
+ }
+
+ // 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
+ if (isAllAppsApplication(source, info)) {
+ ApplicationInfo appInfo = (ApplicationInfo) info;
+ if ((appInfo.flags & ApplicationInfo.DOWNLOADED_FLAG) != 0) {
+ isUninstall = true;
+ } else {
+ isVisible = false;
+ }
+ }
+
+ mActive = isVisible;
+ setVisibility(isVisible ? View.VISIBLE : View.GONE);
+ if (mText.getText().length() > 0) {
+ mText.setText(isUninstall ? R.string.delete_target_uninstall_label
+ : R.string.delete_target_label);
+ }
+ }
+
+ @Override
+ public void onDragEnd() {
+ super.onDragEnd();
+ mActive = false;
+ }
+
+ public void onDragEnter(DragObject d) {
+ super.onDragEnter(d);
+
+ ObjectAnimator anim = ObjectAnimator.ofInt(getBackground(), "alpha",
+ Color.alpha(mHoverColor));
+ anim.setDuration(mTransitionDuration);
+ anim.start();
+ }
+
+ public void onDragExit(DragObject d) {
+ super.onDragExit(d);
+
+ ObjectAnimator anim = ObjectAnimator.ofInt(getBackground(), "alpha", 0);
+ anim.setDuration(mTransitionDuration);
+ anim.start();
+ }
+
+ public void onDrop(DragObject d) {
+ ItemInfo item = (ItemInfo) d.dragInfo;
+
+ if (isAllAppsApplication(d.dragSource, item)) {
+ // Uninstall the application if it is being dragged from AppsCustomize
+ mLauncher.startApplicationUninstallActivity((ApplicationInfo) item);
+ } else if (isWorkspaceApplication(d)) {
+ LauncherModel.deleteItemFromDatabase(mLauncher, item);
+ } else if (isWorkspaceFolder(d)) {
+ // Remove the folder from the workspace and delete the contents from launcher model
+ FolderInfo folderInfo = (FolderInfo) item;
+ mLauncher.removeFolder(folderInfo);
+ LauncherModel.deleteFolderContentsFromDatabase(mLauncher, folderInfo);
+ } else if (isWorkspaceWidget(d)) {
+ // Remove the widget from the workspace
+ mLauncher.removeAppWidget((LauncherAppWidgetInfo) item);
+ LauncherModel.deleteItemFromDatabase(mLauncher, item);
+
+ final LauncherAppWidgetInfo launcherAppWidgetInfo = (LauncherAppWidgetInfo) item;
+ final LauncherAppWidgetHost appWidgetHost = mLauncher.getAppWidgetHost();
+ 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() {
+ appWidgetHost.deleteAppWidgetId(launcherAppWidgetInfo.appWidgetId);
+ }
+ }.start();
+ }
+ }
+ }
+}
diff --git a/src/com/android/launcher2/DeleteZone.java b/src/com/android/launcher2/DeleteZone.java
index 98d2b8366..025b292ff 100644
--- a/src/com/android/launcher2/DeleteZone.java
+++ b/src/com/android/launcher2/DeleteZone.java
@@ -16,8 +16,10 @@
package com.android.launcher2;
-import com.android.launcher.R;
-
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
@@ -29,10 +31,8 @@ import android.graphics.drawable.TransitionDrawable;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.AccelerateInterpolator;
-import android.view.animation.AlphaAnimation;
-import android.view.animation.Animation;
-import android.view.animation.AnimationSet;
-import android.view.animation.TranslateAnimation;
+
+import com.android.launcher.R;
public class DeleteZone extends IconDropTarget {
private static final int ORIENTATION_HORIZONTAL = 1;
@@ -42,10 +42,8 @@ public class DeleteZone extends IconDropTarget {
private static final int XLARGE_ANIMATION_DURATION = 200;
private static final int LEFT_DRAWABLE = 0;
- private AnimationSet mInAnimation;
- private AnimationSet mOutAnimation;
- private Animation mHandleInAnimation;
- private Animation mHandleOutAnimation;
+ private AnimatorSet mInAnimation;
+ private AnimatorSet mOutAnimation;
private int mOrientation;
private DragController mDragController;
@@ -63,14 +61,14 @@ public class DeleteZone extends IconDropTarget {
public DeleteZone(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
- final int srcColor = context.getResources().getColor(R.color.delete_color_filter);
+ final int srcColor = context.getResources().getColor(R.color.delete_target_hover_tint);
mHoverPaint.setColorFilter(new PorterDuffColorFilter(srcColor, PorterDuff.Mode.SRC_ATOP));
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DeleteZone, defStyle, 0);
mOrientation = a.getInt(R.styleable.DeleteZone_direction, ORIENTATION_HORIZONTAL);
a.recycle();
- if (LauncherApplication.isScreenXLarge()) {
+ if (LauncherApplication.isScreenLarge()) {
int tb = getResources().getDimensionPixelSize(
R.dimen.delete_zone_vertical_drag_padding);
int lr = getResources().getDimensionPixelSize(
@@ -83,7 +81,7 @@ public class DeleteZone extends IconDropTarget {
protected void onFinishInflate() {
super.onFinishInflate();
mTransition = (TransitionDrawable) getCompoundDrawables()[LEFT_DRAWABLE];
- if (LauncherApplication.isScreenXLarge()) {
+ if (LauncherApplication.isScreenLarge()) {
mTransition.setCrossFadeEnabled(false);
}
@@ -92,19 +90,17 @@ public class DeleteZone extends IconDropTarget {
mDragTextColor = r.getColor(R.color.workspace_delete_zone_drag_text_color);
}
- public boolean acceptDrop(DragSource source, int x, int y, int xOffset, int yOffset,
- DragView dragView, Object dragInfo) {
+ public boolean acceptDrop(DragObject d) {
return true;
}
- public void onDrop(DragSource source, int x, int y, int xOffset, int yOffset,
- DragView dragView, Object dragInfo) {
+ public void onDrop(DragObject d) {
if (!mDragAndDropEnabled) return;
- final ItemInfo item = (ItemInfo) dragInfo;
+ final ItemInfo item = (ItemInfo) d.dragInfo;
// On x-large screens, you can uninstall an app by dragging from all apps
- if (item instanceof ApplicationInfo && LauncherApplication.isScreenXLarge()) {
+ if (item instanceof ApplicationInfo && LauncherApplication.isScreenLarge()) {
mLauncher.startApplicationUninstallActivity((ApplicationInfo) item);
}
@@ -114,18 +110,12 @@ public class DeleteZone extends IconDropTarget {
if (item instanceof LauncherAppWidgetInfo) {
mLauncher.removeAppWidget((LauncherAppWidgetInfo) item);
}
- } else if (source instanceof UserFolder) {
- final UserFolder userFolder = (UserFolder) source;
- final UserFolderInfo userFolderInfo = (UserFolderInfo) userFolder.getInfo();
- // Item must be a ShortcutInfo otherwise it couldn't have been in the folder
- // in the first place.
- userFolderInfo.remove((ShortcutInfo)item);
}
- if (item instanceof UserFolderInfo) {
- final UserFolderInfo userFolderInfo = (UserFolderInfo)item;
- LauncherModel.deleteUserFolderContentsFromDatabase(mLauncher, userFolderInfo);
- mLauncher.removeFolder(userFolderInfo);
+ if (item instanceof FolderInfo) {
+ final FolderInfo folderInfo = (FolderInfo)item;
+ LauncherModel.deleteFolderContentsFromDatabase(mLauncher, folderInfo);
+ mLauncher.removeFolder(folderInfo);
} else if (item instanceof LauncherAppWidgetInfo) {
final LauncherAppWidgetInfo launcherAppWidgetInfo = (LauncherAppWidgetInfo) item;
final LauncherAppWidgetHost appWidgetHost = mLauncher.getAppWidgetHost();
@@ -143,21 +133,19 @@ public class DeleteZone extends IconDropTarget {
LauncherModel.deleteItemFromDatabase(mLauncher, item);
}
- public void onDragEnter(DragSource source, int x, int y, int xOffset, int yOffset,
- DragView dragView, Object dragInfo) {
+ public void onDragEnter(DragObject d) {
if (mDragAndDropEnabled) {
mTransition.reverseTransition(getTransitionAnimationDuration());
setTextColor(mDragTextColor);
- super.onDragEnter(source, x, y, xOffset, yOffset, dragView, dragInfo);
+ super.onDragEnter(d);
}
}
- public void onDragExit(DragSource source, int x, int y, int xOffset, int yOffset,
- DragView dragView, Object dragInfo) {
+ public void onDragExit(DragObject d) {
if (mDragAndDropEnabled) {
mTransition.reverseTransition(getTransitionAnimationDuration());
setTextColor(mTextColor);
- super.onDragExit(source, x, y, xOffset, yOffset, dragView, dragInfo);
+ super.onDragExit(d);
}
}
@@ -168,7 +156,7 @@ public class DeleteZone extends IconDropTarget {
getHitRect(mRegion);
mRegionF.set(mRegion);
- if (LauncherApplication.isScreenXLarge()) {
+ if (LauncherApplication.isScreenLarge()) {
// This region will be a "dead zone" for scrolling; make it extend to the edge of
// the screen so users don't accidentally trigger a scroll while deleting items
mRegionF.top = mLauncher.getWorkspace().getTop();
@@ -181,10 +169,10 @@ public class DeleteZone extends IconDropTarget {
mTransition.resetTransition();
createAnimations();
- startAnimation(mInAnimation);
+ mInAnimation.start();
if (mOverlappingViews != null) {
for (View view : mOverlappingViews) {
- view.startAnimation(mHandleOutAnimation);
+ createOutAlphaAnim(view).start();
}
}
setVisibility(VISIBLE);
@@ -196,68 +184,72 @@ public class DeleteZone extends IconDropTarget {
mActive = false;
mDragController.setDeleteRegion(null);
- if (mOutAnimation != null) startAnimation(mOutAnimation);
- if (mHandleInAnimation != null && mOverlappingViews != null) {
+ mOutAnimation.start();
+ if (mOverlappingViews != null) {
for (View view : mOverlappingViews) {
- view.startAnimation(mHandleInAnimation);
+ createInAlphaAnim(view).start();
}
}
- setVisibility(GONE);
}
}
+ private Animator createAlphaAnim(View v, float start, float end) {
+ Animator anim = ObjectAnimator.ofFloat(v, "alpha", start, end);
+ anim.setDuration(getAnimationDuration());
+ return anim;
+ }
+ private Animator createInAlphaAnim(View v) {
+ return createAlphaAnim(v, 0f, 1f);
+ }
+ private Animator createOutAlphaAnim(View v) {
+ return createAlphaAnim(v, 1f, 0f);
+ }
+
private void createAnimations() {
int duration = getAnimationDuration();
- if (mHandleInAnimation == null) {
- mHandleInAnimation = new AlphaAnimation(0.0f, 1.0f);
- mHandleInAnimation.setDuration(duration);
- }
+ Animator inAlphaAnim = createInAlphaAnim(this);
if (mInAnimation == null) {
- mInAnimation = new FastAnimationSet();
- if (!LauncherApplication.isScreenXLarge()) {
- final AnimationSet animationSet = mInAnimation;
- animationSet.setInterpolator(new AccelerateInterpolator());
- animationSet.addAnimation(new AlphaAnimation(0.0f, 1.0f));
+ mInAnimation = new AnimatorSet();
+ mInAnimation.setInterpolator(new AccelerateInterpolator());
+ mInAnimation.setDuration(duration);
+ if (!LauncherApplication.isScreenLarge()) {
+ Animator translateAnim;
if (mOrientation == ORIENTATION_HORIZONTAL) {
- animationSet.addAnimation(new TranslateAnimation(Animation.ABSOLUTE, 0.0f,
- Animation.ABSOLUTE, 0.0f, Animation.RELATIVE_TO_SELF, 1.0f,
- Animation.RELATIVE_TO_SELF, 0.0f));
+ translateAnim = ObjectAnimator.ofFloat(this, "translationY",
+ getMeasuredWidth(), 0f);
} else {
- animationSet.addAnimation(new TranslateAnimation(Animation.RELATIVE_TO_SELF,
- 1.0f, Animation.RELATIVE_TO_SELF, 0.0f, Animation.ABSOLUTE, 0.0f,
- Animation.ABSOLUTE, 0.0f));
+ translateAnim = ObjectAnimator.ofFloat(this, "translationX",
+ getMeasuredHeight(), 0f);
}
- animationSet.setDuration(duration);
+ mInAnimation.playTogether(translateAnim, inAlphaAnim);
} else {
- mInAnimation.addAnimation(mHandleInAnimation);
+ mInAnimation.play(inAlphaAnim);
}
}
- if (mHandleOutAnimation == null) {
- mHandleOutAnimation = new AlphaAnimation(1.0f, 0.0f);
- mHandleOutAnimation.setFillAfter(true);
- mHandleOutAnimation.setDuration(duration);
- }
-
+ Animator outAlphaAnim = createOutAlphaAnim(this);
if (mOutAnimation == null) {
- mOutAnimation = new FastAnimationSet();
- if (!LauncherApplication.isScreenXLarge()) {
- final AnimationSet animationSet = mOutAnimation;
- animationSet.setInterpolator(new AccelerateInterpolator());
- animationSet.addAnimation(new AlphaAnimation(1.0f, 0.0f));
+ mOutAnimation = new AnimatorSet();
+ mOutAnimation.setInterpolator(new AccelerateInterpolator());
+ mOutAnimation.setDuration(duration);
+ if (!LauncherApplication.isScreenLarge()) {
+ Animator translateAnim;
if (mOrientation == ORIENTATION_HORIZONTAL) {
- animationSet.addAnimation(new FastTranslateAnimation(Animation.ABSOLUTE, 0.0f,
- Animation.ABSOLUTE, 0.0f, Animation.RELATIVE_TO_SELF, 0.0f,
- Animation.RELATIVE_TO_SELF, 1.0f));
+ translateAnim = ObjectAnimator.ofFloat(this, "translationY", 0f,
+ getMeasuredWidth());
} else {
- animationSet.addAnimation(new FastTranslateAnimation(Animation.RELATIVE_TO_SELF,
- 0.0f, Animation.RELATIVE_TO_SELF, 1.0f, Animation.ABSOLUTE, 0.0f,
- Animation.ABSOLUTE, 0.0f));
+ translateAnim = ObjectAnimator.ofFloat(this, "translationX", 0f,
+ getMeasuredHeight());
}
- animationSet.setDuration(duration);
+ mOutAnimation.playTogether(translateAnim, outAlphaAnim);
} else {
- mOutAnimation.addAnimation(mHandleOutAnimation);
+ mOutAnimation.addListener(new AnimatorListenerAdapter() {
+ public void onAnimationEnd(Animator animation) {
+ setVisibility(GONE);
+ }
+ });
+ mOutAnimation.play(outAlphaAnim);
}
}
}
@@ -267,46 +259,12 @@ public class DeleteZone extends IconDropTarget {
}
private int getTransitionAnimationDuration() {
- return LauncherApplication.isScreenXLarge() ?
+ return LauncherApplication.isScreenLarge() ?
XLARGE_TRANSITION_DURATION : TRANSITION_DURATION;
}
private int getAnimationDuration() {
- return LauncherApplication.isScreenXLarge() ?
+ return LauncherApplication.isScreenLarge() ?
XLARGE_ANIMATION_DURATION : ANIMATION_DURATION;
}
-
- private static class FastTranslateAnimation extends TranslateAnimation {
- public FastTranslateAnimation(int fromXType, float fromXValue, int toXType, float toXValue,
- int fromYType, float fromYValue, int toYType, float toYValue) {
- super(fromXType, fromXValue, toXType, toXValue,
- fromYType, fromYValue, toYType, toYValue);
- }
-
- @Override
- public boolean willChangeTransformationMatrix() {
- return true;
- }
-
- @Override
- public boolean willChangeBounds() {
- return false;
- }
- }
-
- private static class FastAnimationSet extends AnimationSet {
- FastAnimationSet() {
- super(false);
- }
-
- @Override
- public boolean willChangeTransformationMatrix() {
- return true;
- }
-
- @Override
- public boolean willChangeBounds() {
- return false;
- }
- }
}
diff --git a/src/com/android/launcher2/DragController.java b/src/com/android/launcher2/DragController.java
index cb4509b21..5b1b20a68 100644
--- a/src/com/android/launcher2/DragController.java
+++ b/src/com/android/launcher2/DragController.java
@@ -16,8 +16,6 @@
package com.android.launcher2;
-import java.util.ArrayList;
-
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Rect;
@@ -36,6 +34,8 @@ import android.view.inputmethod.InputMethodManager;
import com.android.launcher.R;
+import java.util.ArrayList;
+
/**
* Class for initiating a drag within a view or across multiple views.
*/
@@ -73,10 +73,10 @@ public class DragController {
private boolean mDragging;
/** X coordinate of the down event. */
- private float mMotionDownX;
+ private int mMotionDownX;
/** Y coordinate of the down event. */
- private float mMotionDownY;
+ private int mMotionDownY;
/** Info about the screen for clamping. */
private DisplayMetrics mDisplayMetrics = new DisplayMetrics();
@@ -84,25 +84,12 @@ public class DragController {
/** Original view that is being dragged. */
private View mOriginator;
- /** X offset from the upper-left corner of the cell to where we touched. */
- private float mTouchOffsetX;
-
- /** Y offset from the upper-left corner of the cell to where we touched. */
- private float mTouchOffsetY;
-
/** the area at the edge of the screen that makes the workspace go left
* or right while you're dragging.
*/
private int mScrollZone;
- /** Where the drag originated */
- private DragSource mDragSource;
-
- /** The data associated with the object being dragged */
- private Object mDragInfo;
-
- /** The view that moves around while you drag. */
- private DragView mDragView;
+ private DropTarget.DragObject mDragObject = new DropTarget.DragObject();
/** Who can receive drop events */
private ArrayList<DropTarget> mDropTargets = new ArrayList<DropTarget>();
@@ -289,22 +276,24 @@ public class DragController {
listener.onDragStart(source, dragInfo, dragAction);
}
- int registrationX = ((int)mMotionDownX) - screenX;
- int registrationY = ((int)mMotionDownY) - screenY;
+ final int registrationX = ((int)mMotionDownX) - screenX;
+ final int registrationY = ((int)mMotionDownY) - screenY;
final int dragRegionLeft = dragRegion == null ? 0 : dragRegion.left;
final int dragRegionTop = dragRegion == null ? 0 : dragRegion.top;
- mTouchOffsetX = mMotionDownX - screenX - dragRegionLeft;
- mTouchOffsetY = mMotionDownY - screenY - dragRegionTop;
mDragging = true;
- mDragSource = source;
- mDragInfo = dragInfo;
+
+ mDragObject.dragComplete = false;
+ mDragObject.xOffset = mMotionDownX - (screenX + dragRegionLeft);
+ mDragObject.yOffset = mMotionDownY - (screenY + dragRegionTop);
+ mDragObject.dragSource = source;
+ mDragObject.dragInfo = dragInfo;
mVibrator.vibrate(VIBRATE_DURATION);
- DragView dragView = mDragView = new DragView(mContext, b, registrationX, registrationY,
- 0, 0, b.getWidth(), b.getHeight());
+ final DragView dragView = mDragObject.dragView = new DragView(mContext, b, registrationX,
+ registrationY, 0, 0, b.getWidth(), b.getHeight());
final DragSource dragSource = source;
dragView.setOnDrawRunnable(new Runnable() {
@@ -314,8 +303,7 @@ public class DragController {
});
if (dragRegion != null) {
- dragView.setDragRegion(dragRegionLeft, dragRegion.top,
- dragRegion.right - dragRegionLeft, dragRegion.bottom - dragRegionTop);
+ dragView.setDragRegion(new Rect(dragRegion));
}
dragView.show(mWindowToken, (int)mMotionDownX, (int)mMotionDownY);
@@ -386,7 +374,8 @@ public class DragController {
public void cancelDrag() {
if (mDragging) {
// Should we also be calling onDragExit() here?
- mDragSource.onDropCompleted(null, mDragInfo, false);
+ mDragObject.dragComplete = true;
+ mDragObject.dragSource.onDropCompleted(null, mDragObject, false);
}
endDrag();
}
@@ -400,9 +389,9 @@ public class DragController {
for (DragListener listener : mListeners) {
listener.onDragEnd();
}
- if (mDragView != null) {
- mDragView.remove();
- mDragView = null;
+ if (mDragObject.dragView != null) {
+ mDragObject.dragView.remove();
+ mDragObject.dragView = null;
}
}
}
@@ -459,33 +448,29 @@ public class DragController {
}
private void handleMoveEvent(int x, int y) {
- mDragView.move(x, y);
+ mDragObject.dragView.move(x, y);
// Drop on someone?
final int[] coordinates = mCoordinatesTemp;
DropTarget dropTarget = findDropTarget(x, y, coordinates);
+ mDragObject.x = coordinates[0];
+ mDragObject.y = coordinates[1];
if (dropTarget != null) {
- DropTarget delegate = dropTarget.getDropTargetDelegate(
- mDragSource, coordinates[0], coordinates[1],
- (int) mTouchOffsetX, (int) mTouchOffsetY, mDragView, mDragInfo);
+ DropTarget delegate = dropTarget.getDropTargetDelegate(mDragObject);
if (delegate != null) {
dropTarget = delegate;
}
if (mLastDropTarget != dropTarget) {
if (mLastDropTarget != null) {
- mLastDropTarget.onDragExit(mDragSource, coordinates[0], coordinates[1],
- (int) mTouchOffsetX, (int) mTouchOffsetY, mDragView, mDragInfo);
+ mLastDropTarget.onDragExit(mDragObject);
}
- dropTarget.onDragEnter(mDragSource, coordinates[0], coordinates[1],
- (int) mTouchOffsetX, (int) mTouchOffsetY, mDragView, mDragInfo);
+ dropTarget.onDragEnter(mDragObject);
}
- dropTarget.onDragOver(mDragSource, coordinates[0], coordinates[1],
- (int) mTouchOffsetX, (int) mTouchOffsetY, mDragView, mDragInfo);
+ dropTarget.onDragOver(mDragObject);
} else {
if (mLastDropTarget != null) {
- mLastDropTarget.onDragExit(mDragSource, coordinates[0], coordinates[1],
- (int) mTouchOffsetX, (int) mTouchOffsetY, mDragView, mDragInfo);
+ mLastDropTarget.onDragExit(mDragObject);
}
}
mLastDropTarget = dropTarget;
@@ -578,18 +563,18 @@ public class DragController {
final int[] coordinates = mCoordinatesTemp;
final DropTarget dropTarget = findDropTarget((int) x, (int) y, coordinates);
+ mDragObject.x = coordinates[0];
+ mDragObject.y = coordinates[1];
boolean accepted = false;
if (dropTarget != null) {
- dropTarget.onDragExit(mDragSource, coordinates[0], coordinates[1],
- (int) mTouchOffsetX, (int) mTouchOffsetY, mDragView, mDragInfo);
- if (dropTarget.acceptDrop(mDragSource, coordinates[0], coordinates[1],
- (int) mTouchOffsetX, (int) mTouchOffsetY, mDragView, mDragInfo)) {
- dropTarget.onDrop(mDragSource, coordinates[0], coordinates[1],
- (int) mTouchOffsetX, (int) mTouchOffsetY, mDragView, mDragInfo);
+ mDragObject.dragComplete = true;
+ dropTarget.onDragExit(mDragObject);
+ if (dropTarget.acceptDrop(mDragObject)) {
+ dropTarget.onDrop(mDragObject);
accepted = true;
}
}
- mDragSource.onDropCompleted((View) dropTarget, mDragInfo, accepted);
+ mDragObject.dragSource.onDropCompleted((View) dropTarget, mDragObject, accepted);
}
private DropTarget findDropTarget(int x, int y, int[] dropCoordinates) {
@@ -608,9 +593,10 @@ public class DragController {
target.getLocationOnScreen(dropCoordinates);
r.offset(dropCoordinates[0] - target.getLeft(), dropCoordinates[1] - target.getTop());
+ mDragObject.x = x;
+ mDragObject.y = y;
if (r.contains(x, y)) {
- DropTarget delegate = target.getDropTargetDelegate(mDragSource,
- x, y, (int)mTouchOffsetX, (int)mTouchOffsetY, mDragView, mDragInfo);
+ DropTarget delegate = target.getDropTargetDelegate(mDragObject);
if (delegate != null) {
target = delegate;
target.getLocationOnScreen(dropCoordinates);
@@ -701,7 +687,7 @@ public class DragController {
}
DragView getDragView() {
- return mDragView;
+ return mDragObject.dragView;
}
private class ScrollRunnable implements Runnable {
diff --git a/src/com/android/launcher2/DragLayer.java b/src/com/android/launcher2/DragLayer.java
index eb539450f..af47bea78 100644
--- a/src/com/android/launcher2/DragLayer.java
+++ b/src/com/android/launcher2/DragLayer.java
@@ -16,10 +16,11 @@
package com.android.launcher2;
-import com.android.launcher.R;
+import java.util.ArrayList;
import android.content.Context;
import android.graphics.Bitmap;
+import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.MotionEvent;
@@ -27,6 +28,8 @@ import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageView;
+import com.android.launcher.R;
+
/**
* A ViewGroup that coordinates dragging across its descendants
*/
@@ -34,6 +37,14 @@ public class DragLayer extends FrameLayout {
private DragController mDragController;
private int[] mTmpXY = new int[2];
+ // Variables relating to resizing widgets
+ private final ArrayList<AppWidgetResizeFrame> mResizeFrames =
+ new ArrayList<AppWidgetResizeFrame>();
+ private AppWidgetResizeFrame mCurrentResizeFrame;
+ private int mXDown, mYDown;
+ private Folder mCurrentFolder = null;
+ private Launcher mLauncher;
+
/**
* Used to create a new DragLayer from XML.
*
@@ -47,7 +58,8 @@ public class DragLayer extends FrameLayout {
setMotionEventSplittingEnabled(false);
}
- public void setDragController(DragController controller) {
+ public void setup(Launcher launcher, DragController controller) {
+ mLauncher = launcher;
mDragController = controller;
}
@@ -56,31 +68,78 @@ public class DragLayer extends FrameLayout {
return mDragController.dispatchKeyEvent(event) || super.dispatchKeyEvent(event);
}
+ private boolean handleTouchDown(MotionEvent ev) {
+ Rect hitRect = new Rect();
+ int x = (int) ev.getX();
+ int y = (int) ev.getY();
+
+ for (AppWidgetResizeFrame child: mResizeFrames) {
+ child.getHitRect(hitRect);
+ if (hitRect.contains(x, y)) {
+ if (child.beginResizeIfPointInRegion(x - child.getLeft(), y - child.getTop())) {
+ mCurrentResizeFrame = child;
+ mXDown = x;
+ mYDown = y;
+ requestDisallowInterceptTouchEvent(true);
+ return true;
+ }
+ }
+ }
+ if (mCurrentFolder != null) {
+ mCurrentFolder.getHitRect(hitRect);
+ int[] screenPos = new int[2];
+ View parent = (View) mCurrentFolder.getParent();
+ if (parent != null) {
+ parent.getLocationOnScreen(screenPos);
+ hitRect.offset(screenPos[0], screenPos[1]);
+ if (!hitRect.contains(x, y)) {
+ mLauncher.closeFolder();
+ }
+ }
+ }
+ return false;
+ }
+
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
- // If the current CellLayoutChildren has a resize frame, we need to detect if any touch
- // event has occurred which doesn't result in resizing a widget. In this case, we
- // dismiss any visible resize frames.
- final Workspace w = (Workspace) findViewById(R.id.workspace);
- if (w != null) {
- final CellLayout currentPage = (CellLayout) w.getChildAt(w.getCurrentPage());
- final CellLayoutChildren childrenLayout = currentPage.getChildrenLayout();
-
- if (childrenLayout.hasResizeFrames() && !childrenLayout.isWidgetBeingResized()) {
- post(new Runnable() {
- public void run() {
- if (!childrenLayout.isWidgetBeingResized()) {
- childrenLayout.clearAllResizeFrames();
- }
- }
- });
+ if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+ if (handleTouchDown(ev)) {
+ return true;
}
}
+ clearAllResizeFrames();
return mDragController.onInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
+ boolean handled = false;
+ int action = ev.getAction();
+
+ int x = (int) ev.getX();
+ int y = (int) ev.getY();
+
+ if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+ if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+ if (handleTouchDown(ev)) {
+ return true;
+ }
+ }
+ }
+
+ if (mCurrentResizeFrame != null) {
+ handled = true;
+ switch (action) {
+ case MotionEvent.ACTION_MOVE:
+ mCurrentResizeFrame.visualizeResizeForDelta(x - mXDown, y - mYDown);
+ break;
+ case MotionEvent.ACTION_CANCEL:
+ case MotionEvent.ACTION_UP:
+ mCurrentResizeFrame.commitResizeForDelta(x - mXDown, y - mYDown);
+ mCurrentResizeFrame = null;
+ }
+ }
+ if (handled) return true;
return mDragController.onTouchEvent(ev);
}
@@ -103,4 +162,98 @@ public class DragLayer extends FrameLayout {
v.getLocationOnScreen(mTmpXY);
return createDragView(mDragController.getViewBitmap(v), mTmpXY[0], mTmpXY[1]);
}
+
+ public static class LayoutParams extends FrameLayout.LayoutParams {
+ public int x, y;
+ public boolean customPosition = false;
+
+ /**
+ * {@inheritDoc}
+ */
+ public LayoutParams(int width, int height) {
+ super(width, height);
+ }
+
+ public void setWidth(int width) {
+ this.width = width;
+ }
+
+ public int getWidth() {
+ return width;
+ }
+
+ public void setHeight(int height) {
+ this.height = height;
+ }
+
+ public int getHeight() {
+ return height;
+ }
+
+ public void setX(int x) {
+ this.x = x;
+ }
+
+ public int getX() {
+ return x;
+ }
+
+ public void setY(int y) {
+ this.y = y;
+ }
+
+ public int getY() {
+ return y;
+ }
+ }
+
+ protected void onLayout(boolean changed, int l, int t, int r, int b) {
+ super.onLayout(changed, l, t, r, b);
+ int count = getChildCount();
+ for (int i = 0; i < count; i++) {
+ View child = getChildAt(i);
+ final FrameLayout.LayoutParams flp = (FrameLayout.LayoutParams) child.getLayoutParams();
+ if (flp instanceof LayoutParams) {
+ final LayoutParams lp = (LayoutParams) flp;
+ if (lp.customPosition) {
+ child.layout(lp.x, lp.y, lp.x + lp.width, lp.y + lp.height);
+ }
+ }
+ }
+ }
+
+ public void clearAllResizeFrames() {
+ if (mResizeFrames.size() > 0) {
+ for (AppWidgetResizeFrame frame: mResizeFrames) {
+ removeView(frame);
+ }
+ mResizeFrames.clear();
+ }
+ }
+
+ public boolean hasResizeFrames() {
+ return mResizeFrames.size() > 0;
+ }
+
+ public boolean isWidgetBeingResized() {
+ return mCurrentResizeFrame != null;
+ }
+
+ public void addResizeFrame(ItemInfo itemInfo, LauncherAppWidgetHostView widget,
+ CellLayout cellLayout) {
+ AppWidgetResizeFrame resizeFrame = new AppWidgetResizeFrame(getContext(),
+ itemInfo, widget, cellLayout, this);
+
+ LayoutParams lp = new LayoutParams(-1, -1);
+ lp.customPosition = true;
+
+ addView(resizeFrame, lp);
+ mResizeFrames.add(resizeFrame);
+
+ resizeFrame.snapToWidget(false);
+ }
+
+ public void setCurrentFolder(Folder f) {
+ mCurrentFolder = f;
+ }
}
diff --git a/src/com/android/launcher2/DragSource.java b/src/com/android/launcher2/DragSource.java
index 4dbdaf71a..2a8f263a5 100644
--- a/src/com/android/launcher2/DragSource.java
+++ b/src/com/android/launcher2/DragSource.java
@@ -18,18 +18,18 @@ package com.android.launcher2;
import android.view.View;
+import com.android.launcher2.DropTarget.DragObject;
+
/**
* Interface defining an object that can originate a drag.
*
*/
public interface DragSource {
- void setDragController(DragController dragger);
-
/**
* Callback from the DragController when it begins drawing the drag view.
* This allows the DragSource to dim or hide the original view.
*/
void onDragViewVisible();
- void onDropCompleted(View target, Object dragInfo, boolean success);
+ void onDropCompleted(View target, DragObject d, boolean success);
}
diff --git a/src/com/android/launcher2/DragView.java b/src/com/android/launcher2/DragView.java
index 45620b90b..b02e22b16 100644
--- a/src/com/android/launcher2/DragView.java
+++ b/src/com/android/launcher2/DragView.java
@@ -26,6 +26,7 @@ import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PixelFormat;
+import android.graphics.Rect;
import android.os.IBinder;
import android.view.Gravity;
import android.view.View;
@@ -42,10 +43,7 @@ public class DragView extends View {
private int mRegistrationX;
private int mRegistrationY;
- private int mDragRegionLeft = 0;
- private int mDragRegionTop = 0;
- private int mDragRegionWidth;
- private int mDragRegionHeight;
+ private Rect mDragRegion = null;
ValueAnimator mAnim;
private float mOffsetX = 0.0f;
@@ -87,8 +85,8 @@ public class DragView extends View {
scale.setScale(scaleFactor, scaleFactor);
}
- final int offsetX = res.getInteger(R.integer.config_dragViewOffsetX);
- final int offsetY = res.getInteger(R.integer.config_dragViewOffsetY);
+ final int offsetX = res.getDimensionPixelSize(R.dimen.dragViewOffsetX);
+ final int offsetY = res.getDimensionPixelSize(R.dimen.dragViewOffsetY);
// Animate the view into the correct position
mAnim = ValueAnimator.ofFloat(0.0f, 1.0f);
@@ -117,7 +115,7 @@ public class DragView extends View {
});
mBitmap = Bitmap.createBitmap(bitmap, left, top, width, height, scale, true);
- setDragRegion(0, 0, width, height);
+ setDragRegion(new Rect(0, 0, width, height));
// The point in our scaled bitmap that the touch events are located
mRegistrationX = registrationX;
@@ -132,31 +130,32 @@ public class DragView extends View {
return mOffsetY;
}
- public void setDragRegion(int left, int top, int width, int height) {
- mDragRegionLeft = left;
- mDragRegionTop = top;
- mDragRegionWidth = width;
- mDragRegionHeight = height;
- }
-
public void setOnDrawRunnable(Runnable r) {
mOnDrawRunnable = r;
}
public int getDragRegionLeft() {
- return mDragRegionLeft;
+ return mDragRegion.left;
}
public int getDragRegionTop() {
- return mDragRegionTop;
+ return mDragRegion.top;
}
public int getDragRegionWidth() {
- return mDragRegionWidth;
+ return mDragRegion.width();
}
public int getDragRegionHeight() {
- return mDragRegionHeight;
+ return mDragRegion.height();
+ }
+
+ public void setDragRegion(Rect r) {
+ mDragRegion = r;
+ }
+
+ public Rect getDragRegion() {
+ return mDragRegion;
}
@Override
diff --git a/src/com/android/launcher2/DropTarget.java b/src/com/android/launcher2/DropTarget.java
index 308dbbee3..6e18479ac 100644
--- a/src/com/android/launcher2/DropTarget.java
+++ b/src/com/android/launcher2/DropTarget.java
@@ -23,6 +23,36 @@ import android.graphics.Rect;
*
*/
public interface DropTarget {
+
+ class DragObject {
+ public int x = -1;
+ public int y = -1;
+
+ /** X offset from the upper-left corner of the cell to where we touched. */
+ public int xOffset = -1;
+
+ /** Y offset from the upper-left corner of the cell to where we touched. */
+ public int yOffset = -1;
+
+ /** This indicates whether a drag is in final stages, either drop or cancel. It
+ * differentiates onDragExit, since this is called when the drag is ending, above
+ * the current drag target, or when the drag moves off the current drag object.
+ */
+ public boolean dragComplete = false;
+
+ /** The view that moves around while you drag. */
+ public DragView dragView = null;
+
+ /** The data associated with the object being dragged */
+ public Object dragInfo = null;
+
+ /** Where the drag originated */
+ public DragSource dragSource = null;
+
+ public DragObject() {
+ }
+ }
+
/**
* Used to temporarily disable certain drop targets
*
@@ -44,17 +74,13 @@ public interface DropTarget {
* @param dragInfo Data associated with the object being dragged
*
*/
- void onDrop(DragSource source, int x, int y, int xOffset, int yOffset,
- DragView dragView, Object dragInfo);
-
- void onDragEnter(DragSource source, int x, int y, int xOffset, int yOffset,
- DragView dragView, Object dragInfo);
+ void onDrop(DragObject dragObject);
+
+ void onDragEnter(DragObject dragObject);
- void onDragOver(DragSource source, int x, int y, int xOffset, int yOffset,
- DragView dragView, Object dragInfo);
+ void onDragOver(DragObject dragObject);
- void onDragExit(DragSource source, int x, int y, int xOffset, int yOffset,
- DragView dragView, Object dragInfo);
+ void onDragExit(DragObject dragObject);
/**
* Allows a DropTarget to delegate drag and drop events to another object.
@@ -73,8 +99,7 @@ public interface DropTarget {
*
* @return The DropTarget to delegate to, or null to not delegate to another object.
*/
- DropTarget getDropTargetDelegate(DragSource source, int x, int y, int xOffset, int yOffset,
- DragView dragView, Object dragInfo);
+ DropTarget getDropTargetDelegate(DragObject dragObject);
/**
* Check if a drop action can occur at, or near, the requested location.
@@ -91,8 +116,7 @@ public interface DropTarget {
* @param dragInfo Data associated with the object being dragged
* @return True if the drop will be accepted, false otherwise.
*/
- boolean acceptDrop(DragSource source, int x, int y, int xOffset, int yOffset,
- DragView dragView, Object dragInfo);
+ boolean acceptDrop(DragObject dragObject);
// These methods are implemented in Views
void getHitRect(Rect outRect);
diff --git a/src/com/android/launcher2/FastBitmapDrawable.java b/src/com/android/launcher2/FastBitmapDrawable.java
index a45329467..3e75fb6d0 100644
--- a/src/com/android/launcher2/FastBitmapDrawable.java
+++ b/src/com/android/launcher2/FastBitmapDrawable.java
@@ -49,6 +49,11 @@ class FastBitmapDrawable extends Drawable {
}
@Override
+ public void setColorFilter(ColorFilter cf) {
+ mPaint.setColorFilter(cf);
+ }
+
+ @Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
@@ -64,10 +69,6 @@ class FastBitmapDrawable extends Drawable {
}
@Override
- public void setColorFilter(ColorFilter cf) {
- }
-
- @Override
public int getIntrinsicWidth() {
return mWidth;
}
diff --git a/src/com/android/launcher2/FocusHelper.java b/src/com/android/launcher2/FocusHelper.java
new file mode 100644
index 000000000..25d941b65
--- /dev/null
+++ b/src/com/android/launcher2/FocusHelper.java
@@ -0,0 +1,938 @@
+/*
+ * 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.
+ */
+
+package com.android.launcher2;
+
+import android.content.res.Configuration;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewParent;
+import android.widget.TabHost;
+import android.widget.TabWidget;
+
+import com.android.launcher.R;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+
+/**
+ * A keyboard listener we set on all the button bar buttons.
+ */
+class ButtonBarKeyEventListener implements View.OnKeyListener {
+ @Override
+ public boolean onKey(View v, int keyCode, KeyEvent event) {
+ return FocusHelper.handleButtonBarButtonKeyEvent(v, keyCode, event);
+ }
+}
+
+/**
+ * A keyboard listener we set on the indicator buttons.
+ */
+class IndicatorKeyEventListener implements View.OnKeyListener {
+ @Override
+ public boolean onKey(View v, int keyCode, KeyEvent event) {
+ return FocusHelper.handleIndicatorButtonKeyEvent(v, keyCode, event);
+ }
+}
+
+/**
+ * A keyboard listener we set on all the dock buttons.
+ */
+class DockKeyEventListener implements View.OnKeyListener {
+ @Override
+ public boolean onKey(View v, int keyCode, KeyEvent event) {
+ final Configuration configuration = v.getResources().getConfiguration();
+ return FocusHelper.handleDockButtonKeyEvent(v, keyCode, event, configuration.orientation);
+ }
+}
+
+/**
+ * A keyboard listener we set on the last tab button in AppsCustomize to jump to then
+ * market icon and vice versa.
+ */
+class AppsCustomizeTabKeyEventListener implements View.OnKeyListener {
+ @Override
+ public boolean onKey(View v, int keyCode, KeyEvent event) {
+ return FocusHelper.handleAppsCustomizeTabKeyEvent(v, keyCode, event);
+ }
+}
+
+public class FocusHelper {
+ /**
+ * Private helper to get the parent TabHost in the view hiearchy.
+ */
+ private static TabHost findTabHostParent(View v) {
+ ViewParent p = v.getParent();
+ while (p != null && !(p instanceof TabHost)) {
+ p = p.getParent();
+ }
+ return (TabHost) p;
+ }
+
+ /**
+ * Handles key events in a AppsCustomize tab between the last tab view and the shop button.
+ */
+ static boolean handleAppsCustomizeTabKeyEvent(View v, int keyCode, KeyEvent e) {
+ final TabHost tabHost = findTabHostParent(v);
+ final ViewGroup contents = (ViewGroup)
+ tabHost.findViewById(com.android.internal.R.id.tabcontent);
+ final View shop = tabHost.findViewById(R.id.market_button);
+
+ final int action = e.getAction();
+ final boolean handleKeyEvent = (action != KeyEvent.ACTION_UP);
+ boolean wasHandled = false;
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_DPAD_RIGHT:
+ if (handleKeyEvent) {
+ // Select the shop button if we aren't on it
+ if (v != shop) {
+ shop.requestFocus();
+ }
+ }
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_DPAD_DOWN:
+ if (handleKeyEvent) {
+ // Select the content view (down is handled by the tab key handler otherwise)
+ if (v == shop) {
+ contents.requestFocus();
+ wasHandled = true;
+ }
+ }
+ break;
+ default: break;
+ }
+ return wasHandled;
+ }
+
+ /**
+ * Private helper to determine whether a view is visible.
+ */
+ private static boolean isVisible(View v) {
+ return v.getVisibility() == View.VISIBLE;
+ }
+
+ /**
+ * Handles key events in a PageViewExtendedLayout containing PagedViewWidgets.
+ */
+ static boolean handlePagedViewGridLayoutWidgetKeyEvent(PagedViewWidget w, int keyCode,
+ KeyEvent e) {
+
+ final PagedViewGridLayout parent = (PagedViewGridLayout) w.getParent();
+ final ViewGroup container = (ViewGroup) parent.getParent();
+ final TabHost tabHost = findTabHostParent(container);
+ final TabWidget tabs = (TabWidget) tabHost.findViewById(com.android.internal.R.id.tabs);
+ final int widgetIndex = parent.indexOfChild(w);
+ final int widgetCount = parent.getChildCount();
+ final int pageIndex = container.indexOfChild(parent);
+ final int pageCount = container.getChildCount();
+ final int cellCountX = parent.getCellCountX();
+ final int cellCountY = parent.getCellCountY();
+ final int x = widgetIndex % cellCountX;
+ final int y = widgetIndex / cellCountX;
+
+ final int action = e.getAction();
+ final boolean handleKeyEvent = (action != KeyEvent.ACTION_UP);
+ PagedViewGridLayout newParent = null;
+ boolean wasHandled = false;
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_DPAD_LEFT:
+ if (handleKeyEvent) {
+ // Select the previous widget or the last widget on the previous page
+ if (widgetIndex > 0) {
+ parent.getChildAt(widgetIndex - 1).requestFocus();
+ } else {
+ if (pageIndex > 0) {
+ newParent = (PagedViewGridLayout)
+ container.getChildAt(pageIndex - 1);
+ newParent.getChildAt(newParent.getChildCount() - 1).requestFocus();
+ }
+ }
+ }
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_DPAD_RIGHT:
+ if (handleKeyEvent) {
+ // Select the next widget or the first widget on the next page
+ if (widgetIndex < (widgetCount - 1)) {
+ parent.getChildAt(widgetIndex + 1).requestFocus();
+ } else {
+ if (pageIndex < (pageCount - 1)) {
+ newParent = (PagedViewGridLayout)
+ container.getChildAt(pageIndex + 1);
+ newParent.getChildAt(0).requestFocus();
+ }
+ }
+ }
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_DPAD_UP:
+ if (handleKeyEvent) {
+ // Select the closest icon in the previous row, otherwise select the tab bar
+ if (y > 0) {
+ int newWidgetIndex = ((y - 1) * cellCountX) + x;
+ parent.getChildAt(newWidgetIndex).requestFocus();
+ } else {
+ tabs.requestFocus();
+ }
+ }
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_DPAD_DOWN:
+ if (handleKeyEvent) {
+ // Select the closest icon in the previous row, otherwise do nothing
+ if (y < (cellCountY - 1)) {
+ int newWidgetIndex = Math.min(widgetCount - 1, ((y + 1) * cellCountX) + x);
+ parent.getChildAt(newWidgetIndex).requestFocus();
+ }
+ }
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_ENTER:
+ case KeyEvent.KEYCODE_DPAD_CENTER:
+ if (handleKeyEvent) {
+ // Simulate a click on the widget
+ View.OnClickListener clickListener = (View.OnClickListener) container;
+ clickListener.onClick(w);
+ }
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_PAGE_UP:
+ if (handleKeyEvent) {
+ // Select the first item on the previous page, or the first item on this page
+ // if there is no previous page
+ if (pageIndex > 0) {
+ newParent = (PagedViewGridLayout) container.getChildAt(pageIndex - 1);
+ newParent.getChildAt(0).requestFocus();
+ } else {
+ parent.getChildAt(0).requestFocus();
+ }
+ }
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_PAGE_DOWN:
+ if (handleKeyEvent) {
+ // Select the first item on the next page, or the last item on this page
+ // if there is no next page
+ if (pageIndex < (pageCount - 1)) {
+ newParent = (PagedViewGridLayout) container.getChildAt(pageIndex + 1);
+ newParent.getChildAt(0).requestFocus();
+ } else {
+ parent.getChildAt(widgetCount - 1).requestFocus();
+ }
+ }
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_MOVE_HOME:
+ if (handleKeyEvent) {
+ // Select the first item on this page
+ parent.getChildAt(0).requestFocus();
+ }
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_MOVE_END:
+ if (handleKeyEvent) {
+ // Select the last item on this page
+ parent.getChildAt(widgetCount - 1).requestFocus();
+ }
+ wasHandled = true;
+ break;
+ default: break;
+ }
+ return wasHandled;
+ }
+
+ /**
+ * Private helper method to get the PagedViewCellLayoutChildren given a PagedViewCellLayout
+ * index.
+ */
+ private static PagedViewCellLayoutChildren getPagedViewCellLayoutChildrenForIndex(
+ ViewGroup container, int i) {
+ ViewGroup parent = (ViewGroup) container.getChildAt(i);
+ return (PagedViewCellLayoutChildren) parent.getChildAt(0);
+ }
+
+ /**
+ * Handles key events in a PageViewCellLayout containing PagedViewIcons.
+ */
+ static boolean handlePagedViewIconKeyEvent(PagedViewIcon v, int keyCode, KeyEvent e) {
+ final PagedViewCellLayoutChildren parent = (PagedViewCellLayoutChildren) v.getParent();
+ final PagedViewCellLayout parentLayout = (PagedViewCellLayout) parent.getParent();
+ // Note we have an extra parent because of the
+ // PagedViewCellLayout/PagedViewCellLayoutChildren relationship
+ final ViewGroup container = (ViewGroup) parentLayout.getParent();
+ final TabHost tabHost = findTabHostParent(container);
+ final TabWidget tabs = (TabWidget) tabHost.findViewById(com.android.internal.R.id.tabs);
+ final int widgetIndex = parent.indexOfChild(v);
+ final int widgetCount = parent.getChildCount();
+ final int pageIndex = container.indexOfChild(parentLayout);
+ final int pageCount = container.getChildCount();
+ final int cellCountX = parentLayout.getCellCountX();
+ final int cellCountY = parentLayout.getCellCountY();
+ final int x = widgetIndex % cellCountX;
+ final int y = widgetIndex / cellCountX;
+
+ final int action = e.getAction();
+ final boolean handleKeyEvent = (action != KeyEvent.ACTION_UP);
+ PagedViewCellLayoutChildren newParent = null;
+ boolean wasHandled = false;
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_DPAD_LEFT:
+ if (handleKeyEvent) {
+ // Select the previous icon or the last icon on the previous page
+ if (widgetIndex > 0) {
+ parent.getChildAt(widgetIndex - 1).requestFocus();
+ } else {
+ if (pageIndex > 0) {
+ newParent = getPagedViewCellLayoutChildrenForIndex(container,
+ pageIndex - 1);
+ newParent.getChildAt(newParent.getChildCount() - 1).requestFocus();
+ }
+ }
+ }
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_DPAD_RIGHT:
+ if (handleKeyEvent) {
+ // Select the next icon or the first icon on the next page
+ if (widgetIndex < (widgetCount - 1)) {
+ parent.getChildAt(widgetIndex + 1).requestFocus();
+ } else {
+ if (pageIndex < (pageCount - 1)) {
+ newParent = getPagedViewCellLayoutChildrenForIndex(container,
+ pageIndex + 1);
+ newParent.getChildAt(0).requestFocus();
+ }
+ }
+ }
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_DPAD_UP:
+ if (handleKeyEvent) {
+ // Select the closest icon in the previous row, otherwise select the tab bar
+ if (y > 0) {
+ int newWidgetIndex = ((y - 1) * cellCountX) + x;
+ parent.getChildAt(newWidgetIndex).requestFocus();
+ } else {
+ tabs.requestFocus();
+ }
+ }
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_DPAD_DOWN:
+ if (handleKeyEvent) {
+ // Select the closest icon in the previous row, otherwise do nothing
+ if (y < (cellCountY - 1)) {
+ int newWidgetIndex = Math.min(widgetCount - 1, ((y + 1) * cellCountX) + x);
+ parent.getChildAt(newWidgetIndex).requestFocus();
+ }
+ }
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_ENTER:
+ case KeyEvent.KEYCODE_DPAD_CENTER:
+ if (handleKeyEvent) {
+ // Simulate a click on the icon
+ View.OnClickListener clickListener = (View.OnClickListener) container;
+ clickListener.onClick(v);
+ }
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_PAGE_UP:
+ if (handleKeyEvent) {
+ // Select the first icon on the previous page, or the first icon on this page
+ // if there is no previous page
+ if (pageIndex > 0) {
+ newParent = getPagedViewCellLayoutChildrenForIndex(container,
+ pageIndex - 1);
+ newParent.getChildAt(0).requestFocus();
+ } else {
+ parent.getChildAt(0).requestFocus();
+ }
+ }
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_PAGE_DOWN:
+ if (handleKeyEvent) {
+ // Select the first icon on the next page, or the last icon on this page
+ // if there is no next page
+ if (pageIndex < (pageCount - 1)) {
+ newParent = getPagedViewCellLayoutChildrenForIndex(container,
+ pageIndex + 1);
+ newParent.getChildAt(0).requestFocus();
+ } else {
+ parent.getChildAt(widgetCount - 1).requestFocus();
+ }
+ }
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_MOVE_HOME:
+ if (handleKeyEvent) {
+ // Select the first icon on this page
+ parent.getChildAt(0).requestFocus();
+ }
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_MOVE_END:
+ if (handleKeyEvent) {
+ // Select the last icon on this page
+ parent.getChildAt(widgetCount - 1).requestFocus();
+ }
+ wasHandled = true;
+ break;
+ default: break;
+ }
+ return wasHandled;
+ }
+
+ /**
+ * Handles key events in the tab widget.
+ */
+ static boolean handleTabKeyEvent(AccessibleTabView v, int keyCode, KeyEvent e) {
+ if (!LauncherApplication.isScreenLarge()) return false;
+
+ final FocusOnlyTabWidget parent = (FocusOnlyTabWidget) v.getParent();
+ final TabHost tabHost = findTabHostParent(parent);
+ final ViewGroup contents = (ViewGroup)
+ tabHost.findViewById(com.android.internal.R.id.tabcontent);
+ final int tabCount = parent.getTabCount();
+ final int tabIndex = parent.getChildTabIndex(v);
+
+ final int action = e.getAction();
+ final boolean handleKeyEvent = (action != KeyEvent.ACTION_UP);
+ boolean wasHandled = false;
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_DPAD_LEFT:
+ if (handleKeyEvent) {
+ // Select the previous tab
+ if (tabIndex > 0) {
+ parent.getChildTabViewAt(tabIndex - 1).requestFocus();
+ }
+ }
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_DPAD_RIGHT:
+ if (handleKeyEvent) {
+ // Select the next tab, or if the last tab has a focus right id, select that
+ if (tabIndex < (tabCount - 1)) {
+ parent.getChildTabViewAt(tabIndex + 1).requestFocus();
+ } else {
+ if (v.getNextFocusRightId() != View.NO_ID) {
+ tabHost.findViewById(v.getNextFocusRightId()).requestFocus();
+ }
+ }
+ }
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_DPAD_UP:
+ // Do nothing
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_DPAD_DOWN:
+ if (handleKeyEvent) {
+ // Select the content view
+ contents.requestFocus();
+ }
+ wasHandled = true;
+ break;
+ default: break;
+ }
+ return wasHandled;
+ }
+
+ /**
+ * Handles key events in the workspace button bar.
+ */
+ static boolean handleButtonBarButtonKeyEvent(View v, int keyCode, KeyEvent e) {
+ if (!LauncherApplication.isScreenLarge()) return false;
+
+ final ViewGroup parent = (ViewGroup) v.getParent();
+ final ViewGroup launcher = (ViewGroup) parent.getParent();
+ final Workspace workspace = (Workspace) launcher.findViewById(R.id.workspace);
+ final int buttonIndex = parent.indexOfChild(v);
+ final int buttonCount = parent.getChildCount();
+ final int pageIndex = workspace.getCurrentPage();
+ final int pageCount = workspace.getChildCount();
+ final int firstButtonIndex = parent.indexOfChild(parent.findViewById(R.id.search_button));
+ final int lastButtonIndex = parent.indexOfChild(parent.findViewById(R.id.configure_button));
+
+ final int action = e.getAction();
+ final boolean handleKeyEvent = (action != KeyEvent.ACTION_UP);
+ boolean wasHandled = false;
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_DPAD_LEFT:
+ if (handleKeyEvent) {
+ // Select the previous button, otherwise do nothing (since the button bar is
+ // static)
+ if (buttonIndex > firstButtonIndex) {
+ int newButtonIndex = buttonIndex - 1;
+ while (newButtonIndex >= firstButtonIndex) {
+ View prev = parent.getChildAt(newButtonIndex);
+ if (isVisible(prev) && prev.isFocusable()) {
+ prev.requestFocus();
+ break;
+ }
+ --newButtonIndex;
+ }
+ } else {
+ if (pageIndex > 0) {
+ // Snap to previous page and clear focus
+ workspace.snapToPage(pageIndex - 1);
+ }
+ }
+ }
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_DPAD_RIGHT:
+ if (handleKeyEvent) {
+ // Select the next button, otherwise do nothing (since the button bar is
+ // static)
+ if (buttonIndex < lastButtonIndex) {
+ int newButtonIndex = buttonIndex + 1;
+ while (newButtonIndex <= lastButtonIndex) {
+ View next = parent.getChildAt(newButtonIndex);
+ if (isVisible(next) && next.isFocusable()) {
+ next.requestFocus();
+ break;
+ }
+ ++newButtonIndex;
+ }
+ } else {
+ if (pageIndex < (pageCount - 1)) {
+ // Snap to next page and clear focus
+ workspace.snapToPage(pageIndex + 1);
+ }
+ }
+ }
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_DPAD_UP:
+ // Do nothing
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_DPAD_DOWN:
+ if (handleKeyEvent) {
+ // Select the first bubble text view in the current page of the workspace
+ final CellLayout layout = (CellLayout) workspace.getChildAt(pageIndex);
+ final CellLayoutChildren children = layout.getChildrenLayout();
+ final View newIcon = getBubbleTextViewInDirection(layout, children, -1, 1);
+ if (newIcon != null) {
+ newIcon.requestFocus();
+ } else {
+ workspace.requestFocus();
+ }
+ }
+ wasHandled = true;
+ break;
+ default: break;
+ }
+ return wasHandled;
+ }
+
+ /**
+ * Handles key events in the prev/next indicators.
+ */
+ static boolean handleIndicatorButtonKeyEvent(View v, int keyCode, KeyEvent e) {
+ final ViewGroup launcher = (ViewGroup) v.getParent();
+ final Workspace workspace = (Workspace) launcher.findViewById(R.id.workspace);
+ final ViewGroup hotseat = (ViewGroup) launcher.findViewById(R.id.all_apps_button_cluster);
+ final View previousIndicator = launcher.findViewById(R.id.previous_screen);
+ final View nextIndicator = launcher.findViewById(R.id.next_screen);
+ final int pageIndex = workspace.getCurrentPage();
+ final int pageCount = workspace.getChildCount();
+
+ final int action = e.getAction();
+ final boolean handleKeyEvent = (action != KeyEvent.ACTION_UP);
+ boolean wasHandled = false;
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_DPAD_LEFT:
+ if (handleKeyEvent) {
+ if (v == previousIndicator) {
+ if (pageIndex > 0) {
+ // Snap to previous page and clear focus
+ workspace.snapToPage(pageIndex - 1);
+ }
+ } else if (v == nextIndicator) {
+ // Select the last button in the hot seat
+ hotseat.getChildAt(hotseat.getChildCount() - 1).requestFocus();
+ }
+ }
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_DPAD_RIGHT:
+ if (handleKeyEvent) {
+ if (v == previousIndicator) {
+ // Select the first button in the hot seat
+ hotseat.getChildAt(0).requestFocus();
+ } else if (v == nextIndicator) {
+ if (pageIndex < (pageCount - 1)) {
+ // Snap to next page and clear focus
+ workspace.snapToPage(pageIndex + 1);
+ }
+ }
+ }
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_DPAD_UP:
+ if (handleKeyEvent) {
+ // Select the first bubble text view in the current page of the workspace
+ final CellLayout layout = (CellLayout) workspace.getChildAt(pageIndex);
+ final CellLayoutChildren children = layout.getChildrenLayout();
+ final View newIcon = getBubbleTextViewInDirection(layout, children, -1, 1);
+ if (newIcon != null) {
+ newIcon.requestFocus();
+ } else {
+ workspace.requestFocus();
+ }
+ }
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_DPAD_DOWN:
+ // Do nothing
+ wasHandled = true;
+ break;
+ default: break;
+ }
+ return wasHandled;
+ }
+
+ /**
+ * Handles key events in the workspace dock (bottom of the screen).
+ */
+ static boolean handleDockButtonKeyEvent(View v, int keyCode, KeyEvent e, int orientation) {
+ final ViewGroup parent = (ViewGroup) v.getParent();
+ final ViewGroup launcher = (ViewGroup) parent.getParent();
+ final Workspace workspace = (Workspace) launcher.findViewById(R.id.workspace);
+ final int buttonIndex = parent.indexOfChild(v);
+ final int buttonCount = parent.getChildCount();
+ final int pageIndex = workspace.getCurrentPage();
+ final int pageCount = workspace.getChildCount();
+ final View previousIndicator = launcher.findViewById(R.id.previous_screen);
+ final View nextIndicator = launcher.findViewById(R.id.next_screen);
+
+ // NOTE: currently we don't special case for the phone UI in different
+ // orientations, even though the dock is on the side in landscape mode. This
+ // is to ensure that accessibility consistency is maintained across rotations.
+
+ final int action = e.getAction();
+ final boolean handleKeyEvent = (action != KeyEvent.ACTION_UP);
+ boolean wasHandled = false;
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_DPAD_LEFT:
+ if (handleKeyEvent) {
+
+ // Select the previous button, otherwise select the previous page indicator
+ if (buttonIndex > 0) {
+ parent.getChildAt(buttonIndex - 1).requestFocus();
+ } else {
+ previousIndicator.requestFocus();
+ }
+ }
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_DPAD_RIGHT:
+ if (handleKeyEvent) {
+ // Select the next button, otherwise select the next page indicator
+ if (buttonIndex < (buttonCount - 1)) {
+ parent.getChildAt(buttonIndex + 1).requestFocus();
+ } else {
+ nextIndicator.requestFocus();
+ }
+ }
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_DPAD_UP:
+ if (handleKeyEvent) {
+ // Select the first bubble text view in the current page of the workspace
+ final CellLayout layout = (CellLayout) workspace.getChildAt(pageIndex);
+ final CellLayoutChildren children = layout.getChildrenLayout();
+ final View newIcon = getBubbleTextViewInDirection(layout, children, -1, 1);
+ if (newIcon != null) {
+ newIcon.requestFocus();
+ } else {
+ workspace.requestFocus();
+ }
+ }
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_DPAD_DOWN:
+ // Do nothing
+ wasHandled = true;
+ break;
+ default: break;
+ }
+ return wasHandled;
+ }
+
+ /**
+ * Private helper method to get the CellLayoutChildren given a CellLayout index.
+ */
+ private static CellLayoutChildren getCellLayoutChildrenForIndex(ViewGroup container, int i) {
+ ViewGroup parent = (ViewGroup) container.getChildAt(i);
+ return (CellLayoutChildren) parent.getChildAt(0);
+ }
+
+ /**
+ * Private helper method to sort all the CellLayout children in order of their (x,y) spatially
+ * from top left to bottom right.
+ */
+ private static ArrayList<View> getCellLayoutChildrenSortedSpatially(CellLayout layout,
+ ViewGroup parent) {
+ // First we order each the CellLayout children by their x,y coordinates
+ final int cellCountX = layout.getCountX();
+ final int count = parent.getChildCount();
+ ArrayList<View> views = new ArrayList<View>();
+ for (int j = 0; j < count; ++j) {
+ views.add(parent.getChildAt(j));
+ }
+ Collections.sort(views, new Comparator<View>() {
+ @Override
+ public int compare(View lhs, View rhs) {
+ CellLayout.LayoutParams llp = (CellLayout.LayoutParams) lhs.getLayoutParams();
+ CellLayout.LayoutParams rlp = (CellLayout.LayoutParams) rhs.getLayoutParams();
+ int lvIndex = (llp.cellY * cellCountX) + llp.cellX;
+ int rvIndex = (rlp.cellY * cellCountX) + rlp.cellX;
+ return lvIndex - rvIndex;
+ }
+ });
+ return views;
+ }
+ /**
+ * Private helper method to find the index of the next BubbleTextView in the delta direction.
+ * @param delta either -1 or 1 depending on the direction we want to search
+ */
+ private static View findIndexOfBubbleTextView(ArrayList<View> views, int i, int delta) {
+ // Then we find the next BubbleTextView offset by delta from i
+ final int count = views.size();
+ int newI = i + delta;
+ while (0 <= newI && newI < count) {
+ View newV = views.get(newI);
+ if (newV instanceof BubbleTextView) {
+ return newV;
+ }
+ newI += delta;
+ }
+ return null;
+ }
+ private static View getBubbleTextViewInDirection(CellLayout layout, ViewGroup parent, int i,
+ int delta) {
+ final ArrayList<View> views = getCellLayoutChildrenSortedSpatially(layout, parent);
+ return findIndexOfBubbleTextView(views, i, delta);
+ }
+ private static View getBubbleTextViewInDirection(CellLayout layout, ViewGroup parent, View v,
+ int delta) {
+ final ArrayList<View> views = getCellLayoutChildrenSortedSpatially(layout, parent);
+ return findIndexOfBubbleTextView(views, views.indexOf(v), delta);
+ }
+ /**
+ * Private helper method to find the next closest BubbleTextView in the delta direction on the
+ * next line.
+ * @param delta either -1 or 1 depending on the line and direction we want to search
+ */
+ private static View getClosestBubbleTextViewOnLine(CellLayout layout, ViewGroup parent, View v,
+ int lineDelta) {
+ final ArrayList<View> views = getCellLayoutChildrenSortedSpatially(layout, parent);
+ final CellLayout.LayoutParams lp = (CellLayout.LayoutParams) v.getLayoutParams();
+ final int cellCountX = layout.getCountX();
+ final int cellCountY = layout.getCountY();
+ final int row = lp.cellY;
+ final int newRow = row + lineDelta;
+ if (0 <= newRow && newRow < cellCountY) {
+ float closestDistance = Float.MAX_VALUE;
+ int closestIndex = -1;
+ int index = views.indexOf(v);
+ int endIndex = (lineDelta < 0) ? -1 : views.size();
+ while (index != endIndex) {
+ View newV = views.get(index);
+ CellLayout.LayoutParams tmpLp = (CellLayout.LayoutParams) newV.getLayoutParams();
+ boolean satisfiesRow = (lineDelta < 0) ? (tmpLp.cellY < row) : (tmpLp.cellY > row);
+ if (satisfiesRow && newV instanceof BubbleTextView) {
+ float tmpDistance = (float) Math.sqrt(Math.pow(tmpLp.cellX - lp.cellX, 2) +
+ Math.pow(tmpLp.cellY - lp.cellY, 2));
+ if (tmpDistance < closestDistance) {
+ closestIndex = index;
+ closestDistance = tmpDistance;
+ }
+ }
+ if (index <= endIndex) {
+ ++index;
+ } else {
+ --index;
+ }
+ }
+ if (closestIndex > -1) {
+ return views.get(closestIndex);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Handles key events in a Workspace containing BubbleTextView.
+ */
+ static boolean handleBubbleTextViewKeyEvent(BubbleTextView v, int keyCode, KeyEvent e) {
+ CellLayoutChildren parent = (CellLayoutChildren) v.getParent();
+ 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);
+ int iconIndex = parent.indexOfChild(v);
+ int iconCount = parent.getChildCount();
+ int pageIndex = workspace.indexOfChild(layout);
+ int pageCount = workspace.getChildCount();
+
+ final int action = e.getAction();
+ final boolean handleKeyEvent = (action != KeyEvent.ACTION_UP);
+ boolean wasHandled = false;
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_DPAD_LEFT:
+ if (handleKeyEvent) {
+ // Select the previous icon or the last icon on the previous page if possible
+ View newIcon = getBubbleTextViewInDirection(layout, parent, v, -1);
+ if (newIcon != null) {
+ newIcon.requestFocus();
+ } else {
+ if (pageIndex > 0) {
+ parent = getCellLayoutChildrenForIndex(workspace, pageIndex - 1);
+ newIcon = getBubbleTextViewInDirection(layout, parent,
+ parent.getChildCount(), -1);
+ if (newIcon != null) {
+ newIcon.requestFocus();
+ } else {
+ // Snap to the previous page
+ workspace.snapToPage(pageIndex - 1);
+ }
+ }
+ }
+ }
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_DPAD_RIGHT:
+ if (handleKeyEvent) {
+ // Select the next icon or the first icon on the next page if possible
+ View newIcon = getBubbleTextViewInDirection(layout, parent, v, 1);
+ if (newIcon != null) {
+ newIcon.requestFocus();
+ } else {
+ if (pageIndex < (pageCount - 1)) {
+ parent = getCellLayoutChildrenForIndex(workspace, pageIndex + 1);
+ newIcon = getBubbleTextViewInDirection(layout, parent, -1, 1);
+ if (newIcon != null) {
+ newIcon.requestFocus();
+ } else {
+ // Snap to the next page
+ workspace.snapToPage(pageIndex + 1);
+ }
+ }
+ }
+ }
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_DPAD_UP:
+ if (handleKeyEvent) {
+ // Select the closest icon in the previous line, otherwise select the tab bar
+ View newIcon = getClosestBubbleTextViewOnLine(layout, parent, v, -1);
+ if (newIcon != null) {
+ newIcon.requestFocus();
+ wasHandled = true;
+ } else {
+ tabs.requestFocus();
+ }
+ }
+ break;
+ case KeyEvent.KEYCODE_DPAD_DOWN:
+ if (handleKeyEvent) {
+ // Select the closest icon in the next line, otherwise select the tab bar
+ View newIcon = getClosestBubbleTextViewOnLine(layout, parent, v, 1);
+ if (newIcon != null) {
+ newIcon.requestFocus();
+ wasHandled = true;
+ }
+ }
+ break;
+ case KeyEvent.KEYCODE_PAGE_UP:
+ if (handleKeyEvent) {
+ // Select the first icon on the previous page or the first icon on this page
+ // if there is no previous page
+ if (pageIndex > 0) {
+ parent = getCellLayoutChildrenForIndex(workspace, pageIndex - 1);
+ View newIcon = getBubbleTextViewInDirection(layout, parent, -1, 1);
+ if (newIcon != null) {
+ newIcon.requestFocus();
+ } else {
+ // Snap to the previous page
+ workspace.snapToPage(pageIndex - 1);
+ }
+ } else {
+ View newIcon = getBubbleTextViewInDirection(layout, parent, -1, 1);
+ if (newIcon != null) {
+ newIcon.requestFocus();
+ }
+ }
+ }
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_PAGE_DOWN:
+ if (handleKeyEvent) {
+ // Select the first icon on the next page or the last icon on this page
+ // if there is no previous page
+ if (pageIndex < (pageCount - 1)) {
+ parent = getCellLayoutChildrenForIndex(workspace, pageIndex + 1);
+ View newIcon = getBubbleTextViewInDirection(layout, parent, -1, 1);
+ if (newIcon != null) {
+ newIcon.requestFocus();
+ } else {
+ // Snap to the next page
+ workspace.snapToPage(pageIndex + 1);
+ }
+ } else {
+ View newIcon = getBubbleTextViewInDirection(layout, parent,
+ parent.getChildCount(), -1);
+ if (newIcon != null) {
+ newIcon.requestFocus();
+ }
+ }
+ }
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_MOVE_HOME:
+ if (handleKeyEvent) {
+ // Select the first icon on this page
+ View newIcon = getBubbleTextViewInDirection(layout, parent, -1, 1);
+ if (newIcon != null) {
+ newIcon.requestFocus();
+ }
+ }
+ wasHandled = true;
+ break;
+ case KeyEvent.KEYCODE_MOVE_END:
+ if (handleKeyEvent) {
+ // Select the last icon on this page
+ View newIcon = getBubbleTextViewInDirection(layout, parent,
+ parent.getChildCount(), -1);
+ if (newIcon != null) {
+ newIcon.requestFocus();
+ }
+ }
+ wasHandled = true;
+ break;
+ default: break;
+ }
+ return wasHandled;
+ }
+}
diff --git a/src/com/android/launcher2/FocusOnlyTabWidget.java b/src/com/android/launcher2/FocusOnlyTabWidget.java
new file mode 100644
index 000000000..8e9f58c61
--- /dev/null
+++ b/src/com/android/launcher2/FocusOnlyTabWidget.java
@@ -0,0 +1,86 @@
+/*
+ * 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.
+ */
+
+package com.android.launcher2;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.TabWidget;
+
+public class FocusOnlyTabWidget extends TabWidget {
+ public FocusOnlyTabWidget(Context context) {
+ super(context);
+ }
+
+ public FocusOnlyTabWidget(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public FocusOnlyTabWidget(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ public View getSelectedTab() {
+ final int count = getTabCount();
+ for (int i = 0; i < count; ++i) {
+ View v = getChildTabViewAt(i);
+ if (v.isSelected()) {
+ return v;
+ }
+ }
+ return null;
+ }
+
+ public int getChildTabIndex(View v) {
+ final int tabCount = getTabCount();
+ for (int i = 0; i < tabCount; ++i) {
+ if (getChildTabViewAt(i) == v) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ public void setCurrentTabToFocusedTab() {
+ View tab = null;
+ int index = -1;
+ final int count = getTabCount();
+ for (int i = 0; i < count; ++i) {
+ View v = getChildTabViewAt(i);
+ if (v.hasFocus()) {
+ tab = v;
+ index = i;
+ break;
+ }
+ }
+ if (index > -1) {
+ super.setCurrentTab(index);
+ super.onFocusChange(tab, true);
+ }
+ }
+ public void superOnFocusChange(View v, boolean hasFocus) {
+ super.onFocusChange(v, hasFocus);
+ }
+
+ @Override
+ public void onFocusChange(android.view.View v, boolean hasFocus) {
+ if (v == this && hasFocus && getTabCount() > 0) {
+ getSelectedTab().requestFocus();
+ return;
+ }
+ }
+}
diff --git a/src/com/android/launcher2/Folder.java b/src/com/android/launcher2/Folder.java
index 059e73d8b..d81183c6b 100644
--- a/src/com/android/launcher2/Folder.java
+++ b/src/com/android/launcher2/Folder.java
@@ -16,40 +16,80 @@
package com.android.launcher2;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
+import android.animation.PropertyValuesHolder;
+import android.animation.ValueAnimator;
+import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.content.Context;
+import android.graphics.Color;
import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
-import android.widget.AbsListView;
+import android.view.animation.AccelerateInterpolator;
+import android.view.animation.DecelerateInterpolator;
import android.widget.AdapterView;
-import android.widget.BaseAdapter;
-import android.widget.Button;
import android.widget.LinearLayout;
+import android.widget.TextView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import com.android.launcher.R;
+import com.android.launcher2.FolderInfo.FolderListener;
+
+import java.util.ArrayList;
/**
* Represents a set of icons chosen by the user or generated by the system.
*/
public class Folder extends LinearLayout implements DragSource, OnItemLongClickListener,
- OnItemClickListener, OnClickListener, View.OnLongClickListener {
+ OnItemClickListener, OnClickListener, View.OnLongClickListener, DropTarget, FolderListener {
- protected AbsListView mContent;
protected DragController mDragController;
-
+
protected Launcher mLauncher;
- protected Button mCloseButton;
-
protected FolderInfo mInfo;
-
- /**
- * Which item is being dragged
- */
- protected ShortcutInfo mDragItem;
+
+ private static final String TAG = "Launcher.Folder";
+
+ static final int STATE_NONE = -1;
+ static final int STATE_SMALL = 0;
+ static final int STATE_ANIMATING = 1;
+ static final int STATE_OPEN = 2;
+
+ private int mExpandDuration;
+ protected CellLayout mContent;
+ private final LayoutInflater mInflater;
+ private final IconCache mIconCache;
+ private int mState = STATE_NONE;
+ private int[] mDragItemPosition = new int[2];
+ private static final int FULL_GROW = 0;
+ private static final int PARTIAL_GROW = 1;
+ private static final int REORDER_ANIMATION_DURATION = 230;
+ private static final int ON_EXIT_CLOSE_DELAY = 800;
+ private int mMode = PARTIAL_GROW;
+ private boolean mRearrangeOnClose = false;
+ private FolderIcon mFolderIcon;
+ private int mMaxCountX;
+ private int mMaxCountY;
+ private Rect mNewSize = new Rect();
+ private ArrayList<View> mItemsInReadingOrder = new ArrayList<View>();
+ private Drawable mIconDrawable;
+ boolean mItemsInvalidated = false;
+ private ShortcutInfo mCurrentDragInfo;
+ private View mCurrentDragView;
+ boolean mSuppressOnAdd = false;
+ private int[] mTargetCell = new int[2];
+ private int[] mPreviousTargetCell = new int[2];
+ private int[] mEmptyCell = new int[2];
+ private Alarm mReorderAlarm = new Alarm();
+ private Alarm mOnExitAlarm = new Alarm();
/**
* Used to inflate the Workspace from XML.
@@ -60,21 +100,22 @@ public class Folder extends LinearLayout implements DragSource, OnItemLongClickL
public Folder(Context context, AttributeSet attrs) {
super(context, attrs);
setAlwaysDrawnWithCacheEnabled(false);
+ mInflater = LayoutInflater.from(context);
+ mIconCache = ((LauncherApplication)context.getApplicationContext()).getIconCache();
+ mExpandDuration = getResources().getInteger(R.integer.config_folderAnimDuration);
+
+ mMaxCountX = LauncherModel.getCellCountX() - 1;
+ mMaxCountY = LauncherModel.getCellCountY() - 1;
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
-
- mContent = (AbsListView) findViewById(R.id.folder_content);
- mContent.setOnItemClickListener(this);
- mContent.setOnItemLongClickListener(this);
-
- mCloseButton = (Button) findViewById(R.id.folder_close);
- mCloseButton.setOnClickListener(this);
- mCloseButton.setOnLongClickListener(this);
+ mContent = (CellLayout) findViewById(R.id.folder_content);
+ mContent.setGridSize(0, 0);
+ mContent.enableHardwareLayers();
}
-
+
public void onItemClick(AdapterView parent, View v, int position, long id) {
ShortcutInfo app = (ShortcutInfo) parent.getItemAtPosition(position);
int[] pos = new int[2];
@@ -85,12 +126,54 @@ public class Folder extends LinearLayout implements DragSource, OnItemLongClickL
}
public void onClick(View v) {
- mLauncher.closeFolder(this);
+ Object tag = v.getTag();
+ if (tag instanceof ShortcutInfo) {
+ // refactor this code from Folder
+ ShortcutInfo item = (ShortcutInfo) tag;
+ int[] pos = new int[2];
+ v.getLocationOnScreen(pos);
+ item.intent.setSourceBounds(new Rect(pos[0], pos[1],
+ pos[0] + v.getWidth(), pos[1] + v.getHeight()));
+ mLauncher.startActivitySafely(item.intent, item);
+ }
}
public boolean onLongClick(View v) {
- mLauncher.closeFolder(this);
- mLauncher.showRenameDialog(mInfo);
+ Object tag = v.getTag();
+ if (tag instanceof ShortcutInfo) {
+ ShortcutInfo item = (ShortcutInfo) tag;
+ if (!v.isInTouchMode()) {
+ return false;
+ }
+
+ mLauncher.getWorkspace().onDragStartedWithItem(v);
+ mDragController.startDrag(v, this, item, DragController.DRAG_ACTION_COPY);
+ mDragItemPosition[0] = item.cellX;
+ mDragItemPosition[1] = item.cellY;
+ mIconDrawable = ((TextView) v).getCompoundDrawables()[1];
+
+ mCurrentDragInfo = item;
+ mEmptyCell[0] = item.cellX;
+ mEmptyCell[1] = item.cellY;
+ mCurrentDragView = v;
+ mContent.removeView(mCurrentDragView);
+ mInfo.remove(item);
+ } else {
+ mLauncher.closeFolder(this);
+ mLauncher.showRenameDialog(mInfo);
+ }
+ return true;
+ }
+
+ public Drawable getDragDrawable() {
+ return mIconDrawable;
+ }
+
+ /**
+ * We need to handle touch events to prevent them from falling through to the workspace below.
+ */
+ @Override
+ public boolean onTouchEvent(MotionEvent ev) {
return true;
}
@@ -103,42 +186,24 @@ public class Folder extends LinearLayout implements DragSource, OnItemLongClickL
mDragController.startDrag(view, this, app, DragController.DRAG_ACTION_COPY);
mLauncher.closeFolder(this);
- mDragItem = app;
-
return true;
}
- @Override
public void setDragController(DragController dragController) {
mDragController = dragController;
}
- @Override
- public void onDropCompleted(View target, Object dragInfo, boolean success) {
- }
-
- @Override
public void onDragViewVisible() {
}
- /**
- * Sets the adapter used to populate the content area. The adapter must only
- * contains ShortcutInfo items.
- *
- * @param adapter The list of applications to display in the folder.
- */
- void setContentAdapter(BaseAdapter adapter) {
- mContent.setAdapter(adapter);
+ void setLauncher(Launcher launcher) {
+ mLauncher = launcher;
}
- void notifyDataSetChanged() {
- ((BaseAdapter) mContent.getAdapter()).notifyDataSetChanged();
+ void setFolderIcon(FolderIcon icon) {
+ mFolderIcon = icon;
}
- void setLauncher(Launcher launcher) {
- mLauncher = launcher;
- }
-
/**
* @return the FolderInfo object associated with this folder
*/
@@ -146,10 +211,12 @@ public class Folder extends LinearLayout implements DragSource, OnItemLongClickL
return mInfo;
}
- // When the folder opens, we need to refresh the GridView's selection by
- // forcing a layout
void onOpen() {
+ // When the folder opens, we need to refresh the GridView's selection by
+ // forcing a layout
+ // TODO: find out if this is still necessary
mContent.requestLayout();
+ requestFocus();
}
void onClose() {
@@ -159,6 +226,533 @@ public class Folder extends LinearLayout implements DragSource, OnItemLongClickL
void bind(FolderInfo info) {
mInfo = info;
- mCloseButton.setText(info.title);
+ ArrayList<ShortcutInfo> children = info.contents;
+ setupContentForNumItems(children.size());
+ for (int i = 0; i < children.size(); i++) {
+ ShortcutInfo child = (ShortcutInfo) children.get(i);
+ createAndAddShortcut(child);
+ }
+ mItemsInvalidated = true;
+ mInfo.addListener(this);
+ }
+
+ /**
+ * Creates a new UserFolder, inflated from R.layout.user_folder.
+ *
+ * @param context The application's context.
+ *
+ * @return A new UserFolder.
+ */
+ static Folder fromXml(Context context) {
+ return (Folder) LayoutInflater.from(context).inflate(R.layout.user_folder, null);
+ }
+
+ /**
+ * This method is intended to make the UserFolder to be visually identical in size and position
+ * to its associated FolderIcon. This allows for a seamless transition into the expanded state.
+ */
+ private void positionAndSizeAsIcon() {
+ if (!(getParent() instanceof CellLayoutChildren)) return;
+
+ CellLayout.LayoutParams iconLp = (CellLayout.LayoutParams) mFolderIcon.getLayoutParams();
+ CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams();
+
+ if (mMode == PARTIAL_GROW) {
+ setScaleX(0.8f);
+ setScaleY(0.8f);
+ setAlpha(0f);
+ } else {
+ lp.width = iconLp.width;
+ lp.height = iconLp.height;
+ lp.x = iconLp.x;
+ lp.y = iconLp.y;
+ mContent.setAlpha(0);
+ }
+ mState = STATE_SMALL;
+ }
+
+ public void animateOpen() {
+ if (mState != STATE_SMALL) {
+ positionAndSizeAsIcon();
+ }
+ if (!(getParent() instanceof CellLayoutChildren)) return;
+
+ ObjectAnimator oa;
+ CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams();
+
+ centerAboutIcon();
+ if (mMode == PARTIAL_GROW) {
+ PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 1);
+ PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX", 1.0f);
+ PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY", 1.0f);
+ oa = ObjectAnimator.ofPropertyValuesHolder(this, alpha, scaleX, scaleY);
+ } else {
+ PropertyValuesHolder width = PropertyValuesHolder.ofInt("width", mNewSize.width());
+ PropertyValuesHolder height = PropertyValuesHolder.ofInt("height", mNewSize.height());
+ PropertyValuesHolder x = PropertyValuesHolder.ofInt("x", mNewSize.left);
+ PropertyValuesHolder y = PropertyValuesHolder.ofInt("y", mNewSize.top);
+ oa = ObjectAnimator.ofPropertyValuesHolder(lp, width, height, x, y);
+ oa.addUpdateListener(new AnimatorUpdateListener() {
+ public void onAnimationUpdate(ValueAnimator animation) {
+ requestLayout();
+ }
+ });
+
+ PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 1.0f);
+ ObjectAnimator alphaOa = ObjectAnimator.ofPropertyValuesHolder(mContent, alpha);
+ alphaOa.setDuration(mExpandDuration);
+ alphaOa.setInterpolator(new AccelerateInterpolator(2.0f));
+ alphaOa.start();
+ }
+
+ oa.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ mState = STATE_ANIMATING;
+ }
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mState = STATE_OPEN;
+ }
+ });
+ oa.setDuration(mExpandDuration);
+ oa.start();
+ }
+
+ public void animateClosed() {
+ if (!(getParent() instanceof CellLayoutChildren)) return;
+
+ CellLayoutChildren clc = (CellLayoutChildren) getParent();
+ final CellLayout cellLayout = (CellLayout) clc.getParent();
+ ObjectAnimator oa;
+
+ if (mMode == PARTIAL_GROW) {
+ PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 0);
+ PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX", 0.9f);
+ PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY", 0.9f);
+ oa = ObjectAnimator.ofPropertyValuesHolder(this, alpha, scaleX, scaleY);
+ } else {
+ CellLayout.LayoutParams iconLp = (CellLayout.LayoutParams) mFolderIcon.getLayoutParams();
+ CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams();
+
+ PropertyValuesHolder width = PropertyValuesHolder.ofInt("width", iconLp.width);
+ PropertyValuesHolder height = PropertyValuesHolder.ofInt("height", iconLp.height);
+ PropertyValuesHolder x = PropertyValuesHolder.ofInt("x",iconLp.x);
+ PropertyValuesHolder y = PropertyValuesHolder.ofInt("y", iconLp.y);
+ oa = ObjectAnimator.ofPropertyValuesHolder(lp, width, height, x, y);
+ oa.addUpdateListener(new AnimatorUpdateListener() {
+ public void onAnimationUpdate(ValueAnimator animation) {
+ requestLayout();
+ }
+ });
+
+ PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 0f);
+ ObjectAnimator alphaOa = ObjectAnimator.ofPropertyValuesHolder(mContent, alpha);
+ alphaOa.setDuration(mExpandDuration);
+ alphaOa.setInterpolator(new DecelerateInterpolator(2.0f));
+ alphaOa.start();
+ }
+
+ oa.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ onCloseComplete();
+ cellLayout.removeViewWithoutMarkingCells(Folder.this);
+ mState = STATE_SMALL;
+ }
+ @Override
+ public void onAnimationStart(Animator animation) {
+ mState = STATE_ANIMATING;
+ }
+ });
+ oa.setDuration(mExpandDuration);
+ oa.start();
+ }
+
+ void notifyDataSetChanged() {
+ // recreate all the children if the data set changes under us. We may want to do this more
+ // intelligently (ie just removing the views that should no longer exist)
+ mContent.removeAllViewsInLayout();
+ bind(mInfo);
+ }
+
+ public boolean acceptDrop(DragObject d) {
+ final ItemInfo item = (ItemInfo) d.dragInfo;
+ final int itemType = item.itemType;
+ return ((itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION ||
+ itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT) &&
+ !isFull());
+ }
+
+ protected boolean findAndSetEmptyCells(ShortcutInfo item) {
+ int[] emptyCell = new int[2];
+ if (mContent.findCellForSpan(emptyCell, item.spanX, item.spanY)) {
+ item.cellX = emptyCell[0];
+ item.cellY = emptyCell[1];
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ protected void createAndAddShortcut(ShortcutInfo item) {
+ final TextView textView =
+ (TextView) mInflater.inflate(R.layout.application_boxed, this, false);
+ textView.setCompoundDrawablesWithIntrinsicBounds(null,
+ new FastBitmapDrawable(item.getIcon(mIconCache)), null, null);
+ textView.setText(item.title);
+ textView.setTag(item);
+
+ textView.setOnClickListener(this);
+ textView.setOnLongClickListener(this);
+
+ CellLayout.LayoutParams lp =
+ new CellLayout.LayoutParams(item.cellX, item.cellY, item.spanX, item.spanY);
+ boolean insert = false;
+ mContent.addViewToCellLayout(textView, insert ? 0 : -1, (int)item.id, lp, true);
+ }
+
+ public void onDragEnter(DragObject d) {
+ mPreviousTargetCell[0] = -1;
+ mPreviousTargetCell[1] = -1;
+ mContent.onDragEnter();
+ mOnExitAlarm.cancelAlarm();
+ }
+
+ OnAlarmListener mReorderAlarmListener = new OnAlarmListener() {
+ public void onAlarm(Alarm alarm) {
+ realTimeReorder(mEmptyCell, mTargetCell);
+ }
+ };
+
+ boolean readingOrderGreaterThan(int[] v1, int[] v2) {
+ if (v1[1] > v2[1] || (v1[1] == v2[1] && v1[0] > v2[0])) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ private void realTimeReorder(int[] empty, int[] target) {
+ boolean wrap;
+ int startX;
+ int endX;
+ int startY;
+ if (readingOrderGreaterThan(target, empty)) {
+ wrap = empty[0] >= mContent.getCountX() - 1;
+ startY = wrap ? empty[1] + 1 : empty[1];
+ for (int y = startY; y <= target[1]; y++) {
+ startX = y == empty[1] ? empty[0] + 1 : 0;
+ endX = y < target[1] ? mContent.getCountX() - 1 : target[0];
+ for (int x = startX; x <= endX; x++) {
+ View v = mContent.getChildAt(x,y);
+ if (mContent.animateChildToPosition(v, empty[0], empty[1],
+ REORDER_ANIMATION_DURATION)) {
+ empty[0] = x;
+ empty[1] = y;
+ }
+ }
+ }
+ } else {
+ wrap = empty[0] == 0;
+ startY = wrap ? empty[1] - 1 : empty[1];
+ for (int y = startY; y >= target[1]; y--) {
+ startX = y == empty[1] ? empty[0] - 1 : mContent.getCountX() - 1;
+ endX = y > target[1] ? 0 : target[0];
+ for (int x = startX; x >= endX; x--) {
+ View v = mContent.getChildAt(x,y);
+ if (mContent.animateChildToPosition(v, empty[0], empty[1],
+ REORDER_ANIMATION_DURATION)) {
+ empty[0] = x;
+ empty[1] = y;
+ }
+ }
+ }
+ }
+ }
+
+ public void onDragOver(DragObject d) {
+ float[] r = getDragViewVisualCenter(d.x, d.y, d.xOffset, d.yOffset, d.dragView, null);
+ mTargetCell = mContent.findNearestArea((int) r[0], (int) r[1], 1, 1, mTargetCell);
+
+ if (mTargetCell[0] != mPreviousTargetCell[0] || mTargetCell[1] != mPreviousTargetCell[1]) {
+ mReorderAlarm.cancelAlarm();
+ mReorderAlarm.setOnAlarmListener(mReorderAlarmListener);
+ mReorderAlarm.setAlarm(150);
+ mPreviousTargetCell[0] = mTargetCell[0];
+ mPreviousTargetCell[1] = mTargetCell[1];
+ }
+ }
+
+ // This is used to compute the visual center of the dragView. The idea is that
+ // the visual center represents the user's interpretation of where the item is, and hence
+ // is the appropriate point to use when determining drop location.
+ private float[] getDragViewVisualCenter(int x, int y, int xOffset, int yOffset,
+ DragView dragView, float[] recycle) {
+ float res[];
+ if (recycle == null) {
+ res = new float[2];
+ } else {
+ res = recycle;
+ }
+
+ // These represent the visual top and left of drag view if a dragRect was provided.
+ // If a dragRect was not provided, then they correspond to the actual view left and
+ // top, as the dragRect is in that case taken to be the entire dragView.
+ // R.dimen.dragViewOffsetY.
+ int left = x - xOffset;
+ int top = y - yOffset;
+
+ // In order to find the visual center, we shift by half the dragRect
+ res[0] = left + dragView.getDragRegion().width() / 2;
+ res[1] = top + dragView.getDragRegion().height() / 2;
+
+ return res;
+ }
+
+ OnAlarmListener mOnExitAlarmListener = new OnAlarmListener() {
+ public void onAlarm(Alarm alarm) {
+ mLauncher.closeFolder(Folder.this);
+ mCurrentDragInfo = null;
+ mCurrentDragView = null;
+ mSuppressOnAdd = false;
+ mRearrangeOnClose = true;
+ }
+ };
+
+ public void onDragExit(DragObject d) {
+ // We only close the folder if this is a true drag exit, ie. not because a drop
+ // has occurred above the folder.
+ if (!d.dragComplete) {
+ mOnExitAlarm.setOnAlarmListener(mOnExitAlarmListener);
+ mOnExitAlarm.setAlarm(ON_EXIT_CLOSE_DELAY);
+ }
+ mReorderAlarm.cancelAlarm();
+ mContent.onDragExit();
+ }
+
+ public void onDropCompleted(View target, DragObject d, boolean success) {
+ mCurrentDragInfo = null;
+ mCurrentDragView = null;
+ mSuppressOnAdd = false;
+ if (!success) {
+ if (d.dragView != null) {
+ if (target instanceof CellLayout) {
+ // TODO: we should animate the item back to the folder in this case
+ }
+ }
+ // TODO: if the drag fails, we need to re-add the item
+ }
+ }
+
+ public boolean isDropEnabled() {
+ return true;
+ }
+
+ public DropTarget getDropTargetDelegate(DragObject d) {
+ return null;
+ }
+
+ private void setupContentDimension(int count) {
+ ArrayList<View> list = getItemsInReadingOrder();
+
+ int countX = mContent.getCountX();
+ int countY = mContent.getCountY();
+ boolean done = false;
+
+ while (!done) {
+ int oldCountX = countX;
+ int oldCountY = countY;
+ if (countX * countY < count) {
+ // Current grid is too small, expand it
+ if (countX <= countY && countX < mMaxCountX) {
+ countX++;
+ } else if (countY < mMaxCountY) {
+ countY++;
+ }
+ if (countY == 0) countY++;
+ } else if ((countY - 1) * countX >= count && countY >= countX) {
+ countY = Math.max(0, countY - 1);
+ } else if ((countX - 1) * countY >= count) {
+ countX = Math.max(0, countX - 1);
+ }
+ done = countX == oldCountX && countY == oldCountY;
+ }
+ mContent.setGridSize(countX, countY);
+ arrangeChildren(list);
+ }
+
+ public boolean isFull() {
+ return getItemCount() >= mMaxCountX * mMaxCountY;
+ }
+
+ private void centerAboutIcon() {
+ CellLayout.LayoutParams iconLp = (CellLayout.LayoutParams) mFolderIcon.getLayoutParams();
+ CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams();
+
+ int width = getPaddingLeft() + getPaddingRight() + mContent.getDesiredWidth();
+ int height = getPaddingTop() + getPaddingBottom() + mContent.getDesiredHeight();
+
+ int centerX = iconLp.x + iconLp.width / 2;
+ int centerY = iconLp.y + iconLp.height / 2;
+ int centeredLeft = centerX - width / 2;
+ int centeredTop = centerY - height / 2;
+
+ CellLayoutChildren clc = (CellLayoutChildren) getParent();
+ int parentWidth = 0;
+ int parentHeight = 0;
+ if (clc != null) {
+ parentWidth = clc.getMeasuredWidth();
+ parentHeight = clc.getMeasuredHeight();
+ }
+
+ int left = Math.min(Math.max(0, centeredLeft), parentWidth - width);
+ int top = Math.min(Math.max(0, centeredTop), parentHeight - height);
+
+ int folderPivotX = width / 2 + (centeredLeft - left);
+ int folderPivotY = height / 2 + (centeredTop - top);
+ setPivotX(folderPivotX);
+ setPivotY(folderPivotY);
+ int folderIconPivotX = (int) (mFolderIcon.getMeasuredWidth() *
+ (1.0f * folderPivotX / width));
+ int folderIconPivotY = (int) (mFolderIcon.getMeasuredHeight() *
+ (1.0f * folderPivotY / height));
+ mFolderIcon.setPivotX(folderIconPivotX);
+ mFolderIcon.setPivotY(folderIconPivotY);
+
+ if (mMode == PARTIAL_GROW) {
+ lp.width = width;
+ lp.height = height;
+ lp.x = left;
+ lp.y = top;
+ } else {
+ mNewSize.set(left, top, left + width, top + height);
+ }
+ }
+
+ private void setupContentForNumItems(int count) {
+ setupContentDimension(count);
+
+ CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams();
+ if (lp == null) {
+ lp = new CellLayout.LayoutParams(0, 0, -1, -1);
+ lp.isLockedToGrid = false;
+ setLayoutParams(lp);
+ }
+ centerAboutIcon();
+ }
+
+ private void arrangeChildren(ArrayList<View> list) {
+ int[] vacant = new int[2];
+ if (list == null) {
+ list = getItemsInReadingOrder();
+ }
+ mContent.removeAllViews();
+
+ for (int i = 0; i < list.size(); i++) {
+ View v = list.get(i);
+ mContent.getVacantCell(vacant, 1, 1);
+ CellLayout.LayoutParams lp = (CellLayout.LayoutParams) v.getLayoutParams();
+ lp.cellX = vacant[0];
+ lp.cellY = vacant[1];
+ ItemInfo info = (ItemInfo) v.getTag();
+ info.cellX = vacant[0];
+ info.cellY = vacant[1];
+ boolean insert = false;
+ mContent.addViewToCellLayout(v, insert ? 0 : -1, (int)info.id, lp, true);
+ LauncherModel.addOrMoveItemInDatabase(mLauncher, info, mInfo.id, 0,
+ info.cellX, info.cellY);
+ }
+ mItemsInvalidated = true;
+ }
+
+ public int getItemCount() {
+ return mContent.getChildrenLayout().getChildCount();
+ }
+
+ public View getItemAt(int index) {
+ return mContent.getChildrenLayout().getChildAt(index);
+ }
+
+ private void onCloseComplete() {
+ if (mRearrangeOnClose) {
+ setupContentForNumItems(getItemCount());
+ mRearrangeOnClose = false;
+ }
+ }
+
+ public void onDrop(DragObject d) {
+ ShortcutInfo item;
+ if (d.dragInfo instanceof ApplicationInfo) {
+ // Came from all apps -- make a copy
+ item = ((ApplicationInfo) d.dragInfo).makeShortcut();
+ item.spanX = 1;
+ item.spanY = 1;
+ } else {
+ item = (ShortcutInfo) d.dragInfo;
+ }
+ // Dragged from self onto self
+ if (item == mCurrentDragInfo) {
+ ShortcutInfo si = (ShortcutInfo) mCurrentDragView.getTag();
+ CellLayout.LayoutParams lp = (CellLayout.LayoutParams) mCurrentDragView.getLayoutParams();
+ si.cellX = lp.cellX = mEmptyCell[0];
+ si.cellX = lp.cellY = mEmptyCell[1];
+ mContent.addViewToCellLayout(mCurrentDragView, -1, (int)item.id, lp, true);
+ mSuppressOnAdd = true;
+ mItemsInvalidated = true;
+ setupContentDimension(getItemCount());
+ }
+ mInfo.add(item);
+ }
+
+ public void onAdd(ShortcutInfo item) {
+ mItemsInvalidated = true;
+ if (mSuppressOnAdd) return;
+ if (!findAndSetEmptyCells(item)) {
+ // The current layout is full, can we expand it?
+ setupContentForNumItems(getItemCount() + 1);
+ findAndSetEmptyCells(item);
+ }
+ createAndAddShortcut(item);
+ LauncherModel.addOrMoveItemInDatabase(
+ mLauncher, item, mInfo.id, 0, item.cellX, item.cellY);
+ }
+
+ public void onRemove(ShortcutInfo item) {
+ mItemsInvalidated = true;
+ if (item == mCurrentDragInfo) return;
+ View v = mContent.getChildAt(mDragItemPosition[0], mDragItemPosition[1]);
+ mContent.removeView(v);
+ if (mState == STATE_ANIMATING) {
+ mRearrangeOnClose = true;
+ } else {
+ setupContentForNumItems(getItemCount());
+ }
+ }
+
+ public void onItemsChanged() {
+ }
+
+ public ArrayList<View> getItemsInReadingOrder() {
+ return getItemsInReadingOrder(true);
+ }
+
+ public ArrayList<View> getItemsInReadingOrder(boolean includeCurrentDragItem) {
+ if (mItemsInvalidated) {
+ mItemsInReadingOrder.clear();
+ for (int j = 0; j < mContent.getCountY(); j++) {
+ for (int i = 0; i < mContent.getCountX(); i++) {
+ View v = mContent.getChildAt(i, j);
+ if (v != null) {
+ ShortcutInfo info = (ShortcutInfo) v.getTag();
+ if (info != mCurrentDragInfo || includeCurrentDragItem) {
+ mItemsInReadingOrder.add(v);
+ }
+ }
+ }
+ }
+ mItemsInvalidated = false;
+ }
+ return mItemsInReadingOrder;
}
}
diff --git a/src/com/android/launcher2/FolderIcon.java b/src/com/android/launcher2/FolderIcon.java
index dd83c781a..18b242bfa 100644
--- a/src/com/android/launcher2/FolderIcon.java
+++ b/src/com/android/launcher2/FolderIcon.java
@@ -16,23 +16,67 @@
package com.android.launcher2;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
+import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.content.Context;
import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.LayoutInflater;
+import android.view.View;
import android.view.ViewGroup;
+import android.widget.FrameLayout;
+import android.widget.TextView;
import com.android.launcher.R;
+import com.android.launcher2.DropTarget.DragObject;
+import com.android.launcher2.FolderInfo.FolderListener;
+
+import java.util.ArrayList;
/**
* An icon that can appear on in the workspace representing an {@link UserFolder}.
*/
-public class FolderIcon extends BubbleTextView implements DropTarget {
- private UserFolderInfo mInfo;
+public class FolderIcon extends FrameLayout implements FolderListener {
private Launcher mLauncher;
- private Drawable mCloseIcon;
- private Drawable mOpenIcon;
+ Folder mFolder;
+ FolderInfo mInfo;
+
+ // The number of icons to display in the
+ private static final int NUM_ITEMS_IN_PREVIEW = 4;
+ private static final int CONSUMPTION_ANIMATION_DURATION = 100;
+
+ // The degree to which the inner ring grows when accepting drop
+ private static final float INNER_RING_GROWTH_FACTOR = 0.1f;
+
+ // The degree to which the inner ring is scaled in its natural state
+ private static final float INNER_RING_BASELINE_SCALE = 1.0f;
+
+ // The degree to which the outer ring grows when accepting drop
+ private static final float OUTER_RING_BASELINE_SCALE = 0.7f;
+
+ // The degree to which the outer ring is scaled in its natural state
+ private static final float OUTER_RING_GROWTH_FACTOR = 0.3f;
+
+ // The amount of vertical spread between items in the stack [0...1]
+ private static final float PERSPECTIVE_SHIFT_FACTOR = 0.3f;
+
+ // 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.3f;
+
+ // The percentage of the FolderIcons view that will be dedicated to the items preview
+ private static final float SPACE_PERCENTAGE_FOR_ICONS = 0.8f;
+
+ private int mOriginalWidth = -1;
+ private int mOriginalHeight = -1;
+
+ FolderRingAnimator mFolderRingAnimator = null;
public FolderIcon(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -43,69 +87,283 @@ public class FolderIcon extends BubbleTextView implements DropTarget {
}
public boolean isDropEnabled() {
- return !((Workspace)getParent().getParent()).isSmall();
+ final ViewGroup cellLayoutChildren = (ViewGroup) getParent();
+ final ViewGroup cellLayout = (ViewGroup) cellLayoutChildren.getParent();
+ final Workspace workspace = (Workspace) cellLayout.getParent();
+ return !workspace.isSmall();
}
static FolderIcon fromXml(int resId, Launcher launcher, ViewGroup group,
- UserFolderInfo folderInfo, IconCache iconCache) {
+ FolderInfo folderInfo, IconCache iconCache) {
FolderIcon icon = (FolderIcon) LayoutInflater.from(launcher).inflate(resId, group, false);
final Resources resources = launcher.getResources();
- Drawable d = iconCache.getFullResIcon(resources, R.drawable.ic_launcher_folder);
- icon.mCloseIcon = d;
- icon.mOpenIcon = iconCache.getFullResIcon(resources, R.drawable.ic_launcher_folder_open);
- icon.setCompoundDrawablesWithIntrinsicBounds(null, d, null, null);
- icon.setText(folderInfo.title);
+ Drawable d = iconCache.getFullResIcon(resources, R.drawable.portal_ring_inner_holo);
+ icon.setBackgroundDrawable(d);
icon.setTag(folderInfo);
icon.setOnClickListener(launcher);
icon.mInfo = folderInfo;
icon.mLauncher = launcher;
-
+
+ Folder folder = Folder.fromXml(launcher);
+ folder.setDragController(launcher.getDragController());
+ folder.setLauncher(launcher);
+ folder.setFolderIcon(icon);
+ folder.bind(folderInfo);
+ icon.mFolder = folder;
+ icon.mFolderRingAnimator = new FolderRingAnimator(launcher, icon);
+ folderInfo.addListener(icon);
+
return icon;
}
- public boolean acceptDrop(DragSource source, int x, int y, int xOffset, int yOffset,
- DragView dragView, Object dragInfo) {
- final ItemInfo item = (ItemInfo) dragInfo;
+ public static class FolderRingAnimator {
+ public int mFolderLocX;
+ public int mFolderLocY;
+ public float mOuterRingScale;
+ public float mInnerRingScale;
+ public FolderIcon mFolderIcon = null;
+ private Launcher mLauncher;
+ public Drawable mOuterRingDrawable = null;
+ public Drawable mInnerRingDrawable = null;
+ public static Drawable sSharedOuterRingDrawable = null;
+ public static Drawable sSharedInnerRingDrawable = null;
+ private ValueAnimator mAcceptAnimator;
+ private ValueAnimator mNeutralAnimator;
+
+ public FolderRingAnimator(Launcher launcher, FolderIcon folderIcon) {
+ mLauncher = launcher;
+ mFolderIcon = folderIcon;
+ mOuterRingDrawable =
+ launcher.getResources().getDrawable(R.drawable.portal_ring_outer_holo);
+ mInnerRingDrawable =
+ launcher.getResources().getDrawable(R.drawable.portal_ring_inner_holo);
+ if (sSharedOuterRingDrawable == null) {
+ sSharedOuterRingDrawable =
+ launcher.getResources().getDrawable(R.drawable.portal_ring_outer_holo);
+ }
+ if (sSharedInnerRingDrawable == null) {
+ sSharedInnerRingDrawable =
+ launcher.getResources().getDrawable(R.drawable.portal_ring_inner_holo);
+ }
+ }
+
+ // Location is expressed in window coordinates
+ public void setLocation(int x, int y) {
+ mFolderLocX = x;
+ mFolderLocY = y;
+ }
+
+ public void animateToAcceptState() {
+ if (mNeutralAnimator != null) {
+ mNeutralAnimator.cancel();
+ }
+ mAcceptAnimator = ValueAnimator.ofFloat(0f, 1f);
+ mAcceptAnimator.setDuration(CONSUMPTION_ANIMATION_DURATION);
+ mAcceptAnimator.addUpdateListener(new AnimatorUpdateListener() {
+ public void onAnimationUpdate(ValueAnimator animation) {
+ final float percent = (Float) animation.getAnimatedValue();
+ mOuterRingScale = OUTER_RING_BASELINE_SCALE + percent * OUTER_RING_GROWTH_FACTOR;
+ mInnerRingScale = INNER_RING_BASELINE_SCALE + percent * INNER_RING_GROWTH_FACTOR;
+ mLauncher.getWorkspace().invalidate();
+ if (mFolderIcon != null) {
+ mFolderIcon.invalidate();
+ }
+ }
+ });
+ mAcceptAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ if (mFolderIcon != null) {
+ mFolderIcon.setBackgroundDrawable(null);
+ }
+ }
+ });
+ mAcceptAnimator.start();
+ }
+
+ public void animateToNaturalState() {
+ if (mAcceptAnimator != null) {
+ mAcceptAnimator.cancel();
+ }
+ mNeutralAnimator = ValueAnimator.ofFloat(0f, 1f);
+ mNeutralAnimator.setDuration(CONSUMPTION_ANIMATION_DURATION);
+ mNeutralAnimator.addUpdateListener(new AnimatorUpdateListener() {
+ public void onAnimationUpdate(ValueAnimator animation) {
+ final float percent = (Float) animation.getAnimatedValue();
+ mOuterRingScale = OUTER_RING_BASELINE_SCALE + OUTER_RING_GROWTH_FACTOR
+ - percent * OUTER_RING_GROWTH_FACTOR;
+ mInnerRingScale = INNER_RING_BASELINE_SCALE + INNER_RING_GROWTH_FACTOR
+ - percent * INNER_RING_GROWTH_FACTOR;
+ mLauncher.getWorkspace().invalidate();
+ if (mFolderIcon != null) {
+ mFolderIcon.invalidate();
+ }
+ }
+ });
+ mNeutralAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (mFolderIcon != null) {
+ mFolderIcon.setBackgroundDrawable(mInnerRingDrawable);
+ }
+ mLauncher.getWorkspace().hideFolderAccept(FolderRingAnimator.this);
+ }
+ });
+ mNeutralAnimator.start();
+ }
+
+ // Location is expressed in window coordinates
+ public void getLocation(int[] loc) {
+ loc[0] = mFolderLocX;
+ loc[1] = mFolderLocY;
+ }
+
+ public float getOuterRingScale() {
+ return mOuterRingScale;
+ }
+
+ public float getInnerRingScale() {
+ return mInnerRingScale;
+ }
+ }
+
+ private boolean willAcceptItem(ItemInfo item) {
final int itemType = item.itemType;
- return (itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION ||
- itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT)
- && item.container != mInfo.id;
+ return ((itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION ||
+ itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT) &&
+ !mFolder.isFull() && item != mInfo);
+ }
+
+ public boolean acceptDrop(Object dragInfo) {
+ final ItemInfo item = (ItemInfo) dragInfo;
+ return willAcceptItem(item);
}
- public void onDrop(DragSource source, int x, int y, int xOffset, int yOffset,
- DragView dragView, Object dragInfo) {
+ public void addItem(ShortcutInfo item) {
+ mInfo.add(item);
+ LauncherModel.addOrMoveItemInDatabase(mLauncher, item, mInfo.id, 0, item.cellX, item.cellY);
+ }
+
+ void saveState(CellLayout.LayoutParams lp) {
+ mOriginalWidth = lp.width;
+ mOriginalHeight = lp.height;
+ }
+
+ private void determineFolderLocationInWorkspace() {
+ int tvLocation[] = new int[2];
+ int wsLocation[] = new int[2];
+ getLocationInWindow(tvLocation);
+ mLauncher.getWorkspace().getLocationInWindow(wsLocation);
+
+ int x = tvLocation[0] - wsLocation[0] + getMeasuredWidth() / 2;
+ int y = tvLocation[1] - wsLocation[1] + getMeasuredHeight() / 2;
+ mFolderRingAnimator.setLocation(x, y);
+ }
+
+ public void onDragEnter(Object dragInfo) {
+ if (!willAcceptItem((ItemInfo) dragInfo)) return;
+ determineFolderLocationInWorkspace();
+ mLauncher.getWorkspace().showFolderAccept(mFolderRingAnimator);
+ mFolderRingAnimator.animateToAcceptState();
+ }
+
+ public void onDragOver(Object dragInfo) {
+ }
+
+ public void onDragExit(Object dragInfo) {
+ if (!willAcceptItem((ItemInfo) dragInfo)) return;
+ mFolderRingAnimator.animateToNaturalState();
+ }
+
+ public void onDrop(Object dragInfo) {
ShortcutInfo item;
if (dragInfo instanceof ApplicationInfo) {
// Came from all apps -- make a copy
- item = ((ApplicationInfo)dragInfo).makeShortcut();
+ item = ((ApplicationInfo) dragInfo).makeShortcut();
} else {
- item = (ShortcutInfo)dragInfo;
+ item = (ShortcutInfo) dragInfo;
}
- mInfo.add(item);
- LauncherModel.addOrMoveItemInDatabase(mLauncher, item, mInfo.id, 0, 0, 0);
+ item.cellX = -1;
+ item.cellY = -1;
+ addItem(item);
}
- public void onDragEnter(DragSource source, int x, int y, int xOffset, int yOffset,
- DragView dragView, Object dragInfo) {
- if (acceptDrop(source, x, y, xOffset, yOffset, dragView, dragInfo)) {
- setCompoundDrawablesWithIntrinsicBounds(null, mOpenIcon, null, null);
+ public DropTarget getDropTargetDelegate(DragObject d) {
+ return null;
+ }
+
+ @Override
+ protected void dispatchDraw(Canvas canvas) {
+ if (mFolder == null) return;
+ if (mFolder.getItemCount() == 0) return;
+
+ canvas.save();
+ TextView v = (TextView) mFolder.getItemAt(0);
+ Drawable d = v.getCompoundDrawables()[1];
+
+ if (mOriginalWidth < 0 || mOriginalHeight < 0) {
+ mOriginalWidth = getMeasuredWidth();
+ mOriginalHeight = getMeasuredHeight();
+ }
+
+ int unscaledHeight = (int) (d.getIntrinsicHeight() * (1 + PERSPECTIVE_SHIFT_FACTOR));
+ float baselineIconScale = SPACE_PERCENTAGE_FOR_ICONS / (unscaledHeight / (mOriginalHeight * 1.0f));
+
+ int baselineHeight = (int) (d.getIntrinsicHeight() * baselineIconScale);
+ int totalStackHeight = (int) (baselineHeight * (1 + PERSPECTIVE_SHIFT_FACTOR));
+ int baselineWidth = (int) (d.getIntrinsicWidth() * baselineIconScale);
+ float maxPerpectiveShift = baselineHeight * PERSPECTIVE_SHIFT_FACTOR;
+
+ ArrayList<View> items = mFolder.getItemsInReadingOrder(false);
+ int firstItemIndex = Math.max(0, items.size() - NUM_ITEMS_IN_PREVIEW);
+
+ int xShift = (int) (mOriginalWidth - baselineWidth) / 2;
+ int yShift = (int) (mOriginalHeight - totalStackHeight) / 2;
+ canvas.translate(xShift, yShift);
+ for (int i = firstItemIndex; i < items.size(); i++) {
+ int index = i - firstItemIndex;
+ index += Math.max(0, NUM_ITEMS_IN_PREVIEW - items.size());
+
+ float r = (index * 1.0f) / (NUM_ITEMS_IN_PREVIEW - 1);
+ float scale = (1 - PERSPECTIVE_SCALE_FACTOR * (1 - r));
+ r = (float) Math.pow(r, 2);
+
+ float transY = r * maxPerpectiveShift;
+ float transX = (1 - scale) * baselineWidth / 2.0f;
+
+ v = (TextView) items.get(i);
+ d = v.getCompoundDrawables()[1];
+
+ canvas.save();
+ canvas.translate(transX, transY);
+ canvas.scale(baselineIconScale * scale, baselineIconScale * scale);
+
+ int overlayAlpha = (int) (80 * (1 - r));
+ if (d != null) {
+ d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
+ d.setColorFilter(Color.argb(overlayAlpha, 0, 0, 0), PorterDuff.Mode.SRC_ATOP);
+ d.draw(canvas);
+ d.clearColorFilter();
+ }
+ canvas.restore();
}
+ canvas.restore();
}
- public void onDragOver(DragSource source, int x, int y, int xOffset, int yOffset,
- DragView dragView, Object dragInfo) {
+ public void onItemsChanged() {
+ invalidate();
+ requestLayout();
}
- public void onDragExit(DragSource source, int x, int y, int xOffset, int yOffset,
- DragView dragView, Object dragInfo) {
- setCompoundDrawablesWithIntrinsicBounds(null, mCloseIcon, null, null);
+ public void onAdd(ShortcutInfo item) {
+ invalidate();
+ requestLayout();
}
- @Override
- public DropTarget getDropTargetDelegate(DragSource source, int x, int y, int xOffset, int yOffset,
- DragView dragView, Object dragInfo) {
- return null;
+ public void onRemove(ShortcutInfo item) {
+ invalidate();
+ requestLayout();
}
}
diff --git a/src/com/android/launcher2/FolderInfo.java b/src/com/android/launcher2/FolderInfo.java
index 8732690c3..805a51f39 100644
--- a/src/com/android/launcher2/FolderInfo.java
+++ b/src/com/android/launcher2/FolderInfo.java
@@ -16,12 +16,15 @@
package com.android.launcher2;
+import java.util.ArrayList;
+
+import android.content.ContentValues;
/**
* Represents a folder containing shortcuts or apps.
*/
class FolderInfo extends ItemInfo {
-
+
/**
* Whether this folder has been opened
*/
@@ -31,4 +34,67 @@ class FolderInfo extends ItemInfo {
* The folder name.
*/
CharSequence title;
+
+ /**
+ * The apps and shortcuts
+ */
+ ArrayList<ShortcutInfo> contents = new ArrayList<ShortcutInfo>();
+
+ ArrayList<FolderListener> listeners = new ArrayList<FolderListener>();
+
+ FolderInfo() {
+ itemType = LauncherSettings.Favorites.ITEM_TYPE_FOLDER;
+ }
+
+ /**
+ * Add an app or shortcut
+ *
+ * @param item
+ */
+ public void add(ShortcutInfo item) {
+ contents.add(item);
+ for (int i = 0; i < listeners.size(); i++) {
+ listeners.get(i).onAdd(item);
+ }
+ }
+
+ /**
+ * Remove an app or shortcut. Does not change the DB.
+ *
+ * @param item
+ */
+ public void remove(ShortcutInfo item) {
+ contents.remove(item);
+ for (int i = 0; i < listeners.size(); i++) {
+ listeners.get(i).onRemove(item);
+ }
+ }
+
+ @Override
+ void onAddToDatabase(ContentValues values) {
+ super.onAddToDatabase(values);
+ values.put(LauncherSettings.Favorites.TITLE, title.toString());
+ }
+
+ void addListener(FolderListener listener) {
+ listeners.add(listener);
+ }
+
+ void removeListener(FolderListener listener) {
+ if (listeners.contains(listener)) {
+ listeners.remove(listener);
+ }
+ }
+
+ void itemsChanged() {
+ for (int i = 0; i < listeners.size(); i++) {
+ listeners.get(i).onItemsChanged();
+ }
+ }
+
+ interface FolderListener {
+ public void onAdd(ShortcutInfo item);
+ public void onRemove(ShortcutInfo item);
+ public void onItemsChanged();
+ }
}
diff --git a/src/com/android/launcher2/HolographicPagedViewIcon.java b/src/com/android/launcher2/HolographicPagedViewIcon.java
index 5e1816991..7123e2a45 100644
--- a/src/com/android/launcher2/HolographicPagedViewIcon.java
+++ b/src/com/android/launcher2/HolographicPagedViewIcon.java
@@ -41,7 +41,6 @@ public class HolographicPagedViewIcon extends TextView {
@Override
protected void onDraw(Canvas canvas) {
Bitmap overlay = mOriginalIcon.getHolographicOutline();
-
if (overlay != null) {
final int offset = getScrollX();
final int compoundPaddingLeft = getCompoundPaddingLeft();
diff --git a/src/com/android/launcher2/IconCache.java b/src/com/android/launcher2/IconCache.java
index 0c26bf05c..5c07cfb42 100644
--- a/src/com/android/launcher2/IconCache.java
+++ b/src/com/android/launcher2/IconCache.java
@@ -24,6 +24,7 @@ import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
+import android.util.Pair;
import android.util.DisplayMetrics;
import java.util.HashMap;
@@ -54,7 +55,7 @@ public class IconCache {
mContext = context;
mPackageManager = context.getPackageManager();
mBubble = new Utilities.BubbleText(context);
- if (LauncherApplication.isScreenXLarge()) {
+ if (LauncherApplication.isScreenLarge()) {
mIconDpi = DisplayMetrics.DENSITY_HIGH;
} else {
mIconDpi = context.getResources().getDisplayMetrics().densityDpi;
@@ -187,4 +188,16 @@ public class IconCache {
}
return entry;
}
+
+ public HashMap<ComponentName,Bitmap> getAllIcons() {
+ synchronized (mCache) {
+ HashMap<ComponentName,Bitmap> set = new HashMap<ComponentName,Bitmap>();
+ int i = 0;
+ for (ComponentName cn : mCache.keySet()) {
+ final CacheEntry e = mCache.get(cn);
+ set.put(cn, e.icon);
+ }
+ return set;
+ }
+ }
}
diff --git a/src/com/android/launcher2/IconDropTarget.java b/src/com/android/launcher2/IconDropTarget.java
index fb5d0f081..202b38d9e 100644
--- a/src/com/android/launcher2/IconDropTarget.java
+++ b/src/com/android/launcher2/IconDropTarget.java
@@ -28,7 +28,7 @@ import android.widget.TextView;
* Implements a DropTarget which allows applications to be dropped on it,
* in order to launch the application info for that app.
*/
-public class IconDropTarget extends TextView implements DropTarget, DragController.DragListener {
+public class IconDropTarget extends StrokedTextView implements DropTarget, DragController.DragListener {
protected Launcher mLauncher;
/**
@@ -82,32 +82,27 @@ public class IconDropTarget extends TextView implements DropTarget, DragControll
mDragAndDropEnabled = enabled;
}
- public boolean acceptDrop(DragSource source, int x, int y, int xOffset, int yOffset,
- DragView dragView, Object dragInfo) {
+ public boolean acceptDrop(DragObject d) {
return false;
}
- public void onDrop(DragSource source, int x, int y, int xOffset, int yOffset,
- DragView dragView, Object dragInfo) {
+ public void onDrop(DragObject d) {
// Do nothing
}
- public void onDragEnter(DragSource source, int x, int y, int xOffset, int yOffset,
- DragView dragView, Object dragInfo) {
+ public void onDragEnter(DragObject d) {
if (mDragAndDropEnabled) {
- dragView.setPaint(mHoverPaint);
+ d.dragView.setPaint(mHoverPaint);
}
}
- public void onDragOver(DragSource source, int x, int y, int xOffset, int yOffset,
- DragView dragView, Object dragInfo) {
+ public void onDragOver(DragObject d) {
// Do nothing
}
- public void onDragExit(DragSource source, int x, int y, int xOffset, int yOffset,
- DragView dragView, Object dragInfo) {
+ public void onDragExit(DragObject d) {
if (mDragAndDropEnabled) {
- dragView.setPaint(null);
+ d.dragView.setPaint(null);
}
}
@@ -126,7 +121,7 @@ public class IconDropTarget extends TextView implements DropTarget, DragControll
@Override
public void getHitRect(Rect outRect) {
super.getHitRect(outRect);
- if (LauncherApplication.isScreenXLarge()) {
+ if (LauncherApplication.isScreenLarge()) {
outRect.top -= mDragPadding[0];
outRect.right += mDragPadding[1];
outRect.bottom += mDragPadding[2];
@@ -135,8 +130,7 @@ public class IconDropTarget extends TextView implements DropTarget, DragControll
}
@Override
- public DropTarget getDropTargetDelegate(DragSource source, int x, int y, int xOffset,
- int yOffset, DragView dragView, Object dragInfo) {
+ public DropTarget getDropTargetDelegate(DragObject d) {
return null;
}
}
diff --git a/src/com/android/launcher2/InfoDropTarget.java b/src/com/android/launcher2/InfoDropTarget.java
new file mode 100644
index 000000000..7e6b700df
--- /dev/null
+++ b/src/com/android/launcher2/InfoDropTarget.java
@@ -0,0 +1,114 @@
+/*
+ * 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.
+ */
+
+package com.android.launcher2;
+
+import android.animation.ObjectAnimator;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Color;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffColorFilter;
+import android.util.AttributeSet;
+import android.view.View;
+
+import com.android.launcher.R;
+
+public class InfoDropTarget extends ButtonDropTarget {
+
+ private int mHoverColor = 0xFF0000FF;
+
+ public InfoDropTarget(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public InfoDropTarget(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+
+ // Get the hover color
+ Resources r = getResources();
+ mHoverColor = r.getColor(R.color.info_target_hover_tint);
+ mHoverPaint.setColorFilter(new PorterDuffColorFilter(
+ mHoverColor, PorterDuff.Mode.SRC_ATOP));
+ setBackgroundColor(mHoverColor);
+ getBackground().setAlpha(0);
+ }
+
+ private boolean isApplication(Object info) {
+ if (info instanceof ApplicationInfo) return true;
+ return (((ItemInfo) info).itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION);
+ }
+
+ @Override
+ public boolean acceptDrop(DragObject d) {
+ // acceptDrop is called just before onDrop. We do the work here, rather than
+ // in onDrop, because it allows us to reject the drop (by returning false)
+ // so that the object being dragged isn't removed from the drag source.
+ ComponentName componentName = null;
+ if (d.dragInfo instanceof ApplicationInfo) {
+ componentName = ((ApplicationInfo) d.dragInfo).componentName;
+ } else if (d.dragInfo instanceof ShortcutInfo) {
+ componentName = ((ShortcutInfo) d.dragInfo).intent.getComponent();
+ }
+ if (componentName != null) {
+ mLauncher.startApplicationDetailsActivity(componentName);
+ }
+ return false;
+ }
+
+ @Override
+ public void onDragStart(DragSource source, Object info, int dragAction) {
+ ItemInfo item = (ItemInfo) info;
+ boolean isVisible = true;
+
+ // If we are dragging a widget or shortcut, hide the info target
+ if (!isApplication(info)) {
+ isVisible = false;
+ }
+
+ mActive = isVisible;
+ setVisibility(isVisible ? View.VISIBLE : View.GONE);
+ }
+
+ @Override
+ public void onDragEnd() {
+ super.onDragEnd();
+ mActive = false;
+ }
+
+ public void onDragEnter(DragObject d) {
+ super.onDragEnter(d);
+
+ ObjectAnimator anim = ObjectAnimator.ofInt(getBackground(), "alpha",
+ Color.alpha(mHoverColor));
+ anim.setDuration(mTransitionDuration);
+ anim.start();
+ }
+
+ public void onDragExit(DragObject d) {
+ super.onDragExit(d);
+
+ ObjectAnimator anim = ObjectAnimator.ofInt(getBackground(), "alpha", 0);
+ anim.setDuration(mTransitionDuration);
+ anim.start();
+ }
+}
diff --git a/src/com/android/launcher2/ItemInfo.java b/src/com/android/launcher2/ItemInfo.java
index b3612140d..3bb3b073a 100644
--- a/src/com/android/launcher2/ItemInfo.java
+++ b/src/com/android/launcher2/ItemInfo.java
@@ -38,7 +38,7 @@ class ItemInfo {
/**
* One of {@link LauncherSettings.Favorites#ITEM_TYPE_APPLICATION},
* {@link LauncherSettings.Favorites#ITEM_TYPE_SHORTCUT},
- * {@link LauncherSettings.Favorites#ITEM_TYPE_USER_FOLDER}, or
+ * {@link LauncherSettings.Favorites#ITEM_TYPE_FOLDER}, or
* {@link LauncherSettings.Favorites#ITEM_TYPE_APPWIDGET}.
*/
int itemType;
diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java
index 5c5542aa8..7d2c74184 100644
--- a/src/com/android/launcher2/Launcher.java
+++ b/src/com/android/launcher2/Launcher.java
@@ -17,15 +17,12 @@
package com.android.launcher2;
-import com.android.common.Search;
-import com.android.launcher.R;
-import com.android.launcher2.Workspace.ShrinkState;
-
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.animation.PropertyValuesHolder;
import android.animation.ValueAnimator;
-import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
@@ -42,12 +39,12 @@ import android.content.ContentResolver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
-import android.content.IntentFilter;
import android.content.Intent.ShortcutIconResource;
+import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
@@ -63,10 +60,8 @@ import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
-import android.os.Parcelable;
import android.os.SystemClock;
import android.os.SystemProperties;
-import android.provider.LiveFolders;
import android.provider.Settings;
import android.speech.RecognizerIntent;
import android.text.Selection;
@@ -83,10 +78,9 @@ import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.View;
-import android.view.ViewGroup;
-import android.view.WindowManager;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
+import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
import android.view.animation.DecelerateInterpolator;
import android.view.inputmethod.InputMethodManager;
@@ -95,10 +89,13 @@ import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.PopupWindow;
-import android.widget.TabHost;
import android.widget.TextView;
import android.widget.Toast;
+import com.android.common.Search;
+import com.android.launcher.R;
+import com.android.launcher2.Workspace.ShrinkState;
+
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileNotFoundException;
@@ -107,7 +104,6 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
-
/**
* Default launcher application.
*/
@@ -132,11 +128,9 @@ public final class Launcher extends Activity
private static final int MENU_SETTINGS = MENU_NOTIFICATIONS + 1;
private static final int REQUEST_CREATE_SHORTCUT = 1;
- private static final int REQUEST_CREATE_LIVE_FOLDER = 4;
private static final int REQUEST_CREATE_APPWIDGET = 5;
private static final int REQUEST_PICK_APPLICATION = 6;
private static final int REQUEST_PICK_SHORTCUT = 7;
- private static final int REQUEST_PICK_LIVE_FOLDER = 8;
private static final int REQUEST_PICK_APPWIDGET = 9;
private static final int REQUEST_PICK_WALLPAPER = 10;
@@ -155,7 +149,7 @@ public final class Launcher extends Activity
// Type: int
private static final String RUNTIME_STATE = "launcher.state";
// Type: long
- private static final String RUNTIME_STATE_USER_FOLDERS = "launcher.user_folder";
+ private static final String RUNTIME_STATE_FOLDERS = "launcher.folder";
// Type: int
private static final String RUNTIME_STATE_PENDING_ADD_SCREEN = "launcher.add_screen";
// Type: int
@@ -170,8 +164,7 @@ public final class Launcher extends Activity
private static final String TOOLBAR_ICON_METADATA_NAME = "com.android.launcher.toolbar_icon";
/** The different states that Launcher can be in. */
- private enum State { WORKSPACE, ALL_APPS, CUSTOMIZE,
- CUSTOMIZE_SPRING_LOADED, ALL_APPS_SPRING_LOADED };
+ private enum State { WORKSPACE, APPS_CUSTOMIZE, APPS_CUSTOMIZE_SPRING_LOADED };
private State mState = State.WORKSPACE;
private AnimatorSet mStateAnimation;
@@ -201,18 +194,12 @@ public final class Launcher extends Activity
private FolderInfo mFolderInfo;
private DeleteZone mDeleteZone;
- private HandleView mHandleView;
- private AllAppsView mAllAppsGrid;
- private CustomizeTrayTabHost mHomeCustomizationDrawer;
- private boolean mAutoAdvanceRunning = false;
-
- private View mButtonCluster;
+ private ViewGroup mButtonCluster;
private View mAllAppsButton;
- private View mDivider;
- private View mConfigureButton;
-
- private AllAppsPagedView mAllAppsPagedView = null;
- private CustomizePagedView mCustomizePagedView = null;
+ private SearchDropTargetBar mSearchDeleteBar;
+ private AppsCustomizeTabHost mAppsCustomizeTabHost;
+ private AppsCustomizePagedView mAppsCustomizeContent;
+ private boolean mAutoAdvanceRunning = false;
private Bundle mSavedState;
@@ -269,6 +256,8 @@ public final class Launcher extends Activity
private static Drawable.ConstantState sVoiceSearchIcon;
private static Drawable.ConstantState sAppMarketIcon;
+ private DragLayer mDragLayer;
+
private BubbleTextView mWaitingForResume;
private static ArrayList<PendingAddArguments> sPendingAddList
@@ -285,13 +274,6 @@ public final class Launcher extends Activity
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
-
- if (LauncherApplication.isInPlaceRotationEnabled()) {
- // hide the status bar (temporary until we get the status bar design figured out)
- getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
- this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
- }
-
LauncherApplication app = ((LauncherApplication)getApplication());
mModel = app.setLauncher(this);
mIconCache = app.getIconCache();
@@ -310,13 +292,6 @@ public final class Launcher extends Activity
loadHotseats();
checkForLocaleChange();
setContentView(R.layout.launcher);
- mHomeCustomizationDrawer = (CustomizeTrayTabHost) findViewById(R.id.customization_drawer);
- if (mHomeCustomizationDrawer != null) {
- // share the same customization workspace across all the tabs
- mCustomizePagedView = (CustomizePagedView) findViewById(
- R.id.customization_drawer_tab_contents);
-
- }
setupViews();
registerContentObservers();
@@ -327,8 +302,8 @@ public final class Launcher extends Activity
restoreState(mSavedState);
// Update customization drawer _after_ restoring the states
- if (mCustomizePagedView != null) {
- mCustomizePagedView.update();
+ if (mAppsCustomizeContent != null) {
+ mAppsCustomizeContent.onPackagesUpdated();
}
if (PROFILE_STARTUP) {
@@ -347,35 +322,18 @@ public final class Launcher extends Activity
registerReceiver(mCloseSystemDialogsReceiver, filter);
// If we have a saved version of these external icons, we load them up immediately
- if (LauncherApplication.isScreenXLarge()) {
- if (sGlobalSearchIcon == null || sVoiceSearchIcon == null || sAppMarketIcon == null) {
- updateIconsAffectedByPackageManagerChanges();
- }
- if (sGlobalSearchIcon != null) {
- updateGlobalSearchIcon(sGlobalSearchIcon);
- }
- if (sVoiceSearchIcon != null) {
- updateVoiceSearchIcon(sVoiceSearchIcon);
- }
- if (sAppMarketIcon != null) {
- updateAppMarketIcon(sAppMarketIcon);
- }
+ if (sGlobalSearchIcon == null || sVoiceSearchIcon == null || sAppMarketIcon == null) {
+ updateIconsAffectedByPackageManagerChanges();
}
- }
-
- @Override
- public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
- super.dispatchPopulateAccessibilityEvent(event);
-
- // we want to take over text population so it is context dependent
- event.getText().clear();
- if (mState == State.ALL_APPS) {
- event.getText().add(getString(R.string.all_apps_button_label));
- } else if (mState == State.WORKSPACE) {
- event.getText().add(getString(R.string.all_apps_home_button_label));
+ if (sGlobalSearchIcon != null) {
+ updateGlobalSearchIcon(sGlobalSearchIcon);
+ }
+ if (sVoiceSearchIcon != null) {
+ updateVoiceSearchIcon(sVoiceSearchIcon);
+ }
+ if (sAppMarketIcon != null) {
+ updateAppMarketIcon(sAppMarketIcon);
}
-
- return true;
}
private void checkForLocaleChange() {
@@ -648,12 +606,6 @@ public final class Launcher extends Activity
case REQUEST_CREATE_SHORTCUT:
completeAddShortcut(args.intent, args.screen, args.cellX, args.cellY);
break;
- case REQUEST_PICK_LIVE_FOLDER:
- addLiveFolder(args.intent);
- break;
- case REQUEST_CREATE_LIVE_FOLDER:
- completeAddLiveFolder(args.intent, args.screen, args.cellX, args.cellY);
- break;
case REQUEST_PICK_APPWIDGET:
addAppWidgetFromPick(args.intent);
break;
@@ -738,7 +690,9 @@ public final class Launcher extends Activity
public Object onRetainNonConfigurationInstance() {
// Flag the loader to stop early before switching
mModel.stopLoader();
- mAllAppsGrid.surrender();
+ if (mAppsCustomizeContent != null) {
+ mAppsCustomizeContent.surrender();
+ }
return Boolean.TRUE;
}
@@ -771,8 +725,10 @@ public final class Launcher extends Activity
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
- boolean handled = super.onKeyDown(keyCode, event);
- if (!handled && acceptFilter() && keyCode != KeyEvent.KEYCODE_ENTER) {
+ final int uniChar = event.getUnicodeChar();
+ final boolean handled = super.onKeyDown(keyCode, event);
+ final boolean isKeyNotWhitespace = uniChar > 0 && !Character.isWhitespace(uniChar);
+ if (!handled && acceptFilter() && isKeyNotWhitespace) {
boolean gotKey = TextKeyListener.getInstance().onKeyDown(mWorkspace, mDefaultKeySsb,
keyCode, event);
if (gotKey && mDefaultKeySsb != null && mDefaultKeySsb.length() > 0) {
@@ -832,10 +788,8 @@ public final class Launcher extends Activity
State state = intToState(savedState.getInt(RUNTIME_STATE, State.WORKSPACE.ordinal()));
- if (state == State.ALL_APPS) {
+ if (state == State.APPS_CUSTOMIZE) {
showAllApps(false);
- } else if (state == State.CUSTOMIZE) {
- showCustomizationDrawer(false);
}
final int currentScreen = savedState.getInt(RUNTIME_STATE_CURRENT_SCREEN, -1);
@@ -859,31 +813,19 @@ public final class Launcher extends Activity
mRestoring = true;
}
- // Restore the current AllApps drawer tab
- if (mAllAppsGrid != null && mAllAppsGrid instanceof AllAppsTabbed) {
- String curTab = savedState.getString("allapps_currentTab");
- if (curTab != null) {
- AllAppsTabbed tabhost = (AllAppsTabbed) mAllAppsGrid;
- tabhost.setCurrentTabByTag(curTab);
- }
- int curPage = savedState.getInt("allapps_currentPage", -1);
- if (curPage > -1) {
- mAllAppsPagedView.setRestorePage(curPage);
- }
- }
- // Restore the current customization drawer tab
- if (mHomeCustomizationDrawer != null) {
- String curTab = savedState.getString("customize_currentTab");
+ // Restore the AppsCustomize tab
+ if (mAppsCustomizeTabHost != null) {
+ String curTab = savedState.getString("apps_customize_currentTab");
if (curTab != null) {
// We set this directly so that there is no delay before the tab is set
- mCustomizePagedView.setCustomizationFilter(
- mHomeCustomizationDrawer.getCustomizeFilterForTabTag(curTab));
- mHomeCustomizationDrawer.setCurrentTabByTag(curTab);
+ mAppsCustomizeContent.setContentType(
+ mAppsCustomizeTabHost.getContentTypeForTabTag(curTab));
+ mAppsCustomizeTabHost.setCurrentTabByTag(curTab);
}
- // Note: currently we do not restore the page for the customization tray because unlike
- // AllApps, the page content can change drastically
+ // Note: currently we do not restore the page for the AppsCustomize pane because the
+ // change in layout can drastically affect the saved page index
}
}
@@ -893,172 +835,110 @@ public final class Launcher extends Activity
private void setupViews() {
final DragController dragController = mDragController;
- DragLayer dragLayer = (DragLayer) findViewById(R.id.drag_layer);
- dragLayer.setDragController(dragController);
-
- mAllAppsGrid = (AllAppsView)dragLayer.findViewById(R.id.all_apps_view);
- mAllAppsGrid.setLauncher(this);
- mAllAppsGrid.setDragController(dragController);
- ((View) mAllAppsGrid).setWillNotDraw(false); // We don't want a hole punched in our window.
- // Manage focusability manually since this thing is always visible (in non-xlarge)
- ((View) mAllAppsGrid).setFocusable(false);
-
- if (LauncherApplication.isScreenXLarge()) {
- // They need to be INVISIBLE initially so that they will be measured in the layout.
- // Otherwise the animations are messed up when we show them for the first time.
- ((View) mAllAppsGrid).setVisibility(View.INVISIBLE);
- mHomeCustomizationDrawer.setVisibility(View.INVISIBLE);
- }
-
- mWorkspace = (Workspace) dragLayer.findViewById(R.id.workspace);
-
- final Workspace workspace = mWorkspace;
- workspace.setHapticFeedbackEnabled(false);
-
- DeleteZone deleteZone = (DeleteZone) dragLayer.findViewById(R.id.delete_zone);
- mDeleteZone = deleteZone;
-
- View handleView = findViewById(R.id.all_apps_button);
- if (handleView != null && handleView instanceof HandleView) {
- // we don't use handle view in xlarge mode
- mHandleView = (HandleView)handleView;
- mHandleView.setLauncher(this);
- mHandleView.setOnClickListener(this);
- mHandleView.setOnLongClickListener(this);
- }
-
- if (mCustomizePagedView != null) {
- mCustomizePagedView.setLauncher(this);
- mCustomizePagedView.setDragController(dragController);
- mCustomizePagedView.setAllAppsPagedView(mAllAppsPagedView);
- } else {
- ImageView hotseatLeft = (ImageView) findViewById(R.id.hotseat_left);
- hotseatLeft.setContentDescription(mHotseatLabels[0]);
- hotseatLeft.setImageDrawable(mHotseatIcons[0]);
- ImageView hotseatRight = (ImageView) findViewById(R.id.hotseat_right);
- hotseatRight.setContentDescription(mHotseatLabels[1]);
- hotseatRight.setImageDrawable(mHotseatIcons[1]);
-
- mPreviousView = (ImageView) dragLayer.findViewById(R.id.previous_screen);
- mNextView = (ImageView) dragLayer.findViewById(R.id.next_screen);
-
- Drawable previous = mPreviousView.getDrawable();
- Drawable next = mNextView.getDrawable();
- mWorkspace.setIndicators(previous, next);
+ mDragLayer = (DragLayer) findViewById(R.id.drag_layer);
+ mWorkspace = (Workspace) mDragLayer.findViewById(R.id.workspace);
- mPreviousView.setHapticFeedbackEnabled(false);
- mPreviousView.setOnLongClickListener(this);
- mNextView.setHapticFeedbackEnabled(false);
- mNextView.setOnLongClickListener(this);
- }
+ // Setup the drag layer
+ mDragLayer.setup(this, dragController);
- workspace.setOnLongClickListener(this);
- workspace.setDragController(dragController);
- workspace.setLauncher(this);
- workspace.setWallpaperDimension();
+ // Setup the workspace
+ mWorkspace.setHapticFeedbackEnabled(false);
+ mWorkspace.setOnLongClickListener(this);
+ mWorkspace.setup(this, dragController);
+ mWorkspace.setWallpaperDimension();
- deleteZone.setLauncher(this);
- deleteZone.setDragController(dragController);
+ // Get the search/delete bar
+ mSearchDeleteBar = (SearchDropTargetBar) mDragLayer.findViewById(R.id.qsb_bar);
- final View allAppsButton = findViewById(R.id.all_apps_button);
- final View divider = findViewById(R.id.divider);
- final View configureButton = findViewById(R.id.configure_button);
+ // Setup AppsCustomize
+ mAppsCustomizeTabHost = (AppsCustomizeTabHost)
+ findViewById(R.id.apps_customize_pane);
+ mAppsCustomizeContent = (AppsCustomizePagedView)
+ mAppsCustomizeTabHost.findViewById(R.id.apps_customize_pane_content);
+ mAppsCustomizeContent.setup(this, dragController);
- if (LauncherApplication.isScreenXLarge()) {
- deleteZone.setOverlappingViews(new View[] { allAppsButton, divider, configureButton });
- } else {
- deleteZone.setOverlappingView(findViewById(R.id.all_apps_button_cluster));
- }
- dragController.addDragListener(deleteZone);
-
- DeleteZone allAppsDeleteZone = (DeleteZone) findViewById(R.id.all_apps_delete_zone);
- if (allAppsDeleteZone != null) {
- allAppsDeleteZone.setLauncher(this);
- allAppsDeleteZone.setDragController(dragController);
- allAppsDeleteZone.setDragAndDropEnabled(false);
- dragController.addDragListener(allAppsDeleteZone);
- dragController.addDropTarget(allAppsDeleteZone);
- }
-
- ApplicationInfoDropTarget allAppsInfoTarget = (ApplicationInfoDropTarget)
- findViewById(R.id.all_apps_info_target);
- if (allAppsInfoTarget != null) {
- allAppsInfoTarget.setLauncher(this);
- dragController.addDragListener(allAppsInfoTarget);
- allAppsInfoTarget.setDragAndDropEnabled(false);
- View marketButton = findViewById(R.id.market_button);
- if (marketButton != null) {
- allAppsInfoTarget.setOverlappingView(marketButton);
- marketButton.setOnClickListener(new OnClickListener() {
- public void onClick(View v) {
- onClickAppMarketButton(v);
- }
- });
+ // Setup AppsCustomize button
+ mAllAppsButton = mDragLayer.findViewById(R.id.all_apps_button);
+ mAllAppsButton.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ onClickAllAppsButton(v);
}
- }
-
- dragController.setDragScoller(workspace);
- dragController.setScrollView(dragLayer);
- dragController.setMoveTarget(workspace);
+ });
- // The order here is bottom to top.
- dragController.addDropTarget(workspace);
- dragController.addDropTarget(deleteZone);
- if (allAppsInfoTarget != null) {
- dragController.addDropTarget(allAppsInfoTarget);
- }
- if (allAppsDeleteZone != null) {
- dragController.addDropTarget(allAppsDeleteZone);
+ if (!LauncherApplication.isScreenLarge()) {
+ // Setup AppsCustomize button on the phone
+ HandleView handleView = (HandleView) mAllAppsButton;
+ handleView.setLauncher(this);
+ handleView.setOnLongClickListener(this);
+
+ // Setup Hotseat
+ ImageView hotseatLeft = (ImageView) findViewById(R.id.hotseat_left);
+ hotseatLeft.setContentDescription(mHotseatLabels[0]);
+ hotseatLeft.setImageDrawable(mHotseatIcons[0]);
+ ImageView hotseatRight = (ImageView) findViewById(R.id.hotseat_right);
+ hotseatRight.setContentDescription(mHotseatLabels[1]);
+ hotseatRight.setImageDrawable(mHotseatIcons[1]);
+
+ View.OnKeyListener listener = new IndicatorKeyEventListener();
+ mPreviousView = (ImageView) mDragLayer.findViewById(R.id.previous_screen);
+ mPreviousView.setOnKeyListener(listener);
+ mNextView = (ImageView) mDragLayer.findViewById(R.id.next_screen);
+ mNextView.setOnKeyListener(listener);
+
+ Drawable previous = mPreviousView.getDrawable();
+ Drawable next = mNextView.getDrawable();
+ mWorkspace.setIndicators(previous, next);
+
+ mPreviousView.setHapticFeedbackEnabled(false);
+ mPreviousView.setOnLongClickListener(this);
+ mNextView.setHapticFeedbackEnabled(false);
+ mNextView.setOnLongClickListener(this);
+ }
+
+ if (!LauncherApplication.isScreenLarge()) {
+ // Setup keylistener for button cluster
+ mButtonCluster = (ViewGroup) findViewById(R.id.all_apps_button_cluster);
+ View.OnKeyListener listener = null;
+ if (LauncherApplication.isScreenLarge()) {
+ // For tablets, AllApps lives in the button bar at the top
+ listener = new ButtonBarKeyEventListener();
+ } else {
+ // For phones, AppsCustomize lives in the "dock" at the bottom
+ listener = new DockKeyEventListener();
+ }
+ int buttonCount = mButtonCluster.getChildCount();
+ for (int i = 0; i < buttonCount; ++i) {
+ mButtonCluster.getChildAt(i).setOnKeyListener(listener);
+ }
}
- mButtonCluster = findViewById(R.id.all_apps_button_cluster);
-
- mAllAppsButton = findViewById(R.id.all_apps_button);
- mDivider = findViewById(R.id.divider);
- mConfigureButton = findViewById(R.id.configure_button);
- // We had previously set these click handlers in XML, but the first time we launched
- // Configure or All Apps we had an extra 50ms of delay while the java reflection methods
- // found the right handler. Setting the handlers directly here eliminates that cost.
- if (mConfigureButton != null) {
- mConfigureButton.setOnClickListener(new OnClickListener() {
- public void onClick(View v) {
- onClickConfigureButton(v);
- }
- });
- }
- if (mDivider != null) {
- mDivider.setOnClickListener(new OnClickListener() {
- public void onClick(View v) {
- onClickAllAppsButton(v);
- }
- });
- }
- if (mAllAppsButton != null) {
- mAllAppsButton.setOnClickListener(new OnClickListener() {
- public void onClick(View v) {
- onClickAllAppsButton(v);
- }
- });
+ // Setup the drag controller (the drop targets have to be added in reverse order)
+ dragController.setDragScoller(mWorkspace);
+ dragController.setScrollView(mDragLayer);
+ dragController.setMoveTarget(mWorkspace);
+ dragController.addDropTarget(mWorkspace);
+ if (mSearchDeleteBar != null) {
+ mSearchDeleteBar.setup(this, dragController);
}
}
@SuppressWarnings({"UnusedDeclaration"})
public void previousScreen(View v) {
- if (mState != State.ALL_APPS) {
+ if (mState != State.APPS_CUSTOMIZE) {
mWorkspace.scrollLeft();
}
}
@SuppressWarnings({"UnusedDeclaration"})
public void nextScreen(View v) {
- if (mState != State.ALL_APPS) {
+ if (mState != State.APPS_CUSTOMIZE) {
mWorkspace.scrollRight();
}
}
@SuppressWarnings({"UnusedDeclaration"})
public void launchHotSeat(View v) {
- if (mState == State.ALL_APPS) return;
+ if (mState == State.APPS_CUSTOMIZE) return;
int index = -1;
if (v.getId() == R.id.hotseat_left) {
@@ -1254,6 +1134,11 @@ public final class Launcher extends Activity
if (Intent.ACTION_SCREEN_OFF.equals(action)) {
mUserPresent = false;
updateRunning();
+
+ // Reset AllApps to it's initial state
+ if (mAppsCustomizeContent != null) {
+ mAppsCustomizeContent.reset();
+ }
} else if (Intent.ACTION_USER_PRESENT.equals(action)) {
mUserPresent = true;
updateRunning();
@@ -1408,11 +1293,7 @@ public final class Launcher extends Activity
!= Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
// In all these cases, only animate if we're already on home
-
- if (LauncherApplication.isScreenXLarge()) {
- mWorkspace.unshrink(alreadyOnHome);
- }
-
+ mWorkspace.unshrink(alreadyOnHome);
mWorkspace.exitWidgetResizeMode();
if (alreadyOnHome && mState == State.WORKSPACE && !mWorkspace.isTouchActive()) {
mWorkspace.moveToDefaultScreen(true);
@@ -1425,6 +1306,11 @@ public final class Launcher extends Activity
INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
}
+
+ // Reset AllApps to it's initial state
+ if (mAppsCustomizeContent != null) {
+ mAppsCustomizeContent.reset();
+ }
}
}
@@ -1446,7 +1332,7 @@ public final class Launcher extends Activity
final FolderInfo info = folders.get(i).getInfo();
ids[i] = info.id;
}
- outState.putLongArray(RUNTIME_STATE_USER_FOLDERS, ids);
+ outState.putLongArray(RUNTIME_STATE_FOLDERS, ids);
} else {
super.onSaveInstanceState(outState);
}
@@ -1464,21 +1350,11 @@ public final class Launcher extends Activity
outState.putLong(RUNTIME_STATE_PENDING_FOLDER_RENAME_ID, mFolderInfo.id);
}
- // Save the current AllApps drawer tab
- if (mAllAppsGrid != null && mAllAppsGrid instanceof AllAppsTabbed) {
- AllAppsTabbed tabhost = (AllAppsTabbed) mAllAppsGrid;
- String currentTabTag = tabhost.getCurrentTabTag();
+ // Save the current AppsCustomize tab
+ if (mAppsCustomizeTabHost != null) {
+ String currentTabTag = mAppsCustomizeTabHost.getCurrentTabTag();
if (currentTabTag != null) {
- outState.putString("allapps_currentTab", currentTabTag);
- outState.putInt("allapps_currentPage", mAllAppsPagedView.getCurrentPage());
- }
- }
-
- // Save the current customization drawer tab
- if (mHomeCustomizationDrawer != null) {
- String currentTabTag = mHomeCustomizationDrawer.getCurrentTabTag();
- if (currentTabTag != null) {
- outState.putString("customize_currentTab", currentTabTag);
+ outState.putString("apps_customize_currentTab", currentTabTag);
}
}
}
@@ -1487,6 +1363,11 @@ public final class Launcher extends Activity
public void onDestroy() {
super.onDestroy();
+ // Stop callbacks from LauncherModel
+ LauncherApplication app = ((LauncherApplication) getApplication());
+ mModel.stopLoader();
+ app.setLauncher(null);
+
try {
mAppWidgetHost.stopListening();
} catch (NullPointerException ex) {
@@ -1498,7 +1379,6 @@ public final class Launcher extends Activity
TextKeyListener.getInstance().release();
- mModel.stopLoader();
unbindDesktopItems();
@@ -1522,6 +1402,10 @@ public final class Launcher extends Activity
ValueAnimator.clearAllAnimations();
}
+ public DragController getDragController() {
+ return mDragController;
+ }
+
@Override
public void startActivityForResult(Intent intent, int requestCode) {
if (requestCode >= 0) mWaitingForResult = true;
@@ -1589,22 +1473,9 @@ public final class Launcher extends Activity
public boolean onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
- // If all apps is animating, don't show the menu, because we don't know
- // which one to show.
- if (mAllAppsGrid.isAnimating()) {
- return false;
- }
-
- // Only show the add and wallpaper options when we're not in all apps.
- boolean visible = !mAllAppsGrid.isVisible();
- menu.setGroupVisible(MENU_GROUP_ADD, visible);
- menu.setGroupVisible(MENU_GROUP_WALLPAPER, visible);
-
- // Disable add if the workspace is full.
- if (visible) {
- CellLayout layout = (CellLayout) mWorkspace.getChildAt(mWorkspace.getCurrentPage());
- menu.setGroupEnabled(MENU_GROUP_ADD, layout.existsEmptyCell());
- }
+ // TODO-APPS_CUSTOMIZE: Remove this for the phone UI at some point, along with all the menu
+ // related code?
+ if (mAppsCustomizeContent != null && mAppsCustomizeContent.isAnimating()) return false;
return true;
}
@@ -1654,15 +1525,8 @@ public final class Launcher extends Activity
}
private void addItems() {
- if (LauncherApplication.isScreenXLarge()) {
- // Animate the widget chooser up from the bottom of the screen
- if (mState != State.CUSTOMIZE) {
- showCustomizationDrawer(true);
- }
- } else {
- showWorkspace(true);
- showAddDialog(-1, -1);
- }
+ showWorkspace(true);
+ showAddDialog(-1, -1);
}
private void resetAddInfo() {
@@ -1771,38 +1635,15 @@ public final class Launcher extends Activity
startActivityForResult(intent, REQUEST_PICK_WALLPAPER);
}
- void addLiveFolderFromDrop(ComponentName componentName, int screen, int[] position) {
- resetAddInfo();
- mAddScreen = screen;
- mAddDropPosition = position;
-
- Intent createFolderIntent = new Intent(LiveFolders.ACTION_CREATE_LIVE_FOLDER);
- createFolderIntent.setComponent(componentName);
-
- addLiveFolder(createFolderIntent);
- }
-
- void addLiveFolder(Intent intent) { // YYY add screen intersect etc. parameters here
- // Handle case where user selected "Folder"
- String folderName = getResources().getString(R.string.group_folder);
- String shortcutName = intent.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);
-
- if (folderName != null && folderName.equals(shortcutName)) {
- addFolder(mAddScreen, mAddIntersectCellX, mAddIntersectCellY);
- } else {
- startActivityForResultSafely(intent, REQUEST_CREATE_LIVE_FOLDER);
- }
- }
-
- void addFolder(int screen, int intersectCellX, int intersectCellY) {
- UserFolderInfo folderInfo = new UserFolderInfo();
+ FolderIcon addFolder(int screen, int intersectCellX, int intersectCellY) {
+ FolderInfo folderInfo = new FolderInfo();
folderInfo.title = getText(R.string.folder_name);
final CellLayout layout = (CellLayout) mWorkspace.getChildAt(screen);
final int[] cellXY = mTmpAddItemCellCoordinates;
if (!layout.findCellForSpanThatIntersects(cellXY, 1, 1, intersectCellX, intersectCellY)) {
showOutOfSpaceMessage();
- return;
+ return null;
}
// Update the model
@@ -1816,73 +1657,13 @@ public final class Launcher extends Activity
(ViewGroup) mWorkspace.getChildAt(mWorkspace.getCurrentPage()),
folderInfo, mIconCache);
mWorkspace.addInScreen(newFolder, screen, cellXY[0], cellXY[1], 1, 1, isWorkspaceLocked());
+ return newFolder;
}
void removeFolder(FolderInfo folder) {
sFolders.remove(folder.id);
}
- private void completeAddLiveFolder(
- Intent data, int screen, int intersectCellX, int intersectCellY) {
- final CellLayout layout = (CellLayout) mWorkspace.getChildAt(screen);
- final int[] cellXY = mTmpAddItemCellCoordinates;
- if (!layout.findCellForSpanThatIntersects(cellXY, 1, 1, intersectCellX, intersectCellY)) {
- showOutOfSpaceMessage();
- return;
- }
-
- final LiveFolderInfo info = addLiveFolder(this, data, screen, cellXY[0], cellXY[1], false);
-
- if (!mRestoring) {
- final View view = LiveFolderIcon.fromXml(R.layout.live_folder_icon, this,
- (ViewGroup) mWorkspace.getChildAt(mWorkspace.getCurrentPage()), info);
- mWorkspace.addInScreen(view, screen, cellXY[0], cellXY[1], 1, 1, isWorkspaceLocked());
- }
- }
-
- static LiveFolderInfo addLiveFolder(Context context, Intent data,
- int screen, int cellX, int cellY, boolean notify) {
-
- Intent baseIntent = data.getParcelableExtra(LiveFolders.EXTRA_LIVE_FOLDER_BASE_INTENT);
- String name = data.getStringExtra(LiveFolders.EXTRA_LIVE_FOLDER_NAME);
-
- Drawable icon = null;
- Intent.ShortcutIconResource iconResource = null;
-
- Parcelable extra = data.getParcelableExtra(LiveFolders.EXTRA_LIVE_FOLDER_ICON);
- if (extra != null && extra instanceof Intent.ShortcutIconResource) {
- try {
- iconResource = (Intent.ShortcutIconResource) extra;
- final PackageManager packageManager = context.getPackageManager();
- Resources resources = packageManager.getResourcesForApplication(
- iconResource.packageName);
- final int id = resources.getIdentifier(iconResource.resourceName, null, null);
- icon = resources.getDrawable(id);
- } catch (Exception e) {
- Log.w(TAG, "Could not load live folder icon: " + extra);
- }
- }
-
- if (icon == null) {
- icon = context.getResources().getDrawable(R.drawable.ic_launcher_folder);
- }
-
- final LiveFolderInfo info = new LiveFolderInfo();
- info.icon = Utilities.createIconBitmap(icon, context);
- info.title = name;
- info.iconResource = iconResource;
- info.uri = data.getData();
- info.baseIntent = baseIntent;
- info.displayMode = data.getIntExtra(LiveFolders.EXTRA_LIVE_FOLDER_DISPLAY_MODE,
- LiveFolders.DISPLAY_MODE_GRID);
-
- LauncherModel.addItemToDatabase(context, info, LauncherSettings.Favorites.CONTAINER_DESKTOP,
- screen, cellX, cellY, notify);
- sFolders.put(info.id, info);
-
- return info;
- }
-
private void showNotifications() {
final StatusBarManager statusBar = (StatusBarManager) getSystemService(STATUS_BAR_SERVICE);
if (statusBar != null) {
@@ -1944,7 +1725,7 @@ public final class Launcher extends Activity
@Override
public void onBackPressed() {
- if (mState == State.ALL_APPS || mState == State.CUSTOMIZE) {
+ if (mState == State.APPS_CUSTOMIZE) {
showWorkspace(true);
} else if (mWorkspace.getOpenFolder() != null) {
closeFolder();
@@ -1959,24 +1740,26 @@ public final class Launcher extends Activity
}
}
- private void closeFolder() {
+ public void closeFolder() {
Folder folder = mWorkspace.getOpenFolder();
if (folder != null) {
closeFolder(folder);
+ mDragLayer.setCurrentFolder(null);
}
}
void closeFolder(Folder folder) {
folder.getInfo().opened = false;
+
ViewGroup parent = (ViewGroup) folder.getParent().getParent();
if (parent != null) {
CellLayout cl = (CellLayout) parent;
- cl.removeViewWithoutMarkingCells(folder);
- if (folder instanceof DropTarget) {
- // Live folders aren't DropTargets.
- mDragController.removeDropTarget((DropTarget)folder);
- }
+ FolderIcon fi = (FolderIcon) cl.getChildAt(folder.mInfo.cellX, folder.mInfo.cellY);
+ shrinkAndFadeInFolderIcon(fi);
+ mDragController.removeDropTarget((DropTarget)folder);
}
+
+ folder.animateClosed();
folder.onClose();
}
@@ -2021,9 +1804,12 @@ public final class Launcher extends Activity
mWaitingForResume.setStayPressed(true);
}
} else if (tag instanceof FolderInfo) {
- handleFolderClick((FolderInfo) tag);
- } else if (v == mHandleView) {
- if (mState == State.ALL_APPS) {
+ if (v instanceof FolderIcon) {
+ FolderIcon fi = (FolderIcon) v;
+ handleFolderClick(fi);
+ }
+ } else if (v == mAllAppsButton) {
+ if (mState == State.APPS_CUSTOMIZE) {
showWorkspace(true);
} else {
showAllApps(true);
@@ -2143,15 +1929,16 @@ public final class Launcher extends Activity
}
}
- private void handleFolderClick(FolderInfo folderInfo) {
- if (!folderInfo.opened) {
+ private void handleFolderClick(FolderIcon folderIcon) {
+ final FolderInfo info = folderIcon.mInfo;
+ if (!info.opened) {
// Close any open folder
closeFolder();
// Open the requested folder
- openFolder(folderInfo);
+ openFolder(folderIcon);
} else {
// Find the open folder...
- Folder openFolder = mWorkspace.getFolderForTag(folderInfo);
+ Folder openFolder = mWorkspace.getFolderForTag(info);
int folderScreen;
if (openFolder != null) {
folderScreen = mWorkspace.getPageForView(openFolder);
@@ -2161,12 +1948,32 @@ public final class Launcher extends Activity
// Close any folder open on the current screen
closeFolder();
// Pull the folder onto this screen
- openFolder(folderInfo);
+ openFolder(folderIcon);
}
}
}
}
+ private void growAndFadeOutFolderIcon(FolderIcon fi) {
+ PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 0);
+ PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX", 1.5f);
+ PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY", 1.5f);
+
+ ObjectAnimator oa = ObjectAnimator.ofPropertyValuesHolder(fi, alpha, scaleX, scaleY);
+ oa.setDuration(getResources().getInteger(R.integer.config_folderAnimDuration));
+ oa.start();
+ }
+
+ private void shrinkAndFadeInFolderIcon(FolderIcon fi) {
+ PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 1.0f);
+ PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX", 1.0f);
+ PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY", 1.0f);
+
+ ObjectAnimator oa = ObjectAnimator.ofPropertyValuesHolder(fi, alpha, scaleX, scaleY);
+ oa.setDuration(getResources().getInteger(R.integer.config_folderAnimDuration));
+ oa.start();
+ }
+
/**
* Opens the user folder described by the specified tag. The opening of the folder
* is animated relative to the specified View. If the View is null, no animation
@@ -2174,26 +1981,17 @@ public final class Launcher extends Activity
*
* @param folderInfo The FolderInfo describing the folder to open.
*/
- public void openFolder(FolderInfo folderInfo) {
- Folder openFolder;
+ public void openFolder(FolderIcon folderIcon) {
+ Folder folder = folderIcon.mFolder;
+ FolderInfo info = folder.mInfo;
- if (folderInfo instanceof UserFolderInfo) {
- openFolder = UserFolder.fromXml(this);
- } else if (folderInfo instanceof LiveFolderInfo) {
- openFolder = com.android.launcher2.LiveFolder.fromXml(this, folderInfo);
- } else {
- return;
- }
+ growAndFadeOutFolderIcon(folderIcon);
+ info.opened = true;
- openFolder.setDragController(mDragController);
- openFolder.setLauncher(this);
-
- openFolder.bind(folderInfo);
- folderInfo.opened = true;
-
- mWorkspace.addInFullScreen(openFolder, folderInfo.screen);
-
- openFolder.onOpen();
+ mWorkspace.addInFullScreen(folder, info.screen);
+ mDragLayer.setCurrentFolder(folder);
+ folder.animateOpen();
+ folder.onOpen();
}
public boolean onLongClick(View v) {
@@ -2203,21 +2001,21 @@ public final class Launcher extends Activity
switch (v.getId()) {
case R.id.previous_screen:
- if (mState != State.ALL_APPS) {
+ if (mState != State.APPS_CUSTOMIZE) {
mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,
HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
showPreviews(v);
}
return true;
case R.id.next_screen:
- if (mState != State.ALL_APPS) {
+ if (mState != State.APPS_CUSTOMIZE) {
mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,
HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
showPreviews(v);
}
return true;
case R.id.all_apps_button:
- if (mState != State.ALL_APPS) {
+ if (mState != State.APPS_CUSTOMIZE) {
mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,
HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
showPreviews(v);
@@ -2248,11 +2046,7 @@ public final class Launcher extends Activity
mWorkspace.setAllowLongPress(false);
mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,
HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
- if (LauncherApplication.isScreenXLarge()) {
- addItems();
- } else {
- showAddDialog(longClickCellInfo.cellX, longClickCellInfo.cellY);
- }
+ addItems();
} else {
if (!(itemUnderLongClick instanceof Folder)) {
// User long pressed on an item
@@ -2278,11 +2072,12 @@ public final class Launcher extends Activity
for (int i = 0; i < count; i++) {
((ImageView) group.getChildAt(i)).setImageDrawable(null);
}
- ArrayList<Bitmap> bitmaps = (ArrayList<Bitmap>) v.getTag(R.id.icon);
+ ArrayList<Bitmap> bitmaps =
+ (ArrayList<Bitmap>) v.getTag(R.id.all_apps_button_cluster);
for (Bitmap bitmap : bitmaps) bitmap.recycle();
v.setTag(R.id.workspace, null);
- v.setTag(R.id.icon, null);
+ v.setTag(R.id.all_apps_button_cluster, null);
window.setOnDismissListener(null);
}
});
@@ -2374,7 +2169,7 @@ public final class Launcher extends Activity
anchor.setTag(p);
anchor.setTag(R.id.workspace, preview);
- anchor.setTag(R.id.icon, bitmaps);
+ anchor.setTag(R.id.all_apps_button_cluster, bitmaps);
}
class PreviewTouchHandler implements View.OnClickListener, Runnable, View.OnFocusChangeListener {
@@ -2404,10 +2199,6 @@ public final class Launcher extends Activity
return mWorkspace;
}
- TabHost getCustomizationDrawer() {
- return mHomeCustomizationDrawer;
- }
-
@Override
protected Dialog onCreateDialog(int id) {
switch (id) {
@@ -2533,7 +2324,9 @@ public final class Launcher extends Activity
final FolderIcon folderIcon = (FolderIcon)
mWorkspace.getViewForTag(mFolderInfo);
if (folderIcon != null) {
- folderIcon.setText(name);
+ // TODO: At some point we'll probably want some version of setting
+ // the text for a folder icon.
+ //folderIcon.setText(name);
getWorkspace().requestLayout();
} else {
lockAllApps();
@@ -2554,114 +2347,20 @@ public final class Launcher extends Activity
// Now a part of LauncherModel.Callbacks. Used to reorder loading steps.
public boolean isAllAppsVisible() {
- return mState == State.ALL_APPS;
+ return (mState == State.APPS_CUSTOMIZE);
}
// AllAppsView.Watcher
public void zoomed(float zoom) {
- // In XLarge view, we zoom down the workspace below all apps so it's still visible
- if (zoom == 1.0f && !LauncherApplication.isScreenXLarge()) {
+ if (zoom == 1.0f) {
mWorkspace.setVisibility(View.GONE);
}
}
-
- private void showAndEnableToolbarButton(View button) {
- button.setVisibility(View.VISIBLE);
- button.setFocusable(true);
- button.setClickable(true);
- }
-
- private void hideToolbarButton(View button) {
- button.setAlpha(0.0f);
- // We can't set it to GONE, otherwise the RelativeLayout gets screwed up
- button.setVisibility(View.INVISIBLE);
- }
-
- private void disableToolbarButton(View button) {
- button.setFocusable(false);
- button.setClickable(false);
- }
-
- /**
- * Helper function for showing or hiding a toolbar button, possibly animated.
- *
- * @param show If true, create an animation to the show the item. Otherwise, hide it.
- * @param view The toolbar button to be animated
- * @param seq A AnimatorSet that will be used to animate the transition. If null, the
- * transition will not be animated.
- */
- private void hideOrShowToolbarButton(boolean show, final View view, AnimatorSet seq) {
- final boolean showing = show;
- final boolean hiding = !show;
-
- final int duration = show ?
- getResources().getInteger(R.integer.config_toolbarButtonFadeInTime) :
- getResources().getInteger(R.integer.config_toolbarButtonFadeOutTime);
-
- if (seq != null) {
- ValueAnimator anim = ValueAnimator.ofFloat(view.getAlpha(), show ? 1.0f : 0.0f);
- anim.setDuration(duration);
- anim.addUpdateListener(new AnimatorUpdateListener() {
- public void onAnimationUpdate(ValueAnimator animation) {
- view.setAlpha((Float) animation.getAnimatedValue());
- }
- });
- anim.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationStart(Animator animation) {
- if (showing) showAndEnableToolbarButton(view);
- if (hiding) disableToolbarButton(view);
- }
- @Override
- public void onAnimationEnd(Animator animation) {
- if (hiding) hideToolbarButton(view);
- }
- });
- seq.play(anim);
- } else {
- if (showing) {
- showAndEnableToolbarButton(view);
- view.setAlpha(1f);
- } else {
- disableToolbarButton(view);
- hideToolbarButton(view);
- }
- }
- }
-
- /**
- * Show/hide the appropriate toolbar buttons for newState.
- * If showSeq or hideSeq is null, the transition will be done immediately (not animated).
- *
- * @param newState The state that is being switched to
- * @param showSeq AnimatorSet in which to put "show" animations, or null.
- * @param hideSeq AnimatorSet in which to put "hide" animations, or null.
- */
- private void hideAndShowToolbarButtons(State newState, AnimatorSet showSeq, AnimatorSet hideSeq) {
- switch (newState) {
- case WORKSPACE:
- hideOrShowToolbarButton(true, mButtonCluster, showSeq);
- mDeleteZone.setOverlappingViews(
- new View[] { mAllAppsButton, mDivider, mConfigureButton });
- mDeleteZone.setDragAndDropEnabled(true);
- mDeleteZone.setText(getResources().getString(R.string.delete_zone_label_workspace));
- break;
- case ALL_APPS:
- hideOrShowToolbarButton(false, mButtonCluster, hideSeq);
- mDeleteZone.setDragAndDropEnabled(false);
- mDeleteZone.setText(getResources().getString(R.string.delete_zone_label_all_apps));
- break;
- case CUSTOMIZE:
- hideOrShowToolbarButton(false, mButtonCluster, hideSeq);
- mDeleteZone.setDragAndDropEnabled(false);
- break;
- }
- }
/**
* Helper method for the cameraZoomIn/cameraZoomOut animations
* @param view The view being animated
- * @param state The state that we are moving in or out of -- either ALL_APPS or CUSTOMIZE
+ * @param state The state that we are moving in or out of (eg. APPS_CUSTOMIZE)
* @param scaleFactor The scale factor used for the zoom
*/
private void setPivotsForZoom(View view, State state, float scaleFactor) {
@@ -2671,7 +2370,7 @@ public final class Launcher extends Activity
// Set pivotY so that at the starting zoom factor, the view is partially
// visible. Modifying initialHeightFactor changes how much of the view is
// initially showing, and hence the perceived angle from which the view enters.
- if (state == State.ALL_APPS) {
+ if (state == State.APPS_CUSTOMIZE) {
final float initialHeightFactor = 0.175f;
view.setPivotY((1 - initialHeightFactor) * height);
} else {
@@ -2684,60 +2383,54 @@ public final class Launcher extends Activity
* Zoom the camera out from the workspace to reveal 'toView'.
* Assumes that the view to show is anchored at either the very top or very bottom
* of the screen.
- * @param toState The state to zoom out to. Must be ALL_APPS or CUSTOMIZE.
+ * @param toState The state to zoom out to. Must be APPS_CUSTOMIZE.
*/
- private void cameraZoomOut(State toState, boolean animated) {
+ private void cameraZoomOut(State toState, boolean animated, boolean springLoaded) {
final Resources res = getResources();
- final boolean toAllApps = (toState == State.ALL_APPS);
-
- final int duration = toAllApps ?
- res.getInteger(R.integer.config_allAppsZoomInTime) :
- res.getInteger(R.integer.config_customizeZoomInTime);
- final int fadeDuration = toAllApps ?
- res.getInteger(R.integer.config_allAppsFadeInTime) :
- res.getInteger(R.integer.config_customizeFadeInTime);
- final float scale = toAllApps ?
- (float) res.getInteger(R.integer.config_allAppsZoomScaleFactor) :
- (float) res.getInteger(R.integer.config_customizeZoomScaleFactor);
-
- final View toView = toAllApps ? (View) mAllAppsGrid : mHomeCustomizationDrawer;
+ final int duration = res.getInteger(R.integer.config_appsCustomizeZoomInTime);
+ final int fadeDuration = res.getInteger(R.integer.config_appsCustomizeFadeInTime);
+ final float scale = (float) res.getInteger(R.integer.config_appsCustomizeZoomScaleFactor);
+ final View toView = mAppsCustomizeTabHost;
setPivotsForZoom(toView, toState, scale);
- if (toAllApps) {
- mWorkspace.shrink(ShrinkState.BOTTOM_HIDDEN, animated);
+
+ if (springLoaded) {
+ if (toState == State.APPS_CUSTOMIZE) {
+ // Shrink workspaces away if going back to AppsCustomize from spring loaded mode
+ mWorkspace.shrink(ShrinkState.BOTTOM_HIDDEN, animated);
+ } else {
+ // Shrink workspaces to bottom if going back to AllApps from spring loaded mode
+ mWorkspace.shrink(ShrinkState.BOTTOM_VISIBLE, animated);
+ }
} else {
- mWorkspace.shrink(ShrinkState.TOP, animated);
+ // Shrink workspaces away if going to AllApps/AppsCustomize from workspace
+ mWorkspace.shrink(ShrinkState.BOTTOM_HIDDEN, animated);
}
if (animated) {
final ValueAnimator scaleAnim = ValueAnimator.ofFloat(0f, 1f).setDuration(duration);
scaleAnim.setInterpolator(new Workspace.ZoomOutInterpolator());
- scaleAnim.addUpdateListener(new AnimatorUpdateListener() {
- public void onAnimationUpdate(ValueAnimator animation) {
- final float b = (Float) animation.getAnimatedValue();
- final float a = 1f - b;
+ scaleAnim.addUpdateListener(new LauncherAnimatorUpdateListener() {
+ public void onAnimationUpdate(float a, float b) {
((View) toView.getParent()).fastInvalidate();
toView.setFastScaleX(a * scale + b * 1f);
toView.setFastScaleY(a * scale + b * 1f);
}
});
- if (toAllApps) {
- toView.setFastAlpha(0f);
- ValueAnimator alphaAnim = ValueAnimator.ofFloat(0f, 1f).setDuration(fadeDuration);
- alphaAnim.setInterpolator(new DecelerateInterpolator(1.5f));
- alphaAnim.addUpdateListener(new AnimatorUpdateListener() {
- public void onAnimationUpdate(ValueAnimator animation) {
- final float b = (Float) animation.getAnimatedValue();
- final float a = 1f - b;
- // don't need to invalidate because we do so above
- toView.setFastAlpha(a * 0f + b * 1f);
- }
- });
- alphaAnim.start();
- }
+ toView.setVisibility(View.VISIBLE);
+ toView.setFastAlpha(0f);
+ ValueAnimator alphaAnim = ValueAnimator.ofFloat(0f, 1f).setDuration(fadeDuration);
+ alphaAnim.setInterpolator(new DecelerateInterpolator(1.5f));
+ alphaAnim.addUpdateListener(new LauncherAnimatorUpdateListener() {
+ public void onAnimationUpdate(float a, float b) {
+ // don't need to invalidate because we do so above
+ toView.setFastAlpha(a * 0f + b * 1f);
+ }
+ });
+ alphaAnim.start();
if (toView instanceof LauncherTransitionable) {
((LauncherTransitionable) toView).onLauncherTransitionStart(scaleAnim);
@@ -2749,9 +2442,7 @@ public final class Launcher extends Activity
toView.setTranslationX(0.0f);
toView.setTranslationY(0.0f);
toView.setVisibility(View.VISIBLE);
- if (!toAllApps) {
- toView.setFastAlpha(1.0f);
- }
+ toView.bringToFront();
}
@Override
public void onAnimationEnd(Animator animation) {
@@ -2766,21 +2457,12 @@ public final class Launcher extends Activity
}
});
- AnimatorSet toolbarHideAnim = new AnimatorSet();
- AnimatorSet toolbarShowAnim = new AnimatorSet();
- hideAndShowToolbarButtons(toState, toolbarShowAnim, toolbarHideAnim);
-
// toView should appear right at the end of the workspace shrink animation
final int startDelay = 0;
if (mStateAnimation != null) mStateAnimation.cancel();
mStateAnimation = new AnimatorSet();
- mStateAnimation.playTogether(scaleAnim, toolbarHideAnim);
mStateAnimation.play(scaleAnim).after(startDelay);
-
- // Show the new toolbar buttons just as the main animation is ending
- final int fadeInTime = res.getInteger(R.integer.config_toolbarButtonFadeInTime);
- mStateAnimation.play(toolbarShowAnim).after(duration + startDelay - fadeInTime);
mStateAnimation.start();
} else {
toView.setTranslationX(0.0f);
@@ -2788,47 +2470,33 @@ public final class Launcher extends Activity
toView.setScaleX(1.0f);
toView.setScaleY(1.0f);
toView.setVisibility(View.VISIBLE);
+ toView.bringToFront();
if (toView instanceof LauncherTransitionable) {
((LauncherTransitionable) toView).onLauncherTransitionStart(null);
((LauncherTransitionable) toView).onLauncherTransitionEnd(null);
}
- hideAndShowToolbarButtons(toState, null, null);
}
}
/**
* Zoom the camera back into the workspace, hiding 'fromView'.
* This is the opposite of cameraZoomOut.
- * @param fromState The current state (must be ALL_APPS or CUSTOMIZE).
+ * @param fromState The current state (must be APPS_CUSTOMIZE).
* @param animated If true, the transition will be animated.
*/
- private void cameraZoomIn(State fromState, boolean animated) {
- cameraZoomIn(fromState, animated, false);
- }
-
private void cameraZoomIn(State fromState, boolean animated, boolean springLoaded) {
Resources res = getResources();
- final boolean fromAllApps = (fromState == State.ALL_APPS);
- int duration = fromAllApps ?
- res.getInteger(R.integer.config_allAppsZoomOutTime) :
- res.getInteger(R.integer.config_customizeZoomOutTime);
-
- final float scaleFactor = fromAllApps ?
- (float) res.getInteger(R.integer.config_allAppsZoomScaleFactor) :
- (float) res.getInteger(R.integer.config_customizeZoomScaleFactor);
-
- final View fromView = fromAllApps ? (View) mAllAppsGrid : mHomeCustomizationDrawer;
-
- mCustomizePagedView.endChoiceMode();
- mAllAppsPagedView.endChoiceMode();
+ final int duration = res.getInteger(R.integer.config_appsCustomizeZoomOutTime);
+ final float scaleFactor = (float)
+ res.getInteger(R.integer.config_appsCustomizeZoomScaleFactor);
+ final View fromView = mAppsCustomizeTabHost;
setPivotsForZoom(fromView, fromState, scaleFactor);
if (!springLoaded) {
mWorkspace.unshrink(animated);
}
-
if (animated) {
if (mStateAnimation != null) mStateAnimation.cancel();
mStateAnimation = new AnimatorSet();
@@ -2838,22 +2506,18 @@ public final class Launcher extends Activity
ValueAnimator scaleAnim = ValueAnimator.ofFloat(0f, 1f).setDuration(duration);
scaleAnim.setInterpolator(new Workspace.ZoomInInterpolator());
- scaleAnim.addUpdateListener(new AnimatorUpdateListener() {
- public void onAnimationUpdate(ValueAnimator animation) {
- final float b = (Float) animation.getAnimatedValue();
- final float a = 1f - b;
+ scaleAnim.addUpdateListener(new LauncherAnimatorUpdateListener() {
+ public void onAnimationUpdate(float a, float b) {
((View)fromView.getParent()).fastInvalidate();
fromView.setFastScaleX(a * oldScaleX + b * scaleFactor);
fromView.setFastScaleY(a * oldScaleY + b * scaleFactor);
}
});
final ValueAnimator alphaAnim = ValueAnimator.ofFloat(0f, 1f);
- alphaAnim.setDuration(res.getInteger(R.integer.config_allAppsFadeOutTime));
+ alphaAnim.setDuration(res.getInteger(R.integer.config_appsCustomizeFadeOutTime));
alphaAnim.setInterpolator(new DecelerateInterpolator(1.5f));
- alphaAnim.addUpdateListener(new AnimatorUpdateListener() {
- public void onAnimationUpdate(ValueAnimator animation) {
- final float b = (Float) animation.getAnimatedValue();
- final float a = 1f - b;
+ alphaAnim.addUpdateListener(new LauncherAnimatorUpdateListener() {
+ public void onAnimationUpdate(float a, float b) {
// don't need to invalidate because we do so above
fromView.setFastAlpha(a * 1f + b * 0f);
}
@@ -2871,18 +2535,7 @@ public final class Launcher extends Activity
}
});
- AnimatorSet toolbarHideAnim = new AnimatorSet();
- AnimatorSet toolbarShowAnim = new AnimatorSet();
- if (!springLoaded) {
- hideAndShowToolbarButtons(State.WORKSPACE, toolbarShowAnim, toolbarHideAnim);
- }
-
- mStateAnimation.playTogether(scaleAnim, toolbarHideAnim, alphaAnim);
-
- // Show the new toolbar buttons at the very end of the whole animation
- final int fadeInTime = res.getInteger(R.integer.config_toolbarButtonFadeInTime);
- final int unshrinkTime = res.getInteger(R.integer.config_workspaceUnshrinkTime);
- mStateAnimation.play(toolbarShowAnim).after(unshrinkTime - fadeInTime);
+ mStateAnimation.playTogether(scaleAnim, alphaAnim);
mStateAnimation.start();
} else {
fromView.setVisibility(View.GONE);
@@ -2890,40 +2543,9 @@ public final class Launcher extends Activity
((LauncherTransitionable) fromView).onLauncherTransitionStart(null);
((LauncherTransitionable) fromView).onLauncherTransitionEnd(null);
}
- if (!springLoaded) {
- hideAndShowToolbarButtons(State.WORKSPACE, null, null);
- }
}
}
- void showAllApps(boolean animated) {
- if (mState != State.WORKSPACE) {
- return;
- }
-
- if (LauncherApplication.isScreenXLarge()) {
- cameraZoomOut(State.ALL_APPS, animated);
- } else {
- mAllAppsGrid.zoom(1.0f, animated);
- }
-
- ((View) mAllAppsGrid).setFocusable(true);
- ((View) mAllAppsGrid).requestFocus();
-
- // TODO: fade these two too
- mDeleteZone.setVisibility(View.GONE);
-
- // Change the state *after* we've called all the transition code
- mState = State.ALL_APPS;
-
- // Pause the auto-advance of widgets until we are out of AllApps
- mUserPresent = false;
- updateRunning();
-
- // send an accessibility event to announce the context change
- getWindow().getDecorView().sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
- }
-
void showWorkspace(boolean animated) {
showWorkspace(animated, null);
}
@@ -2936,10 +2558,8 @@ public final class Launcher extends Activity
} else {
mWorkspace.unshrink(animated);
}
- if (mState == State.ALL_APPS) {
+ if (mState == State.APPS_CUSTOMIZE) {
closeAllApps(animated);
- } else if (mState == State.CUSTOMIZE) {
- hideCustomizationDrawer(animated);
}
// Change the state *after* we've called all the transition code
@@ -2954,30 +2574,80 @@ public final class Launcher extends Activity
}
void enterSpringLoadedDragMode(CellLayout layout) {
+ // Enter spring loaded mode on a new layout
mWorkspace.enterSpringLoadedDragMode(layout);
- if (mState == State.ALL_APPS) {
- cameraZoomIn(State.ALL_APPS, true, true);
- mState = State.ALL_APPS_SPRING_LOADED;
- } else if (mState == State.CUSTOMIZE) {
- cameraZoomIn(State.CUSTOMIZE, true, true);
- mState = State.CUSTOMIZE_SPRING_LOADED;
- }/* else {
- // we're already in spring loaded mode; don't do anything
- }*/
+
+ if (mState == State.APPS_CUSTOMIZE) {
+ mState = State.APPS_CUSTOMIZE_SPRING_LOADED;
+ cameraZoomIn(State.APPS_CUSTOMIZE, true, true);
+ }
+ // Otherwise, we are not in spring loaded mode, so don't do anything.
}
void exitSpringLoadedDragMode() {
- if (mState == State.ALL_APPS_SPRING_LOADED) {
+ if (mState == State.APPS_CUSTOMIZE_SPRING_LOADED) {
mWorkspace.exitSpringLoadedDragMode(Workspace.ShrinkState.BOTTOM_VISIBLE);
- cameraZoomOut(State.ALL_APPS, true);
- mState = State.ALL_APPS;
- } else if (mState == State.CUSTOMIZE_SPRING_LOADED) {
- mWorkspace.exitSpringLoadedDragMode(Workspace.ShrinkState.TOP);
- cameraZoomOut(State.CUSTOMIZE, true);
- mState = State.CUSTOMIZE;
- }/* else {
- // we're not in spring loaded mode; don't do anything
- }*/
+ cameraZoomOut(State.APPS_CUSTOMIZE, true, true);
+ mState = State.APPS_CUSTOMIZE;
+ }
+ // Otherwise, we are not in spring loaded mode, so don't do anything.
+ }
+
+ /**
+ * Shows the dock/hotseat area.
+ */
+ void showDock(boolean animated) {
+ if (!LauncherApplication.isScreenLarge()) {
+ if (animated) {
+ int duration = mSearchDeleteBar.getTransitionInDuration();
+ mButtonCluster.animate().alpha(1f).setDuration(duration);
+ mPreviousView.animate().alpha(1f).setDuration(duration);
+ mNextView.animate().alpha(1f).setDuration(duration);
+ } else {
+ mButtonCluster.setAlpha(1f);
+ mPreviousView.setAlpha(1f);
+ mNextView.setAlpha(1f);
+ }
+ }
+ }
+
+ /**
+ * Hides the dock/hotseat area.
+ */
+ void hideDock(boolean animated) {
+ if (!LauncherApplication.isScreenLarge()) {
+ if (animated) {
+ int duration = mSearchDeleteBar.getTransitionOutDuration();
+ mButtonCluster.animate().alpha(0f).setDuration(duration);
+ mPreviousView.animate().alpha(0f).setDuration(duration);
+ mNextView.animate().alpha(0f).setDuration(duration);
+ } else {
+ mButtonCluster.setAlpha(0f);
+ mPreviousView.setAlpha(0f);
+ mNextView.setAlpha(0f);
+ }
+ }
+ }
+
+ void showAllApps(boolean animated) {
+ if (mState != State.WORKSPACE) return;
+
+ cameraZoomOut(State.APPS_CUSTOMIZE, animated, false);
+ mAppsCustomizeTabHost.requestFocus();
+
+ // Hide the search bar and dock
+ mSearchDeleteBar.hideSearchBar(animated);
+ hideDock(animated);
+
+ // Change the state *after* we've called all the transition code
+ mState = State.APPS_CUSTOMIZE;
+
+ // Pause the auto-advance of widgets until we are out of AllApps
+ mUserPresent = false;
+ updateRunning();
+
+ // Send an accessibility event to announce the context change
+ getWindow().getDecorView().sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
}
/**
@@ -3020,15 +2690,16 @@ public final class Launcher extends Activity
* - From another workspace
*/
void closeAllApps(boolean animated) {
- if (mState == State.ALL_APPS || mState == State.ALL_APPS_SPRING_LOADED) {
+ if (mState == State.APPS_CUSTOMIZE || mState == State.APPS_CUSTOMIZE_SPRING_LOADED) {
mWorkspace.setVisibility(View.VISIBLE);
- if (LauncherApplication.isScreenXLarge()) {
- cameraZoomIn(State.ALL_APPS, animated);
- } else {
- mAllAppsGrid.zoom(0.0f, animated);
- }
- ((View)mAllAppsGrid).setFocusable(false);
- mWorkspace.getChildAt(mWorkspace.getCurrentPage()).requestFocus();
+ cameraZoomIn(State.APPS_CUSTOMIZE, animated, false);
+
+ // Show the search bar and dock
+ mSearchDeleteBar.showSearchBar(animated);
+ showDock(animated);
+
+ // Set focus to the AppsCustomize button
+ findViewById(R.id.all_apps_button).requestFocus();
}
}
@@ -3040,29 +2711,6 @@ public final class Launcher extends Activity
// TODO
}
- // Show the customization drawer (only exists in x-large configuration)
- private void showCustomizationDrawer(boolean animated) {
- if (mState != State.WORKSPACE) {
- return;
- }
-
- cameraZoomOut(State.CUSTOMIZE, animated);
-
- // Change the state *after* we've called all the transition code
- mState = State.CUSTOMIZE;
-
- // Pause the auto-advance of widgets until we are out of Customization drawer
- mUserPresent = false;
- updateRunning();
- }
-
- // Hide the customization drawer (only exists in x-large configuration)
- void hideCustomizationDrawer(boolean animated) {
- if (mState == State.CUSTOMIZE || mState == State.CUSTOMIZE_SPRING_LOADED) {
- cameraZoomIn(State.CUSTOMIZE, animated);
- }
- }
-
/**
* Add an item from all apps or customize onto the given workspace screen.
* If layout is null, add to the current screen.
@@ -3102,7 +2750,6 @@ public final class Launcher extends Activity
private Drawable.ConstantState updateTextButtonWithIconFromExternalActivity(
int buttonId, ComponentName activityName, int fallbackDrawableId) {
TextView button = (TextView) findViewById(buttonId);
- if (button == null) return null;
Drawable toolbarIcon = getExternalPackageToolbarIcon(activityName);
// If we were unable to find the icon via the meta-data, use a generic one
@@ -3119,7 +2766,6 @@ public final class Launcher extends Activity
private Drawable.ConstantState updateButtonWithIconFromExternalActivity(
int buttonId, ComponentName activityName, int fallbackDrawableId) {
ImageView button = (ImageView) findViewById(buttonId);
- if (button == null) return null;
Drawable toolbarIcon = getExternalPackageToolbarIcon(activityName);
// If we were unable to find the icon via the meta-data, use a generic one
@@ -3134,27 +2780,43 @@ public final class Launcher extends Activity
private void updateTextButtonWithDrawable(int buttonId, Drawable.ConstantState d) {
TextView button = (TextView) findViewById(buttonId);
- if (button == null) return;
button.setCompoundDrawables(d.newDrawable(getResources()), null, null, null);
}
private void updateButtonWithDrawable(int buttonId, Drawable.ConstantState d) {
ImageView button = (ImageView) findViewById(buttonId);
- if (button == null) return;
button.setImageDrawable(d.newDrawable(getResources()));
}
private void updateGlobalSearchIcon() {
- if (LauncherApplication.isScreenXLarge()) {
- final SearchManager searchManager =
- (SearchManager) getSystemService(Context.SEARCH_SERVICE);
- ComponentName activityName = searchManager.getGlobalSearchActivity();
- if (activityName != null) {
+ final ImageView searchButton = (ImageView) findViewById(R.id.search_button);
+ final View searchDivider = findViewById(R.id.search_divider);
+
+ final SearchManager searchManager =
+ (SearchManager) getSystemService(Context.SEARCH_SERVICE);
+ ComponentName activityName = searchManager.getGlobalSearchActivity();
+ if (activityName != null) {
+ // In landscape mode on the Phone UI, we only have enough space to show the magnifying
+ // glass icon
+ boolean iconLoaded = false;
+ if (!LauncherApplication.isScreenLarge()) {
+ // TODO-APPS_CUSTOMIZE: Remove when the QSB fixes itself?
+ int orientation = getResources().getConfiguration().orientation;
+ if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
+ searchButton.setImageResource(R.drawable.ic_generic_search);
+ iconLoaded = true;
+ sGlobalSearchIcon = null;
+ }
+ }
+ if (!iconLoaded) {
sGlobalSearchIcon = updateButtonWithIconFromExternalActivity(
R.id.search_button, activityName, R.drawable.ic_generic_search);
- } else {
- findViewById(R.id.search_button).setVisibility(View.GONE);
}
+ searchButton.setVisibility(View.VISIBLE);
+ searchDivider.setVisibility(View.VISIBLE);
+ } else {
+ searchButton.setVisibility(View.GONE);
+ searchDivider.setVisibility(View.GONE);
}
}
@@ -3163,15 +2825,19 @@ public final class Launcher extends Activity
}
private void updateVoiceSearchIcon() {
- if (LauncherApplication.isScreenXLarge()) {
- Intent intent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
- ComponentName activityName = intent.resolveActivity(getPackageManager());
- if (activityName != null) {
- sVoiceSearchIcon = updateButtonWithIconFromExternalActivity(
- R.id.voice_button, activityName, R.drawable.ic_voice_search);
- } else {
- findViewById(R.id.voice_button).setVisibility(View.GONE);
- }
+ final View searchDivider = findViewById(R.id.search_divider);
+ final View voiceButton = findViewById(R.id.voice_button);
+
+ Intent intent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
+ ComponentName activityName = intent.resolveActivity(getPackageManager());
+ if (activityName != null) {
+ sVoiceSearchIcon = updateButtonWithIconFromExternalActivity(
+ R.id.voice_button, activityName, R.drawable.ic_voice_search);
+ searchDivider.setVisibility(View.VISIBLE);
+ voiceButton.setVisibility(View.VISIBLE);
+ } else {
+ searchDivider.setVisibility(View.GONE);
+ voiceButton.setVisibility(View.GONE);
}
}
@@ -3183,16 +2849,21 @@ public final class Launcher extends Activity
* Sets the app market icon (shown when all apps is visible on x-large screens)
*/
private void updateAppMarketIcon() {
- if (LauncherApplication.isScreenXLarge()) {
- Intent intent = new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_APP_MARKET);
- // Find the app market activity by resolving an intent.
- // (If multiple app markets are installed, it will return the ResolverActivity.)
- ComponentName activityName = intent.resolveActivity(getPackageManager());
- if (activityName != null) {
- mAppMarketIntent = intent;
- sAppMarketIcon = updateTextButtonWithIconFromExternalActivity(
- R.id.market_button, activityName, R.drawable.app_market_generic);
- }
+ final View marketButton = findViewById(R.id.market_button);
+ Intent intent = new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_APP_MARKET);
+ // Find the app market activity by resolving an intent.
+ // (If multiple app markets are installed, it will return the ResolverActivity.)
+ ComponentName activityName = intent.resolveActivity(getPackageManager());
+ if (activityName != null) {
+ mAppMarketIntent = intent;
+ sAppMarketIcon = updateTextButtonWithIconFromExternalActivity(
+ R.id.market_button, activityName, R.drawable.app_market_generic);
+ marketButton.setVisibility(View.VISIBLE);
+ } else {
+ // We should hide and disable the view so that we don't try and restore the visibility
+ // of it when we swap between drag & normal states from IconDropTarget subclasses.
+ marketButton.setVisibility(View.GONE);
+ marketButton.setEnabled(false);
}
}
@@ -3213,12 +2884,11 @@ public final class Launcher extends Activity
Dialog createDialog() {
mAdapter = new AddAdapter(Launcher.this);
- final AlertDialog.Builder builder = new AlertDialog.Builder(Launcher.this);
+ final AlertDialog.Builder builder = new AlertDialog.Builder(Launcher.this,
+ AlertDialog.THEME_HOLO_DARK);
builder.setTitle(getString(R.string.menu_item_add_item));
builder.setAdapter(mAdapter, this);
- builder.setInverseBackgroundForced(true);
-
AlertDialog dialog = builder.create();
dialog.setOnCancelListener(this);
dialog.setOnDismissListener(this);
@@ -3233,6 +2903,8 @@ public final class Launcher extends Activity
}
public void onDismiss(DialogInterface dialog) {
+ mWaitingForResult = false;
+ cleanup();
}
private void cleanup() {
@@ -3250,47 +2922,26 @@ public final class Launcher extends Activity
Resources res = getResources();
cleanup();
- switch (which) {
+ AddAdapter.ListItem item = (AddAdapter.ListItem) mAdapter.getItem(which);
+ switch (item.actionTag) {
case AddAdapter.ITEM_SHORTCUT: {
pickShortcut();
break;
}
-
- case AddAdapter.ITEM_APPWIDGET: {
- int appWidgetId = Launcher.this.mAppWidgetHost.allocateAppWidgetId();
-
- Intent pickIntent = new Intent(AppWidgetManager.ACTION_APPWIDGET_PICK);
- pickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
- // start the pick activity
- startActivityForResult(pickIntent, REQUEST_PICK_APPWIDGET);
+ case AddAdapter.ITEM_APPLICATION: {
+ if (mAppsCustomizeTabHost != null) {
+ mAppsCustomizeTabHost.selectAppsTab();
+ }
+ showAllApps(true);
break;
}
-
- case AddAdapter.ITEM_LIVE_FOLDER: {
- // Insert extra item to handle inserting folder
- Bundle bundle = new Bundle();
-
- ArrayList<String> shortcutNames = new ArrayList<String>();
- shortcutNames.add(res.getString(R.string.group_folder));
- bundle.putStringArrayList(Intent.EXTRA_SHORTCUT_NAME, shortcutNames);
-
- ArrayList<ShortcutIconResource> shortcutIcons =
- new ArrayList<ShortcutIconResource>();
- shortcutIcons.add(ShortcutIconResource.fromContext(Launcher.this,
- R.drawable.ic_launcher_folder));
- bundle.putParcelableArrayList(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, shortcutIcons);
-
- Intent pickIntent = new Intent(Intent.ACTION_PICK_ACTIVITY);
- pickIntent.putExtra(Intent.EXTRA_INTENT,
- new Intent(LiveFolders.ACTION_CREATE_LIVE_FOLDER));
- pickIntent.putExtra(Intent.EXTRA_TITLE,
- getText(R.string.title_select_live_folder));
- pickIntent.putExtras(bundle);
-
- startActivityForResult(pickIntent, REQUEST_PICK_LIVE_FOLDER);
+ case AddAdapter.ITEM_APPWIDGET: {
+ if (mAppsCustomizeTabHost != null) {
+ mAppsCustomizeTabHost.selectWidgetsTab();
+ }
+ showAllApps(true);
break;
}
-
case AddAdapter.ITEM_WALLPAPER: {
startWallpaper();
break;
@@ -3370,9 +3021,6 @@ public final class Launcher extends Activity
}
}
- void setAllAppsPagedView(AllAppsPagedView view) {
- mAllAppsPagedView = view;
- }
/**
* Refreshes the shortcuts shown on the workspace.
@@ -3381,6 +3029,8 @@ public final class Launcher extends Activity
*/
public void startBinding() {
final Workspace workspace = mWorkspace;
+
+ mWorkspace.clearDropTargets();
int count = workspace.getChildCount();
for (int i = 0; i < count; i++) {
// Use removeAllViewsInLayout() to avoid an extra requestLayout() and invalidate().
@@ -3426,21 +3076,13 @@ public final class Launcher extends Activity
workspace.addInScreen(shortcut, item.screen, item.cellX, item.cellY, 1, 1,
false);
break;
- case LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER:
+ case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
final FolderIcon newFolder = FolderIcon.fromXml(R.layout.folder_icon, this,
(ViewGroup) workspace.getChildAt(workspace.getCurrentPage()),
- (UserFolderInfo) item, mIconCache);
+ (FolderInfo) item, mIconCache);
workspace.addInScreen(newFolder, item.screen, item.cellX, item.cellY, 1, 1,
false);
break;
- case LauncherSettings.Favorites.ITEM_TYPE_LIVE_FOLDER:
- final FolderIcon newLiveFolder = LiveFolderIcon.fromXml(
- R.layout.live_folder_icon, this,
- (ViewGroup) workspace.getChildAt(workspace.getCurrentPage()),
- (LiveFolderInfo) item);
- workspace.addInScreen(newLiveFolder, item.screen, item.cellX, item.cellY, 1, 1,
- false);
- break;
}
}
@@ -3509,12 +3151,14 @@ public final class Launcher extends Activity
mWorkspace.getChildAt(mWorkspace.getCurrentPage()).requestFocus();
}
- final long[] userFolders = mSavedState.getLongArray(RUNTIME_STATE_USER_FOLDERS);
- if (userFolders != null) {
- for (long folderId : userFolders) {
+ final long[] folders = mSavedState.getLongArray(RUNTIME_STATE_FOLDERS);
+ if (folders != null) {
+ for (long folderId : folders) {
final FolderInfo info = sFolders.get(folderId);
- if (info != null) {
- openFolder(info);
+ final FolderIcon folderIcon = (FolderIcon)
+ mWorkspace.getViewForTag(info);
+ if (folderIcon != null) {
+ openFolder(folderIcon);
}
}
final Folder openFolder = mWorkspace.getOpenFolder();
@@ -3531,15 +3175,6 @@ public final class Launcher extends Activity
mSavedInstanceState = null;
}
- // Workaround a bug that occurs when rotating the device while the customization mode is
- // open, we trigger a new layout on all the CellLayout children.
- if (LauncherApplication.isScreenXLarge() && (mState == State.CUSTOMIZE)) {
- final int childCount = mWorkspace.getChildCount();
- for (int i = 0; i < childCount; ++i) {
- mWorkspace.getChildAt(i).requestLayout();
- }
- }
-
mWorkspaceLoading = false;
// If we received the result of any pending adds while the loader was running (e.g. the
@@ -3566,9 +3201,8 @@ public final class Launcher extends Activity
* Implementation of the method from LauncherModel.Callbacks.
*/
public void bindAllApplications(ArrayList<ApplicationInfo> apps) {
- mAllAppsGrid.setApps(apps);
- if (mCustomizePagedView != null) {
- mCustomizePagedView.setApps(apps);
+ if (mAppsCustomizeContent != null) {
+ mAppsCustomizeContent.setApps(apps);
}
updateIconsAffectedByPackageManagerChanges();
}
@@ -3581,9 +3215,9 @@ public final class Launcher extends Activity
public void bindAppsAdded(ArrayList<ApplicationInfo> apps) {
setLoadOnResume();
removeDialog(DIALOG_CREATE_SHORTCUT);
- mAllAppsGrid.addApps(apps);
- if (mCustomizePagedView != null) {
- mCustomizePagedView.addApps(apps);
+
+ if (mAppsCustomizeContent != null) {
+ mAppsCustomizeContent.addApps(apps);
}
updateIconsAffectedByPackageManagerChanges();
}
@@ -3599,11 +3233,9 @@ public final class Launcher extends Activity
if (mWorkspace != null) {
mWorkspace.updateShortcuts(apps);
}
- if (mAllAppsGrid != null) {
- mAllAppsGrid.updateApps(apps);
- }
- if (mCustomizePagedView != null) {
- mCustomizePagedView.updateApps(apps);
+
+ if (mAppsCustomizeContent != null) {
+ mAppsCustomizeContent.updateApps(apps);
}
updateIconsAffectedByPackageManagerChanges();
}
@@ -3618,9 +3250,9 @@ public final class Launcher extends Activity
if (permanent) {
mWorkspace.removeItems(apps);
}
- mAllAppsGrid.removeApps(apps);
- if (mCustomizePagedView != null) {
- mCustomizePagedView.removeApps(apps);
+
+ if (mAppsCustomizeContent != null) {
+ mAppsCustomizeContent.removeApps(apps);
}
updateIconsAffectedByPackageManagerChanges();
}
@@ -3629,9 +3261,9 @@ public final class Launcher extends Activity
* A number of packages were updated.
*/
public void bindPackagesUpdated() {
- // update the customization drawer contents
- if (mCustomizePagedView != null) {
- mCustomizePagedView.update();
+
+ if (mAppsCustomizeContent != null) {
+ mAppsCustomizeContent.onPackagesUpdated();
}
}
@@ -3691,7 +3323,10 @@ public final class Launcher extends Activity
Log.d(TAG, "mDesktopItems.size=" + mDesktopItems.size());
Log.d(TAG, "sFolders.size=" + sFolders.size());
mModel.dumpState();
- mAllAppsGrid.dumpState();
+
+ if (mAppsCustomizeContent != null) {
+ mAppsCustomizeContent.dumpState();
+ }
Log.d(TAG, "END launcher2 dump state");
}
}
diff --git a/src/com/android/launcher2/LauncherAnimatorUpdateListener.java b/src/com/android/launcher2/LauncherAnimatorUpdateListener.java
new file mode 100644
index 000000000..dd821134d
--- /dev/null
+++ b/src/com/android/launcher2/LauncherAnimatorUpdateListener.java
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ */
+
+package com.android.launcher2;
+
+import android.animation.ValueAnimator;
+import android.animation.ValueAnimator.AnimatorUpdateListener;
+
+abstract class LauncherAnimatorUpdateListener implements AnimatorUpdateListener {
+ public void onAnimationUpdate(ValueAnimator animation) {
+ final float b = (Float) animation.getAnimatedValue();
+ final float a = 1f - b;
+ onAnimationUpdate(a, b);
+ }
+
+ abstract void onAnimationUpdate(float a, float b);
+} \ No newline at end of file
diff --git a/src/com/android/launcher2/LauncherAppWidgetHostView.java b/src/com/android/launcher2/LauncherAppWidgetHostView.java
index 7f60cac3d..670c8b666 100644
--- a/src/com/android/launcher2/LauncherAppWidgetHostView.java
+++ b/src/com/android/launcher2/LauncherAppWidgetHostView.java
@@ -18,10 +18,12 @@ package com.android.launcher2;
import android.appwidget.AppWidgetHostView;
import android.content.Context;
+import android.content.res.Resources;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
+import android.view.ViewGroup;
import com.android.launcher.R;
@@ -38,8 +40,15 @@ public class LauncherAppWidgetHostView extends AppWidgetHostView
public LauncherAppWidgetHostView(Context context) {
super(context);
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+
+ Resources r = context.getResources();
+ // We add necessary padding to the AppWidgetHostView
+ setPadding(r.getDimensionPixelSize(R.dimen.app_widget_padding_left),
+ r.getDimensionPixelSize(R.dimen.app_widget_padding_top),
+ r.getDimensionPixelSize(R.dimen.app_widget_padding_right),
+ r.getDimensionPixelSize(R.dimen.app_widget_padding_bottom));
}
-
+
@Override
protected View getErrorView() {
return mInflater.inflate(R.layout.appwidget_error, this, false);
@@ -51,7 +60,7 @@ public class LauncherAppWidgetHostView extends AppWidgetHostView
mHasPerformedLongPress = false;
return true;
}
-
+
// Watch for longpress events at this level to make sure
// users can always pick up this widget
switch (ev.getAction()) {
@@ -59,7 +68,7 @@ public class LauncherAppWidgetHostView extends AppWidgetHostView
postCheckForLongClick();
break;
}
-
+
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
mHasPerformedLongPress = false;
@@ -68,7 +77,7 @@ public class LauncherAppWidgetHostView extends AppWidgetHostView
}
break;
}
-
+
// Otherwise continue letting touch events fall through to children
return false;
}
@@ -122,4 +131,9 @@ public class LauncherAppWidgetHostView extends AppWidgetHostView
}
super.onVisibilityChanged(changedView, visibility);
}
+
+ @Override
+ public int getDescendantFocusability() {
+ return ViewGroup.FOCUS_BLOCK_DESCENDANTS;
+ }
}
diff --git a/src/com/android/launcher2/LauncherApplication.java b/src/com/android/launcher2/LauncherApplication.java
index 8b32f47dd..68b164436 100644
--- a/src/com/android/launcher2/LauncherApplication.java
+++ b/src/com/android/launcher2/LauncherApplication.java
@@ -23,24 +23,20 @@ import android.content.IntentFilter;
import android.content.res.Configuration;
import android.database.ContentObserver;
import android.os.Handler;
-import dalvik.system.VMRuntime;
public class LauncherApplication extends Application {
public LauncherModel mModel;
public IconCache mIconCache;
- private static boolean sIsScreenXLarge;
+ private static boolean sIsScreenLarge;
private static float sScreenDensity;
- private static final boolean ENABLE_ROTATION = false;
@Override
public void onCreate() {
- VMRuntime.getRuntime().setMinimumHeapSize(4 * 1024 * 1024);
-
super.onCreate();
// set sIsScreenXLarge and sScreenDensity *before* creating icon cache
final int screenSize = getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK;
- sIsScreenXLarge = screenSize == Configuration.SCREENLAYOUT_SIZE_LARGE ||
+ sIsScreenLarge = screenSize == Configuration.SCREENLAYOUT_SIZE_LARGE ||
screenSize == Configuration.SCREENLAYOUT_SIZE_XLARGE;
sScreenDensity = getResources().getDisplayMetrics().density;
@@ -101,12 +97,8 @@ public class LauncherApplication extends Application {
return mModel;
}
- public static boolean isInPlaceRotationEnabled() {
- return sIsScreenXLarge && ENABLE_ROTATION;
- }
-
- public static boolean isScreenXLarge() {
- return sIsScreenXLarge;
+ public static boolean isScreenLarge() {
+ return sIsScreenLarge;
}
public static float getScreenDensity() {
diff --git a/src/com/android/launcher2/LauncherModel.java b/src/com/android/launcher2/LauncherModel.java
index c09874901..7cfab2a17 100644
--- a/src/com/android/launcher2/LauncherModel.java
+++ b/src/com/android/launcher2/LauncherModel.java
@@ -37,7 +37,6 @@ import android.content.Intent;
import android.content.Intent.ShortcutIconResource;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
-import android.content.pm.ProviderInfo;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.database.Cursor;
@@ -91,9 +90,6 @@ public class LauncherModel extends BroadcastReceiver {
private AllAppsList mAllAppsList; // only access in worker thread
private IconCache mIconCache;
- final ArrayList<ItemInfo> mItems = new ArrayList<ItemInfo>();
- final ArrayList<LauncherAppWidgetInfo> mAppWidgets = new ArrayList<LauncherAppWidgetInfo>();
- final HashMap<Long, FolderInfo> mFolders = new HashMap<Long, FolderInfo>();
private Bitmap mDefaultIcon;
@@ -271,8 +267,7 @@ public class LauncherModel extends BroadcastReceiver {
Cursor c = cr.query(LauncherSettings.Favorites.CONTENT_URI, null,
"_id=? and (itemType=? or itemType=?)",
new String[] { String.valueOf(id),
- String.valueOf(LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER),
- String.valueOf(LauncherSettings.Favorites.ITEM_TYPE_LIVE_FOLDER) }, null);
+ String.valueOf(LauncherSettings.Favorites.ITEM_TYPE_FOLDER)}, null);
try {
if (c.moveToFirst()) {
@@ -285,11 +280,8 @@ public class LauncherModel extends BroadcastReceiver {
FolderInfo folderInfo = null;
switch (c.getInt(itemTypeIndex)) {
- case LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER:
- folderInfo = findOrMakeUserFolder(folderList, id);
- break;
- case LauncherSettings.Favorites.ITEM_TYPE_LIVE_FOLDER:
- folderInfo = findOrMakeLiveFolder(folderList, id);
+ case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
+ folderInfo = findOrMakeFolder(folderList, id);
break;
}
@@ -391,7 +383,7 @@ public class LauncherModel extends BroadcastReceiver {
/**
* Remove the contents of the specified folder from the database
*/
- static void deleteUserFolderContentsFromDatabase(Context context, UserFolderInfo info) {
+ static void deleteFolderContentsFromDatabase(Context context, FolderInfo info) {
final ContentResolver cr = context.getContentResolver();
cr.delete(LauncherSettings.Favorites.getContentUri(info.id, false), null, null);
@@ -522,9 +514,6 @@ public class LauncherModel extends BroadcastReceiver {
mLoaderTask.stopLocked();
}
}
- mItems.clear();
- mAppWidgets.clear();
- mFolders.clear();
}
/**
@@ -540,6 +529,10 @@ public class LauncherModel extends BroadcastReceiver {
private boolean mStopped;
private boolean mLoadAndBindStepFinished;
+ final ArrayList<ItemInfo> mItems = new ArrayList<ItemInfo>();
+ final ArrayList<LauncherAppWidgetInfo> mAppWidgets = new ArrayList<LauncherAppWidgetInfo>();
+ final HashMap<Long, FolderInfo> mFolders = new HashMap<Long, FolderInfo>();
+
LoaderTask(Context context, boolean isLaunching) {
mContext = context;
mIsLaunching = isLaunching;
@@ -659,22 +652,6 @@ public class LauncherModel extends BroadcastReceiver {
mLoaderTask = null;
}
}
-
- // Trigger a gc to try to clean up after the stuff is done, since the
- // renderscript allocations aren't charged to the java heap.
- if (mStopped) {
- mHandler.post(new Runnable() {
- public void run() {
- System.gc();
- }
- });
- } else {
- mHandler.postIdle(new Runnable() {
- public void run() {
- System.gc();
- }
- });
- }
}
public void stopLocked() {
@@ -843,8 +820,8 @@ public class LauncherModel extends BroadcastReceiver {
break;
default:
// Item is in a user folder
- UserFolderInfo folderInfo =
- findOrMakeUserFolder(mFolders, container);
+ FolderInfo folderInfo =
+ findOrMakeFolder(mFolders, container);
folderInfo.add(info);
break;
}
@@ -864,9 +841,9 @@ public class LauncherModel extends BroadcastReceiver {
}
break;
- case LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER:
+ case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
id = c.getLong(idIndex);
- UserFolderInfo folderInfo = findOrMakeUserFolder(mFolders, id);
+ FolderInfo folderInfo = findOrMakeFolder(mFolders, id);
folderInfo.title = c.getString(titleIndex);
folderInfo.id = id;
@@ -889,57 +866,6 @@ public class LauncherModel extends BroadcastReceiver {
mFolders.put(folderInfo.id, folderInfo);
break;
- case LauncherSettings.Favorites.ITEM_TYPE_LIVE_FOLDER:
- id = c.getLong(idIndex);
- Uri uri = Uri.parse(c.getString(uriIndex));
-
- // Make sure the live folder exists
- final ProviderInfo providerInfo =
- context.getPackageManager().resolveContentProvider(
- uri.getAuthority(), 0);
-
- if (providerInfo == null && !isSafeMode) {
- itemsToRemove.add(id);
- } else {
- LiveFolderInfo liveFolderInfo = findOrMakeLiveFolder(mFolders, id);
- intentDescription = c.getString(intentIndex);
- intent = null;
- if (intentDescription != null) {
- try {
- intent = Intent.parseUri(intentDescription, 0);
- } catch (URISyntaxException e) {
- // Ignore, a live folder might not have a base intent
- }
- }
-
- liveFolderInfo.title = c.getString(titleIndex);
- liveFolderInfo.id = id;
- liveFolderInfo.uri = uri;
- container = c.getInt(containerIndex);
- liveFolderInfo.container = container;
- liveFolderInfo.screen = c.getInt(screenIndex);
- liveFolderInfo.cellX = c.getInt(cellXIndex);
- liveFolderInfo.cellY = c.getInt(cellYIndex);
- liveFolderInfo.baseIntent = intent;
- liveFolderInfo.displayMode = c.getInt(displayModeIndex);
-
- // check & update map of what's occupied
- if (!checkItemPlacement(occupied, liveFolderInfo)) {
- break;
- }
-
- loadLiveFolderIcon(context, c, iconTypeIndex, iconPackageIndex,
- iconResourceIndex, liveFolderInfo);
-
- switch (container) {
- case LauncherSettings.Favorites.CONTAINER_DESKTOP:
- mItems.add(liveFolderInfo);
- break;
- }
- mFolders.put(liveFolderInfo.id, liveFolderInfo);
- }
- break;
-
case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
// Read all Launcher-specific widget details
int appWidgetId = c.getInt(appWidgetIdIndex);
@@ -1294,6 +1220,7 @@ public class LauncherModel extends BroadcastReceiver {
Log.d(TAG, "mLoaderTask.mIsLaunching=" + mIsLaunching);
Log.d(TAG, "mLoaderTask.mStopped=" + mStopped);
Log.d(TAG, "mLoaderTask.mLoadAndBindStepFinished=" + mLoadAndBindStepFinished);
+ Log.d(TAG, "mItems size=" + mItems.size());
}
}
@@ -1374,7 +1301,8 @@ public class LauncherModel extends BroadcastReceiver {
final ArrayList<ApplicationInfo> addedFinal = added;
mHandler.post(new Runnable() {
public void run() {
- if (callbacks == mCallbacks.get()) {
+ Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;
+ if (callbacks == cb && cb != null) {
callbacks.bindAppsAdded(addedFinal);
}
}
@@ -1384,7 +1312,8 @@ public class LauncherModel extends BroadcastReceiver {
final ArrayList<ApplicationInfo> modifiedFinal = modified;
mHandler.post(new Runnable() {
public void run() {
- if (callbacks == mCallbacks.get()) {
+ Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;
+ if (callbacks == cb && cb != null) {
callbacks.bindAppsUpdated(modifiedFinal);
}
}
@@ -1395,7 +1324,8 @@ public class LauncherModel extends BroadcastReceiver {
final ArrayList<ApplicationInfo> removedFinal = removed;
mHandler.post(new Runnable() {
public void run() {
- if (callbacks == mCallbacks.get()) {
+ Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;
+ if (callbacks == cb && cb != null) {
callbacks.bindAppsRemoved(removedFinal, permanent);
}
}
@@ -1405,7 +1335,8 @@ public class LauncherModel extends BroadcastReceiver {
mHandler.post(new Runnable() {
@Override
public void run() {
- if (callbacks == mCallbacks.get()) {
+ Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;
+ if (callbacks == cb && cb != null) {
callbacks.bindPackagesUpdated();
}
}
@@ -1623,13 +1554,11 @@ public class LauncherModel extends BroadcastReceiver {
Parcelable bitmap = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON);
Bitmap icon = null;
- boolean filtered = false;
boolean customIcon = false;
ShortcutIconResource iconResource = null;
if (bitmap != null && bitmap instanceof Bitmap) {
icon = Utilities.createIconBitmap(new FastBitmapDrawable((Bitmap)bitmap), context);
- filtered = true;
customIcon = true;
} else {
Parcelable extra = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE);
@@ -1668,38 +1597,6 @@ public class LauncherModel extends BroadcastReceiver {
return info;
}
- private void loadLiveFolderIcon(Context context, Cursor c, int iconTypeIndex,
- int iconPackageIndex, int iconResourceIndex, LiveFolderInfo liveFolderInfo) {
-
- int iconType = c.getInt(iconTypeIndex);
- switch (iconType) {
- case LauncherSettings.Favorites.ICON_TYPE_RESOURCE:
- String packageName = c.getString(iconPackageIndex);
- String resourceName = c.getString(iconResourceIndex);
- PackageManager packageManager = context.getPackageManager();
- try {
- Resources appResources = packageManager.getResourcesForApplication(packageName);
- final int id = appResources.getIdentifier(resourceName, null, null);
- liveFolderInfo.icon = Utilities.createIconBitmap(
- mIconCache.getFullResIcon(appResources, id), context);
- } catch (Exception e) {
- Resources resources = context.getResources();
- liveFolderInfo.icon = Utilities.createIconBitmap(
- mIconCache.getFullResIcon(resources, R.drawable.ic_launcher_folder),
- context);
- }
- liveFolderInfo.iconResource = new Intent.ShortcutIconResource();
- liveFolderInfo.iconResource.packageName = packageName;
- liveFolderInfo.iconResource.resourceName = resourceName;
- break;
- default:
- Resources resources = context.getResources();
- liveFolderInfo.icon = Utilities.createIconBitmap(
- mIconCache.getFullResIcon(resources, R.drawable.ic_launcher_folder),
- context);
- }
- }
-
void updateSavedIcon(Context context, ShortcutInfo info, Cursor c, int iconIndex) {
// If apps can't be on SD, don't even bother.
if (!mAppsCanBeOnExternalStorage) {
@@ -1735,44 +1632,18 @@ public class LauncherModel extends BroadcastReceiver {
}
/**
- * Return an existing UserFolderInfo object if we have encountered this ID previously,
+ * Return an existing FolderInfo object if we have encountered this ID previously,
* or make a new one.
*/
- private static UserFolderInfo findOrMakeUserFolder(HashMap<Long, FolderInfo> folders, long id) {
- // See if a placeholder was created for us already
- FolderInfo folderInfo = folders.get(id);
- if (folderInfo == null || !(folderInfo instanceof UserFolderInfo)) {
- // No placeholder -- create a new instance
- folderInfo = new UserFolderInfo();
- folders.put(id, folderInfo);
- }
- return (UserFolderInfo) folderInfo;
- }
-
- /**
- * Return an existing UserFolderInfo object if we have encountered this ID previously, or make a
- * new one.
- */
- private static LiveFolderInfo findOrMakeLiveFolder(HashMap<Long, FolderInfo> folders, long id) {
+ private static FolderInfo findOrMakeFolder(HashMap<Long, FolderInfo> folders, long id) {
// See if a placeholder was created for us already
FolderInfo folderInfo = folders.get(id);
- if (folderInfo == null || !(folderInfo instanceof LiveFolderInfo)) {
+ if (folderInfo == null) {
// No placeholder -- create a new instance
- folderInfo = new LiveFolderInfo();
+ folderInfo = new FolderInfo();
folders.put(id, folderInfo);
}
- return (LiveFolderInfo) folderInfo;
- }
-
- private static String getLabel(PackageManager manager, ActivityInfo activityInfo) {
- String label = activityInfo.loadLabel(manager).toString();
- if (label == null) {
- label = manager.getApplicationLabel(activityInfo.applicationInfo).toString();
- if (label == null) {
- label = activityInfo.name;
- }
- }
- return label;
+ return folderInfo;
}
private static final Collator sCollator = Collator.getInstance();
@@ -1790,6 +1661,48 @@ public class LauncherModel extends BroadcastReceiver {
return 0;
}
};
+ public static final Comparator<AppWidgetProviderInfo> WIDGET_NAME_COMPARATOR
+ = new Comparator<AppWidgetProviderInfo>() {
+ public final int compare(AppWidgetProviderInfo a, AppWidgetProviderInfo b) {
+ return sCollator.compare(a.label.toString(), b.label.toString());
+ }
+ };
+ public static class ShortcutNameComparator implements Comparator<ResolveInfo> {
+ private PackageManager mPackageManager;
+ private HashMap<Object, String> mLabelCache;
+ ShortcutNameComparator(PackageManager pm) {
+ mPackageManager = pm;
+ mLabelCache = new HashMap<Object, String>();
+ }
+ public final int compare(ResolveInfo a, ResolveInfo b) {
+ String labelA, labelB;
+ if (mLabelCache.containsKey(a)) labelA = mLabelCache.get(a);
+ else labelA = a.loadLabel(mPackageManager).toString();
+ if (mLabelCache.containsKey(b)) labelB = mLabelCache.get(b);
+ else labelB = b.loadLabel(mPackageManager).toString();
+ return sCollator.compare(labelA, labelB);
+ }
+ };
+ public static class WidgetAndShortcutNameComparator implements Comparator<Object> {
+ private PackageManager mPackageManager;
+ private HashMap<Object, String> mLabelCache;
+ WidgetAndShortcutNameComparator(PackageManager pm) {
+ mPackageManager = pm;
+ mLabelCache = new HashMap<Object, String>();
+ }
+ public final int compare(Object a, Object b) {
+ String labelA, labelB;
+ if (mLabelCache.containsKey(a)) labelA = mLabelCache.get(a);
+ else labelA = (a instanceof AppWidgetProviderInfo) ?
+ ((AppWidgetProviderInfo) a).label :
+ ((ResolveInfo) a).loadLabel(mPackageManager).toString();
+ if (mLabelCache.containsKey(b)) labelB = mLabelCache.get(b);
+ else labelB = (b instanceof AppWidgetProviderInfo) ?
+ ((AppWidgetProviderInfo) b).label :
+ ((ResolveInfo) b).loadLabel(mPackageManager).toString();
+ return sCollator.compare(labelA, labelB);
+ }
+ };
public void dumpState() {
Log.d(TAG, "mCallbacks=" + mCallbacks);
@@ -1797,7 +1710,6 @@ public class LauncherModel extends BroadcastReceiver {
ApplicationInfo.dumpApplicationInfoList(TAG, "mAllAppsList.added", mAllAppsList.added);
ApplicationInfo.dumpApplicationInfoList(TAG, "mAllAppsList.removed", mAllAppsList.removed);
ApplicationInfo.dumpApplicationInfoList(TAG, "mAllAppsList.modified", mAllAppsList.modified);
- Log.d(TAG, "mItems size=" + mItems.size());
if (mLoaderTask != null) {
mLoaderTask.dumpState();
} else {
diff --git a/src/com/android/launcher2/LauncherSettings.java b/src/com/android/launcher2/LauncherSettings.java
index 9c685ceaa..c378405bc 100644
--- a/src/com/android/launcher2/LauncherSettings.java
+++ b/src/com/android/launcher2/LauncherSettings.java
@@ -16,8 +16,8 @@
package com.android.launcher2;
-import android.provider.BaseColumns;
import android.net.Uri;
+import android.provider.BaseColumns;
/**
* Settings related utilities.
@@ -169,11 +169,15 @@ class LauncherSettings {
/**
* The favorite is a user created folder
*/
- static final int ITEM_TYPE_USER_FOLDER = 2;
+ static final int ITEM_TYPE_FOLDER = 2;
/**
- * The favorite is a live folder
- */
+ * The favorite is a live folder
+ *
+ * Note: live folders can no longer be added to Launcher, and any live folders which
+ * exist within the launcher database will be ignored when loading. That said, these
+ * entries in the database may still exist, and are not automatically stripped.
+ */
static final int ITEM_TYPE_LIVE_FOLDER = 3;
/**
diff --git a/src/com/android/launcher2/LiveFolder.java b/src/com/android/launcher2/LiveFolder.java
deleted file mode 100644
index 07a295faa..000000000
--- a/src/com/android/launcher2/LiveFolder.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * 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.launcher2;
-
-import android.content.Context;
-import android.content.Intent;
-import android.util.AttributeSet;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.AdapterView;
-import android.net.Uri;
-import android.provider.LiveFolders;
-import android.os.AsyncTask;
-import android.database.Cursor;
-
-import java.lang.ref.WeakReference;
-
-import com.android.launcher.R;
-
-public class LiveFolder extends Folder {
- private AsyncTask<LiveFolderInfo,Void,Cursor> mLoadingTask;
-
- public LiveFolder(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- static LiveFolder fromXml(Context context, FolderInfo folderInfo) {
- final int layout = isDisplayModeList(folderInfo) ?
- R.layout.live_folder_list : R.layout.live_folder_grid;
- return (LiveFolder) LayoutInflater.from(context).inflate(layout, null);
- }
-
- private static boolean isDisplayModeList(FolderInfo folderInfo) {
- return ((LiveFolderInfo) folderInfo).displayMode ==
- LiveFolders.DISPLAY_MODE_LIST;
- }
-
- @Override
- public void onItemClick(AdapterView parent, View v, int position, long id) {
- LiveFolderAdapter.ViewHolder holder = (LiveFolderAdapter.ViewHolder) v.getTag();
-
- if (holder.useBaseIntent) {
- final Intent baseIntent = ((LiveFolderInfo) mInfo).baseIntent;
- if (baseIntent != null) {
- final Intent intent = new Intent(baseIntent);
- Uri uri = baseIntent.getData();
- uri = uri.buildUpon().appendPath(Long.toString(holder.id)).build();
- intent.setData(uri);
- mLauncher.startActivitySafely(intent, "(position=" + position + ", id=" + id + ")");
- }
- } else if (holder.intent != null) {
- mLauncher.startActivitySafely(holder.intent,
- "(position=" + position + ", id=" + id + ")");
- }
- }
-
- @Override
- public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
- return false;
- }
-
- void bind(FolderInfo info) {
- super.bind(info);
- if (mLoadingTask != null && mLoadingTask.getStatus() == AsyncTask.Status.RUNNING) {
- mLoadingTask.cancel(true);
- }
- mLoadingTask = new FolderLoadingTask(this).execute((LiveFolderInfo) info);
- }
-
- @Override
- void onOpen() {
- super.onOpen();
- requestFocus();
- }
-
- @Override
- void onClose() {
- super.onClose();
- if (mLoadingTask != null && mLoadingTask.getStatus() == AsyncTask.Status.RUNNING) {
- mLoadingTask.cancel(true);
- }
-
- // The adapter can be null if onClose() is called before FolderLoadingTask
- // is done querying the provider
- final LiveFolderAdapter adapter = (LiveFolderAdapter) mContent.getAdapter();
- if (adapter != null) {
- adapter.cleanup();
- }
- }
-
- static class FolderLoadingTask extends AsyncTask<LiveFolderInfo, Void, Cursor> {
- private final WeakReference<LiveFolder> mFolder;
- private LiveFolderInfo mInfo;
-
- FolderLoadingTask(LiveFolder folder) {
- mFolder = new WeakReference<LiveFolder>(folder);
- }
-
- protected Cursor doInBackground(LiveFolderInfo... params) {
- final LiveFolder folder = mFolder.get();
- if (folder != null) {
- mInfo = params[0];
- return LiveFolderAdapter.query(folder.mLauncher, mInfo);
- }
- return null;
- }
-
- @Override
- protected void onPostExecute(Cursor cursor) {
- if (!isCancelled()) {
- if (cursor != null) {
- final LiveFolder folder = mFolder.get();
- if (folder != null) {
- final Launcher launcher = folder.mLauncher;
- folder.setContentAdapter(new LiveFolderAdapter(launcher, mInfo, cursor));
- }
- }
- } else if (cursor != null) {
- cursor.close();
- }
- }
- }
-}
diff --git a/src/com/android/launcher2/LiveFolderAdapter.java b/src/com/android/launcher2/LiveFolderAdapter.java
deleted file mode 100644
index fb9c6a37a..000000000
--- a/src/com/android/launcher2/LiveFolderAdapter.java
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * 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.launcher2;
-
-import android.widget.CursorAdapter;
-import android.widget.TextView;
-import android.widget.ImageView;
-import android.content.Context;
-import android.content.Intent;
-import android.content.res.Resources;
-import android.content.pm.PackageManager;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.LayoutInflater;
-import android.database.Cursor;
-import android.provider.LiveFolders;
-import android.graphics.drawable.Drawable;
-import android.graphics.BitmapFactory;
-import android.graphics.Bitmap;
-
-import java.net.URISyntaxException;
-import java.util.HashMap;
-import java.lang.ref.SoftReference;
-
-import com.android.launcher.R;
-
-class LiveFolderAdapter extends CursorAdapter {
- private boolean mIsList;
- private LayoutInflater mInflater;
-
- private final HashMap<String, Drawable> mIcons = new HashMap<String, Drawable>();
- private final HashMap<Long, SoftReference<Drawable>> mCustomIcons =
- new HashMap<Long, SoftReference<Drawable>>();
- private final Launcher mLauncher;
-
- LiveFolderAdapter(Launcher launcher, LiveFolderInfo info, Cursor cursor) {
- super(launcher, cursor, true);
- mIsList = info.displayMode == LiveFolders.DISPLAY_MODE_LIST;
- mInflater = LayoutInflater.from(launcher);
- mLauncher = launcher;
-
- mLauncher.startManagingCursor(getCursor());
- }
-
- static Cursor query(Context context, LiveFolderInfo info) {
- return context.getContentResolver().query(info.uri, null, null,
- null, LiveFolders.NAME + " ASC");
- }
-
- public View newView(Context context, Cursor cursor, ViewGroup parent) {
- View view;
- final ViewHolder holder = new ViewHolder();
-
- if (!mIsList) {
- view = mInflater.inflate(R.layout.application_boxed, parent, false);
- } else {
- view = mInflater.inflate(R.layout.application_list, parent, false);
- holder.description = (TextView) view.findViewById(R.id.description);
- holder.icon = (ImageView) view.findViewById(R.id.icon);
- }
-
- holder.name = (TextView) view.findViewById(R.id.name);
-
- holder.idIndex = cursor.getColumnIndexOrThrow(LiveFolders._ID);
- holder.nameIndex = cursor.getColumnIndexOrThrow(LiveFolders.NAME);
- holder.descriptionIndex = cursor.getColumnIndex(LiveFolders.DESCRIPTION);
- holder.intentIndex = cursor.getColumnIndex(LiveFolders.INTENT);
- holder.iconBitmapIndex = cursor.getColumnIndex(LiveFolders.ICON_BITMAP);
- holder.iconResourceIndex = cursor.getColumnIndex(LiveFolders.ICON_RESOURCE);
- holder.iconPackageIndex = cursor.getColumnIndex(LiveFolders.ICON_PACKAGE);
-
- view.setTag(holder);
-
- return view;
- }
-
- public void bindView(View view, Context context, Cursor cursor) {
- final ViewHolder holder = (ViewHolder) view.getTag();
-
- holder.id = cursor.getLong(holder.idIndex);
- final Drawable icon = loadIcon(context, cursor, holder);
-
- holder.name.setText(cursor.getString(holder.nameIndex));
-
- if (!mIsList) {
- holder.name.setCompoundDrawablesWithIntrinsicBounds(null, icon, null, null);
- } else {
- final boolean hasIcon = icon != null;
- holder.icon.setVisibility(hasIcon ? View.VISIBLE : View.GONE);
- if (hasIcon) holder.icon.setImageDrawable(icon);
-
- if (holder.descriptionIndex != -1) {
- final String description = cursor.getString(holder.descriptionIndex);
- if (description != null) {
- holder.description.setText(description);
- holder.description.setVisibility(View.VISIBLE);
- } else {
- holder.description.setVisibility(View.GONE);
- }
- } else {
- holder.description.setVisibility(View.GONE);
- }
- }
-
- if (holder.intentIndex != -1) {
- try {
- holder.intent = Intent.parseUri(cursor.getString(holder.intentIndex), 0);
- } catch (URISyntaxException e) {
- // Ignore
- }
- } else {
- holder.useBaseIntent = true;
- }
- }
-
- private Drawable loadIcon(Context context, Cursor cursor, ViewHolder holder) {
- Drawable icon = null;
- byte[] data = null;
-
- if (holder.iconBitmapIndex != -1) {
- data = cursor.getBlob(holder.iconBitmapIndex);
- }
-
- if (data != null) {
- final SoftReference<Drawable> reference = mCustomIcons.get(holder.id);
- if (reference != null) {
- icon = reference.get();
- }
-
- if (icon == null) {
- final Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
- final Bitmap resampled = Utilities.resampleIconBitmap(bitmap, mContext);
- if (bitmap != resampled) {
- // If we got back a different object, we don't need the old one any more.
- bitmap.recycle();
- }
- icon = new FastBitmapDrawable(resampled);
- mCustomIcons.put(holder.id, new SoftReference<Drawable>(icon));
- }
- } else if (holder.iconResourceIndex != -1 && holder.iconPackageIndex != -1) {
- final String resource = cursor.getString(holder.iconResourceIndex);
- icon = mIcons.get(resource);
- if (icon == null) {
- try {
- final PackageManager packageManager = context.getPackageManager();
- Resources resources = packageManager.getResourcesForApplication(
- cursor.getString(holder.iconPackageIndex));
- final int id = resources.getIdentifier(resource,
- null, null);
- icon = new FastBitmapDrawable(
- Utilities.createIconBitmap(resources.getDrawable(id), mContext));
- mIcons.put(resource, icon);
- } catch (Exception e) {
- // Ignore
- }
- }
- }
-
- return icon;
- }
-
- void cleanup() {
- for (Drawable icon : mIcons.values()) {
- icon.setCallback(null);
- }
- mIcons.clear();
-
- for (SoftReference<Drawable> icon : mCustomIcons.values()) {
- final Drawable drawable = icon.get();
- if (drawable != null) {
- drawable.setCallback(null);
- }
- }
- mCustomIcons.clear();
-
- final Cursor cursor = getCursor();
- if (cursor != null) {
- try {
- cursor.close();
- } finally {
- mLauncher.stopManagingCursor(cursor);
- }
- }
- }
-
- static class ViewHolder {
- TextView name;
- TextView description;
- ImageView icon;
-
- Intent intent;
- long id;
- boolean useBaseIntent;
-
- int idIndex;
- int nameIndex;
- int descriptionIndex = -1;
- int intentIndex = -1;
- int iconBitmapIndex = -1;
- int iconResourceIndex = -1;
- int iconPackageIndex = -1;
- }
-}
diff --git a/src/com/android/launcher2/LiveFolderIcon.java b/src/com/android/launcher2/LiveFolderIcon.java
deleted file mode 100644
index 5b73a59a7..000000000
--- a/src/com/android/launcher2/LiveFolderIcon.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * 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.launcher2;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.util.AttributeSet;
-import android.view.ViewGroup;
-import android.view.LayoutInflater;
-import android.graphics.Bitmap;
-
-import com.android.launcher.R;
-
-public class LiveFolderIcon extends FolderIcon {
- public LiveFolderIcon(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- public LiveFolderIcon(Context context) {
- super(context);
- }
-
- static LiveFolderIcon fromXml(int resId, Launcher launcher, ViewGroup group,
- LiveFolderInfo folderInfo) {
-
- LiveFolderIcon icon = (LiveFolderIcon)
- LayoutInflater.from(launcher).inflate(resId, group, false);
-
- final Resources resources = launcher.getResources();
- Bitmap b = folderInfo.icon;
- if (b == null) {
- b = Utilities.createIconBitmap(resources.getDrawable(R.drawable.ic_launcher_folder),
- launcher);
- }
- icon.setCompoundDrawablesWithIntrinsicBounds(null, new FastBitmapDrawable(b), null, null);
- icon.setText(folderInfo.title);
- icon.setTag(folderInfo);
- icon.setOnClickListener(launcher);
-
- return icon;
- }
-
- @Override
- public boolean acceptDrop(DragSource source, int x, int y, int xOffset, int yOffset,
- DragView dragView, Object dragInfo) {
- return false;
- }
-
- @Override
- public void onDrop(DragSource source, int x, int y, int xOffset, int yOffset,
- DragView dragView, Object dragInfo) {
- }
-
- @Override
- public void onDragEnter(DragSource source, int x, int y, int xOffset, int yOffset,
- DragView dragView, Object dragInfo) {
- }
-
- @Override
- public void onDragOver(DragSource source, int x, int y, int xOffset, int yOffset,
- DragView dragView, Object dragInfo) {
- }
-
- @Override
- public void onDragExit(DragSource source, int x, int y, int xOffset, int yOffset,
- DragView dragView, Object dragInfo) {
- }
-}
diff --git a/src/com/android/launcher2/LiveFolderInfo.java b/src/com/android/launcher2/LiveFolderInfo.java
deleted file mode 100644
index 74b021758..000000000
--- a/src/com/android/launcher2/LiveFolderInfo.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * 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.launcher2;
-
-import android.content.ContentValues;
-import android.content.Intent;
-import android.graphics.Bitmap;
-import android.net.Uri;
-
-class LiveFolderInfo extends FolderInfo {
-
- /**
- * The base intent, if it exists.
- */
- Intent baseIntent;
-
- /**
- * The live folder's content uri.
- */
- Uri uri;
-
- /**
- * The live folder's display type.
- */
- int displayMode;
-
- /**
- * The live folder icon.
- */
- Bitmap icon;
-
- /**
- * Reference to the live folder icon as an application's resource.
- */
- Intent.ShortcutIconResource iconResource;
-
- LiveFolderInfo() {
- itemType = LauncherSettings.Favorites.ITEM_TYPE_LIVE_FOLDER;
- }
-
- @Override
- void onAddToDatabase(ContentValues values) {
- super.onAddToDatabase(values);
- values.put(LauncherSettings.Favorites.TITLE, title.toString());
- values.put(LauncherSettings.Favorites.URI, uri.toString());
- if (baseIntent != null) {
- values.put(LauncherSettings.Favorites.INTENT, baseIntent.toUri(0));
- }
- values.put(LauncherSettings.Favorites.ICON_TYPE, LauncherSettings.Favorites.ICON_TYPE_RESOURCE);
- values.put(LauncherSettings.Favorites.DISPLAY_MODE, displayMode);
- if (iconResource != null) {
- values.put(LauncherSettings.Favorites.ICON_PACKAGE, iconResource.packageName);
- values.put(LauncherSettings.Favorites.ICON_RESOURCE, iconResource.resourceName);
- }
- }
-}
diff --git a/src/com/android/launcher2/PagedView.java b/src/com/android/launcher2/PagedView.java
index 13e86b962..1fa23cf4c 100644
--- a/src/com/android/launcher2/PagedView.java
+++ b/src/com/android/launcher2/PagedView.java
@@ -29,6 +29,7 @@ import android.graphics.Rect;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.AttributeSet;
+import android.util.Log;
import android.view.ActionMode;
import android.view.InputDevice;
import android.view.KeyEvent;
@@ -40,6 +41,7 @@ import android.view.ViewGroup;
import android.view.ViewParent;
import android.view.animation.Interpolator;
import android.widget.Checkable;
+import android.widget.ImageView;
import android.widget.Scroller;
import com.android.launcher.R;
@@ -50,6 +52,7 @@ import com.android.launcher.R;
*/
public abstract class PagedView extends ViewGroup {
private static final String TAG = "PagedView";
+ private static final boolean DEBUG = false;
protected static final int INVALID_PAGE = -1;
// the min drag distance for a fling to register, to prevent random page shifts
@@ -60,7 +63,7 @@ public abstract class PagedView extends ViewGroup {
private static final int PAGE_SNAP_ANIMATION_DURATION = 550;
protected static final float NANOTIME_DIV = 1000000000.0f;
- private static final float OVERSCROLL_DAMP_FACTOR = 0.08f;
+ private static final float OVERSCROLL_DAMP_FACTOR = 0.14f;
private static final int MINIMUM_SNAP_VELOCITY = 2200;
private static final int MIN_FLING_VELOCITY = 250;
private static final float RETURN_TO_ORIGINAL_PAGE_THRESHOLD = 0.33f;
@@ -75,7 +78,6 @@ public abstract class PagedView extends ViewGroup {
protected int mCurrentPage;
protected int mNextPage = INVALID_PAGE;
- protected int mRestorePage = -1;
protected int mMaxScrollX;
protected Scroller mScroller;
private VelocityTracker mVelocityTracker;
@@ -110,7 +112,6 @@ public abstract class PagedView extends ViewGroup {
protected int mPageLayoutPaddingRight;
protected int mPageLayoutWidthGap;
protected int mPageLayoutHeightGap;
- protected int mPageLayoutMaxHeight;
protected int mCellCountX = 0;
protected int mCellCountY = 0;
protected boolean mCenterPagesVertically;
@@ -159,6 +160,16 @@ public abstract class PagedView extends ViewGroup {
protected boolean mIsPageMoving = false;
+ // All syncs and layout passes are deferred until data is ready.
+ protected boolean mIsDataReady = false;
+
+ // Scrolling indicator
+ private ImageView mScrollIndicator;
+ private boolean mHasScrollIndicator = true;
+ private static final int sScrollIndicatorFadeInDuration = 150;
+ private static final int sScrollIndicatorFastFadeOutDuration = 50;
+ private static final int sScrollIndicatorFadeOutDuration = 650;
+
public interface PageSwitchListener {
void onPageSwitch(View newPage, int newPageIndex);
}
@@ -190,8 +201,6 @@ public abstract class PagedView extends ViewGroup {
R.styleable.PagedView_pageLayoutWidthGap, -1);
mPageLayoutHeightGap = a.getDimensionPixelSize(
R.styleable.PagedView_pageLayoutHeightGap, -1);
- mPageLayoutMaxHeight = a.getDimensionPixelSize(
- R.styleable.PagedView_pageLayoutMaxHeight, -1);
a.recycle();
setHapticFeedbackEnabled(false);
@@ -222,6 +231,17 @@ public abstract class PagedView extends ViewGroup {
}
/**
+ * Called by subclasses to mark that data is ready, and that we can begin loading and laying
+ * out pages.
+ */
+ protected void setDataIsReady() {
+ mIsDataReady = true;
+ }
+ protected boolean isDataReady() {
+ return mIsDataReady;
+ }
+
+ /**
* Returns the index of the currently displayed page.
*
* @return The index of the currently displayed page.
@@ -242,10 +262,6 @@ public abstract class PagedView extends ViewGroup {
return getWidth();
}
- public int getTouchState() {
- return mTouchState;
- }
-
/**
* Updates the scroll of the current page immediately to its final scroll position. We use this
* in CustomizePagedView to allow tabs to share the same PagedView while resetting the scroll of
@@ -292,12 +308,18 @@ public abstract class PagedView extends ViewGroup {
mIsPageMoving = false;
}
+ protected boolean isPageMoving() {
+ return mIsPageMoving;
+ }
+
// a method that subclasses can override to add behavior
protected void onPageBeginMoving() {
+ showScrollingIndicator();
}
// a method that subclasses can override to add behavior
protected void onPageEndMoving() {
+ hideScrollingIndicator(false);
}
/**
@@ -370,6 +392,11 @@ public abstract class PagedView extends ViewGroup {
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ if (!mIsDataReady) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ return;
+ }
+
final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
if (widthMode != MeasureSpec.EXACTLY) {
@@ -387,12 +414,10 @@ public abstract class PagedView extends ViewGroup {
final int verticalPadding = mPaddingTop + mPaddingBottom;
- if (mPageLayoutMaxHeight != -1) {
- heightSize = Math.min(mPageLayoutMaxHeight, heightSize);
- }
// The children are given the same width and height as the workspace
// unless they were set to WRAP_CONTENT
+ if (DEBUG) Log.d(TAG, "PagedView.onMeasure(): " + widthSize + ", " + heightSize);
final int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
// disallowing padding in paged view (just pass 0)
@@ -420,6 +445,8 @@ public abstract class PagedView extends ViewGroup {
child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
maxChildHeight = Math.max(maxChildHeight, child.getMeasuredHeight());
+ if (DEBUG) Log.d(TAG, "\tmeasure-child" + i + ": " + child.getMeasuredWidth() + ", "
+ + child.getMeasuredHeight());
}
if (heightMode == MeasureSpec.AT_MOST) {
@@ -461,12 +488,18 @@ public abstract class PagedView extends ViewGroup {
childrenX[i] = child.getX();
childrenY[i] = child.getY();
}
- onLayout(false, mLeft, mTop, mRight, mBottom);
+ // Trigger a full re-layout (never just call onLayout directly!)
+ int widthSpec = MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.EXACTLY);
+ int heightSpec = MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.EXACTLY);
+ requestLayout();
+ measure(widthSpec, heightSpec);
+ layout(mLeft, mTop, mRight, mBottom);
for (int i = 0; i < childCount; i++) {
final View child = getChildAt(i);
child.setX(childrenX[i]);
child.setY(childrenY[i]);
}
+
// Also, the page offset has changed (since the pages are now smaller);
// update the page offset, but again preserving absolute X and Y coordinates
scrollToNewPageWithoutMovingPages(mCurrentPage);
@@ -474,6 +507,11 @@ public abstract class PagedView extends ViewGroup {
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ if (!mIsDataReady) {
+ return;
+ }
+
+ if (DEBUG) Log.d(TAG, "PagedView.onLayout()");
if (mFirstLayout && mCurrentPage >= 0 && mCurrentPage < getChildCount()) {
setHorizontalScrollBarEnabled(false);
int newX = getChildOffset(mCurrentPage) - getRelativeChildOffset(mCurrentPage);
@@ -487,6 +525,8 @@ public abstract class PagedView extends ViewGroup {
final int childCount = getChildCount();
int childLeft = 0;
if (childCount > 0) {
+ if (DEBUG) Log.d(TAG, "getRelativeChildOffset(): " + getMeasuredWidth() + ", "
+ + getChildWidth(0));
childLeft = getRelativeChildOffset(0);
}
@@ -500,6 +540,7 @@ public abstract class PagedView extends ViewGroup {
childTop += ((getMeasuredHeight() - verticalPadding) - childHeight) / 2;
}
+ if (DEBUG) Log.d(TAG, "\tlayout-child" + i + ": " + childLeft + ", " + childTop);
child.layout(childLeft, childTop,
childLeft + child.getMeasuredWidth(), childTop + childHeight);
childLeft += childWidth + mPageSpacing;
@@ -518,7 +559,8 @@ public abstract class PagedView extends ViewGroup {
protected void updateAdjacentPagesAlpha() {
if (mFadeInAdjacentScreens) {
if (mDirtyPageAlpha || (mTouchState == TOUCH_STATE_SCROLLING) || !mScroller.isFinished()) {
- int halfScreenSize = getMeasuredWidth() / 2;
+ int screenWidth = getMeasuredWidth();
+ int halfScreenSize = screenWidth / 2;
int screenCenter = mScrollX + halfScreenSize;
final int childCount = getChildCount();
for (int i = 0; i < childCount; ++i) {
@@ -531,7 +573,7 @@ public abstract class PagedView extends ViewGroup {
// we should just assume full page width (and calculate the offset according to
// that).
if (childWidth <= 0) {
- childWidth = getMeasuredWidth();
+ childWidth = screenWidth;
childCenter = (i * childWidth) + (childWidth / 2);
}
@@ -540,10 +582,14 @@ public abstract class PagedView extends ViewGroup {
if (distanceFromScreenCenter > 0) {
if (i > 0) {
d += getScaledMeasuredWidth(getChildAt(i - 1)) / 2;
+ } else {
+ continue;
}
} else {
if (i < childCount - 1) {
d += getScaledMeasuredWidth(getChildAt(i + 1)) / 2;
+ } else {
+ continue;
}
}
d += mPageSpacing;
@@ -576,6 +622,7 @@ public abstract class PagedView extends ViewGroup {
}
protected void screenScrolled(int screenCenter) {
+ updateScrollingIndicator();
}
@Override
@@ -819,7 +866,6 @@ public abstract class PagedView extends ViewGroup {
}
case MotionEvent.ACTION_UP:
- onWallpaperTap(ev);
case MotionEvent.ACTION_CANCEL:
mTouchState = TOUCH_STATE_REST;
mAllowLongPress = false;
@@ -989,6 +1035,7 @@ public abstract class PagedView extends ViewGroup {
mSmoothingTime = System.nanoTime() / NANOTIME_DIV;
if (!mDeferScrollUpdate) {
scrollBy((int) deltaX, 0);
+ if (DEBUG) Log.d(TAG, "onTouchEvent().Scrolling: " + deltaX);
} else {
invalidate();
}
@@ -1155,14 +1202,13 @@ public abstract class PagedView extends ViewGroup {
}
}
- protected void onWallpaperTap(MotionEvent ev) {
- }
+ protected void onWallpaperTap(MotionEvent ev) {}
@Override
public void requestChildFocus(View child, View focused) {
super.requestChildFocus(child, focused);
int page = indexOfChild(child);
- if (page >= 0 && !isInTouchMode()) {
+ if (page >= 0 && page != getCurrentPage() && !isInTouchMode()) {
snapToPage(page);
}
}
@@ -1184,9 +1230,16 @@ public abstract class PagedView extends ViewGroup {
protected void setMinimumWidthOverride(int minimumWidth) {
mMinimumWidth = minimumWidth;
}
+ protected void resetMinimumWidthOverride() {
+ mMinimumWidth = 0;
+ }
protected int getChildWidth(int index) {
- return Math.max(mMinimumWidth, getChildAt(index).getMeasuredWidth());
+ // This functions are called enough times that it actually makes a difference in the
+ // profiler -- so just inline the max() here
+ final int measuredWidth = getChildAt(index).getMeasuredWidth();
+ final int minWidth = mMinimumWidth;
+ return (minWidth > measuredWidth) ? minWidth : measuredWidth;
}
protected int getRelativeChildOffset(int index) {
@@ -1205,7 +1258,12 @@ public abstract class PagedView extends ViewGroup {
}
protected int getScaledMeasuredWidth(View child) {
- return (int) (Math.max(mMinimumWidth, child.getMeasuredWidth()) * mLayoutScale + 0.5f);
+ // This functions are called enough times that it actually makes a difference in the
+ // profiler -- so just inline the max() here
+ final int measuredWidth = child.getMeasuredWidth();
+ final int minWidth = mMinimumWidth;
+ final int maxWidth = (minWidth > measuredWidth) ? minWidth : measuredWidth;
+ return (int) (maxWidth * mLayoutScale + 0.5f);
}
int getPageNearestToCenterOfScreen() {
@@ -1255,6 +1313,9 @@ public abstract class PagedView extends ViewGroup {
whichPage = Math.max(0, Math.min(whichPage, getChildCount() - 1));
int halfScreenSize = getMeasuredWidth() / 2;
+ if (DEBUG) Log.d(TAG, "snapToPage.getChildOffset(): " + getChildOffset(whichPage));
+ if (DEBUG) Log.d(TAG, "snapToPageWithVelocity.getRelativeChildOffset(): "
+ + getMeasuredWidth() + ", " + getChildWidth(whichPage));
final int newX = getChildOffset(whichPage) - getRelativeChildOffset(whichPage);
int delta = newX - mUnboundedScrollX;
int duration = 0;
@@ -1292,6 +1353,9 @@ public abstract class PagedView extends ViewGroup {
protected void snapToPage(int whichPage, int duration) {
whichPage = Math.max(0, Math.min(whichPage, getPageCount() - 1));
+ if (DEBUG) Log.d(TAG, "snapToPage.getChildOffset(): " + getChildOffset(whichPage));
+ if (DEBUG) Log.d(TAG, "snapToPage.getRelativeChildOffset(): " + getMeasuredWidth() + ", "
+ + getChildWidth(whichPage));
int newX = getChildOffset(whichPage) - getRelativeChildOffset(whichPage);
final int sX = mUnboundedScrollX;
final int delta = newX - sX;
@@ -1403,6 +1467,8 @@ public abstract class PagedView extends ViewGroup {
if (page < count) {
int lowerPageBound = getAssociatedLowerPageBound(page);
int upperPageBound = getAssociatedUpperPageBound(page);
+ if (DEBUG) Log.d(TAG, "loadAssociatedPages: " + lowerPageBound + "/"
+ + upperPageBound);
for (int i = 0; i < count; ++i) {
Page layout = (Page) getChildAt(i);
final int childCount = layout.getPageChildCount();
@@ -1496,10 +1562,6 @@ public abstract class PagedView extends ViewGroup {
}
}
- public void setRestorePage(int restorePage) {
- mRestorePage = restorePage;
- }
-
/**
* This method is called ONLY to synchronize the number of pages that the paged view has.
* To actually fill the pages with information, implement syncPageItems() below. It is
@@ -1527,7 +1589,13 @@ public abstract class PagedView extends ViewGroup {
}
protected void invalidatePageData() {
+ if (!mIsDataReady) {
+ return;
+ }
+
if (mContentIsRefreshable) {
+ hideScrollingIndicator(true);
+
// Update all the pages
syncPages();
@@ -1538,12 +1606,6 @@ public abstract class PagedView extends ViewGroup {
mDirtyPageContent.add(true);
}
- // Use the restore page if necessary
- if (mRestorePage > -1) {
- mCurrentPage = mRestorePage;
- mRestorePage = -1;
- }
-
// Load any pages that are necessary for the current window of views
loadAssociatedPages(mCurrentPage);
mDirtyPageAlpha = true;
@@ -1551,4 +1613,80 @@ public abstract class PagedView extends ViewGroup {
requestLayout();
}
}
+
+ private ImageView getScrollingIndicator() {
+ // We use mHasScrollIndicator to prevent future lookups if there is no sibling indicator
+ // found
+ if (mHasScrollIndicator && mScrollIndicator == null) {
+ ViewGroup parent = (ViewGroup) getParent();
+ mScrollIndicator = (ImageView) (parent.findViewById(R.id.paged_view_indicator));
+ mHasScrollIndicator = mScrollIndicator != null;
+ if (mHasScrollIndicator) {
+ mScrollIndicator.setVisibility(View.VISIBLE);
+ }
+ }
+ return mScrollIndicator;
+ }
+
+ protected boolean isScrollingIndicatorEnabled() {
+ return true;
+ }
+
+ protected void showScrollingIndicator() {
+ if (LauncherApplication.isScreenLarge()) return;
+ if (getChildCount() <= 1) return;
+ if (!isScrollingIndicatorEnabled()) return;
+
+ getScrollingIndicator();
+ if (mScrollIndicator != null) {
+ // Update the width of the indicator to the approx. width of each page in the full bar
+ mScrollIndicator.getLayoutParams().width = getPageWidthForScrollingIndicator() / getChildCount();
+ mScrollIndicator.requestLayout();
+
+ // Fade the indicator in
+ updateScrollingIndicatorPosition();
+ mScrollIndicator.animate().alpha(1f).setDuration(sScrollIndicatorFadeInDuration);
+ }
+ }
+
+ protected void hideScrollingIndicator(boolean immediately) {
+ if (LauncherApplication.isScreenLarge()) return;
+ if (getChildCount() <= 1) return;
+ if (!isScrollingIndicatorEnabled()) return;
+
+ getScrollingIndicator();
+ if (mScrollIndicator != null) {
+ // Fade the indicator out
+ updateScrollingIndicatorPosition();
+ mScrollIndicator.animate().alpha(0f).setDuration(immediately ?
+ sScrollIndicatorFastFadeOutDuration : sScrollIndicatorFadeOutDuration);
+ }
+ }
+
+ private void updateScrollingIndicator() {
+ if (LauncherApplication.isScreenLarge()) return;
+ if (getChildCount() <= 1) return;
+ if (!isScrollingIndicatorEnabled()) return;
+
+ getScrollingIndicator();
+ if (mScrollIndicator != null) {
+ updateScrollingIndicatorPosition();
+ }
+ }
+
+ protected int getPageWidthForScrollingIndicator() {
+ return getMeasuredWidth();
+ }
+
+ private void updateScrollingIndicatorPosition() {
+ // We can make the page width smaller to make it look more centered
+ int pageWidth = getPageWidthForScrollingIndicator();
+ int pageOffset = (getMeasuredWidth() - pageWidth) / 2;
+ int maxPageWidth = getChildCount() * pageWidth;
+ float offset = (float) getScrollX() / maxPageWidth;
+ int indicatorWidth = pageWidth / getChildCount();
+ int indicatorCenterOffset = indicatorWidth / 2 - mScrollIndicator.getMeasuredWidth() / 2;
+ int indicatorPos = (int) (offset * pageWidth) + pageOffset + indicatorCenterOffset;
+ mScrollIndicator.setTranslationX(indicatorPos);
+ }
}
diff --git a/src/com/android/launcher2/PagedViewCellLayout.java b/src/com/android/launcher2/PagedViewCellLayout.java
index d715ee35f..d7f8784a5 100644
--- a/src/com/android/launcher2/PagedViewCellLayout.java
+++ b/src/com/android/launcher2/PagedViewCellLayout.java
@@ -17,12 +17,15 @@
package com.android.launcher2;
import android.content.Context;
+import android.content.res.Resources;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewDebug;
import android.view.ViewGroup;
+import com.android.launcher.R;
+
/**
* An abstraction of the original CellLayout which supports laying out items
* which span multiple cells into a grid-like layout. Also supports dimming
@@ -37,7 +40,7 @@ public class PagedViewCellLayout extends ViewGroup implements Page {
private int mCellHeight;
private int mWidthGap;
private int mHeightGap;
- private static int sDefaultCellDimensions = 96;
+ private float mPeekWidth;
protected PagedViewCellLayoutChildren mChildren;
private PagedViewCellLayoutChildren mHolographicChildren;
private boolean mAllowHardwareLayerCreation = false;
@@ -57,7 +60,10 @@ public class PagedViewCellLayout extends ViewGroup implements Page {
setAlwaysDrawnWithCacheEnabled(false);
// setup default cell parameters
- mCellWidth = mCellHeight = sDefaultCellDimensions;
+ Resources resources = context.getResources();
+ mCellWidth = resources.getDimensionPixelSize(R.dimen.apps_customize_cell_width);
+ mCellHeight = resources.getDimensionPixelSize(R.dimen.apps_customize_cell_height);
+ mPeekWidth = resources.getDimensionPixelSize(R.dimen.apps_customize_peek_width);
mCellCountX = LauncherModel.getCellCountX();
mCellCountY = LauncherModel.getCellCountY();
mWidthGap = mHeightGap = -1;
@@ -132,6 +138,15 @@ public class PagedViewCellLayout extends ViewGroup implements Page {
}
}
+ /** Syncs the holographic icon views to the child icon views */
+ public void reloadHolographicIcons(boolean createHolographicOutlines) {
+ if (createHolographicOutlines) {
+ mChildren.loadHolographicOutlines();
+ } else {
+ mChildren.clearHolographicOutlines();
+ }
+ }
+
public boolean addViewToCellLayout(View child, int index, int childId,
PagedViewCellLayout.LayoutParams params) {
final PagedViewCellLayout.LayoutParams lp = params;
@@ -153,7 +168,8 @@ public class PagedViewCellLayout extends ViewGroup implements Page {
if (mAllowHardwareLayerCreation) {
pagedViewIcon.disableCache();
}
- mHolographicChildren.addView(pagedViewIcon.getHolographicOutlineView(), index, lp);
+ mHolographicChildren.addView(pagedViewIcon.getHolographicOutlineView(),
+ index, lp);
}
return true;
}
@@ -188,6 +204,14 @@ public class PagedViewCellLayout extends ViewGroup implements Page {
return mChildren.indexOfChild(v);
}
+ public int getCellCountX() {
+ return mCellCountX;
+ }
+
+ public int getCellCountY() {
+ return mCellCountY;
+ }
+
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
@@ -207,11 +231,11 @@ public class PagedViewCellLayout extends ViewGroup implements Page {
int vSpaceLeft = heightSpecSize - mPaddingTop
- mPaddingBottom - (cellHeight * mCellCountY);
- int heightGap = vSpaceLeft / numHeightGaps;
+ int heightGap = (numHeightGaps <= 0) ? 0 : (vSpaceLeft / numHeightGaps);
int hSpaceLeft = widthSpecSize - mPaddingLeft
- mPaddingRight - (cellWidth * mCellCountX);
- int widthGap = hSpaceLeft / numWidthGaps;
+ int widthGap = (numWidthGaps <= 0) ? 0 : (hSpaceLeft / numWidthGaps);
// center it around the min gaps
int minGap = Math.min(widthGap, heightGap);
@@ -249,11 +273,7 @@ public class PagedViewCellLayout extends ViewGroup implements Page {
}
int getContentWidth() {
- // Return the distance from the left edge of the content of the leftmost icon to
- // the right edge of the content of the rightmost icon
-
- // icons are centered within cells, find out how much padding that accounts for
- return getWidthBeforeFirstLayout() - (mCellWidth - Utilities.getIconContentSize());
+ return getWidthBeforeFirstLayout() + mPaddingLeft + mPaddingRight;
}
int getContentHeight() {
@@ -282,7 +302,20 @@ public class PagedViewCellLayout extends ViewGroup implements Page {
@Override
public boolean onTouchEvent(MotionEvent event) {
- return super.onTouchEvent(event) || true;
+ boolean result = super.onTouchEvent(event);
+ int count = getPageChildCount();
+ if (count > 0) {
+ // We only intercept the touch if we are tapping in empty space after the final row
+ View child = getChildOnPageAt(count - 1);
+ int bottom = child.getBottom();
+ int numRows = (int) Math.ceil((float) getPageChildCount() / getCellCountX());
+ if (numRows < getCellCountY()) {
+ // Add a little bit of buffer if there is room for another row
+ bottom += mCellHeight / 2;
+ }
+ result = result || (event.getY() < bottom);
+ }
+ return result;
}
public void enableCenteredContent(boolean enabled) {
@@ -335,16 +368,37 @@ public class PagedViewCellLayout extends ViewGroup implements Page {
* Estimates the number of cells that the specified width would take up.
*/
public int estimateCellHSpan(int width) {
- // TODO: we need to take widthGap into effect
- return (width + mCellWidth) / mCellWidth;
+ // The space for a page assuming that we want to show half of a column of the previous and
+ // next pages is the width - left padding (current & next page) - right padding (previous &
+ // current page) - half cell width (for previous and next pages)
+ int availWidth = (int) (width - (2 * mPaddingLeft + 2 * mPaddingRight) - (2 * mPeekWidth));
+
+ // We know that we have to fit N cells with N-1 width gaps, so we just juggle to solve for N
+ int n = Math.max(1, (availWidth + mWidthGap) / (mCellWidth + mWidthGap));
+
+ // We don't do anything fancy to determine if we squeeze another row in.
+ return n;
}
/**
* Estimates the number of cells that the specified height would take up.
*/
public int estimateCellVSpan(int height) {
- // TODO: we need to take heightGap into effect
- return (height + mCellHeight) / mCellHeight;
+ // The space for a page is the height - top padding (current page) - bottom padding (current
+ // page)
+ int availHeight = height - (mPaddingTop + mPaddingBottom);
+
+ // We know that we have to fit N cells with N-1 height gaps, so we juggle to solve for N
+ int n = Math.max(1, (availHeight + mHeightGap) / (mCellHeight + mHeightGap));
+
+ // We don't do anything fancy to determine if we squeeze another row in.
+ return n;
+ }
+
+ public void calculateCellCount(int width, int height, int maxCellCountX, int maxCellCountY) {
+ mCellCountX = Math.min(maxCellCountX, estimateCellHSpan(width));
+ mCellCountY = Math.min(maxCellCountY, estimateCellVSpan(height));
+ requestLayout();
}
/**
@@ -465,8 +519,13 @@ public class PagedViewCellLayout extends ViewGroup implements Page {
height = myCellVSpan * cellHeight + ((myCellVSpan - 1) * heightGap) -
topMargin - bottomMargin;
- x = hStartPadding + myCellX * (cellWidth + widthGap) + leftMargin;
- y = vStartPadding + myCellY * (cellHeight + heightGap) + topMargin;
+ if (LauncherApplication.isScreenLarge()) {
+ x = hStartPadding + myCellX * (cellWidth + widthGap) + leftMargin;
+ y = vStartPadding + myCellY * (cellHeight + heightGap) + topMargin;
+ } else {
+ x = myCellX * (cellWidth + widthGap) + leftMargin;
+ y = myCellY * (cellHeight + heightGap) + topMargin;
+ }
}
public Object getTag() {
diff --git a/src/com/android/launcher2/PagedViewCellLayoutChildren.java b/src/com/android/launcher2/PagedViewCellLayoutChildren.java
index 0907c6058..1afdd03cf 100644
--- a/src/com/android/launcher2/PagedViewCellLayoutChildren.java
+++ b/src/com/android/launcher2/PagedViewCellLayoutChildren.java
@@ -168,4 +168,26 @@ public class PagedViewCellLayoutChildren extends ViewGroup {
}
}
}
+
+ public void loadHolographicOutlines() {
+ int count = getChildCount();
+ for (int i = 0; i < count; i++) {
+ View view = getChildAt(i);
+ if (view instanceof PagedViewIcon) {
+ PagedViewIcon icon = (PagedViewIcon) view;
+ icon.loadHolographicIcon();
+ }
+ }
+ }
+
+ public void clearHolographicOutlines() {
+ int count = getChildCount();
+ for (int i = 0; i < count; i++) {
+ View view = getChildAt(i);
+ if (view instanceof PagedViewIcon) {
+ PagedViewIcon icon = (PagedViewIcon) view;
+ icon.clearHolographicIcon();
+ }
+ }
+ }
}
diff --git a/src/com/android/launcher2/PagedViewExtendedLayout.java b/src/com/android/launcher2/PagedViewExtendedLayout.java
index 4ceb44dd4..94890d8ce 100644
--- a/src/com/android/launcher2/PagedViewExtendedLayout.java
+++ b/src/com/android/launcher2/PagedViewExtendedLayout.java
@@ -20,16 +20,14 @@ import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
-import android.view.ViewGroup;
import android.widget.LinearLayout;
/**
- * The linear layout used strictly for the widget/wallpaper tab of the customization tray
+ * The linear layout used strictly for the widget/wallpaper tab of the customization tray.
+ * To be deprecated.
*/
public class PagedViewExtendedLayout extends LinearLayout implements Page {
- static final String TAG = "PagedViewWidgetLayout";
- float mChildrenAlpha = 1f;
- private boolean mHasFixedWidth;
+ static final String TAG = "PagedViewExtendedLayout";
public PagedViewExtendedLayout(Context context) {
this(context, null);
@@ -43,22 +41,20 @@ public class PagedViewExtendedLayout extends LinearLayout implements Page {
super(context, attrs, defStyle);
}
- public void setHasFixedWidth(boolean hasFixedWidth) {
- mHasFixedWidth = hasFixedWidth;
- }
-
- @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- if (mHasFixedWidth) {
+ if (LauncherApplication.isScreenLarge()) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ } else {
// PagedView currently has issues with different-sized pages since it calculates the
// offset of each page to scroll to before it updates the actual size of each page
// (which canchange depending on the content if the contains aren't a fixed size).
- // We work around this by having a fixed size on each widget page).
- int widthSpecSize = getSuggestedMinimumWidth();
- int widthSpecMode = MeasureSpec.EXACTLY;
- widthMeasureSpec = MeasureSpec.makeMeasureSpec(widthSpecSize, widthSpecMode);
+ // We work around this by having a minimum size on each widget page).
+ int widthSpecSize = Math.max(getSuggestedMinimumWidth(),
+ MeasureSpec.getSize(widthMeasureSpec));
+ int widthSpecMode = MeasureSpec.AT_MOST;
+ super.onMeasure(MeasureSpec.makeMeasureSpec(widthSpecSize, widthSpecMode),
+ heightMeasureSpec);
}
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@Override
@@ -80,7 +76,6 @@ public class PagedViewExtendedLayout extends LinearLayout implements Page {
@Override
public void setAlpha(float alpha) {
- mChildrenAlpha = alpha;
setChildrenAlpha(alpha);
super.setAlpha(alpha);
}
@@ -93,37 +88,6 @@ public class PagedViewExtendedLayout extends LinearLayout implements Page {
}
@Override
- public void addView(View child, int index, ViewGroup.LayoutParams params) {
- super.addView(child, index, params);
- child.setAlpha(mChildrenAlpha);
- }
-
-
- @Override
- public void addView(View child, ViewGroup.LayoutParams params) {
- super.addView(child, params);
- child.setAlpha(mChildrenAlpha);
- }
-
- @Override
- public void addView(View child, int index) {
- super.addView(child, index);
- child.setAlpha(mChildrenAlpha);
- }
-
- @Override
- public void addView(View child) {
- super.addView(child);
- child.setAlpha(mChildrenAlpha);
- }
-
- @Override
- public void addView(View child, int width, int height) {
- super.addView(child, width, height);
- child.setAlpha(mChildrenAlpha);
- }
-
- @Override
public void removeAllViewsOnPage() {
removeAllViews();
}
@@ -147,4 +111,11 @@ public class PagedViewExtendedLayout extends LinearLayout implements Page {
public int indexOfChildOnPage(View v) {
return indexOfChild(v);
}
+
+ public static class LayoutParams extends LinearLayout.LayoutParams {
+ public LayoutParams() {
+ super(LinearLayout.LayoutParams.WRAP_CONTENT,
+ LinearLayout.LayoutParams.MATCH_PARENT);
+ }
+ }
}
diff --git a/src/com/android/launcher2/PagedViewGridLayout.java b/src/com/android/launcher2/PagedViewGridLayout.java
new file mode 100644
index 000000000..c6d39fd5f
--- /dev/null
+++ b/src/com/android/launcher2/PagedViewGridLayout.java
@@ -0,0 +1,121 @@
+/*
+ * 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.
+ */
+
+package com.android.launcher2;
+
+import android.content.Context;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.View.MeasureSpec;
+import android.widget.FrameLayout;
+import android.widget.LinearLayout;
+
+/**
+ * The grid based layout used strictly for the widget/wallpaper tab of the AppsCustomize pane
+ */
+public class PagedViewGridLayout extends FrameLayout implements Page {
+ static final String TAG = "PagedViewGridLayout";
+
+ private int mCellCountX;
+ private int mCellCountY;
+
+ public PagedViewGridLayout(Context context, int cellCountX, int cellCountY) {
+ super(context, null, 0);
+ mCellCountX = cellCountX;
+ mCellCountY = cellCountY;
+ }
+
+ int getCellCountX() {
+ return mCellCountX;
+ }
+ int getCellCountY() {
+ return mCellCountY;
+ }
+
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ // PagedView currently has issues with different-sized pages since it calculates the
+ // offset of each page to scroll to before it updates the actual size of each page
+ // (which can change depending on the content if the contents aren't a fixed size).
+ // We work around this by having a minimum size on each widget page).
+ int widthSpecSize = Math.max(getSuggestedMinimumWidth(),
+ MeasureSpec.getSize(widthMeasureSpec));
+ int widthSpecMode = MeasureSpec.AT_MOST;
+ super.onMeasure(MeasureSpec.makeMeasureSpec(widthSpecSize, widthSpecMode),
+ heightMeasureSpec);
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ boolean result = super.onTouchEvent(event);
+ int count = getPageChildCount();
+ if (count > 0) {
+ // We only intercept the touch if we are tapping in empty space after the final row
+ View child = getChildOnPageAt(count - 1);
+ int bottom = child.getBottom();
+ result = result || (event.getY() < bottom);
+ }
+ return result;
+ }
+
+ @Override
+ protected boolean onSetAlpha(int alpha) {
+ return true;
+ }
+
+ @Override
+ public void setAlpha(float alpha) {
+ setChildrenAlpha(alpha);
+ super.setAlpha(alpha);
+ }
+
+ private void setChildrenAlpha(float alpha) {
+ final int childCount = getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ getChildAt(i).setAlpha(alpha);
+ }
+ }
+
+ @Override
+ public void removeAllViewsOnPage() {
+ removeAllViews();
+ }
+
+ @Override
+ public void removeViewOnPageAt(int index) {
+ removeViewAt(index);
+ }
+
+ @Override
+ public int getPageChildCount() {
+ return getChildCount();
+ }
+
+ @Override
+ public View getChildOnPageAt(int i) {
+ return getChildAt(i);
+ }
+
+ @Override
+ public int indexOfChildOnPage(View v) {
+ return indexOfChild(v);
+ }
+
+ public static class LayoutParams extends FrameLayout.LayoutParams {
+ public LayoutParams(int width, int height) {
+ super(width, height);
+ }
+ }
+}
diff --git a/src/com/android/launcher2/PagedViewIcon.java b/src/com/android/launcher2/PagedViewIcon.java
index bde65593a..30f0b1db2 100644
--- a/src/com/android/launcher2/PagedViewIcon.java
+++ b/src/com/android/launcher2/PagedViewIcon.java
@@ -16,9 +16,8 @@
package com.android.launcher2;
-import com.android.launcher.R;
-
import android.animation.ObjectAnimator;
+import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
@@ -31,9 +30,10 @@ import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.util.AttributeSet;
+import android.view.KeyEvent;
import android.widget.Checkable;
-import android.widget.TextView;
+import com.android.launcher.R;
/**
@@ -121,15 +121,15 @@ public class PagedViewIcon extends CachedTextView implements Checkable {
// Set up fade in/out constants
final Resources r = context.getResources();
- final int alpha = r.getInteger(R.integer.icon_allAppsCustomizeFadeAlpha);
+ final int alpha = r.getInteger(R.integer.config_dragAppsCustomizeIconFadeAlpha);
if (alpha > 0) {
- mCheckedAlpha = r.getInteger(R.integer.icon_allAppsCustomizeFadeAlpha) / 256.0f;
- mCheckedFadeInDuration = r.getInteger(R.integer.icon_allAppsCustomizeFadeInTime);
- mCheckedFadeOutDuration = r.getInteger(R.integer.icon_allAppsCustomizeFadeOutTime);
+ mCheckedAlpha = r.getInteger(R.integer.config_dragAppsCustomizeIconFadeAlpha) / 256.0f;
+ mCheckedFadeInDuration =
+ r.getInteger(R.integer.config_dragAppsCustomizeIconFadeInDuration);
+ mCheckedFadeOutDuration =
+ r.getInteger(R.integer.config_dragAppsCustomizeIconFadeOutDuration);
}
- setFocusable(true);
- setBackgroundDrawable(null);
mHolographicOutlineView = new HolographicPagedViewIcon(context, this);
}
@@ -152,16 +152,29 @@ public class PagedViewIcon extends CachedTextView implements Checkable {
return false;
}
+ public void loadHolographicIcon() {
+ if (mHolographicOutline == null) {
+ mHolographicOutline = mIconCache.getOutline(mIconCacheKey);
+ if (!queueHolographicOutlineCreation()) {
+ getHolographicOutlineView().invalidate();
+ }
+ }
+ }
+ public void clearHolographicIcon() {
+ mHolographicOutline = null;
+ getHolographicOutlineView().invalidate();
+ }
+
public void applyFromApplicationInfo(ApplicationInfo info, PagedViewIconCache cache,
boolean scaleUp, boolean createHolographicOutlines) {
+ mIconCache = cache;
+ mIconCacheKey = new PagedViewIconCache.Key(info);
mIcon = info.iconBitmap;
setCompoundDrawablesWithIntrinsicBounds(null, new FastBitmapDrawable(mIcon), null, null);
setText(info.title);
setTag(info);
if (createHolographicOutlines) {
- mIconCache = cache;
- mIconCacheKey = new PagedViewIconCache.Key(info);
mHolographicOutline = mIconCache.getOutline(mIconCacheKey);
if (!queueHolographicOutlineCreation()) {
getHolographicOutlineView().invalidate();
@@ -171,8 +184,8 @@ public class PagedViewIcon extends CachedTextView implements Checkable {
public void applyFromResolveInfo(ResolveInfo info, PackageManager packageManager,
PagedViewIconCache cache, IconCache modelIconCache, boolean createHolographicOutlines) {
- mIcon = Utilities.createIconBitmap(
- modelIconCache.getFullResIcon(info, packageManager), mContext);
+ ComponentName cn = new ComponentName(info.activityInfo.packageName, info.activityInfo.name);
+ mIcon = modelIconCache.getIcon(cn, info);
setCompoundDrawablesWithIntrinsicBounds(null, new FastBitmapDrawable(mIcon), null, null);
setText(info.loadLabel(packageManager));
setTag(info);
@@ -216,12 +229,7 @@ public class PagedViewIcon extends CachedTextView implements Checkable {
Bitmap overlay = null;
// draw any blended overlays
- if (mCheckedOutline == null) {
- if (mHolographicOutline != null && mHolographicAlpha > 0) {
- mPaint.setAlpha(mHolographicAlpha);
- overlay = mHolographicOutline;
- }
- } else {
+ if (mCheckedOutline != null) {
mPaint.setAlpha(255);
overlay = mCheckedOutline;
}
@@ -245,6 +253,18 @@ public class PagedViewIcon extends CachedTextView implements Checkable {
}
@Override
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ return FocusHelper.handlePagedViewIconKeyEvent(this, keyCode, event)
+ || super.onKeyDown(keyCode, event);
+ }
+
+ @Override
+ public boolean onKeyUp(int keyCode, KeyEvent event) {
+ return FocusHelper.handlePagedViewIconKeyEvent(this, keyCode, event)
+ || super.onKeyUp(keyCode, event);
+ }
+
+ @Override
public boolean isChecked() {
return mIsChecked;
}
diff --git a/src/com/android/launcher2/PagedViewWidget.java b/src/com/android/launcher2/PagedViewWidget.java
index 5791fb851..6ddecf1ec 100644
--- a/src/com/android/launcher2/PagedViewWidget.java
+++ b/src/com/android/launcher2/PagedViewWidget.java
@@ -36,6 +36,7 @@ import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.util.AttributeSet;
+import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Checkable;
@@ -61,6 +62,10 @@ public class PagedViewWidget extends LinearLayout implements Checkable {
private final Rect mEraseStrokeRect = new Rect();
private final Paint mEraseStrokeRectPaint = new Paint();
+ private PagedViewIconCache.Key mIconCacheKey;
+ private PagedViewIconCache mIconCache;
+ private String mDimensionsFormatString;
+
private int mAlpha = 255;
private int mHolographicAlpha;
@@ -115,6 +120,7 @@ public class PagedViewWidget extends LinearLayout implements Checkable {
mHandler.post(new Runnable() {
public void run() {
widget.mHolographicOutline = outline;
+ widget.mIconCache.addOutline(widget.mIconCacheKey, outline);
widget.invalidate();
}
});
@@ -149,14 +155,16 @@ public class PagedViewWidget extends LinearLayout implements Checkable {
// Set up fade in/out constants
final Resources r = context.getResources();
- final int alpha = r.getInteger(R.integer.icon_allAppsCustomizeFadeAlpha);
+ final int alpha = r.getInteger(R.integer.config_dragAppsCustomizeIconFadeAlpha);
if (alpha > 0) {
- mCheckedAlpha = r.getInteger(R.integer.icon_allAppsCustomizeFadeAlpha) / 256.0f;
- mCheckedFadeInDuration = r.getInteger(R.integer.icon_allAppsCustomizeFadeInTime);
- mCheckedFadeOutDuration = r.getInteger(R.integer.icon_allAppsCustomizeFadeOutTime);
+ mCheckedAlpha = r.getInteger(R.integer.config_dragAppsCustomizeIconFadeAlpha) / 256.0f;
+ mCheckedFadeInDuration =
+ r.getInteger(R.integer.config_dragAppsCustomizeIconFadeInDuration);
+ mCheckedFadeOutDuration =
+ r.getInteger(R.integer.config_dragAppsCustomizeIconFadeOutDuration);
}
+ mDimensionsFormatString = r.getString(R.string.widget_dims_format);
- setFocusable(true);
setWillNotDraw(false);
setClipToPadding(false);
}
@@ -174,17 +182,44 @@ public class PagedViewWidget extends LinearLayout implements Checkable {
FastBitmapDrawable preview, int maxWidth, int[] cellSpan,
PagedViewIconCache cache, boolean createHolographicOutline) {
final ImageView image = (ImageView) findViewById(R.id.widget_preview);
- image.setMaxWidth(maxWidth);
+ if (maxWidth > -1) {
+ image.setMaxWidth(maxWidth);
+ }
image.setImageDrawable(preview);
mPreviewImageView = image;
final TextView name = (TextView) findViewById(R.id.widget_name);
name.setText(info.label);
name.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
final TextView dims = (TextView) findViewById(R.id.widget_dims);
- dims.setText(mContext.getString(R.string.widget_dims_format, cellSpan[0], cellSpan[1]));
+ dims.setText(String.format(mDimensionsFormatString, cellSpan[0], cellSpan[1]));
dims.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
if (createHolographicOutline) {
+ mIconCache = cache;
+ mIconCacheKey = new PagedViewIconCache.Key(info);
+ mHolographicOutline = mIconCache.getOutline(mIconCacheKey);
+ mPreview = preview;
+ }
+ }
+
+ public void applyFromResolveInfo(PackageManager pm, ResolveInfo info,
+ FastBitmapDrawable preview, PagedViewIconCache cache, boolean createHolographicOutline){
+ final ImageView image = (ImageView) findViewById(R.id.widget_preview);
+ image.setImageDrawable(preview);
+ mPreviewImageView = image;
+ final TextView name = (TextView) findViewById(R.id.widget_name);
+ name.setText(info.loadLabel(pm));
+ name.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
+ final TextView dims = (TextView) findViewById(R.id.widget_dims);
+ if (dims != null) {
+ dims.setText(String.format(mDimensionsFormatString, 1, 1));
+ dims.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
+ }
+
+ if (createHolographicOutline) {
+ mIconCache = cache;
+ mIconCacheKey = new PagedViewIconCache.Key(info);
+ mHolographicOutline = mIconCache.getOutline(mIconCacheKey);
mPreview = preview;
}
}
@@ -201,6 +236,9 @@ public class PagedViewWidget extends LinearLayout implements Checkable {
name.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
if (createHolographicOutline) {
+ mIconCache = cache;
+ mIconCacheKey = new PagedViewIconCache.Key(info);
+ mHolographicOutline = mIconCache.getOutline(mIconCacheKey);
mPreview = preview;
}
}
@@ -218,6 +256,18 @@ public class PagedViewWidget extends LinearLayout implements Checkable {
}
@Override
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ return FocusHelper.handlePagedViewGridLayoutWidgetKeyEvent(this, keyCode, event)
+ || super.onKeyDown(keyCode, event);
+ }
+
+ @Override
+ public boolean onKeyUp(int keyCode, KeyEvent event) {
+ return FocusHelper.handlePagedViewGridLayoutWidgetKeyEvent(this, keyCode, event)
+ || super.onKeyUp(keyCode, event);
+ }
+
+ @Override
protected void onDraw(Canvas canvas) {
if (mAlpha > 0) {
super.onDraw(canvas);
diff --git a/src/com/android/launcher2/RocketLauncher.java b/src/com/android/launcher2/RocketLauncher.java
new file mode 100644
index 000000000..1c6510fa5
--- /dev/null
+++ b/src/com/android/launcher2/RocketLauncher.java
@@ -0,0 +1,426 @@
+/*);
+ * 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.
+ */
+
+// TODO:
+// background stellar matter:
+// - add some slow horizontal parallax motion, or perhaps veeeeery gradual outward drift
+
+package com.android.launcher2;
+
+import android.animation.AnimatorSet;
+import android.animation.PropertyValuesHolder;
+import android.animation.ObjectAnimator;
+import android.animation.TimeAnimator;
+import android.app.Activity;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.support.v13.dreams.BasicDream;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.os.Handler;
+import android.util.AttributeSet;
+import android.util.DisplayMetrics;
+import android.util.Pair;
+import android.view.Gravity;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import java.util.HashMap;
+import java.util.Random;
+
+import com.android.launcher.R;
+
+public class RocketLauncher extends BasicDream {
+ public static final boolean ROCKET_LAUNCHER = true;
+
+ public static class Board extends FrameLayout
+ {
+ public static final boolean FIXED_STARS = true;
+ public static final boolean FLYING_STARS = true;
+ public static final int NUM_ICONS = 20;
+
+ public static final float MANEUVERING_THRUST_SCALE = 0.1f; // tenth speed
+ private boolean mManeuveringThrusters = false;
+ private float mSpeedScale = 1.0f;
+
+ public static final int LAUNCH_ZOOM_TIME = 400; // ms
+
+ HashMap<ComponentName, Bitmap> mIcons;
+ ComponentName[] mComponentNames;
+
+ static Random sRNG = new Random();
+
+ static float lerp(float a, float b, float f) {
+ return (b-a)*f + a;
+ }
+
+ static float randfrange(float a, float b) {
+ return lerp(a, b, sRNG.nextFloat());
+ }
+
+ static int randsign() {
+ return sRNG.nextBoolean() ? 1 : -1;
+ }
+
+ static <E> E pick(E[] array) {
+ if (array.length == 0) return null;
+ return array[sRNG.nextInt(array.length)];
+ }
+
+ public class FlyingIcon extends ImageView {
+ public static final float VMAX = 1000.0f;
+ public static final float VMIN = 100.0f;
+ public static final float ANGULAR_VMAX = 45f;
+ public static final float ANGULAR_VMIN = 0f;
+ public static final float SCALE_MIN = 0.5f;
+ public static final float SCALE_MAX = 4f;
+
+ public float v, vr;
+
+ public final float[] hsv = new float[3];
+
+ public float angle, anglex, angley;
+ public float fuse;
+ public float dist;
+ public float endscale;
+ public float boardCenterX, boardCenterY;
+
+ public ComponentName component;
+
+ public FlyingIcon(Context context, AttributeSet as) {
+ super(context, as);
+ setLayerType(View.LAYER_TYPE_HARDWARE, null);
+
+ setBackgroundResource(R.drawable.flying_icon_bg);
+ //android.util.Log.d("RocketLauncher", "ctor: " + this);
+ hsv[1] = 1f;
+ hsv[2] = 1f;
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ if (!mManeuveringThrusters || component == null) {
+ return false;
+ }
+ if (getAlpha() < 0.5f) {
+ setPressed(false);
+ return false;
+ }
+
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ setPressed(true);
+ Board.this.resetWarpTimer();
+ break;
+ case MotionEvent.ACTION_MOVE:
+ final Rect hit = new Rect();
+ final Point offset = new Point();
+ getGlobalVisibleRect(hit, offset);
+ final int globx = (int) event.getX() + offset.x;
+ final int globy = (int) event.getY() + offset.y;
+ setPressed(hit.contains(globx, globy));
+ Board.this.resetWarpTimer();
+ break;
+ case MotionEvent.ACTION_UP:
+ if (isPressed()) {
+ setPressed(false);
+ postDelayed(new Runnable() {
+ public void run() {
+ try {
+ getContext().startActivity(new Intent(Intent.ACTION_MAIN)
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ .setComponent(component));
+ } catch (android.content.ActivityNotFoundException e) {
+ } catch (SecurityException e) {
+ }
+ }
+ }, LAUNCH_ZOOM_TIME);
+ endscale = 0;
+ AnimatorSet s = new AnimatorSet();
+ s.playTogether(
+ ObjectAnimator.ofFloat(this, "scaleX", 15f),
+ ObjectAnimator.ofFloat(this, "scaleY", 15f),
+ ObjectAnimator.ofFloat(this, "alpha", 0f)
+ );
+
+ // make sure things are still moving until the very last instant the
+ // activity is visible
+ s.setDuration((int)(LAUNCH_ZOOM_TIME * 1.25));
+ s.setInterpolator(new android.view.animation.AccelerateInterpolator(3));
+ s.start();
+ }
+ break;
+ }
+ return true;
+ }
+
+ public String toString() {
+ return String.format("<'%s' @ (%.1f, %.1f) v=%.1f a=%.1f dist/fuse=%.1f/%.1f>",
+ "icon", getX(), getY(), v, angle, dist, fuse);
+ }
+
+ public void randomizeIcon() {
+ component = pick(mComponentNames);
+ setImageBitmap(mIcons.get(component));
+ }
+
+ public void randomize() {
+ v = randfrange(VMIN, VMAX);
+ angle = randfrange(0, 360f);
+ anglex = (float) Math.sin(angle / 180. * Math.PI);
+ angley = (float) Math.cos(angle / 180. * Math.PI);
+ vr = randfrange(ANGULAR_VMIN, ANGULAR_VMAX) * randsign();
+ endscale = randfrange(SCALE_MIN, SCALE_MAX);
+
+ randomizeIcon();
+ }
+ public void reset() {
+ randomize();
+ boardCenterX = (Board.this.getWidth() - getWidth()) / 2;
+ boardCenterY = (Board.this.getHeight() - getHeight()) / 2;
+ setX(boardCenterX);
+ setY(boardCenterY);
+ fuse = (float) Math.max(boardCenterX, boardCenterY);
+ setRotation(180-angle);
+ setScaleX(0f);
+ setScaleY(0f);
+ dist = 0;
+ setAlpha(0f);
+ }
+ public void update(float dt) {
+ dist += v * dt;
+ setX(getX() + anglex * v * dt);
+ setY(getY() + angley * v * dt);
+ //setRotation(getRotation() + vr * dt);
+ if (endscale > 0) {
+ float scale = lerp(0, endscale, (float) Math.sqrt(dist / fuse));
+ setScaleX(scale * lerp(1f, 0.75f, (float) Math.pow((v-VMIN)/(VMAX-VMIN),3)));
+ setScaleY(scale * lerp(1f, 1.5f, (float) Math.pow((v-VMIN)/(VMAX-VMIN),3)));
+ final float q1 = fuse*0.15f;
+ final float q4 = fuse*0.75f;
+ if (dist < q1) {
+ setAlpha((float) Math.sqrt(dist/q1));
+ } else if (dist > q4) {
+ setAlpha((dist >= fuse) ? 0f : (1f-(float)Math.pow((dist-q4)/(fuse-q4),2)));
+ } else {
+ setAlpha(1f);
+ }
+ }
+ }
+ }
+
+ public class FlyingStar extends FlyingIcon {
+ public FlyingStar(Context context, AttributeSet as) {
+ super(context, as);
+ }
+ public void randomizeIcon() {
+ setImageResource(R.drawable.widget_resize_handle_bottom);
+ }
+ public void randomize() {
+ super.randomize();
+ v = randfrange(VMAX*0.75f, VMAX*2f); // fasticate
+ endscale = randfrange(1f, 2f); // ensmallen
+ }
+ }
+
+ TimeAnimator mAnim;
+
+ public Board(Context context, AttributeSet as) {
+ super(context, as);
+
+ setBackgroundColor(0xFF000000);
+
+ LauncherApplication app = (LauncherApplication)context.getApplicationContext();
+ mIcons = app.getIconCache().getAllIcons();
+ mComponentNames = new ComponentName[mIcons.size()];
+ mComponentNames = mIcons.keySet().toArray(mComponentNames);
+ }
+
+ private void reset() {
+ removeAllViews();
+
+ final ViewGroup.LayoutParams wrap = new ViewGroup.LayoutParams(
+ ViewGroup.LayoutParams.WRAP_CONTENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT);
+
+ if (FIXED_STARS) {
+ for(int i=0; i<20; i++) {
+ ImageView fixedStar = new ImageView(getContext(), null);
+ fixedStar.setImageResource(R.drawable.widget_resize_handle_bottom);
+ final float s = randfrange(0.25f, 0.75f);
+ fixedStar.setScaleX(s);
+ fixedStar.setScaleY(s);
+ fixedStar.setAlpha(0.75f);
+ addView(fixedStar, wrap);
+ fixedStar.setX(randfrange(0, getWidth()));
+ fixedStar.setY(randfrange(0, getHeight()));
+ }
+ }
+
+ for(int i=0; i<NUM_ICONS*2; i++) {
+ FlyingIcon nv = (FLYING_STARS && (i < NUM_ICONS))
+ ? new FlyingStar(getContext(), null)
+ : new FlyingIcon(getContext(), null);
+ addView(nv, wrap);
+ nv.reset();
+ }
+
+ mAnim = new TimeAnimator();
+ mAnim.setTimeListener(new TimeAnimator.TimeListener() {
+ public void onTimeUpdate(TimeAnimator animation, long totalTime, long deltaTime) {
+ // setRotation(totalTime * 0.01f); // not as cool as you would think
+
+ final int START_ZOOM_TIME = 3000;
+ if (totalTime < START_ZOOM_TIME) {
+ final float x = totalTime/(float)START_ZOOM_TIME;
+ final float s = 1f-(float)Math.pow(x-1, 4);
+ setScaleX(s); setScaleY(s);
+ } else {
+ setScaleX(1.0f); setScaleY(1.0f);
+ }
+
+ if (mManeuveringThrusters) {
+ if (mSpeedScale > MANEUVERING_THRUST_SCALE) {
+ mSpeedScale -= (2*deltaTime/1000f);
+ }
+ if (mSpeedScale < MANEUVERING_THRUST_SCALE) {
+ mSpeedScale = MANEUVERING_THRUST_SCALE;
+ }
+ } else {
+ if (mSpeedScale < 1.0f) {
+ mSpeedScale += (deltaTime/1000f);
+ }
+ if (mSpeedScale > 1.0f) {
+ mSpeedScale = 1.0f;
+ }
+ }
+
+ for (int i=0; i<getChildCount(); i++) {
+ View v = getChildAt(i);
+ if (!(v instanceof FlyingIcon)) continue;
+ FlyingIcon nv = (FlyingIcon) v;
+ nv.update(deltaTime / 1000f * mSpeedScale);
+ final float scaledWidth = nv.getWidth() * nv.getScaleX();
+ final float scaledHeight = nv.getHeight() * nv.getScaleY();
+ if ( nv.getX() + scaledWidth < 0
+ || nv.getX() - scaledWidth > getWidth()
+ || nv.getY() + scaledHeight < 0
+ || nv.getY() - scaledHeight > getHeight())
+ {
+ nv.reset();
+ }
+ }
+ }
+ });
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ setLayerType(View.LAYER_TYPE_HARDWARE, null);
+ setSystemUiVisibility(View.STATUS_BAR_HIDDEN);
+
+ reset();
+ mAnim.start();
+ }
+
+ protected void onSizeChanged (int w, int h, int oldw, int oldh) {
+ super.onSizeChanged(w,h,oldw,oldh);
+ mAnim.cancel();
+ reset();
+ mAnim.start();
+ }
+
+
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ mAnim.cancel();
+ }
+
+ @Override
+ public boolean isOpaque() {
+ return true;
+ }
+
+ @Override
+ public boolean onInterceptTouchEvent(MotionEvent e) {
+ // we want to eat touch events ourselves if we're in warp speed
+ return (!(ROCKET_LAUNCHER && mManeuveringThrusters));
+ }
+
+ final Runnable mEngageWarp = new Runnable() {
+ @Override
+ public void run() {
+ mManeuveringThrusters = false;
+ }
+ };
+ public void resetWarpTimer() {
+ final Handler h = getHandler();
+ h.removeCallbacks(mEngageWarp);
+ h.postDelayed(mEngageWarp, 5000);
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ if (!ROCKET_LAUNCHER) {
+ return true;
+ }
+
+ if (event.getAction() == MotionEvent.ACTION_DOWN) {
+ if (!mManeuveringThrusters) {
+ mManeuveringThrusters = true;
+ resetWarpTimer();
+ return true;
+ }
+ }
+
+ return false;
+ }
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+
+ DisplayMetrics metrics = new DisplayMetrics();
+ getWindowManager().getDefaultDisplay().getMetrics(metrics);
+ final int longside = metrics.widthPixels > metrics.heightPixels
+ ? metrics.widthPixels : metrics.heightPixels;
+
+ Board b = new Board(this, null);
+ setContentView(b, new ViewGroup.LayoutParams(longside, longside));
+ b.setX((metrics.widthPixels - longside) / 2);
+ b.setY((metrics.heightPixels - longside) / 2);
+ }
+
+ @Override
+ public void onUserInteraction() {
+ if (!ROCKET_LAUNCHER) {
+ finish();
+ }
+ }
+}
diff --git a/src/com/android/launcher2/SearchDropTargetBar.java b/src/com/android/launcher2/SearchDropTargetBar.java
new file mode 100644
index 000000000..d00e2103f
--- /dev/null
+++ b/src/com/android/launcher2/SearchDropTargetBar.java
@@ -0,0 +1,121 @@
+/*
+ * 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.
+ */
+
+package com.android.launcher2;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.FrameLayout;
+
+import com.android.launcher.R;
+
+/*
+ * Ths bar will manage the transition between the QSB search bar and the delete drop
+ * targets so that each of the individual IconDropTargets don't have to.
+ */
+public class SearchDropTargetBar extends FrameLayout implements DragController.DragListener {
+
+ private static final int sTransitionInDuration = 275;
+ private static final int sTransitionOutDuration = 100;
+
+ private boolean mIsSearchBarHidden;
+ private View mQSBSearchBar;
+ private View mDropTargetBar;
+ private ButtonDropTarget mInfoDropTarget;
+ private ButtonDropTarget mDeleteDropTarget;
+
+ public SearchDropTargetBar(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public SearchDropTargetBar(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ public void setup(Launcher launcher, DragController dragController) {
+ dragController.addDragListener(this);
+ dragController.addDragListener(mInfoDropTarget);
+ dragController.addDragListener(mDeleteDropTarget);
+ dragController.addDropTarget(mInfoDropTarget);
+ dragController.addDropTarget(mDeleteDropTarget);
+ mInfoDropTarget.setLauncher(launcher);
+ mDeleteDropTarget.setLauncher(launcher);
+ mDropTargetBar.setBackgroundColor(0x33000000);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+
+ // Get the individual components
+ mQSBSearchBar = findViewById(R.id.qsb_search_bar);
+ mDropTargetBar = findViewById(R.id.drag_target_bar);
+ mInfoDropTarget = (ButtonDropTarget) mDropTargetBar.findViewById(R.id.info_target);
+ mDeleteDropTarget = (ButtonDropTarget) mDropTargetBar.findViewById(R.id.delete_target);
+ }
+
+ /*
+ * Shows and hides the search bar.
+ */
+ public void showSearchBar(boolean animated) {
+ if (animated) {
+ mQSBSearchBar.animate().alpha(1f).setDuration(sTransitionInDuration);
+ } else {
+ mQSBSearchBar.setAlpha(1f);
+ }
+ mIsSearchBarHidden = false;
+ }
+ public void hideSearchBar(boolean animated) {
+ if (animated) {
+ mQSBSearchBar.animate().alpha(0f).setDuration(sTransitionOutDuration);
+ } else {
+ mQSBSearchBar.setAlpha(0f);
+ }
+ mIsSearchBarHidden = true;
+ }
+
+ /*
+ * Gets various transition durations.
+ */
+ public int getTransitionInDuration() {
+ return sTransitionInDuration;
+ }
+ public int getTransitionOutDuration() {
+ return sTransitionOutDuration;
+ }
+
+ /*
+ * DragController.DragListener implementation
+ */
+ @Override
+ public void onDragStart(DragSource source, Object info, int dragAction) {
+ // Animate out the QSB search bar, and animate in the drop target bar
+ mDropTargetBar.animate().alpha(1f).setDuration(sTransitionInDuration);
+ if (!mIsSearchBarHidden) {
+ mQSBSearchBar.animate().alpha(0f).setDuration(sTransitionOutDuration);
+ }
+ }
+
+ @Override
+ public void onDragEnd() {
+ // Restore the QSB search bar, and animate out the drop target bar
+ mDropTargetBar.animate().alpha(0f).setDuration(sTransitionOutDuration);
+ if (!mIsSearchBarHidden) {
+ mQSBSearchBar.animate().alpha(1f).setDuration(sTransitionInDuration);
+ }
+ }
+}
diff --git a/src/com/android/launcher2/ShortcutInfo.java b/src/com/android/launcher2/ShortcutInfo.java
index 72f2d518c..c0f80aeec 100644
--- a/src/com/android/launcher2/ShortcutInfo.java
+++ b/src/com/android/launcher2/ShortcutInfo.java
@@ -148,12 +148,6 @@ class ShortcutInfo extends ItemInfo {
return "ShortcutInfo(title=" + title.toString() + ")";
}
- @Override
- void unbind() {
- super.unbind();
- }
-
-
public static void dumpShortcutInfoList(String tag, String label,
ArrayList<ShortcutInfo> list) {
Log.d(tag, label + " size=" + list.size());
diff --git a/src/com/android/launcher2/ShortcutsAdapter.java b/src/com/android/launcher2/ShortcutsAdapter.java
deleted file mode 100644
index 93c500a44..000000000
--- a/src/com/android/launcher2/ShortcutsAdapter.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * 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.launcher2;
-
-import java.util.ArrayList;
-
-import android.content.Context;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ArrayAdapter;
-import android.widget.TextView;
-
-import com.android.launcher.R;
-
-/**
- * GridView adapter to show the list of applications and shortcuts
- */
-public class ShortcutsAdapter extends ArrayAdapter<ShortcutInfo> {
- private final LayoutInflater mInflater;
- private final IconCache mIconCache;
-
- public ShortcutsAdapter(Context context, ArrayList<ShortcutInfo> apps) {
- super(context, 0, apps);
- mInflater = LayoutInflater.from(context);
- mIconCache = ((LauncherApplication)context.getApplicationContext()).getIconCache();
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- final ShortcutInfo info = getItem(position);
-
- if (convertView == null) {
- convertView = mInflater.inflate(R.layout.application_boxed, parent, false);
- }
-
- final TextView textView = (TextView) convertView;
- textView.setCompoundDrawablesWithIntrinsicBounds(null,
- new FastBitmapDrawable(info.getIcon(mIconCache)), null, null);
- textView.setText(info.title);
-
- return convertView;
- }
-}
diff --git a/src/com/android/launcher2/SmoothPagedView.java b/src/com/android/launcher2/SmoothPagedView.java
index 8b0a83502..fe763f508 100644
--- a/src/com/android/launcher2/SmoothPagedView.java
+++ b/src/com/android/launcher2/SmoothPagedView.java
@@ -87,7 +87,7 @@ public abstract class SmoothPagedView extends PagedView {
}
protected int getScrollMode() {
- return DEFAULT_MODE;
+ return X_LARGE_MODE;
}
/**
diff --git a/src/com/android/launcher2/SpringLoadedDragController.java b/src/com/android/launcher2/SpringLoadedDragController.java
index 900758118..37a94d48f 100644
--- a/src/com/android/launcher2/SpringLoadedDragController.java
+++ b/src/com/android/launcher2/SpringLoadedDragController.java
@@ -26,8 +26,6 @@ public class SpringLoadedDragController implements OnAlarmListener {
// the screen the user is currently hovering over, if any
private CellLayout mScreen;
private Launcher mLauncher;
- boolean mFinishedAnimation = false;
- boolean mWaitingToReenter = false;
public SpringLoadedDragController(Launcher launcher) {
mLauncher = launcher;
@@ -35,35 +33,25 @@ public class SpringLoadedDragController implements OnAlarmListener {
mAlarm.setOnAlarmListener(this);
}
- public void onDragEnter(CellLayout cl, boolean isSpringLoaded) {
- mScreen = cl;
- mAlarm.setAlarm(ENTER_SPRING_LOAD_HOVER_TIME);
- mFinishedAnimation = isSpringLoaded;
- mWaitingToReenter = false;
- }
-
- public void onEnterSpringLoadedMode(boolean waitToReenter) {
- mFinishedAnimation = true;
- mWaitingToReenter = waitToReenter;
+ public void cancel() {
+ mAlarm.cancelAlarm();
}
- public void onDragExit() {
- if (mScreen != null) {
- mScreen.onDragExit();
- }
- mScreen = null;
- if (mFinishedAnimation && !mWaitingToReenter) {
- mAlarm.setAlarm(EXIT_SPRING_LOAD_HOVER_TIME);
+ // Set a new alarm to expire for the screen that we are hovering over now
+ public void setAlarm(CellLayout cl) {
+ if (mScreen != cl) {
+ mAlarm.setAlarm(ENTER_SPRING_LOAD_HOVER_TIME);
}
+ mScreen = cl;
}
// this is called when our timer runs out
public void onAlarm(Alarm alarm) {
if (mScreen != null) {
- // we're currently hovering over a screen
- mLauncher.enterSpringLoadedDragMode(mScreen);
- } else {
- mLauncher.exitSpringLoadedDragMode();
+ // Snap to the screen that we are hovering over now
+ Workspace w = mLauncher.getWorkspace();
+ int page = w.indexOfChild(mScreen);
+ w.snapToPage(page);
}
}
}
diff --git a/src/com/android/launcher2/UserFolder.java b/src/com/android/launcher2/UserFolder.java
deleted file mode 100644
index 251b3f95a..000000000
--- a/src/com/android/launcher2/UserFolder.java
+++ /dev/null
@@ -1,96 +0,0 @@
-package com.android.launcher2;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.LayoutInflater;
-import android.view.View;
-
-import com.android.launcher.R;
-
-/**
- * Folder which contains applications or shortcuts chosen by the user.
- *
- */
-public class UserFolder extends Folder implements DropTarget {
- private static final String TAG = "Launcher.UserFolder";
-
- public UserFolder(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- /**
- * Creates a new UserFolder, inflated from R.layout.user_folder.
- *
- * @param context The application's context.
- *
- * @return A new UserFolder.
- */
- static UserFolder fromXml(Context context) {
- return (UserFolder) LayoutInflater.from(context).inflate(R.layout.user_folder, null);
- }
-
- public boolean acceptDrop(DragSource source, int x, int y, int xOffset, int yOffset,
- DragView dragView, Object dragInfo) {
- final ItemInfo item = (ItemInfo) dragInfo;
- final int itemType = item.itemType;
- return (itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION ||
- itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT)
- && item.container != mInfo.id;
- }
-
- public void onDrop(DragSource source, int x, int y, int xOffset, int yOffset,
- DragView dragView, Object dragInfo) {
- ShortcutInfo item;
- if (dragInfo instanceof ApplicationInfo) {
- // Came from all apps -- make a copy
- item = ((ApplicationInfo)dragInfo).makeShortcut();
- } else {
- item = (ShortcutInfo)dragInfo;
- }
- ((ShortcutsAdapter)mContent.getAdapter()).add(item);
- LauncherModel.addOrMoveItemInDatabase(mLauncher, item, mInfo.id, 0, 0, 0);
- }
-
- public void onDragEnter(DragSource source, int x, int y, int xOffset, int yOffset,
- DragView dragView, Object dragInfo) {
- }
-
- public void onDragOver(DragSource source, int x, int y, int xOffset, int yOffset,
- DragView dragView, Object dragInfo) {
- }
-
- public void onDragExit(DragSource source, int x, int y, int xOffset, int yOffset,
- DragView dragView, Object dragInfo) {
- }
-
- @Override
- public void onDropCompleted(View target, Object dragInfo, boolean success) {
- if (success) {
- ShortcutsAdapter adapter = (ShortcutsAdapter)mContent.getAdapter();
- adapter.remove(mDragItem);
- }
- }
-
- public boolean isDropEnabled() {
- return true;
- }
-
- void bind(FolderInfo info) {
- super.bind(info);
- setContentAdapter(new ShortcutsAdapter(mContext, ((UserFolderInfo) info).contents));
- }
-
- // When the folder opens, we need to refresh the GridView's selection by
- // forcing a layout
- @Override
- void onOpen() {
- super.onOpen();
- requestFocus();
- }
-
- @Override
- public DropTarget getDropTargetDelegate(DragSource source, int x, int y, int xOffset, int yOffset,
- DragView dragView, Object dragInfo) {
- return null;
- }
-}
diff --git a/src/com/android/launcher2/UserFolderInfo.java b/src/com/android/launcher2/UserFolderInfo.java
deleted file mode 100644
index 0b8841c10..000000000
--- a/src/com/android/launcher2/UserFolderInfo.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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.launcher2;
-
-import android.content.ContentValues;
-
-import java.util.ArrayList;
-
-/**
- * Represents a folder containing shortcuts or apps.
- */
-class UserFolderInfo extends FolderInfo {
- /**
- * The apps and shortcuts
- */
- ArrayList<ShortcutInfo> contents = new ArrayList<ShortcutInfo>();
-
- UserFolderInfo() {
- itemType = LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER;
- }
-
- /**
- * Add an app or shortcut
- *
- * @param item
- */
- public void add(ShortcutInfo item) {
- contents.add(item);
- }
-
- /**
- * Remove an app or shortcut. Does not change the DB.
- *
- * @param item
- */
- public void remove(ShortcutInfo item) {
- contents.remove(item);
- }
-
- @Override
- void onAddToDatabase(ContentValues values) {
- super.onAddToDatabase(values);
- values.put(LauncherSettings.Favorites.TITLE, title.toString());
- }
-}
diff --git a/src/com/android/launcher2/Utilities.java b/src/com/android/launcher2/Utilities.java
index 8ab22ebc8..04abd77aa 100644
--- a/src/com/android/launcher2/Utilities.java
+++ b/src/com/android/launcher2/Utilities.java
@@ -16,6 +16,8 @@
package com.android.launcher2;
+import java.util.Random;
+
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
@@ -66,28 +68,6 @@ final class Utilities {
sCanvas.setDrawFilter(new PaintFlagsDrawFilter(Paint.DITHER_FLAG,
Paint.FILTER_BITMAP_FLAG));
}
-
- static Bitmap centerToFit(Bitmap bitmap, int width, int height, Context context) {
- final int bitmapWidth = bitmap.getWidth();
- final int bitmapHeight = bitmap.getHeight();
-
- if (bitmapWidth < width || bitmapHeight < height) {
- int color = context.getResources().getColor(R.color.window_background);
-
- Bitmap centered = Bitmap.createBitmap(bitmapWidth < width ? width : bitmapWidth,
- bitmapHeight < height ? height : bitmapHeight, Bitmap.Config.RGB_565);
- centered.setDensity(bitmap.getDensity());
- Canvas canvas = new Canvas(centered);
- canvas.drawColor(color);
- canvas.drawBitmap(bitmap, (width - bitmapWidth) / 2.0f, (height - bitmapHeight) / 2.0f,
- null);
-
- bitmap = centered;
- }
-
- return bitmap;
- }
-
static int sColors[] = { 0xffff0000, 0xff00ff00, 0xff0000ff };
static int sColorIndex = 0;
@@ -241,7 +221,7 @@ final class Utilities {
final float density = metrics.density;
sIconWidth = sIconHeight = (int) resources.getDimension(R.dimen.app_icon_size);
- if (LauncherApplication.isScreenXLarge()) {
+ if (LauncherApplication.isScreenLarge()) {
sIconContentSize = (int) resources.getDimension(R.dimen.app_icon_content_size);
}
sIconTextureWidth = sIconTextureHeight = sIconWidth + 2;
@@ -389,4 +369,8 @@ final class Utilities {
}
return n;
}
+
+ static int generateRandomId() {
+ return new Random(System.currentTimeMillis()).nextInt(1 << 24);
+ }
}
diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java
index 05b35734b..1048fd570 100644
--- a/src/com/android/launcher2/Workspace.java
+++ b/src/com/android/launcher2/Workspace.java
@@ -16,16 +16,17 @@
package com.android.launcher2;
-import com.android.launcher.R;
-import com.android.launcher2.InstallWidgetReceiver.WidgetMimeTypeHandlerData;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
import android.animation.Animator;
+import android.animation.Animator.AnimatorListener;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
-import android.animation.Animator.AnimatorListener;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.app.AlertDialog;
import android.app.WallpaperManager;
@@ -37,7 +38,6 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
-import android.content.pm.ProviderInfo;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
@@ -45,14 +45,15 @@ import android.graphics.Camera;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
+import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Region.Op;
import android.graphics.drawable.Drawable;
-import android.net.Uri;
import android.os.IBinder;
import android.os.Parcelable;
import android.util.AttributeSet;
+import android.util.DisplayMetrics;
import android.util.Log;
import android.util.Pair;
import android.view.Display;
@@ -61,14 +62,12 @@ import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.DecelerateInterpolator;
-import android.widget.TabHost;
-import android.widget.TabWidget;
import android.widget.TextView;
import android.widget.Toast;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
+import com.android.launcher.R;
+import com.android.launcher2.FolderIcon.FolderRingAnimator;
+import com.android.launcher2.InstallWidgetReceiver.WidgetMimeTypeHandlerData;
/**
* The workspace is a wide area with a wallpaper and a finite number of pages.
@@ -81,9 +80,6 @@ public class Workspace extends SmoothPagedView
@SuppressWarnings({"UnusedDeclaration"})
private static final String TAG = "Launcher.Workspace";
- // How much the screens shrink when we enter spring loaded drag mode
- private static final float SPRING_LOADED_DRAG_SHRINK_FACTOR = 0.7f;
-
// Y rotation to apply to the workspace screens
private static final float WORKSPACE_ROTATION = 12.5f;
@@ -109,17 +105,12 @@ public class Workspace extends SmoothPagedView
private ValueAnimator mBackgroundFadeInAnimation;
private ValueAnimator mBackgroundFadeOutAnimation;
private Drawable mBackground;
- private Drawable mCustomizeTrayBackground;
boolean mDrawBackground = true;
- private boolean mDrawCustomizeTrayBackground;
private float mBackgroundAlpha = 0;
private float mOverScrollMaxBackgroundAlpha = 0.0f;
private int mOverScrollPageIndex = -1;
- private View mCustomizationDrawer;
- private View mCustomizationDrawerContent;
- private int[] mCustomizationDrawerPos = new int[2];
- private float[] mCustomizationDrawerTransformedPos = new float[2];
+
private final WallpaperManager mWallpaperManager;
private IBinder mWindowToken;
@@ -127,6 +118,7 @@ public class Workspace extends SmoothPagedView
private int mDefaultPage;
private boolean mIsDragInProcess = false;
+ private boolean mIsDraggingOverIcon = false;
/**
* CellInfo for the cell that is currently being dragged
@@ -136,7 +128,7 @@ public class Workspace extends SmoothPagedView
/**
* Target drop area calculated during last acceptDrop call.
*/
- private int[] mTargetCell = null;
+ private int[] mTargetCell = new int[2];
/**
* The CellLayout that is currently being dragged over
@@ -151,14 +143,17 @@ public class Workspace extends SmoothPagedView
// return an (x, y) value from helper functions. Do NOT use them to maintain other state.
private int[] mTempCell = new int[2];
private int[] mTempEstimate = new int[2];
- private float[] mTempOriginXY = new float[2];
+ private float[] mDragViewVisualCenter = new float[2];
private float[] mTempDragCoordinates = new float[2];
private float[] mTempTouchCoordinates = new float[2];
private float[] mTempCellLayoutCenterCoordinates = new float[2];
private float[] mTempDragBottomRightCoordinates = new float[2];
+ private float[] mTempFloatTuple = new float[2];
private Matrix mTempInverseMatrix = new Matrix();
+ private int[] mTempLocation = new int[2];
private SpringLoadedDragController mSpringLoadedDragController;
+ private float mSpringLoadedShrinkFactor;
private static final int DEFAULT_CELL_COUNT_X = 4;
private static final int DEFAULT_CELL_COUNT_Y = 4;
@@ -172,9 +167,8 @@ public class Workspace extends SmoothPagedView
private boolean mIsInUnshrinkAnimation = false;
private AnimatorListener mShrinkAnimationListener;
private AnimatorListener mUnshrinkAnimationListener;
- enum ShrinkState { TOP, SPRING_LOADED, MIDDLE, BOTTOM_HIDDEN, BOTTOM_VISIBLE };
+ enum ShrinkState { SPRING_LOADED, MIDDLE, BOTTOM_HIDDEN, BOTTOM_VISIBLE };
private ShrinkState mShrinkState;
- private boolean mWasSpringLoadedOnDragExit = false;
private boolean mWaitingToShrink = false;
private ShrinkState mWaitingToShrinkState;
private AnimatorSet mAnimator;
@@ -209,6 +203,7 @@ public class Workspace extends SmoothPagedView
WallpaperOffsetInterpolator mWallpaperOffset;
boolean mUpdateWallpaperOffsetImmediately = false;
boolean mSyncWallpaperOffsetWithScroll = true;
+ private Runnable mDelayedResizeRunnable;
// info about the last drag
private DragView mLastDragView;
@@ -217,6 +212,17 @@ public class Workspace extends SmoothPagedView
private int mLastDragXOffset;
private int mLastDragYOffset;
+ private ArrayList<FolderRingAnimator> mFolderOuterRings = new ArrayList<FolderRingAnimator>();
+
+ // Variables relating to the creation of user folders by hovering shortcuts over shortcuts
+ private static final int FOLDER_CREATION_TIMEOUT = 250;
+ private final Alarm mFolderCreationAlarm = new Alarm();
+ private FolderRingAnimator mDragFolderRingAnimator = null;
+ private View mLastDragOverView = null;
+ private boolean mCreateUserFolderOnDrop = false;
+ private int mCellWidth = -1;
+ private int mCellHeight = -1;
+
// Variables relating to touch disambiguation (scrolling workspace vs. scrolling a widget)
private float mXDown;
private float mYDown;
@@ -245,7 +251,10 @@ public class Workspace extends SmoothPagedView
super(context, attrs, defStyle);
mContentIsRefreshable = false;
- if (!LauncherApplication.isScreenXLarge()) {
+ // With workspace, data is available straight from the get-go
+ setDataIsReady();
+
+ if (!LauncherApplication.isScreenLarge()) {
mFadeInAdjacentScreens = false;
}
@@ -257,12 +266,15 @@ public class Workspace extends SmoothPagedView
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.Workspace, defStyle, 0);
- if (LauncherApplication.isScreenXLarge()) {
+ final Resources res = context.getResources();
+ if (LauncherApplication.isScreenLarge()) {
// Determine number of rows/columns dynamically
// TODO: This code currently fails on tablets with an aspect ratio < 1.3.
// Around that ratio we should make cells the same size in portrait and
// landscape
- final Resources res = context.getResources();
+ final DisplayMetrics dm = res.getDisplayMetrics();
+ float widthDp = dm.widthPixels / dm.density;
+ float heightDp = dm.heightPixels / dm.density;
TypedArray actionBarSizeTypedArray =
context.obtainStyledAttributes(new int[] { android.R.attr.actionBarSize });
@@ -282,6 +294,9 @@ public class Workspace extends SmoothPagedView
}
}
+ mSpringLoadedShrinkFactor =
+ res.getInteger(R.integer.config_workspaceSpringLoadShrinkPercentage) / 100.0f;
+
// if the value is manually specified, use that instead
cellCountX = a.getInt(R.styleable.Workspace_cellCountX, cellCountX);
cellCountY = a.getInt(R.styleable.Workspace_cellCountY, cellCountY);
@@ -312,7 +327,6 @@ public class Workspace extends SmoothPagedView
try {
final Resources res = getResources();
mBackground = res.getDrawable(R.drawable.all_apps_bg_gradient);
- mCustomizeTrayBackground = res.getDrawable(R.drawable.customize_bg_gradient);
} catch (Resources.NotFoundException e) {
// In this case, we will skip drawing background protection
}
@@ -333,9 +347,6 @@ public class Workspace extends SmoothPagedView
layout = findMatchingPageForDragOver(mLastDragView, mLastDragOriginX,
mLastDragOriginY, mLastDragXOffset, mLastDragYOffset);
}
- mSpringLoadedDragController.onEnterSpringLoadedMode(layout == null);
- } else {
- mDrawCustomizeTrayBackground = false;
}
mWallpaperOffset.setOverrideHorizontalCatchupConstant(false);
mAnimator = null;
@@ -359,65 +370,47 @@ public class Workspace extends SmoothPagedView
@Override
protected int getScrollMode() {
- if (LauncherApplication.isScreenXLarge()) {
- return SmoothPagedView.X_LARGE_MODE;
- } else {
- return SmoothPagedView.DEFAULT_MODE;
- }
+ return SmoothPagedView.X_LARGE_MODE;
}
- @Override
- public void addView(View child, int index, LayoutParams params) {
+ private void onAddView(View child) {
if (!(child instanceof CellLayout)) {
throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
}
- ((CellLayout) child).setOnInterceptTouchListener(this);
- child.setOnClickListener(this);
- child.setClickable(true);
+ CellLayout cl = ((CellLayout) child);
+ cl.setOnInterceptTouchListener(this);
+ cl.setOnClickListener(this);
+ cl.setClickable(true);
+ cl.enableHardwareLayers();
+ }
+
+ @Override
+ public void addView(View child, int index, LayoutParams params) {
+ onAddView(child);
super.addView(child, index, params);
}
@Override
public void addView(View child) {
- if (!(child instanceof CellLayout)) {
- throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
- }
- ((CellLayout) child).setOnInterceptTouchListener(this);
- child.setOnClickListener(this);
- child.setClickable(true);
+ onAddView(child);
super.addView(child);
}
@Override
public void addView(View child, int index) {
- if (!(child instanceof CellLayout)) {
- throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
- }
- ((CellLayout) child).setOnInterceptTouchListener(this);
- child.setOnClickListener(this);
- child.setClickable(true);
+ onAddView(child);
super.addView(child, index);
}
@Override
public void addView(View child, int width, int height) {
- if (!(child instanceof CellLayout)) {
- throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
- }
- ((CellLayout) child).setOnInterceptTouchListener(this);
- child.setOnClickListener(this);
- child.setClickable(true);
+ onAddView(child);
super.addView(child, width, height);
}
@Override
public void addView(View child, LayoutParams params) {
- if (!(child instanceof CellLayout)) {
- throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
- }
- ((CellLayout) child).setOnInterceptTouchListener(this);
- child.setOnClickListener(this);
- child.setClickable(true);
+ onAddView(child);
super.addView(child, params);
}
@@ -511,6 +504,10 @@ public class Workspace extends SmoothPagedView
lp.cellVSpan = spanY;
}
+ if (spanX < 0 && spanY < 0) {
+ lp.isLockedToGrid = false;
+ }
+
// Get the canonical child id to uniquely represent this view in this screen
int childId = LauncherModel.getCellLayoutChildId(-1, screen, x, y, spanX, spanY);
boolean markCellsAsOccupied = !(child instanceof Folder);
@@ -601,19 +598,6 @@ public class Workspace extends SmoothPagedView
mYDown = ev.getY();
}
- if (mIsSmall || mIsInUnshrinkAnimation) {
- if (mLauncher.isAllAppsVisible() && mShrinkState == ShrinkState.BOTTOM_HIDDEN) {
- // Intercept this event so we can show the workspace in full view
- // when it is clicked on and it is small
- AllAppsPagedView allApps = (AllAppsPagedView)
- mLauncher.findViewById(R.id.all_apps_paged_view);
- if (allApps != null) {
- allApps.onInterceptTouchEvent(ev);
- }
- return true;
- }
- return false;
- }
return super.onInterceptTouchEvent(ev);
}
@@ -651,7 +635,14 @@ public class Workspace extends SmoothPagedView
}
}
+ @Override
+ protected boolean isScrollingIndicatorEnabled() {
+ return mShrinkState != ShrinkState.SPRING_LOADED;
+ }
+
protected void onPageBeginMoving() {
+ super.onPageBeginMoving();
+
if (mNextPage != INVALID_PAGE) {
// we're snapping to a particular screen
enableChildrenCache(mCurrentPage, mNextPage);
@@ -660,17 +651,31 @@ public class Workspace extends SmoothPagedView
// swipe it either left or right (but we won't advance by more than one screen)
enableChildrenCache(mCurrentPage - 1, mCurrentPage + 1);
}
- showOutlines();
+
+ // Only show page outlines as we pan if we are on large screen
+ if (LauncherApplication.isScreenLarge()) {
+ showOutlines();
+ }
}
protected void onPageEndMoving() {
+ super.onPageEndMoving();
+
clearChildrenCache();
// Hide the outlines, as long as we're not dragging
if (!mDragController.dragging()) {
- hideOutlines();
+ // Only hide page outlines as we pan if we are on large screen
+ if (LauncherApplication.isScreenLarge()) {
+ hideOutlines();
+ }
}
mOverScrollMaxBackgroundAlpha = 0.0f;
mOverScrollPageIndex = -1;
+
+ if (mDelayedResizeRunnable != null) {
+ mDelayedResizeRunnable.run();
+ mDelayedResizeRunnable = null;
+ }
}
@Override
@@ -730,9 +735,13 @@ public class Workspace extends SmoothPagedView
protected void setWallpaperDimension() {
Display display = mLauncher.getWindowManager().getDefaultDisplay();
- int height = display.getHeight() + (int) getResources().getDimension(R.dimen.status_bar_height);
- final int maxDim = Math.max(display.getWidth(), height);
- final int minDim = Math.min(display.getWidth(), height);
+ Point displaySize = new Point();
+ display.getSize(displaySize);
+ if (LauncherApplication.isScreenLarge()) {
+ displaySize.y += (int) getResources().getDimension(R.dimen.status_bar_height);
+ }
+ final int maxDim = Math.max(displaySize.x, displaySize.y);
+ final int minDim = Math.min(displaySize.x, displaySize.y);
// We need to ensure that there is enough extra space in the wallpaper for the intended
// parallax effects
@@ -796,7 +805,8 @@ public class Workspace extends SmoothPagedView
return offset;
}
private void syncWallpaperOffsetWithScroll() {
- if (LauncherApplication.isScreenXLarge()) {
+ final boolean enableWallpaperEffects = isHardwareAccelerated();
+ if (enableWallpaperEffects) {
mWallpaperOffset.setFinalX(wallpaperOffsetForCurrentScroll());
}
}
@@ -883,7 +893,6 @@ public class Workspace extends SmoothPagedView
}
float fractionToCatchUpIn1MsVertical = mVerticalCatchupConstant;
-
fractionToCatchUpIn1MsHorizontal /= 33f;
fractionToCatchUpIn1MsVertical /= 33f;
@@ -994,12 +1003,6 @@ public class Workspace extends SmoothPagedView
private void showBackgroundGradientForAllApps() {
showBackgroundGradient();
- mDrawCustomizeTrayBackground = false;
- }
-
- private void showBackgroundGradientForCustomizeTray() {
- showBackgroundGradient();
- mDrawCustomizeTrayBackground = true;
}
private void showBackgroundGradient() {
@@ -1094,6 +1097,13 @@ public class Workspace extends SmoothPagedView
@Override
protected void screenScrolled(int screenCenter) {
+ super.screenScrolled(screenCenter);
+
+ // If the screen is not xlarge, then don't rotate the CellLayouts
+ // NOTE: If we don't update the side pages alpha, then we should not hide the side pages.
+ // see unshrink().
+ if (!LauncherApplication.isScreenLarge()) return;
+
final int halfScreenSize = getMeasuredWidth() / 2;
for (int i = 0; i < getChildCount(); i++) {
@@ -1158,12 +1168,17 @@ public class Workspace extends SmoothPagedView
}
});
}
+ }
- if (LauncherApplication.isInPlaceRotationEnabled()) {
- // When the device is rotated, the scroll position of the current screen
- // needs to be refreshed
- setCurrentPage(getCurrentPage());
+ public void showFolderAccept(FolderRingAnimator fra) {
+ mFolderOuterRings.add(fra);
+ }
+
+ public void hideFolderAccept(FolderRingAnimator fra) {
+ if (mFolderOuterRings.contains(fra)) {
+ mFolderOuterRings.remove(fra);
}
+ invalidate();
}
@Override
@@ -1173,32 +1188,71 @@ public class Workspace extends SmoothPagedView
// Draw the background gradient if necessary
if (mBackground != null && mBackgroundAlpha > 0.0f && mDrawBackground) {
int alpha = (int) (mBackgroundAlpha * 255);
- if (mDrawCustomizeTrayBackground) {
- // Find out where to offset the gradient for the customization tray content
- mCustomizationDrawer.getLocationOnScreen(mCustomizationDrawerPos);
- final Matrix m = mCustomizationDrawer.getMatrix();
- mCustomizationDrawerTransformedPos[0] = 0.0f;
- mCustomizationDrawerTransformedPos[1] = mCustomizationDrawerContent.getTop();
- m.mapPoints(mCustomizationDrawerTransformedPos);
-
- // Draw the bg glow behind the gradient
- mCustomizeTrayBackground.setAlpha(alpha);
- mCustomizeTrayBackground.setBounds(mScrollX, 0, mScrollX + getMeasuredWidth(),
- getMeasuredHeight());
- mCustomizeTrayBackground.draw(canvas);
-
- // Draw the bg gradient
- final int offset = (int) (mCustomizationDrawerPos[1] +
- mCustomizationDrawerTransformedPos[1]);
- mBackground.setAlpha(alpha);
- mBackground.setBounds(mScrollX, offset, mScrollX + getMeasuredWidth(),
- offset + getMeasuredHeight());
- mBackground.draw(canvas);
- } else {
- mBackground.setAlpha(alpha);
- mBackground.setBounds(mScrollX, 0, mScrollX + getMeasuredWidth(),
- getMeasuredHeight());
- mBackground.draw(canvas);
+ mBackground.setAlpha(alpha);
+ mBackground.setBounds(mScrollX, 0, mScrollX + getMeasuredWidth(),
+ getMeasuredHeight());
+ mBackground.draw(canvas);
+ }
+
+ // The folder outer / inner ring image(s)
+ for (int i = 0; i < mFolderOuterRings.size(); i++) {
+ View currentPage = getChildAt(getCurrentPage());
+ Matrix m = currentPage.getMatrix();
+
+ // Draw outer ring
+ FolderRingAnimator fra = mFolderOuterRings.get(i);
+ Drawable d = FolderRingAnimator.sSharedOuterRingDrawable;
+ int width = (int) (d.getIntrinsicWidth() * fra.getOuterRingScale());
+ int height = (int) (d.getIntrinsicHeight() * fra.getOuterRingScale());
+ fra.getLocation(mTempLocation);
+
+ // First we map the folder's location from window coordinates to its containing
+ // CellLayout's coordinates. Then we transform the coordinates according to the
+ // CellLayout's transform. Finally, we map this back into the coordinates of the
+ // the window (ie. Workspace).
+ int x = mTempLocation[0] + mScrollX - width / 2 - currentPage.getLeft();
+ int y = mTempLocation[1] + mScrollY - height / 2 - currentPage.getTop();
+ mTempFloatTuple[0] = x;
+ mTempFloatTuple[1] = y;
+ m.mapPoints(mTempFloatTuple);
+ x = (int) (mTempFloatTuple[0]) + currentPage.getLeft();
+ y = (int) (mTempFloatTuple[1]) + currentPage.getTop();
+
+ canvas.save();
+ canvas.translate(x, y);
+ d.setBounds(0, 0, (int) (width * currentPage.getScaleX()),
+ (int) (height * currentPage.getScaleY()));
+ d.draw(canvas);
+ canvas.restore();
+
+ // Draw inner ring
+ if (fra.mFolderIcon != null) {
+ int folderWidth = fra.mFolderIcon != null ?
+ fra.mFolderIcon.getMeasuredWidth() : mCellWidth;
+ int folderHeight = fra.mFolderIcon != null ?
+ fra.mFolderIcon.getMeasuredWidth() : mCellHeight;
+ d = FolderRingAnimator.sSharedInnerRingDrawable;
+ width = (int) (folderWidth * fra.getInnerRingScale());
+ height = (int) (folderHeight * fra.getInnerRingScale());
+
+ // First we map the folder's location from window coordinates to its containing
+ // CellLayout's coordinates. Then we transform the coordinates according to the
+ // CellLayout's transform. Finally, we map this back into the coordinates of the
+ // the window (ie. Workspace).
+ x = mTempLocation[0] + mScrollX - width / 2 - currentPage.getLeft();
+ y = mTempLocation[1] + mScrollY - height / 2 - currentPage.getTop();
+ mTempFloatTuple[0] = x;
+ mTempFloatTuple[1] = y;
+ m.mapPoints(mTempFloatTuple);
+ x = (int) (mTempFloatTuple[0]) + currentPage.getLeft();
+ y = (int) (mTempFloatTuple[1]) + currentPage.getTop();
+
+ canvas.save();
+ canvas.translate(x, y);
+ d.setBounds(0, 0, (int) (width * currentPage.getScaleX()),
+ (int) (height * currentPage.getScaleY()));
+ d.draw(canvas);
+ canvas.restore();
}
}
super.onDraw(canvas);
@@ -1271,6 +1325,14 @@ public class Workspace extends SmoothPagedView
}
@Override
+ public int getDescendantFocusability() {
+ if (mIsSmall) {
+ return ViewGroup.FOCUS_BLOCK_DESCENDANTS;
+ }
+ return super.getDescendantFocusability();
+ }
+
+ @Override
public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
if (!mLauncher.isAllAppsVisible()) {
final Folder openFolder = getOpenFolder();
@@ -1282,19 +1344,6 @@ public class Workspace extends SmoothPagedView
}
}
- @Override
- public boolean dispatchTouchEvent(MotionEvent ev) {
- if (ev.getAction() == MotionEvent.ACTION_DOWN) {
- // (In XLarge mode, the workspace is shrunken below all apps, and responds to taps
- // ie when you click on a mini-screen, it zooms back to that screen)
- if (!LauncherApplication.isScreenXLarge() && mLauncher.isAllAppsVisible()) {
- return false;
- }
- }
-
- return super.dispatchTouchEvent(ev);
- }
-
void enableChildrenCache(int fromPage, int toPage) {
if (fromPage > toPage) {
final int temp = fromPage;
@@ -1322,34 +1371,6 @@ public class Workspace extends SmoothPagedView
}
}
- @Override
- public boolean onTouchEvent(MotionEvent ev) {
- AllAppsPagedView allApps = (AllAppsPagedView)
- mLauncher.findViewById(R.id.all_apps_paged_view);
-
- if (mLauncher.isAllAppsVisible() && mShrinkState == ShrinkState.BOTTOM_HIDDEN
- && allApps != null) {
- if (ev.getAction() == MotionEvent.ACTION_UP &&
- allApps.getTouchState() == TOUCH_STATE_REST) {
-
- // Cancel any scrolling that is in progress.
- if (!mScroller.isFinished()) {
- mScroller.abortAnimation();
- }
- setCurrentPage(mCurrentPage);
-
- if (mShrinkState == ShrinkState.BOTTOM_HIDDEN) {
- mLauncher.showWorkspace(true);
- }
- allApps.onTouchEvent(ev);
- return true;
- } else {
- return allApps.onTouchEvent(ev);
- }
- }
- return super.onTouchEvent(ev);
- }
-
protected void enableChildrenLayers(boolean enable) {
for (int i = 0; i < getPageCount(); i++) {
((ViewGroup)getChildAt(i)).setChildrenLayersEnabled(enable);
@@ -1404,29 +1425,9 @@ public class Workspace extends SmoothPagedView
shrink(shrinkState, true);
}
- private int getCustomizeDrawerHeight() {
- TabHost customizationDrawer = mLauncher.getCustomizationDrawer();
- int height = customizationDrawer.getHeight();
- TabWidget tabWidget = (TabWidget)
- customizationDrawer.findViewById(com.android.internal.R.id.tabs);
- if (tabWidget.getTabCount() > 0) {
- TextView tabText = (TextView) tabWidget.getChildTabViewAt(0);
- // subtract the empty space above the tab text
- height -= ((tabWidget.getHeight() - tabText.getLineHeight())) / 2;
- }
- return height;
- }
// we use this to shrink the workspace for the all apps view and the customize view
public void shrink(ShrinkState shrinkState, boolean animated) {
- // In the launcher interaction model, we're never in the state where we're shrunken and
- // visible in the bottom of the screen, and then want to fade to being invisible.
- // After spring loaded mode ends, this method was getting called twice, the first time
- // with BOTTOM_VISIBLE (what we want) and a second time with BOTTOM_INVISIBLE (not
- // what we want). As a temporary solution, we just change the second call to BOTTOM_VISIBLE
- if (mIsSmall && mShrinkState == ShrinkState.BOTTOM_VISIBLE) {
- shrinkState = ShrinkState.BOTTOM_VISIBLE;
- }
if (mFirstLayout) {
// (mFirstLayout == "first layout has not happened yet")
// if we get a call to shrink() as part of our initialization (for example, if
@@ -1442,6 +1443,9 @@ public class Workspace extends SmoothPagedView
updateWhichPagesAcceptDrops(shrinkState);
}
+ // Hide the scrollbar
+ hideScrollingIndicator(true);
+
CellLayout currentPage = (CellLayout) getChildAt(mCurrentPage);
if (currentPage == null) {
Log.w(TAG, "currentPage is NULL! mCurrentPage " + mCurrentPage
@@ -1495,13 +1499,11 @@ public class Workspace extends SmoothPagedView
} else if (shrinkState == ShrinkState.MIDDLE) {
y = screenHeight / 2 - scaledPageHeight / 2;
finalAlpha = 1.0f;
- } else if (shrinkState == ShrinkState.TOP) {
- y = (screenHeight - getCustomizeDrawerHeight() - scaledPageHeight) / 2;
}
int duration;
if (shrinkState == ShrinkState.BOTTOM_HIDDEN || shrinkState == ShrinkState.BOTTOM_VISIBLE) {
- duration = res.getInteger(R.integer.config_allAppsWorkspaceShrinkTime);
+ duration = res.getInteger(R.integer.config_appsCustomizeWorkspaceShrinkTime);
} else {
duration = res.getInteger(R.integer.config_customizeWorkspaceShrinkTime);
}
@@ -1587,30 +1589,30 @@ public class Workspace extends SmoothPagedView
float offsetFromCenter = (wallpaperTravelHeight / (float) mWallpaperHeight) / 2f;
boolean isLandscape = display.getWidth() > display.getHeight();
- switch (shrinkState) {
- // animating in
- case TOP:
- // customize
- wallpaperOffset = 0.5f + offsetFromCenter;
- mWallpaperOffset.setVerticalCatchupConstant(isLandscape ? 0.46f : 0.44f);
- break;
- case MIDDLE:
- case SPRING_LOADED:
- wallpaperOffset = 0.5f;
- mWallpaperOffset.setVerticalCatchupConstant(isLandscape ? 0.34f : 0.32f);
- break;
- case BOTTOM_HIDDEN:
- case BOTTOM_VISIBLE:
- // allapps
- wallpaperOffset = 0.5f - offsetFromCenter;
- mWallpaperOffset.setVerticalCatchupConstant(isLandscape ? 0.34f : 0.32f);
- break;
+ final boolean enableWallpaperEffects = isHardwareAccelerated();
+ if (enableWallpaperEffects) {
+ switch (shrinkState) {
+ // animating in
+ case MIDDLE:
+ case SPRING_LOADED:
+ wallpaperOffset = 0.5f;
+ mWallpaperOffset.setVerticalCatchupConstant(isLandscape ? 0.34f : 0.32f);
+ break;
+ case BOTTOM_HIDDEN:
+ case BOTTOM_VISIBLE:
+ // allapps
+ wallpaperOffset = 0.5f - offsetFromCenter;
+ mWallpaperOffset.setVerticalCatchupConstant(isLandscape ? 0.34f : 0.32f);
+ break;
+ }
}
setLayoutScale(1.0f);
if (animated) {
- mWallpaperOffset.setHorizontalCatchupConstant(0.46f);
- mWallpaperOffset.setOverrideHorizontalCatchupConstant(true);
+ if (enableWallpaperEffects) {
+ mWallpaperOffset.setHorizontalCatchupConstant(0.46f);
+ mWallpaperOffset.setOverrideHorizontalCatchupConstant(true);
+ }
mSyncWallpaperOffsetWithScroll = false;
@@ -1622,19 +1624,19 @@ public class Workspace extends SmoothPagedView
final float oldVerticalWallpaperOffset = getVerticalWallpaperOffset();
final float newHorizontalWallpaperOffset = 0.5f;
final float newVerticalWallpaperOffset = wallpaperOffset;
- animWithInterpolator.addUpdateListener(new AnimatorUpdateListener() {
- public void onAnimationUpdate(ValueAnimator animation) {
- final float b = (Float) animation.getAnimatedValue();
- final float a = 1f - b;
+ animWithInterpolator.addUpdateListener(new LauncherAnimatorUpdateListener() {
+ public void onAnimationUpdate(float a, float b) {
if (b == 0f) {
// an optimization, and required for correct behavior.
return;
}
fastInvalidate();
- setHorizontalWallpaperOffset(
+ if (enableWallpaperEffects) {
+ setHorizontalWallpaperOffset(
a * oldHorizontalWallpaperOffset + b * newHorizontalWallpaperOffset);
- setVerticalWallpaperOffset(
+ setVerticalWallpaperOffset(
a * oldVerticalWallpaperOffset + b * newVerticalWallpaperOffset);
+ }
for (int i = 0; i < screenCount; i++) {
final CellLayout cl = (CellLayout) getChildAt(i);
cl.fastInvalidate();
@@ -1652,18 +1654,14 @@ public class Workspace extends SmoothPagedView
mAnimator.playTogether(animWithInterpolator);
mAnimator.addListener(mShrinkAnimationListener);
mAnimator.start();
- } else {
+ } else if (enableWallpaperEffects) {
setVerticalWallpaperOffset(wallpaperOffset);
setHorizontalWallpaperOffset(0.5f);
updateWallpaperOffsetImmediately();
}
setChildrenDrawnWithCacheEnabled(true);
- if (shrinkState == ShrinkState.TOP) {
- showBackgroundGradientForCustomizeTray();
- } else {
- showBackgroundGradientForAllApps();
- }
+ showBackgroundGradientForAllApps();
}
/*
@@ -1739,39 +1737,53 @@ public class Workspace extends SmoothPagedView
for (int i = 0; i < screenCount; i++) {
CellLayout cl = (CellLayout) getChildAt(i);
cl.setIsDragOccuring(isDragHappening);
- switch (state) {
- case TOP:
- cl.setIsDefaultDropTarget(i == mCurrentPage);
- case BOTTOM_HIDDEN:
- case BOTTOM_VISIBLE:
- case SPRING_LOADED:
- if (state != ShrinkState.TOP) {
+ if (state == null) {
+ // If we are not in a shrunken state, mark all cell layouts as droppable (if they
+ // have the space)
+ cl.setAcceptsDrops(cl.findCellForSpan(null, spanX, spanY));
+ } else {
+ switch (state) {
+ case BOTTOM_HIDDEN:
+ case BOTTOM_VISIBLE:
+ case SPRING_LOADED:
cl.setIsDefaultDropTarget(false);
- }
- if (!isDragHappening) {
- // even if a drag isn't happening, we don't want to show a screen as
- // accepting drops if it doesn't have at least one free cell
- spanX = 1;
- spanY = 1;
- }
- // the page accepts drops if we can find at least one empty spot
- cl.setAcceptsDrops(cl.findCellForSpan(null, spanX, spanY));
- break;
- default:
- throw new RuntimeException("Unhandled ShrinkState " + state);
+ if (!isDragHappening) {
+ // even if a drag isn't happening, we don't want to show a screen as
+ // accepting drops if it doesn't have at least one free cell
+ spanX = 1;
+ spanY = 1;
+ }
+ // the page accepts drops if we can find at least one empty spot
+ cl.setAcceptsDrops(cl.findCellForSpan(null, spanX, spanY));
+ break;
+ default:
+ throw new RuntimeException("Unhandled ShrinkState " + state);
+ }
}
}
}
/*
- *
- * We call these methods (onDragStartedWithItemSpans/onDragStartedWithItemMinSize) whenever we
- * start a drag in Launcher, regardless of whether the drag has ever entered the Workspace
- *
- * These methods mark the appropriate pages as accepting drops (which alters their visual
- * appearance).
- *
- */
+ *
+ * We call these methods (onDragStartedWithItemSpans/onDragStartedWithSize) whenever we
+ * start a drag in Launcher, regardless of whether the drag has ever entered the Workspace
+ *
+ * These methods mark the appropriate pages as accepting drops (which alters their visual
+ * appearance).
+ *
+ */
+ public void onDragStartedWithItem(View v) {
+ mIsDragInProcess = true;
+
+ final Canvas canvas = new Canvas();
+
+ // We need to add extra padding to the bitmap to make room for the glow effect
+ final int bitmapPadding = HolographicOutlineHelper.MAX_OUTER_BLUR_RADIUS;
+
+ // The outline is used to visualize where the item will land if dropped
+ mDragOutline = createDragOutline(v, canvas, bitmapPadding);
+ }
+
public void onDragStartedWithItemSpans(int spanX, int spanY, Bitmap b) {
mIsDragInProcess = true;
@@ -1781,9 +1793,11 @@ public class Workspace extends SmoothPagedView
final int bitmapPadding = HolographicOutlineHelper.MAX_OUTER_BLUR_RADIUS;
CellLayout cl = (CellLayout) getChildAt(0);
- int[] desiredSize = cl.cellSpansToSize(spanX, spanY);
+
+ int[] size = cl.cellSpansToSize(spanX, spanY);
+
// The outline is used to visualize where the item will land if dropped
- mDragOutline = createDragOutline(b, canvas, bitmapPadding, desiredSize[0], desiredSize[1]);
+ mDragOutline = createDragOutline(b, canvas, bitmapPadding, size[0], size[1]);
updateWhichPagesAcceptDropsDuringDrag(mShrinkState, spanX, spanY);
}
@@ -1794,7 +1808,7 @@ public class Workspace extends SmoothPagedView
mLastDragView = null;
// In the success case, DragController has already called onDragExit()
if (!success) {
- doDragExit();
+ doDragExit(null);
}
mIsDragInProcess = false;
updateWhichPagesAcceptDrops(mShrinkState);
@@ -1809,7 +1823,7 @@ public class Workspace extends SmoothPagedView
int newCurrentPage = indexOfChild(clThatWasClicked);
if (mIsSmall) {
if (springLoaded) {
- setLayoutScale(SPRING_LOADED_DRAG_SHRINK_FACTOR);
+ setLayoutScale(mSpringLoadedShrinkFactor);
}
scrollToNewPageWithoutMovingPages(newCurrentPage);
unshrink(true, springLoaded);
@@ -1820,19 +1834,23 @@ public class Workspace extends SmoothPagedView
public void enterSpringLoadedDragMode(CellLayout clThatWasClicked) {
mShrinkState = ShrinkState.SPRING_LOADED;
unshrink(clThatWasClicked, true);
+ mDragTargetLayout = getCurrentDropLayout();
mDragTargetLayout.onDragEnter();
+ mDragTargetLayout.setIsDragOverlapping(true);
+ showOutlines();
}
public void exitSpringLoadedDragMode(ShrinkState shrinkState) {
shrink(shrinkState);
if (mDragTargetLayout != null) {
mDragTargetLayout.onDragExit();
+ mDragTargetLayout = null;
}
}
public void exitWidgetResizeMode() {
- final CellLayout currentLayout = (CellLayout) getChildAt(getCurrentPage());
- currentLayout.getChildrenLayout().clearAllResizeFrames();
+ DragLayer dragLayer = (DragLayer) mLauncher.findViewById(R.id.drag_layer);
+ dragLayer.clearAllResizeFrames();
}
void unshrink(boolean animated) {
@@ -1845,7 +1863,7 @@ public class Workspace extends SmoothPagedView
float finalScaleFactor = 1.0f;
float finalBackgroundAlpha = 0.0f;
if (springLoaded) {
- finalScaleFactor = SPRING_LOADED_DRAG_SHRINK_FACTOR;
+ finalScaleFactor = mSpringLoadedShrinkFactor;
finalBackgroundAlpha = 1.0f;
} else {
mIsSmall = false;
@@ -1878,19 +1896,31 @@ public class Workspace extends SmoothPagedView
for (int i = 0; i < screenCount; i++) {
final CellLayout cl = (CellLayout)getChildAt(i);
- float finalAlphaValue = (i == mCurrentPage) ? 1.0f : 0.0f;
- float finalAlphaMultiplierValue =
- ((i == mCurrentPage) && (mShrinkState != ShrinkState.SPRING_LOADED)) ?
- 0.0f : 1.0f;
- float rotation = 0.0f;
-
- if (i < mCurrentPage) {
- rotation = WORKSPACE_ROTATION;
- } else if (i > mCurrentPage) {
- rotation = -WORKSPACE_ROTATION;
+ float finalAlphaValue = 0f;
+ float rotation = 0f;
+ if (LauncherApplication.isScreenLarge()) {
+ finalAlphaValue = (i == mCurrentPage) ? 1.0f : 0.0f;
+
+ if (i < mCurrentPage) {
+ rotation = WORKSPACE_ROTATION;
+ } else if (i > mCurrentPage) {
+ rotation = -WORKSPACE_ROTATION;
+ }
+ } else {
+ // Don't hide the side panes on the phone if we don't also update the side pages
+ // alpha. See screenScrolled().
+ finalAlphaValue = 1f;
}
+ float finalAlphaMultiplierValue = 1f;
+
+ float translation = 0f;
- float translation = getOffsetXForRotation(rotation, cl.getWidth(), cl.getHeight());
+ // If the screen is not xlarge, then don't rotate the CellLayouts
+ // NOTE: If we don't update the side pages alpha, then we should not hide the side
+ // pages. see unshrink().
+ if (LauncherApplication.isScreenLarge()) {
+ translation = getOffsetXForRotation(rotation, cl.getWidth(), cl.getHeight());
+ }
oldAlphas[i] = cl.getAlpha();
newAlphas[i] = finalAlphaValue;
@@ -1924,56 +1954,54 @@ public class Workspace extends SmoothPagedView
}
Display display = mLauncher.getWindowManager().getDefaultDisplay();
boolean isLandscape = display.getWidth() > display.getHeight();
- switch (mShrinkState) {
- // animating out
- case TOP:
- // customize
- if (animated) {
- mWallpaperOffset.setHorizontalCatchupConstant(isLandscape ? 0.65f : 0.62f);
- mWallpaperOffset.setVerticalCatchupConstant(isLandscape ? 0.65f : 0.62f);
- mWallpaperOffset.setOverrideHorizontalCatchupConstant(true);
- }
- break;
- case MIDDLE:
- case SPRING_LOADED:
- if (animated) {
- mWallpaperOffset.setHorizontalCatchupConstant(isLandscape ? 0.49f : 0.46f);
- mWallpaperOffset.setVerticalCatchupConstant(isLandscape ? 0.49f : 0.46f);
- mWallpaperOffset.setOverrideHorizontalCatchupConstant(true);
- }
- break;
- case BOTTOM_HIDDEN:
- case BOTTOM_VISIBLE:
- // all apps
- if (animated) {
- mWallpaperOffset.setHorizontalCatchupConstant(isLandscape ? 0.65f : 0.65f);
- mWallpaperOffset.setVerticalCatchupConstant(isLandscape ? 0.65f : 0.65f);
- mWallpaperOffset.setOverrideHorizontalCatchupConstant(true);
- }
- break;
+ final boolean enableWallpaperEffects = isHardwareAccelerated();
+ if (enableWallpaperEffects) {
+ switch (mShrinkState) {
+ // animating out
+ case MIDDLE:
+ case SPRING_LOADED:
+ if (animated) {
+ mWallpaperOffset.setHorizontalCatchupConstant(isLandscape ? 0.49f : 0.46f);
+ mWallpaperOffset.setVerticalCatchupConstant(isLandscape ? 0.49f : 0.46f);
+ mWallpaperOffset.setOverrideHorizontalCatchupConstant(true);
+ }
+ break;
+ case BOTTOM_HIDDEN:
+ case BOTTOM_VISIBLE:
+ // all apps
+ if (animated) {
+ mWallpaperOffset.setHorizontalCatchupConstant(isLandscape ? 0.65f : 0.65f);
+ mWallpaperOffset.setVerticalCatchupConstant(isLandscape ? 0.65f : 0.65f);
+ mWallpaperOffset.setOverrideHorizontalCatchupConstant(true);
+ }
+ break;
+ }
}
if (animated) {
ValueAnimator animWithInterpolator =
ValueAnimator.ofFloat(0f, 1f).setDuration(duration);
animWithInterpolator.setInterpolator(mZoomInInterpolator);
- final float oldHorizontalWallpaperOffset = getHorizontalWallpaperOffset();
- final float oldVerticalWallpaperOffset = getVerticalWallpaperOffset();
- final float newHorizontalWallpaperOffset = wallpaperOffsetForCurrentScroll();
- final float newVerticalWallpaperOffset = 0.5f;
- animWithInterpolator.addUpdateListener(new AnimatorUpdateListener() {
- public void onAnimationUpdate(ValueAnimator animation) {
- final float b = (Float) animation.getAnimatedValue();
- final float a = 1f - b;
+ final float oldHorizontalWallpaperOffset = enableWallpaperEffects ?
+ getHorizontalWallpaperOffset() : 0;
+ final float oldVerticalWallpaperOffset = enableWallpaperEffects ?
+ getVerticalWallpaperOffset() : 0;
+ final float newHorizontalWallpaperOffset = enableWallpaperEffects ?
+ wallpaperOffsetForCurrentScroll() : 0;
+ final float newVerticalWallpaperOffset = enableWallpaperEffects ? 0.5f : 0;
+ animWithInterpolator.addUpdateListener(new LauncherAnimatorUpdateListener() {
+ public void onAnimationUpdate(float a, float b) {
if (b == 0f) {
// an optimization, but not required
return;
}
fastInvalidate();
- setHorizontalWallpaperOffset(
- a * oldHorizontalWallpaperOffset + b * newHorizontalWallpaperOffset);
- setVerticalWallpaperOffset(
- a * oldVerticalWallpaperOffset + b * newVerticalWallpaperOffset);
+ if (enableWallpaperEffects) {
+ setHorizontalWallpaperOffset(a * oldHorizontalWallpaperOffset
+ + b * newHorizontalWallpaperOffset);
+ setVerticalWallpaperOffset(a * oldVerticalWallpaperOffset
+ + b * newVerticalWallpaperOffset);
+ }
for (int i = 0; i < screenCount; i++) {
final CellLayout cl = (CellLayout) getChildAt(i);
cl.fastInvalidate();
@@ -1995,11 +2023,9 @@ public class Workspace extends SmoothPagedView
ValueAnimator rotationAnim =
ValueAnimator.ofFloat(0f, 1f).setDuration(duration);
rotationAnim.setInterpolator(new DecelerateInterpolator(2.0f));
- rotationAnim.addUpdateListener(new AnimatorUpdateListener() {
- public void onAnimationUpdate(ValueAnimator animation) {
+ rotationAnim.addUpdateListener(new LauncherAnimatorUpdateListener() {
+ public void onAnimationUpdate(float a, float b) {
// don't invalidate workspace because we did it above
- final float b = (Float) animation.getAnimatedValue();
- final float a = 1f - b;
if (b == 0f) {
// an optimization, but not required
return;
@@ -2017,9 +2043,11 @@ public class Workspace extends SmoothPagedView
mAnimator.addListener(mUnshrinkAnimationListener);
mAnimator.start();
} else {
- setHorizontalWallpaperOffset(wallpaperOffsetForCurrentScroll());
- setVerticalWallpaperOffset(0.5f);
- updateWallpaperOffsetImmediately();
+ if (enableWallpaperEffects) {
+ setHorizontalWallpaperOffset(wallpaperOffsetForCurrentScroll());
+ setVerticalWallpaperOffset(0.5f);
+ updateWallpaperOffsetImmediately();
+ }
}
}
@@ -2040,7 +2068,8 @@ public class Workspace extends SmoothPagedView
v.getDrawingRect(clipRect);
// For a TextView, adjust the clip rect so that we don't include the text label
- if (v instanceof BubbleTextView) {
+ if (v instanceof FolderIcon) {
+ } else if (v instanceof BubbleTextView) {
final BubbleTextView tv = (BubbleTextView) v;
clipRect.bottom = tv.getExtendedPaddingTop() - (int) BubbleTextView.PADDING_V +
tv.getLayout().getLineTop(0);
@@ -2171,12 +2200,24 @@ public class Workspace extends SmoothPagedView
final int bmpWidth = b.getWidth();
final int bmpHeight = b.getHeight();
+
child.getLocationOnScreen(mTempXY);
final int screenX = (int) mTempXY[0] + (child.getWidth() - bmpWidth) / 2;
final int screenY = (int) mTempXY[1] + (child.getHeight() - bmpHeight) / 2;
+
+ Rect dragRect = null;
+ if ((child instanceof BubbleTextView) && !(child instanceof FolderIcon)) {
+ int iconSize = getResources().getDimensionPixelSize(R.dimen.app_icon_size);
+ int top = child.getPaddingTop();
+ int left = (bmpWidth - iconSize) / 2;
+ int right = left + iconSize;
+ int bottom = top + iconSize;
+ dragRect = new Rect(left, top, right, bottom);
+ }
+
mLauncher.lockScreenOrientation();
- mDragController.startDrag(
- b, screenX, screenY, this, child.getTag(), DragController.DRAG_ACTION_MOVE);
+ mDragController.startDrag(b, screenX, screenY, this, child.getTag(),
+ DragController.DRAG_ACTION_MOVE, dragRect);
b.recycle();
}
@@ -2198,34 +2239,22 @@ public class Workspace extends SmoothPagedView
final CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
// Based on the position of the drag view, find the top left of the original view
- int viewX = dragViewX + (dragView.getWidth() - child.getWidth()) / 2;
- int viewY = dragViewY + (dragView.getHeight() - child.getHeight()) / 2;
- viewX += getResources().getInteger(R.integer.config_dragViewOffsetX);
- viewY += getResources().getInteger(R.integer.config_dragViewOffsetY);
+ int viewX = dragViewX + (dragView.getWidth() - child.getMeasuredWidth()) / 2;
+ int viewY = dragViewY + (dragView.getHeight() - child.getMeasuredHeight()) / 2;
+
+ CellLayout layout = (CellLayout) parent;
// Set its old pos (in the new parent's coordinates); it will be animated
// in animateViewIntoPosition after the next layout pass
- lp.oldX = viewX - (parent.getLeft() - mScrollX);
- lp.oldY = viewY - (parent.getTop() - mScrollY);
+ lp.oldX = viewX - (layout.getLeft() + layout.getLeftPadding() - mScrollX);
+ lp.oldY = viewY - (layout.getTop() + layout.getTopPadding() - mScrollY);
}
- /*
- * We should be careful that this method cannot result in any synchronous requestLayout()
- * calls, as it is called from onLayout().
- */
- public void animateViewIntoPosition(final View view) {
- final CellLayout parent = (CellLayout) view.getParent().getParent();
- final CellLayout.LayoutParams lp = (CellLayout.LayoutParams) view.getLayoutParams();
-
- // Convert the animation params to be relative to the Workspace, not the CellLayout
- final int fromX = lp.oldX + parent.getLeft();
- final int fromY = lp.oldY + parent.getTop();
-
- final int dx = lp.x - lp.oldX;
- final int dy = lp.y - lp.oldY;
+ public void animateViewIntoPosition(final View view, final int fromX, final int fromY,
+ final int dX, final int dY, final Runnable animationEndRunnable) {
// Calculate the duration of the animation based on the object's distance
- final float dist = (float) Math.sqrt(dx*dx + dy*dy);
+ final float dist = (float) Math.sqrt(dX*dX + dY*dY);
final Resources res = getResources();
final float maxDist = (float) res.getInteger(R.integer.config_dropAnimMaxDist);
int duration = res.getInteger(R.integer.config_dropAnimMaxDuration);
@@ -2247,10 +2276,7 @@ public class Workspace extends SmoothPagedView
}
public void onAnimationEnd(Animator animation) {
- if (mDropView != null) {
- mDropView.setVisibility(View.VISIBLE);
- mDropView = null;
- }
+ animationEndRunnable.run();
}
});
@@ -2264,8 +2290,8 @@ public class Workspace extends SmoothPagedView
invalidate(mDropViewPos[0], mDropViewPos[1],
mDropViewPos[0] + view.getWidth(), mDropViewPos[1] + view.getHeight());
- mDropViewPos[0] = fromX + (int) (percent * dx + 0.5f);
- mDropViewPos[1] = fromY + (int) (percent * dy + 0.5f);
+ mDropViewPos[0] = fromX + (int) (percent * dX + 0.5f);
+ mDropViewPos[1] = fromY + (int) (percent * dY + 0.5f);
invalidate(mDropViewPos[0], mDropViewPos[1],
mDropViewPos[0] + view.getWidth(), mDropViewPos[1] + view.getHeight());
}
@@ -2274,14 +2300,39 @@ public class Workspace extends SmoothPagedView
mDropAnim.start();
}
+ /*
+ * We should be careful that this method cannot result in any synchronous requestLayout()
+ * calls, as it is called from onLayout().
+ */
+ public void animateViewIntoPosition(final View view) {
+ final CellLayout parent = (CellLayout) view.getParent().getParent();
+ final CellLayout.LayoutParams lp = (CellLayout.LayoutParams) view.getLayoutParams();
+
+ // Convert the animation params to be relative to the Workspace, not the CellLayout
+ final int fromX = lp.oldX + parent.getLeft() + parent.getLeftPadding();
+ final int fromY = lp.oldY + parent.getTop() + parent.getTopPadding();
+
+ final int dx = lp.x - lp.oldX;
+ final int dy = lp.y - lp.oldY;
+
+ Runnable animationEndRunnable = new Runnable() {
+ public void run() {
+ if (mDropView != null) {
+ mDropView.setVisibility(View.VISIBLE);
+ mDropView = null;
+ }
+ }
+ };
+ animateViewIntoPosition(view, fromX, fromY, dx, dy, animationEndRunnable);
+ }
+
/**
* {@inheritDoc}
*/
- public boolean acceptDrop(DragSource source, int x, int y,
- int xOffset, int yOffset, DragView dragView, Object dragInfo) {
+ public boolean acceptDrop(DragObject d) {
// If it's an external drop (e.g. from All Apps), check if it should be accepted
- if (source != this) {
+ if (d.dragSource != this) {
// Don't accept the drop if we're not over a screen at time of drop
if (mDragTargetLayout == null || !mDragTargetLayout.getAcceptsDrops()) {
return false;
@@ -2302,24 +2353,85 @@ public class Workspace extends SmoothPagedView
return true;
}
- public void onDrop(DragSource source, int x, int y, int xOffset, int yOffset,
- DragView dragView, Object dragInfo) {
- boolean largeOrSpringLoaded = !mIsSmall || mWasSpringLoadedOnDragExit;
- int originX = largeOrSpringLoaded ? x - xOffset : x - xOffset + dragView.getWidth() / 2;
- int originY = largeOrSpringLoaded ? y - yOffset : y - yOffset + dragView.getHeight() / 2;
+ boolean willCreateUserFolder(ItemInfo info, View v, int[] targetCell) {
+ boolean hasntMoved = mDragInfo != null
+ && (mDragInfo.cellX == targetCell[0] && mDragInfo.cellY == targetCell[1]);
- if (mIsSmall || mIsInUnshrinkAnimation) {
- // get originX and originY in the local coordinate system of the screen
- mTempOriginXY[0] = originX;
- mTempOriginXY[1] = originY;
- mapPointFromSelfToChild(mDragTargetLayout, mTempOriginXY);
- originX = (int)mTempOriginXY[0];
- originY = (int)mTempOriginXY[1];
- if (!largeOrSpringLoaded) {
- originX -= mDragTargetLayout.getCellWidth() / 2;
- originY -= mDragTargetLayout.getCellHeight() / 2;
+ if (v == null || hasntMoved) return false;
+
+ boolean aboveShortcut = (v.getTag() instanceof ShortcutInfo);
+ boolean willBecomeShortcut =
+ (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION ||
+ info.itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT);
+
+ return (aboveShortcut && willBecomeShortcut);
+ }
+
+ boolean createUserFolderIfNecessary(View newView, CellLayout target,
+ int[] targetCell, boolean external) {
+ View v = target.getChildAt(targetCell[0], targetCell[1]);
+ boolean hasntMoved = mDragInfo != null
+ && (mDragInfo.cellX == targetCell[0] && mDragInfo.cellY == targetCell[1]);
+
+ if (v == null || hasntMoved || !mCreateUserFolderOnDrop) return false;
+ mCreateUserFolderOnDrop = false;
+ final int screen = (targetCell == null) ? mDragInfo.screen : indexOfChild(target);
+
+ boolean aboveShortcut = (v.getTag() instanceof ShortcutInfo);
+ boolean willBecomeShortcut = (newView.getTag() instanceof ShortcutInfo);
+
+ if (aboveShortcut && willBecomeShortcut) {
+ ShortcutInfo sourceInfo = (ShortcutInfo) newView.getTag();
+ ShortcutInfo destInfo = (ShortcutInfo) v.getTag();
+ // if the drag started here, we need to remove it from the workspace
+ if (!external) {
+ int fromScreen = mDragInfo.screen;
+ CellLayout sourceLayout = (CellLayout) getChildAt(fromScreen);
+ sourceLayout.removeView(newView);
+ }
+
+ target.removeView(v);
+ FolderIcon fi = mLauncher.addFolder(screen, targetCell[0], targetCell[1]);
+ destInfo.cellX = -1;
+ destInfo.cellY = -1;
+ sourceInfo.cellX = -1;
+ sourceInfo.cellY = -1;
+ fi.addItem(destInfo);
+ fi.addItem(sourceInfo);
+ return true;
+ }
+ return false;
+ }
+
+ boolean addToExistingFolderIfNecessary(View newView, CellLayout target, int[] tagetCell,
+ Object dragInfo, boolean external) {
+ View dropOverView = target.getChildAt(tagetCell[0], tagetCell[1]);
+ if (dropOverView instanceof FolderIcon) {
+ FolderIcon fi = (FolderIcon) dropOverView;
+ if (fi.acceptDrop(dragInfo)) {
+ fi.onDrop(dragInfo);
+
+ // if the drag started here, we need to remove it from the workspace
+ if (!external) {
+ int fromScreen = mDragInfo.screen;
+ CellLayout sourceLayout = (CellLayout) getChildAt(fromScreen);
+ sourceLayout.removeView(newView);
+ }
+ return true;
}
}
+ return false;
+ }
+
+ public void onDrop(DragObject d) {
+
+ mDragViewVisualCenter = getDragViewVisualCenter(d.x, d.y, d.xOffset, d.yOffset, d.dragView,
+ mDragViewVisualCenter);
+
+ // We want the point to be mapped to the dragTarget.
+ if (mDragTargetLayout != null) {
+ mapPointFromSelfToChild(mDragTargetLayout, mDragViewVisualCenter, null);
+ }
// When you are in customization mode and drag to a particular screen, make that the
// new current/default screen, so any subsequent taps add items to that screen
@@ -2329,51 +2441,59 @@ public class Workspace extends SmoothPagedView
scrollToNewPageWithoutMovingPages(dragTargetIndex);
}
}
+ CellLayout dropTargetLayout = mDragTargetLayout;
- if (source != this) {
- final int[] touchXY = new int[] { originX, originY };
- if ((mIsSmall || mIsInUnshrinkAnimation) && !mLauncher.isAllAppsVisible()) {
- // When the workspace is shrunk and the drop comes from customize, don't actually
- // add the item to the screen -- customize will do this itself
- ((ItemInfo) dragInfo).dropPos = touchXY;
- return;
- }
- onDropExternal(touchXY, dragInfo, mDragTargetLayout, false);
+ if (d.dragSource != this) {
+ final int[] touchXY = new int[] { (int) mDragViewVisualCenter[0],
+ (int) mDragViewVisualCenter[1] };
+ onDropExternal(touchXY, d.dragInfo, dropTargetLayout, false, d.dragView);
} else if (mDragInfo != null) {
final View cell = mDragInfo.cell;
- CellLayout dropTargetLayout = mDragTargetLayout;
-
- // Handle the case where the user drops when in the scroll area.
- // This is treated as a drop on the adjacent page.
- if (dropTargetLayout == null && mInScrollArea) {
- if (mPendingScrollDirection == DragController.SCROLL_LEFT) {
- dropTargetLayout = (CellLayout) getChildAt(mCurrentPage - 1);
- } else if (mPendingScrollDirection == DragController.SCROLL_RIGHT) {
- dropTargetLayout = (CellLayout) getChildAt(mCurrentPage + 1);
- }
- }
if (dropTargetLayout != null) {
// Move internally
- mTargetCell = findNearestVacantArea(originX, originY,
- mDragInfo.spanX, mDragInfo.spanY, cell, dropTargetLayout,
- mTargetCell);
-
- final int screen = (mTargetCell == null) ?
+ final int screen = (mTargetCell[0] < 0) ?
mDragInfo.screen : indexOfChild(dropTargetLayout);
- if (screen != mCurrentPage) {
+ int spanX = mDragInfo != null ? mDragInfo.spanX : 1;
+ int spanY = mDragInfo != null ? mDragInfo.spanY : 1;
+ // First we find the cell nearest to point at which the item is
+ // dropped, without any consideration to whether there is an item there.
+ mTargetCell = findNearestArea((int) mDragViewVisualCenter[0], (int)
+ mDragViewVisualCenter[1], spanX, spanY, dropTargetLayout, mTargetCell);
+ // If the item being dropped is a shortcut and the nearest drop
+ // cell also contains a shortcut, then create a folder with the two shortcuts.
+ boolean dropInscrollArea = mCurrentPage != screen;
+
+ if (!dropInscrollArea && createUserFolderIfNecessary(cell, dropTargetLayout,
+ mTargetCell, false)) {
+ return;
+ }
+
+ if (addToExistingFolderIfNecessary(cell, dropTargetLayout, mTargetCell,
+ d.dragInfo, false)) {
+ return;
+ }
+
+ // Aside from the special case where we're dropping a shortcut onto a shortcut,
+ // we need to find the nearest cell location that is vacant
+ mTargetCell = findNearestVacantArea((int) mDragViewVisualCenter[0],
+ (int) mDragViewVisualCenter[1], mDragInfo.spanX, mDragInfo.spanY, cell,
+ dropTargetLayout, mTargetCell);
+
+ if (dropInscrollArea && mShrinkState != ShrinkState.SPRING_LOADED) {
snapToPage(screen);
}
- if (mTargetCell != null) {
+ if (mTargetCell[0] >= 0 && mTargetCell[1] >= 0) {
if (screen != mDragInfo.screen) {
// Reparent the view
((CellLayout) getChildAt(mDragInfo.screen)).removeView(cell);
- addInScreen(cell, screen, mTargetCell[0], mTargetCell[1],
- mDragInfo.spanX, mDragInfo.spanY);
+ addInScreen(cell, screen, mTargetCell[0], mTargetCell[1], mDragInfo.spanX,
+ mDragInfo.spanY);
}
+
// update the item's position after drop
final ItemInfo info = (ItemInfo) cell.getTag();
CellLayout.LayoutParams lp = (CellLayout.LayoutParams) cell.getLayoutParams();
@@ -2384,7 +2504,6 @@ public class Workspace extends SmoothPagedView
mTargetCell[0], mTargetCell[1], mDragInfo.spanX, mDragInfo.spanY));
if (cell instanceof LauncherAppWidgetHostView) {
- final CellLayoutChildren children = dropTargetLayout.getChildrenLayout();
final CellLayout cellLayout = dropTargetLayout;
// We post this call so that the widget has a chance to be placed
// in its final location
@@ -2392,10 +2511,20 @@ public class Workspace extends SmoothPagedView
final LauncherAppWidgetHostView hostView = (LauncherAppWidgetHostView) cell;
AppWidgetProviderInfo pinfo = hostView.getAppWidgetInfo();
if (pinfo.resizeMode != AppWidgetProviderInfo.RESIZE_NONE) {
+ final Runnable resizeRunnable = new Runnable() {
+ public void run() {
+ DragLayer dragLayer =
+ (DragLayer) mLauncher.findViewById(R.id.drag_layer);
+ dragLayer.addResizeFrame(info, hostView, cellLayout);
+ }
+ };
post(new Runnable() {
public void run() {
- children.addResizeFrame(info, hostView,
- cellLayout);
+ if (!isPageMoving()) {
+ resizeRunnable.run();
+ } else {
+ mDelayedResizeRunnable = resizeRunnable;
+ }
}
});
}
@@ -2409,17 +2538,35 @@ public class Workspace extends SmoothPagedView
final CellLayout parent = (CellLayout) cell.getParent().getParent();
+ int loc[] = new int[2];
+ getViewLocationRelativeToSelf(d.dragView, loc);
+
// Prepare it to be animated into its new position
// This must be called after the view has been re-parented
- setPositionForDropAnimation(dragView, originX, originY, parent, cell);
- boolean animateDrop = !mWasSpringLoadedOnDragExit;
- parent.onDropChild(cell, animateDrop);
+ setPositionForDropAnimation(d.dragView, loc[0], loc[1], parent, cell);
+ parent.onDropChild(cell, true);
}
}
- public void onDragEnter(DragSource source, int x, int y, int xOffset,
- int yOffset, DragView dragView, Object dragInfo) {
- mDragTargetLayout = null; // Reset the drag state
+ public void getViewLocationRelativeToSelf(View v, int[] location) {
+ getLocationOnScreen(location);
+ int x = location[0];
+ int y = location[1];
+
+ v.getLocationOnScreen(location);
+ int vX = location[0];
+ int vY = location[1];
+
+ location[0] = vX - x;
+ location[1] = vY - y;
+ }
+
+ public void onDragEnter(DragObject d) {
+ mLastDragOverView = null;
+ if (mDragTargetLayout != null) {
+ mDragTargetLayout.onDragExit();
+ mDragTargetLayout = null; // Reset the drag state
+ }
if (!mIsSmall) {
mDragTargetLayout = getCurrentDropLayout();
@@ -2428,44 +2575,7 @@ public class Workspace extends SmoothPagedView
}
}
- public DropTarget getDropTargetDelegate(DragSource source, int x, int y,
- int xOffset, int yOffset, DragView dragView, Object dragInfo) {
-
- if (mIsSmall || mIsInUnshrinkAnimation) {
- // If we're shrunken, don't let anyone drag on folders/etc that are on the mini-screens
- return null;
- }
- // We may need to delegate the drag to a child view. If a 1x1 item
- // would land in a cell occupied by a DragTarget (e.g. a Folder),
- // then drag events should be handled by that child.
-
- ItemInfo item = (ItemInfo) dragInfo;
- CellLayout currentLayout = getCurrentDropLayout();
-
- int dragPointX, dragPointY;
- if (item.spanX == 1 && item.spanY == 1) {
- // For a 1x1, calculate the drop cell exactly as in onDragOver
- dragPointX = x - xOffset;
- dragPointY = y - yOffset;
- } else {
- // Otherwise, use the exact drag coordinates
- dragPointX = x;
- dragPointY = y;
- }
- dragPointX += mScrollX - currentLayout.getLeft();
- dragPointY += mScrollY - currentLayout.getTop();
-
- // If we are dragging over a cell that contains a DropTarget that will
- // accept the drop, delegate to that DropTarget.
- final int[] cellXY = mTempCell;
- currentLayout.estimateDropCell(dragPointX, dragPointY, item.spanX, item.spanY, cellXY);
- View child = currentLayout.getChildAt(cellXY[0], cellXY[1]);
- if (child instanceof DropTarget) {
- DropTarget target = (DropTarget)child;
- if (target.acceptDrop(source, x, y, xOffset, yOffset, dragView, dragInfo)) {
- return target;
- }
- }
+ public DropTarget getDropTargetDelegate(DragObject d) {
return null;
}
@@ -2645,11 +2755,11 @@ public class Workspace extends SmoothPagedView
xy[1] -= (mScrollY - v.getTop());
}
- static private float squaredDistance(float[] point1, float[] point2) {
+ static private float squaredDistance(float[] point1, float[] point2) {
float distanceX = point1[0] - point2[0];
float distanceY = point2[1] - point2[1];
return distanceX * distanceX + distanceY * distanceY;
- }
+ }
/*
*
@@ -2747,38 +2857,75 @@ public class Workspace extends SmoothPagedView
return bestMatchingScreen;
}
- public void onDragOver(DragSource source, int x, int y, int xOffset, int yOffset,
- DragView dragView, Object dragInfo) {
+ // This is used to compute the visual center of the dragView. This point is then
+ // used to visualize drop locations and determine where to drop an item. The idea is that
+ // the visual center represents the user's interpretation of where the item is, and hence
+ // is the appropriate point to use when determining drop location.
+ private float[] getDragViewVisualCenter(int x, int y, int xOffset, int yOffset,
+ DragView dragView, float[] recycle) {
+ float res[];
+ if (recycle == null) {
+ res = new float[2];
+ } else {
+ res = recycle;
+ }
+
+ // First off, the drag view has been shifted in a way that is not represented in the
+ // x and y values or the x/yOffsets. Here we account for that shift.
+ x += getResources().getDimensionPixelSize(R.dimen.dragViewOffsetX);
+ y += getResources().getDimensionPixelSize(R.dimen.dragViewOffsetY);
+
+ // These represent the visual top and left of drag view if a dragRect was provided.
+ // If a dragRect was not provided, then they correspond to the actual view left and
+ // top, as the dragRect is in that case taken to be the entire dragView.
+ // R.dimen.dragViewOffsetY.
+ int left = x - xOffset;
+ int top = y - yOffset;
+
+ // In order to find the visual center, we shift by half the dragRect
+ res[0] = left + dragView.getDragRegion().width() / 2;
+ res[1] = top + dragView.getDragRegion().height() / 2;
+
+ return res;
+ }
+
+ public void onDragOver(DragObject d) {
// When touch is inside the scroll area, skip dragOver actions for the current screen
if (!mInScrollArea) {
CellLayout layout;
- int originX = x - xOffset;
- int originY = y - yOffset;
+ int left = d.x - d.xOffset;
+ int top = d.y - d.yOffset;
+
+ mDragViewVisualCenter = getDragViewVisualCenter(d.x, d.y, d.xOffset, d.yOffset,
+ d.dragView, mDragViewVisualCenter);
+
boolean shrunken = mIsSmall || mIsInUnshrinkAnimation;
if (shrunken) {
- mLastDragView = dragView;
- mLastDragOriginX = originX;
- mLastDragOriginY = originY;
- mLastDragXOffset = xOffset;
- mLastDragYOffset = yOffset;
- layout = findMatchingPageForDragOver(dragView, originX, originY, xOffset, yOffset);
-
- if (layout != mDragTargetLayout) {
+ mLastDragView = d.dragView;
+ mLastDragOriginX = left;
+ mLastDragOriginY = top;
+ mLastDragXOffset = d.xOffset;
+ mLastDragYOffset = d.yOffset;
+ layout = findMatchingPageForDragOver(d.dragView, left, top, d.xOffset, d.yOffset);
+
+ if (layout != null && layout != mDragTargetLayout) {
if (mDragTargetLayout != null) {
mDragTargetLayout.setIsDragOverlapping(false);
- mSpringLoadedDragController.onDragExit();
+ mDragTargetLayout.clearDragOutlines();
}
mDragTargetLayout = layout;
+
// In spring-loaded mode, we still want the user to be able to hover over a
- // full screen (which is traditionally set to not accept drops) if they want to
- // get to pages beyond the screen that is full.
+ // full screen (which is traditionally set to not accept drops) if they want
+ // to get to pages beyond the screen that is full.
+ boolean isInSpringLoadedMode = (mShrinkState == ShrinkState.SPRING_LOADED);
boolean allowDragOver = (mDragTargetLayout != null) &&
- (mDragTargetLayout.getAcceptsDrops() ||
- (mShrinkState == ShrinkState.SPRING_LOADED));
+ (mDragTargetLayout.getAcceptsDrops() || isInSpringLoadedMode);
if (allowDragOver) {
+ if (isInSpringLoadedMode) {
+ mSpringLoadedDragController.setAlarm(mDragTargetLayout);
+ }
mDragTargetLayout.setIsDragOverlapping(true);
- mSpringLoadedDragController.onDragEnter(
- mDragTargetLayout, mShrinkState == ShrinkState.SPRING_LOADED);
}
}
} else {
@@ -2794,70 +2941,128 @@ public class Workspace extends SmoothPagedView
if (!shrunken || mShrinkState == ShrinkState.SPRING_LOADED) {
layout = getCurrentDropLayout();
- final ItemInfo item = (ItemInfo)dragInfo;
- if (dragInfo instanceof LauncherAppWidgetInfo) {
- LauncherAppWidgetInfo widgetInfo = (LauncherAppWidgetInfo)dragInfo;
+ final ItemInfo item = (ItemInfo) d.dragInfo;
+ if (d.dragInfo instanceof LauncherAppWidgetInfo) {
+ LauncherAppWidgetInfo widgetInfo = (LauncherAppWidgetInfo) d.dragInfo;
if (widgetInfo.spanX == -1) {
// Calculate the grid spans needed to fit this widget
- int[] spans = layout.rectToCell(
- widgetInfo.minWidth, widgetInfo.minHeight, null);
+ int[] spans = layout.rectToCell(widgetInfo.minWidth,
+ widgetInfo.minHeight, null);
item.spanX = spans[0];
item.spanY = spans[1];
}
}
- if (source instanceof AllAppsPagedView) {
- // This is a hack to fix the point used to determine which cell an icon from
- // the all apps screen is over
- if (item != null && item.spanX == 1 && layout != null) {
- int dragRegionLeft = (dragView.getWidth() - layout.getCellWidth()) / 2;
-
- originX += dragRegionLeft - dragView.getDragRegionLeft();
- if (dragView.getDragRegionWidth() != layout.getCellWidth()) {
- dragView.setDragRegion(dragView.getDragRegionLeft(),
- dragView.getDragRegionTop(),
- layout.getCellWidth(),
- dragView.getDragRegionHeight());
+ if (mDragTargetLayout != null) {
+ final View child = (mDragInfo == null) ? null : mDragInfo.cell;
+ // We want the point to be mapped to the dragTarget.
+ mapPointFromSelfToChild(mDragTargetLayout, mDragViewVisualCenter, null);
+ ItemInfo info = (ItemInfo) d.dragInfo;
+
+ mTargetCell = findNearestArea((int) mDragViewVisualCenter[0],
+ (int) mDragViewVisualCenter[1], 1, 1, mDragTargetLayout, mTargetCell);
+ final View dragOverView = mDragTargetLayout.getChildAt(mTargetCell[0],
+ mTargetCell[1]);
+
+ boolean userFolderPending = willCreateUserFolder(info, dragOverView,
+ mTargetCell);
+ boolean isOverFolder = dragOverView instanceof FolderIcon;
+ if (dragOverView != mLastDragOverView) {
+ cancelFolderCreation();
+ if (mLastDragOverView != null && mLastDragOverView instanceof FolderIcon) {
+ ((FolderIcon) mLastDragOverView).onDragExit(d.dragInfo);
}
}
- } else if (source == this) {
- // When dragging from the workspace, the drag view is slightly bigger than
- // the original view, and offset vertically. Adjust to account for this.
- final View origView = mDragInfo.cell;
- originX += (dragView.getMeasuredWidth() - origView.getWidth()) / 2;
- originY += (dragView.getMeasuredHeight() - origView.getHeight()) / 2
- + dragView.getOffsetY();
- }
- if (mDragTargetLayout != null) {
- final View child = (mDragInfo == null) ? null : mDragInfo.cell;
- float[] localOrigin = { originX, originY };
- mapPointFromSelfToChild(mDragTargetLayout, localOrigin, null);
- mDragTargetLayout.visualizeDropLocation(child, mDragOutline,
- (int) localOrigin[0], (int) localOrigin[1], item.spanX, item.spanY);
+ if (userFolderPending && dragOverView != mLastDragOverView) {
+ mFolderCreationAlarm.setOnAlarmListener(new
+ FolderCreationAlarmListener(dragOverView));
+ mFolderCreationAlarm.setAlarm(FOLDER_CREATION_TIMEOUT);
+ }
+
+ if (dragOverView != mLastDragOverView && isOverFolder) {
+
+ ((FolderIcon) dragOverView).onDragEnter(d.dragInfo);
+ if (mDragTargetLayout != null) {
+ mDragTargetLayout.clearDragOutlines();
+ }
+ }
+ mLastDragOverView = dragOverView;
+
+ if (!mCreateUserFolderOnDrop && !isOverFolder) {
+ mDragTargetLayout.visualizeDropLocation(child, mDragOutline,
+ (int) mDragViewVisualCenter[0], (int) mDragViewVisualCenter[1],
+ item.spanX, item.spanY);
+ }
}
}
}
}
- private void doDragExit() {
- mWasSpringLoadedOnDragExit = mShrinkState == ShrinkState.SPRING_LOADED;
+ private void cancelFolderCreation() {
+ if (mDragFolderRingAnimator != null && mCreateUserFolderOnDrop) {
+ mDragFolderRingAnimator.animateToNaturalState();
+ }
+ mCreateUserFolderOnDrop = false;
+ mFolderCreationAlarm.cancelAlarm();
+ }
+
+ class FolderCreationAlarmListener implements OnAlarmListener {
+ View v;
+
+ public FolderCreationAlarmListener(View v) {
+ this.v = v;
+ }
+
+ public void onAlarm(Alarm alarm) {
+ int tvLocation[] = new int[2];
+ int wsLocation[] = new int[2];
+ v.getLocationInWindow(tvLocation);
+ getLocationInWindow(wsLocation);
+
+ if (mCellWidth < 0 || mCellHeight < 0 && mDragTargetLayout != null) {
+ mCellWidth = mDragTargetLayout.getCellWidth();
+ mCellHeight = mDragTargetLayout.getCellHeight();
+ }
+ int x = tvLocation[0] - wsLocation[0] + v.getMeasuredWidth() / 2;
+ int y = tvLocation[1] - wsLocation[1] + v.getMeasuredHeight() / 2;
+
+ if (mDragFolderRingAnimator == null) {
+ mDragFolderRingAnimator = new FolderRingAnimator(mLauncher, null);
+ }
+ mDragFolderRingAnimator.setLocation(x, y);
+ mDragFolderRingAnimator.animateToAcceptState();
+ showFolderAccept(mDragFolderRingAnimator);
+ mCreateUserFolderOnDrop = true;
+ if (mDragTargetLayout != null) {
+ mDragTargetLayout.clearDragOutlines();
+ }
+ }
+ }
+
+ private void doDragExit(DragObject d) {
+ if (mDragFolderRingAnimator != null && mCreateUserFolderOnDrop) {
+ mDragFolderRingAnimator.animateToNaturalState();
+ }
+ if (mLastDragOverView != null && mLastDragOverView instanceof FolderIcon) {
+ if (d != null) {
+ ((FolderIcon) mLastDragOverView).onDragExit(d.dragInfo);
+ }
+ }
+ mFolderCreationAlarm.cancelAlarm();
+
if (mDragTargetLayout != null) {
mDragTargetLayout.onDragExit();
}
if (!mIsPageMoving) {
hideOutlines();
}
- if (mShrinkState == ShrinkState.SPRING_LOADED) {
- mLauncher.exitSpringLoadedDragMode();
- }
clearAllHovers();
}
- public void onDragExit(DragSource source, int x, int y, int xOffset,
- int yOffset, DragView dragView, Object dragInfo) {
- doDragExit();
+ public void onDragExit(DragObject d) {
+ doDragExit(d);
}
@Override
@@ -2881,6 +3086,11 @@ public class Workspace extends SmoothPagedView
return false;
}
+ private void onDropExternal(int[] touchXY, Object dragInfo,
+ CellLayout cellLayout, boolean insertAtFirst) {
+ onDropExternal(touchXY, dragInfo, cellLayout, insertAtFirst, null);
+ }
+
/**
* Drop an item that didn't originate on one of the workspace screens.
* It may have come from Launcher (e.g. from all apps or customize), or it may have
@@ -2890,8 +3100,11 @@ public class Workspace extends SmoothPagedView
* to add an item to one of the workspace screens.
*/
private void onDropExternal(int[] touchXY, Object dragInfo,
- CellLayout cellLayout, boolean insertAtFirst) {
+ CellLayout cellLayout, boolean insertAtFirst, DragView dragView) {
int screen = indexOfChild(cellLayout);
+ if (screen != mCurrentPage && mShrinkState != ShrinkState.SPRING_LOADED) {
+ snapToPage(screen);
+ }
if (dragInfo instanceof PendingAddItemInfo) {
PendingAddItemInfo info = (PendingAddItemInfo) dragInfo;
// When dragging and dropping from customization tray, we deal with creating
@@ -2900,9 +3113,6 @@ public class Workspace extends SmoothPagedView
case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
mLauncher.addAppWidgetFromDrop((PendingAddWidgetInfo) info, screen, touchXY);
break;
- case LauncherSettings.Favorites.ITEM_TYPE_LIVE_FOLDER:
- mLauncher.addLiveFolderFromDrop(info.componentName, screen, touchXY);
- break;
case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
mLauncher.processShortcutFromDrop(info.componentName, screen, touchXY);
break;
@@ -2925,27 +3135,50 @@ public class Workspace extends SmoothPagedView
view = mLauncher.createShortcut(R.layout.application, cellLayout,
(ShortcutInfo) info);
break;
- case LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER:
- view = FolderIcon.fromXml(R.layout.folder_icon, mLauncher,
- cellLayout, (UserFolderInfo) info, mIconCache);
+ case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
+ view = FolderIcon.fromXml(R.layout.folder_icon, mLauncher, cellLayout,
+ (FolderInfo) info, mIconCache);
break;
default:
throw new IllegalStateException("Unknown item type: " + info.itemType);
}
- mTargetCell = new int[2];
+ int spanX = mDragInfo != null ? mDragInfo.spanX : 1;
+ int spanY = mDragInfo != null ? mDragInfo.spanY : 1;
+ // First we find the cell nearest to point at which the item is
+ // dropped, without any consideration to whether there is an item there.
+ if (touchXY != null) {
+ mTargetCell = findNearestArea((int) touchXY[0], (int) touchXY[1], spanX, spanY,
+ cellLayout, mTargetCell);
+ if (createUserFolderIfNecessary(view, cellLayout, mTargetCell, true)) {
+ return;
+ }
+ if (addToExistingFolderIfNecessary(view, cellLayout, mTargetCell, dragInfo, true)) {
+ return;
+ }
+ }
+
if (touchXY != null) {
// when dragging and dropping, just find the closest free spot
- cellLayout.findNearestVacantArea(touchXY[0], touchXY[1], 1, 1, mTargetCell);
+ mTargetCell = findNearestVacantArea(touchXY[0], touchXY[1], 1, 1, null,
+ cellLayout, mTargetCell);
} else {
cellLayout.findCellForSpan(mTargetCell, 1, 1);
}
addInScreen(view, indexOfChild(cellLayout), mTargetCell[0],
mTargetCell[1], info.spanX, info.spanY, insertAtFirst);
- boolean animateDrop = !mWasSpringLoadedOnDragExit;
- cellLayout.onDropChild(view, animateDrop);
+ cellLayout.onDropChild(view, false);
cellLayout.animateDrop();
CellLayout.LayoutParams lp = (CellLayout.LayoutParams) view.getLayoutParams();
+ cellLayout.getChildrenLayout().measureChild(view);
+
+ if (dragView != null) {
+ // we have the visual center of the drag view, we need to find the actual
+ // left and top of the dragView.
+ int loc[] = new int[2];
+ getViewLocationRelativeToSelf(dragView, loc);
+ setPositionForDropAnimation(dragView, loc[0], loc[1], cellLayout, view);
+ }
LauncherModel.addOrMoveItemInDatabase(mLauncher, info,
LauncherSettings.Favorites.CONTAINER_DESKTOP, screen,
@@ -2973,43 +3206,42 @@ public class Workspace extends SmoothPagedView
/**
* Calculate the nearest cell where the given object would be dropped.
+ *
+ * pixelX and pixelY should be in the coordinate system of layout
*/
private int[] findNearestVacantArea(int pixelX, int pixelY,
int spanX, int spanY, View ignoreView, CellLayout layout, int[] recycle) {
-
- int localPixelX = pixelX - (layout.getLeft() - mScrollX);
- int localPixelY = pixelY - (layout.getTop() - mScrollY);
-
- // Find the best target drop location
return layout.findNearestVacantArea(
- localPixelX, localPixelY, spanX, spanY, ignoreView, recycle);
+ pixelX, pixelY, spanX, spanY, ignoreView, recycle);
}
- void setLauncher(Launcher launcher) {
- mLauncher = launcher;
- mSpringLoadedDragController = new SpringLoadedDragController(mLauncher);
-
- mCustomizationDrawer = mLauncher.findViewById(R.id.customization_drawer);
- if (mCustomizationDrawer != null) {
- mCustomizationDrawerContent =
- mCustomizationDrawer.findViewById(com.android.internal.R.id.tabcontent);
- }
+ /**
+ * Calculate the nearest cell where the given object would be dropped.
+ *
+ * pixelX and pixelY should be in the coordinate system of layout
+ */
+ private int[] findNearestArea(int pixelX, int pixelY,
+ int spanX, int spanY, CellLayout layout, int[] recycle) {
+ return layout.findNearestArea(
+ pixelX, pixelY, spanX, spanY, recycle);
}
- public void setDragController(DragController dragController) {
+ void setup(Launcher launcher, DragController dragController) {
+ mLauncher = launcher;
+ mSpringLoadedDragController = new SpringLoadedDragController(mLauncher);
mDragController = dragController;
}
/**
* Called at the end of a drag which originated on the workspace.
*/
- public void onDropCompleted(View target, Object dragInfo, boolean success) {
+ public void onDropCompleted(View target, DragObject d, boolean success) {
if (success) {
if (target != this && mDragInfo != null) {
final CellLayout cellLayout = (CellLayout) getChildAt(mDragInfo.screen);
cellLayout.removeView(mDragInfo.cell);
if (mDragInfo.cell instanceof DropTarget) {
- mDragController.removeDropTarget((DropTarget)mDragInfo.cell);
+ mDragController.removeDropTarget((DropTarget) mDragInfo.cell);
}
// final Object tag = mDragInfo.cell.getTag();
}
@@ -3017,7 +3249,7 @@ public class Workspace extends SmoothPagedView
// NOTE: When 'success' is true, onDragExit is called by the DragController before
// calling onDropCompleted(). We call it ourselves here, but maybe this should be
// moved into DragController.cancelDrag().
- doDragExit();
+ doDragExit(null);
((CellLayout) getChildAt(mDragInfo.screen)).onDropChild(mDragInfo.cell, false);
}
mLauncher.unlockScreenOrientation();
@@ -3062,13 +3294,14 @@ public class Workspace extends SmoothPagedView
final int page = mCurrentPage + (direction == DragController.SCROLL_LEFT ? -1 : 1);
final CellLayout layout = (CellLayout) getChildAt(page);
+ cancelFolderCreation();
if (layout != null) {
layout.setIsDragOverlapping(true);
if (mDragTargetLayout != null) {
mDragTargetLayout.onDragExit();
- mDragTargetLayout = null;
+ mDragTargetLayout = layout;
}
// In portrait, need to redraw the edge glow when entering the scroll area
if (getHeight() > getWidth()) {
@@ -3083,7 +3316,6 @@ public class Workspace extends SmoothPagedView
for (int i = 0; i < childCount; i++) {
((CellLayout) getChildAt(i)).setIsDragOverlapping(false);
}
- mSpringLoadedDragController.onDragExit();
// In portrait, workspace is responsible for drawing the edge glow on adjacent pages,
// so we need to redraw the workspace when this may have changed.
@@ -3135,6 +3367,21 @@ public class Workspace extends SmoothPagedView
return null;
}
+ void clearDropTargets() {
+ final int screenCount = getChildCount();
+
+ for (int i = 0; i < screenCount; i++) {
+ final CellLayout layoutParent = (CellLayout) getChildAt(i);
+ final ViewGroup layout = layoutParent.getChildrenLayout();
+ int childCount = layout.getChildCount();
+ for (int j = 0; j < childCount; j++) {
+ View v = layout.getChildAt(j);
+ if (v instanceof DropTarget) {
+ mDragController.removeDropTarget((DropTarget) v);
+ }
+ }
+ }
+ }
void removeItems(final ArrayList<ApplicationInfo> apps) {
final int screenCount = getChildCount();
@@ -3175,8 +3422,8 @@ public class Workspace extends SmoothPagedView
}
}
}
- } else if (tag instanceof UserFolderInfo) {
- final UserFolderInfo info = (UserFolderInfo) tag;
+ } else if (tag instanceof FolderInfo) {
+ final FolderInfo info = (FolderInfo) tag;
final ArrayList<ShortcutInfo> contents = info.contents;
final ArrayList<ShortcutInfo> toRemove = new ArrayList<ShortcutInfo>(1);
final int contentsCount = contents.size();
@@ -3204,20 +3451,6 @@ public class Workspace extends SmoothPagedView
if (folder != null)
folder.notifyDataSetChanged();
}
- } else if (tag instanceof LiveFolderInfo) {
- final LiveFolderInfo info = (LiveFolderInfo) tag;
- final Uri uri = info.uri;
- final ProviderInfo providerInfo = manager.resolveContentProvider(
- uri.getAuthority(), 0);
-
- if (providerInfo != null) {
- for (String packageName: packageNames) {
- if (packageName.equals(providerInfo.packageName)) {
- LauncherModel.deleteItemFromDatabase(mLauncher, info);
- childrenToRemove.add(view);
- }
- }
- }
} else if (tag instanceof LauncherAppWidgetInfo) {
final LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) tag;
final AppWidgetProviderInfo provider =
@@ -3311,5 +3544,4 @@ public class Workspace extends SmoothPagedView
@Override
public void syncPageItems(int page) {
}
-
}
diff --git a/tests/Android.mk b/tests/Android.mk
new file mode 100644
index 000000000..84e955961
--- /dev/null
+++ b/tests/Android.mk
@@ -0,0 +1,15 @@
+# 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.
+#
+include $(call all-subdir-makefiles)
diff --git a/tests/stress/Android.mk b/tests/stress/Android.mk
new file mode 100644
index 000000000..da22bb9f8
--- /dev/null
+++ b/tests/stress/Android.mk
@@ -0,0 +1,33 @@
+# 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.
+#
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+# We only want this apk build for tests.
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := LauncherRotationStressTest
+
+LOCAL_CERTIFICATE := shared
+
+LOCAL_INSTRUMENTATION_FOR := Launcher2
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_PACKAGE)
diff --git a/tests/stress/AndroidManifest.xml b/tests/stress/AndroidManifest.xml
new file mode 100644
index 000000000..ce5dbe426
--- /dev/null
+++ b/tests/stress/AndroidManifest.xml
@@ -0,0 +1,31 @@
+<?xml version="2.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.launcher.stress.launcherrotation">
+
+ <uses-sdk android:minSdkVersion="8" />
+
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation
+ android:name="android.test.InstrumentationTestRunner"
+ android:targetPackage="com.android.launcher"
+ android:label="Rotation stress test using Launcher2">
+ </instrumentation>
+</manifest>
diff --git a/tests/stress/src/com/android/launcher2/stress/LauncherRotationStressTest.java b/tests/stress/src/com/android/launcher2/stress/LauncherRotationStressTest.java
new file mode 100644
index 000000000..3d787f263
--- /dev/null
+++ b/tests/stress/src/com/android/launcher2/stress/LauncherRotationStressTest.java
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+
+package com.android.launcher2.stress;
+
+
+import com.android.launcher2.Launcher;
+
+import android.content.pm.ActivityInfo;
+import android.os.SystemClock;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.TimedTest;
+import android.util.Log;
+
+/**
+ * Run rotation stress test using Launcher2 for 50 iterations.
+ */
+public class LauncherRotationStressTest extends ActivityInstrumentationTestCase2<Launcher> {
+
+ private static final int NUM_ITERATIONS = 50;
+ private static final String LOG_TAG = "LauncherRotationStressTest";
+
+ public LauncherRotationStressTest() {
+ super(Launcher.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ @TimedTest(includeDetailedStats=true)
+ public void testLauncherRotationStress() throws Exception {
+ Launcher launcher = getActivity();
+ for (int i = 0; i < NUM_ITERATIONS; i++) {
+ Log.i(LOG_TAG, "Starting LauncherRotationStressTest " + (i + 1) + " of " +
+ NUM_ITERATIONS);
+ getInstrumentation().waitForIdleSync();
+ SystemClock.sleep(500);
+ launcher.setRequestedOrientation(
+ ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
+ getInstrumentation().waitForIdleSync();
+ SystemClock.sleep(500);
+ launcher.setRequestedOrientation(
+ ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
+ Log.i(LOG_TAG, "Finished LauncherRotationStressTest " + (i + 1) + " of " +
+ NUM_ITERATIONS);
+ }
+ }
+}