summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrint E. Kriebel <bekit@cyngn.com>2014-06-30 22:42:18 -0700
committerBrint E. Kriebel <bekit@cyngn.com>2014-06-30 22:42:18 -0700
commit1cf1cb46e81002f756e6141fcd813eb1df44a2f5 (patch)
tree74c0a8aa932193154abc4e1981c17a6c238582b4
parent4b66843493c8a8cc2bf01ac45566b71b2393a5ec (diff)
parentebf8f37515c23a167cef2bb8cff04854c52fd35b (diff)
downloadandroid_packages_apps_Trebuchet-1cf1cb46e81002f756e6141fcd813eb1df44a2f5.tar.gz
android_packages_apps_Trebuchet-1cf1cb46e81002f756e6141fcd813eb1df44a2f5.tar.bz2
android_packages_apps_Trebuchet-1cf1cb46e81002f756e6141fcd813eb1df44a2f5.zip
Merge branch 'cm-11.0' into stable/cm-11.0
Conflicts: res/values-et/cm_strings.xml res/values-th/cm_arrays.xml res/values-th/cm_strings.xml Change-Id: If66ec311e06bca36268c52b42b61425c3b044556
-rw-r--r--Android.mk46
-rw-r--r--AndroidManifest.xml51
-rw-r--r--CleanSpec.mk2
-rw-r--r--WallpaperPicker/AndroidManifest.xml10
-rw-r--r--WallpaperPicker/README4
-rwxr-xr-xWallpaperPicker/res/drawable-hdpi/ic_actionbar_accept.png (renamed from res/drawable-hdpi/ic_actionbar_accept.png)bin1335 -> 1335 bytes
-rw-r--r--WallpaperPicker/res/drawable-hdpi/ic_images.png (renamed from res/drawable-hdpi/ic_images.png)bin1935 -> 1935 bytes
-rw-r--r--WallpaperPicker/res/drawable-hdpi/tile_picker_focused.9.png (renamed from res/drawable-hdpi/tile_picker_focused.9.png)bin168 -> 168 bytes
-rw-r--r--WallpaperPicker/res/drawable-hdpi/tile_picker_pressed.9.png (renamed from res/drawable-hdpi/tile_picker_pressed.9.png)bin144 -> 144 bytes
-rw-r--r--WallpaperPicker/res/drawable-hdpi/tile_picker_selected.9.png (renamed from res/drawable-hdpi/tile_picker_selected.9.png)bin165 -> 165 bytes
-rw-r--r--WallpaperPicker/res/drawable-hdpi/tile_shadow_bottom.9.png (renamed from res/drawable-hdpi/tile_shadow_bottom.9.png)bin159 -> 159 bytes
-rw-r--r--WallpaperPicker/res/drawable-hdpi/tile_shadow_top.9.png (renamed from res/drawable-hdpi/tile_shadow_top.9.png)bin148 -> 148 bytes
-rwxr-xr-xWallpaperPicker/res/drawable-mdpi/ic_actionbar_accept.png (renamed from res/drawable-mdpi/ic_actionbar_accept.png)bin1191 -> 1191 bytes
-rw-r--r--WallpaperPicker/res/drawable-mdpi/ic_images.png (renamed from res/drawable-mdpi/ic_images.png)bin1332 -> 1332 bytes
-rw-r--r--WallpaperPicker/res/drawable-mdpi/tile_picker_focused.9.png (renamed from res/drawable-mdpi/tile_picker_focused.9.png)bin165 -> 165 bytes
-rw-r--r--WallpaperPicker/res/drawable-mdpi/tile_picker_pressed.9.png (renamed from res/drawable-mdpi/tile_picker_pressed.9.png)bin142 -> 142 bytes
-rw-r--r--WallpaperPicker/res/drawable-mdpi/tile_picker_selected.9.png (renamed from res/drawable-mdpi/tile_picker_selected.9.png)bin159 -> 159 bytes
-rw-r--r--WallpaperPicker/res/drawable-mdpi/tile_shadow_bottom.9.png (renamed from res/drawable-mdpi/tile_shadow_bottom.9.png)bin140 -> 140 bytes
-rw-r--r--WallpaperPicker/res/drawable-mdpi/tile_shadow_top.9.png (renamed from res/drawable-mdpi/tile_shadow_top.9.png)bin138 -> 138 bytes
-rwxr-xr-xWallpaperPicker/res/drawable-xhdpi/ic_actionbar_accept.png (renamed from res/drawable-xhdpi/ic_actionbar_accept.png)bin1599 -> 1599 bytes
-rw-r--r--WallpaperPicker/res/drawable-xhdpi/ic_images.png (renamed from res/drawable-xhdpi/ic_images.png)bin2480 -> 2480 bytes
-rw-r--r--WallpaperPicker/res/drawable-xhdpi/tile_picker_focused.9.png (renamed from res/drawable-xhdpi/tile_picker_focused.9.png)bin174 -> 174 bytes
-rw-r--r--WallpaperPicker/res/drawable-xhdpi/tile_picker_pressed.9.png (renamed from res/drawable-xhdpi/tile_picker_pressed.9.png)bin147 -> 147 bytes
-rw-r--r--WallpaperPicker/res/drawable-xhdpi/tile_picker_selected.9.png (renamed from res/drawable-xhdpi/tile_picker_selected.9.png)bin167 -> 167 bytes
-rw-r--r--WallpaperPicker/res/drawable-xhdpi/tile_shadow_bottom.9.png (renamed from res/drawable-xhdpi/tile_shadow_bottom.9.png)bin164 -> 164 bytes
-rw-r--r--WallpaperPicker/res/drawable-xhdpi/tile_shadow_top.9.png (renamed from res/drawable-xhdpi/tile_shadow_top.9.png)bin151 -> 151 bytes
-rw-r--r--WallpaperPicker/res/drawable-xxhdpi/ic_images.png (renamed from res/drawable-xxhdpi/ic_images.png)bin2097 -> 2097 bytes
-rw-r--r--WallpaperPicker/res/drawable-xxhdpi/tile_picker_focused.9.png (renamed from res/drawable-xxhdpi/tile_picker_focused.9.png)bin189 -> 189 bytes
-rw-r--r--WallpaperPicker/res/drawable-xxhdpi/tile_picker_pressed.9.png (renamed from res/drawable-xxhdpi/tile_picker_pressed.9.png)bin154 -> 154 bytes
-rw-r--r--WallpaperPicker/res/drawable-xxhdpi/tile_picker_selected.9.png (renamed from res/drawable-xxhdpi/tile_picker_selected.9.png)bin175 -> 175 bytes
-rw-r--r--WallpaperPicker/res/drawable-xxhdpi/tile_shadow_bottom.9.png (renamed from res/drawable-xxhdpi/tile_shadow_bottom.9.png)bin185 -> 185 bytes
-rw-r--r--WallpaperPicker/res/drawable-xxhdpi/tile_shadow_top.9.png (renamed from res/drawable-xxhdpi/tile_shadow_top.9.png)bin169 -> 169 bytes
-rw-r--r--WallpaperPicker/res/drawable/wallpaper_tile_fg.xml (renamed from res/drawable/wallpaper_tile_fg.xml)0
-rw-r--r--WallpaperPicker/res/layout/actionbar_set_wallpaper.xml (renamed from res/layout/actionbar_set_wallpaper.xml)24
-rw-r--r--WallpaperPicker/res/layout/wallpaper_cropper.xml (renamed from res/layout/wallpaper_cropper.xml)2
-rw-r--r--WallpaperPicker/res/layout/wallpaper_picker.xml (renamed from res/layout/wallpaper_picker.xml)2
-rw-r--r--WallpaperPicker/res/layout/wallpaper_picker_image_picker_item.xml (renamed from res/layout/wallpaper_picker_image_picker_item.xml)0
-rw-r--r--WallpaperPicker/res/layout/wallpaper_picker_item.xml (renamed from res/layout/wallpaper_picker_item.xml)0
-rw-r--r--WallpaperPicker/res/layout/wallpaper_picker_live_wallpaper_item.xml (renamed from res/layout/wallpaper_picker_live_wallpaper_item.xml)0
-rw-r--r--WallpaperPicker/res/layout/wallpaper_picker_third_party_item.xml (renamed from res/layout/wallpaper_picker_third_party_item.xml)0
-rw-r--r--WallpaperPicker/res/menu/cab_delete_wallpapers.xml (renamed from res/menu/cab_delete_wallpapers.xml)0
-rw-r--r--WallpaperPicker/res/mipmap-hdpi/ic_launcher_wallpaper.png (renamed from res/mipmap-hdpi/ic_launcher_wallpaper.png)bin4418 -> 4418 bytes
-rw-r--r--WallpaperPicker/res/mipmap-mdpi/ic_launcher_wallpaper.png (renamed from res/mipmap-mdpi/ic_launcher_wallpaper.png)bin2871 -> 2871 bytes
-rw-r--r--WallpaperPicker/res/mipmap-xhdpi/ic_launcher_wallpaper.png (renamed from res/mipmap-xhdpi/ic_launcher_wallpaper.png)bin6061 -> 6061 bytes
-rw-r--r--WallpaperPicker/res/mipmap-xxhdpi/ic_launcher_wallpaper.png (renamed from res/mipmap-xxhdpi/ic_launcher_wallpaper.png)bin7596 -> 7596 bytes
-rw-r--r--WallpaperPicker/res/values-nodpi/wallpapers.xml (renamed from res/values-nodpi/wallpapers.xml)0
-rw-r--r--WallpaperPicker/res/values-sw600dp/config.xml18
-rw-r--r--WallpaperPicker/res/values-sw720dp-v19/styles.xml26
-rw-r--r--WallpaperPicker/res/values-sw720dp/dimens.xml28
-rw-r--r--WallpaperPicker/res/values-sw720dp/styles.xml24
-rw-r--r--WallpaperPicker/res/values-v19/styles.xml32
-rw-r--r--WallpaperPicker/res/values/colors.xml22
-rw-r--r--WallpaperPicker/res/values/config.xml21
-rw-r--r--WallpaperPicker/res/values/dimens.xml (renamed from res/layout/list_item_checkable.xml)20
-rw-r--r--WallpaperPicker/res/values/strings.xml53
-rw-r--r--WallpaperPicker/res/values/styles.xml44
-rw-r--r--WallpaperPicker/src/com/android/gallery3d/common/BitmapUtils.java (renamed from src/com/android/gallery3d/common/BitmapUtils.java)0
-rw-r--r--WallpaperPicker/src/com/android/gallery3d/common/Utils.java (renamed from src/com/android/gallery3d/common/Utils.java)0
-rw-r--r--WallpaperPicker/src/com/android/gallery3d/exif/ByteBufferInputStream.java (renamed from src/com/android/gallery3d/exif/ByteBufferInputStream.java)0
-rw-r--r--WallpaperPicker/src/com/android/gallery3d/exif/CountedDataInputStream.java (renamed from src/com/android/gallery3d/exif/CountedDataInputStream.java)0
-rw-r--r--WallpaperPicker/src/com/android/gallery3d/exif/ExifData.java (renamed from src/com/android/gallery3d/exif/ExifData.java)0
-rw-r--r--WallpaperPicker/src/com/android/gallery3d/exif/ExifInterface.java (renamed from src/com/android/gallery3d/exif/ExifInterface.java)0
-rw-r--r--WallpaperPicker/src/com/android/gallery3d/exif/ExifInvalidFormatException.java (renamed from src/com/android/gallery3d/exif/ExifInvalidFormatException.java)0
-rw-r--r--WallpaperPicker/src/com/android/gallery3d/exif/ExifModifier.java (renamed from src/com/android/gallery3d/exif/ExifModifier.java)1
-rw-r--r--WallpaperPicker/src/com/android/gallery3d/exif/ExifOutputStream.java (renamed from src/com/android/gallery3d/exif/ExifOutputStream.java)0
-rw-r--r--WallpaperPicker/src/com/android/gallery3d/exif/ExifParser.java (renamed from src/com/android/gallery3d/exif/ExifParser.java)0
-rw-r--r--WallpaperPicker/src/com/android/gallery3d/exif/ExifReader.java (renamed from src/com/android/gallery3d/exif/ExifReader.java)0
-rw-r--r--WallpaperPicker/src/com/android/gallery3d/exif/ExifTag.java (renamed from src/com/android/gallery3d/exif/ExifTag.java)0
-rw-r--r--WallpaperPicker/src/com/android/gallery3d/exif/IfdData.java (renamed from src/com/android/gallery3d/exif/IfdData.java)0
-rw-r--r--WallpaperPicker/src/com/android/gallery3d/exif/IfdId.java (renamed from src/com/android/gallery3d/exif/IfdId.java)0
-rw-r--r--WallpaperPicker/src/com/android/gallery3d/exif/JpegHeader.java (renamed from src/com/android/gallery3d/exif/JpegHeader.java)0
-rw-r--r--WallpaperPicker/src/com/android/gallery3d/exif/OrderedDataOutputStream.java (renamed from src/com/android/gallery3d/exif/OrderedDataOutputStream.java)0
-rw-r--r--WallpaperPicker/src/com/android/gallery3d/exif/Rational.java (renamed from src/com/android/gallery3d/exif/Rational.java)0
-rw-r--r--WallpaperPicker/src/com/android/gallery3d/glrenderer/BasicTexture.java (renamed from src/com/android/gallery3d/glrenderer/BasicTexture.java)0
-rw-r--r--WallpaperPicker/src/com/android/gallery3d/glrenderer/BitmapTexture.java (renamed from src/com/android/gallery3d/glrenderer/BitmapTexture.java)0
-rw-r--r--WallpaperPicker/src/com/android/gallery3d/glrenderer/GLCanvas.java (renamed from src/com/android/gallery3d/glrenderer/GLCanvas.java)2
-rw-r--r--WallpaperPicker/src/com/android/gallery3d/glrenderer/GLES20Canvas.java (renamed from src/com/android/gallery3d/glrenderer/GLES20Canvas.java)0
-rw-r--r--WallpaperPicker/src/com/android/gallery3d/glrenderer/GLES20IdImpl.java (renamed from src/com/android/gallery3d/glrenderer/GLES20IdImpl.java)0
-rw-r--r--WallpaperPicker/src/com/android/gallery3d/glrenderer/GLId.java (renamed from src/com/android/gallery3d/glrenderer/GLId.java)0
-rw-r--r--WallpaperPicker/src/com/android/gallery3d/glrenderer/GLPaint.java (renamed from src/com/android/gallery3d/glrenderer/GLPaint.java)0
-rw-r--r--WallpaperPicker/src/com/android/gallery3d/glrenderer/RawTexture.java (renamed from src/com/android/gallery3d/glrenderer/RawTexture.java)0
-rw-r--r--WallpaperPicker/src/com/android/gallery3d/glrenderer/Texture.java (renamed from src/com/android/gallery3d/glrenderer/Texture.java)0
-rw-r--r--WallpaperPicker/src/com/android/gallery3d/glrenderer/UploadedTexture.java (renamed from src/com/android/gallery3d/glrenderer/UploadedTexture.java)0
-rw-r--r--WallpaperPicker/src/com/android/gallery3d/util/IntArray.java (renamed from src/com/android/gallery3d/util/IntArray.java)0
-rw-r--r--WallpaperPicker/src/com/android/launcher3/AlphaDisableableButton.java50
-rw-r--r--WallpaperPicker/src/com/android/launcher3/CheckableFrameLayout.java (renamed from src/com/android/launcher3/CheckableFrameLayout.java)0
-rw-r--r--WallpaperPicker/src/com/android/launcher3/CropView.java (renamed from src/com/android/launcher3/CropView.java)3
-rw-r--r--WallpaperPicker/src/com/android/launcher3/DrawableTileSource.java102
-rw-r--r--WallpaperPicker/src/com/android/launcher3/LiveWallpaperListAdapter.java (renamed from src/com/android/launcher3/LiveWallpaperListAdapter.java)11
-rw-r--r--WallpaperPicker/src/com/android/launcher3/SavedWallpaperImages.java (renamed from src/com/android/launcher3/SavedWallpaperImages.java)31
-rw-r--r--WallpaperPicker/src/com/android/launcher3/ThirdPartyWallpaperPickerListAdapter.java (renamed from src/com/android/launcher3/ThirdPartyWallpaperPickerListAdapter.java)6
-rw-r--r--WallpaperPicker/src/com/android/launcher3/WallpaperCropActivity.java (renamed from src/com/android/launcher3/WallpaperCropActivity.java)349
-rw-r--r--WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java (renamed from src/com/android/launcher3/WallpaperPickerActivity.java)483
-rw-r--r--WallpaperPicker/src/com/android/launcher3/WallpaperRootView.java (renamed from src/com/android/launcher3/WallpaperRootView.java)6
-rw-r--r--WallpaperPicker/src/com/android/photos/BitmapRegionTileSource.java528
-rw-r--r--WallpaperPicker/src/com/android/photos/views/BlockingGLTextureView.java (renamed from src/com/android/photos/views/BlockingGLTextureView.java)0
-rw-r--r--WallpaperPicker/src/com/android/photos/views/TiledImageRenderer.java (renamed from src/com/android/photos/views/TiledImageRenderer.java)0
-rw-r--r--WallpaperPicker/src/com/android/photos/views/TiledImageView.java (renamed from src/com/android/photos/views/TiledImageView.java)12
-rw-r--r--proguard.flags3
-rw-r--r--res/anim/drop_down.xml13
-rw-r--r--res/anim/enter_from_left.xml12
-rw-r--r--res/anim/enter_from_right.xml12
-rw-r--r--res/anim/exit_out_left.xml13
-rw-r--r--res/anim/exit_out_right.xml12
-rw-r--r--res/color/listitem_text.xml6
-rw-r--r--res/drawable-hdpi/folder_lock.pngbin0 -> 459 bytes
-rw-r--r--res/drawable-hdpi/folder_lock_light.pngbin0 -> 461 bytes
-rw-r--r--res/drawable-hdpi/folder_unlock.pngbin0 -> 480 bytes
-rw-r--r--res/drawable-hdpi/ic_clear.pngbin501 -> 0 bytes
-rw-r--r--res/drawable-hdpi/ic_default_screen.pngbin18144 -> 998 bytes
-rw-r--r--res/drawable-hdpi/ic_default_screen_pressed.pngbin18857 -> 975 bytes
-rw-r--r--res/drawable-hdpi/ic_iconpacks.pngbin1045 -> 0 bytes
-rw-r--r--res/drawable-hdpi/ic_remove.pngbin0 -> 931 bytes
-rw-r--r--res/drawable-hdpi/ic_setting.pngbin2637 -> 0 bytes
-rw-r--r--res/drawable-hdpi/ic_setting_pressed.pngbin3099 -> 0 bytes
-rw-r--r--res/drawable-hdpi/ic_themes.pngbin0 -> 36132 bytes
-rw-r--r--res/drawable-hdpi/ic_themes_pressed.pngbin0 -> 36132 bytes
-rw-r--r--res/drawable-hdpi/ic_widget.pngbin410 -> 1560 bytes
-rw-r--r--res/drawable-hdpi/ic_widget_pressed.pngbin1961 -> 2332 bytes
-rw-r--r--res/drawable-hdpi/on_boarding_welcome.pngbin0 -> 22423 bytes
-rw-r--r--res/drawable-hdpi/screenpanel_hover.9.pngbin1189 -> 1096 bytes
-rw-r--r--res/drawable-hdpi/search_bg.9.pngbin0 -> 352 bytes
-rw-r--r--res/drawable-mdpi/folder_lock.pngbin0 -> 376 bytes
-rw-r--r--res/drawable-mdpi/folder_lock_light.pngbin0 -> 372 bytes
-rw-r--r--res/drawable-mdpi/folder_unlock.pngbin0 -> 383 bytes
-rw-r--r--res/drawable-mdpi/ic_clear.pngbin329 -> 0 bytes
-rw-r--r--res/drawable-mdpi/ic_default_screen.pngbin17779 -> 673 bytes
-rw-r--r--res/drawable-mdpi/ic_default_screen_pressed.pngbin18202 -> 678 bytes
-rw-r--r--res/drawable-mdpi/ic_iconpacks.pngbin769 -> 0 bytes
-rw-r--r--res/drawable-mdpi/ic_remove.pngbin0 -> 646 bytes
-rw-r--r--res/drawable-mdpi/ic_setting.pngbin1669 -> 0 bytes
-rw-r--r--res/drawable-mdpi/ic_setting_pressed.pngbin1868 -> 0 bytes
-rw-r--r--res/drawable-mdpi/ic_themes.pngbin0 -> 20562 bytes
-rw-r--r--res/drawable-mdpi/ic_themes_pressed.pngbin0 -> 28948 bytes
-rw-r--r--res/drawable-mdpi/ic_widget.pngbin370 -> 1174 bytes
-rw-r--r--res/drawable-mdpi/ic_widget_pressed.pngbin1658 -> 1487 bytes
-rw-r--r--res/drawable-mdpi/on_boarding_welcome.pngbin0 -> 15325 bytes
-rw-r--r--res/drawable-mdpi/screenpanel_hover.9.pngbin913 -> 975 bytes
-rw-r--r--res/drawable-mdpi/search_bg.9.pngbin0 -> 279 bytes
-rw-r--r--res/drawable-sw600dp-hdpi/ic_allapps.pngbin8354 -> 3969 bytes
-rw-r--r--res/drawable-sw600dp-hdpi/ic_allapps_pressed.pngbin9434 -> 3734 bytes
-rw-r--r--res/drawable-sw600dp-mdpi/ic_allapps.pngbin5408 -> 3211 bytes
-rw-r--r--res/drawable-sw600dp-mdpi/ic_allapps_pressed.pngbin6523 -> 3069 bytes
-rw-r--r--res/drawable-sw600dp-xhdpi/ic_allapps.pngbin13262 -> 6138 bytes
-rw-r--r--res/drawable-sw600dp-xhdpi/ic_allapps_pressed.pngbin14475 -> 5703 bytes
-rw-r--r--res/drawable-sw600dp-xxhdpi/ic_allapps.pngbin18116 -> 17636 bytes
-rw-r--r--res/drawable-sw600dp-xxhdpi/ic_allapps_pressed.pngbin18068 -> 15907 bytes
-rw-r--r--res/drawable-sw720dp-xxhdpi/workspace_bg.9.pngbin0 -> 1126 bytes
-rw-r--r--res/drawable-xhdpi/folder_lock.pngbin0 -> 601 bytes
-rw-r--r--res/drawable-xhdpi/folder_lock_light.pngbin0 -> 601 bytes
-rw-r--r--res/drawable-xhdpi/folder_unlock.pngbin0 -> 613 bytes
-rw-r--r--res/drawable-xhdpi/ic_clear.pngbin611 -> 0 bytes
-rw-r--r--res/drawable-xhdpi/ic_default_screen.pngbin18388 -> 1199 bytes
-rw-r--r--res/drawable-xhdpi/ic_default_screen_pressed.pngbin19556 -> 1195 bytes
-rw-r--r--res/drawable-xhdpi/ic_iconpacks.pngbin1430 -> 0 bytes
-rw-r--r--res/drawable-xhdpi/ic_remove.pngbin0 -> 1403 bytes
-rw-r--r--res/drawable-xhdpi/ic_setting.pngbin3625 -> 0 bytes
-rw-r--r--res/drawable-xhdpi/ic_setting_pressed.pngbin4524 -> 0 bytes
-rw-r--r--res/drawable-xhdpi/ic_themes.pngbin0 -> 56644 bytes
-rw-r--r--res/drawable-xhdpi/ic_themes_pressed.pngbin0 -> 56644 bytes
-rw-r--r--res/drawable-xhdpi/ic_widget.pngbin498 -> 1978 bytes
-rw-r--r--res/drawable-xhdpi/ic_widget_pressed.pngbin2359 -> 3360 bytes
-rw-r--r--res/drawable-xhdpi/on_boarding_welcome.pngbin0 -> 34253 bytes
-rw-r--r--res/drawable-xhdpi/screenpanel_hover.9.pngbin1586 -> 1704 bytes
-rw-r--r--res/drawable-xhdpi/search_bg.9.pngbin0 -> 423 bytes
-rw-r--r--res/drawable-xxhdpi/folder_lock.pngbin0 -> 750 bytes
-rw-r--r--res/drawable-xxhdpi/folder_lock_light.pngbin0 -> 746 bytes
-rw-r--r--res/drawable-xxhdpi/folder_unlock.pngbin0 -> 775 bytes
-rw-r--r--res/drawable-xxhdpi/ic_clear.pngbin1102 -> 0 bytes
-rw-r--r--res/drawable-xxhdpi/ic_default_screen.pngbin19024 -> 1888 bytes
-rw-r--r--res/drawable-xxhdpi/ic_default_screen_pressed.pngbin21488 -> 1881 bytes
-rw-r--r--res/drawable-xxhdpi/ic_iconpacks.pngbin2146 -> 0 bytes
-rw-r--r--res/drawable-xxhdpi/ic_remove.pngbin0 -> 2177 bytes
-rw-r--r--res/drawable-xxhdpi/ic_setting.pngbin4105 -> 0 bytes
-rw-r--r--res/drawable-xxhdpi/ic_setting_pressed.pngbin7113 -> 0 bytes
-rw-r--r--res/drawable-xxhdpi/ic_themes.pngbin0 -> 21844 bytes
-rw-r--r--res/drawable-xxhdpi/ic_themes_pressed.pngbin0 -> 24420 bytes
-rw-r--r--res/drawable-xxhdpi/ic_widget.pngbin555 -> 2413 bytes
-rw-r--r--res/drawable-xxhdpi/ic_widget_pressed.pngbin2916 -> 5518 bytes
-rw-r--r--res/drawable-xxhdpi/screenpanel_hover.9.pngbin4418 -> 2605 bytes
-rw-r--r--res/drawable-xxhdpi/search_bg.9.pngbin0 -> 654 bytes
-rw-r--r--res/drawable/above_shadow.xml8
-rw-r--r--res/drawable/acordian_00000.pngbin0 -> 214 bytes
-rw-r--r--res/drawable/acordian_00001.pngbin0 -> 209 bytes
-rw-r--r--res/drawable/acordian_00002.pngbin0 -> 225 bytes
-rw-r--r--res/drawable/acordian_00003.pngbin0 -> 235 bytes
-rw-r--r--res/drawable/acordian_00004.pngbin0 -> 233 bytes
-rw-r--r--res/drawable/acordian_00005.pngbin0 -> 230 bytes
-rw-r--r--res/drawable/acordian_00006.pngbin0 -> 245 bytes
-rw-r--r--res/drawable/acordian_00007.pngbin0 -> 243 bytes
-rw-r--r--res/drawable/acordian_00008.pngbin0 -> 258 bytes
-rw-r--r--res/drawable/acordian_00009.pngbin0 -> 204 bytes
-rw-r--r--res/drawable/acordian_00010.pngbin0 -> 210 bytes
-rw-r--r--res/drawable/acordian_00011.pngbin0 -> 210 bytes
-rw-r--r--res/drawable/acordian_00012.pngbin0 -> 210 bytes
-rw-r--r--res/drawable/acordian_00013.pngbin0 -> 210 bytes
-rw-r--r--res/drawable/acordian_00014.pngbin0 -> 210 bytes
-rw-r--r--res/drawable/acordian_00015.pngbin0 -> 210 bytes
-rw-r--r--res/drawable/acordian_00016.pngbin0 -> 210 bytes
-rw-r--r--res/drawable/acordian_00017.pngbin0 -> 210 bytes
-rw-r--r--res/drawable/acordian_00018.pngbin0 -> 210 bytes
-rw-r--r--res/drawable/acordian_00019.pngbin0 -> 210 bytes
-rw-r--r--res/drawable/acordian_00020.pngbin0 -> 210 bytes
-rw-r--r--res/drawable/acordian_00021.pngbin0 -> 210 bytes
-rw-r--r--res/drawable/acordian_00022.pngbin0 -> 210 bytes
-rw-r--r--res/drawable/acordian_00023.pngbin0 -> 210 bytes
-rw-r--r--res/drawable/acordian_00024.pngbin0 -> 210 bytes
-rw-r--r--res/drawable/acordian_00025.pngbin0 -> 210 bytes
-rw-r--r--res/drawable/acordian_00026.pngbin0 -> 210 bytes
-rw-r--r--res/drawable/acordian_00027.pngbin0 -> 204 bytes
-rw-r--r--res/drawable/acordian_00028.pngbin0 -> 258 bytes
-rw-r--r--res/drawable/acordian_00029.pngbin0 -> 243 bytes
-rw-r--r--res/drawable/acordian_00030.pngbin0 -> 245 bytes
-rw-r--r--res/drawable/acordian_00031.pngbin0 -> 239 bytes
-rw-r--r--res/drawable/acordian_00032.pngbin0 -> 233 bytes
-rw-r--r--res/drawable/acordian_00033.pngbin0 -> 235 bytes
-rw-r--r--res/drawable/acordian_00034.pngbin0 -> 225 bytes
-rw-r--r--res/drawable/acordian_00035.pngbin0 -> 209 bytes
-rw-r--r--res/drawable/acordian_00036.pngbin0 -> 214 bytes
-rw-r--r--res/drawable/acordian_00037.pngbin0 -> 214 bytes
-rw-r--r--res/drawable/acordian_00038.pngbin0 -> 214 bytes
-rw-r--r--res/drawable/acordian_00039.pngbin0 -> 214 bytes
-rw-r--r--res/drawable/acordian_00040.pngbin0 -> 214 bytes
-rw-r--r--res/drawable/acordian_00041.pngbin0 -> 214 bytes
-rw-r--r--res/drawable/acordian_00042.pngbin0 -> 214 bytes
-rw-r--r--res/drawable/acordian_00043.pngbin0 -> 214 bytes
-rw-r--r--res/drawable/acordian_00044.pngbin0 -> 214 bytes
-rw-r--r--res/drawable/acordian_00045.pngbin0 -> 214 bytes
-rw-r--r--res/drawable/acordian_00046.pngbin0 -> 214 bytes
-rw-r--r--res/drawable/acordian_00047.pngbin0 -> 214 bytes
-rw-r--r--res/drawable/acordian_00048.pngbin0 -> 214 bytes
-rw-r--r--res/drawable/acordian_00049.pngbin0 -> 214 bytes
-rw-r--r--res/drawable/below_shadow.xml8
-rw-r--r--res/drawable/carousel_00000.pngbin0 -> 153 bytes
-rw-r--r--res/drawable/carousel_00001.pngbin0 -> 168 bytes
-rw-r--r--res/drawable/carousel_00002.pngbin0 -> 192 bytes
-rw-r--r--res/drawable/carousel_00003.pngbin0 -> 218 bytes
-rw-r--r--res/drawable/carousel_00004.pngbin0 -> 267 bytes
-rw-r--r--res/drawable/carousel_00005.pngbin0 -> 257 bytes
-rw-r--r--res/drawable/carousel_00006.pngbin0 -> 285 bytes
-rw-r--r--res/drawable/carousel_00007.pngbin0 -> 299 bytes
-rw-r--r--res/drawable/carousel_00008.pngbin0 -> 282 bytes
-rw-r--r--res/drawable/carousel_00009.pngbin0 -> 298 bytes
-rw-r--r--res/drawable/carousel_00010.pngbin0 -> 299 bytes
-rw-r--r--res/drawable/carousel_00011.pngbin0 -> 296 bytes
-rw-r--r--res/drawable/carousel_00012.pngbin0 -> 348 bytes
-rw-r--r--res/drawable/carousel_00013.pngbin0 -> 366 bytes
-rw-r--r--res/drawable/carousel_00014.pngbin0 -> 360 bytes
-rw-r--r--res/drawable/carousel_00015.pngbin0 -> 373 bytes
-rw-r--r--res/drawable/carousel_00016.pngbin0 -> 364 bytes
-rw-r--r--res/drawable/carousel_00017.pngbin0 -> 307 bytes
-rw-r--r--res/drawable/carousel_00018.pngbin0 -> 267 bytes
-rw-r--r--res/drawable/carousel_00019.pngbin0 -> 202 bytes
-rw-r--r--res/drawable/carousel_00020.pngbin0 -> 153 bytes
-rw-r--r--res/drawable/carousel_00021.pngbin0 -> 153 bytes
-rw-r--r--res/drawable/carousel_00022.pngbin0 -> 153 bytes
-rw-r--r--res/drawable/carousel_00023.pngbin0 -> 153 bytes
-rw-r--r--res/drawable/carousel_00024.pngbin0 -> 153 bytes
-rw-r--r--res/drawable/carousel_00025.pngbin0 -> 153 bytes
-rw-r--r--res/drawable/carousel_00026.pngbin0 -> 153 bytes
-rw-r--r--res/drawable/carousel_00027.pngbin0 -> 153 bytes
-rw-r--r--res/drawable/carousel_00028.pngbin0 -> 153 bytes
-rw-r--r--res/drawable/carousel_00029.pngbin0 -> 153 bytes
-rw-r--r--res/drawable/carousel_00030.pngbin0 -> 153 bytes
-rw-r--r--res/drawable/carousel_00031.pngbin0 -> 153 bytes
-rw-r--r--res/drawable/carousel_00032.pngbin0 -> 153 bytes
-rw-r--r--res/drawable/carousel_00033.pngbin0 -> 153 bytes
-rw-r--r--res/drawable/carousel_00034.pngbin0 -> 153 bytes
-rw-r--r--res/drawable/carousel_00035.pngbin0 -> 153 bytes
-rw-r--r--res/drawable/carousel_00036.pngbin0 -> 153 bytes
-rw-r--r--res/drawable/carousel_00037.pngbin0 -> 153 bytes
-rw-r--r--res/drawable/carousel_00038.pngbin0 -> 153 bytes
-rw-r--r--res/drawable/carousel_00039.pngbin0 -> 153 bytes
-rw-r--r--res/drawable/carousel_00040.pngbin0 -> 153 bytes
-rw-r--r--res/drawable/carousel_00041.pngbin0 -> 153 bytes
-rw-r--r--res/drawable/carousel_00042.pngbin0 -> 153 bytes
-rw-r--r--res/drawable/carousel_00043.pngbin0 -> 153 bytes
-rw-r--r--res/drawable/carousel_00044.pngbin0 -> 153 bytes
-rw-r--r--res/drawable/carousel_00045.pngbin0 -> 153 bytes
-rw-r--r--res/drawable/carousel_00046.pngbin0 -> 153 bytes
-rw-r--r--res/drawable/carousel_00047.pngbin0 -> 153 bytes
-rw-r--r--res/drawable/carousel_00048.pngbin0 -> 153 bytes
-rw-r--r--res/drawable/carousel_00049.pngbin0 -> 153 bytes
-rw-r--r--res/drawable/cubein_00000.pngbin0 -> 153 bytes
-rw-r--r--res/drawable/cubein_00001.pngbin0 -> 201 bytes
-rw-r--r--res/drawable/cubein_00002.pngbin0 -> 260 bytes
-rw-r--r--res/drawable/cubein_00003.pngbin0 -> 316 bytes
-rw-r--r--res/drawable/cubein_00004.pngbin0 -> 358 bytes
-rw-r--r--res/drawable/cubein_00005.pngbin0 -> 365 bytes
-rw-r--r--res/drawable/cubein_00006.pngbin0 -> 411 bytes
-rw-r--r--res/drawable/cubein_00007.pngbin0 -> 425 bytes
-rw-r--r--res/drawable/cubein_00008.pngbin0 -> 407 bytes
-rw-r--r--res/drawable/cubein_00009.pngbin0 -> 415 bytes
-rw-r--r--res/drawable/cubein_00010.pngbin0 -> 411 bytes
-rw-r--r--res/drawable/cubein_00011.pngbin0 -> 429 bytes
-rw-r--r--res/drawable/cubein_00012.pngbin0 -> 413 bytes
-rw-r--r--res/drawable/cubein_00013.pngbin0 -> 405 bytes
-rw-r--r--res/drawable/cubein_00014.pngbin0 -> 383 bytes
-rw-r--r--res/drawable/cubein_00015.pngbin0 -> 356 bytes
-rw-r--r--res/drawable/cubein_00016.pngbin0 -> 368 bytes
-rw-r--r--res/drawable/cubein_00017.pngbin0 -> 318 bytes
-rw-r--r--res/drawable/cubein_00018.pngbin0 -> 257 bytes
-rw-r--r--res/drawable/cubein_00019.pngbin0 -> 198 bytes
-rw-r--r--res/drawable/cubein_00020.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/cubein_00021.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/cubein_00022.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/cubein_00023.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/cubein_00024.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/cubein_00025.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/cubein_00026.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/cubein_00027.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/cubein_00028.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/cubein_00029.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/cubein_00030.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/cubein_00031.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/cubein_00032.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/cubein_00033.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/cubein_00034.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/cubein_00035.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/cubein_00036.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/cubein_00037.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/cubein_00038.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/cubein_00039.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/cubein_00040.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/cubein_00041.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/cubein_00042.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/cubein_00043.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/cubein_00044.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/cubein_00045.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/cubein_00046.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/cubein_00047.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/cubein_00048.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/cubein_00049.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/cubeout_00000.pngbin0 -> 153 bytes
-rw-r--r--res/drawable/cubeout_00001.pngbin0 -> 206 bytes
-rw-r--r--res/drawable/cubeout_00002.pngbin0 -> 208 bytes
-rw-r--r--res/drawable/cubeout_00003.pngbin0 -> 225 bytes
-rw-r--r--res/drawable/cubeout_00004.pngbin0 -> 260 bytes
-rw-r--r--res/drawable/cubeout_00005.pngbin0 -> 327 bytes
-rw-r--r--res/drawable/cubeout_00006.pngbin0 -> 340 bytes
-rw-r--r--res/drawable/cubeout_00007.pngbin0 -> 327 bytes
-rw-r--r--res/drawable/cubeout_00008.pngbin0 -> 346 bytes
-rw-r--r--res/drawable/cubeout_00009.pngbin0 -> 343 bytes
-rw-r--r--res/drawable/cubeout_00010.pngbin0 -> 339 bytes
-rw-r--r--res/drawable/cubeout_00011.pngbin0 -> 332 bytes
-rw-r--r--res/drawable/cubeout_00012.pngbin0 -> 352 bytes
-rw-r--r--res/drawable/cubeout_00013.pngbin0 -> 327 bytes
-rw-r--r--res/drawable/cubeout_00014.pngbin0 -> 329 bytes
-rw-r--r--res/drawable/cubeout_00015.pngbin0 -> 318 bytes
-rw-r--r--res/drawable/cubeout_00016.pngbin0 -> 266 bytes
-rw-r--r--res/drawable/cubeout_00017.pngbin0 -> 220 bytes
-rw-r--r--res/drawable/cubeout_00018.pngbin0 -> 205 bytes
-rw-r--r--res/drawable/cubeout_00019.pngbin0 -> 167 bytes
-rw-r--r--res/drawable/cubeout_00020.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/cubeout_00021.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/cubeout_00022.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/cubeout_00023.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/cubeout_00024.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/cubeout_00025.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/cubeout_00026.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/cubeout_00027.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/cubeout_00028.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/cubeout_00029.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/cubeout_00030.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/cubeout_00031.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/cubeout_00032.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/cubeout_00033.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/cubeout_00034.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/cubeout_00035.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/cubeout_00036.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/cubeout_00037.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/cubeout_00038.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/cubeout_00039.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/cubeout_00040.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/cubeout_00041.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/cubeout_00042.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/cubeout_00043.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/cubeout_00044.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/cubeout_00045.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/cubeout_00046.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/cubeout_00047.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/cubeout_00048.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/cubeout_00049.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/cylinderin_00000.pngbin0 -> 421 bytes
-rw-r--r--res/drawable/cylinderin_00001.pngbin0 -> 451 bytes
-rw-r--r--res/drawable/cylinderin_00002.pngbin0 -> 449 bytes
-rw-r--r--res/drawable/cylinderin_00003.pngbin0 -> 436 bytes
-rw-r--r--res/drawable/cylinderin_00004.pngbin0 -> 477 bytes
-rw-r--r--res/drawable/cylinderin_00005.pngbin0 -> 502 bytes
-rw-r--r--res/drawable/cylinderin_00006.pngbin0 -> 489 bytes
-rw-r--r--res/drawable/cylinderin_00007.pngbin0 -> 494 bytes
-rw-r--r--res/drawable/cylinderin_00008.pngbin0 -> 491 bytes
-rw-r--r--res/drawable/cylinderin_00009.pngbin0 -> 516 bytes
-rw-r--r--res/drawable/cylinderin_00010.pngbin0 -> 476 bytes
-rw-r--r--res/drawable/cylinderin_00011.pngbin0 -> 500 bytes
-rw-r--r--res/drawable/cylinderin_00012.pngbin0 -> 475 bytes
-rw-r--r--res/drawable/cylinderin_00013.pngbin0 -> 487 bytes
-rw-r--r--res/drawable/cylinderin_00014.pngbin0 -> 555 bytes
-rw-r--r--res/drawable/cylinderin_00015.pngbin0 -> 475 bytes
-rw-r--r--res/drawable/cylinderin_00016.pngbin0 -> 485 bytes
-rw-r--r--res/drawable/cylinderin_00017.pngbin0 -> 487 bytes
-rw-r--r--res/drawable/cylinderin_00018.pngbin0 -> 430 bytes
-rw-r--r--res/drawable/cylinderin_00019.pngbin0 -> 444 bytes
-rw-r--r--res/drawable/cylinderin_00020.pngbin0 -> 421 bytes
-rw-r--r--res/drawable/cylinderin_00021.pngbin0 -> 421 bytes
-rw-r--r--res/drawable/cylinderin_00022.pngbin0 -> 421 bytes
-rw-r--r--res/drawable/cylinderin_00023.pngbin0 -> 421 bytes
-rw-r--r--res/drawable/cylinderin_00024.pngbin0 -> 421 bytes
-rw-r--r--res/drawable/cylinderin_00025.pngbin0 -> 421 bytes
-rw-r--r--res/drawable/cylinderin_00026.pngbin0 -> 421 bytes
-rw-r--r--res/drawable/cylinderin_00027.pngbin0 -> 421 bytes
-rw-r--r--res/drawable/cylinderin_00028.pngbin0 -> 421 bytes
-rw-r--r--res/drawable/cylinderin_00029.pngbin0 -> 421 bytes
-rw-r--r--res/drawable/cylinderin_00030.pngbin0 -> 421 bytes
-rw-r--r--res/drawable/cylinderin_00031.pngbin0 -> 421 bytes
-rw-r--r--res/drawable/cylinderin_00032.pngbin0 -> 421 bytes
-rw-r--r--res/drawable/cylinderin_00033.pngbin0 -> 421 bytes
-rw-r--r--res/drawable/cylinderin_00034.pngbin0 -> 421 bytes
-rw-r--r--res/drawable/cylinderin_00035.pngbin0 -> 421 bytes
-rw-r--r--res/drawable/cylinderin_00036.pngbin0 -> 421 bytes
-rw-r--r--res/drawable/cylinderin_00037.pngbin0 -> 421 bytes
-rw-r--r--res/drawable/cylinderin_00038.pngbin0 -> 421 bytes
-rw-r--r--res/drawable/cylinderin_00039.pngbin0 -> 421 bytes
-rw-r--r--res/drawable/cylinderin_00040.pngbin0 -> 421 bytes
-rw-r--r--res/drawable/cylinderin_00041.pngbin0 -> 421 bytes
-rw-r--r--res/drawable/cylinderin_00042.pngbin0 -> 421 bytes
-rw-r--r--res/drawable/cylinderin_00043.pngbin0 -> 421 bytes
-rw-r--r--res/drawable/cylinderin_00044.pngbin0 -> 421 bytes
-rw-r--r--res/drawable/cylinderin_00045.pngbin0 -> 421 bytes
-rw-r--r--res/drawable/cylinderin_00046.pngbin0 -> 421 bytes
-rw-r--r--res/drawable/cylinderin_00047.pngbin0 -> 421 bytes
-rw-r--r--res/drawable/cylinderin_00048.pngbin0 -> 421 bytes
-rw-r--r--res/drawable/cylinderin_00049.pngbin0 -> 421 bytes
-rw-r--r--res/drawable/cylinderout_00000.pngbin0 -> 372 bytes
-rw-r--r--res/drawable/cylinderout_00001.pngbin0 -> 389 bytes
-rw-r--r--res/drawable/cylinderout_00002.pngbin0 -> 376 bytes
-rw-r--r--res/drawable/cylinderout_00003.pngbin0 -> 374 bytes
-rw-r--r--res/drawable/cylinderout_00004.pngbin0 -> 419 bytes
-rw-r--r--res/drawable/cylinderout_00005.pngbin0 -> 417 bytes
-rw-r--r--res/drawable/cylinderout_00006.pngbin0 -> 414 bytes
-rw-r--r--res/drawable/cylinderout_00007.pngbin0 -> 400 bytes
-rw-r--r--res/drawable/cylinderout_00008.pngbin0 -> 466 bytes
-rw-r--r--res/drawable/cylinderout_00009.pngbin0 -> 430 bytes
-rw-r--r--res/drawable/cylinderout_00010.pngbin0 -> 394 bytes
-rw-r--r--res/drawable/cylinderout_00011.pngbin0 -> 412 bytes
-rw-r--r--res/drawable/cylinderout_00012.pngbin0 -> 420 bytes
-rw-r--r--res/drawable/cylinderout_00013.pngbin0 -> 404 bytes
-rw-r--r--res/drawable/cylinderout_00014.pngbin0 -> 415 bytes
-rw-r--r--res/drawable/cylinderout_00015.pngbin0 -> 446 bytes
-rw-r--r--res/drawable/cylinderout_00016.pngbin0 -> 418 bytes
-rw-r--r--res/drawable/cylinderout_00017.pngbin0 -> 377 bytes
-rw-r--r--res/drawable/cylinderout_00018.pngbin0 -> 372 bytes
-rw-r--r--res/drawable/cylinderout_00019.pngbin0 -> 394 bytes
-rw-r--r--res/drawable/cylinderout_00020.pngbin0 -> 372 bytes
-rw-r--r--res/drawable/cylinderout_00021.pngbin0 -> 372 bytes
-rw-r--r--res/drawable/cylinderout_00022.pngbin0 -> 372 bytes
-rw-r--r--res/drawable/cylinderout_00023.pngbin0 -> 372 bytes
-rw-r--r--res/drawable/cylinderout_00024.pngbin0 -> 372 bytes
-rw-r--r--res/drawable/cylinderout_00025.pngbin0 -> 372 bytes
-rw-r--r--res/drawable/cylinderout_00026.pngbin0 -> 372 bytes
-rw-r--r--res/drawable/cylinderout_00027.pngbin0 -> 372 bytes
-rw-r--r--res/drawable/cylinderout_00028.pngbin0 -> 372 bytes
-rw-r--r--res/drawable/cylinderout_00029.pngbin0 -> 372 bytes
-rw-r--r--res/drawable/cylinderout_00030.pngbin0 -> 372 bytes
-rw-r--r--res/drawable/cylinderout_00031.pngbin0 -> 372 bytes
-rw-r--r--res/drawable/cylinderout_00032.pngbin0 -> 372 bytes
-rw-r--r--res/drawable/cylinderout_00033.pngbin0 -> 372 bytes
-rw-r--r--res/drawable/cylinderout_00034.pngbin0 -> 372 bytes
-rw-r--r--res/drawable/cylinderout_00035.pngbin0 -> 372 bytes
-rw-r--r--res/drawable/cylinderout_00036.pngbin0 -> 372 bytes
-rw-r--r--res/drawable/cylinderout_00037.pngbin0 -> 372 bytes
-rw-r--r--res/drawable/cylinderout_00038.pngbin0 -> 372 bytes
-rw-r--r--res/drawable/cylinderout_00039.pngbin0 -> 372 bytes
-rw-r--r--res/drawable/cylinderout_00040.pngbin0 -> 372 bytes
-rw-r--r--res/drawable/cylinderout_00041.pngbin0 -> 372 bytes
-rw-r--r--res/drawable/cylinderout_00042.pngbin0 -> 372 bytes
-rw-r--r--res/drawable/cylinderout_00043.pngbin0 -> 372 bytes
-rw-r--r--res/drawable/cylinderout_00044.pngbin0 -> 372 bytes
-rw-r--r--res/drawable/cylinderout_00045.pngbin0 -> 372 bytes
-rw-r--r--res/drawable/cylinderout_00046.pngbin0 -> 372 bytes
-rw-r--r--res/drawable/cylinderout_00047.pngbin0 -> 372 bytes
-rw-r--r--res/drawable/cylinderout_00048.pngbin0 -> 372 bytes
-rw-r--r--res/drawable/cylinderout_00049.pngbin0 -> 372 bytes
-rw-r--r--res/drawable/flip_00000.pngbin0 -> 178 bytes
-rw-r--r--res/drawable/flip_00001.pngbin0 -> 208 bytes
-rw-r--r--res/drawable/flip_00002.pngbin0 -> 221 bytes
-rw-r--r--res/drawable/flip_00003.pngbin0 -> 243 bytes
-rw-r--r--res/drawable/flip_00004.pngbin0 -> 346 bytes
-rw-r--r--res/drawable/flip_00005.pngbin0 -> 321 bytes
-rw-r--r--res/drawable/flip_00006.pngbin0 -> 364 bytes
-rw-r--r--res/drawable/flip_00007.pngbin0 -> 377 bytes
-rw-r--r--res/drawable/flip_00008.pngbin0 -> 359 bytes
-rw-r--r--res/drawable/flip_00009.pngbin0 -> 360 bytes
-rw-r--r--res/drawable/flip_00010.pngbin0 -> 359 bytes
-rw-r--r--res/drawable/flip_00011.pngbin0 -> 378 bytes
-rw-r--r--res/drawable/flip_00012.pngbin0 -> 378 bytes
-rw-r--r--res/drawable/flip_00013.pngbin0 -> 369 bytes
-rw-r--r--res/drawable/flip_00014.pngbin0 -> 341 bytes
-rw-r--r--res/drawable/flip_00015.pngbin0 -> 353 bytes
-rw-r--r--res/drawable/flip_00016.pngbin0 -> 325 bytes
-rw-r--r--res/drawable/flip_00017.pngbin0 -> 259 bytes
-rw-r--r--res/drawable/flip_00018.pngbin0 -> 204 bytes
-rw-r--r--res/drawable/flip_00019.pngbin0 -> 220 bytes
-rw-r--r--res/drawable/flip_00020.pngbin0 -> 178 bytes
-rw-r--r--res/drawable/flip_00021.pngbin0 -> 178 bytes
-rw-r--r--res/drawable/flip_00022.pngbin0 -> 178 bytes
-rw-r--r--res/drawable/flip_00023.pngbin0 -> 178 bytes
-rw-r--r--res/drawable/flip_00024.pngbin0 -> 178 bytes
-rw-r--r--res/drawable/flip_00025.pngbin0 -> 178 bytes
-rw-r--r--res/drawable/flip_00026.pngbin0 -> 178 bytes
-rw-r--r--res/drawable/flip_00027.pngbin0 -> 178 bytes
-rw-r--r--res/drawable/flip_00028.pngbin0 -> 178 bytes
-rw-r--r--res/drawable/flip_00029.pngbin0 -> 178 bytes
-rw-r--r--res/drawable/flip_00030.pngbin0 -> 178 bytes
-rw-r--r--res/drawable/flip_00031.pngbin0 -> 178 bytes
-rw-r--r--res/drawable/flip_00032.pngbin0 -> 178 bytes
-rw-r--r--res/drawable/flip_00033.pngbin0 -> 178 bytes
-rw-r--r--res/drawable/flip_00034.pngbin0 -> 178 bytes
-rw-r--r--res/drawable/flip_00035.pngbin0 -> 178 bytes
-rw-r--r--res/drawable/flip_00036.pngbin0 -> 178 bytes
-rw-r--r--res/drawable/flip_00037.pngbin0 -> 178 bytes
-rw-r--r--res/drawable/flip_00038.pngbin0 -> 178 bytes
-rw-r--r--res/drawable/flip_00039.pngbin0 -> 178 bytes
-rw-r--r--res/drawable/flip_00040.pngbin0 -> 178 bytes
-rw-r--r--res/drawable/flip_00041.pngbin0 -> 178 bytes
-rw-r--r--res/drawable/flip_00042.pngbin0 -> 178 bytes
-rw-r--r--res/drawable/flip_00043.pngbin0 -> 178 bytes
-rw-r--r--res/drawable/flip_00044.pngbin0 -> 178 bytes
-rw-r--r--res/drawable/flip_00045.pngbin0 -> 178 bytes
-rw-r--r--res/drawable/flip_00046.pngbin0 -> 178 bytes
-rw-r--r--res/drawable/flip_00047.pngbin0 -> 178 bytes
-rw-r--r--res/drawable/flip_00048.pngbin0 -> 178 bytes
-rw-r--r--res/drawable/flip_00049.pngbin0 -> 178 bytes
-rw-r--r--res/drawable/grid.pngbin0 -> 1971 bytes
-rw-r--r--res/drawable/grid_comfortable.pngbin0 -> 1984 bytes
-rw-r--r--res/drawable/grid_condensed.pngbin0 -> 2033 bytes
-rw-r--r--res/drawable/grid_cozy.pngbin0 -> 2006 bytes
-rw-r--r--res/drawable/handle.pngbin0 -> 442 bytes
-rw-r--r--res/drawable/handle_left.pngbin0 -> 370 bytes
-rw-r--r--res/drawable/handle_reversed.pngbin0 -> 442 bytes
-rw-r--r--res/drawable/launcheranimatedarrow_00000.pngbin0 -> 661 bytes
-rw-r--r--res/drawable/launcheranimatedarrow_00001.pngbin0 -> 749 bytes
-rw-r--r--res/drawable/launcheranimatedarrow_00002.pngbin0 -> 705 bytes
-rw-r--r--res/drawable/launcheranimatedarrow_00003.pngbin0 -> 746 bytes
-rw-r--r--res/drawable/launcheranimatedarrow_00004.pngbin0 -> 747 bytes
-rw-r--r--res/drawable/launcheranimatedarrow_00005.pngbin0 -> 664 bytes
-rw-r--r--res/drawable/launcheranimatedarrow_00006.pngbin0 -> 1007 bytes
-rw-r--r--res/drawable/launcheranimatedarrow_00007.pngbin0 -> 999 bytes
-rw-r--r--res/drawable/launcheranimatedarrow_00008.pngbin0 -> 710 bytes
-rw-r--r--res/drawable/launcheranimatedarrow_00009.pngbin0 -> 968 bytes
-rw-r--r--res/drawable/launcheranimatedarrow_00010.pngbin0 -> 990 bytes
-rw-r--r--res/drawable/launcheranimatedarrow_00011.pngbin0 -> 671 bytes
-rw-r--r--res/drawable/launcheranimatedarrow_00012.pngbin0 -> 744 bytes
-rw-r--r--res/drawable/launcheranimatedarrow_00013.pngbin0 -> 750 bytes
-rw-r--r--res/drawable/launcheranimatedarrow_00014.pngbin0 -> 747 bytes
-rw-r--r--res/drawable/launcheranimatedarrow_00015.pngbin0 -> 736 bytes
-rw-r--r--res/drawable/launcheranimatedarrow_00016.pngbin0 -> 668 bytes
-rw-r--r--res/drawable/listitem_bg.xml6
-rw-r--r--res/drawable/listitem_selector.xml6
-rw-r--r--res/drawable/none_00000.pngbin0 -> 215 bytes
-rw-r--r--res/drawable/none_00001.pngbin0 -> 234 bytes
-rw-r--r--res/drawable/none_00002.pngbin0 -> 247 bytes
-rw-r--r--res/drawable/none_00003.pngbin0 -> 222 bytes
-rw-r--r--res/drawable/none_00004.pngbin0 -> 265 bytes
-rw-r--r--res/drawable/none_00005.pngbin0 -> 246 bytes
-rw-r--r--res/drawable/none_00006.pngbin0 -> 258 bytes
-rw-r--r--res/drawable/none_00007.pngbin0 -> 250 bytes
-rw-r--r--res/drawable/none_00008.pngbin0 -> 256 bytes
-rw-r--r--res/drawable/none_00009.pngbin0 -> 247 bytes
-rw-r--r--res/drawable/none_00010.pngbin0 -> 253 bytes
-rw-r--r--res/drawable/none_00011.pngbin0 -> 261 bytes
-rw-r--r--res/drawable/none_00012.pngbin0 -> 274 bytes
-rw-r--r--res/drawable/none_00013.pngbin0 -> 252 bytes
-rw-r--r--res/drawable/none_00014.pngbin0 -> 263 bytes
-rw-r--r--res/drawable/none_00015.pngbin0 -> 267 bytes
-rw-r--r--res/drawable/none_00016.pngbin0 -> 232 bytes
-rw-r--r--res/drawable/none_00017.pngbin0 -> 222 bytes
-rw-r--r--res/drawable/none_00018.pngbin0 -> 219 bytes
-rw-r--r--res/drawable/none_00019.pngbin0 -> 223 bytes
-rw-r--r--res/drawable/none_00020.pngbin0 -> 220 bytes
-rw-r--r--res/drawable/none_00021.pngbin0 -> 220 bytes
-rw-r--r--res/drawable/none_00022.pngbin0 -> 220 bytes
-rw-r--r--res/drawable/none_00023.pngbin0 -> 220 bytes
-rw-r--r--res/drawable/none_00024.pngbin0 -> 220 bytes
-rw-r--r--res/drawable/none_00025.pngbin0 -> 220 bytes
-rw-r--r--res/drawable/none_00026.pngbin0 -> 220 bytes
-rw-r--r--res/drawable/none_00027.pngbin0 -> 220 bytes
-rw-r--r--res/drawable/none_00028.pngbin0 -> 220 bytes
-rw-r--r--res/drawable/none_00029.pngbin0 -> 220 bytes
-rw-r--r--res/drawable/none_00030.pngbin0 -> 220 bytes
-rw-r--r--res/drawable/none_00031.pngbin0 -> 220 bytes
-rw-r--r--res/drawable/none_00032.pngbin0 -> 220 bytes
-rw-r--r--res/drawable/none_00033.pngbin0 -> 220 bytes
-rw-r--r--res/drawable/none_00034.pngbin0 -> 220 bytes
-rw-r--r--res/drawable/none_00035.pngbin0 -> 220 bytes
-rw-r--r--res/drawable/none_00036.pngbin0 -> 220 bytes
-rw-r--r--res/drawable/none_00037.pngbin0 -> 220 bytes
-rw-r--r--res/drawable/none_00038.pngbin0 -> 220 bytes
-rw-r--r--res/drawable/none_00039.pngbin0 -> 220 bytes
-rw-r--r--res/drawable/none_00040.pngbin0 -> 220 bytes
-rw-r--r--res/drawable/none_00041.pngbin0 -> 220 bytes
-rw-r--r--res/drawable/none_00042.pngbin0 -> 220 bytes
-rw-r--r--res/drawable/none_00043.pngbin0 -> 220 bytes
-rw-r--r--res/drawable/none_00044.pngbin0 -> 220 bytes
-rw-r--r--res/drawable/none_00045.pngbin0 -> 220 bytes
-rw-r--r--res/drawable/none_00046.pngbin0 -> 220 bytes
-rw-r--r--res/drawable/none_00047.pngbin0 -> 220 bytes
-rw-r--r--res/drawable/none_00048.pngbin0 -> 220 bytes
-rw-r--r--res/drawable/none_00049.pngbin0 -> 220 bytes
-rw-r--r--res/drawable/overview_00000.pngbin0 -> 223 bytes
-rw-r--r--res/drawable/overview_00001.pngbin0 -> 268 bytes
-rw-r--r--res/drawable/overview_00002.pngbin0 -> 283 bytes
-rw-r--r--res/drawable/overview_00003.pngbin0 -> 265 bytes
-rw-r--r--res/drawable/overview_00004.pngbin0 -> 277 bytes
-rw-r--r--res/drawable/overview_00005.pngbin0 -> 251 bytes
-rw-r--r--res/drawable/overview_00006.pngbin0 -> 256 bytes
-rw-r--r--res/drawable/overview_00007.pngbin0 -> 242 bytes
-rw-r--r--res/drawable/overview_00008.pngbin0 -> 254 bytes
-rw-r--r--res/drawable/overview_00009.pngbin0 -> 265 bytes
-rw-r--r--res/drawable/overview_00010.pngbin0 -> 247 bytes
-rw-r--r--res/drawable/overview_00011.pngbin0 -> 266 bytes
-rw-r--r--res/drawable/overview_00012.pngbin0 -> 244 bytes
-rw-r--r--res/drawable/overview_00013.pngbin0 -> 240 bytes
-rw-r--r--res/drawable/overview_00014.pngbin0 -> 224 bytes
-rw-r--r--res/drawable/overview_00015.pngbin0 -> 244 bytes
-rw-r--r--res/drawable/overview_00016.pngbin0 -> 254 bytes
-rw-r--r--res/drawable/overview_00017.pngbin0 -> 246 bytes
-rw-r--r--res/drawable/overview_00018.pngbin0 -> 253 bytes
-rw-r--r--res/drawable/overview_00019.pngbin0 -> 259 bytes
-rw-r--r--res/drawable/overview_00020.pngbin0 -> 226 bytes
-rw-r--r--res/drawable/overview_00021.pngbin0 -> 226 bytes
-rw-r--r--res/drawable/overview_00022.pngbin0 -> 226 bytes
-rw-r--r--res/drawable/overview_00023.pngbin0 -> 226 bytes
-rw-r--r--res/drawable/overview_00024.pngbin0 -> 226 bytes
-rw-r--r--res/drawable/overview_00025.pngbin0 -> 226 bytes
-rw-r--r--res/drawable/overview_00026.pngbin0 -> 226 bytes
-rw-r--r--res/drawable/overview_00027.pngbin0 -> 226 bytes
-rw-r--r--res/drawable/overview_00028.pngbin0 -> 226 bytes
-rw-r--r--res/drawable/overview_00029.pngbin0 -> 226 bytes
-rw-r--r--res/drawable/overview_00030.pngbin0 -> 226 bytes
-rw-r--r--res/drawable/overview_00031.pngbin0 -> 226 bytes
-rw-r--r--res/drawable/overview_00032.pngbin0 -> 226 bytes
-rw-r--r--res/drawable/overview_00033.pngbin0 -> 226 bytes
-rw-r--r--res/drawable/overview_00034.pngbin0 -> 226 bytes
-rw-r--r--res/drawable/overview_00035.pngbin0 -> 226 bytes
-rw-r--r--res/drawable/overview_00036.pngbin0 -> 226 bytes
-rw-r--r--res/drawable/overview_00037.pngbin0 -> 226 bytes
-rw-r--r--res/drawable/overview_00038.pngbin0 -> 226 bytes
-rw-r--r--res/drawable/overview_00039.pngbin0 -> 226 bytes
-rw-r--r--res/drawable/overview_00040.pngbin0 -> 226 bytes
-rw-r--r--res/drawable/overview_00041.pngbin0 -> 226 bytes
-rw-r--r--res/drawable/overview_00042.pngbin0 -> 226 bytes
-rw-r--r--res/drawable/overview_00043.pngbin0 -> 226 bytes
-rw-r--r--res/drawable/overview_00044.pngbin0 -> 226 bytes
-rw-r--r--res/drawable/overview_00045.pngbin0 -> 226 bytes
-rw-r--r--res/drawable/overview_00046.pngbin0 -> 226 bytes
-rw-r--r--res/drawable/overview_00047.pngbin0 -> 226 bytes
-rw-r--r--res/drawable/overview_00048.pngbin0 -> 226 bytes
-rw-r--r--res/drawable/overview_00049.pngbin0 -> 226 bytes
-rw-r--r--res/drawable/rotatedown_00000.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/rotatedown_00001.pngbin0 -> 189 bytes
-rw-r--r--res/drawable/rotatedown_00002.pngbin0 -> 285 bytes
-rw-r--r--res/drawable/rotatedown_00003.pngbin0 -> 375 bytes
-rw-r--r--res/drawable/rotatedown_00004.pngbin0 -> 435 bytes
-rw-r--r--res/drawable/rotatedown_00005.pngbin0 -> 502 bytes
-rw-r--r--res/drawable/rotatedown_00006.pngbin0 -> 485 bytes
-rw-r--r--res/drawable/rotatedown_00007.pngbin0 -> 530 bytes
-rw-r--r--res/drawable/rotatedown_00008.pngbin0 -> 491 bytes
-rw-r--r--res/drawable/rotatedown_00009.pngbin0 -> 488 bytes
-rw-r--r--res/drawable/rotatedown_00010.pngbin0 -> 578 bytes
-rw-r--r--res/drawable/rotatedown_00011.pngbin0 -> 498 bytes
-rw-r--r--res/drawable/rotatedown_00012.pngbin0 -> 520 bytes
-rw-r--r--res/drawable/rotatedown_00013.pngbin0 -> 1100 bytes
-rw-r--r--res/drawable/rotatedown_00014.pngbin0 -> 1016 bytes
-rw-r--r--res/drawable/rotatedown_00015.pngbin0 -> 761 bytes
-rw-r--r--res/drawable/rotatedown_00016.pngbin0 -> 924 bytes
-rw-r--r--res/drawable/rotatedown_00017.pngbin0 -> 1024 bytes
-rw-r--r--res/drawable/rotatedown_00018.pngbin0 -> 514 bytes
-rw-r--r--res/drawable/rotatedown_00019.pngbin0 -> 479 bytes
-rw-r--r--res/drawable/rotatedown_00020.pngbin0 -> 532 bytes
-rw-r--r--res/drawable/rotatedown_00021.pngbin0 -> 519 bytes
-rw-r--r--res/drawable/rotatedown_00022.pngbin0 -> 491 bytes
-rw-r--r--res/drawable/rotatedown_00023.pngbin0 -> 533 bytes
-rw-r--r--res/drawable/rotatedown_00024.pngbin0 -> 482 bytes
-rw-r--r--res/drawable/rotatedown_00025.pngbin0 -> 465 bytes
-rw-r--r--res/drawable/rotatedown_00026.pngbin0 -> 429 bytes
-rw-r--r--res/drawable/rotatedown_00027.pngbin0 -> 384 bytes
-rw-r--r--res/drawable/rotatedown_00028.pngbin0 -> 280 bytes
-rw-r--r--res/drawable/rotatedown_00029.pngbin0 -> 205 bytes
-rw-r--r--res/drawable/rotatedown_00030.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/rotatedown_00031.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/rotatedown_00032.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/rotatedown_00033.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/rotatedown_00034.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/rotatedown_00035.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/rotatedown_00036.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/rotatedown_00037.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/rotatedown_00038.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/rotatedown_00039.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/rotatedown_00040.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/rotatedown_00041.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/rotatedown_00042.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/rotatedown_00043.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/rotatedown_00044.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/rotatedown_00045.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/rotatedown_00046.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/rotatedown_00047.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/rotatedown_00048.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/rotatedown_00049.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/rotateup_00000.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/rotateup_00001.pngbin0 -> 189 bytes
-rw-r--r--res/drawable/rotateup_00002.pngbin0 -> 285 bytes
-rw-r--r--res/drawable/rotateup_00003.pngbin0 -> 368 bytes
-rw-r--r--res/drawable/rotateup_00004.pngbin0 -> 432 bytes
-rw-r--r--res/drawable/rotateup_00005.pngbin0 -> 495 bytes
-rw-r--r--res/drawable/rotateup_00006.pngbin0 -> 485 bytes
-rw-r--r--res/drawable/rotateup_00007.pngbin0 -> 536 bytes
-rw-r--r--res/drawable/rotateup_00008.pngbin0 -> 495 bytes
-rw-r--r--res/drawable/rotateup_00009.pngbin0 -> 527 bytes
-rw-r--r--res/drawable/rotateup_00010.pngbin0 -> 569 bytes
-rw-r--r--res/drawable/rotateup_00011.pngbin0 -> 505 bytes
-rw-r--r--res/drawable/rotateup_00012.pngbin0 -> 517 bytes
-rw-r--r--res/drawable/rotateup_00013.pngbin0 -> 1114 bytes
-rw-r--r--res/drawable/rotateup_00014.pngbin0 -> 996 bytes
-rw-r--r--res/drawable/rotateup_00015.pngbin0 -> 768 bytes
-rw-r--r--res/drawable/rotateup_00016.pngbin0 -> 937 bytes
-rw-r--r--res/drawable/rotateup_00017.pngbin0 -> 1013 bytes
-rw-r--r--res/drawable/rotateup_00018.pngbin0 -> 517 bytes
-rw-r--r--res/drawable/rotateup_00019.pngbin0 -> 469 bytes
-rw-r--r--res/drawable/rotateup_00020.pngbin0 -> 587 bytes
-rw-r--r--res/drawable/rotateup_00021.pngbin0 -> 519 bytes
-rw-r--r--res/drawable/rotateup_00022.pngbin0 -> 479 bytes
-rw-r--r--res/drawable/rotateup_00023.pngbin0 -> 535 bytes
-rw-r--r--res/drawable/rotateup_00024.pngbin0 -> 486 bytes
-rw-r--r--res/drawable/rotateup_00025.pngbin0 -> 461 bytes
-rw-r--r--res/drawable/rotateup_00026.pngbin0 -> 438 bytes
-rw-r--r--res/drawable/rotateup_00027.pngbin0 -> 380 bytes
-rw-r--r--res/drawable/rotateup_00028.pngbin0 -> 274 bytes
-rw-r--r--res/drawable/rotateup_00029.pngbin0 -> 205 bytes
-rw-r--r--res/drawable/rotateup_00030.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/rotateup_00031.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/rotateup_00032.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/rotateup_00033.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/rotateup_00034.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/rotateup_00035.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/rotateup_00036.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/rotateup_00037.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/rotateup_00038.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/rotateup_00039.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/rotateup_00040.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/rotateup_00041.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/rotateup_00042.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/rotateup_00043.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/rotateup_00044.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/rotateup_00045.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/rotateup_00046.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/rotateup_00047.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/rotateup_00048.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/rotateup_00049.pngbin0 -> 173 bytes
-rw-r--r--res/drawable/stack_00000.pngbin0 -> 203 bytes
-rw-r--r--res/drawable/stack_00001.pngbin0 -> 217 bytes
-rw-r--r--res/drawable/stack_00002.pngbin0 -> 216 bytes
-rw-r--r--res/drawable/stack_00003.pngbin0 -> 216 bytes
-rw-r--r--res/drawable/stack_00004.pngbin0 -> 241 bytes
-rw-r--r--res/drawable/stack_00005.pngbin0 -> 246 bytes
-rw-r--r--res/drawable/stack_00006.pngbin0 -> 234 bytes
-rw-r--r--res/drawable/stack_00007.pngbin0 -> 240 bytes
-rw-r--r--res/drawable/stack_00008.pngbin0 -> 285 bytes
-rw-r--r--res/drawable/stack_00009.pngbin0 -> 295 bytes
-rw-r--r--res/drawable/stack_00010.pngbin0 -> 289 bytes
-rw-r--r--res/drawable/stack_00011.pngbin0 -> 284 bytes
-rw-r--r--res/drawable/stack_00012.pngbin0 -> 290 bytes
-rw-r--r--res/drawable/stack_00013.pngbin0 -> 278 bytes
-rw-r--r--res/drawable/stack_00014.pngbin0 -> 266 bytes
-rw-r--r--res/drawable/stack_00015.pngbin0 -> 294 bytes
-rw-r--r--res/drawable/stack_00016.pngbin0 -> 285 bytes
-rw-r--r--res/drawable/stack_00017.pngbin0 -> 272 bytes
-rw-r--r--res/drawable/stack_00018.pngbin0 -> 574 bytes
-rw-r--r--res/drawable/stack_00019.pngbin0 -> 213 bytes
-rw-r--r--res/drawable/stack_00020.pngbin0 -> 215 bytes
-rw-r--r--res/drawable/stack_00021.pngbin0 -> 215 bytes
-rw-r--r--res/drawable/stack_00022.pngbin0 -> 215 bytes
-rw-r--r--res/drawable/stack_00023.pngbin0 -> 215 bytes
-rw-r--r--res/drawable/stack_00024.pngbin0 -> 215 bytes
-rw-r--r--res/drawable/stack_00025.pngbin0 -> 215 bytes
-rw-r--r--res/drawable/stack_00026.pngbin0 -> 215 bytes
-rw-r--r--res/drawable/stack_00027.pngbin0 -> 215 bytes
-rw-r--r--res/drawable/stack_00028.pngbin0 -> 215 bytes
-rw-r--r--res/drawable/stack_00029.pngbin0 -> 215 bytes
-rw-r--r--res/drawable/stack_00030.pngbin0 -> 215 bytes
-rw-r--r--res/drawable/stack_00031.pngbin0 -> 215 bytes
-rw-r--r--res/drawable/stack_00032.pngbin0 -> 215 bytes
-rw-r--r--res/drawable/stack_00033.pngbin0 -> 215 bytes
-rw-r--r--res/drawable/stack_00034.pngbin0 -> 215 bytes
-rw-r--r--res/drawable/stack_00035.pngbin0 -> 215 bytes
-rw-r--r--res/drawable/stack_00036.pngbin0 -> 215 bytes
-rw-r--r--res/drawable/stack_00037.pngbin0 -> 215 bytes
-rw-r--r--res/drawable/stack_00038.pngbin0 -> 215 bytes
-rw-r--r--res/drawable/stack_00039.pngbin0 -> 215 bytes
-rw-r--r--res/drawable/stack_00040.pngbin0 -> 215 bytes
-rw-r--r--res/drawable/stack_00041.pngbin0 -> 215 bytes
-rw-r--r--res/drawable/stack_00042.pngbin0 -> 215 bytes
-rw-r--r--res/drawable/stack_00043.pngbin0 -> 215 bytes
-rw-r--r--res/drawable/stack_00044.pngbin0 -> 215 bytes
-rw-r--r--res/drawable/stack_00045.pngbin0 -> 215 bytes
-rw-r--r--res/drawable/stack_00046.pngbin0 -> 215 bytes
-rw-r--r--res/drawable/stack_00047.pngbin0 -> 215 bytes
-rw-r--r--res/drawable/stack_00048.pngbin0 -> 215 bytes
-rw-r--r--res/drawable/stack_00049.pngbin0 -> 215 bytes
-rw-r--r--res/drawable/themes_button.xml (renamed from res/drawable/setting_button.xml)6
-rw-r--r--res/drawable/transition_accordion.xml54
-rw-r--r--res/drawable/transition_arrow.xml21
-rw-r--r--res/drawable/transition_arrow_reverse.xml21
-rw-r--r--res/drawable/transition_carousel.xml55
-rw-r--r--res/drawable/transition_cubein.xml55
-rw-r--r--res/drawable/transition_cubeout.xml55
-rw-r--r--res/drawable/transition_cylinderin.xml55
-rw-r--r--res/drawable/transition_cylinderout.xml55
-rw-r--r--res/drawable/transition_flip.xml55
-rw-r--r--res/drawable/transition_none.xml55
-rw-r--r--res/drawable/transition_overview.xml55
-rw-r--r--res/drawable/transition_rotatedown.xml55
-rw-r--r--res/drawable/transition_rotateup.xml55
-rw-r--r--res/drawable/transition_stack.xml55
-rw-r--r--res/drawable/transition_zoomin.xml55
-rw-r--r--res/drawable/transition_zoomout.xml55
-rw-r--r--res/drawable/zoomin_00000.pngbin0 -> 231 bytes
-rw-r--r--res/drawable/zoomin_00001.pngbin0 -> 263 bytes
-rw-r--r--res/drawable/zoomin_00002.pngbin0 -> 279 bytes
-rw-r--r--res/drawable/zoomin_00003.pngbin0 -> 272 bytes
-rw-r--r--res/drawable/zoomin_00004.pngbin0 -> 287 bytes
-rw-r--r--res/drawable/zoomin_00005.pngbin0 -> 279 bytes
-rw-r--r--res/drawable/zoomin_00006.pngbin0 -> 285 bytes
-rw-r--r--res/drawable/zoomin_00007.pngbin0 -> 328 bytes
-rw-r--r--res/drawable/zoomin_00008.pngbin0 -> 303 bytes
-rw-r--r--res/drawable/zoomin_00009.pngbin0 -> 296 bytes
-rw-r--r--res/drawable/zoomin_00010.pngbin0 -> 307 bytes
-rw-r--r--res/drawable/zoomin_00011.pngbin0 -> 306 bytes
-rw-r--r--res/drawable/zoomin_00012.pngbin0 -> 300 bytes
-rw-r--r--res/drawable/zoomin_00013.pngbin0 -> 294 bytes
-rw-r--r--res/drawable/zoomin_00014.pngbin0 -> 308 bytes
-rw-r--r--res/drawable/zoomin_00015.pngbin0 -> 321 bytes
-rw-r--r--res/drawable/zoomin_00016.pngbin0 -> 321 bytes
-rw-r--r--res/drawable/zoomin_00017.pngbin0 -> 270 bytes
-rw-r--r--res/drawable/zoomin_00018.pngbin0 -> 248 bytes
-rw-r--r--res/drawable/zoomin_00019.pngbin0 -> 247 bytes
-rw-r--r--res/drawable/zoomin_00020.pngbin0 -> 246 bytes
-rw-r--r--res/drawable/zoomin_00021.pngbin0 -> 246 bytes
-rw-r--r--res/drawable/zoomin_00022.pngbin0 -> 246 bytes
-rw-r--r--res/drawable/zoomin_00023.pngbin0 -> 246 bytes
-rw-r--r--res/drawable/zoomin_00024.pngbin0 -> 246 bytes
-rw-r--r--res/drawable/zoomin_00025.pngbin0 -> 246 bytes
-rw-r--r--res/drawable/zoomin_00026.pngbin0 -> 246 bytes
-rw-r--r--res/drawable/zoomin_00027.pngbin0 -> 246 bytes
-rw-r--r--res/drawable/zoomin_00028.pngbin0 -> 246 bytes
-rw-r--r--res/drawable/zoomin_00029.pngbin0 -> 246 bytes
-rw-r--r--res/drawable/zoomin_00030.pngbin0 -> 246 bytes
-rw-r--r--res/drawable/zoomin_00031.pngbin0 -> 246 bytes
-rw-r--r--res/drawable/zoomin_00032.pngbin0 -> 246 bytes
-rw-r--r--res/drawable/zoomin_00033.pngbin0 -> 246 bytes
-rw-r--r--res/drawable/zoomin_00034.pngbin0 -> 246 bytes
-rw-r--r--res/drawable/zoomin_00035.pngbin0 -> 246 bytes
-rw-r--r--res/drawable/zoomin_00036.pngbin0 -> 246 bytes
-rw-r--r--res/drawable/zoomin_00037.pngbin0 -> 246 bytes
-rw-r--r--res/drawable/zoomin_00038.pngbin0 -> 246 bytes
-rw-r--r--res/drawable/zoomin_00039.pngbin0 -> 246 bytes
-rw-r--r--res/drawable/zoomin_00040.pngbin0 -> 246 bytes
-rw-r--r--res/drawable/zoomin_00041.pngbin0 -> 246 bytes
-rw-r--r--res/drawable/zoomin_00042.pngbin0 -> 246 bytes
-rw-r--r--res/drawable/zoomin_00043.pngbin0 -> 246 bytes
-rw-r--r--res/drawable/zoomin_00044.pngbin0 -> 246 bytes
-rw-r--r--res/drawable/zoomin_00045.pngbin0 -> 246 bytes
-rw-r--r--res/drawable/zoomin_00046.pngbin0 -> 246 bytes
-rw-r--r--res/drawable/zoomin_00047.pngbin0 -> 246 bytes
-rw-r--r--res/drawable/zoomin_00048.pngbin0 -> 246 bytes
-rw-r--r--res/drawable/zoomin_00049.pngbin0 -> 246 bytes
-rw-r--r--res/drawable/zoomout_00000.pngbin0 -> 286 bytes
-rw-r--r--res/drawable/zoomout_00001.pngbin0 -> 271 bytes
-rw-r--r--res/drawable/zoomout_00002.pngbin0 -> 295 bytes
-rw-r--r--res/drawable/zoomout_00003.pngbin0 -> 293 bytes
-rw-r--r--res/drawable/zoomout_00004.pngbin0 -> 334 bytes
-rw-r--r--res/drawable/zoomout_00005.pngbin0 -> 337 bytes
-rw-r--r--res/drawable/zoomout_00006.pngbin0 -> 342 bytes
-rw-r--r--res/drawable/zoomout_00007.pngbin0 -> 336 bytes
-rw-r--r--res/drawable/zoomout_00008.pngbin0 -> 343 bytes
-rw-r--r--res/drawable/zoomout_00009.pngbin0 -> 344 bytes
-rw-r--r--res/drawable/zoomout_00010.pngbin0 -> 336 bytes
-rw-r--r--res/drawable/zoomout_00011.pngbin0 -> 332 bytes
-rw-r--r--res/drawable/zoomout_00012.pngbin0 -> 333 bytes
-rw-r--r--res/drawable/zoomout_00013.pngbin0 -> 339 bytes
-rw-r--r--res/drawable/zoomout_00014.pngbin0 -> 346 bytes
-rw-r--r--res/drawable/zoomout_00015.pngbin0 -> 325 bytes
-rw-r--r--res/drawable/zoomout_00016.pngbin0 -> 372 bytes
-rw-r--r--res/drawable/zoomout_00017.pngbin0 -> 309 bytes
-rw-r--r--res/drawable/zoomout_00018.pngbin0 -> 292 bytes
-rw-r--r--res/drawable/zoomout_00019.pngbin0 -> 300 bytes
-rw-r--r--res/drawable/zoomout_00020.pngbin0 -> 279 bytes
-rw-r--r--res/drawable/zoomout_00021.pngbin0 -> 279 bytes
-rw-r--r--res/drawable/zoomout_00022.pngbin0 -> 279 bytes
-rw-r--r--res/drawable/zoomout_00023.pngbin0 -> 279 bytes
-rw-r--r--res/drawable/zoomout_00024.pngbin0 -> 279 bytes
-rw-r--r--res/drawable/zoomout_00025.pngbin0 -> 279 bytes
-rw-r--r--res/drawable/zoomout_00026.pngbin0 -> 279 bytes
-rw-r--r--res/drawable/zoomout_00027.pngbin0 -> 279 bytes
-rw-r--r--res/drawable/zoomout_00028.pngbin0 -> 279 bytes
-rw-r--r--res/drawable/zoomout_00029.pngbin0 -> 279 bytes
-rw-r--r--res/drawable/zoomout_00030.pngbin0 -> 279 bytes
-rw-r--r--res/drawable/zoomout_00031.pngbin0 -> 279 bytes
-rw-r--r--res/drawable/zoomout_00032.pngbin0 -> 279 bytes
-rw-r--r--res/drawable/zoomout_00033.pngbin0 -> 279 bytes
-rw-r--r--res/drawable/zoomout_00034.pngbin0 -> 279 bytes
-rw-r--r--res/drawable/zoomout_00035.pngbin0 -> 279 bytes
-rw-r--r--res/drawable/zoomout_00036.pngbin0 -> 279 bytes
-rw-r--r--res/drawable/zoomout_00037.pngbin0 -> 279 bytes
-rw-r--r--res/drawable/zoomout_00038.pngbin0 -> 279 bytes
-rw-r--r--res/drawable/zoomout_00039.pngbin0 -> 279 bytes
-rw-r--r--res/drawable/zoomout_00040.pngbin0 -> 279 bytes
-rw-r--r--res/drawable/zoomout_00041.pngbin0 -> 279 bytes
-rw-r--r--res/drawable/zoomout_00042.pngbin0 -> 279 bytes
-rw-r--r--res/drawable/zoomout_00043.pngbin0 -> 279 bytes
-rw-r--r--res/drawable/zoomout_00044.pngbin0 -> 279 bytes
-rw-r--r--res/drawable/zoomout_00045.pngbin0 -> 279 bytes
-rw-r--r--res/drawable/zoomout_00046.pngbin0 -> 279 bytes
-rw-r--r--res/drawable/zoomout_00047.pngbin0 -> 279 bytes
-rw-r--r--res/drawable/zoomout_00048.pngbin0 -> 279 bytes
-rw-r--r--res/drawable/zoomout_00049.pngbin0 -> 279 bytes
-rw-r--r--res/layout-land/folder_cling.xml5
-rw-r--r--res/layout-land/launcher.xml38
-rw-r--r--res/layout-land/migration_cling.xml100
-rw-r--r--res/layout-land/migration_workspace_cling.xml70
-rw-r--r--res/layout-land/qsb.xml (renamed from res/layout-land/search_bar.xml)0
-rw-r--r--res/layout-land/workspace_cling.xml63
-rw-r--r--res/layout-port/first_run_cling.xml4
-rw-r--r--res/layout-port/folder_cling.xml3
-rw-r--r--res/layout-port/launcher.xml23
-rw-r--r--res/layout-port/migration_cling.xml100
-rw-r--r--res/layout-port/migration_workspace_cling.xml (renamed from res/layout-port/all_apps_cling.xml)33
-rw-r--r--res/layout-port/qsb.xml (renamed from res/layout-sw720dp/search_bar.xml)7
-rw-r--r--res/layout-port/workspace_cling.xml1
-rw-r--r--res/layout-sw600dp-port/first_run_cling.xml100
-rw-r--r--res/layout-sw600dp-port/folder_cling.xml51
-rw-r--r--res/layout-sw600dp-port/migration_workspace_cling.xml70
-rw-r--r--res/layout-sw600dp/first_run_cling.xml100
-rw-r--r--res/layout-sw600dp/folder_cling.xml66
-rw-r--r--res/layout-sw600dp/migration_cling.xml98
-rw-r--r--res/layout-sw600dp/workspace_cling.xml (renamed from res/layout-land/all_apps_cling.xml)39
-rw-r--r--res/layout-sw720dp-port/folder_cling.xml46
-rw-r--r--res/layout-sw720dp/first_run_cling.xml98
-rw-r--r--res/layout-sw720dp/launcher.xml27
-rw-r--r--res/layout-sw720dp/market_button.xml4
-rw-r--r--res/layout-sw720dp/migration_workspace_cling.xml70
-rw-r--r--res/layout-sw720dp/qsb.xml (renamed from res/layout-port/search_bar.xml)6
-rw-r--r--res/layout/add_list_item.xml4
-rw-r--r--res/layout/apps_customize_pane.xml8
-rw-r--r--res/layout/apps_customize_widget.xml3
-rw-r--r--res/layout/appwidget_error.xml4
-rw-r--r--res/layout/custom_grid_size_dialog.xml33
-rw-r--r--res/layout/custom_workspace_cling.xml32
-rw-r--r--res/layout/dynamic_grid_size_screen.xml52
-rw-r--r--res/layout/folder_icon.xml5
-rw-r--r--res/layout/hidden_folder.xml51
-rw-r--r--res/layout/hidden_folder_apps_list_item.xml33
-rw-r--r--res/layout/iconpack_chooser.xml29
-rw-r--r--res/layout/market_button.xml4
-rw-r--r--res/layout/overview_panel.xml150
-rw-r--r--res/layout/search_drop_target_bar.xml (renamed from res/layout/qsb_bar.xml)3
-rw-r--r--res/layout/settings_pane.xml109
-rw-r--r--res/layout/settings_pane_list_header.xml19
-rw-r--r--res/layout/settings_pane_list_item.xml44
-rw-r--r--res/layout/settings_transitions_screen.xml52
-rw-r--r--res/layout/user_folder.xml50
-rw-r--r--res/layout/wallpaper_picker_clear.xml42
-rw-r--r--res/mipmap-xxhdpi/on_boarding_welcome.pngbin0 -> 50862 bytes
-rw-r--r--res/values-af/cm_arrays.xml13
-rw-r--r--res/values-af/cm_strings.xml62
-rw-r--r--res/values-ar/cm_arrays.xml11
-rw-r--r--res/values-ar/cm_strings.xml72
-rw-r--r--res/values-ca/cm_arrays.xml5
-rw-r--r--res/values-ca/cm_strings.xml72
-rw-r--r--res/values-cs/cm_arrays.xml13
-rw-r--r--res/values-cs/cm_strings.xml72
-rw-r--r--res/values-da/cm_arrays.xml17
-rw-r--r--res/values-da/cm_strings.xml72
-rw-r--r--res/values-de/cm_arrays.xml5
-rw-r--r--res/values-de/cm_strings.xml72
-rw-r--r--res/values-el/cm_arrays.xml5
-rw-r--r--res/values-el/cm_strings.xml72
-rw-r--r--res/values-en/dimens.xml24
-rw-r--r--res/values-es-rXA/cm_arrays.xml13
-rw-r--r--res/values-es-rXA/cm_strings.xml72
-rw-r--r--res/values-es/cm_arrays.xml5
-rw-r--r--res/values-es/cm_strings.xml72
-rw-r--r--res/values-et/cm_arrays.xml21
-rw-r--r--res/values-et/cm_strings.xml72
-rw-r--r--res/values-fi/cm_arrays.xml5
-rw-r--r--res/values-fi/cm_strings.xml72
-rw-r--r--res/values-fr/cm_arrays.xml9
-rw-r--r--res/values-fr/cm_strings.xml72
-rw-r--r--res/values-hu/cm_arrays.xml9
-rw-r--r--res/values-hu/cm_strings.xml72
-rw-r--r--res/values-in/cm_arrays.xml23
-rw-r--r--res/values-in/cm_strings.xml72
-rw-r--r--res/values-it/cm_arrays.xml7
-rw-r--r--res/values-it/cm_strings.xml72
-rw-r--r--res/values-iw/cm_arrays.xml17
-rw-r--r--res/values-iw/cm_strings.xml72
-rw-r--r--res/values-ja/cm_arrays.xml31
-rw-r--r--res/values-ja/cm_strings.xml72
-rw-r--r--res/values-ku/cm_arrays.xml35
-rw-r--r--res/values-ku/cm_strings.xml36
-rw-r--r--res/values-land/config.xml2
-rw-r--r--res/values-land/dimens.xml5
-rw-r--r--res/values-land/styles.xml10
-rw-r--r--res/values-lb/cm_arrays.xml21
-rw-r--r--res/values-lb/cm_strings.xml34
-rw-r--r--res/values-lt/cm_arrays.xml5
-rw-r--r--res/values-lt/cm_strings.xml72
-rw-r--r--res/values-nb/cm_arrays.xml5
-rw-r--r--res/values-nb/cm_strings.xml72
-rw-r--r--res/values-nl/cm_arrays.xml5
-rw-r--r--res/values-nl/cm_strings.xml72
-rw-r--r--res/values-nl/strings.xml2
-rw-r--r--res/values-pl/cm_arrays.xml19
-rw-r--r--res/values-pl/cm_strings.xml72
-rw-r--r--res/values-port/dimens.xml3
-rw-r--r--res/values-pt-rBR/cm_arrays.xml17
-rw-r--r--res/values-pt-rBR/cm_strings.xml72
-rw-r--r--res/values-pt-rPT/cm_arrays.xml19
-rw-r--r--res/values-pt-rPT/cm_strings.xml72
-rw-r--r--res/values-ro/cm_arrays.xml35
-rw-r--r--res/values-ro/cm_strings.xml52
-rw-r--r--res/values-ru/cm_arrays.xml5
-rw-r--r--res/values-ru/cm_strings.xml72
-rw-r--r--res/values-si/cm_arrays.xml5
-rw-r--r--res/values-si/cm_strings.xml72
-rw-r--r--res/values-sk/cm_arrays.xml9
-rw-r--r--res/values-sk/cm_strings.xml72
-rw-r--r--res/values-sr/cm_arrays.xml19
-rw-r--r--res/values-sr/cm_strings.xml72
-rw-r--r--res/values-sv/cm_arrays.xml19
-rw-r--r--res/values-sv/cm_strings.xml59
-rw-r--r--res/values-sw320dp/dimens.xml6
-rw-r--r--res/values-sw340dp-port/config.xml3
-rw-r--r--res/values-sw340dp/dimens.xml2
-rw-r--r--res/values-sw600dp-land/dimens.xml6
-rw-r--r--res/values-sw600dp/dimens.xml7
-rw-r--r--res/values-sw600dp/styles.xml29
-rw-r--r--res/values-sw720dp-land/dimens.xml3
-rw-r--r--res/values-sw720dp-port/dimens.xml1
-rw-r--r--res/values-sw720dp/dimens.xml6
-rw-r--r--res/values-sw720dp/styles.xml51
-rw-r--r--res/values-th/cm_arrays.xml9
-rw-r--r--res/values-th/cm_strings.xml72
-rw-r--r--res/values-tr/cm_arrays.xml17
-rw-r--r--res/values-tr/cm_strings.xml72
-rw-r--r--res/values-uk/cm_arrays.xml21
-rw-r--r--res/values-uk/cm_strings.xml45
-rw-r--r--res/values-v17/styles.xml9
-rw-r--r--res/values-zh-rCN/cm_arrays.xml5
-rw-r--r--res/values-zh-rCN/cm_strings.xml73
-rw-r--r--res/values-zh-rHK/cm_arrays.xml15
-rw-r--r--res/values-zh-rHK/cm_strings.xml55
-rw-r--r--res/values-zh-rTW/cm_arrays.xml35
-rw-r--r--res/values-zh-rTW/cm_strings.xml29
-rw-r--r--res/values/attrs.xml14
-rw-r--r--res/values/cm_arrays.xml43
-rw-r--r--res/values/cm_integers.xml21
-rw-r--r--res/values/cm_strings.xml120
-rw-r--r--res/values/colors.xml10
-rw-r--r--res/values/config.xml16
-rw-r--r--res/values/dimens.xml37
-rw-r--r--res/values/preferences_defaults.xml7
-rw-r--r--res/values/strings.xml64
-rw-r--r--res/values/styles.xml65
-rw-r--r--res/xml-sw600dp/default_workspace.xml75
-rw-r--r--res/xml-sw600dp/default_workspace_gapps.xml171
-rw-r--r--res/xml-sw600dp/default_workspace_no_telephony.xml75
-rw-r--r--res/xml-sw600dp/default_workspace_no_telephony_gapps.xml171
-rw-r--r--res/xml-sw720dp/default_workspace.xml75
-rw-r--r--res/xml-sw720dp/default_workspace_gapps.xml170
-rw-r--r--res/xml-sw720dp/default_workspace_no_telephony.xml75
-rw-r--r--res/xml-sw720dp/default_workspace_no_telephony_gapps.xml171
-rw-r--r--res/xml/default_workspace.xml66
-rw-r--r--res/xml/default_workspace_gapps.xml163
-rw-r--r--res/xml/default_workspace_no_all_apps.xml (renamed from res/drawable/iconpack_button.xml)12
-rw-r--r--res/xml/default_workspace_no_all_apps_gapps.xml56
-rw-r--r--res/xml/default_workspace_no_telephony.xml63
-rw-r--r--res/xml/default_workspace_no_telephony_gapps.xml154
-rw-r--r--res/xml/preferences_drawer.xml42
-rw-r--r--res/xml/preferences_general.xml34
-rw-r--r--res/xml/preferences_headers.xml41
-rw-r--r--res/xml/preferences_homescreen.xml29
-rw-r--r--src/com/android/launcher/home/Home.java201
-rw-r--r--src/com/android/launcher3/AddAdapter.java2
-rw-r--r--src/com/android/launcher3/Alarm.java4
-rw-r--r--src/com/android/launcher3/AllAppsList.java11
-rw-r--r--src/com/android/launcher3/AppInfo.java6
-rw-r--r--src/com/android/launcher3/AppWidgetResizeFrame.java2
-rw-r--r--src/com/android/launcher3/AppsCustomizeLayout.java12
-rw-r--r--src/com/android/launcher3/AppsCustomizePagedView.java174
-rw-r--r--src/com/android/launcher3/BubbleTextView.java9
-rw-r--r--src/com/android/launcher3/BuildInfo.java32
-rw-r--r--src/com/android/launcher3/ButtonDropTarget.java2
-rw-r--r--src/com/android/launcher3/CellLayout.java177
-rw-r--r--src/com/android/launcher3/Cling.java192
-rw-r--r--src/com/android/launcher3/DeferredHandler.java1
-rw-r--r--src/com/android/launcher3/DeleteDropTarget.java42
-rw-r--r--src/com/android/launcher3/DeviceProfile.java886
-rw-r--r--src/com/android/launcher3/DragController.java22
-rw-r--r--src/com/android/launcher3/DragLayer.java109
-rw-r--r--src/com/android/launcher3/DragSource.java16
-rw-r--r--src/com/android/launcher3/DragView.java15
-rw-r--r--src/com/android/launcher3/DrawableStateProxyView.java2
-rw-r--r--src/com/android/launcher3/DynamicGrid.java512
-rw-r--r--src/com/android/launcher3/DynamicGridSizeFragment.java331
-rw-r--r--src/com/android/launcher3/FastBitmapDrawable.java30
-rw-r--r--src/com/android/launcher3/FirstFrameAnimatorHelper.java9
-rw-r--r--src/com/android/launcher3/FocusHelper.java2
-rw-r--r--src/com/android/launcher3/Folder.java342
-rw-r--r--src/com/android/launcher3/FolderIcon.java77
-rw-r--r--src/com/android/launcher3/FolderInfo.java8
-rw-r--r--src/com/android/launcher3/GelIntegrationHelper.java102
-rw-r--r--src/com/android/launcher3/HiddenFolderFragment.java343
-rw-r--r--src/com/android/launcher3/Hotseat.java4
-rw-r--r--src/com/android/launcher3/IconCache.java245
-rw-r--r--src/com/android/launcher3/IconPackHelper.java517
-rw-r--r--src/com/android/launcher3/IconPickerActivity.java152
-rw-r--r--src/com/android/launcher3/InstallShortcutReceiver.java76
-rw-r--r--src/com/android/launcher3/InstallWidgetReceiver.java4
-rw-r--r--src/com/android/launcher3/ItemInfo.java6
-rw-r--r--src/com/android/launcher3/Launcher.java1477
-rw-r--r--src/com/android/launcher3/LauncherAnimUtils.java10
-rw-r--r--src/com/android/launcher3/LauncherAppState.java72
-rw-r--r--src/com/android/launcher3/LauncherAppWidgetHostView.java14
-rw-r--r--src/com/android/launcher3/LauncherBackupAgentHelper.java30
-rw-r--r--src/com/android/launcher3/LauncherBackupHelper.java323
-rw-r--r--src/com/android/launcher3/LauncherClings.java451
-rw-r--r--src/com/android/launcher3/LauncherModel.java741
-rw-r--r--src/com/android/launcher3/LauncherPreferencesBackupHelper.java44
-rw-r--r--src/com/android/launcher3/LauncherProvider.java510
-rw-r--r--src/com/android/launcher3/LauncherScroller.java559
-rw-r--r--src/com/android/launcher3/LauncherSettings.java19
-rw-r--r--src/com/android/launcher3/LauncherWallpaperPickerActivity.java30
-rw-r--r--src/com/android/launcher3/Lists.java64
-rw-r--r--src/com/android/launcher3/LockWallpaperPickerActivity.java1600
-rw-r--r--src/com/android/launcher3/OnAlarmListener.java5
-rw-r--r--src/com/android/launcher3/OverviewSettingsPanel.java233
-rw-r--r--src/com/android/launcher3/PageIndicator.java10
-rw-r--r--src/com/android/launcher3/PageIndicatorMarker.java8
-rw-r--r--src/com/android/launcher3/PagedView.java303
-rw-r--r--src/com/android/launcher3/PagedViewIcon.java12
-rw-r--r--src/com/android/launcher3/PagedViewIconCache.java10
-rw-r--r--src/com/android/launcher3/PagedViewWidget.java6
-rw-r--r--src/com/android/launcher3/PreloadReceiver.java9
-rw-r--r--src/com/android/launcher3/RampUpScroller.java120
-rw-r--r--src/com/android/launcher3/ScrimView.java3
-rw-r--r--src/com/android/launcher3/SearchDropTargetBar.java9
-rw-r--r--src/com/android/launcher3/ShortcutInfo.java32
-rw-r--r--src/com/android/launcher3/SlidingUpPanelLayout.java1315
-rw-r--r--src/com/android/launcher3/SmoothPagedView.java5
-rw-r--r--src/com/android/launcher3/ThemeChangedReceiver.java79
-rw-r--r--src/com/android/launcher3/TransitionEffectsFragment.java220
-rw-r--r--src/com/android/launcher3/Utilities.java83
-rw-r--r--src/com/android/launcher3/WallpaperChangedReceiver.java29
-rw-r--r--src/com/android/launcher3/WidgetPreviewLoader.java87
-rw-r--r--src/com/android/launcher3/Workspace.java751
-rw-r--r--src/com/android/launcher3/list/AutoScrollListView.java117
-rw-r--r--src/com/android/launcher3/list/CompositeCursorAdapter.java532
-rw-r--r--src/com/android/launcher3/list/PinnedHeaderListAdapter.java172
-rw-r--r--src/com/android/launcher3/list/PinnedHeaderListView.java565
-rw-r--r--src/com/android/launcher3/list/SettingsPinnedHeaderAdapter.java373
-rw-r--r--src/com/android/launcher3/settings/FontStylePreference.java142
-rw-r--r--src/com/android/launcher3/settings/HiddenAppsActivity.java302
-rw-r--r--src/com/android/launcher3/settings/SettingsActivity.java274
-rw-r--r--src/com/android/launcher3/settings/SettingsProvider.java15
-rw-r--r--src/com/android/photos/BitmapRegionTileSource.java288
-rw-r--r--src/org/cyanogenmod/trebuchet/TrebuchetLauncher.java331
-rw-r--r--src/org/cyanogenmod/trebuchet/home/HomeUtils.java112
-rw-r--r--src/org/cyanogenmod/trebuchet/home/HomeWrapper.java236
-rw-r--r--update_gallery_files.py2
-rw-r--r--update_system_wallpaper_cropper.py58
-rw-r--r--util/com/android/launcher3/DecoderRing.java335
-rw-r--r--util/etc/launcher_protoutil83
-rw-r--r--util/etc/manifest.txt1
1184 files changed, 18613 insertions, 9352 deletions
diff --git a/Android.mk b/Android.mk
index f5bdaca84..2d4b0a005 100644
--- a/Android.mk
+++ b/Android.mk
@@ -26,19 +26,23 @@ LOCAL_MODULE_TAGS := optional
LOCAL_STATIC_JAVA_LIBRARIES := android-support-v13
LOCAL_SRC_FILES := $(call all-java-files-under, src) \
+ $(call all-java-files-under, WallpaperPicker/src) \
$(call all-renderscript-files-under, src) \
$(call all-proto-files-under, protos)
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/WallpaperPicker/res $(LOCAL_PATH)/res
+
+LOCAL_AAPT_FLAGS := --auto-add-overlay
LOCAL_PROTOC_OPTIMIZE_TYPE := nano
LOCAL_PROTOC_FLAGS := --proto_path=$(LOCAL_PATH)/protos/
-#LOCAL_SDK_VERSION := 19
+# LOCAL_SDK_VERSION := 19
LOCAL_PACKAGE_NAME := Trebuchet
LOCAL_PRIVILEGED_MODULE := true
#LOCAL_CERTIFICATE := shared
-LOCAL_AAPT_FLAGS := --rename-manifest-package com.cyanogenmod.trebuchet
+LOCAL_AAPT_FLAGS += --rename-manifest-package com.cyanogenmod.trebuchet
LOCAL_OVERRIDES_PACKAGES := Launcher3
@@ -47,3 +51,41 @@ LOCAL_PROGUARD_FLAG_FILES := proguard.flags
include $(BUILD_PACKAGE)
include $(call all-makefiles-under,$(LOCAL_PATH))
+
+#
+# Protocol Buffer Debug Utility in Java
+#
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, util) \
+ $(call all-proto-files-under, protos)
+
+LOCAL_PROTOC_OPTIMIZE_TYPE := nano
+LOCAL_PROTOC_FLAGS := --proto_path=$(LOCAL_PATH)/protos/
+
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE := launcher_protoutil_lib
+LOCAL_IS_HOST_MODULE := true
+LOCAL_JAR_MANIFEST := util/etc/manifest.txt
+LOCAL_STATIC_JAVA_LIBRARIES := host-libprotobuf-java-2.3.0-nano
+
+include $(BUILD_HOST_JAVA_LIBRARY)
+
+#
+# Protocol Buffer Debug Utility Wrapper Script
+#
+include $(CLEAR_VARS)
+LOCAL_IS_HOST_MODULE := true
+LOCAL_MODULE_CLASS := EXECUTABLES
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE := launcher_protoutil
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): launcher_protoutil_lib
+$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/util/etc/launcher_protoutil | $(ACP)
+ @echo "Copy: $(PRIVATE_MODULE) ($@)"
+ $(copy-file-to-new-target)
+ $(hide) chmod 755 $@
+
+INTERNAL_DALVIK_MODULES += $(LOCAL_INSTALLED_MODULE)
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index ba7c8b4a7..8262f4886 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -25,12 +25,16 @@
<original-package android:name="com.android.launcher3" />
- <uses-sdk android:minSdkVersion="17" android:targetSdkVersion="19" />
+ <uses-sdk android:targetSdkVersion="19" android:minSdkVersion="16"/>
<permission
android:name="com.android.launcher3.permission.PRELOAD_WORKSPACE"
android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
- android:protectionLevel="system|signature" />
+ android:protectionLevel="signatureOrSystem" />
+ <permission
+ android:name="com.android.launcher.home.permissions.HOME_APP"
+ android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
+ android:protectionLevel="dangerous" />
<permission
android:name="com.android.launcher3.permission.READ_SETTINGS"
android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
@@ -40,7 +44,7 @@
<permission
android:name="com.android.launcher3.permission.WRITE_SETTINGS"
android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
- android:protectionLevel="dangerous"
+ android:protectionLevel="signatureOrSystem"
android:label="@string/permlab_write_settings"
android:description="@string/permdesc_write_settings"/>
@@ -52,16 +56,18 @@
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.SET_WALLPAPER" />
<uses-permission android:name="android.permission.SET_WALLPAPER_HINTS" />
- <uses-permission android:name="android.permission.SET_KEYGUARD_WALLPAPER" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.BIND_APPWIDGET" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.INJECT_EVENTS" />
+ <uses-permission android:name="android.permission.GET_TASKS"/>
<uses-permission android:name="com.android.launcher.permission.READ_SETTINGS" />
<uses-permission android:name="com.android.launcher.permission.WRITE_SETTINGS" />
<uses-permission android:name="com.android.launcher3.permission.READ_SETTINGS" />
<uses-permission android:name="com.android.launcher3.permission.WRITE_SETTINGS" />
<uses-permission android:name="com.android.launcher3.permission.RECEIVE_LAUNCH_BROADCASTS" />
+ <uses-permission android:name="cyanogenmod.permission.PROTECTED_APP" />
<application
android:name="com.android.launcher3.LauncherApplication"
@@ -71,7 +77,7 @@
android:largeHeap="@bool/config_largeHeap"
android:supportsRtl="true">
<activity
- android:name="com.android.launcher3.Launcher"
+ android:name="org.cyanogenmod.trebuchet.TrebuchetLauncher"
android:launchMode="singleTask"
android:clearTaskOnLaunch="true"
android:stateNotNeeded="true"
@@ -86,23 +92,13 @@
</intent-filter>
</activity>
- <activity android:name=".settings.SettingsActivity"
- android:label="@string/preferences_title">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.DEFAULT" />
- <category android:name="com.cyanogenmod.category.LAUNCHER_PREFERENCES" />
- </intent-filter>
- </activity>
-
<activity
- android:name=".settings.HiddenAppsActivity"
- android:label="@string/hidden_apps_title"
- android:exported="false">
- <intent-filter>
- <action android:name=".settings.HiddenAppsActivity" />
- <category android:name="android.intent.category.DEFAULT" />
- </intent-filter>
+ android:name="com.android.launcher3.LauncherWallpaperPickerActivity"
+ android:theme="@style/Theme.WallpaperCropper"
+ android:label="@string/pick_wallpaper"
+ android:icon="@mipmap/ic_launcher_wallpaper"
+ android:finishOnCloseSystemDialogs="true"
+ android:process=":wallpaper_chooser">
</activity>
<activity
@@ -147,6 +143,13 @@
</intent-filter>
</receiver>
+ <receiver
+ android:name="com.android.launcher3.WallpaperChangedReceiver">
+ <intent-filter>
+ <action android:name="android.intent.action.WALLPAPER_CHANGED" />
+ </intent-filter>
+ </receiver>
+
<!-- Intent received used to install shortcuts from other applications -->
<receiver
android:name="com.android.launcher3.InstallShortcutReceiver"
@@ -183,6 +186,12 @@
</intent-filter>
</receiver>
+ <receiver android:name="com.android.launcher3.ThemeChangedReceiver" >
+ <intent-filter>
+ <action android:name="org.cyanogenmod.intent.action.THEME_CHANGED"/>
+ </intent-filter>
+ </receiver>
+
<!-- The settings provider contains Home's data, like the workspace favorites -->
<provider
android:name="com.android.launcher3.LauncherProvider"
diff --git a/CleanSpec.mk b/CleanSpec.mk
index c1323951b..b2c5266fa 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -50,6 +50,8 @@ $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/Launcher2_interm
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/Launcher2_intermediates)
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/Launcher2_intermediates)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/Launcher2.apk)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/Launcher2_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/Launcher2.apk)
# ************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
diff --git a/WallpaperPicker/AndroidManifest.xml b/WallpaperPicker/AndroidManifest.xml
new file mode 100644
index 000000000..86a94d078
--- /dev/null
+++ b/WallpaperPicker/AndroidManifest.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.launcher3"
+ android:versionCode="1"
+ android:versionName="1.0"
+ >
+
+ <uses-sdk android:minSdkVersion="15" android:targetSdkVersion="19" />
+
+</manifest>
diff --git a/WallpaperPicker/README b/WallpaperPicker/README
new file mode 100644
index 000000000..d8efb07f6
--- /dev/null
+++ b/WallpaperPicker/README
@@ -0,0 +1,4 @@
+This project contains the wallpaper picker for Launcher3. It's in a separate
+folder to organize the code separately from the rest of the launcher, and has
+a manifest so that a separate Eclipse project can exist for the wallpaper
+picker (necessary to have the Eclipse build work) \ No newline at end of file
diff --git a/res/drawable-hdpi/ic_actionbar_accept.png b/WallpaperPicker/res/drawable-hdpi/ic_actionbar_accept.png
index 53cf6877e..53cf6877e 100755
--- a/res/drawable-hdpi/ic_actionbar_accept.png
+++ b/WallpaperPicker/res/drawable-hdpi/ic_actionbar_accept.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_images.png b/WallpaperPicker/res/drawable-hdpi/ic_images.png
index 0003c6c65..0003c6c65 100644
--- a/res/drawable-hdpi/ic_images.png
+++ b/WallpaperPicker/res/drawable-hdpi/ic_images.png
Binary files differ
diff --git a/res/drawable-hdpi/tile_picker_focused.9.png b/WallpaperPicker/res/drawable-hdpi/tile_picker_focused.9.png
index c72d6a2c6..c72d6a2c6 100644
--- a/res/drawable-hdpi/tile_picker_focused.9.png
+++ b/WallpaperPicker/res/drawable-hdpi/tile_picker_focused.9.png
Binary files differ
diff --git a/res/drawable-hdpi/tile_picker_pressed.9.png b/WallpaperPicker/res/drawable-hdpi/tile_picker_pressed.9.png
index 44c65ac3c..44c65ac3c 100644
--- a/res/drawable-hdpi/tile_picker_pressed.9.png
+++ b/WallpaperPicker/res/drawable-hdpi/tile_picker_pressed.9.png
Binary files differ
diff --git a/res/drawable-hdpi/tile_picker_selected.9.png b/WallpaperPicker/res/drawable-hdpi/tile_picker_selected.9.png
index 461bacbcb..461bacbcb 100644
--- a/res/drawable-hdpi/tile_picker_selected.9.png
+++ b/WallpaperPicker/res/drawable-hdpi/tile_picker_selected.9.png
Binary files differ
diff --git a/res/drawable-hdpi/tile_shadow_bottom.9.png b/WallpaperPicker/res/drawable-hdpi/tile_shadow_bottom.9.png
index e80558bad..e80558bad 100644
--- a/res/drawable-hdpi/tile_shadow_bottom.9.png
+++ b/WallpaperPicker/res/drawable-hdpi/tile_shadow_bottom.9.png
Binary files differ
diff --git a/res/drawable-hdpi/tile_shadow_top.9.png b/WallpaperPicker/res/drawable-hdpi/tile_shadow_top.9.png
index 7e93865e7..7e93865e7 100644
--- a/res/drawable-hdpi/tile_shadow_top.9.png
+++ b/WallpaperPicker/res/drawable-hdpi/tile_shadow_top.9.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_actionbar_accept.png b/WallpaperPicker/res/drawable-mdpi/ic_actionbar_accept.png
index 35cda8e11..35cda8e11 100755
--- a/res/drawable-mdpi/ic_actionbar_accept.png
+++ b/WallpaperPicker/res/drawable-mdpi/ic_actionbar_accept.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_images.png b/WallpaperPicker/res/drawable-mdpi/ic_images.png
index aabc1237a..aabc1237a 100644
--- a/res/drawable-mdpi/ic_images.png
+++ b/WallpaperPicker/res/drawable-mdpi/ic_images.png
Binary files differ
diff --git a/res/drawable-mdpi/tile_picker_focused.9.png b/WallpaperPicker/res/drawable-mdpi/tile_picker_focused.9.png
index 13b325b87..13b325b87 100644
--- a/res/drawable-mdpi/tile_picker_focused.9.png
+++ b/WallpaperPicker/res/drawable-mdpi/tile_picker_focused.9.png
Binary files differ
diff --git a/res/drawable-mdpi/tile_picker_pressed.9.png b/WallpaperPicker/res/drawable-mdpi/tile_picker_pressed.9.png
index 4e8196d36..4e8196d36 100644
--- a/res/drawable-mdpi/tile_picker_pressed.9.png
+++ b/WallpaperPicker/res/drawable-mdpi/tile_picker_pressed.9.png
Binary files differ
diff --git a/res/drawable-mdpi/tile_picker_selected.9.png b/WallpaperPicker/res/drawable-mdpi/tile_picker_selected.9.png
index eee69ec6d..eee69ec6d 100644
--- a/res/drawable-mdpi/tile_picker_selected.9.png
+++ b/WallpaperPicker/res/drawable-mdpi/tile_picker_selected.9.png
Binary files differ
diff --git a/res/drawable-mdpi/tile_shadow_bottom.9.png b/WallpaperPicker/res/drawable-mdpi/tile_shadow_bottom.9.png
index d95787bac..d95787bac 100644
--- a/res/drawable-mdpi/tile_shadow_bottom.9.png
+++ b/WallpaperPicker/res/drawable-mdpi/tile_shadow_bottom.9.png
Binary files differ
diff --git a/res/drawable-mdpi/tile_shadow_top.9.png b/WallpaperPicker/res/drawable-mdpi/tile_shadow_top.9.png
index 8da913cc4..8da913cc4 100644
--- a/res/drawable-mdpi/tile_shadow_top.9.png
+++ b/WallpaperPicker/res/drawable-mdpi/tile_shadow_top.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_actionbar_accept.png b/WallpaperPicker/res/drawable-xhdpi/ic_actionbar_accept.png
index b52dc3701..b52dc3701 100755
--- a/res/drawable-xhdpi/ic_actionbar_accept.png
+++ b/WallpaperPicker/res/drawable-xhdpi/ic_actionbar_accept.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_images.png b/WallpaperPicker/res/drawable-xhdpi/ic_images.png
index 3f21faf8f..3f21faf8f 100644
--- a/res/drawable-xhdpi/ic_images.png
+++ b/WallpaperPicker/res/drawable-xhdpi/ic_images.png
Binary files differ
diff --git a/res/drawable-xhdpi/tile_picker_focused.9.png b/WallpaperPicker/res/drawable-xhdpi/tile_picker_focused.9.png
index 279e85963..279e85963 100644
--- a/res/drawable-xhdpi/tile_picker_focused.9.png
+++ b/WallpaperPicker/res/drawable-xhdpi/tile_picker_focused.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/tile_picker_pressed.9.png b/WallpaperPicker/res/drawable-xhdpi/tile_picker_pressed.9.png
index abe0e0080..abe0e0080 100644
--- a/res/drawable-xhdpi/tile_picker_pressed.9.png
+++ b/WallpaperPicker/res/drawable-xhdpi/tile_picker_pressed.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/tile_picker_selected.9.png b/WallpaperPicker/res/drawable-xhdpi/tile_picker_selected.9.png
index b047591ac..b047591ac 100644
--- a/res/drawable-xhdpi/tile_picker_selected.9.png
+++ b/WallpaperPicker/res/drawable-xhdpi/tile_picker_selected.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/tile_shadow_bottom.9.png b/WallpaperPicker/res/drawable-xhdpi/tile_shadow_bottom.9.png
index 81571f3b7..81571f3b7 100644
--- a/res/drawable-xhdpi/tile_shadow_bottom.9.png
+++ b/WallpaperPicker/res/drawable-xhdpi/tile_shadow_bottom.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/tile_shadow_top.9.png b/WallpaperPicker/res/drawable-xhdpi/tile_shadow_top.9.png
index 8503a59fe..8503a59fe 100644
--- a/res/drawable-xhdpi/tile_shadow_top.9.png
+++ b/WallpaperPicker/res/drawable-xhdpi/tile_shadow_top.9.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_images.png b/WallpaperPicker/res/drawable-xxhdpi/ic_images.png
index d00db9a00..d00db9a00 100644
--- a/res/drawable-xxhdpi/ic_images.png
+++ b/WallpaperPicker/res/drawable-xxhdpi/ic_images.png
Binary files differ
diff --git a/res/drawable-xxhdpi/tile_picker_focused.9.png b/WallpaperPicker/res/drawable-xxhdpi/tile_picker_focused.9.png
index 1004c14b8..1004c14b8 100644
--- a/res/drawable-xxhdpi/tile_picker_focused.9.png
+++ b/WallpaperPicker/res/drawable-xxhdpi/tile_picker_focused.9.png
Binary files differ
diff --git a/res/drawable-xxhdpi/tile_picker_pressed.9.png b/WallpaperPicker/res/drawable-xxhdpi/tile_picker_pressed.9.png
index 9658444a1..9658444a1 100644
--- a/res/drawable-xxhdpi/tile_picker_pressed.9.png
+++ b/WallpaperPicker/res/drawable-xxhdpi/tile_picker_pressed.9.png
Binary files differ
diff --git a/res/drawable-xxhdpi/tile_picker_selected.9.png b/WallpaperPicker/res/drawable-xxhdpi/tile_picker_selected.9.png
index a3cd30369..a3cd30369 100644
--- a/res/drawable-xxhdpi/tile_picker_selected.9.png
+++ b/WallpaperPicker/res/drawable-xxhdpi/tile_picker_selected.9.png
Binary files differ
diff --git a/res/drawable-xxhdpi/tile_shadow_bottom.9.png b/WallpaperPicker/res/drawable-xxhdpi/tile_shadow_bottom.9.png
index 55250f041..55250f041 100644
--- a/res/drawable-xxhdpi/tile_shadow_bottom.9.png
+++ b/WallpaperPicker/res/drawable-xxhdpi/tile_shadow_bottom.9.png
Binary files differ
diff --git a/res/drawable-xxhdpi/tile_shadow_top.9.png b/WallpaperPicker/res/drawable-xxhdpi/tile_shadow_top.9.png
index 3f2263364..3f2263364 100644
--- a/res/drawable-xxhdpi/tile_shadow_top.9.png
+++ b/WallpaperPicker/res/drawable-xxhdpi/tile_shadow_top.9.png
Binary files differ
diff --git a/res/drawable/wallpaper_tile_fg.xml b/WallpaperPicker/res/drawable/wallpaper_tile_fg.xml
index c299f32c6..c299f32c6 100644
--- a/res/drawable/wallpaper_tile_fg.xml
+++ b/WallpaperPicker/res/drawable/wallpaper_tile_fg.xml
diff --git a/res/layout/actionbar_set_wallpaper.xml b/WallpaperPicker/res/layout/actionbar_set_wallpaper.xml
index 1622742a5..8e349b732 100644
--- a/res/layout/actionbar_set_wallpaper.xml
+++ b/WallpaperPicker/res/layout/actionbar_set_wallpaper.xml
@@ -18,17 +18,15 @@
*/
-->
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
- style="?android:actionButtonStyle"
+<com.android.launcher3.AlphaDisableableButton
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ style="@style/ActionBarSetWallpaperStyle"
+ android:id="@+id/set_wallpaper_button"
android:layout_width="match_parent"
- android:layout_height="match_parent" >
- <TextView style="?android:actionBarTabTextStyle"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="start|center_vertical"
- android:paddingRight="20dp"
- android:drawableLeft="@drawable/ic_actionbar_accept"
- android:drawablePadding="8dp"
- android:gravity="center_vertical"
- android:text="@string/wallpaper_instructions" />
-</FrameLayout>
+ android:layout_height="match_parent"
+ android:paddingRight="20dp"
+ android:drawableLeft="@drawable/ic_actionbar_accept"
+ android:drawablePadding="8dp"
+ android:gravity="start|center_vertical"
+ android:text="@string/wallpaper_instructions">
+</com.android.launcher3.AlphaDisableableButton>
diff --git a/res/layout/wallpaper_cropper.xml b/WallpaperPicker/res/layout/wallpaper_cropper.xml
index 3a3d98a69..abb860898 100644
--- a/res/layout/wallpaper_cropper.xml
+++ b/WallpaperPicker/res/layout/wallpaper_cropper.xml
@@ -32,7 +32,7 @@
android:visibility="invisible"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_gravity="center"
+ android:layout_centerInParent="true"
android:indeterminate="true"
android:indeterminateOnly="true"
android:background="@android:color/transparent" />
diff --git a/res/layout/wallpaper_picker.xml b/WallpaperPicker/res/layout/wallpaper_picker.xml
index c91cc7e6a..c36493d2f 100644
--- a/res/layout/wallpaper_picker.xml
+++ b/WallpaperPicker/res/layout/wallpaper_picker.xml
@@ -33,7 +33,7 @@
android:visibility="invisible"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_gravity="center"
+ android:layout_centerInParent="true"
android:indeterminate="true"
android:indeterminateOnly="true"
android:background="@android:color/transparent" />
diff --git a/res/layout/wallpaper_picker_image_picker_item.xml b/WallpaperPicker/res/layout/wallpaper_picker_image_picker_item.xml
index ae3c43d8e..ae3c43d8e 100644
--- a/res/layout/wallpaper_picker_image_picker_item.xml
+++ b/WallpaperPicker/res/layout/wallpaper_picker_image_picker_item.xml
diff --git a/res/layout/wallpaper_picker_item.xml b/WallpaperPicker/res/layout/wallpaper_picker_item.xml
index 0ac8f97fb..0ac8f97fb 100644
--- a/res/layout/wallpaper_picker_item.xml
+++ b/WallpaperPicker/res/layout/wallpaper_picker_item.xml
diff --git a/res/layout/wallpaper_picker_live_wallpaper_item.xml b/WallpaperPicker/res/layout/wallpaper_picker_live_wallpaper_item.xml
index 29fdb1b82..29fdb1b82 100644
--- a/res/layout/wallpaper_picker_live_wallpaper_item.xml
+++ b/WallpaperPicker/res/layout/wallpaper_picker_live_wallpaper_item.xml
diff --git a/res/layout/wallpaper_picker_third_party_item.xml b/WallpaperPicker/res/layout/wallpaper_picker_third_party_item.xml
index 68661bc00..68661bc00 100644
--- a/res/layout/wallpaper_picker_third_party_item.xml
+++ b/WallpaperPicker/res/layout/wallpaper_picker_third_party_item.xml
diff --git a/res/menu/cab_delete_wallpapers.xml b/WallpaperPicker/res/menu/cab_delete_wallpapers.xml
index 38ac5c4d6..38ac5c4d6 100644
--- a/res/menu/cab_delete_wallpapers.xml
+++ b/WallpaperPicker/res/menu/cab_delete_wallpapers.xml
diff --git a/res/mipmap-hdpi/ic_launcher_wallpaper.png b/WallpaperPicker/res/mipmap-hdpi/ic_launcher_wallpaper.png
index affee851d..affee851d 100644
--- a/res/mipmap-hdpi/ic_launcher_wallpaper.png
+++ b/WallpaperPicker/res/mipmap-hdpi/ic_launcher_wallpaper.png
Binary files differ
diff --git a/res/mipmap-mdpi/ic_launcher_wallpaper.png b/WallpaperPicker/res/mipmap-mdpi/ic_launcher_wallpaper.png
index cb4443bdb..cb4443bdb 100644
--- a/res/mipmap-mdpi/ic_launcher_wallpaper.png
+++ b/WallpaperPicker/res/mipmap-mdpi/ic_launcher_wallpaper.png
Binary files differ
diff --git a/res/mipmap-xhdpi/ic_launcher_wallpaper.png b/WallpaperPicker/res/mipmap-xhdpi/ic_launcher_wallpaper.png
index 60f8dceec..60f8dceec 100644
--- a/res/mipmap-xhdpi/ic_launcher_wallpaper.png
+++ b/WallpaperPicker/res/mipmap-xhdpi/ic_launcher_wallpaper.png
Binary files differ
diff --git a/res/mipmap-xxhdpi/ic_launcher_wallpaper.png b/WallpaperPicker/res/mipmap-xxhdpi/ic_launcher_wallpaper.png
index 023fb5886..023fb5886 100644
--- a/res/mipmap-xxhdpi/ic_launcher_wallpaper.png
+++ b/WallpaperPicker/res/mipmap-xxhdpi/ic_launcher_wallpaper.png
Binary files differ
diff --git a/res/values-nodpi/wallpapers.xml b/WallpaperPicker/res/values-nodpi/wallpapers.xml
index 1e340e4b2..1e340e4b2 100644
--- a/res/values-nodpi/wallpapers.xml
+++ b/WallpaperPicker/res/values-nodpi/wallpapers.xml
diff --git a/WallpaperPicker/res/values-sw600dp/config.xml b/WallpaperPicker/res/values-sw600dp/config.xml
new file mode 100644
index 000000000..62342dcc2
--- /dev/null
+++ b/WallpaperPicker/res/values-sw600dp/config.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <bool name="allow_rotation">true</bool>
+</resources>
diff --git a/WallpaperPicker/res/values-sw720dp-v19/styles.xml b/WallpaperPicker/res/values-sw720dp-v19/styles.xml
new file mode 100644
index 000000000..91078517d
--- /dev/null
+++ b/WallpaperPicker/res/values-sw720dp-v19/styles.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+-->
+
+<resources>
+ <style name="Theme" parent="android:Theme.Holo.Wallpaper.NoTitleBar">
+ <item name="android:windowActionModeOverlay">true</item>
+ <item name="android:windowTranslucentStatus">true</item>
+ <item name="android:windowTranslucentNavigation">true</item>
+ </style>
+</resources>
diff --git a/WallpaperPicker/res/values-sw720dp/dimens.xml b/WallpaperPicker/res/values-sw720dp/dimens.xml
new file mode 100644
index 000000000..9ae155b3c
--- /dev/null
+++ b/WallpaperPicker/res/values-sw720dp/dimens.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resources>
+ <dimen name="app_icon_size">72dp</dimen>
+
+<!-- QSB -->
+ <dimen name="toolbar_button_vertical_padding">8dip</dimen>
+ <dimen name="toolbar_button_horizontal_padding">8dip</dimen>
+
+ <!-- When dragging items on the workspace, the number of dps by which the position of
+ the drag view should be offset from the position of the original view. -->
+ <dimen name="dragViewOffsetX">0dp</dimen>
+ <dimen name="dragViewOffsetY">0dp</dimen>
+</resources>
diff --git a/WallpaperPicker/res/values-sw720dp/styles.xml b/WallpaperPicker/res/values-sw720dp/styles.xml
new file mode 100644
index 000000000..b48909087
--- /dev/null
+++ b/WallpaperPicker/res/values-sw720dp/styles.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+-->
+
+<resources>
+ <style name="Theme" parent="android:Theme.Holo.Wallpaper.NoTitleBar">
+ <item name="android:windowActionModeOverlay">true</item>
+ </style>
+</resources>
diff --git a/WallpaperPicker/res/values-v19/styles.xml b/WallpaperPicker/res/values-v19/styles.xml
new file mode 100644
index 000000000..85a989d55
--- /dev/null
+++ b/WallpaperPicker/res/values-v19/styles.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+-->
+
+<resources>
+ <style name="Theme.WallpaperCropper" parent="@android:style/Theme.Holo">
+ <item name="android:actionBarStyle">@style/WallpaperCropperActionBar</item>
+ <item name="android:windowFullscreen">true</item>
+ <item name="android:windowActionBarOverlay">true</item>
+ <item name="android:windowTranslucentNavigation">true</item>
+ </style>
+
+ <style name="Theme" parent="@android:style/Theme.Holo.Wallpaper.NoTitleBar">
+ <item name="android:windowTranslucentStatus">true</item>
+ <item name="android:windowTranslucentNavigation">true</item>
+ </style>
+</resources>
diff --git a/WallpaperPicker/res/values/colors.xml b/WallpaperPicker/res/values/colors.xml
new file mode 100644
index 000000000..adae7cff6
--- /dev/null
+++ b/WallpaperPicker/res/values/colors.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/assets/res/any/colors.xml
+**
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources>
+ <color name="wallpaper_picker_translucent_gray">#66000000</color>
+</resources>
diff --git a/WallpaperPicker/res/values/config.xml b/WallpaperPicker/res/values/config.xml
new file mode 100644
index 000000000..71580b5b0
--- /dev/null
+++ b/WallpaperPicker/res/values/config.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <bool name="allow_rotation">false</bool>
+ <!-- Specifies whether to expand the cropped area on both sides (rather
+ than just to one side) -->
+ <bool name="center_crop">false</bool>
+</resources>
diff --git a/res/layout/list_item_checkable.xml b/WallpaperPicker/res/values/dimens.xml
index 86d6b1a4c..0447c6d1f 100644
--- a/res/layout/list_item_checkable.xml
+++ b/WallpaperPicker/res/values/dimens.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 The Android Open Source Project
+<!-- Copyright (C) 2013 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -13,14 +13,10 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:minHeight="?android:attr/listPreferredItemHeightSmall"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textColor="?android:attr/textColorAlertDialogListItem"
- android:gravity="center_vertical"
- android:paddingStart="16dip"
- android:paddingEnd="16dip"
- android:checkMark="?android:attr/listChoiceIndicatorSingle"
- android:ellipsize="marquee" />
+
+<resources>
+<!-- Wallpaper picker -->
+ <dimen name="wallpaperThumbnailWidth">106.5dp</dimen>
+ <dimen name="wallpaperThumbnailHeight">94.5dp</dimen>
+ <dimen name="wallpaperItemIconSize">32dp</dimen>
+</resources>
diff --git a/WallpaperPicker/res/values/strings.xml b/WallpaperPicker/res/values/strings.xml
new file mode 100644
index 000000000..1ee3513f9
--- /dev/null
+++ b/WallpaperPicker/res/values/strings.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Button label on Wallpaper picker screen; user selects this button to set a specific wallpaper -->
+ <string name="wallpaper_instructions">Set wallpaper</string>
+ <!-- Error message when an image is selected as a wallpaper,
+ but the wallpaper picker cannot load it -->
+ <string name="image_load_fail">Coudn\'t load image</string>
+ <!-- Error message when an image is selected as a wallpaper,
+ but the wallpaper cropper cannot load it. The user will
+ usually see this when using another app and trying to set
+ an image as the wallpaper -->
+ <string name="wallpaper_load_fail">Couldn\'t load image as wallpaper</string>
+ <!-- Shown when wallpapers are selected in Wallpaper picker -->
+ <!-- String indicating how many media item(s) is(are) selected
+ eg. 1 selected [CHAR LIMIT=30] -->
+ <plurals name="number_of_items_selected">
+ <item quantity="zero">%1$d selected</item>
+ <item quantity="one">%1$d selected</item>
+ <item quantity="other">%1$d selected</item>
+ </plurals>
+ <!-- Accessibility string used as a label for a particular wallpaper in the Wallpaper Picker list.
+ e.g. "Wallpaper 3 of 10" -->
+ <string name="wallpaper_accessibility_name">Wallpaper %1$d of %2$d</string>
+ <!-- Accessibility string used to announce that a wallpaper has been selected. -->
+ <string name="announce_selection">Selected <xliff:g id="label" example="Wallpaper 3 of 10">%1$s</xliff:g></string>
+
+ <!-- Label on button to delete wallpaper(s) -->
+ <string name="wallpaper_delete">Delete</string>
+ <!-- Label on button in Wallpaper Picker to pick an image -->
+ <string name="pick_image">Pick image</string>
+ <!-- Option in "Select wallpaper from" dialog box -->
+ <string name="pick_wallpaper">Wallpapers</string>
+ <!-- Title of activity for cropping wallpapers -->
+ <string name="crop_wallpaper">Crop wallpaper</string>
+</resources>
diff --git a/WallpaperPicker/res/values/styles.xml b/WallpaperPicker/res/values/styles.xml
new file mode 100644
index 000000000..16b11f279
--- /dev/null
+++ b/WallpaperPicker/res/values/styles.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+* Copyright (C) 2013 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+-->
+
+<resources>
+ <style name="Theme.WallpaperCropper" parent="@android:style/Theme.Holo">
+ <item name="android:actionBarStyle">@style/WallpaperCropperActionBar</item>
+ <item name="android:windowFullscreen">true</item>
+ <item name="android:windowActionBarOverlay">true</item>
+ </style>
+
+ <style name="Theme.WallpaperPicker" parent="Theme.WallpaperCropper">
+ <item name="android:windowBackground">@android:color/transparent</item>
+ <item name="android:colorBackgroundCacheHint">@null</item>
+ <item name="android:windowShowWallpaper">true</item>
+ </style>
+
+ <style name="WallpaperCropperActionBar" parent="android:style/Widget.Holo.ActionBar">
+ <item name="android:displayOptions">showCustom</item>
+ <item name="android:background">#88000000</item>
+ </style>
+
+ <style name="Theme" parent="@android:style/Theme.Holo.Wallpaper.NoTitleBar">
+ </style>
+
+ <style name="ActionBarSetWallpaperStyle" parent="@android:style/Widget.Holo.ActionButton">
+ <item name="android:textColor">#ffffffff</item>
+ </style>
+</resources>
diff --git a/src/com/android/gallery3d/common/BitmapUtils.java b/WallpaperPicker/src/com/android/gallery3d/common/BitmapUtils.java
index a671ed2b9..a671ed2b9 100644
--- a/src/com/android/gallery3d/common/BitmapUtils.java
+++ b/WallpaperPicker/src/com/android/gallery3d/common/BitmapUtils.java
diff --git a/src/com/android/gallery3d/common/Utils.java b/WallpaperPicker/src/com/android/gallery3d/common/Utils.java
index 614a081c8..614a081c8 100644
--- a/src/com/android/gallery3d/common/Utils.java
+++ b/WallpaperPicker/src/com/android/gallery3d/common/Utils.java
diff --git a/src/com/android/gallery3d/exif/ByteBufferInputStream.java b/WallpaperPicker/src/com/android/gallery3d/exif/ByteBufferInputStream.java
index 7fb9f22cc..7fb9f22cc 100644
--- a/src/com/android/gallery3d/exif/ByteBufferInputStream.java
+++ b/WallpaperPicker/src/com/android/gallery3d/exif/ByteBufferInputStream.java
diff --git a/src/com/android/gallery3d/exif/CountedDataInputStream.java b/WallpaperPicker/src/com/android/gallery3d/exif/CountedDataInputStream.java
index dfd4a1a10..dfd4a1a10 100644
--- a/src/com/android/gallery3d/exif/CountedDataInputStream.java
+++ b/WallpaperPicker/src/com/android/gallery3d/exif/CountedDataInputStream.java
diff --git a/src/com/android/gallery3d/exif/ExifData.java b/WallpaperPicker/src/com/android/gallery3d/exif/ExifData.java
index 8422382bb..8422382bb 100644
--- a/src/com/android/gallery3d/exif/ExifData.java
+++ b/WallpaperPicker/src/com/android/gallery3d/exif/ExifData.java
diff --git a/src/com/android/gallery3d/exif/ExifInterface.java b/WallpaperPicker/src/com/android/gallery3d/exif/ExifInterface.java
index a1cf0fc85..a1cf0fc85 100644
--- a/src/com/android/gallery3d/exif/ExifInterface.java
+++ b/WallpaperPicker/src/com/android/gallery3d/exif/ExifInterface.java
diff --git a/src/com/android/gallery3d/exif/ExifInvalidFormatException.java b/WallpaperPicker/src/com/android/gallery3d/exif/ExifInvalidFormatException.java
index bf923ec26..bf923ec26 100644
--- a/src/com/android/gallery3d/exif/ExifInvalidFormatException.java
+++ b/WallpaperPicker/src/com/android/gallery3d/exif/ExifInvalidFormatException.java
diff --git a/src/com/android/gallery3d/exif/ExifModifier.java b/WallpaperPicker/src/com/android/gallery3d/exif/ExifModifier.java
index f00362b6b..0531cbad9 100644
--- a/src/com/android/gallery3d/exif/ExifModifier.java
+++ b/WallpaperPicker/src/com/android/gallery3d/exif/ExifModifier.java
@@ -18,7 +18,6 @@ package com.android.gallery3d.exif;
import android.util.Log;
-import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
diff --git a/src/com/android/gallery3d/exif/ExifOutputStream.java b/WallpaperPicker/src/com/android/gallery3d/exif/ExifOutputStream.java
index 7ca05f2e0..7ca05f2e0 100644
--- a/src/com/android/gallery3d/exif/ExifOutputStream.java
+++ b/WallpaperPicker/src/com/android/gallery3d/exif/ExifOutputStream.java
diff --git a/src/com/android/gallery3d/exif/ExifParser.java b/WallpaperPicker/src/com/android/gallery3d/exif/ExifParser.java
index 5467d423d..5467d423d 100644
--- a/src/com/android/gallery3d/exif/ExifParser.java
+++ b/WallpaperPicker/src/com/android/gallery3d/exif/ExifParser.java
diff --git a/src/com/android/gallery3d/exif/ExifReader.java b/WallpaperPicker/src/com/android/gallery3d/exif/ExifReader.java
index 68e972fb7..68e972fb7 100644
--- a/src/com/android/gallery3d/exif/ExifReader.java
+++ b/WallpaperPicker/src/com/android/gallery3d/exif/ExifReader.java
diff --git a/src/com/android/gallery3d/exif/ExifTag.java b/WallpaperPicker/src/com/android/gallery3d/exif/ExifTag.java
index b8b387201..b8b387201 100644
--- a/src/com/android/gallery3d/exif/ExifTag.java
+++ b/WallpaperPicker/src/com/android/gallery3d/exif/ExifTag.java
diff --git a/src/com/android/gallery3d/exif/IfdData.java b/WallpaperPicker/src/com/android/gallery3d/exif/IfdData.java
index 093944aec..093944aec 100644
--- a/src/com/android/gallery3d/exif/IfdData.java
+++ b/WallpaperPicker/src/com/android/gallery3d/exif/IfdData.java
diff --git a/src/com/android/gallery3d/exif/IfdId.java b/WallpaperPicker/src/com/android/gallery3d/exif/IfdId.java
index 7842edbd4..7842edbd4 100644
--- a/src/com/android/gallery3d/exif/IfdId.java
+++ b/WallpaperPicker/src/com/android/gallery3d/exif/IfdId.java
diff --git a/src/com/android/gallery3d/exif/JpegHeader.java b/WallpaperPicker/src/com/android/gallery3d/exif/JpegHeader.java
index e3e787eff..e3e787eff 100644
--- a/src/com/android/gallery3d/exif/JpegHeader.java
+++ b/WallpaperPicker/src/com/android/gallery3d/exif/JpegHeader.java
diff --git a/src/com/android/gallery3d/exif/OrderedDataOutputStream.java b/WallpaperPicker/src/com/android/gallery3d/exif/OrderedDataOutputStream.java
index 428e6b9fc..428e6b9fc 100644
--- a/src/com/android/gallery3d/exif/OrderedDataOutputStream.java
+++ b/WallpaperPicker/src/com/android/gallery3d/exif/OrderedDataOutputStream.java
diff --git a/src/com/android/gallery3d/exif/Rational.java b/WallpaperPicker/src/com/android/gallery3d/exif/Rational.java
index 591d63faf..591d63faf 100644
--- a/src/com/android/gallery3d/exif/Rational.java
+++ b/WallpaperPicker/src/com/android/gallery3d/exif/Rational.java
diff --git a/src/com/android/gallery3d/glrenderer/BasicTexture.java b/WallpaperPicker/src/com/android/gallery3d/glrenderer/BasicTexture.java
index 2e77b903f..2e77b903f 100644
--- a/src/com/android/gallery3d/glrenderer/BasicTexture.java
+++ b/WallpaperPicker/src/com/android/gallery3d/glrenderer/BasicTexture.java
diff --git a/src/com/android/gallery3d/glrenderer/BitmapTexture.java b/WallpaperPicker/src/com/android/gallery3d/glrenderer/BitmapTexture.java
index 100b0b3b9..100b0b3b9 100644
--- a/src/com/android/gallery3d/glrenderer/BitmapTexture.java
+++ b/WallpaperPicker/src/com/android/gallery3d/glrenderer/BitmapTexture.java
diff --git a/src/com/android/gallery3d/glrenderer/GLCanvas.java b/WallpaperPicker/src/com/android/gallery3d/glrenderer/GLCanvas.java
index 305e90521..5b0747704 100644
--- a/src/com/android/gallery3d/glrenderer/GLCanvas.java
+++ b/WallpaperPicker/src/com/android/gallery3d/glrenderer/GLCanvas.java
@@ -20,8 +20,6 @@ import android.graphics.Bitmap;
import android.graphics.Rect;
import android.graphics.RectF;
-import javax.microedition.khronos.opengles.GL11;
-
//
// GLCanvas gives a convenient interface to draw using OpenGL.
//
diff --git a/src/com/android/gallery3d/glrenderer/GLES20Canvas.java b/WallpaperPicker/src/com/android/gallery3d/glrenderer/GLES20Canvas.java
index 4ead1315e..4ead1315e 100644
--- a/src/com/android/gallery3d/glrenderer/GLES20Canvas.java
+++ b/WallpaperPicker/src/com/android/gallery3d/glrenderer/GLES20Canvas.java
diff --git a/src/com/android/gallery3d/glrenderer/GLES20IdImpl.java b/WallpaperPicker/src/com/android/gallery3d/glrenderer/GLES20IdImpl.java
index 6cd7149cb..6cd7149cb 100644
--- a/src/com/android/gallery3d/glrenderer/GLES20IdImpl.java
+++ b/WallpaperPicker/src/com/android/gallery3d/glrenderer/GLES20IdImpl.java
diff --git a/src/com/android/gallery3d/glrenderer/GLId.java b/WallpaperPicker/src/com/android/gallery3d/glrenderer/GLId.java
index 3cec558f6..3cec558f6 100644
--- a/src/com/android/gallery3d/glrenderer/GLId.java
+++ b/WallpaperPicker/src/com/android/gallery3d/glrenderer/GLId.java
diff --git a/src/com/android/gallery3d/glrenderer/GLPaint.java b/WallpaperPicker/src/com/android/gallery3d/glrenderer/GLPaint.java
index 16b220690..16b220690 100644
--- a/src/com/android/gallery3d/glrenderer/GLPaint.java
+++ b/WallpaperPicker/src/com/android/gallery3d/glrenderer/GLPaint.java
diff --git a/src/com/android/gallery3d/glrenderer/RawTexture.java b/WallpaperPicker/src/com/android/gallery3d/glrenderer/RawTexture.java
index 93f0fdff9..93f0fdff9 100644
--- a/src/com/android/gallery3d/glrenderer/RawTexture.java
+++ b/WallpaperPicker/src/com/android/gallery3d/glrenderer/RawTexture.java
diff --git a/src/com/android/gallery3d/glrenderer/Texture.java b/WallpaperPicker/src/com/android/gallery3d/glrenderer/Texture.java
index 3dcae4aec..3dcae4aec 100644
--- a/src/com/android/gallery3d/glrenderer/Texture.java
+++ b/WallpaperPicker/src/com/android/gallery3d/glrenderer/Texture.java
diff --git a/src/com/android/gallery3d/glrenderer/UploadedTexture.java b/WallpaperPicker/src/com/android/gallery3d/glrenderer/UploadedTexture.java
index f41a979b7..f41a979b7 100644
--- a/src/com/android/gallery3d/glrenderer/UploadedTexture.java
+++ b/WallpaperPicker/src/com/android/gallery3d/glrenderer/UploadedTexture.java
diff --git a/src/com/android/gallery3d/util/IntArray.java b/WallpaperPicker/src/com/android/gallery3d/util/IntArray.java
index 2c4dc2c83..2c4dc2c83 100644
--- a/src/com/android/gallery3d/util/IntArray.java
+++ b/WallpaperPicker/src/com/android/gallery3d/util/IntArray.java
diff --git a/WallpaperPicker/src/com/android/launcher3/AlphaDisableableButton.java b/WallpaperPicker/src/com/android/launcher3/AlphaDisableableButton.java
new file mode 100644
index 000000000..f0796c36f
--- /dev/null
+++ b/WallpaperPicker/src/com/android/launcher3/AlphaDisableableButton.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.launcher3;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.Button;
+
+/**
+ * A Button which becomes translucent when it is disabled
+ */
+public class AlphaDisableableButton extends Button {
+ public static float DISABLED_ALPHA_VALUE = 0.4f;
+ public AlphaDisableableButton(Context context) {
+ this(context, null);
+ }
+
+ public AlphaDisableableButton(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public AlphaDisableableButton(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ setLayerType(LAYER_TYPE_HARDWARE, null);
+ }
+
+ @Override
+ public void setEnabled(boolean enabled) {
+ super.setEnabled(enabled);
+ if(enabled) {
+ setAlpha(1.0f);
+ } else {
+ setAlpha(DISABLED_ALPHA_VALUE);
+ }
+ }
+}
diff --git a/src/com/android/launcher3/CheckableFrameLayout.java b/WallpaperPicker/src/com/android/launcher3/CheckableFrameLayout.java
index 5b7d82425..5b7d82425 100644
--- a/src/com/android/launcher3/CheckableFrameLayout.java
+++ b/WallpaperPicker/src/com/android/launcher3/CheckableFrameLayout.java
diff --git a/src/com/android/launcher3/CropView.java b/WallpaperPicker/src/com/android/launcher3/CropView.java
index 9224e3bb2..578b8eafd 100644
--- a/src/com/android/launcher3/CropView.java
+++ b/WallpaperPicker/src/com/android/launcher3/CropView.java
@@ -165,7 +165,8 @@ public class CropView extends TiledImageView implements OnScaleGestureListener {
final float imageWidth = imageDims[0];
final float imageHeight = imageDims[1];
mMinScale = Math.max(w / imageWidth, h / imageHeight);
- mRenderer.scale = Math.max(mMinScale, mRenderer.scale);
+ mRenderer.scale =
+ Math.max(mMinScale, resetScale ? Float.MIN_VALUE : mRenderer.scale);
}
}
}
diff --git a/WallpaperPicker/src/com/android/launcher3/DrawableTileSource.java b/WallpaperPicker/src/com/android/launcher3/DrawableTileSource.java
new file mode 100644
index 000000000..c1f2eff0f
--- /dev/null
+++ b/WallpaperPicker/src/com/android/launcher3/DrawableTileSource.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+
+import com.android.gallery3d.glrenderer.BasicTexture;
+import com.android.gallery3d.glrenderer.BitmapTexture;
+import com.android.photos.views.TiledImageRenderer;
+
+public class DrawableTileSource implements TiledImageRenderer.TileSource {
+ private static final int GL_SIZE_LIMIT = 2048;
+ // This must be no larger than half the size of the GL_SIZE_LIMIT
+ // due to decodePreview being allowed to be up to 2x the size of the target
+ public static final int MAX_PREVIEW_SIZE = GL_SIZE_LIMIT / 2;
+
+ private int mTileSize;
+ private int mPreviewSize;
+ private Drawable mDrawable;
+ private BitmapTexture mPreview;
+
+ public DrawableTileSource(Context context, Drawable d, int previewSize) {
+ mTileSize = TiledImageRenderer.suggestedTileSize(context);
+ mDrawable = d;
+ mPreviewSize = Math.min(previewSize, MAX_PREVIEW_SIZE);
+ }
+
+ @Override
+ public int getTileSize() {
+ return mTileSize;
+ }
+
+ @Override
+ public int getImageWidth() {
+ return mDrawable.getIntrinsicWidth();
+ }
+
+ @Override
+ public int getImageHeight() {
+ return mDrawable.getIntrinsicHeight();
+ }
+
+ @Override
+ public int getRotation() {
+ return 0;
+ }
+
+ @Override
+ public BasicTexture getPreview() {
+ if (mPreviewSize == 0) {
+ return null;
+ }
+ if (mPreview == null){
+ float width = getImageWidth();
+ float height = getImageHeight();
+ while (width > MAX_PREVIEW_SIZE || height > MAX_PREVIEW_SIZE) {
+ width /= 2;
+ height /= 2;
+ }
+ Bitmap b = Bitmap.createBitmap((int) width, (int) height, Bitmap.Config.ARGB_8888);
+ Canvas c = new Canvas(b);
+ mDrawable.setBounds(new Rect(0, 0, (int) width, (int) height));
+ mDrawable.draw(c);
+ c.setBitmap(null);
+ mPreview = new BitmapTexture(b);
+ }
+ return mPreview;
+ }
+
+ @Override
+ public Bitmap getTile(int level, int x, int y, Bitmap bitmap) {
+ int tileSize = getTileSize();
+ if (bitmap == null) {
+ bitmap = Bitmap.createBitmap(tileSize, tileSize, Bitmap.Config.ARGB_8888);
+ }
+ Canvas c = new Canvas(bitmap);
+ Rect bounds = new Rect(0, 0, getImageWidth(), getImageHeight());
+ bounds.offset(-x, -y);
+ mDrawable.setBounds(bounds);
+ mDrawable.draw(c);
+ c.setBitmap(null);
+ return bitmap;
+ }
+}
diff --git a/src/com/android/launcher3/LiveWallpaperListAdapter.java b/WallpaperPicker/src/com/android/launcher3/LiveWallpaperListAdapter.java
index 43d8cfe0c..88f4461bf 100644
--- a/src/com/android/launcher3/LiveWallpaperListAdapter.java
+++ b/WallpaperPicker/src/com/android/launcher3/LiveWallpaperListAdapter.java
@@ -118,13 +118,12 @@ public class LiveWallpaperListAdapter extends BaseAdapter implements ListAdapter
mInfo = info;
}
@Override
- public void onClick(WallpaperCropActivity a) {
+ public void onClick(WallpaperPickerActivity a) {
Intent preview = new Intent(WallpaperManager.ACTION_CHANGE_LIVE_WALLPAPER);
preview.putExtra(WallpaperManager.EXTRA_LIVE_WALLPAPER_COMPONENT,
mInfo.getComponent());
- a.onLiveWallpaperPickerLaunch();
- Utilities.startActivityForResultSafely(
- a, preview, WallpaperPickerActivity.PICK_LIVE_WALLPAPER);
+ a.onLiveWallpaperPickerLaunch(mInfo);
+ a.startActivityForResultSafely(preview, WallpaperPickerActivity.PICK_LIVE_WALLPAPER);
}
}
@@ -190,7 +189,9 @@ public class LiveWallpaperListAdapter extends BaseAdapter implements ListAdapter
LiveWallpaperListAdapter.this.notifyDataSetChanged();
break;
}
- info.mThumbnail.setDither(true);
+ if (info.mThumbnail != null) {
+ info.mThumbnail.setDither(true);
+ }
if (mWallpaperPosition < mWallpapers.size()) {
mWallpapers.set(mWallpaperPosition, info);
} else {
diff --git a/src/com/android/launcher3/SavedWallpaperImages.java b/WallpaperPicker/src/com/android/launcher3/SavedWallpaperImages.java
index a418b8f5c..44bfdf1f9 100644
--- a/src/com/android/launcher3/SavedWallpaperImages.java
+++ b/WallpaperPicker/src/com/android/launcher3/SavedWallpaperImages.java
@@ -49,7 +49,7 @@ public class SavedWallpaperImages extends BaseAdapter implements ListAdapter {
Context mContext;
LayoutInflater mLayoutInflater;
- public static class SavedWallpaperTile extends WallpaperCropActivity.WallpaperTileInfo {
+ public static class SavedWallpaperTile extends WallpaperPickerActivity.WallpaperTileInfo {
private int mDbId;
private Drawable mThumb;
public SavedWallpaperTile(int dbId, Drawable thumb) {
@@ -57,24 +57,21 @@ public class SavedWallpaperImages extends BaseAdapter implements ListAdapter {
mThumb = thumb;
}
@Override
- public void onClick(WallpaperCropActivity a) {
+ public void onClick(WallpaperPickerActivity a) {
String imageFilename = a.getSavedImages().getImageFilename(mDbId);
File file = new File(a.getFilesDir(), imageFilename);
- CropView v = a.getCropView();
- int rotation = WallpaperCropActivity.getRotationFromExif(file.getAbsolutePath());
- v.setTileSource(
- new BitmapRegionTileSource(a, file.getAbsolutePath(), 1024, rotation), null);
- v.moveToLeft();
- v.setTouchEnabled(false);
+ BitmapRegionTileSource.FilePathBitmapSource bitmapSource =
+ new BitmapRegionTileSource.FilePathBitmapSource(file.getAbsolutePath(), 1024);
+ a.setCropViewTileSource(bitmapSource, false, true, null);
}
@Override
- public void onSave(WallpaperCropActivity a) {
+ public void onSave(WallpaperPickerActivity a) {
boolean finishActivityWhenDone = true;
String imageFilename = a.getSavedImages().getImageFilename(mDbId);
a.setWallpaper(imageFilename, finishActivityWhenDone);
}
@Override
- public void onDelete(WallpaperCropActivity a) {
+ public void onDelete(WallpaperPickerActivity a) {
a.getSavedImages().deleteImage(mDbId);
}
@Override
@@ -88,6 +85,9 @@ public class SavedWallpaperImages extends BaseAdapter implements ListAdapter {
}
public SavedWallpaperImages(Activity context) {
+ // We used to store the saved images in the cache directory, but that meant they'd get
+ // deleted sometimes-- move them to the data directory
+ ImageDb.moveFromCacheDirectoryIfNecessary(context);
mDb = new ImageDb(context);
mContext = context;
mLayoutInflater = context.getLayoutInflater();
@@ -218,11 +218,20 @@ public class SavedWallpaperImages extends BaseAdapter implements ListAdapter {
Context mContext;
public ImageDb(Context context) {
- super(context, new File(context.getCacheDir(), DB_NAME).getPath(), null, DB_VERSION);
+ super(context, context.getDatabasePath(DB_NAME).getPath(), null, DB_VERSION);
// Store the context for later use
mContext = context;
}
+ public static void moveFromCacheDirectoryIfNecessary(Context context) {
+ // We used to store the saved images in the cache directory, but that meant they'd get
+ // deleted sometimes-- move them to the data directory
+ File oldSavedImagesFile = new File(context.getCacheDir(), ImageDb.DB_NAME);
+ File savedImagesFile = context.getDatabasePath(ImageDb.DB_NAME);
+ if (oldSavedImagesFile.exists()) {
+ oldSavedImagesFile.renameTo(savedImagesFile);
+ }
+ }
@Override
public void onCreate(SQLiteDatabase database) {
database.execSQL("CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " (" +
diff --git a/src/com/android/launcher3/ThirdPartyWallpaperPickerListAdapter.java b/WallpaperPicker/src/com/android/launcher3/ThirdPartyWallpaperPickerListAdapter.java
index 81cd5a0f0..7a4d48ca9 100644
--- a/src/com/android/launcher3/ThirdPartyWallpaperPickerListAdapter.java
+++ b/WallpaperPicker/src/com/android/launcher3/ThirdPartyWallpaperPickerListAdapter.java
@@ -51,13 +51,13 @@ public class ThirdPartyWallpaperPickerListAdapter extends BaseAdapter implements
mResolveInfo = resolveInfo;
}
@Override
- public void onClick(WallpaperCropActivity a) {
+ public void onClick(WallpaperPickerActivity a) {
final ComponentName itemComponentName = new ComponentName(
mResolveInfo.activityInfo.packageName, mResolveInfo.activityInfo.name);
Intent launchIntent = new Intent(Intent.ACTION_SET_WALLPAPER);
launchIntent.setComponent(itemComponentName);
- Utilities.startActivityForResultSafely(
- a, launchIntent, WallpaperPickerActivity.PICK_WALLPAPER_THIRD_PARTY_ACTIVITY);
+ a.startActivityForResultSafely(
+ launchIntent, WallpaperPickerActivity.PICK_WALLPAPER_THIRD_PARTY_ACTIVITY);
}
}
diff --git a/src/com/android/launcher3/WallpaperCropActivity.java b/WallpaperPicker/src/com/android/launcher3/WallpaperCropActivity.java
index 5796a5ddd..561c4bb6a 100644
--- a/src/com/android/launcher3/WallpaperCropActivity.java
+++ b/WallpaperPicker/src/com/android/launcher3/WallpaperCropActivity.java
@@ -37,15 +37,16 @@ import android.graphics.RectF;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
-import android.util.FloatMath;
import android.util.Log;
import android.view.Display;
import android.view.View;
import android.view.WindowManager;
+import android.widget.Toast;
import com.android.gallery3d.common.Utils;
import com.android.gallery3d.exif.ExifInterface;
import com.android.photos.BitmapRegionTileSource;
+import com.android.photos.BitmapRegionTileSource.BitmapSource;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
@@ -59,7 +60,7 @@ public class WallpaperCropActivity extends Activity {
protected static final String WALLPAPER_WIDTH_KEY = "wallpaper.width";
protected static final String WALLPAPER_HEIGHT_KEY = "wallpaper.height";
- protected static final int DEFAULT_COMPRESS_QUALITY = 90;
+ private static final int DEFAULT_COMPRESS_QUALITY = 90;
/**
* The maximum bitmap size we allow to be returned through the intent.
* Intents have a maximum of 1MB in total size. However, the Bitmap seems to
@@ -68,27 +69,13 @@ public class WallpaperCropActivity extends Activity {
* array instead of a Bitmap instance to avoid overhead.
*/
public static final int MAX_BMAP_IN_INTENT = 750000;
- protected static final float WALLPAPER_SCREENS_SPAN = 2f;
+ private static final float WALLPAPER_SCREENS_SPAN = 2f;
+
+ protected static Point sDefaultWallpaperSize;
protected CropView mCropView;
protected Uri mUri;
-
- public static abstract class WallpaperTileInfo {
- protected View mView;
- public void setView(View v) {
- mView = v;
- }
- public void onClick(WallpaperCropActivity a) {}
- public void onSave(WallpaperCropActivity a) {}
- public void onDelete(WallpaperCropActivity a) {}
- public boolean isSelectable() { return false; }
- public boolean isNamelessWallpaper() { return false; }
- public void onIndexUpdated(CharSequence label) {
- if (isNamelessWallpaper()) {
- mView.setContentDescription(label);
- }
- }
- }
+ protected View mSetWallpaperButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -113,9 +100,6 @@ public class WallpaperCropActivity extends Activity {
return;
}
- int rotation = getRotationFromExif(this, imageUri);
- mCropView.setTileSource(new BitmapRegionTileSource(this, imageUri, 1024, rotation), null);
- mCropView.setTouchEnabled(true);
// Action bar
// Show the custom action bar view
final ActionBar actionBar = getActionBar();
@@ -128,6 +112,67 @@ public class WallpaperCropActivity extends Activity {
cropImageAndSetWallpaper(imageUri, null, finishActivityWhenDone);
}
});
+ mSetWallpaperButton = findViewById(R.id.set_wallpaper_button);
+
+ // Load image in background
+ final BitmapRegionTileSource.UriBitmapSource bitmapSource =
+ new BitmapRegionTileSource.UriBitmapSource(this, imageUri, 1024);
+ mSetWallpaperButton.setEnabled(false);
+ Runnable onLoad = new Runnable() {
+ public void run() {
+ if (bitmapSource.getLoadingState() != BitmapSource.State.LOADED) {
+ Toast.makeText(WallpaperCropActivity.this,
+ getString(R.string.wallpaper_load_fail),
+ Toast.LENGTH_LONG).show();
+ finish();
+ } else {
+ mSetWallpaperButton.setEnabled(true);
+ }
+ }
+ };
+ setCropViewTileSource(bitmapSource, true, false, onLoad);
+ }
+
+ public void setCropViewTileSource(
+ final BitmapRegionTileSource.BitmapSource bitmapSource, final boolean touchEnabled,
+ final boolean moveToLeft, final Runnable postExecute) {
+ final Context context = WallpaperCropActivity.this;
+ final View progressView = findViewById(R.id.loading);
+ final AsyncTask<Void, Void, Void> loadBitmapTask = new AsyncTask<Void, Void, Void>() {
+ protected Void doInBackground(Void...args) {
+ if (!isCancelled()) {
+ bitmapSource.loadInBackground();
+ }
+ return null;
+ }
+ protected void onPostExecute(Void arg) {
+ if (!isCancelled()) {
+ progressView.setVisibility(View.INVISIBLE);
+ if (bitmapSource.getLoadingState() == BitmapSource.State.LOADED) {
+ mCropView.setTileSource(
+ new BitmapRegionTileSource(context, bitmapSource), null);
+ mCropView.setTouchEnabled(touchEnabled);
+ if (moveToLeft) {
+ mCropView.moveToLeft();
+ }
+ }
+ }
+ if (postExecute != null) {
+ postExecute.run();
+ }
+ }
+ };
+ // We don't want to show the spinner every time we load an image, because that would be
+ // annoying; instead, only start showing the spinner if loading the image has taken
+ // longer than 1 sec (ie 1000 ms)
+ progressView.postDelayed(new Runnable() {
+ public void run() {
+ if (loadBitmapTask.getStatus() != AsyncTask.Status.FINISHED) {
+ progressView.setVisibility(View.VISIBLE);
+ }
+ }
+ }, 1000);
+ loadBitmapTask.execute();
}
public boolean enableRotation() {
@@ -140,7 +185,7 @@ public class WallpaperCropActivity extends Activity {
// As a ratio of screen height, the total distance we want the parallax effect to span
// horizontally
- protected static float wallpaperTravelToScreenWidthRatio(int width, int height) {
+ private static float wallpaperTravelToScreenWidthRatio(int width, int height) {
float aspectRatio = width / (float) height;
// At an aspect ratio of 16/10, the wallpaper parallax effect should span 1.5 * screen width
@@ -166,32 +211,34 @@ public class WallpaperCropActivity extends Activity {
}
static protected Point getDefaultWallpaperSize(Resources res, WindowManager windowManager) {
- Point minDims = new Point();
- Point maxDims = new Point();
- windowManager.getDefaultDisplay().getCurrentSizeRange(minDims, maxDims);
-
- int maxDim = Math.max(maxDims.x, maxDims.y);
- int minDim = Math.max(minDims.x, minDims.y);
-
- if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) {
- Point realSize = new Point();
- windowManager.getDefaultDisplay().getRealSize(realSize);
- maxDim = Math.max(realSize.x, realSize.y);
- minDim = Math.min(realSize.x, realSize.y);
- }
+ if (sDefaultWallpaperSize == null) {
+ Point minDims = new Point();
+ Point maxDims = new Point();
+ windowManager.getDefaultDisplay().getCurrentSizeRange(minDims, maxDims);
+
+ int maxDim = Math.max(maxDims.x, maxDims.y);
+ int minDim = Math.max(minDims.x, minDims.y);
+
+ if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) {
+ Point realSize = new Point();
+ windowManager.getDefaultDisplay().getRealSize(realSize);
+ maxDim = Math.max(realSize.x, realSize.y);
+ minDim = Math.min(realSize.x, realSize.y);
+ }
- // We need to ensure that there is enough extra space in the wallpaper
- // for the intended
- // parallax effects
- final int defaultWidth, defaultHeight;
- if (isScreenLarge(res)) {
- defaultWidth = (int) (maxDim * wallpaperTravelToScreenWidthRatio(maxDim, minDim));
- defaultHeight = maxDim;
- } else {
- defaultWidth = Math.max((int) (minDim * WALLPAPER_SCREENS_SPAN), maxDim);
- defaultHeight = maxDim;
+ // We need to ensure that there is enough extra space in the wallpaper
+ // for the intended parallax effects
+ final int defaultWidth, defaultHeight;
+ if (isScreenLarge(res)) {
+ defaultWidth = (int) (maxDim * wallpaperTravelToScreenWidthRatio(maxDim, minDim));
+ defaultHeight = maxDim;
+ } else {
+ defaultWidth = Math.max((int) (minDim * WALLPAPER_SCREENS_SPAN), maxDim);
+ defaultHeight = maxDim;
+ }
+ sDefaultWallpaperSize = new Point(defaultWidth, defaultHeight);
}
- return new Point(defaultWidth, defaultHeight);
+ return sDefaultWallpaperSize;
}
public static int getRotationFromExif(String path) {
@@ -209,16 +256,18 @@ public class WallpaperCropActivity extends Activity {
private static int getRotationFromExifHelper(
String path, Resources res, int resId, Context context, Uri uri) {
ExifInterface ei = new ExifInterface();
+ InputStream is = null;
+ BufferedInputStream bis = null;
try {
if (path != null) {
ei.readExif(path);
} else if (uri != null) {
- InputStream is = context.getContentResolver().openInputStream(uri);
- BufferedInputStream bis = new BufferedInputStream(is);
+ is = context.getContentResolver().openInputStream(uri);
+ bis = new BufferedInputStream(is);
ei.readExif(bis);
} else {
- InputStream is = res.openRawResource(resId);
- BufferedInputStream bis = new BufferedInputStream(is);
+ is = res.openRawResource(resId);
+ bis = new BufferedInputStream(is);
ei.readExif(bis);
}
Integer ori = ei.getTagIntValue(ExifInterface.TAG_ORIENTATION);
@@ -228,7 +277,11 @@ public class WallpaperCropActivity extends Activity {
} catch (IOException e) {
Log.w(LOGTAG, "Getting exif data failed", e);
} catch (NullPointerException e) {
+ // Sometimes the ExifInterface has an internal NPE if Exif data isn't valid
Log.w(LOGTAG, "Getting exif data failed", e);
+ } finally {
+ Utils.closeSilently(bis);
+ Utils.closeSilently(is);
}
return 0;
}
@@ -278,50 +331,25 @@ public class WallpaperCropActivity extends Activity {
cropTask.execute();
}
- protected static boolean isScreenLarge(Resources res) {
+ private static boolean isScreenLarge(Resources res) {
Configuration config = res.getConfiguration();
return config.smallestScreenWidthDp >= 720;
}
protected void cropImageAndSetWallpaper(Uri uri,
OnBitmapCroppedHandler onBitmapCroppedHandler, final boolean finishActivityWhenDone) {
+ boolean centerCrop = getResources().getBoolean(R.bool.center_crop);
// Get the crop
boolean ltr = mCropView.getLayoutDirection() == View.LAYOUT_DIRECTION_LTR;
- Point minDims = new Point();
- Point maxDims = new Point();
Display d = getWindowManager().getDefaultDisplay();
- d.getCurrentSizeRange(minDims, maxDims);
Point displaySize = new Point();
d.getSize(displaySize);
-
- int maxDim = Math.max(maxDims.x, maxDims.y);
- final int minDim = Math.min(minDims.x, minDims.y);
- int defaultWallpaperWidth;
- if (isScreenLarge(getResources())) {
- defaultWallpaperWidth = (int) (maxDim *
- wallpaperTravelToScreenWidthRatio(maxDim, minDim));
- } else {
- defaultWallpaperWidth = Math.max((int)
- (minDim * WALLPAPER_SCREENS_SPAN), maxDim);
- }
-
boolean isPortrait = displaySize.x < displaySize.y;
- int portraitHeight;
- if (isPortrait) {
- portraitHeight = mCropView.getHeight();
- } else {
- // TODO: how to actually get the proper portrait height?
- // This is not quite right:
- portraitHeight = Math.max(maxDims.x, maxDims.y);
- }
- if (android.os.Build.VERSION.SDK_INT >=
- android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) {
- Point realSize = new Point();
- d.getRealSize(realSize);
- portraitHeight = Math.max(realSize.x, realSize.y);
- }
+
+ Point defaultWallpaperSize = getDefaultWallpaperSize(getResources(),
+ getWindowManager());
// Get the crop
RectF cropRect = mCropView.getCrop();
int cropRotation = mCropView.getImageRotation();
@@ -338,23 +366,33 @@ public class WallpaperCropActivity extends Activity {
// ADJUST CROP WIDTH
// Extend the crop all the way to the right, for parallax
// (or all the way to the left, in RTL)
- float extraSpace = ltr ? rotatedInSize[0] - cropRect.right : cropRect.left;
+ float extraSpace;
+ if (centerCrop) {
+ extraSpace = 2f * Math.min(rotatedInSize[0] - cropRect.right, cropRect.left);
+ } else {
+ extraSpace = ltr ? rotatedInSize[0] - cropRect.right : cropRect.left;
+ }
// Cap the amount of extra width
- float maxExtraSpace = defaultWallpaperWidth / cropScale - cropRect.width();
+ float maxExtraSpace = defaultWallpaperSize.x / cropScale - cropRect.width();
extraSpace = Math.min(extraSpace, maxExtraSpace);
- if (ltr) {
- cropRect.right += extraSpace;
+ if (centerCrop) {
+ cropRect.left -= extraSpace / 2f;
+ cropRect.right += extraSpace / 2f;
} else {
- cropRect.left -= extraSpace;
+ if (ltr) {
+ cropRect.right += extraSpace;
+ } else {
+ cropRect.left -= extraSpace;
+ }
}
// ADJUST CROP HEIGHT
if (isPortrait) {
- cropRect.bottom = cropRect.top + portraitHeight / cropScale;
+ cropRect.bottom = cropRect.top + defaultWallpaperSize.y / cropScale;
} else { // LANDSCAPE
float extraPortraitHeight =
- portraitHeight / cropScale - cropRect.height();
+ defaultWallpaperSize.y / cropScale - cropRect.height();
float expandHeight =
Math.min(Math.min(rotatedInSize[1] - cropRect.bottom, cropRect.top),
extraPortraitHeight / 2);
@@ -391,7 +429,6 @@ public class WallpaperCropActivity extends Activity {
String mInFilePath;
byte[] mInImageBytes;
int mInResId = 0;
- InputStream mInStream;
RectF mCropBounds = null;
int mOutWidth, mOutHeight;
int mRotation;
@@ -464,37 +501,36 @@ public class WallpaperCropActivity extends Activity {
}
// Helper to setup input stream
- private void regenerateInputStream() {
+ private InputStream regenerateInputStream() {
if (mInUri == null && mInResId == 0 && mInFilePath == null && mInImageBytes == null) {
Log.w(LOGTAG, "cannot read original file, no input URI, resource ID, or " +
"image byte array given");
} else {
- Utils.closeSilently(mInStream);
try {
if (mInUri != null) {
- mInStream = new BufferedInputStream(
+ return new BufferedInputStream(
mContext.getContentResolver().openInputStream(mInUri));
} else if (mInFilePath != null) {
- mInStream = mContext.openFileInput(mInFilePath);
+ return mContext.openFileInput(mInFilePath);
} else if (mInImageBytes != null) {
- mInStream = new BufferedInputStream(
- new ByteArrayInputStream(mInImageBytes));
+ return new BufferedInputStream(new ByteArrayInputStream(mInImageBytes));
} else {
- mInStream = new BufferedInputStream(
- mResources.openRawResource(mInResId));
+ return new BufferedInputStream(mResources.openRawResource(mInResId));
}
} catch (FileNotFoundException e) {
Log.w(LOGTAG, "cannot read file: " + mInUri.toString(), e);
}
}
+ return null;
}
public Point getImageBounds() {
- regenerateInputStream();
- if (mInStream != null) {
+ InputStream is = regenerateInputStream();
+ if (is != null) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
- BitmapFactory.decodeStream(mInStream, null, options);
+ BitmapFactory.decodeStream(is, null, options);
+ Utils.closeSilently(is);
if (options.outWidth != 0 && options.outHeight != 0) {
return new Point(options.outWidth, options.outHeight);
}
@@ -512,26 +548,32 @@ public class WallpaperCropActivity extends Activity {
public boolean cropBitmap() {
boolean failure = false;
- regenerateInputStream();
WallpaperManager wallpaperManager = null;
if (mSetWallpaper) {
wallpaperManager = WallpaperManager.getInstance(mContext.getApplicationContext());
}
- if (mSetWallpaper && mNoCrop && mInStream != null) {
+
+
+ if (mSetWallpaper && mNoCrop) {
try {
- wallpaperManager.setStream(mInStream);
+ InputStream is = regenerateInputStream();
+ if (is != null) {
+ wallpaperManager.setStream(is);
+ Utils.closeSilently(is);
+ }
} catch (IOException e) {
Log.w(LOGTAG, "cannot write stream to wallpaper", e);
failure = true;
}
return !failure;
- }
- if (mInStream != null) {
+ } else {
// Find crop bounds (scaled to original image size)
Rect roundedTrueCrop = new Rect();
Matrix rotateMatrix = new Matrix();
Matrix inverseRotateMatrix = new Matrix();
+
+ Point bounds = getImageBounds();
if (mRotation > 0) {
rotateMatrix.setRotate(mRotation);
inverseRotateMatrix.setRotate(-mRotation);
@@ -539,7 +581,11 @@ public class WallpaperCropActivity extends Activity {
mCropBounds.roundOut(roundedTrueCrop);
mCropBounds = new RectF(roundedTrueCrop);
- Point bounds = getImageBounds();
+ if (bounds == null) {
+ Log.w(LOGTAG, "cannot get bounds for image");
+ failure = true;
+ return false;
+ }
float[] rotatedBounds = new float[] { bounds.x, bounds.y };
rotateMatrix.mapPoints(rotatedBounds);
@@ -550,7 +596,6 @@ public class WallpaperCropActivity extends Activity {
inverseRotateMatrix.mapRect(mCropBounds);
mCropBounds.offset(bounds.x/2, bounds.y/2);
- regenerateInputStream();
}
mCropBounds.roundOut(roundedTrueCrop);
@@ -562,15 +607,25 @@ public class WallpaperCropActivity extends Activity {
}
// See how much we're reducing the size of the image
- int scaleDownSampleSize = Math.min(roundedTrueCrop.width() / mOutWidth,
- roundedTrueCrop.height() / mOutHeight);
-
+ int scaleDownSampleSize = Math.max(1, Math.min(roundedTrueCrop.width() / mOutWidth,
+ roundedTrueCrop.height() / mOutHeight));
// Attempt to open a region decoder
BitmapRegionDecoder decoder = null;
+ InputStream is = null;
try {
- decoder = BitmapRegionDecoder.newInstance(mInStream, true);
+ is = regenerateInputStream();
+ if (is == null) {
+ Log.w(LOGTAG, "cannot get input stream for uri=" + mInUri.toString());
+ failure = true;
+ return false;
+ }
+ decoder = BitmapRegionDecoder.newInstance(is, false);
+ Utils.closeSilently(is);
} catch (IOException e) {
Log.w(LOGTAG, "cannot open region decoder for file: " + mInUri.toString(), e);
+ } finally {
+ Utils.closeSilently(is);
+ is = null;
}
Bitmap crop = null;
@@ -586,22 +641,49 @@ public class WallpaperCropActivity extends Activity {
if (crop == null) {
// BitmapRegionDecoder has failed, try to crop in-memory
- regenerateInputStream();
+ is = regenerateInputStream();
Bitmap fullSize = null;
- if (mInStream != null) {
+ if (is != null) {
BitmapFactory.Options options = new BitmapFactory.Options();
if (scaleDownSampleSize > 1) {
options.inSampleSize = scaleDownSampleSize;
}
- fullSize = BitmapFactory.decodeStream(mInStream, null, options);
+ fullSize = BitmapFactory.decodeStream(is, null, options);
+ Utils.closeSilently(is);
}
if (fullSize != null) {
+ // Find out the true sample size that was used by the decoder
+ scaleDownSampleSize = bounds.x / fullSize.getWidth();
mCropBounds.left /= scaleDownSampleSize;
mCropBounds.top /= scaleDownSampleSize;
mCropBounds.bottom /= scaleDownSampleSize;
mCropBounds.right /= scaleDownSampleSize;
mCropBounds.roundOut(roundedTrueCrop);
+ // Adjust values to account for issues related to rounding
+ if (roundedTrueCrop.width() > fullSize.getWidth()) {
+ // Adjust the width
+ roundedTrueCrop.right = roundedTrueCrop.left + fullSize.getWidth();
+ }
+ if (roundedTrueCrop.right > fullSize.getWidth()) {
+ // Adjust the left value
+ int adjustment = roundedTrueCrop.left -
+ Math.max(0, roundedTrueCrop.right - roundedTrueCrop.width());
+ roundedTrueCrop.left -= adjustment;
+ roundedTrueCrop.right -= adjustment;
+ }
+ if (roundedTrueCrop.height() > fullSize.getHeight()) {
+ // Adjust the height
+ roundedTrueCrop.bottom = roundedTrueCrop.top + fullSize.getHeight();
+ }
+ if (roundedTrueCrop.bottom > fullSize.getHeight()) {
+ // Adjust the top value
+ int adjustment = roundedTrueCrop.top -
+ Math.max(0, roundedTrueCrop.bottom - roundedTrueCrop.height());
+ roundedTrueCrop.top -= adjustment;
+ roundedTrueCrop.bottom -= adjustment;
+ }
+
crop = Bitmap.createBitmap(fullSize, roundedTrueCrop.left,
roundedTrueCrop.top, roundedTrueCrop.width(),
roundedTrueCrop.height());
@@ -705,7 +787,7 @@ public class WallpaperCropActivity extends Activity {
protected void updateWallpaperDimensions(int width, int height) {
String spKey = getSharedPreferencesKey();
- SharedPreferences sp = getSharedPreferences(spKey, Context.MODE_PRIVATE);
+ SharedPreferences sp = getSharedPreferences(spKey, Context.MODE_MULTI_PROCESS);
SharedPreferences.Editor editor = sp.edit();
if (width != 0 && height != 0) {
editor.putInt(WALLPAPER_WIDTH_KEY, width);
@@ -725,15 +807,13 @@ public class WallpaperCropActivity extends Activity {
WindowManager windowManager,
final WallpaperManager wallpaperManager) {
final Point defaultWallpaperSize = getDefaultWallpaperSize(res, windowManager);
-
- new Thread("suggestWallpaperDimension") {
- public void run() {
- // If we have saved a wallpaper width/height, use that instead
- int savedWidth = sharedPrefs.getInt(WALLPAPER_WIDTH_KEY, defaultWallpaperSize.x);
- int savedHeight = sharedPrefs.getInt(WALLPAPER_HEIGHT_KEY, defaultWallpaperSize.y);
- wallpaperManager.suggestDesiredDimensions(savedWidth, savedHeight);
- }
- }.start();
+ // If we have saved a wallpaper width/height, use that instead
+ int savedWidth = sharedPrefs.getInt(WALLPAPER_WIDTH_KEY, defaultWallpaperSize.x);
+ int savedHeight = sharedPrefs.getInt(WALLPAPER_HEIGHT_KEY, defaultWallpaperSize.y);
+ if (savedWidth != wallpaperManager.getDesiredMinimumWidth() ||
+ savedHeight != wallpaperManager.getDesiredMinimumHeight()) {
+ wallpaperManager.suggestDesiredDimensions(savedWidth, savedHeight);
+ }
}
protected static RectF getMaxCropRect(
@@ -771,23 +851,4 @@ public class WallpaperCropActivity extends Activity {
? "png" // We don't support gif compression.
: "jpg";
}
-
- protected void setWallpaperStripYOffset(int bottom) {
- //
- }
-
- protected SavedWallpaperImages getSavedImages() {
- // for subclasses
- throw new UnsupportedOperationException("Not implemented for WallpaperCropActivity");
- }
-
- protected CropView getCropView() {
- // for subclasses
- throw new UnsupportedOperationException("Not implemented for WallpaperCropActivity");
- }
-
- protected void onLiveWallpaperPickerLaunch() {
- // for subclasses
- throw new UnsupportedOperationException("Not implemented for WallpaperCropActivity");
- }
}
diff --git a/src/com/android/launcher3/WallpaperPickerActivity.java b/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java
index f8e5233f7..7f05ef42d 100644
--- a/src/com/android/launcher3/WallpaperPickerActivity.java
+++ b/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java
@@ -16,7 +16,6 @@
package com.android.launcher3;
-import android.animation.Animator;
import android.animation.LayoutTransition;
import android.app.ActionBar;
import android.app.Activity;
@@ -31,6 +30,7 @@ import android.database.Cursor;
import android.database.DataSetObserver;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Point;
import android.graphics.PorterDuff;
@@ -40,6 +40,8 @@ import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LevelListDrawable;
import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.Build;
import android.os.Bundle;
import android.provider.MediaStore;
import android.util.Log;
@@ -51,10 +53,12 @@ import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
+import android.view.View.OnLayoutChangeListener;
import android.view.ViewGroup;
+import android.view.ViewPropertyAnimator;
import android.view.ViewTreeObserver;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
-import android.view.accessibility.AccessibilityEvent;
+import android.view.WindowManager;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.widget.BaseAdapter;
@@ -63,16 +67,15 @@ import android.widget.HorizontalScrollView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListAdapter;
+import android.widget.Toast;
-import com.android.gallery3d.exif.ExifInterface;
import com.android.photos.BitmapRegionTileSource;
import com.android.launcher3.settings.SettingsProvider;
+import com.android.photos.BitmapRegionTileSource.BitmapSource;
-import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
-import java.io.InputStream;
import java.util.ArrayList;
public class WallpaperPickerActivity extends WallpaperCropActivity {
@@ -82,11 +85,17 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
public static final int PICK_WALLPAPER_THIRD_PARTY_ACTIVITY = 6;
public static final int PICK_LIVE_WALLPAPER = 7;
private static final String TEMP_WALLPAPER_TILES = "TEMP_WALLPAPER_TILES";
+ private static final String SELECTED_INDEX = "SELECTED_INDEX";
+ private static final String OLD_DEFAULT_WALLPAPER_THUMBNAIL_FILENAME = "default_thumb.jpg";
+ private static final String DEFAULT_WALLPAPER_THUMBNAIL_FILENAME = "default_thumb2.jpg";
+ private static final int FLAG_POST_DELAY_MILLIS = 200;
private static final int MENU_WALLPAPER_SCROLL = 0;
+ private View mSelectedTile;
+
+ protected View mSetWallpaperButton;
- private View mSelectedThumb;
private boolean mIgnoreNextTap;
private OnClickListener mThumbnailOnClickListener;
@@ -101,30 +110,74 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
ArrayList<Uri> mTempWallpaperTiles = new ArrayList<Uri>();
private SavedWallpaperImages mSavedImages;
private WallpaperInfo mLiveWallpaperInfoOnPickerLaunch;
+ private int mSelectedIndex = -1;
+ private WallpaperInfo mLastClickedLiveWallpaperInfo;
+
+ public static abstract class WallpaperTileInfo {
+ protected View mView;
+ public void setView(View v) {
+ mView = v;
+ }
+ public void onClick(WallpaperPickerActivity a) {}
+ public void onSave(WallpaperPickerActivity a) {}
+ public void onDelete(WallpaperPickerActivity a) {}
+ public boolean isSelectable() { return false; }
+ public boolean isNamelessWallpaper() { return false; }
+ public void onIndexUpdated(CharSequence label) {
+ if (isNamelessWallpaper()) {
+ mView.setContentDescription(label);
+ }
+ }
+ }
public static class PickImageInfo extends WallpaperTileInfo {
@Override
- public void onClick(WallpaperCropActivity a) {
+ public void onClick(WallpaperPickerActivity a) {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("image/*");
- Utilities.startActivityForResultSafely(((WallpaperPickerActivity)a), intent, IMAGE_PICK);
+ a.startActivityForResultSafely(intent, IMAGE_PICK);
}
}
public static class UriWallpaperInfo extends WallpaperTileInfo {
private Uri mUri;
+ private boolean mFirstClick = true;
+ private BitmapRegionTileSource.UriBitmapSource mBitmapSource;
public UriWallpaperInfo(Uri uri) {
mUri = uri;
}
@Override
- public void onClick(WallpaperCropActivity a) {
- CropView v = a.getCropView();
- int rotation = WallpaperCropActivity.getRotationFromExif(a, mUri);
- v.setTileSource(new BitmapRegionTileSource(a, mUri, 1024, rotation), null);
- v.setTouchEnabled(true);
+ public void onClick(final WallpaperPickerActivity a) {
+ final Runnable onLoad;
+ if (!mFirstClick) {
+ onLoad = null;
+ } else {
+ mFirstClick = false;
+ a.mSetWallpaperButton.setEnabled(false);
+ onLoad = new Runnable() {
+ public void run() {
+ if (mBitmapSource != null &&
+ mBitmapSource.getLoadingState() == BitmapSource.State.LOADED) {
+ a.selectTile(mView);
+ a.mSetWallpaperButton.setEnabled(true);
+ } else {
+ ViewGroup parent = (ViewGroup) mView.getParent();
+ if (parent != null) {
+ parent.removeView(mView);
+ Toast.makeText(a,
+ a.getString(R.string.image_load_fail),
+ Toast.LENGTH_SHORT).show();
+ }
+ }
+ }
+ };
+ }
+ mBitmapSource = new BitmapRegionTileSource.UriBitmapSource(
+ a, mUri, BitmapRegionTileSource.MAX_PREVIEW_SIZE);
+ a.setCropViewTileSource(mBitmapSource, true, false, onLoad);
}
@Override
- public void onSave(final WallpaperCropActivity a) {
+ public void onSave(final WallpaperPickerActivity a) {
boolean finishActivityWhenDone = true;
OnBitmapCroppedHandler h = new OnBitmapCroppedHandler() {
public void onBitmapCropped(byte[] imageBytes) {
@@ -132,10 +185,10 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
// rotation is set to 0 since imageBytes has already been correctly rotated
Bitmap thumb = createThumbnail(
thumbSize, null, null, imageBytes, null, 0, 0, true);
- ((WallpaperPickerActivity)a).getSavedImages().writeImage(thumb, imageBytes);
+ a.getSavedImages().writeImage(thumb, imageBytes);
}
};
- ((WallpaperPickerActivity)a).cropImageAndSetWallpaper(mUri, h, finishActivityWhenDone);
+ a.cropImageAndSetWallpaper(mUri, h, finishActivityWhenDone);
}
@Override
public boolean isSelectable() {
@@ -158,10 +211,12 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
mThumb = thumb;
}
@Override
- public void onClick(WallpaperCropActivity a) {
- int rotation = WallpaperCropActivity.getRotationFromExif(mResources, mResId);
- BitmapRegionTileSource source = new BitmapRegionTileSource(
- mResources, a, mResId, 1024, rotation);
+ public void onClick(WallpaperPickerActivity a) {
+ BitmapRegionTileSource.ResourceBitmapSource bitmapSource =
+ new BitmapRegionTileSource.ResourceBitmapSource(
+ mResources, mResId, BitmapRegionTileSource.MAX_PREVIEW_SIZE);
+ bitmapSource.loadInBackground();
+ BitmapRegionTileSource source = new BitmapRegionTileSource(a, bitmapSource);
CropView v = a.getCropView();
v.setTileSource(source, null);
Point wallpaperSize = WallpaperCropActivity.getDefaultWallpaperSize(
@@ -171,11 +226,56 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
wallpaperSize.x, wallpaperSize.y, false);
v.setScale(wallpaperSize.x / crop.width());
v.setTouchEnabled(false);
+ a.setSystemWallpaperVisiblity(false);
}
@Override
- public void onSave(WallpaperCropActivity a) {
+ public void onSave(WallpaperPickerActivity a) {
boolean finishActivityWhenDone = true;
- ((WallpaperPickerActivity)a).cropImageAndSetWallpaper(mResources, mResId, finishActivityWhenDone);
+ a.cropImageAndSetWallpaper(mResources, mResId, finishActivityWhenDone);
+ }
+ @Override
+ public boolean isSelectable() {
+ return true;
+ }
+ @Override
+ public boolean isNamelessWallpaper() {
+ return true;
+ }
+ }
+
+ public static class DefaultWallpaperInfo extends WallpaperTileInfo {
+ public Drawable mThumb;
+ public DefaultWallpaperInfo(Drawable thumb) {
+ mThumb = thumb;
+ }
+ @Override
+ public void onClick(WallpaperPickerActivity a) {
+ CropView c = a.getCropView();
+
+ Drawable defaultWallpaper = WallpaperManager.getInstance(a).getBuiltInDrawable(
+ c.getWidth(), c.getHeight(), false, 0.5f, 0.5f);
+
+ if (defaultWallpaper == null) {
+ Log.w(TAG, "Null default wallpaper encountered.");
+ c.setTileSource(null, null);
+ return;
+ }
+
+ c.setTileSource(
+ new DrawableTileSource(a, defaultWallpaper, DrawableTileSource.MAX_PREVIEW_SIZE), null);
+ c.setScale(1f);
+ c.setTouchEnabled(false);
+ a.setSystemWallpaperVisiblity(false);
+ }
+ @Override
+ public void onSave(WallpaperPickerActivity a) {
+ try {
+ WallpaperManager.getInstance(a).clear();
+ a.setResult(RESULT_OK);
+ } catch (IOException e) {
+ Log.w("Setting wallpaper to default threw exception", e);
+ }
+ a.finish();
}
@Override
public boolean isSelectable() {
@@ -187,9 +287,65 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
}
}
+ public void setWallpaperStripYOffset(float offset) {
+ mWallpaperStrip.setPadding(0, 0, 0, (int) offset);
+ }
+
+ /**
+ * shows the system wallpaper behind the window and hides the {@link
+ * #mCropView} if visible
+ * @param visible should the system wallpaper be shown
+ */
+ protected void setSystemWallpaperVisiblity(final boolean visible) {
+ // hide our own wallpaper preview if necessary
+ if(!visible) {
+ mCropView.setVisibility(View.VISIBLE);
+ } else {
+ changeWallpaperFlags(visible);
+ }
+ // the change of the flag must be delayed in order to avoid flickering,
+ // a simple post / double post does not suffice here
+ mCropView.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ if(!visible) {
+ changeWallpaperFlags(visible);
+ } else {
+ mCropView.setVisibility(View.INVISIBLE);
+ }
+ }
+ }, FLAG_POST_DELAY_MILLIS);
+ }
+
+ private void changeWallpaperFlags(boolean visible) {
+ int desiredWallpaperFlag = visible ? WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER : 0;
+ int currentWallpaperFlag = getWindow().getAttributes().flags
+ & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
+ if (desiredWallpaperFlag != currentWallpaperFlag) {
+ getWindow().setFlags(desiredWallpaperFlag,
+ WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER);
+ }
+ }
+
@Override
- protected void setWallpaperStripYOffset(int offset) {
- mWallpaperStrip.setPadding(0, 0, 0, offset);
+ public void setCropViewTileSource(BitmapSource bitmapSource,
+ boolean touchEnabled,
+ boolean moveToLeft,
+ final Runnable postExecute) {
+ // we also want to show our own wallpaper instead of the one in the background
+ Runnable showPostExecuteRunnable = new Runnable() {
+ @Override
+ public void run() {
+ if(postExecute != null) {
+ postExecute.run();
+ }
+ setSystemWallpaperVisiblity(false);
+ }
+ };
+ super.setCropViewTileSource(bitmapSource,
+ touchEnabled,
+ moveToLeft,
+ showPostExecuteRunnable);
}
// called by onCreate; this is subclassed to overwrite WallpaperCropActivity
@@ -197,9 +353,11 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
setContentView(R.layout.wallpaper_picker);
mCropView = (CropView) findViewById(R.id.cropView);
+ mCropView.setVisibility(View.INVISIBLE);
+
mWallpaperStrip = findViewById(R.id.wallpaper_strip);
mCropView.setTouchCallback(new CropView.TouchCallback() {
- LauncherViewPropertyAnimator mAnim;
+ ViewPropertyAnimator mAnim;
@Override
public void onTouchDown() {
if (mAnim != null) {
@@ -208,17 +366,14 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
if (mWallpaperStrip.getAlpha() == 1f) {
mIgnoreNextTap = true;
}
- mAnim = new LauncherViewPropertyAnimator(mWallpaperStrip);
+ mAnim = mWallpaperStrip.animate();
mAnim.alpha(0f)
- .setDuration(150)
- .addListener(new Animator.AnimatorListener() {
- public void onAnimationStart(Animator animator) { }
- public void onAnimationEnd(Animator animator) {
- mWallpaperStrip.setVisibility(View.INVISIBLE);
- }
- public void onAnimationCancel(Animator animator) { }
- public void onAnimationRepeat(Animator animator) { }
- });
+ .setDuration(150)
+ .withEndAction(new Runnable() {
+ public void run() {
+ mWallpaperStrip.setVisibility(View.INVISIBLE);
+ }
+ });
mAnim.setInterpolator(new AccelerateInterpolator(0.75f));
mAnim.start();
}
@@ -235,7 +390,7 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
mAnim.cancel();
}
mWallpaperStrip.setVisibility(View.VISIBLE);
- mAnim = new LauncherViewPropertyAnimator(mWallpaperStrip);
+ mAnim = mWallpaperStrip.animate();
mAnim.alpha(1f)
.setDuration(150)
.setInterpolator(new DecelerateInterpolator(0.75f));
@@ -253,18 +408,10 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
}
return;
}
+ mSetWallpaperButton.setEnabled(true);
WallpaperTileInfo info = (WallpaperTileInfo) v.getTag();
- if (info.isSelectable()) {
- if (mSelectedThumb != null) {
- mSelectedThumb.setSelected(false);
- mSelectedThumb = null;
- }
- mSelectedThumb = v;
- v.setSelected(true);
- // TODO: Remove this once the accessibility framework and
- // services have better support for selection state.
- v.announceForAccessibility(
- getString(R.string.announce_selection, v.getContentDescription()));
+ if (info.isSelectable() && v.getVisibility() == View.VISIBLE) {
+ selectTile(v);
}
info.onClick(WallpaperPickerActivity.this);
}
@@ -293,12 +440,12 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
ArrayList<ResourceWallpaperInfo> wallpapers = findBundledWallpapers();
mWallpapersView = (LinearLayout) findViewById(R.id.wallpaper_list);
BuiltInWallpapersAdapter ia = new BuiltInWallpapersAdapter(this, wallpapers);
- populateWallpapersFromAdapter(mWallpapersView, ia, false, true);
+ populateWallpapersFromAdapter(mWallpapersView, ia, false);
// Populate the saved wallpapers
mSavedImages = new SavedWallpaperImages(this);
mSavedImages.loadThumbnailsAndImageIdList();
- populateWallpapersFromAdapter(mWallpapersView, mSavedImages, true, true);
+ populateWallpapersFromAdapter(mWallpapersView, mSavedImages, true);
// Populate the live wallpapers
final LinearLayout liveWallpapersView =
@@ -307,7 +454,7 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
a.registerDataSetObserver(new DataSetObserver() {
public void onChanged() {
liveWallpapersView.removeAllViews();
- populateWallpapersFromAdapter(liveWallpapersView, a, false, false);
+ populateWallpapersFromAdapter(liveWallpapersView, a, false);
initializeScrollForRtl();
updateTileIndices();
}
@@ -318,7 +465,7 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
(LinearLayout) findViewById(R.id.third_party_wallpaper_list);
final ThirdPartyWallpaperPickerListAdapter ta =
new ThirdPartyWallpaperPickerListAdapter(this);
- populateWallpapersFromAdapter(thirdPartyWallpapersView, ta, false, false);
+ populateWallpapersFromAdapter(thirdPartyWallpapersView, ta, false);
// Add a tile for the Gallery
LinearLayout masterWallpaperList = (LinearLayout) findViewById(R.id.master_wallpaper_list);
@@ -342,7 +489,37 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
pickImageTile.setTag(pickImageInfo);
pickImageInfo.setView(pickImageTile);
pickImageTile.setOnClickListener(mThumbnailOnClickListener);
- pickImageInfo.setView(pickImageTile);
+
+ // Add a tile for the default wallpaper
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+ DefaultWallpaperInfo defaultWallpaperInfo = getDefaultWallpaper();
+ if (defaultWallpaperInfo != null) {
+ FrameLayout defaultWallpaperTile = (FrameLayout) createImageTileView(
+ getLayoutInflater(), 0, null, mWallpapersView, defaultWallpaperInfo.mThumb);
+ setWallpaperItemPaddingToZero(defaultWallpaperTile);
+ defaultWallpaperTile.setTag(defaultWallpaperInfo);
+ mWallpapersView.addView(defaultWallpaperTile, 0);
+ defaultWallpaperTile.setOnClickListener(mThumbnailOnClickListener);
+ defaultWallpaperInfo.setView(defaultWallpaperTile);
+ }
+ }
+
+ // Select the first item; wait for a layout pass so that we initialize the dimensions of
+ // cropView or the defaultWallpaperView first
+ mCropView.addOnLayoutChangeListener(new OnLayoutChangeListener() {
+ @Override
+ public void onLayoutChange(View v, int left, int top, int right, int bottom,
+ int oldLeft, int oldTop, int oldRight, int oldBottom) {
+ if ((right - left) > 0 && (bottom - top) > 0) {
+ if (mSelectedIndex >= 0 && mSelectedIndex < mWallpapersView.getChildCount()) {
+ mThumbnailOnClickListener.onClick(
+ mWallpapersView.getChildAt(mSelectedIndex));
+ setSystemWallpaperVisiblity(false);
+ }
+ v.removeOnLayoutChangeListener(this);
+ }
+ }
+ });
updateTileIndices();
@@ -364,12 +541,17 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
new View.OnClickListener() {
@Override
public void onClick(View v) {
- if (mSelectedThumb != null) {
- WallpaperTileInfo info = (WallpaperTileInfo) mSelectedThumb.getTag();
+ if (mSelectedTile != null) {
+ WallpaperTileInfo info = (WallpaperTileInfo) mSelectedTile.getTag();
info.onSave(WallpaperPickerActivity.this);
+ } else {
+ // no tile was selected, so we just finish the activity and go back
+ setResult(Activity.RESULT_OK);
+ finish();
}
}
});
+ mSetWallpaperButton = findViewById(R.id.set_wallpaper_button);
// CAB for deleting items
mActionModeCallback = new ActionMode.Callback() {
@@ -416,6 +598,7 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
if (itemId == R.id.menu_delete) {
int childCount = mWallpapersView.getChildCount();
ArrayList<View> viewsToRemove = new ArrayList<View>();
+ boolean selectedTileRemoved = false;
for (int i = 0; i < childCount; i++) {
CheckableFrameLayout c =
(CheckableFrameLayout) mWallpapersView.getChildAt(i);
@@ -423,11 +606,19 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
WallpaperTileInfo info = (WallpaperTileInfo) c.getTag();
info.onDelete(WallpaperPickerActivity.this);
viewsToRemove.add(c);
+ if (i == mSelectedIndex) {
+ selectedTileRemoved = true;
+ }
}
}
for (View v : viewsToRemove) {
mWallpapersView.removeView(v);
}
+ if (selectedTileRemoved) {
+ mSelectedIndex = -1;
+ mSelectedTile = null;
+ setSystemWallpaperVisiblity(true);
+ }
updateTileIndices();
mode.finish(); // Action picked, so close the CAB
return true;
@@ -444,12 +635,28 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
CheckableFrameLayout c = (CheckableFrameLayout) mWallpapersView.getChildAt(i);
c.setChecked(false);
}
- mSelectedThumb.setSelected(true);
+ if (mSelectedTile != null) {
+ mSelectedTile.setSelected(true);
+ }
mActionMode = null;
}
};
}
+ private void selectTile(View v) {
+ if (mSelectedTile != null) {
+ mSelectedTile.setSelected(false);
+ mSelectedTile = null;
+ }
+ mSelectedTile = v;
+ v.setSelected(true);
+ mSelectedIndex = mWallpapersView.indexOfChild(v);
+ // TODO: Remove this once the accessibility framework and
+ // services have better support for selection state.
+ v.announceForAccessibility(
+ getString(R.string.announce_selection, v.getContentDescription()));
+ }
+
private void initializeScrollForRtl() {
final HorizontalScrollView scroll =
(HorizontalScrollView) findViewById(R.id.wallpaper_scroll_container);
@@ -467,10 +674,6 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
}
}
- public boolean enableRotation() {
- return super.enableRotation() || Launcher.sForceEnableRotation;
- }
-
protected Bitmap getThumbnailOfLastPhoto() {
Cursor cursor = MediaStore.Images.Media.query(getContentResolver(),
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
@@ -490,25 +693,6 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
}
@Override
- public boolean onCreateOptionsMenu(Menu menu) {
- menu.add(0, MENU_WALLPAPER_SCROLL, 0,
- R.string.wallpaper_scroll).setCheckable(true);
-
- return super.onCreateOptionsMenu(menu);
- }
-
- @Override
- public boolean onPrepareOptionsMenu(Menu menu) {
- MenuItem wallpaperScroll = menu.findItem(MENU_WALLPAPER_SCROLL);
-
- wallpaperScroll.setChecked(SettingsProvider.getBoolean(this,
- SettingsProvider.SETTINGS_UI_HOMESCREEN_SCROLLING_WALLPAPER_SCROLL,
- R.bool.preferences_interface_homescreen_scrolling_wallpaper_scroll_default));
-
- return super.onPrepareOptionsMenu(menu);
- }
-
- @Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle presses on the action bar items
switch (item.getItemId()) {
@@ -534,17 +718,19 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
protected void onSaveInstanceState(Bundle outState) {
outState.putParcelableArrayList(TEMP_WALLPAPER_TILES, mTempWallpaperTiles);
+ outState.putInt(SELECTED_INDEX, mSelectedIndex);
}
protected void onRestoreInstanceState(Bundle savedInstanceState) {
ArrayList<Uri> uris = savedInstanceState.getParcelableArrayList(TEMP_WALLPAPER_TILES);
for (Uri uri : uris) {
- addTemporaryWallpaperTile(uri);
+ addTemporaryWallpaperTile(uri, true);
}
+ mSelectedIndex = savedInstanceState.getInt(SELECTED_INDEX, -1);
}
private void populateWallpapersFromAdapter(ViewGroup parent, BaseAdapter adapter,
- boolean addLongPressHandler, boolean selectFirstTile) {
+ boolean addLongPressHandler) {
for (int i = 0; i < adapter.getCount(); i++) {
FrameLayout thumbnail = (FrameLayout) adapter.getView(i, null, parent);
parent.addView(thumbnail, i);
@@ -555,9 +741,6 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
addLongPressHandler(thumbnail);
}
thumbnail.setOnClickListener(mThumbnailOnClickListener);
- if (i == 0 && selectFirstTile) {
- mThumbnailOnClickListener.onClick(thumbnail);
- }
}
}
@@ -647,26 +830,36 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
}
}
- private void addTemporaryWallpaperTile(Uri uri) {
+ private void addTemporaryWallpaperTile(final Uri uri, boolean fromRestore) {
mTempWallpaperTiles.add(uri);
// Add a tile for the image picked from Gallery
- FrameLayout pickedImageThumbnail = (FrameLayout) getLayoutInflater().
+ final FrameLayout pickedImageThumbnail = (FrameLayout) getLayoutInflater().
inflate(R.layout.wallpaper_picker_item, mWallpapersView, false);
+ pickedImageThumbnail.setVisibility(View.GONE);
setWallpaperItemPaddingToZero(pickedImageThumbnail);
+ mWallpapersView.addView(pickedImageThumbnail, 0);
// Load the thumbnail
- ImageView image = (ImageView) pickedImageThumbnail.findViewById(R.id.wallpaper_image);
- Point defaultSize = getDefaultThumbnailSize(this.getResources());
- int rotation = WallpaperCropActivity.getRotationFromExif(this, uri);
- Bitmap thumb = createThumbnail(defaultSize, this, uri, null, null, 0, rotation, false);
- if (thumb != null) {
- image.setImageBitmap(thumb);
- Drawable thumbDrawable = image.getDrawable();
- thumbDrawable.setDither(true);
- } else {
- Log.e(TAG, "Error loading thumbnail for uri=" + uri);
- }
- mWallpapersView.addView(pickedImageThumbnail, 0);
+ final ImageView image = (ImageView) pickedImageThumbnail.findViewById(R.id.wallpaper_image);
+ final Point defaultSize = getDefaultThumbnailSize(this.getResources());
+ final Context context = this;
+ new AsyncTask<Void, Bitmap, Bitmap>() {
+ protected Bitmap doInBackground(Void...args) {
+ int rotation = WallpaperCropActivity.getRotationFromExif(context, uri);
+ return createThumbnail(defaultSize, context, uri, null, null, 0, rotation, false);
+
+ }
+ protected void onPostExecute(Bitmap thumb) {
+ if (thumb != null) {
+ image.setImageBitmap(thumb);
+ Drawable thumbDrawable = image.getDrawable();
+ thumbDrawable.setDither(true);
+ pickedImageThumbnail.setVisibility(View.VISIBLE);
+ } else {
+ Log.e(TAG, "Error loading thumbnail for uri=" + uri);
+ }
+ }
+ }.execute();
UriWallpaperInfo info = new UriWallpaperInfo(uri);
pickedImageThumbnail.setTag(info);
@@ -674,14 +867,16 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
addLongPressHandler(pickedImageThumbnail);
updateTileIndices();
pickedImageThumbnail.setOnClickListener(mThumbnailOnClickListener);
- mThumbnailOnClickListener.onClick(pickedImageThumbnail);
+ if (!fromRestore) {
+ mThumbnailOnClickListener.onClick(pickedImageThumbnail);
+ }
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == IMAGE_PICK && resultCode == RESULT_OK) {
if (data != null && data.getData() != null) {
Uri uri = data.getData();
- addTemporaryWallpaperTile(uri);
+ addTemporaryWallpaperTile(uri, false);
}
} else if (requestCode == PICK_WALLPAPER_THIRD_PARTY_ACTIVITY) {
setResult(RESULT_OK);
@@ -689,11 +884,15 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
} else if (requestCode == PICK_LIVE_WALLPAPER) {
WallpaperManager wm = WallpaperManager.getInstance(this);
final WallpaperInfo oldLiveWallpaper = mLiveWallpaperInfoOnPickerLaunch;
+ final WallpaperInfo clickedWallpaper = mLastClickedLiveWallpaperInfo;
WallpaperInfo newLiveWallpaper = wm.getWallpaperInfo();
// Try to figure out if a live wallpaper was set;
if (newLiveWallpaper != null &&
- (oldLiveWallpaper == null ||
- !oldLiveWallpaper.getComponent().equals(newLiveWallpaper.getComponent()))) {
+ (oldLiveWallpaper == null
+ || !oldLiveWallpaper.getComponent()
+ .equals(newLiveWallpaper.getComponent())
+ || clickedWallpaper.getComponent()
+ .equals(oldLiveWallpaper.getComponent()))) {
// Return if a live wallpaper was set
setResult(RESULT_OK);
finish();
@@ -724,18 +923,35 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
}
// Add an entry for the default wallpaper (stored in system resources)
- ResourceWallpaperInfo defaultWallpaperInfo = getDefaultWallpaperInfo();
- if (defaultWallpaperInfo != null) {
- bundledWallpapers.add(0, defaultWallpaperInfo);
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
+ ResourceWallpaperInfo defaultWallpaperInfo = getPreKKDefaultWallpaperInfo();
+ if (defaultWallpaperInfo != null) {
+ bundledWallpapers.add(0, defaultWallpaperInfo);
+ }
}
return bundledWallpapers;
}
- private ResourceWallpaperInfo getDefaultWallpaperInfo() {
+ private boolean writeImageToFileAsJpeg(File f, Bitmap b) {
+ try {
+ f.createNewFile();
+ FileOutputStream thumbFileStream =
+ openFileOutput(f.getName(), Context.MODE_PRIVATE);
+ b.compress(Bitmap.CompressFormat.JPEG, 95, thumbFileStream);
+ thumbFileStream.close();
+ return true;
+ } catch (IOException e) {
+ Log.e(TAG, "Error while writing bitmap to file " + e);
+ f.delete();
+ }
+ return false;
+ }
+
+ private ResourceWallpaperInfo getPreKKDefaultWallpaperInfo() {
Resources sysRes = Resources.getSystem();
int resId = sysRes.getIdentifier("default_wallpaper", "drawable", "android");
- File defaultThumbFile = new File(getFilesDir(), "default_thumb.jpg");
+ File defaultThumbFile = new File(getFilesDir(), DEFAULT_WALLPAPER_THUMBNAIL_FILENAME);
Bitmap thumb = null;
boolean defaultWallpaperExists = false;
if (defaultThumbFile.exists()) {
@@ -748,17 +964,7 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
thumb = createThumbnail(
defaultThumbSize, this, null, null, sysRes, resId, rotation, false);
if (thumb != null) {
- try {
- defaultThumbFile.createNewFile();
- FileOutputStream thumbFileStream =
- openFileOutput(defaultThumbFile.getName(), Context.MODE_PRIVATE);
- thumb.compress(Bitmap.CompressFormat.JPEG, 95, thumbFileStream);
- thumbFileStream.close();
- defaultWallpaperExists = true;
- } catch (IOException e) {
- Log.e(TAG, "Error while writing default wallpaper thumbnail to file " + e);
- defaultThumbFile.delete();
- }
+ defaultWallpaperExists = writeImageToFileAsJpeg(defaultThumbFile, thumb);
}
}
if (defaultWallpaperExists) {
@@ -767,6 +973,40 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
return null;
}
+ private DefaultWallpaperInfo getDefaultWallpaper() {
+ File defaultThumbFile = new File(getFilesDir(), DEFAULT_WALLPAPER_THUMBNAIL_FILENAME);
+ Bitmap thumb = null;
+ boolean defaultWallpaperExists = false;
+ if (defaultThumbFile.exists()) {
+ thumb = BitmapFactory.decodeFile(defaultThumbFile.getAbsolutePath());
+ defaultWallpaperExists = true;
+ } else {
+ // Delete old thumbnail file, since we had a bug where the thumbnail wasn't being drawn
+ // before
+ new File(getFilesDir(), OLD_DEFAULT_WALLPAPER_THUMBNAIL_FILENAME).delete();
+
+ Resources res = getResources();
+ Point defaultThumbSize = getDefaultThumbnailSize(res);
+ Drawable wallpaperDrawable = WallpaperManager.getInstance(this).getBuiltInDrawable(
+ defaultThumbSize.x, defaultThumbSize.y, true, 0.5f, 0.5f);
+ if (wallpaperDrawable != null) {
+ thumb = Bitmap.createBitmap(
+ defaultThumbSize.x, defaultThumbSize.y, Bitmap.Config.ARGB_8888);
+ Canvas c = new Canvas(thumb);
+ wallpaperDrawable.setBounds(0, 0, defaultThumbSize.x, defaultThumbSize.y);
+ wallpaperDrawable.draw(c);
+ c.setBitmap(null);
+ }
+ if (thumb != null) {
+ defaultWallpaperExists = writeImageToFileAsJpeg(defaultThumbFile, thumb);
+ }
+ }
+ if (defaultWallpaperExists) {
+ return new DefaultWallpaperInfo(new BitmapDrawable(thumb));
+ }
+ return null;
+ }
+
public Pair<ApplicationInfo, Integer> getWallpaperArrayResourceId() {
// Context.getPackageName() may return the "original" package name,
// com.android.launcher3; Resources needs the real package name,
@@ -812,7 +1052,8 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
return mSavedImages;
}
- public void onLiveWallpaperPickerLaunch() {
+ public void onLiveWallpaperPickerLaunch(WallpaperInfo info) {
+ mLastClickedLiveWallpaperInfo = info;
mLiveWallpaperInfoOnPickerLaunch = WallpaperManager.getInstance(this).getWallpaperInfo();
}
@@ -881,4 +1122,10 @@ public class WallpaperPickerActivity extends WallpaperCropActivity {
return view;
}
+
+ // In Launcher3, we override this with a method that catches exceptions
+ // from starting activities; didn't want to copy and paste code into here
+ public void startActivityForResultSafely(Intent intent, int requestCode) {
+ startActivityForResult(intent, requestCode);
+ }
}
diff --git a/src/com/android/launcher3/WallpaperRootView.java b/WallpaperPicker/src/com/android/launcher3/WallpaperRootView.java
index 7b0d4f147..ceaa043a7 100644
--- a/src/com/android/launcher3/WallpaperRootView.java
+++ b/WallpaperPicker/src/com/android/launcher3/WallpaperRootView.java
@@ -22,14 +22,14 @@ import android.util.AttributeSet;
import android.widget.RelativeLayout;
public class WallpaperRootView extends RelativeLayout {
- private final WallpaperCropActivity a;
+ private final WallpaperPickerActivity a;
public WallpaperRootView(Context context, AttributeSet attrs) {
super(context, attrs);
- a = (WallpaperCropActivity) context;
+ a = (WallpaperPickerActivity) context;
}
public WallpaperRootView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
- a = (WallpaperCropActivity) context;
+ a = (WallpaperPickerActivity) context;
}
protected boolean fitSystemWindows(Rect insets) {
diff --git a/WallpaperPicker/src/com/android/photos/BitmapRegionTileSource.java b/WallpaperPicker/src/com/android/photos/BitmapRegionTileSource.java
new file mode 100644
index 000000000..764156de0
--- /dev/null
+++ b/WallpaperPicker/src/com/android/photos/BitmapRegionTileSource.java
@@ -0,0 +1,528 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.photos;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.Config;
+import android.graphics.BitmapFactory;
+import android.graphics.BitmapRegionDecoder;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Build.VERSION_CODES;
+import android.util.Log;
+
+import com.android.gallery3d.common.BitmapUtils;
+import com.android.gallery3d.common.Utils;
+import com.android.gallery3d.exif.ExifInterface;
+import com.android.gallery3d.glrenderer.BasicTexture;
+import com.android.gallery3d.glrenderer.BitmapTexture;
+import com.android.photos.views.TiledImageRenderer;
+
+import java.io.BufferedInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+
+interface SimpleBitmapRegionDecoder {
+ int getWidth();
+ int getHeight();
+ Bitmap decodeRegion(Rect wantRegion, BitmapFactory.Options options);
+}
+
+class SimpleBitmapRegionDecoderWrapper implements SimpleBitmapRegionDecoder {
+ BitmapRegionDecoder mDecoder;
+ private SimpleBitmapRegionDecoderWrapper(BitmapRegionDecoder decoder) {
+ mDecoder = decoder;
+ }
+ public static SimpleBitmapRegionDecoderWrapper newInstance(
+ String pathName, boolean isShareable) {
+ try {
+ BitmapRegionDecoder d = BitmapRegionDecoder.newInstance(pathName, isShareable);
+ if (d != null) {
+ return new SimpleBitmapRegionDecoderWrapper(d);
+ }
+ } catch (IOException e) {
+ Log.w("BitmapRegionTileSource", "getting decoder failed for path " + pathName, e);
+ return null;
+ }
+ return null;
+ }
+ public static SimpleBitmapRegionDecoderWrapper newInstance(
+ InputStream is, boolean isShareable) {
+ try {
+ BitmapRegionDecoder d = BitmapRegionDecoder.newInstance(is, isShareable);
+ if (d != null) {
+ return new SimpleBitmapRegionDecoderWrapper(d);
+ }
+ } catch (IOException e) {
+ Log.w("BitmapRegionTileSource", "getting decoder failed", e);
+ return null;
+ }
+ return null;
+ }
+ public int getWidth() {
+ return mDecoder.getWidth();
+ }
+ public int getHeight() {
+ return mDecoder.getHeight();
+ }
+ public Bitmap decodeRegion(Rect wantRegion, BitmapFactory.Options options) {
+ return mDecoder.decodeRegion(wantRegion, options);
+ }
+}
+
+class DumbBitmapRegionDecoder implements SimpleBitmapRegionDecoder {
+ Bitmap mBuffer;
+ Canvas mTempCanvas;
+ Paint mTempPaint;
+ private DumbBitmapRegionDecoder(Bitmap b) {
+ mBuffer = b;
+ }
+ public static DumbBitmapRegionDecoder newInstance(String pathName) {
+ Bitmap b = BitmapFactory.decodeFile(pathName);
+ if (b != null) {
+ return new DumbBitmapRegionDecoder(b);
+ }
+ return null;
+ }
+ public static DumbBitmapRegionDecoder newInstance(InputStream is) {
+ Bitmap b = BitmapFactory.decodeStream(is);
+ if (b != null) {
+ return new DumbBitmapRegionDecoder(b);
+ }
+ return null;
+ }
+ public int getWidth() {
+ return mBuffer.getWidth();
+ }
+ public int getHeight() {
+ return mBuffer.getHeight();
+ }
+ public Bitmap decodeRegion(Rect wantRegion, BitmapFactory.Options options) {
+ if (mTempCanvas == null) {
+ mTempCanvas = new Canvas();
+ mTempPaint = new Paint();
+ mTempPaint.setFilterBitmap(true);
+ }
+ int sampleSize = Math.max(options.inSampleSize, 1);
+ Bitmap newBitmap = Bitmap.createBitmap(
+ wantRegion.width() / sampleSize,
+ wantRegion.height() / sampleSize,
+ Bitmap.Config.ARGB_8888);
+ mTempCanvas.setBitmap(newBitmap);
+ mTempCanvas.save();
+ mTempCanvas.scale(1f / sampleSize, 1f / sampleSize);
+ mTempCanvas.drawBitmap(mBuffer, -wantRegion.left, -wantRegion.top, mTempPaint);
+ mTempCanvas.restore();
+ mTempCanvas.setBitmap(null);
+ return newBitmap;
+ }
+}
+
+/**
+ * A {@link com.android.photos.views.TiledImageRenderer.TileSource} using
+ * {@link BitmapRegionDecoder} to wrap a local file
+ */
+@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1)
+public class BitmapRegionTileSource implements TiledImageRenderer.TileSource {
+
+ private static final String TAG = "BitmapRegionTileSource";
+
+ private static final boolean REUSE_BITMAP =
+ Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN;
+ private static final int GL_SIZE_LIMIT = 2048;
+ // This must be no larger than half the size of the GL_SIZE_LIMIT
+ // due to decodePreview being allowed to be up to 2x the size of the target
+ public static final int MAX_PREVIEW_SIZE = GL_SIZE_LIMIT / 2;
+
+ public static abstract class BitmapSource {
+ private SimpleBitmapRegionDecoder mDecoder;
+ private Bitmap mPreview;
+ private int mPreviewSize;
+ private int mRotation;
+ public enum State { NOT_LOADED, LOADED, ERROR_LOADING };
+ private State mState = State.NOT_LOADED;
+ public BitmapSource(int previewSize) {
+ mPreviewSize = previewSize;
+ }
+ public boolean loadInBackground() {
+ ExifInterface ei = new ExifInterface();
+ if (readExif(ei)) {
+ Integer ori = ei.getTagIntValue(ExifInterface.TAG_ORIENTATION);
+ if (ori != null) {
+ mRotation = ExifInterface.getRotationForOrientationValue(ori.shortValue());
+ }
+ }
+ mDecoder = loadBitmapRegionDecoder();
+ if (mDecoder == null) {
+ mState = State.ERROR_LOADING;
+ return false;
+ } else {
+ int width = mDecoder.getWidth();
+ int height = mDecoder.getHeight();
+ if (mPreviewSize != 0) {
+ int previewSize = Math.min(mPreviewSize, MAX_PREVIEW_SIZE);
+ BitmapFactory.Options opts = new BitmapFactory.Options();
+ opts.inPreferredConfig = Bitmap.Config.ARGB_8888;
+ opts.inPreferQualityOverSpeed = true;
+
+ float scale = (float) previewSize / Math.max(width, height);
+ opts.inSampleSize = BitmapUtils.computeSampleSizeLarger(scale);
+ opts.inJustDecodeBounds = false;
+ mPreview = loadPreviewBitmap(opts);
+ }
+ mState = State.LOADED;
+ return true;
+ }
+ }
+
+ public State getLoadingState() {
+ return mState;
+ }
+
+ public SimpleBitmapRegionDecoder getBitmapRegionDecoder() {
+ return mDecoder;
+ }
+
+ public Bitmap getPreviewBitmap() {
+ return mPreview;
+ }
+
+ public int getPreviewSize() {
+ return mPreviewSize;
+ }
+
+ public int getRotation() {
+ return mRotation;
+ }
+
+ public abstract boolean readExif(ExifInterface ei);
+ public abstract SimpleBitmapRegionDecoder loadBitmapRegionDecoder();
+ public abstract Bitmap loadPreviewBitmap(BitmapFactory.Options options);
+ }
+
+ public static class FilePathBitmapSource extends BitmapSource {
+ private String mPath;
+ public FilePathBitmapSource(String path, int previewSize) {
+ super(previewSize);
+ mPath = path;
+ }
+ @Override
+ public SimpleBitmapRegionDecoder loadBitmapRegionDecoder() {
+ SimpleBitmapRegionDecoder d;
+ d = SimpleBitmapRegionDecoderWrapper.newInstance(mPath, true);
+ if (d == null) {
+ d = DumbBitmapRegionDecoder.newInstance(mPath);
+ }
+ return d;
+ }
+ @Override
+ public Bitmap loadPreviewBitmap(BitmapFactory.Options options) {
+ return BitmapFactory.decodeFile(mPath, options);
+ }
+ @Override
+ public boolean readExif(ExifInterface ei) {
+ try {
+ ei.readExif(mPath);
+ return true;
+ } catch (NullPointerException e) {
+ Log.w("BitmapRegionTileSource", "reading exif failed", e);
+ return false;
+ } catch (IOException e) {
+ Log.w("BitmapRegionTileSource", "getting decoder failed", e);
+ return false;
+ }
+ }
+ }
+
+ public static class UriBitmapSource extends BitmapSource {
+ private Context mContext;
+ private Uri mUri;
+ public UriBitmapSource(Context context, Uri uri, int previewSize) {
+ super(previewSize);
+ mContext = context;
+ mUri = uri;
+ }
+ private InputStream regenerateInputStream() throws FileNotFoundException {
+ InputStream is = mContext.getContentResolver().openInputStream(mUri);
+ return new BufferedInputStream(is);
+ }
+ @Override
+ public SimpleBitmapRegionDecoder loadBitmapRegionDecoder() {
+ try {
+ InputStream is = regenerateInputStream();
+ SimpleBitmapRegionDecoder regionDecoder =
+ SimpleBitmapRegionDecoderWrapper.newInstance(is, false);
+ Utils.closeSilently(is);
+ if (regionDecoder == null) {
+ is = regenerateInputStream();
+ regionDecoder = DumbBitmapRegionDecoder.newInstance(is);
+ Utils.closeSilently(is);
+ }
+ return regionDecoder;
+ } catch (FileNotFoundException e) {
+ Log.e("BitmapRegionTileSource", "Failed to load URI " + mUri, e);
+ return null;
+ } catch (IOException e) {
+ Log.e("BitmapRegionTileSource", "Failure while reading URI " + mUri, e);
+ return null;
+ }
+ }
+ @Override
+ public Bitmap loadPreviewBitmap(BitmapFactory.Options options) {
+ try {
+ InputStream is = regenerateInputStream();
+ Bitmap b = BitmapFactory.decodeStream(is, null, options);
+ Utils.closeSilently(is);
+ return b;
+ } catch (FileNotFoundException e) {
+ Log.e("BitmapRegionTileSource", "Failed to load URI " + mUri, e);
+ return null;
+ }
+ }
+ @Override
+ public boolean readExif(ExifInterface ei) {
+ InputStream is = null;
+ try {
+ is = regenerateInputStream();
+ ei.readExif(is);
+ Utils.closeSilently(is);
+ return true;
+ } catch (FileNotFoundException e) {
+ Log.e("BitmapRegionTileSource", "Failed to load URI " + mUri, e);
+ return false;
+ } catch (IOException e) {
+ Log.e("BitmapRegionTileSource", "Failed to load URI " + mUri, e);
+ return false;
+ } catch (NullPointerException e) {
+ Log.e("BitmapRegionTileSource", "Failed to read EXIF for URI " + mUri, e);
+ return false;
+ } finally {
+ Utils.closeSilently(is);
+ }
+ }
+ }
+
+ public static class ResourceBitmapSource extends BitmapSource {
+ private Resources mRes;
+ private int mResId;
+ public ResourceBitmapSource(Resources res, int resId, int previewSize) {
+ super(previewSize);
+ mRes = res;
+ mResId = resId;
+ }
+ private InputStream regenerateInputStream() {
+ InputStream is = mRes.openRawResource(mResId);
+ return new BufferedInputStream(is);
+ }
+ @Override
+ public SimpleBitmapRegionDecoder loadBitmapRegionDecoder() {
+ InputStream is = regenerateInputStream();
+ SimpleBitmapRegionDecoder regionDecoder =
+ SimpleBitmapRegionDecoderWrapper.newInstance(is, false);
+ Utils.closeSilently(is);
+ if (regionDecoder == null) {
+ is = regenerateInputStream();
+ regionDecoder = DumbBitmapRegionDecoder.newInstance(is);
+ Utils.closeSilently(is);
+ }
+ return regionDecoder;
+ }
+ @Override
+ public Bitmap loadPreviewBitmap(BitmapFactory.Options options) {
+ return BitmapFactory.decodeResource(mRes, mResId, options);
+ }
+ @Override
+ public boolean readExif(ExifInterface ei) {
+ try {
+ InputStream is = regenerateInputStream();
+ ei.readExif(is);
+ Utils.closeSilently(is);
+ return true;
+ } catch (IOException e) {
+ Log.e("BitmapRegionTileSource", "Error reading resource", e);
+ return false;
+ }
+ }
+ }
+
+ SimpleBitmapRegionDecoder mDecoder;
+ int mWidth;
+ int mHeight;
+ int mTileSize;
+ private BasicTexture mPreview;
+ private final int mRotation;
+
+ // For use only by getTile
+ private Rect mWantRegion = new Rect();
+ private Rect mOverlapRegion = new Rect();
+ private BitmapFactory.Options mOptions;
+ private Canvas mCanvas;
+
+ public BitmapRegionTileSource(Context context, BitmapSource source) {
+ mTileSize = TiledImageRenderer.suggestedTileSize(context);
+ mRotation = source.getRotation();
+ mDecoder = source.getBitmapRegionDecoder();
+ if (mDecoder != null) {
+ mWidth = mDecoder.getWidth();
+ mHeight = mDecoder.getHeight();
+ mOptions = new BitmapFactory.Options();
+ mOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;
+ mOptions.inPreferQualityOverSpeed = true;
+ mOptions.inTempStorage = new byte[16 * 1024];
+ int previewSize = source.getPreviewSize();
+ if (previewSize != 0) {
+ previewSize = Math.min(previewSize, MAX_PREVIEW_SIZE);
+ // Although this is the same size as the Bitmap that is likely already
+ // loaded, the lifecycle is different and interactions are on a different
+ // thread. Thus to simplify, this source will decode its own bitmap.
+ Bitmap preview = decodePreview(source, previewSize);
+ if (preview.getWidth() <= GL_SIZE_LIMIT && preview.getHeight() <= GL_SIZE_LIMIT) {
+ mPreview = new BitmapTexture(preview);
+ } else {
+ Log.w(TAG, String.format(
+ "Failed to create preview of apropriate size! "
+ + " in: %dx%d, out: %dx%d",
+ mWidth, mHeight,
+ preview.getWidth(), preview.getHeight()));
+ }
+ }
+ }
+ }
+
+ @Override
+ public int getTileSize() {
+ return mTileSize;
+ }
+
+ @Override
+ public int getImageWidth() {
+ return mWidth;
+ }
+
+ @Override
+ public int getImageHeight() {
+ return mHeight;
+ }
+
+ @Override
+ public BasicTexture getPreview() {
+ return mPreview;
+ }
+
+ @Override
+ public int getRotation() {
+ return mRotation;
+ }
+
+ @Override
+ public Bitmap getTile(int level, int x, int y, Bitmap bitmap) {
+ int tileSize = getTileSize();
+ if (!REUSE_BITMAP) {
+ return getTileWithoutReusingBitmap(level, x, y, tileSize);
+ }
+
+ int t = tileSize << level;
+ mWantRegion.set(x, y, x + t, y + t);
+
+ if (bitmap == null) {
+ bitmap = Bitmap.createBitmap(tileSize, tileSize, Bitmap.Config.ARGB_8888);
+ }
+
+ mOptions.inSampleSize = (1 << level);
+ mOptions.inBitmap = bitmap;
+
+ try {
+ bitmap = mDecoder.decodeRegion(mWantRegion, mOptions);
+ } finally {
+ if (mOptions.inBitmap != bitmap && mOptions.inBitmap != null) {
+ mOptions.inBitmap = null;
+ }
+ }
+
+ if (bitmap == null) {
+ Log.w("BitmapRegionTileSource", "fail in decoding region");
+ }
+ return bitmap;
+ }
+
+ private Bitmap getTileWithoutReusingBitmap(
+ int level, int x, int y, int tileSize) {
+
+ int t = tileSize << level;
+ mWantRegion.set(x, y, x + t, y + t);
+
+ mOverlapRegion.set(0, 0, mWidth, mHeight);
+
+ mOptions.inSampleSize = (1 << level);
+ Bitmap bitmap = mDecoder.decodeRegion(mOverlapRegion, mOptions);
+
+ if (bitmap == null) {
+ Log.w(TAG, "fail in decoding region");
+ }
+
+ if (mWantRegion.equals(mOverlapRegion)) {
+ return bitmap;
+ }
+
+ Bitmap result = Bitmap.createBitmap(tileSize, tileSize, Config.ARGB_8888);
+ if (mCanvas == null) {
+ mCanvas = new Canvas();
+ }
+ mCanvas.setBitmap(result);
+ mCanvas.drawBitmap(bitmap,
+ (mOverlapRegion.left - mWantRegion.left) >> level,
+ (mOverlapRegion.top - mWantRegion.top) >> level, null);
+ mCanvas.setBitmap(null);
+ return result;
+ }
+
+ /**
+ * Note that the returned bitmap may have a long edge that's longer
+ * than the targetSize, but it will always be less than 2x the targetSize
+ */
+ private Bitmap decodePreview(BitmapSource source, int targetSize) {
+ Bitmap result = source.getPreviewBitmap();
+ if (result == null) {
+ return null;
+ }
+
+ // We need to resize down if the decoder does not support inSampleSize
+ // or didn't support the specified inSampleSize (some decoders only do powers of 2)
+ float scale = (float) targetSize / (float) (Math.max(result.getWidth(), result.getHeight()));
+
+ if (scale <= 0.5) {
+ result = BitmapUtils.resizeBitmapByScale(result, scale, true);
+ }
+ return ensureGLCompatibleBitmap(result);
+ }
+
+ private static Bitmap ensureGLCompatibleBitmap(Bitmap bitmap) {
+ if (bitmap == null || bitmap.getConfig() != null) {
+ return bitmap;
+ }
+ Bitmap newBitmap = bitmap.copy(Config.ARGB_8888, false);
+ bitmap.recycle();
+ return newBitmap;
+ }
+}
diff --git a/src/com/android/photos/views/BlockingGLTextureView.java b/WallpaperPicker/src/com/android/photos/views/BlockingGLTextureView.java
index 8a0505185..8a0505185 100644
--- a/src/com/android/photos/views/BlockingGLTextureView.java
+++ b/WallpaperPicker/src/com/android/photos/views/BlockingGLTextureView.java
diff --git a/src/com/android/photos/views/TiledImageRenderer.java b/WallpaperPicker/src/com/android/photos/views/TiledImageRenderer.java
index c4e493b34..c4e493b34 100644
--- a/src/com/android/photos/views/TiledImageRenderer.java
+++ b/WallpaperPicker/src/com/android/photos/views/TiledImageRenderer.java
diff --git a/src/com/android/photos/views/TiledImageView.java b/WallpaperPicker/src/com/android/photos/views/TiledImageView.java
index af4199c91..94063b027 100644
--- a/src/com/android/photos/views/TiledImageView.java
+++ b/WallpaperPicker/src/com/android/photos/views/TiledImageView.java
@@ -112,6 +112,18 @@ public class TiledImageView extends FrameLayout {
//setTileSource(new ColoredTiles());
}
+ @Override
+ public void setVisibility(int visibility) {
+ super.setVisibility(visibility);
+ // need to update inner view's visibility because it seems like we're causing it to draw
+ // from {@link #dispatchDraw} or {@link #invalidate} even if we are invisible.
+ if (USE_TEXTURE_VIEW) {
+ mTextureView.setVisibility(visibility);
+ } else {
+ mGLSurfaceView.setVisibility(visibility);
+ }
+ }
+
public void destroy() {
if (!IS_SUPPORTED) {
return;
diff --git a/proguard.flags b/proguard.flags
index fc511bff4..df4a99687 100644
--- a/proguard.flags
+++ b/proguard.flags
@@ -8,6 +8,9 @@
public void onClickAllAppsButton(android.view.View);
public void onClickAppMarketButton(android.view.View);
public void dismissFirstRunCling(android.view.View);
+ public void dismissMigrationClingCopyApps(android.view.View);
+ public void dismissMigrationClingUseDefault(android.view.View);
+ public void dismissMigrationWorkspaceCling(android.view.View);
public void dismissWorkspaceCling(android.view.View);
public void dismissAllAppsCling(android.view.View);
}
diff --git a/res/anim/drop_down.xml b/res/anim/drop_down.xml
new file mode 100644
index 000000000..49059a048
--- /dev/null
+++ b/res/anim/drop_down.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:interpolator="@android:interpolator/accelerate_decelerate">
+ <scale
+ android:fromXScale="1.0"
+ android:toXScale="1.0"
+ android:fromYScale="2.5"
+ android:toYScale="1.0"
+ android:pivotX="50%"
+ android:pivotY="50%"
+ android:duration="300"
+ android:fillBefore="false" />
+</set>
diff --git a/res/anim/enter_from_left.xml b/res/anim/enter_from_left.xml
new file mode 100644
index 000000000..e2bdbdda3
--- /dev/null
+++ b/res/anim/enter_from_left.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<set
+ xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <objectAnimator
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:duration="300"
+ android:propertyName="x"
+ android:valueFrom="-1000"
+ android:valueTo="0"
+ android:valueType="floatType" />
+</set>
diff --git a/res/anim/enter_from_right.xml b/res/anim/enter_from_right.xml
new file mode 100644
index 000000000..02a56c7ae
--- /dev/null
+++ b/res/anim/enter_from_right.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<set
+ xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <objectAnimator
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:duration="300"
+ android:propertyName="x"
+ android:valueFrom="1000"
+ android:valueTo="0"
+ android:valueType="floatType" />
+</set>
diff --git a/res/anim/exit_out_left.xml b/res/anim/exit_out_left.xml
new file mode 100644
index 000000000..eae925a2a
--- /dev/null
+++ b/res/anim/exit_out_left.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<set
+ xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <objectAnimator
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:duration="300"
+ android:propertyName="x"
+ android:valueFrom="0"
+ android:valueTo="-1000"
+ android:valueType="floatType" />
+</set>
+
diff --git a/res/anim/exit_out_right.xml b/res/anim/exit_out_right.xml
new file mode 100644
index 000000000..7345c942d
--- /dev/null
+++ b/res/anim/exit_out_right.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<set
+ xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <objectAnimator
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:duration="300"
+ android:propertyName="x"
+ android:valueFrom="0"
+ android:valueTo="1000"
+ android:valueType="floatType" />
+</set>
diff --git a/res/color/listitem_text.xml b/res/color/listitem_text.xml
new file mode 100644
index 000000000..c17b8555d
--- /dev/null
+++ b/res/color/listitem_text.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android" >
+ <item android:state_enabled="true"
+ android:state_pressed="true" android:color="@color/settings_bg_color" />
+ <item android:color="@android:color/white" />
+</selector>
diff --git a/res/drawable-hdpi/folder_lock.png b/res/drawable-hdpi/folder_lock.png
new file mode 100644
index 000000000..9d5ac426d
--- /dev/null
+++ b/res/drawable-hdpi/folder_lock.png
Binary files differ
diff --git a/res/drawable-hdpi/folder_lock_light.png b/res/drawable-hdpi/folder_lock_light.png
new file mode 100644
index 000000000..ca849e8d7
--- /dev/null
+++ b/res/drawable-hdpi/folder_lock_light.png
Binary files differ
diff --git a/res/drawable-hdpi/folder_unlock.png b/res/drawable-hdpi/folder_unlock.png
new file mode 100644
index 000000000..58524209c
--- /dev/null
+++ b/res/drawable-hdpi/folder_unlock.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_clear.png b/res/drawable-hdpi/ic_clear.png
deleted file mode 100644
index 67e0e6695..000000000
--- a/res/drawable-hdpi/ic_clear.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/ic_default_screen.png b/res/drawable-hdpi/ic_default_screen.png
index 832fdef35..8a6996340 100644
--- a/res/drawable-hdpi/ic_default_screen.png
+++ b/res/drawable-hdpi/ic_default_screen.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_default_screen_pressed.png b/res/drawable-hdpi/ic_default_screen_pressed.png
index 2975c6152..e3a7969e5 100644
--- a/res/drawable-hdpi/ic_default_screen_pressed.png
+++ b/res/drawable-hdpi/ic_default_screen_pressed.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_iconpacks.png b/res/drawable-hdpi/ic_iconpacks.png
deleted file mode 100644
index 7985c1847..000000000
--- a/res/drawable-hdpi/ic_iconpacks.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/ic_remove.png b/res/drawable-hdpi/ic_remove.png
new file mode 100644
index 000000000..d26b12b8f
--- /dev/null
+++ b/res/drawable-hdpi/ic_remove.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_setting.png b/res/drawable-hdpi/ic_setting.png
deleted file mode 100644
index c617154f1..000000000
--- a/res/drawable-hdpi/ic_setting.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/ic_setting_pressed.png b/res/drawable-hdpi/ic_setting_pressed.png
deleted file mode 100644
index fb58a4b12..000000000
--- a/res/drawable-hdpi/ic_setting_pressed.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/ic_themes.png b/res/drawable-hdpi/ic_themes.png
new file mode 100644
index 000000000..d627bcd2a
--- /dev/null
+++ b/res/drawable-hdpi/ic_themes.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_themes_pressed.png b/res/drawable-hdpi/ic_themes_pressed.png
new file mode 100644
index 000000000..b6f5c2fb9
--- /dev/null
+++ b/res/drawable-hdpi/ic_themes_pressed.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_widget.png b/res/drawable-hdpi/ic_widget.png
index e7cc5346a..8c57af0de 100644
--- a/res/drawable-hdpi/ic_widget.png
+++ b/res/drawable-hdpi/ic_widget.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_widget_pressed.png b/res/drawable-hdpi/ic_widget_pressed.png
index 4d0a1e43e..081f9f9ce 100644
--- a/res/drawable-hdpi/ic_widget_pressed.png
+++ b/res/drawable-hdpi/ic_widget_pressed.png
Binary files differ
diff --git a/res/drawable-hdpi/on_boarding_welcome.png b/res/drawable-hdpi/on_boarding_welcome.png
new file mode 100644
index 000000000..852a0cb13
--- /dev/null
+++ b/res/drawable-hdpi/on_boarding_welcome.png
Binary files differ
diff --git a/res/drawable-hdpi/screenpanel_hover.9.png b/res/drawable-hdpi/screenpanel_hover.9.png
index 3321fc925..0fed7c9d8 100644
--- a/res/drawable-hdpi/screenpanel_hover.9.png
+++ b/res/drawable-hdpi/screenpanel_hover.9.png
Binary files differ
diff --git a/res/drawable-hdpi/search_bg.9.png b/res/drawable-hdpi/search_bg.9.png
new file mode 100644
index 000000000..798127b50
--- /dev/null
+++ b/res/drawable-hdpi/search_bg.9.png
Binary files differ
diff --git a/res/drawable-mdpi/folder_lock.png b/res/drawable-mdpi/folder_lock.png
new file mode 100644
index 000000000..c44921a29
--- /dev/null
+++ b/res/drawable-mdpi/folder_lock.png
Binary files differ
diff --git a/res/drawable-mdpi/folder_lock_light.png b/res/drawable-mdpi/folder_lock_light.png
new file mode 100644
index 000000000..293444ec8
--- /dev/null
+++ b/res/drawable-mdpi/folder_lock_light.png
Binary files differ
diff --git a/res/drawable-mdpi/folder_unlock.png b/res/drawable-mdpi/folder_unlock.png
new file mode 100644
index 000000000..93e60fc45
--- /dev/null
+++ b/res/drawable-mdpi/folder_unlock.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_clear.png b/res/drawable-mdpi/ic_clear.png
deleted file mode 100644
index 9d08a42b7..000000000
--- a/res/drawable-mdpi/ic_clear.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/ic_default_screen.png b/res/drawable-mdpi/ic_default_screen.png
index 431b16841..60747a922 100644
--- a/res/drawable-mdpi/ic_default_screen.png
+++ b/res/drawable-mdpi/ic_default_screen.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_default_screen_pressed.png b/res/drawable-mdpi/ic_default_screen_pressed.png
index 361f023f8..f18ee2c5f 100644
--- a/res/drawable-mdpi/ic_default_screen_pressed.png
+++ b/res/drawable-mdpi/ic_default_screen_pressed.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_iconpacks.png b/res/drawable-mdpi/ic_iconpacks.png
deleted file mode 100644
index 36e35c215..000000000
--- a/res/drawable-mdpi/ic_iconpacks.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/ic_remove.png b/res/drawable-mdpi/ic_remove.png
new file mode 100644
index 000000000..48c82fa1c
--- /dev/null
+++ b/res/drawable-mdpi/ic_remove.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_setting.png b/res/drawable-mdpi/ic_setting.png
deleted file mode 100644
index 0c8ae9d65..000000000
--- a/res/drawable-mdpi/ic_setting.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/ic_setting_pressed.png b/res/drawable-mdpi/ic_setting_pressed.png
deleted file mode 100644
index 846091f58..000000000
--- a/res/drawable-mdpi/ic_setting_pressed.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/ic_themes.png b/res/drawable-mdpi/ic_themes.png
new file mode 100644
index 000000000..f38a683a8
--- /dev/null
+++ b/res/drawable-mdpi/ic_themes.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_themes_pressed.png b/res/drawable-mdpi/ic_themes_pressed.png
new file mode 100644
index 000000000..29b929b7d
--- /dev/null
+++ b/res/drawable-mdpi/ic_themes_pressed.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_widget.png b/res/drawable-mdpi/ic_widget.png
index 955ebf5b7..5f974c28c 100644
--- a/res/drawable-mdpi/ic_widget.png
+++ b/res/drawable-mdpi/ic_widget.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_widget_pressed.png b/res/drawable-mdpi/ic_widget_pressed.png
index f65f49f8a..0a3e8838f 100644
--- a/res/drawable-mdpi/ic_widget_pressed.png
+++ b/res/drawable-mdpi/ic_widget_pressed.png
Binary files differ
diff --git a/res/drawable-mdpi/on_boarding_welcome.png b/res/drawable-mdpi/on_boarding_welcome.png
new file mode 100644
index 000000000..1d12e8362
--- /dev/null
+++ b/res/drawable-mdpi/on_boarding_welcome.png
Binary files differ
diff --git a/res/drawable-mdpi/screenpanel_hover.9.png b/res/drawable-mdpi/screenpanel_hover.9.png
index dd7740665..7dd885860 100644
--- a/res/drawable-mdpi/screenpanel_hover.9.png
+++ b/res/drawable-mdpi/screenpanel_hover.9.png
Binary files differ
diff --git a/res/drawable-mdpi/search_bg.9.png b/res/drawable-mdpi/search_bg.9.png
new file mode 100644
index 000000000..3b259d4fb
--- /dev/null
+++ b/res/drawable-mdpi/search_bg.9.png
Binary files differ
diff --git a/res/drawable-sw600dp-hdpi/ic_allapps.png b/res/drawable-sw600dp-hdpi/ic_allapps.png
index 8bda43569..4d1aa861b 100644
--- a/res/drawable-sw600dp-hdpi/ic_allapps.png
+++ b/res/drawable-sw600dp-hdpi/ic_allapps.png
Binary files differ
diff --git a/res/drawable-sw600dp-hdpi/ic_allapps_pressed.png b/res/drawable-sw600dp-hdpi/ic_allapps_pressed.png
index 07ff33183..fa5f0f8ba 100644
--- a/res/drawable-sw600dp-hdpi/ic_allapps_pressed.png
+++ b/res/drawable-sw600dp-hdpi/ic_allapps_pressed.png
Binary files differ
diff --git a/res/drawable-sw600dp-mdpi/ic_allapps.png b/res/drawable-sw600dp-mdpi/ic_allapps.png
index e2afea5f3..20bfb793a 100644
--- a/res/drawable-sw600dp-mdpi/ic_allapps.png
+++ b/res/drawable-sw600dp-mdpi/ic_allapps.png
Binary files differ
diff --git a/res/drawable-sw600dp-mdpi/ic_allapps_pressed.png b/res/drawable-sw600dp-mdpi/ic_allapps_pressed.png
index d409c7ed3..cfe8fe80e 100644
--- a/res/drawable-sw600dp-mdpi/ic_allapps_pressed.png
+++ b/res/drawable-sw600dp-mdpi/ic_allapps_pressed.png
Binary files differ
diff --git a/res/drawable-sw600dp-xhdpi/ic_allapps.png b/res/drawable-sw600dp-xhdpi/ic_allapps.png
index 8fed2903a..4e4a8bab0 100644
--- a/res/drawable-sw600dp-xhdpi/ic_allapps.png
+++ b/res/drawable-sw600dp-xhdpi/ic_allapps.png
Binary files differ
diff --git a/res/drawable-sw600dp-xhdpi/ic_allapps_pressed.png b/res/drawable-sw600dp-xhdpi/ic_allapps_pressed.png
index 786b676ff..a76af1b78 100644
--- a/res/drawable-sw600dp-xhdpi/ic_allapps_pressed.png
+++ b/res/drawable-sw600dp-xhdpi/ic_allapps_pressed.png
Binary files differ
diff --git a/res/drawable-sw600dp-xxhdpi/ic_allapps.png b/res/drawable-sw600dp-xxhdpi/ic_allapps.png
index 242965605..96c7e0f27 100644
--- a/res/drawable-sw600dp-xxhdpi/ic_allapps.png
+++ b/res/drawable-sw600dp-xxhdpi/ic_allapps.png
Binary files differ
diff --git a/res/drawable-sw600dp-xxhdpi/ic_allapps_pressed.png b/res/drawable-sw600dp-xxhdpi/ic_allapps_pressed.png
index b93a51bea..9992b4644 100644
--- a/res/drawable-sw600dp-xxhdpi/ic_allapps_pressed.png
+++ b/res/drawable-sw600dp-xxhdpi/ic_allapps_pressed.png
Binary files differ
diff --git a/res/drawable-sw720dp-xxhdpi/workspace_bg.9.png b/res/drawable-sw720dp-xxhdpi/workspace_bg.9.png
new file mode 100644
index 000000000..efc9b0465
--- /dev/null
+++ b/res/drawable-sw720dp-xxhdpi/workspace_bg.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/folder_lock.png b/res/drawable-xhdpi/folder_lock.png
new file mode 100644
index 000000000..5d8610b2f
--- /dev/null
+++ b/res/drawable-xhdpi/folder_lock.png
Binary files differ
diff --git a/res/drawable-xhdpi/folder_lock_light.png b/res/drawable-xhdpi/folder_lock_light.png
new file mode 100644
index 000000000..4342c50f6
--- /dev/null
+++ b/res/drawable-xhdpi/folder_lock_light.png
Binary files differ
diff --git a/res/drawable-xhdpi/folder_unlock.png b/res/drawable-xhdpi/folder_unlock.png
new file mode 100644
index 000000000..a5b99c376
--- /dev/null
+++ b/res/drawable-xhdpi/folder_unlock.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_clear.png b/res/drawable-xhdpi/ic_clear.png
deleted file mode 100644
index d5925c795..000000000
--- a/res/drawable-xhdpi/ic_clear.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/ic_default_screen.png b/res/drawable-xhdpi/ic_default_screen.png
index da1e3a883..fcb9a97ae 100644
--- a/res/drawable-xhdpi/ic_default_screen.png
+++ b/res/drawable-xhdpi/ic_default_screen.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_default_screen_pressed.png b/res/drawable-xhdpi/ic_default_screen_pressed.png
index b8dc28c0c..cb360b20d 100644
--- a/res/drawable-xhdpi/ic_default_screen_pressed.png
+++ b/res/drawable-xhdpi/ic_default_screen_pressed.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_iconpacks.png b/res/drawable-xhdpi/ic_iconpacks.png
deleted file mode 100644
index 207d68a35..000000000
--- a/res/drawable-xhdpi/ic_iconpacks.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/ic_remove.png b/res/drawable-xhdpi/ic_remove.png
new file mode 100644
index 000000000..38a8705ad
--- /dev/null
+++ b/res/drawable-xhdpi/ic_remove.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_setting.png b/res/drawable-xhdpi/ic_setting.png
deleted file mode 100644
index 91ba98c55..000000000
--- a/res/drawable-xhdpi/ic_setting.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/ic_setting_pressed.png b/res/drawable-xhdpi/ic_setting_pressed.png
deleted file mode 100644
index 08aafc405..000000000
--- a/res/drawable-xhdpi/ic_setting_pressed.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/ic_themes.png b/res/drawable-xhdpi/ic_themes.png
new file mode 100644
index 000000000..550e5d09b
--- /dev/null
+++ b/res/drawable-xhdpi/ic_themes.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_themes_pressed.png b/res/drawable-xhdpi/ic_themes_pressed.png
new file mode 100644
index 000000000..49653566a
--- /dev/null
+++ b/res/drawable-xhdpi/ic_themes_pressed.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_widget.png b/res/drawable-xhdpi/ic_widget.png
index fae347ba7..47dcdd14f 100644
--- a/res/drawable-xhdpi/ic_widget.png
+++ b/res/drawable-xhdpi/ic_widget.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_widget_pressed.png b/res/drawable-xhdpi/ic_widget_pressed.png
index eca9bcc26..8bb387b88 100644
--- a/res/drawable-xhdpi/ic_widget_pressed.png
+++ b/res/drawable-xhdpi/ic_widget_pressed.png
Binary files differ
diff --git a/res/drawable-xhdpi/on_boarding_welcome.png b/res/drawable-xhdpi/on_boarding_welcome.png
new file mode 100644
index 000000000..8c101e0db
--- /dev/null
+++ b/res/drawable-xhdpi/on_boarding_welcome.png
Binary files differ
diff --git a/res/drawable-xhdpi/screenpanel_hover.9.png b/res/drawable-xhdpi/screenpanel_hover.9.png
index a44dc113f..251bf2085 100644
--- a/res/drawable-xhdpi/screenpanel_hover.9.png
+++ b/res/drawable-xhdpi/screenpanel_hover.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/search_bg.9.png b/res/drawable-xhdpi/search_bg.9.png
new file mode 100644
index 000000000..947fd4de6
--- /dev/null
+++ b/res/drawable-xhdpi/search_bg.9.png
Binary files differ
diff --git a/res/drawable-xxhdpi/folder_lock.png b/res/drawable-xxhdpi/folder_lock.png
new file mode 100644
index 000000000..16726d395
--- /dev/null
+++ b/res/drawable-xxhdpi/folder_lock.png
Binary files differ
diff --git a/res/drawable-xxhdpi/folder_lock_light.png b/res/drawable-xxhdpi/folder_lock_light.png
new file mode 100644
index 000000000..4226f6af8
--- /dev/null
+++ b/res/drawable-xxhdpi/folder_lock_light.png
Binary files differ
diff --git a/res/drawable-xxhdpi/folder_unlock.png b/res/drawable-xxhdpi/folder_unlock.png
new file mode 100644
index 000000000..95c18cbc2
--- /dev/null
+++ b/res/drawable-xxhdpi/folder_unlock.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_clear.png b/res/drawable-xxhdpi/ic_clear.png
deleted file mode 100644
index 1472e7cc7..000000000
--- a/res/drawable-xxhdpi/ic_clear.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_default_screen.png b/res/drawable-xxhdpi/ic_default_screen.png
index 4577ad2b5..e0ee77426 100644
--- a/res/drawable-xxhdpi/ic_default_screen.png
+++ b/res/drawable-xxhdpi/ic_default_screen.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_default_screen_pressed.png b/res/drawable-xxhdpi/ic_default_screen_pressed.png
index cf9cd10e2..fb8c81575 100644
--- a/res/drawable-xxhdpi/ic_default_screen_pressed.png
+++ b/res/drawable-xxhdpi/ic_default_screen_pressed.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_iconpacks.png b/res/drawable-xxhdpi/ic_iconpacks.png
deleted file mode 100644
index d1aea29da..000000000
--- a/res/drawable-xxhdpi/ic_iconpacks.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_remove.png b/res/drawable-xxhdpi/ic_remove.png
new file mode 100644
index 000000000..ac36b34c0
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_remove.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_setting.png b/res/drawable-xxhdpi/ic_setting.png
deleted file mode 100644
index 6e1e6627c..000000000
--- a/res/drawable-xxhdpi/ic_setting.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_setting_pressed.png b/res/drawable-xxhdpi/ic_setting_pressed.png
deleted file mode 100644
index a202a40fe..000000000
--- a/res/drawable-xxhdpi/ic_setting_pressed.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_themes.png b/res/drawable-xxhdpi/ic_themes.png
new file mode 100644
index 000000000..1f68ae61f
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_themes.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_themes_pressed.png b/res/drawable-xxhdpi/ic_themes_pressed.png
new file mode 100644
index 000000000..da596ab82
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_themes_pressed.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_widget.png b/res/drawable-xxhdpi/ic_widget.png
index 3bdb42d5e..fddfecaa3 100644
--- a/res/drawable-xxhdpi/ic_widget.png
+++ b/res/drawable-xxhdpi/ic_widget.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_widget_pressed.png b/res/drawable-xxhdpi/ic_widget_pressed.png
index db6765f13..3d3670ed4 100644
--- a/res/drawable-xxhdpi/ic_widget_pressed.png
+++ b/res/drawable-xxhdpi/ic_widget_pressed.png
Binary files differ
diff --git a/res/drawable-xxhdpi/screenpanel_hover.9.png b/res/drawable-xxhdpi/screenpanel_hover.9.png
index 1ab18da6a..e8b36d8f1 100644
--- a/res/drawable-xxhdpi/screenpanel_hover.9.png
+++ b/res/drawable-xxhdpi/screenpanel_hover.9.png
Binary files differ
diff --git a/res/drawable-xxhdpi/search_bg.9.png b/res/drawable-xxhdpi/search_bg.9.png
new file mode 100644
index 000000000..6626cd99b
--- /dev/null
+++ b/res/drawable-xxhdpi/search_bg.9.png
Binary files differ
diff --git a/res/drawable/above_shadow.xml b/res/drawable/above_shadow.xml
new file mode 100644
index 000000000..5965c971e
--- /dev/null
+++ b/res/drawable/above_shadow.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+ <gradient
+ android:startColor="#20000000"
+ android:endColor="@android:color/transparent"
+ android:angle="90" >
+ </gradient>
+</shape> \ No newline at end of file
diff --git a/res/drawable/acordian_00000.png b/res/drawable/acordian_00000.png
new file mode 100644
index 000000000..72bebb4b3
--- /dev/null
+++ b/res/drawable/acordian_00000.png
Binary files differ
diff --git a/res/drawable/acordian_00001.png b/res/drawable/acordian_00001.png
new file mode 100644
index 000000000..48f07492b
--- /dev/null
+++ b/res/drawable/acordian_00001.png
Binary files differ
diff --git a/res/drawable/acordian_00002.png b/res/drawable/acordian_00002.png
new file mode 100644
index 000000000..3ae1b69ca
--- /dev/null
+++ b/res/drawable/acordian_00002.png
Binary files differ
diff --git a/res/drawable/acordian_00003.png b/res/drawable/acordian_00003.png
new file mode 100644
index 000000000..da2ffe0bf
--- /dev/null
+++ b/res/drawable/acordian_00003.png
Binary files differ
diff --git a/res/drawable/acordian_00004.png b/res/drawable/acordian_00004.png
new file mode 100644
index 000000000..66f0a26f7
--- /dev/null
+++ b/res/drawable/acordian_00004.png
Binary files differ
diff --git a/res/drawable/acordian_00005.png b/res/drawable/acordian_00005.png
new file mode 100644
index 000000000..475060766
--- /dev/null
+++ b/res/drawable/acordian_00005.png
Binary files differ
diff --git a/res/drawable/acordian_00006.png b/res/drawable/acordian_00006.png
new file mode 100644
index 000000000..b52388848
--- /dev/null
+++ b/res/drawable/acordian_00006.png
Binary files differ
diff --git a/res/drawable/acordian_00007.png b/res/drawable/acordian_00007.png
new file mode 100644
index 000000000..053036747
--- /dev/null
+++ b/res/drawable/acordian_00007.png
Binary files differ
diff --git a/res/drawable/acordian_00008.png b/res/drawable/acordian_00008.png
new file mode 100644
index 000000000..11c23fe1f
--- /dev/null
+++ b/res/drawable/acordian_00008.png
Binary files differ
diff --git a/res/drawable/acordian_00009.png b/res/drawable/acordian_00009.png
new file mode 100644
index 000000000..2fd060a03
--- /dev/null
+++ b/res/drawable/acordian_00009.png
Binary files differ
diff --git a/res/drawable/acordian_00010.png b/res/drawable/acordian_00010.png
new file mode 100644
index 000000000..5debae47a
--- /dev/null
+++ b/res/drawable/acordian_00010.png
Binary files differ
diff --git a/res/drawable/acordian_00011.png b/res/drawable/acordian_00011.png
new file mode 100644
index 000000000..5debae47a
--- /dev/null
+++ b/res/drawable/acordian_00011.png
Binary files differ
diff --git a/res/drawable/acordian_00012.png b/res/drawable/acordian_00012.png
new file mode 100644
index 000000000..5debae47a
--- /dev/null
+++ b/res/drawable/acordian_00012.png
Binary files differ
diff --git a/res/drawable/acordian_00013.png b/res/drawable/acordian_00013.png
new file mode 100644
index 000000000..5debae47a
--- /dev/null
+++ b/res/drawable/acordian_00013.png
Binary files differ
diff --git a/res/drawable/acordian_00014.png b/res/drawable/acordian_00014.png
new file mode 100644
index 000000000..5debae47a
--- /dev/null
+++ b/res/drawable/acordian_00014.png
Binary files differ
diff --git a/res/drawable/acordian_00015.png b/res/drawable/acordian_00015.png
new file mode 100644
index 000000000..5debae47a
--- /dev/null
+++ b/res/drawable/acordian_00015.png
Binary files differ
diff --git a/res/drawable/acordian_00016.png b/res/drawable/acordian_00016.png
new file mode 100644
index 000000000..5debae47a
--- /dev/null
+++ b/res/drawable/acordian_00016.png
Binary files differ
diff --git a/res/drawable/acordian_00017.png b/res/drawable/acordian_00017.png
new file mode 100644
index 000000000..5debae47a
--- /dev/null
+++ b/res/drawable/acordian_00017.png
Binary files differ
diff --git a/res/drawable/acordian_00018.png b/res/drawable/acordian_00018.png
new file mode 100644
index 000000000..5debae47a
--- /dev/null
+++ b/res/drawable/acordian_00018.png
Binary files differ
diff --git a/res/drawable/acordian_00019.png b/res/drawable/acordian_00019.png
new file mode 100644
index 000000000..5debae47a
--- /dev/null
+++ b/res/drawable/acordian_00019.png
Binary files differ
diff --git a/res/drawable/acordian_00020.png b/res/drawable/acordian_00020.png
new file mode 100644
index 000000000..5debae47a
--- /dev/null
+++ b/res/drawable/acordian_00020.png
Binary files differ
diff --git a/res/drawable/acordian_00021.png b/res/drawable/acordian_00021.png
new file mode 100644
index 000000000..5debae47a
--- /dev/null
+++ b/res/drawable/acordian_00021.png
Binary files differ
diff --git a/res/drawable/acordian_00022.png b/res/drawable/acordian_00022.png
new file mode 100644
index 000000000..5debae47a
--- /dev/null
+++ b/res/drawable/acordian_00022.png
Binary files differ
diff --git a/res/drawable/acordian_00023.png b/res/drawable/acordian_00023.png
new file mode 100644
index 000000000..5debae47a
--- /dev/null
+++ b/res/drawable/acordian_00023.png
Binary files differ
diff --git a/res/drawable/acordian_00024.png b/res/drawable/acordian_00024.png
new file mode 100644
index 000000000..5debae47a
--- /dev/null
+++ b/res/drawable/acordian_00024.png
Binary files differ
diff --git a/res/drawable/acordian_00025.png b/res/drawable/acordian_00025.png
new file mode 100644
index 000000000..5debae47a
--- /dev/null
+++ b/res/drawable/acordian_00025.png
Binary files differ
diff --git a/res/drawable/acordian_00026.png b/res/drawable/acordian_00026.png
new file mode 100644
index 000000000..5debae47a
--- /dev/null
+++ b/res/drawable/acordian_00026.png
Binary files differ
diff --git a/res/drawable/acordian_00027.png b/res/drawable/acordian_00027.png
new file mode 100644
index 000000000..2fd060a03
--- /dev/null
+++ b/res/drawable/acordian_00027.png
Binary files differ
diff --git a/res/drawable/acordian_00028.png b/res/drawable/acordian_00028.png
new file mode 100644
index 000000000..11c23fe1f
--- /dev/null
+++ b/res/drawable/acordian_00028.png
Binary files differ
diff --git a/res/drawable/acordian_00029.png b/res/drawable/acordian_00029.png
new file mode 100644
index 000000000..053036747
--- /dev/null
+++ b/res/drawable/acordian_00029.png
Binary files differ
diff --git a/res/drawable/acordian_00030.png b/res/drawable/acordian_00030.png
new file mode 100644
index 000000000..b52388848
--- /dev/null
+++ b/res/drawable/acordian_00030.png
Binary files differ
diff --git a/res/drawable/acordian_00031.png b/res/drawable/acordian_00031.png
new file mode 100644
index 000000000..734bb390d
--- /dev/null
+++ b/res/drawable/acordian_00031.png
Binary files differ
diff --git a/res/drawable/acordian_00032.png b/res/drawable/acordian_00032.png
new file mode 100644
index 000000000..66f0a26f7
--- /dev/null
+++ b/res/drawable/acordian_00032.png
Binary files differ
diff --git a/res/drawable/acordian_00033.png b/res/drawable/acordian_00033.png
new file mode 100644
index 000000000..da2ffe0bf
--- /dev/null
+++ b/res/drawable/acordian_00033.png
Binary files differ
diff --git a/res/drawable/acordian_00034.png b/res/drawable/acordian_00034.png
new file mode 100644
index 000000000..3ae1b69ca
--- /dev/null
+++ b/res/drawable/acordian_00034.png
Binary files differ
diff --git a/res/drawable/acordian_00035.png b/res/drawable/acordian_00035.png
new file mode 100644
index 000000000..48f07492b
--- /dev/null
+++ b/res/drawable/acordian_00035.png
Binary files differ
diff --git a/res/drawable/acordian_00036.png b/res/drawable/acordian_00036.png
new file mode 100644
index 000000000..72bebb4b3
--- /dev/null
+++ b/res/drawable/acordian_00036.png
Binary files differ
diff --git a/res/drawable/acordian_00037.png b/res/drawable/acordian_00037.png
new file mode 100644
index 000000000..72bebb4b3
--- /dev/null
+++ b/res/drawable/acordian_00037.png
Binary files differ
diff --git a/res/drawable/acordian_00038.png b/res/drawable/acordian_00038.png
new file mode 100644
index 000000000..72bebb4b3
--- /dev/null
+++ b/res/drawable/acordian_00038.png
Binary files differ
diff --git a/res/drawable/acordian_00039.png b/res/drawable/acordian_00039.png
new file mode 100644
index 000000000..72bebb4b3
--- /dev/null
+++ b/res/drawable/acordian_00039.png
Binary files differ
diff --git a/res/drawable/acordian_00040.png b/res/drawable/acordian_00040.png
new file mode 100644
index 000000000..72bebb4b3
--- /dev/null
+++ b/res/drawable/acordian_00040.png
Binary files differ
diff --git a/res/drawable/acordian_00041.png b/res/drawable/acordian_00041.png
new file mode 100644
index 000000000..72bebb4b3
--- /dev/null
+++ b/res/drawable/acordian_00041.png
Binary files differ
diff --git a/res/drawable/acordian_00042.png b/res/drawable/acordian_00042.png
new file mode 100644
index 000000000..72bebb4b3
--- /dev/null
+++ b/res/drawable/acordian_00042.png
Binary files differ
diff --git a/res/drawable/acordian_00043.png b/res/drawable/acordian_00043.png
new file mode 100644
index 000000000..72bebb4b3
--- /dev/null
+++ b/res/drawable/acordian_00043.png
Binary files differ
diff --git a/res/drawable/acordian_00044.png b/res/drawable/acordian_00044.png
new file mode 100644
index 000000000..72bebb4b3
--- /dev/null
+++ b/res/drawable/acordian_00044.png
Binary files differ
diff --git a/res/drawable/acordian_00045.png b/res/drawable/acordian_00045.png
new file mode 100644
index 000000000..72bebb4b3
--- /dev/null
+++ b/res/drawable/acordian_00045.png
Binary files differ
diff --git a/res/drawable/acordian_00046.png b/res/drawable/acordian_00046.png
new file mode 100644
index 000000000..72bebb4b3
--- /dev/null
+++ b/res/drawable/acordian_00046.png
Binary files differ
diff --git a/res/drawable/acordian_00047.png b/res/drawable/acordian_00047.png
new file mode 100644
index 000000000..72bebb4b3
--- /dev/null
+++ b/res/drawable/acordian_00047.png
Binary files differ
diff --git a/res/drawable/acordian_00048.png b/res/drawable/acordian_00048.png
new file mode 100644
index 000000000..72bebb4b3
--- /dev/null
+++ b/res/drawable/acordian_00048.png
Binary files differ
diff --git a/res/drawable/acordian_00049.png b/res/drawable/acordian_00049.png
new file mode 100644
index 000000000..72bebb4b3
--- /dev/null
+++ b/res/drawable/acordian_00049.png
Binary files differ
diff --git a/res/drawable/below_shadow.xml b/res/drawable/below_shadow.xml
new file mode 100644
index 000000000..c724e27d3
--- /dev/null
+++ b/res/drawable/below_shadow.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+ <gradient
+ android:startColor="#20000000"
+ android:endColor="@android:color/transparent"
+ android:angle="270" >
+ </gradient>
+</shape> \ No newline at end of file
diff --git a/res/drawable/carousel_00000.png b/res/drawable/carousel_00000.png
new file mode 100644
index 000000000..d444d1318
--- /dev/null
+++ b/res/drawable/carousel_00000.png
Binary files differ
diff --git a/res/drawable/carousel_00001.png b/res/drawable/carousel_00001.png
new file mode 100644
index 000000000..ebd6200a4
--- /dev/null
+++ b/res/drawable/carousel_00001.png
Binary files differ
diff --git a/res/drawable/carousel_00002.png b/res/drawable/carousel_00002.png
new file mode 100644
index 000000000..121f26fa6
--- /dev/null
+++ b/res/drawable/carousel_00002.png
Binary files differ
diff --git a/res/drawable/carousel_00003.png b/res/drawable/carousel_00003.png
new file mode 100644
index 000000000..9a61cb40b
--- /dev/null
+++ b/res/drawable/carousel_00003.png
Binary files differ
diff --git a/res/drawable/carousel_00004.png b/res/drawable/carousel_00004.png
new file mode 100644
index 000000000..4f9a741cc
--- /dev/null
+++ b/res/drawable/carousel_00004.png
Binary files differ
diff --git a/res/drawable/carousel_00005.png b/res/drawable/carousel_00005.png
new file mode 100644
index 000000000..32eadfea5
--- /dev/null
+++ b/res/drawable/carousel_00005.png
Binary files differ
diff --git a/res/drawable/carousel_00006.png b/res/drawable/carousel_00006.png
new file mode 100644
index 000000000..e9d8cd625
--- /dev/null
+++ b/res/drawable/carousel_00006.png
Binary files differ
diff --git a/res/drawable/carousel_00007.png b/res/drawable/carousel_00007.png
new file mode 100644
index 000000000..d4202b14c
--- /dev/null
+++ b/res/drawable/carousel_00007.png
Binary files differ
diff --git a/res/drawable/carousel_00008.png b/res/drawable/carousel_00008.png
new file mode 100644
index 000000000..88247f836
--- /dev/null
+++ b/res/drawable/carousel_00008.png
Binary files differ
diff --git a/res/drawable/carousel_00009.png b/res/drawable/carousel_00009.png
new file mode 100644
index 000000000..503f791fe
--- /dev/null
+++ b/res/drawable/carousel_00009.png
Binary files differ
diff --git a/res/drawable/carousel_00010.png b/res/drawable/carousel_00010.png
new file mode 100644
index 000000000..b439edc22
--- /dev/null
+++ b/res/drawable/carousel_00010.png
Binary files differ
diff --git a/res/drawable/carousel_00011.png b/res/drawable/carousel_00011.png
new file mode 100644
index 000000000..80a7eca42
--- /dev/null
+++ b/res/drawable/carousel_00011.png
Binary files differ
diff --git a/res/drawable/carousel_00012.png b/res/drawable/carousel_00012.png
new file mode 100644
index 000000000..57e72b869
--- /dev/null
+++ b/res/drawable/carousel_00012.png
Binary files differ
diff --git a/res/drawable/carousel_00013.png b/res/drawable/carousel_00013.png
new file mode 100644
index 000000000..6211a520e
--- /dev/null
+++ b/res/drawable/carousel_00013.png
Binary files differ
diff --git a/res/drawable/carousel_00014.png b/res/drawable/carousel_00014.png
new file mode 100644
index 000000000..714466bdd
--- /dev/null
+++ b/res/drawable/carousel_00014.png
Binary files differ
diff --git a/res/drawable/carousel_00015.png b/res/drawable/carousel_00015.png
new file mode 100644
index 000000000..0b34111c4
--- /dev/null
+++ b/res/drawable/carousel_00015.png
Binary files differ
diff --git a/res/drawable/carousel_00016.png b/res/drawable/carousel_00016.png
new file mode 100644
index 000000000..a3c08cd13
--- /dev/null
+++ b/res/drawable/carousel_00016.png
Binary files differ
diff --git a/res/drawable/carousel_00017.png b/res/drawable/carousel_00017.png
new file mode 100644
index 000000000..5fa15a7cb
--- /dev/null
+++ b/res/drawable/carousel_00017.png
Binary files differ
diff --git a/res/drawable/carousel_00018.png b/res/drawable/carousel_00018.png
new file mode 100644
index 000000000..e10df7dd0
--- /dev/null
+++ b/res/drawable/carousel_00018.png
Binary files differ
diff --git a/res/drawable/carousel_00019.png b/res/drawable/carousel_00019.png
new file mode 100644
index 000000000..4e3765b40
--- /dev/null
+++ b/res/drawable/carousel_00019.png
Binary files differ
diff --git a/res/drawable/carousel_00020.png b/res/drawable/carousel_00020.png
new file mode 100644
index 000000000..d444d1318
--- /dev/null
+++ b/res/drawable/carousel_00020.png
Binary files differ
diff --git a/res/drawable/carousel_00021.png b/res/drawable/carousel_00021.png
new file mode 100644
index 000000000..d444d1318
--- /dev/null
+++ b/res/drawable/carousel_00021.png
Binary files differ
diff --git a/res/drawable/carousel_00022.png b/res/drawable/carousel_00022.png
new file mode 100644
index 000000000..d444d1318
--- /dev/null
+++ b/res/drawable/carousel_00022.png
Binary files differ
diff --git a/res/drawable/carousel_00023.png b/res/drawable/carousel_00023.png
new file mode 100644
index 000000000..d444d1318
--- /dev/null
+++ b/res/drawable/carousel_00023.png
Binary files differ
diff --git a/res/drawable/carousel_00024.png b/res/drawable/carousel_00024.png
new file mode 100644
index 000000000..d444d1318
--- /dev/null
+++ b/res/drawable/carousel_00024.png
Binary files differ
diff --git a/res/drawable/carousel_00025.png b/res/drawable/carousel_00025.png
new file mode 100644
index 000000000..d444d1318
--- /dev/null
+++ b/res/drawable/carousel_00025.png
Binary files differ
diff --git a/res/drawable/carousel_00026.png b/res/drawable/carousel_00026.png
new file mode 100644
index 000000000..d444d1318
--- /dev/null
+++ b/res/drawable/carousel_00026.png
Binary files differ
diff --git a/res/drawable/carousel_00027.png b/res/drawable/carousel_00027.png
new file mode 100644
index 000000000..d444d1318
--- /dev/null
+++ b/res/drawable/carousel_00027.png
Binary files differ
diff --git a/res/drawable/carousel_00028.png b/res/drawable/carousel_00028.png
new file mode 100644
index 000000000..d444d1318
--- /dev/null
+++ b/res/drawable/carousel_00028.png
Binary files differ
diff --git a/res/drawable/carousel_00029.png b/res/drawable/carousel_00029.png
new file mode 100644
index 000000000..d444d1318
--- /dev/null
+++ b/res/drawable/carousel_00029.png
Binary files differ
diff --git a/res/drawable/carousel_00030.png b/res/drawable/carousel_00030.png
new file mode 100644
index 000000000..d444d1318
--- /dev/null
+++ b/res/drawable/carousel_00030.png
Binary files differ
diff --git a/res/drawable/carousel_00031.png b/res/drawable/carousel_00031.png
new file mode 100644
index 000000000..d444d1318
--- /dev/null
+++ b/res/drawable/carousel_00031.png
Binary files differ
diff --git a/res/drawable/carousel_00032.png b/res/drawable/carousel_00032.png
new file mode 100644
index 000000000..d444d1318
--- /dev/null
+++ b/res/drawable/carousel_00032.png
Binary files differ
diff --git a/res/drawable/carousel_00033.png b/res/drawable/carousel_00033.png
new file mode 100644
index 000000000..d444d1318
--- /dev/null
+++ b/res/drawable/carousel_00033.png
Binary files differ
diff --git a/res/drawable/carousel_00034.png b/res/drawable/carousel_00034.png
new file mode 100644
index 000000000..d444d1318
--- /dev/null
+++ b/res/drawable/carousel_00034.png
Binary files differ
diff --git a/res/drawable/carousel_00035.png b/res/drawable/carousel_00035.png
new file mode 100644
index 000000000..d444d1318
--- /dev/null
+++ b/res/drawable/carousel_00035.png
Binary files differ
diff --git a/res/drawable/carousel_00036.png b/res/drawable/carousel_00036.png
new file mode 100644
index 000000000..d444d1318
--- /dev/null
+++ b/res/drawable/carousel_00036.png
Binary files differ
diff --git a/res/drawable/carousel_00037.png b/res/drawable/carousel_00037.png
new file mode 100644
index 000000000..d444d1318
--- /dev/null
+++ b/res/drawable/carousel_00037.png
Binary files differ
diff --git a/res/drawable/carousel_00038.png b/res/drawable/carousel_00038.png
new file mode 100644
index 000000000..d444d1318
--- /dev/null
+++ b/res/drawable/carousel_00038.png
Binary files differ
diff --git a/res/drawable/carousel_00039.png b/res/drawable/carousel_00039.png
new file mode 100644
index 000000000..d444d1318
--- /dev/null
+++ b/res/drawable/carousel_00039.png
Binary files differ
diff --git a/res/drawable/carousel_00040.png b/res/drawable/carousel_00040.png
new file mode 100644
index 000000000..d444d1318
--- /dev/null
+++ b/res/drawable/carousel_00040.png
Binary files differ
diff --git a/res/drawable/carousel_00041.png b/res/drawable/carousel_00041.png
new file mode 100644
index 000000000..d444d1318
--- /dev/null
+++ b/res/drawable/carousel_00041.png
Binary files differ
diff --git a/res/drawable/carousel_00042.png b/res/drawable/carousel_00042.png
new file mode 100644
index 000000000..d444d1318
--- /dev/null
+++ b/res/drawable/carousel_00042.png
Binary files differ
diff --git a/res/drawable/carousel_00043.png b/res/drawable/carousel_00043.png
new file mode 100644
index 000000000..d444d1318
--- /dev/null
+++ b/res/drawable/carousel_00043.png
Binary files differ
diff --git a/res/drawable/carousel_00044.png b/res/drawable/carousel_00044.png
new file mode 100644
index 000000000..d444d1318
--- /dev/null
+++ b/res/drawable/carousel_00044.png
Binary files differ
diff --git a/res/drawable/carousel_00045.png b/res/drawable/carousel_00045.png
new file mode 100644
index 000000000..d444d1318
--- /dev/null
+++ b/res/drawable/carousel_00045.png
Binary files differ
diff --git a/res/drawable/carousel_00046.png b/res/drawable/carousel_00046.png
new file mode 100644
index 000000000..d444d1318
--- /dev/null
+++ b/res/drawable/carousel_00046.png
Binary files differ
diff --git a/res/drawable/carousel_00047.png b/res/drawable/carousel_00047.png
new file mode 100644
index 000000000..d444d1318
--- /dev/null
+++ b/res/drawable/carousel_00047.png
Binary files differ
diff --git a/res/drawable/carousel_00048.png b/res/drawable/carousel_00048.png
new file mode 100644
index 000000000..d444d1318
--- /dev/null
+++ b/res/drawable/carousel_00048.png
Binary files differ
diff --git a/res/drawable/carousel_00049.png b/res/drawable/carousel_00049.png
new file mode 100644
index 000000000..d444d1318
--- /dev/null
+++ b/res/drawable/carousel_00049.png
Binary files differ
diff --git a/res/drawable/cubein_00000.png b/res/drawable/cubein_00000.png
new file mode 100644
index 000000000..678a89d23
--- /dev/null
+++ b/res/drawable/cubein_00000.png
Binary files differ
diff --git a/res/drawable/cubein_00001.png b/res/drawable/cubein_00001.png
new file mode 100644
index 000000000..322899f46
--- /dev/null
+++ b/res/drawable/cubein_00001.png
Binary files differ
diff --git a/res/drawable/cubein_00002.png b/res/drawable/cubein_00002.png
new file mode 100644
index 000000000..3d963c7ee
--- /dev/null
+++ b/res/drawable/cubein_00002.png
Binary files differ
diff --git a/res/drawable/cubein_00003.png b/res/drawable/cubein_00003.png
new file mode 100644
index 000000000..7dabd0bf3
--- /dev/null
+++ b/res/drawable/cubein_00003.png
Binary files differ
diff --git a/res/drawable/cubein_00004.png b/res/drawable/cubein_00004.png
new file mode 100644
index 000000000..b73ce02c8
--- /dev/null
+++ b/res/drawable/cubein_00004.png
Binary files differ
diff --git a/res/drawable/cubein_00005.png b/res/drawable/cubein_00005.png
new file mode 100644
index 000000000..d9c7ea1f0
--- /dev/null
+++ b/res/drawable/cubein_00005.png
Binary files differ
diff --git a/res/drawable/cubein_00006.png b/res/drawable/cubein_00006.png
new file mode 100644
index 000000000..2b3198bc9
--- /dev/null
+++ b/res/drawable/cubein_00006.png
Binary files differ
diff --git a/res/drawable/cubein_00007.png b/res/drawable/cubein_00007.png
new file mode 100644
index 000000000..915fbe71f
--- /dev/null
+++ b/res/drawable/cubein_00007.png
Binary files differ
diff --git a/res/drawable/cubein_00008.png b/res/drawable/cubein_00008.png
new file mode 100644
index 000000000..4eee981b6
--- /dev/null
+++ b/res/drawable/cubein_00008.png
Binary files differ
diff --git a/res/drawable/cubein_00009.png b/res/drawable/cubein_00009.png
new file mode 100644
index 000000000..516661963
--- /dev/null
+++ b/res/drawable/cubein_00009.png
Binary files differ
diff --git a/res/drawable/cubein_00010.png b/res/drawable/cubein_00010.png
new file mode 100644
index 000000000..3fdb7af1a
--- /dev/null
+++ b/res/drawable/cubein_00010.png
Binary files differ
diff --git a/res/drawable/cubein_00011.png b/res/drawable/cubein_00011.png
new file mode 100644
index 000000000..273b70afa
--- /dev/null
+++ b/res/drawable/cubein_00011.png
Binary files differ
diff --git a/res/drawable/cubein_00012.png b/res/drawable/cubein_00012.png
new file mode 100644
index 000000000..4ed7571c0
--- /dev/null
+++ b/res/drawable/cubein_00012.png
Binary files differ
diff --git a/res/drawable/cubein_00013.png b/res/drawable/cubein_00013.png
new file mode 100644
index 000000000..6ec50e73c
--- /dev/null
+++ b/res/drawable/cubein_00013.png
Binary files differ
diff --git a/res/drawable/cubein_00014.png b/res/drawable/cubein_00014.png
new file mode 100644
index 000000000..78eee8c7f
--- /dev/null
+++ b/res/drawable/cubein_00014.png
Binary files differ
diff --git a/res/drawable/cubein_00015.png b/res/drawable/cubein_00015.png
new file mode 100644
index 000000000..cbf4bbd53
--- /dev/null
+++ b/res/drawable/cubein_00015.png
Binary files differ
diff --git a/res/drawable/cubein_00016.png b/res/drawable/cubein_00016.png
new file mode 100644
index 000000000..3bd56fc2d
--- /dev/null
+++ b/res/drawable/cubein_00016.png
Binary files differ
diff --git a/res/drawable/cubein_00017.png b/res/drawable/cubein_00017.png
new file mode 100644
index 000000000..2783f73b1
--- /dev/null
+++ b/res/drawable/cubein_00017.png
Binary files differ
diff --git a/res/drawable/cubein_00018.png b/res/drawable/cubein_00018.png
new file mode 100644
index 000000000..052c7b22b
--- /dev/null
+++ b/res/drawable/cubein_00018.png
Binary files differ
diff --git a/res/drawable/cubein_00019.png b/res/drawable/cubein_00019.png
new file mode 100644
index 000000000..7c99a679b
--- /dev/null
+++ b/res/drawable/cubein_00019.png
Binary files differ
diff --git a/res/drawable/cubein_00020.png b/res/drawable/cubein_00020.png
new file mode 100644
index 000000000..1662df8dc
--- /dev/null
+++ b/res/drawable/cubein_00020.png
Binary files differ
diff --git a/res/drawable/cubein_00021.png b/res/drawable/cubein_00021.png
new file mode 100644
index 000000000..1662df8dc
--- /dev/null
+++ b/res/drawable/cubein_00021.png
Binary files differ
diff --git a/res/drawable/cubein_00022.png b/res/drawable/cubein_00022.png
new file mode 100644
index 000000000..1662df8dc
--- /dev/null
+++ b/res/drawable/cubein_00022.png
Binary files differ
diff --git a/res/drawable/cubein_00023.png b/res/drawable/cubein_00023.png
new file mode 100644
index 000000000..1662df8dc
--- /dev/null
+++ b/res/drawable/cubein_00023.png
Binary files differ
diff --git a/res/drawable/cubein_00024.png b/res/drawable/cubein_00024.png
new file mode 100644
index 000000000..1662df8dc
--- /dev/null
+++ b/res/drawable/cubein_00024.png
Binary files differ
diff --git a/res/drawable/cubein_00025.png b/res/drawable/cubein_00025.png
new file mode 100644
index 000000000..1662df8dc
--- /dev/null
+++ b/res/drawable/cubein_00025.png
Binary files differ
diff --git a/res/drawable/cubein_00026.png b/res/drawable/cubein_00026.png
new file mode 100644
index 000000000..1662df8dc
--- /dev/null
+++ b/res/drawable/cubein_00026.png
Binary files differ
diff --git a/res/drawable/cubein_00027.png b/res/drawable/cubein_00027.png
new file mode 100644
index 000000000..1662df8dc
--- /dev/null
+++ b/res/drawable/cubein_00027.png
Binary files differ
diff --git a/res/drawable/cubein_00028.png b/res/drawable/cubein_00028.png
new file mode 100644
index 000000000..1662df8dc
--- /dev/null
+++ b/res/drawable/cubein_00028.png
Binary files differ
diff --git a/res/drawable/cubein_00029.png b/res/drawable/cubein_00029.png
new file mode 100644
index 000000000..1662df8dc
--- /dev/null
+++ b/res/drawable/cubein_00029.png
Binary files differ
diff --git a/res/drawable/cubein_00030.png b/res/drawable/cubein_00030.png
new file mode 100644
index 000000000..1662df8dc
--- /dev/null
+++ b/res/drawable/cubein_00030.png
Binary files differ
diff --git a/res/drawable/cubein_00031.png b/res/drawable/cubein_00031.png
new file mode 100644
index 000000000..1662df8dc
--- /dev/null
+++ b/res/drawable/cubein_00031.png
Binary files differ
diff --git a/res/drawable/cubein_00032.png b/res/drawable/cubein_00032.png
new file mode 100644
index 000000000..1662df8dc
--- /dev/null
+++ b/res/drawable/cubein_00032.png
Binary files differ
diff --git a/res/drawable/cubein_00033.png b/res/drawable/cubein_00033.png
new file mode 100644
index 000000000..1662df8dc
--- /dev/null
+++ b/res/drawable/cubein_00033.png
Binary files differ
diff --git a/res/drawable/cubein_00034.png b/res/drawable/cubein_00034.png
new file mode 100644
index 000000000..1662df8dc
--- /dev/null
+++ b/res/drawable/cubein_00034.png
Binary files differ
diff --git a/res/drawable/cubein_00035.png b/res/drawable/cubein_00035.png
new file mode 100644
index 000000000..1662df8dc
--- /dev/null
+++ b/res/drawable/cubein_00035.png
Binary files differ
diff --git a/res/drawable/cubein_00036.png b/res/drawable/cubein_00036.png
new file mode 100644
index 000000000..1662df8dc
--- /dev/null
+++ b/res/drawable/cubein_00036.png
Binary files differ
diff --git a/res/drawable/cubein_00037.png b/res/drawable/cubein_00037.png
new file mode 100644
index 000000000..1662df8dc
--- /dev/null
+++ b/res/drawable/cubein_00037.png
Binary files differ
diff --git a/res/drawable/cubein_00038.png b/res/drawable/cubein_00038.png
new file mode 100644
index 000000000..1662df8dc
--- /dev/null
+++ b/res/drawable/cubein_00038.png
Binary files differ
diff --git a/res/drawable/cubein_00039.png b/res/drawable/cubein_00039.png
new file mode 100644
index 000000000..1662df8dc
--- /dev/null
+++ b/res/drawable/cubein_00039.png
Binary files differ
diff --git a/res/drawable/cubein_00040.png b/res/drawable/cubein_00040.png
new file mode 100644
index 000000000..1662df8dc
--- /dev/null
+++ b/res/drawable/cubein_00040.png
Binary files differ
diff --git a/res/drawable/cubein_00041.png b/res/drawable/cubein_00041.png
new file mode 100644
index 000000000..1662df8dc
--- /dev/null
+++ b/res/drawable/cubein_00041.png
Binary files differ
diff --git a/res/drawable/cubein_00042.png b/res/drawable/cubein_00042.png
new file mode 100644
index 000000000..1662df8dc
--- /dev/null
+++ b/res/drawable/cubein_00042.png
Binary files differ
diff --git a/res/drawable/cubein_00043.png b/res/drawable/cubein_00043.png
new file mode 100644
index 000000000..1662df8dc
--- /dev/null
+++ b/res/drawable/cubein_00043.png
Binary files differ
diff --git a/res/drawable/cubein_00044.png b/res/drawable/cubein_00044.png
new file mode 100644
index 000000000..1662df8dc
--- /dev/null
+++ b/res/drawable/cubein_00044.png
Binary files differ
diff --git a/res/drawable/cubein_00045.png b/res/drawable/cubein_00045.png
new file mode 100644
index 000000000..1662df8dc
--- /dev/null
+++ b/res/drawable/cubein_00045.png
Binary files differ
diff --git a/res/drawable/cubein_00046.png b/res/drawable/cubein_00046.png
new file mode 100644
index 000000000..1662df8dc
--- /dev/null
+++ b/res/drawable/cubein_00046.png
Binary files differ
diff --git a/res/drawable/cubein_00047.png b/res/drawable/cubein_00047.png
new file mode 100644
index 000000000..1662df8dc
--- /dev/null
+++ b/res/drawable/cubein_00047.png
Binary files differ
diff --git a/res/drawable/cubein_00048.png b/res/drawable/cubein_00048.png
new file mode 100644
index 000000000..1662df8dc
--- /dev/null
+++ b/res/drawable/cubein_00048.png
Binary files differ
diff --git a/res/drawable/cubein_00049.png b/res/drawable/cubein_00049.png
new file mode 100644
index 000000000..1662df8dc
--- /dev/null
+++ b/res/drawable/cubein_00049.png
Binary files differ
diff --git a/res/drawable/cubeout_00000.png b/res/drawable/cubeout_00000.png
new file mode 100644
index 000000000..d444d1318
--- /dev/null
+++ b/res/drawable/cubeout_00000.png
Binary files differ
diff --git a/res/drawable/cubeout_00001.png b/res/drawable/cubeout_00001.png
new file mode 100644
index 000000000..69b57487c
--- /dev/null
+++ b/res/drawable/cubeout_00001.png
Binary files differ
diff --git a/res/drawable/cubeout_00002.png b/res/drawable/cubeout_00002.png
new file mode 100644
index 000000000..58f4191ae
--- /dev/null
+++ b/res/drawable/cubeout_00002.png
Binary files differ
diff --git a/res/drawable/cubeout_00003.png b/res/drawable/cubeout_00003.png
new file mode 100644
index 000000000..096771ec5
--- /dev/null
+++ b/res/drawable/cubeout_00003.png
Binary files differ
diff --git a/res/drawable/cubeout_00004.png b/res/drawable/cubeout_00004.png
new file mode 100644
index 000000000..2d027ffa5
--- /dev/null
+++ b/res/drawable/cubeout_00004.png
Binary files differ
diff --git a/res/drawable/cubeout_00005.png b/res/drawable/cubeout_00005.png
new file mode 100644
index 000000000..bc3876565
--- /dev/null
+++ b/res/drawable/cubeout_00005.png
Binary files differ
diff --git a/res/drawable/cubeout_00006.png b/res/drawable/cubeout_00006.png
new file mode 100644
index 000000000..742bebd0e
--- /dev/null
+++ b/res/drawable/cubeout_00006.png
Binary files differ
diff --git a/res/drawable/cubeout_00007.png b/res/drawable/cubeout_00007.png
new file mode 100644
index 000000000..ec7b63326
--- /dev/null
+++ b/res/drawable/cubeout_00007.png
Binary files differ
diff --git a/res/drawable/cubeout_00008.png b/res/drawable/cubeout_00008.png
new file mode 100644
index 000000000..5eb601422
--- /dev/null
+++ b/res/drawable/cubeout_00008.png
Binary files differ
diff --git a/res/drawable/cubeout_00009.png b/res/drawable/cubeout_00009.png
new file mode 100644
index 000000000..30559fb95
--- /dev/null
+++ b/res/drawable/cubeout_00009.png
Binary files differ
diff --git a/res/drawable/cubeout_00010.png b/res/drawable/cubeout_00010.png
new file mode 100644
index 000000000..fa8b785fd
--- /dev/null
+++ b/res/drawable/cubeout_00010.png
Binary files differ
diff --git a/res/drawable/cubeout_00011.png b/res/drawable/cubeout_00011.png
new file mode 100644
index 000000000..9de04f3e3
--- /dev/null
+++ b/res/drawable/cubeout_00011.png
Binary files differ
diff --git a/res/drawable/cubeout_00012.png b/res/drawable/cubeout_00012.png
new file mode 100644
index 000000000..343901380
--- /dev/null
+++ b/res/drawable/cubeout_00012.png
Binary files differ
diff --git a/res/drawable/cubeout_00013.png b/res/drawable/cubeout_00013.png
new file mode 100644
index 000000000..4fcd8444c
--- /dev/null
+++ b/res/drawable/cubeout_00013.png
Binary files differ
diff --git a/res/drawable/cubeout_00014.png b/res/drawable/cubeout_00014.png
new file mode 100644
index 000000000..df3b99369
--- /dev/null
+++ b/res/drawable/cubeout_00014.png
Binary files differ
diff --git a/res/drawable/cubeout_00015.png b/res/drawable/cubeout_00015.png
new file mode 100644
index 000000000..b4f910f3c
--- /dev/null
+++ b/res/drawable/cubeout_00015.png
Binary files differ
diff --git a/res/drawable/cubeout_00016.png b/res/drawable/cubeout_00016.png
new file mode 100644
index 000000000..262e12942
--- /dev/null
+++ b/res/drawable/cubeout_00016.png
Binary files differ
diff --git a/res/drawable/cubeout_00017.png b/res/drawable/cubeout_00017.png
new file mode 100644
index 000000000..873146bc3
--- /dev/null
+++ b/res/drawable/cubeout_00017.png
Binary files differ
diff --git a/res/drawable/cubeout_00018.png b/res/drawable/cubeout_00018.png
new file mode 100644
index 000000000..2d52f2343
--- /dev/null
+++ b/res/drawable/cubeout_00018.png
Binary files differ
diff --git a/res/drawable/cubeout_00019.png b/res/drawable/cubeout_00019.png
new file mode 100644
index 000000000..1b7bff44a
--- /dev/null
+++ b/res/drawable/cubeout_00019.png
Binary files differ
diff --git a/res/drawable/cubeout_00020.png b/res/drawable/cubeout_00020.png
new file mode 100644
index 000000000..1662df8dc
--- /dev/null
+++ b/res/drawable/cubeout_00020.png
Binary files differ
diff --git a/res/drawable/cubeout_00021.png b/res/drawable/cubeout_00021.png
new file mode 100644
index 000000000..1662df8dc
--- /dev/null
+++ b/res/drawable/cubeout_00021.png
Binary files differ
diff --git a/res/drawable/cubeout_00022.png b/res/drawable/cubeout_00022.png
new file mode 100644
index 000000000..1662df8dc
--- /dev/null
+++ b/res/drawable/cubeout_00022.png
Binary files differ
diff --git a/res/drawable/cubeout_00023.png b/res/drawable/cubeout_00023.png
new file mode 100644
index 000000000..1662df8dc
--- /dev/null
+++ b/res/drawable/cubeout_00023.png
Binary files differ
diff --git a/res/drawable/cubeout_00024.png b/res/drawable/cubeout_00024.png
new file mode 100644
index 000000000..1662df8dc
--- /dev/null
+++ b/res/drawable/cubeout_00024.png
Binary files differ
diff --git a/res/drawable/cubeout_00025.png b/res/drawable/cubeout_00025.png
new file mode 100644
index 000000000..1662df8dc
--- /dev/null
+++ b/res/drawable/cubeout_00025.png
Binary files differ
diff --git a/res/drawable/cubeout_00026.png b/res/drawable/cubeout_00026.png
new file mode 100644
index 000000000..1662df8dc
--- /dev/null
+++ b/res/drawable/cubeout_00026.png
Binary files differ
diff --git a/res/drawable/cubeout_00027.png b/res/drawable/cubeout_00027.png
new file mode 100644
index 000000000..1662df8dc
--- /dev/null
+++ b/res/drawable/cubeout_00027.png
Binary files differ
diff --git a/res/drawable/cubeout_00028.png b/res/drawable/cubeout_00028.png
new file mode 100644
index 000000000..1662df8dc
--- /dev/null
+++ b/res/drawable/cubeout_00028.png
Binary files differ
diff --git a/res/drawable/cubeout_00029.png b/res/drawable/cubeout_00029.png
new file mode 100644
index 000000000..1662df8dc
--- /dev/null
+++ b/res/drawable/cubeout_00029.png
Binary files differ
diff --git a/res/drawable/cubeout_00030.png b/res/drawable/cubeout_00030.png
new file mode 100644
index 000000000..1662df8dc
--- /dev/null
+++ b/res/drawable/cubeout_00030.png
Binary files differ
diff --git a/res/drawable/cubeout_00031.png b/res/drawable/cubeout_00031.png
new file mode 100644
index 000000000..1662df8dc
--- /dev/null
+++ b/res/drawable/cubeout_00031.png
Binary files differ
diff --git a/res/drawable/cubeout_00032.png b/res/drawable/cubeout_00032.png
new file mode 100644
index 000000000..1662df8dc
--- /dev/null
+++ b/res/drawable/cubeout_00032.png
Binary files differ
diff --git a/res/drawable/cubeout_00033.png b/res/drawable/cubeout_00033.png
new file mode 100644
index 000000000..1662df8dc
--- /dev/null
+++ b/res/drawable/cubeout_00033.png
Binary files differ
diff --git a/res/drawable/cubeout_00034.png b/res/drawable/cubeout_00034.png
new file mode 100644
index 000000000..1662df8dc
--- /dev/null
+++ b/res/drawable/cubeout_00034.png
Binary files differ
diff --git a/res/drawable/cubeout_00035.png b/res/drawable/cubeout_00035.png
new file mode 100644
index 000000000..1662df8dc
--- /dev/null
+++ b/res/drawable/cubeout_00035.png
Binary files differ
diff --git a/res/drawable/cubeout_00036.png b/res/drawable/cubeout_00036.png
new file mode 100644
index 000000000..1662df8dc
--- /dev/null
+++ b/res/drawable/cubeout_00036.png
Binary files differ
diff --git a/res/drawable/cubeout_00037.png b/res/drawable/cubeout_00037.png
new file mode 100644
index 000000000..1662df8dc
--- /dev/null
+++ b/res/drawable/cubeout_00037.png
Binary files differ
diff --git a/res/drawable/cubeout_00038.png b/res/drawable/cubeout_00038.png
new file mode 100644
index 000000000..1662df8dc
--- /dev/null
+++ b/res/drawable/cubeout_00038.png
Binary files differ
diff --git a/res/drawable/cubeout_00039.png b/res/drawable/cubeout_00039.png
new file mode 100644
index 000000000..1662df8dc
--- /dev/null
+++ b/res/drawable/cubeout_00039.png
Binary files differ
diff --git a/res/drawable/cubeout_00040.png b/res/drawable/cubeout_00040.png
new file mode 100644
index 000000000..1662df8dc
--- /dev/null
+++ b/res/drawable/cubeout_00040.png
Binary files differ
diff --git a/res/drawable/cubeout_00041.png b/res/drawable/cubeout_00041.png
new file mode 100644
index 000000000..1662df8dc
--- /dev/null
+++ b/res/drawable/cubeout_00041.png
Binary files differ
diff --git a/res/drawable/cubeout_00042.png b/res/drawable/cubeout_00042.png
new file mode 100644
index 000000000..1662df8dc
--- /dev/null
+++ b/res/drawable/cubeout_00042.png
Binary files differ
diff --git a/res/drawable/cubeout_00043.png b/res/drawable/cubeout_00043.png
new file mode 100644
index 000000000..1662df8dc
--- /dev/null
+++ b/res/drawable/cubeout_00043.png
Binary files differ
diff --git a/res/drawable/cubeout_00044.png b/res/drawable/cubeout_00044.png
new file mode 100644
index 000000000..1662df8dc
--- /dev/null
+++ b/res/drawable/cubeout_00044.png
Binary files differ
diff --git a/res/drawable/cubeout_00045.png b/res/drawable/cubeout_00045.png
new file mode 100644
index 000000000..1662df8dc
--- /dev/null
+++ b/res/drawable/cubeout_00045.png
Binary files differ
diff --git a/res/drawable/cubeout_00046.png b/res/drawable/cubeout_00046.png
new file mode 100644
index 000000000..1662df8dc
--- /dev/null
+++ b/res/drawable/cubeout_00046.png
Binary files differ
diff --git a/res/drawable/cubeout_00047.png b/res/drawable/cubeout_00047.png
new file mode 100644
index 000000000..1662df8dc
--- /dev/null
+++ b/res/drawable/cubeout_00047.png
Binary files differ
diff --git a/res/drawable/cubeout_00048.png b/res/drawable/cubeout_00048.png
new file mode 100644
index 000000000..1662df8dc
--- /dev/null
+++ b/res/drawable/cubeout_00048.png
Binary files differ
diff --git a/res/drawable/cubeout_00049.png b/res/drawable/cubeout_00049.png
new file mode 100644
index 000000000..1662df8dc
--- /dev/null
+++ b/res/drawable/cubeout_00049.png
Binary files differ
diff --git a/res/drawable/cylinderin_00000.png b/res/drawable/cylinderin_00000.png
new file mode 100644
index 000000000..c5eeb55a0
--- /dev/null
+++ b/res/drawable/cylinderin_00000.png
Binary files differ
diff --git a/res/drawable/cylinderin_00001.png b/res/drawable/cylinderin_00001.png
new file mode 100644
index 000000000..bfc597a49
--- /dev/null
+++ b/res/drawable/cylinderin_00001.png
Binary files differ
diff --git a/res/drawable/cylinderin_00002.png b/res/drawable/cylinderin_00002.png
new file mode 100644
index 000000000..88114b7e2
--- /dev/null
+++ b/res/drawable/cylinderin_00002.png
Binary files differ
diff --git a/res/drawable/cylinderin_00003.png b/res/drawable/cylinderin_00003.png
new file mode 100644
index 000000000..fe24f3f22
--- /dev/null
+++ b/res/drawable/cylinderin_00003.png
Binary files differ
diff --git a/res/drawable/cylinderin_00004.png b/res/drawable/cylinderin_00004.png
new file mode 100644
index 000000000..c3a655b23
--- /dev/null
+++ b/res/drawable/cylinderin_00004.png
Binary files differ
diff --git a/res/drawable/cylinderin_00005.png b/res/drawable/cylinderin_00005.png
new file mode 100644
index 000000000..e34b658e8
--- /dev/null
+++ b/res/drawable/cylinderin_00005.png
Binary files differ
diff --git a/res/drawable/cylinderin_00006.png b/res/drawable/cylinderin_00006.png
new file mode 100644
index 000000000..7f4d7b9db
--- /dev/null
+++ b/res/drawable/cylinderin_00006.png
Binary files differ
diff --git a/res/drawable/cylinderin_00007.png b/res/drawable/cylinderin_00007.png
new file mode 100644
index 000000000..bef4a2d11
--- /dev/null
+++ b/res/drawable/cylinderin_00007.png
Binary files differ
diff --git a/res/drawable/cylinderin_00008.png b/res/drawable/cylinderin_00008.png
new file mode 100644
index 000000000..3ed252efa
--- /dev/null
+++ b/res/drawable/cylinderin_00008.png
Binary files differ
diff --git a/res/drawable/cylinderin_00009.png b/res/drawable/cylinderin_00009.png
new file mode 100644
index 000000000..6b47c400e
--- /dev/null
+++ b/res/drawable/cylinderin_00009.png
Binary files differ
diff --git a/res/drawable/cylinderin_00010.png b/res/drawable/cylinderin_00010.png
new file mode 100644
index 000000000..5ffd650ed
--- /dev/null
+++ b/res/drawable/cylinderin_00010.png
Binary files differ
diff --git a/res/drawable/cylinderin_00011.png b/res/drawable/cylinderin_00011.png
new file mode 100644
index 000000000..f6ad8cc80
--- /dev/null
+++ b/res/drawable/cylinderin_00011.png
Binary files differ
diff --git a/res/drawable/cylinderin_00012.png b/res/drawable/cylinderin_00012.png
new file mode 100644
index 000000000..27c7d6945
--- /dev/null
+++ b/res/drawable/cylinderin_00012.png
Binary files differ
diff --git a/res/drawable/cylinderin_00013.png b/res/drawable/cylinderin_00013.png
new file mode 100644
index 000000000..a78a4359d
--- /dev/null
+++ b/res/drawable/cylinderin_00013.png
Binary files differ
diff --git a/res/drawable/cylinderin_00014.png b/res/drawable/cylinderin_00014.png
new file mode 100644
index 000000000..4eda97009
--- /dev/null
+++ b/res/drawable/cylinderin_00014.png
Binary files differ
diff --git a/res/drawable/cylinderin_00015.png b/res/drawable/cylinderin_00015.png
new file mode 100644
index 000000000..e3ddc7e98
--- /dev/null
+++ b/res/drawable/cylinderin_00015.png
Binary files differ
diff --git a/res/drawable/cylinderin_00016.png b/res/drawable/cylinderin_00016.png
new file mode 100644
index 000000000..eb48e294c
--- /dev/null
+++ b/res/drawable/cylinderin_00016.png
Binary files differ
diff --git a/res/drawable/cylinderin_00017.png b/res/drawable/cylinderin_00017.png
new file mode 100644
index 000000000..fb7b3aff9
--- /dev/null
+++ b/res/drawable/cylinderin_00017.png
Binary files differ
diff --git a/res/drawable/cylinderin_00018.png b/res/drawable/cylinderin_00018.png
new file mode 100644
index 000000000..5c73e4d98
--- /dev/null
+++ b/res/drawable/cylinderin_00018.png
Binary files differ
diff --git a/res/drawable/cylinderin_00019.png b/res/drawable/cylinderin_00019.png
new file mode 100644
index 000000000..967423915
--- /dev/null
+++ b/res/drawable/cylinderin_00019.png
Binary files differ
diff --git a/res/drawable/cylinderin_00020.png b/res/drawable/cylinderin_00020.png
new file mode 100644
index 000000000..c5eeb55a0
--- /dev/null
+++ b/res/drawable/cylinderin_00020.png
Binary files differ
diff --git a/res/drawable/cylinderin_00021.png b/res/drawable/cylinderin_00021.png
new file mode 100644
index 000000000..c5eeb55a0
--- /dev/null
+++ b/res/drawable/cylinderin_00021.png
Binary files differ
diff --git a/res/drawable/cylinderin_00022.png b/res/drawable/cylinderin_00022.png
new file mode 100644
index 000000000..c5eeb55a0
--- /dev/null
+++ b/res/drawable/cylinderin_00022.png
Binary files differ
diff --git a/res/drawable/cylinderin_00023.png b/res/drawable/cylinderin_00023.png
new file mode 100644
index 000000000..c5eeb55a0
--- /dev/null
+++ b/res/drawable/cylinderin_00023.png
Binary files differ
diff --git a/res/drawable/cylinderin_00024.png b/res/drawable/cylinderin_00024.png
new file mode 100644
index 000000000..c5eeb55a0
--- /dev/null
+++ b/res/drawable/cylinderin_00024.png
Binary files differ
diff --git a/res/drawable/cylinderin_00025.png b/res/drawable/cylinderin_00025.png
new file mode 100644
index 000000000..c5eeb55a0
--- /dev/null
+++ b/res/drawable/cylinderin_00025.png
Binary files differ
diff --git a/res/drawable/cylinderin_00026.png b/res/drawable/cylinderin_00026.png
new file mode 100644
index 000000000..c5eeb55a0
--- /dev/null
+++ b/res/drawable/cylinderin_00026.png
Binary files differ
diff --git a/res/drawable/cylinderin_00027.png b/res/drawable/cylinderin_00027.png
new file mode 100644
index 000000000..c5eeb55a0
--- /dev/null
+++ b/res/drawable/cylinderin_00027.png
Binary files differ
diff --git a/res/drawable/cylinderin_00028.png b/res/drawable/cylinderin_00028.png
new file mode 100644
index 000000000..c5eeb55a0
--- /dev/null
+++ b/res/drawable/cylinderin_00028.png
Binary files differ
diff --git a/res/drawable/cylinderin_00029.png b/res/drawable/cylinderin_00029.png
new file mode 100644
index 000000000..c5eeb55a0
--- /dev/null
+++ b/res/drawable/cylinderin_00029.png
Binary files differ
diff --git a/res/drawable/cylinderin_00030.png b/res/drawable/cylinderin_00030.png
new file mode 100644
index 000000000..c5eeb55a0
--- /dev/null
+++ b/res/drawable/cylinderin_00030.png
Binary files differ
diff --git a/res/drawable/cylinderin_00031.png b/res/drawable/cylinderin_00031.png
new file mode 100644
index 000000000..c5eeb55a0
--- /dev/null
+++ b/res/drawable/cylinderin_00031.png
Binary files differ
diff --git a/res/drawable/cylinderin_00032.png b/res/drawable/cylinderin_00032.png
new file mode 100644
index 000000000..c5eeb55a0
--- /dev/null
+++ b/res/drawable/cylinderin_00032.png
Binary files differ
diff --git a/res/drawable/cylinderin_00033.png b/res/drawable/cylinderin_00033.png
new file mode 100644
index 000000000..c5eeb55a0
--- /dev/null
+++ b/res/drawable/cylinderin_00033.png
Binary files differ
diff --git a/res/drawable/cylinderin_00034.png b/res/drawable/cylinderin_00034.png
new file mode 100644
index 000000000..c5eeb55a0
--- /dev/null
+++ b/res/drawable/cylinderin_00034.png
Binary files differ
diff --git a/res/drawable/cylinderin_00035.png b/res/drawable/cylinderin_00035.png
new file mode 100644
index 000000000..c5eeb55a0
--- /dev/null
+++ b/res/drawable/cylinderin_00035.png
Binary files differ
diff --git a/res/drawable/cylinderin_00036.png b/res/drawable/cylinderin_00036.png
new file mode 100644
index 000000000..c5eeb55a0
--- /dev/null
+++ b/res/drawable/cylinderin_00036.png
Binary files differ
diff --git a/res/drawable/cylinderin_00037.png b/res/drawable/cylinderin_00037.png
new file mode 100644
index 000000000..c5eeb55a0
--- /dev/null
+++ b/res/drawable/cylinderin_00037.png
Binary files differ
diff --git a/res/drawable/cylinderin_00038.png b/res/drawable/cylinderin_00038.png
new file mode 100644
index 000000000..c5eeb55a0
--- /dev/null
+++ b/res/drawable/cylinderin_00038.png
Binary files differ
diff --git a/res/drawable/cylinderin_00039.png b/res/drawable/cylinderin_00039.png
new file mode 100644
index 000000000..c5eeb55a0
--- /dev/null
+++ b/res/drawable/cylinderin_00039.png
Binary files differ
diff --git a/res/drawable/cylinderin_00040.png b/res/drawable/cylinderin_00040.png
new file mode 100644
index 000000000..c5eeb55a0
--- /dev/null
+++ b/res/drawable/cylinderin_00040.png
Binary files differ
diff --git a/res/drawable/cylinderin_00041.png b/res/drawable/cylinderin_00041.png
new file mode 100644
index 000000000..c5eeb55a0
--- /dev/null
+++ b/res/drawable/cylinderin_00041.png
Binary files differ
diff --git a/res/drawable/cylinderin_00042.png b/res/drawable/cylinderin_00042.png
new file mode 100644
index 000000000..c5eeb55a0
--- /dev/null
+++ b/res/drawable/cylinderin_00042.png
Binary files differ
diff --git a/res/drawable/cylinderin_00043.png b/res/drawable/cylinderin_00043.png
new file mode 100644
index 000000000..c5eeb55a0
--- /dev/null
+++ b/res/drawable/cylinderin_00043.png
Binary files differ
diff --git a/res/drawable/cylinderin_00044.png b/res/drawable/cylinderin_00044.png
new file mode 100644
index 000000000..c5eeb55a0
--- /dev/null
+++ b/res/drawable/cylinderin_00044.png
Binary files differ
diff --git a/res/drawable/cylinderin_00045.png b/res/drawable/cylinderin_00045.png
new file mode 100644
index 000000000..c5eeb55a0
--- /dev/null
+++ b/res/drawable/cylinderin_00045.png
Binary files differ
diff --git a/res/drawable/cylinderin_00046.png b/res/drawable/cylinderin_00046.png
new file mode 100644
index 000000000..c5eeb55a0
--- /dev/null
+++ b/res/drawable/cylinderin_00046.png
Binary files differ
diff --git a/res/drawable/cylinderin_00047.png b/res/drawable/cylinderin_00047.png
new file mode 100644
index 000000000..c5eeb55a0
--- /dev/null
+++ b/res/drawable/cylinderin_00047.png
Binary files differ
diff --git a/res/drawable/cylinderin_00048.png b/res/drawable/cylinderin_00048.png
new file mode 100644
index 000000000..c5eeb55a0
--- /dev/null
+++ b/res/drawable/cylinderin_00048.png
Binary files differ
diff --git a/res/drawable/cylinderin_00049.png b/res/drawable/cylinderin_00049.png
new file mode 100644
index 000000000..c5eeb55a0
--- /dev/null
+++ b/res/drawable/cylinderin_00049.png
Binary files differ
diff --git a/res/drawable/cylinderout_00000.png b/res/drawable/cylinderout_00000.png
new file mode 100644
index 000000000..d53161c2b
--- /dev/null
+++ b/res/drawable/cylinderout_00000.png
Binary files differ
diff --git a/res/drawable/cylinderout_00001.png b/res/drawable/cylinderout_00001.png
new file mode 100644
index 000000000..ba768d300
--- /dev/null
+++ b/res/drawable/cylinderout_00001.png
Binary files differ
diff --git a/res/drawable/cylinderout_00002.png b/res/drawable/cylinderout_00002.png
new file mode 100644
index 000000000..c753c3b02
--- /dev/null
+++ b/res/drawable/cylinderout_00002.png
Binary files differ
diff --git a/res/drawable/cylinderout_00003.png b/res/drawable/cylinderout_00003.png
new file mode 100644
index 000000000..903d16029
--- /dev/null
+++ b/res/drawable/cylinderout_00003.png
Binary files differ
diff --git a/res/drawable/cylinderout_00004.png b/res/drawable/cylinderout_00004.png
new file mode 100644
index 000000000..803ba23be
--- /dev/null
+++ b/res/drawable/cylinderout_00004.png
Binary files differ
diff --git a/res/drawable/cylinderout_00005.png b/res/drawable/cylinderout_00005.png
new file mode 100644
index 000000000..ccfb96d48
--- /dev/null
+++ b/res/drawable/cylinderout_00005.png
Binary files differ
diff --git a/res/drawable/cylinderout_00006.png b/res/drawable/cylinderout_00006.png
new file mode 100644
index 000000000..1b7a4c899
--- /dev/null
+++ b/res/drawable/cylinderout_00006.png
Binary files differ
diff --git a/res/drawable/cylinderout_00007.png b/res/drawable/cylinderout_00007.png
new file mode 100644
index 000000000..5366845fa
--- /dev/null
+++ b/res/drawable/cylinderout_00007.png
Binary files differ
diff --git a/res/drawable/cylinderout_00008.png b/res/drawable/cylinderout_00008.png
new file mode 100644
index 000000000..325574a27
--- /dev/null
+++ b/res/drawable/cylinderout_00008.png
Binary files differ
diff --git a/res/drawable/cylinderout_00009.png b/res/drawable/cylinderout_00009.png
new file mode 100644
index 000000000..9280ff34b
--- /dev/null
+++ b/res/drawable/cylinderout_00009.png
Binary files differ
diff --git a/res/drawable/cylinderout_00010.png b/res/drawable/cylinderout_00010.png
new file mode 100644
index 000000000..f667a3261
--- /dev/null
+++ b/res/drawable/cylinderout_00010.png
Binary files differ
diff --git a/res/drawable/cylinderout_00011.png b/res/drawable/cylinderout_00011.png
new file mode 100644
index 000000000..8d38ecf7e
--- /dev/null
+++ b/res/drawable/cylinderout_00011.png
Binary files differ
diff --git a/res/drawable/cylinderout_00012.png b/res/drawable/cylinderout_00012.png
new file mode 100644
index 000000000..80359d12a
--- /dev/null
+++ b/res/drawable/cylinderout_00012.png
Binary files differ
diff --git a/res/drawable/cylinderout_00013.png b/res/drawable/cylinderout_00013.png
new file mode 100644
index 000000000..087953e6c
--- /dev/null
+++ b/res/drawable/cylinderout_00013.png
Binary files differ
diff --git a/res/drawable/cylinderout_00014.png b/res/drawable/cylinderout_00014.png
new file mode 100644
index 000000000..083009a08
--- /dev/null
+++ b/res/drawable/cylinderout_00014.png
Binary files differ
diff --git a/res/drawable/cylinderout_00015.png b/res/drawable/cylinderout_00015.png
new file mode 100644
index 000000000..c5cfb7eb9
--- /dev/null
+++ b/res/drawable/cylinderout_00015.png
Binary files differ
diff --git a/res/drawable/cylinderout_00016.png b/res/drawable/cylinderout_00016.png
new file mode 100644
index 000000000..c1e9eea70
--- /dev/null
+++ b/res/drawable/cylinderout_00016.png
Binary files differ
diff --git a/res/drawable/cylinderout_00017.png b/res/drawable/cylinderout_00017.png
new file mode 100644
index 000000000..cca8ec06e
--- /dev/null
+++ b/res/drawable/cylinderout_00017.png
Binary files differ
diff --git a/res/drawable/cylinderout_00018.png b/res/drawable/cylinderout_00018.png
new file mode 100644
index 000000000..13c2a8ce6
--- /dev/null
+++ b/res/drawable/cylinderout_00018.png
Binary files differ
diff --git a/res/drawable/cylinderout_00019.png b/res/drawable/cylinderout_00019.png
new file mode 100644
index 000000000..3e806b910
--- /dev/null
+++ b/res/drawable/cylinderout_00019.png
Binary files differ
diff --git a/res/drawable/cylinderout_00020.png b/res/drawable/cylinderout_00020.png
new file mode 100644
index 000000000..d53161c2b
--- /dev/null
+++ b/res/drawable/cylinderout_00020.png
Binary files differ
diff --git a/res/drawable/cylinderout_00021.png b/res/drawable/cylinderout_00021.png
new file mode 100644
index 000000000..d53161c2b
--- /dev/null
+++ b/res/drawable/cylinderout_00021.png
Binary files differ
diff --git a/res/drawable/cylinderout_00022.png b/res/drawable/cylinderout_00022.png
new file mode 100644
index 000000000..d53161c2b
--- /dev/null
+++ b/res/drawable/cylinderout_00022.png
Binary files differ
diff --git a/res/drawable/cylinderout_00023.png b/res/drawable/cylinderout_00023.png
new file mode 100644
index 000000000..d53161c2b
--- /dev/null
+++ b/res/drawable/cylinderout_00023.png
Binary files differ
diff --git a/res/drawable/cylinderout_00024.png b/res/drawable/cylinderout_00024.png
new file mode 100644
index 000000000..d53161c2b
--- /dev/null
+++ b/res/drawable/cylinderout_00024.png
Binary files differ
diff --git a/res/drawable/cylinderout_00025.png b/res/drawable/cylinderout_00025.png
new file mode 100644
index 000000000..d53161c2b
--- /dev/null
+++ b/res/drawable/cylinderout_00025.png
Binary files differ
diff --git a/res/drawable/cylinderout_00026.png b/res/drawable/cylinderout_00026.png
new file mode 100644
index 000000000..d53161c2b
--- /dev/null
+++ b/res/drawable/cylinderout_00026.png
Binary files differ
diff --git a/res/drawable/cylinderout_00027.png b/res/drawable/cylinderout_00027.png
new file mode 100644
index 000000000..d53161c2b
--- /dev/null
+++ b/res/drawable/cylinderout_00027.png
Binary files differ
diff --git a/res/drawable/cylinderout_00028.png b/res/drawable/cylinderout_00028.png
new file mode 100644
index 000000000..d53161c2b
--- /dev/null
+++ b/res/drawable/cylinderout_00028.png
Binary files differ
diff --git a/res/drawable/cylinderout_00029.png b/res/drawable/cylinderout_00029.png
new file mode 100644
index 000000000..d53161c2b
--- /dev/null
+++ b/res/drawable/cylinderout_00029.png
Binary files differ
diff --git a/res/drawable/cylinderout_00030.png b/res/drawable/cylinderout_00030.png
new file mode 100644
index 000000000..d53161c2b
--- /dev/null
+++ b/res/drawable/cylinderout_00030.png
Binary files differ
diff --git a/res/drawable/cylinderout_00031.png b/res/drawable/cylinderout_00031.png
new file mode 100644
index 000000000..d53161c2b
--- /dev/null
+++ b/res/drawable/cylinderout_00031.png
Binary files differ
diff --git a/res/drawable/cylinderout_00032.png b/res/drawable/cylinderout_00032.png
new file mode 100644
index 000000000..d53161c2b
--- /dev/null
+++ b/res/drawable/cylinderout_00032.png
Binary files differ
diff --git a/res/drawable/cylinderout_00033.png b/res/drawable/cylinderout_00033.png
new file mode 100644
index 000000000..d53161c2b
--- /dev/null
+++ b/res/drawable/cylinderout_00033.png
Binary files differ
diff --git a/res/drawable/cylinderout_00034.png b/res/drawable/cylinderout_00034.png
new file mode 100644
index 000000000..d53161c2b
--- /dev/null
+++ b/res/drawable/cylinderout_00034.png
Binary files differ
diff --git a/res/drawable/cylinderout_00035.png b/res/drawable/cylinderout_00035.png
new file mode 100644
index 000000000..d53161c2b
--- /dev/null
+++ b/res/drawable/cylinderout_00035.png
Binary files differ
diff --git a/res/drawable/cylinderout_00036.png b/res/drawable/cylinderout_00036.png
new file mode 100644
index 000000000..d53161c2b
--- /dev/null
+++ b/res/drawable/cylinderout_00036.png
Binary files differ
diff --git a/res/drawable/cylinderout_00037.png b/res/drawable/cylinderout_00037.png
new file mode 100644
index 000000000..d53161c2b
--- /dev/null
+++ b/res/drawable/cylinderout_00037.png
Binary files differ
diff --git a/res/drawable/cylinderout_00038.png b/res/drawable/cylinderout_00038.png
new file mode 100644
index 000000000..d53161c2b
--- /dev/null
+++ b/res/drawable/cylinderout_00038.png
Binary files differ
diff --git a/res/drawable/cylinderout_00039.png b/res/drawable/cylinderout_00039.png
new file mode 100644
index 000000000..d53161c2b
--- /dev/null
+++ b/res/drawable/cylinderout_00039.png
Binary files differ
diff --git a/res/drawable/cylinderout_00040.png b/res/drawable/cylinderout_00040.png
new file mode 100644
index 000000000..d53161c2b
--- /dev/null
+++ b/res/drawable/cylinderout_00040.png
Binary files differ
diff --git a/res/drawable/cylinderout_00041.png b/res/drawable/cylinderout_00041.png
new file mode 100644
index 000000000..d53161c2b
--- /dev/null
+++ b/res/drawable/cylinderout_00041.png
Binary files differ
diff --git a/res/drawable/cylinderout_00042.png b/res/drawable/cylinderout_00042.png
new file mode 100644
index 000000000..d53161c2b
--- /dev/null
+++ b/res/drawable/cylinderout_00042.png
Binary files differ
diff --git a/res/drawable/cylinderout_00043.png b/res/drawable/cylinderout_00043.png
new file mode 100644
index 000000000..d53161c2b
--- /dev/null
+++ b/res/drawable/cylinderout_00043.png
Binary files differ
diff --git a/res/drawable/cylinderout_00044.png b/res/drawable/cylinderout_00044.png
new file mode 100644
index 000000000..d53161c2b
--- /dev/null
+++ b/res/drawable/cylinderout_00044.png
Binary files differ
diff --git a/res/drawable/cylinderout_00045.png b/res/drawable/cylinderout_00045.png
new file mode 100644
index 000000000..d53161c2b
--- /dev/null
+++ b/res/drawable/cylinderout_00045.png
Binary files differ
diff --git a/res/drawable/cylinderout_00046.png b/res/drawable/cylinderout_00046.png
new file mode 100644
index 000000000..d53161c2b
--- /dev/null
+++ b/res/drawable/cylinderout_00046.png
Binary files differ
diff --git a/res/drawable/cylinderout_00047.png b/res/drawable/cylinderout_00047.png
new file mode 100644
index 000000000..d53161c2b
--- /dev/null
+++ b/res/drawable/cylinderout_00047.png
Binary files differ
diff --git a/res/drawable/cylinderout_00048.png b/res/drawable/cylinderout_00048.png
new file mode 100644
index 000000000..d53161c2b
--- /dev/null
+++ b/res/drawable/cylinderout_00048.png
Binary files differ
diff --git a/res/drawable/cylinderout_00049.png b/res/drawable/cylinderout_00049.png
new file mode 100644
index 000000000..d53161c2b
--- /dev/null
+++ b/res/drawable/cylinderout_00049.png
Binary files differ
diff --git a/res/drawable/flip_00000.png b/res/drawable/flip_00000.png
new file mode 100644
index 000000000..cbe7f859b
--- /dev/null
+++ b/res/drawable/flip_00000.png
Binary files differ
diff --git a/res/drawable/flip_00001.png b/res/drawable/flip_00001.png
new file mode 100644
index 000000000..086511876
--- /dev/null
+++ b/res/drawable/flip_00001.png
Binary files differ
diff --git a/res/drawable/flip_00002.png b/res/drawable/flip_00002.png
new file mode 100644
index 000000000..ae9f255f7
--- /dev/null
+++ b/res/drawable/flip_00002.png
Binary files differ
diff --git a/res/drawable/flip_00003.png b/res/drawable/flip_00003.png
new file mode 100644
index 000000000..62846c7d1
--- /dev/null
+++ b/res/drawable/flip_00003.png
Binary files differ
diff --git a/res/drawable/flip_00004.png b/res/drawable/flip_00004.png
new file mode 100644
index 000000000..ae70cb81b
--- /dev/null
+++ b/res/drawable/flip_00004.png
Binary files differ
diff --git a/res/drawable/flip_00005.png b/res/drawable/flip_00005.png
new file mode 100644
index 000000000..ccef96be3
--- /dev/null
+++ b/res/drawable/flip_00005.png
Binary files differ
diff --git a/res/drawable/flip_00006.png b/res/drawable/flip_00006.png
new file mode 100644
index 000000000..ce8819c6a
--- /dev/null
+++ b/res/drawable/flip_00006.png
Binary files differ
diff --git a/res/drawable/flip_00007.png b/res/drawable/flip_00007.png
new file mode 100644
index 000000000..b502e2d4a
--- /dev/null
+++ b/res/drawable/flip_00007.png
Binary files differ
diff --git a/res/drawable/flip_00008.png b/res/drawable/flip_00008.png
new file mode 100644
index 000000000..bfaae1d36
--- /dev/null
+++ b/res/drawable/flip_00008.png
Binary files differ
diff --git a/res/drawable/flip_00009.png b/res/drawable/flip_00009.png
new file mode 100644
index 000000000..f974cd4c6
--- /dev/null
+++ b/res/drawable/flip_00009.png
Binary files differ
diff --git a/res/drawable/flip_00010.png b/res/drawable/flip_00010.png
new file mode 100644
index 000000000..9b298a83f
--- /dev/null
+++ b/res/drawable/flip_00010.png
Binary files differ
diff --git a/res/drawable/flip_00011.png b/res/drawable/flip_00011.png
new file mode 100644
index 000000000..27accf584
--- /dev/null
+++ b/res/drawable/flip_00011.png
Binary files differ
diff --git a/res/drawable/flip_00012.png b/res/drawable/flip_00012.png
new file mode 100644
index 000000000..48f3d37b4
--- /dev/null
+++ b/res/drawable/flip_00012.png
Binary files differ
diff --git a/res/drawable/flip_00013.png b/res/drawable/flip_00013.png
new file mode 100644
index 000000000..ed3273f80
--- /dev/null
+++ b/res/drawable/flip_00013.png
Binary files differ
diff --git a/res/drawable/flip_00014.png b/res/drawable/flip_00014.png
new file mode 100644
index 000000000..24cfa1787
--- /dev/null
+++ b/res/drawable/flip_00014.png
Binary files differ
diff --git a/res/drawable/flip_00015.png b/res/drawable/flip_00015.png
new file mode 100644
index 000000000..dc8483e48
--- /dev/null
+++ b/res/drawable/flip_00015.png
Binary files differ
diff --git a/res/drawable/flip_00016.png b/res/drawable/flip_00016.png
new file mode 100644
index 000000000..c445a5b87
--- /dev/null
+++ b/res/drawable/flip_00016.png
Binary files differ
diff --git a/res/drawable/flip_00017.png b/res/drawable/flip_00017.png
new file mode 100644
index 000000000..0d269886a
--- /dev/null
+++ b/res/drawable/flip_00017.png
Binary files differ
diff --git a/res/drawable/flip_00018.png b/res/drawable/flip_00018.png
new file mode 100644
index 000000000..39762fa11
--- /dev/null
+++ b/res/drawable/flip_00018.png
Binary files differ
diff --git a/res/drawable/flip_00019.png b/res/drawable/flip_00019.png
new file mode 100644
index 000000000..02f160ab3
--- /dev/null
+++ b/res/drawable/flip_00019.png
Binary files differ
diff --git a/res/drawable/flip_00020.png b/res/drawable/flip_00020.png
new file mode 100644
index 000000000..cbe7f859b
--- /dev/null
+++ b/res/drawable/flip_00020.png
Binary files differ
diff --git a/res/drawable/flip_00021.png b/res/drawable/flip_00021.png
new file mode 100644
index 000000000..cbe7f859b
--- /dev/null
+++ b/res/drawable/flip_00021.png
Binary files differ
diff --git a/res/drawable/flip_00022.png b/res/drawable/flip_00022.png
new file mode 100644
index 000000000..cbe7f859b
--- /dev/null
+++ b/res/drawable/flip_00022.png
Binary files differ
diff --git a/res/drawable/flip_00023.png b/res/drawable/flip_00023.png
new file mode 100644
index 000000000..cbe7f859b
--- /dev/null
+++ b/res/drawable/flip_00023.png
Binary files differ
diff --git a/res/drawable/flip_00024.png b/res/drawable/flip_00024.png
new file mode 100644
index 000000000..cbe7f859b
--- /dev/null
+++ b/res/drawable/flip_00024.png
Binary files differ
diff --git a/res/drawable/flip_00025.png b/res/drawable/flip_00025.png
new file mode 100644
index 000000000..cbe7f859b
--- /dev/null
+++ b/res/drawable/flip_00025.png
Binary files differ
diff --git a/res/drawable/flip_00026.png b/res/drawable/flip_00026.png
new file mode 100644
index 000000000..cbe7f859b
--- /dev/null
+++ b/res/drawable/flip_00026.png
Binary files differ
diff --git a/res/drawable/flip_00027.png b/res/drawable/flip_00027.png
new file mode 100644
index 000000000..cbe7f859b
--- /dev/null
+++ b/res/drawable/flip_00027.png
Binary files differ
diff --git a/res/drawable/flip_00028.png b/res/drawable/flip_00028.png
new file mode 100644
index 000000000..cbe7f859b
--- /dev/null
+++ b/res/drawable/flip_00028.png
Binary files differ
diff --git a/res/drawable/flip_00029.png b/res/drawable/flip_00029.png
new file mode 100644
index 000000000..cbe7f859b
--- /dev/null
+++ b/res/drawable/flip_00029.png
Binary files differ
diff --git a/res/drawable/flip_00030.png b/res/drawable/flip_00030.png
new file mode 100644
index 000000000..cbe7f859b
--- /dev/null
+++ b/res/drawable/flip_00030.png
Binary files differ
diff --git a/res/drawable/flip_00031.png b/res/drawable/flip_00031.png
new file mode 100644
index 000000000..cbe7f859b
--- /dev/null
+++ b/res/drawable/flip_00031.png
Binary files differ
diff --git a/res/drawable/flip_00032.png b/res/drawable/flip_00032.png
new file mode 100644
index 000000000..cbe7f859b
--- /dev/null
+++ b/res/drawable/flip_00032.png
Binary files differ
diff --git a/res/drawable/flip_00033.png b/res/drawable/flip_00033.png
new file mode 100644
index 000000000..cbe7f859b
--- /dev/null
+++ b/res/drawable/flip_00033.png
Binary files differ
diff --git a/res/drawable/flip_00034.png b/res/drawable/flip_00034.png
new file mode 100644
index 000000000..cbe7f859b
--- /dev/null
+++ b/res/drawable/flip_00034.png
Binary files differ
diff --git a/res/drawable/flip_00035.png b/res/drawable/flip_00035.png
new file mode 100644
index 000000000..cbe7f859b
--- /dev/null
+++ b/res/drawable/flip_00035.png
Binary files differ
diff --git a/res/drawable/flip_00036.png b/res/drawable/flip_00036.png
new file mode 100644
index 000000000..cbe7f859b
--- /dev/null
+++ b/res/drawable/flip_00036.png
Binary files differ
diff --git a/res/drawable/flip_00037.png b/res/drawable/flip_00037.png
new file mode 100644
index 000000000..cbe7f859b
--- /dev/null
+++ b/res/drawable/flip_00037.png
Binary files differ
diff --git a/res/drawable/flip_00038.png b/res/drawable/flip_00038.png
new file mode 100644
index 000000000..cbe7f859b
--- /dev/null
+++ b/res/drawable/flip_00038.png
Binary files differ
diff --git a/res/drawable/flip_00039.png b/res/drawable/flip_00039.png
new file mode 100644
index 000000000..cbe7f859b
--- /dev/null
+++ b/res/drawable/flip_00039.png
Binary files differ
diff --git a/res/drawable/flip_00040.png b/res/drawable/flip_00040.png
new file mode 100644
index 000000000..cbe7f859b
--- /dev/null
+++ b/res/drawable/flip_00040.png
Binary files differ
diff --git a/res/drawable/flip_00041.png b/res/drawable/flip_00041.png
new file mode 100644
index 000000000..cbe7f859b
--- /dev/null
+++ b/res/drawable/flip_00041.png
Binary files differ
diff --git a/res/drawable/flip_00042.png b/res/drawable/flip_00042.png
new file mode 100644
index 000000000..cbe7f859b
--- /dev/null
+++ b/res/drawable/flip_00042.png
Binary files differ
diff --git a/res/drawable/flip_00043.png b/res/drawable/flip_00043.png
new file mode 100644
index 000000000..cbe7f859b
--- /dev/null
+++ b/res/drawable/flip_00043.png
Binary files differ
diff --git a/res/drawable/flip_00044.png b/res/drawable/flip_00044.png
new file mode 100644
index 000000000..cbe7f859b
--- /dev/null
+++ b/res/drawable/flip_00044.png
Binary files differ
diff --git a/res/drawable/flip_00045.png b/res/drawable/flip_00045.png
new file mode 100644
index 000000000..cbe7f859b
--- /dev/null
+++ b/res/drawable/flip_00045.png
Binary files differ
diff --git a/res/drawable/flip_00046.png b/res/drawable/flip_00046.png
new file mode 100644
index 000000000..cbe7f859b
--- /dev/null
+++ b/res/drawable/flip_00046.png
Binary files differ
diff --git a/res/drawable/flip_00047.png b/res/drawable/flip_00047.png
new file mode 100644
index 000000000..cbe7f859b
--- /dev/null
+++ b/res/drawable/flip_00047.png
Binary files differ
diff --git a/res/drawable/flip_00048.png b/res/drawable/flip_00048.png
new file mode 100644
index 000000000..cbe7f859b
--- /dev/null
+++ b/res/drawable/flip_00048.png
Binary files differ
diff --git a/res/drawable/flip_00049.png b/res/drawable/flip_00049.png
new file mode 100644
index 000000000..cbe7f859b
--- /dev/null
+++ b/res/drawable/flip_00049.png
Binary files differ
diff --git a/res/drawable/grid.png b/res/drawable/grid.png
new file mode 100644
index 000000000..79fe901d1
--- /dev/null
+++ b/res/drawable/grid.png
Binary files differ
diff --git a/res/drawable/grid_comfortable.png b/res/drawable/grid_comfortable.png
new file mode 100644
index 000000000..34e3ef2ee
--- /dev/null
+++ b/res/drawable/grid_comfortable.png
Binary files differ
diff --git a/res/drawable/grid_condensed.png b/res/drawable/grid_condensed.png
new file mode 100644
index 000000000..ebc9d4e54
--- /dev/null
+++ b/res/drawable/grid_condensed.png
Binary files differ
diff --git a/res/drawable/grid_cozy.png b/res/drawable/grid_cozy.png
new file mode 100644
index 000000000..929bcb541
--- /dev/null
+++ b/res/drawable/grid_cozy.png
Binary files differ
diff --git a/res/drawable/handle.png b/res/drawable/handle.png
new file mode 100644
index 000000000..6e943f0da
--- /dev/null
+++ b/res/drawable/handle.png
Binary files differ
diff --git a/res/drawable/handle_left.png b/res/drawable/handle_left.png
new file mode 100644
index 000000000..b78889ec0
--- /dev/null
+++ b/res/drawable/handle_left.png
Binary files differ
diff --git a/res/drawable/handle_reversed.png b/res/drawable/handle_reversed.png
new file mode 100644
index 000000000..6e943f0da
--- /dev/null
+++ b/res/drawable/handle_reversed.png
Binary files differ
diff --git a/res/drawable/launcheranimatedarrow_00000.png b/res/drawable/launcheranimatedarrow_00000.png
new file mode 100644
index 000000000..2ed7fe9a7
--- /dev/null
+++ b/res/drawable/launcheranimatedarrow_00000.png
Binary files differ
diff --git a/res/drawable/launcheranimatedarrow_00001.png b/res/drawable/launcheranimatedarrow_00001.png
new file mode 100644
index 000000000..f3707e07c
--- /dev/null
+++ b/res/drawable/launcheranimatedarrow_00001.png
Binary files differ
diff --git a/res/drawable/launcheranimatedarrow_00002.png b/res/drawable/launcheranimatedarrow_00002.png
new file mode 100644
index 000000000..3549389d0
--- /dev/null
+++ b/res/drawable/launcheranimatedarrow_00002.png
Binary files differ
diff --git a/res/drawable/launcheranimatedarrow_00003.png b/res/drawable/launcheranimatedarrow_00003.png
new file mode 100644
index 000000000..891e86c42
--- /dev/null
+++ b/res/drawable/launcheranimatedarrow_00003.png
Binary files differ
diff --git a/res/drawable/launcheranimatedarrow_00004.png b/res/drawable/launcheranimatedarrow_00004.png
new file mode 100644
index 000000000..7cfb1ef8c
--- /dev/null
+++ b/res/drawable/launcheranimatedarrow_00004.png
Binary files differ
diff --git a/res/drawable/launcheranimatedarrow_00005.png b/res/drawable/launcheranimatedarrow_00005.png
new file mode 100644
index 000000000..121f4d516
--- /dev/null
+++ b/res/drawable/launcheranimatedarrow_00005.png
Binary files differ
diff --git a/res/drawable/launcheranimatedarrow_00006.png b/res/drawable/launcheranimatedarrow_00006.png
new file mode 100644
index 000000000..3a38e71f7
--- /dev/null
+++ b/res/drawable/launcheranimatedarrow_00006.png
Binary files differ
diff --git a/res/drawable/launcheranimatedarrow_00007.png b/res/drawable/launcheranimatedarrow_00007.png
new file mode 100644
index 000000000..e81a719fd
--- /dev/null
+++ b/res/drawable/launcheranimatedarrow_00007.png
Binary files differ
diff --git a/res/drawable/launcheranimatedarrow_00008.png b/res/drawable/launcheranimatedarrow_00008.png
new file mode 100644
index 000000000..bd6f40981
--- /dev/null
+++ b/res/drawable/launcheranimatedarrow_00008.png
Binary files differ
diff --git a/res/drawable/launcheranimatedarrow_00009.png b/res/drawable/launcheranimatedarrow_00009.png
new file mode 100644
index 000000000..c7cb60daf
--- /dev/null
+++ b/res/drawable/launcheranimatedarrow_00009.png
Binary files differ
diff --git a/res/drawable/launcheranimatedarrow_00010.png b/res/drawable/launcheranimatedarrow_00010.png
new file mode 100644
index 000000000..1bf30dcc3
--- /dev/null
+++ b/res/drawable/launcheranimatedarrow_00010.png
Binary files differ
diff --git a/res/drawable/launcheranimatedarrow_00011.png b/res/drawable/launcheranimatedarrow_00011.png
new file mode 100644
index 000000000..3cb598806
--- /dev/null
+++ b/res/drawable/launcheranimatedarrow_00011.png
Binary files differ
diff --git a/res/drawable/launcheranimatedarrow_00012.png b/res/drawable/launcheranimatedarrow_00012.png
new file mode 100644
index 000000000..58070de06
--- /dev/null
+++ b/res/drawable/launcheranimatedarrow_00012.png
Binary files differ
diff --git a/res/drawable/launcheranimatedarrow_00013.png b/res/drawable/launcheranimatedarrow_00013.png
new file mode 100644
index 000000000..810d0a229
--- /dev/null
+++ b/res/drawable/launcheranimatedarrow_00013.png
Binary files differ
diff --git a/res/drawable/launcheranimatedarrow_00014.png b/res/drawable/launcheranimatedarrow_00014.png
new file mode 100644
index 000000000..3f9e51861
--- /dev/null
+++ b/res/drawable/launcheranimatedarrow_00014.png
Binary files differ
diff --git a/res/drawable/launcheranimatedarrow_00015.png b/res/drawable/launcheranimatedarrow_00015.png
new file mode 100644
index 000000000..348bfbbc6
--- /dev/null
+++ b/res/drawable/launcheranimatedarrow_00015.png
Binary files differ
diff --git a/res/drawable/launcheranimatedarrow_00016.png b/res/drawable/launcheranimatedarrow_00016.png
new file mode 100644
index 000000000..5b0b28649
--- /dev/null
+++ b/res/drawable/launcheranimatedarrow_00016.png
Binary files differ
diff --git a/res/drawable/listitem_bg.xml b/res/drawable/listitem_bg.xml
new file mode 100644
index 000000000..b81e995f8
--- /dev/null
+++ b/res/drawable/listitem_bg.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android" >
+ <item android:state_enabled="true"
+ android:state_pressed="true" android:drawable="@android:color/white" />
+ <item android:drawable="@color/settings_bg_color" />
+</selector> \ No newline at end of file
diff --git a/res/drawable/listitem_selector.xml b/res/drawable/listitem_selector.xml
new file mode 100644
index 000000000..b81e995f8
--- /dev/null
+++ b/res/drawable/listitem_selector.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android" >
+ <item android:state_enabled="true"
+ android:state_pressed="true" android:drawable="@android:color/white" />
+ <item android:drawable="@color/settings_bg_color" />
+</selector> \ No newline at end of file
diff --git a/res/drawable/none_00000.png b/res/drawable/none_00000.png
new file mode 100644
index 000000000..280dbde5c
--- /dev/null
+++ b/res/drawable/none_00000.png
Binary files differ
diff --git a/res/drawable/none_00001.png b/res/drawable/none_00001.png
new file mode 100644
index 000000000..9318c29d5
--- /dev/null
+++ b/res/drawable/none_00001.png
Binary files differ
diff --git a/res/drawable/none_00002.png b/res/drawable/none_00002.png
new file mode 100644
index 000000000..41288e9bf
--- /dev/null
+++ b/res/drawable/none_00002.png
Binary files differ
diff --git a/res/drawable/none_00003.png b/res/drawable/none_00003.png
new file mode 100644
index 000000000..831375e36
--- /dev/null
+++ b/res/drawable/none_00003.png
Binary files differ
diff --git a/res/drawable/none_00004.png b/res/drawable/none_00004.png
new file mode 100644
index 000000000..0ab2c45ac
--- /dev/null
+++ b/res/drawable/none_00004.png
Binary files differ
diff --git a/res/drawable/none_00005.png b/res/drawable/none_00005.png
new file mode 100644
index 000000000..3a3904cad
--- /dev/null
+++ b/res/drawable/none_00005.png
Binary files differ
diff --git a/res/drawable/none_00006.png b/res/drawable/none_00006.png
new file mode 100644
index 000000000..012ed8a6a
--- /dev/null
+++ b/res/drawable/none_00006.png
Binary files differ
diff --git a/res/drawable/none_00007.png b/res/drawable/none_00007.png
new file mode 100644
index 000000000..f72aa33a4
--- /dev/null
+++ b/res/drawable/none_00007.png
Binary files differ
diff --git a/res/drawable/none_00008.png b/res/drawable/none_00008.png
new file mode 100644
index 000000000..520df34dc
--- /dev/null
+++ b/res/drawable/none_00008.png
Binary files differ
diff --git a/res/drawable/none_00009.png b/res/drawable/none_00009.png
new file mode 100644
index 000000000..d8ce1ca76
--- /dev/null
+++ b/res/drawable/none_00009.png
Binary files differ
diff --git a/res/drawable/none_00010.png b/res/drawable/none_00010.png
new file mode 100644
index 000000000..50ea44727
--- /dev/null
+++ b/res/drawable/none_00010.png
Binary files differ
diff --git a/res/drawable/none_00011.png b/res/drawable/none_00011.png
new file mode 100644
index 000000000..bb664bb06
--- /dev/null
+++ b/res/drawable/none_00011.png
Binary files differ
diff --git a/res/drawable/none_00012.png b/res/drawable/none_00012.png
new file mode 100644
index 000000000..ba415ccdb
--- /dev/null
+++ b/res/drawable/none_00012.png
Binary files differ
diff --git a/res/drawable/none_00013.png b/res/drawable/none_00013.png
new file mode 100644
index 000000000..5727430ea
--- /dev/null
+++ b/res/drawable/none_00013.png
Binary files differ
diff --git a/res/drawable/none_00014.png b/res/drawable/none_00014.png
new file mode 100644
index 000000000..8791adc7e
--- /dev/null
+++ b/res/drawable/none_00014.png
Binary files differ
diff --git a/res/drawable/none_00015.png b/res/drawable/none_00015.png
new file mode 100644
index 000000000..07ae898fa
--- /dev/null
+++ b/res/drawable/none_00015.png
Binary files differ
diff --git a/res/drawable/none_00016.png b/res/drawable/none_00016.png
new file mode 100644
index 000000000..61954a175
--- /dev/null
+++ b/res/drawable/none_00016.png
Binary files differ
diff --git a/res/drawable/none_00017.png b/res/drawable/none_00017.png
new file mode 100644
index 000000000..38d3b8c3a
--- /dev/null
+++ b/res/drawable/none_00017.png
Binary files differ
diff --git a/res/drawable/none_00018.png b/res/drawable/none_00018.png
new file mode 100644
index 000000000..59af03174
--- /dev/null
+++ b/res/drawable/none_00018.png
Binary files differ
diff --git a/res/drawable/none_00019.png b/res/drawable/none_00019.png
new file mode 100644
index 000000000..6dbff8983
--- /dev/null
+++ b/res/drawable/none_00019.png
Binary files differ
diff --git a/res/drawable/none_00020.png b/res/drawable/none_00020.png
new file mode 100644
index 000000000..cbcff0391
--- /dev/null
+++ b/res/drawable/none_00020.png
Binary files differ
diff --git a/res/drawable/none_00021.png b/res/drawable/none_00021.png
new file mode 100644
index 000000000..cbcff0391
--- /dev/null
+++ b/res/drawable/none_00021.png
Binary files differ
diff --git a/res/drawable/none_00022.png b/res/drawable/none_00022.png
new file mode 100644
index 000000000..cbcff0391
--- /dev/null
+++ b/res/drawable/none_00022.png
Binary files differ
diff --git a/res/drawable/none_00023.png b/res/drawable/none_00023.png
new file mode 100644
index 000000000..cbcff0391
--- /dev/null
+++ b/res/drawable/none_00023.png
Binary files differ
diff --git a/res/drawable/none_00024.png b/res/drawable/none_00024.png
new file mode 100644
index 000000000..cbcff0391
--- /dev/null
+++ b/res/drawable/none_00024.png
Binary files differ
diff --git a/res/drawable/none_00025.png b/res/drawable/none_00025.png
new file mode 100644
index 000000000..cbcff0391
--- /dev/null
+++ b/res/drawable/none_00025.png
Binary files differ
diff --git a/res/drawable/none_00026.png b/res/drawable/none_00026.png
new file mode 100644
index 000000000..cbcff0391
--- /dev/null
+++ b/res/drawable/none_00026.png
Binary files differ
diff --git a/res/drawable/none_00027.png b/res/drawable/none_00027.png
new file mode 100644
index 000000000..cbcff0391
--- /dev/null
+++ b/res/drawable/none_00027.png
Binary files differ
diff --git a/res/drawable/none_00028.png b/res/drawable/none_00028.png
new file mode 100644
index 000000000..cbcff0391
--- /dev/null
+++ b/res/drawable/none_00028.png
Binary files differ
diff --git a/res/drawable/none_00029.png b/res/drawable/none_00029.png
new file mode 100644
index 000000000..cbcff0391
--- /dev/null
+++ b/res/drawable/none_00029.png
Binary files differ
diff --git a/res/drawable/none_00030.png b/res/drawable/none_00030.png
new file mode 100644
index 000000000..cbcff0391
--- /dev/null
+++ b/res/drawable/none_00030.png
Binary files differ
diff --git a/res/drawable/none_00031.png b/res/drawable/none_00031.png
new file mode 100644
index 000000000..cbcff0391
--- /dev/null
+++ b/res/drawable/none_00031.png
Binary files differ
diff --git a/res/drawable/none_00032.png b/res/drawable/none_00032.png
new file mode 100644
index 000000000..cbcff0391
--- /dev/null
+++ b/res/drawable/none_00032.png
Binary files differ
diff --git a/res/drawable/none_00033.png b/res/drawable/none_00033.png
new file mode 100644
index 000000000..cbcff0391
--- /dev/null
+++ b/res/drawable/none_00033.png
Binary files differ
diff --git a/res/drawable/none_00034.png b/res/drawable/none_00034.png
new file mode 100644
index 000000000..cbcff0391
--- /dev/null
+++ b/res/drawable/none_00034.png
Binary files differ
diff --git a/res/drawable/none_00035.png b/res/drawable/none_00035.png
new file mode 100644
index 000000000..cbcff0391
--- /dev/null
+++ b/res/drawable/none_00035.png
Binary files differ
diff --git a/res/drawable/none_00036.png b/res/drawable/none_00036.png
new file mode 100644
index 000000000..cbcff0391
--- /dev/null
+++ b/res/drawable/none_00036.png
Binary files differ
diff --git a/res/drawable/none_00037.png b/res/drawable/none_00037.png
new file mode 100644
index 000000000..cbcff0391
--- /dev/null
+++ b/res/drawable/none_00037.png
Binary files differ
diff --git a/res/drawable/none_00038.png b/res/drawable/none_00038.png
new file mode 100644
index 000000000..cbcff0391
--- /dev/null
+++ b/res/drawable/none_00038.png
Binary files differ
diff --git a/res/drawable/none_00039.png b/res/drawable/none_00039.png
new file mode 100644
index 000000000..cbcff0391
--- /dev/null
+++ b/res/drawable/none_00039.png
Binary files differ
diff --git a/res/drawable/none_00040.png b/res/drawable/none_00040.png
new file mode 100644
index 000000000..cbcff0391
--- /dev/null
+++ b/res/drawable/none_00040.png
Binary files differ
diff --git a/res/drawable/none_00041.png b/res/drawable/none_00041.png
new file mode 100644
index 000000000..cbcff0391
--- /dev/null
+++ b/res/drawable/none_00041.png
Binary files differ
diff --git a/res/drawable/none_00042.png b/res/drawable/none_00042.png
new file mode 100644
index 000000000..cbcff0391
--- /dev/null
+++ b/res/drawable/none_00042.png
Binary files differ
diff --git a/res/drawable/none_00043.png b/res/drawable/none_00043.png
new file mode 100644
index 000000000..cbcff0391
--- /dev/null
+++ b/res/drawable/none_00043.png
Binary files differ
diff --git a/res/drawable/none_00044.png b/res/drawable/none_00044.png
new file mode 100644
index 000000000..cbcff0391
--- /dev/null
+++ b/res/drawable/none_00044.png
Binary files differ
diff --git a/res/drawable/none_00045.png b/res/drawable/none_00045.png
new file mode 100644
index 000000000..cbcff0391
--- /dev/null
+++ b/res/drawable/none_00045.png
Binary files differ
diff --git a/res/drawable/none_00046.png b/res/drawable/none_00046.png
new file mode 100644
index 000000000..cbcff0391
--- /dev/null
+++ b/res/drawable/none_00046.png
Binary files differ
diff --git a/res/drawable/none_00047.png b/res/drawable/none_00047.png
new file mode 100644
index 000000000..cbcff0391
--- /dev/null
+++ b/res/drawable/none_00047.png
Binary files differ
diff --git a/res/drawable/none_00048.png b/res/drawable/none_00048.png
new file mode 100644
index 000000000..cbcff0391
--- /dev/null
+++ b/res/drawable/none_00048.png
Binary files differ
diff --git a/res/drawable/none_00049.png b/res/drawable/none_00049.png
new file mode 100644
index 000000000..cbcff0391
--- /dev/null
+++ b/res/drawable/none_00049.png
Binary files differ
diff --git a/res/drawable/overview_00000.png b/res/drawable/overview_00000.png
new file mode 100644
index 000000000..e000c6108
--- /dev/null
+++ b/res/drawable/overview_00000.png
Binary files differ
diff --git a/res/drawable/overview_00001.png b/res/drawable/overview_00001.png
new file mode 100644
index 000000000..ee52cae5e
--- /dev/null
+++ b/res/drawable/overview_00001.png
Binary files differ
diff --git a/res/drawable/overview_00002.png b/res/drawable/overview_00002.png
new file mode 100644
index 000000000..401629303
--- /dev/null
+++ b/res/drawable/overview_00002.png
Binary files differ
diff --git a/res/drawable/overview_00003.png b/res/drawable/overview_00003.png
new file mode 100644
index 000000000..9fce3248f
--- /dev/null
+++ b/res/drawable/overview_00003.png
Binary files differ
diff --git a/res/drawable/overview_00004.png b/res/drawable/overview_00004.png
new file mode 100644
index 000000000..6089f3611
--- /dev/null
+++ b/res/drawable/overview_00004.png
Binary files differ
diff --git a/res/drawable/overview_00005.png b/res/drawable/overview_00005.png
new file mode 100644
index 000000000..0195e61d5
--- /dev/null
+++ b/res/drawable/overview_00005.png
Binary files differ
diff --git a/res/drawable/overview_00006.png b/res/drawable/overview_00006.png
new file mode 100644
index 000000000..c91cc1ede
--- /dev/null
+++ b/res/drawable/overview_00006.png
Binary files differ
diff --git a/res/drawable/overview_00007.png b/res/drawable/overview_00007.png
new file mode 100644
index 000000000..ca57ff22c
--- /dev/null
+++ b/res/drawable/overview_00007.png
Binary files differ
diff --git a/res/drawable/overview_00008.png b/res/drawable/overview_00008.png
new file mode 100644
index 000000000..c42692f20
--- /dev/null
+++ b/res/drawable/overview_00008.png
Binary files differ
diff --git a/res/drawable/overview_00009.png b/res/drawable/overview_00009.png
new file mode 100644
index 000000000..e38b36827
--- /dev/null
+++ b/res/drawable/overview_00009.png
Binary files differ
diff --git a/res/drawable/overview_00010.png b/res/drawable/overview_00010.png
new file mode 100644
index 000000000..4416302f8
--- /dev/null
+++ b/res/drawable/overview_00010.png
Binary files differ
diff --git a/res/drawable/overview_00011.png b/res/drawable/overview_00011.png
new file mode 100644
index 000000000..013cdec94
--- /dev/null
+++ b/res/drawable/overview_00011.png
Binary files differ
diff --git a/res/drawable/overview_00012.png b/res/drawable/overview_00012.png
new file mode 100644
index 000000000..fe08ca75d
--- /dev/null
+++ b/res/drawable/overview_00012.png
Binary files differ
diff --git a/res/drawable/overview_00013.png b/res/drawable/overview_00013.png
new file mode 100644
index 000000000..4907c3715
--- /dev/null
+++ b/res/drawable/overview_00013.png
Binary files differ
diff --git a/res/drawable/overview_00014.png b/res/drawable/overview_00014.png
new file mode 100644
index 000000000..26acf47bc
--- /dev/null
+++ b/res/drawable/overview_00014.png
Binary files differ
diff --git a/res/drawable/overview_00015.png b/res/drawable/overview_00015.png
new file mode 100644
index 000000000..258059ae2
--- /dev/null
+++ b/res/drawable/overview_00015.png
Binary files differ
diff --git a/res/drawable/overview_00016.png b/res/drawable/overview_00016.png
new file mode 100644
index 000000000..8c164c139
--- /dev/null
+++ b/res/drawable/overview_00016.png
Binary files differ
diff --git a/res/drawable/overview_00017.png b/res/drawable/overview_00017.png
new file mode 100644
index 000000000..dd1df3330
--- /dev/null
+++ b/res/drawable/overview_00017.png
Binary files differ
diff --git a/res/drawable/overview_00018.png b/res/drawable/overview_00018.png
new file mode 100644
index 000000000..b3e54a3e6
--- /dev/null
+++ b/res/drawable/overview_00018.png
Binary files differ
diff --git a/res/drawable/overview_00019.png b/res/drawable/overview_00019.png
new file mode 100644
index 000000000..5a0b1cbc1
--- /dev/null
+++ b/res/drawable/overview_00019.png
Binary files differ
diff --git a/res/drawable/overview_00020.png b/res/drawable/overview_00020.png
new file mode 100644
index 000000000..a54f07a80
--- /dev/null
+++ b/res/drawable/overview_00020.png
Binary files differ
diff --git a/res/drawable/overview_00021.png b/res/drawable/overview_00021.png
new file mode 100644
index 000000000..a54f07a80
--- /dev/null
+++ b/res/drawable/overview_00021.png
Binary files differ
diff --git a/res/drawable/overview_00022.png b/res/drawable/overview_00022.png
new file mode 100644
index 000000000..a54f07a80
--- /dev/null
+++ b/res/drawable/overview_00022.png
Binary files differ
diff --git a/res/drawable/overview_00023.png b/res/drawable/overview_00023.png
new file mode 100644
index 000000000..a54f07a80
--- /dev/null
+++ b/res/drawable/overview_00023.png
Binary files differ
diff --git a/res/drawable/overview_00024.png b/res/drawable/overview_00024.png
new file mode 100644
index 000000000..a54f07a80
--- /dev/null
+++ b/res/drawable/overview_00024.png
Binary files differ
diff --git a/res/drawable/overview_00025.png b/res/drawable/overview_00025.png
new file mode 100644
index 000000000..a54f07a80
--- /dev/null
+++ b/res/drawable/overview_00025.png
Binary files differ
diff --git a/res/drawable/overview_00026.png b/res/drawable/overview_00026.png
new file mode 100644
index 000000000..a54f07a80
--- /dev/null
+++ b/res/drawable/overview_00026.png
Binary files differ
diff --git a/res/drawable/overview_00027.png b/res/drawable/overview_00027.png
new file mode 100644
index 000000000..a54f07a80
--- /dev/null
+++ b/res/drawable/overview_00027.png
Binary files differ
diff --git a/res/drawable/overview_00028.png b/res/drawable/overview_00028.png
new file mode 100644
index 000000000..a54f07a80
--- /dev/null
+++ b/res/drawable/overview_00028.png
Binary files differ
diff --git a/res/drawable/overview_00029.png b/res/drawable/overview_00029.png
new file mode 100644
index 000000000..a54f07a80
--- /dev/null
+++ b/res/drawable/overview_00029.png
Binary files differ
diff --git a/res/drawable/overview_00030.png b/res/drawable/overview_00030.png
new file mode 100644
index 000000000..a54f07a80
--- /dev/null
+++ b/res/drawable/overview_00030.png
Binary files differ
diff --git a/res/drawable/overview_00031.png b/res/drawable/overview_00031.png
new file mode 100644
index 000000000..a54f07a80
--- /dev/null
+++ b/res/drawable/overview_00031.png
Binary files differ
diff --git a/res/drawable/overview_00032.png b/res/drawable/overview_00032.png
new file mode 100644
index 000000000..a54f07a80
--- /dev/null
+++ b/res/drawable/overview_00032.png
Binary files differ
diff --git a/res/drawable/overview_00033.png b/res/drawable/overview_00033.png
new file mode 100644
index 000000000..a54f07a80
--- /dev/null
+++ b/res/drawable/overview_00033.png
Binary files differ
diff --git a/res/drawable/overview_00034.png b/res/drawable/overview_00034.png
new file mode 100644
index 000000000..a54f07a80
--- /dev/null
+++ b/res/drawable/overview_00034.png
Binary files differ
diff --git a/res/drawable/overview_00035.png b/res/drawable/overview_00035.png
new file mode 100644
index 000000000..a54f07a80
--- /dev/null
+++ b/res/drawable/overview_00035.png
Binary files differ
diff --git a/res/drawable/overview_00036.png b/res/drawable/overview_00036.png
new file mode 100644
index 000000000..a54f07a80
--- /dev/null
+++ b/res/drawable/overview_00036.png
Binary files differ
diff --git a/res/drawable/overview_00037.png b/res/drawable/overview_00037.png
new file mode 100644
index 000000000..a54f07a80
--- /dev/null
+++ b/res/drawable/overview_00037.png
Binary files differ
diff --git a/res/drawable/overview_00038.png b/res/drawable/overview_00038.png
new file mode 100644
index 000000000..a54f07a80
--- /dev/null
+++ b/res/drawable/overview_00038.png
Binary files differ
diff --git a/res/drawable/overview_00039.png b/res/drawable/overview_00039.png
new file mode 100644
index 000000000..a54f07a80
--- /dev/null
+++ b/res/drawable/overview_00039.png
Binary files differ
diff --git a/res/drawable/overview_00040.png b/res/drawable/overview_00040.png
new file mode 100644
index 000000000..a54f07a80
--- /dev/null
+++ b/res/drawable/overview_00040.png
Binary files differ
diff --git a/res/drawable/overview_00041.png b/res/drawable/overview_00041.png
new file mode 100644
index 000000000..a54f07a80
--- /dev/null
+++ b/res/drawable/overview_00041.png
Binary files differ
diff --git a/res/drawable/overview_00042.png b/res/drawable/overview_00042.png
new file mode 100644
index 000000000..a54f07a80
--- /dev/null
+++ b/res/drawable/overview_00042.png
Binary files differ
diff --git a/res/drawable/overview_00043.png b/res/drawable/overview_00043.png
new file mode 100644
index 000000000..a54f07a80
--- /dev/null
+++ b/res/drawable/overview_00043.png
Binary files differ
diff --git a/res/drawable/overview_00044.png b/res/drawable/overview_00044.png
new file mode 100644
index 000000000..a54f07a80
--- /dev/null
+++ b/res/drawable/overview_00044.png
Binary files differ
diff --git a/res/drawable/overview_00045.png b/res/drawable/overview_00045.png
new file mode 100644
index 000000000..a54f07a80
--- /dev/null
+++ b/res/drawable/overview_00045.png
Binary files differ
diff --git a/res/drawable/overview_00046.png b/res/drawable/overview_00046.png
new file mode 100644
index 000000000..a54f07a80
--- /dev/null
+++ b/res/drawable/overview_00046.png
Binary files differ
diff --git a/res/drawable/overview_00047.png b/res/drawable/overview_00047.png
new file mode 100644
index 000000000..a54f07a80
--- /dev/null
+++ b/res/drawable/overview_00047.png
Binary files differ
diff --git a/res/drawable/overview_00048.png b/res/drawable/overview_00048.png
new file mode 100644
index 000000000..a54f07a80
--- /dev/null
+++ b/res/drawable/overview_00048.png
Binary files differ
diff --git a/res/drawable/overview_00049.png b/res/drawable/overview_00049.png
new file mode 100644
index 000000000..a54f07a80
--- /dev/null
+++ b/res/drawable/overview_00049.png
Binary files differ
diff --git a/res/drawable/rotatedown_00000.png b/res/drawable/rotatedown_00000.png
new file mode 100644
index 000000000..07ccb92e0
--- /dev/null
+++ b/res/drawable/rotatedown_00000.png
Binary files differ
diff --git a/res/drawable/rotatedown_00001.png b/res/drawable/rotatedown_00001.png
new file mode 100644
index 000000000..98f1b6761
--- /dev/null
+++ b/res/drawable/rotatedown_00001.png
Binary files differ
diff --git a/res/drawable/rotatedown_00002.png b/res/drawable/rotatedown_00002.png
new file mode 100644
index 000000000..927f5d1a5
--- /dev/null
+++ b/res/drawable/rotatedown_00002.png
Binary files differ
diff --git a/res/drawable/rotatedown_00003.png b/res/drawable/rotatedown_00003.png
new file mode 100644
index 000000000..fcb6f47e3
--- /dev/null
+++ b/res/drawable/rotatedown_00003.png
Binary files differ
diff --git a/res/drawable/rotatedown_00004.png b/res/drawable/rotatedown_00004.png
new file mode 100644
index 000000000..16797d611
--- /dev/null
+++ b/res/drawable/rotatedown_00004.png
Binary files differ
diff --git a/res/drawable/rotatedown_00005.png b/res/drawable/rotatedown_00005.png
new file mode 100644
index 000000000..4c43eb8b6
--- /dev/null
+++ b/res/drawable/rotatedown_00005.png
Binary files differ
diff --git a/res/drawable/rotatedown_00006.png b/res/drawable/rotatedown_00006.png
new file mode 100644
index 000000000..2f03ec42b
--- /dev/null
+++ b/res/drawable/rotatedown_00006.png
Binary files differ
diff --git a/res/drawable/rotatedown_00007.png b/res/drawable/rotatedown_00007.png
new file mode 100644
index 000000000..6a6d080b8
--- /dev/null
+++ b/res/drawable/rotatedown_00007.png
Binary files differ
diff --git a/res/drawable/rotatedown_00008.png b/res/drawable/rotatedown_00008.png
new file mode 100644
index 000000000..bf9f3103f
--- /dev/null
+++ b/res/drawable/rotatedown_00008.png
Binary files differ
diff --git a/res/drawable/rotatedown_00009.png b/res/drawable/rotatedown_00009.png
new file mode 100644
index 000000000..f911bf4bc
--- /dev/null
+++ b/res/drawable/rotatedown_00009.png
Binary files differ
diff --git a/res/drawable/rotatedown_00010.png b/res/drawable/rotatedown_00010.png
new file mode 100644
index 000000000..f84dd2051
--- /dev/null
+++ b/res/drawable/rotatedown_00010.png
Binary files differ
diff --git a/res/drawable/rotatedown_00011.png b/res/drawable/rotatedown_00011.png
new file mode 100644
index 000000000..7106a7db8
--- /dev/null
+++ b/res/drawable/rotatedown_00011.png
Binary files differ
diff --git a/res/drawable/rotatedown_00012.png b/res/drawable/rotatedown_00012.png
new file mode 100644
index 000000000..13cd0b2c6
--- /dev/null
+++ b/res/drawable/rotatedown_00012.png
Binary files differ
diff --git a/res/drawable/rotatedown_00013.png b/res/drawable/rotatedown_00013.png
new file mode 100644
index 000000000..4589bf263
--- /dev/null
+++ b/res/drawable/rotatedown_00013.png
Binary files differ
diff --git a/res/drawable/rotatedown_00014.png b/res/drawable/rotatedown_00014.png
new file mode 100644
index 000000000..6b59e5d07
--- /dev/null
+++ b/res/drawable/rotatedown_00014.png
Binary files differ
diff --git a/res/drawable/rotatedown_00015.png b/res/drawable/rotatedown_00015.png
new file mode 100644
index 000000000..890746b83
--- /dev/null
+++ b/res/drawable/rotatedown_00015.png
Binary files differ
diff --git a/res/drawable/rotatedown_00016.png b/res/drawable/rotatedown_00016.png
new file mode 100644
index 000000000..56d9e2343
--- /dev/null
+++ b/res/drawable/rotatedown_00016.png
Binary files differ
diff --git a/res/drawable/rotatedown_00017.png b/res/drawable/rotatedown_00017.png
new file mode 100644
index 000000000..d2d80406c
--- /dev/null
+++ b/res/drawable/rotatedown_00017.png
Binary files differ
diff --git a/res/drawable/rotatedown_00018.png b/res/drawable/rotatedown_00018.png
new file mode 100644
index 000000000..43afa3ed8
--- /dev/null
+++ b/res/drawable/rotatedown_00018.png
Binary files differ
diff --git a/res/drawable/rotatedown_00019.png b/res/drawable/rotatedown_00019.png
new file mode 100644
index 000000000..4c6ec9095
--- /dev/null
+++ b/res/drawable/rotatedown_00019.png
Binary files differ
diff --git a/res/drawable/rotatedown_00020.png b/res/drawable/rotatedown_00020.png
new file mode 100644
index 000000000..2cfdd90ee
--- /dev/null
+++ b/res/drawable/rotatedown_00020.png
Binary files differ
diff --git a/res/drawable/rotatedown_00021.png b/res/drawable/rotatedown_00021.png
new file mode 100644
index 000000000..a54e05333
--- /dev/null
+++ b/res/drawable/rotatedown_00021.png
Binary files differ
diff --git a/res/drawable/rotatedown_00022.png b/res/drawable/rotatedown_00022.png
new file mode 100644
index 000000000..7f9c0214c
--- /dev/null
+++ b/res/drawable/rotatedown_00022.png
Binary files differ
diff --git a/res/drawable/rotatedown_00023.png b/res/drawable/rotatedown_00023.png
new file mode 100644
index 000000000..86c20dfbd
--- /dev/null
+++ b/res/drawable/rotatedown_00023.png
Binary files differ
diff --git a/res/drawable/rotatedown_00024.png b/res/drawable/rotatedown_00024.png
new file mode 100644
index 000000000..cacf6274b
--- /dev/null
+++ b/res/drawable/rotatedown_00024.png
Binary files differ
diff --git a/res/drawable/rotatedown_00025.png b/res/drawable/rotatedown_00025.png
new file mode 100644
index 000000000..f80765d5b
--- /dev/null
+++ b/res/drawable/rotatedown_00025.png
Binary files differ
diff --git a/res/drawable/rotatedown_00026.png b/res/drawable/rotatedown_00026.png
new file mode 100644
index 000000000..cb0714379
--- /dev/null
+++ b/res/drawable/rotatedown_00026.png
Binary files differ
diff --git a/res/drawable/rotatedown_00027.png b/res/drawable/rotatedown_00027.png
new file mode 100644
index 000000000..4f5639729
--- /dev/null
+++ b/res/drawable/rotatedown_00027.png
Binary files differ
diff --git a/res/drawable/rotatedown_00028.png b/res/drawable/rotatedown_00028.png
new file mode 100644
index 000000000..b1b114e5c
--- /dev/null
+++ b/res/drawable/rotatedown_00028.png
Binary files differ
diff --git a/res/drawable/rotatedown_00029.png b/res/drawable/rotatedown_00029.png
new file mode 100644
index 000000000..b20104e93
--- /dev/null
+++ b/res/drawable/rotatedown_00029.png
Binary files differ
diff --git a/res/drawable/rotatedown_00030.png b/res/drawable/rotatedown_00030.png
new file mode 100644
index 000000000..07ccb92e0
--- /dev/null
+++ b/res/drawable/rotatedown_00030.png
Binary files differ
diff --git a/res/drawable/rotatedown_00031.png b/res/drawable/rotatedown_00031.png
new file mode 100644
index 000000000..07ccb92e0
--- /dev/null
+++ b/res/drawable/rotatedown_00031.png
Binary files differ
diff --git a/res/drawable/rotatedown_00032.png b/res/drawable/rotatedown_00032.png
new file mode 100644
index 000000000..07ccb92e0
--- /dev/null
+++ b/res/drawable/rotatedown_00032.png
Binary files differ
diff --git a/res/drawable/rotatedown_00033.png b/res/drawable/rotatedown_00033.png
new file mode 100644
index 000000000..07ccb92e0
--- /dev/null
+++ b/res/drawable/rotatedown_00033.png
Binary files differ
diff --git a/res/drawable/rotatedown_00034.png b/res/drawable/rotatedown_00034.png
new file mode 100644
index 000000000..07ccb92e0
--- /dev/null
+++ b/res/drawable/rotatedown_00034.png
Binary files differ
diff --git a/res/drawable/rotatedown_00035.png b/res/drawable/rotatedown_00035.png
new file mode 100644
index 000000000..07ccb92e0
--- /dev/null
+++ b/res/drawable/rotatedown_00035.png
Binary files differ
diff --git a/res/drawable/rotatedown_00036.png b/res/drawable/rotatedown_00036.png
new file mode 100644
index 000000000..07ccb92e0
--- /dev/null
+++ b/res/drawable/rotatedown_00036.png
Binary files differ
diff --git a/res/drawable/rotatedown_00037.png b/res/drawable/rotatedown_00037.png
new file mode 100644
index 000000000..07ccb92e0
--- /dev/null
+++ b/res/drawable/rotatedown_00037.png
Binary files differ
diff --git a/res/drawable/rotatedown_00038.png b/res/drawable/rotatedown_00038.png
new file mode 100644
index 000000000..07ccb92e0
--- /dev/null
+++ b/res/drawable/rotatedown_00038.png
Binary files differ
diff --git a/res/drawable/rotatedown_00039.png b/res/drawable/rotatedown_00039.png
new file mode 100644
index 000000000..07ccb92e0
--- /dev/null
+++ b/res/drawable/rotatedown_00039.png
Binary files differ
diff --git a/res/drawable/rotatedown_00040.png b/res/drawable/rotatedown_00040.png
new file mode 100644
index 000000000..07ccb92e0
--- /dev/null
+++ b/res/drawable/rotatedown_00040.png
Binary files differ
diff --git a/res/drawable/rotatedown_00041.png b/res/drawable/rotatedown_00041.png
new file mode 100644
index 000000000..07ccb92e0
--- /dev/null
+++ b/res/drawable/rotatedown_00041.png
Binary files differ
diff --git a/res/drawable/rotatedown_00042.png b/res/drawable/rotatedown_00042.png
new file mode 100644
index 000000000..07ccb92e0
--- /dev/null
+++ b/res/drawable/rotatedown_00042.png
Binary files differ
diff --git a/res/drawable/rotatedown_00043.png b/res/drawable/rotatedown_00043.png
new file mode 100644
index 000000000..07ccb92e0
--- /dev/null
+++ b/res/drawable/rotatedown_00043.png
Binary files differ
diff --git a/res/drawable/rotatedown_00044.png b/res/drawable/rotatedown_00044.png
new file mode 100644
index 000000000..07ccb92e0
--- /dev/null
+++ b/res/drawable/rotatedown_00044.png
Binary files differ
diff --git a/res/drawable/rotatedown_00045.png b/res/drawable/rotatedown_00045.png
new file mode 100644
index 000000000..07ccb92e0
--- /dev/null
+++ b/res/drawable/rotatedown_00045.png
Binary files differ
diff --git a/res/drawable/rotatedown_00046.png b/res/drawable/rotatedown_00046.png
new file mode 100644
index 000000000..07ccb92e0
--- /dev/null
+++ b/res/drawable/rotatedown_00046.png
Binary files differ
diff --git a/res/drawable/rotatedown_00047.png b/res/drawable/rotatedown_00047.png
new file mode 100644
index 000000000..07ccb92e0
--- /dev/null
+++ b/res/drawable/rotatedown_00047.png
Binary files differ
diff --git a/res/drawable/rotatedown_00048.png b/res/drawable/rotatedown_00048.png
new file mode 100644
index 000000000..07ccb92e0
--- /dev/null
+++ b/res/drawable/rotatedown_00048.png
Binary files differ
diff --git a/res/drawable/rotatedown_00049.png b/res/drawable/rotatedown_00049.png
new file mode 100644
index 000000000..07ccb92e0
--- /dev/null
+++ b/res/drawable/rotatedown_00049.png
Binary files differ
diff --git a/res/drawable/rotateup_00000.png b/res/drawable/rotateup_00000.png
new file mode 100644
index 000000000..75e575f94
--- /dev/null
+++ b/res/drawable/rotateup_00000.png
Binary files differ
diff --git a/res/drawable/rotateup_00001.png b/res/drawable/rotateup_00001.png
new file mode 100644
index 000000000..d43792b1d
--- /dev/null
+++ b/res/drawable/rotateup_00001.png
Binary files differ
diff --git a/res/drawable/rotateup_00002.png b/res/drawable/rotateup_00002.png
new file mode 100644
index 000000000..f77000771
--- /dev/null
+++ b/res/drawable/rotateup_00002.png
Binary files differ
diff --git a/res/drawable/rotateup_00003.png b/res/drawable/rotateup_00003.png
new file mode 100644
index 000000000..f5c2493b6
--- /dev/null
+++ b/res/drawable/rotateup_00003.png
Binary files differ
diff --git a/res/drawable/rotateup_00004.png b/res/drawable/rotateup_00004.png
new file mode 100644
index 000000000..b84318252
--- /dev/null
+++ b/res/drawable/rotateup_00004.png
Binary files differ
diff --git a/res/drawable/rotateup_00005.png b/res/drawable/rotateup_00005.png
new file mode 100644
index 000000000..342b3f9ae
--- /dev/null
+++ b/res/drawable/rotateup_00005.png
Binary files differ
diff --git a/res/drawable/rotateup_00006.png b/res/drawable/rotateup_00006.png
new file mode 100644
index 000000000..cbf69d75e
--- /dev/null
+++ b/res/drawable/rotateup_00006.png
Binary files differ
diff --git a/res/drawable/rotateup_00007.png b/res/drawable/rotateup_00007.png
new file mode 100644
index 000000000..8826db503
--- /dev/null
+++ b/res/drawable/rotateup_00007.png
Binary files differ
diff --git a/res/drawable/rotateup_00008.png b/res/drawable/rotateup_00008.png
new file mode 100644
index 000000000..6c363edaa
--- /dev/null
+++ b/res/drawable/rotateup_00008.png
Binary files differ
diff --git a/res/drawable/rotateup_00009.png b/res/drawable/rotateup_00009.png
new file mode 100644
index 000000000..48e289034
--- /dev/null
+++ b/res/drawable/rotateup_00009.png
Binary files differ
diff --git a/res/drawable/rotateup_00010.png b/res/drawable/rotateup_00010.png
new file mode 100644
index 000000000..5749ccd29
--- /dev/null
+++ b/res/drawable/rotateup_00010.png
Binary files differ
diff --git a/res/drawable/rotateup_00011.png b/res/drawable/rotateup_00011.png
new file mode 100644
index 000000000..2a0463c92
--- /dev/null
+++ b/res/drawable/rotateup_00011.png
Binary files differ
diff --git a/res/drawable/rotateup_00012.png b/res/drawable/rotateup_00012.png
new file mode 100644
index 000000000..9bcfa09d4
--- /dev/null
+++ b/res/drawable/rotateup_00012.png
Binary files differ
diff --git a/res/drawable/rotateup_00013.png b/res/drawable/rotateup_00013.png
new file mode 100644
index 000000000..bc4ebb9db
--- /dev/null
+++ b/res/drawable/rotateup_00013.png
Binary files differ
diff --git a/res/drawable/rotateup_00014.png b/res/drawable/rotateup_00014.png
new file mode 100644
index 000000000..181456805
--- /dev/null
+++ b/res/drawable/rotateup_00014.png
Binary files differ
diff --git a/res/drawable/rotateup_00015.png b/res/drawable/rotateup_00015.png
new file mode 100644
index 000000000..48c34408b
--- /dev/null
+++ b/res/drawable/rotateup_00015.png
Binary files differ
diff --git a/res/drawable/rotateup_00016.png b/res/drawable/rotateup_00016.png
new file mode 100644
index 000000000..772a31d6a
--- /dev/null
+++ b/res/drawable/rotateup_00016.png
Binary files differ
diff --git a/res/drawable/rotateup_00017.png b/res/drawable/rotateup_00017.png
new file mode 100644
index 000000000..ddad38c9e
--- /dev/null
+++ b/res/drawable/rotateup_00017.png
Binary files differ
diff --git a/res/drawable/rotateup_00018.png b/res/drawable/rotateup_00018.png
new file mode 100644
index 000000000..a401751be
--- /dev/null
+++ b/res/drawable/rotateup_00018.png
Binary files differ
diff --git a/res/drawable/rotateup_00019.png b/res/drawable/rotateup_00019.png
new file mode 100644
index 000000000..2091c5e6e
--- /dev/null
+++ b/res/drawable/rotateup_00019.png
Binary files differ
diff --git a/res/drawable/rotateup_00020.png b/res/drawable/rotateup_00020.png
new file mode 100644
index 000000000..61ca3b246
--- /dev/null
+++ b/res/drawable/rotateup_00020.png
Binary files differ
diff --git a/res/drawable/rotateup_00021.png b/res/drawable/rotateup_00021.png
new file mode 100644
index 000000000..27c4258f3
--- /dev/null
+++ b/res/drawable/rotateup_00021.png
Binary files differ
diff --git a/res/drawable/rotateup_00022.png b/res/drawable/rotateup_00022.png
new file mode 100644
index 000000000..6f158ba2f
--- /dev/null
+++ b/res/drawable/rotateup_00022.png
Binary files differ
diff --git a/res/drawable/rotateup_00023.png b/res/drawable/rotateup_00023.png
new file mode 100644
index 000000000..6a0a4dae0
--- /dev/null
+++ b/res/drawable/rotateup_00023.png
Binary files differ
diff --git a/res/drawable/rotateup_00024.png b/res/drawable/rotateup_00024.png
new file mode 100644
index 000000000..cdfde2a76
--- /dev/null
+++ b/res/drawable/rotateup_00024.png
Binary files differ
diff --git a/res/drawable/rotateup_00025.png b/res/drawable/rotateup_00025.png
new file mode 100644
index 000000000..2ac9ffa0e
--- /dev/null
+++ b/res/drawable/rotateup_00025.png
Binary files differ
diff --git a/res/drawable/rotateup_00026.png b/res/drawable/rotateup_00026.png
new file mode 100644
index 000000000..2e41a9719
--- /dev/null
+++ b/res/drawable/rotateup_00026.png
Binary files differ
diff --git a/res/drawable/rotateup_00027.png b/res/drawable/rotateup_00027.png
new file mode 100644
index 000000000..fc68c10aa
--- /dev/null
+++ b/res/drawable/rotateup_00027.png
Binary files differ
diff --git a/res/drawable/rotateup_00028.png b/res/drawable/rotateup_00028.png
new file mode 100644
index 000000000..cc5fb9c28
--- /dev/null
+++ b/res/drawable/rotateup_00028.png
Binary files differ
diff --git a/res/drawable/rotateup_00029.png b/res/drawable/rotateup_00029.png
new file mode 100644
index 000000000..43ef7a180
--- /dev/null
+++ b/res/drawable/rotateup_00029.png
Binary files differ
diff --git a/res/drawable/rotateup_00030.png b/res/drawable/rotateup_00030.png
new file mode 100644
index 000000000..75e575f94
--- /dev/null
+++ b/res/drawable/rotateup_00030.png
Binary files differ
diff --git a/res/drawable/rotateup_00031.png b/res/drawable/rotateup_00031.png
new file mode 100644
index 000000000..75e575f94
--- /dev/null
+++ b/res/drawable/rotateup_00031.png
Binary files differ
diff --git a/res/drawable/rotateup_00032.png b/res/drawable/rotateup_00032.png
new file mode 100644
index 000000000..75e575f94
--- /dev/null
+++ b/res/drawable/rotateup_00032.png
Binary files differ
diff --git a/res/drawable/rotateup_00033.png b/res/drawable/rotateup_00033.png
new file mode 100644
index 000000000..75e575f94
--- /dev/null
+++ b/res/drawable/rotateup_00033.png
Binary files differ
diff --git a/res/drawable/rotateup_00034.png b/res/drawable/rotateup_00034.png
new file mode 100644
index 000000000..75e575f94
--- /dev/null
+++ b/res/drawable/rotateup_00034.png
Binary files differ
diff --git a/res/drawable/rotateup_00035.png b/res/drawable/rotateup_00035.png
new file mode 100644
index 000000000..75e575f94
--- /dev/null
+++ b/res/drawable/rotateup_00035.png
Binary files differ
diff --git a/res/drawable/rotateup_00036.png b/res/drawable/rotateup_00036.png
new file mode 100644
index 000000000..75e575f94
--- /dev/null
+++ b/res/drawable/rotateup_00036.png
Binary files differ
diff --git a/res/drawable/rotateup_00037.png b/res/drawable/rotateup_00037.png
new file mode 100644
index 000000000..75e575f94
--- /dev/null
+++ b/res/drawable/rotateup_00037.png
Binary files differ
diff --git a/res/drawable/rotateup_00038.png b/res/drawable/rotateup_00038.png
new file mode 100644
index 000000000..75e575f94
--- /dev/null
+++ b/res/drawable/rotateup_00038.png
Binary files differ
diff --git a/res/drawable/rotateup_00039.png b/res/drawable/rotateup_00039.png
new file mode 100644
index 000000000..75e575f94
--- /dev/null
+++ b/res/drawable/rotateup_00039.png
Binary files differ
diff --git a/res/drawable/rotateup_00040.png b/res/drawable/rotateup_00040.png
new file mode 100644
index 000000000..75e575f94
--- /dev/null
+++ b/res/drawable/rotateup_00040.png
Binary files differ
diff --git a/res/drawable/rotateup_00041.png b/res/drawable/rotateup_00041.png
new file mode 100644
index 000000000..75e575f94
--- /dev/null
+++ b/res/drawable/rotateup_00041.png
Binary files differ
diff --git a/res/drawable/rotateup_00042.png b/res/drawable/rotateup_00042.png
new file mode 100644
index 000000000..75e575f94
--- /dev/null
+++ b/res/drawable/rotateup_00042.png
Binary files differ
diff --git a/res/drawable/rotateup_00043.png b/res/drawable/rotateup_00043.png
new file mode 100644
index 000000000..75e575f94
--- /dev/null
+++ b/res/drawable/rotateup_00043.png
Binary files differ
diff --git a/res/drawable/rotateup_00044.png b/res/drawable/rotateup_00044.png
new file mode 100644
index 000000000..75e575f94
--- /dev/null
+++ b/res/drawable/rotateup_00044.png
Binary files differ
diff --git a/res/drawable/rotateup_00045.png b/res/drawable/rotateup_00045.png
new file mode 100644
index 000000000..75e575f94
--- /dev/null
+++ b/res/drawable/rotateup_00045.png
Binary files differ
diff --git a/res/drawable/rotateup_00046.png b/res/drawable/rotateup_00046.png
new file mode 100644
index 000000000..75e575f94
--- /dev/null
+++ b/res/drawable/rotateup_00046.png
Binary files differ
diff --git a/res/drawable/rotateup_00047.png b/res/drawable/rotateup_00047.png
new file mode 100644
index 000000000..75e575f94
--- /dev/null
+++ b/res/drawable/rotateup_00047.png
Binary files differ
diff --git a/res/drawable/rotateup_00048.png b/res/drawable/rotateup_00048.png
new file mode 100644
index 000000000..75e575f94
--- /dev/null
+++ b/res/drawable/rotateup_00048.png
Binary files differ
diff --git a/res/drawable/rotateup_00049.png b/res/drawable/rotateup_00049.png
new file mode 100644
index 000000000..75e575f94
--- /dev/null
+++ b/res/drawable/rotateup_00049.png
Binary files differ
diff --git a/res/drawable/stack_00000.png b/res/drawable/stack_00000.png
new file mode 100644
index 000000000..b7e7f0bd2
--- /dev/null
+++ b/res/drawable/stack_00000.png
Binary files differ
diff --git a/res/drawable/stack_00001.png b/res/drawable/stack_00001.png
new file mode 100644
index 000000000..8b7f3a564
--- /dev/null
+++ b/res/drawable/stack_00001.png
Binary files differ
diff --git a/res/drawable/stack_00002.png b/res/drawable/stack_00002.png
new file mode 100644
index 000000000..c9e3aed80
--- /dev/null
+++ b/res/drawable/stack_00002.png
Binary files differ
diff --git a/res/drawable/stack_00003.png b/res/drawable/stack_00003.png
new file mode 100644
index 000000000..565f69b99
--- /dev/null
+++ b/res/drawable/stack_00003.png
Binary files differ
diff --git a/res/drawable/stack_00004.png b/res/drawable/stack_00004.png
new file mode 100644
index 000000000..2726dacc4
--- /dev/null
+++ b/res/drawable/stack_00004.png
Binary files differ
diff --git a/res/drawable/stack_00005.png b/res/drawable/stack_00005.png
new file mode 100644
index 000000000..266f1dcc0
--- /dev/null
+++ b/res/drawable/stack_00005.png
Binary files differ
diff --git a/res/drawable/stack_00006.png b/res/drawable/stack_00006.png
new file mode 100644
index 000000000..f26c0d042
--- /dev/null
+++ b/res/drawable/stack_00006.png
Binary files differ
diff --git a/res/drawable/stack_00007.png b/res/drawable/stack_00007.png
new file mode 100644
index 000000000..f6bd36217
--- /dev/null
+++ b/res/drawable/stack_00007.png
Binary files differ
diff --git a/res/drawable/stack_00008.png b/res/drawable/stack_00008.png
new file mode 100644
index 000000000..d9c20d803
--- /dev/null
+++ b/res/drawable/stack_00008.png
Binary files differ
diff --git a/res/drawable/stack_00009.png b/res/drawable/stack_00009.png
new file mode 100644
index 000000000..54620e210
--- /dev/null
+++ b/res/drawable/stack_00009.png
Binary files differ
diff --git a/res/drawable/stack_00010.png b/res/drawable/stack_00010.png
new file mode 100644
index 000000000..7ec4b8719
--- /dev/null
+++ b/res/drawable/stack_00010.png
Binary files differ
diff --git a/res/drawable/stack_00011.png b/res/drawable/stack_00011.png
new file mode 100644
index 000000000..300b98ac6
--- /dev/null
+++ b/res/drawable/stack_00011.png
Binary files differ
diff --git a/res/drawable/stack_00012.png b/res/drawable/stack_00012.png
new file mode 100644
index 000000000..eae0e919a
--- /dev/null
+++ b/res/drawable/stack_00012.png
Binary files differ
diff --git a/res/drawable/stack_00013.png b/res/drawable/stack_00013.png
new file mode 100644
index 000000000..fa24d7461
--- /dev/null
+++ b/res/drawable/stack_00013.png
Binary files differ
diff --git a/res/drawable/stack_00014.png b/res/drawable/stack_00014.png
new file mode 100644
index 000000000..ad0a8108c
--- /dev/null
+++ b/res/drawable/stack_00014.png
Binary files differ
diff --git a/res/drawable/stack_00015.png b/res/drawable/stack_00015.png
new file mode 100644
index 000000000..125950961
--- /dev/null
+++ b/res/drawable/stack_00015.png
Binary files differ
diff --git a/res/drawable/stack_00016.png b/res/drawable/stack_00016.png
new file mode 100644
index 000000000..cc0e9076b
--- /dev/null
+++ b/res/drawable/stack_00016.png
Binary files differ
diff --git a/res/drawable/stack_00017.png b/res/drawable/stack_00017.png
new file mode 100644
index 000000000..174165b54
--- /dev/null
+++ b/res/drawable/stack_00017.png
Binary files differ
diff --git a/res/drawable/stack_00018.png b/res/drawable/stack_00018.png
new file mode 100644
index 000000000..0fb9cea69
--- /dev/null
+++ b/res/drawable/stack_00018.png
Binary files differ
diff --git a/res/drawable/stack_00019.png b/res/drawable/stack_00019.png
new file mode 100644
index 000000000..4a66a8fda
--- /dev/null
+++ b/res/drawable/stack_00019.png
Binary files differ
diff --git a/res/drawable/stack_00020.png b/res/drawable/stack_00020.png
new file mode 100644
index 000000000..ebe970d76
--- /dev/null
+++ b/res/drawable/stack_00020.png
Binary files differ
diff --git a/res/drawable/stack_00021.png b/res/drawable/stack_00021.png
new file mode 100644
index 000000000..ebe970d76
--- /dev/null
+++ b/res/drawable/stack_00021.png
Binary files differ
diff --git a/res/drawable/stack_00022.png b/res/drawable/stack_00022.png
new file mode 100644
index 000000000..ebe970d76
--- /dev/null
+++ b/res/drawable/stack_00022.png
Binary files differ
diff --git a/res/drawable/stack_00023.png b/res/drawable/stack_00023.png
new file mode 100644
index 000000000..ebe970d76
--- /dev/null
+++ b/res/drawable/stack_00023.png
Binary files differ
diff --git a/res/drawable/stack_00024.png b/res/drawable/stack_00024.png
new file mode 100644
index 000000000..ebe970d76
--- /dev/null
+++ b/res/drawable/stack_00024.png
Binary files differ
diff --git a/res/drawable/stack_00025.png b/res/drawable/stack_00025.png
new file mode 100644
index 000000000..ebe970d76
--- /dev/null
+++ b/res/drawable/stack_00025.png
Binary files differ
diff --git a/res/drawable/stack_00026.png b/res/drawable/stack_00026.png
new file mode 100644
index 000000000..ebe970d76
--- /dev/null
+++ b/res/drawable/stack_00026.png
Binary files differ
diff --git a/res/drawable/stack_00027.png b/res/drawable/stack_00027.png
new file mode 100644
index 000000000..ebe970d76
--- /dev/null
+++ b/res/drawable/stack_00027.png
Binary files differ
diff --git a/res/drawable/stack_00028.png b/res/drawable/stack_00028.png
new file mode 100644
index 000000000..ebe970d76
--- /dev/null
+++ b/res/drawable/stack_00028.png
Binary files differ
diff --git a/res/drawable/stack_00029.png b/res/drawable/stack_00029.png
new file mode 100644
index 000000000..ebe970d76
--- /dev/null
+++ b/res/drawable/stack_00029.png
Binary files differ
diff --git a/res/drawable/stack_00030.png b/res/drawable/stack_00030.png
new file mode 100644
index 000000000..ebe970d76
--- /dev/null
+++ b/res/drawable/stack_00030.png
Binary files differ
diff --git a/res/drawable/stack_00031.png b/res/drawable/stack_00031.png
new file mode 100644
index 000000000..ebe970d76
--- /dev/null
+++ b/res/drawable/stack_00031.png
Binary files differ
diff --git a/res/drawable/stack_00032.png b/res/drawable/stack_00032.png
new file mode 100644
index 000000000..ebe970d76
--- /dev/null
+++ b/res/drawable/stack_00032.png
Binary files differ
diff --git a/res/drawable/stack_00033.png b/res/drawable/stack_00033.png
new file mode 100644
index 000000000..ebe970d76
--- /dev/null
+++ b/res/drawable/stack_00033.png
Binary files differ
diff --git a/res/drawable/stack_00034.png b/res/drawable/stack_00034.png
new file mode 100644
index 000000000..ebe970d76
--- /dev/null
+++ b/res/drawable/stack_00034.png
Binary files differ
diff --git a/res/drawable/stack_00035.png b/res/drawable/stack_00035.png
new file mode 100644
index 000000000..ebe970d76
--- /dev/null
+++ b/res/drawable/stack_00035.png
Binary files differ
diff --git a/res/drawable/stack_00036.png b/res/drawable/stack_00036.png
new file mode 100644
index 000000000..ebe970d76
--- /dev/null
+++ b/res/drawable/stack_00036.png
Binary files differ
diff --git a/res/drawable/stack_00037.png b/res/drawable/stack_00037.png
new file mode 100644
index 000000000..ebe970d76
--- /dev/null
+++ b/res/drawable/stack_00037.png
Binary files differ
diff --git a/res/drawable/stack_00038.png b/res/drawable/stack_00038.png
new file mode 100644
index 000000000..ebe970d76
--- /dev/null
+++ b/res/drawable/stack_00038.png
Binary files differ
diff --git a/res/drawable/stack_00039.png b/res/drawable/stack_00039.png
new file mode 100644
index 000000000..ebe970d76
--- /dev/null
+++ b/res/drawable/stack_00039.png
Binary files differ
diff --git a/res/drawable/stack_00040.png b/res/drawable/stack_00040.png
new file mode 100644
index 000000000..ebe970d76
--- /dev/null
+++ b/res/drawable/stack_00040.png
Binary files differ
diff --git a/res/drawable/stack_00041.png b/res/drawable/stack_00041.png
new file mode 100644
index 000000000..ebe970d76
--- /dev/null
+++ b/res/drawable/stack_00041.png
Binary files differ
diff --git a/res/drawable/stack_00042.png b/res/drawable/stack_00042.png
new file mode 100644
index 000000000..ebe970d76
--- /dev/null
+++ b/res/drawable/stack_00042.png
Binary files differ
diff --git a/res/drawable/stack_00043.png b/res/drawable/stack_00043.png
new file mode 100644
index 000000000..ebe970d76
--- /dev/null
+++ b/res/drawable/stack_00043.png
Binary files differ
diff --git a/res/drawable/stack_00044.png b/res/drawable/stack_00044.png
new file mode 100644
index 000000000..ebe970d76
--- /dev/null
+++ b/res/drawable/stack_00044.png
Binary files differ
diff --git a/res/drawable/stack_00045.png b/res/drawable/stack_00045.png
new file mode 100644
index 000000000..ebe970d76
--- /dev/null
+++ b/res/drawable/stack_00045.png
Binary files differ
diff --git a/res/drawable/stack_00046.png b/res/drawable/stack_00046.png
new file mode 100644
index 000000000..ebe970d76
--- /dev/null
+++ b/res/drawable/stack_00046.png
Binary files differ
diff --git a/res/drawable/stack_00047.png b/res/drawable/stack_00047.png
new file mode 100644
index 000000000..ebe970d76
--- /dev/null
+++ b/res/drawable/stack_00047.png
Binary files differ
diff --git a/res/drawable/stack_00048.png b/res/drawable/stack_00048.png
new file mode 100644
index 000000000..ebe970d76
--- /dev/null
+++ b/res/drawable/stack_00048.png
Binary files differ
diff --git a/res/drawable/stack_00049.png b/res/drawable/stack_00049.png
new file mode 100644
index 000000000..ebe970d76
--- /dev/null
+++ b/res/drawable/stack_00049.png
Binary files differ
diff --git a/res/drawable/setting_button.xml b/res/drawable/themes_button.xml
index 4d66a1ac7..3006b9a6e 100644
--- a/res/drawable/setting_button.xml
+++ b/res/drawable/themes_button.xml
@@ -15,7 +15,7 @@
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_focused="true" android:drawable="@drawable/ic_setting_pressed" />
- <item android:state_pressed="true" android:drawable="@drawable/ic_setting_pressed" />
- <item android:drawable="@drawable/ic_setting" />
+ <item android:state_focused="true" android:drawable="@drawable/ic_themes_pressed" />
+ <item android:state_pressed="true" android:drawable="@drawable/ic_themes_pressed" />
+ <item android:drawable="@drawable/ic_themes" />
</selector>
diff --git a/res/drawable/transition_accordion.xml b/res/drawable/transition_accordion.xml
new file mode 100644
index 000000000..5650ba2e6
--- /dev/null
+++ b/res/drawable/transition_accordion.xml
@@ -0,0 +1,54 @@
+<animation-list
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/transition_accordian" android:oneshot="false">
+ <item android:drawable="@drawable/acordian_00000" android:duration="30" />
+ <item android:drawable="@drawable/acordian_00001" android:duration="30" />
+ <item android:drawable="@drawable/acordian_00002" android:duration="30" />
+ <item android:drawable="@drawable/acordian_00003" android:duration="30" />
+ <item android:drawable="@drawable/acordian_00004" android:duration="30" />
+ <item android:drawable="@drawable/acordian_00005" android:duration="30" />
+ <item android:drawable="@drawable/acordian_00006" android:duration="30" />
+ <item android:drawable="@drawable/acordian_00007" android:duration="30" />
+ <item android:drawable="@drawable/acordian_00008" android:duration="30" />
+ <item android:drawable="@drawable/acordian_00009" android:duration="30" />
+ <item android:drawable="@drawable/acordian_00010" android:duration="30" />
+ <item android:drawable="@drawable/acordian_00011" android:duration="30" />
+ <item android:drawable="@drawable/acordian_00012" android:duration="30" />
+ <item android:drawable="@drawable/acordian_00013" android:duration="30" />
+ <item android:drawable="@drawable/acordian_00014" android:duration="30" />
+ <item android:drawable="@drawable/acordian_00015" android:duration="30" />
+ <item android:drawable="@drawable/acordian_00016" android:duration="30" />
+ <item android:drawable="@drawable/acordian_00017" android:duration="30" />
+ <item android:drawable="@drawable/acordian_00018" android:duration="30" />
+ <item android:drawable="@drawable/acordian_00019" android:duration="30" />
+ <item android:drawable="@drawable/acordian_00020" android:duration="30" />
+ <item android:drawable="@drawable/acordian_00021" android:duration="30" />
+ <item android:drawable="@drawable/acordian_00022" android:duration="30" />
+ <item android:drawable="@drawable/acordian_00023" android:duration="30" />
+ <item android:drawable="@drawable/acordian_00024" android:duration="30" />
+ <item android:drawable="@drawable/acordian_00025" android:duration="30" />
+ <item android:drawable="@drawable/acordian_00026" android:duration="30" />
+ <item android:drawable="@drawable/acordian_00027" android:duration="30" />
+ <item android:drawable="@drawable/acordian_00028" android:duration="30" />
+ <item android:drawable="@drawable/acordian_00029" android:duration="30" />
+ <item android:drawable="@drawable/acordian_00030" android:duration="30" />
+ <item android:drawable="@drawable/acordian_00031" android:duration="30" />
+ <item android:drawable="@drawable/acordian_00032" android:duration="30" />
+ <item android:drawable="@drawable/acordian_00033" android:duration="30" />
+ <item android:drawable="@drawable/acordian_00034" android:duration="30" />
+ <item android:drawable="@drawable/acordian_00035" android:duration="30" />
+ <item android:drawable="@drawable/acordian_00036" android:duration="30" />
+ <item android:drawable="@drawable/acordian_00037" android:duration="30" />
+ <item android:drawable="@drawable/acordian_00038" android:duration="30" />
+ <item android:drawable="@drawable/acordian_00039" android:duration="30" />
+ <item android:drawable="@drawable/acordian_00040" android:duration="30" />
+ <item android:drawable="@drawable/acordian_00041" android:duration="30" />
+ <item android:drawable="@drawable/acordian_00042" android:duration="30" />
+ <item android:drawable="@drawable/acordian_00043" android:duration="30" />
+ <item android:drawable="@drawable/acordian_00044" android:duration="30" />
+ <item android:drawable="@drawable/acordian_00045" android:duration="30" />
+ <item android:drawable="@drawable/acordian_00046" android:duration="30" />
+ <item android:drawable="@drawable/acordian_00047" android:duration="30" />
+ <item android:drawable="@drawable/acordian_00048" android:duration="30" />
+ <item android:drawable="@drawable/acordian_00049" android:duration="30" />
+</animation-list>
diff --git a/res/drawable/transition_arrow.xml b/res/drawable/transition_arrow.xml
new file mode 100644
index 000000000..540db93d8
--- /dev/null
+++ b/res/drawable/transition_arrow.xml
@@ -0,0 +1,21 @@
+<animation-list
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/transition_arrow" android:oneshot="true">
+ <item android:drawable="@drawable/launcheranimatedarrow_00000" android:duration="30" />
+ <item android:drawable="@drawable/launcheranimatedarrow_00001" android:duration="30" />
+ <item android:drawable="@drawable/launcheranimatedarrow_00002" android:duration="30" />
+ <item android:drawable="@drawable/launcheranimatedarrow_00003" android:duration="30" />
+ <item android:drawable="@drawable/launcheranimatedarrow_00004" android:duration="30" />
+ <item android:drawable="@drawable/launcheranimatedarrow_00005" android:duration="30" />
+ <item android:drawable="@drawable/launcheranimatedarrow_00006" android:duration="30" />
+ <item android:drawable="@drawable/launcheranimatedarrow_00007" android:duration="30" />
+ <item android:drawable="@drawable/launcheranimatedarrow_00008" android:duration="30" />
+ <item android:drawable="@drawable/launcheranimatedarrow_00009" android:duration="30" />
+ <item android:drawable="@drawable/launcheranimatedarrow_00010" android:duration="30" />
+ <item android:drawable="@drawable/launcheranimatedarrow_00011" android:duration="30" />
+ <item android:drawable="@drawable/launcheranimatedarrow_00012" android:duration="30" />
+ <item android:drawable="@drawable/launcheranimatedarrow_00013" android:duration="30" />
+ <item android:drawable="@drawable/launcheranimatedarrow_00014" android:duration="30" />
+ <item android:drawable="@drawable/launcheranimatedarrow_00015" android:duration="30" />
+ <item android:drawable="@drawable/launcheranimatedarrow_00016" android:duration="30" />
+</animation-list>
diff --git a/res/drawable/transition_arrow_reverse.xml b/res/drawable/transition_arrow_reverse.xml
new file mode 100644
index 000000000..855f08fb4
--- /dev/null
+++ b/res/drawable/transition_arrow_reverse.xml
@@ -0,0 +1,21 @@
+<animation-list
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/transition_arrow_reverse" android:oneshot="true">
+ <item android:drawable="@drawable/launcheranimatedarrow_00016" android:duration="30" />
+ <item android:drawable="@drawable/launcheranimatedarrow_00015" android:duration="30" />
+ <item android:drawable="@drawable/launcheranimatedarrow_00014" android:duration="30" />
+ <item android:drawable="@drawable/launcheranimatedarrow_00013" android:duration="30" />
+ <item android:drawable="@drawable/launcheranimatedarrow_00012" android:duration="30" />
+ <item android:drawable="@drawable/launcheranimatedarrow_00011" android:duration="30" />
+ <item android:drawable="@drawable/launcheranimatedarrow_00010" android:duration="30" />
+ <item android:drawable="@drawable/launcheranimatedarrow_00009" android:duration="30" />
+ <item android:drawable="@drawable/launcheranimatedarrow_00008" android:duration="30" />
+ <item android:drawable="@drawable/launcheranimatedarrow_00007" android:duration="30" />
+ <item android:drawable="@drawable/launcheranimatedarrow_00006" android:duration="30" />
+ <item android:drawable="@drawable/launcheranimatedarrow_00005" android:duration="30" />
+ <item android:drawable="@drawable/launcheranimatedarrow_00004" android:duration="30" />
+ <item android:drawable="@drawable/launcheranimatedarrow_00003" android:duration="30" />
+ <item android:drawable="@drawable/launcheranimatedarrow_00002" android:duration="30" />
+ <item android:drawable="@drawable/launcheranimatedarrow_00001" android:duration="30" />
+ <item android:drawable="@drawable/launcheranimatedarrow_00000" android:duration="30" />
+</animation-list>
diff --git a/res/drawable/transition_carousel.xml b/res/drawable/transition_carousel.xml
new file mode 100644
index 000000000..bebb5c006
--- /dev/null
+++ b/res/drawable/transition_carousel.xml
@@ -0,0 +1,55 @@
+<animation-list
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/transition_carousel" android:oneshot="false">
+ <item android:drawable="@drawable/carousel_00000" android:duration="30" />
+ <item android:drawable="@drawable/carousel_00001" android:duration="30" />
+ <item android:drawable="@drawable/carousel_00002" android:duration="30" />
+ <item android:drawable="@drawable/carousel_00003" android:duration="30" />
+ <item android:drawable="@drawable/carousel_00004" android:duration="30" />
+ <item android:drawable="@drawable/carousel_00005" android:duration="30" />
+ <item android:drawable="@drawable/carousel_00006" android:duration="30" />
+ <item android:drawable="@drawable/carousel_00007" android:duration="30" />
+ <item android:drawable="@drawable/carousel_00008" android:duration="30" />
+ <item android:drawable="@drawable/carousel_00009" android:duration="30" />
+ <item android:drawable="@drawable/carousel_00010" android:duration="30" />
+ <item android:drawable="@drawable/carousel_00011" android:duration="30" />
+ <item android:drawable="@drawable/carousel_00012" android:duration="30" />
+ <item android:drawable="@drawable/carousel_00013" android:duration="30" />
+ <item android:drawable="@drawable/carousel_00014" android:duration="30" />
+ <item android:drawable="@drawable/carousel_00015" android:duration="30" />
+ <item android:drawable="@drawable/carousel_00016" android:duration="30" />
+ <item android:drawable="@drawable/carousel_00017" android:duration="30" />
+ <item android:drawable="@drawable/carousel_00018" android:duration="30" />
+ <item android:drawable="@drawable/carousel_00019" android:duration="30" />
+ <item android:drawable="@drawable/carousel_00020" android:duration="30" />
+ <item android:drawable="@drawable/carousel_00021" android:duration="30" />
+ <item android:drawable="@drawable/carousel_00022" android:duration="30" />
+ <item android:drawable="@drawable/carousel_00023" android:duration="30" />
+ <item android:drawable="@drawable/carousel_00024" android:duration="30" />
+ <item android:drawable="@drawable/carousel_00025" android:duration="30" />
+ <item android:drawable="@drawable/carousel_00026" android:duration="30" />
+ <item android:drawable="@drawable/carousel_00027" android:duration="30" />
+ <item android:drawable="@drawable/carousel_00028" android:duration="30" />
+ <item android:drawable="@drawable/carousel_00029" android:duration="30" />
+ <item android:drawable="@drawable/carousel_00030" android:duration="30" />
+ <item android:drawable="@drawable/carousel_00031" android:duration="30" />
+ <item android:drawable="@drawable/carousel_00032" android:duration="30" />
+ <item android:drawable="@drawable/carousel_00033" android:duration="30" />
+ <item android:drawable="@drawable/carousel_00034" android:duration="30" />
+ <item android:drawable="@drawable/carousel_00035" android:duration="30" />
+ <item android:drawable="@drawable/carousel_00036" android:duration="30" />
+ <item android:drawable="@drawable/carousel_00037" android:duration="30" />
+ <item android:drawable="@drawable/carousel_00038" android:duration="30" />
+ <item android:drawable="@drawable/carousel_00039" android:duration="30" />
+ <item android:drawable="@drawable/carousel_00040" android:duration="30" />
+ <item android:drawable="@drawable/carousel_00041" android:duration="30" />
+ <item android:drawable="@drawable/carousel_00042" android:duration="30" />
+ <item android:drawable="@drawable/carousel_00043" android:duration="30" />
+ <item android:drawable="@drawable/carousel_00044" android:duration="30" />
+ <item android:drawable="@drawable/carousel_00045" android:duration="30" />
+ <item android:drawable="@drawable/carousel_00046" android:duration="30" />
+ <item android:drawable="@drawable/carousel_00047" android:duration="30" />
+ <item android:drawable="@drawable/carousel_00048" android:duration="30" />
+ <item android:drawable="@drawable/carousel_00049" android:duration="30" />
+ <item android:drawable="@drawable/carousel_00049" android:duration="30" />
+</animation-list>
diff --git a/res/drawable/transition_cubein.xml b/res/drawable/transition_cubein.xml
new file mode 100644
index 000000000..b5a9321f3
--- /dev/null
+++ b/res/drawable/transition_cubein.xml
@@ -0,0 +1,55 @@
+<animation-list
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/transition_cubein" android:oneshot="false">
+ <item android:drawable="@drawable/cubein_00000" android:duration="30" />
+ <item android:drawable="@drawable/cubein_00001" android:duration="30" />
+ <item android:drawable="@drawable/cubein_00002" android:duration="30" />
+ <item android:drawable="@drawable/cubein_00003" android:duration="30" />
+ <item android:drawable="@drawable/cubein_00004" android:duration="30" />
+ <item android:drawable="@drawable/cubein_00005" android:duration="30" />
+ <item android:drawable="@drawable/cubein_00006" android:duration="30" />
+ <item android:drawable="@drawable/cubein_00007" android:duration="30" />
+ <item android:drawable="@drawable/cubein_00008" android:duration="30" />
+ <item android:drawable="@drawable/cubein_00009" android:duration="30" />
+ <item android:drawable="@drawable/cubein_00010" android:duration="30" />
+ <item android:drawable="@drawable/cubein_00011" android:duration="30" />
+ <item android:drawable="@drawable/cubein_00012" android:duration="30" />
+ <item android:drawable="@drawable/cubein_00013" android:duration="30" />
+ <item android:drawable="@drawable/cubein_00014" android:duration="30" />
+ <item android:drawable="@drawable/cubein_00015" android:duration="30" />
+ <item android:drawable="@drawable/cubein_00016" android:duration="30" />
+ <item android:drawable="@drawable/cubein_00017" android:duration="30" />
+ <item android:drawable="@drawable/cubein_00018" android:duration="30" />
+ <item android:drawable="@drawable/cubein_00019" android:duration="30" />
+ <item android:drawable="@drawable/cubein_00020" android:duration="30" />
+ <item android:drawable="@drawable/cubein_00021" android:duration="30" />
+ <item android:drawable="@drawable/cubein_00022" android:duration="30" />
+ <item android:drawable="@drawable/cubein_00023" android:duration="30" />
+ <item android:drawable="@drawable/cubein_00024" android:duration="30" />
+ <item android:drawable="@drawable/cubein_00025" android:duration="30" />
+ <item android:drawable="@drawable/cubein_00026" android:duration="30" />
+ <item android:drawable="@drawable/cubein_00027" android:duration="30" />
+ <item android:drawable="@drawable/cubein_00028" android:duration="30" />
+ <item android:drawable="@drawable/cubein_00029" android:duration="30" />
+ <item android:drawable="@drawable/cubein_00030" android:duration="30" />
+ <item android:drawable="@drawable/cubein_00031" android:duration="30" />
+ <item android:drawable="@drawable/cubein_00032" android:duration="30" />
+ <item android:drawable="@drawable/cubein_00033" android:duration="30" />
+ <item android:drawable="@drawable/cubein_00034" android:duration="30" />
+ <item android:drawable="@drawable/cubein_00035" android:duration="30" />
+ <item android:drawable="@drawable/cubein_00036" android:duration="30" />
+ <item android:drawable="@drawable/cubein_00037" android:duration="30" />
+ <item android:drawable="@drawable/cubein_00038" android:duration="30" />
+ <item android:drawable="@drawable/cubein_00039" android:duration="30" />
+ <item android:drawable="@drawable/cubein_00040" android:duration="30" />
+ <item android:drawable="@drawable/cubein_00041" android:duration="30" />
+ <item android:drawable="@drawable/cubein_00042" android:duration="30" />
+ <item android:drawable="@drawable/cubein_00043" android:duration="30" />
+ <item android:drawable="@drawable/cubein_00044" android:duration="30" />
+ <item android:drawable="@drawable/cubein_00045" android:duration="30" />
+ <item android:drawable="@drawable/cubein_00046" android:duration="30" />
+ <item android:drawable="@drawable/cubein_00047" android:duration="30" />
+ <item android:drawable="@drawable/cubein_00048" android:duration="30" />
+ <item android:drawable="@drawable/cubein_00049" android:duration="30" />
+ <item android:drawable="@drawable/cubein_00049" android:duration="30" />
+</animation-list>
diff --git a/res/drawable/transition_cubeout.xml b/res/drawable/transition_cubeout.xml
new file mode 100644
index 000000000..c8694bb6f
--- /dev/null
+++ b/res/drawable/transition_cubeout.xml
@@ -0,0 +1,55 @@
+<animation-list
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/transition_cubeout" android:oneshot="false">
+ <item android:drawable="@drawable/cubeout_00000" android:duration="30" />
+ <item android:drawable="@drawable/cubeout_00001" android:duration="30" />
+ <item android:drawable="@drawable/cubeout_00002" android:duration="30" />
+ <item android:drawable="@drawable/cubeout_00003" android:duration="30" />
+ <item android:drawable="@drawable/cubeout_00004" android:duration="30" />
+ <item android:drawable="@drawable/cubeout_00005" android:duration="30" />
+ <item android:drawable="@drawable/cubeout_00006" android:duration="30" />
+ <item android:drawable="@drawable/cubeout_00007" android:duration="30" />
+ <item android:drawable="@drawable/cubeout_00008" android:duration="30" />
+ <item android:drawable="@drawable/cubeout_00009" android:duration="30" />
+ <item android:drawable="@drawable/cubeout_00010" android:duration="30" />
+ <item android:drawable="@drawable/cubeout_00011" android:duration="30" />
+ <item android:drawable="@drawable/cubeout_00012" android:duration="30" />
+ <item android:drawable="@drawable/cubeout_00013" android:duration="30" />
+ <item android:drawable="@drawable/cubeout_00014" android:duration="30" />
+ <item android:drawable="@drawable/cubeout_00015" android:duration="30" />
+ <item android:drawable="@drawable/cubeout_00016" android:duration="30" />
+ <item android:drawable="@drawable/cubeout_00017" android:duration="30" />
+ <item android:drawable="@drawable/cubeout_00018" android:duration="30" />
+ <item android:drawable="@drawable/cubeout_00019" android:duration="30" />
+ <item android:drawable="@drawable/cubeout_00020" android:duration="30" />
+ <item android:drawable="@drawable/cubeout_00021" android:duration="30" />
+ <item android:drawable="@drawable/cubeout_00022" android:duration="30" />
+ <item android:drawable="@drawable/cubeout_00023" android:duration="30" />
+ <item android:drawable="@drawable/cubeout_00024" android:duration="30" />
+ <item android:drawable="@drawable/cubeout_00025" android:duration="30" />
+ <item android:drawable="@drawable/cubeout_00026" android:duration="30" />
+ <item android:drawable="@drawable/cubeout_00027" android:duration="30" />
+ <item android:drawable="@drawable/cubeout_00028" android:duration="30" />
+ <item android:drawable="@drawable/cubeout_00029" android:duration="30" />
+ <item android:drawable="@drawable/cubeout_00030" android:duration="30" />
+ <item android:drawable="@drawable/cubeout_00031" android:duration="30" />
+ <item android:drawable="@drawable/cubeout_00032" android:duration="30" />
+ <item android:drawable="@drawable/cubeout_00033" android:duration="30" />
+ <item android:drawable="@drawable/cubeout_00034" android:duration="30" />
+ <item android:drawable="@drawable/cubeout_00035" android:duration="30" />
+ <item android:drawable="@drawable/cubeout_00036" android:duration="30" />
+ <item android:drawable="@drawable/cubeout_00037" android:duration="30" />
+ <item android:drawable="@drawable/cubeout_00038" android:duration="30" />
+ <item android:drawable="@drawable/cubeout_00039" android:duration="30" />
+ <item android:drawable="@drawable/cubeout_00040" android:duration="30" />
+ <item android:drawable="@drawable/cubeout_00041" android:duration="30" />
+ <item android:drawable="@drawable/cubeout_00042" android:duration="30" />
+ <item android:drawable="@drawable/cubeout_00043" android:duration="30" />
+ <item android:drawable="@drawable/cubeout_00044" android:duration="30" />
+ <item android:drawable="@drawable/cubeout_00045" android:duration="30" />
+ <item android:drawable="@drawable/cubeout_00046" android:duration="30" />
+ <item android:drawable="@drawable/cubeout_00047" android:duration="30" />
+ <item android:drawable="@drawable/cubeout_00048" android:duration="30" />
+ <item android:drawable="@drawable/cubeout_00049" android:duration="30" />
+ <item android:drawable="@drawable/cubeout_00049" android:duration="30" />
+</animation-list>
diff --git a/res/drawable/transition_cylinderin.xml b/res/drawable/transition_cylinderin.xml
new file mode 100644
index 000000000..e51d32e9c
--- /dev/null
+++ b/res/drawable/transition_cylinderin.xml
@@ -0,0 +1,55 @@
+<animation-list
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/transition_cylinderin" android:oneshot="false">
+ <item android:drawable="@drawable/cylinderin_00000" android:duration="30" />
+ <item android:drawable="@drawable/cylinderin_00001" android:duration="30" />
+ <item android:drawable="@drawable/cylinderin_00002" android:duration="30" />
+ <item android:drawable="@drawable/cylinderin_00003" android:duration="30" />
+ <item android:drawable="@drawable/cylinderin_00004" android:duration="30" />
+ <item android:drawable="@drawable/cylinderin_00005" android:duration="30" />
+ <item android:drawable="@drawable/cylinderin_00006" android:duration="30" />
+ <item android:drawable="@drawable/cylinderin_00007" android:duration="30" />
+ <item android:drawable="@drawable/cylinderin_00008" android:duration="30" />
+ <item android:drawable="@drawable/cylinderin_00009" android:duration="30" />
+ <item android:drawable="@drawable/cylinderin_00010" android:duration="30" />
+ <item android:drawable="@drawable/cylinderin_00011" android:duration="30" />
+ <item android:drawable="@drawable/cylinderin_00012" android:duration="30" />
+ <item android:drawable="@drawable/cylinderin_00013" android:duration="30" />
+ <item android:drawable="@drawable/cylinderin_00014" android:duration="30" />
+ <item android:drawable="@drawable/cylinderin_00015" android:duration="30" />
+ <item android:drawable="@drawable/cylinderin_00016" android:duration="30" />
+ <item android:drawable="@drawable/cylinderin_00017" android:duration="30" />
+ <item android:drawable="@drawable/cylinderin_00018" android:duration="30" />
+ <item android:drawable="@drawable/cylinderin_00019" android:duration="30" />
+ <item android:drawable="@drawable/cylinderin_00020" android:duration="30" />
+ <item android:drawable="@drawable/cylinderin_00021" android:duration="30" />
+ <item android:drawable="@drawable/cylinderin_00022" android:duration="30" />
+ <item android:drawable="@drawable/cylinderin_00023" android:duration="30" />
+ <item android:drawable="@drawable/cylinderin_00024" android:duration="30" />
+ <item android:drawable="@drawable/cylinderin_00025" android:duration="30" />
+ <item android:drawable="@drawable/cylinderin_00026" android:duration="30" />
+ <item android:drawable="@drawable/cylinderin_00027" android:duration="30" />
+ <item android:drawable="@drawable/cylinderin_00028" android:duration="30" />
+ <item android:drawable="@drawable/cylinderin_00029" android:duration="30" />
+ <item android:drawable="@drawable/cylinderin_00030" android:duration="30" />
+ <item android:drawable="@drawable/cylinderin_00031" android:duration="30" />
+ <item android:drawable="@drawable/cylinderin_00032" android:duration="30" />
+ <item android:drawable="@drawable/cylinderin_00033" android:duration="30" />
+ <item android:drawable="@drawable/cylinderin_00034" android:duration="30" />
+ <item android:drawable="@drawable/cylinderin_00035" android:duration="30" />
+ <item android:drawable="@drawable/cylinderin_00036" android:duration="30" />
+ <item android:drawable="@drawable/cylinderin_00037" android:duration="30" />
+ <item android:drawable="@drawable/cylinderin_00038" android:duration="30" />
+ <item android:drawable="@drawable/cylinderin_00039" android:duration="30" />
+ <item android:drawable="@drawable/cylinderin_00040" android:duration="30" />
+ <item android:drawable="@drawable/cylinderin_00041" android:duration="30" />
+ <item android:drawable="@drawable/cylinderin_00042" android:duration="30" />
+ <item android:drawable="@drawable/cylinderin_00043" android:duration="30" />
+ <item android:drawable="@drawable/cylinderin_00044" android:duration="30" />
+ <item android:drawable="@drawable/cylinderin_00045" android:duration="30" />
+ <item android:drawable="@drawable/cylinderin_00046" android:duration="30" />
+ <item android:drawable="@drawable/cylinderin_00047" android:duration="30" />
+ <item android:drawable="@drawable/cylinderin_00048" android:duration="30" />
+ <item android:drawable="@drawable/cylinderin_00049" android:duration="30" />
+ <item android:drawable="@drawable/cylinderin_00049" android:duration="30" />
+</animation-list>
diff --git a/res/drawable/transition_cylinderout.xml b/res/drawable/transition_cylinderout.xml
new file mode 100644
index 000000000..451964ee2
--- /dev/null
+++ b/res/drawable/transition_cylinderout.xml
@@ -0,0 +1,55 @@
+<animation-list
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/transition_cylinderout" android:oneshot="false">
+ <item android:drawable="@drawable/cylinderout_00000" android:duration="30" />
+ <item android:drawable="@drawable/cylinderout_00001" android:duration="30" />
+ <item android:drawable="@drawable/cylinderout_00002" android:duration="30" />
+ <item android:drawable="@drawable/cylinderout_00003" android:duration="30" />
+ <item android:drawable="@drawable/cylinderout_00004" android:duration="30" />
+ <item android:drawable="@drawable/cylinderout_00005" android:duration="30" />
+ <item android:drawable="@drawable/cylinderout_00006" android:duration="30" />
+ <item android:drawable="@drawable/cylinderout_00007" android:duration="30" />
+ <item android:drawable="@drawable/cylinderout_00008" android:duration="30" />
+ <item android:drawable="@drawable/cylinderout_00009" android:duration="30" />
+ <item android:drawable="@drawable/cylinderout_00010" android:duration="30" />
+ <item android:drawable="@drawable/cylinderout_00011" android:duration="30" />
+ <item android:drawable="@drawable/cylinderout_00012" android:duration="30" />
+ <item android:drawable="@drawable/cylinderout_00013" android:duration="30" />
+ <item android:drawable="@drawable/cylinderout_00014" android:duration="30" />
+ <item android:drawable="@drawable/cylinderout_00015" android:duration="30" />
+ <item android:drawable="@drawable/cylinderout_00016" android:duration="30" />
+ <item android:drawable="@drawable/cylinderout_00017" android:duration="30" />
+ <item android:drawable="@drawable/cylinderout_00018" android:duration="30" />
+ <item android:drawable="@drawable/cylinderout_00019" android:duration="30" />
+ <item android:drawable="@drawable/cylinderout_00020" android:duration="30" />
+ <item android:drawable="@drawable/cylinderout_00021" android:duration="30" />
+ <item android:drawable="@drawable/cylinderout_00022" android:duration="30" />
+ <item android:drawable="@drawable/cylinderout_00023" android:duration="30" />
+ <item android:drawable="@drawable/cylinderout_00024" android:duration="30" />
+ <item android:drawable="@drawable/cylinderout_00025" android:duration="30" />
+ <item android:drawable="@drawable/cylinderout_00026" android:duration="30" />
+ <item android:drawable="@drawable/cylinderout_00027" android:duration="30" />
+ <item android:drawable="@drawable/cylinderout_00028" android:duration="30" />
+ <item android:drawable="@drawable/cylinderout_00029" android:duration="30" />
+ <item android:drawable="@drawable/cylinderout_00030" android:duration="30" />
+ <item android:drawable="@drawable/cylinderout_00031" android:duration="30" />
+ <item android:drawable="@drawable/cylinderout_00032" android:duration="30" />
+ <item android:drawable="@drawable/cylinderout_00033" android:duration="30" />
+ <item android:drawable="@drawable/cylinderout_00034" android:duration="30" />
+ <item android:drawable="@drawable/cylinderout_00035" android:duration="30" />
+ <item android:drawable="@drawable/cylinderout_00036" android:duration="30" />
+ <item android:drawable="@drawable/cylinderout_00037" android:duration="30" />
+ <item android:drawable="@drawable/cylinderout_00038" android:duration="30" />
+ <item android:drawable="@drawable/cylinderout_00039" android:duration="30" />
+ <item android:drawable="@drawable/cylinderout_00040" android:duration="30" />
+ <item android:drawable="@drawable/cylinderout_00041" android:duration="30" />
+ <item android:drawable="@drawable/cylinderout_00042" android:duration="30" />
+ <item android:drawable="@drawable/cylinderout_00043" android:duration="30" />
+ <item android:drawable="@drawable/cylinderout_00044" android:duration="30" />
+ <item android:drawable="@drawable/cylinderout_00045" android:duration="30" />
+ <item android:drawable="@drawable/cylinderout_00046" android:duration="30" />
+ <item android:drawable="@drawable/cylinderout_00047" android:duration="30" />
+ <item android:drawable="@drawable/cylinderout_00048" android:duration="30" />
+ <item android:drawable="@drawable/cylinderout_00049" android:duration="30" />
+ <item android:drawable="@drawable/cylinderout_00049" android:duration="30" />
+</animation-list>
diff --git a/res/drawable/transition_flip.xml b/res/drawable/transition_flip.xml
new file mode 100644
index 000000000..30897202e
--- /dev/null
+++ b/res/drawable/transition_flip.xml
@@ -0,0 +1,55 @@
+<animation-list
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/transition_flip" android:oneshot="false">
+ <item android:drawable="@drawable/flip_00000" android:duration="30" />
+ <item android:drawable="@drawable/flip_00001" android:duration="30" />
+ <item android:drawable="@drawable/flip_00002" android:duration="30" />
+ <item android:drawable="@drawable/flip_00003" android:duration="30" />
+ <item android:drawable="@drawable/flip_00004" android:duration="30" />
+ <item android:drawable="@drawable/flip_00005" android:duration="30" />
+ <item android:drawable="@drawable/flip_00006" android:duration="30" />
+ <item android:drawable="@drawable/flip_00007" android:duration="30" />
+ <item android:drawable="@drawable/flip_00008" android:duration="30" />
+ <item android:drawable="@drawable/flip_00009" android:duration="30" />
+ <item android:drawable="@drawable/flip_00010" android:duration="30" />
+ <item android:drawable="@drawable/flip_00011" android:duration="30" />
+ <item android:drawable="@drawable/flip_00012" android:duration="30" />
+ <item android:drawable="@drawable/flip_00013" android:duration="30" />
+ <item android:drawable="@drawable/flip_00014" android:duration="30" />
+ <item android:drawable="@drawable/flip_00015" android:duration="30" />
+ <item android:drawable="@drawable/flip_00016" android:duration="30" />
+ <item android:drawable="@drawable/flip_00017" android:duration="30" />
+ <item android:drawable="@drawable/flip_00018" android:duration="30" />
+ <item android:drawable="@drawable/flip_00019" android:duration="30" />
+ <item android:drawable="@drawable/flip_00020" android:duration="30" />
+ <item android:drawable="@drawable/flip_00021" android:duration="30" />
+ <item android:drawable="@drawable/flip_00022" android:duration="30" />
+ <item android:drawable="@drawable/flip_00023" android:duration="30" />
+ <item android:drawable="@drawable/flip_00024" android:duration="30" />
+ <item android:drawable="@drawable/flip_00025" android:duration="30" />
+ <item android:drawable="@drawable/flip_00026" android:duration="30" />
+ <item android:drawable="@drawable/flip_00027" android:duration="30" />
+ <item android:drawable="@drawable/flip_00028" android:duration="30" />
+ <item android:drawable="@drawable/flip_00029" android:duration="30" />
+ <item android:drawable="@drawable/flip_00030" android:duration="30" />
+ <item android:drawable="@drawable/flip_00031" android:duration="30" />
+ <item android:drawable="@drawable/flip_00032" android:duration="30" />
+ <item android:drawable="@drawable/flip_00033" android:duration="30" />
+ <item android:drawable="@drawable/flip_00034" android:duration="30" />
+ <item android:drawable="@drawable/flip_00035" android:duration="30" />
+ <item android:drawable="@drawable/flip_00036" android:duration="30" />
+ <item android:drawable="@drawable/flip_00037" android:duration="30" />
+ <item android:drawable="@drawable/flip_00038" android:duration="30" />
+ <item android:drawable="@drawable/flip_00039" android:duration="30" />
+ <item android:drawable="@drawable/flip_00040" android:duration="30" />
+ <item android:drawable="@drawable/flip_00041" android:duration="30" />
+ <item android:drawable="@drawable/flip_00042" android:duration="30" />
+ <item android:drawable="@drawable/flip_00043" android:duration="30" />
+ <item android:drawable="@drawable/flip_00044" android:duration="30" />
+ <item android:drawable="@drawable/flip_00045" android:duration="30" />
+ <item android:drawable="@drawable/flip_00046" android:duration="30" />
+ <item android:drawable="@drawable/flip_00047" android:duration="30" />
+ <item android:drawable="@drawable/flip_00048" android:duration="30" />
+ <item android:drawable="@drawable/flip_00049" android:duration="30" />
+ <item android:drawable="@drawable/flip_00049" android:duration="30" />
+</animation-list>
diff --git a/res/drawable/transition_none.xml b/res/drawable/transition_none.xml
new file mode 100644
index 000000000..e357939b5
--- /dev/null
+++ b/res/drawable/transition_none.xml
@@ -0,0 +1,55 @@
+<animation-list
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/transition_none" android:oneshot="false">
+ <item android:drawable="@drawable/none_00000" android:duration="30" />
+ <item android:drawable="@drawable/none_00001" android:duration="30" />
+ <item android:drawable="@drawable/none_00002" android:duration="30" />
+ <item android:drawable="@drawable/none_00003" android:duration="30" />
+ <item android:drawable="@drawable/none_00004" android:duration="30" />
+ <item android:drawable="@drawable/none_00005" android:duration="30" />
+ <item android:drawable="@drawable/none_00006" android:duration="30" />
+ <item android:drawable="@drawable/none_00007" android:duration="30" />
+ <item android:drawable="@drawable/none_00008" android:duration="30" />
+ <item android:drawable="@drawable/none_00009" android:duration="30" />
+ <item android:drawable="@drawable/none_00010" android:duration="30" />
+ <item android:drawable="@drawable/none_00011" android:duration="30" />
+ <item android:drawable="@drawable/none_00012" android:duration="30" />
+ <item android:drawable="@drawable/none_00013" android:duration="30" />
+ <item android:drawable="@drawable/none_00014" android:duration="30" />
+ <item android:drawable="@drawable/none_00015" android:duration="30" />
+ <item android:drawable="@drawable/none_00016" android:duration="30" />
+ <item android:drawable="@drawable/none_00017" android:duration="30" />
+ <item android:drawable="@drawable/none_00018" android:duration="30" />
+ <item android:drawable="@drawable/none_00019" android:duration="30" />
+ <item android:drawable="@drawable/none_00020" android:duration="30" />
+ <item android:drawable="@drawable/none_00021" android:duration="30" />
+ <item android:drawable="@drawable/none_00022" android:duration="30" />
+ <item android:drawable="@drawable/none_00023" android:duration="30" />
+ <item android:drawable="@drawable/none_00024" android:duration="30" />
+ <item android:drawable="@drawable/none_00025" android:duration="30" />
+ <item android:drawable="@drawable/none_00026" android:duration="30" />
+ <item android:drawable="@drawable/none_00027" android:duration="30" />
+ <item android:drawable="@drawable/none_00028" android:duration="30" />
+ <item android:drawable="@drawable/none_00029" android:duration="30" />
+ <item android:drawable="@drawable/none_00030" android:duration="30" />
+ <item android:drawable="@drawable/none_00031" android:duration="30" />
+ <item android:drawable="@drawable/none_00032" android:duration="30" />
+ <item android:drawable="@drawable/none_00033" android:duration="30" />
+ <item android:drawable="@drawable/none_00034" android:duration="30" />
+ <item android:drawable="@drawable/none_00035" android:duration="30" />
+ <item android:drawable="@drawable/none_00036" android:duration="30" />
+ <item android:drawable="@drawable/none_00037" android:duration="30" />
+ <item android:drawable="@drawable/none_00038" android:duration="30" />
+ <item android:drawable="@drawable/none_00039" android:duration="30" />
+ <item android:drawable="@drawable/none_00040" android:duration="30" />
+ <item android:drawable="@drawable/none_00041" android:duration="30" />
+ <item android:drawable="@drawable/none_00042" android:duration="30" />
+ <item android:drawable="@drawable/none_00043" android:duration="30" />
+ <item android:drawable="@drawable/none_00044" android:duration="30" />
+ <item android:drawable="@drawable/none_00045" android:duration="30" />
+ <item android:drawable="@drawable/none_00046" android:duration="30" />
+ <item android:drawable="@drawable/none_00047" android:duration="30" />
+ <item android:drawable="@drawable/none_00048" android:duration="30" />
+ <item android:drawable="@drawable/none_00049" android:duration="30" />
+ <item android:drawable="@drawable/none_00049" android:duration="30" />
+</animation-list>
diff --git a/res/drawable/transition_overview.xml b/res/drawable/transition_overview.xml
new file mode 100644
index 000000000..47dac7d92
--- /dev/null
+++ b/res/drawable/transition_overview.xml
@@ -0,0 +1,55 @@
+<animation-list
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/transition_overview" android:oneshot="false">
+ <item android:drawable="@drawable/overview_00000" android:duration="30" />
+ <item android:drawable="@drawable/overview_00001" android:duration="30" />
+ <item android:drawable="@drawable/overview_00002" android:duration="30" />
+ <item android:drawable="@drawable/overview_00003" android:duration="30" />
+ <item android:drawable="@drawable/overview_00004" android:duration="30" />
+ <item android:drawable="@drawable/overview_00005" android:duration="30" />
+ <item android:drawable="@drawable/overview_00006" android:duration="30" />
+ <item android:drawable="@drawable/overview_00007" android:duration="30" />
+ <item android:drawable="@drawable/overview_00008" android:duration="30" />
+ <item android:drawable="@drawable/overview_00009" android:duration="30" />
+ <item android:drawable="@drawable/overview_00010" android:duration="30" />
+ <item android:drawable="@drawable/overview_00011" android:duration="30" />
+ <item android:drawable="@drawable/overview_00012" android:duration="30" />
+ <item android:drawable="@drawable/overview_00013" android:duration="30" />
+ <item android:drawable="@drawable/overview_00014" android:duration="30" />
+ <item android:drawable="@drawable/overview_00015" android:duration="30" />
+ <item android:drawable="@drawable/overview_00016" android:duration="30" />
+ <item android:drawable="@drawable/overview_00017" android:duration="30" />
+ <item android:drawable="@drawable/overview_00018" android:duration="30" />
+ <item android:drawable="@drawable/overview_00019" android:duration="30" />
+ <item android:drawable="@drawable/overview_00020" android:duration="30" />
+ <item android:drawable="@drawable/overview_00021" android:duration="30" />
+ <item android:drawable="@drawable/overview_00022" android:duration="30" />
+ <item android:drawable="@drawable/overview_00023" android:duration="30" />
+ <item android:drawable="@drawable/overview_00024" android:duration="30" />
+ <item android:drawable="@drawable/overview_00025" android:duration="30" />
+ <item android:drawable="@drawable/overview_00026" android:duration="30" />
+ <item android:drawable="@drawable/overview_00027" android:duration="30" />
+ <item android:drawable="@drawable/overview_00028" android:duration="30" />
+ <item android:drawable="@drawable/overview_00029" android:duration="30" />
+ <item android:drawable="@drawable/overview_00030" android:duration="30" />
+ <item android:drawable="@drawable/overview_00031" android:duration="30" />
+ <item android:drawable="@drawable/overview_00032" android:duration="30" />
+ <item android:drawable="@drawable/overview_00033" android:duration="30" />
+ <item android:drawable="@drawable/overview_00034" android:duration="30" />
+ <item android:drawable="@drawable/overview_00035" android:duration="30" />
+ <item android:drawable="@drawable/overview_00036" android:duration="30" />
+ <item android:drawable="@drawable/overview_00037" android:duration="30" />
+ <item android:drawable="@drawable/overview_00038" android:duration="30" />
+ <item android:drawable="@drawable/overview_00039" android:duration="30" />
+ <item android:drawable="@drawable/overview_00040" android:duration="30" />
+ <item android:drawable="@drawable/overview_00041" android:duration="30" />
+ <item android:drawable="@drawable/overview_00042" android:duration="30" />
+ <item android:drawable="@drawable/overview_00043" android:duration="30" />
+ <item android:drawable="@drawable/overview_00044" android:duration="30" />
+ <item android:drawable="@drawable/overview_00045" android:duration="30" />
+ <item android:drawable="@drawable/overview_00046" android:duration="30" />
+ <item android:drawable="@drawable/overview_00047" android:duration="30" />
+ <item android:drawable="@drawable/overview_00048" android:duration="30" />
+ <item android:drawable="@drawable/overview_00049" android:duration="30" />
+ <item android:drawable="@drawable/overview_00049" android:duration="30" />
+</animation-list>
diff --git a/res/drawable/transition_rotatedown.xml b/res/drawable/transition_rotatedown.xml
new file mode 100644
index 000000000..f05f71003
--- /dev/null
+++ b/res/drawable/transition_rotatedown.xml
@@ -0,0 +1,55 @@
+<animation-list
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/transition_rotatedown" android:oneshot="false">
+ <item android:drawable="@drawable/rotatedown_00000" android:duration="30" />
+ <item android:drawable="@drawable/rotatedown_00001" android:duration="30" />
+ <item android:drawable="@drawable/rotatedown_00002" android:duration="30" />
+ <item android:drawable="@drawable/rotatedown_00003" android:duration="30" />
+ <item android:drawable="@drawable/rotatedown_00004" android:duration="30" />
+ <item android:drawable="@drawable/rotatedown_00005" android:duration="30" />
+ <item android:drawable="@drawable/rotatedown_00006" android:duration="30" />
+ <item android:drawable="@drawable/rotatedown_00007" android:duration="30" />
+ <item android:drawable="@drawable/rotatedown_00008" android:duration="30" />
+ <item android:drawable="@drawable/rotatedown_00009" android:duration="30" />
+ <item android:drawable="@drawable/rotatedown_00010" android:duration="30" />
+ <item android:drawable="@drawable/rotatedown_00011" android:duration="30" />
+ <item android:drawable="@drawable/rotatedown_00012" android:duration="30" />
+ <item android:drawable="@drawable/rotatedown_00013" android:duration="30" />
+ <item android:drawable="@drawable/rotatedown_00014" android:duration="30" />
+ <item android:drawable="@drawable/rotatedown_00015" android:duration="30" />
+ <item android:drawable="@drawable/rotatedown_00016" android:duration="30" />
+ <item android:drawable="@drawable/rotatedown_00017" android:duration="30" />
+ <item android:drawable="@drawable/rotatedown_00018" android:duration="30" />
+ <item android:drawable="@drawable/rotatedown_00019" android:duration="30" />
+ <item android:drawable="@drawable/rotatedown_00020" android:duration="30" />
+ <item android:drawable="@drawable/rotatedown_00021" android:duration="30" />
+ <item android:drawable="@drawable/rotatedown_00022" android:duration="30" />
+ <item android:drawable="@drawable/rotatedown_00023" android:duration="30" />
+ <item android:drawable="@drawable/rotatedown_00024" android:duration="30" />
+ <item android:drawable="@drawable/rotatedown_00025" android:duration="30" />
+ <item android:drawable="@drawable/rotatedown_00026" android:duration="30" />
+ <item android:drawable="@drawable/rotatedown_00027" android:duration="30" />
+ <item android:drawable="@drawable/rotatedown_00028" android:duration="30" />
+ <item android:drawable="@drawable/rotatedown_00029" android:duration="30" />
+ <item android:drawable="@drawable/rotatedown_00030" android:duration="30" />
+ <item android:drawable="@drawable/rotatedown_00031" android:duration="30" />
+ <item android:drawable="@drawable/rotatedown_00032" android:duration="30" />
+ <item android:drawable="@drawable/rotatedown_00033" android:duration="30" />
+ <item android:drawable="@drawable/rotatedown_00034" android:duration="30" />
+ <item android:drawable="@drawable/rotatedown_00035" android:duration="30" />
+ <item android:drawable="@drawable/rotatedown_00036" android:duration="30" />
+ <item android:drawable="@drawable/rotatedown_00037" android:duration="30" />
+ <item android:drawable="@drawable/rotatedown_00038" android:duration="30" />
+ <item android:drawable="@drawable/rotatedown_00039" android:duration="30" />
+ <item android:drawable="@drawable/rotatedown_00040" android:duration="30" />
+ <item android:drawable="@drawable/rotatedown_00041" android:duration="30" />
+ <item android:drawable="@drawable/rotatedown_00042" android:duration="30" />
+ <item android:drawable="@drawable/rotatedown_00043" android:duration="30" />
+ <item android:drawable="@drawable/rotatedown_00044" android:duration="30" />
+ <item android:drawable="@drawable/rotatedown_00045" android:duration="30" />
+ <item android:drawable="@drawable/rotatedown_00046" android:duration="30" />
+ <item android:drawable="@drawable/rotatedown_00047" android:duration="30" />
+ <item android:drawable="@drawable/rotatedown_00048" android:duration="30" />
+ <item android:drawable="@drawable/rotatedown_00049" android:duration="30" />
+ <item android:drawable="@drawable/rotatedown_00049" android:duration="30" />
+</animation-list>
diff --git a/res/drawable/transition_rotateup.xml b/res/drawable/transition_rotateup.xml
new file mode 100644
index 000000000..3a2e8fa8e
--- /dev/null
+++ b/res/drawable/transition_rotateup.xml
@@ -0,0 +1,55 @@
+<animation-list
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/transition_rotateup" android:oneshot="false">
+ <item android:drawable="@drawable/rotateup_00000" android:duration="30" />
+ <item android:drawable="@drawable/rotateup_00001" android:duration="30" />
+ <item android:drawable="@drawable/rotateup_00002" android:duration="30" />
+ <item android:drawable="@drawable/rotateup_00003" android:duration="30" />
+ <item android:drawable="@drawable/rotateup_00004" android:duration="30" />
+ <item android:drawable="@drawable/rotateup_00005" android:duration="30" />
+ <item android:drawable="@drawable/rotateup_00006" android:duration="30" />
+ <item android:drawable="@drawable/rotateup_00007" android:duration="30" />
+ <item android:drawable="@drawable/rotateup_00008" android:duration="30" />
+ <item android:drawable="@drawable/rotateup_00009" android:duration="30" />
+ <item android:drawable="@drawable/rotateup_00010" android:duration="30" />
+ <item android:drawable="@drawable/rotateup_00011" android:duration="30" />
+ <item android:drawable="@drawable/rotateup_00012" android:duration="30" />
+ <item android:drawable="@drawable/rotateup_00013" android:duration="30" />
+ <item android:drawable="@drawable/rotateup_00014" android:duration="30" />
+ <item android:drawable="@drawable/rotateup_00015" android:duration="30" />
+ <item android:drawable="@drawable/rotateup_00016" android:duration="30" />
+ <item android:drawable="@drawable/rotateup_00017" android:duration="30" />
+ <item android:drawable="@drawable/rotateup_00018" android:duration="30" />
+ <item android:drawable="@drawable/rotateup_00019" android:duration="30" />
+ <item android:drawable="@drawable/rotateup_00020" android:duration="30" />
+ <item android:drawable="@drawable/rotateup_00021" android:duration="30" />
+ <item android:drawable="@drawable/rotateup_00022" android:duration="30" />
+ <item android:drawable="@drawable/rotateup_00023" android:duration="30" />
+ <item android:drawable="@drawable/rotateup_00024" android:duration="30" />
+ <item android:drawable="@drawable/rotateup_00025" android:duration="30" />
+ <item android:drawable="@drawable/rotateup_00026" android:duration="30" />
+ <item android:drawable="@drawable/rotateup_00027" android:duration="30" />
+ <item android:drawable="@drawable/rotateup_00028" android:duration="30" />
+ <item android:drawable="@drawable/rotateup_00029" android:duration="30" />
+ <item android:drawable="@drawable/rotateup_00030" android:duration="30" />
+ <item android:drawable="@drawable/rotateup_00031" android:duration="30" />
+ <item android:drawable="@drawable/rotateup_00032" android:duration="30" />
+ <item android:drawable="@drawable/rotateup_00033" android:duration="30" />
+ <item android:drawable="@drawable/rotateup_00034" android:duration="30" />
+ <item android:drawable="@drawable/rotateup_00035" android:duration="30" />
+ <item android:drawable="@drawable/rotateup_00036" android:duration="30" />
+ <item android:drawable="@drawable/rotateup_00037" android:duration="30" />
+ <item android:drawable="@drawable/rotateup_00038" android:duration="30" />
+ <item android:drawable="@drawable/rotateup_00039" android:duration="30" />
+ <item android:drawable="@drawable/rotateup_00040" android:duration="30" />
+ <item android:drawable="@drawable/rotateup_00041" android:duration="30" />
+ <item android:drawable="@drawable/rotateup_00042" android:duration="30" />
+ <item android:drawable="@drawable/rotateup_00043" android:duration="30" />
+ <item android:drawable="@drawable/rotateup_00044" android:duration="30" />
+ <item android:drawable="@drawable/rotateup_00045" android:duration="30" />
+ <item android:drawable="@drawable/rotateup_00046" android:duration="30" />
+ <item android:drawable="@drawable/rotateup_00047" android:duration="30" />
+ <item android:drawable="@drawable/rotateup_00048" android:duration="30" />
+ <item android:drawable="@drawable/rotateup_00049" android:duration="30" />
+ <item android:drawable="@drawable/rotateup_00049" android:duration="30" />
+</animation-list>
diff --git a/res/drawable/transition_stack.xml b/res/drawable/transition_stack.xml
new file mode 100644
index 000000000..1483a1bae
--- /dev/null
+++ b/res/drawable/transition_stack.xml
@@ -0,0 +1,55 @@
+<animation-list
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/transition_stack" android:oneshot="false">
+ <item android:drawable="@drawable/stack_00000" android:duration="30" />
+ <item android:drawable="@drawable/stack_00001" android:duration="30" />
+ <item android:drawable="@drawable/stack_00002" android:duration="30" />
+ <item android:drawable="@drawable/stack_00003" android:duration="30" />
+ <item android:drawable="@drawable/stack_00004" android:duration="30" />
+ <item android:drawable="@drawable/stack_00005" android:duration="30" />
+ <item android:drawable="@drawable/stack_00006" android:duration="30" />
+ <item android:drawable="@drawable/stack_00007" android:duration="30" />
+ <item android:drawable="@drawable/stack_00008" android:duration="30" />
+ <item android:drawable="@drawable/stack_00009" android:duration="30" />
+ <item android:drawable="@drawable/stack_00010" android:duration="30" />
+ <item android:drawable="@drawable/stack_00011" android:duration="30" />
+ <item android:drawable="@drawable/stack_00012" android:duration="30" />
+ <item android:drawable="@drawable/stack_00013" android:duration="30" />
+ <item android:drawable="@drawable/stack_00014" android:duration="30" />
+ <item android:drawable="@drawable/stack_00015" android:duration="30" />
+ <item android:drawable="@drawable/stack_00016" android:duration="30" />
+ <item android:drawable="@drawable/stack_00017" android:duration="30" />
+ <item android:drawable="@drawable/stack_00018" android:duration="30" />
+ <item android:drawable="@drawable/stack_00019" android:duration="30" />
+ <item android:drawable="@drawable/stack_00020" android:duration="30" />
+ <item android:drawable="@drawable/stack_00021" android:duration="30" />
+ <item android:drawable="@drawable/stack_00022" android:duration="30" />
+ <item android:drawable="@drawable/stack_00023" android:duration="30" />
+ <item android:drawable="@drawable/stack_00024" android:duration="30" />
+ <item android:drawable="@drawable/stack_00025" android:duration="30" />
+ <item android:drawable="@drawable/stack_00026" android:duration="30" />
+ <item android:drawable="@drawable/stack_00027" android:duration="30" />
+ <item android:drawable="@drawable/stack_00028" android:duration="30" />
+ <item android:drawable="@drawable/stack_00029" android:duration="30" />
+ <item android:drawable="@drawable/stack_00030" android:duration="30" />
+ <item android:drawable="@drawable/stack_00031" android:duration="30" />
+ <item android:drawable="@drawable/stack_00032" android:duration="30" />
+ <item android:drawable="@drawable/stack_00033" android:duration="30" />
+ <item android:drawable="@drawable/stack_00034" android:duration="30" />
+ <item android:drawable="@drawable/stack_00035" android:duration="30" />
+ <item android:drawable="@drawable/stack_00036" android:duration="30" />
+ <item android:drawable="@drawable/stack_00037" android:duration="30" />
+ <item android:drawable="@drawable/stack_00038" android:duration="30" />
+ <item android:drawable="@drawable/stack_00039" android:duration="30" />
+ <item android:drawable="@drawable/stack_00040" android:duration="30" />
+ <item android:drawable="@drawable/stack_00041" android:duration="30" />
+ <item android:drawable="@drawable/stack_00042" android:duration="30" />
+ <item android:drawable="@drawable/stack_00043" android:duration="30" />
+ <item android:drawable="@drawable/stack_00044" android:duration="30" />
+ <item android:drawable="@drawable/stack_00045" android:duration="30" />
+ <item android:drawable="@drawable/stack_00046" android:duration="30" />
+ <item android:drawable="@drawable/stack_00047" android:duration="30" />
+ <item android:drawable="@drawable/stack_00048" android:duration="30" />
+ <item android:drawable="@drawable/stack_00049" android:duration="30" />
+ <item android:drawable="@drawable/stack_00049" android:duration="30" />
+</animation-list>
diff --git a/res/drawable/transition_zoomin.xml b/res/drawable/transition_zoomin.xml
new file mode 100644
index 000000000..cf76e5312
--- /dev/null
+++ b/res/drawable/transition_zoomin.xml
@@ -0,0 +1,55 @@
+<animation-list
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/transition_zoomin" android:oneshot="false">
+ <item android:drawable="@drawable/zoomin_00000" android:duration="30" />
+ <item android:drawable="@drawable/zoomin_00001" android:duration="30" />
+ <item android:drawable="@drawable/zoomin_00002" android:duration="30" />
+ <item android:drawable="@drawable/zoomin_00003" android:duration="30" />
+ <item android:drawable="@drawable/zoomin_00004" android:duration="30" />
+ <item android:drawable="@drawable/zoomin_00005" android:duration="30" />
+ <item android:drawable="@drawable/zoomin_00006" android:duration="30" />
+ <item android:drawable="@drawable/zoomin_00007" android:duration="30" />
+ <item android:drawable="@drawable/zoomin_00008" android:duration="30" />
+ <item android:drawable="@drawable/zoomin_00009" android:duration="30" />
+ <item android:drawable="@drawable/zoomin_00010" android:duration="30" />
+ <item android:drawable="@drawable/zoomin_00011" android:duration="30" />
+ <item android:drawable="@drawable/zoomin_00012" android:duration="30" />
+ <item android:drawable="@drawable/zoomin_00013" android:duration="30" />
+ <item android:drawable="@drawable/zoomin_00014" android:duration="30" />
+ <item android:drawable="@drawable/zoomin_00015" android:duration="30" />
+ <item android:drawable="@drawable/zoomin_00016" android:duration="30" />
+ <item android:drawable="@drawable/zoomin_00017" android:duration="30" />
+ <item android:drawable="@drawable/zoomin_00018" android:duration="30" />
+ <item android:drawable="@drawable/zoomin_00019" android:duration="30" />
+ <item android:drawable="@drawable/zoomin_00020" android:duration="30" />
+ <item android:drawable="@drawable/zoomin_00021" android:duration="30" />
+ <item android:drawable="@drawable/zoomin_00022" android:duration="30" />
+ <item android:drawable="@drawable/zoomin_00023" android:duration="30" />
+ <item android:drawable="@drawable/zoomin_00024" android:duration="30" />
+ <item android:drawable="@drawable/zoomin_00025" android:duration="30" />
+ <item android:drawable="@drawable/zoomin_00026" android:duration="30" />
+ <item android:drawable="@drawable/zoomin_00027" android:duration="30" />
+ <item android:drawable="@drawable/zoomin_00028" android:duration="30" />
+ <item android:drawable="@drawable/zoomin_00029" android:duration="30" />
+ <item android:drawable="@drawable/zoomin_00030" android:duration="30" />
+ <item android:drawable="@drawable/zoomin_00031" android:duration="30" />
+ <item android:drawable="@drawable/zoomin_00032" android:duration="30" />
+ <item android:drawable="@drawable/zoomin_00033" android:duration="30" />
+ <item android:drawable="@drawable/zoomin_00034" android:duration="30" />
+ <item android:drawable="@drawable/zoomin_00035" android:duration="30" />
+ <item android:drawable="@drawable/zoomin_00036" android:duration="30" />
+ <item android:drawable="@drawable/zoomin_00037" android:duration="30" />
+ <item android:drawable="@drawable/zoomin_00038" android:duration="30" />
+ <item android:drawable="@drawable/zoomin_00039" android:duration="30" />
+ <item android:drawable="@drawable/zoomin_00040" android:duration="30" />
+ <item android:drawable="@drawable/zoomin_00041" android:duration="30" />
+ <item android:drawable="@drawable/zoomin_00042" android:duration="30" />
+ <item android:drawable="@drawable/zoomin_00043" android:duration="30" />
+ <item android:drawable="@drawable/zoomin_00044" android:duration="30" />
+ <item android:drawable="@drawable/zoomin_00045" android:duration="30" />
+ <item android:drawable="@drawable/zoomin_00046" android:duration="30" />
+ <item android:drawable="@drawable/zoomin_00047" android:duration="30" />
+ <item android:drawable="@drawable/zoomin_00048" android:duration="30" />
+ <item android:drawable="@drawable/zoomin_00049" android:duration="30" />
+ <item android:drawable="@drawable/zoomin_00049" android:duration="30" />
+</animation-list>
diff --git a/res/drawable/transition_zoomout.xml b/res/drawable/transition_zoomout.xml
new file mode 100644
index 000000000..1acdb0c94
--- /dev/null
+++ b/res/drawable/transition_zoomout.xml
@@ -0,0 +1,55 @@
+<animation-list
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/transition_zoomout" android:oneshot="false">
+ <item android:drawable="@drawable/zoomout_00000" android:duration="30" />
+ <item android:drawable="@drawable/zoomout_00001" android:duration="30" />
+ <item android:drawable="@drawable/zoomout_00002" android:duration="30" />
+ <item android:drawable="@drawable/zoomout_00003" android:duration="30" />
+ <item android:drawable="@drawable/zoomout_00004" android:duration="30" />
+ <item android:drawable="@drawable/zoomout_00005" android:duration="30" />
+ <item android:drawable="@drawable/zoomout_00006" android:duration="30" />
+ <item android:drawable="@drawable/zoomout_00007" android:duration="30" />
+ <item android:drawable="@drawable/zoomout_00008" android:duration="30" />
+ <item android:drawable="@drawable/zoomout_00009" android:duration="30" />
+ <item android:drawable="@drawable/zoomout_00010" android:duration="30" />
+ <item android:drawable="@drawable/zoomout_00011" android:duration="30" />
+ <item android:drawable="@drawable/zoomout_00012" android:duration="30" />
+ <item android:drawable="@drawable/zoomout_00013" android:duration="30" />
+ <item android:drawable="@drawable/zoomout_00014" android:duration="30" />
+ <item android:drawable="@drawable/zoomout_00015" android:duration="30" />
+ <item android:drawable="@drawable/zoomout_00016" android:duration="30" />
+ <item android:drawable="@drawable/zoomout_00017" android:duration="30" />
+ <item android:drawable="@drawable/zoomout_00018" android:duration="30" />
+ <item android:drawable="@drawable/zoomout_00019" android:duration="30" />
+ <item android:drawable="@drawable/zoomout_00020" android:duration="30" />
+ <item android:drawable="@drawable/zoomout_00021" android:duration="30" />
+ <item android:drawable="@drawable/zoomout_00022" android:duration="30" />
+ <item android:drawable="@drawable/zoomout_00023" android:duration="30" />
+ <item android:drawable="@drawable/zoomout_00024" android:duration="30" />
+ <item android:drawable="@drawable/zoomout_00025" android:duration="30" />
+ <item android:drawable="@drawable/zoomout_00026" android:duration="30" />
+ <item android:drawable="@drawable/zoomout_00027" android:duration="30" />
+ <item android:drawable="@drawable/zoomout_00028" android:duration="30" />
+ <item android:drawable="@drawable/zoomout_00029" android:duration="30" />
+ <item android:drawable="@drawable/zoomout_00030" android:duration="30" />
+ <item android:drawable="@drawable/zoomout_00031" android:duration="30" />
+ <item android:drawable="@drawable/zoomout_00032" android:duration="30" />
+ <item android:drawable="@drawable/zoomout_00033" android:duration="30" />
+ <item android:drawable="@drawable/zoomout_00034" android:duration="30" />
+ <item android:drawable="@drawable/zoomout_00035" android:duration="30" />
+ <item android:drawable="@drawable/zoomout_00036" android:duration="30" />
+ <item android:drawable="@drawable/zoomout_00037" android:duration="30" />
+ <item android:drawable="@drawable/zoomout_00038" android:duration="30" />
+ <item android:drawable="@drawable/zoomout_00039" android:duration="30" />
+ <item android:drawable="@drawable/zoomout_00040" android:duration="30" />
+ <item android:drawable="@drawable/zoomout_00041" android:duration="30" />
+ <item android:drawable="@drawable/zoomout_00042" android:duration="30" />
+ <item android:drawable="@drawable/zoomout_00043" android:duration="30" />
+ <item android:drawable="@drawable/zoomout_00044" android:duration="30" />
+ <item android:drawable="@drawable/zoomout_00045" android:duration="30" />
+ <item android:drawable="@drawable/zoomout_00046" android:duration="30" />
+ <item android:drawable="@drawable/zoomout_00047" android:duration="30" />
+ <item android:drawable="@drawable/zoomout_00048" android:duration="30" />
+ <item android:drawable="@drawable/zoomout_00049" android:duration="30" />
+ <item android:drawable="@drawable/zoomout_00049" android:duration="30" />
+</animation-list>
diff --git a/res/drawable/zoomin_00000.png b/res/drawable/zoomin_00000.png
new file mode 100644
index 000000000..f48138061
--- /dev/null
+++ b/res/drawable/zoomin_00000.png
Binary files differ
diff --git a/res/drawable/zoomin_00001.png b/res/drawable/zoomin_00001.png
new file mode 100644
index 000000000..d2f01b4d5
--- /dev/null
+++ b/res/drawable/zoomin_00001.png
Binary files differ
diff --git a/res/drawable/zoomin_00002.png b/res/drawable/zoomin_00002.png
new file mode 100644
index 000000000..f0bea7934
--- /dev/null
+++ b/res/drawable/zoomin_00002.png
Binary files differ
diff --git a/res/drawable/zoomin_00003.png b/res/drawable/zoomin_00003.png
new file mode 100644
index 000000000..23bd3d5ff
--- /dev/null
+++ b/res/drawable/zoomin_00003.png
Binary files differ
diff --git a/res/drawable/zoomin_00004.png b/res/drawable/zoomin_00004.png
new file mode 100644
index 000000000..9f343a2dc
--- /dev/null
+++ b/res/drawable/zoomin_00004.png
Binary files differ
diff --git a/res/drawable/zoomin_00005.png b/res/drawable/zoomin_00005.png
new file mode 100644
index 000000000..cf7d82ad5
--- /dev/null
+++ b/res/drawable/zoomin_00005.png
Binary files differ
diff --git a/res/drawable/zoomin_00006.png b/res/drawable/zoomin_00006.png
new file mode 100644
index 000000000..5043dfdab
--- /dev/null
+++ b/res/drawable/zoomin_00006.png
Binary files differ
diff --git a/res/drawable/zoomin_00007.png b/res/drawable/zoomin_00007.png
new file mode 100644
index 000000000..013cbbf3c
--- /dev/null
+++ b/res/drawable/zoomin_00007.png
Binary files differ
diff --git a/res/drawable/zoomin_00008.png b/res/drawable/zoomin_00008.png
new file mode 100644
index 000000000..d8acca68a
--- /dev/null
+++ b/res/drawable/zoomin_00008.png
Binary files differ
diff --git a/res/drawable/zoomin_00009.png b/res/drawable/zoomin_00009.png
new file mode 100644
index 000000000..982aa00bf
--- /dev/null
+++ b/res/drawable/zoomin_00009.png
Binary files differ
diff --git a/res/drawable/zoomin_00010.png b/res/drawable/zoomin_00010.png
new file mode 100644
index 000000000..7a5b96457
--- /dev/null
+++ b/res/drawable/zoomin_00010.png
Binary files differ
diff --git a/res/drawable/zoomin_00011.png b/res/drawable/zoomin_00011.png
new file mode 100644
index 000000000..94c374b3f
--- /dev/null
+++ b/res/drawable/zoomin_00011.png
Binary files differ
diff --git a/res/drawable/zoomin_00012.png b/res/drawable/zoomin_00012.png
new file mode 100644
index 000000000..f4ca0cb6a
--- /dev/null
+++ b/res/drawable/zoomin_00012.png
Binary files differ
diff --git a/res/drawable/zoomin_00013.png b/res/drawable/zoomin_00013.png
new file mode 100644
index 000000000..fbb30e04c
--- /dev/null
+++ b/res/drawable/zoomin_00013.png
Binary files differ
diff --git a/res/drawable/zoomin_00014.png b/res/drawable/zoomin_00014.png
new file mode 100644
index 000000000..8e93f17c1
--- /dev/null
+++ b/res/drawable/zoomin_00014.png
Binary files differ
diff --git a/res/drawable/zoomin_00015.png b/res/drawable/zoomin_00015.png
new file mode 100644
index 000000000..bad7462a6
--- /dev/null
+++ b/res/drawable/zoomin_00015.png
Binary files differ
diff --git a/res/drawable/zoomin_00016.png b/res/drawable/zoomin_00016.png
new file mode 100644
index 000000000..282a8073f
--- /dev/null
+++ b/res/drawable/zoomin_00016.png
Binary files differ
diff --git a/res/drawable/zoomin_00017.png b/res/drawable/zoomin_00017.png
new file mode 100644
index 000000000..ae94999f2
--- /dev/null
+++ b/res/drawable/zoomin_00017.png
Binary files differ
diff --git a/res/drawable/zoomin_00018.png b/res/drawable/zoomin_00018.png
new file mode 100644
index 000000000..3fcc59e52
--- /dev/null
+++ b/res/drawable/zoomin_00018.png
Binary files differ
diff --git a/res/drawable/zoomin_00019.png b/res/drawable/zoomin_00019.png
new file mode 100644
index 000000000..be9cfcbb3
--- /dev/null
+++ b/res/drawable/zoomin_00019.png
Binary files differ
diff --git a/res/drawable/zoomin_00020.png b/res/drawable/zoomin_00020.png
new file mode 100644
index 000000000..303e8f87f
--- /dev/null
+++ b/res/drawable/zoomin_00020.png
Binary files differ
diff --git a/res/drawable/zoomin_00021.png b/res/drawable/zoomin_00021.png
new file mode 100644
index 000000000..303e8f87f
--- /dev/null
+++ b/res/drawable/zoomin_00021.png
Binary files differ
diff --git a/res/drawable/zoomin_00022.png b/res/drawable/zoomin_00022.png
new file mode 100644
index 000000000..303e8f87f
--- /dev/null
+++ b/res/drawable/zoomin_00022.png
Binary files differ
diff --git a/res/drawable/zoomin_00023.png b/res/drawable/zoomin_00023.png
new file mode 100644
index 000000000..303e8f87f
--- /dev/null
+++ b/res/drawable/zoomin_00023.png
Binary files differ
diff --git a/res/drawable/zoomin_00024.png b/res/drawable/zoomin_00024.png
new file mode 100644
index 000000000..303e8f87f
--- /dev/null
+++ b/res/drawable/zoomin_00024.png
Binary files differ
diff --git a/res/drawable/zoomin_00025.png b/res/drawable/zoomin_00025.png
new file mode 100644
index 000000000..303e8f87f
--- /dev/null
+++ b/res/drawable/zoomin_00025.png
Binary files differ
diff --git a/res/drawable/zoomin_00026.png b/res/drawable/zoomin_00026.png
new file mode 100644
index 000000000..303e8f87f
--- /dev/null
+++ b/res/drawable/zoomin_00026.png
Binary files differ
diff --git a/res/drawable/zoomin_00027.png b/res/drawable/zoomin_00027.png
new file mode 100644
index 000000000..303e8f87f
--- /dev/null
+++ b/res/drawable/zoomin_00027.png
Binary files differ
diff --git a/res/drawable/zoomin_00028.png b/res/drawable/zoomin_00028.png
new file mode 100644
index 000000000..303e8f87f
--- /dev/null
+++ b/res/drawable/zoomin_00028.png
Binary files differ
diff --git a/res/drawable/zoomin_00029.png b/res/drawable/zoomin_00029.png
new file mode 100644
index 000000000..303e8f87f
--- /dev/null
+++ b/res/drawable/zoomin_00029.png
Binary files differ
diff --git a/res/drawable/zoomin_00030.png b/res/drawable/zoomin_00030.png
new file mode 100644
index 000000000..303e8f87f
--- /dev/null
+++ b/res/drawable/zoomin_00030.png
Binary files differ
diff --git a/res/drawable/zoomin_00031.png b/res/drawable/zoomin_00031.png
new file mode 100644
index 000000000..303e8f87f
--- /dev/null
+++ b/res/drawable/zoomin_00031.png
Binary files differ
diff --git a/res/drawable/zoomin_00032.png b/res/drawable/zoomin_00032.png
new file mode 100644
index 000000000..303e8f87f
--- /dev/null
+++ b/res/drawable/zoomin_00032.png
Binary files differ
diff --git a/res/drawable/zoomin_00033.png b/res/drawable/zoomin_00033.png
new file mode 100644
index 000000000..303e8f87f
--- /dev/null
+++ b/res/drawable/zoomin_00033.png
Binary files differ
diff --git a/res/drawable/zoomin_00034.png b/res/drawable/zoomin_00034.png
new file mode 100644
index 000000000..303e8f87f
--- /dev/null
+++ b/res/drawable/zoomin_00034.png
Binary files differ
diff --git a/res/drawable/zoomin_00035.png b/res/drawable/zoomin_00035.png
new file mode 100644
index 000000000..303e8f87f
--- /dev/null
+++ b/res/drawable/zoomin_00035.png
Binary files differ
diff --git a/res/drawable/zoomin_00036.png b/res/drawable/zoomin_00036.png
new file mode 100644
index 000000000..303e8f87f
--- /dev/null
+++ b/res/drawable/zoomin_00036.png
Binary files differ
diff --git a/res/drawable/zoomin_00037.png b/res/drawable/zoomin_00037.png
new file mode 100644
index 000000000..303e8f87f
--- /dev/null
+++ b/res/drawable/zoomin_00037.png
Binary files differ
diff --git a/res/drawable/zoomin_00038.png b/res/drawable/zoomin_00038.png
new file mode 100644
index 000000000..303e8f87f
--- /dev/null
+++ b/res/drawable/zoomin_00038.png
Binary files differ
diff --git a/res/drawable/zoomin_00039.png b/res/drawable/zoomin_00039.png
new file mode 100644
index 000000000..303e8f87f
--- /dev/null
+++ b/res/drawable/zoomin_00039.png
Binary files differ
diff --git a/res/drawable/zoomin_00040.png b/res/drawable/zoomin_00040.png
new file mode 100644
index 000000000..303e8f87f
--- /dev/null
+++ b/res/drawable/zoomin_00040.png
Binary files differ
diff --git a/res/drawable/zoomin_00041.png b/res/drawable/zoomin_00041.png
new file mode 100644
index 000000000..303e8f87f
--- /dev/null
+++ b/res/drawable/zoomin_00041.png
Binary files differ
diff --git a/res/drawable/zoomin_00042.png b/res/drawable/zoomin_00042.png
new file mode 100644
index 000000000..303e8f87f
--- /dev/null
+++ b/res/drawable/zoomin_00042.png
Binary files differ
diff --git a/res/drawable/zoomin_00043.png b/res/drawable/zoomin_00043.png
new file mode 100644
index 000000000..303e8f87f
--- /dev/null
+++ b/res/drawable/zoomin_00043.png
Binary files differ
diff --git a/res/drawable/zoomin_00044.png b/res/drawable/zoomin_00044.png
new file mode 100644
index 000000000..303e8f87f
--- /dev/null
+++ b/res/drawable/zoomin_00044.png
Binary files differ
diff --git a/res/drawable/zoomin_00045.png b/res/drawable/zoomin_00045.png
new file mode 100644
index 000000000..303e8f87f
--- /dev/null
+++ b/res/drawable/zoomin_00045.png
Binary files differ
diff --git a/res/drawable/zoomin_00046.png b/res/drawable/zoomin_00046.png
new file mode 100644
index 000000000..303e8f87f
--- /dev/null
+++ b/res/drawable/zoomin_00046.png
Binary files differ
diff --git a/res/drawable/zoomin_00047.png b/res/drawable/zoomin_00047.png
new file mode 100644
index 000000000..303e8f87f
--- /dev/null
+++ b/res/drawable/zoomin_00047.png
Binary files differ
diff --git a/res/drawable/zoomin_00048.png b/res/drawable/zoomin_00048.png
new file mode 100644
index 000000000..303e8f87f
--- /dev/null
+++ b/res/drawable/zoomin_00048.png
Binary files differ
diff --git a/res/drawable/zoomin_00049.png b/res/drawable/zoomin_00049.png
new file mode 100644
index 000000000..303e8f87f
--- /dev/null
+++ b/res/drawable/zoomin_00049.png
Binary files differ
diff --git a/res/drawable/zoomout_00000.png b/res/drawable/zoomout_00000.png
new file mode 100644
index 000000000..94284f9b9
--- /dev/null
+++ b/res/drawable/zoomout_00000.png
Binary files differ
diff --git a/res/drawable/zoomout_00001.png b/res/drawable/zoomout_00001.png
new file mode 100644
index 000000000..8c2a2596a
--- /dev/null
+++ b/res/drawable/zoomout_00001.png
Binary files differ
diff --git a/res/drawable/zoomout_00002.png b/res/drawable/zoomout_00002.png
new file mode 100644
index 000000000..e3c4cb49b
--- /dev/null
+++ b/res/drawable/zoomout_00002.png
Binary files differ
diff --git a/res/drawable/zoomout_00003.png b/res/drawable/zoomout_00003.png
new file mode 100644
index 000000000..95af18d06
--- /dev/null
+++ b/res/drawable/zoomout_00003.png
Binary files differ
diff --git a/res/drawable/zoomout_00004.png b/res/drawable/zoomout_00004.png
new file mode 100644
index 000000000..4d8af9632
--- /dev/null
+++ b/res/drawable/zoomout_00004.png
Binary files differ
diff --git a/res/drawable/zoomout_00005.png b/res/drawable/zoomout_00005.png
new file mode 100644
index 000000000..6db1ab05a
--- /dev/null
+++ b/res/drawable/zoomout_00005.png
Binary files differ
diff --git a/res/drawable/zoomout_00006.png b/res/drawable/zoomout_00006.png
new file mode 100644
index 000000000..277d8c4ac
--- /dev/null
+++ b/res/drawable/zoomout_00006.png
Binary files differ
diff --git a/res/drawable/zoomout_00007.png b/res/drawable/zoomout_00007.png
new file mode 100644
index 000000000..4fe81f665
--- /dev/null
+++ b/res/drawable/zoomout_00007.png
Binary files differ
diff --git a/res/drawable/zoomout_00008.png b/res/drawable/zoomout_00008.png
new file mode 100644
index 000000000..fadd58a14
--- /dev/null
+++ b/res/drawable/zoomout_00008.png
Binary files differ
diff --git a/res/drawable/zoomout_00009.png b/res/drawable/zoomout_00009.png
new file mode 100644
index 000000000..5b6003e07
--- /dev/null
+++ b/res/drawable/zoomout_00009.png
Binary files differ
diff --git a/res/drawable/zoomout_00010.png b/res/drawable/zoomout_00010.png
new file mode 100644
index 000000000..b77a4f88b
--- /dev/null
+++ b/res/drawable/zoomout_00010.png
Binary files differ
diff --git a/res/drawable/zoomout_00011.png b/res/drawable/zoomout_00011.png
new file mode 100644
index 000000000..85fbbb831
--- /dev/null
+++ b/res/drawable/zoomout_00011.png
Binary files differ
diff --git a/res/drawable/zoomout_00012.png b/res/drawable/zoomout_00012.png
new file mode 100644
index 000000000..eb8acb213
--- /dev/null
+++ b/res/drawable/zoomout_00012.png
Binary files differ
diff --git a/res/drawable/zoomout_00013.png b/res/drawable/zoomout_00013.png
new file mode 100644
index 000000000..3501c8514
--- /dev/null
+++ b/res/drawable/zoomout_00013.png
Binary files differ
diff --git a/res/drawable/zoomout_00014.png b/res/drawable/zoomout_00014.png
new file mode 100644
index 000000000..fd600be1b
--- /dev/null
+++ b/res/drawable/zoomout_00014.png
Binary files differ
diff --git a/res/drawable/zoomout_00015.png b/res/drawable/zoomout_00015.png
new file mode 100644
index 000000000..b88c6bcd8
--- /dev/null
+++ b/res/drawable/zoomout_00015.png
Binary files differ
diff --git a/res/drawable/zoomout_00016.png b/res/drawable/zoomout_00016.png
new file mode 100644
index 000000000..c618a55fc
--- /dev/null
+++ b/res/drawable/zoomout_00016.png
Binary files differ
diff --git a/res/drawable/zoomout_00017.png b/res/drawable/zoomout_00017.png
new file mode 100644
index 000000000..c54b0dc8f
--- /dev/null
+++ b/res/drawable/zoomout_00017.png
Binary files differ
diff --git a/res/drawable/zoomout_00018.png b/res/drawable/zoomout_00018.png
new file mode 100644
index 000000000..8e974a18a
--- /dev/null
+++ b/res/drawable/zoomout_00018.png
Binary files differ
diff --git a/res/drawable/zoomout_00019.png b/res/drawable/zoomout_00019.png
new file mode 100644
index 000000000..79c6fb0e0
--- /dev/null
+++ b/res/drawable/zoomout_00019.png
Binary files differ
diff --git a/res/drawable/zoomout_00020.png b/res/drawable/zoomout_00020.png
new file mode 100644
index 000000000..b4be2aa37
--- /dev/null
+++ b/res/drawable/zoomout_00020.png
Binary files differ
diff --git a/res/drawable/zoomout_00021.png b/res/drawable/zoomout_00021.png
new file mode 100644
index 000000000..b4be2aa37
--- /dev/null
+++ b/res/drawable/zoomout_00021.png
Binary files differ
diff --git a/res/drawable/zoomout_00022.png b/res/drawable/zoomout_00022.png
new file mode 100644
index 000000000..b4be2aa37
--- /dev/null
+++ b/res/drawable/zoomout_00022.png
Binary files differ
diff --git a/res/drawable/zoomout_00023.png b/res/drawable/zoomout_00023.png
new file mode 100644
index 000000000..b4be2aa37
--- /dev/null
+++ b/res/drawable/zoomout_00023.png
Binary files differ
diff --git a/res/drawable/zoomout_00024.png b/res/drawable/zoomout_00024.png
new file mode 100644
index 000000000..b4be2aa37
--- /dev/null
+++ b/res/drawable/zoomout_00024.png
Binary files differ
diff --git a/res/drawable/zoomout_00025.png b/res/drawable/zoomout_00025.png
new file mode 100644
index 000000000..b4be2aa37
--- /dev/null
+++ b/res/drawable/zoomout_00025.png
Binary files differ
diff --git a/res/drawable/zoomout_00026.png b/res/drawable/zoomout_00026.png
new file mode 100644
index 000000000..b4be2aa37
--- /dev/null
+++ b/res/drawable/zoomout_00026.png
Binary files differ
diff --git a/res/drawable/zoomout_00027.png b/res/drawable/zoomout_00027.png
new file mode 100644
index 000000000..b4be2aa37
--- /dev/null
+++ b/res/drawable/zoomout_00027.png
Binary files differ
diff --git a/res/drawable/zoomout_00028.png b/res/drawable/zoomout_00028.png
new file mode 100644
index 000000000..b4be2aa37
--- /dev/null
+++ b/res/drawable/zoomout_00028.png
Binary files differ
diff --git a/res/drawable/zoomout_00029.png b/res/drawable/zoomout_00029.png
new file mode 100644
index 000000000..b4be2aa37
--- /dev/null
+++ b/res/drawable/zoomout_00029.png
Binary files differ
diff --git a/res/drawable/zoomout_00030.png b/res/drawable/zoomout_00030.png
new file mode 100644
index 000000000..b4be2aa37
--- /dev/null
+++ b/res/drawable/zoomout_00030.png
Binary files differ
diff --git a/res/drawable/zoomout_00031.png b/res/drawable/zoomout_00031.png
new file mode 100644
index 000000000..b4be2aa37
--- /dev/null
+++ b/res/drawable/zoomout_00031.png
Binary files differ
diff --git a/res/drawable/zoomout_00032.png b/res/drawable/zoomout_00032.png
new file mode 100644
index 000000000..b4be2aa37
--- /dev/null
+++ b/res/drawable/zoomout_00032.png
Binary files differ
diff --git a/res/drawable/zoomout_00033.png b/res/drawable/zoomout_00033.png
new file mode 100644
index 000000000..b4be2aa37
--- /dev/null
+++ b/res/drawable/zoomout_00033.png
Binary files differ
diff --git a/res/drawable/zoomout_00034.png b/res/drawable/zoomout_00034.png
new file mode 100644
index 000000000..b4be2aa37
--- /dev/null
+++ b/res/drawable/zoomout_00034.png
Binary files differ
diff --git a/res/drawable/zoomout_00035.png b/res/drawable/zoomout_00035.png
new file mode 100644
index 000000000..b4be2aa37
--- /dev/null
+++ b/res/drawable/zoomout_00035.png
Binary files differ
diff --git a/res/drawable/zoomout_00036.png b/res/drawable/zoomout_00036.png
new file mode 100644
index 000000000..b4be2aa37
--- /dev/null
+++ b/res/drawable/zoomout_00036.png
Binary files differ
diff --git a/res/drawable/zoomout_00037.png b/res/drawable/zoomout_00037.png
new file mode 100644
index 000000000..b4be2aa37
--- /dev/null
+++ b/res/drawable/zoomout_00037.png
Binary files differ
diff --git a/res/drawable/zoomout_00038.png b/res/drawable/zoomout_00038.png
new file mode 100644
index 000000000..b4be2aa37
--- /dev/null
+++ b/res/drawable/zoomout_00038.png
Binary files differ
diff --git a/res/drawable/zoomout_00039.png b/res/drawable/zoomout_00039.png
new file mode 100644
index 000000000..b4be2aa37
--- /dev/null
+++ b/res/drawable/zoomout_00039.png
Binary files differ
diff --git a/res/drawable/zoomout_00040.png b/res/drawable/zoomout_00040.png
new file mode 100644
index 000000000..b4be2aa37
--- /dev/null
+++ b/res/drawable/zoomout_00040.png
Binary files differ
diff --git a/res/drawable/zoomout_00041.png b/res/drawable/zoomout_00041.png
new file mode 100644
index 000000000..b4be2aa37
--- /dev/null
+++ b/res/drawable/zoomout_00041.png
Binary files differ
diff --git a/res/drawable/zoomout_00042.png b/res/drawable/zoomout_00042.png
new file mode 100644
index 000000000..b4be2aa37
--- /dev/null
+++ b/res/drawable/zoomout_00042.png
Binary files differ
diff --git a/res/drawable/zoomout_00043.png b/res/drawable/zoomout_00043.png
new file mode 100644
index 000000000..b4be2aa37
--- /dev/null
+++ b/res/drawable/zoomout_00043.png
Binary files differ
diff --git a/res/drawable/zoomout_00044.png b/res/drawable/zoomout_00044.png
new file mode 100644
index 000000000..b4be2aa37
--- /dev/null
+++ b/res/drawable/zoomout_00044.png
Binary files differ
diff --git a/res/drawable/zoomout_00045.png b/res/drawable/zoomout_00045.png
new file mode 100644
index 000000000..b4be2aa37
--- /dev/null
+++ b/res/drawable/zoomout_00045.png
Binary files differ
diff --git a/res/drawable/zoomout_00046.png b/res/drawable/zoomout_00046.png
new file mode 100644
index 000000000..b4be2aa37
--- /dev/null
+++ b/res/drawable/zoomout_00046.png
Binary files differ
diff --git a/res/drawable/zoomout_00047.png b/res/drawable/zoomout_00047.png
new file mode 100644
index 000000000..b4be2aa37
--- /dev/null
+++ b/res/drawable/zoomout_00047.png
Binary files differ
diff --git a/res/drawable/zoomout_00048.png b/res/drawable/zoomout_00048.png
new file mode 100644
index 000000000..b4be2aa37
--- /dev/null
+++ b/res/drawable/zoomout_00048.png
Binary files differ
diff --git a/res/drawable/zoomout_00049.png b/res/drawable/zoomout_00049.png
new file mode 100644
index 000000000..b4be2aa37
--- /dev/null
+++ b/res/drawable/zoomout_00049.png
Binary files differ
diff --git a/res/layout-land/folder_cling.xml b/res/layout-land/folder_cling.xml
index 86286d71b..5dd372973 100644
--- a/res/layout-land/folder_cling.xml
+++ b/res/layout-land/folder_cling.xml
@@ -16,7 +16,7 @@
<com.android.launcher3.Cling
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3"
- launcher:drawIdentifier="folder_portrait">
+ launcher:drawIdentifier="folder_landscape">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
@@ -25,6 +25,7 @@
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp">
<LinearLayout
+ android:id="@+id/folder_bubble"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
@@ -59,6 +60,6 @@
android:id="@+id/cling_dismiss"
android:layout_marginBottom="15dp"
android:layout_marginEnd="20dp"
- android:layout_gravity="bottom|end"
+ android:layout_gravity="bottom|right"
android:onClick="dismissFolderCling" />
</com.android.launcher3.Cling>
diff --git a/res/layout-land/launcher.xml b/res/layout-land/launcher.xml
index 2f64efe39..3e8503a67 100644
--- a/res/layout-land/launcher.xml
+++ b/res/layout-land/launcher.xml
@@ -36,9 +36,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
- launcher:defaultScreen="@integer/config_workspaceDefaultScreen"
- launcher:pageSpacing="@dimen/workspace_page_spacing"
- launcher:pageIndicator="@id/page_indicator" />
+ launcher:defaultScreen="@integer/config_workspaceDefaultScreen" />
<include layout="@layout/hotseat"
android:id="@+id/hotseat"
@@ -47,8 +45,8 @@
android:layout_gravity="end" />
<include
- android:id="@+id/qsb_bar"
- layout="@layout/qsb_bar" />
+ android:id="@+id/search_drop_target_bar"
+ layout="@layout/search_drop_target_bar" />
<!-- The Workspace cling must appear under the AppsCustomizePagedView below to ensure
that it is still visible during the transition to AllApps and doesn't overlay on
@@ -63,43 +61,33 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone" />
+ <include layout="@layout/migration_cling"
+ android:id="@+id/migration_cling"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:visibility="gone" />
+ <include layout="@layout/migration_workspace_cling"
+ android:id="@+id/migration_workspace_cling"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:visibility="gone" />
<include layout="@layout/workspace_cling"
android:id="@+id/workspace_cling"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone" />
-
<include layout="@layout/folder_cling"
android:id="@+id/folder_cling"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone" />
- <!-- TODO: Fix
- <com.android.launcher3.DrawableStateProxyView
- android:id="@+id/voice_button_proxy"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:layout_gravity="top|start"
- android:layout_marginTop="64dp"
- android:clickable="true"
- android:onClick="onClickVoiceButton"
- android:importantForAccessibility="no"
- launcher:sourceViewId="@+id/voice_button" />
- -->
-
<include layout="@layout/apps_customize_pane"
android:id="@+id/apps_customize_pane"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="invisible" />
- <include layout="@layout/all_apps_cling"
- android:id="@+id/all_apps_cling"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:visibility="gone" />
-
<include layout="@layout/overview_panel"
android:id="@+id/overview_panel"
android:visibility="gone" />
diff --git a/res/layout-land/migration_cling.xml b/res/layout-land/migration_cling.xml
new file mode 100644
index 000000000..343f43f1f
--- /dev/null
+++ b/res/layout-land/migration_cling.xml
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<com.android.launcher3.Cling
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ launcher:drawIdentifier="migration_landscape">
+ <FrameLayout
+ android:id="@+id/content"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="top"
+ android:orientation="vertical">
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="top"
+ android:gravity="center"
+ android:text="@string/first_run_cling_title"
+ android:textSize="42dp"
+ android:textColor="#FFffffff" />
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="10dp"
+ android:layout_marginBottom="0dp"
+ android:layout_gravity="center_horizontal"
+ android:src="@drawable/on_boarding_welcome" />
+
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:src="@drawable/cling_arrow_up" />
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="25dp"
+ android:layout_marginRight="25dp"
+ android:paddingLeft="25dp"
+ android:paddingRight="25dp"
+ android:paddingTop="20dp"
+ android:paddingBottom="20dp"
+ android:orientation="vertical"
+ android:background="@drawable/cling">
+ <TextView
+ style="@style/ClingTitleText"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/migration_cling_title" />
+ <TextView
+ style="@style/ClingText"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/migration_cling_description" />
+ </LinearLayout>
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="bottom"
+ android:layout_marginLeft="25dp"
+ android:layout_marginRight="25dp"
+ android:layout_marginBottom="25dp"
+ android:orientation="vertical">
+ <Button
+ style="@style/ClingButton"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/migration_cling_copy_apps"
+ android:onClick="dismissMigrationClingCopyApps" />
+ <Button
+ style="@style/ClingButton"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/migration_cling_use_default"
+ android:onClick="dismissMigrationClingUseDefault" />
+ </LinearLayout>
+ </FrameLayout>
+</com.android.launcher3.Cling>
diff --git a/res/layout-land/migration_workspace_cling.xml b/res/layout-land/migration_workspace_cling.xml
new file mode 100644
index 000000000..1148be45f
--- /dev/null
+++ b/res/layout-land/migration_workspace_cling.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<com.android.launcher3.Cling
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ launcher:drawIdentifier="migration_workspace_landscape">
+ <LinearLayout
+ android:id="@+id/content"
+ android:layout_width="400dp"
+ android:layout_height="wrap_content"
+ android:layout_gravity="end|center_vertical"
+ android:paddingEnd="60dp"
+ android:paddingRight="60dp"
+ android:orientation="vertical">
+ <LinearLayout
+ android:id="@+id/migration_workspace_cling_bubble"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginRight="4dp"
+ android:paddingLeft="20dp"
+ android:paddingRight="20dp"
+ android:paddingTop="20dp"
+ android:paddingBottom="20dp"
+ android:orientation="vertical"
+ android:background="@drawable/cling">
+ <TextView
+ style="@style/ClingTitleText"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/workspace_cling_title" />
+ <TextView
+ style="@style/ClingText"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/workspace_cling_move_item" />
+ </LinearLayout>
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:src="@drawable/cling_arrow_end" />
+ </LinearLayout>
+ <Button
+ style="@style/ClingButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="5dp"
+ android:layout_gravity="right"
+ android:onClick="dismissMigrationWorkspaceCling" />
+ </LinearLayout>
+</com.android.launcher3.Cling>
diff --git a/res/layout-land/search_bar.xml b/res/layout-land/qsb.xml
index d56e380d0..d56e380d0 100644
--- a/res/layout-land/search_bar.xml
+++ b/res/layout-land/qsb.xml
diff --git a/res/layout-land/workspace_cling.xml b/res/layout-land/workspace_cling.xml
index db33db06f..d3b07d74d 100644
--- a/res/layout-land/workspace_cling.xml
+++ b/res/layout-land/workspace_cling.xml
@@ -18,24 +18,20 @@
xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3"
android:layout_width="match_parent"
android:layout_height="match_parent"
- launcher:drawIdentifier="workspace_portrait">
+ launcher:drawIdentifier="workspace_landscape">
<FrameLayout
android:id="@+id/content"
android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_marginStart="25dp"
- android:layout_marginEnd="25dp"
- android:layout_marginTop="310dp">
+ android:layout_height="match_parent">
<LinearLayout
+ android:id="@+id/workspace_cling_bubble"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
+ android:layout_marginStart="25dp"
+ android:layout_marginEnd="25dp"
+ android:layout_marginTop="30dp"
android:orientation="vertical">
- <ImageView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_horizontal"
- android:src="@drawable/cling_arrow_up" />
<LinearLayout
android:paddingLeft="20dp"
android:paddingRight="20dp"
@@ -56,14 +52,57 @@
android:layout_height="wrap_content"
android:text="@string/workspace_cling_move_item" />
</LinearLayout>
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:src="@drawable/cling_arrow_down" />
+ </LinearLayout>
+
+ <LinearLayout
+ android:id="@+id/focused_hotseat_app_bubble"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="bottom|left"
+ android:layout_marginLeft="25dp"
+ android:layout_marginBottom="90dp"
+ android:orientation="vertical"
+ android:visibility="gone">
+ <LinearLayout
+ android:paddingLeft="20dp"
+ android:paddingRight="20dp"
+ android:paddingTop="20dp"
+ android:paddingBottom="20dp"
+ android:layout_width="240dp"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:background="@drawable/cling">
+ <TextView
+ android:id="@+id/focused_hotseat_app_title"
+ style="@style/ClingTitleText"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+ <TextView
+ android:id="@+id/focused_hotseat_app_description"
+ style="@style/ClingText"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+ </LinearLayout>
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="left"
+ android:layout_marginLeft="78dp"
+ android:src="@drawable/cling_arrow_down" />
</LinearLayout>
</FrameLayout>
+
<Button
style="@style/ClingButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="15dp"
- android:layout_marginEnd="20dp"
- android:layout_gravity="bottom|end"
+ android:layout_marginRight="20dp"
+ android:layout_gravity="bottom|right"
android:onClick="dismissWorkspaceCling" />
</com.android.launcher3.Cling>
diff --git a/res/layout-port/first_run_cling.xml b/res/layout-port/first_run_cling.xml
index 4830e5df8..ac3939cfd 100644
--- a/res/layout-port/first_run_cling.xml
+++ b/res/layout-port/first_run_cling.xml
@@ -39,16 +39,14 @@
android:layout_marginBottom="10dp"
android:text="@string/first_run_cling_title"
android:textColor="#FFFFFFFF"
- android:textSize="30sp"
android:gravity="center" />
<TextView
- style="@style/ClingAltTitleText"
+ style="@style/ClingAltText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="@string/first_run_cling_description"
android:textColor="#80000000"
- android:textSize="16sp"
android:gravity="center" />
</LinearLayout>
<TextView
diff --git a/res/layout-port/folder_cling.xml b/res/layout-port/folder_cling.xml
index 86286d71b..1a1b11fce 100644
--- a/res/layout-port/folder_cling.xml
+++ b/res/layout-port/folder_cling.xml
@@ -25,6 +25,7 @@
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp">
<LinearLayout
+ android:id="@+id/folder_bubble"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
@@ -59,6 +60,6 @@
android:id="@+id/cling_dismiss"
android:layout_marginBottom="15dp"
android:layout_marginEnd="20dp"
- android:layout_gravity="bottom|end"
+ android:layout_gravity="bottom|right"
android:onClick="dismissFolderCling" />
</com.android.launcher3.Cling>
diff --git a/res/layout-port/launcher.xml b/res/layout-port/launcher.xml
index 98cd0f3b6..c55aec867 100644
--- a/res/layout-port/launcher.xml
+++ b/res/layout-port/launcher.xml
@@ -35,8 +35,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
launcher:defaultScreen="@integer/config_workspaceDefaultScreen"
- launcher:pageSpacing="@dimen/workspace_page_spacing"
- launcher:pageIndicator="@id/page_indicator">
+ launcher:pageIndicator="@+id/page_indicator">
</com.android.launcher3.Workspace>
<include layout="@layout/hotseat"
@@ -54,8 +53,8 @@
android:layout_gravity="center_horizontal" />
<include
- android:id="@+id/qsb_bar"
- layout="@layout/qsb_bar" />
+ android:id="@+id/search_drop_target_bar"
+ layout="@layout/search_drop_target_bar" />
<!-- The Workspace cling must appear under the AppsCustomizePagedView below to ensure
that it is still visible during the transition to AllApps and doesn't overlay on
@@ -70,6 +69,16 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone" />
+ <include layout="@layout/migration_cling"
+ android:id="@+id/migration_cling"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:visibility="gone" />
+ <include layout="@layout/migration_workspace_cling"
+ android:id="@+id/migration_workspace_cling"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:visibility="gone" />
<include layout="@layout/workspace_cling"
android:id="@+id/workspace_cling"
android:layout_width="match_parent"
@@ -99,12 +108,6 @@
android:layout_height="match_parent"
android:visibility="invisible" />
- <include layout="@layout/all_apps_cling"
- android:id="@+id/all_apps_cling"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:visibility="gone" />
-
<include layout="@layout/overview_panel"
android:id="@+id/overview_panel"
android:visibility="gone" />
diff --git a/res/layout-port/migration_cling.xml b/res/layout-port/migration_cling.xml
new file mode 100644
index 000000000..1bffe6c82
--- /dev/null
+++ b/res/layout-port/migration_cling.xml
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<com.android.launcher3.Cling
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ launcher:drawIdentifier="migration_portrait">
+ <FrameLayout
+ android:id="@+id/content"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="top"
+ android:orientation="vertical">
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="top"
+ android:gravity="center"
+ android:text="@string/first_run_cling_title"
+ android:textSize="42dp"
+ android:textColor="#FFffffff" />
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="10dp"
+ android:layout_marginBottom="0dp"
+ android:layout_gravity="center_horizontal"
+ android:src="@drawable/on_boarding_welcome" />
+
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:src="@drawable/cling_arrow_up" />
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="25dp"
+ android:layout_marginRight="25dp"
+ android:paddingLeft="25dp"
+ android:paddingRight="25dp"
+ android:paddingTop="20dp"
+ android:paddingBottom="20dp"
+ android:orientation="vertical"
+ android:background="@drawable/cling">
+ <TextView
+ style="@style/ClingTitleText"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/migration_cling_title" />
+ <TextView
+ style="@style/ClingText"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/migration_cling_description" />
+ </LinearLayout>
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="bottom"
+ android:layout_marginLeft="25dp"
+ android:layout_marginRight="25dp"
+ android:layout_marginBottom="25dp"
+ android:orientation="vertical">
+ <Button
+ style="@style/ClingButton"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/migration_cling_copy_apps"
+ android:onClick="dismissMigrationClingCopyApps" />
+ <Button
+ style="@style/ClingButton"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/migration_cling_use_default"
+ android:onClick="dismissMigrationClingUseDefault" />
+ </LinearLayout>
+ </FrameLayout>
+</com.android.launcher3.Cling>
diff --git a/res/layout-port/all_apps_cling.xml b/res/layout-port/migration_workspace_cling.xml
index ed99d78a0..576bb41f2 100644
--- a/res/layout-port/all_apps_cling.xml
+++ b/res/layout-port/migration_workspace_cling.xml
@@ -18,18 +18,18 @@
xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3"
android:layout_width="match_parent"
android:layout_height="match_parent"
- launcher:drawIdentifier="all_apps">
+ launcher:drawIdentifier="migration_workspace_portrait">
<FrameLayout
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
+ android:id="@+id/migration_workspace_cling_bubble"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_gravity="top"
+ android:layout_gravity="bottom"
android:layout_marginStart="25dp"
android:layout_marginEnd="25dp"
- android:layout_marginTop="30dp"
android:orientation="vertical">
<LinearLayout
android:paddingLeft="20dp"
@@ -44,22 +44,27 @@
style="@style/ClingTitleText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:text="@string/all_apps_cling_cm" />
+ android:text="@string/workspace_cling_title" />
<TextView
style="@style/ClingText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:text="@string/all_apps_cling_summary" />
+ android:text="@string/workspace_cling_move_item" />
</LinearLayout>
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:src="@drawable/cling_arrow_down" />
</LinearLayout>
- </FrameLayout>
- <Button
- style="@style/ClingButton"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginBottom="60dp"
- android:layout_marginRight="20dp"
- android:layout_gravity="bottom|right"
- android:onClick="dismissAllAppsCling" />
+ <Button
+ style="@style/ClingButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="15dp"
+ android:layout_marginEnd="20dp"
+ android:layout_gravity="bottom|right"
+ android:onClick="dismissMigrationWorkspaceCling" />
+ </FrameLayout>
</com.android.launcher3.Cling>
diff --git a/res/layout-sw720dp/search_bar.xml b/res/layout-port/qsb.xml
index 1c96ca380..f7a1c8773 100644
--- a/res/layout-sw720dp/search_bar.xml
+++ b/res/layout-port/qsb.xml
@@ -16,13 +16,12 @@
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3"
- style="@style/SearchDropTargetBar"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:background="@drawable/search_frame">
+ android:background="@drawable/search_bg">
<!-- Global search icon -->
<com.android.launcher3.HolographicLinearLayout
- style="@style/SearchButton"
+ style="@style/SearchButton.WithPaddingStart"
launcher:sourceImageViewId="@+id/search_button"
android:id="@+id/search_button_container"
android:layout_width="match_parent"
@@ -31,7 +30,6 @@
android:layout_centerVertical="true"
android:layout_alignParentStart="true"
android:layout_toStartOf="@+id/voice_button_container"
- android:paddingStart="8dp"
android:onClick="onClickSearchButton"
android:focusable="true"
android:clickable="true"
@@ -57,6 +55,7 @@
android:layout_centerVertical="true"
android:layout_alignParentEnd="true"
android:paddingEnd="8dp"
+ android:paddingRight="8dp"
android:onClick="onClickVoiceButton"
android:focusable="true"
android:clickable="true"
diff --git a/res/layout-port/workspace_cling.xml b/res/layout-port/workspace_cling.xml
index b926ca967..624568668 100644
--- a/res/layout-port/workspace_cling.xml
+++ b/res/layout-port/workspace_cling.xml
@@ -24,6 +24,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
+ android:id="@+id/workspace_cling_bubble"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
diff --git a/res/layout-sw600dp-port/first_run_cling.xml b/res/layout-sw600dp-port/first_run_cling.xml
new file mode 100644
index 000000000..d80c084ab
--- /dev/null
+++ b/res/layout-sw600dp-port/first_run_cling.xml
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<com.android.launcher3.Cling
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ launcher:drawIdentifier="first_run_portrait">
+ <FrameLayout
+ android:id="@+id/content"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <LinearLayout
+ android:id="@+id/bubble_content"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:layout_marginLeft="100dp"
+ android:layout_marginRight="100dp"
+ android:orientation="vertical">
+ <TextView
+ style="@style/ClingAltTitleText"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:layout_marginBottom="10dp"
+ android:text="@string/first_run_cling_title"
+ android:textColor="#FFFFFFFF"
+ android:gravity="center" />
+ <TextView
+ style="@style/ClingAltText"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:text="@string/first_run_cling_description"
+ android:textColor="#80000000"
+ android:gravity="center" />
+ </LinearLayout>
+ <TextView
+ style="@style/ClingHintText"
+ android:id="@+id/search_bar_hint"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="top|end"
+ android:layout_marginEnd="30dp"
+ android:layout_marginTop="80dp"
+ android:gravity="center_horizontal"
+ android:maxWidth="160dp"
+ android:visibility="gone"
+ android:drawableTop="@drawable/cling_arrow_up"
+ android:drawablePadding="10dp"
+ android:text="@string/first_run_cling_search_bar_hint" />
+ <TextView
+ style="@style/ClingHintText"
+ android:id="@+id/custom_content_hint"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="top|start"
+ android:layout_marginStart="30dp"
+ android:layout_marginTop="120dp"
+ android:gravity="start"
+ android:maxWidth="160dp"
+ android:visibility="gone"
+ android:drawableStart="@drawable/cling_arrow_start"
+ android:drawablePadding="10dp"
+ android:text="@string/first_run_cling_custom_content_hint" />
+ <TextView
+ style="@style/ClingHintText"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="bottom|end"
+ android:layout_marginEnd="30dp"
+ android:layout_marginBottom="120dp"
+ android:maxWidth="180dp"
+ android:drawableEnd="@drawable/cling_arrow_end"
+ android:drawablePadding="10dp"
+ android:text="@string/first_run_cling_create_screens_hint" />
+ </FrameLayout>
+ <Button
+ style="@style/ClingButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="30dp"
+ android:layout_marginEnd="30dp"
+ android:layout_gravity="bottom|end"
+ android:onClick="dismissFirstRunCling" />
+</com.android.launcher3.Cling>
diff --git a/res/layout-sw600dp-port/folder_cling.xml b/res/layout-sw600dp-port/folder_cling.xml
deleted file mode 100644
index 87086cb62..000000000
--- a/res/layout-sw600dp-port/folder_cling.xml
+++ /dev/null
@@ -1,51 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<com.android.launcher3.Cling
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3"
- launcher:drawIdentifier="folder_portrait">
- <FrameLayout
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_marginStart="20dp"
- android:layout_marginEnd="10dp"
- android:layout_marginTop="@dimen/folderClingMarginTop">
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical">
- <TextView
- style="@style/ClingTitleText"
- android:id="@+id/folder_cling_title"
- android:text="@string/folder_cling_title" />
- <TextView
- style="@style/ClingText"
- android:id="@+id/folder_cling_create_folder"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/folder_cling_create_folder" />
- </LinearLayout>
- </FrameLayout>
- <Button
- style="@style/ClingButton"
- android:id="@+id/cling_dismiss"
- android:minWidth="168dp"
- android:textSize="24sp"
- android:layout_marginBottom="27dp"
- android:layout_marginEnd="36dp"
- android:layout_gravity="bottom|end"
- android:onClick="dismissFolderCling" />
-</com.android.launcher3.Cling>
diff --git a/res/layout-sw600dp-port/migration_workspace_cling.xml b/res/layout-sw600dp-port/migration_workspace_cling.xml
new file mode 100644
index 000000000..eb13137a1
--- /dev/null
+++ b/res/layout-sw600dp-port/migration_workspace_cling.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<com.android.launcher3.Cling
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ launcher:drawIdentifier="migration_workspace_large_portrait">
+ <FrameLayout
+ android:id="@+id/content"
+ android:layout_width="480dp"
+ android:layout_height="match_parent"
+ android:layout_gravity="bottom|center_horizontal">
+ <LinearLayout
+ android:id="@+id/migration_workspace_cling_bubble"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="bottom"
+ android:layout_marginStart="25dp"
+ android:layout_marginEnd="25dp"
+ android:orientation="vertical">
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginRight="4dp"
+ android:paddingLeft="20dp"
+ android:paddingRight="20dp"
+ android:paddingTop="20dp"
+ android:paddingBottom="20dp"
+ android:orientation="vertical"
+ android:background="@drawable/cling">
+ <TextView
+ style="@style/ClingTitleText"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/workspace_cling_title" />
+ <TextView
+ style="@style/ClingText"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/workspace_cling_move_item" />
+ </LinearLayout>
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:src="@drawable/cling_arrow_down" />
+ <Button
+ style="@style/ClingButton"
+ android:id="@+id/dismiss_migration_workspace_cling_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="right"
+ android:onClick="dismissMigrationWorkspaceCling" />
+ </LinearLayout>
+ </FrameLayout>
+</com.android.launcher3.Cling>
diff --git a/res/layout-sw600dp/first_run_cling.xml b/res/layout-sw600dp/first_run_cling.xml
new file mode 100644
index 000000000..295765b6e
--- /dev/null
+++ b/res/layout-sw600dp/first_run_cling.xml
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<com.android.launcher3.Cling
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ launcher:drawIdentifier="first_run_landscape">
+ <FrameLayout
+ android:id="@+id/content"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <LinearLayout
+ android:id="@+id/bubble_content"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:layout_marginLeft="100dp"
+ android:layout_marginRight="100dp"
+ android:orientation="vertical">
+ <TextView
+ style="@style/ClingAltTitleText"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:layout_marginBottom="10dp"
+ android:text="@string/first_run_cling_title"
+ android:textColor="#FFFFFFFF"
+ android:gravity="center" />
+ <TextView
+ style="@style/ClingAltText"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:text="@string/first_run_cling_description"
+ android:textColor="#80000000"
+ android:gravity="center" />
+ </LinearLayout>
+ <TextView
+ style="@style/ClingHintText"
+ android:id="@+id/search_bar_hint"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="top|start"
+ android:layout_marginStart="60dp"
+ android:layout_marginTop="105dp"
+ android:gravity="start"
+ android:maxWidth="160dp"
+ android:visibility="gone"
+ android:drawableStart="@drawable/cling_arrow_start"
+ android:drawablePadding="10dp"
+ android:text="@string/first_run_cling_search_bar_hint" />
+ <TextView
+ style="@style/ClingHintText"
+ android:id="@+id/custom_content_hint"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="top|start"
+ android:layout_marginStart="60dp"
+ android:layout_marginTop="200dp"
+ android:gravity="start"
+ android:maxWidth="160dp"
+ android:visibility="gone"
+ android:drawableStart="@drawable/cling_arrow_start"
+ android:drawablePadding="10dp"
+ android:text="@string/first_run_cling_custom_content_hint" />
+ <TextView
+ style="@style/ClingHintText"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="bottom|end"
+ android:layout_marginEnd="30dp"
+ android:layout_marginBottom="120dp"
+ android:maxWidth="180dp"
+ android:drawableEnd="@drawable/cling_arrow_end"
+ android:drawablePadding="10dp"
+ android:text="@string/first_run_cling_create_screens_hint" />
+ </FrameLayout>
+ <Button
+ style="@style/ClingButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="30dp"
+ android:layout_marginEnd="30dp"
+ android:layout_gravity="bottom|end"
+ android:onClick="dismissFirstRunCling" />
+</com.android.launcher3.Cling>
diff --git a/res/layout-sw600dp/folder_cling.xml b/res/layout-sw600dp/folder_cling.xml
new file mode 100644
index 000000000..f21aef4e4
--- /dev/null
+++ b/res/layout-sw600dp/folder_cling.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<com.android.launcher3.Cling
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3"
+ launcher:drawIdentifier="folder_large">
+ <LinearLayout
+ android:id="@+id/folder_bubble"
+ android:layout_width="300dp"
+ android:layout_height="match_parent"
+ android:layout_gravity="left|top"
+ android:paddingTop="28dp"
+ android:paddingRight="10dp"
+ android:orientation="vertical">
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:src="@drawable/cling_arrow_start" />
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginRight="4dp"
+ android:paddingLeft="20dp"
+ android:paddingRight="20dp"
+ android:paddingTop="20dp"
+ android:paddingBottom="20dp"
+ android:orientation="vertical"
+ android:background="@drawable/cling">
+ <TextView
+ style="@style/ClingTitleText"
+ android:id="@+id/folder_cling_title"
+ android:text="@string/folder_cling_title" />
+ <TextView
+ style="@style/ClingText"
+ android:id="@+id/folder_cling_create_folder"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/folder_cling_create_folder" />
+ </LinearLayout>
+ </LinearLayout>
+ <Button
+ style="@style/ClingButton"
+ android:id="@+id/cling_dismiss"
+ android:layout_marginTop="5dp"
+ android:layout_gravity="right"
+ android:onClick="dismissFolderCling" />
+ </LinearLayout>
+</com.android.launcher3.Cling>
diff --git a/res/layout-sw600dp/migration_cling.xml b/res/layout-sw600dp/migration_cling.xml
new file mode 100644
index 000000000..19def6a56
--- /dev/null
+++ b/res/layout-sw600dp/migration_cling.xml
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<com.android.launcher3.Cling
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ launcher:drawIdentifier="migration_portrait">
+ <LinearLayout
+ android:id="@+id/content"
+ android:layout_width="360dp"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:orientation="vertical">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="top"
+ android:layout_marginBottom="15dp"
+ android:orientation="vertical">
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:text="@string/first_run_cling_title"
+ android:textSize="42dp"
+ android:textColor="#FFffffff" />
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="10dp"
+ android:layout_marginBottom="0dp"
+ android:layout_gravity="center_horizontal"
+ android:src="@drawable/on_boarding_welcome" />
+
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:src="@drawable/cling_arrow_up" />
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="4dp"
+ android:layout_marginRight="4dp"
+ android:paddingLeft="25dp"
+ android:paddingRight="25dp"
+ android:paddingTop="20dp"
+ android:paddingBottom="20dp"
+ android:orientation="vertical"
+ android:background="@drawable/cling">
+ <TextView
+ style="@style/ClingTitleText"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/migration_cling_title" />
+ <TextView
+ style="@style/ClingText"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/migration_cling_description" />
+ </LinearLayout>
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="bottom"
+ android:orientation="vertical">
+ <Button
+ style="@style/ClingButton"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/migration_cling_copy_apps"
+ android:onClick="dismissMigrationClingCopyApps" />
+ <Button
+ style="@style/ClingButton"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/migration_cling_use_default"
+ android:onClick="dismissMigrationClingUseDefault" />
+ </LinearLayout>
+ </LinearLayout>
+</com.android.launcher3.Cling>
diff --git a/res/layout-land/all_apps_cling.xml b/res/layout-sw600dp/workspace_cling.xml
index 19a93a5f3..63b5522ca 100644
--- a/res/layout-land/all_apps_cling.xml
+++ b/res/layout-sw600dp/workspace_cling.xml
@@ -18,47 +18,48 @@
xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3"
android:layout_width="match_parent"
android:layout_height="match_parent"
- launcher:drawIdentifier="all_apps">
+ launcher:drawIdentifier="workspace_large">
<FrameLayout
android:id="@+id/content"
android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_marginStart="25dp"
- android:layout_marginEnd="25dp"
- android:layout_marginTop="310dp">
+ android:layout_height="match_parent">
<LinearLayout
- android:layout_width="match_parent"
+ android:id="@+id/workspace_cling_bubble"
+ android:layout_width="400dp"
android:layout_height="wrap_content"
- android:layout_gravity="top"
+ android:layout_gravity="center_horizontal|bottom"
android:orientation="vertical">
<LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
android:paddingLeft="20dp"
android:paddingRight="20dp"
android:paddingTop="20dp"
android:paddingBottom="20dp"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
android:orientation="vertical"
android:background="@drawable/cling">
<TextView
style="@style/ClingTitleText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:text="@string/all_apps_cling_cm" />
+ android:text="@string/workspace_cling_title" />
<TextView
style="@style/ClingText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:text="@string/all_apps_cling_summary" />
+ android:text="@string/workspace_cling_move_item" />
</LinearLayout>
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:src="@drawable/cling_arrow_down" />
+ <Button
+ style="@style/ClingButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="right"
+ android:onClick="dismissWorkspaceCling" />
</LinearLayout>
</FrameLayout>
- <Button
- style="@style/ClingButton"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginBottom="15dp"
- android:layout_marginEnd="20dp"
- android:layout_gravity="bottom|end"
- android:onClick="dismissAllAppsCling" />
</com.android.launcher3.Cling>
diff --git a/res/layout-sw720dp-port/folder_cling.xml b/res/layout-sw720dp-port/folder_cling.xml
deleted file mode 100644
index 40d4e20a5..000000000
--- a/res/layout-sw720dp-port/folder_cling.xml
+++ /dev/null
@@ -1,46 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<com.android.launcher3.Cling
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3"
- launcher:drawIdentifier="folder_large">
- <FrameLayout
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_marginStart="@dimen/cling_text_block_offset_x"
- android:layout_marginTop="@dimen/cling_text_block_offset_y">
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical">
- <TextView
- style="@style/ClingTitleText"
- android:id="@+id/folder_cling_title"
- android:text="@string/folder_cling_title" />
- <TextView
- style="@style/ClingText"
- android:id="@+id/folder_cling_create_folder"
- android:layout_width="480dp"
- android:layout_height="wrap_content"
- android:text="@string/folder_cling_create_folder" />
- <Button
- style="@style/ClingButton"
- android:id="@+id/cling_dismiss"
- android:layout_marginTop="15dp"
- android:onClick="dismissFolderCling" />
- </LinearLayout>
- </FrameLayout>
-</com.android.launcher3.Cling>
diff --git a/res/layout-sw720dp/first_run_cling.xml b/res/layout-sw720dp/first_run_cling.xml
new file mode 100644
index 000000000..c43d8d32e
--- /dev/null
+++ b/res/layout-sw720dp/first_run_cling.xml
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<com.android.launcher3.Cling
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ launcher:drawIdentifier="first_run_portrait">
+ <FrameLayout
+ android:id="@+id/content"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <LinearLayout
+ android:id="@+id/bubble_content"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:layout_marginLeft="100dp"
+ android:layout_marginRight="100dp"
+ android:orientation="vertical">
+ <TextView
+ style="@style/ClingAltTitleText"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:layout_marginBottom="10dp"
+ android:text="@string/first_run_cling_title"
+ android:textColor="#FFFFFFFF"
+ android:gravity="center" />
+ <TextView
+ style="@style/ClingAltText"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:text="@string/first_run_cling_description"
+ android:textColor="#80000000"
+ android:gravity="center" />
+ </LinearLayout>
+ <TextView
+ style="@style/ClingHintText"
+ android:id="@+id/search_bar_hint"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="top|end"
+ android:layout_marginEnd="120dp"
+ android:layout_marginTop="80dp"
+ android:gravity="center_horizontal"
+ android:maxWidth="160dp"
+ android:visibility="gone"
+ android:drawableTop="@drawable/cling_arrow_up"
+ android:drawablePadding="10dp"
+ android:text="@string/first_run_cling_search_bar_hint" />
+ <TextView
+ style="@style/ClingHintText"
+ android:id="@+id/custom_content_hint"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical|start"
+ android:layout_marginStart="30dp"
+ android:gravity="start"
+ android:maxWidth="160dp"
+ android:visibility="gone"
+ android:drawableStart="@drawable/cling_arrow_start"
+ android:drawablePadding="10dp"
+ android:text="@string/first_run_cling_custom_content_hint" />
+ <TextView
+ style="@style/ClingHintText"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical|end"
+ android:layout_marginEnd="30dp"
+ android:maxWidth="180dp"
+ android:drawableEnd="@drawable/cling_arrow_end"
+ android:drawablePadding="10dp"
+ android:text="@string/first_run_cling_create_screens_hint" />
+ </FrameLayout>
+ <Button
+ style="@style/ClingButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="30dp"
+ android:layout_marginEnd="40dp"
+ android:layout_gravity="bottom|end"
+ android:onClick="dismissFirstRunCling" />
+</com.android.launcher3.Cling>
diff --git a/res/layout-sw720dp/launcher.xml b/res/layout-sw720dp/launcher.xml
index 7b0d770ec..d7d67cc3f 100644
--- a/res/layout-sw720dp/launcher.xml
+++ b/res/layout-sw720dp/launcher.xml
@@ -36,7 +36,6 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
launcher:defaultScreen="@integer/config_workspaceDefaultScreen"
- launcher:pageSpacing="@dimen/workspace_page_spacing"
launcher:pageIndicator="@id/page_indicator">
</com.android.launcher3.Workspace>
@@ -46,8 +45,8 @@
android:layout_height="match_parent" />
<include
- android:id="@+id/qsb_bar"
- layout="@layout/qsb_bar" />
+ android:id="@+id/search_drop_target_bar"
+ layout="@layout/search_drop_target_bar" />
<!-- Keep these behind the workspace so that they are not visible when
we go into AllApps -->
@@ -61,17 +60,31 @@
<!-- The Workspace cling must appear under the AppsCustomizePagedView below to ensure
that it is still visible during the transition to AllApps and doesn't overlay on
top of that view. -->
+ <com.android.launcher3.ScrimView
+ android:id="@+id/cling_scrim"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:visibility="gone" />
<include layout="@layout/first_run_cling"
android:id="@+id/first_run_cling"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone" />
+ <include layout="@layout/migration_cling"
+ android:id="@+id/migration_cling"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:visibility="gone" />
+ <include layout="@layout/migration_workspace_cling"
+ android:id="@+id/migration_workspace_cling"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:visibility="gone" />
<include layout="@layout/workspace_cling"
android:id="@+id/workspace_cling"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone" />
-
<include layout="@layout/folder_cling"
android:id="@+id/folder_cling"
android:layout_width="match_parent"
@@ -94,12 +107,6 @@
android:layout_height="match_parent"
android:visibility="invisible" />
- <include layout="@layout/all_apps_cling"
- android:id="@+id/all_apps_cling"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:visibility="gone" />
-
<include layout="@layout/overview_panel"
android:id="@+id/overview_panel"
android:visibility="gone" />
diff --git a/res/layout-sw720dp/market_button.xml b/res/layout-sw720dp/market_button.xml
index f1e99599e..7eaeafac3 100644
--- a/res/layout-sw720dp/market_button.xml
+++ b/res/layout-sw720dp/market_button.xml
@@ -18,8 +18,8 @@
style="@style/MarketButton"
android:onClick="onClickAppMarketButton"
android:gravity="center"
- android:paddingStart="32dp"
- android:paddingEnd="32dp"
+ android:paddingLeft="32dp"
+ android:paddingRight="32dp"
android:drawablePadding="10dp"
android:background="@drawable/tab_widget_indicator_selector"
android:text="@string/market"
diff --git a/res/layout-sw720dp/migration_workspace_cling.xml b/res/layout-sw720dp/migration_workspace_cling.xml
new file mode 100644
index 000000000..eb13137a1
--- /dev/null
+++ b/res/layout-sw720dp/migration_workspace_cling.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<com.android.launcher3.Cling
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ launcher:drawIdentifier="migration_workspace_large_portrait">
+ <FrameLayout
+ android:id="@+id/content"
+ android:layout_width="480dp"
+ android:layout_height="match_parent"
+ android:layout_gravity="bottom|center_horizontal">
+ <LinearLayout
+ android:id="@+id/migration_workspace_cling_bubble"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="bottom"
+ android:layout_marginStart="25dp"
+ android:layout_marginEnd="25dp"
+ android:orientation="vertical">
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginRight="4dp"
+ android:paddingLeft="20dp"
+ android:paddingRight="20dp"
+ android:paddingTop="20dp"
+ android:paddingBottom="20dp"
+ android:orientation="vertical"
+ android:background="@drawable/cling">
+ <TextView
+ style="@style/ClingTitleText"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/workspace_cling_title" />
+ <TextView
+ style="@style/ClingText"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/workspace_cling_move_item" />
+ </LinearLayout>
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:src="@drawable/cling_arrow_down" />
+ <Button
+ style="@style/ClingButton"
+ android:id="@+id/dismiss_migration_workspace_cling_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="right"
+ android:onClick="dismissMigrationWorkspaceCling" />
+ </LinearLayout>
+ </FrameLayout>
+</com.android.launcher3.Cling>
diff --git a/res/layout-port/search_bar.xml b/res/layout-sw720dp/qsb.xml
index 1c96ca380..399666ab0 100644
--- a/res/layout-port/search_bar.xml
+++ b/res/layout-sw720dp/qsb.xml
@@ -19,10 +19,10 @@
style="@style/SearchDropTargetBar"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:background="@drawable/search_frame">
+ android:background="@drawable/search_bg">
<!-- Global search icon -->
<com.android.launcher3.HolographicLinearLayout
- style="@style/SearchButton"
+ style="@style/SearchButton.WithPaddingStart"
launcher:sourceImageViewId="@+id/search_button"
android:id="@+id/search_button_container"
android:layout_width="match_parent"
@@ -31,7 +31,6 @@
android:layout_centerVertical="true"
android:layout_alignParentStart="true"
android:layout_toStartOf="@+id/voice_button_container"
- android:paddingStart="8dp"
android:onClick="onClickSearchButton"
android:focusable="true"
android:clickable="true"
@@ -57,6 +56,7 @@
android:layout_centerVertical="true"
android:layout_alignParentEnd="true"
android:paddingEnd="8dp"
+ android:paddingRight="8dp"
android:onClick="onClickVoiceButton"
android:focusable="true"
android:clickable="true"
diff --git a/res/layout/add_list_item.xml b/res/layout/add_list_item.xml
index 0ae011330..e937d7bc1 100644
--- a/res/layout/add_list_item.xml
+++ b/res/layout/add_list_item.xml
@@ -21,5 +21,5 @@
android:textAppearance="?android:attr/textAppearanceLarge"
android:gravity="center_vertical"
android:drawablePadding="14dip"
- android:paddingStart="15dip"
- android:paddingEnd="15dip" />
+ android:paddingLeft="15dip"
+ android:paddingRight="15dip" />
diff --git a/res/layout/apps_customize_pane.xml b/res/layout/apps_customize_pane.xml
index bc10e708a..1352e1904 100644
--- a/res/layout/apps_customize_pane.xml
+++ b/res/layout/apps_customize_pane.xml
@@ -27,19 +27,17 @@
android:id="@+id/apps_customize_pane_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:layout_marginBottom="@dimen/apps_customize_page_indicator_offset"
launcher:widgetCountX="@integer/apps_customize_widget_cell_count_x"
launcher:widgetCountY="@integer/apps_customize_widget_cell_count_y"
launcher:clingFocusedX="@integer/apps_customize_cling_focused_x"
launcher:clingFocusedY="@integer/apps_customize_cling_focused_y"
launcher:maxGap="@dimen/workspace_max_gap"
- launcher:pageIndicator="@+id/page_indicator" />
+ launcher:pageIndicator="@+id/apps_customize_page_indicator" />
<include
- android:id="@+id/page_indicator"
+ android:id="@+id/apps_customize_page_indicator"
layout="@layout/page_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_gravity="bottom|center_horizontal"
- android:layout_marginBottom="@dimen/apps_customize_page_indicator_margin" />
+ android:layout_gravity="center_horizontal|bottom" />
</FrameLayout>
</com.android.launcher3.AppsCustomizeLayout>
diff --git a/res/layout/apps_customize_widget.xml b/res/layout/apps_customize_widget.xml
index f2d234266..7c98b4a9b 100644
--- a/res/layout/apps_customize_widget.xml
+++ b/res/layout/apps_customize_widget.xml
@@ -28,12 +28,13 @@
<!-- The preview of the widget or shortcut. -->
<com.android.launcher3.PagedViewWidgetImageView
android:id="@+id/widget_preview"
+ style="@style/PagedViewWidgetImageView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:paddingTop="@dimen/app_widget_preview_padding_top"
- android:paddingStart="@dimen/app_widget_preview_padding_left"
android:paddingEnd="@dimen/app_widget_preview_padding_right"
+ android:paddingRight="@dimen/app_widget_preview_padding_right"
android:scaleType="matrix"
android:background="@drawable/screenpanel" />
<LinearLayout
diff --git a/res/layout/appwidget_error.xml b/res/layout/appwidget_error.xml
index f5a914819..03d4ae424 100644
--- a/res/layout/appwidget_error.xml
+++ b/res/layout/appwidget_error.xml
@@ -19,8 +19,8 @@
android:layout_height="wrap_content"
android:paddingTop="10dip"
android:paddingBottom="10dip"
- android:paddingStart="20dip"
- android:paddingEnd="20dip"
+ android:paddingLeft="20dip"
+ android:paddingRight="20dip"
android:gravity="center"
android:background="@drawable/bg_appwidget_error"
android:textAppearance="?android:attr/textAppearanceMediumInverse"
diff --git a/res/layout/custom_grid_size_dialog.xml b/res/layout/custom_grid_size_dialog.xml
new file mode 100644
index 000000000..d7345ee56
--- /dev/null
+++ b/res/layout/custom_grid_size_dialog.xml
@@ -0,0 +1,33 @@
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" >
+
+ <LinearLayout
+ android:id="@+id/grid_number_pickers"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerHorizontal="true"
+ android:orientation="horizontal">
+
+ <NumberPicker
+ android:id="@+id/custom_rows"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginRight="@dimen/dialog_padding"/>
+
+ <NumberPicker
+ android:id="@+id/custom_columns"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="@dimen/dialog_padding"/>
+
+ </LinearLayout>
+
+ <Button
+ android:id="@+id/dialog_confirm_button"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/dialog_confirm"
+ android:layout_below="@id/grid_number_pickers"
+ android:layout_marginTop="@dimen/dialog_padding"/>
+</RelativeLayout> \ No newline at end of file
diff --git a/res/layout/custom_workspace_cling.xml b/res/layout/custom_workspace_cling.xml
deleted file mode 100644
index 3744f2e4b..000000000
--- a/res/layout/custom_workspace_cling.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<!-- dummy layout, to be replaced in overlays -->
-<com.android.launcher3.Cling
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- launcher:drawIdentifier="workspace_custom">
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textSize="20dp"
- android:textColor="@android:color/holo_blue_light"
- android:text="@string/dummy_custom_cling_error_message"
- android:gravity="start"
- android:layout_gravity="bottom|start"
- />
-</com.android.launcher3.Cling>
diff --git a/res/layout/dynamic_grid_size_screen.xml b/res/layout/dynamic_grid_size_screen.xml
new file mode 100644
index 000000000..38db4b05c
--- /dev/null
+++ b/res/layout/dynamic_grid_size_screen.xml
@@ -0,0 +1,52 @@
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_gravity="center_horizontal|bottom"
+ android:background="@color/settings_bg_color"
+ android:orientation="vertical"
+ android:paddingBottom="@dimen/overview_panel_bottom_padding"
+ android:paddingTop="@dimen/overview_panel_bottom_padding"
+ android:clickable="true" >
+
+ <LinearLayout
+ android:id="@+id/dynamic_grid_title"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:background="@drawable/listitem_bg"
+ android:clickable="true" >
+
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:adjustViewBounds="true"
+ android:src="@drawable/handle_left" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/grid_size_text"
+ android:textAllCaps="true"
+ android:fontFamily="sans-serif-condensed"
+ android:textColor="@android:color/white"
+ android:layout_gravity="center_vertical"
+ android:textSize="16sp" />
+ </LinearLayout>
+
+ <ImageView
+ android:id="@+id/dynamic_grid_size_image"
+ android:layout_width="@dimen/dynamic_grid_size_image_width"
+ android:layout_height="@dimen/dynamic_grid_size_image_height"
+ android:layout_gravity="center_horizontal"
+ android:adjustViewBounds="true"
+ android:layout_marginBottom="@dimen/grid_padding"/>
+
+ <ListView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/dynamic_grid_list"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:listSelector="@android:color/transparent"
+ android:splitMotionEvents="false"/>
+</LinearLayout>
diff --git a/res/layout/folder_icon.xml b/res/layout/folder_icon.xml
index 44056828c..5147f9960 100644
--- a/res/layout/folder_icon.xml
+++ b/res/layout/folder_icon.xml
@@ -30,5 +30,8 @@
android:src="@drawable/portal_ring_inner_holo"/>
<com.android.launcher3.BubbleTextView
style="@style/WorkspaceIcon"
- android:id="@+id/folder_icon_name" />
+ android:id="@+id/folder_icon_name"
+ android:layout_gravity="top"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
</com.android.launcher3.FolderIcon>
diff --git a/res/layout/hidden_folder.xml b/res/layout/hidden_folder.xml
new file mode 100644
index 000000000..ca06f6e48
--- /dev/null
+++ b/res/layout/hidden_folder.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@color/settings_bg_color"
+ android:orientation="vertical"
+ android:paddingLeft="@dimen/overview_panel_button_spacing"
+ android:paddingRight="@dimen/overview_panel_button_spacing"
+ android:paddingTop="@dimen/overview_panel_bottom_padding"
+ android:focusable="true"
+ android:focusableInTouchMode="true"
+ android:clickable="true" >
+
+ <RelativeLayout
+ android:id="@+id/folder_title_lock"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal" >
+ <ImageView
+ android:id="@+id/folder_lock_icon"
+ android:layout_width="25dp"
+ android:layout_height="25dp"
+ android:layout_alignParentRight="true"
+ android:layout_centerVertical="true"
+ android:src="@drawable/folder_unlock"
+ android:background="@drawable/listitem_bg" />
+
+ <EditText
+ android:id="@+id/folder_name"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:paddingBottom="@dimen/folder_name_padding"
+ android:paddingTop="@dimen/folder_name_padding"
+ android:hint="@string/folder_hint_text"
+ android:textColor="@android:color/white"
+ android:textSize="20sp"
+ android:textColorHighlight="#ffCCCCCC"
+ android:textCursorDrawable="@null"
+ android:singleLine="true"
+ android:background="#00000000" />
+ </RelativeLayout>
+
+ <ListView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/hidden_apps_list"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="5dp" />
+
+</LinearLayout>
diff --git a/res/layout/hidden_folder_apps_list_item.xml b/res/layout/hidden_folder_apps_list_item.xml
new file mode 100644
index 000000000..f3af4ad1d
--- /dev/null
+++ b/res/layout/hidden_folder_apps_list_item.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:minHeight="48dp"
+ android:gravity="center_vertical"
+ android:paddingRight="?android:attr/scrollbarSize"
+ android:background="?android:attr/selectableItemBackground">
+
+ <ImageView android:id="@+id/icon"
+ android:layout_width="40dp"
+ android:layout_height="40dp"
+ android:layout_gravity="center" />
+
+ <TextView android:id="@+id/title"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="15dip"
+ android:layout_marginRight="6dip"
+ android:layout_marginTop="6dip"
+ android:layout_marginBottom="6dip"
+ android:layout_weight="1"
+ android:singleLine="true"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:ellipsize="marquee"
+ android:fadingEdge="horizontal" />
+
+ <ImageView android:id="@+id/remove"
+ android:layout_width="40dp"
+ android:layout_height="40dp"
+ android:layout_gravity="center"
+ android:src="@drawable/ic_remove"/>
+</LinearLayout> \ No newline at end of file
diff --git a/res/layout/iconpack_chooser.xml b/res/layout/iconpack_chooser.xml
deleted file mode 100644
index 105a95969..000000000
--- a/res/layout/iconpack_chooser.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:orientation="horizontal">
- <ImageView
- android:id="@+id/icon"
- android:layout_gravity="center_vertical"
- android:layout_width="@dimen/app_icon_size"
- android:layout_height="@dimen/app_icon_size"
- android:layout_margin="8dp"/>
- <TextView
- android:id="@+id/title"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:paddingStart="8dip"
- android:paddingEnd="8dip"
- android:layout_gravity="center_vertical"
- android:layout_weight="1"
- android:textAppearance="?android:attr/textAppearanceLarge"
- android:textSize="19sp"/>
- <RadioButton
- android:id="@+id/radio"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
- android:focusable="false"
- android:clickable="false"
- android:duplicateParentState="true" />
-</LinearLayout>
diff --git a/res/layout/market_button.xml b/res/layout/market_button.xml
index 4a718c3d6..41e6ec7cc 100644
--- a/res/layout/market_button.xml
+++ b/res/layout/market_button.xml
@@ -18,8 +18,8 @@
style="@style/MarketButton"
android:onClick="onClickAppMarketButton"
android:gravity="center"
- android:paddingStart="16dp"
- android:paddingEnd="16dp"
+ android:paddingLeft="16dp"
+ android:paddingRight="16dp"
android:background="@drawable/tab_widget_indicator_selector"
android:contentDescription="@string/market"
android:shadowColor="@color/workspace_all_apps_and_delete_zone_text_shadow_color"
diff --git a/res/layout/overview_panel.xml b/res/layout/overview_panel.xml
index 479b622ec..cf9f616d7 100644
--- a/res/layout/overview_panel.xml
+++ b/res/layout/overview_panel.xml
@@ -1,7 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2013 The Android Open Source Project
+<!--
+ Copyright (C) 2013 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
+ Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
@@ -13,138 +14,37 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<FrameLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
+
+<com.android.launcher3.SlidingUpPanelLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:slidingpanel="http://schemas.android.com/apk/res/com.android.launcher3"
+ android:id="@+id/sliding_layout"
android:layout_width="match_parent"
- android:layout_height="match_parent">
+ android:layout_height="match_parent"
+ android:gravity="bottom"
+ slidingpanel:overlay="false"
+ slidingpanel:panelHeight="@dimen/sliding_panel_padding" >
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="wrap_content"
+ android:id="@+id/default_home_screen_panel"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:layout_gravity="center_horizontal|top"
- android:paddingTop="@dimen/overview_panel_top_padding">
+ android:layout_gravity="center_horizontal"
+ android:background="@color/settings_bg_color"
+ android:paddingTop="@dimen/overview_panel_top_padding" >
- <TextView
+ <ImageView
android:id="@+id/default_screen_button"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/app_icon_size"
android:layout_weight="1"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
+ android:src="@drawable/default_screen_button"
+ android:scaleType="fitCenter"
+ android:gravity="top"
android:paddingLeft="@dimen/overview_panel_button_spacing"
- android:paddingRight="@dimen/overview_panel_button_spacing"
- android:text="@string/default_screen_button_text"
- android:drawablePadding="4dp"
- android:drawableTop="@drawable/default_screen_button"
- android:gravity="center_horizontal"
- android:fontFamily="sans-serif-condensed"
- android:textAllCaps="true"
- android:textSize="12sp" />
-
- <TextView
- android:id="@+id/transition_effect_button"
- android:layout_weight="1"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:paddingLeft="@dimen/overview_panel_button_spacing"
- android:paddingRight="@dimen/overview_panel_button_spacing"
- android:text="@string/transition_effect_button_text"
- android:drawablePadding="4dp"
- android:drawableTop="@drawable/wallpaper_button"
- android:gravity="center_horizontal"
- android:fontFamily="sans-serif-condensed"
- android:textAllCaps="true"
- android:textSize="12sp" />
-
- <TextView
- android:id="@+id/icon_pack_button"
- android:layout_weight="1"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:paddingLeft="@dimen/overview_panel_button_spacing"
- android:paddingRight="@dimen/overview_panel_button_spacing"
- android:text="@string/icon_packs_title"
- android:drawablePadding="4dp"
- android:drawableTop="@drawable/iconpack_button"
- android:gravity="center_horizontal"
- android:fontFamily="sans-serif-condensed"
- android:textAllCaps="true"
- android:textSize="12sp" />
-
+ android:paddingRight="@dimen/overview_panel_button_spacing"/>
</LinearLayout>
- <LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:layout_gravity="center_horizontal|bottom"
- android:paddingBottom="@dimen/overview_panel_bottom_padding">
+ <include layout="@layout/settings_pane" />
- <TextView
- android:id="@+id/wallpaper_button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:paddingLeft="@dimen/overview_panel_button_spacing"
- android:paddingRight="@dimen/overview_panel_button_spacing"
- android:text="@string/wallpaper_button_text"
- android:drawablePadding="4dp"
- android:drawableTop="@drawable/wallpaper_button"
- android:gravity="center_horizontal"
- android:fontFamily="sans-serif-condensed"
- android:textAllCaps="true"
- android:textSize="12sp" />
- <TextView
- android:id="@+id/sort_button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:paddingLeft="@dimen/overview_panel_button_spacing"
- android:paddingRight="@dimen/overview_panel_button_spacing"
- android:text="@string/sort_button_text"
- android:drawablePadding="4dp"
- android:drawableTop="@drawable/wallpaper_button"
- android:gravity="center_horizontal"
- android:fontFamily="sans-serif-condensed"
- android:textAllCaps="true"
- android:textSize="12sp" />
- <TextView
- android:id="@+id/widget_button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:paddingLeft="@dimen/overview_panel_button_spacing"
- android:paddingRight="@dimen/overview_panel_button_spacing"
- android:text="@string/widget_button_text"
- android:drawablePadding="4dp"
- android:gravity="center_horizontal"
- android:drawableTop="@drawable/widget_button"
- android:fontFamily="sans-serif-condensed"
- android:textAllCaps="true"
- android:textSize="12sp"/>
- <TextView
- android:id="@+id/filter_button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:paddingLeft="@dimen/overview_panel_button_spacing"
- android:paddingRight="@dimen/overview_panel_button_spacing"
- android:text="@string/filter_button_text"
- android:drawablePadding="4dp"
- android:gravity="center_horizontal"
- android:drawableTop="@drawable/widget_button"
- android:fontFamily="sans-serif-condensed"
- android:textAllCaps="true"
- android:textSize="12sp"/>
- <TextView
- android:id="@+id/settings_button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:paddingLeft="@dimen/overview_panel_button_spacing"
- android:paddingRight="@dimen/overview_panel_button_spacing"
- android:text="@string/settings_button_text"
- android:drawablePadding="4dp"
- android:gravity="center_horizontal"
- android:drawableTop="@drawable/setting_button"
- android:fontFamily="sans-serif-condensed"
- android:textAllCaps="true"
- android:textSize="12sp" />
- </LinearLayout>
-</FrameLayout>
+</com.android.launcher3.SlidingUpPanelLayout>
diff --git a/res/layout/qsb_bar.xml b/res/layout/search_drop_target_bar.xml
index 030acf6be..2d51b93ab 100644
--- a/res/layout/qsb_bar.xml
+++ b/res/layout/search_drop_target_bar.xml
@@ -15,14 +15,13 @@
-->
<com.android.launcher3.SearchDropTargetBar
xmlns:android="http://schemas.android.com/apk/res/android"
- style="@style/QSBBar"
+ android:orientation="horizontal"
android:focusable="false"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- Drag specific targets container -->
<LinearLayout
- style="@style/SearchDropTargetBar"
android:id="@+id/drag_target_bar"
android:layout_width="match_parent"
android:layout_height="match_parent"
diff --git a/res/layout/settings_pane.xml b/res/layout/settings_pane.xml
new file mode 100644
index 000000000..495d0997d
--- /dev/null
+++ b/res/layout/settings_pane.xml
@@ -0,0 +1,109 @@
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_gravity="center_horizontal|bottom"
+ android:background="@color/settings_bg_color"
+ android:orientation="vertical"
+ android:paddingBottom="@dimen/overview_panel_bottom_padding" >
+
+ <LinearLayout
+ android:id="@+id/settings_pane_header"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:paddingTop="@dimen/overview_panel_top_padding" >
+
+ <ImageView
+ android:id="@+id/settings_drag_arrow"
+ android:layout_width="@dimen/overview_panel_handle_size"
+ android:layout_height="@dimen/overview_panel_handle_size"
+ android:layout_gravity="center_horizontal"
+ android:adjustViewBounds="true"
+ android:background="@drawable/launcheranimatedarrow_00000"/>
+
+ <RelativeLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:layout_gravity="center_horizontal|bottom"
+ android:paddingBottom="@dimen/overview_panel_bottom_padding"
+ android:paddingTop="@dimen/overview_panel_list_padding"
+ android:layout_marginLeft="@dimen/overview_panel_button_spacing"
+ android:layout_marginRight="@dimen/overview_panel_button_spacing">
+
+ <TextView
+ android:id="@+id/wallpaper_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:drawablePadding="4dp"
+ android:drawableTop="@drawable/wallpaper_button"
+ android:fontFamily="sans-serif-condensed"
+ android:gravity="center_horizontal"
+ android:paddingLeft="@dimen/overview_panel_button_spacing"
+ android:paddingRight="@dimen/overview_panel_button_spacing"
+ android:text="@string/wallpaper_button_text"
+ android:textAllCaps="true"
+ android:textSize="12sp"
+ android:textColor="@android:color/white"
+ android:layout_alignParentTop="true"
+ android:layout_alignParentLeft="true"/>
+
+ <TextView
+ android:id="@+id/widget_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:drawablePadding="4dp"
+ android:drawableTop="@drawable/widget_button"
+ android:fontFamily="sans-serif-condensed"
+ android:gravity="center_horizontal"
+ android:paddingLeft="@dimen/overview_panel_button_spacing"
+ android:paddingRight="@dimen/overview_panel_button_spacing"
+ android:text="@string/widget_button_text"
+ android:textAllCaps="true"
+ android:textSize="12sp"
+ android:textColor="@android:color/white"
+ android:layout_alignParentTop="true"
+ android:layout_centerHorizontal="true" />
+
+ <TextView
+ android:id="@+id/themes_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:drawablePadding="4dp"
+ android:drawableTop="@drawable/themes_button"
+ android:fontFamily="sans-serif-condensed"
+ android:gravity="center_horizontal"
+ android:paddingLeft="@dimen/overview_panel_button_spacing"
+ android:paddingRight="@dimen/overview_panel_button_spacing"
+ android:text="@string/themes_button_text"
+ android:textAllCaps="true"
+ android:textSize="12sp"
+ android:textColor="@android:color/white"
+ android:layout_alignParentTop="true"
+ android:layout_alignParentRight="true" />
+
+ </RelativeLayout>
+ </LinearLayout>
+
+ <view
+ class="com.android.launcher3.list.PinnedHeaderListView"
+ android:id="@+id/settings_home_screen_listview"
+ android:layout_width="match_parent"
+ android:layout_height="0dip"
+ android:fastScrollEnabled="true"
+ android:layout_weight="1" />
+
+ </LinearLayout>
+
+ <LinearLayout
+ android:id="@+id/dark_panel"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@android:color/background_dark"
+ android:visibility="gone" />
+</FrameLayout> \ No newline at end of file
diff --git a/res/layout/settings_pane_list_header.xml b/res/layout/settings_pane_list_header.xml
new file mode 100644
index 000000000..700f5e773
--- /dev/null
+++ b/res/layout/settings_pane_list_header.xml
@@ -0,0 +1,19 @@
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal|bottom"
+ android:background="@color/settings_bg_color"
+ android:paddingLeft="@dimen/overview_panel_list_padding"
+ android:paddingRight="@dimen/overview_panel_list_padding"
+ android:orientation="horizontal" >
+
+ <TextView
+ android:id="@+id/item_name"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:drawablePadding="4dp"
+ android:fontFamily="sans-serif-condensed"
+ android:gravity="left"
+ android:textSize="16sp"
+ android:textColor="@color/settings_header_text"/>
+</RelativeLayout>
diff --git a/res/layout/settings_pane_list_item.xml b/res/layout/settings_pane_list_item.xml
new file mode 100644
index 000000000..0053f4c73
--- /dev/null
+++ b/res/layout/settings_pane_list_item.xml
@@ -0,0 +1,44 @@
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal|bottom"
+ android:background="@drawable/listitem_bg"
+ android:paddingLeft="@dimen/overview_panel_list_padding"
+ android:paddingRight="@dimen/overview_panel_list_padding"
+ android:orientation="horizontal" >
+
+ <TextView
+ android:id="@+id/item_name"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:drawablePadding="4dp"
+ android:fontFamily="sans-serif-condensed"
+ android:gravity="left"
+ android:paddingBottom="@dimen/overview_panel_list_padding"
+ android:paddingTop="@dimen/overview_panel_list_padding"
+ android:textSize="20sp"
+ android:textColor="@color/listitem_text"
+ android:layout_alignParentLeft="true"
+ android:scrollHorizontally="true"
+ android:ellipsize="end"
+ android:maxLines="1"/>
+
+ <TextView
+ android:id="@+id/item_state"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:drawablePadding="4dp"
+ android:fontFamily="sans-serif-condensed"
+ android:gravity="right"
+ android:paddingBottom="@dimen/overview_panel_list_padding"
+ android:paddingTop="@dimen/overview_panel_list_padding"
+ android:textSize="20sp"
+ android:textAllCaps="true"
+ android:textColor="@color/listitem_text"
+ android:layout_alignParentRight="true"
+ android:layout_toRightOf="@id/item_name"
+ android:scrollHorizontally="true"
+ android:ellipsize="end"
+ android:maxLines="1"/>
+
+</RelativeLayout> \ No newline at end of file
diff --git a/res/layout/settings_transitions_screen.xml b/res/layout/settings_transitions_screen.xml
new file mode 100644
index 000000000..37535e912
--- /dev/null
+++ b/res/layout/settings_transitions_screen.xml
@@ -0,0 +1,52 @@
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_gravity="center_horizontal|bottom"
+ android:background="@color/settings_bg_color"
+ android:orientation="vertical"
+ android:paddingBottom="@dimen/overview_panel_bottom_padding"
+ android:paddingTop="@dimen/overview_panel_bottom_padding"
+ android:clickable="true" >
+
+ <LinearLayout
+ android:id="@+id/transition_title"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:background="@drawable/listitem_bg"
+ android:clickable="true" >
+
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:adjustViewBounds="true"
+ android:src="@drawable/handle_left" />
+
+ <TextView
+ android:id="@+id/transition_effect_title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/scroll_effect_text"
+ android:textAllCaps="true"
+ android:fontFamily="sans-serif-condensed"
+ android:textColor="@android:color/white"
+ android:layout_gravity="center_vertical"
+ android:textSize="16sp" />
+ </LinearLayout>
+
+ <ImageView
+ android:id="@+id/settings_transition_image"
+ android:layout_width="150dp"
+ android:layout_height="150dp"
+ android:layout_gravity="center_horizontal"
+ android:adjustViewBounds="true" />
+
+ <ListView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/settings_transitions_list"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:listSelector="@android:color/transparent"
+ android:splitMotionEvents="false"/>
+</LinearLayout>
diff --git a/res/layout/user_folder.xml b/res/layout/user_folder.xml
index 5d5f33b1f..28476db69 100644
--- a/res/layout/user_folder.xml
+++ b/res/layout/user_folder.xml
@@ -34,21 +34,41 @@
android:hapticFeedbackEnabled="false" />
</ScrollView>
- <com.android.launcher3.FolderEditText
- android:id="@+id/folder_name"
+ <RelativeLayout
+ android:id="@+id/folder_title_section"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_centerHorizontal="true"
- android:paddingTop="@dimen/folder_name_padding"
- android:paddingBottom="@dimen/folder_name_padding"
- android:background="#00000000"
- android:hint="@string/folder_hint_text"
- android:textSize="14sp"
- android:textColor="#ff777777"
- android:textColorHighlight="#ffCCCCCC"
- android:textCursorDrawable="@null"
- android:gravity="center_horizontal"
- android:singleLine="true"
- android:imeOptions="flagNoExtractUi"
- android:fontFamily="sans-serif-condensed"/>
+ android:orientation="horizontal" >
+
+ <ImageView
+ android:id="@+id/folder_lock"
+ android:layout_width="@dimen/folder_lock_icon"
+ android:layout_height="@dimen/folder_lock_icon"
+ android:paddingBottom="@dimen/folder_name_padding"
+ android:paddingTop="@dimen/folder_name_padding"
+ android:adjustViewBounds="true"
+ android:layout_alignParentRight="true"
+ android:src="@drawable/folder_unlock" />
+
+ <com.android.launcher3.FolderEditText
+ android:id="@+id/folder_name"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerHorizontal="true"
+ android:background="#00000000"
+ android:fontFamily="sans-serif-condensed"
+ android:gravity="center_horizontal"
+ android:hint="@string/folder_hint_text"
+ android:imeOptions="flagNoExtractUi"
+ android:paddingBottom="@dimen/folder_name_padding"
+ android:paddingTop="@dimen/folder_name_padding"
+ android:singleLine="true"
+ android:textColor="#ff777777"
+ android:textColorHighlight="#ffCCCCCC"
+ android:textCursorDrawable="@null"
+ android:layout_alignParentLeft="true"
+ android:layout_toLeftOf="@id/folder_lock"
+ android:textSize="16sp" />
+ </RelativeLayout>
+
</com.android.launcher3.Folder>
diff --git a/res/layout/wallpaper_picker_clear.xml b/res/layout/wallpaper_picker_clear.xml
deleted file mode 100644
index 727c3b422..000000000
--- a/res/layout/wallpaper_picker_clear.xml
+++ /dev/null
@@ -1,42 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The CyanogenMod Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<com.android.launcher3.CheckableFrameLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="@dimen/wallpaperThumbnailWidth"
- android:layout_height="@dimen/wallpaperThumbnailHeight"
- android:focusable="true"
- android:clickable="true"
- android:background="@drawable/wallpaper_tile_fg"
- android:foreground="@drawable/wallpaper_tile_fg">
- <ImageView
- android:id="@+id/wallpaper_image"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:background="@color/wallpaper_picker_translucent_gray"
- android:scaleType="centerCrop" />
- <TextView
- android:id="@+id/wallpaper_item_label"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:ellipsize="marquee"
- android:gravity="center"
- android:layout_gravity="center"
- android:text="@string/clear_keyguard_wallpaper"
- android:drawableTop="@drawable/ic_clear"
- android:drawablePadding="4dp"
- android:textColor="@android:color/white"/>
-</com.android.launcher3.CheckableFrameLayout>
diff --git a/res/mipmap-xxhdpi/on_boarding_welcome.png b/res/mipmap-xxhdpi/on_boarding_welcome.png
new file mode 100644
index 000000000..7b11dea0e
--- /dev/null
+++ b/res/mipmap-xxhdpi/on_boarding_welcome.png
Binary files differ
diff --git a/res/values-af/cm_arrays.xml b/res/values-af/cm_arrays.xml
index 78bfee283..966761f24 100644
--- a/res/values-af/cm_arrays.xml
+++ b/res/values-af/cm_arrays.xml
@@ -16,19 +16,14 @@
limitations under the License.
-->
<resources>
- <string-array name="preferences_interface_general_icons_text_font_family_entries">
- <item>Gereelde</item>
- <item>Lig</item>
- <item>Verkorte</item>
- </string-array>
<string-array name="transition_effect_entries">
<item>Geen</item>
- <item>Zoom in</item>
- <item>Zoom uit</item>
+ <item>Vergroot</item>
+ <item>Verklein</item>
<item>Roteer op</item>
<item>Roteer af</item>
- <item>Kubus in</item>
- <item>Kubus uit</item>
+ <item>Blokkie in</item>
+ <item>Blokkie uit</item>
<item>Stapel</item>
<item>Trek klavier</item>
<item>Spieël</item>
diff --git a/res/values-af/cm_strings.xml b/res/values-af/cm_strings.xml
index a501119de..3ef65004b 100644
--- a/res/values-af/cm_strings.xml
+++ b/res/values-af/cm_strings.xml
@@ -16,49 +16,27 @@
limitations under the License.
-->
<resources>
- <string name="application_copyright">Kopiereg \u00A9 2014 Die CyanogenMod Projek</string>
- <string name="sort_button_text">Sorteer</string>
- <string name="filter_button_text">Filter</string>
- <string name="default_screen_button_text">Verstek skerm</string>
- <string name="transition_effect_button_text">Rol effek</string>
- <string name="sort_mode_title">Titel</string>
- <string name="sort_mode_launch_count">Begin telling</string>
- <string name="sort_mode_install_time">Iinstalleer tyd</string>
+ <string name="launcher_settings">LANSEERDER INSTELLINGS</string>
+ <string name="home_screen_settings">TUIS SKERM INSTELLINGS</string>
+ <string name="drawer_settings">LAAI INSTELLINGS</string>
+ <string name="setting_state_on">AAN</string>
+ <string name="setting_state_off">AF</string>
+ <string name="themes_button_text">Temas</string>
<string name="scrolling_page_outlines">Bladsy buitelyne</string>
<string name="scrolling_fade_adjacent">Vervaag kant bladsye</string>
- <string name="wallpaper_scroll">Rol muurpapier</string>
- <string name="preferences_title">Instellings</string>
- <string name="preferences_application_title">Program</string>
- <string name="preferences_interface_homescreen_title">Tuis skerm</string>
- <string name="preferences_interface_homescreen_search_title">Soekbalk</string>
- <string name="preferences_interface_homescreen_search_summary">Wys soekbalk altyd aan die bokant van die skerm</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_title">Steek ikoon etikette weg</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">Steek ikoon etikette op Tuis Skerm weg</string>
- <string name="preferences_interface_drawer_title">Laai</string>
- <string name="preferences_interface_drawer_summary">Program en legstuk laai</string>
- <string name="preferences_interface_drawer_apps_category">Programme</string>
- <string name="preferences_interface_drawer_hidden_apps_title">Versteekte programme</string>
- <string name="preferences_interface_drawer_hidden_apps_summary">Steek programme van die laai weg</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">Verwyder kortpaaie</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">Verwyder kortpaaie of versteekte programme van die tuis skerm</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_title">Verwyder legstukke</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_summary">Verwyder legstukke of versteekte programme van die tuis skerm</string>
- <string name="preferences_interface_drawer_hide_icon_labels_title">Steek ikoon etikette weg</string>
- <string name="preferences_interface_drawer_hide_icon_labels_summary">Steek ikoon etikette weg in die laai</string>
- <string name="preferences_interface_dock_title">Dok</string>
- <string name="preferences_interface_general_title">Algemeen</string>
- <string name="preferences_interface_general_icons_category">Ikone</string>
- <string name="preferences_interface_general_icons_large_title">Groter ikone</string>
- <string name="preferences_interface_general_icons_large_summary">Gebruik ekstra groot toepassing ikone in tuis skerm en laai</string>
- <string name="preferences_interface_general_icons_text_style_title">Teksfont styl</string>
- <string name="preferences_interface_general_icons_text_style_summary">Variant en styl van font om te gebruik vir ikoon teks</string>
- <string name="dialog_pick_iconpack_title">Kies ikoon stel</string>
- <string name="default_iconpack_title">Standaard ikone</string>
- <string name="icon_packs_title">Ikoon stelle</string>
- <string name="no_iconpacks_summary">Geen ikoon stelle geïnstalleer</string>
- <string name="clear_keyguard_wallpaper">Verwyder</string>
- <string name="all_apps_cling_cm">Verpersoonlik jou laai</string>
- <string name="all_apps_cling_summary">Tik die bladsy aanwyser vir bykomende konfigurasie-instellings</string>
- <string name="menu_hidden_apps_delete">Herstel</string>
+ <string name="scrolling_wallpaper">Rol agtergrond</string>
<string name="hidden_apps_title">Versteekte programme</string>
+ <string name="scroll_effect_text">Rol effek</string>
+ <string name="drawer_sorting_text">Sorteer metode</string>
+ <string name="sort_mode_title">Titel</string>
+ <string name="sort_mode_launch_count">Begin telling</string>
+ <string name="sort_mode_install_time">Iinstalleer tyd</string>
+ <string name="home_screen_search_text">Soekbalk</string>
+ <string name="larger_icons_text">Groter ikone</string>
+ <string name="icon_labels">Ikoon etikette</string>
+ <string name="icon_labels_show">Vertoon</string>
+ <string name="icon_labels_hide">Wegsteek</string>
+ <string name="protected_app_settings">Beskermde programme</string>
+ <string name="search_screen_left_text">Soek paneel</string>
+ <string name="search_screen_left_unsupported_toast">Jy moet \'n ondersteunde soek program hê en CyanogenMod om hierdie funksie te gebruik.</string>
</resources>
diff --git a/res/values-ar/cm_arrays.xml b/res/values-ar/cm_arrays.xml
index 97cd1b0ba..78682bcb6 100644
--- a/res/values-ar/cm_arrays.xml
+++ b/res/values-ar/cm_arrays.xml
@@ -16,24 +16,19 @@
limitations under the License.
-->
<resources>
- <string-array name="preferences_interface_general_icons_text_font_family_entries">
- <item>العادية</item>
- <item>فاتح</item>
- <item>مكثف</item>
- </string-array>
<string-array name="transition_effect_entries">
<item>لا شيء</item>
<item>تكبير</item>
<item>تصغير</item>
<item>تدوير للأعلى</item>
- <item>تدوير لأسفل</item>
+ <item>تدوير للأسفل</item>
<item>مكعب لداخل</item>
<item>مكعب للخارج</item>
<item>جميع</item>
<item>Accordion</item>
<item>لف</item>
- <item>اسطوانة الداخل</item>
- <item>اسطوانة الخارج</item>
+ <item>اسطوانة لداخل</item>
+ <item>اسطوانة للخارج</item>
<item>دائري</item>
<item>نظرة عامّة</item>
</string-array>
diff --git a/res/values-ar/cm_strings.xml b/res/values-ar/cm_strings.xml
index d0161cdce..e9fd70329 100644
--- a/res/values-ar/cm_strings.xml
+++ b/res/values-ar/cm_strings.xml
@@ -16,49 +16,37 @@
limitations under the License.
-->
<resources>
- <string name="application_copyright">حقوق الطبع والنشر \u00A9 2013 لي مشروع CyanogenMod</string>
- <string name="sort_button_text">ترتيب</string>
- <string name="filter_button_text">التصفية</string>
- <string name="default_screen_button_text">الشاشة الافتراضية</string>
- <string name="transition_effect_button_text">تأثير التمرير</string>
- <string name="sort_mode_title">العنوان</string>
- <string name="sort_mode_launch_count">عداد الإنطلاق</string>
- <string name="sort_mode_install_time">وقت التثبيت</string>
+ <string name="launcher_settings">إعدادات اللنشر</string>
+ <string name="home_screen_settings">إعدادات الشاشة الرئيسية</string>
+ <string name="drawer_settings">إعدادات الفراغ</string>
+ <string name="app_settings">إعدادات التطبيق</string>
+ <string name="setting_state_on">يعمل</string>
+ <string name="setting_state_off">لايعمل</string>
+ <string name="themes_button_text">المواضيع</string>
<string name="scrolling_page_outlines">الخطوط العريضة لي الصفحة</string>
<string name="scrolling_fade_adjacent">تتلاشى الصفحات الجانبية</string>
- <string name="wallpaper_scroll">تمرير الخلفية</string>
- <string name="preferences_title">إعدادات</string>
- <string name="preferences_application_title">التطبيق</string>
- <string name="preferences_interface_homescreen_title">الشاشة الرئيسية</string>
- <string name="preferences_interface_homescreen_search_title">شريط البحث</string>
- <string name="preferences_interface_homescreen_search_summary">إستمرار إظهار شريط البحث في أعلى الشاشة</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_title">إخفاء تسميات الرمز</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">إخفاء تسميات الرموز على الشاشة الرئيسية</string>
- <string name="preferences_interface_drawer_title">الفراغ</string>
- <string name="preferences_interface_drawer_summary">فراغ التطبيقات والمصغرات</string>
- <string name="preferences_interface_drawer_apps_category">تطبيقات</string>
- <string name="preferences_interface_drawer_hidden_apps_title">تطبيقات المخفية</string>
- <string name="preferences_interface_drawer_hidden_apps_summary">إخفاء تطبيقات من الفراغ</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">إزالة اختصارات</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">إزالة الاختصارات للتطبيقات المخفية من الشاشة الرئيسية</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_title">إزالة المصغرات</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_summary">إزالة مصغرات التطبيقات المخفية من الشاشة الرئيسية</string>
- <string name="preferences_interface_drawer_hide_icon_labels_title">إخفاء تسميات الرمز</string>
- <string name="preferences_interface_drawer_hide_icon_labels_summary">إخفاء تسميات الرمز في الفراغ</string>
- <string name="preferences_interface_dock_title">حوض</string>
- <string name="preferences_interface_general_title">عام</string>
- <string name="preferences_interface_general_icons_category">أيقونات</string>
- <string name="preferences_interface_general_icons_large_title">أيقونات كبيرة</string>
- <string name="preferences_interface_general_icons_large_summary">استخدام الرموز إضافية كبيرة لي التطبيق في الشاشة الرئيسية و الفراغ</string>
- <string name="preferences_interface_general_icons_text_style_title">نمط خط النص</string>
- <string name="preferences_interface_general_icons_text_style_summary">شكل ونمط الخط لاستخدامه لرمز النص</string>
- <string name="dialog_pick_iconpack_title">اختر حزمة الأيقونة</string>
- <string name="default_iconpack_title">الإيقونات الافتراضية</string>
- <string name="icon_packs_title">حزم الإيقونات</string>
- <string name="no_iconpacks_summary">لا توجد حزم أيقونات لتثبيت</string>
- <string name="clear_keyguard_wallpaper">تصفية</string>
- <string name="all_apps_cling_cm">تخصيص الفراغ</string>
- <string name="all_apps_cling_summary">انقر فوق مؤشر الصفحة لعرض إعدادات التكوين الإضافي</string>
- <string name="menu_hidden_apps_delete">إعادة تعيين</string>
+ <string name="scrolling_wallpaper">تمرير الخلفية</string>
+ <string name="grid_size_text">حجم الشبكة</string>
+ <string name="grid_size_comfortable">مريحة</string>
+ <string name="grid_size_cozy">مريح</string>
+ <string name="grid_size_condensed">مكثف</string>
+ <string name="grid_size_custom">مخصص</string>
+ <string name="preferences_interface_homescreen_custom">حدد حجم مخصص</string>
+ <string name="preferences_interface_homescreen_rows_title">عدد الصفوف</string>
+ <string name="preferences_interface_homescreen_columns_title">عدد الأعمدة</string>
<string name="hidden_apps_title">تطبيقات المخفية</string>
+ <string name="scroll_effect_text">تأثير التمرير</string>
+ <string name="drawer_sorting_text">وضع الفرز</string>
+ <string name="sort_mode_title">العنوان</string>
+ <string name="sort_mode_launch_count">عداد الإنطلاق</string>
+ <string name="sort_mode_install_time">وقت التثبيت</string>
+ <string name="home_screen_search_text">شريط البحث</string>
+ <string name="larger_icons_text">أيقونات كبيرة</string>
+ <string name="icon_labels">تسميات الرمز</string>
+ <string name="icon_labels_show">إظهار</string>
+ <string name="icon_labels_hide">إخفاء</string>
+ <string name="protected_app_settings">التطبيقات المحمية</string>
+ <string name="search_screen_left_text">لوحة البحث</string>
+ <string name="search_screen_left_unsupported_toast">يجب أن يكون تطبيق البحث و CyanogenMod مدعومين لستخدام هذه الميزة.</string>
+ <string name="dialog_confirm">تأكيد</string>
</resources>
diff --git a/res/values-ca/cm_arrays.xml b/res/values-ca/cm_arrays.xml
index 5dd971cbd..5207e1dfd 100644
--- a/res/values-ca/cm_arrays.xml
+++ b/res/values-ca/cm_arrays.xml
@@ -16,11 +16,6 @@
limitations under the License.
-->
<resources>
- <string-array name="preferences_interface_general_icons_text_font_family_entries">
- <item>Normal</item>
- <item>Fina</item>
- <item>Condensada</item>
- </string-array>
<string-array name="transition_effect_entries">
<item>Cap</item>
<item>Amplia</item>
diff --git a/res/values-ca/cm_strings.xml b/res/values-ca/cm_strings.xml
index ff387a6e1..5c153cc59 100644
--- a/res/values-ca/cm_strings.xml
+++ b/res/values-ca/cm_strings.xml
@@ -16,49 +16,37 @@
limitations under the License.
-->
<resources>
- <string name="application_copyright">Copyright \u00A9 2014 The CyanogenMod Project</string>
- <string name="sort_button_text">Ordena</string>
- <string name="filter_button_text">Filtre</string>
- <string name="default_screen_button_text">Pantalla predeterminada</string>
- <string name="transition_effect_button_text">Efecte desplaçament</string>
- <string name="sort_mode_title">Títol</string>
- <string name="sort_mode_launch_count">Vegades executat</string>
- <string name="sort_mode_install_time">Hora d\'instal·lació</string>
+ <string name="launcher_settings">CONFIGURACIÓ DEL LLANÇADOR</string>
+ <string name="home_screen_settings">CONFIGURACIÓ DE LA PANTALLA D\'INICI</string>
+ <string name="drawer_settings">CONFIGURACIÓ DEL CALAIX</string>
+ <string name="app_settings">CONFIGURACIÓ DE L\'APP</string>
+ <string name="setting_state_on">SÍ</string>
+ <string name="setting_state_off">NO</string>
+ <string name="themes_button_text">Temes</string>
<string name="scrolling_page_outlines">Vores de la pàgina</string>
<string name="scrolling_fade_adjacent">Esvaeix els costats de les pàgines</string>
- <string name="wallpaper_scroll">Desplaça el fons de pantalla</string>
- <string name="preferences_title">Ajustaments</string>
- <string name="preferences_application_title">App</string>
- <string name="preferences_interface_homescreen_title">Pantalla d\'inici</string>
- <string name="preferences_interface_homescreen_search_title">Barra de cerca</string>
- <string name="preferences_interface_homescreen_search_summary">Mostra sempre la barra de cerca a la part superior de la pantalla</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_title">Amaga les etiquetes de les icones</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">Amaga les etiquetes de les icones de la pantalla d\'inici</string>
- <string name="preferences_interface_drawer_title">Calaix</string>
- <string name="preferences_interface_drawer_summary">Calaix d\'apps i widgets</string>
- <string name="preferences_interface_drawer_apps_category">Apps</string>
- <string name="preferences_interface_drawer_hidden_apps_title">Apps amagades</string>
- <string name="preferences_interface_drawer_hidden_apps_summary">Amaga les apps del calaix</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">Treu les dreceres</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">Treu les dreceres de les apps amagades de la pantalla d\'inici</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_title">Treu els widgets</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_summary">Treu els widgets de les apps amagades de la pantalla d\'inici</string>
- <string name="preferences_interface_drawer_hide_icon_labels_title">Amaga les etiquetes de les icones</string>
- <string name="preferences_interface_drawer_hide_icon_labels_summary">Amaga les etiquetes de les icones al calaix</string>
- <string name="preferences_interface_dock_title">Barra d\'aplicacions</string>
- <string name="preferences_interface_general_title">General</string>
- <string name="preferences_interface_general_icons_category">Icones</string>
- <string name="preferences_interface_general_icons_large_title">Icones més grans</string>
- <string name="preferences_interface_general_icons_large_summary">Utilitza icones d\'aplicació extra grans a la pantalla d\'inici i al calaix</string>
- <string name="preferences_interface_general_icons_text_style_title">Estil del tipus de lletra del text</string>
- <string name="preferences_interface_general_icons_text_style_summary">Variant i estil del tipus de lletra pel text de les icones</string>
- <string name="dialog_pick_iconpack_title">Escull un paquet d\'icones</string>
- <string name="default_iconpack_title">Icones per defecte</string>
- <string name="icon_packs_title">Paquets d\'icones</string>
- <string name="no_iconpacks_summary">No hi ha paquets d\'icones instal·lats</string>
- <string name="clear_keyguard_wallpaper">Neteja</string>
- <string name="all_apps_cling_cm">Personalitza el teu calaix</string>
- <string name="all_apps_cling_summary">Pica l\'indicador de pàgina per veure les opcions de configuració addicionals</string>
- <string name="menu_hidden_apps_delete">Reinicia</string>
+ <string name="scrolling_wallpaper">Desplaça el fons de pantalla</string>
+ <string name="grid_size_text">Mida de la graella</string>
+ <string name="grid_size_comfortable">Còmoda</string>
+ <string name="grid_size_cozy">Acollidora</string>
+ <string name="grid_size_condensed">Condensada</string>
+ <string name="grid_size_custom">Personalitzada</string>
+ <string name="preferences_interface_homescreen_custom">Selecciona la mida personalitzada</string>
+ <string name="preferences_interface_homescreen_rows_title">Nombre de files</string>
+ <string name="preferences_interface_homescreen_columns_title">Nombre de columnes</string>
<string name="hidden_apps_title">Apps amagades</string>
+ <string name="scroll_effect_text">Efecte desplaçament</string>
+ <string name="drawer_sorting_text">Mode d\'ordenació</string>
+ <string name="sort_mode_title">Títol</string>
+ <string name="sort_mode_launch_count">Vegades executat</string>
+ <string name="sort_mode_install_time">Hora d\'instal·lació</string>
+ <string name="home_screen_search_text">Barra de cerca</string>
+ <string name="larger_icons_text">Icones grans</string>
+ <string name="icon_labels">Etiquetes de les icones</string>
+ <string name="icon_labels_show">Mostra</string>
+ <string name="icon_labels_hide">Amaga</string>
+ <string name="protected_app_settings">Apps protegides</string>
+ <string name="search_screen_left_text">Quadre de cerca</string>
+ <string name="search_screen_left_unsupported_toast">Has de tenir una app de cerca suportada i perquè CyanogenMod utilitzi aquesta característica.</string>
+ <string name="dialog_confirm">Confirma</string>
</resources>
diff --git a/res/values-cs/cm_arrays.xml b/res/values-cs/cm_arrays.xml
index bffc61fef..aa326e178 100644
--- a/res/values-cs/cm_arrays.xml
+++ b/res/values-cs/cm_arrays.xml
@@ -16,24 +16,19 @@
limitations under the License.
-->
<resources>
- <string-array name="preferences_interface_general_icons_text_font_family_entries">
- <item>Obyčejné</item>
- <item>Slabé</item>
- <item>Zůžené</item>
- </string-array>
<string-array name="transition_effect_entries">
<item>Žádný</item>
- <item>Přiblížení</item>
+ <item>Příblížení</item>
<item>Oddálení</item>
- <item>Rotace nahoru</item>
- <item>Rotace dolu</item>
+ <item>Otočení nahoru</item>
+ <item>Otočení dolu</item>
<item>Uvnitř krychle</item>
<item>Vně krychle</item>
<item>Vrstvy</item>
<item>Harmonika</item>
<item>Překlopení</item>
<item>Uvnitř válce</item>
- <item>Vně válce</item>
+ <item>Mimo válec</item>
<item>Kolotoč</item>
<item>Přehled</item>
</string-array>
diff --git a/res/values-cs/cm_strings.xml b/res/values-cs/cm_strings.xml
index 449e1db3a..f5c603f52 100644
--- a/res/values-cs/cm_strings.xml
+++ b/res/values-cs/cm_strings.xml
@@ -16,49 +16,37 @@
limitations under the License.
-->
<resources>
- <string name="application_copyright">Copyright \u00A9 2014 CyanogenMod projekt</string>
- <string name="sort_button_text">Třídit</string>
- <string name="filter_button_text">Filtr</string>
- <string name="default_screen_button_text">Výchozí obrazovka</string>
- <string name="transition_effect_button_text">Efekt přechodu</string>
- <string name="sort_mode_title">Název</string>
- <string name="sort_mode_launch_count">Počet spuštění</string>
- <string name="sort_mode_install_time">Čas instalace</string>
+ <string name="launcher_settings">NASTAVENÍ SPOUŠTĚČE</string>
+ <string name="home_screen_settings">NASTAVENÍ DOMOVSKÉ OBRAZOVKY</string>
+ <string name="drawer_settings">NASTAVENÍ SLOŽKY</string>
+ <string name="app_settings">NASTAVENÍ APL</string>
+ <string name="setting_state_on">Zap.</string>
+ <string name="setting_state_off">Vyp.</string>
+ <string name="themes_button_text">Motivy</string>
<string name="scrolling_page_outlines">Ohraničení stránek</string>
<string name="scrolling_fade_adjacent">Prolínat hrany ploch</string>
- <string name="wallpaper_scroll">Posouvání tapety</string>
- <string name="preferences_title">Nastavení</string>
- <string name="preferences_application_title">Aplikace</string>
- <string name="preferences_interface_homescreen_title">Domovská plocha</string>
- <string name="preferences_interface_homescreen_search_title">Vyhledávací lišta</string>
- <string name="preferences_interface_homescreen_search_summary">Trvale zobrazit lištu vyhledávání vždy u horní hrany plochy</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_title">Skrýt popisky ikon</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">Skrýt popisky ikon na domovské ploše</string>
- <string name="preferences_interface_drawer_title">Aplikační složka</string>
- <string name="preferences_interface_drawer_summary">Složka aplikací a widgetů</string>
- <string name="preferences_interface_drawer_apps_category">Aplikace</string>
- <string name="preferences_interface_drawer_hidden_apps_title">Skryté aplikace</string>
- <string name="preferences_interface_drawer_hidden_apps_summary">Skrýt aplikace ve složce</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">Odebrat zástupce</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">Odebrat zástupce skrytých aplikací z domovské plochy</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_title">Odebrat widgety</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_summary">Odebrat widgety skrytých aplikací z domovské plochy</string>
- <string name="preferences_interface_drawer_hide_icon_labels_title">Skrýt popisky ikon</string>
- <string name="preferences_interface_drawer_hide_icon_labels_summary">Skrýt popisky ikon ve složce</string>
- <string name="preferences_interface_dock_title">Dok</string>
- <string name="preferences_interface_general_title">Obecné</string>
- <string name="preferences_interface_general_icons_category">Ikony</string>
- <string name="preferences_interface_general_icons_large_title">Větší ikony</string>
- <string name="preferences_interface_general_icons_large_summary">Použít větší ikony aplikací na plochách a aplikační složce</string>
- <string name="preferences_interface_general_icons_text_style_title">Vzhled písma</string>
- <string name="preferences_interface_general_icons_text_style_summary">Vzhled a varianta pro popis ikon</string>
- <string name="dialog_pick_iconpack_title">Vyberte balíček ikon</string>
- <string name="default_iconpack_title">Výchozí ikony</string>
- <string name="icon_packs_title">Balíčky ikon</string>
- <string name="no_iconpacks_summary">Není nainstalován žádný balíček ikon</string>
- <string name="clear_keyguard_wallpaper">Odstranit</string>
- <string name="all_apps_cling_cm">Upravit vlastní složku</string>
- <string name="all_apps_cling_summary">Dotykem na indikátor stránky zobrazit další možnosti nastavení</string>
- <string name="menu_hidden_apps_delete">Obnovit</string>
+ <string name="scrolling_wallpaper">Posouvání tapety</string>
+ <string name="grid_size_text">Velikost mřížky</string>
+ <string name="grid_size_comfortable">Komfortní</string>
+ <string name="grid_size_cozy">Pohodlná</string>
+ <string name="grid_size_condensed">Zůžená</string>
+ <string name="grid_size_custom">Vlastní</string>
+ <string name="preferences_interface_homescreen_custom">Zvolte vlastní velikost</string>
+ <string name="preferences_interface_homescreen_rows_title">Počet řádek</string>
+ <string name="preferences_interface_homescreen_columns_title">Počet sloupců</string>
<string name="hidden_apps_title">Skryté aplikace</string>
+ <string name="scroll_effect_text">Efekt přechodu</string>
+ <string name="drawer_sorting_text">Režim třídění</string>
+ <string name="sort_mode_title">Název</string>
+ <string name="sort_mode_launch_count">Počet spuštění</string>
+ <string name="sort_mode_install_time">Čas instalace</string>
+ <string name="home_screen_search_text">Vyhledávací lišta</string>
+ <string name="larger_icons_text">Větší ikony</string>
+ <string name="icon_labels">Popisky ikon</string>
+ <string name="icon_labels_show">Zobrazit</string>
+ <string name="icon_labels_hide">Skrýt</string>
+ <string name="protected_app_settings">Chráněné aplikace</string>
+ <string name="search_screen_left_text">Panel vyhledávání</string>
+ <string name="search_screen_left_unsupported_toast">Pro použití této funkce musíte mít nainstalovanou podporovanou aplikaci vyhledávání a CyanogenMod.</string>
+ <string name="dialog_confirm">Potvrdit</string>
</resources>
diff --git a/res/values-da/cm_arrays.xml b/res/values-da/cm_arrays.xml
index dcc77c789..038d014d7 100644
--- a/res/values-da/cm_arrays.xml
+++ b/res/values-da/cm_arrays.xml
@@ -16,24 +16,19 @@
limitations under the License.
-->
<resources>
- <string-array name="preferences_interface_general_icons_text_font_family_entries">
- <item>Regulær</item>
- <item>Lys</item>
- <item>Kondenseret</item>
- </string-array>
<string-array name="transition_effect_entries">
<item>Ingen</item>
<item>Zoom ind</item>
<item>Zoom ud</item>
- <item>Rotér op</item>
- <item>Rotér ned</item>
- <item>Terning ind</item>
- <item>Terning ud</item>
+ <item>Rotere op</item>
+ <item>Rotere ned</item>
+ <item>Indvendig terning</item>
+ <item>Udvendig terning</item>
<item>Stak</item>
<item>Harmonika</item>
<item>Flip</item>
- <item>Cylinder ind</item>
- <item>Cylinder ud</item>
+ <item>Indvendig cylinder</item>
+ <item>Udvendig cylinder</item>
<item>Karrusel</item>
<item>Overblik</item>
</string-array>
diff --git a/res/values-da/cm_strings.xml b/res/values-da/cm_strings.xml
index 0149c9c91..5d584f8d6 100644
--- a/res/values-da/cm_strings.xml
+++ b/res/values-da/cm_strings.xml
@@ -16,49 +16,37 @@
limitations under the License.
-->
<resources>
- <string name="application_copyright">Copyright \u00A9 2014 The CyanogenMod Project</string>
- <string name="sort_button_text">Sortér</string>
- <string name="filter_button_text">Filtrér</string>
- <string name="default_screen_button_text">Standardskærm</string>
- <string name="transition_effect_button_text">Rulleeffekt</string>
- <string name="sort_mode_title">Titel</string>
- <string name="sort_mode_launch_count">Antal gange brugt</string>
- <string name="sort_mode_install_time">Installationstidspunkt</string>
+ <string name="launcher_settings">INDSTILLINGER FOR LAUNCHER</string>
+ <string name="home_screen_settings">INDSTILLINGER FOR STARTSKÆRM</string>
+ <string name="drawer_settings">INDSTILLINGER FOR OVERSIGT</string>
+ <string name="app_settings">APP-INDSTILLINGER</string>
+ <string name="setting_state_on">TIL</string>
+ <string name="setting_state_off">FRA</string>
+ <string name="themes_button_text">Temaer</string>
<string name="scrolling_page_outlines">Sideomrids</string>
<string name="scrolling_fade_adjacent">Sideovergange</string>
- <string name="wallpaper_scroll">Rul baggrund</string>
- <string name="preferences_title">Indstillinger</string>
- <string name="preferences_application_title">App</string>
- <string name="preferences_interface_homescreen_title">Startskærm</string>
- <string name="preferences_interface_homescreen_search_title">Søgelinje</string>
- <string name="preferences_interface_homescreen_search_summary">Vis permanent søgelinje i toppen af skærmen</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_title">Skjul ikontekster</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">Skjul ikontekster på startskærmen</string>
- <string name="preferences_interface_drawer_title">Oversigt</string>
- <string name="preferences_interface_drawer_summary">Oversigt over apps og widgets</string>
- <string name="preferences_interface_drawer_apps_category">Apps</string>
- <string name="preferences_interface_drawer_hidden_apps_title">Skjulte apps</string>
- <string name="preferences_interface_drawer_hidden_apps_summary">Skjul apps fra oversigten</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">Fjern genveje</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">Fjern genveje til skjulte apps fra startskærmen</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_title">Fjern widgets</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_summary">Fjern widgets fra skjulte apps fra startskærmen</string>
- <string name="preferences_interface_drawer_hide_icon_labels_title">Skjul ikontekster</string>
- <string name="preferences_interface_drawer_hide_icon_labels_summary">Skjul ikontekster i oversigten</string>
- <string name="preferences_interface_dock_title">Docklinje</string>
- <string name="preferences_interface_general_title">Generelt</string>
- <string name="preferences_interface_general_icons_category">Ikoner</string>
- <string name="preferences_interface_general_icons_large_title">Større ikoner</string>
- <string name="preferences_interface_general_icons_large_summary">Brug ekstra store app-ikoner på startskærm og i oversigten</string>
- <string name="preferences_interface_general_icons_text_style_title">Font til tekster</string>
- <string name="preferences_interface_general_icons_text_style_summary">Fontvariant og -stilart til ikontekster</string>
- <string name="dialog_pick_iconpack_title">Vælg ikonpakke</string>
- <string name="default_iconpack_title">Standardikoner</string>
- <string name="icon_packs_title">Ikonpakker</string>
- <string name="no_iconpacks_summary">Ingen ikonpakker installeret</string>
- <string name="clear_keyguard_wallpaper">Ryd</string>
- <string name="all_apps_cling_cm">Tilpas din oversigt</string>
- <string name="all_apps_cling_summary">Tryk på sideindikatoren for at vise yderligere konfigurationsindstillinger</string>
- <string name="menu_hidden_apps_delete">Nulstil</string>
+ <string name="scrolling_wallpaper">Rul baggrund</string>
+ <string name="grid_size_text">Gitterstørrelse</string>
+ <string name="grid_size_comfortable">Behageligt</string>
+ <string name="grid_size_cozy">Hyggeligt</string>
+ <string name="grid_size_condensed">Sammentrængt</string>
+ <string name="grid_size_custom">Brugerdefineret</string>
+ <string name="preferences_interface_homescreen_custom">Vælg brugerdefineret størrelse</string>
+ <string name="preferences_interface_homescreen_rows_title">Antal rækker</string>
+ <string name="preferences_interface_homescreen_columns_title">Antal kolonner</string>
<string name="hidden_apps_title">Skjulte apps</string>
+ <string name="scroll_effect_text">Rulleeffekt</string>
+ <string name="drawer_sorting_text">Sorteringstilstand</string>
+ <string name="sort_mode_title">Titel</string>
+ <string name="sort_mode_launch_count">Antal gange brugt</string>
+ <string name="sort_mode_install_time">Installationstidspunkt</string>
+ <string name="home_screen_search_text">Søgelinje</string>
+ <string name="larger_icons_text">Større ikoner</string>
+ <string name="icon_labels">Ikontekster</string>
+ <string name="icon_labels_show">Vis</string>
+ <string name="icon_labels_hide">Skjul</string>
+ <string name="protected_app_settings">Beskyttede apps</string>
+ <string name="search_screen_left_text">Søgepanel</string>
+ <string name="search_screen_left_unsupported_toast">Du skal have en understøttet søge-app og CyanogenMod for at anvende denne funktion.</string>
+ <string name="dialog_confirm">Bekræft</string>
</resources>
diff --git a/res/values-de/cm_arrays.xml b/res/values-de/cm_arrays.xml
index 6f5eb308f..b1fb3b5f1 100644
--- a/res/values-de/cm_arrays.xml
+++ b/res/values-de/cm_arrays.xml
@@ -16,11 +16,6 @@
limitations under the License.
-->
<resources>
- <string-array name="preferences_interface_general_icons_text_font_family_entries">
- <item>Normal</item>
- <item>Dünn</item>
- <item>Schmal</item>
- </string-array>
<string-array name="transition_effect_entries">
<item>Keine</item>
<item>Hineinzoomen</item>
diff --git a/res/values-de/cm_strings.xml b/res/values-de/cm_strings.xml
index 8e784472e..30b1e5fb8 100644
--- a/res/values-de/cm_strings.xml
+++ b/res/values-de/cm_strings.xml
@@ -16,49 +16,37 @@
limitations under the License.
-->
<resources>
- <string name="application_copyright">Copyright \u00A9 2014 The CyanogenMod Project</string>
- <string name="sort_button_text">Sortieren</string>
- <string name="filter_button_text">Filtern</string>
- <string name="default_screen_button_text">Standardseite</string>
- <string name="transition_effect_button_text">Scroll-Effekt</string>
- <string name="sort_mode_title">Titel</string>
- <string name="sort_mode_launch_count">Aufrufanzahl</string>
- <string name="sort_mode_install_time">Installationsdatum</string>
+ <string name="launcher_settings">LAUNCHER-EINSTELLUNGEN</string>
+ <string name="home_screen_settings">STARTBILDSCHIRM-EINSTELLUNGEN</string>
+ <string name="drawer_settings">APP-ÜBERSICHT-EINSTELLUNGEN</string>
+ <string name="app_settings">APP-EINSTELLUNGEN</string>
+ <string name="setting_state_on">AN</string>
+ <string name="setting_state_off">AUS</string>
+ <string name="themes_button_text">Designs</string>
<string name="scrolling_page_outlines">Seitenumriss anzeigen</string>
<string name="scrolling_fade_adjacent">Seiten einblenden</string>
- <string name="wallpaper_scroll">Hintergrundbild scrollen</string>
- <string name="preferences_title">Einstellungen</string>
- <string name="preferences_application_title">App</string>
- <string name="preferences_interface_homescreen_title">Startbildschirm</string>
- <string name="preferences_interface_homescreen_search_title">Suchleiste</string>
- <string name="preferences_interface_homescreen_search_summary">Dauerhafte Anzeige der Suchleiste am oberen Bildschirmrand</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_title">Beschriftung nicht anzeigen</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">Symbolbeschriftungen auf den Startseiten ausblenden</string>
- <string name="preferences_interface_drawer_title">App-Übersicht</string>
- <string name="preferences_interface_drawer_summary">App- und Widget-Übersicht</string>
- <string name="preferences_interface_drawer_apps_category">Apps</string>
- <string name="preferences_interface_drawer_hidden_apps_title">Versteckte Apps</string>
- <string name="preferences_interface_drawer_hidden_apps_summary">Apps in der App-Übersicht verstecken</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">Verknüpfungen entfernen</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">Verknüpfungen für versteckte Apps vom Startbildschirm entfernen</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_title">Widgets entfernen</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_summary">Widgets von versteckten Apps vom Startbildschirm entfernen</string>
- <string name="preferences_interface_drawer_hide_icon_labels_title">Beschriftung nicht anzeigen</string>
- <string name="preferences_interface_drawer_hide_icon_labels_summary">Symbolbeschriftungen in der App-Übersicht ausblenden</string>
- <string name="preferences_interface_dock_title">Dock</string>
- <string name="preferences_interface_general_title">Allgemein</string>
- <string name="preferences_interface_general_icons_category">Symbole</string>
- <string name="preferences_interface_general_icons_large_title">Große Symbole</string>
- <string name="preferences_interface_general_icons_large_summary">Große Symbole für Apps im Startbildschirm und der App-Übersicht verwenden</string>
- <string name="preferences_interface_general_icons_text_style_title">Schriftstil</string>
- <string name="preferences_interface_general_icons_text_style_summary">Schriftart und Schriftstil der Symbolbeschriftung</string>
- <string name="dialog_pick_iconpack_title">Symbolpaket auswählen</string>
- <string name="default_iconpack_title">Standardsymbole</string>
- <string name="icon_packs_title">Symbolpakete</string>
- <string name="no_iconpacks_summary">Es sind keine Symbolpakete installiert</string>
- <string name="clear_keyguard_wallpaper">Zurücksetzen</string>
- <string name="all_apps_cling_cm">App-Übersicht konfigurieren</string>
- <string name="all_apps_cling_summary">Berühren Sie den Seitenindikator, um die erweiterten Einstellungen zu öffnen.</string>
- <string name="menu_hidden_apps_delete">Zurücksetzen</string>
+ <string name="scrolling_wallpaper">Hintergrundbild scrollen</string>
+ <string name="grid_size_text">Rastergröße</string>
+ <string name="grid_size_comfortable">Normal</string>
+ <string name="grid_size_cozy">Mittel</string>
+ <string name="grid_size_condensed">Klein</string>
+ <string name="grid_size_custom">Benutzerdefiniert</string>
+ <string name="preferences_interface_homescreen_custom">Benutzerdefinierte Größe auswählen</string>
+ <string name="preferences_interface_homescreen_rows_title">Anzahl der Zeilen</string>
+ <string name="preferences_interface_homescreen_columns_title">Anzahl der Spalten</string>
<string name="hidden_apps_title">Versteckte Apps</string>
+ <string name="scroll_effect_text">Scroll-Effekt</string>
+ <string name="drawer_sorting_text">Sortiermodus</string>
+ <string name="sort_mode_title">Titel</string>
+ <string name="sort_mode_launch_count">Aufrufanzahl</string>
+ <string name="sort_mode_install_time">Installationsdatum</string>
+ <string name="home_screen_search_text">Suchleiste</string>
+ <string name="larger_icons_text">Große Symbole</string>
+ <string name="icon_labels">Symbol-Beschriftungen</string>
+ <string name="icon_labels_show">Anzeigen</string>
+ <string name="icon_labels_hide">Verbergen</string>
+ <string name="protected_app_settings">Geschützte Apps</string>
+ <string name="search_screen_left_text">Google Now</string>
+ <string name="search_screen_left_unsupported_toast">Um diese Funktion nutzen zu können, müssen Sie CyanogenMod und eine unterstützte Such-App installiert haben.</string>
+ <string name="dialog_confirm">Bestätigen</string>
</resources>
diff --git a/res/values-el/cm_arrays.xml b/res/values-el/cm_arrays.xml
index af43fa119..b37f8c596 100644
--- a/res/values-el/cm_arrays.xml
+++ b/res/values-el/cm_arrays.xml
@@ -16,11 +16,6 @@
limitations under the License.
-->
<resources>
- <string-array name="preferences_interface_general_icons_text_font_family_entries">
- <item>Κανονική</item>
- <item>Λεπτή</item>
- <item>Συμπυκνωμένη</item>
- </string-array>
<string-array name="transition_effect_entries">
<item>Κανένα</item>
<item>Μεγέθυνση</item>
diff --git a/res/values-el/cm_strings.xml b/res/values-el/cm_strings.xml
index df3a2a6bb..b21a14baa 100644
--- a/res/values-el/cm_strings.xml
+++ b/res/values-el/cm_strings.xml
@@ -16,49 +16,37 @@
limitations under the License.
-->
<resources>
- <string name="application_copyright">Copyright \u00A9 2014 The CyanogenMod Project</string>
- <string name="sort_button_text">Ταξινόμηση</string>
- <string name="filter_button_text">Φιλτράρισμα</string>
- <string name="default_screen_button_text">Προεπιλ. οθόνη</string>
- <string name="transition_effect_button_text">Εφέ κύλισης</string>
- <string name="sort_mode_title">Τίτλος</string>
- <string name="sort_mode_launch_count">Αριθμός εκκινήσεων</string>
- <string name="sort_mode_install_time">Χρόνος εγκατάστασης</string>
+ <string name="launcher_settings">ΓΕΝΙΚΕΣ ΡΥΘΜΙΣΕΙΣ</string>
+ <string name="home_screen_settings">ΡΥΘΜΙΣΕΙΣ ΑΡΧΙΚΗΣ ΟΘΟΝΗΣ</string>
+ <string name="drawer_settings">ΡΥΘΜΙΣΕΙΣ ΣΥΡΤΑΡΙΟΥ</string>
+ <string name="app_settings">ΡΥΘΜΙΣΕΙΣ ΕΦΑΡΜΟΓΩΝ</string>
+ <string name="setting_state_on">ΕΝΕΡΓΟ</string>
+ <string name="setting_state_off">ΑΝΕΝΕΡΓΟ</string>
+ <string name="themes_button_text">Θέματα</string>
<string name="scrolling_page_outlines">Περίγραμμα σελιδών</string>
<string name="scrolling_fade_adjacent">Ξεθώριασμα πλευρικών σελίδων</string>
- <string name="wallpaper_scroll">Κύλιση ταπετσαρίας</string>
- <string name="preferences_title">Ρυθμίσεις</string>
- <string name="preferences_application_title">Εφαρμογή</string>
- <string name="preferences_interface_homescreen_title">Αρχική οθόνη</string>
- <string name="preferences_interface_homescreen_search_title">Μπάρα αναζήτησης</string>
- <string name="preferences_interface_homescreen_search_summary">Εμφάνιση της μπάρας αναζήτησης στο πάνω μέρος της οθόνης</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_title">Απόκρυψη ετικετών εικονιδίων</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">Απόκρυψη ετικετών εικονιδίων στην αρχική οθόνη</string>
- <string name="preferences_interface_drawer_title">Συρτάρι</string>
- <string name="preferences_interface_drawer_summary">Συρτάρι εφαρμογών και widget</string>
- <string name="preferences_interface_drawer_apps_category">Εφαρμογές</string>
- <string name="preferences_interface_drawer_hidden_apps_title">Κρυμμένες εφαρμογές</string>
- <string name="preferences_interface_drawer_hidden_apps_summary">Απόκρυψη εφαρμογών από το συρτάρι</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">Αφαίρεση συντομεύσεων</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">Αφαίρεση συντομεύσεων των κρυμμένων εφαρμογών από την αρχική οθόνη</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_title">Αφαίρεση widget</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_summary">Αφαίρεση widget των κρυμμένων εφαρμογών από την αρχική οθόνη</string>
- <string name="preferences_interface_drawer_hide_icon_labels_title">Απόκρυψη ετικετών εικονιδίων</string>
- <string name="preferences_interface_drawer_hide_icon_labels_summary">Απόκρυψη ετικετών εικονιδίων στο συρτάρι</string>
- <string name="preferences_interface_dock_title">Μπάρα εφαρμογών</string>
- <string name="preferences_interface_general_title">Γενικά</string>
- <string name="preferences_interface_general_icons_category">Εικονίδια</string>
- <string name="preferences_interface_general_icons_large_title">Μεγαλύτερα εικονίδια</string>
- <string name="preferences_interface_general_icons_large_summary">Χρήση μεγάλων εικονιδίων εφαρμογών στην αρχική οθόνη και το συρτάρι</string>
- <string name="preferences_interface_general_icons_text_style_title">Στυλ γραμματοσειράς κειμένου</string>
- <string name="preferences_interface_general_icons_text_style_summary">Τύπος και στυλ της γραμματοσειράς που χρησιμοποιείται για το κείμενο των εικονιδίων</string>
- <string name="dialog_pick_iconpack_title">Επιλογή πακέτου εικονιδίων</string>
- <string name="default_iconpack_title">Προεπιλεγμένα εικονίδια</string>
- <string name="icon_packs_title">Πακέτα εικονιδίων</string>
- <string name="no_iconpacks_summary">Δεν υπάρχουν εγκατεστημένα πακέτα εικονιδίων</string>
- <string name="clear_keyguard_wallpaper">Εκκαθάριση</string>
- <string name="all_apps_cling_cm">Προσαρμόστε το συρτάρι σας</string>
- <string name="all_apps_cling_summary">Αγγίξτε την ένδειξη σελίδας για προβολή πρόσθετων ρυθμίσεων</string>
- <string name="menu_hidden_apps_delete">Επαναφορά</string>
+ <string name="scrolling_wallpaper">Κύλιση ταπετσαρίας</string>
+ <string name="grid_size_text">Μέγεθος πλέγματος</string>
+ <string name="grid_size_comfortable">Άνετο</string>
+ <string name="grid_size_cozy">Κανονικό</string>
+ <string name="grid_size_condensed">Συμπυκνωμένο</string>
+ <string name="grid_size_custom">Προσαρμοσμένο</string>
+ <string name="preferences_interface_homescreen_custom">Επιλέξτε προσαρμοσμένο μέγεθος</string>
+ <string name="preferences_interface_homescreen_rows_title">Αριθμός γραμμών</string>
+ <string name="preferences_interface_homescreen_columns_title">Αριθμός στηλών</string>
<string name="hidden_apps_title">Κρυμμένες εφαρμογές</string>
+ <string name="scroll_effect_text">Εφέ κύλισης</string>
+ <string name="drawer_sorting_text">Ταξινόμηση</string>
+ <string name="sort_mode_title">Τίτλος</string>
+ <string name="sort_mode_launch_count">Αριθμός εκκινήσεων</string>
+ <string name="sort_mode_install_time">Χρόνος εγκατάστασης</string>
+ <string name="home_screen_search_text">Μπάρα αναζήτησης</string>
+ <string name="larger_icons_text">Μεγαλύτερα εικονίδια</string>
+ <string name="icon_labels">Ετικέτες εικονιδίων</string>
+ <string name="icon_labels_show">Εμφάνιση</string>
+ <string name="icon_labels_hide">Απόκρυψη</string>
+ <string name="protected_app_settings">Προστατευμένες εφαρμογές</string>
+ <string name="search_screen_left_text">Σελίδα αναζήτησης</string>
+ <string name="search_screen_left_unsupported_toast">Πρέπει να έχετε μια υποστηριζόμενη εφαρμογή αναζήτησης και CyanogenMod για να χρησιμοποιήσετε αυτήν τη δυνατότητα.</string>
+ <string name="dialog_confirm">Επιβεβαίωση</string>
</resources>
diff --git a/res/values-en/dimens.xml b/res/values-en/dimens.xml
new file mode 100644
index 000000000..01d4693c7
--- /dev/null
+++ b/res/values-en/dimens.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resources>
+<!-- Cling -->
+ <dimen name="cling_title_text_size">22sp</dimen>
+ <dimen name="cling_text_size">16sp</dimen>
+ <dimen name="cling_alt_title_text_size">30sp</dimen>
+ <dimen name="cling_alt_text_size">16sp</dimen>
+ <dimen name="cling_hint_text_size">18sp</dimen>
+</resources>
diff --git a/res/values-es-rXA/cm_arrays.xml b/res/values-es-rXA/cm_arrays.xml
index 530baacc2..8cab04774 100644
--- a/res/values-es-rXA/cm_arrays.xml
+++ b/res/values-es-rXA/cm_arrays.xml
@@ -16,17 +16,12 @@
limitations under the License.
-->
<resources>
- <string-array name="preferences_interface_general_icons_text_font_family_entries">
- <item>Normal</item>
- <item>Fina</item>
- <item>Comprimida</item>
- </string-array>
<string-array name="transition_effect_entries">
<item>Nengún</item>
- <item>Zoom entrante</item>
- <item>Zoom saliente</item>
- <item>Rotar arriba</item>
- <item>Rotar abaxo</item>
+ <item>Acercar</item>
+ <item>Allonxar</item>
+ <item>Xirar arriba</item>
+ <item>Xirar abaxo</item>
<item>Cúbicu entrante</item>
<item>Cúbicu saliente</item>
<item>Empilar</item>
diff --git a/res/values-es-rXA/cm_strings.xml b/res/values-es-rXA/cm_strings.xml
index df3dedecb..8c6a2e4c1 100644
--- a/res/values-es-rXA/cm_strings.xml
+++ b/res/values-es-rXA/cm_strings.xml
@@ -16,49 +16,37 @@
limitations under the License.
-->
<resources>
- <string name="application_copyright">Copyright \u00A9 2014 The CyanogenMod Project</string>
- <string name="sort_button_text">Ordenar</string>
- <string name="filter_button_text">Filtriar</string>
- <string name="default_screen_button_text">Pantalla por defeutu</string>
- <string name="transition_effect_button_text">Efeutu de desplazamientu</string>
- <string name="sort_mode_title">Títulu</string>
- <string name="sort_mode_launch_count">Vegaes executáu</string>
- <string name="sort_mode_install_time">Data d\'instalación</string>
+ <string name="launcher_settings">AXUSTES DEL LLANZADOR</string>
+ <string name="home_screen_settings">AXUSTES DE PANTALLA D\'ANICIU</string>
+ <string name="drawer_settings">AXUSTES DE LES APLICACIONES</string>
+ <string name="app_settings">AXUSTES D\'APLICACIÓN</string>
+ <string name="setting_state_on">SÍ</string>
+ <string name="setting_state_off">NON</string>
+ <string name="themes_button_text">Temes</string>
<string name="scrolling_page_outlines">Berbesos de pantalla</string>
<string name="scrolling_fade_adjacent">Efeutu de dilíu</string>
- <string name="wallpaper_scroll">Desplazar fondu</string>
- <string name="preferences_title">Axustes</string>
- <string name="preferences_application_title">Aplicación</string>
- <string name="preferences_interface_homescreen_title">Pantalla d\'aniciu</string>
- <string name="preferences_interface_homescreen_search_title">Barra de gueta</string>
- <string name="preferences_interface_homescreen_search_summary">Habilitar permantentemente la barra de gueta</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_title">Anubrir etiquetes de los iconos</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">Anubrir les etiquetes de los iconos na pantalla d\'aniciu</string>
- <string name="preferences_interface_drawer_title">Aplicaciones</string>
- <string name="preferences_interface_drawer_summary">Aplicaciones y widgets</string>
- <string name="preferences_interface_drawer_apps_category">Aplicaciones</string>
- <string name="preferences_interface_drawer_hidden_apps_title">Aplicaciones anubríes</string>
- <string name="preferences_interface_drawer_hidden_apps_summary">Anubrir aplicaciones pa que nun s\'amuesen</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">Desaniciar atayos</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">Desaniciar atayos d\'aplicaciones anubríes de la pantalla d\'aniciu</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_title">Desaniciar widgets</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_summary">Desaniciar widgets d\'aplicaciones anubríes de la pantalla d\'aniciu</string>
- <string name="preferences_interface_drawer_hide_icon_labels_title">Anubrir etiquetes de los iconos</string>
- <string name="preferences_interface_drawer_hide_icon_labels_summary">Anubrir les etiquetes de los iconos de la pantalla d\'aniciu</string>
- <string name="preferences_interface_dock_title">Barra d\'aplicaciones</string>
- <string name="preferences_interface_general_title">Xeneral</string>
- <string name="preferences_interface_general_icons_category">Iconos</string>
- <string name="preferences_interface_general_icons_large_title">Iconos grandes</string>
- <string name="preferences_interface_general_icons_large_summary">Usar iconos grandes na pantalla d\'aniciu y d\'aplicaciones</string>
- <string name="preferences_interface_general_icons_text_style_title">Estilu\'l testu</string>
- <string name="preferences_interface_general_icons_text_style_summary">Camudar l\'estilu\'l testu pa les etiquetes de los iconos</string>
- <string name="dialog_pick_iconpack_title">Esbillar paquete d\'iconos</string>
- <string name="default_iconpack_title">Iconos por defeutu</string>
- <string name="icon_packs_title">Paquetes d\'iconos</string>
- <string name="no_iconpacks_summary">Nun hai paquetes d\'iconos instalaos</string>
- <string name="clear_keyguard_wallpaper">Llimpiar</string>
- <string name="all_apps_cling_cm">Personaliza les tos aplicaciones</string>
- <string name="all_apps_cling_summary">Primi l\'indicador de páxina p\'amosar axustes adicionales</string>
- <string name="menu_hidden_apps_delete">Restablecer</string>
+ <string name="scrolling_wallpaper">Desplazar fondu</string>
+ <string name="grid_size_text">Tamañu del rexáu</string>
+ <string name="grid_size_comfortable">Confortable</string>
+ <string name="grid_size_cozy">Acoyedor</string>
+ <string name="grid_size_condensed">Condensáu</string>
+ <string name="grid_size_custom">Personalizáu</string>
+ <string name="preferences_interface_homescreen_custom">Esbilla\'l tamañu personalizáu</string>
+ <string name="preferences_interface_homescreen_rows_title">Númberu de fileres</string>
+ <string name="preferences_interface_homescreen_columns_title">Númberu de columnes</string>
<string name="hidden_apps_title">Aplicaciones anubríes</string>
+ <string name="scroll_effect_text">Efeutu de desplazamientu</string>
+ <string name="drawer_sorting_text">Mou d\'ordenación</string>
+ <string name="sort_mode_title">Títulu</string>
+ <string name="sort_mode_launch_count">Vegaes executáu</string>
+ <string name="sort_mode_install_time">Data d\'instalación</string>
+ <string name="home_screen_search_text">Barra de gueta</string>
+ <string name="larger_icons_text">Iconos grandes</string>
+ <string name="icon_labels">Etiquetes de los iconos</string>
+ <string name="icon_labels_show">Amosar</string>
+ <string name="icon_labels_hide">Anubrir</string>
+ <string name="protected_app_settings">Apps protexíes</string>
+ <string name="search_screen_left_text">Panel de gueta</string>
+ <string name="search_screen_left_unsupported_toast">Ye necesario tener una aplicación de gueta y CyanogenMod pa poder usar esta carauterística.</string>
+ <string name="dialog_confirm">Confirmar</string>
</resources>
diff --git a/res/values-es/cm_arrays.xml b/res/values-es/cm_arrays.xml
index 1f36f82a1..3f1f46dab 100644
--- a/res/values-es/cm_arrays.xml
+++ b/res/values-es/cm_arrays.xml
@@ -16,11 +16,6 @@
limitations under the License.
-->
<resources>
- <string-array name="preferences_interface_general_icons_text_font_family_entries">
- <item>Normal</item>
- <item>Fina</item>
- <item>Comprimida</item>
- </string-array>
<string-array name="transition_effect_entries">
<item>Ninguno</item>
<item>Zoom entrante</item>
diff --git a/res/values-es/cm_strings.xml b/res/values-es/cm_strings.xml
index e0478d8ea..44727d129 100644
--- a/res/values-es/cm_strings.xml
+++ b/res/values-es/cm_strings.xml
@@ -16,49 +16,37 @@
limitations under the License.
-->
<resources>
- <string name="application_copyright">Copyright \u00A9 2014 The CyanogenMod Project</string>
- <string name="sort_button_text">Ordenar</string>
- <string name="filter_button_text">Filtrar</string>
- <string name="default_screen_button_text">Pantalla por defecto</string>
- <string name="transition_effect_button_text">Efecto de desplazamiento</string>
- <string name="sort_mode_title">Título</string>
- <string name="sort_mode_launch_count">Veces ejecutado</string>
- <string name="sort_mode_install_time">Fecha de instalación</string>
+ <string name="launcher_settings">AJUSTES DEL LANZADOR</string>
+ <string name="home_screen_settings">AJUSTES DEL INICIO</string>
+ <string name="drawer_settings">AJUSTES DE LAS APLICACIONES</string>
+ <string name="app_settings">AJUSTES DE LA APLICACIÓN</string>
+ <string name="setting_state_on">SÍ</string>
+ <string name="setting_state_off">NO</string>
+ <string name="themes_button_text">Temas</string>
<string name="scrolling_page_outlines">Bordes de pantalla</string>
<string name="scrolling_fade_adjacent">Efecto de fundido</string>
- <string name="wallpaper_scroll">Desplazar fondo</string>
- <string name="preferences_title">Ajustes</string>
- <string name="preferences_application_title">Aplicación</string>
- <string name="preferences_interface_homescreen_title">Pantalla de inicio</string>
- <string name="preferences_interface_homescreen_search_title">Barra de búsqueda</string>
- <string name="preferences_interface_homescreen_search_summary">Habilitar la barra de búsqueda permanentemente</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_title">Ocultar etiquetas</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">Ocultar las etiquetas de los iconos en la pantalla de inicio</string>
- <string name="preferences_interface_drawer_title">Aplicaciones</string>
- <string name="preferences_interface_drawer_summary">Aplicaciones y widgets</string>
- <string name="preferences_interface_drawer_apps_category">Aplicaciones</string>
- <string name="preferences_interface_drawer_hidden_apps_title">Ocultar aplicaciones</string>
- <string name="preferences_interface_drawer_hidden_apps_summary">Ocultar aplicaciones para que no se muestren</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">Eliminar iconos</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">Eliminar iconos de aplicaciones ocultas de la pantalla de inicio</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_title">Eliminar widgets</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_summary">Eliminar widgets de aplicaciones ocultas de la pantalla de inicio</string>
- <string name="preferences_interface_drawer_hide_icon_labels_title">Ocultar etiquetas</string>
- <string name="preferences_interface_drawer_hide_icon_labels_summary">Ocultar las etiquetas de los iconos de la pantalla de inicio</string>
- <string name="preferences_interface_dock_title">Barra de aplicaciones</string>
- <string name="preferences_interface_general_title">General</string>
- <string name="preferences_interface_general_icons_category">Iconos</string>
- <string name="preferences_interface_general_icons_large_title">Iconos grandes</string>
- <string name="preferences_interface_general_icons_large_summary">Usar iconos grandes en la pantalla de inicio y de aplicaciones</string>
- <string name="preferences_interface_general_icons_text_style_title">Estilo del texto</string>
- <string name="preferences_interface_general_icons_text_style_summary">Cambiar el estilo de texto para las etiquetas de los iconos</string>
- <string name="dialog_pick_iconpack_title">Escoger paquete de iconos</string>
- <string name="default_iconpack_title">Iconos por defecto</string>
- <string name="icon_packs_title">Paquetes de iconos</string>
- <string name="no_iconpacks_summary">No hay paquetes de iconos instalados</string>
- <string name="clear_keyguard_wallpaper">Limpiar</string>
- <string name="all_apps_cling_cm">Personalizar tus aplicaciones</string>
- <string name="all_apps_cling_summary">Tocar el indicador de página para mostrar ajustes adicionales</string>
- <string name="menu_hidden_apps_delete">Restablecer</string>
+ <string name="scrolling_wallpaper">Desplazar fondo de pantalla</string>
+ <string name="grid_size_text">Tamaño de la cuadrícula</string>
+ <string name="grid_size_comfortable">Normal</string>
+ <string name="grid_size_cozy">Cómoda</string>
+ <string name="grid_size_condensed">Comprimida</string>
+ <string name="grid_size_custom">Personalizada</string>
+ <string name="preferences_interface_homescreen_custom">Selecciona el tamaño personalizado</string>
+ <string name="preferences_interface_homescreen_rows_title">Número de filas</string>
+ <string name="preferences_interface_homescreen_columns_title">Número de columnas</string>
<string name="hidden_apps_title">Ocultar aplicaciones</string>
+ <string name="scroll_effect_text">Efecto de desplazamiento</string>
+ <string name="drawer_sorting_text">Modo de ordenación</string>
+ <string name="sort_mode_title">Título</string>
+ <string name="sort_mode_launch_count">Veces ejecutado</string>
+ <string name="sort_mode_install_time">Fecha de instalación</string>
+ <string name="home_screen_search_text">Barra de búsqueda</string>
+ <string name="larger_icons_text">Iconos grandes</string>
+ <string name="icon_labels">Etiquetas de iconos</string>
+ <string name="icon_labels_show">Mostrar</string>
+ <string name="icon_labels_hide">Ocultar</string>
+ <string name="protected_app_settings">Aplicaciones protegidas</string>
+ <string name="search_screen_left_text">Panel de búsqueda</string>
+ <string name="search_screen_left_unsupported_toast">Debes tener una aplicación de búsqueda y CyanogenMod para poder utilizar esta característica.</string>
+ <string name="dialog_confirm">Confirmar</string>
</resources>
diff --git a/res/values-et/cm_arrays.xml b/res/values-et/cm_arrays.xml
index c652830e5..0a9de69ed 100644
--- a/res/values-et/cm_arrays.xml
+++ b/res/values-et/cm_arrays.xml
@@ -16,24 +16,19 @@
limitations under the License.
-->
<resources>
- <string-array name="preferences_interface_general_icons_text_font_family_entries">
- <item>Regulaarne</item>
- <item>Kerge</item>
- <item>Lühendatud</item>
- </string-array>
<string-array name="transition_effect_entries">
<item>Puudub</item>
- <item>Suumi Sisse</item>
- <item>Suumi Välja</item>
- <item>Pööra Üles</item>
- <item>Pööra Alla</item>
- <item>Kuubik Sisse</item>
- <item>Kuubik Välja</item>
+ <item>Suumi sisse</item>
+ <item>Suumi välja</item>
+ <item>Pööra üles</item>
+ <item>Pööra alla</item>
+ <item>Kuubik sisse</item>
+ <item>Kuubik välja</item>
<item>Kihid</item>
<item>Akordion</item>
<item>Pööra ümber</item>
- <item>Silinder Sisse</item>
- <item>Silinder Välja</item>
+ <item>Silinder sisse</item>
+ <item>Silinder välja</item>
<item>Karussell</item>
<item>Ülevaade</item>
</string-array>
diff --git a/res/values-et/cm_strings.xml b/res/values-et/cm_strings.xml
index 3b3ff2b5f..1b97ec2a1 100644
--- a/res/values-et/cm_strings.xml
+++ b/res/values-et/cm_strings.xml
@@ -16,49 +16,37 @@
limitations under the License.
-->
<resources>
- <string name="application_copyright">Autoriõigus \u00A9 2014 The CyanogenMod Project</string>
- <string name="sort_button_text">Sorteeri</string>
- <string name="filter_button_text">Filtreeri</string>
- <string name="default_screen_button_text">Vaikimisi ekraan</string>
- <string name="transition_effect_button_text">Kerimisefekt</string>
- <string name="sort_mode_title">Pealkiri</string>
- <string name="sort_mode_launch_count">Käivitamiste arv</string>
- <string name="sort_mode_install_time">Installeerimise aeg</string>
+ <string name="launcher_settings">KÄIVITAJA SEADED</string>
+ <string name="home_screen_settings">KODUEKRAANI SEADED</string>
+ <string name="drawer_settings">SAHTLI SEADED</string>
+ <string name="app_settings">RAKENDUSE SEADED</string>
+ <string name="setting_state_on">SEES</string>
+ <string name="setting_state_off">VÄLJAS</string>
+ <string name="themes_button_text">Teemad</string>
<string name="scrolling_page_outlines">Lehe äärisjooned</string>
<string name="scrolling_fade_adjacent">Sulanda äärislehed</string>
- <string name="wallpaper_scroll">Keri taustapilti</string>
- <string name="preferences_title">Sätted</string>
- <string name="preferences_application_title">Rakendus</string>
- <string name="preferences_interface_homescreen_title">Koduekraan</string>
- <string name="preferences_interface_homescreen_search_title">Otsinguriba</string>
- <string name="preferences_interface_homescreen_search_summary">Näita püsivat otsinguriba ekraani ülaosas</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_title">Peida ikoonide sildid</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">Peida ikoonide sildid koduekraanil</string>
- <string name="preferences_interface_drawer_title">Sahtel</string>
- <string name="preferences_interface_drawer_summary">Rakenduste ja vidinate sahtel</string>
- <string name="preferences_interface_drawer_apps_category">Rakendused</string>
- <string name="preferences_interface_drawer_hidden_apps_title">Peidetud rakendused</string>
- <string name="preferences_interface_drawer_hidden_apps_summary">Peida rakendusi sahtlist</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">Eemalda otseteed</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">Eemalda peidetud rakenduste otseteed koduekraanilt</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_title">Eemalda vidinad</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_summary">Eemalda peidetud rakenduste vidinad koduekraanilt</string>
- <string name="preferences_interface_drawer_hide_icon_labels_title">Peida ikoonide sildid</string>
- <string name="preferences_interface_drawer_hide_icon_labels_summary">Peida ikoonide sildid sahtlis</string>
- <string name="preferences_interface_dock_title">Dokk</string>
- <string name="preferences_interface_general_title">Üldine</string>
- <string name="preferences_interface_general_icons_category">Ikoonid</string>
- <string name="preferences_interface_general_icons_large_title">Suuremad ikoonid</string>
- <string name="preferences_interface_general_icons_large_summary">Kasuta ülisuuri rakenduste ikoone koduekraanil ja sahtlis</string>
- <string name="preferences_interface_general_icons_text_style_title">Kirja fondistiil</string>
- <string name="preferences_interface_general_icons_text_style_summary">Fondi tüüp ja stiil mida kasutatakse ikoonidel</string>
- <string name="dialog_pick_iconpack_title">Vali ikoonipakk</string>
- <string name="default_iconpack_title">Vaikimisi ikoonid</string>
- <string name="icon_packs_title">Ikoonipakid</string>
- <string name="no_iconpacks_summary">Ühtegi ikoonipakki pole installitud</string>
- <string name="clear_keyguard_wallpaper">Selge</string>
- <string name="all_apps_cling_cm">Kohandage oma sahtlit</string>
- <string name="all_apps_cling_summary">Puudutage lehe indikaatoril et näha täiendavaid sätteid</string>
- <string name="menu_hidden_apps_delete">Lähtesta</string>
+ <string name="scrolling_wallpaper">Keri taustapilti</string>
+ <string name="grid_size_text">Ruudustiku suurus</string>
+ <string name="grid_size_comfortable">Mugav</string>
+ <string name="grid_size_cozy">Kodune</string>
+ <string name="grid_size_condensed">Kärbitud</string>
+ <string name="grid_size_custom">Isiklik</string>
+ <string name="preferences_interface_homescreen_custom">Vali sobiv suurus</string>
+ <string name="preferences_interface_homescreen_rows_title">Ridade arv</string>
+ <string name="preferences_interface_homescreen_columns_title">Veergude arv</string>
<string name="hidden_apps_title">Peidetud rakendused</string>
+ <string name="scroll_effect_text">Kerimisefekt</string>
+ <string name="drawer_sorting_text">Sortimisrežiim</string>
+ <string name="sort_mode_title">Pealkiri</string>
+ <string name="sort_mode_launch_count">Käivitamiste arv</string>
+ <string name="sort_mode_install_time">Installeerimise aeg</string>
+ <string name="home_screen_search_text">Otsinguriba</string>
+ <string name="larger_icons_text">Suuremad ikoonid</string>
+ <string name="icon_labels">Ikooni sildid</string>
+ <string name="icon_labels_show">Näita</string>
+ <string name="icon_labels_hide">Peida</string>
+ <string name="protected_app_settings">Kaitstud rakendused</string>
+ <string name="search_screen_left_text">Otsingupaneel</string>
+ <string name="search_screen_left_unsupported_toast">Teil peab olema toetatud otsingurakendus ja CyanogenMod et kasutada seda võimalust.</string>
+ <string name="dialog_confirm">Kinnita</string>
</resources>
diff --git a/res/values-fi/cm_arrays.xml b/res/values-fi/cm_arrays.xml
index b466c383d..9b1d7a28e 100644
--- a/res/values-fi/cm_arrays.xml
+++ b/res/values-fi/cm_arrays.xml
@@ -16,11 +16,6 @@
limitations under the License.
-->
<resources>
- <string-array name="preferences_interface_general_icons_text_font_family_entries">
- <item>Tavallinen</item>
- <item>Ohut</item>
- <item>Tiivistetty</item>
- </string-array>
<string-array name="transition_effect_entries">
<item>Ei mitään</item>
<item>Lähennä</item>
diff --git a/res/values-fi/cm_strings.xml b/res/values-fi/cm_strings.xml
index 679510ca5..a9556788e 100644
--- a/res/values-fi/cm_strings.xml
+++ b/res/values-fi/cm_strings.xml
@@ -16,49 +16,37 @@
limitations under the License.
-->
<resources>
- <string name="application_copyright">Copyright \u00A9 2014 The CyanogenMod Project</string>
- <string name="sort_button_text">Järjestä</string>
- <string name="filter_button_text">Suodatin</string>
- <string name="default_screen_button_text">Oletusnäyttö</string>
- <string name="transition_effect_button_text">Vieritysefekti</string>
- <string name="sort_mode_title">Nimi</string>
- <string name="sort_mode_launch_count">Käynnistyskerrat</string>
- <string name="sort_mode_install_time">Asennuspäivä</string>
+ <string name="launcher_settings">LAUNCHERIN ASETUKSET</string>
+ <string name="home_screen_settings">KOTINÄYTÖN ASETUKSET</string>
+ <string name="drawer_settings">SOVELLUSVALIKON ASETUKSET</string>
+ <string name="app_settings">SOVELLUKSEN ASETUKSET</string>
+ <string name="setting_state_on">PÄÄLLÄ</string>
+ <string name="setting_state_off">POIS</string>
+ <string name="themes_button_text">Teemat</string>
<string name="scrolling_page_outlines">Sivun ulkoreunat</string>
<string name="scrolling_fade_adjacent">Häivytä sivun reunat</string>
- <string name="wallpaper_scroll">Vieritä taustakuvaa</string>
- <string name="preferences_title">Asetukset</string>
- <string name="preferences_application_title">Sovellus</string>
- <string name="preferences_interface_homescreen_title">Kotinäyttö</string>
- <string name="preferences_interface_homescreen_search_title">Hakupalkki</string>
- <string name="preferences_interface_homescreen_search_summary">Näytä pysyvä hakupalkki näytön yläreunassa</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_title">Piilota kuvakkeiden tekstit</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">Piilota kuvakkeiden tekstit kotinäytöllä</string>
- <string name="preferences_interface_drawer_title">Sovellusvalikko</string>
- <string name="preferences_interface_drawer_summary">Sovellus- ja widgetvalikko</string>
- <string name="preferences_interface_drawer_apps_category">Sovellukset</string>
- <string name="preferences_interface_drawer_hidden_apps_title">Piilotetut sovellukset</string>
- <string name="preferences_interface_drawer_hidden_apps_summary">Piilota sovellukset valikosta</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">Poista kuvakkeet</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">Poista piilotettujen sovellusten kuvakkeet kotinäytöltä</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_title">Poista widgetit</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_summary">Poista piilotettujen sovellusten widgetit kotinäytöltä</string>
- <string name="preferences_interface_drawer_hide_icon_labels_title">Piilota kuvakkeiden tekstit</string>
- <string name="preferences_interface_drawer_hide_icon_labels_summary">Piilota kuvakkeiden tekstit valikossa</string>
- <string name="preferences_interface_dock_title">Alapalkki</string>
- <string name="preferences_interface_general_title">Yleiset</string>
- <string name="preferences_interface_general_icons_category">Kuvakkeet</string>
- <string name="preferences_interface_general_icons_large_title">Suuremmat kuvakkeet</string>
- <string name="preferences_interface_general_icons_large_summary">Käytä erittäin suuria sovelluskuvakkeita kotinäytöllä ja sovellusvalikossa</string>
- <string name="preferences_interface_general_icons_text_style_title">Fonttityyli</string>
- <string name="preferences_interface_general_icons_text_style_summary">Muuta kuvakkeiden fonttien tyyliä</string>
- <string name="dialog_pick_iconpack_title">Valitse kuvakepaketti</string>
- <string name="default_iconpack_title">Oletuskuvakkeet</string>
- <string name="icon_packs_title">Kuvakepaketit</string>
- <string name="no_iconpacks_summary">Kuvakepaketteja ei asennettu</string>
- <string name="clear_keyguard_wallpaper">Tyhjennä</string>
- <string name="all_apps_cling_cm">Muokkaa sovellusvalikkoa</string>
- <string name="all_apps_cling_summary">Napauta sivun ilmaisinta nähdäksesi lisää asetuksia</string>
- <string name="menu_hidden_apps_delete">Nollaa</string>
+ <string name="scrolling_wallpaper">Vieritä taustakuvaa</string>
+ <string name="grid_size_text">Ruudukon koko</string>
+ <string name="grid_size_comfortable">Mukava</string>
+ <string name="grid_size_cozy">Kodikas</string>
+ <string name="grid_size_condensed">Tiivistetty</string>
+ <string name="grid_size_custom">Muokattu</string>
+ <string name="preferences_interface_homescreen_custom">Valitse mukautettu koko</string>
+ <string name="preferences_interface_homescreen_rows_title">Rivien määrä</string>
+ <string name="preferences_interface_homescreen_columns_title">Sarakkeiden määrä</string>
<string name="hidden_apps_title">Piilotetut sovellukset</string>
+ <string name="scroll_effect_text">Vieritysefekti</string>
+ <string name="drawer_sorting_text">Lajittelu</string>
+ <string name="sort_mode_title">Nimi</string>
+ <string name="sort_mode_launch_count">Käynnistyskerrat</string>
+ <string name="sort_mode_install_time">Asennuspäivä</string>
+ <string name="home_screen_search_text">Hakupalkki</string>
+ <string name="larger_icons_text">Suuremmat kuvakkeet</string>
+ <string name="icon_labels">Kuvakkeiden otsikot</string>
+ <string name="icon_labels_show">Näytä</string>
+ <string name="icon_labels_hide">Piilota</string>
+ <string name="protected_app_settings">Suojatut sovellukset</string>
+ <string name="search_screen_left_text">Hakupaneeli</string>
+ <string name="search_screen_left_unsupported_toast">Sinulla tulee olla tuettu hakusovellus ja CyanogenMod käyttääksesi tätä toimintoa.</string>
+ <string name="dialog_confirm">Vahvista</string>
</resources>
diff --git a/res/values-fr/cm_arrays.xml b/res/values-fr/cm_arrays.xml
index 15ef135ee..46a63a475 100644
--- a/res/values-fr/cm_arrays.xml
+++ b/res/values-fr/cm_arrays.xml
@@ -16,15 +16,10 @@
limitations under the License.
-->
<resources>
- <string-array name="preferences_interface_general_icons_text_font_family_entries">
- <item>Régulier</item>
- <item>Léger</item>
- <item>Condensé</item>
- </string-array>
<string-array name="transition_effect_entries">
<item>Aucun</item>
- <item>Zoom avant</item>
- <item>Zoom arrière</item>
+ <item>Zoom</item>
+ <item>Dézoom</item>
<item>Rotation vers le haut</item>
<item>Rotation vers le bas</item>
<item>Cube intérieur</item>
diff --git a/res/values-fr/cm_strings.xml b/res/values-fr/cm_strings.xml
index 1ba03261b..5de215d40 100644
--- a/res/values-fr/cm_strings.xml
+++ b/res/values-fr/cm_strings.xml
@@ -16,49 +16,37 @@
limitations under the License.
-->
<resources>
- <string name="application_copyright">Copyright \u00A9 2014 The CyanogenMod Project</string>
- <string name="sort_button_text">Trier</string>
- <string name="filter_button_text">Filtre</string>
- <string name="default_screen_button_text">Écran par défaut</string>
- <string name="transition_effect_button_text">Effet de défilement</string>
- <string name="sort_mode_title">Titre</string>
- <string name="sort_mode_launch_count">Nombre de lancements</string>
- <string name="sort_mode_install_time">Durée d\'installation</string>
+ <string name="launcher_settings">PARAMÈTRES DU LANCEUR</string>
+ <string name="home_screen_settings">PARAMÈTRES DE L\'ÉCRAN D\'ACCUEIL</string>
+ <string name="drawer_settings">PARAMÈTRES DE L\'ÉCRAN DES APPLICATIONS</string>
+ <string name="app_settings">PARAMÈTRES DE L\'APPLICATION</string>
+ <string name="setting_state_on">OUI</string>
+ <string name="setting_state_off">NON</string>
+ <string name="themes_button_text">Thèmes</string>
<string name="scrolling_page_outlines">Espacement des pages</string>
<string name="scrolling_fade_adjacent">Estomper les pages adjacentes</string>
- <string name="wallpaper_scroll">Défilement du fond d\'écran</string>
- <string name="preferences_title">Paramètres</string>
- <string name="preferences_application_title">Application</string>
- <string name="preferences_interface_homescreen_title">Écran d\'accueil</string>
- <string name="preferences_interface_homescreen_search_title">Barre de recherche</string>
- <string name="preferences_interface_homescreen_search_summary">Afficher la barre de recherche persistante en haut de l\'écran</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_title">Masquer le nom des icônes</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">Masquer le nom des icônes sur l\'écran d\'accueil</string>
- <string name="preferences_interface_drawer_title">Liste d\'applications</string>
- <string name="preferences_interface_drawer_summary">Applications et widgets de la liste des applications</string>
- <string name="preferences_interface_drawer_apps_category">Applications</string>
- <string name="preferences_interface_drawer_hidden_apps_title">Applications masquées</string>
- <string name="preferences_interface_drawer_hidden_apps_summary">Masquer les applications de la liste des applications</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">Supprimer les raccourcis</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">Supprimer les raccourcis sur l\'écran d\'accueil des applications masquées</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_title">Supprimer les widgets</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_summary">Supprimer les widgets sur l\'écran d\'accueil des applications masquées</string>
- <string name="preferences_interface_drawer_hide_icon_labels_title">Masquer le nom des icônes</string>
- <string name="preferences_interface_drawer_hide_icon_labels_summary">Masquer le nom des icônes dans la liste des applications</string>
- <string name="preferences_interface_dock_title">Dock</string>
- <string name="preferences_interface_general_title">Général</string>
- <string name="preferences_interface_general_icons_category">Icônes</string>
- <string name="preferences_interface_general_icons_large_title">Grandes icônes</string>
- <string name="preferences_interface_general_icons_large_summary">Utiliser des icônes extra-larges dans l\'écran d\'accueil et la liste d\'applications</string>
- <string name="preferences_interface_general_icons_text_style_title">Style de police de texte</string>
- <string name="preferences_interface_general_icons_text_style_summary">Variante et style de police à utiliser pour le texte des l\'icônes</string>
- <string name="dialog_pick_iconpack_title">Choisissez le pack d\'icônes</string>
- <string name="default_iconpack_title">Icônes par défaut</string>
- <string name="icon_packs_title">Packs d\'icônes</string>
- <string name="no_iconpacks_summary">Aucun pack d\'icônes installé</string>
- <string name="clear_keyguard_wallpaper">Supprimer</string>
- <string name="all_apps_cling_cm">Personnaliser votre affichage</string>
- <string name="all_apps_cling_summary">Appuyez sur l\'indicateur de page pour afficher les paramètres de configuration supplémentaires</string>
- <string name="menu_hidden_apps_delete">Réinitialiser</string>
+ <string name="scrolling_wallpaper">Défilement du fond d\'écran</string>
+ <string name="grid_size_text">Taille de la grille</string>
+ <string name="grid_size_comfortable">Confortable</string>
+ <string name="grid_size_cozy">Cosy</string>
+ <string name="grid_size_condensed">Condensé</string>
+ <string name="grid_size_custom">Personnalisée</string>
+ <string name="preferences_interface_homescreen_custom">Sélectionner la taille personnalisée</string>
+ <string name="preferences_interface_homescreen_rows_title">Nombre de lignes</string>
+ <string name="preferences_interface_homescreen_columns_title">Nombre de colonnes</string>
<string name="hidden_apps_title">Applications masquées</string>
+ <string name="scroll_effect_text">Effet de défilement</string>
+ <string name="drawer_sorting_text">Mode de tri</string>
+ <string name="sort_mode_title">Titre</string>
+ <string name="sort_mode_launch_count">Nombre de lancements</string>
+ <string name="sort_mode_install_time">Durée d\'installation</string>
+ <string name="home_screen_search_text">Barre de recherche</string>
+ <string name="larger_icons_text">Grandes icônes</string>
+ <string name="icon_labels">Nom des icônes</string>
+ <string name="icon_labels_show">Afficher</string>
+ <string name="icon_labels_hide">Masquer</string>
+ <string name="protected_app_settings">Applications protégées</string>
+ <string name="search_screen_left_text">Panneau de recherche</string>
+ <string name="search_screen_left_unsupported_toast">Vous devez avoir une application de recherche compatible et CyanogenMod pour utiliser cette fonctionnalité.</string>
+ <string name="dialog_confirm">Confirmer</string>
</resources>
diff --git a/res/values-hu/cm_arrays.xml b/res/values-hu/cm_arrays.xml
index e7b15fe2c..06a15a2fd 100644
--- a/res/values-hu/cm_arrays.xml
+++ b/res/values-hu/cm_arrays.xml
@@ -16,15 +16,10 @@
limitations under the License.
-->
<resources>
- <string-array name="preferences_interface_general_icons_text_font_family_entries">
- <item>Szokásos</item>
- <item>Világos</item>
- <item>Tömörített</item>
- </string-array>
<string-array name="transition_effect_entries">
<item>Nincs</item>
- <item>Nagyítás befelé</item>
- <item>Nagyítás kifelé</item>
+ <item>Nagyítás</item>
+ <item>Kicsinyítés</item>
<item>Forgatás felfelé</item>
<item>Forgatás lefelé</item>
<item>Kocka belül</item>
diff --git a/res/values-hu/cm_strings.xml b/res/values-hu/cm_strings.xml
index 434fd319e..4dd032e66 100644
--- a/res/values-hu/cm_strings.xml
+++ b/res/values-hu/cm_strings.xml
@@ -16,49 +16,37 @@
limitations under the License.
-->
<resources>
- <string name="application_copyright">Copyright \u00A9 2014 The CyanogenMod Project</string>
- <string name="sort_button_text">Rendezés</string>
- <string name="filter_button_text">Szűrő</string>
- <string name="default_screen_button_text">Alapértelmezett képernyő</string>
- <string name="transition_effect_button_text">Görgetés effekt</string>
- <string name="sort_mode_title">Név</string>
- <string name="sort_mode_launch_count">Indítások száma</string>
- <string name="sort_mode_install_time">Telepítés ideje</string>
+ <string name="launcher_settings">PROGRAMINDÍTÓ BEÁLLÍTÁSOK</string>
+ <string name="home_screen_settings">KEZDŐKÉPERNYŐ BEÁLLÍTÁSOK</string>
+ <string name="drawer_settings">ALKALMAZÁSKÉPERNYŐ BEÁLLÍTÁSOK</string>
+ <string name="app_settings">ALKALMAZÁS BEÁLLÍTÁSAI</string>
+ <string name="setting_state_on">BE</string>
+ <string name="setting_state_off">KI</string>
+ <string name="themes_button_text">Témák</string>
<string name="scrolling_page_outlines">Oldal körvonalak</string>
<string name="scrolling_fade_adjacent">Elhalványuló váltás az oldalak közt</string>
- <string name="wallpaper_scroll">Háttérkép görgetése</string>
- <string name="preferences_title">Beállítások</string>
- <string name="preferences_application_title">Alkamazás</string>
- <string name="preferences_interface_homescreen_title">Kezdőképernyő</string>
- <string name="preferences_interface_homescreen_search_title">Keresési sáv</string>
- <string name="preferences_interface_homescreen_search_summary">Állandó keresési sáv megjelenítése a képernyő felső </string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_title">Ikon feliratok elrejtése</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">Elrejti a kezdőképernyőn lévő ikonok neveit</string>
- <string name="preferences_interface_drawer_title">Alkalmazásképernyők</string>
- <string name="preferences_interface_drawer_summary">Alkalmazások és modulok</string>
- <string name="preferences_interface_drawer_apps_category">Alkalmazások</string>
- <string name="preferences_interface_drawer_hidden_apps_title">Rejtett alkalmazások</string>
- <string name="preferences_interface_drawer_hidden_apps_summary">Alkalmazások elrejtése az alkalmazásképernyőről</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">Rejtett alkalmazások (parancsikonok)</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">Rejtett alkalmazások ikonjainak eltávolítása</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_title">Rejtett alkalmazások (modulok)</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_summary">Rejtett alkalmazás moduljának eltávolítása</string>
- <string name="preferences_interface_drawer_hide_icon_labels_title">Ikon feliratok elrejtése</string>
- <string name="preferences_interface_drawer_hide_icon_labels_summary">Ikon feliratok elrejtése az alkalmazásképernyőkről</string>
- <string name="preferences_interface_dock_title">Dokkoló</string>
- <string name="preferences_interface_general_title">Általános</string>
- <string name="preferences_interface_general_icons_category">Ikonok</string>
- <string name="preferences_interface_general_icons_large_title">Nagyobb ikonok</string>
- <string name="preferences_interface_general_icons_large_summary">Extra méretű ikonok a kezdő ill. alkalmazás képernyőkön</string>
- <string name="preferences_interface_general_icons_text_style_title">Szöveg betűtípusa</string>
- <string name="preferences_interface_general_icons_text_style_summary">Ikon szövegének típusa</string>
- <string name="dialog_pick_iconpack_title">Ikoncsomag választása</string>
- <string name="default_iconpack_title">Alapértelmezett ikonok</string>
- <string name="icon_packs_title">Ikon csomagok</string>
- <string name="no_iconpacks_summary">Nincsenek telepítve ikoncsomagok</string>
- <string name="clear_keyguard_wallpaper">Törlés</string>
- <string name="all_apps_cling_cm">Alkalmazásképernyők testreszabása</string>
- <string name="all_apps_cling_summary">Érintse meg az oldaljelölőt a további konfigurációs beállítások megtekintéséhez</string>
- <string name="menu_hidden_apps_delete">Visszaállítás</string>
+ <string name="scrolling_wallpaper">Háttérkép görgetése</string>
+ <string name="grid_size_text">Rácsméret</string>
+ <string name="grid_size_comfortable">Kényelmes</string>
+ <string name="grid_size_cozy">Hangulatos</string>
+ <string name="grid_size_condensed">Tömörített</string>
+ <string name="grid_size_custom">Egyéni</string>
+ <string name="preferences_interface_homescreen_custom">Válassza ki az egyéni méretet</string>
+ <string name="preferences_interface_homescreen_rows_title">Sorok száma</string>
+ <string name="preferences_interface_homescreen_columns_title">Oszlopok száma</string>
<string name="hidden_apps_title">Rejtett alkalmazások</string>
+ <string name="scroll_effect_text">Görgetés effekt</string>
+ <string name="drawer_sorting_text">Rendezési mód</string>
+ <string name="sort_mode_title">Név</string>
+ <string name="sort_mode_launch_count">Indítások száma</string>
+ <string name="sort_mode_install_time">Telepítés ideje</string>
+ <string name="home_screen_search_text">Keresési sáv</string>
+ <string name="larger_icons_text">Nagyobb ikonok</string>
+ <string name="icon_labels">Ikon feliratok</string>
+ <string name="icon_labels_show">Megjelenítés</string>
+ <string name="icon_labels_hide">Elrejtés</string>
+ <string name="protected_app_settings">Védett alkalmazások</string>
+ <string name="search_screen_left_text">Keresés panel</string>
+ <string name="search_screen_left_unsupported_toast">Rendelkeznie kell egy támogatott kereső alkalmazással és CyanogenMod-dal, hogy használhassa ezt a funkciót.</string>
+ <string name="dialog_confirm">Megerősítés</string>
</resources>
diff --git a/res/values-in/cm_arrays.xml b/res/values-in/cm_arrays.xml
index d7c2e6fb6..4e7c2d485 100644
--- a/res/values-in/cm_arrays.xml
+++ b/res/values-in/cm_arrays.xml
@@ -16,24 +16,19 @@
limitations under the License.
-->
<resources>
- <string-array name="preferences_interface_general_icons_text_font_family_entries">
- <item>Reguler</item>
- <item>Terang</item>
- <item>Condensed</item>
- </string-array>
<string-array name="transition_effect_entries">
<item>Tidak Ada</item>
- <item>Perkecil</item>
- <item>Perbesar</item>
- <item>Putar ke Atas</item>
- <item>Putar ke Bawah</item>
- <item>Kubus Masuk</item>
- <item>Kubus Keluar</item>
+ <item>Memperbesar</item>
+ <item>Memperkecil</item>
+ <item>Memutar keatas</item>
+ <item>Memutar kebawah</item>
+ <item>Kubus masuk</item>
+ <item>Kubus keluar</item>
<item>Tumpukan</item>
- <item>Accordion</item>
+ <item>Akordion</item>
<item>Membalik</item>
- <item>Silinder Masuk</item>
- <item>Silinder Keluar</item>
+ <item>Silinder masuk</item>
+ <item>Silinder keluar</item>
<item>Komedi putar</item>
<item>Overview</item>
</string-array>
diff --git a/res/values-in/cm_strings.xml b/res/values-in/cm_strings.xml
index 85cd71ba4..3d9070e40 100644
--- a/res/values-in/cm_strings.xml
+++ b/res/values-in/cm_strings.xml
@@ -16,49 +16,37 @@
limitations under the License.
-->
<resources>
- <string name="application_copyright">Hak cipta \u00A9 2013 The CyanogenMod Project</string>
- <string name="sort_button_text">Urutkan</string>
- <string name="filter_button_text">Filter</string>
- <string name="default_screen_button_text">Layar default</string>
- <string name="transition_effect_button_text">Efek scroll</string>
- <string name="sort_mode_title">Judul</string>
- <string name="sort_mode_launch_count">Hitungan peluncur</string>
- <string name="sort_mode_install_time">Waktu pemasangan</string>
+ <string name="launcher_settings">PENGATURAN PELUNCUR</string>
+ <string name="home_screen_settings">PENGATURAN LAYAR HOME</string>
+ <string name="drawer_settings">PENGATURAN DRAWER</string>
+ <string name="app_settings">PENGATURAN APL</string>
+ <string name="setting_state_on">ON</string>
+ <string name="setting_state_off">OFF</string>
+ <string name="themes_button_text">Tema</string>
<string name="scrolling_page_outlines">Garis luar halaman</string>
<string name="scrolling_fade_adjacent">Fade side pages</string>
- <string name="wallpaper_scroll">Wallpaper gulir</string>
- <string name="preferences_title">Pengaturan</string>
- <string name="preferences_application_title">App</string>
- <string name="preferences_interface_homescreen_title">Layar home</string>
- <string name="preferences_interface_homescreen_search_title">Bar pencarian</string>
- <string name="preferences_interface_homescreen_search_summary">Tampilkan bar pencarian tetap di atas layar</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_title">Sembunyikan label ikon</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">Sembunyikan label ikon pada homescreen</string>
- <string name="preferences_interface_drawer_title">Drawer</string>
- <string name="preferences_interface_drawer_summary">Aplikasi dan widgets drawer</string>
- <string name="preferences_interface_drawer_apps_category">Aplikasi</string>
- <string name="preferences_interface_drawer_hidden_apps_title">Aplikasi tersembunyi</string>
- <string name="preferences_interface_drawer_hidden_apps_summary">Sembunyikan aplikasi dari drawer</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">Hapus pintasan</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">Hapus cara pintas apps yang tersembunyi dari homescreen</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_title">Hapus widget</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_summary">Hapus aplikasi widget tersembunyi dari homescreen</string>
- <string name="preferences_interface_drawer_hide_icon_labels_title">Sembunyikan label ikon</string>
- <string name="preferences_interface_drawer_hide_icon_labels_summary">Sembunyikan label ikon di drawer</string>
- <string name="preferences_interface_dock_title">Dock</string>
- <string name="preferences_interface_general_title">Umum</string>
- <string name="preferences_interface_general_icons_category">Ikon</string>
- <string name="preferences_interface_general_icons_large_title">Ikon lebih besar</string>
- <string name="preferences_interface_general_icons_large_summary">Gunakan ikon aplikasi lebih besar di homescreen dan drawer</string>
- <string name="preferences_interface_general_icons_text_style_title">Gaya teks font</string>
- <string name="preferences_interface_general_icons_text_style_summary">Varian dan gaya font untuk menggunakan teks icon</string>
- <string name="dialog_pick_iconpack_title">Pilih paket ikon</string>
- <string name="default_iconpack_title">Ikon semula</string>
- <string name="icon_packs_title">Paket ikon</string>
- <string name="no_iconpacks_summary">Tidak ada ikon paket yang diinstal</string>
- <string name="clear_keyguard_wallpaper">Bersihkan</string>
- <string name="all_apps_cling_cm">Sesuaikan drawer anda</string>
- <string name="all_apps_cling_summary">Tap indikator halaman untuk melihat pengaturan konfigurasi tambahan</string>
- <string name="menu_hidden_apps_delete">Kembalikan</string>
+ <string name="scrolling_wallpaper">Gulir wallpaper</string>
+ <string name="grid_size_text">Ukuran grid</string>
+ <string name="grid_size_comfortable">Comfortable</string>
+ <string name="grid_size_cozy">Cozy</string>
+ <string name="grid_size_condensed">Condensed</string>
+ <string name="grid_size_custom">Kustom</string>
+ <string name="preferences_interface_homescreen_custom">Pilih ukuran kustom</string>
+ <string name="preferences_interface_homescreen_rows_title">Jumlah baris</string>
+ <string name="preferences_interface_homescreen_columns_title">Jumlah kolom</string>
<string name="hidden_apps_title">Aplikasi tersembunyi</string>
+ <string name="scroll_effect_text">Efek gulir</string>
+ <string name="drawer_sorting_text">Mode penyortiran</string>
+ <string name="sort_mode_title">Judul</string>
+ <string name="sort_mode_launch_count">Hitungan peluncur</string>
+ <string name="sort_mode_install_time">Waktu pemasangan</string>
+ <string name="home_screen_search_text">Bar pencarian</string>
+ <string name="larger_icons_text">Ikon lebih besar</string>
+ <string name="icon_labels">Label ikon</string>
+ <string name="icon_labels_show">Tampilkan</string>
+ <string name="icon_labels_hide">Sembunyikan</string>
+ <string name="protected_app_settings">Aplikasi yang di lindungi</string>
+ <string name="search_screen_left_text">Panel pencarian</string>
+ <string name="search_screen_left_unsupported_toast">Anda harus memiliki apl pencarain yang didukung dan CyanogenMod untuk menggunakan fitur ini.</string>
+ <string name="dialog_confirm">Konfirmasi</string>
</resources>
diff --git a/res/values-it/cm_arrays.xml b/res/values-it/cm_arrays.xml
index 890b4566a..529ea113b 100644
--- a/res/values-it/cm_arrays.xml
+++ b/res/values-it/cm_arrays.xml
@@ -16,15 +16,10 @@
limitations under the License.
-->
<resources>
- <string-array name="preferences_interface_general_icons_text_font_family_entries">
- <item>Regolare</item>
- <item>Luminoso</item>
- <item>Condensato</item>
- </string-array>
<string-array name="transition_effect_entries">
<item>Nessuno</item>
- <item>Riduci</item>
<item>Ingrandisci</item>
+ <item>Riduci</item>
<item>Ruota su</item>
<item>Ruota giù</item>
<item>Cubo interno</item>
diff --git a/res/values-it/cm_strings.xml b/res/values-it/cm_strings.xml
index 1b1e072a8..a2dba2e78 100644
--- a/res/values-it/cm_strings.xml
+++ b/res/values-it/cm_strings.xml
@@ -16,49 +16,37 @@
limitations under the License.
-->
<resources>
- <string name="application_copyright">Copyright \u00A9 2014 The CyanogenMod Project</string>
- <string name="sort_button_text">Ordina</string>
- <string name="filter_button_text">Filtro</string>
- <string name="default_screen_button_text">Schermata predefinita</string>
- <string name="transition_effect_button_text">Effetto scorrimento</string>
- <string name="sort_mode_title">Titolo</string>
- <string name="sort_mode_launch_count">Numero avvii</string>
- <string name="sort_mode_install_time">Tempo installazione</string>
+ <string name="launcher_settings">IMPOSTAZIONI LAUNCHER</string>
+ <string name="home_screen_settings">IMPOSTAZIONI SCHERMATA HOME</string>
+ <string name="drawer_settings">IMPOSTAZIONI DRAWER</string>
+ <string name="app_settings">IMPOSTAZIONI APP</string>
+ <string name="setting_state_on">ON</string>
+ <string name="setting_state_off">OFF</string>
+ <string name="themes_button_text">Temi</string>
<string name="scrolling_page_outlines">Contorni pagina</string>
<string name="scrolling_fade_adjacent">Dissolvenza pagine laterali</string>
- <string name="wallpaper_scroll">Scorrimento wallpaper</string>
- <string name="preferences_title">Impostazioni</string>
- <string name="preferences_application_title">App</string>
- <string name="preferences_interface_homescreen_title">Schermata Home</string>
- <string name="preferences_interface_homescreen_search_title">Barra di ricerca</string>
- <string name="preferences_interface_homescreen_search_summary">Mostra la barra di ricerca persistente nella parte superiore dello schermo</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_title">Nascondi etichette icone</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">Nascondi le etichette delle icone sulla schermata Home</string>
- <string name="preferences_interface_drawer_title">Drawer</string>
- <string name="preferences_interface_drawer_summary">Drawer app e widget</string>
- <string name="preferences_interface_drawer_apps_category">App</string>
- <string name="preferences_interface_drawer_hidden_apps_title">App nascoste</string>
- <string name="preferences_interface_drawer_hidden_apps_summary">Nascondi le app dal drawer</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">Rimuovi scorciatoie</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">Rimuovi le scorciatoie delle app nascoste dalla schermata Home</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_title">Rimuovi widget</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_summary">Rimuovi i widget delle app nascoste dalla schermata Home</string>
- <string name="preferences_interface_drawer_hide_icon_labels_title">Nascondi etichette icone</string>
- <string name="preferences_interface_drawer_hide_icon_labels_summary">Nascondi le etichette delle icone nel drawer</string>
- <string name="preferences_interface_dock_title">Dock</string>
- <string name="preferences_interface_general_title">Generale</string>
- <string name="preferences_interface_general_icons_category">Icone</string>
- <string name="preferences_interface_general_icons_large_title">Icone grandi</string>
- <string name="preferences_interface_general_icons_large_summary">Usa le icone grandi delle app nella schermata Home e nel drawer</string>
- <string name="preferences_interface_general_icons_text_style_title">Stile caratteri testo</string>
- <string name="preferences_interface_general_icons_text_style_summary">Varianti e stile dei caratteri per il testo dell\'icona</string>
- <string name="dialog_pick_iconpack_title">Scegli pacchetto icone</string>
- <string name="default_iconpack_title">Icone predefinite</string>
- <string name="icon_packs_title">Pacchetti icone</string>
- <string name="no_iconpacks_summary">Nessun pacchetto di icone installato</string>
- <string name="clear_keyguard_wallpaper">Svuota</string>
- <string name="all_apps_cling_cm">Personalizza il drawer</string>
- <string name="all_apps_cling_summary">Tocca l\'indicatore della pagina per visualizzare le impostazioni di configurazione aggiuntive</string>
- <string name="menu_hidden_apps_delete">Ripristina</string>
+ <string name="scrolling_wallpaper">Sfondo scorrevole</string>
+ <string name="grid_size_text">Dimensione griglia</string>
+ <string name="grid_size_comfortable">Confortevole</string>
+ <string name="grid_size_cozy">Accogliente</string>
+ <string name="grid_size_condensed">Condensato</string>
+ <string name="grid_size_custom">Personalizzata</string>
+ <string name="preferences_interface_homescreen_custom">Personalizza dimensione</string>
+ <string name="preferences_interface_homescreen_rows_title">Numero di righe</string>
+ <string name="preferences_interface_homescreen_columns_title">Numero di colonne</string>
<string name="hidden_apps_title">App nascoste</string>
+ <string name="scroll_effect_text">Effetto scorrimento</string>
+ <string name="drawer_sorting_text">Modalità ordinamento</string>
+ <string name="sort_mode_title">Titolo</string>
+ <string name="sort_mode_launch_count">Numero avvii</string>
+ <string name="sort_mode_install_time">Tempo installazione</string>
+ <string name="home_screen_search_text">Barra di ricerca</string>
+ <string name="larger_icons_text">Icone grandi</string>
+ <string name="icon_labels">Etichette icone</string>
+ <string name="icon_labels_show">Visualizza</string>
+ <string name="icon_labels_hide">Nascondi</string>
+ <string name="protected_app_settings">App protette</string>
+ <string name="search_screen_left_text">Pannello ricerca</string>
+ <string name="search_screen_left_unsupported_toast">È necessario disporre di un app per la ricerca supportata e CyanogenMod per utilizzare questa funzionalità.</string>
+ <string name="dialog_confirm">Conferma</string>
</resources>
diff --git a/res/values-iw/cm_arrays.xml b/res/values-iw/cm_arrays.xml
index c6d027d04..bc7066482 100644
--- a/res/values-iw/cm_arrays.xml
+++ b/res/values-iw/cm_arrays.xml
@@ -16,24 +16,19 @@
limitations under the License.
-->
<resources>
- <string-array name="preferences_interface_general_icons_text_font_family_entries">
- <item>רגיל</item>
- <item>לבן</item>
- <item>מרוכז</item>
- </string-array>
<string-array name="transition_effect_entries">
<item>ללא</item>
<item>התקרבות</item>
<item>התרחקות</item>
- <item>סובב שמאלה</item>
- <item>סובב ימינה</item>
- <item>קוביית פנים</item>
- <item>קוביית חוץ</item>
+ <item>סובב למעלה</item>
+ <item>סובב למטע</item>
+ <item>קובייה פנימה</item>
+ <item>קוביה החוצה</item>
<item>מחסנית</item>
<item>אקורדיון</item>
<item>היפוך</item>
- <item>גליל פנימי</item>
- <item>גליל חיצוני</item>
+ <item>גליל פנימה</item>
+ <item>גליל החוצה</item>
<item>קרוסלה</item>
<item>תקציר</item>
</string-array>
diff --git a/res/values-iw/cm_strings.xml b/res/values-iw/cm_strings.xml
index 05d328735..8bbf211f1 100644
--- a/res/values-iw/cm_strings.xml
+++ b/res/values-iw/cm_strings.xml
@@ -16,49 +16,37 @@
limitations under the License.
-->
<resources>
- <string name="application_copyright">Copyright \u00A9 2014 The CyanogenMod Project</string>
- <string name="sort_button_text">מיין</string>
- <string name="filter_button_text">סינון</string>
- <string name="default_screen_button_text">מסך ברירת מחדל</string>
- <string name="transition_effect_button_text">אפקט גלילה</string>
- <string name="sort_mode_title">כותרת</string>
- <string name="sort_mode_launch_count">מספר הפעלות</string>
- <string name="sort_mode_install_time">זמן התקנה</string>
+ <string name="launcher_settings">הגדרות מפעיל</string>
+ <string name="home_screen_settings">הגדרות מסך הבית</string>
+ <string name="drawer_settings">הגדרות מגירת יישומים</string>
+ <string name="app_settings">הגדרות יישום</string>
+ <string name="setting_state_on">מופעל</string>
+ <string name="setting_state_off">מושבת</string>
+ <string name="themes_button_text">ערכות עיצוב</string>
<string name="scrolling_page_outlines">תיאור דף</string>
<string name="scrolling_fade_adjacent">עימום דפים צדדיים</string>
- <string name="wallpaper_scroll">גלילת טפט</string>
- <string name="preferences_title">העדפות</string>
- <string name="preferences_application_title">יישום</string>
- <string name="preferences_interface_homescreen_title">מסך הבית</string>
- <string name="preferences_interface_homescreen_search_title">סרגל החיפוש</string>
- <string name="preferences_interface_homescreen_search_summary">הצג את שורת החיפוש תמיד בחלק העליון של המסך</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_title">הסתר תוויות הסמלים</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">הסתר תוויות הסמלים על מסך הבית</string>
- <string name="preferences_interface_drawer_title">מגירה</string>
- <string name="preferences_interface_drawer_summary">מגירת הווידג\'טים והיישומים</string>
- <string name="preferences_interface_drawer_apps_category">יישומים</string>
- <string name="preferences_interface_drawer_hidden_apps_title">יישומים מוסתרים</string>
- <string name="preferences_interface_drawer_hidden_apps_summary">הסתר יישומים מהמגירה</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">הסר קיצורי דרך</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">הסר את קיצורי הדרך של היישומים המוסתרים ממסך הבית</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_title">הסר ווידג\'טים</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_summary">הסר את הווידג\'טים של היישומים המוסתרים ממסך הבית</string>
- <string name="preferences_interface_drawer_hide_icon_labels_title">הסתר תוויות הסמלים</string>
- <string name="preferences_interface_drawer_hide_icon_labels_summary">הסתר תוויות הסמלים במגירה</string>
- <string name="preferences_interface_dock_title">עגינה</string>
- <string name="preferences_interface_general_title">כללי</string>
- <string name="preferences_interface_general_icons_category">סמלים</string>
- <string name="preferences_interface_general_icons_large_title">סמלים גדולים יותר</string>
- <string name="preferences_interface_general_icons_large_summary">השתמש בצלמיות יישום גדול מאוד במסך הבית ובמגירה</string>
- <string name="preferences_interface_general_icons_text_style_title">סגנון הגופן של הטקסט</string>
- <string name="preferences_interface_general_icons_text_style_summary">סגנון ועיצוב הגופן עבור טקסט הסמלים</string>
- <string name="dialog_pick_iconpack_title">בחר ערכת סמלים</string>
- <string name="default_iconpack_title">סמלי ברירת מחדל</string>
- <string name="icon_packs_title">אוסף סמלים</string>
- <string name="no_iconpacks_summary">לא מותקנות ערכות סמל</string>
- <string name="clear_keyguard_wallpaper">נקה</string>
- <string name="all_apps_cling_cm">התאמה אישית של מגירת היישומים</string>
- <string name="all_apps_cling_summary">הקש על מחוון הדף כדי להציג הגדרות נוספות</string>
- <string name="menu_hidden_apps_delete">אפס</string>
+ <string name="scrolling_wallpaper">גלילת טפט</string>
+ <string name="grid_size_text">גודל רשת</string>
+ <string name="grid_size_comfortable">נוח</string>
+ <string name="grid_size_cozy">נעים</string>
+ <string name="grid_size_condensed">מרוכז</string>
+ <string name="grid_size_custom">מותאם אישית</string>
+ <string name="preferences_interface_homescreen_custom">בחר גודל מותאם אישית</string>
+ <string name="preferences_interface_homescreen_rows_title">מספר שורות</string>
+ <string name="preferences_interface_homescreen_columns_title">מספר עמודות</string>
<string name="hidden_apps_title">יישומים מוסתרים</string>
+ <string name="scroll_effect_text">אפקט גלילה</string>
+ <string name="drawer_sorting_text">מצב המיון</string>
+ <string name="sort_mode_title">כותרת</string>
+ <string name="sort_mode_launch_count">מספר הפעלות</string>
+ <string name="sort_mode_install_time">זמן התקנה</string>
+ <string name="home_screen_search_text">סרגל החיפוש</string>
+ <string name="larger_icons_text">סמלים גדולים יותר</string>
+ <string name="icon_labels">תוויות סמלים</string>
+ <string name="icon_labels_show">הצג</string>
+ <string name="icon_labels_hide">הסתר</string>
+ <string name="protected_app_settings">יישומים מוגנים</string>
+ <string name="search_screen_left_text">לוח חיפוש</string>
+ <string name="search_screen_left_unsupported_toast">אתה חייב יישום חיפוש נתמך ו-CyanogenMod כדי להשתמש בתכונה זו.</string>
+ <string name="dialog_confirm">אשר</string>
</resources>
diff --git a/res/values-ja/cm_arrays.xml b/res/values-ja/cm_arrays.xml
index e78f2b716..b215aa601 100644
--- a/res/values-ja/cm_arrays.xml
+++ b/res/values-ja/cm_arrays.xml
@@ -16,25 +16,20 @@
limitations under the License.
-->
<resources>
- <string-array name="preferences_interface_general_icons_text_font_family_entries">
- <item>標準</item>
- <item>Light</item>
- <item>Condensed</item>
- </string-array>
<string-array name="transition_effect_entries">
<item>なし</item>
- <item>ズームイン</item>
- <item>ズームアウト</item>
- <item>上回転</item>
- <item>下回転</item>
- <item>キューブイン</item>
- <item>キューブアウト</item>
- <item>スタック</item>
- <item>アコーディオン</item>
- <item>フリップ</item>
- <item>シリンダーイン</item>
- <item>シリンダーアウト</item>
- <item>カルーセル</item>
- <item>オーバービュー</item>
+ <item>Zoom in</item>
+ <item>Zoom out</item>
+ <item>Rotate up</item>
+ <item>Rotate down</item>
+ <item>Cube in</item>
+ <item>Cube out</item>
+ <item>Stack</item>
+ <item>Accordion</item>
+ <item>Flip</item>
+ <item>Cylinder in</item>
+ <item>Cylinder out</item>
+ <item>Carousel</item>
+ <item>Overview</item>
</string-array>
</resources>
diff --git a/res/values-ja/cm_strings.xml b/res/values-ja/cm_strings.xml
index 3a6bd8644..e127daab2 100644
--- a/res/values-ja/cm_strings.xml
+++ b/res/values-ja/cm_strings.xml
@@ -16,49 +16,37 @@
limitations under the License.
-->
<resources>
- <string name="application_copyright">Copyright \u00A9 2014 The CyanogenMod Project</string>
- <string name="sort_button_text">並べ替え</string>
- <string name="filter_button_text">フィルター</string>
- <string name="default_screen_button_text">デフォルトの画面</string>
- <string name="transition_effect_button_text">スクロール効果</string>
- <string name="sort_mode_title">タイトル</string>
- <string name="sort_mode_launch_count">起動回数</string>
- <string name="sort_mode_install_time">インストール日時</string>
+ <string name="launcher_settings">ランチャーの設定</string>
+ <string name="home_screen_settings">ホーム画面の設定</string>
+ <string name="drawer_settings">ドロワーの設定</string>
+ <string name="app_settings">アプリの設定</string>
+ <string name="setting_state_on">ON</string>
+ <string name="setting_state_off">OFF</string>
+ <string name="themes_button_text">テーマ</string>
<string name="scrolling_page_outlines">ページの外枠を表示</string>
<string name="scrolling_fade_adjacent">側面のページをフェード</string>
- <string name="wallpaper_scroll">壁紙をスクロール</string>
- <string name="preferences_title">設定</string>
- <string name="preferences_application_title">アプリ</string>
- <string name="preferences_interface_homescreen_title">ホーム画面</string>
- <string name="preferences_interface_homescreen_search_title">検索バー</string>
- <string name="preferences_interface_homescreen_search_summary">画面の上部に検索バーを常に表示する</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_title">アイコンラベルを非表示にする</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">ホーム画面でアイコンラベルを非表示にする</string>
- <string name="preferences_interface_drawer_title">ドロワー</string>
- <string name="preferences_interface_drawer_summary">アプリとウィジェットのドロワー</string>
- <string name="preferences_interface_drawer_apps_category">アプリ</string>
- <string name="preferences_interface_drawer_hidden_apps_title">非表示にするアプリ</string>
- <string name="preferences_interface_drawer_hidden_apps_summary">ドロワーからアプリを非表示にする</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">ショートカットを削除</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">ホーム画面から非表示にしたアプリのショートカットを削除する</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_title">ウィジェットを削除</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_summary">ホーム画面から非表示にしたアプリのウィジェットを削除する</string>
- <string name="preferences_interface_drawer_hide_icon_labels_title">アイコンラベルを非表示にする</string>
- <string name="preferences_interface_drawer_hide_icon_labels_summary">ドロワーでアイコンラベルを非表示にする</string>
- <string name="preferences_interface_dock_title">ドック</string>
- <string name="preferences_interface_general_title">全般</string>
- <string name="preferences_interface_general_icons_category">アイコン</string>
- <string name="preferences_interface_general_icons_large_title">大きいアイコン</string>
- <string name="preferences_interface_general_icons_large_summary">ホーム画面とドロワーで大きいアイコンを使用する</string>
- <string name="preferences_interface_general_icons_text_style_title">テキストのフォントスタイル</string>
- <string name="preferences_interface_general_icons_text_style_summary">アイコンテキストに使用するフォントスタイルと種類</string>
- <string name="dialog_pick_iconpack_title">アイコンパックを選択</string>
- <string name="default_iconpack_title">デフォルトのアイコン</string>
- <string name="icon_packs_title">アイコンパック</string>
- <string name="no_iconpacks_summary">アイコンパックがインストールされていません</string>
- <string name="clear_keyguard_wallpaper">クリア</string>
- <string name="all_apps_cling_cm">ドロワーをカスタマイズ</string>
- <string name="all_apps_cling_summary">追加の構成設定を表示するには、ページインジケータをタップします。</string>
- <string name="menu_hidden_apps_delete">リセット</string>
+ <string name="scrolling_wallpaper">壁紙のスクロール</string>
+ <string name="grid_size_text">グリッドサイズ</string>
+ <string name="grid_size_comfortable">Comfortable</string>
+ <string name="grid_size_cozy">Cozy</string>
+ <string name="grid_size_condensed">Condensed</string>
+ <string name="grid_size_custom">カスタム</string>
+ <string name="preferences_interface_homescreen_custom">カスタムのサイズを選択</string>
+ <string name="preferences_interface_homescreen_rows_title">行数</string>
+ <string name="preferences_interface_homescreen_columns_title">列数</string>
<string name="hidden_apps_title">非表示にするアプリ</string>
+ <string name="scroll_effect_text">スクロール効果</string>
+ <string name="drawer_sorting_text">並べ替えモード</string>
+ <string name="sort_mode_title">タイトル</string>
+ <string name="sort_mode_launch_count">起動回数</string>
+ <string name="sort_mode_install_time">インストール日時</string>
+ <string name="home_screen_search_text">検索バー</string>
+ <string name="larger_icons_text">大きいアイコン</string>
+ <string name="icon_labels">アイコンラベル</string>
+ <string name="icon_labels_show">表示</string>
+ <string name="icon_labels_hide">非表示</string>
+ <string name="protected_app_settings">アプリの保護</string>
+ <string name="search_screen_left_text">検索パネル</string>
+ <string name="search_screen_left_unsupported_toast">この機能を利用するには、サポートされている検索アプリとCyanogenModが必要です。</string>
+ <string name="dialog_confirm">確認</string>
</resources>
diff --git a/res/values-ku/cm_arrays.xml b/res/values-ku/cm_arrays.xml
new file mode 100644
index 000000000..6770e6dc4
--- /dev/null
+++ b/res/values-ku/cm_arrays.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.net-->
+<!--
+ Copyright (C) 2014 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <string-array name="transition_effect_entries">
+ <item>هیچ</item>
+ <item>زومکردن بۆ ناو</item>
+ <item>زومکردن بۆ دەرەوە</item>
+ <item>سوڕانەوە بۆ سەرەوە</item>
+ <item>سوڕانەوە بۆ خوارەوە</item>
+ <item>شەشپاڵو بۆ ناو</item>
+ <item>شەشپاڵو دەرەوە</item>
+ <item>كەتەكە</item>
+ <item>ئۆكۆردێون</item>
+ <item>قاتکردن</item>
+ <item>لولەک لەناو</item>
+ <item>لولەک بۆ دەرەوە</item>
+ <item>غارغارێن</item>
+ <item>پیشاندانی گشتی</item>
+ </string-array>
+</resources>
diff --git a/res/values-ku/cm_strings.xml b/res/values-ku/cm_strings.xml
new file mode 100644
index 000000000..449353f02
--- /dev/null
+++ b/res/values-ku/cm_strings.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.net-->
+<!--
+ Copyright (C) 2014 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <string name="home_screen_settings">رێکخستنی شاشەی سەرەکی</string>
+ <string name="setting_state_on">هەڵگیرساو</string>
+ <string name="setting_state_off">کووژاوە</string>
+ <string name="themes_button_text">رووکارەکان</string>
+ <string name="grid_size_custom">دروستکراو</string>
+ <string name="hidden_apps_title">شاردنەوەی بەرنامەکان</string>
+ <string name="drawer_sorting_text">جۆری پۆڵێنکردن</string>
+ <string name="sort_mode_title">ناونیشان</string>
+ <string name="sort_mode_launch_count">دانانی هه‌ژمار</string>
+ <string name="sort_mode_install_time">کاتی دامەزراندن</string>
+ <string name="home_screen_search_text">شریتی گەڕان</string>
+ <string name="larger_icons_text">وێنۆچکەی گەورەتر</string>
+ <string name="icon_labels_show">پیشاندان</string>
+ <string name="icon_labels_hide">شاردنەوە</string>
+ <string name="protected_app_settings">بەرنامە پارێزراوەکان</string>
+ <string name="search_screen_left_text">پەرەی گەران</string>
+ <string name="dialog_confirm">دلنیاکردنەوە</string>
+</resources>
diff --git a/res/values-land/config.xml b/res/values-land/config.xml
index 121bb0c14..31115c9cb 100644
--- a/res/values-land/config.xml
+++ b/res/values-land/config.xml
@@ -18,6 +18,4 @@
<!-- Workspace -->
<!-- Whether or not the drop targets drop down as opposed to fade in -->
<bool name="config_useDropTargetDownTransition">false</bool>
- <!-- Whether or not to fade the side pages -->
- <bool name="config_workspaceFadeAdjacentScreens">false</bool>
</resources>
diff --git a/res/values-land/dimens.xml b/res/values-land/dimens.xml
index 5961b1936..07d92798d 100644
--- a/res/values-land/dimens.xml
+++ b/res/values-land/dimens.xml
@@ -19,11 +19,6 @@
<dimen name="toolbar_button_vertical_padding">8dip</dimen>
<dimen name="toolbar_button_horizontal_padding">0dip</dimen>
-<!-- Workspace -->
- <!-- We really want the page spacing to be the max of either the button bar
- height or the qsb bar height -->
- <dimen name="workspace_page_spacing">-1dp</dimen>
-
<!-- AppsCustomize -->
<dimen name="apps_customize_tab_bar_height">42dp</dimen>
<integer name="apps_customize_widget_cell_count_x">3</integer>
diff --git a/res/values-land/styles.xml b/res/values-land/styles.xml
index ccb5fcb06..87a744455 100644
--- a/res/values-land/styles.xml
+++ b/res/values-land/styles.xml
@@ -19,15 +19,11 @@
<resources>
<!-- Search Bar -->
- <style name="QSBBar">
- </style>
- <style name="SearchDropTargetBar">
- </style>
<style name="SearchButton">
</style>
<style name="DropTargetButtonContainer">
<item name="android:layout_width">match_parent</item>
- <item name="android:layout_height">0dp</item>
+ <item name="android:layout_height">wrap_content</item>
</style>
<style name="DropTargetButton">
<item name="android:layout_width">wrap_content</item>
@@ -36,8 +32,8 @@
<item name="android:gravity">center</item>
<item name="android:paddingTop">@dimen/toolbar_button_vertical_padding</item>
<item name="android:paddingBottom">@dimen/toolbar_button_vertical_padding</item>
- <item name="android:paddingStart">@dimen/toolbar_button_horizontal_padding</item>
- <item name="android:paddingEnd">@dimen/toolbar_button_horizontal_padding</item>
+ <item name="android:paddingLeft">@dimen/toolbar_button_horizontal_padding</item>
+ <item name="android:paddingRight">@dimen/toolbar_button_horizontal_padding</item>
<item name="android:shadowColor">#DD000000</item>
<item name="android:shadowDx">0.0</item>
<item name="android:shadowDy">1.0</item>
diff --git a/res/values-lb/cm_arrays.xml b/res/values-lb/cm_arrays.xml
index 6074c5ac9..5c2e3c8a4 100644
--- a/res/values-lb/cm_arrays.xml
+++ b/res/values-lb/cm_arrays.xml
@@ -16,24 +16,19 @@
limitations under the License.
-->
<resources>
- <string-array name="preferences_interface_general_icons_text_font_family_entries">
- <item>Normal</item>
- <item>Dënn</item>
- <item>Schmuel</item>
- </string-array>
<string-array name="transition_effect_entries">
<item>Keen</item>
- <item>Erazoomen</item>
- <item>Erauszoomen</item>
- <item>Eroprotéieren</item>
- <item>Erofrotéieren</item>
- <item>Wierfel bannen</item>
- <item>Wierfel baussen</item>
+ <item>Zoom in</item>
+ <item>Zoom out</item>
+ <item>Rotate up</item>
+ <item>Rotate down</item>
+ <item>Cube in</item>
+ <item>Cube out</item>
<item>Koup</item>
<item>Akkordeon</item>
<item>Ëmdréinen</item>
- <item>Zylinder bannen</item>
- <item>Zylinder baussen</item>
+ <item>Cylinder in</item>
+ <item>Cylinder out</item>
<item>Karussell</item>
<item>Iwwersiicht</item>
</string-array>
diff --git a/res/values-lb/cm_strings.xml b/res/values-lb/cm_strings.xml
index 19a760f55..7c98f88d1 100644
--- a/res/values-lb/cm_strings.xml
+++ b/res/values-lb/cm_strings.xml
@@ -16,38 +16,10 @@
limitations under the License.
-->
<resources>
- <string name="application_copyright">Copyright \u00A9 2014 The CyanogenMod Project</string>
- <string name="sort_button_text">Zortéieren</string>
- <string name="filter_button_text">Filteren</string>
- <string name="default_screen_button_text">Standardsäit</string>
- <string name="transition_effect_button_text">Scrolleffekt</string>
+ <string name="setting_state_on">UN</string>
+ <string name="scrolling_page_outlines">Säiterummen</string>
+ <string name="scrolling_fade_adjacent">Säiten um Rand ausblenden</string>
<string name="sort_mode_title">Titel</string>
<string name="sort_mode_launch_count">Startunzuel</string>
<string name="sort_mode_install_time">Installatiounszäit</string>
- <string name="scrolling_page_outlines">Säiterummen</string>
- <string name="scrolling_fade_adjacent">Säiten um Rand ausblenden</string>
- <string name="wallpaper_scroll">Hannergrondbild scrollen</string>
- <string name="preferences_title">Astellungen</string>
- <string name="preferences_application_title">App</string>
- <string name="preferences_interface_homescreen_title">Startschierm</string>
- <string name="preferences_interface_homescreen_search_title">Sichkëscht</string>
- <string name="preferences_interface_homescreen_search_summary">D\'Sichfeld um ieweschte Bord vum Schierm ëmmer uweisen</string>
- <string name="preferences_interface_drawer_title">App-Iwwersiicht</string>
- <string name="preferences_interface_drawer_apps_category">Apps</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">Ofkierzungen ewechhuelen</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_title">Widgets ewechhuelen</string>
- <string name="preferences_interface_dock_title">Dock</string>
- <string name="preferences_interface_general_title">Allgemeng</string>
- <string name="preferences_interface_general_icons_category">Symboler</string>
- <string name="preferences_interface_general_icons_large_title">Grouss Symboler</string>
- <string name="preferences_interface_general_icons_large_summary">Grouss Symboler fir d\'Apps um Startschierm a bei der App-Iwwersiicht benotzen</string>
- <string name="preferences_interface_general_icons_text_style_title">Schrëftstil</string>
- <string name="preferences_interface_general_icons_text_style_summary">Schrëftaart a -stil vum Text ënner de Symboler</string>
- <string name="dialog_pick_iconpack_title">Symbolpak auswielen</string>
- <string name="default_iconpack_title">Standardsymboler</string>
- <string name="icon_packs_title">Symbolpäck</string>
- <string name="no_iconpacks_summary">Keng Symbolpäck installéiert</string>
- <string name="all_apps_cling_cm">App-Iwwersiicht konfiguréieren</string>
- <string name="all_apps_cling_summary">Dréck de Säitenindikator fir zousätzlech Astellungen ze gesinn</string>
- <string name="menu_hidden_apps_delete">Zrécksetzen</string>
</resources>
diff --git a/res/values-lt/cm_arrays.xml b/res/values-lt/cm_arrays.xml
index 47465cbdc..83b8e4562 100644
--- a/res/values-lt/cm_arrays.xml
+++ b/res/values-lt/cm_arrays.xml
@@ -16,11 +16,6 @@
limitations under the License.
-->
<resources>
- <string-array name="preferences_interface_general_icons_text_font_family_entries">
- <item>Įprastas</item>
- <item>Plonas</item>
- <item>Suglaustas</item>
- </string-array>
<string-array name="transition_effect_entries">
<item>Joks</item>
<item>Padidinti</item>
diff --git a/res/values-lt/cm_strings.xml b/res/values-lt/cm_strings.xml
index 116b19e46..271c9a6da 100644
--- a/res/values-lt/cm_strings.xml
+++ b/res/values-lt/cm_strings.xml
@@ -16,49 +16,37 @@
limitations under the License.
-->
<resources>
- <string name="application_copyright">Autorinės teisės \u00A9 2014 „CyanogenMod“ projektas</string>
- <string name="sort_button_text">Rūšiuoti</string>
- <string name="filter_button_text">Filtras</string>
- <string name="default_screen_button_text">Numatytasis ekranas</string>
- <string name="transition_effect_button_text">Slinkimo efektas</string>
+ <string name="launcher_settings">PALEIDĖJO NUSTATYMAI</string>
+ <string name="home_screen_settings">PAGRINDINIO EKRANO NUSTATYMAI</string>
+ <string name="drawer_settings">STALČIAUS NUSTATYMAI</string>
+ <string name="app_settings">PROGRAMOS NUSTATYMAI</string>
+ <string name="setting_state_on">ĮJUNGTA</string>
+ <string name="setting_state_off">IŠJUNGTA</string>
+ <string name="themes_button_text">Temos</string>
+ <string name="scrolling_page_outlines">Puslapio kontūrai</string>
+ <string name="scrolling_fade_adjacent">Išblukinti šoninius puslapius</string>
+ <string name="scrolling_wallpaper">Slinkti darbalaukio foną</string>
+ <string name="grid_size_text">Tinklelio dydis</string>
+ <string name="grid_size_comfortable">Patogus</string>
+ <string name="grid_size_cozy">Jaukus</string>
+ <string name="grid_size_condensed">Suglaustas</string>
+ <string name="grid_size_custom">Individualus</string>
+ <string name="preferences_interface_homescreen_custom">Pasirinkite individualų dydį</string>
+ <string name="preferences_interface_homescreen_rows_title">Eilučių skaičius</string>
+ <string name="preferences_interface_homescreen_columns_title">Stulpelių skaičius</string>
+ <string name="hidden_apps_title">Paslėptos programos</string>
+ <string name="scroll_effect_text">Slinkimo efektas</string>
+ <string name="drawer_sorting_text">Rūšiavimo režimas</string>
<string name="sort_mode_title">Pavadinimas</string>
<string name="sort_mode_launch_count">Paleidimų kiekis</string>
<string name="sort_mode_install_time">Įdiegimo laikas</string>
- <string name="scrolling_page_outlines">Puslapio kontūrai</string>
- <string name="scrolling_fade_adjacent">Išblukinti šoninius ekranus</string>
- <string name="wallpaper_scroll">Slinkti ekrano foną</string>
- <string name="preferences_title">Nustatymai</string>
- <string name="preferences_application_title">Programa</string>
- <string name="preferences_interface_homescreen_title">Pagrindinis ekranas</string>
- <string name="preferences_interface_homescreen_search_title">Paieškos juosta</string>
- <string name="preferences_interface_homescreen_search_summary">Rodyti nuolatinę paieškos juostą ekrano viršuje</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_title">Paslėpti piktogramų pavadinimus</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">Paslėpti piktogramų pavadinimus pagrindiniame ekrane</string>
- <string name="preferences_interface_drawer_title">Stalčius</string>
- <string name="preferences_interface_drawer_summary">Programų ir valdiklių stalčius</string>
- <string name="preferences_interface_drawer_apps_category">Programos</string>
- <string name="preferences_interface_drawer_hidden_apps_title">Paslėptos programos</string>
- <string name="preferences_interface_drawer_hidden_apps_summary">Paslėpti programas iš stalčiaus</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">Pašalinti nuorodas</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">Pašalinti paslėptų programų nuorodas iš pagrindinio ekrano</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_title">Pašalinti valdiklius</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_summary">Pašalinti paslėptų programų valdiklius iš pagrindinio ekrano</string>
- <string name="preferences_interface_drawer_hide_icon_labels_title">Paslėpti piktogramų pavadinimus</string>
- <string name="preferences_interface_drawer_hide_icon_labels_summary">Paslėpti piktogramų pavadinimus iš stalčiaus</string>
- <string name="preferences_interface_dock_title">Dokas</string>
- <string name="preferences_interface_general_title">Bendra</string>
- <string name="preferences_interface_general_icons_category">Piktogramos</string>
- <string name="preferences_interface_general_icons_large_title">Didesnės piktogramos</string>
- <string name="preferences_interface_general_icons_large_summary">Naudoti didesnes programų piktogramas pagrindiniame ekrane ir stalčiuje</string>
- <string name="preferences_interface_general_icons_text_style_title">Teksto šrifto stilius</string>
- <string name="preferences_interface_general_icons_text_style_summary">Piktogramos teksto šrifto variantas ir stilius</string>
- <string name="dialog_pick_iconpack_title">Pasirinkti piktogramų paketą</string>
- <string name="default_iconpack_title">Numatytosios piktogramos</string>
- <string name="icon_packs_title">Piktogramų paketai</string>
- <string name="no_iconpacks_summary">Piktogramų paketai neįdiegti</string>
- <string name="clear_keyguard_wallpaper">Išvalyti</string>
- <string name="all_apps_cling_cm">Tinkinti savo stalčių</string>
- <string name="all_apps_cling_summary">Bakstelėkite puslapio indikatorių norėdami peržiūrėti papildomus konfigūracijos nustatymus</string>
- <string name="menu_hidden_apps_delete">Atkurti</string>
- <string name="hidden_apps_title">Paslėptos programos</string>
+ <string name="home_screen_search_text">Paieškos juosta</string>
+ <string name="larger_icons_text">Didesnės piktogramos</string>
+ <string name="icon_labels">Piktogramų pavadinimai</string>
+ <string name="icon_labels_show">Rodyti</string>
+ <string name="icon_labels_hide">Paslėpti</string>
+ <string name="protected_app_settings">Apsaugotos programos</string>
+ <string name="search_screen_left_text">Paieškos panėlė</string>
+ <string name="search_screen_left_unsupported_toast">Jūs privalote turėti palaikomą paieškos programą ir „CyanogenMod“ norėdami naudotis šia funkcija.</string>
+ <string name="dialog_confirm">Patvirtinti</string>
</resources>
diff --git a/res/values-nb/cm_arrays.xml b/res/values-nb/cm_arrays.xml
index ffec66d24..55f4e24f4 100644
--- a/res/values-nb/cm_arrays.xml
+++ b/res/values-nb/cm_arrays.xml
@@ -16,11 +16,6 @@
limitations under the License.
-->
<resources>
- <string-array name="preferences_interface_general_icons_text_font_family_entries">
- <item>Vanlig</item>
- <item>Lys</item>
- <item>Kondensert</item>
- </string-array>
<string-array name="transition_effect_entries">
<item>Ingen</item>
<item>Zoome inn</item>
diff --git a/res/values-nb/cm_strings.xml b/res/values-nb/cm_strings.xml
index ed18d7186..7078b4992 100644
--- a/res/values-nb/cm_strings.xml
+++ b/res/values-nb/cm_strings.xml
@@ -16,49 +16,37 @@
limitations under the License.
-->
<resources>
- <string name="application_copyright">Copyright \u00A9 2014 The CyanogenMod Project</string>
- <string name="sort_button_text">Sorter</string>
- <string name="filter_button_text">Filter</string>
- <string name="default_screen_button_text">Standardskjermbildet</string>
- <string name="transition_effect_button_text">Bla effekt</string>
- <string name="sort_mode_title">Tittel</string>
- <string name="sort_mode_launch_count">Start teller</string>
- <string name="sort_mode_install_time">Installeringstid</string>
+ <string name="launcher_settings">LAUNCHER INNSTILLINGER</string>
+ <string name="home_screen_settings">HJEMMESKJERM INNSTILLINGER</string>
+ <string name="drawer_settings">SKUFF INNSTILLINGER</string>
+ <string name="app_settings">APP-INNSTILLINGER</string>
+ <string name="setting_state_on">PÅ</string>
+ <string name="setting_state_off">AV</string>
+ <string name="themes_button_text">Temaer</string>
<string name="scrolling_page_outlines">Skjermkontur</string>
<string name="scrolling_fade_adjacent">Fade skjermsider</string>
- <string name="wallpaper_scroll">Bla bakgrunn</string>
- <string name="preferences_title">Innstillinger</string>
- <string name="preferences_application_title">App</string>
- <string name="preferences_interface_homescreen_title">Hjemmeskjerm</string>
- <string name="preferences_interface_homescreen_search_title">Søkefeltet</string>
- <string name="preferences_interface_homescreen_search_summary">Vis vedvarende søkefeltet øverst på skjermen</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_title">Skjule ikonetiketter</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">Skjule ikonetiketter på hjemmeskjerm</string>
- <string name="preferences_interface_drawer_title">Skuff</string>
- <string name="preferences_interface_drawer_summary">Programmer og widgets skuff</string>
- <string name="preferences_interface_drawer_apps_category">Apps</string>
- <string name="preferences_interface_drawer_hidden_apps_title">Skjulte programmer</string>
- <string name="preferences_interface_drawer_hidden_apps_summary">Skjul apps fra skuffen</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">Fjern snarveier</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">Fjerne snarveier til skjulte programmer fra hjemmeskjerm</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_title">Fjern widgets</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_summary">Fjerne widgeter av skjulte programmer fra hjemmeskjerm</string>
- <string name="preferences_interface_drawer_hide_icon_labels_title">Skjul ikonetiketter</string>
- <string name="preferences_interface_drawer_hide_icon_labels_summary">Skjul ikonetiketter i skuffen</string>
- <string name="preferences_interface_dock_title">Dock</string>
- <string name="preferences_interface_general_title">Generelt</string>
- <string name="preferences_interface_general_icons_category">Ikoner</string>
- <string name="preferences_interface_general_icons_large_title">Større ikoner</string>
- <string name="preferences_interface_general_icons_large_summary">Bruk ekstra store programikoner på hjemmeskjerm og skuff</string>
- <string name="preferences_interface_general_icons_text_style_title">Skrifttype</string>
- <string name="preferences_interface_general_icons_text_style_summary">Variant og stil på skrift brukt til ikon tekst</string>
- <string name="dialog_pick_iconpack_title">Velg ikon pakke</string>
- <string name="default_iconpack_title">Standardikoner</string>
- <string name="icon_packs_title">Symbol-pakker</string>
- <string name="no_iconpacks_summary">Ingen ikon pakker installert</string>
- <string name="clear_keyguard_wallpaper">Fjern</string>
- <string name="all_apps_cling_cm">Tilpasse din skuff</string>
- <string name="all_apps_cling_summary">Trykk på sideindikatoren for å vise flere konfigurasjonsinnstillinger</string>
- <string name="menu_hidden_apps_delete">Tilbakestille</string>
+ <string name="scrolling_wallpaper">Scroll bakgrunn</string>
+ <string name="grid_size_text">Rutenettstørrelse</string>
+ <string name="grid_size_comfortable">Komfortabel</string>
+ <string name="grid_size_cozy">Koselig</string>
+ <string name="grid_size_condensed">Kondensert</string>
+ <string name="grid_size_custom">Egendefinert</string>
+ <string name="preferences_interface_homescreen_custom">Velg egendefinert størrelse</string>
+ <string name="preferences_interface_homescreen_rows_title">Antall rader</string>
+ <string name="preferences_interface_homescreen_columns_title">Antall kolonner</string>
<string name="hidden_apps_title">Skjulte programmer</string>
+ <string name="scroll_effect_text">Bla effekt</string>
+ <string name="drawer_sorting_text">Sorteringsmodus</string>
+ <string name="sort_mode_title">Tittel</string>
+ <string name="sort_mode_launch_count">Start teller</string>
+ <string name="sort_mode_install_time">Installeringstid</string>
+ <string name="home_screen_search_text">Søkefelt</string>
+ <string name="larger_icons_text">Større ikoner</string>
+ <string name="icon_labels">Ikonetiketter</string>
+ <string name="icon_labels_show">Vis</string>
+ <string name="icon_labels_hide">Skjul</string>
+ <string name="protected_app_settings">Beskyttede apps</string>
+ <string name="search_screen_left_text">Søke-panelet</string>
+ <string name="search_screen_left_unsupported_toast">Du må ha en støttet søke app og CyanogenMod for å bruke denne funksjonen.</string>
+ <string name="dialog_confirm">Bekreft</string>
</resources>
diff --git a/res/values-nl/cm_arrays.xml b/res/values-nl/cm_arrays.xml
index 9c2a4e878..55de714b7 100644
--- a/res/values-nl/cm_arrays.xml
+++ b/res/values-nl/cm_arrays.xml
@@ -16,11 +16,6 @@
limitations under the License.
-->
<resources>
- <string-array name="preferences_interface_general_icons_text_font_family_entries">
- <item>Standaard</item>
- <item>Licht</item>
- <item>Smal</item>
- </string-array>
<string-array name="transition_effect_entries">
<item>Geen</item>
<item>Inzoomen</item>
diff --git a/res/values-nl/cm_strings.xml b/res/values-nl/cm_strings.xml
index bf5021141..cdf3e7e4e 100644
--- a/res/values-nl/cm_strings.xml
+++ b/res/values-nl/cm_strings.xml
@@ -16,49 +16,37 @@
limitations under the License.
-->
<resources>
- <string name="application_copyright">Copyright \u00A9 2014 The CyanogenMod Project</string>
- <string name="sort_button_text">Sorteren</string>
- <string name="filter_button_text">Filteren</string>
- <string name="default_screen_button_text">Standaard\nscherm</string>
- <string name="transition_effect_button_text">Overgangs\neffect</string>
- <string name="sort_mode_title">Titel</string>
- <string name="sort_mode_launch_count">Aantal starts</string>
- <string name="sort_mode_install_time">Tijd van installatie</string>
+ <string name="launcher_settings">INSTELLINGEN STARTPAGINA</string>
+ <string name="home_screen_settings">INSTELLINGEN THUISSCHERM</string>
+ <string name="drawer_settings">INSTELLINGEN OVERZICHT</string>
+ <string name="app_settings">INSTELLINGEN APPS</string>
+ <string name="setting_state_on">AAN</string>
+ <string name="setting_state_off">UIT</string>
+ <string name="themes_button_text">Thema\'s</string>
<string name="scrolling_page_outlines">Paginacontouren</string>
<string name="scrolling_fade_adjacent">Zijkant pagina\'s vervagen</string>
- <string name="wallpaper_scroll">Achtergrond schuiven</string>
- <string name="preferences_title">Instellingen</string>
- <string name="preferences_application_title">App</string>
- <string name="preferences_interface_homescreen_title">Startscherm</string>
- <string name="preferences_interface_homescreen_search_title">Zoekbalk</string>
- <string name="preferences_interface_homescreen_search_summary">Zoekbalk permanent tonen bovenaan het scherm</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_title">Labels verbergen</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">Labels verbergen onder pictogrammen op het startscherm</string>
- <string name="preferences_interface_drawer_title">Overzicht</string>
- <string name="preferences_interface_drawer_summary">App- en widgetoverzicht</string>
- <string name="preferences_interface_drawer_apps_category">Apps</string>
- <string name="preferences_interface_drawer_hidden_apps_title">Verborgen apps</string>
- <string name="preferences_interface_drawer_hidden_apps_summary">Apps verbergen in het app-overzicht</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">Snelkoppelingen verbergen</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">Snelkoppelingen van verborgen apps niet weergeven op startscherm</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_title">Widgets verbergen</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_summary">Widgets van verborgen apps niet weergeven op startscherm</string>
- <string name="preferences_interface_drawer_hide_icon_labels_title">Labels verbergen</string>
- <string name="preferences_interface_drawer_hide_icon_labels_summary">Labels verbergen onder pictogrammen in het appoverzicht</string>
- <string name="preferences_interface_dock_title">Dock</string>
- <string name="preferences_interface_general_title">Algemeen</string>
- <string name="preferences_interface_general_icons_category">Pictogrammen</string>
- <string name="preferences_interface_general_icons_large_title">Grote pictogrammen</string>
- <string name="preferences_interface_general_icons_large_summary">Extra grote pictogrammen gebruiken voor apps op het startscherm en in het overzicht</string>
- <string name="preferences_interface_general_icons_text_style_title">Lettertypestijl</string>
- <string name="preferences_interface_general_icons_text_style_summary">Stijl van tekst bij pictogrammen</string>
- <string name="dialog_pick_iconpack_title">Pictogrampakket kiezen</string>
- <string name="default_iconpack_title">Standaard</string>
- <string name="icon_packs_title">Pictogram\npakket</string>
- <string name="no_iconpacks_summary">Geen pictogrampakketten geïnstalleerd</string>
- <string name="clear_keyguard_wallpaper">Verwijderen</string>
- <string name="all_apps_cling_cm">App-overzicht aanpassen</string>
- <string name="all_apps_cling_summary">Tik op de pagina-indicator voor extra instellingen</string>
- <string name="menu_hidden_apps_delete">Opnieuw instellen</string>
+ <string name="scrolling_wallpaper">Achtergrond schuiven</string>
+ <string name="grid_size_text">Rastergrootte</string>
+ <string name="grid_size_comfortable">Comfortabel</string>
+ <string name="grid_size_cozy">Knus</string>
+ <string name="grid_size_condensed">Smal</string>
+ <string name="grid_size_custom">Aangepast</string>
+ <string name="preferences_interface_homescreen_custom">Aangepaste grootte</string>
+ <string name="preferences_interface_homescreen_rows_title">Aantal rijen</string>
+ <string name="preferences_interface_homescreen_columns_title">Aantal kolommen</string>
<string name="hidden_apps_title">Verborgen apps</string>
+ <string name="scroll_effect_text">Overgangseffect</string>
+ <string name="drawer_sorting_text">Sorteren op</string>
+ <string name="sort_mode_title">Titel</string>
+ <string name="sort_mode_launch_count">Aantal starts</string>
+ <string name="sort_mode_install_time">Tijd van installatie</string>
+ <string name="home_screen_search_text">Zoekbalk</string>
+ <string name="larger_icons_text">Grote pictogrammen</string>
+ <string name="icon_labels">Pictogramlabels</string>
+ <string name="icon_labels_show">Aan</string>
+ <string name="icon_labels_hide">Uit</string>
+ <string name="protected_app_settings">Beschermde apps</string>
+ <string name="search_screen_left_text">Zoekscherm</string>
+ <string name="search_screen_left_unsupported_toast">Een ondersteunde zoek-app en CyanogenMod zijn vereist om deze functie te gebruiken.</string>
+ <string name="dialog_confirm">Bevestig</string>
</resources>
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index e2a2a0719..3cae98a9d 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -119,6 +119,6 @@
<string name="custom_workspace_cling_title_2" msgid="662588444436552198"></string>
<string name="custom_workspace_cling_description_2" msgid="8097921091798539310"></string>
<string name="widget_button_text" msgid="2880537293434387943">"Widgets"</string>
- <string name="wallpaper_button_text" msgid="8404103075899945851">"Achtergronden"</string>
+ <string name="wallpaper_button_text" msgid="8404103075899945851">"Achtergrond"</string>
<string name="settings_button_text" msgid="8119458837558863227">"Instellingen"</string>
</resources>
diff --git a/res/values-pl/cm_arrays.xml b/res/values-pl/cm_arrays.xml
index c5e7253ab..4d6e4626c 100644
--- a/res/values-pl/cm_arrays.xml
+++ b/res/values-pl/cm_arrays.xml
@@ -16,24 +16,19 @@
limitations under the License.
-->
<resources>
- <string-array name="preferences_interface_general_icons_text_font_family_entries">
- <item>Regularny</item>
- <item>Lekki</item>
- <item>Skondensowany</item>
- </string-array>
<string-array name="transition_effect_entries">
<item>Brak</item>
- <item>Przybliżenie</item>
- <item>Oddalenie</item>
- <item>Obrót w górę</item>
+ <item>Zbliżanie</item>
+ <item>Oddalanie</item>
+ <item>Obrót do góry</item>
<item>Obrót w dół</item>
- <item>Kostka do wewnątrz</item>
- <item>Kostka do zewnątrz</item>
+ <item>Kostka (w środku)</item>
+ <item>Kostka (na zewnątrz)</item>
<item>Stos</item>
<item>Akordeon</item>
<item>Obrót</item>
- <item>Cylinder do wewnątrz</item>
- <item>Cylinder do zewnątrz</item>
+ <item>Cylinder (w środku)</item>
+ <item>Cylinder (na zewnątrz)</item>
<item>Karuzela</item>
<item>Przegląd</item>
</string-array>
diff --git a/res/values-pl/cm_strings.xml b/res/values-pl/cm_strings.xml
index 6bf22dc0f..31541d7a7 100644
--- a/res/values-pl/cm_strings.xml
+++ b/res/values-pl/cm_strings.xml
@@ -16,49 +16,37 @@
limitations under the License.
-->
<resources>
- <string name="application_copyright">Copyright \u00A9 2014 The CyanogenMod Project</string>
- <string name="sort_button_text">Sortowanie</string>
- <string name="filter_button_text">Filtruj</string>
- <string name="default_screen_button_text">Ekran domyślny</string>
- <string name="transition_effect_button_text">Efekt przewijania</string>
- <string name="sort_mode_title">Tytuł</string>
- <string name="sort_mode_launch_count">Liczba uruchomień</string>
- <string name="sort_mode_install_time">Data instalacji</string>
+ <string name="launcher_settings">USTAWIENIA LAUNCHERA</string>
+ <string name="home_screen_settings">USTAWIENIA EKRANU GŁÓWNEGO</string>
+ <string name="drawer_settings">USTAWIENIA SZUFLADY APLIKACJI</string>
+ <string name="app_settings">USTAWIENIA APLIKACJI</string>
+ <string name="setting_state_on">WŁĄCZONE</string>
+ <string name="setting_state_off">WYŁĄCZONE</string>
+ <string name="themes_button_text">Motywy</string>
<string name="scrolling_page_outlines">Kontury strony</string>
<string name="scrolling_fade_adjacent">Przenikaj strony boczne</string>
- <string name="wallpaper_scroll">Przewijaj tapetę</string>
- <string name="preferences_title">Ustawienia</string>
- <string name="preferences_application_title">Aplikacja</string>
- <string name="preferences_interface_homescreen_title">Ekran głowny</string>
- <string name="preferences_interface_homescreen_search_title">Pasek wyszukiwania</string>
- <string name="preferences_interface_homescreen_search_summary">Pokazuj pasek wyszukiwania na stałe</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_title">Ukryj etykiety ikon</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">Ukrywa etykiety ikon na ekranie głównym</string>
- <string name="preferences_interface_drawer_title">Szuflada</string>
- <string name="preferences_interface_drawer_summary">Szuflada aplikacji i widżetów</string>
- <string name="preferences_interface_drawer_apps_category">Aplikacje</string>
- <string name="preferences_interface_drawer_hidden_apps_title">Ukryte aplikacje</string>
- <string name="preferences_interface_drawer_hidden_apps_summary">Ukrywanie aplikacji z szuflady</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">Usuń skróty</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">Usuwa skróty ukrytych aplikacji z ekranu głównego</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_title">Usuń widżety</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_summary">Usuwa widżety ukrytych aplikacji z ekranu głównego</string>
- <string name="preferences_interface_drawer_hide_icon_labels_title">Ukryj etykiety ikon</string>
- <string name="preferences_interface_drawer_hide_icon_labels_summary">Ukryj etykiety ikon w szufladzie</string>
- <string name="preferences_interface_dock_title">Dok</string>
- <string name="preferences_interface_general_title">Ogólne</string>
- <string name="preferences_interface_general_icons_category">Ikony</string>
- <string name="preferences_interface_general_icons_large_title">Większe ikony</string>
- <string name="preferences_interface_general_icons_large_summary">Użyj ekstra dużych ikon na ekranie głównym i szufladzie</string>
- <string name="preferences_interface_general_icons_text_style_title">Styl czcionki tekstu</string>
- <string name="preferences_interface_general_icons_text_style_summary">Wariant i styl czcionki używanej do tekstu przy ikonach</string>
- <string name="dialog_pick_iconpack_title">Wybierz paczkę ikon</string>
- <string name="default_iconpack_title">Domyślne ikony</string>
- <string name="icon_packs_title">Paczki ikon</string>
- <string name="no_iconpacks_summary">Brak zainstalowanych paczek ikon</string>
- <string name="clear_keyguard_wallpaper">Wyczyść</string>
- <string name="all_apps_cling_cm">Dostosuj szufladę</string>
- <string name="all_apps_cling_summary">Naciśnij na wskaźnik strony by zobaczyć dodatkowe opcje konfiguracji</string>
- <string name="menu_hidden_apps_delete">Przywróć domyślne</string>
+ <string name="scrolling_wallpaper">Przewijanie tapety</string>
+ <string name="grid_size_text">Rozmiar siatki</string>
+ <string name="grid_size_comfortable">Wygodny</string>
+ <string name="grid_size_cozy">Luźny</string>
+ <string name="grid_size_condensed">Zagęszczony</string>
+ <string name="grid_size_custom">Własny</string>
+ <string name="preferences_interface_homescreen_custom">Wybierz własny rozmiar</string>
+ <string name="preferences_interface_homescreen_rows_title">Liczba wierszy</string>
+ <string name="preferences_interface_homescreen_columns_title">Liczba kolumn</string>
<string name="hidden_apps_title">Ukryte aplikacje</string>
+ <string name="scroll_effect_text">Efekt przewijania</string>
+ <string name="drawer_sorting_text">Tryb sortowania</string>
+ <string name="sort_mode_title">Tytuł</string>
+ <string name="sort_mode_launch_count">Liczba uruchomień</string>
+ <string name="sort_mode_install_time">Data instalacji</string>
+ <string name="home_screen_search_text">Pasek wyszukiwania</string>
+ <string name="larger_icons_text">Większe ikony</string>
+ <string name="icon_labels">Etykiety ikon</string>
+ <string name="icon_labels_show">Pokaż</string>
+ <string name="icon_labels_hide">Ukryj</string>
+ <string name="protected_app_settings">Chronione aplikacje</string>
+ <string name="search_screen_left_text">Pasek wyszukiwania</string>
+ <string name="search_screen_left_unsupported_toast">Musisz posiadać aplikację wyszukiwania wspieraną przez CyanogenMod by używać tej funkcji.</string>
+ <string name="dialog_confirm">Potwierdź</string>
</resources>
diff --git a/res/values-port/dimens.xml b/res/values-port/dimens.xml
index 7194a2a77..7753ab318 100644
--- a/res/values-port/dimens.xml
+++ b/res/values-port/dimens.xml
@@ -15,9 +15,6 @@
-->
<resources>
-<!-- Workspace -->
- <dimen name="workspace_page_spacing">-1dp</dimen>
-
<!-- AppsCustomize -->
<integer name="apps_customize_cling_focused_x">1</integer>
<integer name="apps_customize_cling_focused_y">1</integer>
diff --git a/res/values-pt-rBR/cm_arrays.xml b/res/values-pt-rBR/cm_arrays.xml
index b03d887be..c7bc16cc4 100644
--- a/res/values-pt-rBR/cm_arrays.xml
+++ b/res/values-pt-rBR/cm_arrays.xml
@@ -16,19 +16,14 @@
limitations under the License.
-->
<resources>
- <string-array name="preferences_interface_general_icons_text_font_family_entries">
- <item>Normal</item>
- <item>Leve</item>
- <item>Condensado</item>
- </string-array>
<string-array name="transition_effect_entries">
<item>Nenhum</item>
- <item>Dar Zoom</item>
- <item>Tirar Zoom</item>
- <item>Rotacionar p/ Cima</item>
- <item>Rotacionar p/ Baixo</item>
- <item>Cubo Interno</item>
- <item>Cubo Externo</item>
+ <item>Aumentar zoom</item>
+ <item>Diminuir o zoom</item>
+ <item>Girar para cima</item>
+ <item>Girar para baixo</item>
+ <item>Cubo interno</item>
+ <item>Cubo externo</item>
<item>Pilha</item>
<item>Acordeão</item>
<item>Girar</item>
diff --git a/res/values-pt-rBR/cm_strings.xml b/res/values-pt-rBR/cm_strings.xml
index 01381a48e..af903e032 100644
--- a/res/values-pt-rBR/cm_strings.xml
+++ b/res/values-pt-rBR/cm_strings.xml
@@ -16,49 +16,37 @@
limitations under the License.
-->
<resources>
- <string name="application_copyright">Copyright \u00A9 2014 The CyanogenMod Project</string>
- <string name="sort_button_text">Ordenar</string>
- <string name="filter_button_text">Filtrar</string>
- <string name="default_screen_button_text">Tela padrão</string>
- <string name="transition_effect_button_text">Efeito de rolagem</string>
- <string name="sort_mode_title">Título</string>
- <string name="sort_mode_launch_count">Contador de inicialização</string>
- <string name="sort_mode_install_time">Hora da instalação</string>
+ <string name="launcher_settings">CONFIGURAÇÕES DO LAUNCHER</string>
+ <string name="home_screen_settings">CONFIGURAÇÕES DA TELA DE INÍCIO</string>
+ <string name="drawer_settings">CONFIGURAÇÕES DA GAVETA APLICAÇÕES</string>
+ <string name="app_settings">CONFIGURAÇÕES DE APLICATIVO</string>
+ <string name="setting_state_on">LIG</string>
+ <string name="setting_state_off">DESL</string>
+ <string name="themes_button_text">Temas</string>
<string name="scrolling_page_outlines">Contorno de página</string>
<string name="scrolling_fade_adjacent">Esmaecer páginas laterais</string>
- <string name="wallpaper_scroll">Rolar papel de parede</string>
- <string name="preferences_title">Preferências</string>
- <string name="preferences_application_title">Aplicação</string>
- <string name="preferences_interface_homescreen_title">Tela Inicial</string>
- <string name="preferences_interface_homescreen_search_title">Barra de pesquisa</string>
- <string name="preferences_interface_homescreen_search_summary">Exibir barra de pesquisa persistente no topo da tela</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_title">Ocultar as legendas dos ícones</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">Oculta as legendas dos ícones na tela inicial</string>
- <string name="preferences_interface_drawer_title">Gaveta de apps</string>
- <string name="preferences_interface_drawer_summary">Gaveta de aplicativos e widgets</string>
- <string name="preferences_interface_drawer_apps_category">Aplicativos</string>
- <string name="preferences_interface_drawer_hidden_apps_title">Aplicativos ocultos</string>
- <string name="preferences_interface_drawer_hidden_apps_summary">Ocultar aplicativos da gaveta</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">Remover atalhos</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">Remover os atalhos de aplicativos ocultos da tela inicial</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_title">Remover widgets</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_summary">Remover os widgets dos aplicativos ocultos da tela inicial</string>
- <string name="preferences_interface_drawer_hide_icon_labels_title">Ocultar as legendas dos ícones</string>
- <string name="preferences_interface_drawer_hide_icon_labels_summary">Ocultar as legendas dos ícones na gaveta</string>
- <string name="preferences_interface_dock_title">Dock</string>
- <string name="preferences_interface_general_title">Geral</string>
- <string name="preferences_interface_general_icons_category">Ícones</string>
- <string name="preferences_interface_general_icons_large_title">Ícones grandes</string>
- <string name="preferences_interface_general_icons_large_summary">Usar ícones de aplicação extra grandes na tela inicial e gaveta de aplicativos</string>
- <string name="preferences_interface_general_icons_text_style_title">Estilo da fonte</string>
- <string name="preferences_interface_general_icons_text_style_summary">Estilo da fonte para usar nos textos dos ícones</string>
- <string name="dialog_pick_iconpack_title">Escolher o pacote de ícones</string>
- <string name="default_iconpack_title">Ícones padrão</string>
- <string name="icon_packs_title">Pacote de ícones</string>
- <string name="no_iconpacks_summary">Nenhum pacote de ícones instalado</string>
- <string name="clear_keyguard_wallpaper">Limpar</string>
- <string name="all_apps_cling_cm">Personalizar sua gaveta de aplicativos</string>
- <string name="all_apps_cling_summary">Toque o indicador desta página para visualizar configurações adicionais</string>
- <string name="menu_hidden_apps_delete">Redefinir</string>
+ <string name="scrolling_wallpaper">Rolar papel de parede</string>
+ <string name="grid_size_text">Tamanho da grade</string>
+ <string name="grid_size_comfortable">Confortável</string>
+ <string name="grid_size_cozy">Aconchegante</string>
+ <string name="grid_size_condensed">Condensado</string>
+ <string name="grid_size_custom">Personalizado</string>
+ <string name="preferences_interface_homescreen_custom">Selecione tamanho personalizado</string>
+ <string name="preferences_interface_homescreen_rows_title">Número de linhas</string>
+ <string name="preferences_interface_homescreen_columns_title">Número de colunas</string>
<string name="hidden_apps_title">Aplicativos ocultos</string>
+ <string name="scroll_effect_text">Efeito de rolagem</string>
+ <string name="drawer_sorting_text">Modo de ordenação</string>
+ <string name="sort_mode_title">Título</string>
+ <string name="sort_mode_launch_count">Contador de inicialização</string>
+ <string name="sort_mode_install_time">Hora da instalação</string>
+ <string name="home_screen_search_text">Barra de pesquisa</string>
+ <string name="larger_icons_text">Ícones grandes</string>
+ <string name="icon_labels">Etiquetas de ícones</string>
+ <string name="icon_labels_show">Mostrar</string>
+ <string name="icon_labels_hide">Ocultar</string>
+ <string name="protected_app_settings">Aplicativos protegidos</string>
+ <string name="search_screen_left_text">Painel de pesquisa</string>
+ <string name="search_screen_left_unsupported_toast">Você precisa ter instalado um aplicativo de pesquisa suportado e o CyanogenMod para utilizar este recurso.</string>
+ <string name="dialog_confirm">Confirmar</string>
</resources>
diff --git a/res/values-pt-rPT/cm_arrays.xml b/res/values-pt-rPT/cm_arrays.xml
index c720a9ef3..ed3ede04b 100644
--- a/res/values-pt-rPT/cm_arrays.xml
+++ b/res/values-pt-rPT/cm_arrays.xml
@@ -16,23 +16,18 @@
limitations under the License.
-->
<resources>
- <string-array name="preferences_interface_general_icons_text_font_family_entries">
- <item>Normal</item>
- <item>Fino</item>
- <item>Condensado</item>
- </string-array>
<string-array name="transition_effect_entries">
<item>Nenhum</item>
- <item>Zoom In</item>
- <item>Zoom Out</item>
- <item>Rodar para Cima</item>
- <item>Rodar para Baixo</item>
- <item>Cubo para Dentro</item>
- <item>Cubo para Fora</item>
+ <item>Zoom para dentro</item>
+ <item>Zoom para fora</item>
+ <item>Rodar para cima</item>
+ <item>Rodar para baixo</item>
+ <item>Cubo para dentro</item>
+ <item>Cubo para fora</item>
<item>Pilha</item>
<item>Acordeão</item>
<item>Virar</item>
- <item>Cilindro para Dentro</item>
+ <item>Cilindro para dentro</item>
<item>Cilindro para Fora</item>
<item>Carrossel</item>
<item>Vista geral</item>
diff --git a/res/values-pt-rPT/cm_strings.xml b/res/values-pt-rPT/cm_strings.xml
index 127a341d6..79311bdaa 100644
--- a/res/values-pt-rPT/cm_strings.xml
+++ b/res/values-pt-rPT/cm_strings.xml
@@ -16,49 +16,37 @@
limitations under the License.
-->
<resources>
- <string name="application_copyright">Copyright \u00A9 2014 The CyanogenMod Project</string>
- <string name="sort_button_text">Ordenar</string>
- <string name="filter_button_text">Filtrar</string>
- <string name="default_screen_button_text">Ecrã Padrão</string>
- <string name="transition_effect_button_text">Efeito de transição</string>
- <string name="sort_mode_title">Título</string>
- <string name="sort_mode_launch_count">Contagem de inicializações</string>
- <string name="sort_mode_install_time">Data de instalação</string>
+ <string name="launcher_settings">DEFINIÇÕES DO LANÇADOR</string>
+ <string name="home_screen_settings">DEFINIÇÕES DO ECRÃ INICIAL</string>
+ <string name="drawer_settings">DEFINIÇÕES DA GAVETA APLICAÇÕES</string>
+ <string name="app_settings">DEFINIÇÕES DA APLICAÇÃO</string>
+ <string name="setting_state_on">LIG.</string>
+ <string name="setting_state_off">DESL.</string>
+ <string name="themes_button_text">Temas</string>
<string name="scrolling_page_outlines">Contorno das páginas</string>
<string name="scrolling_fade_adjacent">Desvanecer as páginas laterais</string>
- <string name="wallpaper_scroll">Deslizar papel de parede</string>
- <string name="preferences_title">Definições</string>
- <string name="preferences_application_title">Aplicação</string>
- <string name="preferences_interface_homescreen_title">Ecrã inicial</string>
- <string name="preferences_interface_homescreen_search_title">Barra de pesquisa</string>
- <string name="preferences_interface_homescreen_search_summary">Mostrar barra de pesquisa persistente no topo do ecrã</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_title">Ocultar as legendas dos ícones</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">Oculta as legendas dos ícones no ambiente de trabalho</string>
- <string name="preferences_interface_drawer_title">Gaveta de aplicações</string>
- <string name="preferences_interface_drawer_summary">Gaveta de aplicações e widgets</string>
- <string name="preferences_interface_drawer_apps_category">Aplicações</string>
- <string name="preferences_interface_drawer_hidden_apps_title">Aplicações ocultas</string>
- <string name="preferences_interface_drawer_hidden_apps_summary">Ocultar aplicações da gaveta</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">Remover atalhos</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">Remover os atalhos de aplicações ocultas do ambiente de trabalho</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_title">Remover widgets</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_summary">Remover os widgets das aplicações ocultas do ambiente de trabalho</string>
- <string name="preferences_interface_drawer_hide_icon_labels_title">Ocultar as legendas dos ícones</string>
- <string name="preferences_interface_drawer_hide_icon_labels_summary">Ocultar as legendas dos ícones na gaveta de aplicações</string>
- <string name="preferences_interface_dock_title">Dock</string>
- <string name="preferences_interface_general_title">Geral</string>
- <string name="preferences_interface_general_icons_category">Ícones</string>
- <string name="preferences_interface_general_icons_large_title">Ícones grandes</string>
- <string name="preferences_interface_general_icons_large_summary">Usar ícones de aplicação extra grandes no ecrã inicial e na gaveta de aplicações</string>
- <string name="preferences_interface_general_icons_text_style_title">Estilo de tipo de letra</string>
- <string name="preferences_interface_general_icons_text_style_summary">Variante e estilo do tipo de letra a usar para o texto dos ícones</string>
- <string name="dialog_pick_iconpack_title">Escolher pacote de ícones</string>
- <string name="default_iconpack_title">Ícones padrão</string>
- <string name="icon_packs_title">Pacotes de Ícones</string>
- <string name="no_iconpacks_summary">Nenhum pacote de ícones instalado</string>
- <string name="clear_keyguard_wallpaper">Limpar</string>
- <string name="all_apps_cling_cm">Personalize a sua gaveta de aplicações</string>
- <string name="all_apps_cling_summary">Toque no indicador de página para ver definições adicionais</string>
- <string name="menu_hidden_apps_delete">Restaurar</string>
+ <string name="scrolling_wallpaper">Deslizar imagem de fundo</string>
+ <string name="grid_size_text">Tamanho da grelha</string>
+ <string name="grid_size_comfortable">Confortável</string>
+ <string name="grid_size_cozy">Cómodo</string>
+ <string name="grid_size_condensed">Condensado</string>
+ <string name="grid_size_custom">Personalizado</string>
+ <string name="preferences_interface_homescreen_custom">Selecionar o tamanho personalizado</string>
+ <string name="preferences_interface_homescreen_rows_title">Número de linhas</string>
+ <string name="preferences_interface_homescreen_columns_title">Número de colunas</string>
<string name="hidden_apps_title">Aplicações ocultas</string>
+ <string name="scroll_effect_text">Efeito de transição</string>
+ <string name="drawer_sorting_text">Ordenar por</string>
+ <string name="sort_mode_title">Título</string>
+ <string name="sort_mode_launch_count">Contagem de inicializações</string>
+ <string name="sort_mode_install_time">Data de instalação</string>
+ <string name="home_screen_search_text">Barra de pesquisa</string>
+ <string name="larger_icons_text">Ícones grandes</string>
+ <string name="icon_labels">Legendas dos ícones</string>
+ <string name="icon_labels_show">Mostrar</string>
+ <string name="icon_labels_hide">Ocultar</string>
+ <string name="protected_app_settings">Aplicações protegidas</string>
+ <string name="search_screen_left_text">Painel de pesquisa</string>
+ <string name="search_screen_left_unsupported_toast">Deve ter instalada uma aplicação de pesquisa suportada e a CyanogenMod para utilizar este recurso.</string>
+ <string name="dialog_confirm">Confirmar</string>
</resources>
diff --git a/res/values-ro/cm_arrays.xml b/res/values-ro/cm_arrays.xml
new file mode 100644
index 000000000..a8fbba5d0
--- /dev/null
+++ b/res/values-ro/cm_arrays.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.net-->
+<!--
+ Copyright (C) 2014 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <string-array name="transition_effect_entries">
+ <item>Nimic</item>
+ <item>Zoom in</item>
+ <item>Zoom out</item>
+ <item>Rotire în sus</item>
+ <item>Rotire în jos</item>
+ <item>Cub interior</item>
+ <item>Cub exterior</item>
+ <item>Stivă</item>
+ <item>Acordeon</item>
+ <item>Flip</item>
+ <item>Cilindru interor</item>
+ <item>Cilindru exterior</item>
+ <item>Carusel</item>
+ <item>Privire de ansamblu</item>
+ </string-array>
+</resources>
diff --git a/res/values-ro/cm_strings.xml b/res/values-ro/cm_strings.xml
new file mode 100644
index 000000000..a38b471b2
--- /dev/null
+++ b/res/values-ro/cm_strings.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.net-->
+<!--
+ Copyright (C) 2014 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <string name="launcher_settings">SETĂRI LAUNCHER</string>
+ <string name="home_screen_settings">SETĂRI ECRAN PRINCIPAL</string>
+ <string name="drawer_settings">SETĂRI ECRAN APLICAȚII</string>
+ <string name="app_settings">SETĂRI APLICAȚIE</string>
+ <string name="setting_state_on">ACTIV</string>
+ <string name="setting_state_off">INACTIV</string>
+ <string name="themes_button_text">Teme</string>
+ <string name="scrolling_page_outlines">Contururi pagină</string>
+ <string name="scrolling_fade_adjacent">Estompează paginile secundare</string>
+ <string name="scrolling_wallpaper">Scroll-ează fundal</string>
+ <string name="grid_size_text">Dimensiune grilă</string>
+ <string name="grid_size_comfortable">Confortabil</string>
+ <string name="grid_size_cozy">Comod</string>
+ <string name="grid_size_condensed">Condensat</string>
+ <string name="grid_size_custom">Particularizat</string>
+ <string name="preferences_interface_homescreen_custom">Selectare dimensiune particularizată</string>
+ <string name="preferences_interface_homescreen_rows_title">Numărul de rânduri</string>
+ <string name="preferences_interface_homescreen_columns_title">Numărul de coloane</string>
+ <string name="hidden_apps_title">Aplicații ascunse</string>
+ <string name="scroll_effect_text">Efect scroll</string>
+ <string name="drawer_sorting_text">Mod sortare</string>
+ <string name="sort_mode_title">Titlu</string>
+ <string name="sort_mode_launch_count">Numărare lansare</string>
+ <string name="sort_mode_install_time">Timp de instalare</string>
+ <string name="home_screen_search_text">Bară de căutare</string>
+ <string name="larger_icons_text">Icon-uri mai mari</string>
+ <string name="icon_labels">Etichete icon-uri</string>
+ <string name="icon_labels_show">Arată</string>
+ <string name="icon_labels_hide">Ascunde</string>
+ <string name="protected_app_settings">Aplicații protejate</string>
+ <string name="search_screen_left_text">Panou de căutare</string>
+ <string name="search_screen_left_unsupported_toast">Trebuie să ai o aplicație de căutare suportată și CyanogenMod să folosească această caracteristică.</string>
+ <string name="dialog_confirm">Confirmă</string>
+</resources>
diff --git a/res/values-ru/cm_arrays.xml b/res/values-ru/cm_arrays.xml
index 8d6d774e1..903c4747c 100644
--- a/res/values-ru/cm_arrays.xml
+++ b/res/values-ru/cm_arrays.xml
@@ -16,11 +16,6 @@
limitations under the License.
-->
<resources>
- <string-array name="preferences_interface_general_icons_text_font_family_entries">
- <item>Обычный</item>
- <item>Облегчённый</item>
- <item>Сжатый</item>
- </string-array>
<string-array name="transition_effect_entries">
<item>Нет</item>
<item>Увеличение</item>
diff --git a/res/values-ru/cm_strings.xml b/res/values-ru/cm_strings.xml
index af3f3baa0..be4dcdc16 100644
--- a/res/values-ru/cm_strings.xml
+++ b/res/values-ru/cm_strings.xml
@@ -16,49 +16,37 @@
limitations under the License.
-->
<resources>
- <string name="application_copyright">\u00A9 Проект CyanogenMod, 2014</string>
- <string name="sort_button_text">Сортировка</string>
- <string name="filter_button_text">Фильтрация</string>
- <string name="default_screen_button_text">Экран по умолчанию</string>
- <string name="transition_effect_button_text">Эффект прокрутки</string>
- <string name="sort_mode_title">По названию</string>
- <string name="sort_mode_launch_count">По частоте использования</string>
- <string name="sort_mode_install_time">По времени установки</string>
+ <string name="launcher_settings">НАСТРОЙКИ ЛАУНЧЕРА</string>
+ <string name="home_screen_settings">ДОМАШНИЙ ЭКРАН</string>
+ <string name="drawer_settings">МЕНЮ ПРИЛОЖЕНИЙ</string>
+ <string name="app_settings">НАСТРОЙКИ ПРИЛОЖЕНИЯ</string>
+ <string name="setting_state_on">ВКЛ.</string>
+ <string name="setting_state_off">ВЫКЛ.</string>
+ <string name="themes_button_text">Темы</string>
<string name="scrolling_page_outlines">Границы страниц</string>
<string name="scrolling_fade_adjacent">Затемнять края при переходе</string>
- <string name="wallpaper_scroll">Прокрутка обоев</string>
- <string name="preferences_title">Настройки</string>
- <string name="preferences_application_title">Приложение</string>
- <string name="preferences_interface_homescreen_title">Домашний экран</string>
- <string name="preferences_interface_homescreen_search_title">Строка поиска</string>
- <string name="preferences_interface_homescreen_search_summary">Показывать постоянную строку поиска вверху экрана</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_title">Скрывать подписи значков</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">Не отображать текст у ярлыков на домашнем экране</string>
- <string name="preferences_interface_drawer_title">Меню приложений</string>
- <string name="preferences_interface_drawer_summary">Список приложений и виджетов</string>
- <string name="preferences_interface_drawer_apps_category">Приложения</string>
- <string name="preferences_interface_drawer_hidden_apps_title">Скрытые приложения</string>
- <string name="preferences_interface_drawer_hidden_apps_summary">Выбрать приложения, которые не будут отображаться в меню</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">Удалять ярлыки</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">Убирать ярлыки скрытых приложений с домашнего экрана</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_title">Удалять виджеты</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_summary">Убирать виджеты скрытых приложений с домашнего экрана</string>
- <string name="preferences_interface_drawer_hide_icon_labels_title">Скрывать подписи значков</string>
- <string name="preferences_interface_drawer_hide_icon_labels_summary">Не отображать текст у ярлыков в меню приложений</string>
- <string name="preferences_interface_dock_title">Нижняя панель</string>
- <string name="preferences_interface_general_title">Общие</string>
- <string name="preferences_interface_general_icons_category">Значки</string>
- <string name="preferences_interface_general_icons_large_title">Крупные значки</string>
- <string name="preferences_interface_general_icons_large_summary">Использовать крупные значки приложений на домашнем экране и в меню приложений</string>
- <string name="preferences_interface_general_icons_text_style_title">Тип шрифта</string>
- <string name="preferences_interface_general_icons_text_style_summary">Выбор стиля шрифта для подписей значков</string>
- <string name="dialog_pick_iconpack_title">Выберите набор значков</string>
- <string name="default_iconpack_title">Значки по умолчанию</string>
- <string name="icon_packs_title">Наборы значков</string>
- <string name="no_iconpacks_summary">Наборы значков не установлены</string>
- <string name="clear_keyguard_wallpaper">Очистить</string>
- <string name="all_apps_cling_cm">Настройте меню приложений по своему вкусу</string>
- <string name="all_apps_cling_summary">Коснитесь индикатора страницы внизу для перехода к настройкам.</string>
- <string name="menu_hidden_apps_delete">Сброс</string>
+ <string name="scrolling_wallpaper">Прокрутка обоев</string>
+ <string name="grid_size_text">Размер сетки</string>
+ <string name="grid_size_comfortable">Комфортная</string>
+ <string name="grid_size_cozy">Удобная</string>
+ <string name="grid_size_condensed">Сжатая</string>
+ <string name="grid_size_custom">Настраиваемая</string>
+ <string name="preferences_interface_homescreen_custom">Выберите размер сетки</string>
+ <string name="preferences_interface_homescreen_rows_title">Количество строк</string>
+ <string name="preferences_interface_homescreen_columns_title">Количество столбцов</string>
<string name="hidden_apps_title">Скрытые приложения</string>
+ <string name="scroll_effect_text">Эффект прокрутки</string>
+ <string name="drawer_sorting_text">Режим сортировки</string>
+ <string name="sort_mode_title">По назв.</string>
+ <string name="sort_mode_launch_count">По частоте исп.</string>
+ <string name="sort_mode_install_time">По врем. устан.</string>
+ <string name="home_screen_search_text">Строка поиска</string>
+ <string name="larger_icons_text">Крупные значки</string>
+ <string name="icon_labels">Подписи значков</string>
+ <string name="icon_labels_show">Показ.</string>
+ <string name="icon_labels_hide">Скрывать</string>
+ <string name="protected_app_settings">Заблокированные приложения</string>
+ <string name="search_screen_left_text">Поисковый экран слева</string>
+ <string name="search_screen_left_unsupported_toast">Для использования этой функции необходимо наличие поддерживаемого приложения поиска и CyanogenMod.</string>
+ <string name="dialog_confirm">Подтвердить</string>
</resources>
diff --git a/res/values-si/cm_arrays.xml b/res/values-si/cm_arrays.xml
index 3ff25c0b8..0cb9638aa 100644
--- a/res/values-si/cm_arrays.xml
+++ b/res/values-si/cm_arrays.xml
@@ -16,11 +16,6 @@
limitations under the License.
-->
<resources>
- <string-array name="preferences_interface_general_icons_text_font_family_entries">
- <item>විධිමත්</item>
- <item>සැහැල්ලු</item>
- <item>ඝනීභූත</item>
- </string-array>
<string-array name="transition_effect_entries">
<item>කිසිවක් නැත</item>
<item>ඇතුලට විශාලනය</item>
diff --git a/res/values-si/cm_strings.xml b/res/values-si/cm_strings.xml
index 9804bb914..49ad20a95 100644
--- a/res/values-si/cm_strings.xml
+++ b/res/values-si/cm_strings.xml
@@ -16,49 +16,37 @@
limitations under the License.
-->
<resources>
- <string name="application_copyright">ප්‍රකාශන අයිතිය \u00A9 2014 CyanogenMod ව්‍යාපෘතිය</string>
- <string name="sort_button_text">සුබෙදන්න</string>
- <string name="filter_button_text">පෙරහන</string>
- <string name="default_screen_button_text">පෙරනිමි තිරය</string>
- <string name="transition_effect_button_text">අනුචලන ආටෝපය</string>
- <string name="sort_mode_title">පටබැඳිනාමය</string>
- <string name="sort_mode_launch_count">දියත් කල වාර ගණන</string>
- <string name="sort_mode_install_time">ස්ථාපිත වේලාව</string>
+ <string name="launcher_settings">දියත් කරකයේ සැකසීම්</string>
+ <string name="home_screen_settings">මුල් තිරයේ සැකසීම්</string>
+ <string name="drawer_settings">ලාච්චුවේ සැකසීම්</string>
+ <string name="app_settings">යෙදුම් සැකසීම්</string>
+ <string name="setting_state_on">සක්‍රීයයි</string>
+ <string name="setting_state_off">අක්‍රීයයි</string>
+ <string name="themes_button_text">තේමා</string>
<string name="scrolling_page_outlines">පිටුවේ පිට මායිම්</string>
<string name="scrolling_fade_adjacent">පැති පිටු අවපැහැ කරන්න</string>
- <string name="wallpaper_scroll">වෝල්පේපරය අනුචලනය කරන්න</string>
- <string name="preferences_title">සැකසීම්</string>
- <string name="preferences_application_title">යෙදුම</string>
- <string name="preferences_interface_homescreen_title">මුල් තිරය</string>
- <string name="preferences_interface_homescreen_search_title">සෙවුම් තීරුව</string>
- <string name="preferences_interface_homescreen_search_summary">තිරය මුදුනෙහි අප්‍රතිහත සෙවුම් තීරුව පෙන්වන්න</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_title">අයිකන ලේබල සඟවන්න</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">මුල් තිරයේ අයිකන ලේබල සඟවන්න</string>
- <string name="preferences_interface_drawer_title">ලාච්චුව</string>
- <string name="preferences_interface_drawer_summary">යෙදුම් සහ විජට ලාච්චුව</string>
- <string name="preferences_interface_drawer_apps_category">යෙදුම්</string>
- <string name="preferences_interface_drawer_hidden_apps_title">සැඟවුණු යෙදුම්</string>
- <string name="preferences_interface_drawer_hidden_apps_summary">යෙදුම් ලාච්චුවේ නොපෙන්වන්න</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">කෙටිමං ඉවත් කරන්න</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">සැඟවුණු යෙදුම්හි කෙටිමං මුල් තිරයෙන් ඉවත් කරන්න</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_title">විජට ඉවත් කරන්න</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_summary">සැඟවුණු යෙදුම්හි විජට මුල් තිරයෙන් ඉවත් කරන්න</string>
- <string name="preferences_interface_drawer_hide_icon_labels_title">අයිකන ලේබල සඟවන්න</string>
- <string name="preferences_interface_drawer_hide_icon_labels_summary">ලාච්චුව තුල අයිකන ලේබල සඟවන්න</string>
- <string name="preferences_interface_dock_title">ඈඳීම</string>
- <string name="preferences_interface_general_title">ප්‍රධාන</string>
- <string name="preferences_interface_general_icons_category">අයිකන</string>
- <string name="preferences_interface_general_icons_large_title">විශාල අයිකන</string>
- <string name="preferences_interface_general_icons_large_summary">මුල් තිරයේ හා ලාච්චුවේ අති විශාල යෙදුම් අයිකන භාවිතා කරන්න</string>
- <string name="preferences_interface_general_icons_text_style_title">පෙළ ෆොන්ට විලාසය</string>
- <string name="preferences_interface_general_icons_text_style_summary">අයිකන පෙළ සඳහා භාවිතයට ෆොන්ටයේ ප්‍රභේදය සහ විලාසය</string>
- <string name="dialog_pick_iconpack_title">අයිකන පොදිය තෝරන්න</string>
- <string name="default_iconpack_title">පෙරනිමි අයිකන</string>
- <string name="icon_packs_title">අයිකන පොදි</string>
- <string name="no_iconpacks_summary">අයිකන පොදි කිසිවක් පිහිටුවා නැත</string>
- <string name="clear_keyguard_wallpaper">හිස් කරන්න</string>
- <string name="all_apps_cling_cm">ඔබගේ ලාච්චුව රිසිකරණය කරන්න</string>
- <string name="all_apps_cling_summary">අතිරේක වින්‍යාසන සැකසීම් බැලීමට පිටු දර්ශකය මත තට්ටු කරන්න</string>
- <string name="menu_hidden_apps_delete">ප්‍රත්‍යාරම්භනය</string>
+ <string name="scrolling_wallpaper">වෝල්පේපරය අනුචලනය කරන්න</string>
+ <string name="grid_size_text">කොටු සැලැස්මේ ප්‍රමාණය</string>
+ <string name="grid_size_comfortable">සැපපහසු</string>
+ <string name="grid_size_cozy">ප්‍රියජනක</string>
+ <string name="grid_size_condensed">ඝනීභූත</string>
+ <string name="grid_size_custom">රිසිවූ</string>
+ <string name="preferences_interface_homescreen_custom">රිසිකළ ප්‍රමාණය තෝරන්න</string>
+ <string name="preferences_interface_homescreen_rows_title">පේළි ගණන</string>
+ <string name="preferences_interface_homescreen_columns_title">තීරු ගණන</string>
<string name="hidden_apps_title">සැඟවුණු යෙදුම්</string>
+ <string name="scroll_effect_text">අනුචලන ආටෝපය</string>
+ <string name="drawer_sorting_text">සුබෙදීමේ ප්‍රකාරය</string>
+ <string name="sort_mode_title">පටබැඳිනාමය</string>
+ <string name="sort_mode_launch_count">දියත් කල වාර ගණන</string>
+ <string name="sort_mode_install_time">ස්ථාපිත වේලාව</string>
+ <string name="home_screen_search_text">සෙවුම් තීරුව</string>
+ <string name="larger_icons_text">විශාල අයිකන</string>
+ <string name="icon_labels">අයිකන ලේබල</string>
+ <string name="icon_labels_show">පෙන්වන්න</string>
+ <string name="icon_labels_hide">සඟවන්න</string>
+ <string name="protected_app_settings">ආරක්ෂිත යෙදුම්</string>
+ <string name="search_screen_left_text">සෙවීම් පුවරුව</string>
+ <string name="search_screen_left_unsupported_toast">මෙම විශේෂාංගය භාවිතාකිරීම සඳහා, ඔබ සතුව, සහාය දක්වන සෙවීම් යෙදුමක් සහ CyanogenMod තිබිය යුතුමය.</string>
+ <string name="dialog_confirm">තහවුරු කරන්න</string>
</resources>
diff --git a/res/values-sk/cm_arrays.xml b/res/values-sk/cm_arrays.xml
index 10b82522c..baa3dd8a5 100644
--- a/res/values-sk/cm_arrays.xml
+++ b/res/values-sk/cm_arrays.xml
@@ -16,15 +16,10 @@
limitations under the License.
-->
<resources>
- <string-array name="preferences_interface_general_icons_text_font_family_entries">
- <item>Pravidelný</item>
- <item>Svetlý</item>
- <item>Zhustený</item>
- </string-array>
<string-array name="transition_effect_entries">
<item>Žiadny</item>
- <item>Priblíženie</item>
- <item>Oddialenie</item>
+ <item>Priblížiť</item>
+ <item>Oddialiť</item>
<item>Otočenie hore</item>
<item>Otočenie dolu</item>
<item>Kocka zvnútra</item>
diff --git a/res/values-sk/cm_strings.xml b/res/values-sk/cm_strings.xml
index 6a78d0a7d..cbfff3a91 100644
--- a/res/values-sk/cm_strings.xml
+++ b/res/values-sk/cm_strings.xml
@@ -16,49 +16,37 @@
limitations under the License.
-->
<resources>
- <string name="application_copyright">Autorské práva \u00A9 2014 Projekt CyanogenMod</string>
- <string name="sort_button_text">Zoradiť</string>
- <string name="filter_button_text">Filtrovať</string>
- <string name="default_screen_button_text">Predvolená obrazovka</string>
- <string name="transition_effect_button_text">Efekt posunu</string>
- <string name="sort_mode_title">Názov</string>
- <string name="sort_mode_launch_count">Počet spustení</string>
- <string name="sort_mode_install_time">Čas inštalácie</string>
+ <string name="launcher_settings">NASTAVENIA SPÚŠŤAČA</string>
+ <string name="home_screen_settings">NASTAVENIA DOMOVSKEJ OBRAZOVKY</string>
+ <string name="drawer_settings">NASTAVENIA PONUKY</string>
+ <string name="app_settings">NASTAVENIA APLIKÁCIÍ</string>
+ <string name="setting_state_on">Zapnuté</string>
+ <string name="setting_state_off">VYPNUTÉ</string>
+ <string name="themes_button_text">Témy</string>
<string name="scrolling_page_outlines">Obrysy stránky</string>
<string name="scrolling_fade_adjacent">Stmavnuté bočné strany</string>
- <string name="wallpaper_scroll">Posun tapety</string>
- <string name="preferences_title">Nastavenia</string>
- <string name="preferences_application_title">Aplikácia</string>
- <string name="preferences_interface_homescreen_title">Domovská obrazovka</string>
- <string name="preferences_interface_homescreen_search_title">Vyhľadávací panel</string>
- <string name="preferences_interface_homescreen_search_summary">Zobraziť pretrvávajúci vyhľadávací panel v hornej časti obrazovky</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_title">Skryť menovky ikon</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">Skryť menovky ikon z domovskej obrazovky</string>
- <string name="preferences_interface_drawer_title">Ponuka aplikácií</string>
- <string name="preferences_interface_drawer_summary">Aplikácie a miniaplikácie ponuky</string>
- <string name="preferences_interface_drawer_apps_category">Aplikácie</string>
- <string name="preferences_interface_drawer_hidden_apps_title">Skryté aplikácie</string>
- <string name="preferences_interface_drawer_hidden_apps_summary">Skryť aplikácie zo zoznamu aplikácií</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">Vymazať odkazy</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">Vymazať odkazy skrytých aplikácií z domovskej obrazovky</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_title">Vymazať miniaplikácie</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_summary">Vymazať miniaplikácie skrytých aplikácií z domovskej obrazovky</string>
- <string name="preferences_interface_drawer_hide_icon_labels_title">Skryť menovky ikon</string>
- <string name="preferences_interface_drawer_hide_icon_labels_summary">Skryť menovky ikon v ponuke aplikácií</string>
- <string name="preferences_interface_dock_title">Dok</string>
- <string name="preferences_interface_general_title">Všeobecné</string>
- <string name="preferences_interface_general_icons_category">Ikony</string>
- <string name="preferences_interface_general_icons_large_title">Väčšie ikony</string>
- <string name="preferences_interface_general_icons_large_summary">Použiť extra veľké ikony aplikácií na domovskej obrazovke a v ponuke aplikácií</string>
- <string name="preferences_interface_general_icons_text_style_title">Štýl písma textu</string>
- <string name="preferences_interface_general_icons_text_style_summary">Variant a štýl písma na použitie pre text ikony</string>
- <string name="dialog_pick_iconpack_title">Vyberte balík ikon</string>
- <string name="default_iconpack_title">Predvolené ikony</string>
- <string name="icon_packs_title">Balíky ikon</string>
- <string name="no_iconpacks_summary">Žiadne balíky ikon nie sú nainštalované</string>
- <string name="clear_keyguard_wallpaper">Vymazať</string>
- <string name="all_apps_cling_cm">Prispôsobte si vašu ponuku</string>
- <string name="all_apps_cling_summary">Kliknite na ukazovateľ stránky pre zobrazenie ďalších nastavení</string>
- <string name="menu_hidden_apps_delete">Obnoviť</string>
+ <string name="scrolling_wallpaper">Posun tapety</string>
+ <string name="grid_size_text">Veľkosť mriežky</string>
+ <string name="grid_size_comfortable">Pohodlná</string>
+ <string name="grid_size_cozy">Útulná</string>
+ <string name="grid_size_condensed">Zhustená</string>
+ <string name="grid_size_custom">Vlastná</string>
+ <string name="preferences_interface_homescreen_custom">Vyberte vlastnú veľkosť</string>
+ <string name="preferences_interface_homescreen_rows_title">Počet riadkov</string>
+ <string name="preferences_interface_homescreen_columns_title">Počet stĺpcov</string>
<string name="hidden_apps_title">Skryté aplikácie</string>
+ <string name="scroll_effect_text">Efekt posunu</string>
+ <string name="drawer_sorting_text">Režim triedenia</string>
+ <string name="sort_mode_title">Názov</string>
+ <string name="sort_mode_launch_count">Počet spustení</string>
+ <string name="sort_mode_install_time">Čas inštalácie</string>
+ <string name="home_screen_search_text">Vyhľadávací panel</string>
+ <string name="larger_icons_text">Väčšie ikony</string>
+ <string name="icon_labels">Menovky ikon</string>
+ <string name="icon_labels_show">Zobraziť</string>
+ <string name="icon_labels_hide">Skryť</string>
+ <string name="protected_app_settings">Chránené aplikácie</string>
+ <string name="search_screen_left_text">Panel vyhľadávania</string>
+ <string name="search_screen_left_unsupported_toast">Musíte mať podporovaný vyhľadávač a CyanogenMod pre použitie tejto funkcie.</string>
+ <string name="dialog_confirm">Potvrdiť</string>
</resources>
diff --git a/res/values-sr/cm_arrays.xml b/res/values-sr/cm_arrays.xml
index 54f520e01..6a4f6cc49 100644
--- a/res/values-sr/cm_arrays.xml
+++ b/res/values-sr/cm_arrays.xml
@@ -16,22 +16,17 @@
limitations under the License.
-->
<resources>
- <string-array name="preferences_interface_general_icons_text_font_family_entries">
- <item>Обично</item>
- <item>Светло</item>
- <item>Кондензовано</item>
- </string-array>
<string-array name="transition_effect_entries">
- <item>Без ефекта</item>
- <item>Увећај</item>
- <item>Умањи</item>
- <item>Ротирај нагоре</item>
- <item>Ротирај надоле</item>
+ <item>Ниједан</item>
+ <item>Увећавање</item>
+ <item>Умањивање</item>
+ <item>Ротирање нагоре</item>
+ <item>Ротирање надоле</item>
<item>Коцка унутра</item>
<item>Коцка споља</item>
<item>Листање карата</item>
- <item>Хармонијски</item>
- <item>Флип</item>
+ <item>Хармоника</item>
+ <item>Окрет</item>
<item>Цилиндар унутра</item>
<item>Цилиндар споља</item>
<item>Рингишпил</item>
diff --git a/res/values-sr/cm_strings.xml b/res/values-sr/cm_strings.xml
index 4c4eaf47b..6d22910fd 100644
--- a/res/values-sr/cm_strings.xml
+++ b/res/values-sr/cm_strings.xml
@@ -16,49 +16,37 @@
limitations under the License.
-->
<resources>
- <string name="application_copyright">Copyright \u00A9 2014 The CyanogenMod Project</string>
- <string name="sort_button_text">Приказ</string>
- <string name="filter_button_text">Филтер</string>
- <string name="default_screen_button_text">Подразумевани екран</string>
- <string name="transition_effect_button_text">Ефекат скроловања</string>
+ <string name="launcher_settings">ПОДЕШАВАЊА ПОКРЕТАЧА</string>
+ <string name="home_screen_settings">ПОДЕШАВАЊА ПОЧЕТНОГ ЕКРАНА</string>
+ <string name="drawer_settings">ПОДЕШАВАЊА ФИОКЕ</string>
+ <string name="app_settings">ПОДЕШАВАЊА АПЛИКАЦИЈА</string>
+ <string name="setting_state_on">ДА</string>
+ <string name="setting_state_off">НЕ</string>
+ <string name="themes_button_text">Теме</string>
+ <string name="scrolling_page_outlines">Контура странице</string>
+ <string name="scrolling_fade_adjacent">Замагљени крајеви страница</string>
+ <string name="scrolling_wallpaper">Скроловање позадине</string>
+ <string name="grid_size_text">Величина мреже</string>
+ <string name="grid_size_comfortable">Комфорно</string>
+ <string name="grid_size_cozy">Удобно</string>
+ <string name="grid_size_condensed">Кондензовано</string>
+ <string name="grid_size_custom">Прилагођено</string>
+ <string name="preferences_interface_homescreen_custom">Изабери прилагођену величину</string>
+ <string name="preferences_interface_homescreen_rows_title">Број редова</string>
+ <string name="preferences_interface_homescreen_columns_title">Број колона</string>
+ <string name="hidden_apps_title">Сакривене апликације</string>
+ <string name="scroll_effect_text">Ефекат</string>
+ <string name="drawer_sorting_text">Сортирање</string>
<string name="sort_mode_title">Наслов</string>
<string name="sort_mode_launch_count">Број покретања</string>
<string name="sort_mode_install_time">Време инсталирања</string>
- <string name="scrolling_page_outlines">Контура странице</string>
- <string name="scrolling_fade_adjacent">Замагљени крајеви страница</string>
- <string name="wallpaper_scroll">Скроловање позадине</string>
- <string name="preferences_title">Подешавања</string>
- <string name="preferences_application_title">Апликације</string>
- <string name="preferences_interface_homescreen_title">Почетни екран</string>
- <string name="preferences_interface_homescreen_search_title">Табла за претрагу</string>
- <string name="preferences_interface_homescreen_search_summary">Прикажи упорну таблу за претрагу на врху екрана</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_title">Сакриј етикете икона</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">Сакријте етикете икона на почетном екрану</string>
- <string name="preferences_interface_drawer_title">Фиока</string>
- <string name="preferences_interface_drawer_summary">Фиока за апликације и виџете</string>
- <string name="preferences_interface_drawer_apps_category">Апликације</string>
- <string name="preferences_interface_drawer_hidden_apps_title">Скривене апликације</string>
- <string name="preferences_interface_drawer_hidden_apps_summary">Сакријте апликације из фиоке</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">Уклони пречице</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">Уклоните пречице скривених апликација са почетног екрана</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_title">Уклони виџете</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_summary">Уклоните виџете скривених апликација са почетног екрана</string>
- <string name="preferences_interface_drawer_hide_icon_labels_title">Сакриј етикете икона</string>
- <string name="preferences_interface_drawer_hide_icon_labels_summary">Сакријте етикете икона у фиоци</string>
- <string name="preferences_interface_dock_title">Док</string>
- <string name="preferences_interface_general_title">Oпште</string>
- <string name="preferences_interface_general_icons_category">Иконе</string>
- <string name="preferences_interface_general_icons_large_title">Веће иконе</string>
- <string name="preferences_interface_general_icons_large_summary">Користите екстра велике апликационе иконе на почетном екрану и фиоци</string>
- <string name="preferences_interface_general_icons_text_style_title">Стил фонта текста</string>
- <string name="preferences_interface_general_icons_text_style_summary">Варијанту и стил фонта користити за текст на иконама</string>
- <string name="dialog_pick_iconpack_title">Одаберите пакет икона</string>
- <string name="default_iconpack_title">Подразумеване иконе</string>
- <string name="icon_packs_title">Пакети икона</string>
- <string name="no_iconpacks_summary">Нема инсталираних пакета са иконама</string>
- <string name="clear_keyguard_wallpaper">Чисто</string>
- <string name="all_apps_cling_cm">Прилагодите фиоку</string>
- <string name="all_apps_cling_summary">Додирните индикатор странице да би сте видели додатна подешавања</string>
- <string name="menu_hidden_apps_delete">Ресетовање</string>
- <string name="hidden_apps_title">Скривене апликације</string>
+ <string name="home_screen_search_text">Трака за претрагу</string>
+ <string name="larger_icons_text">Веће иконе</string>
+ <string name="icon_labels">Ознаке икона</string>
+ <string name="icon_labels_show">Прикажи</string>
+ <string name="icon_labels_hide">Сакриј</string>
+ <string name="protected_app_settings">Заштићене апликације</string>
+ <string name="search_screen_left_text">Панел за претрагу</string>
+ <string name="search_screen_left_unsupported_toast">Мораш да имаш подржану апликацију за претрагу и CyanogenMod да би користио ову функцију.</string>
+ <string name="dialog_confirm">Потврди</string>
</resources>
diff --git a/res/values-sv/cm_arrays.xml b/res/values-sv/cm_arrays.xml
index 82f1a1f1e..96f037287 100644
--- a/res/values-sv/cm_arrays.xml
+++ b/res/values-sv/cm_arrays.xml
@@ -16,24 +16,19 @@
limitations under the License.
-->
<resources>
- <string-array name="preferences_interface_general_icons_text_font_family_entries">
- <item>Vanlig</item>
- <item>Ljus</item>
- <item>Kondenserad</item>
- </string-array>
<string-array name="transition_effect_entries">
<item>Ingen</item>
- <item>Zooma In</item>
+ <item>Zooma in</item>
<item>Zooma ut</item>
- <item>Rotera upp</item>
- <item>Rotera ner</item>
- <item>Kub in</item>
- <item>Kub ut</item>
+ <item>Rotera uppåt</item>
+ <item>Rotera nedåt</item>
+ <item>Kub inåt</item>
+ <item>Kub utåt</item>
<item>Stack</item>
<item>Dragspel</item>
<item>Vänd</item>
- <item>Cylinder in</item>
- <item>Cylinder ut</item>
+ <item>Cylinder inåt</item>
+ <item>Cylinder utåt</item>
<item>Karusell</item>
<item>Översikt</item>
</string-array>
diff --git a/res/values-sv/cm_strings.xml b/res/values-sv/cm_strings.xml
index 530ebab3a..417a2d842 100644
--- a/res/values-sv/cm_strings.xml
+++ b/res/values-sv/cm_strings.xml
@@ -16,49 +16,24 @@
limitations under the License.
-->
<resources>
- <string name="application_copyright">Copyright \u00A9 2014 The CyanogenMod Project</string>
- <string name="sort_button_text">Sortera</string>
- <string name="filter_button_text">Filtrera</string>
- <string name="default_screen_button_text">Standardskärm</string>
- <string name="transition_effect_button_text">Rullningseffekt</string>
- <string name="sort_mode_title">Titel</string>
- <string name="sort_mode_launch_count">Startantal</string>
- <string name="sort_mode_install_time">Installationstillfälle</string>
+ <string name="launcher_settings">LAUNCHERINSTÄLLNINGAR</string>
+ <string name="home_screen_settings">HEMSKÄRMSINSTÄLLNINGAR</string>
+ <string name="drawer_settings">APPMENYINSTÄLLNINGAR</string>
+ <string name="setting_state_on">PÅ</string>
+ <string name="setting_state_off">AV</string>
+ <string name="themes_button_text">Teman</string>
<string name="scrolling_page_outlines">Skärmkonturer</string>
<string name="scrolling_fade_adjacent">Tona skärmsidor</string>
- <string name="wallpaper_scroll">Rulla bakgrundsbild</string>
- <string name="preferences_title">Inställningar</string>
- <string name="preferences_application_title">App</string>
- <string name="preferences_interface_homescreen_title">Hemskärm</string>
- <string name="preferences_interface_homescreen_search_title">Sökfält</string>
- <string name="preferences_interface_homescreen_search_summary">Visa beständigt sökfält längst upp på skärmen</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_title">Dölj ikonetiketter</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">Dölj ikonetiketter på hemskärmen</string>
- <string name="preferences_interface_drawer_title">Appmeny</string>
- <string name="preferences_interface_drawer_summary">App- och widgetmeny</string>
- <string name="preferences_interface_drawer_apps_category">Appar</string>
- <string name="preferences_interface_drawer_hidden_apps_title">Gömda appar</string>
- <string name="preferences_interface_drawer_hidden_apps_summary">Göm appar från menyn</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">Ta bort genvägar</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">Ta bort genvägarna till gömda appar från hemskärmen</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_title">Ta bort widgetar</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_summary">Ta bort widgetarna från gömda appar från hemskärmen</string>
- <string name="preferences_interface_drawer_hide_icon_labels_title">Göm ikonetiketter</string>
- <string name="preferences_interface_drawer_hide_icon_labels_summary">Göm ikonetiketter i appmenyn</string>
- <string name="preferences_interface_dock_title">Docka</string>
- <string name="preferences_interface_general_title">Allmänt</string>
- <string name="preferences_interface_general_icons_category">Ikoner</string>
- <string name="preferences_interface_general_icons_large_title">Större ikoner</string>
- <string name="preferences_interface_general_icons_large_summary">Använda extra stora appikoner på hemskärmen och appmenyn</string>
- <string name="preferences_interface_general_icons_text_style_title">Typsnitt</string>
- <string name="preferences_interface_general_icons_text_style_summary">Variant och stil på typsnitt som används för ikontext</string>
- <string name="dialog_pick_iconpack_title">Välj ikonpaket</string>
- <string name="default_iconpack_title">Standardikoner</string>
- <string name="icon_packs_title">Ikonpaket</string>
- <string name="no_iconpacks_summary">Inga ikonpaket installerade</string>
- <string name="clear_keyguard_wallpaper">Ta bort</string>
- <string name="all_apps_cling_cm">Anpassa din appmeny</string>
- <string name="all_apps_cling_summary">Tryck på sidindikatorn för att se ytterligare inställningar</string>
- <string name="menu_hidden_apps_delete">Återställ</string>
+ <string name="scrolling_wallpaper">Rulla bakgrundsbild</string>
<string name="hidden_apps_title">Gömda appar</string>
+ <string name="scroll_effect_text">Rullningseffekt</string>
+ <string name="drawer_sorting_text">Sorteringsläge</string>
+ <string name="sort_mode_title">Titel</string>
+ <string name="sort_mode_launch_count">Startantal</string>
+ <string name="sort_mode_install_time">Installationstillfälle</string>
+ <string name="home_screen_search_text">Sökfält</string>
+ <string name="larger_icons_text">Större ikoner</string>
+ <string name="protected_app_settings">Skyddade appar</string>
+ <string name="search_screen_left_text">Sökpanel</string>
+ <string name="search_screen_left_unsupported_toast">Du måste ha en stödd sökapp och CyanogenMod för att använda denna funktion.</string>
</resources>
diff --git a/res/values-sw320dp/dimens.xml b/res/values-sw320dp/dimens.xml
index bcc465e94..93fb82130 100644
--- a/res/values-sw320dp/dimens.xml
+++ b/res/values-sw320dp/dimens.xml
@@ -16,6 +16,8 @@
<resources>
<!-- Workspace -->
- <dimen name="overview_panel_bottom_padding">35dp</dimen>
- <dimen name="overview_panel_button_spacing">15dp</dimen>
+ <dimen name="overview_panel_bottom_padding">50dp</dimen>
+ <dimen name="overview_panel_button_spacing">17dp</dimen>
+ <dimen name="overview_panel_side_padding">28dp</dimen>
+ <dimen name="overview_panel_list_padding">16dp</dimen>
</resources>
diff --git a/res/values-sw340dp-port/config.xml b/res/values-sw340dp-port/config.xml
index d31ee5969..5f71077c7 100644
--- a/res/values-sw340dp-port/config.xml
+++ b/res/values-sw340dp-port/config.xml
@@ -15,7 +15,4 @@
-->
<resources>
-<!-- Workspace -->
- <!-- Whether or not to fade the side pages -->
- <bool name="config_workspaceFadeAdjacentScreens">false</bool>
</resources>
diff --git a/res/values-sw340dp/dimens.xml b/res/values-sw340dp/dimens.xml
index 69d6e58a3..56b9a3b04 100644
--- a/res/values-sw340dp/dimens.xml
+++ b/res/values-sw340dp/dimens.xml
@@ -17,4 +17,6 @@
<resources>
<!-- Drag padding to add to the bottom of drop targets -->
<dimen name="drop_target_drag_padding">20dp</dimen>
+
+ <dimen name="overview_panel_button_spacing">22dp</dimen>
</resources>
diff --git a/res/values-sw600dp-land/dimens.xml b/res/values-sw600dp-land/dimens.xml
index 7f5594de3..f9ca01bee 100644
--- a/res/values-sw600dp-land/dimens.xml
+++ b/res/values-sw600dp-land/dimens.xml
@@ -15,12 +15,6 @@
-->
<resources>
-<!-- AppsCustomize -->
- <dimen name="apps_customize_pageLayoutWidthGap">36dp</dimen>
- <dimen name="apps_customize_pageLayoutHeightGap">8dp</dimen>
- <dimen name="apps_customize_pageLayoutPaddingTop">20dp</dimen>
- <dimen name="apps_customize_pageLayoutPaddingBottom">14dp</dimen>
-
<!-- QSB -->
<dimen name="toolbar_button_vertical_padding">12dip</dimen>
<dimen name="toolbar_button_horizontal_padding">20dip</dimen>
diff --git a/res/values-sw600dp/dimens.xml b/res/values-sw600dp/dimens.xml
index 8d6c7f4e3..3360d302c 100644
--- a/res/values-sw600dp/dimens.xml
+++ b/res/values-sw600dp/dimens.xml
@@ -23,4 +23,11 @@
<dimen name="app_widget_preview_label_margin_top">8dp</dimen>
<dimen name="app_widget_preview_label_margin_left">@dimen/app_widget_preview_padding_left</dimen>
<dimen name="app_widget_preview_label_margin_right">@dimen/app_widget_preview_padding_right</dimen>
+
+ <dimen name="sliding_panel_padding">180dp</dimen>
+ <dimen name="overview_panel_button_spacing">32dp</dimen>
+
+ <!-- Dynamic Grid settings -->
+ <dimen name="dynamic_grid_size_image_width">300dp</dimen>
+ <dimen name="dynamic_grid_size_image_height">300dp</dimen>
</resources>
diff --git a/res/values-sw600dp/styles.xml b/res/values-sw600dp/styles.xml
index 375430417..bcbbafdbb 100644
--- a/res/values-sw600dp/styles.xml
+++ b/res/values-sw600dp/styles.xml
@@ -18,33 +18,4 @@
-->
<resources>
- <style name="ClingButton">
- <item name="android:layout_width">wrap_content</item>
- <item name="android:layout_height">wrap_content</item>
- <item name="android:paddingTop">10dp</item>
- <item name="android:paddingBottom">15dp</item>
- <item name="android:paddingStart">35dp</item>
- <item name="android:paddingEnd">35dp</item>
- <item name="android:text">@string/cling_dismiss</item>
- <item name="android:textStyle">bold</item>
- <item name="android:background">@drawable/cling_button_bg</item>
- </style>
- <style name="ClingTitleText">
- <item name="android:layout_width">wrap_content</item>
- <item name="android:layout_height">wrap_content</item>
- <item name="android:layout_marginBottom">5dp</item>
- <item name="android:textSize">30sp</item>
- <item name="android:textColor">#33B5E5</item>
- <item name="android:shadowColor">#000000</item>
- <item name="android:shadowDy">2</item>
- <item name="android:shadowRadius">2.0</item>
- </style>
- <style name="ClingText">
- <item name="android:textSize">22sp</item>
- <item name="android:textColor">#FFFFFF</item>
- <item name="android:shadowColor">#000000</item>
- <item name="android:shadowDy">2</item>
- <item name="android:shadowRadius">2.0</item>
- <item name="android:lineSpacingMultiplier">1.1</item>
- </style>
</resources>
diff --git a/res/values-sw720dp-land/dimens.xml b/res/values-sw720dp-land/dimens.xml
index eb8f83c43..433a5d40d 100644
--- a/res/values-sw720dp-land/dimens.xml
+++ b/res/values-sw720dp-land/dimens.xml
@@ -21,9 +21,6 @@
<integer name="apps_customize_cling_focused_x">4</integer>
<integer name="apps_customize_cling_focused_y">2</integer>
-<!-- Workspace -->
- <dimen name="workspace_page_spacing">50dp</dimen>
-
<!-- the area at the edge of the screen that makes the workspace go left
or right while you're dragging. -->
<dimen name="scroll_zone">100dip</dimen>
diff --git a/res/values-sw720dp-port/dimens.xml b/res/values-sw720dp-port/dimens.xml
index 62bdaaa97..9fe312bfe 100644
--- a/res/values-sw720dp-port/dimens.xml
+++ b/res/values-sw720dp-port/dimens.xml
@@ -19,7 +19,6 @@
<!-- the area at the edge of the screen that makes the workspace go left
or right while you're dragging. -->
<dimen name="scroll_zone">40dp</dimen>
- <dimen name="workspace_page_spacing">24dp</dimen>
<integer name="apps_customize_cling_focused_x">2</integer>
<integer name="apps_customize_cling_focused_y">2</integer>
diff --git a/res/values-sw720dp/dimens.xml b/res/values-sw720dp/dimens.xml
index 01227e147..6a57e4374 100644
--- a/res/values-sw720dp/dimens.xml
+++ b/res/values-sw720dp/dimens.xml
@@ -21,12 +21,10 @@
<dimen name="toolbar_button_vertical_padding">8dip</dimen>
<dimen name="toolbar_button_horizontal_padding">8dip</dimen>
- <!-- dimensions for the wallpaper picker wallpaper thumbnail width -->
- <dimen name="wallpaper_chooser_grid_width">196dp</dimen>
- <dimen name="wallpaper_chooser_grid_height">140dp</dimen>
-
<!-- When dragging items on the workspace, the number of dps by which the position of
the drag view should be offset from the position of the original view. -->
<dimen name="dragViewOffsetX">0dp</dimen>
<dimen name="dragViewOffsetY">0dp</dimen>
+
+ <dimen name="overview_panel_button_spacing">35dp</dimen>
</resources>
diff --git a/res/values-sw720dp/styles.xml b/res/values-sw720dp/styles.xml
index 9738a124b..71f030400 100644
--- a/res/values-sw720dp/styles.xml
+++ b/res/values-sw720dp/styles.xml
@@ -18,57 +18,14 @@
-->
<resources>
-<!-- Clings -->
- <style name="ClingButton">
- <item name="android:layout_width">wrap_content</item>
- <item name="android:layout_height">wrap_content</item>
- <item name="android:paddingTop">10dp</item>
- <item name="android:paddingBottom">15dp</item>
- <item name="android:paddingStart">35dp</item>
- <item name="android:paddingEnd">35dp</item>
- <item name="android:text">@string/cling_dismiss</item>
- <item name="android:textSize">20sp</item>
- <item name="android:textStyle">bold</item>
- <item name="android:background">@drawable/cling_button_bg</item>
- </style>
- <style name="ClingTitleText">
- <item name="android:layout_width">wrap_content</item>
- <item name="android:layout_height">wrap_content</item>
- <item name="android:layout_marginBottom">5dp</item>
- <item name="android:textSize">32sp</item>
- <item name="android:textColor">#49C0EC</item>
- <item name="android:shadowColor">#000000</item>
- <item name="android:shadowDy">2</item>
- <item name="android:shadowRadius">2.0</item>
- </style>
- <style name="ClingText">
- <item name="android:textSize">22sp</item>
- <item name="android:textColor">#FFFFFF</item>
- <item name="android:shadowColor">#000000</item>
- <item name="android:shadowDy">2</item>
- <item name="android:shadowRadius">2.0</item>
- <item name="android:lineSpacingMultiplier">1.1</item>
- </style>
-
<!-- Workspace -->
- <style name="Theme" parent="android:Theme.Holo.Wallpaper.NoTitleBar">
- <item name="android:windowActionModeOverlay">true</item>
- <item name="android:windowTranslucentStatus">true</item>
- <item name="android:windowTranslucentNavigation">true</item>
- </style>
-
<style name="TabIndicator.AppsCustomize">
- <item name="android:paddingStart">32dp</item>
- <item name="android:paddingEnd">32dp</item>
+ <item name="android:paddingLeft">32dp</item>
+ <item name="android:paddingRight">32dp</item>
<item name="android:textSize">14sp</item>
<item name="android:maxWidth">240dp</item>
</style>
- <!-- QSB Search / Drop Target bar -->
- <style name="QSBBar">
- </style>
- <style name="SearchDropTargetBar">
- </style>
<style name="SearchButton">
</style>
<style name="DropTargetButtonContainer">
@@ -81,8 +38,8 @@
<item name="android:layout_gravity">center</item>
<item name="android:gravity">center_vertical</item>
<item name="android:drawablePadding">7.5dp</item>
- <item name="android:paddingStart">60dp</item>
- <item name="android:paddingEnd">60dp</item>
+ <item name="android:paddingLeft">60dp</item>
+ <item name="android:paddingRight">60dp</item>
<item name="android:textColor">#FFFFFFFF</item>
<item name="android:textSize">16sp</item>
<item name="android:shadowColor">#393939</item>
diff --git a/res/values-th/cm_arrays.xml b/res/values-th/cm_arrays.xml
index 1f612140a..1fdc6cf54 100644
--- a/res/values-th/cm_arrays.xml
+++ b/res/values-th/cm_arrays.xml
@@ -16,15 +16,10 @@
limitations under the License.
-->
<resources>
- <string-array name="preferences_interface_general_icons_text_font_family_entries">
- <item>ปกติ</item>
- <item>บาง</item>
- <item>บีบ</item>
- </string-array>
<string-array name="transition_effect_entries">
<item>ไม่มี</item>
- <item>ขยาย</item>
- <item>ย่อ</item>
+ <item>ซูมเข้า</item>
+ <item>ซูมออก</item>
<item>หมุนขึ้น</item>
<item>หมุนลง</item>
<item>เข้าลูกบาศก์</item>
diff --git a/res/values-th/cm_strings.xml b/res/values-th/cm_strings.xml
index 8fc18cb92..a3ecfdf3c 100644
--- a/res/values-th/cm_strings.xml
+++ b/res/values-th/cm_strings.xml
@@ -16,49 +16,37 @@
limitations under the License.
-->
<resources>
- <string name="application_copyright">สงวนลิขสิทธิ์ \u00A9 2014 The CyanogenMod Project</string>
- <string name="sort_button_text">เรียงลำดับ</string>
- <string name="filter_button_text">ตัวกรอง</string>
- <string name="default_screen_button_text">หน้าจอเริ่มต้น</string>
- <string name="transition_effect_button_text">เอฟเฟกต์เลื่อน</string>
- <string name="sort_mode_title">ชื่อเรื่อง</string>
- <string name="sort_mode_launch_count">ตัวนับครั้งการเปิด</string>
- <string name="sort_mode_install_time">เวลาติดตั้ง</string>
+ <string name="launcher_settings">ตั้งค่าหน้าตัวเรียกใช้งาน</string>
+ <string name="home_screen_settings">ตั้งค่าหน้าจอหลัก</string>
+ <string name="drawer_settings">ตั้งค่าแผงแสดงแอป</string>
+ <string name="app_settings">ตั้งค่าแอป</string>
+ <string name="setting_state_on">เปิด</string>
+ <string name="setting_state_off">ปิด</string>
+ <string name="themes_button_text">ชุดรูปแบบ</string>
<string name="scrolling_page_outlines">โครงร่างหน้า</string>
<string name="scrolling_fade_adjacent">จากหน้าด้านข้าง</string>
- <string name="wallpaper_scroll">เลื่อนภาพพื้นหลัง</string>
- <string name="preferences_title">ตั้งค่า</string>
- <string name="preferences_application_title">แอป</string>
- <string name="preferences_interface_homescreen_title">หน้าจอหลัก</string>
- <string name="preferences_interface_homescreen_search_title">แถบค้นหา</string>
- <string name="preferences_interface_homescreen_search_summary">แสดงแถบค้นหาแบบคงที่ด้านบนของหน้าจอ</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_title">ซ่อนป้ายชื่อไอคอน</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">ซ่อนป้ายชื่อบนหน้าจอหลัก</string>
- <string name="preferences_interface_drawer_title">พื้นที่วาง</string>
- <string name="preferences_interface_drawer_summary">พื้นที่วางแอป และ วิดเจ็ท</string>
- <string name="preferences_interface_drawer_apps_category">แอป</string>
- <string name="preferences_interface_drawer_hidden_apps_title">ซ่อนแอป</string>
- <string name="preferences_interface_drawer_hidden_apps_summary">ซ่อนแอปจากพื้นที่วางแอป</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">เอาทางลัดออก</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">เอาทางลัดของแอปที่ซ่อนออกจากหน้าจอหลัก</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_title">นำวิดเจ็ดออก</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_summary">นำวิดเจ็ทของแอปที่ถูกซ่อนออกจากจอหลัก</string>
- <string name="preferences_interface_drawer_hide_icon_labels_title">ซ่อนป้ายชื่อไอคอน</string>
- <string name="preferences_interface_drawer_hide_icon_labels_summary">ซ่อนป้ายชื่อไอคอนในที่วางแอป</string>
- <string name="preferences_interface_dock_title">แถบวาง</string>
- <string name="preferences_interface_general_title">ทั่วไป</string>
- <string name="preferences_interface_general_icons_category">ไอคอน</string>
- <string name="preferences_interface_general_icons_large_title">ไอคอนขนาดใหญ่</string>
- <string name="preferences_interface_general_icons_large_summary">ใช้ไอคอนแอปพิเคชันขนาดใหญ่มากในจอหลักและที่วางแอป</string>
- <string name="preferences_interface_general_icons_text_style_title">รูปแบบข้อความ</string>
- <string name="preferences_interface_general_icons_text_style_summary">ลักษณะของแบบอักษรที่จะใช้สำหรับป้ายชื่อไอคอน</string>
- <string name="dialog_pick_iconpack_title">เลือกชุดไอคอน</string>
- <string name="default_iconpack_title">ไอคอนเริ่มต้น</string>
- <string name="icon_packs_title">ชุดไอคอน</string>
- <string name="no_iconpacks_summary">ไม่มีชุดไอคอนที่ติดตั้งอยู่</string>
- <string name="clear_keyguard_wallpaper">ล้าง</string>
- <string name="all_apps_cling_cm">กำหนดที่วางแอปของคุณ</string>
- <string name="all_apps_cling_summary">แตะตัวแบ่งหน้าเพื่อดูการตั้งค่าเพิ่มเติม</string>
- <string name="menu_hidden_apps_delete">ล้างค่า</string>
+ <string name="scrolling_wallpaper">เลื่อนภาพพื้นหลัง</string>
+ <string name="grid_size_text">ขนาดกริด</string>
+ <string name="grid_size_comfortable">สะดวกสบาย</string>
+ <string name="grid_size_cozy">โคซี่</string>
+ <string name="grid_size_condensed">บีบ</string>
+ <string name="grid_size_custom">กำหนดเอง</string>
+ <string name="preferences_interface_homescreen_custom">เลือกขนาดกำหนดเอง</string>
+ <string name="preferences_interface_homescreen_rows_title">จำนวนแถว</string>
+ <string name="preferences_interface_homescreen_columns_title">จำนวนคอลัมน์</string>
<string name="hidden_apps_title">ซ่อนแอป</string>
+ <string name="scroll_effect_text">เอฟเฟกต์เลื่อน</string>
+ <string name="drawer_sorting_text">วิธีการเรียง</string>
+ <string name="sort_mode_title">ชื่อเรื่อง</string>
+ <string name="sort_mode_launch_count">ตัวนับครั้งการเปิด</string>
+ <string name="sort_mode_install_time">เวลาติดตั้ง</string>
+ <string name="home_screen_search_text">แถบค้นหา</string>
+ <string name="larger_icons_text">ไอคอนขนาดใหญ่</string>
+ <string name="icon_labels">ป้ายชื่อไอคอน</string>
+ <string name="icon_labels_show">แสดง</string>
+ <string name="icon_labels_hide">ซ่อน</string>
+ <string name="protected_app_settings">แอปที่ป้องกัน</string>
+ <string name="search_screen_left_text">แผงค้นหา</string>
+ <string name="search_screen_left_unsupported_toast">คุณต้องมีแอปที่รองรับการค้นหากับ CyanogenMod เพื่อใช้ความสามารถนี้</string>
+ <string name="dialog_confirm">Google</string>
</resources>
diff --git a/res/values-tr/cm_arrays.xml b/res/values-tr/cm_arrays.xml
index 6631a719b..bfe889901 100644
--- a/res/values-tr/cm_arrays.xml
+++ b/res/values-tr/cm_arrays.xml
@@ -16,24 +16,19 @@
limitations under the License.
-->
<resources>
- <string-array name="preferences_interface_general_icons_text_font_family_entries">
- <item>Normal</item>
- <item>İnce</item>
- <item>Kalın</item>
- </string-array>
<string-array name="transition_effect_entries">
<item>Hiçbiri</item>
<item>Yakınlaştır</item>
<item>Uzaklaştır</item>
- <item>Yukarı Döndür</item>
- <item>Aşağı Döndür</item>
- <item>Kübün İçi</item>
- <item>Kübün dışı</item>
+ <item>Yukarı döndür</item>
+ <item>Aşağı döndür</item>
+ <item>Küp içi</item>
+ <item>Küp dışı</item>
<item>Yığın</item>
<item>Akordiyon</item>
<item>Çevir</item>
- <item>Silindirin İçi</item>
- <item>Silindirin Dışı</item>
+ <item>Silindir içi</item>
+ <item>Silindir dışı</item>
<item>Karusel</item>
<item>Genel Görünüm</item>
</string-array>
diff --git a/res/values-tr/cm_strings.xml b/res/values-tr/cm_strings.xml
index 529b76b03..4a7db9ca2 100644
--- a/res/values-tr/cm_strings.xml
+++ b/res/values-tr/cm_strings.xml
@@ -16,49 +16,37 @@
limitations under the License.
-->
<resources>
- <string name="application_copyright">Telif Hakkı \u00A9 2014 CyanogenMod Projesi</string>
- <string name="sort_button_text">Sırala</string>
- <string name="filter_button_text">Filtrele</string>
- <string name="default_screen_button_text">Varsayılan ekran</string>
- <string name="transition_effect_button_text">Kaydırma efekti</string>
- <string name="sort_mode_title">Başlık</string>
- <string name="sort_mode_launch_count">Çalıştırma sayısı</string>
- <string name="sort_mode_install_time">Kurulum zamanı</string>
+ <string name="launcher_settings">BAŞLATICI AYARLARI</string>
+ <string name="home_screen_settings">ANA EKRAN AYARLARI</string>
+ <string name="drawer_settings">ÇEKMECE AYARLARI</string>
+ <string name="app_settings">UYGULAMA AYARLARI</string>
+ <string name="setting_state_on">AÇIK</string>
+ <string name="setting_state_off">KAPALI</string>
+ <string name="themes_button_text">Temalar</string>
<string name="scrolling_page_outlines">Sayfa anahatları</string>
<string name="scrolling_fade_adjacent">Yan sayfaları soldur</string>
- <string name="wallpaper_scroll">Duvarkağıdını kaydır</string>
- <string name="preferences_title">Ayarlar</string>
- <string name="preferences_application_title">Uygulama</string>
- <string name="preferences_interface_homescreen_title">Ana Ekran</string>
- <string name="preferences_interface_homescreen_search_title">Arama çubuğu</string>
- <string name="preferences_interface_homescreen_search_summary">Ekranın üstünde kalıcı arama çubuğu göster</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_title">Simge etiketlerini gizle</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">Ana ekranda simge etiketlerini gizle</string>
- <string name="preferences_interface_drawer_title">Uygulama çekmecesi</string>
- <string name="preferences_interface_drawer_summary">Uygulama ve widget çekmecesi</string>
- <string name="preferences_interface_drawer_apps_category">Uygulamalar</string>
- <string name="preferences_interface_drawer_hidden_apps_title">Gizli uygulamalar</string>
- <string name="preferences_interface_drawer_hidden_apps_summary">Uygulamaları menüden gizle</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">Kısayolları kaldır</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">Ana ekrandan gizli uygulamaların kısayollarını kaldır</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_title">Widgetları kaldır</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_summary">Ana ekrandan gizli uygulamaların widgetlarını kaldır</string>
- <string name="preferences_interface_drawer_hide_icon_labels_title">Simge etiketlerini gizle</string>
- <string name="preferences_interface_drawer_hide_icon_labels_summary">Çekmecedeki simge etiketlerini gizle</string>
- <string name="preferences_interface_dock_title">Ünite</string>
- <string name="preferences_interface_general_title">Genel</string>
- <string name="preferences_interface_general_icons_category">Simgeler</string>
- <string name="preferences_interface_general_icons_large_title">Büyük simgeler</string>
- <string name="preferences_interface_general_icons_large_summary">Ana ekranda ve uygulama çekmecesinde çok büyük uyg. simgeleri kullan</string>
- <string name="preferences_interface_general_icons_text_style_title">Yazı tipi stili</string>
- <string name="preferences_interface_general_icons_text_style_summary">Simge yazısı için yazı tipi</string>
- <string name="dialog_pick_iconpack_title">Simge paketi seç</string>
- <string name="default_iconpack_title">Varsayılan simgeler</string>
- <string name="icon_packs_title">Simge paketleri</string>
- <string name="no_iconpacks_summary">Yüklü simge paketi yok</string>
- <string name="clear_keyguard_wallpaper">Temizle</string>
- <string name="all_apps_cling_cm">Uygulama çekmecesini özelleştir</string>
- <string name="all_apps_cling_summary">Ek ayarlara bakmak için sayfa göstergesine dokun</string>
- <string name="menu_hidden_apps_delete">Sıfırla</string>
+ <string name="scrolling_wallpaper">Duvarkağıdını kaydır</string>
+ <string name="grid_size_text">Izgara boyutu</string>
+ <string name="grid_size_comfortable">Rahat</string>
+ <string name="grid_size_cozy">Rahat</string>
+ <string name="grid_size_condensed">Kalın</string>
+ <string name="grid_size_custom">Özel</string>
+ <string name="preferences_interface_homescreen_custom">Özel boyut seçin</string>
+ <string name="preferences_interface_homescreen_rows_title">Satır sayısı</string>
+ <string name="preferences_interface_homescreen_columns_title">Sütun sayısı</string>
<string name="hidden_apps_title">Gizli uygulamalar</string>
+ <string name="scroll_effect_text">Kaydırma efekti</string>
+ <string name="drawer_sorting_text">Sıralama modu</string>
+ <string name="sort_mode_title">Başlık</string>
+ <string name="sort_mode_launch_count">Çalıştırma sayısı</string>
+ <string name="sort_mode_install_time">Kurulum zamanı</string>
+ <string name="home_screen_search_text">Arama çubuğu</string>
+ <string name="larger_icons_text">Daha büyük simgeler</string>
+ <string name="icon_labels">Simge etiketleri</string>
+ <string name="icon_labels_show">Göster</string>
+ <string name="icon_labels_hide">Gizle</string>
+ <string name="protected_app_settings">Korunan uygulamalar</string>
+ <string name="search_screen_left_text">Arama paneli</string>
+ <string name="search_screen_left_unsupported_toast">Bu özelliği kullanabilmeniz için desteklenen bir arama uygulaması ve CyanogenMod\'a sahip olmanız gerekiyor.</string>
+ <string name="dialog_confirm">Onayla</string>
</resources>
diff --git a/res/values-uk/cm_arrays.xml b/res/values-uk/cm_arrays.xml
index 69fc3dfe5..63cab2291 100644
--- a/res/values-uk/cm_arrays.xml
+++ b/res/values-uk/cm_arrays.xml
@@ -16,24 +16,19 @@
limitations under the License.
-->
<resources>
- <string-array name="preferences_interface_general_icons_text_font_family_entries">
- <item>Звичайний</item>
- <item>Легкий</item>
- <item>Стиснутий</item>
- </string-array>
<string-array name="transition_effect_entries">
<item>Немає</item>
- <item>Збільшення</item>
- <item>Зменшення</item>
- <item>Поворот вверх</item>
- <item>Поворот вниз</item>
- <item>В середині куба</item>
- <item>Ззовні куба</item>
+ <item>Zoom in</item>
+ <item>Zoom out</item>
+ <item>Rotate up</item>
+ <item>Rotate down</item>
+ <item>Cube in</item>
+ <item>Cube out</item>
<item>Стек</item>
<item>Гармошка</item>
<item>Переворот</item>
- <item>В середині циліндра</item>
- <item>Ззовні циліндра</item>
+ <item>Cylinder in</item>
+ <item>Cylinder out</item>
<item>Карусель</item>
<item>Огляд</item>
</string-array>
diff --git a/res/values-uk/cm_strings.xml b/res/values-uk/cm_strings.xml
index 005ef45e7..1c975b681 100644
--- a/res/values-uk/cm_strings.xml
+++ b/res/values-uk/cm_strings.xml
@@ -16,49 +16,10 @@
limitations under the License.
-->
<resources>
- <string name="application_copyright">Всі права захищені \u00A9 2014 The CyanogenMod Project</string>
- <string name="sort_button_text">Сортувати</string>
- <string name="filter_button_text">Фільтр</string>
- <string name="default_screen_button_text">Екран за замовчуванням</string>
- <string name="transition_effect_button_text">Ефект гортання</string>
- <string name="sort_mode_title">По назві</string>
- <string name="sort_mode_launch_count">По частоті використання</string>
- <string name="sort_mode_install_time">По часу встановлення</string>
<string name="scrolling_page_outlines">Межі сторінок</string>
<string name="scrolling_fade_adjacent">Затемняти краї при гортанні</string>
- <string name="wallpaper_scroll">Прокручувати шпалери</string>
- <string name="preferences_title">Налаштування</string>
- <string name="preferences_application_title">Програма</string>
- <string name="preferences_interface_homescreen_title">Домашній екран</string>
- <string name="preferences_interface_homescreen_search_title">Рядок пошуку</string>
- <string name="preferences_interface_homescreen_search_summary">Завжди показувати рядок пошуку зверху екрану</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_title">Приховувати підписи значків</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">Не відображати текст ярликів на домашньому екрані</string>
- <string name="preferences_interface_drawer_title">Меню програм</string>
- <string name="preferences_interface_drawer_summary">Список програм і віджетів</string>
- <string name="preferences_interface_drawer_apps_category">Програми</string>
- <string name="preferences_interface_drawer_hidden_apps_title">Приховані програми</string>
- <string name="preferences_interface_drawer_hidden_apps_summary">Приховати програми з меню програм</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">Видаляти ярлики</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">Прибирати ярлики прихованих програм з домашнього екрану</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_title">Видаляти віджети</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_summary">Прибирати віджети прихованих програм з домашнього екрану</string>
- <string name="preferences_interface_drawer_hide_icon_labels_title">Приховувати підписи значків</string>
- <string name="preferences_interface_drawer_hide_icon_labels_summary">Не відображати текст ярликів в меню програм</string>
- <string name="preferences_interface_dock_title">Нижня панель</string>
- <string name="preferences_interface_general_title">Загальні</string>
- <string name="preferences_interface_general_icons_category">Значки</string>
- <string name="preferences_interface_general_icons_large_title">Великі значки</string>
- <string name="preferences_interface_general_icons_large_summary">Використовувати великі значки на домашньому екрані та меню програм</string>
- <string name="preferences_interface_general_icons_text_style_title">Стиль шрифту</string>
- <string name="preferences_interface_general_icons_text_style_summary">Стиль та варіант шрифту для тексту під значками</string>
- <string name="dialog_pick_iconpack_title">Вибрати набір значків</string>
- <string name="default_iconpack_title">Типові значки</string>
- <string name="icon_packs_title">Набори значків</string>
- <string name="no_iconpacks_summary">Жодного набору значків не встановлено</string>
- <string name="clear_keyguard_wallpaper">Очистити</string>
- <string name="all_apps_cling_cm">Налаштуйте меню програм</string>
- <string name="all_apps_cling_summary">Торкніться індикатора сторінки знизу, щоб перейти до налаштувань</string>
- <string name="menu_hidden_apps_delete">Скидання</string>
<string name="hidden_apps_title">Приховані програми</string>
+ <string name="sort_mode_title">По назві</string>
+ <string name="sort_mode_launch_count">По частоті використання</string>
+ <string name="sort_mode_install_time">По часу встановлення</string>
</resources>
diff --git a/res/values-v17/styles.xml b/res/values-v17/styles.xml
new file mode 100644
index 000000000..71c4bfa66
--- /dev/null
+++ b/res/values-v17/styles.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <style name="PagedViewWidgetImageView">
+ <item name="android:paddingStart">@dimen/app_widget_preview_padding_left</item>
+ </style>
+ <style name="SearchButton.WithPaddingStart">
+ <item name="android:paddingStart">8dp</item>
+ </style>
+</resources>
diff --git a/res/values-zh-rCN/cm_arrays.xml b/res/values-zh-rCN/cm_arrays.xml
index 0e02c2853..0c16fd116 100644
--- a/res/values-zh-rCN/cm_arrays.xml
+++ b/res/values-zh-rCN/cm_arrays.xml
@@ -16,11 +16,6 @@
limitations under the License.
-->
<resources>
- <string-array name="preferences_interface_general_icons_text_font_family_entries">
- <item>常规</item>
- <item>Light</item>
- <item>Condensed</item>
- </string-array>
<string-array name="transition_effect_entries">
<item>无</item>
<item>放大</item>
diff --git a/res/values-zh-rCN/cm_strings.xml b/res/values-zh-rCN/cm_strings.xml
index 408769dac..2c617d8e2 100644
--- a/res/values-zh-rCN/cm_strings.xml
+++ b/res/values-zh-rCN/cm_strings.xml
@@ -16,49 +16,38 @@
limitations under the License.
-->
<resources>
- <string name="application_copyright">版权所有 \u00A9 2014 CyanogenMod 项目</string>
- <string name="sort_button_text">排序</string>
- <string name="filter_button_text">过滤器</string>
- <string name="default_screen_button_text">默认屏幕</string>
- <string name="transition_effect_button_text">滚动特效</string>
- <string name="sort_mode_title">标题</string>
- <string name="sort_mode_launch_count">启动次数</string>
- <string name="sort_mode_install_time">安装时间</string>
+ <string name="launcher_settings">启动器设置</string>
+ <string name="home_screen_settings">主屏幕设置</string>
+ <string name="drawer_settings">抽屉设置</string>
+ <string name="app_settings">应用设置</string>
+ <string name="setting_state_on">打开</string>
+ <string name="setting_state_off">关闭</string>
+ <string name="themes_button_text">主题</string>
<string name="scrolling_page_outlines">页概述</string>
<string name="scrolling_fade_adjacent">边页淡出</string>
- <string name="wallpaper_scroll">滚动壁纸</string>
- <string name="preferences_title">设置</string>
- <string name="preferences_application_title">应用程序</string>
- <string name="preferences_interface_homescreen_title">主屏</string>
- <string name="preferences_interface_homescreen_search_title">搜索栏</string>
- <string name="preferences_interface_homescreen_search_summary">在屏幕上方始终显示搜索栏</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_title">隐藏图标标签</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">在主屏幕上隐藏图标标签</string>
- <string name="preferences_interface_drawer_title">抽屉</string>
- <string name="preferences_interface_drawer_summary">应用和小部件抽屉</string>
- <string name="preferences_interface_drawer_apps_category">应用</string>
- <string name="preferences_interface_drawer_hidden_apps_title">隐藏的应用</string>
- <string name="preferences_interface_drawer_hidden_apps_summary">从抽屉隐藏应用</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">移除快捷方式</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">从主屏幕移除已隐藏应用的快捷方式</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_title">移除小部件</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_summary">从主屏幕移除已隐藏应用的小部件</string>
- <string name="preferences_interface_drawer_hide_icon_labels_title">隐藏图标标签</string>
- <string name="preferences_interface_drawer_hide_icon_labels_summary">在抽屉里隐藏图标标签</string>
- <string name="preferences_interface_dock_title">基座</string>
- <string name="preferences_interface_general_title">通用</string>
- <string name="preferences_interface_general_icons_category">图标</string>
- <string name="preferences_interface_general_icons_large_title">大图标</string>
- <string name="preferences_interface_general_icons_large_summary">显示大图标</string>
- <string name="preferences_interface_general_icons_text_style_title">字体样式</string>
- <string name="preferences_interface_general_icons_text_style_summary">图标字体样式</string>
- <string name="dialog_pick_iconpack_title">选择图标包</string>
- <string name="default_iconpack_title">默认图标</string>
- <string name="icon_packs_title">图标包</string>
- <string name="no_iconpacks_summary">没有安装的图标包</string>
- <string name="clear_keyguard_wallpaper">清除</string>
- <string name="all_apps_cling_cm">自定义抽屉</string>
- <string name="all_apps_cling_summary">点击页面指示器以查看其他设置</string>
- <string name="menu_hidden_apps_delete">重置</string>
+ <string name="scrolling_wallpaper">滚动壁纸</string>
+ <string name="grid_size_text">网格大小</string>
+ <string name="grid_size_comfortable">宽松</string>
+ <string name="grid_size_cozy">合适</string>
+ <string name="grid_size_condensed">紧凑</string>
+ <string name="grid_size_custom">自定义
+</string>
+ <string name="preferences_interface_homescreen_custom">选择自定义尺寸</string>
+ <string name="preferences_interface_homescreen_rows_title">行数</string>
+ <string name="preferences_interface_homescreen_columns_title">列数</string>
<string name="hidden_apps_title">隐藏的应用</string>
+ <string name="scroll_effect_text">滚动特效</string>
+ <string name="drawer_sorting_text">排序模式</string>
+ <string name="sort_mode_title">标题</string>
+ <string name="sort_mode_launch_count">启动次数</string>
+ <string name="sort_mode_install_time">安装时间</string>
+ <string name="home_screen_search_text">搜索栏</string>
+ <string name="larger_icons_text">大图标</string>
+ <string name="icon_labels">图标标签</string>
+ <string name="icon_labels_show">显示</string>
+ <string name="icon_labels_hide">隐藏</string>
+ <string name="protected_app_settings">受保护的应用</string>
+ <string name="search_screen_left_text">搜索面板</string>
+ <string name="search_screen_left_unsupported_toast">您必须有一个受支持的搜索应用和 CyanogenMod 以使用此功能。</string>
+ <string name="dialog_confirm">确认</string>
</resources>
diff --git a/res/values-zh-rHK/cm_arrays.xml b/res/values-zh-rHK/cm_arrays.xml
index b589a80ea..9c806f151 100644
--- a/res/values-zh-rHK/cm_arrays.xml
+++ b/res/values-zh-rHK/cm_arrays.xml
@@ -16,24 +16,19 @@
limitations under the License.
-->
<resources>
- <string-array name="preferences_interface_general_icons_text_font_family_entries">
- <item>正常</item>
- <item>明亮</item>
- <item>簡明</item>
- </string-array>
<string-array name="transition_effect_entries">
<item>無</item>
<item>放大</item>
<item>縮小</item>
<item>向上旋轉</item>
- <item>向下旋轉</item>
- <item>Cube In</item>
- <item>Cube Out</item>
+ <item>Rotate down</item>
+ <item>Cube in</item>
+ <item>Cube out</item>
<item>堆疊</item>
<item>手風琴</item>
<item>翻轉</item>
- <item>膛入</item>
- <item>膛出</item>
+ <item>Cylinder in</item>
+ <item>Cylinder out</item>
<item>幻燈片 </item>
<item>概述</item>
</string-array>
diff --git a/res/values-zh-rHK/cm_strings.xml b/res/values-zh-rHK/cm_strings.xml
index ce4bfcf4f..0b720c055 100644
--- a/res/values-zh-rHK/cm_strings.xml
+++ b/res/values-zh-rHK/cm_strings.xml
@@ -16,49 +16,20 @@
limitations under the License.
-->
<resources>
- <string name="application_copyright">版權所有 \u00A9 2013年 CyanogenMod 計畫</string>
- <string name="sort_button_text">排序</string>
- <string name="filter_button_text">篩選過濾</string>
- <string name="default_screen_button_text">預設螢幕</string>
- <string name="transition_effect_button_text">滾動效果</string>
- <string name="sort_mode_title">標題</string>
- <string name="sort_mode_launch_count">啟動次數</string>
- <string name="sort_mode_install_time">安裝時間</string>
+ <string name="launcher_settings">啟動器設定</string>
+ <string name="home_screen_settings">主螢幕設定</string>
+ <string name="drawer_settings">抽屜設定</string>
+ <string name="setting_state_on">開啟</string>
+ <string name="setting_state_off">關閉</string>
+ <string name="themes_button_text">主題</string>
<string name="scrolling_page_outlines">頁面輪廓</string>
<string name="scrolling_fade_adjacent">邊頁淡出</string>
- <string name="wallpaper_scroll">滾動牆紙</string>
- <string name="preferences_title">設定</string>
- <string name="preferences_application_title">應用程式</string>
- <string name="preferences_interface_homescreen_title">主螢幕</string>
- <string name="preferences_interface_homescreen_search_title">搜尋欄</string>
- <string name="preferences_interface_homescreen_search_summary">在螢幕上方顯示搜尋欄</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_title">隱藏圖示標籤</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">隱藏主螢幕的圖示標籤</string>
- <string name="preferences_interface_drawer_title">抽屜</string>
- <string name="preferences_interface_drawer_summary">應用程式和小工具的抽屜</string>
- <string name="preferences_interface_drawer_apps_category">應用程式</string>
- <string name="preferences_interface_drawer_hidden_apps_title">隱藏的應用程式</string>
- <string name="preferences_interface_drawer_hidden_apps_summary">隱藏從抽屜的應用程式</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">移除捷徑</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">從主螢幕移除已隱藏的應用程式捷徑</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_title">移除小工具</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_summary">從主螢幕移除已隱藏的應用程式小工具</string>
- <string name="preferences_interface_drawer_hide_icon_labels_title">隱藏圖示標籤</string>
- <string name="preferences_interface_drawer_hide_icon_labels_summary">隱藏在抽屜裡的圖示標籤</string>
- <string name="preferences_interface_dock_title">基座</string>
- <string name="preferences_interface_general_title">一般</string>
- <string name="preferences_interface_general_icons_category">圖示</string>
- <string name="preferences_interface_general_icons_large_title">大圖示</string>
- <string name="preferences_interface_general_icons_large_summary">使用超大的應用程序圖標於主螢幕和抽屜</string>
- <string name="preferences_interface_general_icons_text_style_title">字體風格</string>
- <string name="preferences_interface_general_icons_text_style_summary">變體和字體風格用來應用於圖示的文本上</string>
- <string name="dialog_pick_iconpack_title">選擇圖示包</string>
- <string name="default_iconpack_title">預設圖示</string>
- <string name="icon_packs_title">圖示包</string>
- <string name="no_iconpacks_summary">沒有安裝圖示包</string>
- <string name="clear_keyguard_wallpaper">清除</string>
- <string name="all_apps_cling_cm">自訂您的抽屜</string>
- <string name="all_apps_cling_summary">點擊頁面指標來查看其他配置設定</string>
- <string name="menu_hidden_apps_delete">重設</string>
<string name="hidden_apps_title">隱藏的應用程式</string>
+ <string name="scroll_effect_text">滾動效果</string>
+ <string name="drawer_sorting_text">排序模式</string>
+ <string name="sort_mode_title">標題</string>
+ <string name="sort_mode_launch_count">啟動次數</string>
+ <string name="sort_mode_install_time">安裝時間</string>
+ <string name="home_screen_search_text">搜尋列</string>
+ <string name="larger_icons_text">大圖示</string>
</resources>
diff --git a/res/values-zh-rTW/cm_arrays.xml b/res/values-zh-rTW/cm_arrays.xml
new file mode 100644
index 000000000..a5b57d64c
--- /dev/null
+++ b/res/values-zh-rTW/cm_arrays.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.net-->
+<!--
+ Copyright (C) 2014 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <string-array name="transition_effect_entries">
+ <item>無</item>
+ <item>Zoom in</item>
+ <item>Zoom out</item>
+ <item>Rotate up</item>
+ <item>Rotate down</item>
+ <item>Cube in</item>
+ <item>Cube out</item>
+ <item>Stack</item>
+ <item>手風琴</item>
+ <item>Flip</item>
+ <item>Cylinder in</item>
+ <item>Cylinder out</item>
+ <item>Carousel</item>
+ <item>概述</item>
+ </string-array>
+</resources>
diff --git a/res/values-zh-rTW/cm_strings.xml b/res/values-zh-rTW/cm_strings.xml
new file mode 100644
index 000000000..acec787c7
--- /dev/null
+++ b/res/values-zh-rTW/cm_strings.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.net-->
+<!--
+ Copyright (C) 2014 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <string name="setting_state_on">開啟</string>
+ <string name="setting_state_off">關閉</string>
+ <string name="themes_button_text">主題</string>
+ <string name="scrolling_fade_adjacent">邊頁淡出</string>
+ <string name="hidden_apps_title">隱藏的應用程式</string>
+ <string name="sort_mode_title">標題</string>
+ <string name="sort_mode_launch_count">啟動次數</string>
+ <string name="sort_mode_install_time">安裝時間</string>
+ <string name="home_screen_search_text">搜尋列</string>
+ <string name="larger_icons_text">大圖示</string>
+</resources>
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index a2d3a83e0..c64b4f9ec 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -103,8 +103,7 @@
<attr name="pageLayoutPaddingBottom" format="dimension" />
<attr name="pageLayoutPaddingLeft" format="dimension" />
<attr name="pageLayoutPaddingRight" format="dimension" />
- <!-- The space between adjacent pages of the PagedView. -->
- <attr name="pageSpacing" format="dimension" />
+
<!-- The page indicator for this workspace -->
<attr name="pageIndicator" format="reference" />
</declare-styleable>
@@ -157,4 +156,15 @@
</declare-styleable>
<declare-styleable name="CustomClingText">
</declare-styleable>
+
+ <declare-styleable name="SlidingUpPanelLayout">
+ <attr name="panelHeight" format="dimension" />
+ <attr name="shadowHeight" format="dimension" />
+ <attr name="paralaxOffset" format="dimension" />
+ <attr name="fadeColor" format="color" />
+ <attr name="flingVelocity" format="integer" />
+ <attr name="dragView" format="reference" />
+ <attr name="overlay" format="boolean"/>
+ </declare-styleable>
+
</resources>
diff --git a/res/values/cm_arrays.xml b/res/values/cm_arrays.xml
index 502b7a65c..e8b02dbcb 100644
--- a/res/values/cm_arrays.xml
+++ b/res/values/cm_arrays.xml
@@ -15,30 +15,19 @@
limitations under the License.
-->
<resources>
- <string-array name="preferences_interface_general_icons_text_font_family_entries">
- <item>Regular</item>
- <item>Light</item>
- <item>Condensed</item>
- </string-array>
- <string-array name="preferences_interface_general_icons_text_font_family_values" translatable="false">
- <item>sans-serif</item>
- <item>sans-serif-light</item>
- <item>sans-serif-condensed</item>
- </string-array>
-
<string-array name="transition_effect_entries">
<item>None</item>
- <item>Zoom In</item>
- <item>Zoom Out</item>
- <item>Rotate Up</item>
- <item>Rotate Down</item>
- <item>Cube In</item>
- <item>Cube Out</item>
+ <item>Zoom in</item>
+ <item>Zoom out</item>
+ <item>Rotate up</item>
+ <item>Rotate down</item>
+ <item>Cube in</item>
+ <item>Cube out</item>
<item>Stack</item>
<item>Accordion</item>
<item>Flip</item>
- <item>Cylinder In</item>
- <item>Cylinder Out</item>
+ <item>Cylinder in</item>
+ <item>Cylinder out</item>
<item>Carousel</item>
<item>Overview</item>
</string-array>
@@ -58,4 +47,20 @@
<item>carousel</item>
<item>overview</item>
</string-array>
+ <string-array name="transition_effect_drawables" translatable="false">
+ <item>@drawable/transition_none</item>
+ <item>@drawable/transition_zoomin</item>
+ <item>@drawable/transition_zoomout</item>
+ <item>@drawable/transition_rotateup</item>
+ <item>@drawable/transition_rotatedown</item>
+ <item>@drawable/transition_cubein</item>
+ <item>@drawable/transition_cubeout</item>
+ <item>@drawable/transition_stack</item>
+ <item>@drawable/transition_accordion</item>
+ <item>@drawable/transition_flip</item>
+ <item>@drawable/transition_cylinderin</item>
+ <item>@drawable/transition_cylinderout</item>
+ <item>@drawable/transition_carousel</item>
+ <item>@drawable/transition_overview</item>
+ </string-array>
</resources>
diff --git a/res/values/cm_integers.xml b/res/values/cm_integers.xml
new file mode 100644
index 000000000..f3b0464ef
--- /dev/null
+++ b/res/values/cm_integers.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2014 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <integer name="qsb_initial_alpha_state">55</integer>
+ <integer name="qsb_end_alpha_state">220</integer>
+ <integer name="qsb_buttons_end_colorfilter">120</integer>
+</resources>
diff --git a/res/values/cm_strings.xml b/res/values/cm_strings.xml
index d4effcc40..b924922fb 100644
--- a/res/values/cm_strings.xml
+++ b/res/values/cm_strings.xml
@@ -17,86 +17,74 @@
<resources>
<!-- Application name -->
<string name="cm_application_name" translatable="false">Trebuchet</string>
- <!-- App copyright -->
- <string name="application_copyright">Copyright \u00A9 2014 The CyanogenMod Project</string>
<!-- App version -->
<string name="application_version" translatable="false">1.0</string>
- <!-- Strings for the customization mode -->
- <!-- Text for sorting mode button -->
- <string name="sort_button_text">Sort</string>
- <!-- Text for filter button -->
- <string name="filter_button_text">Filter</string>
- <!-- Text for default screen button -->
- <string name="default_screen_button_text">Default screen</string>
- <!-- Text for transition effect button -->
- <string name="transition_effect_button_text">Scroll effect</string>
+ <string name="launcher_settings">LAUNCHER SETTINGS</string>
+ <string name="home_screen_settings">HOME SCREEN SETTINGS</string>
+ <string name="drawer_settings">DRAWER SETTINGS</string>
+ <string name="app_settings">APP SETTINGS</string>
- <string name="sort_mode_title">Title</string>
- <string name="sort_mode_launch_count">Launch count</string>
- <string name="sort_mode_install_time">Install time</string>
+ <!-- Settings states -->
+ <string name="setting_state_on">ON</string>
+ <string name="setting_state_off">OFF</string>
+
+ <!-- Themes button -->
+ <string name="themes_button_text">Themes</string>
<string name="scrolling_page_outlines">Page outlines</string>
<string name="scrolling_fade_adjacent">Fade side pages</string>
+ <!-- Wallpaper scroll effect -->
+ <string name="scrolling_wallpaper">Scroll wallpaper</string>
- <string name="wallpaper_scroll">Scroll wallpaper</string>
-
- <!-- Settings -->
- <string name="preferences_title">Settings</string>
- <!-- Application -->
- <string name="preferences_application_title">App</string>
-
- <!-- UI -->
- <!-- Homescreen -->
- <string name="preferences_interface_homescreen_title">Homescreen</string>
- <string name="preferences_interface_homescreen_search_title">Search bar</string>
- <string name="preferences_interface_homescreen_search_summary">Show persistent search bar at top of screen</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_title">Hide icon labels</string>
- <string name="preferences_interface_homescreen_general_hide_icon_labels_summary">Hide icon labels on homescreen</string>
-
- <!-- Drawer -->
- <string name="preferences_interface_drawer_title">Drawer</string>
- <string name="preferences_interface_drawer_summary">Apps and widgets drawer</string>
- <string name="preferences_interface_drawer_apps_category">Apps</string>
- <string name="preferences_interface_drawer_hidden_apps_title">Hidden apps</string>
- <string name="preferences_interface_drawer_hidden_apps_summary">Hide apps from the drawer</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_title">Remove shortcuts</string>
- <string name="preferences_interface_drawer_hidden_apps_shortcuts_summary">Remove the shortcuts of hidden apps from the homescreen</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_title">Remove widgets</string>
- <string name="preferences_interface_drawer_hidden_apps_widgets_summary">Remove the widgets of hidden apps from the homescreen</string>
- <string name="preferences_interface_drawer_hide_icon_labels_title">Hide icon labels</string>
- <string name="preferences_interface_drawer_hide_icon_labels_summary">Hide icon labels in drawer</string>
-
- <!-- Dock -->
- <string name="preferences_interface_dock_title">Dock</string>
-
- <!-- General -->
- <string name="preferences_interface_general_title">General</string>
- <string name="preferences_interface_general_icons_category">Icons</string>
- <string name="preferences_interface_general_icons_large_title">Larger icons</string>
- <string name="preferences_interface_general_icons_large_summary">Use extra large application icons in homescreen and drawer</string>
- <string name="preferences_interface_general_icons_text_style_title">Text font style</string>
- <string name="preferences_interface_general_icons_text_style_summary">Variant and style of font to use for icon text</string>
- <string name="dialog_pick_iconpack_title">Pick icon pack</string>
- <string name="default_iconpack_title">Default icons</string>
- <string name="icon_packs_title">Icon packs</string>
- <string name="no_iconpacks_summary">No icon packs installed</string>
+ <!-- Dynamic Grid -->
+ <string name="grid_size_text">Grid size</string>
+ <string name="grid_size_comfortable">Comfortable</string>
+ <string name="grid_size_cozy">Cozy</string>
+ <string name="grid_size_condensed">Condensed</string>
+ <string name="grid_size_custom">Custom</string>
+ <string name="preferences_interface_homescreen_custom">Select custom size</string>
+ <string name="preferences_interface_homescreen_rows_title">Number of rows</string>
+ <string name="preferences_interface_homescreen_columns_title">Number of columns</string>
<!-- Folder titles -->
<string name="google_title" translatable="false">Google</string>
- <!-- Clear keyguard wallpaper tile text -->
- <string name="clear_keyguard_wallpaper">Clear</string>
+ <!-- Hidden apps -->
+ <string name="hidden_apps_title">Hidden apps</string>
- <!-- The title text for the all apps cling [CHAR_LIMIT=60] -->
- <string name="all_apps_cling_cm">Customize your drawer</string>
- <!-- The description of how to access Trebuchet settings [CHAR_LIMIT=160] -->
- <string name="all_apps_cling_summary">Tap the page indicator to view additional configuration settings</string>
+ <!-- Scroll effect -->
+ <string name="scroll_effect_text">Scroll effect</string>
- <!-- Noun, menu item used to reset hidden apps list -->
- <string name="menu_hidden_apps_delete">Reset</string>
+ <!-- Drawer sorting mode -->
+ <string name="drawer_sorting_text">Sorting mode</string>
+
+ <string name="sort_mode_title">Title</string>
+ <string name="sort_mode_launch_count">Launch count</string>
+ <string name="sort_mode_install_time">Install time</string>
+
+ <!-- Home screen search bar -->
+ <string name="home_screen_search_text">Search bar</string>
+
+ <!-- Larger icons -->
+ <string name="larger_icons_text">Larger icons</string>
+
+ <!-- Icon labels -->
+ <string name="icon_labels">Icon labels</string>
+ <string name="icon_labels_show">Show</string>
+ <string name="icon_labels_hide">Hide</string>
+
+ <!-- Protected apps -->
+ <string name="protected_app_settings">Protected apps</string>
+
+ <!-- Text for hiding/showing search screen on left (if installed) -->
+ <string name="search_screen_left_text">Search panel</string>
+
+ <!-- Toast message when search screen on left is not supported -->
+ <string name="search_screen_left_unsupported_toast">You must have a supported search app and CyanogenMod to use this feature.</string>
+
+ <!-- Dialog -->
+ <string name="dialog_confirm">Confirm</string>
- <!-- Hidden apps -->
- <string name="hidden_apps_title">Hidden apps</string>
</resources>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index dc35a3f68..434cdf9e5 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -32,9 +32,15 @@
<color name="workspace_icon_text_color">#FFF</color>
<color name="apps_customize_icon_text_color">#FFF</color>
- <color name="wallpaper_picker_translucent_gray">#66000000</color>
<color name="folder_items_text_color">#FF333333</color>
+ <color name="folder_items_glow_color">#FFCCCCCC</color>
<color name="outline_color">#FFFFFFFF</color>
-
+
<color name="first_run_cling_circle_background_color">#64b1ea</color>
+
+ <color name="settings_header_text">#FF6cd2ea</color>
+ <color name="settings_bg_color">#FF485459</color>
+ <color name="settings_bg_header_color">#FFb2b0ab</color>
+ <color name="settings_bg_selected_color">#26000000</color>
+ <color name="settings_transition_selected_color">#50000000</color>
</resources>
diff --git a/res/values/config.xml b/res/values/config.xml
index b7880fe1f..003de5ae5 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -1,4 +1,14 @@
<resources>
+<!-- Dynamic Grid -->
+ <integer name="config_dynamic_grid_max_long_edge_cell_count">6</integer>
+ <integer name="config_dynamic_grid_max_short_edge_cell_count">5</integer>
+ <integer name="config_dynamic_grid_min_edge_cell_count">3</integer>
+ <!-- Out of 100, the percent of space the overview bar should try and take vertically. -->
+ <integer name="config_dynamic_grid_overview_icon_zone_percentage">20</integer>
+ <!-- Out of 100, the percent to shrink the workspace during overview mode. -->
+ <integer name="config_dynamic_grid_overview_scale_percentage">80</integer>
+
+<!-- Miscellaneous -->
<bool name="config_largeHeap">false</bool>
<bool name="is_tablet">false</bool>
<bool name="is_large_tablet">false</bool>
@@ -19,8 +29,9 @@
<!-- Out of 100, the percent to shrink the workspace during spring loaded mode. -->
<integer name="config_workspaceSpringLoadShrinkPercentage">80</integer>
+
<!-- Out of 100, the percent to shrink the workspace during overview mode. -->
- <integer name="config_workspaceOverviewShrinkPercentage">58</integer>
+ <integer name="config_workspaceOverviewShrinkPercentage">90</integer>
<!-- Fade/zoom in/out duration & scale in the AllApps transition.
Note: This should be less than the workspaceShrinkTime as they happen together. -->
@@ -91,4 +102,7 @@
filter the activities shown in the launcher. Can be empty. -->
<string name="app_filter_class" translatable="false"></string>
+ <!-- Name of a subclass of com.android.launcher3.BuildInfo used to
+ get build information. Can be empty. -->
+ <string name="build_info_class" translatable="false"></string>
</resources>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 3b692a1d1..9641269aa 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -20,11 +20,13 @@
<dimen name="dynamic_grid_search_bar_max_width">500dp</dimen>
<dimen name="dynamic_grid_search_bar_height">48dp</dimen>
<dimen name="dynamic_grid_page_indicator_height">24dp</dimen>
-
-<!-- Wallpaper picker -->
- <dimen name="wallpaperThumbnailWidth">106.5dp</dimen>
- <dimen name="wallpaperThumbnailHeight">94.5dp</dimen>
- <dimen name="wallpaperItemIconSize">32dp</dimen>
+ <dimen name="dynamic_grid_icon_drawable_padding">4dp</dimen>
+ <dimen name="dynamic_grid_all_apps_cell_padding">18dp</dimen>
+ <dimen name="dynamic_grid_workspace_page_spacing">8dp</dimen>
+ <dimen name="dynamic_grid_overview_min_icon_zone_height">80dp</dimen>
+ <dimen name="dynamic_grid_overview_max_icon_zone_height">120dp</dimen>
+ <dimen name="dynamic_grid_overview_bar_item_width">48dp</dimen>
+ <dimen name="dynamic_grid_overview_bar_spacer_width">68dp</dimen>
<!-- Cling -->
<dimen name="clingPunchThroughGraphicCenterRadius">94dp</dimen>
@@ -36,15 +38,23 @@
<add-resource type="dimen" name="custom_cling_margin_top" />
<add-resource type="dimen" name="custom_cling_margin_right" />
<add-resource type="dimen" name="custom_cling_margin_left" />
+
+ <dimen name="cling_title_text_size">20sp</dimen>
+ <dimen name="cling_text_size">14sp</dimen>
+ <dimen name="cling_alt_title_text_size">24sp</dimen>
+ <dimen name="cling_alt_text_size">16sp</dimen>
+ <dimen name="cling_hint_text_size">14sp</dimen>
<!-- Workspace -->
<dimen name="workspace_max_gap">16dp</dimen>
<dimen name="workspace_overscroll_drawable_padding">0dp</dimen>
- <dimen name="workspace_spring_loaded_page_spacing">15dp</dimen>
<dimen name="overview_panel_top_padding">20dp</dimen>
<dimen name="overview_panel_bottom_padding">50dp</dimen>
<dimen name="overview_panel_button_spacing">30dp</dimen>
- <dimen name="overview_mode_page_offset">130dp</dimen>
+ <dimen name="overview_panel_handle_size">30dp</dimen>
+ <dimen name="overview_mode_page_offset">60dp</dimen>
+ <dimen name="sliding_panel_padding">175dp</dimen>
+ <dimen name="overview_scaling_padding">50dp</dimen>
<!-- QSB -->
<dimen name="toolbar_button_vertical_padding">4dip</dimen>
@@ -98,4 +108,17 @@
<!-- The amount that the preview contents are inset from the preview background -->
<dimen name="folder_preview_padding">4dp</dimen>
<dimen name="folder_name_padding">10dp</dimen>
+ <dimen name="folder_lock_icon">50dp</dimen>
+
+ <!-- Settings Pane dimen -->
+ <dimen name="settings_pane_handle">48dp</dimen>
+
+ <!-- Dynamic Grid settings -->
+ <dimen name="dialog_padding">10dp</dimen>
+
+ <dimen name="grid_padding">15dp</dimen>
+ <dimen name="grid_custom_text">50dp</dimen>
+
+ <dimen name="dynamic_grid_size_image_width">150dp</dimen>
+ <dimen name="dynamic_grid_size_image_height">150dp</dimen>
</resources>
diff --git a/res/values/preferences_defaults.xml b/res/values/preferences_defaults.xml
index 98d8bb7a8..64d904a0f 100644
--- a/res/values/preferences_defaults.xml
+++ b/res/values/preferences_defaults.xml
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="preferences_interface_homescreen_search_default">true</bool>
+ <bool name="preferences_interface_homescreen_search_screen_left_default">false</bool>
<string name="preferences_interface_homescreen_scrolling_transition_effect">none</string>
<bool name="preferences_interface_homescreen_scrolling_wallpaper_scroll_default">true</bool>
<bool name="preferences_interface_homescreen_scrolling_page_outlines_default">@bool/config_workspaceDefaultShowOutlines</bool>
@@ -8,10 +9,8 @@
<bool name="preferences_interface_homescreen_hide_icon_labels_default">false</bool>
<string name="preferences_interface_drawer_scrolling_transition_effect">stack</string>
<bool name="preferences_interface_drawer_scrolling_fade_adjacent_default">false</bool>
- <bool name="preferences_interface_drawer_remove_hidden_apps_shortcuts_default">false</bool>
- <bool name="preferences_interface_drawer_remove_hidden_apps_widgets_default">false</bool>
+ <bool name="preferences_interface_drawer_remove_hidden_apps_shortcuts_default">true</bool>
+ <bool name="preferences_interface_drawer_remove_hidden_apps_widgets_default">true</bool>
<bool name="preferences_interface_drawer_hide_icon_labels_default">false</bool>
<bool name="preferences_interface_general_icons_large_default">@bool/config_largeIcons</bool>
- <string name="preferences_interface_general_icons_text_font_family_default">sans-serif-condensed</string>
- <integer name="preferences_interface_general_icons_text_font_style_default">0</integer>
</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index cafa42442..9cb6c293b 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -28,30 +28,6 @@
<string name="uid_name">Android Core Apps</string>
<!-- Default folder name -->
<string name="folder_name"></string>
- <!-- Button label on Wallpaper picker screen; user selects this button to set a specific wallpaper -->
- <string name="wallpaper_instructions">Set wallpaper</string>
- <!-- Shown when wallpapers are selected in Wallpaper picker -->
- <!-- String indicating how many media item(s) is(are) selected
- eg. 1 selected [CHAR LIMIT=30] -->
- <plurals name="number_of_items_selected">
- <item quantity="zero">%1$d selected</item>
- <item quantity="one">%1$d selected</item>
- <item quantity="other">%1$d selected</item>
- </plurals>
- <!-- Accessibility string used as a label for a particular wallpaper in the Wallpaper Picker list.
- e.g. "Wallpaper 3 of 10" -->
- <string name="wallpaper_accessibility_name">Wallpaper %1$d of %2$d</string>
- <!-- Accessibility string used to announce that a wallpaper has been selected. -->
- <string name="announce_selection">Selected <xliff:g id="label" example="Wallpaper 3 of 10">%1$s</xliff:g></string>
-
- <!-- Label on button to delete wallpaper(s) -->
- <string name="wallpaper_delete">Delete</string>
- <!-- Label on button in Wallpaper Picker to pick an image -->
- <string name="pick_image">Pick image</string>
- <!-- Option in "Select wallpaper from" dialog box -->
- <string name="pick_wallpaper">Wallpapers</string>
- <!-- Title of activity for cropping wallpapers -->
- <string name="crop_wallpaper">Crop wallpaper</string>
<!-- Displayed when user selects a shortcut for an app that was uninstalled [CHAR_LIMIT=none]-->
<string name="activity_not_found">App isn\'t installed.</string>
<!-- Labels for the tabs in the customize drawer -->
@@ -109,9 +85,9 @@ s -->
<!-- Error message when user has filled a home screen -->
<string name="out_of_space">No more room on this Home screen.</string>
<!-- Error message when user has filled the hotseat -->
- <string name="hotseat_out_of_space">No more room on the hotseat.</string>
+ <string name="hotseat_out_of_space">No more room in the Favorites tray</string>
<!-- Error message when user tries to drop an invalid item on the hotseat -->
- <string name="invalid_hotseat_item">This widget is too large for the hotseat.</string>
+ <string name="invalid_hotseat_item">This widget is too large for the Favorites tray</string>
<!-- Message displayed when a shortcut is created by an external application -->
<string name="shortcut_installed">Shortcut \"<xliff:g id="name" example="Browser">%s</xliff:g>\" created.</string>
<!-- Message displayed when a shortcut is uninstalled by an external application -->
@@ -230,8 +206,8 @@ s -->
<string name="apps_customize_widgets_scroll_format">Widgets page %1$d of %2$d</string>
<!-- Clings -->
- <!-- The title text for the workspace cling [CHAR_LIMIT=60] -->
- <string name="first_run_cling_title">Welcome!</string>
+ <!-- The title text for the workspace cling [CHAR_LIMIT=30] -->
+ <string name="first_run_cling_title">Welcome</string>
<!-- The description of how to use the workspace [CHAR_LIMIT=60] -->
<string name="first_run_cling_description">Make yourself at home.</string>
<!-- The description of how to use the workspace [CHAR_LIMIT=60] -->
@@ -240,17 +216,21 @@ s -->
<string name="first_run_cling_search_bar_hint"></string>
<!-- The description of how to use the workspace [CHAR_LIMIT=60] -->
<string name="first_run_cling_create_screens_hint">Create more screens for apps and folders</string>
- <!-- The title text for the workspace cling [CHAR_LIMIT=60] -->
+ <!-- The title text for the migration cling [CHAR_LIMIT=30] -->
+ <string name="migration_cling_title">Copy your app icons</string>
+ <!-- The description of what migration does [CHAR_LIMIT=70] -->
+ <string name="migration_cling_description">Import icons and folders from your old Home screens?</string>
+ <!-- The description of the button to migrate apps from another launcher [CHAR_LIMIT=30] -->
+ <string name="migration_cling_copy_apps">COPY ICONS</string>
+ <!-- The description of the button to use the default launcher layout [CHAR_LIMIT=30] -->
+ <string name="migration_cling_use_default">START FRESH</string>
+ <!-- The title text for the workspace cling [CHAR_LIMIT=30] -->
<string name="workspace_cling_title">Organize your space</string>
- <!-- The description of how to use the workspace [CHAR_LIMIT=160] -->
+ <!-- The description of how to use the workspace [CHAR_LIMIT=70] -->
<string name="workspace_cling_move_item">Touch &amp; hold background to manage wallpaper, widgets and settings.</string>
- <!-- The title text for the All Apps cling [CHAR_LIMIT=60] -->
- <string name="all_apps_cling_title">Choose some apps</string>
- <!-- The description of how to pick up and add an item to the workspace [CHAR_LIMIT=160] -->
- <string name="all_apps_cling_add_item">To add an app to your Home screen, touch &amp; hold it.</string>
- <!-- The title text for the Folder cling [CHAR_LIMIT=60] -->
+ <!-- The title text for the Folder cling [CHAR_LIMIT=30] -->
<string name="folder_cling_title">Here\'s a folder</string>
- <!-- The description of how to create a folder [CHAR_LIMIT=160] -->
+ <!-- The description of how to create a folder [CHAR_LIMIT=70] -->
<string name="folder_cling_create_folder">To create one like this, touch &amp; hold an app, then move it over another.</string>
<!-- The text on the button to dismiss a cling [CHAR_LIMIT=30] -->
<string name="cling_dismiss">OK</string>
@@ -272,18 +252,6 @@ s -->
<!-- Folder name format -->
<string name="folder_name_format">Folder: <xliff:g id="name" example="Games">%1$s</xliff:g></string>
- <!-- Strings used in device overlays -->
-
- <!-- Clings -->
- <!-- Dummy string [CHAR_LIMIT=40] -->
- <string name="custom_workspace_cling_title_1"></string>
- <!-- Dummy string [CHAR_LIMIT=60] -->
- <string name="custom_workspace_cling_description_1"></string>
- <!-- Dummy string [CHAR_LIMIT=40] -->
- <string name="custom_workspace_cling_title_2"></string>
- <!-- Dummy string [CHAR_LIMIT=60] -->
- <string name="custom_workspace_cling_description_2"></string>
-
<!-- Debug-only activity name. [DO NOT TRANSLATE] -->
<string name="debug_memory_activity">* HPROF</string>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index a1d2c5ccf..c18dccbab 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -18,30 +18,13 @@
-->
<resources>
- <style name="Theme.WallpaperCropper" parent="@android:style/Theme.Holo">
- <item name="android:actionBarStyle">@style/WallpaperCropperActionBar</item>
- <item name="android:windowFullscreen">true</item>
- <item name="android:windowActionBarOverlay">true</item>
- <item name="android:windowTranslucentNavigation">true</item>
- </style>
-
- <style name="WallpaperCropperActionBar" parent="android:style/Widget.Holo.ActionBar">
- <item name="android:displayOptions">showCustom</item>
- <item name="android:background">#88000000</item>
- </style>
-
- <style name="Theme" parent="@android:style/Theme.Holo.Wallpaper.NoTitleBar">
- <item name="android:windowTranslucentStatus">true</item>
- <item name="android:windowTranslucentNavigation">true</item>
- </style>
-
<style name="ClingButton">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:paddingTop">15dp</item>
<item name="android:paddingBottom">15dp</item>
- <item name="android:paddingStart">50dp</item>
- <item name="android:paddingEnd">50dp</item>
+ <item name="android:paddingLeft">50dp</item>
+ <item name="android:paddingRight">50dp</item>
<item name="android:text">@string/cling_dismiss</item>
<item name="android:textColor">#ffffff</item>
<item name="android:textStyle">bold</item>
@@ -52,27 +35,33 @@
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_marginBottom">5dp</item>
- <item name="android:textSize">22sp</item>
+ <item name="android:textSize">@dimen/cling_title_text_size</item>
<item name="android:textColor">#ffffff</item>
<item name="android:fontFamily">sans-serif-condensed</item>
</style>
+ <style name="ClingText">
+ <item name="android:layout_width">wrap_content</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:textSize">@dimen/cling_text_size</item>
+ <item name="android:textColor">#80000000</item>
+ <item name="android:lineSpacingMultiplier">1.1</item>
+ </style>
<style name="ClingAltTitleText">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
- <item name="android:textSize">24sp</item>
+ <item name="android:textSize">@dimen/cling_alt_title_text_size</item>
<item name="android:textColor">#49C0EC</item>
</style>
- <style name="ClingText">
+ <style name="ClingAltText">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
- <item name="android:textSize">16sp</item>
- <item name="android:textColor">#80000000</item>
- <item name="android:lineSpacingMultiplier">1.1</item>
+ <item name="android:textSize">@dimen/cling_alt_text_size</item>
+ <item name="android:textColor">#49C0EC</item>
</style>
<style name="ClingHintText">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
- <item name="android:textSize">18sp</item>
+ <item name="android:textSize">@dimen/cling_hint_text_size</item>
<item name="android:textColor">#80ffffff</item>
<item name="android:fontFamily">sans-serif-condensed</item>
</style>
@@ -98,14 +87,10 @@
<style name="WorkspaceIcon.AppsCustomize">
<item name="android:background">@null</item>
<item name="android:textColor">@color/apps_customize_icon_text_color</item>
- <item name="android:drawablePadding">4dp</item>
+ <item name="android:drawablePadding">@dimen/dynamic_grid_icon_drawable_padding</item>
<item name="android:shadowRadius">4.0</item>
<item name="android:shadowColor">#FF000000</item>
</style>
-
- <style name="QSBBar">
- <item name="android:orientation">horizontal</item>
- </style>
<style name="SearchDropTargetBar">
</style>
<style name="SearchButton">
@@ -120,8 +105,8 @@
<item name="android:layout_gravity">center</item>
<item name="android:gravity">center_vertical</item>
<item name="android:drawablePadding">7.5dp</item>
- <item name="android:paddingStart">25dp</item>
- <item name="android:paddingEnd">25dp</item>
+ <item name="android:paddingLeft">25dp</item>
+ <item name="android:paddingRight">25dp</item>
<item name="android:textColor">#FFFFFFFF</item>
<item name="android:textSize">16sp</item>
<item name="android:singleLine">true</item>
@@ -136,8 +121,8 @@
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">match_parent</item>
<item name="android:gravity">center</item>
- <item name="android:paddingStart">20dp</item>
- <item name="android:paddingEnd">20dp</item>
+ <item name="android:paddingLeft">20dp</item>
+ <item name="android:paddingRight">20dp</item>
<item name="android:background">@drawable/tab_widget_indicator_selector</item>
<item name="android:textColor">?android:attr/textColorPrimary</item>
<item name="android:textSize">12sp</item>
@@ -151,8 +136,8 @@
</style>
<style name="MarketButton">
- <item name="android:paddingStart">5dp</item>
- <item name="android:paddingEnd">5dp</item>
+ <item name="android:paddingLeft">5dp</item>
+ <item name="android:paddingRight">5dp</item>
<item name="android:textColor">@color/workspace_all_apps_and_delete_zone_text_color</item>
<item name="android:textSize">18sp</item>
<item name="android:shadowColor">@color/workspace_all_apps_and_delete_zone_text_shadow_color</item>
@@ -166,4 +151,10 @@
</style>
<style name="CustomClingText">
</style>
+ <style name="PagedViewWidgetImageView">
+ <item name="android:paddingLeft">@dimen/app_widget_preview_padding_left</item>
+ </style>
+ <style name="SearchButton.WithPaddingStart">
+ <item name="android:paddingLeft">8dp</item>
+ </style>
</resources>
diff --git a/res/xml-sw600dp/default_workspace.xml b/res/xml-sw600dp/default_workspace.xml
index 64896f245..b8034e320 100644
--- a/res/xml-sw600dp/default_workspace.xml
+++ b/res/xml-sw600dp/default_workspace.xml
@@ -26,37 +26,6 @@
launcher:spanX="5"
launcher:spanY="3" />
<favorite
- launcher:packageName="com.android.vending"
- launcher:className="com.android.vending.AssetBrowserActivity"
- launcher:container="-100"
- launcher:screen="1"
- launcher:x="4"
- launcher:y="4" />
- <folder
- launcher:screen="1"
- launcher:x="0"
- launcher:y="4"
- launcher:title="@string/google_title">
- <favorite
- launcher:className="com.google.android.maps.MapsActivity"
- launcher:packageName="com.google.android.apps.maps" />
- <favorite
- launcher:className="com.google.android.gm.GmailActivity"
- launcher:packageName="com.google.android.gm" />
- <favorite
- launcher:className="com.google.android.apps.plus.phone.HomeActivity"
- launcher:packageName="com.google.android.apps.plus" />
- <favorite
- launcher:className="com.android.calendar.AllInOneActivity"
- launcher:packageName="com.google.android.calendar" />
- <favorite
- launcher:className="com.google.android.maps.driveabout.app.DestinationActivity"
- launcher:packageName="com.google.android.apps.maps" />
- <favorite
- launcher:className="com.google.android.apps.plus.phone.ConversationListActivity"
- launcher:packageName="com.google.android.apps.plus" />
- </folder>
- <favorite
launcher:packageName="com.andrew.apollo"
launcher:className="com.andrew.apollo.ui.activities.HomeActivity"
launcher:screen="1"
@@ -71,13 +40,6 @@
<!-- Screen [2] -->
<favorite
- launcher:packageName="com.cyanogenmod.gallerynext"
- launcher:className="com.cyanogenmod.gallerynext.app.GalleryActivity"
- launcher:container="-100"
- launcher:screen="2"
- launcher:x="0"
- launcher:y="4" />
- <favorite
launcher:packageName="com.android.gallery3d"
launcher:className="com.android.gallery3d.app.Gallery"
launcher:container="-100"
@@ -92,15 +54,6 @@
launcher:x="4"
launcher:y="4" />
<appwidget
- launcher:packageName="com.android.vending"
- launcher:className="com.google.android.finsky.widget.consumption.NowPlayingWidgetProvider"
- launcher:container="-100"
- launcher:screen="2"
- launcher:x="0"
- launcher:y="0"
- launcher:spanX="5"
- launcher:spanY="4" />
- <appwidget
launcher:packageName="com.android.mms"
launcher:className="com.android.mms.widget.MmsWidgetProvider"
launcher:container="-100"
@@ -112,13 +65,6 @@
<!-- Hotseat -->
<favorite
- launcher:packageName="com.google.android.talk"
- launcher:className="com.google.android.talk.SigningInActivity"
- launcher:container="-101"
- launcher:screen="4"
- launcher:x="4"
- launcher:y="0" />
- <favorite
launcher:packageName="com.android.mms"
launcher:className="com.android.mms.ui.ConversationList"
launcher:container="-101"
@@ -126,13 +72,6 @@
launcher:x="4"
launcher:y="0" />
<favorite
- launcher:packageName="com.android.chrome"
- launcher:className="com.google.android.apps.chrome.Main"
- launcher:container="-101"
- launcher:screen="5"
- launcher:x="5"
- launcher:y="0" />
- <favorite
launcher:packageName="com.android.browser"
launcher:className="com.android.browser.BrowserActivity"
launcher:container="-101"
@@ -140,13 +79,6 @@
launcher:x="5"
launcher:y="0" />
<favorite
- launcher:packageName="com.google.android.music"
- launcher:className="com.android.music.activitymanagement.TopLevelActivity"
- launcher:container="-101"
- launcher:screen="2"
- launcher:x="2"
- launcher:y="0" />
- <favorite
launcher:packageName="com.android.camera2"
launcher:className="com.android.camera.CameraLauncher"
launcher:container="-101"
@@ -154,13 +86,6 @@
launcher:x="2"
launcher:y="0" />
<favorite
- launcher:packageName="com.google.android.youtube"
- launcher:className="com.google.android.youtube.app.honeycomb.Shell$HomeActivity"
- launcher:container="-101"
- launcher:screen="1"
- launcher:x="1"
- launcher:y="0" />
- <favorite
launcher:packageName="com.android.contacts"
launcher:className="com.android.contacts.activities.PeopleActivity"
launcher:container="-101"
diff --git a/res/xml-sw600dp/default_workspace_gapps.xml b/res/xml-sw600dp/default_workspace_gapps.xml
new file mode 100644
index 000000000..8be9f421d
--- /dev/null
+++ b/res/xml-sw600dp/default_workspace_gapps.xml
@@ -0,0 +1,171 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2013-2014 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<favorites xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher3">
+ <!-- Screen [1] -->
+ <appwidget
+ launcher:packageName="com.cyanogenmod.lockclock"
+ launcher:className="com.cyanogenmod.lockclock.ClockWidgetProvider"
+ launcher:container="-100"
+ launcher:screen="1"
+ launcher:x="0"
+ launcher:y="0"
+ launcher:spanX="5"
+ launcher:spanY="3" />
+ <favorite
+ launcher:packageName="com.android.vending"
+ launcher:className="com.android.vending.AssetBrowserActivity"
+ launcher:container="-100"
+ launcher:screen="1"
+ launcher:x="4"
+ launcher:y="4" />
+ <folder
+ launcher:screen="1"
+ launcher:x="0"
+ launcher:y="4"
+ launcher:title="@string/google_title">
+ <favorite
+ launcher:className="com.google.android.maps.MapsActivity"
+ launcher:packageName="com.google.android.apps.maps" />
+ <favorite
+ launcher:className="com.google.android.gm.ConversationListActivityGmail"
+ launcher:packageName="com.google.android.gm" />
+ <favorite
+ launcher:className="com.google.android.apps.plus.phone.HomeActivity"
+ launcher:packageName="com.google.android.apps.plus" />
+ <favorite
+ launcher:className="com.android.calendar.AllInOneActivity"
+ launcher:packageName="com.google.android.calendar" />
+ <favorite
+ launcher:className="com.google.android.maps.driveabout.app.DestinationActivity"
+ launcher:packageName="com.google.android.apps.maps" />
+ <favorite
+ launcher:className="com.google.android.apps.plus.phone.ConversationListActivity"
+ launcher:packageName="com.google.android.apps.plus" />
+ </folder>
+ <favorite
+ launcher:packageName="com.andrew.apollo"
+ launcher:className="com.andrew.apollo.ui.activities.HomeActivity"
+ launcher:screen="1"
+ launcher:x="0"
+ launcher:y="4" />
+ <favorite
+ launcher:packageName="com.bel.android.dspmanager"
+ launcher:className="com.bel.android.dspmanager.activity.DSPManager"
+ launcher:screen="1"
+ launcher:x="4"
+ launcher:y="4" />
+
+ <!-- Screen [2] -->
+ <favorite
+ launcher:packageName="com.cyngn.gallerynext"
+ launcher:className="com.cyngn.gallerynext.app.GalleryActivity"
+ launcher:container="-100"
+ launcher:screen="2"
+ launcher:x="0"
+ launcher:y="4" />
+ <favorite
+ launcher:packageName="com.android.gallery3d"
+ launcher:className="com.android.gallery3d.app.Gallery"
+ launcher:container="-100"
+ launcher:screen="2"
+ launcher:x="0"
+ launcher:y="4" />
+ <favorite
+ launcher:packageName="com.android.settings"
+ launcher:className="com.android.settings.Settings"
+ launcher:container="-100"
+ launcher:screen="2"
+ launcher:x="4"
+ launcher:y="4" />
+ <appwidget
+ launcher:packageName="com.android.vending"
+ launcher:className="com.google.android.finsky.widget.consumption.NowPlayingWidgetProvider"
+ launcher:container="-100"
+ launcher:screen="2"
+ launcher:x="0"
+ launcher:y="0"
+ launcher:spanX="5"
+ launcher:spanY="4" />
+ <appwidget
+ launcher:packageName="com.android.mms"
+ launcher:className="com.android.mms.widget.MmsWidgetProvider"
+ launcher:container="-100"
+ launcher:screen="2"
+ launcher:x="0"
+ launcher:y="0"
+ launcher:spanX="5"
+ launcher:spanY="2" />
+
+ <!-- Hotseat -->
+ <favorite
+ launcher:packageName="com.google.android.talk"
+ launcher:className="com.google.android.talk.SigningInActivity"
+ launcher:container="-101"
+ launcher:screen="4"
+ launcher:x="4"
+ launcher:y="0" />
+ <favorite
+ launcher:packageName="com.android.mms"
+ launcher:className="com.android.mms.ui.ConversationList"
+ launcher:container="-101"
+ launcher:screen="4"
+ launcher:x="4"
+ launcher:y="0" />
+ <favorite
+ launcher:packageName="com.android.chrome"
+ launcher:className="com.google.android.apps.chrome.Main"
+ launcher:container="-101"
+ launcher:screen="5"
+ launcher:x="5"
+ launcher:y="0" />
+ <favorite
+ launcher:packageName="com.android.browser"
+ launcher:className="com.android.browser.BrowserActivity"
+ launcher:container="-101"
+ launcher:screen="5"
+ launcher:x="5"
+ launcher:y="0" />
+ <favorite
+ launcher:packageName="com.google.android.music"
+ launcher:className="com.android.music.activitymanagement.TopLevelActivity"
+ launcher:container="-101"
+ launcher:screen="2"
+ launcher:x="2"
+ launcher:y="0" />
+ <favorite
+ launcher:packageName="com.android.camera2"
+ launcher:className="com.android.camera.CameraLauncher"
+ launcher:container="-101"
+ launcher:screen="2"
+ launcher:x="2"
+ launcher:y="0" />
+ <favorite
+ launcher:packageName="com.google.android.youtube"
+ launcher:className="com.google.android.youtube.app.honeycomb.Shell$HomeActivity"
+ launcher:container="-101"
+ launcher:screen="1"
+ launcher:x="1"
+ launcher:y="0" />
+ <favorite
+ launcher:packageName="com.android.contacts"
+ launcher:className="com.android.contacts.activities.PeopleActivity"
+ launcher:container="-101"
+ launcher:screen="1"
+ launcher:x="1"
+ launcher:y="0" />
+
+</favorites>
diff --git a/res/xml-sw600dp/default_workspace_no_telephony.xml b/res/xml-sw600dp/default_workspace_no_telephony.xml
index fb81f178b..522640a4d 100644
--- a/res/xml-sw600dp/default_workspace_no_telephony.xml
+++ b/res/xml-sw600dp/default_workspace_no_telephony.xml
@@ -26,37 +26,6 @@
launcher:spanX="5"
launcher:spanY="3" />
<favorite
- launcher:packageName="com.android.vending"
- launcher:className="com.android.vending.AssetBrowserActivity"
- launcher:container="-100"
- launcher:screen="1"
- launcher:x="4"
- launcher:y="4" />
- <folder
- launcher:screen="1"
- launcher:x="0"
- launcher:y="4"
- launcher:title="@string/google_title">
- <favorite
- launcher:className="com.google.android.maps.MapsActivity"
- launcher:packageName="com.google.android.apps.maps" />
- <favorite
- launcher:className="com.google.android.gm.GmailActivity"
- launcher:packageName="com.google.android.gm" />
- <favorite
- launcher:className="com.google.android.apps.plus.phone.HomeActivity"
- launcher:packageName="com.google.android.apps.plus" />
- <favorite
- launcher:className="com.android.calendar.AllInOneActivity"
- launcher:packageName="com.google.android.calendar" />
- <favorite
- launcher:className="com.google.android.maps.driveabout.app.DestinationActivity"
- launcher:packageName="com.google.android.apps.maps" />
- <favorite
- launcher:className="com.google.android.apps.plus.phone.ConversationListActivity"
- launcher:packageName="com.google.android.apps.plus" />
- </folder>
- <favorite
launcher:packageName="com.andrew.apollo"
launcher:className="com.andrew.apollo.ui.activities.HomeActivity"
launcher:screen="1"
@@ -71,13 +40,6 @@
<!-- Screen [2] -->
<favorite
- launcher:packageName="com.cyanogenmod.gallerynext"
- launcher:className="com.cyanogenmod.gallerynext.app.GalleryActivity"
- launcher:container="-100"
- launcher:screen="2"
- launcher:x="0"
- launcher:y="4" />
- <favorite
launcher:packageName="com.android.gallery3d"
launcher:className="com.android.gallery3d.app.Gallery"
launcher:container="-100"
@@ -92,15 +54,6 @@
launcher:x="4"
launcher:y="4" />
<appwidget
- launcher:packageName="com.android.vending"
- launcher:className="com.google.android.finsky.widget.consumption.NowPlayingWidgetProvider"
- launcher:container="-100"
- launcher:screen="2"
- launcher:x="0"
- launcher:y="0"
- launcher:spanX="5"
- launcher:spanY="4"/>
- <appwidget
launcher:packageName="com.android.settings"
launcher:className="com.android.settings.widget.SettingsAppWidgetProvider"
launcher:container="-100"
@@ -112,13 +65,6 @@
<!-- Hotseat -->
<favorite
- launcher:packageName="com.google.android.talk"
- launcher:className="com.google.android.talk.SigningInActivity"
- launcher:container="-101"
- launcher:screen="4"
- launcher:x="4"
- launcher:y="0" />
- <favorite
launcher:packageName="com.android.email"
launcher:className="com.android.email.activity.Welcome"
launcher:container="-101"
@@ -126,13 +72,6 @@
launcher:x="4"
launcher:y="0" />
<favorite
- launcher:packageName="com.android.chrome"
- launcher:className="com.google.android.apps.chrome.Main"
- launcher:container="-101"
- launcher:screen="5"
- launcher:x="5"
- launcher:y="0" />
- <favorite
launcher:packageName="com.android.browser"
launcher:className="com.android.browser.BrowserActivity"
launcher:container="-101"
@@ -140,13 +79,6 @@
launcher:x="5"
launcher:y="0" />
<favorite
- launcher:packageName="com.google.android.music"
- launcher:className="com.android.music.activitymanagement.TopLevelActivity"
- launcher:container="-101"
- launcher:screen="2"
- launcher:x="2"
- launcher:y="0" />
- <favorite
launcher:packageName="com.android.camera2"
launcher:className="com.android.camera.CameraLauncher"
launcher:container="-101"
@@ -154,13 +86,6 @@
launcher:x="2"
launcher:y="0" />
<favorite
- launcher:packageName="com.google.android.youtube"
- launcher:className="com.google.android.youtube.app.honeycomb.Shell$HomeActivity"
- launcher:container="-101"
- launcher:screen="1"
- launcher:x="1"
- launcher:y="0" />
- <favorite
launcher:packageName="com.android.contacts"
launcher:className="com.android.contacts.activities.PeopleActivity"
launcher:container="-101"
diff --git a/res/xml-sw600dp/default_workspace_no_telephony_gapps.xml b/res/xml-sw600dp/default_workspace_no_telephony_gapps.xml
new file mode 100644
index 000000000..ba1dfbc86
--- /dev/null
+++ b/res/xml-sw600dp/default_workspace_no_telephony_gapps.xml
@@ -0,0 +1,171 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2013-2014 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<favorites xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher3">
+ <!-- Screen [1] -->
+ <appwidget
+ launcher:packageName="com.cyanogenmod.lockclock"
+ launcher:className="com.cyanogenmod.lockclock.ClockWidgetProvider"
+ launcher:container="-100"
+ launcher:screen="1"
+ launcher:x="0"
+ launcher:y="0"
+ launcher:spanX="5"
+ launcher:spanY="3" />
+ <favorite
+ launcher:packageName="com.android.vending"
+ launcher:className="com.android.vending.AssetBrowserActivity"
+ launcher:container="-100"
+ launcher:screen="1"
+ launcher:x="4"
+ launcher:y="4" />
+ <folder
+ launcher:screen="1"
+ launcher:x="0"
+ launcher:y="4"
+ launcher:title="@string/google_title">
+ <favorite
+ launcher:className="com.google.android.maps.MapsActivity"
+ launcher:packageName="com.google.android.apps.maps" />
+ <favorite
+ launcher:className="com.google.android.gm.ConversationListActivityGmail"
+ launcher:packageName="com.google.android.gm" />
+ <favorite
+ launcher:className="com.google.android.apps.plus.phone.HomeActivity"
+ launcher:packageName="com.google.android.apps.plus" />
+ <favorite
+ launcher:className="com.android.calendar.AllInOneActivity"
+ launcher:packageName="com.google.android.calendar" />
+ <favorite
+ launcher:className="com.google.android.maps.driveabout.app.DestinationActivity"
+ launcher:packageName="com.google.android.apps.maps" />
+ <favorite
+ launcher:className="com.google.android.apps.plus.phone.ConversationListActivity"
+ launcher:packageName="com.google.android.apps.plus" />
+ </folder>
+ <favorite
+ launcher:packageName="com.andrew.apollo"
+ launcher:className="com.andrew.apollo.ui.activities.HomeActivity"
+ launcher:screen="1"
+ launcher:x="0"
+ launcher:y="4" />
+ <favorite
+ launcher:packageName="com.bel.android.dspmanager"
+ launcher:className="com.bel.android.dspmanager.activity.DSPManager"
+ launcher:screen="1"
+ launcher:x="4"
+ launcher:y="4" />
+
+ <!-- Screen [2] -->
+ <favorite
+ launcher:packageName="com.cyngn.gallerynext"
+ launcher:className="com.cyngn.gallerynext.app.GalleryActivity"
+ launcher:container="-100"
+ launcher:screen="2"
+ launcher:x="0"
+ launcher:y="4" />
+ <favorite
+ launcher:packageName="com.android.gallery3d"
+ launcher:className="com.android.gallery3d.app.Gallery"
+ launcher:container="-100"
+ launcher:screen="2"
+ launcher:x="0"
+ launcher:y="4" />
+ <favorite
+ launcher:packageName="com.android.settings"
+ launcher:className="com.android.settings.Settings"
+ launcher:container="-100"
+ launcher:screen="2"
+ launcher:x="4"
+ launcher:y="4" />
+ <appwidget
+ launcher:packageName="com.android.vending"
+ launcher:className="com.google.android.finsky.widget.consumption.NowPlayingWidgetProvider"
+ launcher:container="-100"
+ launcher:screen="2"
+ launcher:x="0"
+ launcher:y="0"
+ launcher:spanX="5"
+ launcher:spanY="4"/>
+ <appwidget
+ launcher:packageName="com.android.settings"
+ launcher:className="com.android.settings.widget.SettingsAppWidgetProvider"
+ launcher:container="-100"
+ launcher:screen="2"
+ launcher:x="0"
+ launcher:y="0"
+ launcher:spanX="5"
+ launcher:spanY="1" />
+
+ <!-- Hotseat -->
+ <favorite
+ launcher:packageName="com.google.android.talk"
+ launcher:className="com.google.android.talk.SigningInActivity"
+ launcher:container="-101"
+ launcher:screen="4"
+ launcher:x="4"
+ launcher:y="0" />
+ <favorite
+ launcher:packageName="com.android.email"
+ launcher:className="com.android.email.activity.Welcome"
+ launcher:container="-101"
+ launcher:screen="4"
+ launcher:x="4"
+ launcher:y="0" />
+ <favorite
+ launcher:packageName="com.android.chrome"
+ launcher:className="com.google.android.apps.chrome.Main"
+ launcher:container="-101"
+ launcher:screen="5"
+ launcher:x="5"
+ launcher:y="0" />
+ <favorite
+ launcher:packageName="com.android.browser"
+ launcher:className="com.android.browser.BrowserActivity"
+ launcher:container="-101"
+ launcher:screen="5"
+ launcher:x="5"
+ launcher:y="0" />
+ <favorite
+ launcher:packageName="com.google.android.music"
+ launcher:className="com.android.music.activitymanagement.TopLevelActivity"
+ launcher:container="-101"
+ launcher:screen="2"
+ launcher:x="2"
+ launcher:y="0" />
+ <favorite
+ launcher:packageName="com.android.camera2"
+ launcher:className="com.android.camera.CameraLauncher"
+ launcher:container="-101"
+ launcher:screen="2"
+ launcher:x="2"
+ launcher:y="0" />
+ <favorite
+ launcher:packageName="com.google.android.youtube"
+ launcher:className="com.google.android.youtube.app.honeycomb.Shell$HomeActivity"
+ launcher:container="-101"
+ launcher:screen="1"
+ launcher:x="1"
+ launcher:y="0" />
+ <favorite
+ launcher:packageName="com.android.contacts"
+ launcher:className="com.android.contacts.activities.PeopleActivity"
+ launcher:container="-101"
+ launcher:screen="1"
+ launcher:x="1"
+ launcher:y="0" />
+
+</favorites>
diff --git a/res/xml-sw720dp/default_workspace.xml b/res/xml-sw720dp/default_workspace.xml
index e9231cc37..85920d732 100644
--- a/res/xml-sw720dp/default_workspace.xml
+++ b/res/xml-sw720dp/default_workspace.xml
@@ -26,37 +26,6 @@
launcher:spanX="6"
launcher:spanY="3" />
<favorite
- launcher:packageName="com.android.vending"
- launcher:className="com.android.vending.AssetBrowserActivity"
- launcher:container="-100"
- launcher:screen="1"
- launcher:x="7"
- launcher:y="4" />
- <folder
- launcher:screen="1"
- launcher:x="0"
- launcher:y="4"
- launcher:title="@string/google_title">
- <favorite
- launcher:className="com.google.android.maps.MapsActivity"
- launcher:packageName="com.google.android.apps.maps" />
- <favorite
- launcher:className="com.google.android.gm.GmailActivity"
- launcher:packageName="com.google.android.gm" />
- <favorite
- launcher:className="com.google.android.apps.plus.phone.HomeActivity"
- launcher:packageName="com.google.android.apps.plus" />
- <favorite
- launcher:className="com.android.calendar.AllInOneActivity"
- launcher:packageName="com.google.android.calendar" />
- <favorite
- launcher:className="com.google.android.maps.driveabout.app.DestinationActivity"
- launcher:packageName="com.google.android.apps.maps" />
- <favorite
- launcher:className="com.google.android.apps.plus.phone.ConversationListActivity"
- launcher:packageName="com.google.android.apps.plus" />
- </folder>
- <favorite
launcher:packageName="com.bel.android.dspmanager"
launcher:className="com.bel.android.dspmanager.activity.DSPManager"
launcher:screen="1"
@@ -71,13 +40,6 @@
<!-- Screen [2] -->
<favorite
- launcher:packageName="com.cyanogenmod.gallerynext"
- launcher:className="com.cyanogenmod.gallerynext.app.GalleryActivity"
- launcher:container="-100"
- launcher:screen="2"
- launcher:x="0"
- launcher:y="4" />
- <favorite
launcher:packageName="com.android.gallery3d"
launcher:className="com.android.gallery3d.app.Gallery"
launcher:container="-100"
@@ -92,15 +54,6 @@
launcher:x="7"
launcher:y="4" />
<appwidget
- launcher:packageName="com.android.vending"
- launcher:className="com.google.android.finsky.widget.consumption.NowPlayingWidgetProvider"
- launcher:container="-100"
- launcher:screen="2"
- launcher:x="1"
- launcher:y="0"
- launcher:spanX="6"
- launcher:spanY="4"/>
- <appwidget
launcher:packageName="com.android.mms"
launcher:className="com.android.mms.widget.MmsWidgetProvider"
launcher:screen="2"
@@ -111,13 +64,6 @@
<!-- Hotseat -->
<favorite
- launcher:packageName="com.google.android.talk"
- launcher:className="com.google.android.talk.SigningInActivity"
- launcher:container="-101"
- launcher:screen="5"
- launcher:x="5"
- launcher:y="0" />
- <favorite
launcher:packageName="com.android.mms"
launcher:className="com.android.mms.ui.ConversationList"
launcher:container="-101"
@@ -125,13 +71,6 @@
launcher:x="5"
launcher:y="0" />
<favorite
- launcher:packageName="com.android.chrome"
- launcher:className="com.google.android.apps.chrome.Main"
- launcher:container="-101"
- launcher:screen="6"
- launcher:x="6"
- launcher:y="0" />
- <favorite
launcher:packageName="com.android.browser"
launcher:className="com.android.browser.BrowserActivity"
launcher:container="-101"
@@ -139,13 +78,6 @@
launcher:x="6"
launcher:y="0" />
<favorite
- launcher:packageName="com.google.android.music"
- launcher:className="com.android.music.activitymanagement.TopLevelActivity"
- launcher:container="-101"
- launcher:screen="3"
- launcher:x="3"
- launcher:y="0" />
- <favorite
launcher:packageName="com.android.camera2"
launcher:className="com.android.camera.CameraLauncher"
launcher:container="-101"
@@ -153,13 +85,6 @@
launcher:x="3"
launcher:y="0" />
<favorite
- launcher:packageName="com.google.android.youtube"
- launcher:className="com.google.android.youtube.app.honeycomb.Shell$HomeActivity"
- launcher:container="-101"
- launcher:screen="2"
- launcher:x="2"
- launcher:y="0" />
- <favorite
launcher:packageName="com.android.contacts"
launcher:className="com.android.contacts.activities.PeopleActivity"
launcher:container="-101"
diff --git a/res/xml-sw720dp/default_workspace_gapps.xml b/res/xml-sw720dp/default_workspace_gapps.xml
new file mode 100644
index 000000000..2a65712cc
--- /dev/null
+++ b/res/xml-sw720dp/default_workspace_gapps.xml
@@ -0,0 +1,170 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2013-2014 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<favorites xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher3">
+ <!-- Screen [1] -->
+ <appwidget
+ launcher:packageName="com.cyanogenmod.lockclock"
+ launcher:className="com.cyanogenmod.lockclock.ClockWidgetProvider"
+ launcher:container="-100"
+ launcher:screen="1"
+ launcher:x="1"
+ launcher:y="0"
+ launcher:spanX="6"
+ launcher:spanY="3" />
+ <favorite
+ launcher:packageName="com.android.vending"
+ launcher:className="com.android.vending.AssetBrowserActivity"
+ launcher:container="-100"
+ launcher:screen="1"
+ launcher:x="7"
+ launcher:y="4" />
+ <folder
+ launcher:screen="1"
+ launcher:x="0"
+ launcher:y="4"
+ launcher:title="@string/google_title">
+ <favorite
+ launcher:className="com.google.android.maps.MapsActivity"
+ launcher:packageName="com.google.android.apps.maps" />
+ <favorite
+ launcher:className="com.google.android.gm.ConversationListActivityGmail"
+ launcher:packageName="com.google.android.gm" />
+ <favorite
+ launcher:className="com.google.android.apps.plus.phone.HomeActivity"
+ launcher:packageName="com.google.android.apps.plus" />
+ <favorite
+ launcher:className="com.android.calendar.AllInOneActivity"
+ launcher:packageName="com.google.android.calendar" />
+ <favorite
+ launcher:className="com.google.android.maps.driveabout.app.DestinationActivity"
+ launcher:packageName="com.google.android.apps.maps" />
+ <favorite
+ launcher:className="com.google.android.apps.plus.phone.ConversationListActivity"
+ launcher:packageName="com.google.android.apps.plus" />
+ </folder>
+ <favorite
+ launcher:packageName="com.bel.android.dspmanager"
+ launcher:className="com.bel.android.dspmanager.activity.DSPManager"
+ launcher:screen="1"
+ launcher:x="7"
+ launcher:y="4" />
+ <favorite
+ launcher:packageName="com.andrew.apollo"
+ launcher:className="com.andrew.apollo.ui.activities.HomeActivity"
+ launcher:screen="1"
+ launcher:x="0"
+ launcher:y="4" />
+
+ <!-- Screen [2] -->
+ <favorite
+ launcher:packageName="com.cyngn.gallerynext"
+ launcher:className="com.cyngn.gallerynext.app.GalleryActivity"
+ launcher:container="-100"
+ launcher:screen="2"
+ launcher:x="0"
+ launcher:y="4" />
+ <favorite
+ launcher:packageName="com.android.gallery3d"
+ launcher:className="com.android.gallery3d.app.Gallery"
+ launcher:container="-100"
+ launcher:screen="2"
+ launcher:x="0"
+ launcher:y="4" />
+ <favorite
+ launcher:packageName="com.android.settings"
+ launcher:className="com.android.settings.Settings"
+ launcher:container="-100"
+ launcher:screen="2"
+ launcher:x="7"
+ launcher:y="4" />
+ <appwidget
+ launcher:packageName="com.android.vending"
+ launcher:className="com.google.android.finsky.widget.consumption.NowPlayingWidgetProvider"
+ launcher:container="-100"
+ launcher:screen="2"
+ launcher:x="1"
+ launcher:y="0"
+ launcher:spanX="6"
+ launcher:spanY="4"/>
+ <appwidget
+ launcher:packageName="com.android.mms"
+ launcher:className="com.android.mms.widget.MmsWidgetProvider"
+ launcher:screen="2"
+ launcher:x="2"
+ launcher:y="0"
+ launcher:spanX="4"
+ launcher:spanY="2" />
+
+ <!-- Hotseat -->
+ <favorite
+ launcher:packageName="com.google.android.talk"
+ launcher:className="com.google.android.talk.SigningInActivity"
+ launcher:container="-101"
+ launcher:screen="5"
+ launcher:x="5"
+ launcher:y="0" />
+ <favorite
+ launcher:packageName="com.android.mms"
+ launcher:className="com.android.mms.ui.ConversationList"
+ launcher:container="-101"
+ launcher:screen="5"
+ launcher:x="5"
+ launcher:y="0" />
+ <favorite
+ launcher:packageName="com.android.chrome"
+ launcher:className="com.google.android.apps.chrome.Main"
+ launcher:container="-101"
+ launcher:screen="6"
+ launcher:x="6"
+ launcher:y="0" />
+ <favorite
+ launcher:packageName="com.android.browser"
+ launcher:className="com.android.browser.BrowserActivity"
+ launcher:container="-101"
+ launcher:screen="6"
+ launcher:x="6"
+ launcher:y="0" />
+ <favorite
+ launcher:packageName="com.google.android.music"
+ launcher:className="com.android.music.activitymanagement.TopLevelActivity"
+ launcher:container="-101"
+ launcher:screen="3"
+ launcher:x="3"
+ launcher:y="0" />
+ <favorite
+ launcher:packageName="com.android.camera2"
+ launcher:className="com.android.camera.CameraLauncher"
+ launcher:container="-101"
+ launcher:screen="3"
+ launcher:x="3"
+ launcher:y="0" />
+ <favorite
+ launcher:packageName="com.google.android.youtube"
+ launcher:className="com.google.android.youtube.app.honeycomb.Shell$HomeActivity"
+ launcher:container="-101"
+ launcher:screen="2"
+ launcher:x="2"
+ launcher:y="0" />
+ <favorite
+ launcher:packageName="com.android.contacts"
+ launcher:className="com.android.contacts.activities.PeopleActivity"
+ launcher:container="-101"
+ launcher:screen="2"
+ launcher:x="2"
+ launcher:y="0" />
+
+</favorites>
diff --git a/res/xml-sw720dp/default_workspace_no_telephony.xml b/res/xml-sw720dp/default_workspace_no_telephony.xml
index b15cebbb4..df557bff9 100644
--- a/res/xml-sw720dp/default_workspace_no_telephony.xml
+++ b/res/xml-sw720dp/default_workspace_no_telephony.xml
@@ -26,37 +26,6 @@
launcher:spanX="6"
launcher:spanY="3"/>
<favorite
- launcher:packageName="com.android.vending"
- launcher:className="com.android.vending.AssetBrowserActivity"
- launcher:container="-100"
- launcher:screen="1"
- launcher:x="7"
- launcher:y="4" />
- <folder
- launcher:screen="1"
- launcher:x="0"
- launcher:y="4"
- launcher:title="@string/google_title">
- <favorite
- launcher:className="com.google.android.maps.MapsActivity"
- launcher:packageName="com.google.android.apps.maps" />
- <favorite
- launcher:className="com.google.android.gm.GmailActivity"
- launcher:packageName="com.google.android.gm" />
- <favorite
- launcher:className="com.google.android.apps.plus.phone.HomeActivity"
- launcher:packageName="com.google.android.apps.plus" />
- <favorite
- launcher:className="com.android.calendar.AllInOneActivity"
- launcher:packageName="com.google.android.calendar" />
- <favorite
- launcher:className="com.google.android.maps.driveabout.app.DestinationActivity"
- launcher:packageName="com.google.android.apps.maps" />
- <favorite
- launcher:className="com.google.android.apps.plus.phone.ConversationListActivity"
- launcher:packageName="com.google.android.apps.plus" />
- </folder>
- <favorite
launcher:packageName="com.bel.android.dspmanager"
launcher:className="com.bel.android.dspmanager.activity.DSPManager"
launcher:screen="1"
@@ -71,13 +40,6 @@
<!-- Screen [2] -->
<favorite
- launcher:packageName="com.cyanogenmod.gallerynext"
- launcher:className="com.cyanogenmod.gallerynext.app.GalleryActivity"
- launcher:container="-100"
- launcher:screen="2"
- launcher:x="0"
- launcher:y="4" />
- <favorite
launcher:packageName="com.android.gallery3d"
launcher:className="com.android.gallery3d.app.Gallery"
launcher:container="-100"
@@ -92,15 +54,6 @@
launcher:x="7"
launcher:y="4" />
<appwidget
- launcher:packageName="com.android.vending"
- launcher:className="com.google.android.finsky.widget.consumption.NowPlayingWidgetProvider"
- launcher:container="-100"
- launcher:screen="2"
- launcher:x="1"
- launcher:y="0"
- launcher:spanX="6"
- launcher:spanY="4"/>
- <appwidget
launcher:packageName="com.android.settings"
launcher:className="com.android.settings.widget.SettingsAppWidgetProvider"
launcher:container="-100"
@@ -112,13 +65,6 @@
<!-- Hotseat -->
<favorite
- launcher:packageName="com.google.android.talk"
- launcher:className="com.google.android.talk.SigningInActivity"
- launcher:container="-101"
- launcher:screen="5"
- launcher:x="5"
- launcher:y="0" />
- <favorite
launcher:packageName="com.android.email"
launcher:className="com.android.email.activity.Welcome"
launcher:container="-101"
@@ -126,13 +72,6 @@
launcher:x="5"
launcher:y="0" />
<favorite
- launcher:packageName="com.android.chrome"
- launcher:className="com.google.android.apps.chrome.Main"
- launcher:container="-101"
- launcher:screen="6"
- launcher:x="6"
- launcher:y="0" />
- <favorite
launcher:packageName="com.android.browser"
launcher:className="com.android.browser.BrowserActivity"
launcher:container="-101"
@@ -140,13 +79,6 @@
launcher:x="6"
launcher:y="0" />
<favorite
- launcher:packageName="com.google.android.music"
- launcher:className="com.android.music.activitymanagement.TopLevelActivity"
- launcher:container="-101"
- launcher:screen="3"
- launcher:x="3"
- launcher:y="0" />
- <favorite
launcher:packageName="com.android.camera2"
launcher:className="com.android.camera.CameraLauncher"
launcher:container="-101"
@@ -154,13 +86,6 @@
launcher:x="3"
launcher:y="0" />
<favorite
- launcher:packageName="com.google.android.youtube"
- launcher:className="com.google.android.youtube.app.honeycomb.Shell$HomeActivity"
- launcher:container="-101"
- launcher:screen="2"
- launcher:x="2"
- launcher:y="0" />
- <favorite
launcher:packageName="com.android.contacts"
launcher:className="com.android.contacts.activities.PeopleActivity"
launcher:container="-101"
diff --git a/res/xml-sw720dp/default_workspace_no_telephony_gapps.xml b/res/xml-sw720dp/default_workspace_no_telephony_gapps.xml
new file mode 100644
index 000000000..2deae95e4
--- /dev/null
+++ b/res/xml-sw720dp/default_workspace_no_telephony_gapps.xml
@@ -0,0 +1,171 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2013-2014 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<favorites xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher3">
+ <!-- Screen [1] -->
+ <appwidget
+ launcher:packageName="com.cyanogenmod.lockclock"
+ launcher:className="com.cyanogenmod.lockclock.ClockWidgetProvider"
+ launcher:container="-100"
+ launcher:screen="1"
+ launcher:x="1"
+ launcher:y="0"
+ launcher:spanX="6"
+ launcher:spanY="3"/>
+ <favorite
+ launcher:packageName="com.android.vending"
+ launcher:className="com.android.vending.AssetBrowserActivity"
+ launcher:container="-100"
+ launcher:screen="1"
+ launcher:x="7"
+ launcher:y="4" />
+ <folder
+ launcher:screen="1"
+ launcher:x="0"
+ launcher:y="4"
+ launcher:title="@string/google_title">
+ <favorite
+ launcher:className="com.google.android.maps.MapsActivity"
+ launcher:packageName="com.google.android.apps.maps" />
+ <favorite
+ launcher:className="com.google.android.gm.ConversationListActivityGmail"
+ launcher:packageName="com.google.android.gm" />
+ <favorite
+ launcher:className="com.google.android.apps.plus.phone.HomeActivity"
+ launcher:packageName="com.google.android.apps.plus" />
+ <favorite
+ launcher:className="com.android.calendar.AllInOneActivity"
+ launcher:packageName="com.google.android.calendar" />
+ <favorite
+ launcher:className="com.google.android.maps.driveabout.app.DestinationActivity"
+ launcher:packageName="com.google.android.apps.maps" />
+ <favorite
+ launcher:className="com.google.android.apps.plus.phone.ConversationListActivity"
+ launcher:packageName="com.google.android.apps.plus" />
+ </folder>
+ <favorite
+ launcher:packageName="com.bel.android.dspmanager"
+ launcher:className="com.bel.android.dspmanager.activity.DSPManager"
+ launcher:screen="1"
+ launcher:x="7"
+ launcher:y="4" />
+ <favorite
+ launcher:packageName="com.andrew.apollo"
+ launcher:className="com.andrew.apollo.ui.activities.HomeActivity"
+ launcher:screen="1"
+ launcher:x="0"
+ launcher:y="4" />
+
+ <!-- Screen [2] -->
+ <favorite
+ launcher:packageName="com.cyngn.gallerynext"
+ launcher:className="com.cyngn.gallerynext.app.GalleryActivity"
+ launcher:container="-100"
+ launcher:screen="2"
+ launcher:x="0"
+ launcher:y="4" />
+ <favorite
+ launcher:packageName="com.android.gallery3d"
+ launcher:className="com.android.gallery3d.app.Gallery"
+ launcher:container="-100"
+ launcher:screen="2"
+ launcher:x="0"
+ launcher:y="4" />
+ <favorite
+ launcher:packageName="com.android.settings"
+ launcher:className="com.android.settings.Settings"
+ launcher:container="-100"
+ launcher:screen="2"
+ launcher:x="7"
+ launcher:y="4" />
+ <appwidget
+ launcher:packageName="com.android.vending"
+ launcher:className="com.google.android.finsky.widget.consumption.NowPlayingWidgetProvider"
+ launcher:container="-100"
+ launcher:screen="2"
+ launcher:x="1"
+ launcher:y="0"
+ launcher:spanX="6"
+ launcher:spanY="4"/>
+ <appwidget
+ launcher:packageName="com.android.settings"
+ launcher:className="com.android.settings.widget.SettingsAppWidgetProvider"
+ launcher:container="-100"
+ launcher:screen="2"
+ launcher:x="2"
+ launcher:y="0"
+ launcher:spanX="4"
+ launcher:spanY="1" />
+
+ <!-- Hotseat -->
+ <favorite
+ launcher:packageName="com.google.android.talk"
+ launcher:className="com.google.android.talk.SigningInActivity"
+ launcher:container="-101"
+ launcher:screen="5"
+ launcher:x="5"
+ launcher:y="0" />
+ <favorite
+ launcher:packageName="com.android.email"
+ launcher:className="com.android.email.activity.Welcome"
+ launcher:container="-101"
+ launcher:screen="5"
+ launcher:x="5"
+ launcher:y="0" />
+ <favorite
+ launcher:packageName="com.android.chrome"
+ launcher:className="com.google.android.apps.chrome.Main"
+ launcher:container="-101"
+ launcher:screen="6"
+ launcher:x="6"
+ launcher:y="0" />
+ <favorite
+ launcher:packageName="com.android.browser"
+ launcher:className="com.android.browser.BrowserActivity"
+ launcher:container="-101"
+ launcher:screen="6"
+ launcher:x="6"
+ launcher:y="0" />
+ <favorite
+ launcher:packageName="com.google.android.music"
+ launcher:className="com.android.music.activitymanagement.TopLevelActivity"
+ launcher:container="-101"
+ launcher:screen="3"
+ launcher:x="3"
+ launcher:y="0" />
+ <favorite
+ launcher:packageName="com.android.camera2"
+ launcher:className="com.android.camera.CameraLauncher"
+ launcher:container="-101"
+ launcher:screen="3"
+ launcher:x="3"
+ launcher:y="0" />
+ <favorite
+ launcher:packageName="com.google.android.youtube"
+ launcher:className="com.google.android.youtube.app.honeycomb.Shell$HomeActivity"
+ launcher:container="-101"
+ launcher:screen="2"
+ launcher:x="2"
+ launcher:y="0" />
+ <favorite
+ launcher:packageName="com.android.contacts"
+ launcher:className="com.android.contacts.activities.PeopleActivity"
+ launcher:container="-101"
+ launcher:screen="2"
+ launcher:x="2"
+ launcher:y="0" />
+
+</favorites>
diff --git a/res/xml/default_workspace.xml b/res/xml/default_workspace.xml
index 37676ff43..4174bc818 100644
--- a/res/xml/default_workspace.xml
+++ b/res/xml/default_workspace.xml
@@ -24,44 +24,6 @@
launcher:y="0"
launcher:spanX="4"
launcher:spanY="2" />
- <folder launcher:screen="1" launcher:x="0" launcher:y="3" launcher:title="@string/google_title">
- <favorite
- launcher:className="com.google.android.gm.GmailActivity"
- launcher:packageName="com.google.android.gm" />
- <favorite
- launcher:className="com.google.android.apps.plus.phone.HomeActivity"
- launcher:packageName="com.google.android.apps.plus" />
- <favorite
- launcher:className="com.google.android.maps.MapsActivity"
- launcher:packageName="com.google.android.apps.maps" />
- <favorite
- launcher:className="com.android.music.activitymanagement.TopLevelActivity"
- launcher:packageName="com.google.android.music" />
- <favorite
- launcher:className="com.google.android.youtube.videos.EntryPoint"
- launcher:packageName="com.google.android.videos" />
- <favorite
- launcher:className="com.google.android.apps.books.app.BooksActivity"
- launcher:packageName="com.google.android.apps.books" />
- <favorite
- launcher:className="com.google.apps.dots.android.app.activity.CurrentsStartActivity"
- launcher:packageName="com.google.android.apps.magazines" />
- <favorite
- launcher:className="com.google.android.gms.games.ui.destination.main.MainActivity"
- launcher:packageName="com.google.android.play.games" />
- <favorite
- launcher:className="com.google.android.apps.docs.app.NewMainProxyActivity"
- launcher:packageName="com.google.android.apps.docs" />
- <favorite
- launcher:className="com.google.android.youtube.app.honeycomb.Shell$HomeActivity"
- launcher:packageName="com.google.android.youtube" />
- <favorite
- launcher:className="com.google.android.apps.plus.phone.ConversationListActivity"
- launcher:packageName="com.google.android.apps.plus" />
- <favorite
- launcher:className="com.google.android.talk.SigningInActivity"
- launcher:packageName="com.google.android.talk" />
- </folder>
<favorite
launcher:packageName="com.andrew.apollo"
launcher:className="com.andrew.apollo.ui.activities.HomeActivity"
@@ -83,14 +45,6 @@
<!-- Screen [2] -->
<appwidget
- launcher:packageName="com.android.vending"
- launcher:className="com.google.android.finsky.widget.consumption.NowPlayingWidgetProvider"
- launcher:screen="2"
- launcher:x="0"
- launcher:y="0"
- launcher:spanX="4"
- launcher:spanY="2" />
- <appwidget
launcher:packageName="com.android.mms"
launcher:className="com.android.mms.widget.MmsWidgetProvider"
launcher:screen="2"
@@ -99,12 +53,6 @@
launcher:spanX="4"
launcher:spanY="2" />
<favorite
- launcher:packageName="com.cyanogenmod.gallerynext"
- launcher:className="com.cyanogenmod.gallerynext.app.GalleryActivity"
- launcher:screen="2"
- launcher:x="0"
- launcher:y="3" />
- <favorite
launcher:packageName="com.android.gallery3d"
launcher:className="com.android.gallery3d.app.Gallery"
launcher:screen="2"
@@ -133,13 +81,6 @@
launcher:x="1"
launcher:y="0" />
<favorite
- launcher:packageName="com.android.chrome"
- launcher:className="com.google.android.apps.chrome.Main"
- launcher:container="-101"
- launcher:screen="3"
- launcher:x="3"
- launcher:y="0" />
- <favorite
launcher:packageName="com.android.browser"
launcher:className="com.android.browser.BrowserActivity"
launcher:container="-101"
@@ -147,13 +88,6 @@
launcher:x="3"
launcher:y="0" />
<favorite
- launcher:packageName="com.cyngn.cameranext"
- launcher:className="com.android.camera.CameraLauncher"
- launcher:container="-101"
- launcher:screen="4"
- launcher:x="4"
- launcher:y="0" />
- <favorite
launcher:packageName="com.android.camera2"
launcher:className="com.android.camera.CameraLauncher"
launcher:container="-101"
diff --git a/res/xml/default_workspace_gapps.xml b/res/xml/default_workspace_gapps.xml
new file mode 100644
index 000000000..b2b6cfc7f
--- /dev/null
+++ b/res/xml/default_workspace_gapps.xml
@@ -0,0 +1,163 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2013-2014 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<favorites xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher3">
+ <!-- Screen [1] -->
+ <appwidget
+ launcher:packageName="com.cyanogenmod.lockclock"
+ launcher:className="com.cyanogenmod.lockclock.ClockWidgetProvider"
+ launcher:screen="1"
+ launcher:x="0"
+ launcher:y="0"
+ launcher:spanX="4"
+ launcher:spanY="2" />
+ <folder launcher:screen="1" launcher:x="0" launcher:y="3" launcher:title="@string/google_title">
+ <favorite
+ launcher:className="com.google.android.gm.ConversationListActivityGmail"
+ launcher:packageName="com.google.android.gm" />
+ <favorite
+ launcher:className="com.google.android.apps.plus.phone.HomeActivity"
+ launcher:packageName="com.google.android.apps.plus" />
+ <favorite
+ launcher:className="com.google.android.maps.MapsActivity"
+ launcher:packageName="com.google.android.apps.maps" />
+ <favorite
+ launcher:className="com.android.music.activitymanagement.TopLevelActivity"
+ launcher:packageName="com.google.android.music" />
+ <favorite
+ launcher:className="com.google.android.youtube.videos.EntryPoint"
+ launcher:packageName="com.google.android.videos" />
+ <favorite
+ launcher:className="com.google.android.apps.books.app.BooksActivity"
+ launcher:packageName="com.google.android.apps.books" />
+ <favorite
+ launcher:className="com.google.apps.dots.android.app.activity.CurrentsStartActivity"
+ launcher:packageName="com.google.android.apps.magazines" />
+ <favorite
+ launcher:className="com.google.android.gms.games.ui.destination.main.MainActivity"
+ launcher:packageName="com.google.android.play.games" />
+ <favorite
+ launcher:className="com.google.android.apps.docs.app.NewMainProxyActivity"
+ launcher:packageName="com.google.android.apps.docs" />
+ <favorite
+ launcher:className="com.google.android.youtube.app.honeycomb.Shell$HomeActivity"
+ launcher:packageName="com.google.android.youtube" />
+ <favorite
+ launcher:className="com.google.android.apps.plus.phone.ConversationListActivity"
+ launcher:packageName="com.google.android.apps.plus" />
+ <favorite
+ launcher:className="com.google.android.talk.SigningInActivity"
+ launcher:packageName="com.google.android.talk" />
+ </folder>
+ <favorite
+ launcher:packageName="com.andrew.apollo"
+ launcher:className="com.andrew.apollo.ui.activities.HomeActivity"
+ launcher:screen="1"
+ launcher:x="0"
+ launcher:y="3" />
+ <favorite
+ launcher:packageName="com.android.vending"
+ launcher:className="com.android.vending.AssetBrowserActivity"
+ launcher:screen="1"
+ launcher:x="3"
+ launcher:y="3" />
+ <favorite
+ launcher:packageName="com.bel.android.dspmanager"
+ launcher:className="com.bel.android.dspmanager.activity.DSPManager"
+ launcher:screen="1"
+ launcher:x="3"
+ launcher:y="3" />
+
+ <!-- Screen [2] -->
+ <appwidget
+ launcher:packageName="com.android.vending"
+ launcher:className="com.google.android.finsky.widget.consumption.NowPlayingWidgetProvider"
+ launcher:screen="2"
+ launcher:x="0"
+ launcher:y="0"
+ launcher:spanX="4"
+ launcher:spanY="2" />
+ <appwidget
+ launcher:packageName="com.android.mms"
+ launcher:className="com.android.mms.widget.MmsWidgetProvider"
+ launcher:screen="2"
+ launcher:x="0"
+ launcher:y="0"
+ launcher:spanX="4"
+ launcher:spanY="2" />
+ <favorite
+ launcher:packageName="com.cyngn.gallerynext"
+ launcher:className="com.cyngn.gallerynext.app.GalleryActivity"
+ launcher:screen="2"
+ launcher:x="0"
+ launcher:y="3" />
+ <favorite
+ launcher:packageName="com.android.gallery3d"
+ launcher:className="com.android.gallery3d.app.Gallery"
+ launcher:screen="2"
+ launcher:x="0"
+ launcher:y="3" />
+ <favorite
+ launcher:packageName="com.android.settings"
+ launcher:className="com.android.settings.Settings"
+ launcher:screen="2"
+ launcher:x="3"
+ launcher:y="3" />
+
+ <!-- Hotseat (We use the screen as the position of the item in the hotseat) -->
+ <favorite
+ launcher:packageName="com.android.dialer"
+ launcher:className="com.android.dialer.DialtactsActivity"
+ launcher:container="-101"
+ launcher:screen="0"
+ launcher:x="0"
+ launcher:y="0" />
+ <favorite
+ launcher:packageName="com.android.mms"
+ launcher:className="com.android.mms.ui.ConversationList"
+ launcher:container="-101"
+ launcher:screen="1"
+ launcher:x="1"
+ launcher:y="0" />
+ <favorite
+ launcher:packageName="com.android.chrome"
+ launcher:className="com.google.android.apps.chrome.Main"
+ launcher:container="-101"
+ launcher:screen="3"
+ launcher:x="3"
+ launcher:y="0" />
+ <favorite
+ launcher:packageName="com.android.browser"
+ launcher:className="com.android.browser.BrowserActivity"
+ launcher:container="-101"
+ launcher:screen="3"
+ launcher:x="3"
+ launcher:y="0" />
+ <favorite
+ launcher:packageName="com.cyngn.cameranext"
+ launcher:className="com.android.camera.CameraLauncher"
+ launcher:container="-101"
+ launcher:screen="4"
+ launcher:x="4"
+ launcher:y="0" />
+ <favorite
+ launcher:packageName="com.android.camera2"
+ launcher:className="com.android.camera.CameraLauncher"
+ launcher:container="-101"
+ launcher:screen="4"
+ launcher:x="4"
+ launcher:y="0" />
+</favorites>
diff --git a/res/drawable/iconpack_button.xml b/res/xml/default_workspace_no_all_apps.xml
index fedfb7a8e..9a46908d9 100644
--- a/res/drawable/iconpack_button.xml
+++ b/res/xml/default_workspace_no_all_apps.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
+<!-- Copyright (C) 2013 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -14,8 +14,8 @@
limitations under the License.
-->
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_focused="true" android:drawable="@drawable/ic_iconpacks_pressed" />
- <item android:state_pressed="true" android:drawable="@drawable/ic_iconpacks_pressed" />
- <item android:drawable="@drawable/ic_iconpacks" />
-</selector>
+<favorites xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3">
+ <!-- Hotseat (We use the screen as the position of the item in the hotseat) -->
+ <!-- Dialer Hangouts Maps Chrome Camera -->
+</favorites>
+
diff --git a/res/xml/default_workspace_no_all_apps_gapps.xml b/res/xml/default_workspace_no_all_apps_gapps.xml
new file mode 100644
index 000000000..7e1301cef
--- /dev/null
+++ b/res/xml/default_workspace_no_all_apps_gapps.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<favorites xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3">
+ <!-- Hotseat (We use the screen as the position of the item in the hotseat) -->
+ <!-- Dialer Hangouts Maps Chrome Camera -->
+ <favorite
+ launcher:packageName="com.google.android.dialer"
+ launcher:className="com.google.android.dialer.extensions.GoogleDialtactsActivity"
+ launcher:container="-101"
+ launcher:screen="0"
+ launcher:x="0"
+ launcher:y="0" />
+ <favorite
+ launcher:packageName="com.google.android.talk"
+ launcher:className="com.google.android.talk.SigningInActivity"
+ launcher:container="-101"
+ launcher:screen="1"
+ launcher:x="1"
+ launcher:y="0" />
+ <favorite
+ launcher:packageName="com.google.android.apps.maps"
+ launcher:className="com.google.android.maps.MapsActivity"
+ launcher:container="-101"
+ launcher:screen="2"
+ launcher:x="2"
+ launcher:y="0"/>
+ <favorite
+ launcher:packageName="com.android.chrome"
+ launcher:className="com.google.android.apps.chrome.Main"
+ launcher:container="-101"
+ launcher:screen="3"
+ launcher:x="3"
+ launcher:y="0" />
+ <favorite
+ launcher:packageName="com.google.android.GoogleCamera"
+ launcher:className="com.android.camera.CameraLauncher"
+ launcher:container="-101"
+ launcher:screen="4"
+ launcher:x="4"
+ launcher:y="0" />
+</favorites>
+
diff --git a/res/xml/default_workspace_no_telephony.xml b/res/xml/default_workspace_no_telephony.xml
index ce11edd35..868ffbece 100644
--- a/res/xml/default_workspace_no_telephony.xml
+++ b/res/xml/default_workspace_no_telephony.xml
@@ -24,35 +24,6 @@
launcher:y="0"
launcher:spanX="4"
launcher:spanY="2" />
- <folder launcher:screen="1" launcher:x="0" launcher:y="3" launcher:title="@string/google_title">
- <favorite
- launcher:className="com.google.android.maps.MapsActivity"
- launcher:packageName="com.google.android.apps.maps" />
- <favorite
- launcher:className="com.google.android.gm.GmailActivity"
- launcher:packageName="com.google.android.gm" />
- <favorite
- launcher:className="com.google.android.apps.plus.phone.HomeActivity"
- launcher:packageName="com.google.android.apps.plus" />
- <favorite
- launcher:className="com.android.music.activitymanagement.TopLevelActivity"
- launcher:packageName="com.google.android.music" />
- <favorite
- launcher:className="com.google.android.youtube.app.honeycomb.Shell$HomeActivity"
- launcher:packageName="com.google.android.youtube" />
- <favorite
- launcher:className="com.google.android.talk.SigningInActivity"
- launcher:packageName="com.google.android.talk" />
- <favorite
- launcher:className="com.android.calendar.AllInOneActivity"
- launcher:packageName="com.google.android.calendar" />
- <favorite
- launcher:className="com.google.android.maps.driveabout.app.DestinationActivity"
- launcher:packageName="com.google.android.apps.maps" />
- <favorite
- launcher:className="com.google.android.apps.plus.phone.ConversationListActivity"
- launcher:packageName="com.google.android.apps.plus" />
- </folder>
<favorite
launcher:packageName="com.andrew.apollo"
launcher:className="com.andrew.apollo.ui.activities.HomeActivity"
@@ -60,12 +31,6 @@
launcher:x="0"
launcher:y="3" />
<favorite
- launcher:packageName="com.android.vending"
- launcher:className="com.android.vending.AssetBrowserActivity"
- launcher:screen="1"
- launcher:x="3"
- launcher:y="3" />
- <favorite
launcher:packageName="com.bel.android.dspmanager"
launcher:className="com.bel.android.dspmanager.activity.DSPManager"
launcher:screen="1"
@@ -74,14 +39,6 @@
<!-- Screen [2] -->
<appwidget
- launcher:packageName="com.android.vending"
- launcher:className="com.google.android.finsky.widget.consumption.NowPlayingWidgetProvider"
- launcher:screen="2"
- launcher:x="0"
- launcher:y="0"
- launcher:spanX="4"
- launcher:spanY="2" />
- <appwidget
launcher:packageName="com.android.settings"
launcher:className="com.android.settings.widget.SettingsAppWidgetProvider"
launcher:screen="2"
@@ -90,12 +47,6 @@
launcher:spanX="4"
launcher:spanY="1" />
<favorite
- launcher:packageName="com.cyanogenmod.gallerynext"
- launcher:className="com.cyanogenmod.gallerynext.app.GalleryActivity"
- launcher:screen="2"
- launcher:x="0"
- launcher:y="3" />
- <favorite
launcher:packageName="com.android.gallery3d"
launcher:className="com.android.gallery3d.app.Gallery"
launcher:screen="2"
@@ -117,13 +68,6 @@
launcher:x="0"
launcher:y="0" />
<favorite
- launcher:packageName="com.google.android.gm"
- launcher:className="com.google.android.gm.ConversationListActivityGmail"
- launcher:container="-101"
- launcher:screen="1"
- launcher:x="1"
- launcher:y="0" />
- <favorite
launcher:packageName="com.android.email"
launcher:className="com.android.email.activity.Welcome"
launcher:container="-101"
@@ -131,13 +75,6 @@
launcher:x="1"
launcher:y="0" />
<favorite
- launcher:packageName="com.android.chrome"
- launcher:className="com.google.android.apps.chrome.Main"
- launcher:container="-101"
- launcher:screen="3"
- launcher:x="3"
- launcher:y="0" />
- <favorite
launcher:packageName="com.android.browser"
launcher:className="com.android.browser.BrowserActivity"
launcher:container="-101"
diff --git a/res/xml/default_workspace_no_telephony_gapps.xml b/res/xml/default_workspace_no_telephony_gapps.xml
new file mode 100644
index 000000000..f23d12bf4
--- /dev/null
+++ b/res/xml/default_workspace_no_telephony_gapps.xml
@@ -0,0 +1,154 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2013-2014 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<favorites xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher3">
+ <!-- Screen [1] -->
+ <appwidget
+ launcher:packageName="com.cyanogenmod.lockclock"
+ launcher:className="com.cyanogenmod.lockclock.ClockWidgetProvider"
+ launcher:screen="1"
+ launcher:x="0"
+ launcher:y="0"
+ launcher:spanX="4"
+ launcher:spanY="2" />
+ <folder launcher:screen="1" launcher:x="0" launcher:y="3" launcher:title="@string/google_title">
+ <favorite
+ launcher:className="com.google.android.maps.MapsActivity"
+ launcher:packageName="com.google.android.apps.maps" />
+ <favorite
+ launcher:className="com.google.android.gm.ConversationListActivityGmail"
+ launcher:packageName="com.google.android.gm" />
+ <favorite
+ launcher:className="com.google.android.apps.plus.phone.HomeActivity"
+ launcher:packageName="com.google.android.apps.plus" />
+ <favorite
+ launcher:className="com.android.music.activitymanagement.TopLevelActivity"
+ launcher:packageName="com.google.android.music" />
+ <favorite
+ launcher:className="com.google.android.youtube.app.honeycomb.Shell$HomeActivity"
+ launcher:packageName="com.google.android.youtube" />
+ <favorite
+ launcher:className="com.google.android.talk.SigningInActivity"
+ launcher:packageName="com.google.android.talk" />
+ <favorite
+ launcher:className="com.android.calendar.AllInOneActivity"
+ launcher:packageName="com.google.android.calendar" />
+ <favorite
+ launcher:className="com.google.android.maps.driveabout.app.DestinationActivity"
+ launcher:packageName="com.google.android.apps.maps" />
+ <favorite
+ launcher:className="com.google.android.apps.plus.phone.ConversationListActivity"
+ launcher:packageName="com.google.android.apps.plus" />
+ </folder>
+ <favorite
+ launcher:packageName="com.andrew.apollo"
+ launcher:className="com.andrew.apollo.ui.activities.HomeActivity"
+ launcher:screen="1"
+ launcher:x="0"
+ launcher:y="3" />
+ <favorite
+ launcher:packageName="com.android.vending"
+ launcher:className="com.android.vending.AssetBrowserActivity"
+ launcher:screen="1"
+ launcher:x="3"
+ launcher:y="3" />
+ <favorite
+ launcher:packageName="com.bel.android.dspmanager"
+ launcher:className="com.bel.android.dspmanager.activity.DSPManager"
+ launcher:screen="1"
+ launcher:x="3"
+ launcher:y="3" />
+
+ <!-- Screen [2] -->
+ <appwidget
+ launcher:packageName="com.android.vending"
+ launcher:className="com.google.android.finsky.widget.consumption.NowPlayingWidgetProvider"
+ launcher:screen="2"
+ launcher:x="0"
+ launcher:y="0"
+ launcher:spanX="4"
+ launcher:spanY="2" />
+ <appwidget
+ launcher:packageName="com.android.settings"
+ launcher:className="com.android.settings.widget.SettingsAppWidgetProvider"
+ launcher:screen="2"
+ launcher:x="0"
+ launcher:y="0"
+ launcher:spanX="4"
+ launcher:spanY="1" />
+ <favorite
+ launcher:packageName="com.cyngn.gallerynext"
+ launcher:className="com.cyngn.gallerynext.app.GalleryActivity"
+ launcher:screen="2"
+ launcher:x="0"
+ launcher:y="3" />
+ <favorite
+ launcher:packageName="com.android.gallery3d"
+ launcher:className="com.android.gallery3d.app.Gallery"
+ launcher:screen="2"
+ launcher:x="0"
+ launcher:y="3" />
+ <favorite
+ launcher:packageName="com.android.settings"
+ launcher:className="com.android.settings.Settings"
+ launcher:screen="2"
+ launcher:x="3"
+ launcher:y="3" />
+
+ <!-- Hotseat (We use the screen as the position of the item in the hotseat) -->
+ <favorite
+ launcher:packageName="com.android.contacts"
+ launcher:className="com.android.contacts.activities.PeopleActivity"
+ launcher:container="-101"
+ launcher:screen="0"
+ launcher:x="0"
+ launcher:y="0" />
+ <favorite
+ launcher:packageName="com.google.android.gm"
+ launcher:className="com.google.android.gm.ConversationListActivityGmail"
+ launcher:container="-101"
+ launcher:screen="1"
+ launcher:x="1"
+ launcher:y="0" />
+ <favorite
+ launcher:packageName="com.android.email"
+ launcher:className="com.android.email.activity.Welcome"
+ launcher:container="-101"
+ launcher:screen="1"
+ launcher:x="1"
+ launcher:y="0" />
+ <favorite
+ launcher:packageName="com.android.chrome"
+ launcher:className="com.google.android.apps.chrome.Main"
+ launcher:container="-101"
+ launcher:screen="3"
+ launcher:x="3"
+ launcher:y="0" />
+ <favorite
+ launcher:packageName="com.android.browser"
+ launcher:className="com.android.browser.BrowserActivity"
+ launcher:container="-101"
+ launcher:screen="3"
+ launcher:x="3"
+ launcher:y="0" />
+ <favorite
+ launcher:packageName="com.android.camera2"
+ launcher:className="com.android.camera.CameraLauncher"
+ launcher:container="-101"
+ launcher:screen="4"
+ launcher:x="4"
+ launcher:y="0" />
+</favorites>
diff --git a/res/xml/preferences_drawer.xml b/res/xml/preferences_drawer.xml
deleted file mode 100644
index b22597516..000000000
--- a/res/xml/preferences_drawer.xml
+++ /dev/null
@@ -1,42 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher3"
- android:key="ui_drawer"
- android:title="@string/preferences_interface_drawer_title">
- <PreferenceCategory android:title="@string/preferences_interface_drawer_apps_category">
- <Preference android:key="ui_drawer_hidden_apps"
- android:title="@string/preferences_interface_drawer_hidden_apps_title"
- android:summary="@string/preferences_interface_drawer_hidden_apps_summary">
- <intent android:action=".settings.HiddenAppsActivity"/>
- </Preference>
- <CheckBoxPreference android:key="ui_drawer_remove_hidden_apps_shortcuts"
- android:title="@string/preferences_interface_drawer_hidden_apps_shortcuts_title"
- android:summary="@string/preferences_interface_drawer_hidden_apps_shortcuts_summary"
- android:defaultValue="@bool/preferences_interface_drawer_remove_hidden_apps_shortcuts_default" />
- <CheckBoxPreference android:key="ui_drawer_remove_hidden_apps_widgets"
- android:title="@string/preferences_interface_drawer_hidden_apps_widgets_title"
- android:summary="@string/preferences_interface_drawer_hidden_apps_widgets_summary"
- android:defaultValue="@bool/preferences_interface_drawer_remove_hidden_apps_widgets_default" />
- </PreferenceCategory>
- <PreferenceCategory android:title="@string/preferences_interface_general_icons_category">
- <CheckBoxPreference android:key="ui_drawer_hide_icon_labels"
- android:title="@string/preferences_interface_drawer_hide_icon_labels_title"
- android:summary="@string/preferences_interface_drawer_hide_icon_labels_summary"
- android:defaultValue="@bool/preferences_interface_drawer_hide_icon_labels_default" />
- </PreferenceCategory>
-</PreferenceScreen> \ No newline at end of file
diff --git a/res/xml/preferences_general.xml b/res/xml/preferences_general.xml
deleted file mode 100644
index 96b93ec44..000000000
--- a/res/xml/preferences_general.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher3"
- android:key="ui_general"
- android:title="@string/preferences_interface_general_title">
- <PreferenceCategory android:title="@string/preferences_interface_general_icons_category">
- <CheckBoxPreference android:key="ui_general_icons_large"
- android:title="@string/preferences_interface_general_icons_large_title"
- android:summary="@string/preferences_interface_general_icons_large_summary"
- android:defaultValue="@bool/preferences_interface_general_icons_large_default" />
- <com.android.launcher3.settings.FontStylePreference android:key="ui_general_icons_text_font"
- android:title="@string/preferences_interface_general_icons_text_style_title"
- android:summary="@string/preferences_interface_general_icons_text_style_summary"
- android:entries="@array/preferences_interface_general_icons_text_font_family_entries"
- android:entryValues="@array/preferences_interface_general_icons_text_font_family_values"
- android:defaultValue="@string/preferences_interface_general_icons_text_font_family_default" />
- </PreferenceCategory>
-
-</PreferenceScreen>
diff --git a/res/xml/preferences_headers.xml b/res/xml/preferences_headers.xml
deleted file mode 100644
index 42a08a9bd..000000000
--- a/res/xml/preferences_headers.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2014 The CyanogenMod Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<preference-headers xmlns:android="http://schemas.android.com/apk/res/android">
-
- <header android:id="@+id/preferences_homescreen_section"
- android:fragment="com.android.launcher3.settings.SettingsActivity$HomescreenFragment"
- android:title="@string/preferences_interface_homescreen_title" />
-
- <header android:id="@+id/preferences_drawer_section"
- android:fragment="com.android.launcher3.settings.SettingsActivity$DrawerFragment"
- android:title="@string/preferences_interface_drawer_title"
- android:summary="@string/preferences_interface_drawer_summary" />
-
- <!--<header android:id="@+id/preferences_dock_section"
- android:title="@string/preferences_interface_dock_title" />-->
-
- <header android:id="@+id/preferences_general_section"
- android:fragment="com.android.launcher3.settings.SettingsActivity$GeneralFragment"
- android:title="@string/preferences_interface_general_title" />
-
- <header android:id="@+id/preferences_application_section"
- android:title="@string/preferences_application_title" />
-
- <header android:id="@+id/preferences_application_version"
- android:summary="@string/application_copyright" />
-
-</preference-headers>
diff --git a/res/xml/preferences_homescreen.xml b/res/xml/preferences_homescreen.xml
deleted file mode 100644
index 1754cfa02..000000000
--- a/res/xml/preferences_homescreen.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher3"
- android:key="ui_homescreen"
- android:title="@string/preferences_interface_homescreen_title">
- <CheckBoxPreference android:key="ui_homescreen_search"
- android:title="@string/preferences_interface_homescreen_search_title"
- android:summary="@string/preferences_interface_homescreen_search_summary"
- android:defaultValue="@bool/preferences_interface_homescreen_search_default" />
- <CheckBoxPreference android:key="ui_homescreen_general_hide_icon_labels"
- android:title="@string/preferences_interface_homescreen_general_hide_icon_labels_title"
- android:summary="@string/preferences_interface_homescreen_general_hide_icon_labels_summary"
- android:defaultValue="@bool/preferences_interface_homescreen_hide_icon_labels_default" />
-</PreferenceScreen>
diff --git a/src/com/android/launcher/home/Home.java b/src/com/android/launcher/home/Home.java
new file mode 100644
index 000000000..5dce71e86
--- /dev/null
+++ b/src/com/android/launcher/home/Home.java
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2014 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher.home;
+
+import android.content.Context;
+import android.view.View;
+import android.view.ViewGroup.LayoutParams;
+
+/**
+ * The generic contract that should supports a <code>Home</code> app to could
+ * be invoked and registered by an Android launcher.<br/>
+ * <br/>
+ * This interface contains the version 1 of the <code>Home Host App</code> protocol.<br/>
+ * <br/>
+ * <br/>
+ * A <code>Home</code> app should:
+ * <ul>
+ * <li>
+ * should have at least a constructor with no arguments
+ * </li>
+ * <li>
+ * declares inside its manifest a <code>com.android.launcher.home</code> metadata with the
+ * full qualified that contains this interface<br/>
+ * <pre>
+ * &lt;meta-data android:name="com.android.launcher.home" value="org.cyanogenmod.launcher.home.HomeStub"/&gt;
+ * </pre>
+ * </li>
+ * <li>
+ * define the "com.android.launcher.home.permissions.HOME_APP" permission<br/>
+ * <pre>
+ * &lt;uses-permission android:name="com.android.launcher.home.permissions.HOME_APP"/&gt;
+ * </pre>
+ * </li>
+ * <li>
+ * implements the contract defined by this protocol.
+ * </li>
+ * </ul>
+ * <br/>
+ * Implementors classes of this protocol should be aware that all the {@link Context} references
+ * passed to this class owns to the host launcher app. This means that you cannot access
+ * to settings defined by the <code>Home</code> app inside its shared context.
+ */
+public interface Home {
+
+ /**
+ * A SHA-1 hash of all declared method of this interface. Home apps should compute as:<br/>
+ * <br/>
+ * <pre>
+ * for method in Home.class.getDeclaredMehod
+ * sha1.update method.toString.bytes
+ * </pre><br/>
+ * DO NOT MODIFY!
+ */
+ public static final String SIGNATURE = "5/A6Mxkz8gHHzzVf4qZR+hiSOAw=";
+
+ /**
+ * Defines the name of the metadata used to declared the full qualified Home stub class
+ * that implements this protocol.
+ */
+ public static final String METADATA_HOME_STUB = "com.android.launcher.home";
+
+ /**
+ * Defines the name of the permission that the Home app should explicitly declare.
+ */
+ public static final String PERMISSION_HOME_APP = "com.android.launcher.home.permissions.HOME_APP";
+
+ // Notification flags
+ public static final int FLAG_NOTIFY_MASK = 0x0000;
+ public static final int FLAG_NOTIFY_ON_RESUME = FLAG_NOTIFY_MASK + 0x0002;
+ public static final int FLAG_NOTIFY_ON_PAUSE = FLAG_NOTIFY_MASK + 0x0004;
+ public static final int FLAG_NOTIFY_ON_SHOW = FLAG_NOTIFY_MASK + 0x0008;
+ public static final int FLAG_NOTIFY_ON_SCROLL_PROGRESS_CHANGED = FLAG_NOTIFY_MASK + 0x0010;
+ public static final int FLAG_NOTIFY_ON_HIDE = FLAG_NOTIFY_MASK + 0x0020;
+ public static final int FLAG_NOTIFY_ALL = FLAG_NOTIFY_ON_RESUME | FLAG_NOTIFY_ON_PAUSE |
+ FLAG_NOTIFY_ON_SHOW | FLAG_NOTIFY_ON_SCROLL_PROGRESS_CHANGED | FLAG_NOTIFY_ON_HIDE;
+
+ // Operation support flags
+ public static final int FLAG_OP_MASK = 0x1000;
+ public static final int FLAG_OP_CUSTOM_SEARCH = FLAG_OP_MASK + 0x0002;
+ public static final int FLAG_OP_ALL = FLAG_OP_CUSTOM_SEARCH;
+
+ // Search modes
+ public static final int MODE_SEARCH_TEXT = 0x0000;
+ public static final int MODE_SEARCH_VOICE = 0x0001;
+
+ /**
+ * Invoked the first time the <code>Home</code> app is created.<br/>
+ * This method should be used by implementors classes of this protocol to load the needed
+ * resources.
+ * @param context the current {@link Context} of the host launcher.
+ */
+ void onStart(Context context);
+
+ /**
+ * Invoked when the <code>Home</code> app should be destroy.<br/>
+ * This method should be used by implementors classes of this protocol to unload all unneeded
+ * resources.
+ * @param context the current {@link Context} of the host launcher.
+ */
+ void onDestroy(Context context);
+
+ /**
+ * Invoked when the host launcher enters in resume mode.
+ * @param context the current {@link Context} of the host launcher.
+ */
+ void onResume(Context context);
+
+ /**
+ * Invoked when the host launcher enters in pause mode.
+ * @param context the current {@link Context} of the host launcher.
+ */
+ void onPause(Context context);
+
+ /**
+ * Invoked when the custom content page is totally displayed.
+ * @param context the current {@link Context} of the host launcher.
+ */
+ void onShow(Context context);
+
+ /**
+ * Invoked when the custom content page is scrolled.
+ * @param context the current {@link Context} of the host launcher.
+ * @param progress the current scroll progress.
+ */
+ void onScrollProgressChanged(Context context, float progress);
+
+ /**
+ * Invoked when the custom content page is totally hidden.
+ * @param context the current {@link Context} of the host launcher.
+ */
+ void onHide(Context context);
+
+ /**
+ * Invoked by the host launcher to request an invalidation of the ui elements and data used by
+ * the <code>Home</code> implementation class.
+ * @param context the current {@link Context} of the host launcher.
+ */
+ void onInvalidate(Context context);
+
+ /**
+ * Invoked when the host launcher request enter in search mode.
+ * @param context the current {@link Context} of the host launcher.
+ * @param mode the requested search mode. Must be one of:
+ * <ul>
+ * <li>{@link #MODE_SEARCH_TEXT}: Textual mode</li>
+ * <li>{@link #MODE_SEARCH_VOICE}: Voice mode</li>
+ * </ul>
+ */
+ void onRequestSearch(Context context, int mode);
+
+ /**
+ * Returns an instance of a {@link View} that holds the custom content to be displayed
+ * by this <code>Home</code> app.
+ * @param context the current {@link Context} of the host launcher.
+ * @return View The custom content view that will be enclosed inside a
+ * <code>com.android.launcher3.Launcher.QSBScroller</code>.<br/>
+ * Be aware the the height layout of the returned should be defined as
+ * {link {@link LayoutParams#WRAP_CONTENT}, so the view could be scrolled inside the
+ * custom content page.
+ */
+ View createCustomView(Context context);
+
+ /**
+ * Returns the name of the Home app (LIMIT: 30 characters).
+ * @param context the current {@link Context} of the host launcher.
+ */
+ String getName(Context context);
+
+ /**
+ * Implementations should return the combination of notification flags that want to listen to.
+ * @see #FLAG_NOTIFY_ON_RESUME
+ * @see #FLAG_NOTIFY_ON_PAUSE
+ * @see #FLAG_NOTIFY_ON_SHOW
+ * @see #FLAG_NOTIFY_ON_SCROLL_PROGRESS_CHANGED
+ * @see #FLAG_NOTIFY_ON_HIDE
+ * @see #FLAG_NOTIFY_ALL
+ */
+ int getNotificationFlags();
+
+ /**
+ * Implementations should return the combination of operation flags that want they want
+ * to support to.
+ * @see #FLAG_OP_CUSTOM_SEARCH
+ * @see #FLAG_OP_ALL
+ */
+ int getOperationFlags();
+}
diff --git a/src/com/android/launcher3/AddAdapter.java b/src/com/android/launcher3/AddAdapter.java
index ad15e75c6..5308a3de4 100644
--- a/src/com/android/launcher3/AddAdapter.java
+++ b/src/com/android/launcher3/AddAdapter.java
@@ -27,8 +27,6 @@ import android.widget.TextView;
import java.util.ArrayList;
-import com.android.launcher3.R;
-
/**
* Adapter showing the types of items that can be added to a {@link Workspace}.
*/
diff --git a/src/com/android/launcher3/Alarm.java b/src/com/android/launcher3/Alarm.java
index 91f9bd091..e9f1fd963 100644
--- a/src/com/android/launcher3/Alarm.java
+++ b/src/com/android/launcher3/Alarm.java
@@ -78,7 +78,3 @@ public class Alarm implements Runnable{
return mAlarmPending;
}
}
-
-interface OnAlarmListener {
- public void onAlarm(Alarm alarm);
-}
diff --git a/src/com/android/launcher3/AllAppsList.java b/src/com/android/launcher3/AllAppsList.java
index d955e4eae..89b291f28 100644
--- a/src/com/android/launcher3/AllAppsList.java
+++ b/src/com/android/launcher3/AllAppsList.java
@@ -16,9 +16,6 @@
package com.android.launcher3;
-import java.util.ArrayList;
-import java.util.List;
-
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -26,13 +23,16 @@ import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
+import java.util.ArrayList;
+import java.util.List;
+
/**
* Stores the list of all applications for the all apps view.
*/
class AllAppsList {
public static final int DEFAULT_APPLICATIONS_NUMBER = 42;
-
+
/** The list off all apps. */
public ArrayList<AppInfo> data =
new ArrayList<AppInfo>(DEFAULT_APPLICATIONS_NUMBER);
@@ -115,8 +115,7 @@ class AllAppsList {
data.remove(i);
}
}
- // This is more aggressive than it needs to be.
- mIconCache.flush();
+ mIconCache.remove(packageName);
}
/**
diff --git a/src/com/android/launcher3/AppInfo.java b/src/com/android/launcher3/AppInfo.java
index 53f81bb1c..da222f11f 100644
--- a/src/com/android/launcher3/AppInfo.java
+++ b/src/com/android/launcher3/AppInfo.java
@@ -18,9 +18,9 @@ package com.android.launcher3;
import android.content.ComponentName;
import android.content.Intent;
+import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.PackageInfo;
import android.content.pm.ResolveInfo;
import android.graphics.Bitmap;
import android.util.Log;
@@ -64,6 +64,10 @@ class AppInfo extends ItemInfo {
return intent;
}
+ protected Intent getRestoredIntent() {
+ return null;
+ }
+
/**
* Must not hold the Context.
*/
diff --git a/src/com/android/launcher3/AppWidgetResizeFrame.java b/src/com/android/launcher3/AppWidgetResizeFrame.java
index ba31621f1..c2125b796 100644
--- a/src/com/android/launcher3/AppWidgetResizeFrame.java
+++ b/src/com/android/launcher3/AppWidgetResizeFrame.java
@@ -13,8 +13,6 @@ import android.view.Gravity;
import android.widget.FrameLayout;
import android.widget.ImageView;
-import com.android.launcher3.R;
-
public class AppWidgetResizeFrame extends FrameLayout {
private LauncherAppWidgetHostView mWidgetView;
private CellLayout mCellLayout;
diff --git a/src/com/android/launcher3/AppsCustomizeLayout.java b/src/com/android/launcher3/AppsCustomizeLayout.java
index ea1c36a9c..16e5449e6 100644
--- a/src/com/android/launcher3/AppsCustomizeLayout.java
+++ b/src/com/android/launcher3/AppsCustomizeLayout.java
@@ -67,12 +67,12 @@ public class AppsCustomizeLayout extends FrameLayout implements LauncherTransiti
mContent = (FrameLayout) findViewById(R.id.apps_customize_content);
if (mAppsCustomizePane == null) throw new Resources.NotFoundException();
- findViewById(R.id.page_indicator).setOnClickListener(new OnClickListener() {
+ /*findViewById(R.id.page_indicator).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mAppsCustomizePane.enterOverviewMode();
}
- });
+ });*/
}
public boolean onInterceptTouchEvent(MotionEvent ev) {
@@ -136,6 +136,10 @@ public class AppsCustomizeLayout extends FrameLayout implements LauncherTransiti
@Override
public View getContent() {
+ View appsCustomizeContent = mAppsCustomizePane.getContent();
+ if (appsCustomizeContent != null) {
+ return appsCustomizeContent;
+ }
return mContent;
}
@@ -171,12 +175,12 @@ public class AppsCustomizeLayout extends FrameLayout implements LauncherTransiti
}
// Dismiss the workspace cling
- l.dismissWorkspaceCling(null);
+ l.getLauncherClings().dismissWorkspaceCling(null);
}
@Override
public void onLauncherTransitionStep(Launcher l, float t) {
- // Do nothing
+ mAppsCustomizePane.onLauncherTransitionStep(l, t);
}
@Override
diff --git a/src/com/android/launcher3/AppsCustomizePagedView.java b/src/com/android/launcher3/AppsCustomizePagedView.java
index ed504cf2e..f2c08a3e1 100644
--- a/src/com/android/launcher3/AppsCustomizePagedView.java
+++ b/src/com/android/launcher3/AppsCustomizePagedView.java
@@ -40,6 +40,7 @@ import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Process;
+import android.provider.Settings;
import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
import android.util.Log;
@@ -170,9 +171,29 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
* The different sort modes than can be used to order items.
*/
public enum SortMode {
- Title,
- LaunchCount,
- InstallTime
+ Title(0),
+ LaunchCount(1),
+ InstallTime(2);
+
+ private final int mValue;
+ private SortMode(int value) {
+ mValue = value;
+ }
+
+ public int getValue() {
+ return mValue;
+ }
+
+ public static SortMode getModeForValue(int value) {
+ switch (value) {
+ case 1:
+ return LaunchCount;
+ case 2:
+ return InstallTime;
+ default :
+ return Title;
+ }
+ }
}
private SortMode mSortMode = SortMode.Title;
@@ -197,8 +218,8 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
private ArrayList<AppInfo> mFilteredApps;
private ArrayList<Object> mFilteredWidgets;
- private ArrayList<ComponentName> mHiddenApps;
- private ArrayList<String> mHiddenPackages;
+ private ArrayList<ComponentName> mProtectedApps;
+ private ArrayList<String> mProtectedPackages;
// Cling
private boolean mHasShownAllAppsCling;
@@ -216,6 +237,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
private PagedViewCellLayout mWidgetSpacingLayout;
private int mNumAppsPages;
private int mNumWidgetPages;
+ private Rect mAllAppsPadding = new Rect();
// Animation states
enum State { NORMAL, OVERVIEW};
@@ -236,8 +258,6 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
private boolean mOverscrollTransformsSet;
private float mLastOverscrollPivotX;
- public static boolean DISABLE_ALL_APPS = false;
-
// Previews & outlines
ArrayList<AppsCustomizeAsyncTask> mRunningTasks;
private static final int sPageSleepDelay = 200;
@@ -323,17 +343,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
}
- String[] flattened = SettingsProvider.getStringCustomDefault(context,
- SettingsProvider.SETTINGS_UI_DRAWER_HIDDEN_APPS, "").split("\\|");
- mHiddenApps = new ArrayList<ComponentName>(flattened.length);
- mHiddenPackages = new ArrayList<String>(flattened.length);
- for (String flat : flattened) {
- ComponentName cmp = ComponentName.unflattenFromString(flat);
- if (cmp != null) {
- mHiddenApps.add(cmp);
- mHiddenPackages.add(cmp.getPackageName());
- }
- }
+ updateProtectedAppsList(context);
}
@Override
@@ -361,6 +371,20 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
grid.edgeMarginPx, 2 * grid.edgeMarginPx);
}
+ void setAllAppsPadding(Rect r) {
+ mAllAppsPadding.set(r);
+ }
+ void setWidgetsPageIndicatorPadding(int pageIndicatorHeight) {
+ mPageLayoutPaddingBottom = pageIndicatorHeight;
+ }
+
+ WidgetPreviewLoader getWidgetPreviewLoader() {
+ if (mWidgetPreviewLoader == null) {
+ mWidgetPreviewLoader = new WidgetPreviewLoader(mLauncher);
+ }
+ return mWidgetPreviewLoader;
+ }
+
/** Returns the item index of the center item on this page so that we can restore to this
* item index when we rotate. */
private int getMiddleComponentIndexOnCurrentPage() {
@@ -426,10 +450,6 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
}
protected void onDataReady(int width, int height) {
- if (mWidgetPreviewLoader == null) {
- mWidgetPreviewLoader = new WidgetPreviewLoader(mLauncher);
- }
-
// Now that the data is ready, we can calculate the content width, the number of cells to
// use for each page
LauncherAppState app = LauncherAppState.getInstance();
@@ -487,7 +507,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
if (!isDataReady()) {
- if ((DISABLE_ALL_APPS || !mFilteredApps.isEmpty()) && !mFilteredWidgets.isEmpty()) {
+ if (((LauncherAppState.isDisableAllApps() || !mFilteredApps.isEmpty()) && !mFilteredWidgets.isEmpty())) {
setDataIsReady();
setMeasuredDimension(width, height);
onDataReady(width, height);
@@ -801,13 +821,13 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
int[] previewSizeBeforeScale = new int[1];
- preview = mWidgetPreviewLoader.generateWidgetPreview(createWidgetInfo.componentName,
+ preview = getWidgetPreviewLoader().generateWidgetPreview(createWidgetInfo.componentName,
createWidgetInfo.previewImage, createWidgetInfo.icon, spanX, spanY,
maxWidth, maxHeight, null, previewSizeBeforeScale);
// Compare the size of the drag preview to the preview in the AppsCustomize tray
int previewWidthInAppsCustomize = Math.min(previewSizeBeforeScale[0],
- mWidgetPreviewLoader.maxWidthForWidgetPreview(spanX));
+ getWidgetPreviewLoader().maxWidthForWidgetPreview(spanX));
scale = previewWidthInAppsCustomize / (float) preview.getWidth();
// The bitmap in the AppsCustomize tray is always the the same size, so there
@@ -888,16 +908,26 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
*/
private void endDragging(View target, boolean isFlingToDelete, boolean success) {
if (isFlingToDelete || !success || (target != mLauncher.getWorkspace() &&
- !(target instanceof DeleteDropTarget))) {
+ !(target instanceof DeleteDropTarget) && !(target instanceof Folder))) {
// Exit spring loaded mode if we have not successfully dropped or have not handled the
// drop in Workspace
- mLauncher.exitSpringLoadedDragMode();
+ mLauncher.getWorkspace().removeExtraEmptyScreen(true, new Runnable() {
+ @Override
+ public void run() {
+ mLauncher.exitSpringLoadedDragMode();
+ mLauncher.unlockScreenOrientation(false);
+ }
+ });
+ } else {
+ mLauncher.unlockScreenOrientation(false);
}
- mLauncher.unlockScreenOrientation(false);
}
@Override
public View getContent() {
+ if (getChildCount() > 0) {
+ return getChildAt(0);
+ }
return null;
}
@@ -921,7 +951,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
public void onLauncherTransitionEnd(Launcher l, boolean animated, boolean toWorkspace) {
mInTransition = false;
for (AsyncTaskPageData d : mDeferredSyncWidgetPageItems) {
- onSyncWidgetPageItems(d);
+ onSyncWidgetPageItems(d, false);
}
mDeferredSyncWidgetPageItems.clear();
for (Runnable r : mDeferredPrepareLoadWidgetPreviewsTasks) {
@@ -978,6 +1008,23 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
}
@Override
+ public boolean supportsAppInfoDropTarget() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsDeleteDropTarget() {
+ return false;
+ }
+
+ @Override
+ public float getIntrinsicIconScaleFactor() {
+ LauncherAppState app = LauncherAppState.getInstance();
+ DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
+ return (float) grid.allAppsIconSizePx / grid.iconSizePx;
+ }
+
+ @Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
cancelAllTasks();
@@ -1021,12 +1068,12 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
}
public void setContentType(ContentType type) {
- int page = getCurrentPage();
- if (mContentType != type) {
- page = 0;
+ // Widgets appear to be cleared every time you leave, always force invalidate for them
+ if (mContentType != type || type == ContentType.Widgets) {
+ int page = (mContentType != type) ? 0 : getCurrentPage();
+ mContentType = type;
+ invalidatePageData(page, true);
}
- mContentType = type;
- invalidatePageData(page, true);
}
public ContentType getContentType() {
@@ -1073,6 +1120,8 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
int heightSpec = MeasureSpec.makeMeasureSpec(mContentHeight, MeasureSpec.AT_MOST);
layout.setMinimumWidth(getPageContentWidth());
layout.measure(widthSpec, heightSpec);
+ layout.setPadding(mAllAppsPadding.left, mAllAppsPadding.top, mAllAppsPadding.right,
+ mAllAppsPadding.bottom);
setVisibilityOnChildren(layout, View.VISIBLE);
}
@@ -1127,7 +1176,6 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
icon.setOnLongClickListener(this);
icon.setOnTouchListener(this);
icon.setOnKeyListener(this);
- Utilities.applyTypeface(icon);
int index = i - startIndex;
int x = index % mCellCountX;
@@ -1230,9 +1278,9 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
mRunningTasks.remove(task);
if (task.isCancelled()) return;
// do cleanup inside onSyncWidgetPageItems
- onSyncWidgetPageItems(data);
+ onSyncWidgetPageItems(data, false);
}
- }, mWidgetPreviewLoader);
+ }, getWidgetPreviewLoader());
// Ensure that the task is appropriately prioritized and runs in parallel
AppsCustomizeAsyncTask t = new AppsCustomizeAsyncTask(page,
@@ -1293,7 +1341,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
createItemInfo.minSpanX = minSpanXY[0];
createItemInfo.minSpanY = minSpanXY[1];
- widget.applyFromAppWidgetProviderInfo(info, -1, spanXY, mWidgetPreviewLoader);
+ widget.applyFromAppWidgetProviderInfo(info, -1, spanXY, getWidgetPreviewLoader());
widget.setTag(createItemInfo);
widget.setShortPressListener(this);
} else if (rawInfo instanceof ResolveInfo) {
@@ -1303,7 +1351,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
createItemInfo.itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
createItemInfo.componentName = new ComponentName(info.activityInfo.packageName,
info.activityInfo.name);
- widget.applyFromResolveInfo(mPackageManager, info, mWidgetPreviewLoader);
+ widget.applyFromResolveInfo(mPackageManager, info, getWidgetPreviewLoader());
widget.setTag(createItemInfo);
}
widget.setOnClickListener(this);
@@ -1340,13 +1388,13 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
maxPreviewHeight = maxSize[1];
}
- mWidgetPreviewLoader.setPreviewSize(
+ getWidgetPreviewLoader().setPreviewSize(
maxPreviewWidth, maxPreviewHeight, mWidgetSpacingLayout);
if (immediate) {
AsyncTaskPageData data = new AsyncTaskPageData(page, items,
- maxPreviewWidth, maxPreviewHeight, null, null, mWidgetPreviewLoader);
+ maxPreviewWidth, maxPreviewHeight, null, null, getWidgetPreviewLoader());
loadWidgetPreviewsInBackground(null, data);
- onSyncWidgetPageItems(data);
+ onSyncWidgetPageItems(data, immediate);
} else {
if (mInTransition) {
mDeferredPrepareLoadWidgetPreviewsTasks.add(this);
@@ -1381,12 +1429,12 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
task.syncThreadPriority();
}
- images.add(mWidgetPreviewLoader.getPreview(items.get(i)));
+ images.add(getWidgetPreviewLoader().getPreview(items.get(i)));
}
}
- private void onSyncWidgetPageItems(AsyncTaskPageData data) {
- if (mInTransition) {
+ private void onSyncWidgetPageItems(AsyncTaskPageData data, boolean immediatelySyncItems) {
+ if (!immediatelySyncItems && mInTransition) {
mDeferredSyncWidgetPageItems.add(data);
return;
}
@@ -1908,6 +1956,10 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
public void setup(Launcher launcher, DragController dragController) {
mLauncher = launcher;
mDragController = dragController;
+ int sortMode = SettingsProvider.getIntCustomDefault(mLauncher, SettingsProvider.SETTINGS_UI_DRAWER_SORT_MODE, -1);
+ if (sortMode != -1) {
+ setSortMode(SortMode.getModeForValue(sortMode));
+ }
}
/**
@@ -1954,7 +2006,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
}
public void setApps(ArrayList<AppInfo> list) {
- if (!DISABLE_ALL_APPS) {
+ if (!LauncherAppState.isDisableAllApps()) {
mApps = list;
filterAppsWithoutInvalidate();
updatePageCountsAndInvalidateData();
@@ -1974,7 +2026,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
}
public void addApps(ArrayList<AppInfo> list) {
- if (!DISABLE_ALL_APPS) {
+ if (!LauncherAppState.isDisableAllApps()) {
addAppsWithoutInvalidate(list);
filterAppsWithoutInvalidate();
updatePageCountsAndInvalidateData();
@@ -2006,7 +2058,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
}
public void removeApps(ArrayList<AppInfo> appInfos) {
- if (!DISABLE_ALL_APPS) {
+ if (!LauncherAppState.isDisableAllApps()) {
removeAppsWithoutInvalidate(appInfos);
filterAppsWithoutInvalidate();
updatePageCountsAndInvalidateData();
@@ -2017,7 +2069,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
// We remove and re-add the updated applications list because it's properties may have
// changed (ie. the title), and this will ensure that the items will be in their proper
// place in the list.
- if (!DISABLE_ALL_APPS) {
+ if (!LauncherAppState.isDisableAllApps()) {
removeAppsWithoutInvalidate(list);
addAppsWithoutInvalidate(list);
filterAppsWithoutInvalidate();
@@ -2025,13 +2077,31 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
}
}
+ private void updateProtectedAppsList(Context context) {
+ String protectedComponents = Settings.Secure.getString(context.getContentResolver(),
+ LauncherModel.SETTINGS_PROTECTED_COMPONENTS);
+ protectedComponents = protectedComponents == null ? "" : protectedComponents;
+ String [] flattened = protectedComponents.split("\\|");
+ mProtectedApps = new ArrayList<ComponentName>(flattened.length);
+ mProtectedPackages = new ArrayList<String>(flattened.length);
+ for (String flat : flattened) {
+ ComponentName cmp = ComponentName.unflattenFromString(flat);
+ if (cmp != null) {
+ mProtectedApps.add(cmp);
+ mProtectedPackages.add(cmp.getPackageName());
+ }
+ }
+ }
+
public void filterAppsWithoutInvalidate() {
+ updateProtectedAppsList(mLauncher);
+
mFilteredApps = new ArrayList<AppInfo>(mApps);
Iterator<AppInfo> iterator = mFilteredApps.iterator();
while (iterator.hasNext()) {
AppInfo appInfo = iterator.next();
boolean system = (appInfo.flags & AppInfo.DOWNLOADED_FLAG) == 0;
- if (mHiddenApps.contains(appInfo.componentName) ||
+ if (mProtectedApps.contains(appInfo.componentName) ||
(system && !getShowSystemApps()) ||
(!system && !getShowDownloadedApps())) {
iterator.remove();
@@ -2046,6 +2116,8 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
}
public void filterWidgetsWithoutInvalidate() {
+ updateProtectedAppsList(mLauncher);
+
mFilteredWidgets = new ArrayList<Object>(mWidgets);
Iterator<Object> iterator = mFilteredWidgets.iterator();
@@ -2074,7 +2146,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
flags = 0;
}
boolean system = (flags & AppInfo.DOWNLOADED_FLAG) == 0;
- if (mHiddenPackages.contains(packageName) ||
+ if (mProtectedPackages.contains(packageName) ||
(system && !getShowSystemApps()) ||
(!system && !getShowDownloadedApps())) {
iterator.remove();
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index 659b2b9d9..c9448850e 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -20,7 +20,6 @@ import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
-import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.Region;
import android.graphics.Region.Op;
@@ -87,7 +86,7 @@ public class BubbleTextView extends TextView {
// Ensure we are using the right text size
LauncherAppState app = LauncherAppState.getInstance();
DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
- setTextSize(TypedValue.COMPLEX_UNIT_SP, grid.iconTextSize);
+ setTextSize(TypedValue.COMPLEX_UNIT_PX, grid.iconTextSizePx);
setTextColor(getResources().getColor(R.color.workspace_icon_text_color));
}
@@ -111,7 +110,7 @@ public class BubbleTextView extends TextView {
Bitmap b = info.getIcon(iconCache);
setCompoundDrawables(null,
Utilities.createIconDrawable(b), null, null);
- setCompoundDrawablePadding((int) ((grid.folderIconSizePx - grid.iconSizePx) / 2f));
+ setCompoundDrawablePadding(grid.iconDrawablePaddingPx);
setText(info.title);
setTag(info);
}
@@ -203,6 +202,10 @@ public class BubbleTextView extends TextView {
destCanvas.restore();
}
+ public void setGlowColor(int color) {
+ mFocusedOutlineColor = mFocusedGlowColor = mPressedOutlineColor = mPressedGlowColor = color;
+ }
+
/**
* Returns a new bitmap to be used as the object outline, e.g. to visualize the drop location.
* Responsibility for the bitmap is transferred to the caller.
diff --git a/src/com/android/launcher3/BuildInfo.java b/src/com/android/launcher3/BuildInfo.java
new file mode 100644
index 000000000..b49ee0d9b
--- /dev/null
+++ b/src/com/android/launcher3/BuildInfo.java
@@ -0,0 +1,32 @@
+package com.android.launcher3;
+
+import android.text.TextUtils;
+import android.util.Log;
+
+public class BuildInfo {
+ private static final boolean DBG = false;
+ private static final String TAG = "BuildInfo";
+
+ public boolean isDogfoodBuild() {
+ return false;
+ }
+
+ public static BuildInfo loadByName(String className) {
+ if (TextUtils.isEmpty(className)) return new BuildInfo();
+
+ if (DBG) Log.d(TAG, "Loading BuildInfo: " + className);
+ try {
+ Class<?> cls = Class.forName(className);
+ return (BuildInfo) cls.newInstance();
+ } catch (ClassNotFoundException e) {
+ Log.e(TAG, "Bad BuildInfo class", e);
+ } catch (InstantiationException e) {
+ Log.e(TAG, "Bad BuildInfo class", e);
+ } catch (IllegalAccessException e) {
+ Log.e(TAG, "Bad BuildInfo class", e);
+ } catch (ClassCastException e) {
+ Log.e(TAG, "Bad BuildInfo class", e);
+ }
+ return new BuildInfo();
+ }
+}
diff --git a/src/com/android/launcher3/ButtonDropTarget.java b/src/com/android/launcher3/ButtonDropTarget.java
index d51ae46e8..019f86c21 100644
--- a/src/com/android/launcher3/ButtonDropTarget.java
+++ b/src/com/android/launcher3/ButtonDropTarget.java
@@ -25,8 +25,6 @@ import android.util.AttributeSet;
import android.view.View;
import android.widget.TextView;
-import com.android.launcher3.R;
-
/**
* Implements a DropTarget.
diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java
index dc2db8773..373617145 100644
--- a/src/com/android/launcher3/CellLayout.java
+++ b/src/com/android/launcher3/CellLayout.java
@@ -74,6 +74,7 @@ public class CellLayout extends ViewGroup {
private int mHeightGap;
private int mMaxGap;
private boolean mScrollingTransformsDirty = false;
+ private boolean mDropPending = false;
private final Rect mRect = new Rect();
private final CellInfo mCellInfo = new CellInfo();
@@ -97,6 +98,7 @@ public class CellLayout extends ViewGroup {
private int mForegroundAlpha = 0;
private float mBackgroundAlpha;
private float mBackgroundAlphaMultiplier = 1.0f;
+ private boolean mDrawBackground = true;
private Drawable mNormalBackground;
private Drawable mActiveGlowBackground;
@@ -130,8 +132,8 @@ public class CellLayout extends ViewGroup {
private HashMap<CellLayout.LayoutParams, Animator> mReorderAnimators = new
HashMap<CellLayout.LayoutParams, Animator>();
- private HashMap<View, ReorderHintAnimation>
- mShakeAnimators = new HashMap<View, ReorderHintAnimation>();
+ private HashMap<View, ReorderPreviewAnimation>
+ mShakeAnimators = new HashMap<View, ReorderPreviewAnimation>();
private boolean mItemPlacementDirty = false;
@@ -146,19 +148,20 @@ public class CellLayout extends ViewGroup {
private boolean mIsHotseat = false;
private float mHotseatScale = 1f;
- public static final int MODE_DRAG_OVER = 0;
- public static final int MODE_ON_DROP = 1;
- public static final int MODE_ON_DROP_EXTERNAL = 2;
- public static final int MODE_ACCEPT_DROP = 3;
+ public static final int MODE_SHOW_REORDER_HINT = 0;
+ public static final int MODE_DRAG_OVER = 1;
+ public static final int MODE_ON_DROP = 2;
+ public static final int MODE_ON_DROP_EXTERNAL = 3;
+ public static final int MODE_ACCEPT_DROP = 4;
private static final boolean DESTRUCTIVE_REORDER = false;
private static final boolean DEBUG_VISUALIZE_OCCUPIED = false;
static final int LANDSCAPE = 0;
static final int PORTRAIT = 1;
- private static final float REORDER_HINT_MAGNITUDE = 0.12f;
+ private static final float REORDER_PREVIEW_MAGNITUDE = 0.12f;
private static final int REORDER_ANIMATION_DURATION = 150;
- private float mReorderHintAnimationMagnitude;
+ private float mReorderPreviewAnimationMagnitude;
private ArrayList<View> mIntersectingViews = new ArrayList<View>();
private Rect mOccupiedRect = new Rect();
@@ -212,7 +215,7 @@ public class CellLayout extends ViewGroup {
setAlwaysDrawnWithCacheEnabled(false);
final Resources res = getResources();
- mHotseatScale = (float) grid.hotseatIconSize / grid.iconSize;
+ mHotseatScale = (float) grid.hotseatIconSizePx / grid.iconSizePx;
mNormalBackground = res.getDrawable(R.drawable.screenpanel);
mActiveGlowBackground = res.getDrawable(R.drawable.screenpanel_hover);
@@ -222,7 +225,7 @@ public class CellLayout extends ViewGroup {
mForegroundPadding =
res.getDimensionPixelSize(R.dimen.workspace_overscroll_drawable_padding);
- mReorderHintAnimationMagnitude = (REORDER_HINT_MAGNITUDE *
+ mReorderPreviewAnimationMagnitude = (REORDER_PREVIEW_MAGNITUDE *
grid.iconSizePx);
mNormalBackground.setFilterBitmap(true);
@@ -330,6 +333,14 @@ public class CellLayout extends ViewGroup {
mShortcutsAndWidgets.setInvertIfRtl(invert);
}
+ public void setDropPending(boolean pending) {
+ mDropPending = pending;
+ }
+
+ public boolean isDropPending() {
+ return mDropPending;
+ }
+
private void invalidateBubbleTextView(BubbleTextView icon) {
final int padding = icon.getPressedOrFocusedBackgroundPadding();
invalidate(icon.getLeft() + getPaddingLeft() - padding,
@@ -376,6 +387,10 @@ public class CellLayout extends ViewGroup {
mUseActiveGlowBackground = use;
}
+ void disableBackground() {
+ mDrawBackground = false;
+ }
+
boolean getIsDragOverlapping() {
return mIsDragOverlapping;
}
@@ -404,7 +419,7 @@ public class CellLayout extends ViewGroup {
// When we're small, we are either drawn normally or in the "accepts drops" state (during
// a drag). However, we also drag the mini hover background *over* one of those two
// backgrounds
- if (mBackgroundAlpha > 0.0f) {
+ if (mDrawBackground && mBackgroundAlpha > 0.0f) {
Drawable bg;
if (mUseActiveGlowBackground) {
@@ -2076,6 +2091,8 @@ public class CellLayout extends ViewGroup {
}
}
+ solution.intersectingViews = new ArrayList<View>(mIntersectingViews);
+
// First we try to find a solution which respects the push mechanic. That is,
// we try to find a solution such that no displaced item travels through another item
// without also displacing that item.
@@ -2124,8 +2141,9 @@ public class CellLayout extends ViewGroup {
}
}
- ItemConfiguration simpleSwap(int pixelX, int pixelY, int minSpanX, int minSpanY, int spanX,
- int spanY, int[] direction, View dragView, boolean decX, ItemConfiguration solution) {
+ ItemConfiguration findReorderSolution(int pixelX, int pixelY, int minSpanX, int minSpanY,
+ int spanX, int spanY, int[] direction, View dragView, boolean decX,
+ ItemConfiguration solution) {
// Copy the current state into the solution. This solution will be manipulated as necessary.
copyCurrentStateToSolution(solution, false);
// Copy the current occupied array into the temporary occupied array. This array will be
@@ -2147,11 +2165,11 @@ public class CellLayout extends ViewGroup {
// We try shrinking the widget down to size in an alternating pattern, shrink 1 in
// x, then 1 in y etc.
if (spanX > minSpanX && (minSpanY == spanY || decX)) {
- return simpleSwap(pixelX, pixelY, minSpanX, minSpanY, spanX - 1, spanY, direction,
- dragView, false, solution);
+ return findReorderSolution(pixelX, pixelY, minSpanX, minSpanY, spanX - 1, spanY,
+ direction, dragView, false, solution);
} else if (spanY > minSpanY) {
- return simpleSwap(pixelX, pixelY, minSpanX, minSpanY, spanX, spanY - 1, direction,
- dragView, true, solution);
+ return findReorderSolution(pixelX, pixelY, minSpanX, minSpanY, spanX, spanY - 1,
+ direction, dragView, true, solution);
}
solution.isSolution = false;
} else {
@@ -2231,25 +2249,30 @@ public class CellLayout extends ViewGroup {
}
}
- // This method starts or changes the reorder hint animations
- private void beginOrAdjustHintAnimations(ItemConfiguration solution, View dragView, int delay) {
+
+ // This method starts or changes the reorder preview animations
+ private void beginOrAdjustReorderPreviewAnimations(ItemConfiguration solution,
+ View dragView, int delay, int mode) {
int childCount = mShortcutsAndWidgets.getChildCount();
for (int i = 0; i < childCount; i++) {
View child = mShortcutsAndWidgets.getChildAt(i);
if (child == dragView) continue;
CellAndSpan c = solution.map.get(child);
+ boolean skip = mode == ReorderPreviewAnimation.MODE_HINT && solution.intersectingViews
+ != null && !solution.intersectingViews.contains(child);
+
LayoutParams lp = (LayoutParams) child.getLayoutParams();
- if (c != null) {
- ReorderHintAnimation rha = new ReorderHintAnimation(child, lp.cellX, lp.cellY,
- c.x, c.y, c.spanX, c.spanY);
+ if (c != null && !skip) {
+ ReorderPreviewAnimation rha = new ReorderPreviewAnimation(child, mode, lp.cellX,
+ lp.cellY, c.x, c.y, c.spanX, c.spanY);
rha.animate();
}
}
}
- // Class which represents the reorder hint animations. These animations show that an item is
+ // Class which represents the reorder preview animations. These animations show that an item is
// in a temporary state, and hint at where the item will return to.
- class ReorderHintAnimation {
+ class ReorderPreviewAnimation {
View child;
float finalDeltaX;
float finalDeltaY;
@@ -2257,11 +2280,18 @@ public class CellLayout extends ViewGroup {
float initDeltaY;
float finalScale;
float initScale;
- private static final int DURATION = 300;
+ int mode;
+ boolean repeating = false;
+ private static final int PREVIEW_DURATION = 300;
+ private static final int HINT_DURATION = Workspace.REORDER_TIMEOUT;
+
+ public static final int MODE_HINT = 0;
+ public static final int MODE_PREVIEW = 1;
+
Animator a;
- public ReorderHintAnimation(View child, int cellX0, int cellY0, int cellX1, int cellY1,
- int spanX, int spanY) {
+ public ReorderPreviewAnimation(View child, int mode, int cellX0, int cellY0, int cellX1,
+ int cellY1, int spanX, int spanY) {
regionToCenterPoint(cellX0, cellY0, spanX, spanY, mTmpPoint);
final int x0 = mTmpPoint[0];
final int y0 = mTmpPoint[1];
@@ -2272,20 +2302,22 @@ public class CellLayout extends ViewGroup {
final int dY = y1 - y0;
finalDeltaX = 0;
finalDeltaY = 0;
+ int dir = mode == MODE_HINT ? -1 : 1;
if (dX == dY && dX == 0) {
} else {
if (dY == 0) {
- finalDeltaX = - Math.signum(dX) * mReorderHintAnimationMagnitude;
+ finalDeltaX = - dir * Math.signum(dX) * mReorderPreviewAnimationMagnitude;
} else if (dX == 0) {
- finalDeltaY = - Math.signum(dY) * mReorderHintAnimationMagnitude;
+ finalDeltaY = - dir * Math.signum(dY) * mReorderPreviewAnimationMagnitude;
} else {
double angle = Math.atan( (float) (dY) / dX);
- finalDeltaX = (int) (- Math.signum(dX) *
- Math.abs(Math.cos(angle) * mReorderHintAnimationMagnitude));
- finalDeltaY = (int) (- Math.signum(dY) *
- Math.abs(Math.sin(angle) * mReorderHintAnimationMagnitude));
+ finalDeltaX = (int) (- dir * Math.signum(dX) *
+ Math.abs(Math.cos(angle) * mReorderPreviewAnimationMagnitude));
+ finalDeltaY = (int) (- dir * Math.signum(dY) *
+ Math.abs(Math.sin(angle) * mReorderPreviewAnimationMagnitude));
}
}
+ this.mode = mode;
initDeltaX = child.getTranslationX();
initDeltaY = child.getTranslationY();
finalScale = getChildrenScale() - 4.0f / child.getWidth();
@@ -2295,7 +2327,7 @@ public class CellLayout extends ViewGroup {
void animate() {
if (mShakeAnimators.containsKey(child)) {
- ReorderHintAnimation oldAnimation = mShakeAnimators.get(child);
+ ReorderPreviewAnimation oldAnimation = mShakeAnimators.get(child);
oldAnimation.cancel();
mShakeAnimators.remove(child);
if (finalDeltaX == 0 && finalDeltaY == 0) {
@@ -2310,14 +2342,15 @@ public class CellLayout extends ViewGroup {
a = va;
va.setRepeatMode(ValueAnimator.REVERSE);
va.setRepeatCount(ValueAnimator.INFINITE);
- va.setDuration(DURATION);
+ va.setDuration(mode == MODE_HINT ? HINT_DURATION : PREVIEW_DURATION);
va.setStartDelay((int) (Math.random() * 60));
va.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float r = ((Float) animation.getAnimatedValue()).floatValue();
- float x = r * finalDeltaX + (1 - r) * initDeltaX;
- float y = r * finalDeltaY + (1 - r) * initDeltaY;
+ float r1 = (mode == MODE_HINT && repeating) ? 1.0f : r;
+ float x = r1 * finalDeltaX + (1 - r1) * initDeltaX;
+ float y = r1 * finalDeltaY + (1 - r1) * initDeltaY;
child.setTranslationX(x);
child.setTranslationY(y);
float s = r * finalScale + (1 - r) * initScale;
@@ -2331,6 +2364,7 @@ public class CellLayout extends ViewGroup {
initDeltaX = 0;
initDeltaY = 0;
initScale = getChildrenScale();
+ repeating = true;
}
});
mShakeAnimators.put(child, this);
@@ -2362,8 +2396,8 @@ public class CellLayout extends ViewGroup {
}
}
- private void completeAndClearReorderHintAnimations() {
- for (ReorderHintAnimation a: mShakeAnimators.values()) {
+ private void completeAndClearReorderPreviewAnimations() {
+ for (ReorderPreviewAnimation a: mShakeAnimators.values()) {
a.completeAnimationImmediately();
}
mShakeAnimators.clear();
@@ -2506,20 +2540,21 @@ public class CellLayout extends ViewGroup {
}
void revertTempState() {
- if (!isItemPlacementDirty() || DESTRUCTIVE_REORDER) return;
- final int count = mShortcutsAndWidgets.getChildCount();
- for (int i = 0; i < count; i++) {
- View child = mShortcutsAndWidgets.getChildAt(i);
- LayoutParams lp = (LayoutParams) child.getLayoutParams();
- if (lp.tmpCellX != lp.cellX || lp.tmpCellY != lp.cellY) {
- lp.tmpCellX = lp.cellX;
- lp.tmpCellY = lp.cellY;
- animateChildToPosition(child, lp.cellX, lp.cellY, REORDER_ANIMATION_DURATION,
- 0, false, false);
+ completeAndClearReorderPreviewAnimations();
+ if (isItemPlacementDirty() && !DESTRUCTIVE_REORDER) {
+ final int count = mShortcutsAndWidgets.getChildCount();
+ for (int i = 0; i < count; i++) {
+ View child = mShortcutsAndWidgets.getChildAt(i);
+ LayoutParams lp = (LayoutParams) child.getLayoutParams();
+ if (lp.tmpCellX != lp.cellX || lp.tmpCellY != lp.cellY) {
+ lp.tmpCellX = lp.cellX;
+ lp.tmpCellY = lp.cellY;
+ animateChildToPosition(child, lp.cellX, lp.cellY, REORDER_ANIMATION_DURATION,
+ 0, false, false);
+ }
}
+ setItemPlacementDirty(false);
}
- completeAndClearReorderHintAnimations();
- setItemPlacementDirty(false);
}
boolean createAreaForResize(int cellX, int cellY, int spanX, int spanY,
@@ -2528,7 +2563,7 @@ public class CellLayout extends ViewGroup {
regionToCenterPoint(cellX, cellY, spanX, spanY, pixelXY);
// First we determine if things have moved enough to cause a different layout
- ItemConfiguration swapSolution = simpleSwap(pixelXY[0], pixelXY[1], spanX, spanY,
+ ItemConfiguration swapSolution = findReorderSolution(pixelXY[0], pixelXY[1], spanX, spanY,
spanX, spanY, direction, dragView, true, new ItemConfiguration());
setUseTempCoords(true);
@@ -2542,18 +2577,18 @@ public class CellLayout extends ViewGroup {
if (commit) {
commitTempPlacement();
- completeAndClearReorderHintAnimations();
+ completeAndClearReorderPreviewAnimations();
setItemPlacementDirty(false);
} else {
- beginOrAdjustHintAnimations(swapSolution, dragView,
- REORDER_ANIMATION_DURATION);
+ beginOrAdjustReorderPreviewAnimations(swapSolution, dragView,
+ REORDER_ANIMATION_DURATION, ReorderPreviewAnimation.MODE_PREVIEW);
}
mShortcutsAndWidgets.requestLayout();
}
return swapSolution.isSolution;
}
- int[] createArea(int pixelX, int pixelY, int minSpanX, int minSpanY, int spanX, int spanY,
+ int[] performReorder(int pixelX, int pixelY, int minSpanX, int minSpanY, int spanX, int spanY,
View dragView, int[] result, int resultSpan[], int mode) {
// First we determine if things have moved enough to cause a different layout
result = findNearestArea(pixelX, pixelY, spanX, spanY, result);
@@ -2580,7 +2615,8 @@ public class CellLayout extends ViewGroup {
mPreviousReorderDirection[1] = mDirectionVector[1];
}
- ItemConfiguration swapSolution = simpleSwap(pixelX, pixelY, minSpanX, minSpanY,
+ // Find a solution involving pushing / displacing any items in the way
+ ItemConfiguration swapSolution = findReorderSolution(pixelX, pixelY, minSpanX, minSpanY,
spanX, spanY, mDirectionVector, dragView, true, new ItemConfiguration());
// We attempt the approach which doesn't shuffle views at all
@@ -2588,12 +2624,29 @@ public class CellLayout extends ViewGroup {
minSpanY, spanX, spanY, dragView, new ItemConfiguration());
ItemConfiguration finalSolution = null;
+
+ // If the reorder solution requires resizing (shrinking) the item being dropped, we instead
+ // favor a solution in which the item is not resized, but
if (swapSolution.isSolution && swapSolution.area() >= noShuffleSolution.area()) {
finalSolution = swapSolution;
} else if (noShuffleSolution.isSolution) {
finalSolution = noShuffleSolution;
}
+ if (mode == MODE_SHOW_REORDER_HINT) {
+ if (finalSolution != null) {
+ beginOrAdjustReorderPreviewAnimations(finalSolution, dragView, 0,
+ ReorderPreviewAnimation.MODE_HINT);
+ result[0] = finalSolution.dragViewX;
+ result[1] = finalSolution.dragViewY;
+ resultSpan[0] = finalSolution.dragViewSpanX;
+ resultSpan[1] = finalSolution.dragViewSpanY;
+ } else {
+ result[0] = result[1] = resultSpan[0] = resultSpan[1] = -1;
+ }
+ return result;
+ }
+
boolean foundSolution = true;
if (!DESTRUCTIVE_REORDER) {
setUseTempCoords(true);
@@ -2618,11 +2671,11 @@ public class CellLayout extends ViewGroup {
if (!DESTRUCTIVE_REORDER &&
(mode == MODE_ON_DROP || mode == MODE_ON_DROP_EXTERNAL)) {
commitTempPlacement();
- completeAndClearReorderHintAnimations();
+ completeAndClearReorderPreviewAnimations();
setItemPlacementDirty(false);
} else {
- beginOrAdjustHintAnimations(finalSolution, dragView,
- REORDER_ANIMATION_DURATION);
+ beginOrAdjustReorderPreviewAnimations(finalSolution, dragView,
+ REORDER_ANIMATION_DURATION, ReorderPreviewAnimation.MODE_PREVIEW);
}
}
} else {
@@ -2649,6 +2702,7 @@ public class CellLayout extends ViewGroup {
HashMap<View, CellAndSpan> map = new HashMap<View, CellAndSpan>();
private HashMap<View, CellAndSpan> savedMap = new HashMap<View, CellAndSpan>();
ArrayList<View> sortedViews = new ArrayList<View>();
+ ArrayList<View> intersectingViews;
boolean isSolution = false;
int dragViewX, dragViewY, dragViewSpanX, dragViewSpanY;
@@ -3108,7 +3162,8 @@ out: for (int i = x; i < x + spanX - 1 && x < xCount; i++) {
if (x < mCountX && y < mCountY) {
return mOccupied[x][y];
} else {
- throw new RuntimeException("Position exceeds the bound of this CellLayout");
+ Log.w(TAG, "Position exceeds the bound of this CellLayout");
+ return false;
}
}
diff --git a/src/com/android/launcher3/Cling.java b/src/com/android/launcher3/Cling.java
index 01a54b4e1..a6139ccbc 100644
--- a/src/com/android/launcher3/Cling.java
+++ b/src/com/android/launcher3/Cling.java
@@ -18,8 +18,8 @@ package com.android.launcher3;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
-import android.content.Context;
import android.content.ComponentName;
+import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.content.res.TypedArray;
@@ -30,6 +30,7 @@ import android.util.DisplayMetrics;
import android.view.FocusFinder;
import android.view.MotionEvent;
import android.view.View;
+import android.view.ViewGroup;
import android.view.animation.AccelerateInterpolator;
import android.widget.FrameLayout;
import android.widget.TextView;
@@ -37,11 +38,6 @@ import android.widget.TextView;
public class Cling extends FrameLayout implements Insettable, View.OnClickListener,
View.OnLongClickListener, View.OnTouchListener {
- static final String FIRST_RUN_CLING_DISMISSED_KEY = "cling_gel.first_run.dismissed";
- static final String WORKSPACE_CLING_DISMISSED_KEY = "cling_gel.workspace.dismissed";
- static final String FOLDER_CLING_DISMISSED_KEY = "cling_gel.folder.dismissed";
- static final String ALL_APPS_CLING_DISMISSED_KEY = "cling_gel.all_apps.dismissed";
-
private static String FIRST_RUN_PORTRAIT = "first_run_portrait";
private static String FIRST_RUN_LANDSCAPE = "first_run_landscape";
@@ -50,16 +46,24 @@ public class Cling extends FrameLayout implements Insettable, View.OnClickListen
private static String WORKSPACE_LARGE = "workspace_large";
private static String WORKSPACE_CUSTOM = "workspace_custom";
+ private static String MIGRATION_PORTRAIT = "migration_portrait";
+ private static String MIGRATION_LANDSCAPE = "migration_landscape";
+
+ private static String MIGRATION_WORKSPACE_PORTRAIT = "migration_workspace_portrait";
+ private static String MIGRATION_WORKSPACE_LARGE_PORTRAIT = "migration_workspace_large_portrait";
+ private static String MIGRATION_WORKSPACE_LANDSCAPE = "migration_workspace_landscape";
+
private static String FOLDER_PORTRAIT = "folder_portrait";
private static String FOLDER_LANDSCAPE = "folder_landscape";
private static String FOLDER_LARGE = "folder_large";
- private static String ALL_APPS = "all_apps";
-
private static float FIRST_RUN_CIRCLE_BUFFER_DPS = 60;
+ private static float FIRST_RUN_MAX_CIRCLE_RADIUS_DPS = 180;
private static float WORKSPACE_INNER_CIRCLE_RADIUS_DPS = 50;
private static float WORKSPACE_OUTER_CIRCLE_RADIUS_DPS = 60;
private static float WORKSPACE_CIRCLE_Y_OFFSET_DPS = 30;
+ private static float MIGRATION_WORKSPACE_INNER_CIRCLE_RADIUS_DPS = 42;
+ private static float MIGRATION_WORKSPACE_OUTER_CIRCLE_RADIUS_DPS = 46;
private Launcher mLauncher;
private boolean mIsInitialized;
@@ -73,6 +77,7 @@ public class Cling extends FrameLayout implements Insettable, View.OnClickListen
private Rect mFocusedHotseatAppBounds;
private Paint mErasePaint;
+ private Paint mBorderPaint;
private Paint mBubblePaint;
private Paint mDotPaint;
@@ -80,7 +85,6 @@ public class Cling extends FrameLayout implements Insettable, View.OnClickListen
private int mBackgroundColor;
private final Rect mInsets = new Rect();
- private int[] mPosition;
public Cling(Context context) {
this(context, null, 0);
@@ -105,7 +109,7 @@ public class Cling extends FrameLayout implements Insettable, View.OnClickListen
if (!mIsInitialized) {
mLauncher = l;
mScrimView = scrim;
- mBackgroundColor = 0xdd000000;
+ mBackgroundColor = 0xcc000000;
setOnLongClickListener(this);
setOnClickListener(this);
setOnTouchListener(this);
@@ -116,6 +120,10 @@ public class Cling extends FrameLayout implements Insettable, View.OnClickListen
mErasePaint.setAlpha(0);
mErasePaint.setAntiAlias(true);
+ mBorderPaint = new Paint();
+ mBorderPaint.setColor(0xFFFFFFFF);
+ mBorderPaint.setAntiAlias(true);
+
int circleColor = getResources().getColor(
R.color.first_run_cling_circle_background_color);
mBubblePaint = new Paint();
@@ -130,20 +138,15 @@ public class Cling extends FrameLayout implements Insettable, View.OnClickListen
}
}
- void setPunchThroughForView(View view) {
- mPosition = new int[2];
- view.getLocationOnScreen(mPosition);
- mPosition[0] += view.getWidth() / 2;
- mPosition[1] += view.getHeight() / 2;
- }
-
void setFocusedHotseatApp(int drawableId, int appRank, ComponentName cn, String title,
String description) {
// Get the app to draw
Resources r = getResources();
int appIconId = drawableId;
Hotseat hotseat = mLauncher.getHotseat();
- if (hotseat != null && appIconId > -1 && appRank > -1 && !title.isEmpty() &&
+ // Skip the focused app in the large layouts
+ if (!mDrawIdentifier.equals(WORKSPACE_LARGE) &&
+ hotseat != null && appIconId > -1 && appRank > -1 && !title.isEmpty() &&
!description.isEmpty()) {
// Set the app bounds
int x = hotseat.getCellXFromOrder(appRank);
@@ -157,7 +160,7 @@ public class Cling extends FrameLayout implements Insettable, View.OnClickListen
pos.left + Utilities.sIconTextureWidth,
pos.top + Utilities.sIconTextureHeight);
Utilities.scaleRectAboutCenter(mFocusedHotseatAppBounds,
- (grid.hotseatIconSize / grid.iconSize));
+ ((float) grid.hotseatIconSizePx / grid.iconSizePx));
// Set the title
TextView v = (TextView) findViewById(R.id.focused_hotseat_app_title);
@@ -177,6 +180,82 @@ public class Cling extends FrameLayout implements Insettable, View.OnClickListen
}
}
+ void setOpenFolderRect(Rect r) {
+ if (mDrawIdentifier.equals(FOLDER_LANDSCAPE) ||
+ mDrawIdentifier.equals(FOLDER_LARGE)) {
+ ViewGroup vg = (ViewGroup) findViewById(R.id.folder_bubble);
+ ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) vg.getLayoutParams();
+ lp.topMargin = r.top - mInsets.bottom;
+ lp.leftMargin = r.right;
+ vg.setLayoutDirection(View.LAYOUT_DIRECTION_LTR);
+ vg.requestLayout();
+ }
+ }
+
+ void updateMigrationWorkspaceBubblePosition() {
+ DisplayMetrics metrics = new DisplayMetrics();
+ mLauncher.getWindowManager().getDefaultDisplay().getMetrics(metrics);
+
+ // Get the page indicator bounds
+ LauncherAppState app = LauncherAppState.getInstance();
+ DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
+ Rect pageIndicatorBounds = grid.getWorkspacePageIndicatorBounds(mInsets);
+
+ if (mDrawIdentifier.equals(MIGRATION_WORKSPACE_PORTRAIT)) {
+ View bubble = findViewById(R.id.migration_workspace_cling_bubble);
+ ViewGroup.MarginLayoutParams lp =
+ (ViewGroup.MarginLayoutParams) bubble.getLayoutParams();
+ lp.bottomMargin = grid.heightPx - pageIndicatorBounds.top;
+ bubble.requestLayout();
+ } else if (mDrawIdentifier.equals(MIGRATION_WORKSPACE_LARGE_PORTRAIT)) {
+ View bubble = findViewById(R.id.content);
+ ViewGroup.MarginLayoutParams lp =
+ (ViewGroup.MarginLayoutParams) bubble.getLayoutParams();
+ lp.bottomMargin = grid.heightPx - pageIndicatorBounds.top;
+ bubble.requestLayout();
+ } else if (mDrawIdentifier.equals(MIGRATION_WORKSPACE_LANDSCAPE)) {
+ View bubble = findViewById(R.id.content);
+ ViewGroup.MarginLayoutParams lp =
+ (ViewGroup.MarginLayoutParams) bubble.getLayoutParams();
+ if (grid.isLayoutRtl) {
+ lp.leftMargin = pageIndicatorBounds.right;
+ } else {
+ lp.rightMargin = (grid.widthPx - pageIndicatorBounds.left);
+ }
+ bubble.requestLayout();
+ }
+ }
+
+ void updateWorkspaceBubblePosition() {
+ DisplayMetrics metrics = new DisplayMetrics();
+ mLauncher.getWindowManager().getDefaultDisplay().getMetrics(metrics);
+
+ // Get the cut-out bounds
+ LauncherAppState app = LauncherAppState.getInstance();
+ DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
+ Rect cutOutBounds = getWorkspaceCutOutBounds(metrics);
+
+ if (mDrawIdentifier.equals(WORKSPACE_LARGE)) {
+ View bubble = findViewById(R.id.workspace_cling_bubble);
+ ViewGroup.MarginLayoutParams lp =
+ (ViewGroup.MarginLayoutParams) bubble.getLayoutParams();
+ lp.bottomMargin = grid.heightPx - cutOutBounds.top - mInsets.bottom;
+ bubble.requestLayout();
+ }
+ }
+
+ private Rect getWorkspaceCutOutBounds(DisplayMetrics metrics) {
+ int halfWidth = metrics.widthPixels / 2;
+ int halfHeight = metrics.heightPixels / 2;
+ int yOffset = DynamicGrid.pxFromDp(WORKSPACE_CIRCLE_Y_OFFSET_DPS, metrics);
+ if (mDrawIdentifier.equals(WORKSPACE_LARGE)) {
+ yOffset = 0;
+ }
+ int radius = DynamicGrid.pxFromDp(WORKSPACE_OUTER_CIRCLE_RADIUS_DPS, metrics);
+ return new Rect(halfWidth - radius, halfHeight - yOffset - radius, halfWidth + radius,
+ halfHeight - yOffset + radius);
+ }
+
void show(boolean animate, int duration) {
setVisibility(View.VISIBLE);
setLayerType(View.LAYER_TYPE_HARDWARE, null);
@@ -184,7 +263,9 @@ public class Cling extends FrameLayout implements Insettable, View.OnClickListen
mDrawIdentifier.equals(WORKSPACE_LANDSCAPE) ||
mDrawIdentifier.equals(WORKSPACE_LARGE) ||
mDrawIdentifier.equals(WORKSPACE_CUSTOM) ||
- mDrawIdentifier.equals(ALL_APPS)) {
+ mDrawIdentifier.equals(MIGRATION_WORKSPACE_PORTRAIT) ||
+ mDrawIdentifier.equals(MIGRATION_WORKSPACE_LARGE_PORTRAIT) ||
+ mDrawIdentifier.equals(MIGRATION_WORKSPACE_LANDSCAPE)) {
View content = getContent();
content.setAlpha(0f);
content.animate()
@@ -230,7 +311,9 @@ public class Cling extends FrameLayout implements Insettable, View.OnClickListen
void hide(final int duration, final Runnable postCb) {
if (mDrawIdentifier.equals(FIRST_RUN_PORTRAIT) ||
- mDrawIdentifier.equals(FIRST_RUN_LANDSCAPE)) {
+ mDrawIdentifier.equals(FIRST_RUN_LANDSCAPE) ||
+ mDrawIdentifier.equals(MIGRATION_PORTRAIT) ||
+ mDrawIdentifier.equals(MIGRATION_LANDSCAPE)) {
View content = getContent();
content.animate()
.alpha(0f)
@@ -311,8 +394,7 @@ public class Cling extends FrameLayout implements Insettable, View.OnClickListen
return (mDrawIdentifier.equals(WORKSPACE_PORTRAIT)
|| mDrawIdentifier.equals(WORKSPACE_LANDSCAPE)
|| mDrawIdentifier.equals(WORKSPACE_LARGE)
- || mDrawIdentifier.equals(WORKSPACE_CUSTOM)
- || mDrawIdentifier.equals(ALL_APPS));
+ || mDrawIdentifier.equals(WORKSPACE_CUSTOM));
}
@Override
@@ -353,7 +435,7 @@ public class Cling extends FrameLayout implements Insettable, View.OnClickListen
intent.setComponent(mFocusedHotseatAppComponent);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
mLauncher.startActivity(intent, null);
- mLauncher.dismissWorkspaceCling(this);
+ mLauncher.getLauncherClings().dismissWorkspaceCling(this);
}
}
}
@@ -363,10 +445,12 @@ public class Cling extends FrameLayout implements Insettable, View.OnClickListen
if (mDrawIdentifier.equals(WORKSPACE_PORTRAIT) ||
mDrawIdentifier.equals(WORKSPACE_LANDSCAPE) ||
mDrawIdentifier.equals(WORKSPACE_LARGE)) {
- mLauncher.dismissWorkspaceCling(null);
+ mLauncher.getLauncherClings().dismissWorkspaceCling(null);
return true;
- } else if (mDrawIdentifier.equals(ALL_APPS)) {
- mLauncher.dismissAllAppsCling(null);
+ } else if (mDrawIdentifier.equals(MIGRATION_WORKSPACE_PORTRAIT) ||
+ mDrawIdentifier.equals(MIGRATION_WORKSPACE_LARGE_PORTRAIT) ||
+ mDrawIdentifier.equals(MIGRATION_WORKSPACE_LANDSCAPE)) {
+ mLauncher.getLauncherClings().dismissMigrationWorkspaceCling(null);
return true;
}
return false;
@@ -377,6 +461,11 @@ public class Cling extends FrameLayout implements Insettable, View.OnClickListen
if (mIsInitialized) {
canvas.save();
+ // Get the page indicator bounds
+ LauncherAppState app = LauncherAppState.getInstance();
+ DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
+ Rect pageIndicatorBounds = grid.getWorkspacePageIndicatorBounds(mInsets);
+
// Get the background override if there is one
if (mBackground == null) {
if (mDrawIdentifier.equals(WORKSPACE_CUSTOM)) {
@@ -395,7 +484,9 @@ public class Cling extends FrameLayout implements Insettable, View.OnClickListen
} else if (mDrawIdentifier.equals(WORKSPACE_PORTRAIT) ||
mDrawIdentifier.equals(WORKSPACE_LANDSCAPE) ||
mDrawIdentifier.equals(WORKSPACE_LARGE) ||
- mDrawIdentifier.equals(ALL_APPS)) {
+ mDrawIdentifier.equals(MIGRATION_WORKSPACE_PORTRAIT) ||
+ mDrawIdentifier.equals(MIGRATION_WORKSPACE_LARGE_PORTRAIT) ||
+ mDrawIdentifier.equals(MIGRATION_WORKSPACE_LANDSCAPE)) {
// Initialize the draw buffer (to allow punching through)
eraseBg = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(),
Bitmap.Config.ARGB_8888);
@@ -421,29 +512,23 @@ public class Cling extends FrameLayout implements Insettable, View.OnClickListen
bubbleContent.getGlobalVisibleRect(bubbleRect);
mBubblePaint.setAlpha((int) (255 * alpha));
float buffer = DynamicGrid.pxFromDp(FIRST_RUN_CIRCLE_BUFFER_DPS, metrics);
+ float maxRadius = DynamicGrid.pxFromDp(FIRST_RUN_MAX_CIRCLE_RADIUS_DPS, metrics);
+ float radius = Math.min(maxRadius, (bubbleContent.getMeasuredWidth() + buffer) / 2);
canvas.drawCircle(metrics.widthPixels / 2,
- bubbleRect.centerY(),
- (bubbleContent.getMeasuredWidth() + buffer) / 2,
+ bubbleRect.centerY(), radius,
mBubblePaint);
} else if (mDrawIdentifier.equals(WORKSPACE_PORTRAIT) ||
mDrawIdentifier.equals(WORKSPACE_LANDSCAPE) ||
- mDrawIdentifier.equals(WORKSPACE_LARGE) ||
- mDrawIdentifier.equals(ALL_APPS)) {
- int offset = DynamicGrid.pxFromDp(WORKSPACE_CIRCLE_Y_OFFSET_DPS, metrics);
- mErasePaint.setAlpha((int) (128));
- int punchX = metrics.widthPixels / 2;
- int punchY = metrics.heightPixels / 2 - offset;
- if (mPosition != null) {
- punchX = mPosition[0];
- punchY = mPosition[1];
- }
- eraseCanvas.drawCircle(punchX,
- punchY,
+ mDrawIdentifier.equals(WORKSPACE_LARGE)) {
+ Rect cutOutBounds = getWorkspaceCutOutBounds(metrics);
+ // Draw the outer circle
+ mErasePaint.setAlpha(128);
+ eraseCanvas.drawCircle(cutOutBounds.centerX(), cutOutBounds.centerY(),
DynamicGrid.pxFromDp(WORKSPACE_OUTER_CIRCLE_RADIUS_DPS, metrics),
mErasePaint);
+ // Draw the inner circle
mErasePaint.setAlpha(0);
- eraseCanvas.drawCircle(punchX,
- punchY,
+ eraseCanvas.drawCircle(cutOutBounds.centerX(), cutOutBounds.centerY(),
DynamicGrid.pxFromDp(WORKSPACE_INNER_CIRCLE_RADIUS_DPS, metrics),
mErasePaint);
canvas.drawBitmap(eraseBg, 0, 0, null);
@@ -458,8 +543,25 @@ public class Cling extends FrameLayout implements Insettable, View.OnClickListen
mFocusedHotseatApp.setAlpha((int) (255 * alpha));
mFocusedHotseatApp.draw(canvas);
}
+ } else if (mDrawIdentifier.equals(MIGRATION_WORKSPACE_PORTRAIT) ||
+ mDrawIdentifier.equals(MIGRATION_WORKSPACE_LARGE_PORTRAIT) ||
+ mDrawIdentifier.equals(MIGRATION_WORKSPACE_LANDSCAPE)) {
+ int offset = DynamicGrid.pxFromDp(WORKSPACE_CIRCLE_Y_OFFSET_DPS, metrics);
+ // Draw the outer circle
+ eraseCanvas.drawCircle(pageIndicatorBounds.centerX(),
+ pageIndicatorBounds.centerY(),
+ DynamicGrid.pxFromDp(MIGRATION_WORKSPACE_OUTER_CIRCLE_RADIUS_DPS, metrics),
+ mBorderPaint);
+ // Draw the inner circle
+ mErasePaint.setAlpha(0);
+ eraseCanvas.drawCircle(pageIndicatorBounds.centerX(),
+ pageIndicatorBounds.centerY(),
+ DynamicGrid.pxFromDp(MIGRATION_WORKSPACE_INNER_CIRCLE_RADIUS_DPS, metrics),
+ mErasePaint);
+ canvas.drawBitmap(eraseBg, 0, 0, null);
+ eraseCanvas.setBitmap(null);
+ eraseBg = null;
}
-
canvas.restore();
}
diff --git a/src/com/android/launcher3/DeferredHandler.java b/src/com/android/launcher3/DeferredHandler.java
index 92ecf9643..a2d121d63 100644
--- a/src/com/android/launcher3/DeferredHandler.java
+++ b/src/com/android/launcher3/DeferredHandler.java
@@ -21,6 +21,7 @@ import android.os.Looper;
import android.os.Message;
import android.os.MessageQueue;
import android.util.Pair;
+
import java.util.LinkedList;
import java.util.ListIterator;
diff --git a/src/com/android/launcher3/DeleteDropTarget.java b/src/com/android/launcher3/DeleteDropTarget.java
index 150d958a8..94a335f5d 100644
--- a/src/com/android/launcher3/DeleteDropTarget.java
+++ b/src/com/android/launcher3/DeleteDropTarget.java
@@ -29,6 +29,7 @@ import android.content.res.Resources;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.drawable.TransitionDrawable;
+import android.os.AsyncTask;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewConfiguration;
@@ -95,7 +96,7 @@ public class DeleteDropTarget extends ButtonDropTarget {
}
private boolean isAllAppsApplication(DragSource source, Object info) {
- return (source instanceof AppsCustomizePagedView) && (info instanceof AppInfo);
+ return source.supportsAppInfoDropTarget() && (info instanceof AppInfo);
}
private boolean isAllAppsWidget(DragSource source, Object info) {
if (source instanceof AppsCustomizePagedView) {
@@ -151,12 +152,12 @@ public class DeleteDropTarget extends ButtonDropTarget {
return true;
}
- if (!AppsCustomizePagedView.DISABLE_ALL_APPS &&
+ if (!LauncherAppState.isDisableAllApps() &&
item.itemType == LauncherSettings.Favorites.ITEM_TYPE_FOLDER) {
return true;
}
- if (!AppsCustomizePagedView.DISABLE_ALL_APPS &&
+ if (!LauncherAppState.isDisableAllApps() &&
item.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION &&
item instanceof AppInfo) {
AppInfo appInfo = (AppInfo) info;
@@ -165,7 +166,7 @@ public class DeleteDropTarget extends ButtonDropTarget {
if (item.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION &&
item instanceof ShortcutInfo) {
- if (AppsCustomizePagedView.DISABLE_ALL_APPS) {
+ if (LauncherAppState.isDisableAllApps()) {
ShortcutInfo shortcutInfo = (ShortcutInfo) info;
return (shortcutInfo.flags & AppInfo.DOWNLOADED_FLAG) != 0;
} else {
@@ -179,8 +180,9 @@ public class DeleteDropTarget extends ButtonDropTarget {
@Override
public void onDragStart(DragSource source, Object info, int dragAction) {
boolean isVisible = true;
- boolean useUninstallLabel = !AppsCustomizePagedView.DISABLE_ALL_APPS &&
+ boolean useUninstallLabel = !LauncherAppState.isDisableAllApps() &&
isAllAppsApplication(source, info);
+ boolean useDeleteLabel = !useUninstallLabel && source.supportsDeleteDropTarget();
// If we are dragging an application from AppsCustomize, only show the control if we can
// delete the app (it was downloaded), and rename the string to "uninstall" in such a case.
@@ -191,15 +193,17 @@ public class DeleteDropTarget extends ButtonDropTarget {
if (useUninstallLabel) {
setCompoundDrawablesRelativeWithIntrinsicBounds(mUninstallDrawable, null, null, null);
- } else {
+ } else if (useDeleteLabel) {
setCompoundDrawablesRelativeWithIntrinsicBounds(mRemoveDrawable, null, null, null);
+ } else {
+ isVisible = false;
}
mCurrentDrawable = (TransitionDrawable) getCurrentDrawable();
mActive = isVisible;
resetHoverColor();
((ViewGroup) getParent()).setVisibility(isVisible ? View.VISIBLE : View.GONE);
- if (getText().length() > 0) {
+ if (isVisible && getText().length() > 0) {
setText(useUninstallLabel ? R.string.delete_target_uninstall_label
: R.string.delete_target_label);
}
@@ -266,21 +270,10 @@ public class DeleteDropTarget extends ButtonDropTarget {
}
private boolean isUninstallFromWorkspace(DragObject d) {
- if (AppsCustomizePagedView.DISABLE_ALL_APPS && isWorkspaceOrFolderApplication(d)) {
+ if (LauncherAppState.isDisableAllApps() && isWorkspaceOrFolderApplication(d)) {
ShortcutInfo shortcut = (ShortcutInfo) d.dragInfo;
- if (shortcut.intent != null && shortcut.intent.getComponent() != null) {
- Set<String> categories = shortcut.intent.getCategories();
- boolean includesLauncherCategory = false;
- if (categories != null) {
- for (String category : categories) {
- if (category.equals(Intent.CATEGORY_LAUNCHER)) {
- includesLauncherCategory = true;
- break;
- }
- }
- }
- return includesLauncherCategory;
- }
+ // Only allow manifest shortcuts to initiate an un-install.
+ return !InstallShortcutReceiver.isValidShortcutLaunchIntent(shortcut.intent);
}
return false;
}
@@ -340,11 +333,12 @@ public class DeleteDropTarget extends ButtonDropTarget {
if (appWidgetHost != null) {
// Deleting an app widget ID is a void call but writes to disk before returning
// to the caller...
- new Thread("deleteAppWidgetId") {
- public void run() {
+ new AsyncTask<Void, Void, Void>() {
+ public Void doInBackground(Void ... args) {
appWidgetHost.deleteAppWidgetId(launcherAppWidgetInfo.appWidgetId);
+ return null;
}
- }.start();
+ }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void) null);
}
}
if (wasWaitingForUninstall && !mWaitingForUninstall) {
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
new file mode 100644
index 000000000..99819caf3
--- /dev/null
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -0,0 +1,886 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3;
+
+import android.appwidget.AppWidgetHostView;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.graphics.Paint;
+import android.graphics.Paint.FontMetrics;
+import android.graphics.Point;
+import android.graphics.PointF;
+import android.graphics.Rect;
+import android.util.DisplayMetrics;
+import android.view.Display;
+import android.view.Gravity;
+import android.view.Surface;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewGroup.LayoutParams;
+import android.view.WindowManager;
+import android.widget.FrameLayout;
+import android.widget.LinearLayout;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+
+import com.android.launcher3.settings.SettingsProvider;
+
+class DeviceProfileQuery {
+ float widthDps;
+ float heightDps;
+ float value;
+ PointF dimens;
+
+ DeviceProfileQuery(float w, float h, float v) {
+ widthDps = w;
+ heightDps = h;
+ value = v;
+ dimens = new PointF(w, h);
+ }
+}
+
+public class DeviceProfile {
+ public static interface DeviceProfileCallbacks {
+ public void onAvailableSizeChanged(DeviceProfile grid);
+ }
+
+ public final static int GRID_SIZE_MAX = 3;
+ public final static int GRID_SIZE_MIN = 2;
+
+ public enum GridSize {
+ Comfortable(0),
+ Cozy(1),
+ Condensed(2),
+ Custom(3);
+
+ private final int mValue;
+ private GridSize(int value) {
+ mValue = value;
+ }
+
+ public int getValue() {
+ return mValue;
+ }
+
+ public static GridSize getModeForValue(int value) {
+ switch (value) {
+ case 1:
+ return Cozy;
+ case 2:
+ return Condensed;
+ case 3:
+ return Custom;
+ default :
+ return Comfortable;
+ }
+ }
+ }
+
+ String name;
+ float minWidthDps;
+ float minHeightDps;
+ float numRows;
+ float numColumns;
+ int numRowsBase;
+ int numColumnsBase;
+ float numHotseatIcons;
+ private float iconSize;
+ private float iconTextSize;
+ private int iconDrawablePaddingOriginalPx;
+ private float hotseatIconSize;
+
+ boolean isLandscape;
+ boolean isTablet;
+ boolean isLargeTablet;
+ boolean isLayoutRtl;
+ boolean transposeLayoutWithOrientation;
+
+ int desiredWorkspaceLeftRightMarginPx;
+ int edgeMarginPx;
+ Rect defaultWidgetPadding;
+
+ int widthPx;
+ int heightPx;
+ int availableWidthPx;
+ int availableHeightPx;
+ int defaultPageSpacingPx;
+
+ int overviewModeMinIconZoneHeightPx;
+ int overviewModeMaxIconZoneHeightPx;
+ int overviewModeBarItemWidthPx;
+ int overviewModeBarSpacerWidthPx;
+ float overviewModeIconZoneRatio;
+ float overviewModeScaleFactor;
+
+ int iconSizePx;
+ int iconTextSizePx;
+ int iconDrawablePaddingPx;
+ int cellWidthPx;
+ int cellHeightPx;
+ int allAppsIconSizePx;
+ int allAppsIconTextSizePx;
+ int allAppsCellWidthPx;
+ int allAppsCellHeightPx;
+ int allAppsCellPaddingPx;
+ int folderBackgroundOffset;
+ int folderIconSizePx;
+ int folderCellWidthPx;
+ int folderCellHeightPx;
+ int hotseatCellWidthPx;
+ int hotseatCellHeightPx;
+ int hotseatIconSizePx;
+ int hotseatBarHeightPx;
+ int hotseatAllAppsRank;
+ int allAppsNumRows;
+ int allAppsNumCols;
+ int searchBarSpaceWidthPx;
+ int searchBarSpaceMaxWidthPx;
+ int searchBarSpaceHeightPx;
+ int searchBarHeightPx;
+ int pageIndicatorHeightPx;
+
+
+ boolean searchBarVisible;
+
+ float dragViewScale;
+
+ private ArrayList<DeviceProfileCallbacks> mCallbacks = new ArrayList<DeviceProfileCallbacks>();
+
+ DeviceProfile(String n, float w, float h, float r, float c,
+ float is, float its, float hs, float his) {
+ // Ensure that we have an odd number of hotseat items (since we need to place all apps)
+ if (!LauncherAppState.isDisableAllApps() && hs % 2 == 0) {
+ throw new RuntimeException("All Device Profiles must have an odd number of hotseat spaces");
+ }
+
+ name = n;
+ minWidthDps = w;
+ minHeightDps = h;
+ numRows = r;
+ numColumns = c;
+ iconSize = is;
+ iconTextSize = its;
+ numHotseatIcons = hs;
+ hotseatIconSize = his;
+ }
+
+ DeviceProfile(Context context,
+ ArrayList<DeviceProfile> profiles,
+ float minWidth, float minHeight,
+ int wPx, int hPx,
+ int awPx, int ahPx,
+ Resources res) {
+ DisplayMetrics dm = res.getDisplayMetrics();
+ ArrayList<DeviceProfileQuery> points =
+ new ArrayList<DeviceProfileQuery>();
+ transposeLayoutWithOrientation =
+ res.getBoolean(R.bool.hotseat_transpose_layout_with_orientation);
+ minWidthDps = minWidth;
+ minHeightDps = minHeight;
+
+ ComponentName cn = new ComponentName(context.getPackageName(),
+ this.getClass().getName());
+ defaultWidgetPadding = AppWidgetHostView.getDefaultPaddingForWidget(context, cn, null);
+ edgeMarginPx = res.getDimensionPixelSize(R.dimen.dynamic_grid_edge_margin);
+ desiredWorkspaceLeftRightMarginPx = 2 * edgeMarginPx;
+ pageIndicatorHeightPx =
+ res.getDimensionPixelSize(R.dimen.dynamic_grid_page_indicator_height);
+ defaultPageSpacingPx =
+ res.getDimensionPixelSize(R.dimen.dynamic_grid_workspace_page_spacing);
+ allAppsCellPaddingPx =
+ res.getDimensionPixelSize(R.dimen.dynamic_grid_all_apps_cell_padding);
+ overviewModeMinIconZoneHeightPx =
+ res.getDimensionPixelSize(R.dimen.dynamic_grid_overview_min_icon_zone_height);
+ overviewModeMaxIconZoneHeightPx =
+ res.getDimensionPixelSize(R.dimen.dynamic_grid_overview_max_icon_zone_height);
+ overviewModeBarItemWidthPx =
+ res.getDimensionPixelSize(R.dimen.dynamic_grid_overview_bar_item_width);
+ overviewModeBarSpacerWidthPx =
+ res.getDimensionPixelSize(R.dimen.dynamic_grid_overview_bar_spacer_width);
+ overviewModeIconZoneRatio =
+ res.getInteger(R.integer.config_dynamic_grid_overview_icon_zone_percentage) / 100f;
+ overviewModeScaleFactor =
+ res.getInteger(R.integer.config_dynamic_grid_overview_scale_percentage) / 100f;
+
+ // Interpolate the rows
+ for (DeviceProfile p : profiles) {
+ points.add(new DeviceProfileQuery(p.minWidthDps, p.minHeightDps, p.numRows));
+ }
+ numRows = Math.round(invDistWeightedInterpolate(minWidth, minHeight, points));
+ numRowsBase = (int) numRows;
+ int gridResize = SettingsProvider.getIntCustomDefault(context,
+ SettingsProvider.SETTINGS_UI_DYNAMIC_GRID_SIZE, 0);
+ if (GridSize.getModeForValue(gridResize) != GridSize.Custom) {
+ numRows += gridResize;
+ } else {
+ int iTempNumberOfRows = SettingsProvider.getIntCustomDefault(context,
+ SettingsProvider.SETTINGS_UI_HOMESCREEN_ROWS, (int)numRows);
+ if (iTempNumberOfRows > 0) {
+ numRows = iTempNumberOfRows;
+ }
+ }
+ // Interpolate the columns
+ points.clear();
+ for (DeviceProfile p : profiles) {
+ points.add(new DeviceProfileQuery(p.minWidthDps, p.minHeightDps, p.numColumns));
+ }
+ numColumns = Math.round(invDistWeightedInterpolate(minWidth, minHeight, points));
+ numColumnsBase = (int) numColumns;
+ if (GridSize.getModeForValue(gridResize) != GridSize.Custom) {
+ numColumns += gridResize;
+ } else {
+ int iTempNumberOfColumns = SettingsProvider.getIntCustomDefault(context,
+ SettingsProvider.SETTINGS_UI_HOMESCREEN_COLUMNS, (int)numColumns);
+ if (iTempNumberOfColumns > 0) {
+ numColumns = iTempNumberOfColumns;
+ }
+ }
+ // Interpolate the hotseat length
+ points.clear();
+ for (DeviceProfile p : profiles) {
+ points.add(new DeviceProfileQuery(p.minWidthDps, p.minHeightDps, p.numHotseatIcons));
+ }
+ numHotseatIcons = Math.round(invDistWeightedInterpolate(minWidth, minHeight, points));
+ hotseatAllAppsRank = (int) (numHotseatIcons / 2);
+
+ // Interpolate the icon size
+ points.clear();
+ for (DeviceProfile p : profiles) {
+ points.add(new DeviceProfileQuery(p.minWidthDps, p.minHeightDps, p.iconSize));
+ }
+ iconSize = invDistWeightedInterpolate(minWidth, minHeight, points);
+ // AllApps uses the original non-scaled icon size
+ allAppsIconSizePx = DynamicGrid.pxFromDp(iconSize, dm);
+
+ // Interpolate the icon text size
+ points.clear();
+ for (DeviceProfile p : profiles) {
+ points.add(new DeviceProfileQuery(p.minWidthDps, p.minHeightDps, p.iconTextSize));
+ }
+ iconTextSize = invDistWeightedInterpolate(minWidth, minHeight, points);
+ iconDrawablePaddingOriginalPx =
+ res.getDimensionPixelSize(R.dimen.dynamic_grid_icon_drawable_padding);
+ // AllApps uses the original non-scaled icon text size
+ allAppsIconTextSizePx = DynamicGrid.pxFromDp(iconTextSize, dm);
+
+ // Interpolate the hotseat icon size
+ points.clear();
+ for (DeviceProfile p : profiles) {
+ points.add(new DeviceProfileQuery(p.minWidthDps, p.minHeightDps, p.hotseatIconSize));
+ }
+ // Hotseat
+ hotseatIconSize = invDistWeightedInterpolate(minWidth, minHeight, points);
+
+ // Calculate the remaining vars
+ updateFromConfiguration(context, res, wPx, hPx, awPx, ahPx);
+ updateAvailableDimensions(context);
+
+ // Search Bar
+ searchBarVisible = SettingsProvider.getBoolean(context, SettingsProvider.SETTINGS_UI_HOMESCREEN_SEARCH,
+ R.bool.preferences_interface_homescreen_search_default);
+ searchBarSpaceWidthPx = Math.min(searchBarSpaceMaxWidthPx, widthPx);
+ searchBarSpaceHeightPx = 2 * edgeMarginPx + (searchBarVisible ? searchBarHeightPx : 2 * edgeMarginPx);
+ }
+
+ void addCallback(DeviceProfileCallbacks cb) {
+ mCallbacks.add(cb);
+ cb.onAvailableSizeChanged(this);
+ }
+ void removeCallback(DeviceProfileCallbacks cb) {
+ mCallbacks.remove(cb);
+ }
+
+ private int getDeviceOrientation(Context context) {
+ WindowManager windowManager = (WindowManager)
+ context.getSystemService(Context.WINDOW_SERVICE);
+ Resources resources = context.getResources();
+ DisplayMetrics dm = resources.getDisplayMetrics();
+ Configuration config = resources.getConfiguration();
+ int rotation = windowManager.getDefaultDisplay().getRotation();
+
+ boolean isLandscape = (config.orientation == Configuration.ORIENTATION_LANDSCAPE) &&
+ (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180);
+ boolean isRotatedPortrait = (config.orientation == Configuration.ORIENTATION_PORTRAIT) &&
+ (rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270);
+ if (isLandscape || isRotatedPortrait) {
+ return CellLayout.LANDSCAPE;
+ } else {
+ return CellLayout.PORTRAIT;
+ }
+ }
+
+ private void updateAvailableDimensions(Context context) {
+ WindowManager windowManager = (WindowManager)
+ context.getSystemService(Context.WINDOW_SERVICE);
+ Display display = windowManager.getDefaultDisplay();
+ Resources resources = context.getResources();
+ DisplayMetrics dm = resources.getDisplayMetrics();
+ Configuration config = resources.getConfiguration();
+
+ // There are three possible configurations that the dynamic grid accounts for, portrait,
+ // landscape with the nav bar at the bottom, and landscape with the nav bar at the side.
+ // To prevent waiting for fitSystemWindows(), we make the observation that in landscape,
+ // the height is the smallest height (either with the nav bar at the bottom or to the
+ // side) and otherwise, the height is simply the largest possible height for a portrait
+ // device.
+ Point size = new Point();
+ Point smallestSize = new Point();
+ Point largestSize = new Point();
+ display.getSize(size);
+ display.getCurrentSizeRange(smallestSize, largestSize);
+ availableWidthPx = size.x;
+ if (config.orientation == Configuration.ORIENTATION_LANDSCAPE) {
+ availableHeightPx = smallestSize.y;
+ } else {
+ availableHeightPx = largestSize.y;
+ }
+
+ // Check to see if the icons fit in the new available height. If not, then we need to
+ // shrink the icon size.
+ float scale = 1f;
+ int drawablePadding = iconDrawablePaddingOriginalPx;
+ updateIconSize(1f, drawablePadding, resources, dm);
+ float usedHeight = (cellHeightPx * numRows);
+
+ Rect workspacePadding = getWorkspacePadding();
+ int maxHeight = (availableHeightPx - workspacePadding.top - workspacePadding.bottom);
+ if (usedHeight > maxHeight) {
+ scale = maxHeight / usedHeight;
+ drawablePadding = 0;
+ }
+ updateIconSize(scale, drawablePadding, resources, dm);
+
+ // Make the callbacks
+ for (DeviceProfileCallbacks cb : mCallbacks) {
+ cb.onAvailableSizeChanged(this);
+ }
+ }
+
+ private void updateIconSize(float scale, int drawablePadding, Resources resources,
+ DisplayMetrics dm) {
+ iconSizePx = (int) (DynamicGrid.pxFromDp(iconSize, dm) * scale);
+ iconTextSizePx = (int) (DynamicGrid.pxFromSp(iconTextSize, dm) * scale);
+ iconDrawablePaddingPx = drawablePadding;
+ hotseatIconSizePx = (int) (DynamicGrid.pxFromDp(hotseatIconSize, dm) * scale);
+
+ // Search Bar
+ searchBarSpaceWidthPx = Math.min(searchBarSpaceMaxWidthPx, widthPx);
+ searchBarSpaceMaxWidthPx = resources.getDimensionPixelSize(R.dimen.dynamic_grid_search_bar_max_width);
+ searchBarHeightPx = resources.getDimensionPixelSize(R.dimen.dynamic_grid_search_bar_height);
+ searchBarSpaceHeightPx = searchBarHeightPx + getSearchBarTopOffset();
+
+ // Calculate the actual text height
+ Paint textPaint = new Paint();
+ textPaint.setTextSize(iconTextSizePx);
+ FontMetrics fm = textPaint.getFontMetrics();
+ cellWidthPx = iconSizePx;
+ cellHeightPx = iconSizePx + iconDrawablePaddingPx + (int) Math.ceil(fm.bottom - fm.top);
+ final float scaleDps = resources.getDimensionPixelSize(R.dimen.dragViewScale);
+ dragViewScale = (iconSizePx + scaleDps) / iconSizePx;
+
+ // Hotseat
+ hotseatBarHeightPx = iconSizePx + 4 * edgeMarginPx;
+ hotseatCellWidthPx = iconSizePx;
+ hotseatCellHeightPx = iconSizePx;
+
+ // Folder
+ folderCellWidthPx = cellWidthPx + 3 * edgeMarginPx;
+ folderCellHeightPx = cellHeightPx + edgeMarginPx;
+ folderBackgroundOffset = -edgeMarginPx;
+ folderIconSizePx = iconSizePx + 2 * -folderBackgroundOffset;
+
+ // All Apps
+ Rect padding = getWorkspacePadding(isLandscape ?
+ CellLayout.LANDSCAPE : CellLayout.PORTRAIT);
+ int pageIndicatorOffset =
+ resources.getDimensionPixelSize(R.dimen.apps_customize_page_indicator_offset);
+
+ if (isPhone()) {
+ searchBarSpaceWidthPx = Math.min(searchBarSpaceMaxWidthPx, widthPx);
+ } else {
+ searchBarSpaceWidthPx = widthPx - (isLandscape ? 3 : 1) * iconSizePx;
+ }
+
+ allAppsCellWidthPx = allAppsIconSizePx;
+ allAppsCellHeightPx = allAppsIconSizePx + drawablePadding + iconTextSizePx;
+ int maxLongEdgeCellCount =
+ resources.getInteger(R.integer.config_dynamic_grid_max_long_edge_cell_count);
+ int maxShortEdgeCellCount =
+ resources.getInteger(R.integer.config_dynamic_grid_max_short_edge_cell_count);
+ int minEdgeCellCount =
+ resources.getInteger(R.integer.config_dynamic_grid_min_edge_cell_count);
+ int maxRows = (isLandscape ? maxShortEdgeCellCount : maxLongEdgeCellCount);
+ int maxCols = (isLandscape ? maxLongEdgeCellCount : maxShortEdgeCellCount);
+
+ allAppsNumRows = (availableHeightPx - pageIndicatorHeightPx) /
+ (allAppsCellHeightPx + allAppsCellPaddingPx);
+ allAppsNumRows = Math.max(minEdgeCellCount, Math.min(maxRows, allAppsNumRows));
+ allAppsNumCols = (availableWidthPx) /
+ (allAppsCellWidthPx + allAppsCellPaddingPx);
+ allAppsNumCols = Math.max(minEdgeCellCount, Math.min(maxCols, allAppsNumCols));
+ }
+
+ void updateFromConfiguration(Context context, Resources resources, int wPx, int hPx,
+ int awPx, int ahPx) {
+ Configuration configuration = resources.getConfiguration();
+ isLandscape = (configuration.orientation == Configuration.ORIENTATION_LANDSCAPE);
+ isTablet = resources.getBoolean(R.bool.is_tablet);
+ isLargeTablet = resources.getBoolean(R.bool.is_large_tablet);
+ if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) {
+ isLayoutRtl = (configuration.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL);
+ } else {
+ isLayoutRtl = false;
+ }
+ widthPx = wPx;
+ heightPx = hPx;
+ availableWidthPx = awPx;
+ availableHeightPx = ahPx;
+
+ updateAvailableDimensions(context);
+ }
+
+ private float dist(PointF p0, PointF p1) {
+ return (float) Math.sqrt((p1.x - p0.x)*(p1.x-p0.x) +
+ (p1.y-p0.y)*(p1.y-p0.y));
+ }
+
+ private float weight(PointF a, PointF b,
+ float pow) {
+ float d = dist(a, b);
+ if (d == 0f) {
+ return Float.POSITIVE_INFINITY;
+ }
+ return (float) (1f / Math.pow(d, pow));
+ }
+
+ private float invDistWeightedInterpolate(float width, float height,
+ ArrayList<DeviceProfileQuery> points) {
+ float sum = 0;
+ float weights = 0;
+ float pow = 5;
+ float kNearestNeighbors = 3;
+ final PointF xy = new PointF(width, height);
+
+ ArrayList<DeviceProfileQuery> pointsByNearness = points;
+ Collections.sort(pointsByNearness, new Comparator<DeviceProfileQuery>() {
+ public int compare(DeviceProfileQuery a, DeviceProfileQuery b) {
+ return (int) (dist(xy, a.dimens) - dist(xy, b.dimens));
+ }
+ });
+
+ for (int i = 0; i < pointsByNearness.size(); ++i) {
+ DeviceProfileQuery p = pointsByNearness.get(i);
+ if (i < kNearestNeighbors) {
+ float w = weight(xy, p.dimens, pow);
+ if (w == Float.POSITIVE_INFINITY) {
+ return p.value;
+ }
+ weights += w;
+ }
+ }
+
+ for (int i = 0; i < pointsByNearness.size(); ++i) {
+ DeviceProfileQuery p = pointsByNearness.get(i);
+ if (i < kNearestNeighbors) {
+ float w = weight(xy, p.dimens, pow);
+ sum += w * p.value / weights;
+ }
+ }
+
+ return sum;
+ }
+
+ /** Returns the search bar top offset */
+ int getSearchBarTopOffset() {
+ if (isTablet() && !isVerticalBarLayout()) {
+ return searchBarVisible ? 4 * edgeMarginPx : 0;
+ } else {
+ return searchBarVisible ? 2 * edgeMarginPx : 0;
+ }
+ }
+
+ /** Returns the search bar bounds in the current orientation */
+ Rect getSearchBarBounds() {
+ return getSearchBarBounds(isLandscape ? CellLayout.LANDSCAPE : CellLayout.PORTRAIT);
+ }
+ /** Returns the search bar bounds in the specified orientation */
+ Rect getSearchBarBounds(int orientation) {
+ Rect bounds = new Rect();
+ if (orientation == CellLayout.LANDSCAPE &&
+ transposeLayoutWithOrientation) {
+ if (isLayoutRtl) {
+ bounds.set(availableWidthPx - searchBarSpaceHeightPx, edgeMarginPx,
+ availableWidthPx, availableHeightPx - edgeMarginPx);
+ } else {
+ bounds.set(0, edgeMarginPx, searchBarSpaceHeightPx,
+ availableHeightPx - edgeMarginPx);
+ }
+ } else {
+ if (isTablet()) {
+ // Pad the left and right of the workspace to ensure consistent spacing
+ // between all icons
+ int width = (orientation == CellLayout.LANDSCAPE)
+ ? Math.max(widthPx, heightPx)
+ : Math.min(widthPx, heightPx);
+ // XXX: If the icon size changes across orientations, we will have to take
+ // that into account here too.
+ int gap = (int) ((width - 2 * edgeMarginPx -
+ (numColumns * cellWidthPx)) / (2 * (numColumns + 1)));
+ bounds.set(edgeMarginPx + gap, getSearchBarTopOffset(),
+ availableWidthPx - (edgeMarginPx + gap),
+ searchBarVisible ? searchBarSpaceHeightPx : edgeMarginPx);
+ } else {
+ bounds.set(desiredWorkspaceLeftRightMarginPx - defaultWidgetPadding.left,
+ getSearchBarTopOffset(),
+ availableWidthPx - (desiredWorkspaceLeftRightMarginPx -
+ defaultWidgetPadding.right), searchBarVisible ? searchBarSpaceHeightPx : edgeMarginPx);
+ }
+ }
+ return bounds;
+ }
+
+ /** Returns the bounds of the workspace page indicators. */
+ Rect getWorkspacePageIndicatorBounds(Rect insets) {
+ Rect workspacePadding = getWorkspacePadding();
+ if (isLandscape && transposeLayoutWithOrientation) {
+ if (isLayoutRtl) {
+ return new Rect(workspacePadding.left, workspacePadding.top,
+ workspacePadding.left + pageIndicatorHeightPx,
+ heightPx - workspacePadding.bottom - insets.bottom);
+ } else {
+ int pageIndicatorLeft = widthPx - workspacePadding.right;
+ return new Rect(pageIndicatorLeft, workspacePadding.top,
+ pageIndicatorLeft + pageIndicatorHeightPx,
+ heightPx - workspacePadding.bottom - insets.bottom);
+ }
+ } else {
+ int pageIndicatorTop = heightPx - insets.bottom - workspacePadding.bottom;
+ return new Rect(workspacePadding.left, pageIndicatorTop,
+ widthPx - workspacePadding.right, pageIndicatorTop + pageIndicatorHeightPx);
+ }
+ }
+
+ /** Returns the workspace padding in the specified orientation */
+ Rect getWorkspacePadding() {
+ return getWorkspacePadding(isLandscape ? CellLayout.LANDSCAPE : CellLayout.PORTRAIT);
+ }
+ Rect getWorkspacePadding(int orientation) {
+ Rect searchBarBounds = getSearchBarBounds(orientation);
+ Rect padding = new Rect();
+ if (orientation == CellLayout.LANDSCAPE &&
+ transposeLayoutWithOrientation) {
+ // Pad the left and right of the workspace with search/hotseat bar sizes
+ if (isLayoutRtl) {
+ padding.set(hotseatBarHeightPx, edgeMarginPx,
+ searchBarBounds.width(), edgeMarginPx);
+ } else {
+ padding.set(searchBarBounds.width(), edgeMarginPx,
+ hotseatBarHeightPx, edgeMarginPx);
+ }
+ } else {
+ if (isTablet()) {
+ // Pad the left and right of the workspace to ensure consistent spacing
+ // between all icons
+ float gapScale = 1f + (dragViewScale - 1f) / 2f;
+ int width = (orientation == CellLayout.LANDSCAPE)
+ ? Math.max(widthPx, heightPx)
+ : Math.min(widthPx, heightPx);
+ int height = (orientation != CellLayout.LANDSCAPE)
+ ? Math.max(widthPx, heightPx)
+ : Math.min(widthPx, heightPx);
+ int paddingTop = searchBarBounds.bottom;
+ int paddingBottom = hotseatBarHeightPx + pageIndicatorHeightPx;
+ int availableWidth = Math.max(0, width - (int) ((numColumns * cellWidthPx) +
+ (numColumns * gapScale * cellWidthPx)));
+ int availableHeight = Math.max(0, height - paddingTop - paddingBottom
+ - (int) (2 * numRows * cellHeightPx));
+ padding.set(availableWidth / 2, paddingTop + availableHeight / 2,
+ availableWidth / 2, paddingBottom + availableHeight / 2);
+ } else {
+ // Pad the top and bottom of the workspace with search/hotseat bar sizes
+ padding.set(desiredWorkspaceLeftRightMarginPx - defaultWidgetPadding.left,
+ searchBarBounds.bottom,
+ desiredWorkspaceLeftRightMarginPx - defaultWidgetPadding.right,
+ hotseatBarHeightPx + pageIndicatorHeightPx);
+ }
+ }
+ return padding;
+ }
+
+ int getWorkspacePageSpacing(int orientation) {
+ if ((orientation == CellLayout.LANDSCAPE &&
+ transposeLayoutWithOrientation) || isLargeTablet()) {
+ // In landscape mode the page spacing is set to the default.
+ return defaultPageSpacingPx;
+ } else {
+ // In portrait, we want the pages spaced such that there is no
+ // overhang of the previous / next page into the current page viewport.
+ // We assume symmetrical padding in portrait mode.
+ return Math.max(defaultPageSpacingPx, 2 * getWorkspacePadding().left);
+ }
+ }
+
+ Rect getOverviewModeButtonBarRect() {
+ int zoneHeight = (int) (overviewModeIconZoneRatio * availableHeightPx);
+ zoneHeight = Math.min(overviewModeMaxIconZoneHeightPx,
+ Math.max(overviewModeMinIconZoneHeightPx, zoneHeight));
+ return new Rect(0, availableHeightPx - zoneHeight, 0, availableHeightPx);
+ }
+
+ float getOverviewModeScale() {
+ Rect workspacePadding = getWorkspacePadding();
+ Rect overviewBar = getOverviewModeButtonBarRect();
+ int pageSpace = availableHeightPx - workspacePadding.top - workspacePadding.bottom;
+ return (overviewModeScaleFactor * (pageSpace - overviewBar.height())) / pageSpace;
+ }
+
+ // The rect returned will be extended to below the system ui that covers the workspace
+ Rect getHotseatRect() {
+ if (isVerticalBarLayout()) {
+ return new Rect(availableWidthPx - hotseatBarHeightPx, 0,
+ Integer.MAX_VALUE, availableHeightPx);
+ } else {
+ return new Rect(0, availableHeightPx - hotseatBarHeightPx,
+ availableWidthPx, Integer.MAX_VALUE);
+ }
+ }
+
+ int calculateCellWidth(int width, int countX) {
+ return width / countX;
+ }
+ int calculateCellHeight(int height, int countY) {
+ return height / countY;
+ }
+
+ boolean isPhone() {
+ return !isTablet && !isLargeTablet;
+ }
+ boolean isTablet() {
+ return isTablet;
+ }
+ boolean isLargeTablet() {
+ return isLargeTablet;
+ }
+
+ boolean isVerticalBarLayout() {
+ return isLandscape && transposeLayoutWithOrientation;
+ }
+
+ boolean shouldFadeAdjacentWorkspaceScreens() {
+ return isVerticalBarLayout() || isLargeTablet();
+ }
+
+ int getVisibleChildCount(ViewGroup parent) {
+ int visibleChildren = 0;
+ for (int i = 0; i < parent.getChildCount(); i++) {
+ if (parent.getChildAt(i).getVisibility() != View.GONE) {
+ visibleChildren++;
+ }
+ }
+ return visibleChildren;
+ }
+
+ int calculateOverviewModeWidth(int visibleChildCount) {
+ return visibleChildCount * overviewModeBarItemWidthPx +
+ (visibleChildCount-1) * overviewModeBarSpacerWidthPx;
+ }
+
+ public void layout(Launcher launcher) {
+ // Update search bar for live settings
+ searchBarVisible = SettingsProvider.getBoolean(launcher, SettingsProvider.SETTINGS_UI_HOMESCREEN_SEARCH,
+ R.bool.preferences_interface_homescreen_search_default);
+ searchBarSpaceHeightPx = 2 * edgeMarginPx + (searchBarVisible ? searchBarHeightPx : 2 * edgeMarginPx);
+ FrameLayout.LayoutParams lp;
+ Resources res = launcher.getResources();
+ boolean hasVerticalBarLayout = isVerticalBarLayout();
+
+ // Layout the search bar space
+ View searchBar = launcher.getSearchBar();
+ lp = (FrameLayout.LayoutParams) searchBar.getLayoutParams();
+ if (hasVerticalBarLayout) {
+ // Vertical search bar space
+ lp.gravity = Gravity.TOP | Gravity.LEFT;
+ lp.width = searchBarSpaceHeightPx;
+ lp.height = LayoutParams.WRAP_CONTENT;
+ searchBar.setPadding(
+ 0, 2 * edgeMarginPx, 0,
+ 2 * edgeMarginPx);
+
+ searchBar.setVisibility(searchBarVisible ? View.VISIBLE : View.GONE);
+ LinearLayout targets = (LinearLayout) searchBar.findViewById(R.id.drag_target_bar);
+ targets.setOrientation(LinearLayout.VERTICAL);
+ } else {
+ // Horizontal search bar space
+ lp.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL;
+ lp.width = searchBarSpaceWidthPx;
+ lp.height = searchBarSpaceHeightPx;
+ searchBar.setPadding(
+ 2 * edgeMarginPx,
+ getSearchBarTopOffset(),
+ 2 * edgeMarginPx, 0);
+ }
+ searchBar.setLayoutParams(lp);
+
+ // Layout the drop target icons
+ LinearLayout dropTargetBar = (LinearLayout) launcher.getSearchBar().getDropTargetBar();
+ if (hasVerticalBarLayout) {
+ dropTargetBar.setOrientation(LinearLayout.VERTICAL);
+ } else {
+ dropTargetBar.setOrientation(LinearLayout.HORIZONTAL);
+ }
+
+ // Layout the search bar
+ View qsbBar = launcher.getQsbBar();
+ qsbBar.setVisibility(searchBarVisible ? View.VISIBLE : View.GONE);
+ LayoutParams vglp = qsbBar.getLayoutParams();
+ vglp.width = LayoutParams.MATCH_PARENT;
+ vglp.height = LayoutParams.MATCH_PARENT;
+ qsbBar.setLayoutParams(vglp);
+
+ // Layout the voice proxy
+ View voiceButtonProxy = launcher.findViewById(R.id.voice_button_proxy);
+ if (voiceButtonProxy != null) {
+ if (hasVerticalBarLayout) {
+ // TODO: MOVE THIS INTO SEARCH BAR MEASURE
+ } else {
+ lp = (FrameLayout.LayoutParams) voiceButtonProxy.getLayoutParams();
+ lp.gravity = Gravity.TOP | Gravity.END;
+ lp.width = (widthPx - searchBarSpaceWidthPx) / 2 +
+ 2 * iconSizePx;
+ lp.height = searchBarSpaceHeightPx;
+ }
+ }
+
+ // Layout the workspace
+ PagedView workspace = (PagedView) launcher.findViewById(R.id.workspace);
+ lp = (FrameLayout.LayoutParams) workspace.getLayoutParams();
+ lp.gravity = Gravity.CENTER;
+ int orientation = isLandscape ? CellLayout.LANDSCAPE : CellLayout.PORTRAIT;
+ Rect padding = getWorkspacePadding(orientation);
+ workspace.setLayoutParams(lp);
+ workspace.setPadding(padding.left, padding.top, padding.right, padding.bottom);
+ workspace.setPageSpacing(getWorkspacePageSpacing(orientation));
+
+ // Layout the hotseat
+ View hotseat = launcher.findViewById(R.id.hotseat);
+ lp = (FrameLayout.LayoutParams) hotseat.getLayoutParams();
+ if (hasVerticalBarLayout) {
+ // Vertical hotseat
+ lp.gravity = Gravity.END;
+ lp.width = hotseatBarHeightPx;
+ lp.height = LayoutParams.MATCH_PARENT;
+ hotseat.findViewById(R.id.layout).setPadding(0, 2 * edgeMarginPx, 0, 2 * edgeMarginPx);
+ } else if (isTablet()) {
+ // Pad the hotseat with the workspace padding calculated above
+ lp.gravity = Gravity.BOTTOM;
+ lp.width = LayoutParams.MATCH_PARENT;
+ lp.height = hotseatBarHeightPx;
+ hotseat.setPadding(edgeMarginPx + padding.left, 0,
+ edgeMarginPx + padding.right,
+ 2 * edgeMarginPx);
+ } else {
+ // For phones, layout the hotseat without any bottom margin
+ // to ensure that we have space for the folders
+ lp.gravity = Gravity.BOTTOM;
+ lp.width = LayoutParams.MATCH_PARENT;
+ lp.height = hotseatBarHeightPx;
+ hotseat.findViewById(R.id.layout).setPadding(2 * edgeMarginPx, 0,
+ 2 * edgeMarginPx, 0);
+ }
+ hotseat.setLayoutParams(lp);
+
+ // Layout the page indicators
+ View pageIndicator = launcher.findViewById(R.id.page_indicator);
+ if (pageIndicator != null) {
+ if (hasVerticalBarLayout) {
+ // Hide the page indicators when we have vertical search/hotseat
+ pageIndicator.setVisibility(View.GONE);
+ } else {
+ // Put the page indicators above the hotseat
+ lp = (FrameLayout.LayoutParams) pageIndicator.getLayoutParams();
+ lp.gravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
+ lp.width = LayoutParams.WRAP_CONTENT;
+ lp.height = LayoutParams.WRAP_CONTENT;
+ lp.bottomMargin = Math.max(hotseatBarHeightPx, lp.bottomMargin);
+ pageIndicator.setLayoutParams(lp);
+ }
+ }
+
+ // Layout the apps customize
+ View appsCustomize = launcher.findViewById(R.id.apps_customize_pane_content);
+ lp = (FrameLayout.LayoutParams) appsCustomize.getLayoutParams();
+ lp.gravity = Gravity.CENTER;
+ appsCustomize.setLayoutParams(lp);
+
+ // Layout AllApps
+ AppsCustomizeLayout host = (AppsCustomizeLayout)
+ launcher.findViewById(R.id.apps_customize_pane);
+ if (host != null) {
+ // Center the all apps page indicator
+ int pageIndicatorHeight = (int) (pageIndicatorHeightPx * Math.min(1f,
+ (allAppsIconSizePx / DynamicGrid.DEFAULT_ICON_SIZE_PX)));
+ pageIndicator = host.findViewById(R.id.apps_customize_page_indicator);
+ if (pageIndicator != null) {
+ lp = (FrameLayout.LayoutParams) pageIndicator.getLayoutParams();
+ lp.gravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
+ lp.width = LayoutParams.WRAP_CONTENT;
+ lp.height = pageIndicatorHeight;
+ pageIndicator.setLayoutParams(lp);
+ }
+
+ AppsCustomizePagedView pagedView = (AppsCustomizePagedView)
+ host.findViewById(R.id.apps_customize_pane_content);
+ padding = new Rect();
+ if (pagedView != null) {
+ // Constrain the dimensions of all apps so that it does not span the full width
+ int paddingLR = (availableWidthPx - (allAppsCellWidthPx * allAppsNumCols)) /
+ (2 * (allAppsNumCols + 1));
+ int paddingTB = (availableHeightPx - (allAppsCellHeightPx * allAppsNumRows)) /
+ (2 * (allAppsNumRows + 1));
+ paddingLR = Math.min(paddingLR, (int)((paddingLR + paddingTB) * 0.75f));
+ paddingTB = Math.min(paddingTB, (int)((paddingLR + paddingTB) * 0.75f));
+ int maxAllAppsWidth = (allAppsNumCols * (allAppsCellWidthPx + 2 * paddingLR));
+ int gridPaddingLR = (availableWidthPx - maxAllAppsWidth) / 2;
+ // Only adjust the side paddings on landscape phones, or tablets
+ if ((isTablet() || isLandscape) && gridPaddingLR > (allAppsCellWidthPx / 4)) {
+ padding.left = padding.right = gridPaddingLR;
+ }
+ // The icons are centered, so we can't just offset by the page indicator height
+ // because the empty space will actually be pageIndicatorHeight + paddingTB
+ padding.bottom = Math.max(0, pageIndicatorHeight - paddingTB);
+ pagedView.setAllAppsPadding(padding);
+ pagedView.setWidgetsPageIndicatorPadding(pageIndicatorHeight);
+ }
+ }
+
+ // Layout the Overview Mode
+// ViewGroup overviewMode = launcher.getOverviewPanel();
+// if (overviewMode != null) {
+// Rect r = getOverviewModeButtonBarRect();
+// lp = (FrameLayout.LayoutParams) overviewMode.getLayoutParams();
+// lp.gravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
+// lp.width = Math.min(availableWidthPx,
+// calculateOverviewModeWidth(getVisibleChildCount(overviewMode)));
+// lp.height = r.height();
+// overviewMode.setLayoutParams(lp);
+// }
+ }
+}
diff --git a/src/com/android/launcher3/DragController.java b/src/com/android/launcher3/DragController.java
index 5b5c35c5a..4c3ea2a0a 100644
--- a/src/com/android/launcher3/DragController.java
+++ b/src/com/android/launcher3/DragController.java
@@ -16,6 +16,7 @@
package com.android.launcher3;
+import android.content.ComponentName;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
@@ -25,16 +26,9 @@ import android.graphics.Rect;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;
-import android.view.HapticFeedbackConstants;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-import android.view.VelocityTracker;
-import android.view.View;
-import android.view.ViewConfiguration;
+import android.view.*;
import android.view.inputmethod.InputMethodManager;
-import com.android.launcher3.R;
-
import java.util.ArrayList;
/**
@@ -203,7 +197,7 @@ public class DragController {
* @param dragRegion Coordinates within the bitmap b for the position of item being dragged.
* Makes dragging feel more precise, e.g. you can clip out a transparent border
*/
- public void startDrag(Bitmap b, int dragLayerX, int dragLayerY,
+ public DragView startDrag(Bitmap b, int dragLayerX, int dragLayerY,
DragSource source, Object dragInfo, int dragAction, Point dragOffset, Rect dragRegion,
float initialDragViewScale) {
if (PROFILE_DRAWING_DURING_DRAG) {
@@ -250,6 +244,7 @@ public class DragController {
mLauncher.getDragLayer().performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
dragView.show(mMotionDownX, mMotionDownY);
handleMoveEvent(mMotionDownX, mMotionDownY);
+ return dragView;
}
/**
@@ -323,7 +318,7 @@ public class DragController {
}
endDrag();
}
- public void onAppsRemoved(ArrayList<AppInfo> appInfos, Context context) {
+ public void onAppsRemoved(final ArrayList<String> packageNames, ArrayList<AppInfo> appInfos) {
// Cancel the current drag if we are removing an app that we are dragging
if (mDragObject != null) {
Object rawDragInfo = mDragObject.dragInfo;
@@ -332,9 +327,10 @@ public class DragController {
for (AppInfo info : appInfos) {
// Added null checks to prevent NPE we've seen in the wild
if (dragInfo != null &&
- dragInfo.intent != null) {
- boolean isSameComponent =
- dragInfo.intent.getComponent().equals(info.componentName);
+ dragInfo.intent != null && info != null) {
+ ComponentName cn = dragInfo.intent.getComponent();
+ boolean isSameComponent = cn.equals(info.componentName) ||
+ packageNames.contains(cn.getPackageName());
if (isSameComponent) {
cancelDrag();
return;
diff --git a/src/com/android/launcher3/DragLayer.java b/src/com/android/launcher3/DragLayer.java
index 401f4ed52..3ff4293af 100644
--- a/src/com/android/launcher3/DragLayer.java
+++ b/src/com/android/launcher3/DragLayer.java
@@ -24,11 +24,13 @@ import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
-import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
-import android.view.*;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.view.animation.DecelerateInterpolator;
@@ -63,8 +65,6 @@ public class DragLayer extends FrameLayout implements ViewGroup.OnHierarchyChang
private boolean mHoverPointClosesFolder = false;
private Rect mHitRect = new Rect();
- private int mWorkspaceIndex = -1;
- private int mQsbIndex = -1;
public static final int ANIMATION_END_DISAPPEAR = 0;
public static final int ANIMATION_END_FADE_OUT = 1;
public static final int ANIMATION_END_REMAIN_VISIBLE = 2;
@@ -73,6 +73,8 @@ public class DragLayer extends FrameLayout implements ViewGroup.OnHierarchyChang
private final Rect mInsets = new Rect();
+ private int mDragViewIndex;
+
/**
* Used to create a new DragLayer from XML.
*
@@ -106,21 +108,34 @@ public class DragLayer extends FrameLayout implements ViewGroup.OnHierarchyChang
final int n = getChildCount();
for (int i = 0; i < n; i++) {
final View child = getChildAt(i);
- final FrameLayout.LayoutParams flp = (FrameLayout.LayoutParams) child.getLayoutParams();
- if (child instanceof Insettable) {
- ((Insettable)child).setInsets(insets);
- } else {
- flp.topMargin += (insets.top - mInsets.top);
- flp.leftMargin += (insets.left - mInsets.left);
- flp.rightMargin += (insets.right - mInsets.right);
- flp.bottomMargin += (insets.bottom - mInsets.bottom);
+ if (child.getId() == R.id.overview_panel) {
+ continue;
}
- child.setLayoutParams(flp);
+ setInsets(child, insets, mInsets);
}
mInsets.set(insets);
return true; // I'll take it from here
}
+ @Override
+ public void addView(View child, int index, android.view.ViewGroup.LayoutParams params) {
+ super.addView(child, index, params);
+ setInsets(child, mInsets, new Rect());
+ }
+
+ private void setInsets(View child, Rect newInsets, Rect oldInsets) {
+ final FrameLayout.LayoutParams flp = (FrameLayout.LayoutParams) child.getLayoutParams();
+ if (child instanceof Insettable) {
+ ((Insettable) child).setInsets(newInsets);
+ } else {
+ flp.topMargin += (newInsets.top - oldInsets.top);
+ flp.leftMargin += (newInsets.left - oldInsets.left);
+ flp.rightMargin += (newInsets.right - oldInsets.right);
+ flp.bottomMargin += (newInsets.bottom - oldInsets.bottom);
+ }
+ child.setLayoutParams(flp);
+ }
+
private boolean isEventOverFolderTextRegion(Folder folder, MotionEvent ev) {
getDescendantRectRelativeToSelf(folder.getEditTextRegion(), mHitRect);
if (mHitRect.contains((int) ev.getX(), (int) ev.getY())) {
@@ -156,7 +171,8 @@ public class DragLayer extends FrameLayout implements ViewGroup.OnHierarchyChang
}
Folder currentFolder = mLauncher.getWorkspace().getOpenFolder();
- if (currentFolder != null && !mLauncher.isFolderClingVisible() && intercept) {
+ if (currentFolder != null && !mLauncher.getLauncherClings().isFolderClingVisible() &&
+ intercept) {
if (currentFolder.isEditingName()) {
if (!isEventOverFolderTextRegion(currentFolder, ev)) {
currentFolder.dismissEditingName();
@@ -212,22 +228,19 @@ public class DragLayer extends FrameLayout implements ViewGroup.OnHierarchyChang
sendTapOutsideFolderAccessibilityEvent(currentFolder.isEditingName());
mHoverPointClosesFolder = true;
return true;
- } else if (isOverFolder) {
- mHoverPointClosesFolder = false;
- } else {
- return true;
}
+ mHoverPointClosesFolder = false;
+ break;
case MotionEvent.ACTION_HOVER_MOVE:
isOverFolder = isEventOverFolder(currentFolder, ev);
if (!isOverFolder && !mHoverPointClosesFolder) {
sendTapOutsideFolderAccessibilityEvent(currentFolder.isEditingName());
mHoverPointClosesFolder = true;
return true;
- } else if (isOverFolder) {
- mHoverPointClosesFolder = false;
- } else {
+ } else if (!isOverFolder) {
return true;
}
+ mHoverPointClosesFolder = false;
}
}
}
@@ -480,7 +493,7 @@ public class DragLayer extends FrameLayout implements ViewGroup.OnHierarchyChang
}
public void animateViewIntoPosition(DragView dragView, final View child) {
- animateViewIntoPosition(dragView, child, null);
+ animateViewIntoPosition(dragView, child, null, null);
}
public void animateViewIntoPosition(DragView dragView, final int[] pos, float alpha,
@@ -496,8 +509,8 @@ public class DragLayer extends FrameLayout implements ViewGroup.OnHierarchyChang
}
public void animateViewIntoPosition(DragView dragView, final View child,
- final Runnable onFinishAnimationRunnable) {
- animateViewIntoPosition(dragView, child, -1, onFinishAnimationRunnable, null);
+ final Runnable onFinishAnimationRunnable, View anchorView) {
+ animateViewIntoPosition(dragView, child, -1, onFinishAnimationRunnable, anchorView);
}
public void animateViewIntoPosition(DragView dragView, final View child, int duration,
@@ -522,14 +535,18 @@ public class DragLayer extends FrameLayout implements ViewGroup.OnHierarchyChang
scale *= childScale;
int toX = coord[0];
int toY = coord[1];
+ float toScale = scale;
if (child instanceof TextView) {
TextView tv = (TextView) child;
+ // Account for the source scale of the icon (ie. from AllApps to Workspace, in which
+ // the workspace may have smaller icon bounds).
+ toScale = scale / dragView.getIntrinsicIconScaleFactor();
// The child may be scaled (always about the center of the view) so to account for it,
// we have to offset the position by the scaled size. Once we do that, we can center
// the drag view about the scaled child view.
- toY += Math.round(scale * tv.getPaddingTop());
- toY -= dragView.getMeasuredHeight() * (1 - scale) / 2;
+ toY += Math.round(toScale * tv.getPaddingTop());
+ toY -= dragView.getMeasuredHeight() * (1 - toScale) / 2;
toX -= (dragView.getMeasuredWidth() - Math.round(scale * child.getMeasuredWidth())) / 2;
} else if (child instanceof FolderIcon) {
// Account for holographic blur padding on the drag view
@@ -555,7 +572,7 @@ public class DragLayer extends FrameLayout implements ViewGroup.OnHierarchyChang
}
}
};
- animateViewIntoPosition(dragView, fromX, fromY, toX, toY, 1, 1, 1, scale, scale,
+ animateViewIntoPosition(dragView, fromX, fromY, toX, toY, 1, 1, 1, toScale, toScale,
onCompleteRunnable, ANIMATION_END_DISAPPEAR, duration, anchorView);
}
@@ -645,8 +662,10 @@ public class DragLayer extends FrameLayout implements ViewGroup.OnHierarchyChang
int x = (int) (fromLeft + Math.round(((to.left - fromLeft) * motionPercent)));
int y = (int) (fromTop + Math.round(((to.top - fromTop) * motionPercent)));
- int xPos = x - mDropView.getScrollX() + (mAnchorView != null
- ? (mAnchorViewInitialScrollX - mAnchorView.getScrollX()) : 0);
+ int anchorAdjust = mAnchorView == null ? 0 : (int) (mAnchorView.getScaleX() *
+ (mAnchorViewInitialScrollX - mAnchorView.getScrollX()));
+
+ int xPos = x - mDropView.getScrollX() + anchorAdjust;
int yPos = y - mDropView.getScrollY();
mDropView.setTranslationX(xPos);
@@ -755,31 +774,26 @@ public class DragLayer extends FrameLayout implements ViewGroup.OnHierarchyChang
}
private void updateChildIndices() {
- if (mLauncher != null) {
- mWorkspaceIndex = indexOfChild(mLauncher.getWorkspace());
- mQsbIndex = indexOfChild(mLauncher.getSearchBar());
+ mDragViewIndex = -1;
+ int childCount = getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ if (getChildAt(i) instanceof DragView) {
+ mDragViewIndex = i;
+ }
}
}
@Override
protected int getChildDrawingOrder(int childCount, int i) {
- // TODO: We have turned off this custom drawing order because it now effects touch
- // dispatch order. We need to sort that issue out and then decide how to go about this.
- if (true || LauncherAppState.isScreenLandscape(getContext()) ||
- mWorkspaceIndex == -1 || mQsbIndex == -1 ||
- mLauncher.getWorkspace().isDrawingBackgroundGradient()) {
+ if (mDragViewIndex == -1) {
return i;
- }
-
- // This ensures that the workspace is drawn above the hotseat and qsb,
- // except when the workspace is drawing a background gradient, in which
- // case we want the workspace to stay behind these elements.
- if (i == mQsbIndex) {
- return mWorkspaceIndex;
- } else if (i == mWorkspaceIndex) {
- return mQsbIndex;
- } else {
+ } else if (i == mDragViewIndex) {
+ return getChildCount()-1;
+ } else if (i < mDragViewIndex) {
return i;
+ } else {
+ // i > mDragViewIndex
+ return i-1;
}
}
@@ -800,7 +814,6 @@ public class DragLayer extends FrameLayout implements ViewGroup.OnHierarchyChang
/**
* Note: this is a reimplementation of View.isLayoutRtl() since that is currently hidden api.
*/
- @Override
public boolean isLayoutRtl() {
return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
}
diff --git a/src/com/android/launcher3/DragSource.java b/src/com/android/launcher3/DragSource.java
index 2ef99ae08..7369eeac2 100644
--- a/src/com/android/launcher3/DragSource.java
+++ b/src/com/android/launcher3/DragSource.java
@@ -31,6 +31,22 @@ public interface DragSource {
boolean supportsFlingToDelete();
/**
+ * @return whether items dragged from this source supports 'App Info'
+ */
+ boolean supportsAppInfoDropTarget();
+
+ /**
+ * @return whether items dragged from this source supports 'Delete' drop target (e.g. to remove
+ * a shortcut.
+ */
+ boolean supportsDeleteDropTarget();
+
+ /*
+ * @return the scale of the icons over the workspace icon size
+ */
+ float getIntrinsicIconScaleFactor();
+
+ /**
* A callback specifically made back to the source after an item from this source has been flung
* to be deleted on a DropTarget. In such a situation, this method will be called after
* onDropCompleted, and more importantly, after the fling animation has completed.
diff --git a/src/com/android/launcher3/DragView.java b/src/com/android/launcher3/DragView.java
index 686cf62ff..ea34e46f9 100644
--- a/src/com/android/launcher3/DragView.java
+++ b/src/com/android/launcher3/DragView.java
@@ -14,7 +14,6 @@
* limitations under the License.
*/
-
package com.android.launcher3;
import android.animation.ValueAnimator;
@@ -30,8 +29,6 @@ import android.graphics.Rect;
import android.view.View;
import android.view.animation.DecelerateInterpolator;
-import com.android.launcher3.R;
-
public class DragView extends View {
private static float sDragAlpha = 1f;
@@ -51,6 +48,9 @@ public class DragView extends View {
private float mOffsetX = 0.0f;
private float mOffsetY = 0.0f;
private float mInitialScale = 1f;
+ // The intrinsic icon scale factor is the scale factor for a drag icon over the workspace
+ // size. This is ignored for non-icons.
+ private float mIntrinsicIconScale = 1f;
/**
* Construct the drag view.
@@ -120,6 +120,15 @@ public class DragView extends View {
mPaint = new Paint(Paint.FILTER_BITMAP_FLAG);
}
+ /** Sets the scale of the view over the normal workspace icon size. */
+ public void setIntrinsicIconScaleFactor(float scale) {
+ mIntrinsicIconScale = scale;
+ }
+
+ public float getIntrinsicIconScaleFactor() {
+ return mIntrinsicIconScale;
+ }
+
public float getOffsetY() {
return mOffsetY;
}
diff --git a/src/com/android/launcher3/DrawableStateProxyView.java b/src/com/android/launcher3/DrawableStateProxyView.java
index 0758de1f7..c83659ad5 100644
--- a/src/com/android/launcher3/DrawableStateProxyView.java
+++ b/src/com/android/launcher3/DrawableStateProxyView.java
@@ -23,8 +23,6 @@ import android.view.MotionEvent;
import android.view.View;
import android.widget.LinearLayout;
-import com.android.launcher3.R;
-
public class DrawableStateProxyView extends LinearLayout {
private View mView;
diff --git a/src/com/android/launcher3/DynamicGrid.java b/src/com/android/launcher3/DynamicGrid.java
index 6457fdc31..9be377e8e 100644
--- a/src/com/android/launcher3/DynamicGrid.java
+++ b/src/com/android/launcher3/DynamicGrid.java
@@ -16,495 +16,14 @@
package com.android.launcher3;
-import android.appwidget.AppWidgetHostView;
-import android.content.ComponentName;
import android.content.Context;
-import android.content.res.Configuration;
import android.content.res.Resources;
-import android.graphics.Paint;
-import android.graphics.Paint.FontMetrics;
-import android.graphics.PointF;
-import android.graphics.Rect;
import android.util.DisplayMetrics;
import android.util.TypedValue;
-import android.view.Gravity;
-import android.view.View;
-import android.view.ViewGroup.LayoutParams;
-import android.widget.FrameLayout;
-import android.widget.LinearLayout;
import com.android.launcher3.settings.SettingsProvider;
import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-
-
-class DeviceProfileQuery {
- float widthDps;
- float heightDps;
- float value;
- PointF dimens;
-
- DeviceProfileQuery(float w, float h, float v) {
- widthDps = w;
- heightDps = h;
- value = v;
- dimens = new PointF(w, h);
- }
-}
-
-class DeviceProfile {
- String name;
- float minWidthDps;
- float minHeightDps;
- float numRows;
- float numColumns;
- float iconSize;
- float iconTextSize;
- float numHotseatIcons;
- float hotseatIconSize;
-
- boolean isLandscape;
- boolean isTablet;
- boolean isLargeTablet;
- boolean transposeLayoutWithOrientation;
-
- int desiredWorkspaceLeftRightMarginPx;
- int edgeMarginPx;
- Rect defaultWidgetPadding;
-
- int widthPx;
- int heightPx;
- int availableWidthPx;
- int availableHeightPx;
- int iconSizePx;
- int iconTextSizePx;
- int cellWidthPx;
- int cellHeightPx;
- int folderBackgroundOffset;
- int folderIconSizePx;
- int folderCellWidthPx;
- int folderCellHeightPx;
- int hotseatCellWidthPx;
- int hotseatCellHeightPx;
- int hotseatIconSizePx;
- int hotseatBarHeightPx;
- int hotseatAllAppsRank;
- int allAppsNumRows;
- int allAppsNumCols;
- boolean searchBarVisible;
- int searchBarSpaceWidthPx;
- int searchBarSpaceMaxWidthPx;
- int searchBarSpaceHeightPx;
- int searchBarHeightPx;
- int pageIndicatorHeightPx;
-
- DeviceProfile(String n, float w, float h, float r, float c,
- float is, float its, float hs, float his) {
- // Ensure that we have an odd number of hotseat items (since we need to place all apps)
- if (!AppsCustomizePagedView.DISABLE_ALL_APPS && hs % 2 == 0) {
- throw new RuntimeException("All Device Profiles must have an odd number of hotseat spaces");
- }
-
- name = n;
- minWidthDps = w;
- minHeightDps = h;
- numRows = r;
- numColumns = c;
- iconSize = is;
- iconTextSize = its;
- numHotseatIcons = hs;
- hotseatIconSize = his;
- }
-
- DeviceProfile(Context context,
- ArrayList<DeviceProfile> profiles,
- float minWidth, float minHeight,
- int wPx, int hPx,
- int awPx, int ahPx,
- Resources resources) {
- DisplayMetrics dm = resources.getDisplayMetrics();
- ArrayList<DeviceProfileQuery> points =
- new ArrayList<DeviceProfileQuery>();
- transposeLayoutWithOrientation =
- resources.getBoolean(R.bool.hotseat_transpose_layout_with_orientation);
- minWidthDps = minWidth;
- minHeightDps = minHeight;
-
- ComponentName cn = new ComponentName(context.getPackageName(),
- this.getClass().getName());
- defaultWidgetPadding = AppWidgetHostView.getDefaultPaddingForWidget(context, cn, null);
- edgeMarginPx = resources.getDimensionPixelSize(R.dimen.dynamic_grid_edge_margin);
- desiredWorkspaceLeftRightMarginPx = 2 * edgeMarginPx;
- pageIndicatorHeightPx = resources.getDimensionPixelSize(R.dimen.dynamic_grid_page_indicator_height);
-
- // Interpolate the rows
- for (DeviceProfile p : profiles) {
- points.add(new DeviceProfileQuery(p.minWidthDps, p.minHeightDps, p.numRows));
- }
- numRows = Math.round(invDistWeightedInterpolate(minWidth, minHeight, points));
- // Interpolate the columns
- points.clear();
- for (DeviceProfile p : profiles) {
- points.add(new DeviceProfileQuery(p.minWidthDps, p.minHeightDps, p.numColumns));
- }
- numColumns = Math.round(invDistWeightedInterpolate(minWidth, minHeight, points));
- // Interpolate the icon size
- points.clear();
- for (DeviceProfile p : profiles) {
- points.add(new DeviceProfileQuery(p.minWidthDps, p.minHeightDps, p.iconSize));
- }
- iconSize = invDistWeightedInterpolate(minWidth, minHeight, points);
- iconSizePx = DynamicGrid.pxFromDp(iconSize, dm);
-
- // Interpolate the icon text size
- points.clear();
- for (DeviceProfile p : profiles) {
- points.add(new DeviceProfileQuery(p.minWidthDps, p.minHeightDps, p.iconTextSize));
- }
- iconTextSize = invDistWeightedInterpolate(minWidth, minHeight, points);
- iconTextSizePx = DynamicGrid.pxFromSp(iconTextSize, dm);
-
- // Interpolate the hotseat size
- points.clear();
- for (DeviceProfile p : profiles) {
- points.add(new DeviceProfileQuery(p.minWidthDps, p.minHeightDps, p.numHotseatIcons));
- }
- numHotseatIcons = Math.round(invDistWeightedInterpolate(minWidth, minHeight, points));
- // Interpolate the hotseat icon size
- points.clear();
- for (DeviceProfile p : profiles) {
- points.add(new DeviceProfileQuery(p.minWidthDps, p.minHeightDps, p.hotseatIconSize));
- }
- // Hotseat
- hotseatIconSize = invDistWeightedInterpolate(minWidth, minHeight, points);
- hotseatIconSizePx = DynamicGrid.pxFromDp(hotseatIconSize, dm);
- hotseatAllAppsRank = (int) Math.ceil(numColumns / 2);
-
- // Calculate other vars based on Configuration
- updateFromConfiguration(resources, wPx, hPx, awPx, ahPx);
-
- // Search Bar
- searchBarVisible = SettingsProvider.getBoolean(context, SettingsProvider.SETTINGS_UI_HOMESCREEN_SEARCH,
- R.bool.preferences_interface_homescreen_search_default);
- searchBarSpaceMaxWidthPx = resources.getDimensionPixelSize(R.dimen.dynamic_grid_search_bar_max_width);
- searchBarHeightPx = resources.getDimensionPixelSize(R.dimen.dynamic_grid_search_bar_height);
-
- searchBarSpaceHeightPx = searchBarHeightPx + (searchBarVisible ? 2 * edgeMarginPx : 0);
-
- // Calculate the actual text height
- Paint textPaint = new Paint();
- textPaint.setTextSize(iconTextSizePx);
- FontMetrics fm = textPaint.getFontMetrics();
- cellWidthPx = iconSizePx;
- cellHeightPx = iconSizePx + (int) Math.ceil(fm.bottom - fm.top);
-
- // At this point, if the cells do not fit into the available height, then we need
- // to shrink the icon size
- /*
- Rect padding = getWorkspacePadding(isLandscape ?
- CellLayout.LANDSCAPE : CellLayout.PORTRAIT);
- int h = (int) (numRows * cellHeightPx) + padding.top + padding.bottom;
- if (h > availableHeightPx) {
- float delta = h - availableHeightPx;
- int deltaPx = (int) Math.ceil(delta / numRows);
- iconSizePx -= deltaPx;
- iconSize = DynamicGrid.dpiFromPx(iconSizePx, dm);
- cellWidthPx = iconSizePx;
- cellHeightPx = iconSizePx + (int) Math.ceil(fm.bottom - fm.top);
- }
- */
-
- // Hotseat
- hotseatBarHeightPx = iconSizePx + 4 * edgeMarginPx;
- hotseatCellWidthPx = iconSizePx;
- hotseatCellHeightPx = iconSizePx;
-
- // Folder
- folderCellWidthPx = cellWidthPx + 3 * edgeMarginPx;
- folderCellHeightPx = cellHeightPx + (int) ((3f/2f) * edgeMarginPx);
- folderBackgroundOffset = -edgeMarginPx;
- folderIconSizePx = iconSizePx + 2 * -folderBackgroundOffset;
- }
-
- void updateFromConfiguration(Resources resources, int wPx, int hPx,
- int awPx, int ahPx) {
- isLandscape = (resources.getConfiguration().orientation ==
- Configuration.ORIENTATION_LANDSCAPE);
- isTablet = resources.getBoolean(R.bool.is_tablet);
- isLargeTablet = resources.getBoolean(R.bool.is_large_tablet);
- widthPx = wPx;
- heightPx = hPx;
- availableWidthPx = awPx;
- availableHeightPx = ahPx;
-
- Rect padding = getWorkspacePadding(isLandscape ?
- CellLayout.LANDSCAPE : CellLayout.PORTRAIT);
- int pageIndicatorOffset =
- resources.getDimensionPixelSize(R.dimen.apps_customize_page_indicator_offset);
- if (isLandscape) {
- allAppsNumRows = (availableHeightPx - pageIndicatorOffset - 4 * edgeMarginPx) /
- (iconSizePx + iconTextSizePx + 2 * edgeMarginPx);
- } else {
- allAppsNumRows = (int) numRows + 1;
- }
- allAppsNumCols = (availableWidthPx - padding.left - padding.right - 2 * edgeMarginPx) /
- (iconSizePx + 2 * edgeMarginPx);
- allAppsNumCols = (int) Math.min(numColumns, allAppsNumCols);
-
- if (isPhone()) {
- searchBarSpaceWidthPx = Math.min(searchBarSpaceMaxWidthPx, widthPx);
- } else {
- searchBarSpaceWidthPx = wPx - (isLandscape ? 3 : 1) * iconSizePx;
- }
- }
-
- private float dist(PointF p0, PointF p1) {
- return (float) Math.sqrt((p1.x - p0.x)*(p1.x-p0.x) +
- (p1.y-p0.y)*(p1.y-p0.y));
- }
-
- private float weight(PointF a, PointF b,
- float pow) {
- float d = dist(a, b);
- if (d == 0f) {
- return Float.POSITIVE_INFINITY;
- }
- return (float) (1f / Math.pow(d, pow));
- }
-
- private float invDistWeightedInterpolate(float width, float height,
- ArrayList<DeviceProfileQuery> points) {
- float sum = 0;
- float weights = 0;
- float pow = 5;
- float kNearestNeighbors = 3;
- final PointF xy = new PointF(width, height);
-
- ArrayList<DeviceProfileQuery> pointsByNearness = points;
- Collections.sort(pointsByNearness, new Comparator<DeviceProfileQuery>() {
- public int compare(DeviceProfileQuery a, DeviceProfileQuery b) {
- return (int) (dist(xy, a.dimens) - dist(xy, b.dimens));
- }
- });
-
- for (int i = 0; i < pointsByNearness.size(); ++i) {
- DeviceProfileQuery p = pointsByNearness.get(i);
- if (i < kNearestNeighbors) {
- float w = weight(xy, p.dimens, pow);
- if (w == Float.POSITIVE_INFINITY) {
- return p.value;
- }
- weights += w;
- }
- }
-
- for (int i = 0; i < pointsByNearness.size(); ++i) {
- DeviceProfileQuery p = pointsByNearness.get(i);
- if (i < kNearestNeighbors) {
- float w = weight(xy, p.dimens, pow);
- sum += w * p.value / weights;
- }
- }
-
- return sum;
- }
-
- Rect getWorkspacePadding(int orientation) {
- Rect padding = new Rect();
- if (orientation == CellLayout.LANDSCAPE &&
- transposeLayoutWithOrientation) {
- // Pad the left and right of the workspace with search/hotseat bar sizes
- padding.set(searchBarVisible ? searchBarSpaceHeightPx : edgeMarginPx, edgeMarginPx,
- hotseatBarHeightPx, edgeMarginPx);
- } else {
- if (isTablet()) {
- // Pad the left and right of the workspace to ensure consistent spacing
- // between all icons
- int width = (orientation == CellLayout.LANDSCAPE)
- ? Math.max(widthPx, heightPx)
- : Math.min(widthPx, heightPx);
- // XXX: If the icon size changes across orientations, we will have to take
- // that into account here too.
- int gap = (int) ((width - 2 * edgeMarginPx -
- (numColumns * cellWidthPx)) / (2 * (numColumns + 1)));
- padding.set(edgeMarginPx + gap,
- searchBarVisible ? searchBarSpaceHeightPx : edgeMarginPx,
- edgeMarginPx + gap,
- hotseatBarHeightPx + pageIndicatorHeightPx);
- } else {
- // Pad the top and bottom of the workspace with search/hotseat bar sizes
- padding.set(desiredWorkspaceLeftRightMarginPx - defaultWidgetPadding.left,
- searchBarVisible ? searchBarSpaceHeightPx : edgeMarginPx,
- desiredWorkspaceLeftRightMarginPx - defaultWidgetPadding.right,
- hotseatBarHeightPx + pageIndicatorHeightPx);
- }
- }
- return padding;
- }
-
- // The rect returned will be extended to below the system ui that covers the workspace
- Rect getHotseatRect() {
- if (isVerticalBarLayout()) {
- return new Rect(availableWidthPx - hotseatBarHeightPx, 0,
- Integer.MAX_VALUE, availableHeightPx);
- } else {
- return new Rect(0, availableHeightPx - hotseatBarHeightPx,
- availableWidthPx, Integer.MAX_VALUE);
- }
- }
-
- int calculateCellWidth(int width, int countX) {
- return width / countX;
- }
- int calculateCellHeight(int height, int countY) {
- return height / countY;
- }
-
- boolean isPhone() {
- return !isTablet && !isLargeTablet;
- }
- boolean isTablet() {
- return isTablet;
- }
- boolean isLargeTablet() {
- return isLargeTablet;
- }
-
- boolean isVerticalBarLayout() {
- return isLandscape && transposeLayoutWithOrientation;
- }
-
- public void layout(Launcher launcher) {
- FrameLayout.LayoutParams lp;
- Resources res = launcher.getResources();
- boolean hasVerticalBarLayout = isVerticalBarLayout();
-
- // Layout the search bar space
- View searchBar = launcher.getSearchBar();
- lp = (FrameLayout.LayoutParams) searchBar.getLayoutParams();
- if (hasVerticalBarLayout) {
- // Vertical search bar
- lp.gravity = Gravity.TOP | Gravity.LEFT;
- lp.width = searchBarSpaceHeightPx;
- lp.height = LayoutParams.MATCH_PARENT;
- searchBar.setPadding(
- 0, 2 * edgeMarginPx, 0,
- 2 * edgeMarginPx);
- } else {
- // Horizontal search bar
- lp.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL;
- lp.width = searchBarSpaceWidthPx;
- lp.height = searchBarSpaceHeightPx;
- searchBar.setPadding(
- 2 * edgeMarginPx,
- 2 * edgeMarginPx,
- 2 * edgeMarginPx, 0);
- }
- searchBar.setLayoutParams(lp);
-
- // Layout the drop target icons
- LinearLayout dropTargetBar = (LinearLayout) launcher.getSearchBar().getDropTargetBar();
- if (hasVerticalBarLayout) {
- dropTargetBar.setOrientation(LinearLayout.VERTICAL);
- } else {
- dropTargetBar.setOrientation(LinearLayout.HORIZONTAL);
- }
-
- // Layout the search bar
- View qsbBar = launcher.getQsbBar();
- qsbBar.setVisibility(searchBarVisible ? View.VISIBLE : View.GONE);
- LayoutParams vglp = qsbBar.getLayoutParams();
- vglp.width = LayoutParams.MATCH_PARENT;
- vglp.height = LayoutParams.MATCH_PARENT;
- qsbBar.setLayoutParams(vglp);
-
- // Layout the voice proxy
- View voiceButtonProxy = launcher.findViewById(R.id.voice_button_proxy);
- if (voiceButtonProxy != null) {
- if (hasVerticalBarLayout) {
- // TODO: MOVE THIS INTO SEARCH BAR MEASURE
- } else {
- lp = (FrameLayout.LayoutParams) voiceButtonProxy.getLayoutParams();
- lp.gravity = Gravity.TOP | Gravity.END;
- lp.width = (widthPx - searchBarSpaceWidthPx) / 2 +
- 2 * iconSizePx;
- lp.height = searchBarSpaceHeightPx;
- }
- }
-
- // Layout the workspace
- View workspace = launcher.findViewById(R.id.workspace);
- lp = (FrameLayout.LayoutParams) workspace.getLayoutParams();
- lp.gravity = Gravity.CENTER;
- Rect padding = getWorkspacePadding(isLandscape
- ? CellLayout.LANDSCAPE
- : CellLayout.PORTRAIT);
- workspace.setPadding(padding.left, padding.top,
- padding.right, padding.bottom);
- workspace.setLayoutParams(lp);
-
- // Layout the hotseat
- View hotseat = launcher.findViewById(R.id.hotseat);
- lp = (FrameLayout.LayoutParams) hotseat.getLayoutParams();
- if (hasVerticalBarLayout) {
- // Vertical hotseat
- lp.gravity = Gravity.RIGHT;
- lp.width = hotseatBarHeightPx;
- lp.height = LayoutParams.MATCH_PARENT;
- hotseat.setPadding(0, 2 * edgeMarginPx,
- 2 * edgeMarginPx, 2 * edgeMarginPx);
- } else if (isTablet()) {
- // Pad the hotseat with the grid gap calculated above
- int gridGap = (int) ((widthPx - 2 * edgeMarginPx -
- (numColumns * cellWidthPx)) / (2 * (numColumns + 1)));
- int gridWidth = (int) ((numColumns * cellWidthPx) +
- ((numColumns - 1) * gridGap));
- int hotseatGap = (int) Math.max(0,
- (gridWidth - (numHotseatIcons * hotseatCellWidthPx))
- / (numHotseatIcons - 1));
- lp.gravity = Gravity.BOTTOM;
- lp.width = LayoutParams.MATCH_PARENT;
- lp.height = hotseatBarHeightPx;
- hotseat.setPadding(2 * edgeMarginPx + gridGap + hotseatGap, 0,
- 2 * edgeMarginPx + gridGap + hotseatGap,
- 2 * edgeMarginPx);
- } else {
- // For phones, layout the hotseat without any bottom margin
- // to ensure that we have space for the folders
- lp.gravity = Gravity.BOTTOM;
- lp.width = LayoutParams.MATCH_PARENT;
- lp.height = hotseatBarHeightPx;
- hotseat.findViewById(R.id.layout).setPadding(2 * edgeMarginPx, 0,
- 2 * edgeMarginPx, 0);
- }
- hotseat.setLayoutParams(lp);
-
- // Layout the page indicators
- View pageIndicator = launcher.findViewById(R.id.page_indicator);
- if (pageIndicator != null) {
- if (hasVerticalBarLayout) {
- // Hide the page indicators when we have vertical search/hotseat
- pageIndicator.setVisibility(View.GONE);
- } else {
- // Put the page indicators above the hotseat
- lp = (FrameLayout.LayoutParams) pageIndicator.getLayoutParams();
- lp.gravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
- lp.width = LayoutParams.WRAP_CONTENT;
- lp.height = LayoutParams.WRAP_CONTENT;
- lp.bottomMargin = hotseatBarHeightPx;
- pageIndicator.setLayoutParams(lp);
- }
- }
-
- // Layout the apps customize
- View appsCustomize = launcher.findViewById(R.id.apps_customize_pane_content);
- lp = (FrameLayout.LayoutParams) appsCustomize.getLayoutParams();
- lp.gravity = Gravity.CENTER;
- appsCustomize.setLayoutParams(lp);
- }
-}
public class DynamicGrid {
@SuppressWarnings("unused")
@@ -514,6 +33,10 @@ public class DynamicGrid {
private float mMinWidth;
private float mMinHeight;
+ // This is a static that we use for the default icon size on a 4/5-inch phone
+ static float DEFAULT_ICON_SIZE_DP = 60;
+ static float DEFAULT_ICON_SIZE_PX = 0;
+
public static float dpiFromPx(int size, DisplayMetrics metrics){
float densityRatio = (float) metrics.densityDpi / DisplayMetrics.DENSITY_DEFAULT;
return (size / densityRatio);
@@ -534,29 +57,34 @@ public class DynamicGrid {
DisplayMetrics dm = resources.getDisplayMetrics();
ArrayList<DeviceProfile> deviceProfiles =
new ArrayList<DeviceProfile>();
- boolean hasAA = !AppsCustomizePagedView.DISABLE_ALL_APPS;
+ boolean hasAA = !LauncherAppState.isDisableAllApps();
boolean useLargeIcons = SettingsProvider.getBoolean(context, SettingsProvider.SETTINGS_UI_GENERAL_ICONS_LARGE,
R.bool.preferences_interface_general_icons_large_default);
+ DEFAULT_ICON_SIZE_PX = pxFromDp(DEFAULT_ICON_SIZE_DP, dm);
// Our phone profiles include the bar sizes in each orientation
deviceProfiles.add(new DeviceProfile("Super Short Stubby",
- 255, 300, 2, 3, (useLargeIcons ? 54 : 48), 13, (hasAA ? 5 : 4), (useLargeIcons ? 54 : 48)));
+ 255, 300, 2, 3, (useLargeIcons ? 54 : 48), 13, (hasAA ? 5 : 5), (useLargeIcons ? 54 : 48)));
deviceProfiles.add(new DeviceProfile("Shorter Stubby",
- 255, 400, 3, 3, (useLargeIcons ? 54 : 48), 13, (hasAA ? 5 : 4), (useLargeIcons ? 54 : 48)));
+ 255, 400, 3, 3, (useLargeIcons ? 54 : 48), 13, (hasAA ? 5 : 5), (useLargeIcons ? 54 : 48)));
deviceProfiles.add(new DeviceProfile("Short Stubby",
- 275, 420, 3, 4, (useLargeIcons ? 54 : 48), 13, (hasAA ? 5 : 4), (useLargeIcons ? 54 : 48)));
+ 275, 420, 3, 4, (useLargeIcons ? 54 : 48), 13, (hasAA ? 5 : 5), (useLargeIcons ? 54 : 48)));
deviceProfiles.add(new DeviceProfile("Stubby",
- 255, 450, 3, 4, (useLargeIcons ? 54 : 48), 13, (hasAA ? 5 : 4), (useLargeIcons ? 54 : 48)));
- deviceProfiles.add(new DeviceProfile("Nexus S",
- 296, 491.33f, 4, 4, (useLargeIcons ? 56 : 48), 13, (hasAA ? 5 : 4), (useLargeIcons ? 56 : 48)));
+ 255, 450, 3, 4, (useLargeIcons ? 54 : 48), 13, (hasAA ? 5 : 5), (useLargeIcons ? 54 : 48)));
+ deviceProfiles.add(new DeviceProfile("Nexus 5",
+ 359, 567, 4, 4, (useLargeIcons ? DEFAULT_ICON_SIZE_DP : 56), 13, (hasAA ? 5 : 5), 56));
deviceProfiles.add(new DeviceProfile("Nexus 4",
- 359, 518, 4, 4, (useLargeIcons ? 60 : 52), 13, (hasAA ? 5 : 4), (useLargeIcons ? 56 : 48)));
+ 359, 518, 4, 4, (useLargeIcons ? DEFAULT_ICON_SIZE_DP : 52), 13, (hasAA ? 5 : 5), (useLargeIcons ? 56 : 48)));
+ deviceProfiles.add(new DeviceProfile("Large Phone",
+ 335, 567, 4, 4, (useLargeIcons ? DEFAULT_ICON_SIZE_DP : 56), 13, (hasAA ? 5 : 5), 56));
+ deviceProfiles.add(new DeviceProfile("Large Phone",
+ 406, 694, 5, 5, (useLargeIcons ? 64 : 56), 14.4f, 5, 56));
// The tablet profile is odd in that the landscape orientation
// also includes the nav bar on the side
deviceProfiles.add(new DeviceProfile("Nexus 7",
575, 904, 5, 5, (useLargeIcons ? 72 : 60), 14.4f, 7, (useLargeIcons ? 60 : 52)));
// Larger tablet profiles always have system bars on the top & bottom
deviceProfiles.add(new DeviceProfile("Nexus 10",
- 727, 1207, 5, 8, (useLargeIcons ? 80 : 64), 14.4f, 9, (useLargeIcons ? 64 : 56)));
+ 727, 1207, 5, 8, (useLargeIcons ? 76 : 64), 14.4f, 9, (useLargeIcons ? 64 : 56)));
/*
deviceProfiles.add(new DeviceProfile("Nexus 7",
600, 960, 5, 5, 72, 14.4f, 5, 60));
@@ -574,7 +102,7 @@ public class DynamicGrid {
resources);
}
- DeviceProfile getDeviceProfile() {
+ public DeviceProfile getDeviceProfile() {
return mProfile;
}
@@ -583,7 +111,7 @@ public class DynamicGrid {
"Wd: " + mProfile.minWidthDps + ", Hd: " + mProfile.minHeightDps +
", W: " + mProfile.widthPx + ", H: " + mProfile.heightPx +
" [r: " + mProfile.numRows + ", c: " + mProfile.numColumns +
- ", is: " + mProfile.iconSizePx + ", its: " + mProfile.iconTextSize +
+ ", is: " + mProfile.iconSizePx + ", its: " + mProfile.iconTextSizePx +
", cw: " + mProfile.cellWidthPx + ", ch: " + mProfile.cellHeightPx +
", hc: " + mProfile.numHotseatIcons + ", his: " + mProfile.hotseatIconSizePx + "]";
}
diff --git a/src/com/android/launcher3/DynamicGridSizeFragment.java b/src/com/android/launcher3/DynamicGridSizeFragment.java
new file mode 100644
index 000000000..586c2bd49
--- /dev/null
+++ b/src/com/android/launcher3/DynamicGridSizeFragment.java
@@ -0,0 +1,331 @@
+package com.android.launcher3;
+
+import android.animation.Animator;
+import android.animation.ObjectAnimator;
+import android.app.Dialog;
+import android.app.Fragment;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.util.DisplayMetrics;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.ListView;
+import android.widget.NumberPicker;
+import android.widget.TextView;
+import com.android.launcher3.settings.SettingsProvider;
+
+public class DynamicGridSizeFragment extends Fragment implements NumberPicker.OnValueChangeListener, Dialog.OnDismissListener{
+ public static final String DYNAMIC_GRID_SIZE_FRAGMENT = "dynamicGridSizeFragment";
+ public static final int MIN_DYNAMIC_GRID_ROWS = 2;
+ public static final int MIN_DYNAMIC_GRID_COLUMNS = 3;
+ ImageView mDynamicGridImage;
+ ListView mListView;
+ View mCurrentSelection;
+ GridSizeArrayAdapter mAdapter;
+ DeviceProfile.GridSize mCurrentSize;
+
+ Dialog mDialog;
+
+ int mCustomGridRows = 0;
+ int mCustomGridColumns = 0;
+
+ View.OnClickListener mSettingsItemListener = new View.OnClickListener() {
+
+ @Override
+ public void onClick(View v) {
+ mCurrentSize = DeviceProfile.GridSize
+ .getModeForValue((Integer) v.getTag());
+
+ setCleared(mCurrentSelection);
+ setSelected(v);
+ mCurrentSelection = v;
+
+ if (mCurrentSize == DeviceProfile.GridSize.Custom) {
+ showNumberPicker();
+ }
+
+ ((GridSizeArrayAdapter) mListView.getAdapter()).notifyDataSetChanged();
+
+ mAdapter.notifyDataSetInvalidated();
+ setCurrentImage();
+ }
+ };
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ View v = inflater.inflate(R.layout.dynamic_grid_size_screen, container, false);
+ mDynamicGridImage = (ImageView) v.findViewById(R.id.dynamic_grid_size_image);
+ mDynamicGridImage.setBackground(getResources().getDrawable(R.drawable.grid));
+
+ LinearLayout titleLayout = (LinearLayout) v.findViewById(R.id.dynamic_grid_title);
+ titleLayout.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ setSize();
+ }
+ });
+
+ mCurrentSize = DeviceProfile.GridSize.getModeForValue(
+ SettingsProvider.getIntCustomDefault(getActivity(),
+ SettingsProvider.SETTINGS_UI_DYNAMIC_GRID_SIZE, 0));
+
+ setCurrentImage();
+
+ mListView = (ListView) v.findViewById(R.id.dynamic_grid_list);
+ Resources res = getResources();
+ String [] values = {
+ res.getString(R.string.grid_size_comfortable),
+ res.getString(R.string.grid_size_cozy),
+ res.getString(R.string.grid_size_condensed),
+ res.getString(R.string.grid_size_custom)};
+ mAdapter = new GridSizeArrayAdapter(getActivity(),
+ R.layout.settings_pane_list_item, values);
+ mListView.setAdapter(mAdapter);
+
+ return v;
+ }
+
+ private void setCurrentImage() {
+ Drawable d = null;
+ boolean custom = false;
+
+ switch (mCurrentSize) {
+ case Comfortable:
+ d = getResources().getDrawable(R.drawable.grid_comfortable);
+ break;
+ case Cozy:
+ d = getResources().getDrawable(R.drawable.grid_cozy);
+ break;
+ case Condensed:
+ d = getResources().getDrawable(R.drawable.grid_condensed);
+ break;
+ default:
+
+ custom = true;
+ break;
+ }
+
+ if (d != null && !custom) {
+ mDynamicGridImage.setImageBitmap(null);
+ mDynamicGridImage.setBackground(d);
+ } else if (custom) {
+ mDynamicGridImage.setBackground(null);
+ mDynamicGridImage.setImageBitmap(writeOnDrawable(R.drawable.grid));
+ }
+ }
+
+ public Bitmap writeOnDrawable(int drawableId){
+ LauncherAppState app = LauncherAppState.getInstance();
+ DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
+
+ int rows = mCustomGridRows == 0 ? (int) grid.numRows : mCustomGridRows;
+ int columns = mCustomGridColumns == 0 ? (int) grid.numColumns : mCustomGridColumns;
+
+ String text = rows + " " + "\u00d7" + " " + columns;
+
+ Bitmap bm = BitmapFactory.decodeResource(getResources(),
+ drawableId).copy(Bitmap.Config.ARGB_8888, true);
+
+ Paint paint = new Paint();
+ paint.setStyle(Paint.Style.FILL);
+ paint.setColor(Color.BLACK);
+ int px = getResources().getDimensionPixelOffset(R.dimen.grid_custom_text);
+ paint.setTextSize(px);
+
+ Canvas canvas = new Canvas(bm);
+
+ float canvasWidth = canvas.getWidth();
+ float sentenceWidth = paint.measureText(text);
+ float startPositionX = (canvasWidth - sentenceWidth) / 2;
+
+ canvas.drawText(text, startPositionX, bm.getHeight()/2, paint);
+
+ return bm;
+ }
+
+ @Override
+ public Animator onCreateAnimator(int transit, boolean enter, int nextAnim) {
+ if (enter) {
+ DisplayMetrics displaymetrics = new DisplayMetrics();
+ getActivity().getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
+ int width = displaymetrics.widthPixels;
+ final ObjectAnimator anim = ObjectAnimator.ofFloat(this, "translationX", width, 0);
+
+ final View darkPanel = ((Launcher) getActivity()).getDarkPanel();
+ darkPanel.setVisibility(View.VISIBLE);
+ ObjectAnimator anim2 = ObjectAnimator.ofFloat(
+ darkPanel , "alpha", 0.0f, 0.3f);
+ anim2.start();
+
+ anim.addListener(new Animator.AnimatorListener() {
+ @Override
+ public void onAnimationStart(Animator arg0) {}
+ @Override
+ public void onAnimationRepeat(Animator arg0) {}
+ @Override
+ public void onAnimationEnd(Animator arg0) {
+ darkPanel.setVisibility(View.GONE);
+ }
+ @Override
+ public void onAnimationCancel(Animator arg0) {}
+ });
+
+ return anim;
+ } else {
+ return super.onCreateAnimator(transit, enter, nextAnim);
+ }
+ }
+
+ public void setSize() {
+ ((Launcher) getActivity()).setDynamicGridSize(mCurrentSize);
+ }
+
+ private void setSelected(View v) {
+ v.setBackgroundColor(Color.WHITE);
+ TextView t = (TextView) v.findViewById(R.id.item_name);
+ t.setTextColor(getResources().getColor(R.color.settings_bg_color));
+ }
+
+ private void setCleared(View v) {
+ v.setBackgroundColor(getResources().getColor(R.color.settings_bg_color));
+ TextView t = (TextView) v.findViewById(R.id.item_name);
+ t.setTextColor(Color.WHITE);
+ }
+
+ private void showNumberPicker() {
+ mDialog = new Dialog(getActivity());
+ mDialog.setTitle(getResources().getString(R.string.preferences_interface_homescreen_custom));
+ mDialog.setContentView(R.layout.custom_grid_size_dialog);
+
+ NumberPicker nPRows= (NumberPicker) mDialog.findViewById(R.id.custom_rows);
+ NumberPicker nPColumns = (NumberPicker) mDialog.findViewById(R.id.custom_columns);
+
+ LauncherAppState app = LauncherAppState.getInstance();
+ DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
+
+ int rows = grid.numRowsBase;
+ int columns = grid.numColumnsBase;
+ if (mCustomGridColumns == 0) {
+ mCustomGridColumns = (int) grid.numColumns;
+ }
+ if (mCustomGridRows == 0) {
+ mCustomGridRows = (int) grid.numRows;
+ }
+
+ nPRows.setMinValue(Math.max(MIN_DYNAMIC_GRID_ROWS, rows - DeviceProfile.GRID_SIZE_MIN));
+ nPRows.setMaxValue(rows + DeviceProfile.GRID_SIZE_MAX);
+ nPRows.setValue(mCustomGridRows);
+ nPRows.setWrapSelectorWheel(false);
+ nPRows.setOnValueChangedListener(this);
+ nPRows.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS);
+
+ nPColumns.setMinValue(Math.max(MIN_DYNAMIC_GRID_COLUMNS, columns - DeviceProfile.GRID_SIZE_MIN));
+ nPColumns.setMaxValue(columns + DeviceProfile.GRID_SIZE_MAX);
+ nPColumns.setValue(mCustomGridColumns);
+ nPColumns.setWrapSelectorWheel(false);
+ nPColumns.setOnValueChangedListener(this);
+ nPColumns.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS);
+
+ Button b = (Button) mDialog.findViewById(R.id.dialog_confirm_button);
+ b.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (mDialog != null) {
+ mDialog.dismiss();
+ }
+ }
+ });
+ mDialog.setOnDismissListener(this);
+ mDialog.show();
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ if (mDialog != null) {
+ mDialog.dismiss();
+ }
+ }
+
+ @Override
+ public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
+ if (picker.getId() == R.id.custom_rows) {
+ mCustomGridRows = newVal;
+ } else if (picker.getId() == R.id.custom_columns) {
+ mCustomGridColumns = newVal;
+ }
+ }
+
+ @Override
+ public void onDismiss(DialogInterface dialog) {
+ SettingsProvider.putInt(getActivity(),
+ SettingsProvider.SETTINGS_UI_HOMESCREEN_ROWS, mCustomGridRows);
+ SettingsProvider.putInt(getActivity(),
+ SettingsProvider.SETTINGS_UI_HOMESCREEN_COLUMNS, mCustomGridColumns);
+
+ mAdapter.notifyDataSetInvalidated();
+
+ setCurrentImage();
+ }
+
+ private class GridSizeArrayAdapter extends ArrayAdapter<String> {
+ Context mContext;
+ String[] mTitles;
+
+ public GridSizeArrayAdapter(Context context, int textViewResourceId,
+ String[] objects) {
+ super(context, textViewResourceId, objects);
+
+ mContext = context;
+ mTitles = objects;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ LayoutInflater inflater = (LayoutInflater) mContext
+ .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ convertView = inflater.inflate(R.layout.settings_pane_list_item,
+ parent, false);
+ TextView textView = (TextView) convertView
+ .findViewById(R.id.item_name);
+ textView.setText(mTitles[position]);
+ // Set Selected State
+ if (position == mCurrentSize.getValue()) {
+ mCurrentSelection = convertView;
+ setSelected(mCurrentSelection);
+ }
+
+ if (position == DeviceProfile.GridSize.Custom.getValue()) {
+ LauncherAppState app = LauncherAppState.getInstance();
+ DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
+
+ String state = mTitles[position];
+ int rows = SettingsProvider.getIntCustomDefault(getActivity(),
+ SettingsProvider.SETTINGS_UI_HOMESCREEN_ROWS, grid.numRowsBase);
+ int columns = SettingsProvider.getIntCustomDefault(getActivity(),
+ SettingsProvider.SETTINGS_UI_HOMESCREEN_COLUMNS, grid.numColumnsBase);
+ state += " " + "(" + rows + " " + "\u00d7" + " " + columns + ")";
+
+ textView.setText(state);
+ }
+
+ convertView.setOnClickListener(mSettingsItemListener);
+ convertView.setTag(position);
+ return convertView;
+ }
+ }
+}
diff --git a/src/com/android/launcher3/FastBitmapDrawable.java b/src/com/android/launcher3/FastBitmapDrawable.java
index 8061c619d..847a8e1bc 100644
--- a/src/com/android/launcher3/FastBitmapDrawable.java
+++ b/src/com/android/launcher3/FastBitmapDrawable.java
@@ -35,8 +35,7 @@ class FastBitmapDrawable extends Drawable {
mAlpha = 255;
mBitmap = b;
if (b != null) {
- mWidth = mBitmap.getWidth();
- mHeight = mBitmap.getHeight();
+ setBounds(0, 0, b.getWidth(), b.getHeight());
} else {
mWidth = mHeight = 0;
}
@@ -67,6 +66,7 @@ class FastBitmapDrawable extends Drawable {
public void setFilterBitmap(boolean filterBitmap) {
mPaint.setFilterBitmap(filterBitmap);
+ mPaint.setAntiAlias(filterBitmap);
}
public int getAlpha() {
@@ -75,32 +75,30 @@ class FastBitmapDrawable extends Drawable {
@Override
public int getIntrinsicWidth() {
- return mWidth;
+ int width = getBounds().width();
+ if (width == 0) {
+ width = mBitmap.getWidth();
+ }
+ return width;
}
@Override
public int getIntrinsicHeight() {
- return mHeight;
+ int height = getBounds().height();
+ if (height == 0) {
+ height = mBitmap.getHeight();
+ }
+ return height;
}
@Override
public int getMinimumWidth() {
- return mWidth;
+ return getBounds().width();
}
@Override
public int getMinimumHeight() {
- return mHeight;
- }
-
- public void setBitmap(Bitmap b) {
- mBitmap = b;
- if (b != null) {
- mWidth = mBitmap.getWidth();
- mHeight = mBitmap.getHeight();
- } else {
- mWidth = mHeight = 0;
- }
+ return getBounds().height();
}
public Bitmap getBitmap() {
diff --git a/src/com/android/launcher3/FirstFrameAnimatorHelper.java b/src/com/android/launcher3/FirstFrameAnimatorHelper.java
index 78fdadd4f..f4c49d77a 100644
--- a/src/com/android/launcher3/FirstFrameAnimatorHelper.java
+++ b/src/com/android/launcher3/FirstFrameAnimatorHelper.java
@@ -91,29 +91,30 @@ public class FirstFrameAnimatorHelper extends AnimatorListenerAdapter
mStartTime = currentTime;
}
+ final long currentPlayTime = animation.getCurrentPlayTime();
if (!mHandlingOnAnimationUpdate &&
sVisible &&
// If the current play time exceeds the duration, the animation
// will get finished, even if we call setCurrentPlayTime -- therefore
// don't adjust the animation in that case
- animation.getCurrentPlayTime() < animation.getDuration()) {
+ currentPlayTime < animation.getDuration()) {
mHandlingOnAnimationUpdate = true;
long frameNum = sGlobalFrameCounter - mStartFrame;
// If we haven't drawn our first frame, reset the time to t = 0
// (give up after MAX_DELAY ms of waiting though - might happen, for example, if we
// are no longer in the foreground and no frames are being rendered ever)
- if (frameNum == 0 && currentTime < mStartTime + MAX_DELAY) {
+ if (frameNum == 0 && currentTime < mStartTime + MAX_DELAY && currentPlayTime > 0) {
// The first frame on animations doesn't always trigger an invalidate...
// force an invalidate here to make sure the animation continues to advance
mTarget.getRootView().invalidate();
animation.setCurrentPlayTime(0);
-
// For the second frame, if the first frame took more than 16ms,
// adjust the start time and pretend it took only 16ms anyway. This
// prevents a large jump in the animation due to an expensive first frame
} else if (frameNum == 1 && currentTime < mStartTime + MAX_DELAY &&
!mAdjustedSecondFrameTime &&
- currentTime > mStartTime + IDEAL_FRAME_DURATION) {
+ currentTime > mStartTime + IDEAL_FRAME_DURATION &&
+ currentPlayTime > IDEAL_FRAME_DURATION) {
animation.setCurrentPlayTime(IDEAL_FRAME_DURATION);
mAdjustedSecondFrameTime = true;
} else {
diff --git a/src/com/android/launcher3/FocusHelper.java b/src/com/android/launcher3/FocusHelper.java
index 357af49f6..b92b17f22 100644
--- a/src/com/android/launcher3/FocusHelper.java
+++ b/src/com/android/launcher3/FocusHelper.java
@@ -548,7 +548,7 @@ public class FocusHelper {
final CellLayout layout = (CellLayout) parent.getParent();
final Workspace workspace = (Workspace) layout.getParent();
final ViewGroup launcher = (ViewGroup) workspace.getParent();
- final ViewGroup tabs = (ViewGroup) launcher.findViewById(R.id.qsb_bar);
+ final ViewGroup tabs = (ViewGroup) launcher.findViewById(R.id.search_drop_target_bar);
final ViewGroup hotseat = (ViewGroup) launcher.findViewById(R.id.hotseat);
int pageIndex = workspace.indexOfChild(layout);
int pageCount = workspace.getChildCount();
diff --git a/src/com/android/launcher3/Folder.java b/src/com/android/launcher3/Folder.java
index a00f3c1da..71183c342 100644
--- a/src/com/android/launcher3/Folder.java
+++ b/src/com/android/launcher3/Folder.java
@@ -20,11 +20,13 @@ import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
+import android.content.ComponentName;
import android.content.Context;
+import android.content.Intent;
import android.content.res.Resources;
import android.graphics.PointF;
import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
+import android.os.Bundle;
import android.os.SystemClock;
import android.support.v4.widget.AutoScrollHelper;
import android.text.InputType;
@@ -43,7 +45,9 @@ import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
+import android.widget.ImageView;
import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
import android.widget.ScrollView;
import android.widget.TextView;
@@ -62,6 +66,12 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
View.OnFocusChangeListener {
private static final String TAG = "Launcher.Folder";
+ private static final String PROTECTED_ACTION = "cyanogenmod.intent.action.PACKAGE_PROTECTED";
+ private static final String PROTECTED_STATE =
+ "cyanogenmod.intent.action.PACKAGE_PROTECTED_STATE";
+ private static final String PROTECTED_COMPONENT =
+ "cyanogenmod.intent.action.PACKAGE_PROTECTED_COMPONENT";
+
protected DragController mDragController;
protected Launcher mLauncher;
protected FolderInfo mInfo;
@@ -71,6 +81,8 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
static final int STATE_ANIMATING = 1;
static final int STATE_OPEN = 2;
+ private static final int CLOSE_FOLDER_DELAY_MS = 150;
+
private int mExpandDuration;
protected CellLayout mContent;
private ScrollView mScrollView;
@@ -79,17 +91,17 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
private int mState = STATE_NONE;
private static final int REORDER_ANIMATION_DURATION = 230;
private static final int REORDER_DELAY = 250;
- private static final int ON_EXIT_CLOSE_DELAY = 800;
+ private static final int ON_EXIT_CLOSE_DELAY = 400;
private boolean mRearrangeOnClose = false;
private FolderIcon mFolderIcon;
private int mMaxCountX;
private int mMaxCountY;
private int mMaxNumItems;
private ArrayList<View> mItemsInReadingOrder = new ArrayList<View>();
- private Drawable mIconDrawable;
boolean mItemsInvalidated = false;
private ShortcutInfo mCurrentDragInfo;
private View mCurrentDragView;
+ private boolean mIsExternalDrag;
boolean mSuppressOnAdd = false;
private int[] mTargetCell = new int[2];
private int[] mPreviousTargetCell = new int[2];
@@ -103,6 +115,8 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
private boolean mSuppressFolderDeletion = false;
private boolean mItemAddedBackToSelfViaIcon = false;
FolderEditText mFolderName;
+ ImageView mFolderLock;
+ RelativeLayout mFolderTitleSection;
private float mFolderIconPivotX;
private float mFolderIconPivotY;
@@ -116,6 +130,11 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
private int DRAG_MODE_REORDER = 1;
private int mDragMode = DRAG_MODE_NONE;
+ // We avoid measuring the scroll view with a 0 width or height, as this
+ // results in CellLayout being measured as UNSPECIFIED, which it does
+ // not support.
+ private static final int MIN_CONTENT_DIMEN = 5;
+
private boolean mDestroyed;
private AutoScrollHelper mAutoScrollHelper;
@@ -124,6 +143,8 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
private boolean mDeferDropAfterUninstall;
private boolean mUninstallSuccessful;
+ private boolean mHiddenFolder = false;
+
/**
* Used to inflate the Workspace from XML.
*
@@ -141,8 +162,13 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
Resources res = getResources();
mMaxCountX = (int) grid.numColumns;
- mMaxCountY = (int) grid.numRows;
- mMaxNumItems = mMaxCountX * mMaxCountY;
+ // Allow scrolling folders when DISABLE_ALL_APPS is true.
+ if (LauncherAppState.isDisableAllApps()) {
+ mMaxCountY = mMaxNumItems = Integer.MAX_VALUE;
+ } else {
+ mMaxCountY = (int) grid.numRows;
+ mMaxNumItems = mMaxCountX * mMaxCountY;
+ }
mInputMethodManager = (InputMethodManager)
getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
@@ -167,6 +193,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
super.onFinishInflate();
mScrollView = (ScrollView) findViewById(R.id.scroll_view);
mContent = (CellLayout) findViewById(R.id.folder_content);
+ int measureSpec = MeasureSpec.UNSPECIFIED;
LauncherAppState app = LauncherAppState.getInstance();
DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
@@ -181,7 +208,6 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
// We find out how tall the text view wants to be (it is set to wrap_content), so that
// we can allocate the appropriate amount of space for it.
- int measureSpec = MeasureSpec.UNSPECIFIED;
mFolderName.measure(measureSpec, measureSpec);
mFolderNameHeight = mFolderName.getMeasuredHeight();
@@ -199,6 +225,12 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
mFolderName.setVisibility(View.GONE);
mFolderNameHeight = getPaddingBottom();
}
+
+ mFolderLock = (ImageView) findViewById(R.id.folder_lock);
+ mFolderTitleSection = (RelativeLayout) findViewById(R.id.folder_title_section);
+ mFolderLock.measure(measureSpec, measureSpec);
+ mFolderLock.setOnClickListener(this);
+ mFolderTitleSection.measure(measureSpec, measureSpec);
}
private ActionMode.Callback mActionModeCallback = new ActionMode.Callback() {
@@ -223,6 +255,60 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
if (tag instanceof ShortcutInfo) {
mLauncher.onClick(v);
}
+
+ if (v.getId() == R.id.folder_lock) {
+ startHiddenFolderManager();
+ }
+ }
+
+ public void startHiddenFolderManager() {
+ Bundle bundle = new Bundle();
+ bundle.putBoolean(HiddenFolderFragment.HIDDEN_FOLDER_STATUS, mInfo.hidden);
+ mLauncher.validateLockForHiddenFolders(bundle, mFolderIcon);
+ }
+
+ public String[] getComponentTitles() {
+ int size = mItemsInReadingOrder.size();
+ String[] componentsTitles = new String[size];
+ for (int i = 0; i < size; i++) {
+ View v = mItemsInReadingOrder.get(i);
+ Object tag = v.getTag();
+ if (tag instanceof ShortcutInfo) {
+ componentsTitles[i] = ((ShortcutInfo) tag).title.toString();
+ }
+ }
+ return componentsTitles;
+ }
+
+ public String[] getComponents() {
+ String components = getComponentString();
+ return components.split("\\|");
+ }
+
+ public void modifyProtectedApps(boolean protect) {
+ String components = getComponentString();
+
+ Intent intent = new Intent();
+ intent.setAction(PROTECTED_ACTION);
+ intent.putExtra(PROTECTED_STATE, protect);
+ intent.putExtra(PROTECTED_COMPONENT, components);
+
+ mLauncher.sendBroadcast(intent);
+ }
+
+ private String getComponentString() {
+ int size = mItemsInReadingOrder.size();
+ String components = "";
+ for (int i = 0; i < size; i++) {
+ View v = mItemsInReadingOrder.get(i);
+ Object tag = v.getTag();
+ if (tag instanceof ShortcutInfo) {
+ ComponentName componentName = ((ShortcutInfo) tag).getIntent().getComponent();
+ components += componentName.flattenToString() + "|";
+ }
+ }
+
+ return components;
}
public boolean onLongClick(View v) {
@@ -236,11 +322,10 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
return false;
}
- mLauncher.dismissFolderCling(null);
+ mLauncher.getLauncherClings().dismissFolderCling(null);
mLauncher.getWorkspace().onDragStartedWithItem(v);
mLauncher.getWorkspace().beginDragShared(v, this);
- mIconDrawable = ((TextView) v).getCompoundDrawables()[1];
mCurrentDragInfo = item;
mEmptyCell[0] = item.cellX;
@@ -262,6 +347,8 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
public void startEditingFolderName() {
mFolderName.setHint("");
mIsEditingName = true;
+
+ mInputMethodManager.showSoftInput(mFolderName, 0);
}
public void dismissEditingName() {
@@ -305,10 +392,6 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
return mFolderName;
}
- public Drawable getDragDrawable() {
- return mIconDrawable;
- }
-
/**
* We need to handle touch events to prevent them from falling through to the workspace below.
*/
@@ -383,7 +466,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
int count = 0;
for (int i = 0; i < children.size(); i++) {
ShortcutInfo child = (ShortcutInfo) children.get(i);
- if (!createAndAddShortcut(child)) {
+ if (createAndAddShortcut(child) == null) {
overflow.add(child);
} else {
count++;
@@ -405,12 +488,26 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
updateTextViewFocus();
mInfo.addListener(this);
+ setFolderName();
+ updateItemLocationsInDatabase();
+ }
+
+ public void setFolderName() {
if (!sDefaultFolderName.contentEquals(mInfo.title)) {
mFolderName.setText(mInfo.title);
} else {
mFolderName.setText("");
}
updateItemLocationsInDatabase();
+
+ // In case any children didn't come across during loading, clean up the folder accordingly
+ mFolderIcon.post(new Runnable() {
+ public void run() {
+ if (getItemCount() <= 1) {
+ replaceFolderWithFinalItem();
+ }
+ }
+ });
}
/**
@@ -459,11 +556,15 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
public void onAnimationEnd(Animator animation) {
mState = STATE_OPEN;
setLayerType(LAYER_TYPE_NONE, null);
- Cling cling = mLauncher.showFirstRunFoldersCling();
- if (cling != null) {
- cling.bringScrimToFront();
- bringToFront();
- cling.bringToFront();
+
+ // Only show cling if we are not in the middle of a drag - this would be quite jarring.
+ if (!mDragController.isDragging()) {
+ Cling cling = mLauncher.getLauncherClings().showFoldersCling();
+ if (cling != null) {
+ cling.bringScrimToFront();
+ bringToFront();
+ cling.bringToFront();
+ }
}
setFocusOnFirstChild();
}
@@ -471,6 +572,23 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
oa.setDuration(mExpandDuration);
setLayerType(LAYER_TYPE_HARDWARE, null);
oa.start();
+
+ // Make sure the folder picks up the last drag move even if the finger doesn't move.
+ if (mDragController.isDragging()) {
+ mDragController.forceTouchMove();
+ }
+ }
+
+ public void beginExternalDrag(ShortcutInfo item) {
+ setupContentForNumItems(getItemCount() + 1);
+ findAndSetEmptyCells(item);
+
+ mCurrentDragInfo = item;
+ mEmptyCell[0] = item.cellX;
+ mEmptyCell[1] = item.cellY;
+ mIsExternalDrag = true;
+
+ mDragInProgress = true;
}
private void sendCustomAccessibilityEvent(int type, String text) {
@@ -537,7 +655,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
}
}
- protected boolean createAndAddShortcut(ShortcutInfo item) {
+ protected View createAndAddShortcut(ShortcutInfo item) {
final BubbleTextView textView =
(BubbleTextView) mInflater.inflate(R.layout.application, this, false);
textView.setCompoundDrawables(null,
@@ -546,7 +664,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
textView.setTag(item);
textView.setTextColor(getResources().getColor(R.color.folder_items_text_color));
textView.setShadowsEnabled(false);
- Utilities.applyTypeface(textView);
+ textView.setGlowColor(getResources().getColor(R.color.folder_items_glow_color));
textView.setOnClickListener(this);
textView.setOnLongClickListener(this);
@@ -558,7 +676,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
// This shouldn't happen, log it.
Log.e(TAG, "Folder order not properly persisted during bind");
if (!findAndSetEmptyCells(item)) {
- return false;
+ return null;
}
}
@@ -567,7 +685,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
boolean insert = false;
textView.setOnKeyListener(new FolderKeyEventListener());
mContent.addViewToCellLayout(textView, insert ? 0 : -1, (int)item.id, lp, true);
- return true;
+ return textView;
}
public void onDragEnter(DragObject d) {
@@ -716,6 +834,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
mCurrentDragView = null;
mSuppressOnAdd = false;
mRearrangeOnClose = true;
+ mIsExternalDrag = false;
}
public void onDragExit(DragObject d) {
@@ -749,7 +868,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
success && (!beingCalledAfterUninstall || mUninstallSuccessful);
if (successfulDrop) {
- if (mDeleteFolderOnDropCompleted && !mItemAddedBackToSelfViaIcon) {
+ if (mDeleteFolderOnDropCompleted && !mItemAddedBackToSelfViaIcon && target != this) {
replaceFolderWithFinalItem();
}
} else {
@@ -768,6 +887,12 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
}
}
+ // This is kind of hacky, but in general, dropping on the workspace handles removing
+ // the extra screen, but dropping elsewhere (back to self, or onto delete) doesn't.
+ if (target != mLauncher.getWorkspace()) {
+ mLauncher.getWorkspace().removeExtraEmptyScreen(true, null);
+ }
+
mDeleteFolderOnDropCompleted = false;
mDragInProgress = false;
mItemAddedBackToSelfViaIcon = false;
@@ -793,10 +918,25 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
}
@Override
+ public float getIntrinsicIconScaleFactor() {
+ return 1f;
+ }
+
+ @Override
public boolean supportsFlingToDelete() {
return true;
}
+ @Override
+ public boolean supportsAppInfoDropTarget() {
+ return false;
+ }
+
+ @Override
+ public boolean supportsDeleteDropTarget() {
+ return true;
+ }
+
public void onFlingToDelete(DragObject d, int x, int y, PointF vec) {
// Do nothing
}
@@ -812,7 +952,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
View v = list.get(i);
ItemInfo info = (ItemInfo) v.getTag();
LauncherModel.moveItemInDatabase(mLauncher, info, mInfo.id, 0,
- info.cellX, info.cellY);
+ info.cellX, info.cellY);
}
}
@@ -965,31 +1105,48 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
Rect workspacePadding = grid.getWorkspacePadding(grid.isLandscape ?
CellLayout.LANDSCAPE : CellLayout.PORTRAIT);
int maxContentAreaHeight = grid.availableHeightPx -
- 4 * grid.edgeMarginPx -
workspacePadding.top - workspacePadding.bottom -
- getPaddingTop() - getPaddingBottom() -
mFolderNameHeight;
- return Math.min(maxContentAreaHeight,
+ int height = Math.min(maxContentAreaHeight,
mContent.getDesiredHeight());
+ return Math.max(height, MIN_CONTENT_DIMEN);
+ }
+
+ private int getContentAreaWidth() {
+ return Math.max(mContent.getDesiredWidth(), MIN_CONTENT_DIMEN);
}
private int getFolderHeight() {
- int height = getPaddingTop() + getPaddingBottom()
- + getContentAreaHeight() + mFolderNameHeight;
+ int height = getPaddingTop() + getPaddingBottom() + mFolderNameHeight
+ + getContentAreaHeight();
return height;
}
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- int width = getPaddingLeft() + getPaddingRight() + mContent.getDesiredWidth();
+ int width = getPaddingLeft()
+ + getPaddingRight()
+ + Math.max(mContent.getDesiredWidth(),
+ mFolderTitleSection.getMeasuredWidth());
int height = getFolderHeight();
- int contentAreaWidthSpec = MeasureSpec.makeMeasureSpec(mContent.getDesiredWidth(),
+ int contentAreaWidthSpec = MeasureSpec.makeMeasureSpec(getContentAreaWidth(),
MeasureSpec.EXACTLY);
int contentAreaHeightSpec = MeasureSpec.makeMeasureSpec(getContentAreaHeight(),
MeasureSpec.EXACTLY);
- mContent.setFixedSize(mContent.getDesiredWidth(), mContent.getDesiredHeight());
+
+ if (LauncherAppState.isDisableAllApps()) {
+ // Don't cap the height of the content to allow scrolling.
+ mContent.setFixedSize(getContentAreaWidth(), mContent.getDesiredHeight());
+ } else {
+ mContent.setFixedSize(getContentAreaWidth(), getContentAreaHeight());
+ }
+
mScrollView.measure(contentAreaWidthSpec, contentAreaHeightSpec);
- mFolderName.measure(contentAreaWidthSpec,
- MeasureSpec.makeMeasureSpec(mFolderNameHeight, MeasureSpec.EXACTLY));
+ mFolderName.measure(contentAreaWidthSpec, MeasureSpec.makeMeasureSpec(
+ mFolderNameHeight, MeasureSpec.EXACTLY));
+ mFolderLock.measure(contentAreaWidthSpec, MeasureSpec.makeMeasureSpec(
+ mFolderNameHeight, MeasureSpec.EXACTLY));
+ mFolderTitleSection.measure(contentAreaWidthSpec, MeasureSpec
+ .makeMeasureSpec(mFolderNameHeight, MeasureSpec.EXACTLY));
setMeasuredDimension(width, height);
}
@@ -1051,13 +1208,16 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
}
private void replaceFolderWithFinalItem() {
+ if (mInfo.hidden) {
+ return;
+ }
// Add the last remaining child to the workspace in place of the folder
Runnable onCompleteRunnable = new Runnable() {
@Override
public void run() {
CellLayout cellLayout = mLauncher.getCellLayout(mInfo.container, mInfo.screenId);
- View child = null;
+ View child = null;
// Move the item from the folder to the workspace, in the position of the folder
if (getItemCount() == 1) {
ShortcutInfo finalItem = mInfo.contents.get(0);
@@ -1069,7 +1229,10 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
if (getItemCount() <= 1) {
// Remove the folder
LauncherModel.deleteItemFromDatabase(mLauncher, mInfo);
- cellLayout.removeView(mFolderIcon);
+ if (cellLayout != null) {
+ // b/12446428 -- sometimes the cell layout has already gone away?
+ cellLayout.removeView(mFolderIcon);
+ }
if (mFolderIcon instanceof DropTarget) {
mDragController.removeDropTarget((DropTarget) mFolderIcon);
}
@@ -1087,6 +1250,8 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
View finalChild = getItemAt(0);
if (finalChild != null) {
mFolderIcon.performDestroyAnimation(finalChild, onCompleteRunnable);
+ } else {
+ onCompleteRunnable.run();
}
mDestroyed = true;
}
@@ -1109,34 +1274,75 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
}
public void onDrop(DragObject d) {
- ShortcutInfo item;
- if (d.dragInfo instanceof AppInfo) {
- // Came from all apps -- make a copy
- item = ((AppInfo) d.dragInfo).makeShortcut();
- item.spanX = 1;
- item.spanY = 1;
- } else {
- item = (ShortcutInfo) d.dragInfo;
+ Runnable cleanUpRunnable = null;
+
+ // If we are coming from All Apps space, we need to remove the extra empty screen (which is
+ // normally done in Workspace#onDropExternal, as well zoom back in and close the folder.
+ if (d.dragSource != mLauncher.getWorkspace() && !(d.dragSource instanceof Folder)) {
+ cleanUpRunnable = new Runnable() {
+ @Override
+ public void run() {
+ mLauncher.getWorkspace().removeExtraEmptyScreen(false, new Runnable() {
+ @Override
+ public void run() {
+ mLauncher.closeFolder();
+ mLauncher.exitSpringLoadedDragModeDelayed(true,
+ Launcher.EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT_FOLDER_CLOSE,
+ null);
+ }
+ }, CLOSE_FOLDER_DELAY_MS, false);
+ }
+ };
}
- // Dragged from self onto self, currently this is the only path possible, however
- // we keep this as a distinct code path.
- if (item == mCurrentDragInfo) {
- ShortcutInfo si = (ShortcutInfo) mCurrentDragView.getTag();
- CellLayout.LayoutParams lp = (CellLayout.LayoutParams) mCurrentDragView.getLayoutParams();
+
+ View currentDragView;
+ ShortcutInfo si = mCurrentDragInfo;
+ if (mIsExternalDrag) {
+ si.cellX = mEmptyCell[0];
+ si.cellY = mEmptyCell[1];
+ currentDragView = createAndAddShortcut(si);
+ } else {
+ currentDragView = mCurrentDragView;
+ CellLayout.LayoutParams lp = (CellLayout.LayoutParams) currentDragView.getLayoutParams();
si.cellX = lp.cellX = mEmptyCell[0];
si.cellX = lp.cellY = mEmptyCell[1];
- mContent.addViewToCellLayout(mCurrentDragView, -1, (int)item.id, lp, true);
- if (d.dragView.hasDrawn()) {
- mLauncher.getDragLayer().animateViewIntoPosition(d.dragView, mCurrentDragView);
- } else {
- d.deferDragViewCleanupPostAnimation = false;
- mCurrentDragView.setVisibility(VISIBLE);
+ mContent.addViewToCellLayout(currentDragView, -1, (int) si.id, lp, true);
+ }
+
+ if (d.dragView.hasDrawn()) {
+
+ // Temporarily reset the scale such that the animation target gets calculated correctly.
+ float scaleX = getScaleX();
+ float scaleY = getScaleY();
+ setScaleX(1.0f);
+ setScaleY(1.0f);
+ mLauncher.getDragLayer().animateViewIntoPosition(d.dragView, currentDragView,
+ cleanUpRunnable, null);
+ setScaleX(scaleX);
+ setScaleY(scaleY);
+ } else {
+ d.deferDragViewCleanupPostAnimation = false;
+ currentDragView.setVisibility(VISIBLE);
+ }
+ mItemsInvalidated = true;
+ setupContentDimensions(getItemCount());
+
+ // Actually move the item in the database if it was an external drag.
+ if (mIsExternalDrag) {
+ LauncherModel.addOrMoveItemInDatabase(
+ mLauncher, si, mInfo.id, 0, si.cellX, si.cellY);
+
+ // We only need to update the locations if it doesn't get handled in #onDropCompleted.
+ if (d.dragSource != this) {
+ updateItemLocationsInDatabaseBatch();
}
- mItemsInvalidated = true;
- setupContentDimensions(getItemCount());
- mSuppressOnAdd = true;
+ mIsExternalDrag = false;
}
- mInfo.add(item);
+
+ // Temporarily suppress the listener, as we did all the work already here.
+ mSuppressOnAdd = true;
+ mInfo.add(si);
+ mSuppressOnAdd = false;
}
// This is used so the item doesn't immediately appear in the folder when added. In one case
@@ -1218,6 +1424,20 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
return mItemsInReadingOrder;
}
+ public ShortcutInfo getShortcutForComponent(ComponentName componentName) {
+ for (View v : mItemsInReadingOrder) {
+ Object tag = v.getTag();
+ if (tag instanceof ShortcutInfo) {
+ ComponentName cName = ((ShortcutInfo) tag).getIntent().getComponent();
+ if (cName.equals(componentName)) {
+ return (ShortcutInfo) tag;
+ }
+ }
+ }
+
+ return null;
+ }
+
public void getLocationInDragLayer(int[] loc) {
mLauncher.getDragLayer().getLocationInDragLayer(this, loc);
}
@@ -1232,4 +1452,8 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
public void getHitRectRelativeToDragLayer(Rect outRect) {
getHitRect(outRect);
}
+
+ public View getViewFromPosition(int position) {
+ return mItemsInReadingOrder.get(position);
+ }
}
diff --git a/src/com/android/launcher3/FolderIcon.java b/src/com/android/launcher3/FolderIcon.java
index 9b7919b42..464b35da9 100644
--- a/src/com/android/launcher3/FolderIcon.java
+++ b/src/com/android/launcher3/FolderIcon.java
@@ -36,11 +36,10 @@ import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
+import android.widget.FrameLayout;
import android.widget.ImageView;
-import android.widget.LinearLayout;
import android.widget.TextView;
-import com.android.launcher3.R;
import com.android.launcher3.DropTarget.DragObject;
import com.android.launcher3.FolderInfo.FolderListener;
@@ -49,7 +48,7 @@ import java.util.ArrayList;
/**
* An icon that can appear on in the workspace representing an {@link UserFolder}.
*/
-public class FolderIcon extends LinearLayout implements FolderListener {
+public class FolderIcon extends FrameLayout implements FolderListener {
private Launcher mLauncher;
private Folder mFolder;
private FolderInfo mInfo;
@@ -76,10 +75,16 @@ public class FolderIcon extends LinearLayout implements FolderListener {
// Flag as to whether or not to draw an outer ring. Currently none is designed.
public static final boolean HAS_OUTER_RING = true;
+ // Flag whether the folder should open itself when an item is dragged over is enabled.
+ public static final boolean SPRING_LOADING_ENABLED = true;
+
// The degree to which the item in the back of the stack is scaled [0...1]
// (0 means it's not scaled at all, 1 means it's scaled to nothing)
private static final float PERSPECTIVE_SCALE_FACTOR = 0.35f;
+ // Delay when drag enters until the folder opens, in miliseconds.
+ private static final int ON_OPEN_DELAY = 800;
+
public static Drawable sSharedFolderLeaveBehind = null;
private ImageView mPreviewBackground;
@@ -104,6 +109,9 @@ public class FolderIcon extends LinearLayout implements FolderListener {
private PreviewItemDrawingParams mAnimParams = new PreviewItemDrawingParams(0, 0, 0, 0);
private ArrayList<ShortcutInfo> mHiddenItems = new ArrayList<ShortcutInfo>();
+ private Alarm mOpenAlarm = new Alarm();
+ private ItemInfo mDragInfo;
+
public FolderIcon(Context context, AttributeSet attrs) {
super(context, attrs);
init();
@@ -134,18 +142,20 @@ public class FolderIcon extends LinearLayout implements FolderListener {
"INITIAL_ITEM_ANIMATION_DURATION, as sequencing of adding first two items " +
"is dependent on this");
}
+ LauncherAppState app = LauncherAppState.getInstance();
+ DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
FolderIcon icon = (FolderIcon) LayoutInflater.from(launcher).inflate(resId, group, false);
icon.setClipToPadding(false);
icon.mFolderName = (BubbleTextView) icon.findViewById(R.id.folder_icon_name);
icon.mFolderName.setText(folderInfo.title);
- Utilities.applyTypeface(icon.mFolderName);
- icon.mPreviewBackground = (ImageView) icon.findViewById(R.id.preview_background);
- LauncherAppState app = LauncherAppState.getInstance();
- DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
+ icon.mFolderName.setCompoundDrawablePadding(0);
+ FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) icon.mFolderName.getLayoutParams();
+ lp.topMargin = grid.iconSizePx + grid.iconDrawablePaddingPx;
+
// Offset the preview background to center this view accordingly
- LinearLayout.LayoutParams lp =
- (LinearLayout.LayoutParams) icon.mPreviewBackground.getLayoutParams();
+ icon.mPreviewBackground = (ImageView) icon.findViewById(R.id.preview_background);
+ lp = (FrameLayout.LayoutParams) icon.mPreviewBackground.getLayoutParams();
lp.topMargin = grid.folderBackgroundOffset;
lp.width = grid.folderIconSizePx;
lp.height = grid.folderIconSizePx;
@@ -308,14 +318,23 @@ public class FolderIcon extends LinearLayout implements FolderListener {
private boolean willAcceptItem(ItemInfo item) {
final int itemType = item.itemType;
+
+ boolean hidden = false;
+ if (item instanceof FolderInfo){
+ hidden = ((FolderInfo) item).hidden;
+ }
return ((itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION ||
itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT ||
itemType == LauncherSettings.Favorites.ITEM_TYPE_FOLDER) &&
- !mFolder.isFull() && item != mInfo && !mInfo.opened);
+ !mFolder.isFull() && item != mInfo && !mInfo.opened &&
+ !hidden);
}
public boolean acceptDrop(Object dragInfo) {
final ItemInfo item = (ItemInfo) dragInfo;
+ if (mInfo.hidden) {
+ return false;
+ }
return !mFolder.isDestroyed() && willAcceptItem(item);
}
@@ -331,11 +350,32 @@ public class FolderIcon extends LinearLayout implements FolderListener {
mFolderRingAnimator.setCellLayout(layout);
mFolderRingAnimator.animateToAcceptState();
layout.showFolderAccept(mFolderRingAnimator);
+ mOpenAlarm.setOnAlarmListener(mOnOpenListener);
+ if (SPRING_LOADING_ENABLED) {
+ mOpenAlarm.setAlarm(ON_OPEN_DELAY);
+ }
+ mDragInfo = (ItemInfo) dragInfo;
}
public void onDragOver(Object dragInfo) {
}
+ OnAlarmListener mOnOpenListener = new OnAlarmListener() {
+ public void onAlarm(Alarm alarm) {
+ ShortcutInfo item;
+ if (mDragInfo instanceof AppInfo) {
+ // Came from all apps -- make a copy.
+ item = ((AppInfo) mDragInfo).makeShortcut();
+ item.spanX = 1;
+ item.spanY = 1;
+ } else {
+ item = (ShortcutInfo) mDragInfo;
+ }
+ mFolder.beginExternalDrag(item);
+ mLauncher.openFolder(FolderIcon.this);
+ }
+ };
+
public void performCreateAnimation(final ShortcutInfo destInfo, final View destView,
final ShortcutInfo srcInfo, final DragView srcView, Rect dstRect,
float scaleRelativeToDragLayer, Runnable postAnimationRunnable) {
@@ -371,6 +411,7 @@ public class FolderIcon extends LinearLayout implements FolderListener {
public void onDragExit() {
mFolderRingAnimator.animateToNaturalState();
+ mOpenAlarm.cancelAlarm();
}
private void onDrop(final ShortcutInfo item, DragView animateView, Rect finalRect,
@@ -548,12 +589,10 @@ public class FolderIcon extends LinearLayout implements FolderListener {
if (d != null) {
mOldBounds.set(d.getBounds());
d.setBounds(0, 0, mIntrinsicIconSize, mIntrinsicIconSize);
- d.setFilterBitmap(true);
d.setColorFilter(Color.argb(params.overlayAlpha, 255, 255, 255),
PorterDuff.Mode.SRC_ATOP);
d.draw(canvas);
d.clearColorFilter();
- d.setFilterBitmap(false);
d.setBounds(mOldBounds);
}
canvas.restore();
@@ -580,6 +619,20 @@ public class FolderIcon extends LinearLayout implements FolderListener {
}
int nItemsInPreview = Math.min(items.size(), NUM_ITEMS_IN_PREVIEW);
+
+ // Hidden folder - don't display Preview
+ if (mInfo.hidden) {
+ mParams = computePreviewItemDrawingParams(NUM_ITEMS_IN_PREVIEW/2, mParams);
+ canvas.save();
+ canvas.translate(mParams.transX + mPreviewOffsetX, mParams.transY + mPreviewOffsetY);
+ canvas.scale(mParams.scale, mParams.scale);
+ Drawable lock = getResources().getDrawable(R.drawable.folder_lock);
+ lock.setBounds(0, 0, mIntrinsicIconSize, mIntrinsicIconSize);
+ lock.draw(canvas);
+ canvas.restore();
+ return;
+ }
+
if (!mAnimating) {
for (int i = nItemsInPreview - 1; i >= 0; i--) {
v = (TextView) items.get(i);
diff --git a/src/com/android/launcher3/FolderInfo.java b/src/com/android/launcher3/FolderInfo.java
index bb5ae8200..133bfd089 100644
--- a/src/com/android/launcher3/FolderInfo.java
+++ b/src/com/android/launcher3/FolderInfo.java
@@ -16,10 +16,10 @@
package com.android.launcher3;
-import java.util.ArrayList;
-
import android.content.ContentValues;
+import java.util.ArrayList;
+
/**
* Represents a folder containing shortcuts or apps.
*/
@@ -31,9 +31,10 @@ class FolderInfo extends ItemInfo {
boolean opened;
/**
- * The apps and shortcuts
+ * The apps and shortcuts and hidden status
*/
ArrayList<ShortcutInfo> contents = new ArrayList<ShortcutInfo>();
+ Boolean hidden = false;
ArrayList<FolderListener> listeners = new ArrayList<FolderListener>();
@@ -78,6 +79,7 @@ class FolderInfo extends ItemInfo {
void onAddToDatabase(ContentValues values) {
super.onAddToDatabase(values);
values.put(LauncherSettings.Favorites.TITLE, title.toString());
+ values.put(LauncherSettings.Favorites.HIDDEN, hidden ? 1 : 0);
}
void addListener(FolderListener listener) {
diff --git a/src/com/android/launcher3/GelIntegrationHelper.java b/src/com/android/launcher3/GelIntegrationHelper.java
new file mode 100644
index 000000000..f43e7e6a0
--- /dev/null
+++ b/src/com/android/launcher3/GelIntegrationHelper.java
@@ -0,0 +1,102 @@
+package com.android.launcher3;
+
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.service.gesture.EdgeGestureManager;
+import com.android.internal.util.gesture.EdgeGesturePosition;
+
+import java.util.List;
+
+/**
+ * A singleton wrapper class for GEL Integration.
+ * Requires EdgeGestureManager functionality that is only available
+ * in CyanogenMod.
+ */
+public class GelIntegrationHelper {
+ // The Intent for the search activity (resolves to Google Now when installed)
+ public final static String INTENT_ACTION_ASSIST = "android.intent.action.ASSIST";
+
+ private static final String GEL_ACTIVITY = "com.google.android.velvet.ui.VelvetActivity";
+ private static final String GEL_PACKAGE_NAME = "com.google.android.googlequicksearchbox";
+
+ private static final int EDGE_GESTURE_SERVICE_RIGHT_EDGE = 4;
+ private static final int EDGE_GESTURE_SERVICE_LEFT_EDGE = 1;
+ private static final int EDGE_GESTURE_SERVICE_NO_EDGE = -1;
+
+ private EdgeGestureManager.EdgeGestureActivationListener mEdgeGestureActivationListener = null;
+ private static GelIntegrationHelper sInstance;
+
+ private GelIntegrationHelper() {}
+
+ public static GelIntegrationHelper getInstance() {
+ if(sInstance == null) {
+ sInstance = new GelIntegrationHelper();
+ }
+ return sInstance;
+ }
+
+ /**
+ * 1. Registers an EdgeGestureActivationListener with the EdgeGestureManager so that
+ * the user can return to Trebuchet when they swipe from the right edge of the device.
+ * 2. Starts the Google Now Activity with an exit_out_right transition animation so that
+ * the new Activity appears to slide in as another screen (similar to GEL).
+ */
+ public void registerSwipeBackGestureListenerAndStartGel(final Activity launcherActivity, boolean isLayoutRtl) {
+ EdgeGestureManager edgeGestureManager = EdgeGestureManager.getInstance();
+ if(mEdgeGestureActivationListener == null) {
+ mEdgeGestureActivationListener = new EdgeGestureManager.EdgeGestureActivationListener() {
+ ActivityManager mAm = (ActivityManager)
+ launcherActivity.getSystemService(Activity.ACTIVITY_SERVICE);
+
+ @Override
+ public void onEdgeGestureActivation(int touchX, int touchY,
+ EdgeGesturePosition position, int flags) {
+ // Retrieve the top level activity information
+ List< ActivityManager.RunningTaskInfo > taskInfo = mAm.getRunningTasks(1);
+ ComponentName topActivityComponentInfo = taskInfo.get(0).topActivity;
+ String topActivityClassName = topActivityComponentInfo.getClassName();
+ String topActivityPackageName = topActivityComponentInfo.getPackageName();
+
+ // If the top level activity is Google Now, return to home.
+ // Otherwise, do nothing.
+ if(GEL_ACTIVITY.equals(topActivityClassName)
+ && GEL_PACKAGE_NAME.equals(topActivityPackageName)) {
+ Intent homeIntent = new Intent(Intent.ACTION_MAIN);
+ homeIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NO_ANIMATION);
+ homeIntent.addCategory(Intent.CATEGORY_HOME);
+ launcherActivity.startActivity(homeIntent);
+ launcherActivity.overridePendingTransition(0, 0);
+ dropEventsUntilLift();
+ }
+ }
+ };
+ edgeGestureManager.setEdgeGestureActivationListener(mEdgeGestureActivationListener);
+ }
+ mEdgeGestureActivationListener.restoreListenerState();
+ int edge = isLayoutRtl ? EDGE_GESTURE_SERVICE_LEFT_EDGE : EDGE_GESTURE_SERVICE_RIGHT_EDGE;
+ edgeGestureManager.updateEdgeGestureActivationListener(mEdgeGestureActivationListener,
+ edge);
+
+ // Start the Google Now Activity
+ Intent i = new Intent(INTENT_ACTION_ASSIST);
+ launcherActivity.startActivity(i);
+ launcherActivity.overridePendingTransition(0, R.anim.exit_out_right);
+ }
+
+ /**
+ * Handle necessary cleanup and reset tasks for GEL integration, to be called from onResume.
+ */
+ public void handleGelResume() {
+ // If there is an active EdgeGestureActivationListener for GEL integration,
+ // it should stop listening when we have resumed the launcher.
+ if(mEdgeGestureActivationListener != null) {
+ EdgeGestureManager edgeGestureManager = EdgeGestureManager.getInstance();
+ // Update the listener so it is not listening to any postions (-1)
+ edgeGestureManager.updateEdgeGestureActivationListener(mEdgeGestureActivationListener,
+ EDGE_GESTURE_SERVICE_NO_EDGE);
+ }
+ }
+
+}
diff --git a/src/com/android/launcher3/HiddenFolderFragment.java b/src/com/android/launcher3/HiddenFolderFragment.java
new file mode 100644
index 000000000..07b0e4a8a
--- /dev/null
+++ b/src/com/android/launcher3/HiddenFolderFragment.java
@@ -0,0 +1,343 @@
+package com.android.launcher3;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+
+import android.app.Fragment;
+import android.app.FragmentTransaction;
+import android.media.Image;
+import android.text.InputType;
+import android.view.KeyEvent;
+import android.view.MenuItem;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.*;
+import com.android.launcher3.settings.SettingsProvider;
+
+import android.app.Activity;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.graphics.drawable.Drawable;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+
+public class HiddenFolderFragment extends Fragment {
+ public static final String HIDDEN_FOLDER_FRAGMENT = "hiddenFolderFragment";
+ public static final String HIDDEN_FOLDER_NAME = "hiddenFolderName";
+ public static final String HIDDEN_FOLDER_STATUS = "hiddenFolderStatus";
+ public static final String HIDDEN_FOLDER_INFO = "hiddenFolderInfo";
+ public static final String HIDDEN_FOLDER_INFO_TITLES = "hiddenFolderInfoTitles";
+ public static final String HIDDEN_FOLDER_LAUNCH = "hiddenFolderLaunchPosition";
+
+ private static final int REQ_LOCK_PATTERN = 1;
+
+ private String[] mComponentInfo;
+ private String[] mComponentTitles;
+ private boolean mHidden;
+ private PackageManager mPackageManager;
+ private AppsAdapter mAppsAdapter;
+ private ArrayList<AppEntry> mAppEntries;
+
+ private EditText mFolderName;
+ private ListView mListView;
+
+ private Launcher mLauncher;
+
+ private boolean mAuth = false;
+ private boolean mSent = false;
+
+ private OnClickListener mClicklistener = new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mHidden = !mHidden;
+
+ ImageView mLock = (ImageView) v;
+ Drawable mLockIcon = mHidden ? getResources().getDrawable(R.drawable.folder_lock_light)
+ : getResources().getDrawable(R.drawable.folder_unlock);
+ mLock.setImageDrawable(mLockIcon);
+ }
+ };
+
+ @Override
+ public View onCreateView (LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ View v = inflater.inflate(R.layout.hidden_folder, container, false);
+
+ mLauncher = (Launcher) getActivity();
+ mPackageManager = mLauncher.getPackageManager();
+
+ mHidden = getArguments().getBoolean(HIDDEN_FOLDER_STATUS);
+ Folder folder = mLauncher.mHiddenFolderIcon.getFolder();
+ mComponentInfo = folder.getComponents();
+ mComponentTitles = folder.getComponentTitles();
+ String title = mLauncher.mHiddenFolderIcon.getFolderInfo().title.toString();
+
+ mFolderName = (EditText) v.findViewById(R.id.folder_name);
+ mFolderName.setText(title);
+ mFolderName.setSelectAllOnFocus(true);
+ mFolderName.setInputType(mFolderName.getInputType() |
+ InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS | InputType.TYPE_TEXT_FLAG_CAP_WORDS);
+ mFolderName.setImeOptions(EditorInfo.IME_ACTION_DONE);
+ mFolderName.setOnEditorActionListener(new TextView.OnEditorActionListener() {
+ @Override
+ public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
+ if (actionId == EditorInfo.IME_ACTION_DONE) {
+ doneEditingText(v);
+ return true;
+ }
+ return false;
+ }
+ });
+ mFolderName.setOnFocusChangeListener(new View.OnFocusChangeListener() {
+ @Override
+ public void onFocusChange(View v, boolean hasFocus) {
+ if (!hasFocus) {
+ doneEditingText(v);
+ }
+ }
+ });
+
+ ImageView mLock = (ImageView) v.findViewById(R.id.folder_lock_icon);
+ Drawable mLockIcon = mHidden ? getResources().getDrawable(R.drawable.folder_lock_light)
+ : getResources().getDrawable(R.drawable.folder_unlock);
+ mLock.setImageDrawable(mLockIcon);
+ mLock.setOnClickListener(mClicklistener);
+
+ mAppsAdapter = new AppsAdapter(mLauncher, R.layout.hidden_apps_list_item);
+ mAppsAdapter.setNotifyOnChange(true);
+ mAppEntries = loadApps();
+ mAppsAdapter.clear();
+ mAppsAdapter.addAll(mAppEntries);
+
+ mListView = (ListView) v.findViewById(R.id.hidden_apps_list);
+ mListView.setAdapter(mAppsAdapter);
+
+ return v;
+ }
+
+ private void doneEditingText(View v) {
+ InputMethodManager mInputMethodManager = (InputMethodManager)
+ mLauncher.getSystemService(Context.INPUT_METHOD_SERVICE);
+ mInputMethodManager.hideSoftInputFromWindow(v.getWindowToken(), 0);
+
+ mListView.requestFocus();
+ }
+
+ private ArrayList<AppEntry> loadApps() {
+ ArrayList<AppEntry> apps = new ArrayList<AppEntry>();
+ int size = mComponentInfo.length;
+ for (int i = 0; i < size; i++) {
+ apps.add(new AppEntry(mComponentInfo[i], mComponentTitles[i]));
+ }
+ return apps;
+ }
+
+ private void removeComponentFromFolder(AppEntry app) {
+ mLauncher.mHiddenFolderIcon.getFolderInfo().remove(
+ mLauncher.mHiddenFolderIcon.getFolder()
+ .getShortcutForComponent(app.componentName));
+
+ mAppEntries.remove(app);
+ mAppsAdapter.remove(app);
+ mAppsAdapter.notifyDataSetInvalidated();
+ }
+
+ public void saveHiddenFolderStatus(int position) {
+ String newTitle = mFolderName.getText().toString();
+ if (mLauncher.mHiddenFolderIcon != null) {
+ if (position != -1) {
+ Folder folder = mLauncher.mHiddenFolderIcon.getFolder();
+ View v = folder.getViewFromPosition(position);
+ Object tag = v.getTag();
+ if (tag instanceof ShortcutInfo) {
+ mLauncher.startActivitySafely(v,
+ ((ShortcutInfo) tag).getIntent(),
+ v.getTag());
+
+ return;
+ }
+ }
+
+ // Folder name
+ FolderInfo info = mLauncher.mHiddenFolderIcon.getFolderInfo();
+ if (!info.title.equals(newTitle)) {
+ info.setTitle(newTitle);
+ mLauncher.mHiddenFolderIcon.getFolder().setFolderName();
+ LauncherModel.updateItemInDatabase(mLauncher, info);
+ }
+
+ // Folder hidden status
+ if (info.hidden == mHidden) {
+ return;
+ } else {
+ info.hidden = mHidden;
+ // flip the boolean value to accomodate framework
+ // in framework "false" is "protected" and "true" is "visible"
+ mLauncher.mHiddenFolderIcon.getFolder().modifyProtectedApps(!info.hidden);
+
+ LauncherModel.updateItemInDatabase(mLauncher, info);
+ // We need to make sure this change gets written to the DB before
+ // OnResume restarts the process
+ mLauncher.mModel.flushWorkerThread();
+ }
+ }
+
+ FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
+ fragmentTransaction
+ .remove(mLauncher.mHiddenFolderFragment).commit();
+ }
+
+ public class AppsAdapter extends ArrayAdapter<AppEntry> {
+
+ private final LayoutInflater mInflator;
+
+ private ConcurrentHashMap<String, Drawable> mIcons;
+ private Drawable mDefaultImg;
+ private List<AppEntry> mApps;
+
+ public AppsAdapter(Context context, int textViewResourceId) {
+ super(context, textViewResourceId);
+
+ mApps = new ArrayList<AppEntry>();
+
+ mInflator = LayoutInflater.from(context);
+
+ // set the default icon till the actual app icon is loaded in async
+ // task
+ mDefaultImg = context.getResources().getDrawable(
+ android.R.mipmap.sym_def_app_icon);
+ mIcons = new ConcurrentHashMap<String, Drawable>();
+ }
+
+ @Override
+ public View getView(final int position, View convertView,
+ ViewGroup parent) {
+ final AppViewHolder viewHolder;
+
+ if (convertView == null) {
+ convertView = mInflator.inflate(
+ R.layout.hidden_folder_apps_list_item, parent, false);
+ viewHolder = new AppViewHolder(convertView, position);
+ convertView.setTag(viewHolder);
+ } else {
+ viewHolder = (AppViewHolder) convertView.getTag();
+ }
+
+ final AppEntry app = getItem(position);
+
+ viewHolder.title.setText(app.title);
+
+ Drawable icon = mIcons.get(app.componentName.getPackageName());
+ viewHolder.icon.setImageDrawable(icon != null ? icon : mDefaultImg);
+ viewHolder.remove.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ removeComponentFromFolder(app);
+ }
+ });
+
+ convertView.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ saveHiddenFolderStatus(viewHolder.position);
+ }
+ });
+
+ return convertView;
+ }
+
+ @Override
+ public boolean hasStableIds() {
+ return true;
+ }
+
+ @Override
+ public void notifyDataSetChanged() {
+ super.notifyDataSetChanged();
+ // If we have new items, we have to load their icons
+ // If items were deleted, remove them from our mApps
+ List<AppEntry> newApps = new ArrayList<AppEntry>(getCount());
+ List<AppEntry> oldApps = new ArrayList<AppEntry>(getCount());
+ for (int i = 0; i < getCount(); i++) {
+ AppEntry app = getItem(i);
+ if (mApps.contains(app)) {
+ oldApps.add(app);
+ } else {
+ newApps.add(app);
+ }
+ }
+
+ if (newApps.size() > 0) {
+ new LoadIconsTask().execute(newApps.toArray(new AppEntry[] {}));
+ newApps.addAll(oldApps);
+ mApps = newApps;
+ } else {
+ mApps = oldApps;
+ }
+ }
+
+ /**
+ * An asynchronous task to load the icons of the installed applications.
+ */
+ private class LoadIconsTask extends AsyncTask<AppEntry, Void, Void> {
+ @Override
+ protected Void doInBackground(AppEntry... apps) {
+ for (AppEntry app : apps) {
+ try {
+ if (mIcons.containsKey(app.componentName
+ .getPackageName())) {
+ continue;
+ }
+ Drawable icon = mPackageManager
+ .getApplicationIcon(app.componentName
+ .getPackageName());
+ mIcons.put(app.componentName.getPackageName(), icon);
+ publishProgress();
+ } catch (PackageManager.NameNotFoundException e) {
+ // ignored; app will show up with default image
+ }
+ }
+
+ return null;
+ }
+
+ @Override
+ protected void onProgressUpdate(Void... progress) {
+ notifyDataSetChanged();
+ }
+ }
+ }
+
+ private final class AppEntry {
+
+ public final ComponentName componentName;
+ public final String title;
+
+ public AppEntry(String component, String title) {
+ componentName = ComponentName.unflattenFromString(component);
+ this.title = title;
+ }
+ }
+
+ private static class AppViewHolder {
+ public final TextView title;
+ public final ImageView icon;
+ public final ImageView remove;
+ public final int position;
+
+ public AppViewHolder(View parentView, int position) {
+ icon = (ImageView) parentView.findViewById(R.id.icon);
+ remove = (ImageView) parentView.findViewById(R.id.remove);
+ title = (TextView) parentView.findViewById(R.id.title);
+ this.position = position;
+ }
+ }
+}
diff --git a/src/com/android/launcher3/Hotseat.java b/src/com/android/launcher3/Hotseat.java
index 2812b4129..0cca03b8c 100644
--- a/src/com/android/launcher3/Hotseat.java
+++ b/src/com/android/launcher3/Hotseat.java
@@ -149,7 +149,7 @@ public class Hotseat extends FrameLayout {
void addAllAppsFolder(IconCache iconCache,
ArrayList<AppInfo> allApps, ArrayList<ComponentName> onWorkspace,
Launcher launcher, Workspace workspace) {
- if (AppsCustomizePagedView.DISABLE_ALL_APPS) {
+ if (LauncherAppState.isDisableAllApps()) {
FolderInfo fi = new FolderInfo();
fi.cellX = getCellXFromOrder(mAllAppsButtonRank);
@@ -179,7 +179,7 @@ public class Hotseat extends FrameLayout {
}
void addAppsToAllAppsFolder(ArrayList<AppInfo> apps) {
- if (AppsCustomizePagedView.DISABLE_ALL_APPS) {
+ if (LauncherAppState.isDisableAllApps()) {
View v = mContent.getChildAt(getCellXFromOrder(mAllAppsButtonRank), getCellYFromOrder(mAllAppsButtonRank));
FolderIcon fi = null;
diff --git a/src/com/android/launcher3/IconCache.java b/src/com/android/launcher3/IconCache.java
index e1659e795..1dade8027 100644
--- a/src/com/android/launcher3/IconCache.java
+++ b/src/com/android/launcher3/IconCache.java
@@ -16,6 +16,8 @@
package com.android.launcher3;
+import com.android.launcher3.backup.BackupProtos;
+
import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.Context;
@@ -25,16 +27,24 @@ import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
import android.graphics.Canvas;
+import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.text.TextUtils;
-
+import android.util.Log;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.Map.Entry;
-import com.android.launcher3.settings.SettingsProvider;
-
/**
* Cache of application icons. Icons can be made from any thread.
*/
@@ -43,7 +53,9 @@ public class IconCache {
private static final String TAG = "Launcher.IconCache";
private static final int INITIAL_ICON_CACHE_CAPACITY = 50;
- private IconPackHelper mIconPackHelper;
+ private static final String RESOURCE_FILE_PREFIX = "icon_";
+
+ private static final boolean DEBUG = true;
private static class CacheEntry {
public Bitmap icon;
@@ -67,9 +79,6 @@ public class IconCache {
// need to set mIconDpi before getting default icon
mDefaultIcon = makeDefaultIcon();
-
- mIconPackHelper = new IconPackHelper(context);
- loadIconPack();
}
public Drawable getFullResDefaultActivityIcon() {
@@ -117,18 +126,12 @@ public class IconCache {
resources = null;
}
if (resources != null) {
- int iconId = 0;
- if (mIconPackHelper != null && mIconPackHelper.isIconPackLoaded()) {
- iconId = mIconPackHelper.getResourceIdForActivityIcon(info);
- if (iconId != 0) {
- return getFullResIcon(mIconPackHelper.getIconPackResources(), iconId);
- }
- }
- iconId = info.getIconResource();
+ int iconId = info.getIconResource();
if (iconId != 0) {
return getFullResIcon(resources, iconId);
}
}
+
return getFullResDefaultActivityIcon();
}
@@ -144,16 +147,6 @@ public class IconCache {
return b;
}
- private void loadIconPack() {
- mIconPackHelper.unloadIconPack();
- String iconPack = SettingsProvider.getStringCustomDefault(mContext,
- SettingsProvider.SETTINGS_UI_GENERAL_ICONS_ICON_PACK, "");
- if (!TextUtils.isEmpty(iconPack) && !mIconPackHelper.loadIconPack(iconPack)) {
- SettingsProvider.putString(mContext,
- SettingsProvider.SETTINGS_UI_GENERAL_ICONS_ICON_PACK, "");
- }
- }
-
/**
* Remove any records for the supplied ComponentName.
*/
@@ -164,13 +157,27 @@ public class IconCache {
}
/**
+ * Remove any records for the supplied package name.
+ */
+ public void remove(String packageName) {
+ HashSet<ComponentName> forDeletion = new HashSet<ComponentName>();
+ for (ComponentName componentName: mCache.keySet()) {
+ if (componentName.getPackageName().equals(packageName)) {
+ forDeletion.add(componentName);
+ }
+ }
+ for (ComponentName condemned: forDeletion) {
+ remove(condemned);
+ }
+ }
+
+ /**
* Empty out the cache.
*/
public void flush() {
synchronized (mCache) {
mCache.clear();
}
- loadIconPack();
}
/**
@@ -181,7 +188,7 @@ public class IconCache {
Iterator<Entry<ComponentName, CacheEntry>> it = mCache.entrySet().iterator();
while (it.hasNext()) {
final CacheEntry e = it.next().getValue();
- if (e.icon.getWidth() != grid.iconSizePx || e.icon.getHeight() != grid.iconSizePx) {
+ if (e.icon.getWidth() < grid.iconSizePx || e.icon.getHeight() < grid.iconSizePx) {
it.remove();
}
}
@@ -202,15 +209,22 @@ public class IconCache {
}
public Bitmap getIcon(Intent intent) {
+ return getIcon(intent, null);
+ }
+
+ public Bitmap getIcon(Intent intent, String title) {
synchronized (mCache) {
final ResolveInfo resolveInfo = mPackageManager.resolveActivity(intent, 0);
ComponentName component = intent.getComponent();
- if (resolveInfo == null || component == null) {
+ if (component == null) {
return mDefaultIcon;
}
CacheEntry entry = cacheLocked(component, resolveInfo, null);
+ if (title != null) {
+ entry.title = title;
+ }
return entry.icon;
}
}
@@ -239,28 +253,34 @@ public class IconCache {
mCache.put(componentName, entry);
- ComponentName key = LauncherModel.getComponentNameFromResolveInfo(info);
- if (labelCache != null && labelCache.containsKey(key)) {
- entry.title = labelCache.get(key).toString();
- } else {
- entry.title = info.loadLabel(mPackageManager).toString();
- if (labelCache != null) {
- labelCache.put(key, entry.title);
+ if (info != null) {
+ ComponentName key = LauncherModel.getComponentNameFromResolveInfo(info);
+ if (labelCache != null && labelCache.containsKey(key)) {
+ entry.title = labelCache.get(key).toString();
+ } else {
+ entry.title = info.loadLabel(mPackageManager).toString();
+ if (labelCache != null) {
+ labelCache.put(key, entry.title);
+ }
+ }
+ if (entry.title == null) {
+ entry.title = info.activityInfo.name;
}
- }
- if (entry.title == null) {
- entry.title = info.activityInfo.name;
- }
- Drawable icon = getFullResIcon(info);
- if (mIconPackHelper.isIconPackLoaded() && (mIconPackHelper
- .getResourceIdForActivityIcon(info.activityInfo) == 0)) {
entry.icon = Utilities.createIconBitmap(
- icon, mContext, mIconPackHelper.getIconBack(),
- mIconPackHelper.getIconMask(), mIconPackHelper.getIconUpon(), mIconPackHelper.getIconScale());
+ getFullResIcon(info), mContext);
} else {
- entry.icon = Utilities.createIconBitmap(
- icon, mContext);
+ entry.title = "";
+ Bitmap preloaded = getPreloadedIcon(componentName);
+ if (preloaded != null) {
+ if (DEBUG) Log.d(TAG, "using preloaded icon for " +
+ componentName.toShortString());
+ entry.icon = preloaded;
+ } else {
+ if (DEBUG) Log.d(TAG, "using default icon for " +
+ componentName.toShortString());
+ entry.icon = mDefaultIcon;
+ }
}
}
return entry;
@@ -276,4 +296,137 @@ public class IconCache {
return set;
}
}
+
+ /**
+ * Pre-load an icon into the persistent cache.
+ *
+ * <P>Queries for a component that does not exist in the package manager
+ * will be answered by the persistent cache.
+ *
+ * @param context application context
+ * @param componentName the icon should be returned for this component
+ * @param icon the icon to be persisted
+ * @param dpi the native density of the icon
+ */
+ public static void preloadIcon(Context context, ComponentName componentName, Bitmap icon,
+ int dpi) {
+ // TODO rescale to the correct native DPI
+ try {
+ PackageManager packageManager = context.getPackageManager();
+ packageManager.getActivityIcon(componentName);
+ // component is present on the system already, do nothing
+ return;
+ } catch (PackageManager.NameNotFoundException e) {
+ // pass
+ }
+
+ final String key = componentName.flattenToString();
+ FileOutputStream resourceFile = null;
+ try {
+ resourceFile = context.openFileOutput(getResourceFilename(componentName),
+ Context.MODE_PRIVATE);
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ if (icon.compress(android.graphics.Bitmap.CompressFormat.PNG, 75, os)) {
+ byte[] buffer = os.toByteArray();
+ resourceFile.write(buffer, 0, buffer.length);
+ } else {
+ Log.w(TAG, "failed to encode cache for " + key);
+ return;
+ }
+ } catch (FileNotFoundException e) {
+ Log.w(TAG, "failed to pre-load cache for " + key, e);
+ } catch (IOException e) {
+ Log.w(TAG, "failed to pre-load cache for " + key, e);
+ } finally {
+ if (resourceFile != null) {
+ try {
+ resourceFile.close();
+ } catch (IOException e) {
+ Log.d(TAG, "failed to save restored icon for: " + key, e);
+ }
+ }
+ }
+ }
+
+ /**
+ * Read a pre-loaded icon from the persistent icon cache.
+ *
+ * @param componentName the component that should own the icon
+ * @returns a bitmap if one is cached, or null.
+ */
+ private Bitmap getPreloadedIcon(ComponentName componentName) {
+ final String key = componentName.flattenToShortString();
+
+ if (DEBUG) Log.v(TAG, "looking for pre-load icon for " + key);
+ Bitmap icon = null;
+ FileInputStream resourceFile = null;
+ try {
+ resourceFile = mContext.openFileInput(getResourceFilename(componentName));
+ byte[] buffer = new byte[1024];
+ ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+ int bytesRead = 0;
+ while(bytesRead >= 0) {
+ bytes.write(buffer, 0, bytesRead);
+ bytesRead = resourceFile.read(buffer, 0, buffer.length);
+ }
+ if (DEBUG) Log.d(TAG, "read " + bytes.size());
+ icon = BitmapFactory.decodeByteArray(bytes.toByteArray(), 0, bytes.size());
+ if (icon == null) {
+ Log.w(TAG, "failed to decode pre-load icon for " + key);
+ }
+ } catch (FileNotFoundException e) {
+ if (DEBUG) Log.d(TAG, "there is no restored icon for: " + key, e);
+ } catch (IOException e) {
+ Log.w(TAG, "failed to read pre-load icon for: " + key, e);
+ } finally {
+ if(resourceFile != null) {
+ try {
+ resourceFile.close();
+ } catch (IOException e) {
+ Log.d(TAG, "failed to manage pre-load icon file: " + key, e);
+ }
+ }
+ }
+
+ if (icon != null) {
+ // TODO: handle alpha mask in the view layer
+ Bitmap b = Bitmap.createBitmap(Math.max(icon.getWidth(), 1),
+ Math.max(icon.getHeight(), 1),
+ Bitmap.Config.ARGB_8888);
+ Canvas c = new Canvas(b);
+ Paint paint = new Paint();
+ paint.setAlpha(127);
+ c.drawBitmap(icon, 0, 0, paint);
+ c.setBitmap(null);
+ icon.recycle();
+ icon = b;
+ }
+
+ return icon;
+ }
+
+ /**
+ * Remove a pre-loaded icon from the persistent icon cache.
+ *
+ * @param componentName the component that should own the icon
+ * @returns true on success
+ */
+ public boolean deletePreloadedIcon(ComponentName componentName) {
+ if (componentName == null) {
+ return false;
+ }
+ if (mCache.remove(componentName) != null) {
+ if (DEBUG) Log.d(TAG, "removed pre-loaded icon from the in-memory cache");
+ }
+ boolean success = mContext.deleteFile(getResourceFilename(componentName));
+ if (DEBUG && success) Log.d(TAG, "removed pre-loaded icon from persistent cache");
+
+ return success;
+ }
+
+ private static String getResourceFilename(ComponentName component) {
+ String resourceName = component.flattenToShortString();
+ String filename = resourceName.replace(File.separatorChar, '_');
+ return RESOURCE_FILE_PREFIX + filename;
+ }
}
diff --git a/src/com/android/launcher3/IconPackHelper.java b/src/com/android/launcher3/IconPackHelper.java
deleted file mode 100644
index 69fadd965..000000000
--- a/src/com/android/launcher3/IconPackHelper.java
+++ /dev/null
@@ -1,517 +0,0 @@
-package com.android.launcher3;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.lang.reflect.Field;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlPullParserFactory;
-
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.pm.ActivityInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.content.res.Resources;
-import android.content.res.XmlResourceParser;
-import android.graphics.drawable.Drawable;
-import android.text.TextUtils;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.BaseAdapter;
-import android.widget.ImageView;
-import android.widget.RadioButton;
-import android.widget.TextView;
-import android.widget.Toast;
-
-import com.android.launcher3.Launcher;
-import com.android.launcher3.settings.SettingsProvider;
-
-public class IconPackHelper {
-
- static final String ICON_MASK_TAG = "iconmask";
- static final String ICON_BACK_TAG = "iconback";
- static final String ICON_UPON_TAG = "iconupon";
- static final String ICON_SCALE_TAG = "scale";
-
- public final static String[] sSupportedActions = new String[] {
- "org.adw.launcher.THEMES",
- "com.gau.go.launcherex.theme"
- };
-
- public static final String[] sSupportedCategories = new String[] {
- "com.fede.launcher.THEME_ICONPACK",
- "com.anddoes.launcher.THEME",
- "com.teslacoilsw.launcher.THEME"
- };
-
- // Holds package/class -> drawable
- private Map<String, String> mIconPackResources;
- private final Context mContext;
- private String mLoadedIconPackName;
- private Resources mLoadedIconPackResource;
- private Drawable mIconBack, mIconUpon, mIconMask;
- private float mIconScale;
-
- public Drawable getIconBack() {
- return mIconBack;
- }
-
- public Drawable getIconMask() {
- return mIconMask;
- }
-
- public Drawable getIconUpon() {
- return mIconUpon;
- }
-
- public float getIconScale() {
- return mIconScale;
- }
-
- IconPackHelper(Context context) {
- mContext = context;
- mIconPackResources = new HashMap<String, String>();
- }
-
- private Drawable getDrawableForName(String name) {
- if (isIconPackLoaded()) {
- String item = mIconPackResources.get(name);
- if (!TextUtils.isEmpty(item)) {
- int id = getResourceIdForDrawable(item);
- if (id != 0) {
- return mLoadedIconPackResource.getDrawable(id);
- }
- }
- }
- return null;
- }
-
- public static Map<String, IconPackInfo> getSupportedPackages(Context context) {
- Intent i = new Intent();
- Map<String, IconPackInfo> packages = new HashMap<String, IconPackInfo>();
- PackageManager packageManager = context.getPackageManager();
- for (String action : sSupportedActions) {
- i.setAction(action);
- for (ResolveInfo r : packageManager.queryIntentActivities(i, 0)) {
- IconPackInfo info = new IconPackInfo(r, packageManager);
- packages.put(r.activityInfo.packageName, info);
- }
- }
- i = new Intent(Intent.ACTION_MAIN);
- for (String category : sSupportedCategories) {
- i.addCategory(category);
- for (ResolveInfo r : packageManager.queryIntentActivities(i, 0)) {
- IconPackInfo info = new IconPackInfo(r, packageManager);
- packages.put(r.activityInfo.packageName, info);
- }
- i.removeCategory(category);
- }
- return packages;
- }
-
- private static void loadResourcesFromXmlParser(XmlPullParser parser,
- Map<String, String> iconPackResources) throws XmlPullParserException, IOException {
- int eventType = parser.getEventType();
- do {
-
- if (eventType != XmlPullParser.START_TAG) {
- continue;
- }
-
- if (parser.getName().equalsIgnoreCase(ICON_MASK_TAG) ||
- parser.getName().equalsIgnoreCase(ICON_BACK_TAG) ||
- parser.getName().equalsIgnoreCase(ICON_UPON_TAG)) {
- String icon = parser.getAttributeValue(null, "img");
- if (icon == null) {
- if (parser.getAttributeCount() == 1) {
- icon = parser.getAttributeValue(0);
- }
- }
- iconPackResources.put(parser.getName().toLowerCase(), icon);
- continue;
- }
-
- if (parser.getName().equalsIgnoreCase(ICON_SCALE_TAG)) {
- String factor = parser.getAttributeValue(null, "factor");
- if (factor == null) {
- if (parser.getAttributeCount() == 1) {
- factor = parser.getAttributeValue(0);
- }
- }
- iconPackResources.put(parser.getName().toLowerCase(), factor);
- continue;
- }
-
- if (!parser.getName().equalsIgnoreCase("item")) {
- continue;
- }
-
- String component = parser.getAttributeValue(null, "component");
- String drawable = parser.getAttributeValue(null, "drawable");
-
- // Validate component/drawable exist
- if (TextUtils.isEmpty(component) || TextUtils.isEmpty(drawable)) {
- continue;
- }
-
- // Validate format/length of component
- if (!component.startsWith("ComponentInfo{") || !component.endsWith("}")
- || component.length() < 16) {
- continue;
- }
-
- // Sanitize stored value
- component = component.substring(14, component.length() - 1).toLowerCase();
-
- ComponentName name = null;
- if (!component.contains("/")) {
- // Package icon reference
- iconPackResources.put(component, drawable);
- } else {
- name = ComponentName.unflattenFromString(component);
- if (name != null) {
- iconPackResources.put(name.getPackageName(), drawable);
- iconPackResources.put(name.getPackageName() + "." + name.getClassName(), drawable);
- }
- }
- } while ((eventType = parser.next()) != XmlPullParser.END_DOCUMENT);
- }
-
- private static void loadApplicationResources(Context context,
- Map<String, String> iconPackResources, String packageName) {
- Field[] drawableItems = null;
- try {
- Context appContext = context.createPackageContext(packageName,
- Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);
- drawableItems = Class.forName(packageName+".R$drawable",
- true, appContext.getClassLoader()).getFields();
- } catch (Exception e){
- return;
- }
-
- for (Field f : drawableItems) {
- String name = f.getName();
-
- String icon = name.toLowerCase();
- name = name.replaceAll("_", ".");
-
- iconPackResources.put(name, icon);
-
- int activityIndex = name.lastIndexOf(".");
- if (activityIndex <= 0 || activityIndex == name.length() - 1) {
- continue;
- }
-
- String iconPackage = name.substring(0, activityIndex);
- if (TextUtils.isEmpty(iconPackage)) {
- continue;
- }
- iconPackResources.put(iconPackage, icon);
-
- String iconActivity = name.substring(activityIndex + 1);
- if (TextUtils.isEmpty(iconActivity)) {
- continue;
- }
- iconPackResources.put(iconPackage + "." + iconActivity, icon);
- }
- }
-
- public boolean loadIconPack(String packageName) {
- mIconPackResources = getIconPackResources(mContext, packageName);
- Resources res = null;
- try {
- res = mContext.getPackageManager().getResourcesForApplication(packageName);
- } catch (PackageManager.NameNotFoundException e) {
- e.printStackTrace();
- return false;
- }
- mLoadedIconPackResource = res;
- mLoadedIconPackName = packageName;
- mIconBack = getDrawableForName(ICON_BACK_TAG);
- mIconMask = getDrawableForName(ICON_MASK_TAG);
- mIconUpon = getDrawableForName(ICON_UPON_TAG);
- String scale = mIconPackResources.get(ICON_SCALE_TAG);
- if (scale != null) {
- try {
- mIconScale = Float.valueOf(scale);
- } catch (NumberFormatException e) {
- }
- }
- return true;
- }
-
- public static Map<String, String> getIconPackResources(Context context, String packageName) {
- if (TextUtils.isEmpty(packageName)) {
- return null;
- }
-
- Resources res = null;
- try {
- res = context.getPackageManager().getResourcesForApplication(packageName);
- } catch (PackageManager.NameNotFoundException e) {
- e.printStackTrace();
- return null;
- }
-
- XmlPullParser parser = null;
- InputStream inputStream = null;
- Map<String, String> iconPackResources = new HashMap<String, String>();
-
- try {
- inputStream = res.getAssets().open("appfilter.xml");
- XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
- parser = factory.newPullParser();
- parser.setInput(inputStream, "UTF-8");
- } catch (Exception e) {
- // Catch any exception since we want to fall back to parsing the xml/
- // resource in all cases
- int resId = res.getIdentifier("appfilter", "xml", packageName);
- if (resId != 0) {
- parser = res.getXml(resId);
- }
- }
-
- if (parser != null) {
- try {
- loadResourcesFromXmlParser(parser, iconPackResources);
- return iconPackResources;
- } catch (XmlPullParserException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- } finally {
- // Cleanup resources
- if (parser instanceof XmlResourceParser) {
- ((XmlResourceParser) parser).close();
- }
- if (inputStream != null) {
- try {
- inputStream.close();
- } catch (IOException e) {
- }
- }
- }
- }
-
- // Application uses a different theme format (most likely launcher pro)
- int arrayId = res.getIdentifier("theme_iconpack", "array", packageName);
- if (arrayId == 0) {
- arrayId = res.getIdentifier("icon_pack", "array", packageName);
- }
-
- if (arrayId != 0) {
- String[] iconPack = res.getStringArray(arrayId);
- for (String entry : iconPack) {
-
- if (TextUtils.isEmpty(entry)) {
- continue;
- }
-
- String icon = entry.toLowerCase();
- entry = entry.replaceAll("_", ".");
-
- iconPackResources.put(entry, icon);
-
- int activityIndex = entry.lastIndexOf(".");
- if (activityIndex <= 0 || activityIndex == entry.length() - 1) {
- continue;
- }
-
- String iconPackage = entry.substring(0, activityIndex);
- if (TextUtils.isEmpty(iconPackage)) {
- continue;
- }
- iconPackResources.put(iconPackage, icon);
-
- String iconActivity = entry.substring(activityIndex + 1);
- if (TextUtils.isEmpty(iconActivity)) {
- continue;
- }
- iconPackResources.put(iconPackage + "." + iconActivity, icon);
- }
- } else {
- loadApplicationResources(context, iconPackResources, packageName);
- }
- return iconPackResources;
- }
-
- public void unloadIconPack() {
- mLoadedIconPackResource = null;
- mLoadedIconPackName = null;
- mIconPackResources = null;
- mIconMask = null;
- mIconBack = null;
- mIconUpon = null;
- mIconScale = 1f;
- }
-
- public static void pickIconPack(final Context context, final boolean pickIcon) {
- Map<String, IconPackInfo> supportedPackages = getSupportedPackages(context);
- if (supportedPackages.isEmpty()) {
- Toast.makeText(context, R.string.no_iconpacks_summary, Toast.LENGTH_SHORT).show();
- return;
- }
-
- final IconAdapter adapter = new IconAdapter(context, supportedPackages);
- AlertDialog.Builder builder = new AlertDialog.Builder(context);
- builder.setTitle(R.string.dialog_pick_iconpack_title);
- if (!pickIcon) {
- builder.setAdapter(adapter, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int position) {
- if (adapter.isCurrentIconPack(position)) {
- ((Launcher) context).getWorkspace().exitOverviewMode(true);
- return;
- }
- String selectedPackage = adapter.getItem(position);
- SettingsProvider.putString(context,
- SettingsProvider.SETTINGS_UI_GENERAL_ICONS_ICON_PACK, selectedPackage);
- LauncherAppState.getInstance().getIconCache().flush();
- LauncherAppState.getInstance().getModel().forceReload();
- ((Launcher) context).getWorkspace().exitOverviewMode(true);
- }
- });
- } else {
- builder.setAdapter(adapter, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- String selectedPackage = adapter.getItem(which);
- Launcher launcherActivity = (Launcher) context;
- if (TextUtils.isEmpty(selectedPackage)) {
- launcherActivity.onActivityResult(Launcher.REQUEST_PICK_ICON, Activity.RESULT_OK, null);
- } else {
- Intent i = new Intent();
- i.setClass(context, IconPickerActivity.class);
- i.putExtra(IconPickerActivity.PACKAGE_NAME_EXTRA, selectedPackage);
- launcherActivity.startActivityForResult(i, Launcher.REQUEST_PICK_ICON);
- }
- }
- });
- }
- builder.show().getWindow().getDecorView().setAlpha(0.8f);
- }
-
- boolean isIconPackLoaded() {
- return mLoadedIconPackResource != null &&
- mLoadedIconPackName != null &&
- mIconPackResources != null;
- }
-
- private int getResourceIdForDrawable(String resource) {
- int resId = mLoadedIconPackResource.getIdentifier(resource, "drawable", mLoadedIconPackName);
- return resId;
- }
-
- public Resources getIconPackResources() {
- return mLoadedIconPackResource;
- }
-
- public int getResourceIdForActivityIcon(ActivityInfo info) {
- String drawable = mIconPackResources.get(info.packageName.toLowerCase()
- + "." + info.name.toLowerCase());
- if (drawable == null) {
- // Icon pack doesn't have an icon for the activity, fallback to package icon
- drawable = mIconPackResources.get(info.packageName.toLowerCase());
- if (drawable == null) {
- return 0;
- }
- }
- return getResourceIdForDrawable(drawable);
- }
-
- static class IconPackInfo {
- String packageName;
- CharSequence label;
- Drawable icon;
-
- IconPackInfo(ResolveInfo r, PackageManager packageManager) {
- packageName = r.activityInfo.packageName;
- icon = r.loadIcon(packageManager);
- label = r.loadLabel(packageManager);
- }
-
- IconPackInfo(){
- }
-
- public IconPackInfo(String label, Drawable icon, String packageName) {
- this.label = label;
- this.icon = icon;
- this.packageName = packageName;
- }
- }
-
- private static class IconAdapter extends BaseAdapter {
- ArrayList<IconPackInfo> mSupportedPackages;
- LayoutInflater mLayoutInflater;
- String mCurrentIconPack;
- int mCurrentIconPackPosition = -1;
-
- IconAdapter(Context ctx, Map<String, IconPackInfo> supportedPackages) {
- mLayoutInflater = LayoutInflater.from(ctx);
- mSupportedPackages = new ArrayList<IconPackInfo>(supportedPackages.values());
- Collections.sort(mSupportedPackages, new Comparator<IconPackInfo>() {
- @Override
- public int compare(IconPackInfo lhs, IconPackInfo rhs) {
- return lhs.label.toString().compareToIgnoreCase(rhs.label.toString());
- }
- });
-
- Resources res = ctx.getResources();
- String defaultLabel = res.getString(R.string.default_iconpack_title);
- Drawable icon = res.getDrawable(R.mipmap.ic_launcher_home);
- mSupportedPackages.add(0, new IconPackInfo(defaultLabel, icon, ""));
-
- mCurrentIconPack = SettingsProvider.getStringCustomDefault(ctx,
- SettingsProvider.SETTINGS_UI_GENERAL_ICONS_ICON_PACK, "");
- }
-
- @Override
- public int getCount() {
- return mSupportedPackages.size();
- }
-
- @Override
- public String getItem(int position) {
- return (String) mSupportedPackages.get(position).packageName;
- }
-
- @Override
- public long getItemId(int position) {
- return 0;
- }
-
- public boolean isCurrentIconPack(int position) {
- return mCurrentIconPackPosition == position;
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- if (convertView == null) {
- convertView = mLayoutInflater.inflate(R.layout.iconpack_chooser, null);
- }
- IconPackInfo info = mSupportedPackages.get(position);
- TextView txtView = (TextView) convertView.findViewById(R.id.title);
- txtView.setText(info.label);
- ImageView imgView = (ImageView) convertView.findViewById(R.id.icon);
- imgView.setImageDrawable(info.icon);
- RadioButton radioButton = (RadioButton) convertView.findViewById(R.id.radio);
- boolean isCurrentIconPack = info.packageName.equals(mCurrentIconPack);
- radioButton.setChecked(isCurrentIconPack);
- if (isCurrentIconPack) {
- mCurrentIconPackPosition = position;
- }
- return convertView;
- }
- }
-
-} \ No newline at end of file
diff --git a/src/com/android/launcher3/IconPickerActivity.java b/src/com/android/launcher3/IconPickerActivity.java
deleted file mode 100644
index 5f08eda68..000000000
--- a/src/com/android/launcher3/IconPickerActivity.java
+++ /dev/null
@@ -1,152 +0,0 @@
-package com.android.launcher3;
-
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.LinkedHashSet;
-import java.util.Map;
-
-import android.app.Activity;
-import android.app.ActivityManager;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.res.Resources;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
-import android.os.AsyncTask;
-import android.os.Bundle;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.AdapterView;
-import android.widget.BaseAdapter;
-import android.widget.GridView;
-import android.widget.ImageView;
-
-public class IconPickerActivity extends Activity {
-
- public static final String SELECTED_RESOURCE_EXTRA = "selected_resource";
- public static final String SELECTED_BITMAP_EXTRA = "bitmap";
- public static final String PACKAGE_NAME_EXTRA = "package";
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- ActivityManager activityManager =
- (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
- int iconSize = activityManager.getLauncherLargeIconSize();
- final String pkgName = getIntent().getStringExtra(PACKAGE_NAME_EXTRA);
-
- GridView gridview = new GridView(this);
- gridview.setNumColumns(GridView.AUTO_FIT);
- gridview.setHorizontalSpacing(40);
- gridview.setVerticalSpacing(40);
- gridview.setPadding(20, 20, 20, 0);
- gridview.setFastScrollEnabled(true);
- gridview.setColumnWidth(iconSize);
- gridview.setStretchMode(GridView.STRETCH_COLUMN_WIDTH);
-
- gridview.setAdapter(new ImageAdapter(this, pkgName));
- gridview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> adapterView, View v, int position, long id) {
- Intent in = new Intent();
- DrawableInfo d = (DrawableInfo) adapterView.getAdapter().getItem(position);
- in.putExtra(SELECTED_RESOURCE_EXTRA, pkgName + "|" + d.resource_name);
- in.putExtra(SELECTED_BITMAP_EXTRA, ((BitmapDrawable)d.drawable.get()).getBitmap());
- setResult(Activity.RESULT_OK, in);
- finish();
- }
- });
- setContentView(gridview);
- }
-
- public class ImageAdapter extends BaseAdapter {
- private Context mContext;
- private Resources mResources;
- private ArrayList<DrawableInfo> mDrawables = new ArrayList<DrawableInfo>();
-
- public class FetchDrawable extends AsyncTask<Integer, Void, Drawable> {
- WeakReference<ImageView> mImageView;
-
- FetchDrawable(ImageView imgView) {
- mImageView = new WeakReference<ImageView>(imgView);
- }
-
- @Override
- protected Drawable doInBackground(Integer... position) {
- DrawableInfo info = getItem(position[0]);
- int itemId = info.resource_id;
- Drawable d = mResources.getDrawable(itemId);
- info.drawable = new WeakReference<Drawable>(d);
- return d;
- }
-
- @Override
- public void onPostExecute(Drawable result) {
- if (mImageView.get() != null) {
- mImageView.get().setImageDrawable(result);
- }
- }
- }
-
- public ImageAdapter(Context c, String pkgName) {
- mContext = c;
- Map<String, String> resources = IconPackHelper.getIconPackResources(c, pkgName);
- try {
- mResources = c.getPackageManager().getResourcesForApplication(pkgName);
- LinkedHashSet<String> drawables = new LinkedHashSet<String>(resources.values());
- for (String s : drawables) {
- int id = mResources.getIdentifier(s, "drawable", pkgName);
- if (id != 0) {
- mDrawables.add(new DrawableInfo(s, id));
- }
- }
- } catch (NameNotFoundException e) {
- }
- }
-
- public int getCount() {
- return mDrawables.size();
- }
-
- public DrawableInfo getItem(int position) {
- return mDrawables.get(position);
- }
-
- public long getItemId(int position) {
- return 0;
- }
-
- public View getView(final int position, View convertView, ViewGroup parent) {
- final ImageView imageView;
- if (convertView == null) {
- imageView = new ImageView(mContext);
- imageView.setLayoutParams(new GridView.LayoutParams(
- GridView.LayoutParams.WRAP_CONTENT, GridView.LayoutParams.WRAP_CONTENT));
- imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
- } else {
- imageView = (ImageView) convertView;
- Object tag = imageView.getTag();
- if (tag != null && tag instanceof FetchDrawable) {
- ((FetchDrawable) tag).cancel(true);
- }
- }
- FetchDrawable req = new FetchDrawable(imageView);
- imageView.setTag(req);
- req.execute(position);
- return imageView;
- }
- }
-
- private class DrawableInfo {
- WeakReference<Drawable> drawable;
- final String resource_name;
- final int resource_id;
- DrawableInfo(String n, int i) {
- resource_name = n;
- resource_id = i;
- }
- }
-}
diff --git a/src/com/android/launcher3/InstallShortcutReceiver.java b/src/com/android/launcher3/InstallShortcutReceiver.java
index 7df73b1f6..28cef1346 100644
--- a/src/com/android/launcher3/InstallShortcutReceiver.java
+++ b/src/com/android/launcher3/InstallShortcutReceiver.java
@@ -24,17 +24,20 @@ import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
+import android.text.TextUtils;
import android.util.Base64;
import android.util.Log;
import android.widget.Toast;
+import org.json.JSONObject;
+import org.json.JSONStringer;
+import org.json.JSONTokener;
+
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
-import org.json.*;
-
public class InstallShortcutReceiver extends BroadcastReceiver {
private static final String TAG = "InstallShortcutReceiver";
private static final boolean DBG = false;
@@ -108,6 +111,9 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
public static void removeFromInstallQueue(SharedPreferences sharedPrefs,
ArrayList<String> packageNames) {
+ if (packageNames.isEmpty()) {
+ return;
+ }
synchronized(sLock) {
Set<String> strings = sharedPrefs.getStringSet(APPS_PENDING_INSTALL, null);
if (DBG) {
@@ -218,18 +224,11 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
if (intent == null) {
return;
}
+
// This name is only used for comparisons and notifications, so fall back to activity name
// if not supplied
- String name = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);
- if (name == null) {
- try {
- PackageManager pm = context.getPackageManager();
- ActivityInfo info = pm.getActivityInfo(intent.getComponent(), 0);
- name = info.loadLabel(pm).toString();
- } catch (PackageManager.NameNotFoundException nnfe) {
- return;
- }
- }
+ String name = ensureValidName(context, intent,
+ data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME)).toString();
Bitmap icon = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON);
Intent.ShortcutIconResource iconResource =
data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE);
@@ -272,6 +271,12 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
//final Intent data = pendingInfo.data;
final Intent intent = pendingInfo.launchIntent;
final String name = pendingInfo.name;
+
+ if (LauncherAppState.isDisableAllApps() && !isValidShortcutLaunchIntent(intent)) {
+ if (DBG) Log.d(TAG, "Ignoring shortcut with launchIntent:" + intent);
+ continue;
+ }
+
final boolean exists = LauncherModel.shortcutExists(context, name, intent);
//final boolean allowDuplicate = data.getBooleanExtra(Launcher.EXTRA_SHORTCUT_DUPLICATE, true);
@@ -299,11 +304,35 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
// Add the new apps to the model and bind them
if (!addShortcuts.isEmpty()) {
LauncherAppState app = LauncherAppState.getInstance();
- app.getModel().addAndBindAddedApps(context, addShortcuts, null);
+ app.getModel().addAndBindAddedWorkspaceApps(context, addShortcuts);
}
}
}
+ /**
+ * Returns true if the intent is a valid launch intent for a shortcut.
+ * This is used to identify shortcuts which are different from the ones exposed by the
+ * applications' manifest file.
+ *
+ * When DISABLE_ALL_APPS is true, shortcuts exposed via the app's manifest should never be
+ * duplicated or removed(unless the app is un-installed).
+ *
+ * @param launchIntent The intent that will be launched when the shortcut is clicked.
+ */
+ static boolean isValidShortcutLaunchIntent(Intent launchIntent) {
+ if (launchIntent != null
+ && Intent.ACTION_MAIN.equals(launchIntent.getAction())
+ && launchIntent.getComponent() != null
+ && launchIntent.getCategories() != null
+ && launchIntent.getCategories().size() == 1
+ && launchIntent.hasCategory(Intent.CATEGORY_LAUNCHER)
+ && launchIntent.getExtras() == null
+ && TextUtils.isEmpty(launchIntent.getDataString())) {
+ return false;
+ }
+ return true;
+ }
+
private static ShortcutInfo getShortcutInfo(Context context, Intent data,
Intent launchIntent) {
if (launchIntent.getAction() == null) {
@@ -315,6 +344,25 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
}
LauncherAppState app = LauncherAppState.getInstance();
- return app.getModel().infoFromShortcutIntent(context, data, null);
+ ShortcutInfo info = app.getModel().infoFromShortcutIntent(context, data, null);
+ info.title = ensureValidName(context, launchIntent, info.title);
+ return info;
+ }
+
+ /**
+ * Ensures that we have a valid, non-null name. If the provided name is null, we will return
+ * the application name instead.
+ */
+ private static CharSequence ensureValidName(Context context, Intent intent, CharSequence name) {
+ if (name == null) {
+ try {
+ PackageManager pm = context.getPackageManager();
+ ActivityInfo info = pm.getActivityInfo(intent.getComponent(), 0);
+ name = info.loadLabel(pm).toString();
+ } catch (PackageManager.NameNotFoundException nnfe) {
+ return "";
+ }
+ }
+ return name;
}
}
diff --git a/src/com/android/launcher3/InstallWidgetReceiver.java b/src/com/android/launcher3/InstallWidgetReceiver.java
index 0ef478074..74b9e3d99 100644
--- a/src/com/android/launcher3/InstallWidgetReceiver.java
+++ b/src/com/android/launcher3/InstallWidgetReceiver.java
@@ -16,8 +16,6 @@
package com.android.launcher3;
-import java.util.List;
-
import android.appwidget.AppWidgetProviderInfo;
import android.content.ClipData;
import android.content.Context;
@@ -33,7 +31,7 @@ import android.widget.ImageView;
import android.widget.ListAdapter;
import android.widget.TextView;
-import com.android.launcher3.R;
+import java.util.List;
/**
diff --git a/src/com/android/launcher3/ItemInfo.java b/src/com/android/launcher3/ItemInfo.java
index 8c4cefd5f..3dc92c9c2 100644
--- a/src/com/android/launcher3/ItemInfo.java
+++ b/src/com/android/launcher3/ItemInfo.java
@@ -27,7 +27,7 @@ import java.io.IOException;
/**
* Represents an item in the launcher.
*/
-class ItemInfo {
+public class ItemInfo {
static final int NO_ID = -1;
@@ -122,6 +122,10 @@ class ItemInfo {
throw new RuntimeException("Unexpected Intent");
}
+ protected Intent getRestoredIntent() {
+ throw new RuntimeException("Unexpected Intent");
+ }
+
/**
* Write the fields of this item to the DB
*
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 416c80641..ab3f1daa0 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -17,8 +17,6 @@
package com.android.launcher3;
-import android.accounts.Account;
-import android.accounts.AccountManager;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
@@ -29,8 +27,10 @@ import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityOptions;
-import android.app.AlertDialog;
import android.app.Dialog;
+import android.app.Fragment;
+import android.app.FragmentManager;
+import android.app.FragmentTransaction;
import android.app.SearchManager;
import android.appwidget.AppWidgetHostView;
import android.appwidget.AppWidgetManager;
@@ -41,13 +41,14 @@ import android.content.ComponentCallbacks2;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
-import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.database.ContentObserver;
@@ -55,6 +56,7 @@ import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Point;
import android.graphics.PorterDuff;
+import android.graphics.PorterDuffColorFilter;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.net.Uri;
@@ -65,7 +67,6 @@ import android.os.Handler;
import android.os.Message;
import android.os.StrictMode;
import android.os.SystemClock;
-import android.provider.Settings;
import android.speech.RecognizerIntent;
import android.text.Selection;
import android.text.SpannableStringBuilder;
@@ -83,14 +84,12 @@ import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.View;
-import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityEvent;
-import android.view.accessibility.AccessibilityManager;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.view.inputmethod.InputMethodManager;
@@ -101,8 +100,9 @@ import android.widget.PopupMenu;
import android.widget.TextView;
import android.widget.Toast;
+import com.android.launcher.home.Home;
import com.android.launcher3.DropTarget.DragObject;
-import com.android.launcher3.settings.SettingsActivity;
+import com.android.launcher3.PagedView.TransitionEffect;
import com.android.launcher3.settings.SettingsProvider;
import java.io.DataInputStream;
@@ -119,6 +119,8 @@ import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
/**
* Default launcher application.
@@ -129,12 +131,16 @@ public class Launcher extends Activity
static final String TAG = "Launcher";
static final boolean LOGD = false;
+ DeviceProfile mGrid;
+
static final boolean PROFILE_STARTUP = false;
static final boolean DEBUG_WIDGETS = false;
static final boolean DEBUG_STRICT_MODE = false;
static final boolean DEBUG_RESUME_TIME = false;
static final boolean DEBUG_DUMP_LOG = false;
+ static final boolean ENABLE_DEBUG_INTENTS = false; // allow DebugIntents to run
+
private static final int REQUEST_CREATE_SHORTCUT = 1;
private static final int REQUEST_CREATE_APPWIDGET = 5;
private static final int REQUEST_PICK_APPLICATION = 6;
@@ -143,8 +149,11 @@ public class Launcher extends Activity
private static final int REQUEST_PICK_WALLPAPER = 10;
private static final int REQUEST_BIND_APPWIDGET = 11;
+
static final int REQUEST_PICK_ICON = 13;
+ private static final int REQUEST_LOCK_PATTERN = 14;
+
/**
* IntentStarter uses request codes starting with this. This must be greater than all activity
* request codes used internally.
@@ -161,6 +170,7 @@ public class Launcher extends Activity
// adb shell setprop log.tag.PROPERTY_NAME [VERBOSE | SUPPRESS]
static final String FORCE_ENABLE_ROTATION_PROPERTY = "launcher_force_rotate";
static final String DUMP_STATE_PROPERTY = "launcher_dump_state";
+ static final String DISABLE_ALL_APPS_PROPERTY = "launcher_noallapps";
// The Intent extra that defines whether to ignore the launch animation
static final String INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION =
@@ -188,6 +198,13 @@ public class Launcher extends Activity
private static final String RUNTIME_STATE_PENDING_ADD_SPAN_Y = "launcher.add_span_y";
// Type: parcelable
private static final String RUNTIME_STATE_PENDING_ADD_WIDGET_INFO = "launcher.add_widget_info";
+ // Type: parcelable
+ private static final String RUNTIME_STATE_PENDING_ADD_WIDGET_ID = "launcher.add_widget_id";
+ // Type: int[]
+ private static final String RUNTIME_STATE_VIEW_IDS = "launcher.view_ids";
+
+
+ static final String FIRST_RUN_ACTIVITY_DISPLAYED = "launcher.first_run_activity_displayed";
private static final String TOOLBAR_ICON_METADATA_NAME = "com.android.launcher.toolbar_icon";
private static final String TOOLBAR_SEARCH_ICON_METADATA_NAME =
@@ -203,25 +220,31 @@ public class Launcher extends Activity
public static final String SHOW_WEIGHT_WATCHER = "debug.show_mem";
public static final boolean SHOW_WEIGHT_WATCHER_DEFAULT = false;
+ public static final String USER_HAS_MIGRATED = "launcher.user_migrated_from_old_data";
+
/** The different states that Launcher can be in. */
private enum State { NONE, WORKSPACE, APPS_CUSTOMIZE, APPS_CUSTOMIZE_SPRING_LOADED };
private State mState = State.WORKSPACE;
private AnimatorSet mStateAnimation;
static final int APPWIDGET_HOST_ID = 1024;
- private static final int EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT = 300;
- private static final int EXIT_SPRINGLOADED_MODE_LONG_TIMEOUT = 600;
- private static final int SHOW_CLING_DURATION = 250;
- private static final int DISMISS_CLING_DURATION = 200;
+ public static final int EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT = 300;
+ public static final int EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT_FOLDER_CLOSE = 400;
+ private static final int ON_ACTIVITY_RESULT_ANIMATION_DELAY = 500;
private static final Object sLock = new Object();
private static int sScreen = DEFAULT_SCREEN;
+ private HashMap<Integer, Integer> mItemIdToViewId = new HashMap<Integer, Integer>();
+ private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
+
// How long to wait before the new-shortcut animation automatically pans the workspace
private static int NEW_APPS_PAGE_MOVE_DELAY = 500;
private static int NEW_APPS_ANIMATION_INACTIVE_TIMEOUT_SECONDS = 5;
private static int NEW_APPS_ANIMATION_DELAY = 500;
+ private boolean mGelIntegrationEnabled = false;
+
private final BroadcastReceiver mCloseSystemDialogsReceiver
= new CloseSystemDialogsIntentReceiver();
private final ContentObserver mWidgetObserver = new AppWidgetResetObserver();
@@ -230,22 +253,37 @@ public class Launcher extends Activity
private Workspace mWorkspace;
private View mLauncherView;
+ private View mPageIndicators;
private DragLayer mDragLayer;
private DragController mDragController;
private View mWeightWatcher;
+ private TransitionEffectsFragment mTransitionEffectsFragment;
+ private DynamicGridSizeFragment mDynamicGridSizeFragment;
+ private LauncherClings mLauncherClings;
+ protected HiddenFolderFragment mHiddenFolderFragment;
+
private AppWidgetManager mAppWidgetManager;
private LauncherAppWidgetHost mAppWidgetHost;
private ItemInfo mPendingAddInfo = new ItemInfo();
private AppWidgetProviderInfo mPendingAddWidgetInfo;
+ private int mPendingAddWidgetId = -1;
private int[] mTmpAddItemCellCoordinates = new int[2];
private FolderInfo mFolderInfo;
+ protected FolderIcon mHiddenFolderIcon;
+ private boolean mHiddenFolderAuth = false;
+
private Hotseat mHotseat;
+
private View mOverviewPanel;
+ private View mDarkPanel;
+ OverviewSettingsPanel mOverviewSettingsPanel;
+
+// private ViewGroup mOverviewPanel;
private View mAllAppsButton;
@@ -253,7 +291,10 @@ public class Launcher extends Activity
private AppsCustomizeLayout mAppsCustomizeLayout;
private AppsCustomizePagedView mAppsCustomizeContent;
private boolean mAutoAdvanceRunning = false;
+ private View mQsb;
private View mQsbBar;
+ private ImageView mQsbBarSearch;
+ private ImageView mQsbBarVoice;
private Bundle mSavedState;
// We set the state in both onCreate and then onNewIntent in some cases, which causes both
@@ -280,14 +321,12 @@ public class Launcher extends Activity
private Dialog mTransitionEffectDialog;
- private LauncherModel mModel;
+ protected LauncherModel mModel;
private IconCache mIconCache;
private boolean mUserPresent = true;
private boolean mVisible = false;
private boolean mHasFocus = false;
private boolean mAttached = false;
- private static final boolean DISABLE_CLINGS = false;
- private static final boolean DISABLE_CUSTOM_CLINGS = true;
private static LocaleConfiguration sLocaleConfiguration = null;
@@ -315,6 +354,7 @@ public class Launcher extends Activity
private Drawable mWorkspaceBackgroundDrawable;
private final ArrayList<Integer> mSynchronouslyBoundPages = new ArrayList<Integer>();
+ private static final boolean DISABLE_SYNCHRONOUS_BINDING_CURRENT_PAGE = false;
static final ArrayList<String> sDumpLogs = new ArrayList<String>();
static Date sDateStamp = new Date();
@@ -338,9 +378,6 @@ public class Launcher extends Activity
private BubbleTextView mWaitingForResume;
- private HideFromAccessibilityHelper mHideFromAccessibilityHelper
- = new HideFromAccessibilityHelper();
-
// Preferences
private boolean mHideIconLabels;
@@ -368,10 +405,33 @@ public class Launcher extends Activity
private Stats mStats;
- private static boolean isPropertyEnabled(String propertyName) {
+ public Animator.AnimatorListener mAnimatorListener = new Animator.AnimatorListener() {
+ @Override
+ public void onAnimationStart(Animator arg0) {}
+ @Override
+ public void onAnimationRepeat(Animator arg0) {}
+ @Override
+ public void onAnimationEnd(Animator arg0) {
+ mDarkPanel.setVisibility(View.GONE);
+ }
+ @Override
+ public void onAnimationCancel(Animator arg0) {}
+ };
+
+ static boolean isPropertyEnabled(String propertyName) {
return Log.isLoggable(propertyName, Log.VERBOSE);
}
+ private BroadcastReceiver protectedAppsChangedReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ // Update the workspace
+ updateDynamicGrid();
+ mWorkspace.hideOutlines();
+ mSearchDropTargetBar.showSearchBar(false);
+ }
+ };
+
@Override
protected void onCreate(Bundle savedInstanceState) {
if (DEBUG_STRICT_MODE) {
@@ -391,36 +451,14 @@ public class Launcher extends Activity
super.onCreate(savedInstanceState);
- LauncherAppState.setApplicationContext(getApplicationContext());
- LauncherAppState app = LauncherAppState.getInstance();
-
- mHideIconLabels = SettingsProvider.getBoolean(this,
- SettingsProvider.SETTINGS_UI_HOMESCREEN_HIDE_ICON_LABELS,
- R.bool.preferences_interface_homescreen_hide_icon_labels_default);
-
- // Determine the dynamic grid properties
- Point smallestSize = new Point();
- Point largestSize = new Point();
- Point realSize = new Point();
- Display display = getWindowManager().getDefaultDisplay();
- display.getCurrentSizeRange(smallestSize, largestSize);
- display.getRealSize(realSize);
- DisplayMetrics dm = new DisplayMetrics();
- display.getMetrics(dm);
- // Lazy-initialize the dynamic grid
- DeviceProfile grid = app.initDynamicGrid(this,
- Math.min(smallestSize.x, smallestSize.y),
- Math.min(largestSize.x, largestSize.y),
- realSize.x, realSize.y,
- dm.widthPixels, dm.heightPixels);
+ initializeDynamicGrid();
// the LauncherApplication should call this, but in case of Instrumentation it might not be present yet
mSharedPrefs = getSharedPreferences(LauncherAppState.getSharedPreferencesKey(),
Context.MODE_PRIVATE);
- mModel = app.setLauncher(this);
- mIconCache = app.getIconCache();
- mIconCache.flushInvalidIcons(grid);
+
mDragController = new DragController(this);
+ mLauncherClings = new LauncherClings(this);
mInflater = getLayoutInflater();
mStats = new Stats(this);
@@ -445,7 +483,7 @@ public class Launcher extends Activity
setContentView(R.layout.launcher);
setupViews();
- grid.layout(this);
+ mGrid.layout(this);
registerContentObservers();
@@ -454,25 +492,21 @@ public class Launcher extends Activity
mSavedState = savedInstanceState;
restoreState(mSavedState);
- // Update customization drawer _after_ restoring the states
- if (mAppsCustomizeContent != null) {
- mAppsCustomizeContent.onPackagesUpdated(
- LauncherModel.getSortedWidgetsAndShortcuts(this));
- }
+ restoreGelSetting();
if (PROFILE_STARTUP) {
android.os.Debug.stopMethodTracing();
}
if (!mRestoring) {
- if (sPausedFromUserAction) {
+ if (DISABLE_SYNCHRONOUS_BINDING_CURRENT_PAGE || sPausedFromUserAction) {
// If the user leaves launcher, then we should just load items asynchronously when
// they return.
- mModel.startLoader(true, -1);
+ mModel.startLoader(true, PagedView.INVALID_RESTORE_PAGE);
} else {
// We only load the page synchronously if the user rotates (or triggers a
// configuration change) while launcher is in the foreground
- mModel.startLoader(true, mWorkspace.getCurrentPage());
+ mModel.startLoader(true, mWorkspace.getRestorePage());
}
}
@@ -488,7 +522,60 @@ public class Launcher extends Activity
// On large interfaces, we want the screen to auto-rotate based on the current orientation
unlockScreenOrientation(true);
- showFirstRunCling();
+ // The two first run cling paths are mutually exclusive, if the launcher is preinstalled
+ // on the device, then we always show the first run cling experience (or if there is no
+ // launcher2). Otherwise, we prompt the user upon started for migration
+ showFirstRunActivity();
+ if (mLauncherClings.shouldShowFirstRunOrMigrationClings()) {
+ if (mModel.canMigrateFromOldLauncherDb(this)) {
+ mLauncherClings.showMigrationCling();
+ } else {
+ mLauncherClings.showFirstRunCling();
+ }
+ } else {
+ mLauncherClings.removeFirstRunAndMigrationClings();
+ }
+ IntentFilter protectedAppsFilter = new IntentFilter(
+ "cyanogenmod.intent.action.PROTECTED_COMPONENT_UPDATE");
+ registerReceiver(protectedAppsChangedReceiver, protectedAppsFilter,
+ "cyanogenmod.permission.PROTECTED_APP", null);
+ }
+
+ public void restoreGelSetting() {
+ mGelIntegrationEnabled = SettingsProvider.getBoolean(this,
+ SettingsProvider.SETTINGS_UI_HOMESCREEN_SEARCH_SCREEN_LEFT,
+ R.bool.preferences_interface_homescreen_search_screen_left_default);
+ }
+
+ void initializeDynamicGrid() {
+ LauncherAppState.setApplicationContext(getApplicationContext());
+ LauncherAppState app = LauncherAppState.getInstance();
+
+ mHideIconLabels = SettingsProvider.getBoolean(this,
+ SettingsProvider.SETTINGS_UI_HOMESCREEN_HIDE_ICON_LABELS,
+ R.bool.preferences_interface_homescreen_hide_icon_labels_default);
+
+ restoreGelSetting();
+
+ // Determine the dynamic grid properties
+ Point smallestSize = new Point();
+ Point largestSize = new Point();
+ Point realSize = new Point();
+ Display display = getWindowManager().getDefaultDisplay();
+ display.getCurrentSizeRange(smallestSize, largestSize);
+ display.getRealSize(realSize);
+ DisplayMetrics dm = new DisplayMetrics();
+ display.getMetrics(dm);
+ // Lazy-initialize the dynamic grid
+ mGrid = app.initDynamicGrid(this,
+ Math.min(smallestSize.x, smallestSize.y),
+ Math.min(largestSize.x, largestSize.y),
+ realSize.x, realSize.y,
+ dm.widthPixels, dm.heightPixels);
+
+ mModel = app.setLauncher(this);
+ mIconCache = app.getIconCache();
+ mIconCache.flushInvalidIcons(mGrid);
}
protected void onUserLeaveHint() {
@@ -496,17 +583,64 @@ public class Launcher extends Activity
sPausedFromUserAction = true;
}
- /** To be overriden by subclasses to hint to Launcher that we have custom content */
- protected boolean hasCustomContentToLeft() {
+ /** To be overridden by subclasses to hint to Launcher that we have custom content */
+ protected boolean hasCustomSearchSupport() {
return false;
}
+ protected boolean hasCustomContentToLeft() {
+ return isGelIntegrationSupported() && isGelIntegrationEnabled();
+ }
+
+ public boolean isGelIntegrationSupported() {
+ final SearchManager searchManager =
+ (SearchManager) getSystemService(Context.SEARCH_SERVICE);
+ ComponentName globalSearchActivity = searchManager.getGlobalSearchActivity();
+
+ // Currently the only custom content available is the GEL launcher integration,
+ // only supported on CyanogenMod.
+ return globalSearchActivity != null && isCM();
+ }
+
+ public boolean isGelIntegrationEnabled() {
+ return mGelIntegrationEnabled;
+ }
+
+ public void onCustomContentLaunch() {
+ if(isGelIntegrationEnabled() && isGelIntegrationSupported()) {
+ GelIntegrationHelper.getInstance().registerSwipeBackGestureListenerAndStartGel(this, mWorkspace.isLayoutRtl());
+ }
+ }
+
+ /**
+ * Check if the device running this application is running CyanogenMod.
+ * @return true if this device is running CM.
+ */
+ protected boolean isCM() {
+ return getPackageManager().hasSystemFeature("com.cyanogenmod.android");
+ }
+
/**
* To be overridden by subclasses to create the custom content and call
* {@link #addToCustomContentPage}. This will only be invoked if
* {@link #hasCustomContentToLeft()} is {@code true}.
*/
- protected void addCustomContentToLeft() {
+ protected void populateCustomContentContainer() {
+ }
+
+ /**
+ * To be overridden by subclasses to indicate that there is an activity to launch
+ * before showing the standard launcher experience.
+ */
+ protected boolean hasFirstRunActivity() {
+ return false;
+ }
+
+ /**
+ * To be overridden by subclasses to launch any first run activity
+ */
+ protected Intent getFirstRunActivity() {
+ return null;
}
/**
@@ -521,13 +655,22 @@ public class Launcher extends Activity
if (!mWorkspace.hasCustomContent() && hasCustomContentToLeft()) {
// Create the custom content page and call the subclass to populate it.
- mWorkspace.createCustomContentPage();
- addCustomContentToLeft();
+ mWorkspace.createCustomContentContainer();
+ populateCustomContentContainer();
} else if (mWorkspace.hasCustomContent() && !hasCustomContentToLeft()) {
mWorkspace.removeCustomContentPage();
}
}
+ /** To be overriden by subclasses to hint to Launcher that we have custom content and
+ * support {@link #hasCustomSearchSupport()}
+ * @see com.android.launcher.home.Home#MODE_SEARCH_TEXT
+ * @see com.android.launcher.home.Home#MODE_SEARCH_VOICE
+ * */
+ protected void requestSearch(int mode) {
+ // To be implemented
+ }
+
private void updateGlobalIcons() {
boolean searchVisible = false;
boolean voiceVisible = false;
@@ -590,12 +733,12 @@ public class Launcher extends Activity
mIconCache.flush();
final LocaleConfiguration localeConfiguration = sLocaleConfiguration;
- new Thread("WriteLocaleConfiguration") {
- @Override
- public void run() {
+ new AsyncTask<Void, Void, Void>() {
+ public Void doInBackground(Void ... args) {
writeConfiguration(Launcher.this, localeConfiguration);
+ return null;
}
- }.start();
+ }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void) null);
}
}
@@ -659,10 +802,6 @@ public class Launcher extends Activity
return mInflater;
}
- public DragLayer getDragLayer() {
- return mDragLayer;
- }
-
boolean isDraggingEnabled() {
// We prevent dragging when we are loading the workspace as it is possible to pick up a view
// that is subsequently removed from the workspace in startBinding().
@@ -682,6 +821,34 @@ public class Launcher extends Activity
}
/**
+ * Copied from View -- the View version of the method isn't called
+ * anywhere else in our process and only exists for API level 17+,
+ * so it's ok to keep our own version with no API requirement.
+ */
+ public static int generateViewId() {
+ for (;;) {
+ final int result = sNextGeneratedId.get();
+ // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
+ int newValue = result + 1;
+ if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
+ if (sNextGeneratedId.compareAndSet(result, newValue)) {
+ return result;
+ }
+ }
+ }
+
+ public int getViewIdForItem(ItemInfo info) {
+ // This cast is safe given the > 2B range for int.
+ int itemId = (int) info.id;
+ if (mItemIdToViewId.containsKey(itemId)) {
+ return mItemIdToViewId.get(itemId);
+ }
+ int viewId = generateViewId();
+ mItemIdToViewId.put(itemId, viewId);
+ return viewId;
+ }
+
+ /**
* Returns whether we should delay spring loaded mode -- for shortcuts and widgets that have
* a configuration step, this allows the proper animations to run after other transitions.
*/
@@ -718,14 +885,27 @@ public class Launcher extends Activity
final int requestCode, final int resultCode, final Intent data) {
// Reset the startActivity waiting flag
mWaitingForResult = false;
+ int pendingAddWidgetId = mPendingAddWidgetId;
+ mPendingAddWidgetId = -1;
+
+ Runnable exitSpringLoaded = new Runnable() {
+ @Override
+ public void run() {
+ exitSpringLoadedDragModeDelayed((resultCode != RESULT_CANCELED),
+ EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT, null);
+ }
+ };
if (requestCode == REQUEST_BIND_APPWIDGET) {
- int appWidgetId = data != null ?
+ final int appWidgetId = data != null ?
data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1) : -1;
if (resultCode == RESULT_CANCELED) {
completeTwoStageWidgetDrop(RESULT_CANCELED, appWidgetId);
+ mWorkspace.removeExtraEmptyScreen(true, exitSpringLoaded,
+ ON_ACTIVITY_RESULT_ANIMATION_DELAY, false);
} else if (resultCode == RESULT_OK) {
- addAppWidgetImpl(appWidgetId, mPendingAddInfo, null, mPendingAddWidgetInfo);
+ addAppWidgetImpl(appWidgetId, mPendingAddInfo, null,
+ mPendingAddWidgetInfo, ON_ACTIVITY_RESULT_ANIMATION_DELAY);
}
return;
} else if (requestCode == REQUEST_PICK_WALLPAPER) {
@@ -733,24 +913,67 @@ public class Launcher extends Activity
mWorkspace.exitOverviewMode(false);
}
return;
+ } else if (requestCode == REQUEST_LOCK_PATTERN) {
+ mHiddenFolderAuth = true;
+ switch (resultCode) {
+ case RESULT_OK:
+ FragmentManager fragmentManager = getFragmentManager();
+ FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
+
+ fragmentTransaction.setCustomAnimations(0, 0);
+ fragmentTransaction.replace(R.id.launcher, mHiddenFolderFragment,
+ HiddenFolderFragment.HIDDEN_FOLDER_FRAGMENT);
+ fragmentTransaction.commit();
+ break;
+ case RESULT_CANCELED:
+ // User failed to enter/confirm a lock pattern, back out
+ break;
+ }
+ return;
}
- boolean delayExitSpringLoadedMode = false;
boolean isWidgetDrop = (requestCode == REQUEST_PICK_APPWIDGET ||
requestCode == REQUEST_CREATE_APPWIDGET);
// We have special handling for widgets
if (isWidgetDrop) {
- int appWidgetId = data != null ?
- data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1) : -1;
- if (appWidgetId < 0) {
+ final int appWidgetId;
+ int widgetId = data != null ? data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1)
+ : -1;
+ if (widgetId < 0) {
+ appWidgetId = pendingAddWidgetId;
+ } else {
+ appWidgetId = widgetId;
+ }
+
+ final int result;
+ final Runnable onComplete;
+ if (appWidgetId < 0 || resultCode == RESULT_CANCELED) {
Log.e(TAG, "Error: appWidgetId (EXTRA_APPWIDGET_ID) was not returned from the \\" +
"widget configuration activity.");
- completeTwoStageWidgetDrop(RESULT_CANCELED, appWidgetId);
- mWorkspace.stripEmptyScreens();
+ result = RESULT_CANCELED;
+ completeTwoStageWidgetDrop(result, appWidgetId);
+ onComplete = new Runnable() {
+ @Override
+ public void run() {
+ exitSpringLoadedDragModeDelayed(false, 0, null);
+ }
+ };
} else {
- completeTwoStageWidgetDrop(resultCode, appWidgetId);
+ result = resultCode;
+ final CellLayout dropLayout =
+ (CellLayout) mWorkspace.getScreenWithId(mPendingAddInfo.screenId);
+ dropLayout.setDropPending(true);
+ onComplete = new Runnable() {
+ @Override
+ public void run() {
+ completeTwoStageWidgetDrop(result, appWidgetId);
+ dropLayout.setDropPending(false);
+ }
+ };
}
+ mWorkspace.removeExtraEmptyScreen(true, onComplete, ON_ACTIVITY_RESULT_ANIMATION_DELAY,
+ false);
return;
}
@@ -770,15 +993,15 @@ public class Launcher extends Activity
if (isWorkspaceLocked()) {
sPendingAddList.add(args);
} else {
- delayExitSpringLoadedMode = completeAdd(args);
+ completeAdd(args);
}
+ mWorkspace.removeExtraEmptyScreen(true, exitSpringLoaded,
+ ON_ACTIVITY_RESULT_ANIMATION_DELAY, false);
} else if (resultCode == RESULT_CANCELED) {
- mWorkspace.stripEmptyScreens();
+ mWorkspace.removeExtraEmptyScreen(true, exitSpringLoaded,
+ ON_ACTIVITY_RESULT_ANIMATION_DELAY, false);
}
mDragLayer.clearAnimatedView();
- // Exit spring loaded mode if necessary after cancelling the configuration of a widget
- exitSpringLoadedDragModeDelayed((resultCode != RESULT_CANCELED), delayExitSpringLoadedMode,
- null);
}
private void completeTwoStageWidgetDrop(final int resultCode, final int appWidgetId) {
@@ -798,25 +1021,19 @@ public class Launcher extends Activity
public void run() {
completeAddAppWidget(appWidgetId, mPendingAddInfo.container,
mPendingAddInfo.screenId, layout, null);
- exitSpringLoadedDragModeDelayed((resultCode != RESULT_CANCELED), false,
- null);
+ exitSpringLoadedDragModeDelayed((resultCode != RESULT_CANCELED),
+ EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT, null);
}
};
} else if (resultCode == RESULT_CANCELED) {
+ mAppWidgetHost.deleteAppWidgetId(appWidgetId);
animationType = Workspace.CANCEL_TWO_STAGE_WIDGET_DROP_ANIMATION;
- onCompleteRunnable = new Runnable() {
- @Override
- public void run() {
- exitSpringLoadedDragModeDelayed((resultCode != RESULT_CANCELED), false,
- null);
- }
- };
}
if (mDragLayer.getAnimatedView() != null) {
mWorkspace.animateWidgetDrop(mPendingAddInfo, cellLayout,
(DragView) mDragLayer.getAnimatedView(), onCompleteRunnable,
animationType, boundWidget, true);
- } else {
+ } else if (onCompleteRunnable != null) {
// The animated view may be null in the case of a rotation during widget configuration
onCompleteRunnable.run();
}
@@ -843,15 +1060,15 @@ public class Launcher extends Activity
}
super.onResume();
- if (settingsChanged()) {
- android.os.Process.killProcess(android.os.Process.myPid());
+ if(isGelIntegrationEnabled() && isGelIntegrationSupported()) {
+ GelIntegrationHelper.getInstance().handleGelResume();
}
// Restore the previous launcher state
if (mOnResumeState == State.WORKSPACE) {
showWorkspace(false);
} else if (mOnResumeState == State.APPS_CUSTOMIZE) {
- showAllApps(false, AppsCustomizePagedView.ContentType.Applications, false);
+ showAllApps(false, mAppsCustomizeContent.getContentType(), false);
}
mOnResumeState = State.NONE;
@@ -862,7 +1079,7 @@ public class Launcher extends Activity
sPausedFromUserAction = false;
if (mRestoring || mOnResumeNeedsLoad) {
mWorkspaceLoading = true;
- mModel.startLoader(true, -1);
+ mModel.startLoader(true, PagedView.INVALID_RESTORE_PAGE);
mRestoring = false;
mOnResumeNeedsLoad = false;
}
@@ -937,6 +1154,29 @@ public class Launcher extends Activity
mWorkspace.updateInteractionForState();
mWorkspace.onResume();
mAppsCustomizeContent.onResume();
+
+ //Close out Fragments
+ Fragment f = getFragmentManager().findFragmentByTag(
+ TransitionEffectsFragment.TRANSITION_EFFECTS_FRAGMENT);
+ if (f != null) {
+ mTransitionEffectsFragment.setEffect();
+ }
+ f = getFragmentManager().findFragmentByTag(
+ DynamicGridSizeFragment.DYNAMIC_GRID_SIZE_FRAGMENT);
+ if (f != null) {
+ mDynamicGridSizeFragment.setSize();
+ mWorkspace.hideOutlines();
+ }
+ Fragment f1 = getFragmentManager().findFragmentByTag(
+ HiddenFolderFragment.HIDDEN_FOLDER_FRAGMENT);
+ if (f1 != null && !mHiddenFolderAuth) {
+ mHiddenFolderFragment.saveHiddenFolderStatus(-1);
+ FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
+ fragmentTransaction
+ .remove(mHiddenFolderFragment).commit();
+ } else {
+ mHiddenFolderAuth = false;
+ }
}
@Override
@@ -954,12 +1194,9 @@ public class Launcher extends Activity
if (mWorkspace.getCustomContentCallbacks() != null) {
mWorkspace.getCustomContentCallbacks().onHide();
}
- }
- protected void onFinishBindingItems() {
- if (mWorkspace != null && hasCustomContentToLeft() && mWorkspace.hasCustomContent()) {
- addCustomContentToLeft();
- }
+ //Reset the OverviewPanel position
+ ((SlidingUpPanelLayout) mOverviewPanel).collapsePane();
}
QSBScroller mQsbScroller = new QSBScroller() {
@@ -969,6 +1206,7 @@ public class Launcher extends Activity
public void setScrollY(int scroll) {
scrollY = scroll;
+ // Be careful of feature check isSearchBarEnabled
if (mWorkspace.isOnOrMovingToCustomContent()) {
mSearchDropTargetBar.setTranslationY(- scrollY);
getQsbBar().setTranslationY(-scrollY);
@@ -978,7 +1216,9 @@ public class Launcher extends Activity
public void resetQSBScroll() {
mSearchDropTargetBar.animate().translationY(0).start();
- getQsbBar().animate().translationY(0).start();
+ if (isSearchBarEnabled()) {
+ getQsbBar().animate().translationY(0).start();
+ }
}
public interface CustomContentCallbacks {
@@ -992,17 +1232,11 @@ public class Launcher extends Activity
public void onScrollProgressChanged(float progress);
}
- protected void startSettings() {
- Intent settings;
- // If we are on CyanogenMod the launcher settings are accessed from system settings.
- if (!getPackageManager().hasSystemFeature("com.cyanogenmod.android")) {
- settings = new Intent().setClass(this, SettingsActivity.class);
- settings.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
- | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
- } else {
- settings = new Intent(android.provider.Settings.ACTION_SETTINGS);
- }
+ protected void startThemeSettings() {
+ Intent settings = new Intent().setClassName(OverviewSettingsPanel.ANDROID_SETTINGS,
+ OverviewSettingsPanel.THEME_SETTINGS);
startActivity(settings);
+
if (mWorkspace.isInOverviewMode()) {
mWorkspace.exitOverviewMode(false);
} else if (mAppsCustomizeContent.isInOverviewMode()) {
@@ -1038,89 +1272,88 @@ public class Launcher extends Activity
mAppsCustomizeContent.setSortMode(AppsCustomizePagedView.SortMode.LaunchCount);
break;
}
+ mOverviewSettingsPanel.notifyDataSetInvalidated();
+ SettingsProvider.putInt(getBaseContext(), SettingsProvider.SETTINGS_UI_DRAWER_SORT_MODE,
+ mAppsCustomizeContent.getSortMode().getValue());
return true;
}
});
popupMenu.show();
}
- public void onClickTransitionEffectButton(View v) {
- AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ public void onClickDynamicGridSizeButton() {
+ FragmentManager fragmentManager = getFragmentManager();
+ FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
- // Load values
- final PagedView pagedView = isAllAppsVisible() ? mAppsCustomizeContent : mWorkspace;
- final PagedView.TransitionEffect oldEffect = pagedView.getTransitionEffect();
- final String oldEffectName = oldEffect != null ? oldEffect.getName() :
- PagedView.TransitionEffect.TRANSITION_EFFECT_NONE;
+ mDynamicGridSizeFragment = new DynamicGridSizeFragment();
+ fragmentTransaction.replace(R.id.launcher, mDynamicGridSizeFragment,
+ DynamicGridSizeFragment.DYNAMIC_GRID_SIZE_FRAGMENT);
+ fragmentTransaction.commit();
+ }
- final String[] titles = getResources().getStringArray(R.array.transition_effect_entries);
- final String[] values = getResources().getStringArray(R.array.transition_effect_values);
+ public void setDynamicGridSize(DeviceProfile.GridSize size) {
+ SettingsProvider.putInt(this,
+ SettingsProvider.SETTINGS_UI_DYNAMIC_GRID_SIZE, size.getValue());
- int selected = -1;
- for (int i = values.length - 1; i >= 0; i--) {
- if (values[i].equals(oldEffectName)) {
- selected = i;
- break;
- }
- }
+ updateDynamicGrid();
- // Create title view with overflow menu
- View customTitle = getLayoutInflater().inflate(R.layout.dialog_title_overflow_menu, null);
- TextView title = (TextView) customTitle.findViewById(android.R.id.title);
- title.setText(R.string.transition_effect_button_text);
+ mOverviewSettingsPanel.notifyDataSetInvalidated();
- View overflowMenu = customTitle.findViewById(R.id.overflow_menu_button);
- overflowMenu.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- onClickTransitionEffectOverflowMenuButton(v);
- }
- });
+ FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
+ fragmentTransaction
+ .setCustomAnimations(0, R.anim.exit_out_right);
+ fragmentTransaction
+ .remove(mDynamicGridSizeFragment).commit();
- builder.setCustomTitle(customTitle);
+ mDarkPanel.setVisibility(View.VISIBLE);
+ ObjectAnimator anim = ObjectAnimator.ofFloat(
+ mDarkPanel, "alpha", 0.3f, 0.0f);
+ anim.start();
+ anim.addListener(mAnimatorListener);
- builder.setSingleChoiceItems(titles, selected, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- String effect = values[which];
- PagedView.TransitionEffect.setFromString(pagedView, effect);
-
- // Show the changes immediately
- final int currentPage = pagedView.getNextPage();
- final int nextPage = currentPage + (currentPage != pagedView.getPageCount() - 1 ? 1 : -1);
- pagedView.snapToPageImmediately(currentPage);
- pagedView.snapToPage(nextPage, new Runnable() {
- @Override
- public void run() {
- pagedView.snapToPage(currentPage);
- }
- });
+ }
- SettingsProvider.get(Launcher.this).edit()
- .putString(!isAllAppsVisible() ?
- SettingsProvider.SETTINGS_UI_HOMESCREEN_SCROLLING_TRANSITION_EFFECT :
- SettingsProvider.SETTINGS_UI_DRAWER_SCROLLING_TRANSITION_EFFECT, effect)
- .commit();
- }
- });
+ public void onClickTransitionEffectButton(View v, final boolean pageOrDrawer) {
+ Bundle bundle = new Bundle();
+ bundle.putBoolean(TransitionEffectsFragment.PAGE_OR_DRAWER_SCROLL_SELECT,
+ pageOrDrawer);
+ FragmentManager fragmentManager = getFragmentManager();
+ FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
- if (isAllAppsVisible()) {
- mAppsCustomizeContent.exitOverviewMode(true);
- } else {
- mWorkspace.exitOverviewMode(true);
- }
+ mTransitionEffectsFragment = new TransitionEffectsFragment();
+ mTransitionEffectsFragment.setArguments(bundle);
+ fragmentTransaction.setCustomAnimations(0, 0);
+ fragmentTransaction.replace(R.id.launcher, mTransitionEffectsFragment,
+ TransitionEffectsFragment.TRANSITION_EFFECTS_FRAGMENT);
+ fragmentTransaction.commit();
+ }
- builder.setPositiveButton(android.R.string.ok, null)
- .setOnDismissListener(new DialogInterface.OnDismissListener() {
- @Override
- public void onDismiss(DialogInterface dialog) {
- mTransitionEffectDialog = null;
- }
- });
- mTransitionEffectDialog = builder.create();
- mTransitionEffectDialog.show();
- mTransitionEffectDialog.setCanceledOnTouchOutside(true);
- mTransitionEffectDialog.getWindow().getDecorView().setAlpha(0.6f);
+ public void setTransitionEffect(boolean pageOrDrawer, String newTransitionEffect) {
+ String mSettingsProviderValue = pageOrDrawer ?
+ SettingsProvider.SETTINGS_UI_DRAWER_SCROLLING_TRANSITION_EFFECT
+ : SettingsProvider.SETTINGS_UI_HOMESCREEN_SCROLLING_TRANSITION_EFFECT;
+ PagedView pagedView = pageOrDrawer ? mAppsCustomizeContent : mWorkspace;
+
+ SettingsProvider
+ .get(getApplicationContext())
+ .edit()
+ .putString(mSettingsProviderValue,
+ newTransitionEffect).commit();
+ TransitionEffect.setFromString(pagedView, newTransitionEffect);
+
+ mOverviewSettingsPanel.notifyDataSetInvalidated();
+
+ FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
+ fragmentTransaction
+ .setCustomAnimations(0, R.anim.exit_out_right);
+ fragmentTransaction
+ .remove(mTransitionEffectsFragment).commit();
+
+ mDarkPanel.setVisibility(View.VISIBLE);
+ ObjectAnimator anim = ObjectAnimator.ofFloat(
+ mDarkPanel, "alpha", 0.3f, 0.0f);
+ anim.start();
+ anim.addListener(mAnimatorListener);
}
public void onClickTransitionEffectOverflowMenuButton(View v) {
@@ -1175,6 +1408,13 @@ public class Launcher extends Activity
popupMenu.show();
}
+ protected boolean hasSettings() {
+ return false;
+ }
+
+ protected void startSettings() {
+ }
+
public interface QSBScroller {
public void setScrollY(int scrollY);
}
@@ -1271,6 +1511,7 @@ public class Launcher extends Activity
*
* @param savedState The previous state.
*/
+ @SuppressWarnings("unchecked")
private void restoreState(Bundle savedState) {
if (savedState == null) {
return;
@@ -1298,6 +1539,7 @@ public class Launcher extends Activity
mPendingAddInfo.spanX = savedState.getInt(RUNTIME_STATE_PENDING_ADD_SPAN_X);
mPendingAddInfo.spanY = savedState.getInt(RUNTIME_STATE_PENDING_ADD_SPAN_Y);
mPendingAddWidgetInfo = savedState.getParcelable(RUNTIME_STATE_PENDING_ADD_WIDGET_INFO);
+ mPendingAddWidgetId = savedState.getInt(RUNTIME_STATE_PENDING_ADD_WIDGET_ID);
mWaitingForResult = true;
mRestoring = true;
}
@@ -1321,6 +1563,8 @@ public class Launcher extends Activity
int currentIndex = savedState.getInt("apps_customize_currentIndex");
mAppsCustomizeContent.restorePageForIndex(currentIndex);
}
+ mItemIdToViewId = (HashMap<Integer, Integer>)
+ savedState.getSerializable(RUNTIME_STATE_VIEW_IDS);
}
/**
@@ -1332,6 +1576,7 @@ public class Launcher extends Activity
mLauncherView = findViewById(R.id.launcher);
mDragLayer = (DragLayer) findViewById(R.id.drag_layer);
mWorkspace = (Workspace) mDragLayer.findViewById(R.id.workspace);
+ mPageIndicators = mDragLayer.findViewById(R.id.page_indicator);
mLauncherView.setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
@@ -1348,78 +1593,11 @@ public class Launcher extends Activity
}
mOverviewPanel = findViewById(R.id.overview_panel);
- mOverviewPanel.setAlpha(0f);
- View widgetButton = findViewById(R.id.widget_button);
- widgetButton.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View arg0) {
- showAllApps(true, AppsCustomizePagedView.ContentType.Widgets, true);
- }
- });
- widgetButton.setOnTouchListener(getHapticFeedbackTouchListener());
-
- View wallpaperButton = findViewById(R.id.wallpaper_button);
- wallpaperButton.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View arg0) {
- startWallpaper();
- }
- });
- wallpaperButton.setOnTouchListener(getHapticFeedbackTouchListener());
-
- View settingsButton = findViewById(R.id.settings_button);
- settingsButton.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View arg0) {
- startSettings();
- }
- });
- settingsButton.setOnTouchListener(getHapticFeedbackTouchListener());
-
- View defaultScreenButton = findViewById(R.id.default_screen_button);
- defaultScreenButton.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View arg0) {
- mWorkspace.onClickDefaultScreenButton();
- }
- });
- defaultScreenButton.setOnTouchListener(getHapticFeedbackTouchListener());
-
- View transitionEffectButton = findViewById(R.id.transition_effect_button);
- transitionEffectButton.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View arg0) {
- onClickTransitionEffectButton(arg0);
- }
- });
- transitionEffectButton.setOnTouchListener(getHapticFeedbackTouchListener());
-
- View iconPackButton = findViewById(R.id.icon_pack_button);
- iconPackButton.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View arg0) {
- IconPackHelper.pickIconPack(Launcher.this, false);
- }
- });
- iconPackButton.setOnTouchListener(getHapticFeedbackTouchListener());
-
- View sortButton = findViewById(R.id.sort_button);
- sortButton.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View arg0) {
- onClickSortModeButton(arg0);
- }
- });
- sortButton.setOnTouchListener(getHapticFeedbackTouchListener());
-
- View filterButton = findViewById(R.id.filter_button);
- filterButton.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
-
- }
- });
- filterButton.setOnTouchListener(getHapticFeedbackTouchListener());
+ mOverviewSettingsPanel = new OverviewSettingsPanel(
+ this, mOverviewPanel);
+ mOverviewSettingsPanel.initializeAdapter();
+ mOverviewSettingsPanel.initializeViews();
+ mDarkPanel = ((SlidingUpPanelLayout) mOverviewPanel).findViewById(R.id.dark_panel);
// Setup the workspace
mWorkspace.setHapticFeedbackEnabled(false);
@@ -1428,7 +1606,8 @@ public class Launcher extends Activity
dragController.addDragListener(mWorkspace);
// Get the search/delete bar
- mSearchDropTargetBar = (SearchDropTargetBar) mDragLayer.findViewById(R.id.qsb_bar);
+ mSearchDropTargetBar = (SearchDropTargetBar)
+ mDragLayer.findViewById(R.id.search_drop_target_bar);
// Setup AppsCustomize
mAppsCustomizeLayout = (AppsCustomizeLayout) findViewById(R.id.apps_customize_pane);
@@ -1494,7 +1673,6 @@ public class Launcher extends Activity
favorite.setCompoundDrawables(null, d, null, null);
favorite.setOnTouchListener(getHapticFeedbackTouchListener());
}
- Utilities.applyTypeface(favorite);
return favorite;
}
@@ -1662,11 +1840,12 @@ public class Launcher extends Activity
if (appWidgetId != -1) {
// Deleting an app widget ID is a void call but writes to disk before returning
// to the caller...
- new Thread("deleteAppWidgetId") {
- public void run() {
+ new AsyncTask<Void, Void, Void>() {
+ public Void doInBackground(Void ... args) {
mAppWidgetHost.deleteAppWidgetId(appWidgetId);
+ return null;
}
- }.start();
+ }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void) null);
}
showOutOfSpaceMessage(isHotseatLayout(layout));
return;
@@ -1722,6 +1901,15 @@ public class Launcher extends Activity
} else if (Intent.ACTION_USER_PRESENT.equals(action)) {
mUserPresent = true;
updateRunning();
+ } else if (ENABLE_DEBUG_INTENTS && DebugIntents.DELETE_DATABASE.equals(action)) {
+ mModel.resetLoadedState(false, true);
+ mModel.startLoader(false, PagedView.INVALID_RESTORE_PAGE,
+ LauncherModel.LOADER_FLAG_CLEAR_WORKSPACE);
+ } else if (ENABLE_DEBUG_INTENTS && DebugIntents.MIGRATE_DATABASE.equals(action)) {
+ mModel.resetLoadedState(false, true);
+ mModel.startLoader(false, PagedView.INVALID_RESTORE_PAGE,
+ LauncherModel.LOADER_FLAG_CLEAR_WORKSPACE
+ | LauncherModel.LOADER_FLAG_MIGRATE_SHORTCUTS);
}
}
};
@@ -1734,6 +1922,10 @@ public class Launcher extends Activity
final IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_USER_PRESENT);
+ if (ENABLE_DEBUG_INTENTS) {
+ filter.addAction(DebugIntents.DELETE_DATABASE);
+ filter.addAction(DebugIntents.MIGRATE_DATABASE);
+ }
registerReceiver(mReceiver, filter);
FirstFrameAnimatorHelper.initializeDrawListener(getWindow().getDecorView());
mAttached = true;
@@ -1869,6 +2061,30 @@ public class Launcher extends Activity
Toast.makeText(this, getString(strId), Toast.LENGTH_SHORT).show();
}
+ public DragLayer getDragLayer() {
+ return mDragLayer;
+ }
+
+ public Workspace getWorkspace() {
+ return mWorkspace;
+ }
+
+ public Hotseat getHotseat() {
+ return mHotseat;
+ }
+
+ public View getDarkPanel() {
+ return mDarkPanel;
+ }
+
+ public View getOverviewPanel() {
+ return mOverviewPanel;
+ }
+
+ public SearchDropTargetBar getSearchBar() {
+ return mSearchDropTargetBar;
+ }
+
public LauncherAppWidgetHost getAppWidgetHost() {
return mAppWidgetHost;
}
@@ -1877,6 +2093,14 @@ public class Launcher extends Activity
return mModel;
}
+ public LauncherClings getLauncherClings() {
+ return mLauncherClings;
+ }
+
+ protected SharedPreferences getSharedPrefs() {
+ return mSharedPrefs;
+ }
+
public void closeSystemDialogs() {
getWindow().closeAllPanels();
@@ -1913,7 +2137,7 @@ public class Launcher extends Activity
// In all these cases, only animate if we're already on home
mWorkspace.exitWidgetResizeMode();
if (alreadyOnHome && mState == State.WORKSPACE && !mWorkspace.isTouchActive() &&
- openFolder == null) {
+ openFolder == null && shouldMoveToDefaultScreenOnHomeIntent()) {
mWorkspace.moveToDefaultScreen(true);
}
@@ -1936,9 +2160,11 @@ public class Launcher extends Activity
}
// Reset the apps customize page
- if (mAppsCustomizeLayout != null) {
+ if (!alreadyOnHome && mAppsCustomizeLayout != null) {
mAppsCustomizeLayout.reset();
}
+
+ onHomeIntent();
}
if (DEBUG_RESUME_TIME) {
@@ -1946,6 +2172,21 @@ public class Launcher extends Activity
}
}
+ /**
+ * Override point for subclasses to prevent movement to the default screen when the home
+ * button is pressed. Used (for example) in GEL, to prevent movement during a search.
+ */
+ protected boolean shouldMoveToDefaultScreenOnHomeIntent() {
+ return true;
+ }
+
+ /**
+ * Override point for subclasses to provide custom behaviour for when a home intent is fired.
+ */
+ protected void onHomeIntent() {
+ // Do nothing
+ }
+
@Override
public void onRestoreInstanceState(Bundle state) {
super.onRestoreInstanceState(state);
@@ -1957,7 +2198,8 @@ public class Launcher extends Activity
@Override
protected void onSaveInstanceState(Bundle outState) {
if (mWorkspace.getChildCount() > 0) {
- outState.putInt(RUNTIME_STATE_CURRENT_SCREEN, mWorkspace.getRestorePage());
+ outState.putInt(RUNTIME_STATE_CURRENT_SCREEN,
+ mWorkspace.getCurrentPageOffsetFromCustomContent());
}
super.onSaveInstanceState(outState);
@@ -1975,6 +2217,7 @@ public class Launcher extends Activity
outState.putInt(RUNTIME_STATE_PENDING_ADD_SPAN_X, mPendingAddInfo.spanX);
outState.putInt(RUNTIME_STATE_PENDING_ADD_SPAN_Y, mPendingAddInfo.spanY);
outState.putParcelable(RUNTIME_STATE_PENDING_ADD_WIDGET_INFO, mPendingAddWidgetInfo);
+ outState.putInt(RUNTIME_STATE_PENDING_ADD_WIDGET_ID, mPendingAddWidgetId);
}
if (mFolderInfo != null && mWaitingForResult) {
@@ -1984,6 +2227,7 @@ public class Launcher extends Activity
// Save the current AppsCustomize tab
if (mAppsCustomizeLayout != null) {
+ AppsCustomizePagedView.ContentType type = mAppsCustomizeContent.getContentType();
String currentTabTag = mAppsCustomizeContent.getContentType().name();
if (currentTabTag != null) {
outState.putString("apps_customize_currentContentType", currentTabTag);
@@ -1991,6 +2235,7 @@ public class Launcher extends Activity
int currentIndex = mAppsCustomizeContent.getSaveInstanceStateIndex();
outState.putInt("apps_customize_currentIndex", currentIndex);
}
+ outState.putSerializable(RUNTIME_STATE_VIEW_IDS, mItemIdToViewId);
}
@Override
@@ -2029,17 +2274,33 @@ public class Launcher extends Activity
mDragLayer.clearAllResizeFrames();
((ViewGroup) mWorkspace.getParent()).removeAllViews();
- mWorkspace.removeAllViews();
+ mWorkspace.removeAllWorkspaceScreens();
mWorkspace = null;
mDragController = null;
LauncherAnimUtils.onDestroyActivity();
+
+ unregisterReceiver(protectedAppsChangedReceiver);
}
public DragController getDragController() {
return mDragController;
}
+ public void validateLockForHiddenFolders(Bundle bundle, FolderIcon info) {
+ // Validate Lock Pattern
+ Intent lockPatternActivity = new Intent();
+ lockPatternActivity.setClassName(
+ "com.android.settings",
+ "com.android.settings.applications.LockPatternActivity");
+ startActivityForResult(lockPatternActivity, REQUEST_LOCK_PATTERN);
+ mHiddenFolderAuth = false;
+
+ mHiddenFolderIcon = info;
+ mHiddenFolderFragment = new HiddenFolderFragment();
+ mHiddenFolderFragment.setArguments(bundle);
+ }
+
@Override
public void startActivityForResult(Intent intent, int requestCode) {
if (requestCode >= 0) mWaitingForResult = true;
@@ -2119,29 +2380,28 @@ public class Launcher extends Activity
}
}
+ public boolean isOnCustomContent() {
+ return mWorkspace.isOnOrMovingToCustomContent();
+ }
+
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
- if (!isAllAppsVisible()) {
+ if (!isOnCustomContent()) {
+ // Close any open folders
+ closeFolder();
+ // Stop resizing any widgets
+ mWorkspace.exitWidgetResizeMode();
if (!mWorkspace.isInOverviewMode()) {
- mWorkspace.enterOverviewMode();
- } else {
- mWorkspace.exitOverviewMode(true);
- }
- } else {
- if (!mAppsCustomizeContent.isInOverviewMode()) {
- mAppsCustomizeContent.enterOverviewMode();
+ // Show the overview mode
+ showOverviewMode(true);
} else {
- mAppsCustomizeContent.exitOverviewMode(true);
+ showWorkspace(true);
}
}
return false;
}
- void enterAllAppsOverviewMode() {
- mAppsCustomizeContent.enterOverviewMode();
- }
-
@Override
public boolean onSearchRequested() {
startSearch(null, false, null, true);
@@ -2153,6 +2413,10 @@ public class Launcher extends Activity
return mWorkspaceLoading || mWaitingForResult;
}
+ public boolean isWorkspaceLoading() {
+ return mWorkspaceLoading;
+ }
+
private void resetAddInfo() {
mPendingAddInfo.container = ItemInfo.NO_ID;
mPendingAddInfo.screenId = -1;
@@ -2162,10 +2426,17 @@ public class Launcher extends Activity
mPendingAddInfo.dropPos = null;
}
- void addAppWidgetImpl(final int appWidgetId, ItemInfo info, AppWidgetHostView boundWidget,
- AppWidgetProviderInfo appWidgetInfo) {
+ void addAppWidgetImpl(final int appWidgetId, final ItemInfo info,
+ final AppWidgetHostView boundWidget, final AppWidgetProviderInfo appWidgetInfo) {
+ addAppWidgetImpl(appWidgetId, info, boundWidget, appWidgetInfo, 0);
+ }
+
+ void addAppWidgetImpl(final int appWidgetId, final ItemInfo info,
+ final AppWidgetHostView boundWidget, final AppWidgetProviderInfo appWidgetInfo, int
+ delay) {
if (appWidgetInfo.configure != null) {
mPendingAddWidgetInfo = appWidgetInfo;
+ mPendingAddWidgetId = appWidgetId;
// Launch over to configure widget, if needed
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE);
@@ -2174,10 +2445,17 @@ public class Launcher extends Activity
Utilities.startActivityForResultSafely(this, intent, REQUEST_CREATE_APPWIDGET);
} else {
// Otherwise just add it
+ Runnable onComplete = new Runnable() {
+ @Override
+ public void run() {
+ // Exit spring loaded mode if necessary after adding the widget
+ exitSpringLoadedDragModeDelayed(true, EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT,
+ null);
+ }
+ };
completeAddAppWidget(appWidgetId, info.container, info.screenId, boundWidget,
appWidgetInfo);
- // Exit spring loaded mode if necessary after adding the widget
- exitSpringLoadedDragModeDelayed(true, false, null);
+ mWorkspace.removeExtraEmptyScreen(true, onComplete, delay, false);
}
}
@@ -2327,7 +2605,7 @@ public class Launcher extends Activity
}
protected ComponentName getWallpaperPickerComponent() {
- return new ComponentName(WALLPAPER_PICKER_PACKAGE, WALLPAPER_PICKER_ACTIVITY);
+ return new ComponentName(getPackageName(), LauncherWallpaperPickerActivity.class.getName());
}
/**
@@ -2365,10 +2643,15 @@ public class Launcher extends Activity
@Override
public void onBackPressed() {
+ Fragment f1 = getFragmentManager().findFragmentByTag(
+ HiddenFolderFragment.HIDDEN_FOLDER_FRAGMENT);
+ if (f1 != null) {
+ mHiddenFolderFragment.saveHiddenFolderStatus(-1);
+ FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
+ fragmentTransaction
+ .remove(mHiddenFolderFragment).commit();
+ }
if (isAllAppsVisible()) {
- if (isClingsEnabled()) {
- dismissAllAppsCling(null);
- }
if (mAppsCustomizeContent.isInOverviewMode()) {
mAppsCustomizeContent.exitOverviewMode(true);
} else {
@@ -2380,7 +2663,17 @@ public class Launcher extends Activity
}
}
} else if (mWorkspace.isInOverviewMode()) {
- mWorkspace.exitOverviewMode(true);
+ Fragment f = getFragmentManager().findFragmentByTag(
+ TransitionEffectsFragment.TRANSITION_EFFECTS_FRAGMENT);
+ Fragment f2 = getFragmentManager().findFragmentByTag(
+ DynamicGridSizeFragment.DYNAMIC_GRID_SIZE_FRAGMENT);
+ if (f != null) {
+ mTransitionEffectsFragment.setEffect();
+ } else if (f2 != null) {
+ mDynamicGridSizeFragment.setSize();
+ } else {
+ mWorkspace.exitOverviewMode(true);
+ }
} else if (mWorkspace.getOpenFolder() != null) {
Folder openFolder = mWorkspace.getOpenFolder();
if (openFolder.isEditingName()) {
@@ -2454,7 +2747,7 @@ public class Launcher extends Activity
final String shortcutClass = intent.getComponent().getClassName();
if (shortcutClass.equals(WidgetAdder.class.getName())) {
- showAllApps(true, AppsCustomizePagedView.ContentType.Widgets, true);
+ onClickAddWidgetButton();
return;
} else if (shortcutClass.equals(MemoryDumpActivity.class.getName())) {
MemoryDumpActivity.startDump(this);
@@ -2504,8 +2797,12 @@ public class Launcher extends Activity
* @param v The view that was clicked.
*/
public void onClickSearchButton(View v) {
- v.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
+ if (hasCustomSearchSupport()) {
+ requestSearch(Home.MODE_SEARCH_TEXT);
+ return;
+ }
+ v.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
onSearchRequested();
}
@@ -2515,8 +2812,12 @@ public class Launcher extends Activity
* @param v The view that was clicked.
*/
public void onClickVoiceButton(View v) {
- v.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
+ if (hasCustomSearchSupport()) {
+ requestSearch(Home.MODE_SEARCH_VOICE);
+ return;
+ }
+ v.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
startVoice();
}
@@ -2545,7 +2846,15 @@ public class Launcher extends Activity
* @param v The view that was clicked.
*/
public void onClickAllAppsButton(View v) {
- showAllApps(true, AppsCustomizePagedView.ContentType.Applications, true);
+ showAllApps(true, AppsCustomizePagedView.ContentType.Applications, false);
+ }
+
+ /**
+ * Event handler for the (Add) Widgets button that appears after a long press
+ * on the home screen.
+ */
+ protected void onClickAddWidgetButton() {
+ showAllApps(true, AppsCustomizePagedView.ContentType.Widgets, true);
}
public void onTouchDownAllAppsButton(View v) {
@@ -2592,9 +2901,10 @@ public class Launcher extends Activity
void startApplicationDetailsActivity(ComponentName componentName) {
String packageName = componentName.getPackageName();
- Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
+ Intent intent = new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
Uri.fromParts("package", packageName, null));
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK |
+ Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
startActivitySafely(null, intent, "startApplicationDetailsActivity");
}
@@ -2804,6 +3114,11 @@ public class Launcher extends Activity
Folder folder = folderIcon.getFolder();
FolderInfo info = folder.mInfo;
+ if (info.hidden) {
+ folder.startHiddenFolderManager();
+ return;
+ }
+
info.opened = true;
// Just verify that the folder hasn't already been added to the DragLayer.
@@ -2825,7 +3140,7 @@ public class Launcher extends Activity
}
public void closeFolder() {
- Folder folder = mWorkspace.getOpenFolder();
+ Folder folder = mWorkspace != null ? mWorkspace.getOpenFolder() : null;
if (folder != null) {
if (folder.isEditingName()) {
folder.dismissEditingName();
@@ -2833,7 +3148,7 @@ public class Launcher extends Activity
closeFolder(folder);
// Dismiss the folder cling
- dismissFolderCling(null);
+ mLauncherClings.dismissFolderCling(null);
}
}
@@ -2883,7 +3198,8 @@ public class Launcher extends Activity
// The hotseat touch handling does not go through Workspace, and we always allow long press
// on hotseat items.
final View itemUnderLongClick = longClickCellInfo.cell;
- boolean allowLongPress = isHotseatLayout(v) || mWorkspace.allowLongPress();
+ final boolean inHotseat = isHotseatLayout(v);
+ boolean allowLongPress = inHotseat || mWorkspace.allowLongPress();
if (allowLongPress && !mDragController.isDragging()) {
if (itemUnderLongClick == null) {
// User long pressed on empty space
@@ -2909,15 +3225,6 @@ public class Launcher extends Activity
return mHotseat != null && layout != null &&
(layout instanceof CellLayout) && (layout == mHotseat.getLayout());
}
- Hotseat getHotseat() {
- return mHotseat;
- }
- View getOverviewPanel() {
- return mOverviewPanel;
- }
- SearchDropTargetBar getSearchBar() {
- return mSearchDropTargetBar;
- }
/**
* Returns the CellLayout of the specified container at the specified screen.
@@ -2934,39 +3241,12 @@ public class Launcher extends Activity
}
}
- protected Workspace getWorkspace() {
- return mWorkspace;
+ public AppsCustomizePagedView getAppsCustomizeContent() {
+ return mAppsCustomizeContent;
}
public void updateOverviewPanel() {
- View defaultScreenButton = mOverviewPanel.findViewById(R.id.default_screen_button);
- View transitionEffectButton = mOverviewPanel.findViewById(R.id.transition_effect_button);
- View widgetButton = mOverviewPanel.findViewById(R.id.widget_button);
- View wallpaperButton = mOverviewPanel.findViewById(R.id.wallpaper_button);
- View sortButton = mOverviewPanel.findViewById(R.id.sort_button);
- View filterButton = mOverviewPanel.findViewById(R.id.filter_button);
- View iconPackButton = findViewById(R.id.icon_pack_button);
-
- PagedView pagedView = !isAllAppsVisible() ? mWorkspace : mAppsCustomizeContent;
-
- defaultScreenButton.setVisibility((!isAllAppsVisible() && pagedView.getPageCount() > 1) ? View.VISIBLE : View.GONE);
- transitionEffectButton.setVisibility(pagedView.getPageCount() > 1 ? View.VISIBLE : View.GONE);
- widgetButton.setVisibility(!isAllAppsVisible() ? View.VISIBLE : View.GONE);
- wallpaperButton.setVisibility(!isAllAppsVisible() ? View.VISIBLE : View.GONE);
- sortButton.setVisibility(isAllAppsVisible() ? View.VISIBLE : View.GONE);
- // TODO: implement filtering
- // filterButton.setVisibility(isAllAppsVisible() ? View.VISIBLE : View.GONE);
- filterButton.setVisibility(View.GONE);
-
- boolean isVisible = !isAllAppsVisible();
- if (isVisible) {
- int numIconPacks = IconPackHelper.getSupportedPackages(this).size();
- isVisible = numIconPacks > 0;
- }
- iconPackButton.setVisibility(isVisible ? View.VISIBLE : View.GONE);
-
- // Make sure overview panel is drawn above apps customize
- mOverviewPanel.bringToFront();
+ mOverviewSettingsPanel.update();
}
public boolean isAllAppsVisible() {
@@ -3077,23 +3357,6 @@ public class Launcher extends Activity
AppsCustomizePagedView.ContentType contentType = mAppsCustomizeContent.getContentType();
showAppsCustomizeHelper(animated, springLoaded, contentType);
}
-
- public void showAllAppsCling() {
- if (isClingsEnabled() &&
- !mSharedPrefs.getBoolean(Cling.ALL_APPS_CLING_DISMISSED_KEY, false) &&
- !skipCustomClingIfNoAccounts() ) {
- Cling cling = (Cling) findViewById(R.id.all_apps_cling);
- View pageIndicator = mAppsCustomizeLayout.findViewById(R.id.page_indicator);
- cling.setPunchThroughForView(pageIndicator);
- if (cling != null) {
- cling.bringToFront();
- }
- initCling(R.id.all_apps_cling, 0, true, true);
- } else {
- removeCling(R.id.all_apps_cling);
- }
- }
-
private void showAppsCustomizeHelper(final boolean animated, final boolean springLoaded,
final AppsCustomizePagedView.ContentType contentType) {
if (mStateAnimation != null) {
@@ -3116,8 +3379,9 @@ public class Launcher extends Activity
// Shrink workspaces away if going to AppsCustomize from workspace
Animator workspaceAnim =
mWorkspace.getChangeStateAnimation(Workspace.State.SMALL, animated);
- if (!AppsCustomizePagedView.DISABLE_ALL_APPS) {
- // Set the content type for the all apps space
+ if (!LauncherAppState.isDisableAllApps()
+ || contentType == AppsCustomizePagedView.ContentType.Widgets) {
+ // Set the content type for the all apps/widgets space
mAppsCustomizeContent.setContentType(contentType);
}
@@ -3173,10 +3437,6 @@ public class Launcher extends Activity
if (mSearchDropTargetBar != null) {
mSearchDropTargetBar.hideSearchBar(false);
}
-
- if (contentType == AppsCustomizePagedView.ContentType.Applications) {
- showAllAppsCling();
- }
}
});
@@ -3304,7 +3564,7 @@ public class Launcher extends Activity
dispatchOnLauncherTransitionPrepare(fromView, animated, true);
dispatchOnLauncherTransitionPrepare(toView, animated, true);
- mAppsCustomizeContent.pauseScrolling();
+ mAppsCustomizeContent.stopScrolling();
mStateAnimation.addListener(new AnimatorListenerAdapter() {
@Override
@@ -3316,7 +3576,6 @@ public class Launcher extends Activity
onCompleteRunnable.run();
}
mAppsCustomizeContent.updateCurrentPageScroll();
- mAppsCustomizeContent.resumeScrolling();
}
});
@@ -3433,7 +3692,7 @@ public class Launcher extends Activity
}
}
- void exitSpringLoadedDragModeDelayed(final boolean successfulDrop, boolean extendedDelay,
+ void exitSpringLoadedDragModeDelayed(final boolean successfulDrop, int delay,
final Runnable onCompleteRunnable) {
if (mState != State.APPS_CUSTOMIZE_SPRING_LOADED) return;
@@ -3450,9 +3709,8 @@ public class Launcher extends Activity
exitSpringLoadedDragMode();
}
}
- }, (extendedDelay ?
- EXIT_SPRINGLOADED_MODE_LONG_TIMEOUT :
- EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT));
+ }, delay);
+
}
void exitSpringLoadedDragMode() {
@@ -3626,11 +3884,25 @@ public class Launcher extends Activity
}
public View getQsbBar() {
- if (mQsbBar == null) {
- mQsbBar = mInflater.inflate(R.layout.search_bar, mSearchDropTargetBar, false);
- mSearchDropTargetBar.addView(mQsbBar);
+ if (mQsb == null) {
+ mQsb = mInflater.inflate(R.layout.qsb, mSearchDropTargetBar, false);
+ mSearchDropTargetBar.addView(mQsb);
+ }
+ return mQsb;
+ }
+
+ public ImageView getQsbBarSearchButton() {
+ if (mQsbBarSearch == null && getQsbBar() != null) {
+ return (ImageView) getQsbBar().findViewById(R.id.search_button);
}
- return mQsbBar;
+ return mQsbBarSearch;
+ }
+
+ public ImageView getQsbBarVoiceButton() {
+ if (mQsbBarVoice == null && getQsbBar() != null) {
+ return (ImageView) getQsbBar().findViewById(R.id.voice_button);
+ }
+ return mQsbBarVoice;
}
protected boolean updateGlobalSearchIcon() {
@@ -3887,14 +4159,18 @@ public class Launcher extends Activity
// Create the custom content page (this call updates mDefaultScreen which calls
// setCurrentPage() so ensure that all pages are added before calling this).
- // The actual content of the custom page will be added during onFinishBindingItems().
- if (!mWorkspace.hasCustomContent() && hasCustomContentToLeft()) {
- mWorkspace.createCustomContentPage();
+ if (hasCustomContentToLeft()) {
+ mWorkspace.createCustomContentContainer();
+ populateCustomContentContainer();
}
}
@Override
public void bindAddScreens(ArrayList<Long> orderedScreenIds) {
+ // Log to disk
+ Launcher.addDumpLog(TAG, "11683562 - bindAddScreens()", true);
+ Launcher.addDumpLog(TAG, "11683562 - orderedScreenIds: " +
+ TextUtils.join(", ", orderedScreenIds), true);
int count = orderedScreenIds.size();
for (int i = 0; i < count; i++) {
mWorkspace.insertNewWorkspaceScreenBeforeEmptyScreen(orderedScreenIds.get(i));
@@ -3939,23 +4215,25 @@ public class Launcher extends Activity
}
// Add the new screens
- bindAddScreens(newScreens);
+ if (newScreens != null) {
+ bindAddScreens(newScreens);
+ }
// We add the items without animation on non-visible pages, and with
// animations on the new page (which we will try and snap to).
- if (!addNotAnimated.isEmpty()) {
+ if (addNotAnimated != null && !addNotAnimated.isEmpty()) {
bindItems(addNotAnimated, 0,
addNotAnimated.size(), false);
}
- if (!addAnimated.isEmpty()) {
+ if (addAnimated != null && !addAnimated.isEmpty()) {
bindItems(addAnimated, 0,
addAnimated.size(), true);
}
// Remove the extra empty screen
- mWorkspace.removeExtraEmptyScreens();
+ mWorkspace.removeExtraEmptyScreen(false, null);
- if (!AppsCustomizePagedView.DISABLE_ALL_APPS &&
+ if (!LauncherAppState.isDisableAllApps() &&
addedApps != null && mAppsCustomizeContent != null) {
mAppsCustomizeContent.addApps(addedApps);
}
@@ -4053,9 +4331,11 @@ public class Launcher extends Activity
// when we are loading right after we return to launcher.
mWorkspace.postDelayed(new Runnable() {
public void run() {
- mWorkspace.snapToPage(newScreenIndex);
- mWorkspace.postDelayed(startBounceAnimRunnable,
- NEW_APPS_ANIMATION_DELAY);
+ if (mWorkspace != null) {
+ mWorkspace.snapToPage(newScreenIndex);
+ mWorkspace.postDelayed(startBounceAnimRunnable,
+ NEW_APPS_ANIMATION_DELAY);
+ }
}
}, NEW_APPS_PAGE_MOVE_DELAY);
} else {
@@ -4165,13 +4445,6 @@ public class Launcher extends Activity
mWorkspace.getUniqueComponents(true, null);
mIntentsOnWorkspaceFromUpgradePath = mWorkspace.getUniqueComponents(true, null);
}
-
- mWorkspace.post(new Runnable() {
- @Override
- public void run() {
- onFinishBindingItems();
- }
- });
}
private boolean canRunNewAppsAnimation() {
@@ -4190,6 +4463,16 @@ public class Launcher extends Activity
return bounceAnim;
}
+ public boolean useVerticalBarLayout() {
+ return LauncherAppState.getInstance().getDynamicGrid().
+ getDeviceProfile().isVerticalBarLayout();
+ }
+
+ protected Rect getSearchBarBounds() {
+ return LauncherAppState.getInstance().getDynamicGrid().
+ getDeviceProfile().getSearchBarBounds();
+ }
+
@Override
public void bindSearchablesChanged() {
boolean searchVisible = updateGlobalSearchIcon();
@@ -4205,7 +4488,7 @@ public class Launcher extends Activity
* Implementation of the method from LauncherModel.Callbacks.
*/
public void bindAllApplications(final ArrayList<AppInfo> apps) {
- if (AppsCustomizePagedView.DISABLE_ALL_APPS) {
+ if (LauncherAppState.isDisableAllApps()) {
if (mIntentsOnWorkspaceFromUpgradePath != null) {
if (LauncherModel.UPGRADE_USE_MORE_APPS_FOLDER) {
getHotseat().addAllAppsFolder(mIconCache, apps,
@@ -4213,9 +4496,15 @@ public class Launcher extends Activity
}
mIntentsOnWorkspaceFromUpgradePath = null;
}
+ if (mAppsCustomizeContent != null) {
+ mAppsCustomizeContent.onPackagesUpdated(
+ LauncherModel.getSortedWidgetsAndShortcuts(this));
+ }
} else {
if (mAppsCustomizeContent != null) {
mAppsCustomizeContent.setApps(apps);
+ mAppsCustomizeContent.onPackagesUpdated(
+ LauncherModel.getSortedWidgetsAndShortcuts(this));
}
}
}
@@ -4239,7 +4528,7 @@ public class Launcher extends Activity
mWorkspace.updateShortcuts(apps);
}
- if (!AppsCustomizePagedView.DISABLE_ALL_APPS &&
+ if (!LauncherAppState.isDisableAllApps() &&
mAppsCustomizeContent != null) {
mAppsCustomizeContent.updateApps(apps);
}
@@ -4255,27 +4544,28 @@ public class Launcher extends Activity
* Implementation of the method from LauncherModel.Callbacks.
*/
public void bindComponentsRemoved(final ArrayList<String> packageNames,
- final ArrayList<AppInfo> appInfos,
- final boolean packageRemoved) {
+ final ArrayList<AppInfo> appInfos) {
Runnable r = new Runnable() {
public void run() {
- bindComponentsRemoved(packageNames, appInfos, packageRemoved);
+ bindComponentsRemoved(packageNames, appInfos);
}
};
if (waitUntilResume(r)) {
return;
}
- if (packageRemoved) {
+ if (!packageNames.isEmpty()) {
mWorkspace.removeItemsByPackageName(packageNames);
- } else {
+ }
+ if (!appInfos.isEmpty()) {
mWorkspace.removeItemsByApplicationInfo(appInfos);
}
// Notify the drag controller
- mDragController.onAppsRemoved(appInfos, this);
+ mDragController.onAppsRemoved(packageNames, appInfos);
- if (!AppsCustomizePagedView.DISABLE_ALL_APPS &&
+ // Update AllApps
+ if (!LauncherAppState.isDisableAllApps() &&
mAppsCustomizeContent != null) {
mAppsCustomizeContent.removeApps(appInfos);
}
@@ -4291,7 +4581,6 @@ public class Launcher extends Activity
mWidgetsAndShortcuts = null;
}
};
-
public void bindPackagesUpdated(final ArrayList<Object> widgetsAndShortcuts) {
if (waitUntilResume(mBindPackagesUpdatedRunnable, true)) {
mWidgetsAndShortcuts = widgetsAndShortcuts;
@@ -4299,8 +4588,7 @@ public class Launcher extends Activity
}
// Update the widgets pane
- if (!AppsCustomizePagedView.DISABLE_ALL_APPS &&
- mAppsCustomizeContent != null) {
+ if (mAppsCustomizeContent != null) {
mAppsCustomizeContent.onPackagesUpdated(widgetsAndShortcuts);
}
}
@@ -4362,202 +4650,27 @@ public class Launcher extends Activity
}
}
- /* Cling related */
- private boolean isClingsEnabled() {
- if (DISABLE_CLINGS) {
- return false;
- }
-
- // disable clings when running in a test harness
- if(ActivityManager.isRunningInTestHarness()) return false;
-
- // Disable clings for accessibility when explore by touch is enabled
- final AccessibilityManager a11yManager = (AccessibilityManager) getSystemService(
- ACCESSIBILITY_SERVICE);
- if (a11yManager.isTouchExplorationEnabled()) {
- return false;
- }
-
- // Restricted secondary users (child mode) will potentially have very few apps
- // seeded when they start up for the first time. Clings won't work well with that
-// boolean supportsLimitedUsers =
-// android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2;
-// Account[] accounts = AccountManager.get(this).getAccounts();
-// if (supportsLimitedUsers && accounts.length == 0) {
-// UserManager um = (UserManager) getSystemService(Context.USER_SERVICE);
-// Bundle restrictions = um.getUserRestrictions();
-// if (restrictions.getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS, false)) {
-// return false;
-// }
-// }
- return true;
- }
-
- private Cling initCling(int clingId, int scrimId, boolean animate,
- boolean dimNavBarVisibilty) {
- Cling cling = (Cling) findViewById(clingId);
- View scrim = null;
- if (scrimId > 0) {
- scrim = findViewById(R.id.cling_scrim);
- }
- if (cling != null) {
- cling.init(this, scrim);
- cling.show(animate, SHOW_CLING_DURATION);
-
- if (dimNavBarVisibilty) {
- cling.setSystemUiVisibility(cling.getSystemUiVisibility() |
- View.SYSTEM_UI_FLAG_LOW_PROFILE);
- }
- }
- return cling;
- }
-
- private void dismissCling(final Cling cling, final Runnable postAnimationCb,
- final String flag, int duration, boolean restoreNavBarVisibilty) {
- // To catch cases where siblings of top-level views are made invisible, just check whether
- // the cling is directly set to GONE before dismissing it.
- if (cling != null && cling.getVisibility() != View.GONE) {
- final Runnable cleanUpClingCb = new Runnable() {
- public void run() {
- cling.cleanup();
- // We should update the shared preferences on a background thread
- new Thread("dismissClingThread") {
- public void run() {
- SharedPreferences.Editor editor = mSharedPrefs.edit();
- editor.putBoolean(flag, true);
- editor.commit();
- }
- }.start();
- if (postAnimationCb != null) {
- postAnimationCb.run();
- }
- }
- };
- if (duration <= 0) {
- cleanUpClingCb.run();
- } else {
- cling.hide(duration, cleanUpClingCb);
- }
- mHideFromAccessibilityHelper.restoreImportantForAccessibility(mDragLayer);
-
- if (restoreNavBarVisibilty) {
- cling.setSystemUiVisibility(cling.getSystemUiVisibility() &
- ~View.SYSTEM_UI_FLAG_LOW_PROFILE);
- }
- }
- }
-
- private void removeCling(int id) {
- final View cling = findViewById(id);
- if (cling != null) {
- final ViewGroup parent = (ViewGroup) cling.getParent();
- parent.post(new Runnable() {
- @Override
- public void run() {
- parent.removeView(cling);
- }
- });
- mHideFromAccessibilityHelper.restoreImportantForAccessibility(mDragLayer);
- }
- }
-
- private boolean skipCustomClingIfNoAccounts() {
- Cling cling = (Cling) findViewById(R.id.workspace_cling);
- boolean customCling = cling.getDrawIdentifier().equals("workspace_custom");
- if (customCling) {
- AccountManager am = AccountManager.get(this);
- if (am == null) return false;
- Account[] accounts = am.getAccountsByType("com.google");
- return accounts.length == 0;
- }
- return false;
- }
-
- public void updateCustomContentHintVisibility() {
- Cling cling = (Cling) findViewById(R.id.first_run_cling);
- String ccHintStr = getFirstRunCustomContentHint();
-
- if (mWorkspace.hasCustomContent()) {
- // Show the custom content hint if ccHintStr is not empty
- if (cling != null) {
- setCustomContentHintVisibility(cling, ccHintStr, true, true);
- }
- } else {
- // Hide the custom content hint
- if (cling != null) {
- setCustomContentHintVisibility(cling, ccHintStr, false, true);
- }
- }
+ /**
+ * Called when the SearchBar hint should be changed.
+ *
+ * @param hint the hint to be displayed in the search bar.
+ */
+ protected void onSearchBarHintChanged(String hint) {
+ mLauncherClings.updateSearchBarHint(hint);
}
- private void setCustomContentHintVisibility(Cling cling, String ccHintStr, boolean visible,
- boolean animate) {
- final TextView ccHint = (TextView) cling.findViewById(R.id.custom_content_hint);
- if (ccHint != null) {
- if (visible && !ccHintStr.isEmpty()) {
- ccHint.setText(ccHintStr);
- ccHint.setVisibility(View.VISIBLE);
- if (animate) {
- ccHint.setAlpha(0f);
- ccHint.animate().alpha(1f)
- .setDuration(SHOW_CLING_DURATION)
- .start();
- } else {
- ccHint.setAlpha(1f);
- }
+ protected boolean isLauncherPreinstalled() {
+ PackageManager pm = getPackageManager();
+ try {
+ ApplicationInfo ai = pm.getApplicationInfo(getComponentName().getPackageName(), 0);
+ if ((ai.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
+ return true;
} else {
- if (animate) {
- ccHint.animate().alpha(0f)
- .setDuration(SHOW_CLING_DURATION)
- .setListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- ccHint.setVisibility(View.GONE);
- }
- })
- .start();
- } else {
- ccHint.setAlpha(0f);
- ccHint.setVisibility(View.GONE);
- }
+ return false;
}
- }
- }
-
- public void showFirstRunCling() {
- if (isClingsEnabled() &&
- !mSharedPrefs.getBoolean(Cling.FIRST_RUN_CLING_DISMISSED_KEY, false) &&
- !skipCustomClingIfNoAccounts() ) {
- // If we're not using the default workspace layout, replace workspace cling
- // with a custom workspace cling (usually specified in an overlay)
- // For now, only do this on tablets
- if (!DISABLE_CUSTOM_CLINGS) {
- if (mSharedPrefs.getInt(LauncherProvider.DEFAULT_WORKSPACE_RESOURCE_ID, 0) != 0 &&
- getResources().getBoolean(R.bool.config_useCustomClings)) {
- // Use a custom cling
- View cling = findViewById(R.id.workspace_cling);
- ViewGroup clingParent = (ViewGroup) cling.getParent();
- int clingIndex = clingParent.indexOfChild(cling);
- clingParent.removeViewAt(clingIndex);
- View customCling = mInflater.inflate(R.layout.custom_workspace_cling, clingParent, false);
- clingParent.addView(customCling, clingIndex);
- customCling.setId(R.id.workspace_cling);
- }
- }
- Cling cling = (Cling) findViewById(R.id.first_run_cling);
- if (cling != null) {
- String sbHintStr = getFirstRunClingSearchBarHint();
- String ccHintStr = getFirstRunCustomContentHint();
- if (!sbHintStr.isEmpty()) {
- TextView sbHint = (TextView) cling.findViewById(R.id.search_bar_hint);
- sbHint.setText(sbHintStr);
- sbHint.setVisibility(View.VISIBLE);
- }
- setCustomContentHintVisibility(cling, ccHintStr, true, false);
- }
- initCling(R.id.first_run_cling, 0, false, true);
- } else {
- removeCling(R.id.first_run_cling);
+ } catch (NameNotFoundException e) {
+ e.printStackTrace();
+ return false;
}
}
@@ -4583,83 +4696,79 @@ public class Launcher extends Activity
return "";
}
- public void showFirstRunWorkspaceCling() {
- // Enable the clings only if they have not been dismissed before
- if (isClingsEnabled() &&
- !mSharedPrefs.getBoolean(Cling.WORKSPACE_CLING_DISMISSED_KEY, false)) {
- Cling c = initCling(R.id.workspace_cling, 0, false, true);
+ public void dismissFirstRunCling(View v) {
+ mLauncherClings.dismissFirstRunCling(v);
+ }
+ public void dismissMigrationClingCopyApps(View v) {
+ mLauncherClings.dismissMigrationClingCopyApps(v);
+ }
+ public void dismissMigrationClingUseDefault(View v) {
+ mLauncherClings.dismissMigrationClingUseDefault(v);
+ }
+ public void dismissMigrationWorkspaceCling(View v) {
+ mLauncherClings.dismissMigrationWorkspaceCling(v);
+ }
+ public void dismissWorkspaceCling(View v) {
+ mLauncherClings.dismissWorkspaceCling(v);
+ }
+ public void dismissFolderCling(View v) {
+ mLauncherClings.dismissFolderCling(v);
+ }
- // Set the focused hotseat app if there is one
- c.setFocusedHotseatApp(getFirstRunFocusedHotseatAppDrawableId(),
- getFirstRunFocusedHotseatAppRank(),
- getFirstRunFocusedHotseatAppComponentName(),
- getFirstRunFocusedHotseatAppBubbleTitle(),
- getFirstRunFocusedHotseatAppBubbleDescription());
- } else {
- removeCling(R.id.workspace_cling);
- }
+ private boolean shouldRunFirstRunActivity() {
+ return !ActivityManager.isRunningInTestHarness() &&
+ !mSharedPrefs.getBoolean(FIRST_RUN_ACTIVITY_DISPLAYED, false);
}
- public Cling showFirstRunFoldersCling() {
- // Enable the clings only if they have not been dismissed before
- if (isClingsEnabled() &&
- !mSharedPrefs.getBoolean(Cling.FOLDER_CLING_DISMISSED_KEY, false)) {
- Cling cling = initCling(R.id.folder_cling, R.id.cling_scrim,
- true, true);
- return cling;
- } else {
- removeCling(R.id.folder_cling);
- return null;
+
+ public void showFirstRunActivity() {
+ if (shouldRunFirstRunActivity() &&
+ hasFirstRunActivity()) {
+ Intent firstRunIntent = getFirstRunActivity();
+ if (firstRunIntent != null) {
+ startActivity(firstRunIntent);
+ markFirstRunActivityShown();
+ }
}
}
- protected SharedPreferences getSharedPrefs() {
- return mSharedPrefs;
+
+ private void markFirstRunActivityShown() {
+ SharedPreferences.Editor editor = mSharedPrefs.edit();
+ editor.putBoolean(FIRST_RUN_ACTIVITY_DISPLAYED, true);
+ editor.apply();
}
- public boolean isFolderClingVisible() {
- Cling cling = (Cling) findViewById(R.id.folder_cling);
- if (cling != null) {
- return cling.getVisibility() == View.VISIBLE;
- }
- return false;
+
+ void showWorkspaceSearchAndHotseat() {
+ if (mWorkspace != null) mWorkspace.setAlpha(1f);
+ if (mHotseat != null) mHotseat.setAlpha(1f);
+ if (mPageIndicators != null) mPageIndicators.setAlpha(1f);
+ if (mSearchDropTargetBar != null) mSearchDropTargetBar.showSearchBar(false);
}
- public void dismissFirstRunCling(View v) {
- Cling cling = (Cling) findViewById(R.id.first_run_cling);
- Runnable cb = new Runnable() {
- public void run() {
- // Show the workspace cling next
- showFirstRunWorkspaceCling();
- }
- };
- dismissCling(cling, cb, Cling.FIRST_RUN_CLING_DISMISSED_KEY,
- DISMISS_CLING_DURATION, false);
- // Fade out the search bar for the workspace cling coming up
- mSearchDropTargetBar.hideSearchBar(true);
+ void hideWorkspaceSearchAndHotseat() {
+ if (mWorkspace != null) mWorkspace.setAlpha(0f);
+ if (mHotseat != null) mHotseat.setAlpha(0f);
+ if (mPageIndicators != null) mPageIndicators.setAlpha(0f);
+ if (mSearchDropTargetBar != null) mSearchDropTargetBar.hideSearchBar(false);
}
- public void dismissWorkspaceCling(View v) {
- Cling cling = (Cling) findViewById(R.id.workspace_cling);
- Runnable cb = null;
- if (v == null) {
- cb = new Runnable() {
- public void run() {
- mWorkspace.enterOverviewMode();
- }
- };
- }
- dismissCling(cling, cb, Cling.WORKSPACE_CLING_DISMISSED_KEY,
- DISMISS_CLING_DURATION, true);
- // Fade in the search bar
- mSearchDropTargetBar.showSearchBar(true);
+
+ public ItemInfo createAppDragInfo(Intent appLaunchIntent) {
+ ResolveInfo ri = getPackageManager().resolveActivity(appLaunchIntent, 0);
+ if (ri == null) {
+ return null;
+ }
+ return new AppInfo(getPackageManager(), ri, mIconCache, null);
}
- public void dismissFolderCling(View v) {
- Cling cling = (Cling) findViewById(R.id.folder_cling);
- dismissCling(cling, null, Cling.FOLDER_CLING_DISMISSED_KEY,
- DISMISS_CLING_DURATION, true);
+
+ public ItemInfo createShortcutDragInfo(Intent shortcutIntent, CharSequence caption,
+ Bitmap icon) {
+ return new ShortcutInfo(shortcutIntent, caption, icon);
}
- public void dismissAllAppsCling(View v) {
- Cling cling = (Cling) findViewById(R.id.all_apps_cling);
- dismissCling(cling, null, Cling.ALL_APPS_CLING_DISMISSED_KEY,
- DISMISS_CLING_DURATION, true);
+
+ public void startDrag(View dragView, ItemInfo dragInfo, DragSource source) {
+ dragView.setTag(dragInfo);
+ mWorkspace.onDragStartedWithItem(dragView);
+ mWorkspace.beginDragShared(dragView, source);
}
/**
@@ -4725,22 +4834,30 @@ public class Launcher extends Activity
}
public static void addDumpLog(String tag, String log, boolean debugLog) {
+ addDumpLog(tag, log, null, debugLog);
+ }
+
+ public static void addDumpLog(String tag, String log, Exception e, boolean debugLog) {
if (debugLog) {
- Log.d(tag, log);
+ if (e != null) {
+ Log.d(tag, log, e);
+ } else {
+ Log.d(tag, log);
+ }
}
if (DEBUG_DUMP_LOG) {
sDateStamp.setTime(System.currentTimeMillis());
synchronized (sDumpLogs) {
- sDumpLogs.add(sDateFormat.format(sDateStamp) + ": " + tag + ", " + log);
+ sDumpLogs.add(sDateFormat.format(sDateStamp) + ": " + tag + ", " + log
+ + (e == null ? "" : (", Exception: " + e)));
}
}
}
public void dumpLogsToLocalData() {
if (DEBUG_DUMP_LOG) {
- new Thread("DumpLogsToLocalData") {
- @Override
- public void run() {
+ new AsyncTask<Void, Void, Void>() {
+ public Void doInBackground(Void ... args) {
boolean success = false;
sDateStamp.setTime(sRunStart);
String FILENAME = sDateStamp.getMonth() + "-"
@@ -4778,10 +4895,53 @@ public class Launcher extends Activity
} catch (IOException e) {
e.printStackTrace();
}
+ return null;
}
- }.start();
+ }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void) null);
}
}
+
+ public AppsCustomizePagedView.SortMode getAppsCustomizeContentSortMode () {
+ return mAppsCustomizeContent.getSortMode();
+ }
+
+ public boolean shouldShowSearchBar() {
+ return mWorkspace.getShowSearchBar();
+ }
+
+ public boolean shouldHideWorkspaceIconLables() {
+ return mWorkspace.getHideIconLables();
+ }
+
+ public String getWorkspaceTransitionEffect() {
+ TransitionEffect effect = mWorkspace.getTransitionEffect();
+ return effect == null ? TransitionEffect.TRANSITION_EFFECT_NONE : effect.getName();
+ }
+
+ public String getAppsCustomizeTransitionEffect() {
+ TransitionEffect effect = mAppsCustomizeContent.getTransitionEffect();
+ return effect == null ? TransitionEffect.TRANSITION_EFFECT_NONE : effect.getName();
+ }
+
+ public void updateDynamicGrid() {
+ mSearchDropTargetBar.setupQSB(this);
+ mSearchDropTargetBar.hideSearchBar(false);
+
+ initializeDynamicGrid();
+
+ mGrid.layout(this);
+ mWorkspace.showOutlines();
+
+ // Synchronized reload
+ mModel.startLoader(true, mWorkspace.getCurrentPage());
+ mWorkspace.updateCustomContentVisibility();
+ }
+
+ public boolean isSearchBarEnabled() {
+ return SettingsProvider.getBoolean(this,
+ SettingsProvider.SETTINGS_UI_HOMESCREEN_SEARCH,
+ R.bool.preferences_interface_homescreen_search_default);
+ }
}
interface LauncherTransitionable {
@@ -4791,3 +4951,8 @@ interface LauncherTransitionable {
void onLauncherTransitionStep(Launcher l, float t);
void onLauncherTransitionEnd(Launcher l, boolean animated, boolean toWorkspace);
}
+
+interface DebugIntents {
+ static final String DELETE_DATABASE = "com.android.launcher3.action.DELETE_DATABASE";
+ static final String MIGRATE_DATABASE = "com.android.launcher3.action.MIGRATE_DATABASE";
+}
diff --git a/src/com/android/launcher3/LauncherAnimUtils.java b/src/com/android/launcher3/LauncherAnimUtils.java
index 5d4f9c67e..e6c220b2a 100644
--- a/src/com/android/launcher3/LauncherAnimUtils.java
+++ b/src/com/android/launcher3/LauncherAnimUtils.java
@@ -25,12 +25,13 @@ import android.view.View;
import android.view.ViewTreeObserver;
import java.util.HashSet;
+import java.util.WeakHashMap;
public class LauncherAnimUtils {
- static HashSet<Animator> sAnimators = new HashSet<Animator>();
+ static WeakHashMap<Animator, Object> sAnimators = new WeakHashMap<Animator, Object>();
static Animator.AnimatorListener sEndAnimListener = new Animator.AnimatorListener() {
public void onAnimationStart(Animator animation) {
- sAnimators.add(animation);
+ sAnimators.put(animation, null);
}
public void onAnimationRepeat(Animator animation) {
@@ -74,13 +75,12 @@ public class LauncherAnimUtils {
}
public static void onDestroyActivity() {
- HashSet<Animator> animators = new HashSet<Animator>(sAnimators);
+ HashSet<Animator> animators = new HashSet<Animator>(sAnimators.keySet());
for (Animator a : animators) {
if (a.isRunning()) {
a.cancel();
- } else {
- sAnimators.remove(a);
}
+ sAnimators.remove(a);
}
}
diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java
index cba0d61ac..11e18b186 100644
--- a/src/com/android/launcher3/LauncherAppState.java
+++ b/src/com/android/launcher3/LauncherAppState.java
@@ -22,23 +22,23 @@ import android.content.res.Configuration;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.os.Handler;
-import android.provider.Settings;
import android.util.Log;
-import com.android.launcher3.settings.SettingsProvider;
import java.lang.ref.WeakReference;
-public class LauncherAppState {
+public class LauncherAppState implements DeviceProfile.DeviceProfileCallbacks {
private static final String TAG = "LauncherAppState";
private static final String SHARED_PREFERENCES_KEY = "com.android.launcher3.prefs";
+ private final AppFilter mAppFilter;
+ private final BuildInfo mBuildInfo;
private LauncherModel mModel;
private IconCache mIconCache;
- private AppFilter mAppFilter;
private WidgetPreviewLoader.CacheDb mWidgetPreviewCacheDb;
private boolean mIsScreenLarge;
private float mScreenDensity;
private int mLongPressTimeout = 300;
+ private boolean mWallpaperChangedSinceLastCheck;
private static WeakReference<LauncherProvider> sLauncherProvider;
private static Context sContext;
@@ -84,10 +84,11 @@ public class LauncherAppState {
mIsScreenLarge = isScreenLarge(sContext.getResources());
mScreenDensity = sContext.getResources().getDisplayMetrics().density;
- mWidgetPreviewCacheDb = new WidgetPreviewLoader.CacheDb(sContext);
+ recreateWidgetPreviewDb();
mIconCache = new IconCache(sContext);
mAppFilter = AppFilter.loadByName(sContext.getString(R.string.app_filter_class));
+ mBuildInfo = BuildInfo.loadByName(sContext.getString(R.string.build_info_class));
mModel = new LauncherModel(this, mIconCache, mAppFilter);
// Register intent receivers
@@ -113,18 +114,13 @@ public class LauncherAppState {
ContentResolver resolver = sContext.getContentResolver();
resolver.registerContentObserver(LauncherSettings.Favorites.CONTENT_URI, true,
mFavoritesObserver);
-
- // Generate default typeface
- String fontFamily = SettingsProvider.getString(sContext,
- SettingsProvider.SETTINGS_UI_GENERAL_ICONS_TEXT_FONT_FAMILY,
- R.string.preferences_interface_general_icons_text_font_family_default);
-
- // TODO: Implement font styles
- int fontStyle = SettingsProvider.getInt(sContext,
- SettingsProvider.SETTINGS_UI_GENERAL_ICONS_TEXT_FONT_STYLE,
- R.integer.preferences_interface_general_icons_text_font_style_default);
-
- Utilities.generateTypeface(fontFamily, fontStyle);
+ }
+
+ public void recreateWidgetPreviewDb() {
+ if (mWidgetPreviewCacheDb != null) {
+ mWidgetPreviewCacheDb.close();
+ }
+ mWidgetPreviewCacheDb = new WidgetPreviewLoader.CacheDb(sContext);
}
/**
@@ -189,21 +185,20 @@ public class LauncherAppState {
DeviceProfile initDynamicGrid(Context context, int minWidth, int minHeight,
int width, int height,
int availableWidth, int availableHeight) {
- if (mDynamicGrid == null) {
- mDynamicGrid = new DynamicGrid(context,
- context.getResources(),
- minWidth, minHeight, width, height,
- availableWidth, availableHeight);
- }
+
+ mDynamicGrid = new DynamicGrid(context,
+ context.getResources(),
+ minWidth, minHeight, width, height,
+ availableWidth, availableHeight);
+ mDynamicGrid.getDeviceProfile().addCallback(this);
// Update the icon size
DeviceProfile grid = mDynamicGrid.getDeviceProfile();
- Utilities.setIconSize(grid.iconSizePx);
- grid.updateFromConfiguration(context.getResources(), width, height,
+ grid.updateFromConfiguration(context, context.getResources(), width, height,
availableWidth, availableHeight);
return grid;
}
- DynamicGrid getDynamicGrid() {
+ public DynamicGrid getDynamicGrid() {
return mDynamicGrid;
}
@@ -228,4 +223,29 @@ public class LauncherAppState {
public int getLongPressTimeout() {
return mLongPressTimeout;
}
+
+ public void onWallpaperChanged() {
+ mWallpaperChangedSinceLastCheck = true;
+ }
+
+ public boolean hasWallpaperChangedSinceLastCheck() {
+ boolean result = mWallpaperChangedSinceLastCheck;
+ mWallpaperChangedSinceLastCheck = false;
+ return result;
+ }
+
+ @Override
+ public void onAvailableSizeChanged(DeviceProfile grid) {
+ Utilities.setIconSize(grid.iconSizePx);
+ }
+
+ public static boolean isDisableAllApps() {
+ // Returns false on non-dogfood builds.
+ return getInstance().mBuildInfo.isDogfoodBuild() &&
+ Launcher.isPropertyEnabled(Launcher.DISABLE_ALL_APPS_PROPERTY);
+ }
+
+ public static boolean isDogfoodBuild() {
+ return getInstance().mBuildInfo.isDogfoodBuild();
+ }
}
diff --git a/src/com/android/launcher3/LauncherAppWidgetHostView.java b/src/com/android/launcher3/LauncherAppWidgetHostView.java
index 83aef1a2f..51a649a07 100644
--- a/src/com/android/launcher3/LauncherAppWidgetHostView.java
+++ b/src/com/android/launcher3/LauncherAppWidgetHostView.java
@@ -65,6 +65,12 @@ public class LauncherAppWidgetHostView extends AppWidgetHostView implements Touc
}
public boolean onInterceptTouchEvent(MotionEvent ev) {
+ // Just in case the previous long press hasn't been cleared, we make sure to start fresh
+ // on touch down.
+ if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+ mLongPressHelper.cancelLongPress();
+ }
+
// Consume any touch events for ourselves after longpress is triggered
if (mLongPressHelper.hasPerformedLongPress()) {
mLongPressHelper.cancelLongPress();
@@ -110,13 +116,15 @@ public class LauncherAppWidgetHostView extends AppWidgetHostView implements Touc
@Override
public void onTouchComplete() {
- mLongPressHelper.cancelLongPress();
+ if (!mLongPressHelper.hasPerformedLongPress()) {
+ // If a long press has been performed, we don't want to clear the record of that since
+ // we still may be receiving a touch up which we want to intercept
+ mLongPressHelper.cancelLongPress();
+ }
}
@Override
public int getDescendantFocusability() {
return ViewGroup.FOCUS_BLOCK_DESCENDANTS;
}
-
-
}
diff --git a/src/com/android/launcher3/LauncherBackupAgentHelper.java b/src/com/android/launcher3/LauncherBackupAgentHelper.java
index 2b5059b72..de6aedddd 100644
--- a/src/com/android/launcher3/LauncherBackupAgentHelper.java
+++ b/src/com/android/launcher3/LauncherBackupAgentHelper.java
@@ -18,12 +18,22 @@ package com.android.launcher3;
import android.app.backup.BackupAgentHelper;
import android.app.backup.BackupManager;
+import android.app.backup.SharedPreferencesBackupHelper;
import android.content.Context;
+import android.content.SharedPreferences;
+import android.provider.Settings;
+import android.util.Log;
public class LauncherBackupAgentHelper extends BackupAgentHelper {
+ private static final String TAG = "LauncherBackupAgentHelper";
+ static final boolean VERBOSE = true;
+ static final boolean DEBUG = false;
+
private static BackupManager sBackupManager;
+ protected static final String SETTING_RESTORE_ENABLED = "launcher_restore_enabled";
+
/**
* Notify the backup manager that out database is dirty.
*
@@ -38,9 +48,27 @@ public class LauncherBackupAgentHelper extends BackupAgentHelper {
sBackupManager.dataChanged();
}
+ @Override
+ public void onDestroy() {
+ // There is only one process accessing this preference file, but the restore
+ // modifies the file outside the normal codepaths, so it looks like another
+ // process. This forces a reload of the file, in case this process persists.
+ String spKey = LauncherAppState.getSharedPreferencesKey();
+ SharedPreferences sp = getSharedPreferences(spKey, Context.MODE_MULTI_PROCESS);
+ super.onDestroy();
+ }
@Override
public void onCreate() {
- addHelper(LauncherBackupHelper.LAUNCHER_PREFIX, new LauncherBackupHelper(this));
+ boolean restoreEnabled = 0 != Settings.Secure.getInt(
+ getContentResolver(), SETTING_RESTORE_ENABLED, 0);
+ if (VERBOSE) Log.v(TAG, "restore is " + (restoreEnabled ? "enabled" : "disabled"));
+
+ addHelper(LauncherBackupHelper.LAUNCHER_PREFS_PREFIX,
+ new LauncherPreferencesBackupHelper(this,
+ LauncherAppState.getSharedPreferencesKey(),
+ restoreEnabled));
+ addHelper(LauncherBackupHelper.LAUNCHER_PREFIX,
+ new LauncherBackupHelper(this, restoreEnabled));
}
}
diff --git a/src/com/android/launcher3/LauncherBackupHelper.java b/src/com/android/launcher3/LauncherBackupHelper.java
index 9b901eea1..62e6f3102 100644
--- a/src/com/android/launcher3/LauncherBackupHelper.java
+++ b/src/com/android/launcher3/LauncherBackupHelper.java
@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package com.android.launcher3;
import com.google.protobuf.nano.InvalidProtocolBufferNanoException;
@@ -31,14 +30,14 @@ import com.android.launcher3.backup.BackupProtos.Screen;
import com.android.launcher3.backup.BackupProtos.Widget;
import android.app.backup.BackupDataInputStream;
-import android.app.backup.BackupHelper;
-import android.app.backup.BackupDataInput;
import android.app.backup.BackupDataOutput;
+import android.app.backup.BackupHelper;
import android.app.backup.BackupManager;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProviderInfo;
import android.content.ComponentName;
import android.content.ContentResolver;
+import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
@@ -68,7 +67,8 @@ import java.util.zip.CRC32;
public class LauncherBackupHelper implements BackupHelper {
private static final String TAG = "LauncherBackupHelper";
- private static final boolean DEBUG = false;
+ private static final boolean VERBOSE = LauncherBackupAgentHelper.VERBOSE;
+ private static final boolean DEBUG = LauncherBackupAgentHelper.DEBUG;
private static final boolean DEBUG_PAYLOAD = false;
private static final int MAX_JOURNAL_SIZE = 1000000;
@@ -83,6 +83,8 @@ public class LauncherBackupHelper implements BackupHelper {
public static final String LAUNCHER_PREFIX = "L";
+ public static final String LAUNCHER_PREFS_PREFIX = "LP";
+
private static final Bitmap.CompressFormat IMAGE_FORMAT =
android.graphics.Bitmap.CompressFormat.PNG;
@@ -134,14 +136,19 @@ public class LauncherBackupHelper implements BackupHelper {
private static final int SCREEN_RANK_INDEX = 2;
+ private static IconCache mIconCache;
+
private final Context mContext;
+ private final boolean mRestoreEnabled;
+
private HashMap<ComponentName, AppWidgetProviderInfo> mWidgetMap;
private ArrayList<Key> mKeys;
- public LauncherBackupHelper(Context context) {
+ public LauncherBackupHelper(Context context, boolean restoreEnabled) {
mContext = context;
+ mRestoreEnabled = restoreEnabled;
}
private void dataChanged() {
@@ -166,7 +173,7 @@ public class LauncherBackupHelper implements BackupHelper {
@Override
public void performBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
ParcelFileDescriptor newState) {
- Log.v(TAG, "onBackup");
+ if (VERBOSE) Log.v(TAG, "onBackup");
Journal in = readJournal(oldState);
Journal out = new Journal();
@@ -176,19 +183,23 @@ public class LauncherBackupHelper implements BackupHelper {
out.rows = 0;
out.bytes = 0;
- Log.v(TAG, "lastBackupTime=" + lastBackupTime);
+ Log.v(TAG, "lastBackupTime = " + lastBackupTime);
ArrayList<Key> keys = new ArrayList<Key>();
- try {
- backupFavorites(in, data, out, keys);
- backupScreens(in, data, out, keys);
- backupIcons(in, data, out, keys);
- backupWidgets(in, data, out, keys);
- } catch (IOException e) {
- Log.e(TAG, "launcher backup has failed", e);
+ if (launcherIsReady()) {
+ try {
+ backupFavorites(in, data, out, keys);
+ backupScreens(in, data, out, keys);
+ backupIcons(in, data, out, keys);
+ backupWidgets(in, data, out, keys);
+ } catch (IOException e) {
+ Log.e(TAG, "launcher backup has failed", e);
+ }
+ out.key = keys.toArray(new BackupProtos.Key[keys.size()]);
+ } else {
+ out = in;
}
- out.key = keys.toArray(BackupProtos.Key.EMPTY_ARRAY);
writeJournal(newState, out);
Log.v(TAG, "onBackup: wrote " + out.bytes + "b in " + out.rows + " rows.");
}
@@ -202,7 +213,7 @@ public class LauncherBackupHelper implements BackupHelper {
*/
@Override
public void restoreEntity(BackupDataInputStream data) {
- Log.v(TAG, "restoreEntity");
+ if (VERBOSE) Log.v(TAG, "restoreEntity");
if (mKeys == null) {
mKeys = new ArrayList<Key>();
}
@@ -218,10 +229,11 @@ public class LauncherBackupHelper implements BackupHelper {
bytesRead = data.read(buffer, 0, dataSize);
if (DEBUG) Log.d(TAG, "read " + bytesRead + " of " + dataSize + " available");
} catch (IOException e) {
- Log.d(TAG, "failed to read entity from restore data", e);
+ Log.e(TAG, "failed to read entity from restore data", e);
}
try {
key = backupKeyToKey(backupKey);
+ mKeys.add(key);
switch (key.type) {
case Key.FAVORITE:
restoreFavorite(key, buffer, dataSize, mKeys);
@@ -260,7 +272,7 @@ public class LauncherBackupHelper implements BackupHelper {
// will catch any changes the restore process might have made
Journal out = new Journal();
out.t = 0;
- out.key = mKeys.toArray(BackupProtos.Key.EMPTY_ARRAY);
+ out.key = mKeys.toArray(new BackupProtos.Key[mKeys.size()]);
writeJournal(newState, out);
Log.v(TAG, "onRestore: read " + mKeys.size() + " rows");
mKeys.clear();
@@ -295,10 +307,13 @@ public class LauncherBackupHelper implements BackupHelper {
final long updateTime = cursor.getLong(ID_MODIFIED);
Key key = getKey(Key.FAVORITE, id);
keys.add(key);
- currentIds.add(keyToBackupKey(key));
- if (updateTime > in.t) {
+ final String backupKey = keyToBackupKey(key);
+ currentIds.add(backupKey);
+ if (!savedIds.contains(backupKey) || updateTime >= in.t) {
byte[] blob = packFavorite(cursor);
writeRowToBackup(key, blob, out, data);
+ } else {
+ if (VERBOSE) Log.v(TAG, "favorite " + id + " was too old: " + updateTime);
}
}
} finally {
@@ -322,15 +337,21 @@ public class LauncherBackupHelper implements BackupHelper {
* @param keys keys to mark as clean in the notes for next backup
*/
private void restoreFavorite(Key key, byte[] buffer, int dataSize, ArrayList<Key> keys) {
- Log.v(TAG, "unpacking favorite " + key.id + " (" + dataSize + " bytes)");
+ if (VERBOSE) Log.v(TAG, "unpacking favorite " + key.id);
if (DEBUG) Log.d(TAG, "read (" + buffer.length + "): " +
Base64.encodeToString(buffer, 0, dataSize, Base64.NO_WRAP));
+ if (!mRestoreEnabled) {
+ if (VERBOSE) Log.v(TAG, "restore not enabled: skipping database mutation");
+ return;
+ }
+
try {
- Favorite favorite = unpackFavorite(buffer, 0, dataSize);
- if (DEBUG) Log.d(TAG, "unpacked " + favorite.itemType);
+ ContentResolver cr = mContext.getContentResolver();
+ ContentValues values = unpackFavorite(buffer, 0, dataSize);
+ cr.insert(Favorites.CONTENT_URI, values);
} catch (InvalidProtocolBufferNanoException e) {
- Log.w(TAG, "failed to decode proto", e);
+ Log.e(TAG, "failed to decode favorite", e);
}
}
@@ -358,15 +379,19 @@ public class LauncherBackupHelper implements BackupHelper {
Set<String> currentIds = new HashSet<String>(cursor.getCount());
try {
cursor.moveToPosition(-1);
+ if (DEBUG) Log.d(TAG, "dumping screens after: " + in.t);
while(cursor.moveToNext()) {
final long id = cursor.getLong(ID_INDEX);
final long updateTime = cursor.getLong(ID_MODIFIED);
Key key = getKey(Key.SCREEN, id);
keys.add(key);
- currentIds.add(keyToBackupKey(key));
- if (updateTime > in.t) {
+ final String backupKey = keyToBackupKey(key);
+ currentIds.add(backupKey);
+ if (!savedIds.contains(backupKey) || updateTime >= in.t) {
byte[] blob = packScreen(cursor);
writeRowToBackup(key, blob, out, data);
+ } else {
+ if (VERBOSE) Log.v(TAG, "screen " + id + " was too old: " + updateTime);
}
}
} finally {
@@ -390,14 +415,22 @@ public class LauncherBackupHelper implements BackupHelper {
* @param keys keys to mark as clean in the notes for next backup
*/
private void restoreScreen(Key key, byte[] buffer, int dataSize, ArrayList<Key> keys) {
- Log.v(TAG, "unpacking screen " + key.id);
+ if (VERBOSE) Log.v(TAG, "unpacking screen " + key.id);
if (DEBUG) Log.d(TAG, "read (" + buffer.length + "): " +
Base64.encodeToString(buffer, 0, dataSize, Base64.NO_WRAP));
+
+ if (!mRestoreEnabled) {
+ if (VERBOSE) Log.v(TAG, "restore not enabled: skipping database mutation");
+ return;
+ }
+
try {
- Screen screen = unpackScreen(buffer, 0, dataSize);
- if (DEBUG) Log.d(TAG, "unpacked " + screen.rank);
+ ContentResolver cr = mContext.getContentResolver();
+ ContentValues values = unpackScreen(buffer, 0, dataSize);
+ cr.insert(WorkspaceScreens.CONTENT_URI, values);
+
} catch (InvalidProtocolBufferNanoException e) {
- Log.w(TAG, "failed to decode proto", e);
+ Log.e(TAG, "failed to decode screen", e);
}
}
@@ -414,14 +447,12 @@ public class LauncherBackupHelper implements BackupHelper {
private void backupIcons(Journal in, BackupDataOutput data, Journal out,
ArrayList<Key> keys) throws IOException {
// persist icons that haven't been persisted yet
- final LauncherAppState appState = LauncherAppState.getInstanceNoCreate();
- if (appState == null) {
+ if (!initializeIconCache()) {
dataChanged(); // try again later
if (DEBUG) Log.d(TAG, "Launcher is not initialized, delaying icon backup");
return;
}
final ContentResolver cr = mContext.getContentResolver();
- final IconCache iconCache = appState.getIconCache();
final int dpi = mContext.getResources().getDisplayMetrics().densityDpi;
// read the old ID set
@@ -452,30 +483,30 @@ public class LauncherBackupHelper implements BackupHelper {
Log.w(TAG, "empty intent on application favorite: " + id);
}
if (savedIds.contains(backupKey)) {
- if (DEBUG) Log.d(TAG, "already saved icon " + backupKey);
+ if (VERBOSE) Log.v(TAG, "already saved icon " + backupKey);
// remember that we already backed this up previously
keys.add(key);
} else if (backupKey != null) {
if (DEBUG) Log.d(TAG, "I can count this high: " + out.rows);
if ((out.rows - startRows) < MAX_ICONS_PER_PASS) {
- if (DEBUG) Log.d(TAG, "saving icon " + backupKey);
- Bitmap icon = iconCache.getIcon(intent);
+ if (VERBOSE) Log.v(TAG, "saving icon " + backupKey);
+ Bitmap icon = mIconCache.getIcon(intent);
keys.add(key);
- if (icon != null && !iconCache.isDefaultIcon(icon)) {
+ if (icon != null && !mIconCache.isDefaultIcon(icon)) {
byte[] blob = packIcon(dpi, icon);
writeRowToBackup(key, blob, out, data);
}
} else {
- if (DEBUG) Log.d(TAG, "scheduling another run for icon " + backupKey);
+ if (VERBOSE) Log.d(TAG, "deferring icon backup " + backupKey);
// too many icons for this pass, request another.
dataChanged();
}
}
} catch (URISyntaxException e) {
- Log.w(TAG, "invalid URI on application favorite: " + id);
+ Log.e(TAG, "invalid URI on application favorite: " + id);
} catch (IOException e) {
- Log.w(TAG, "unable to save application icon for favorite: " + id);
+ Log.e(TAG, "unable to save application icon for favorite: " + id);
}
}
@@ -500,21 +531,36 @@ public class LauncherBackupHelper implements BackupHelper {
* @param keys keys to mark as clean in the notes for next backup
*/
private void restoreIcon(Key key, byte[] buffer, int dataSize, ArrayList<Key> keys) {
- Log.v(TAG, "unpacking icon " + key.id);
+ if (VERBOSE) Log.v(TAG, "unpacking icon " + key.id);
if (DEBUG) Log.d(TAG, "read (" + buffer.length + "): " +
Base64.encodeToString(buffer, 0, dataSize, Base64.NO_WRAP));
+
try {
Resource res = unpackIcon(buffer, 0, dataSize);
- if (DEBUG) Log.d(TAG, "unpacked " + res.dpi);
- if (DEBUG) Log.d(TAG, "read " +
- Base64.encodeToString(res.data, 0, res.data.length,
- Base64.NO_WRAP));
+ if (DEBUG) {
+ Log.d(TAG, "unpacked " + res.dpi + " dpi icon");
+ }
+ if (DEBUG_PAYLOAD) {
+ Log.d(TAG, "read " +
+ Base64.encodeToString(res.data, 0, res.data.length,
+ Base64.NO_WRAP));
+ }
Bitmap icon = BitmapFactory.decodeByteArray(res.data, 0, res.data.length);
if (icon == null) {
Log.w(TAG, "failed to unpack icon for " + key.name);
}
- } catch (InvalidProtocolBufferNanoException e) {
- Log.w(TAG, "failed to decode proto", e);
+
+ if (!mRestoreEnabled) {
+ if (VERBOSE) {
+ Log.v(TAG, "restore not enabled: skipping database mutation");
+ }
+ return;
+ } else {
+ IconCache.preloadIcon(mContext, ComponentName.unflattenFromString(key.name),
+ icon, res.dpi);
+ }
+ } catch (IOException e) {
+ Log.d(TAG, "failed to save restored icon for: " + key.name, e);
}
}
@@ -532,15 +578,13 @@ public class LauncherBackupHelper implements BackupHelper {
ArrayList<Key> keys) throws IOException {
// persist static widget info that hasn't been persisted yet
final LauncherAppState appState = LauncherAppState.getInstanceNoCreate();
- if (appState == null) {
- dataChanged(); // try again later
- if (DEBUG) Log.d(TAG, "Launcher is not initialized, delaying widget backup");
+ if (appState == null || !initializeIconCache()) {
+ Log.w(TAG, "Failed to get icon cache during restore");
return;
}
final ContentResolver cr = mContext.getContentResolver();
final WidgetPreviewLoader previewLoader = new WidgetPreviewLoader(mContext);
final PagedViewCellLayout widgetSpacingLayout = new PagedViewCellLayout(mContext);
- final IconCache iconCache = appState.getIconCache();
final int dpi = mContext.getResources().getDisplayMetrics().densityDpi;
final DeviceProfile profile = appState.getDynamicGrid().getDeviceProfile();
if (DEBUG) Log.d(TAG, "cellWidthPx: " + profile.cellWidthPx);
@@ -573,22 +617,22 @@ public class LauncherBackupHelper implements BackupHelper {
Log.w(TAG, "empty intent on appwidget: " + id);
}
if (savedIds.contains(backupKey)) {
- if (DEBUG) Log.d(TAG, "already saved widget " + backupKey);
+ if (VERBOSE) Log.v(TAG, "already saved widget " + backupKey);
// remember that we already backed this up previously
keys.add(key);
} else if (backupKey != null) {
if (DEBUG) Log.d(TAG, "I can count this high: " + out.rows);
if ((out.rows - startRows) < MAX_WIDGETS_PER_PASS) {
- if (DEBUG) Log.d(TAG, "saving widget " + backupKey);
+ if (VERBOSE) Log.v(TAG, "saving widget " + backupKey);
previewLoader.setPreviewSize(spanX * profile.cellWidthPx,
spanY * profile.cellHeightPx, widgetSpacingLayout);
- byte[] blob = packWidget(dpi, previewLoader, iconCache, provider);
+ byte[] blob = packWidget(dpi, previewLoader, mIconCache, provider);
keys.add(key);
writeRowToBackup(key, blob, out, data);
} else {
- if (DEBUG) Log.d(TAG, "scheduling another run for widget " + backupKey);
+ if (VERBOSE) Log.d(TAG, "deferring widget backup " + backupKey);
// too many widgets for this pass, request another.
dataChanged();
}
@@ -615,7 +659,7 @@ public class LauncherBackupHelper implements BackupHelper {
* @param keys keys to mark as clean in the notes for next backup
*/
private void restoreWidget(Key key, byte[] buffer, int dataSize, ArrayList<Key> keys) {
- Log.v(TAG, "unpacking widget " + key.id);
+ if (VERBOSE) Log.v(TAG, "unpacking widget " + key.id);
if (DEBUG) Log.d(TAG, "read (" + buffer.length + "): " +
Base64.encodeToString(buffer, 0, dataSize, Base64.NO_WRAP));
try {
@@ -628,8 +672,15 @@ public class LauncherBackupHelper implements BackupHelper {
Log.w(TAG, "failed to unpack widget icon for " + key.name);
}
}
+
+ if (!mRestoreEnabled) {
+ if (VERBOSE) Log.v(TAG, "restore not enabled: skipping database mutation");
+ return;
+ } else {
+ // future site of widget table mutation
+ }
} catch (InvalidProtocolBufferNanoException e) {
- Log.w(TAG, "failed to decode proto", e);
+ Log.e(TAG, "failed to decode widget", e);
}
}
@@ -764,11 +815,48 @@ public class LauncherBackupHelper implements BackupHelper {
}
/** Deserialize a Favorite from persistence, after verifying checksum wrapper. */
- private Favorite unpackFavorite(byte[] buffer, int offset, int dataSize)
+ private ContentValues unpackFavorite(byte[] buffer, int offset, int dataSize)
throws InvalidProtocolBufferNanoException {
Favorite favorite = new Favorite();
MessageNano.mergeFrom(favorite, readCheckedBytes(buffer, offset, dataSize));
- return favorite;
+ if (VERBOSE) Log.v(TAG, "unpacked favorite " + favorite.itemType + ", " +
+ (TextUtils.isEmpty(favorite.title) ? favorite.id : favorite.title));
+ ContentValues values = new ContentValues();
+ values.put(Favorites._ID, favorite.id);
+ values.put(Favorites.SCREEN, favorite.screen);
+ values.put(Favorites.CONTAINER, favorite.container);
+ values.put(Favorites.CELLX, favorite.cellX);
+ values.put(Favorites.CELLY, favorite.cellY);
+ values.put(Favorites.SPANX, favorite.spanX);
+ values.put(Favorites.SPANY, favorite.spanY);
+ values.put(Favorites.ICON_TYPE, favorite.iconType);
+ if (favorite.iconType == Favorites.ICON_TYPE_RESOURCE) {
+ values.put(Favorites.ICON_PACKAGE, favorite.iconPackage);
+ values.put(Favorites.ICON_RESOURCE, favorite.iconResource);
+ }
+ if (favorite.iconType == Favorites.ICON_TYPE_BITMAP) {
+ values.put(Favorites.ICON, favorite.icon);
+ }
+ if (!TextUtils.isEmpty(favorite.title)) {
+ values.put(Favorites.TITLE, favorite.title);
+ } else {
+ values.put(Favorites.TITLE, "");
+ }
+ if (!TextUtils.isEmpty(favorite.intent)) {
+ values.put(Favorites.INTENT, favorite.intent);
+ }
+ values.put(Favorites.ITEM_TYPE, favorite.itemType);
+ if (favorite.itemType == Favorites.ITEM_TYPE_APPWIDGET) {
+ if (!TextUtils.isEmpty(favorite.appWidgetProvider)) {
+ values.put(Favorites.APPWIDGET_PROVIDER, favorite.appWidgetProvider);
+ }
+ values.put(Favorites.APPWIDGET_ID, favorite.appWidgetId);
+ }
+
+ // Let LauncherModel know we've been here.
+ values.put(LauncherSettings.Favorites.RESTORED, 1);
+
+ return values;
}
/** Serialize a Screen for persistence, including a checksum wrapper. */
@@ -781,11 +869,15 @@ public class LauncherBackupHelper implements BackupHelper {
}
/** Deserialize a Screen from persistence, after verifying checksum wrapper. */
- private Screen unpackScreen(byte[] buffer, int offset, int dataSize)
+ private ContentValues unpackScreen(byte[] buffer, int offset, int dataSize)
throws InvalidProtocolBufferNanoException {
Screen screen = new Screen();
MessageNano.mergeFrom(screen, readCheckedBytes(buffer, offset, dataSize));
- return screen;
+ if (VERBOSE) Log.v(TAG, "unpacked screen " + screen.id + "/" + screen.rank);
+ ContentValues values = new ContentValues();
+ values.put(WorkspaceScreens._ID, screen.id);
+ values.put(WorkspaceScreens.SCREEN_RANK, screen.rank);
+ return values;
}
/** Serialize an icon Resource for persistence, including a checksum wrapper. */
@@ -800,10 +892,11 @@ public class LauncherBackupHelper implements BackupHelper {
}
/** Deserialize an icon resource from persistence, after verifying checksum wrapper. */
- private Resource unpackIcon(byte[] buffer, int offset, int dataSize)
+ private static Resource unpackIcon(byte[] buffer, int offset, int dataSize)
throws InvalidProtocolBufferNanoException {
Resource res = new Resource();
MessageNano.mergeFrom(res, readCheckedBytes(buffer, offset, dataSize));
+ if (VERBOSE) Log.v(TAG, "unpacked icon " + res.dpi + "/" + res.data.length);
return res;
}
@@ -842,6 +935,7 @@ public class LauncherBackupHelper implements BackupHelper {
throws InvalidProtocolBufferNanoException {
Widget widget = new Widget();
MessageNano.mergeFrom(widget, readCheckedBytes(buffer, offset, dataSize));
+ if (VERBOSE) Log.v(TAG, "unpacked widget " + widget.provider);
return widget;
}
@@ -852,7 +946,7 @@ public class LauncherBackupHelper implements BackupHelper {
* in that case, do a full backup.
*
* @param oldState the read-0only file descriptor pointing to the old journal
- * @return a Journal protocol bugffer
+ * @return a Journal protocol buffer
*/
private Journal readJournal(ParcelFileDescriptor oldState) {
Journal journal = new Journal();
@@ -861,47 +955,61 @@ public class LauncherBackupHelper implements BackupHelper {
}
FileInputStream inStream = new FileInputStream(oldState.getFileDescriptor());
try {
- int remaining = inStream.available();
- if (DEBUG) Log.d(TAG, "available " + remaining);
- if (remaining < MAX_JOURNAL_SIZE) {
- byte[] buffer = new byte[remaining];
+ int availableBytes = inStream.available();
+ if (DEBUG) Log.d(TAG, "available " + availableBytes);
+ if (availableBytes < MAX_JOURNAL_SIZE) {
+ byte[] buffer = new byte[availableBytes];
int bytesRead = 0;
- while (remaining > 0) {
+ boolean valid = false;
+ InvalidProtocolBufferNanoException lastProtoException = null;
+ while (availableBytes > 0) {
try {
- int result = inStream.read(buffer, bytesRead, remaining);
+ // OMG what are you doing? This is crazy inefficient!
+ // If we read a byte that is not ours, we will cause trouble: b/12491813
+ // However, we don't know how many bytes to expect (oops).
+ // So we have to step through *slowly*, watching for the end.
+ int result = inStream.read(buffer, bytesRead, 1);
if (result > 0) {
- if (DEBUG) Log.d(TAG, "read some bytes: " + result);
- remaining -= result;
+ availableBytes -= result;
bytesRead += result;
+ if (DEBUG && (bytesRead % 100 == 0)) {
+ Log.d(TAG, "read some bytes: " + bytesRead);
+ }
} else {
- // stop reading ands see what there is to parse
- Log.w(TAG, "read error: " + result);
- remaining = 0;
+ Log.w(TAG, "unexpected end of file while reading journal.");
+ // stop reading and see what there is to parse
+ availableBytes = 0;
}
} catch (IOException e) {
- Log.w(TAG, "failed to read the journal", e);
buffer = null;
- remaining = 0;
+ availableBytes = 0;
}
- }
- if (DEBUG) Log.d(TAG, "journal bytes read: " + bytesRead);
- if (buffer != null) {
+ // check the buffer to see if we have a valid journal
try {
MessageNano.mergeFrom(journal, readCheckedBytes(buffer, 0, bytesRead));
+ // if we are here, then we have read a valid, checksum-verified journal
+ valid = true;
+ availableBytes = 0;
+ if (VERBOSE) Log.v(TAG, "read " + bytesRead + " bytes of journal");
} catch (InvalidProtocolBufferNanoException e) {
- Log.d(TAG, "failed to read the journal", e);
+ // if we don't have the whole journal yet, mergeFrom will throw. keep going.
+ lastProtoException = e;
journal.clear();
}
}
+ if (DEBUG) Log.d(TAG, "journal bytes read: " + bytesRead);
+ if (!valid) {
+ Log.w(TAG, "could not find a valid journal", lastProtoException);
+ }
}
} catch (IOException e) {
- Log.d(TAG, "failed to close the journal", e);
+ Log.w(TAG, "failed to close the journal", e);
} finally {
try {
inStream.close();
} catch (IOException e) {
- Log.d(TAG, "failed to close the journal", e);
+ Log.w(TAG, "failed to close the journal", e);
}
}
return journal;
@@ -914,7 +1022,7 @@ public class LauncherBackupHelper implements BackupHelper {
data.writeEntityData(blob, blob.length);
out.rows++;
out.bytes += blob.length;
- Log.v(TAG, "saving " + geKeyType(key) + " " + backupKey + ": " +
+ if (VERBOSE) Log.v(TAG, "saving " + geKeyType(key) + " " + backupKey + ": " +
getKeyName(key) + "/" + blob.length);
if(DEBUG_PAYLOAD) {
String encoded = Base64.encodeToString(blob, 0, blob.length, Base64.NO_WRAP);
@@ -922,7 +1030,7 @@ public class LauncherBackupHelper implements BackupHelper {
for (int offset = 0; offset < encoded.length(); offset += chunkSize) {
int end = offset + chunkSize;
end = Math.min(end, encoded.length());
- Log.d(TAG, "wrote " + encoded.substring(offset, end));
+ Log.w(TAG, "wrote " + encoded.substring(offset, end));
}
}
}
@@ -942,7 +1050,7 @@ public class LauncherBackupHelper implements BackupHelper {
throws IOException {
int rows = 0;
for(String deleted: deletedIds) {
- Log.v(TAG, "dropping icon " + deleted);
+ if (VERBOSE) Log.v(TAG, "dropping deleted item " + deleted);
data.writeEntityHeader(deleted, -1);
rows++;
}
@@ -962,10 +1070,12 @@ public class LauncherBackupHelper implements BackupHelper {
FileOutputStream outStream = null;
try {
outStream = new FileOutputStream(newState.getFileDescriptor());
- outStream.write(writeCheckedBytes(journal));
+ final byte[] journalBytes = writeCheckedBytes(journal);
+ outStream.write(journalBytes);
outStream.close();
+ if (VERBOSE) Log.v(TAG, "wrote " + journalBytes.length + " bytes of journal");
} catch (IOException e) {
- Log.d(TAG, "failed to write backup journal", e);
+ Log.w(TAG, "failed to write backup journal", e);
}
}
@@ -980,7 +1090,7 @@ public class LauncherBackupHelper implements BackupHelper {
}
/** Unwrap a proto message from a CheckedMessage, verifying the checksum. */
- private byte[] readCheckedBytes(byte[] buffer, int offset, int dataSize)
+ private static byte[] readCheckedBytes(byte[] buffer, int offset, int dataSize)
throws InvalidProtocolBufferNanoException {
CheckedMessage wrapper = new CheckedMessage();
MessageNano.mergeFrom(wrapper, buffer, offset, dataSize);
@@ -1004,6 +1114,43 @@ public class LauncherBackupHelper implements BackupHelper {
return mWidgetMap.get(component);
}
+
+ private boolean initializeIconCache() {
+ if (mIconCache != null) {
+ return true;
+ }
+
+ final LauncherAppState appState = LauncherAppState.getInstanceNoCreate();
+ if (appState == null) {
+ Throwable stackTrace = new Throwable();
+ stackTrace.fillInStackTrace();
+ Log.w(TAG, "Failed to get app state during backup/restore", stackTrace);
+ return false;
+ }
+ mIconCache = appState.getIconCache();
+ return mIconCache != null;
+ }
+
+
+ // check if the launcher is in a state to support backup
+ private boolean launcherIsReady() {
+ ContentResolver cr = mContext.getContentResolver();
+ Cursor cursor = cr.query(Favorites.CONTENT_URI, FAVORITE_PROJECTION, null, null, null);
+ if (cursor == null) {
+ // launcher data has been wiped, do nothing
+ return false;
+ }
+ cursor.close();
+
+ if (!initializeIconCache()) {
+ // launcher services are unavailable, try again later
+ dataChanged();
+ return false;
+ }
+
+ return true;
+ }
+
private class KeyParsingException extends Throwable {
private KeyParsingException(Throwable cause) {
super(cause);
diff --git a/src/com/android/launcher3/LauncherClings.java b/src/com/android/launcher3/LauncherClings.java
new file mode 100644
index 000000000..e5e0c1621
--- /dev/null
+++ b/src/com/android/launcher3/LauncherClings.java
@@ -0,0 +1,451 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3;
+
+import android.accounts.Account;
+import android.accounts.AccountManager;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.os.UserManager;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityManager;
+import android.widget.TextView;
+
+class LauncherClings {
+ private static final String FIRST_RUN_CLING_DISMISSED_KEY = "cling_gel.first_run.dismissed";
+ private static final String MIGRATION_CLING_DISMISSED_KEY = "cling_gel.migration.dismissed";
+ private static final String MIGRATION_WORKSPACE_CLING_DISMISSED_KEY =
+ "cling_gel.migration_workspace.dismissed";
+ private static final String WORKSPACE_CLING_DISMISSED_KEY = "cling_gel.workspace.dismissed";
+ private static final String FOLDER_CLING_DISMISSED_KEY = "cling_gel.folder.dismissed";
+
+ private static final boolean DISABLE_CLINGS = false;
+
+ private static final int SHOW_CLING_DURATION = 250;
+ private static final int DISMISS_CLING_DURATION = 200;
+
+ private Launcher mLauncher;
+ private LayoutInflater mInflater;
+ private HideFromAccessibilityHelper mHideFromAccessibilityHelper
+ = new HideFromAccessibilityHelper();
+
+ /** Ctor */
+ public LauncherClings(Launcher launcher) {
+ mLauncher = launcher;
+ mInflater = mLauncher.getLayoutInflater();
+ }
+
+ /** Initializes a cling */
+ private Cling initCling(int clingId, int scrimId, boolean animate,
+ boolean dimNavBarVisibilty) {
+ Cling cling = (Cling) mLauncher.findViewById(clingId);
+ View scrim = null;
+ if (scrimId > 0) {
+ scrim = mLauncher.findViewById(scrimId);
+ }
+ if (cling != null) {
+ cling.init(mLauncher, scrim);
+ cling.show(animate, SHOW_CLING_DURATION);
+
+ if (dimNavBarVisibilty) {
+ cling.setSystemUiVisibility(cling.getSystemUiVisibility() |
+ View.SYSTEM_UI_FLAG_LOW_PROFILE);
+ }
+ }
+ return cling;
+ }
+
+ /** Returns whether the clings are enabled or should be shown */
+ private boolean areClingsEnabled() {
+ if (DISABLE_CLINGS) {
+ return false;
+ }
+
+ // disable clings when running in a test harness
+ if(ActivityManager.isRunningInTestHarness()) return false;
+
+ // Disable clings for accessibility when explore by touch is enabled
+ final AccessibilityManager a11yManager = (AccessibilityManager) mLauncher.getSystemService(
+ Launcher.ACCESSIBILITY_SERVICE);
+ if (a11yManager.isTouchExplorationEnabled()) {
+ return false;
+ }
+
+ // Restricted secondary users (child mode) will potentially have very few apps
+ // seeded when they start up for the first time. Clings won't work well with that
+ boolean supportsLimitedUsers =
+ android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2;
+ Account[] accounts = AccountManager.get(mLauncher).getAccounts();
+ if (supportsLimitedUsers && accounts.length == 0) {
+ UserManager um = (UserManager) mLauncher.getSystemService(Context.USER_SERVICE);
+ Bundle restrictions = um.getUserRestrictions();
+ if (restrictions.getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS, false)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /** Returns whether the folder cling is visible. */
+ public boolean isFolderClingVisible() {
+ Cling cling = (Cling) mLauncher.findViewById(R.id.folder_cling);
+ if (cling != null) {
+ return cling.getVisibility() == View.VISIBLE;
+ }
+ return false;
+ }
+
+ private boolean skipCustomClingIfNoAccounts() {
+ Cling cling = (Cling) mLauncher.findViewById(R.id.workspace_cling);
+ boolean customCling = cling.getDrawIdentifier().equals("workspace_custom");
+ if (customCling) {
+ AccountManager am = AccountManager.get(mLauncher);
+ if (am == null) return false;
+ Account[] accounts = am.getAccountsByType("com.google");
+ return accounts.length == 0;
+ }
+ return false;
+ }
+
+ /** Updates the first run cling custom content hint */
+ private void setCustomContentHintVisibility(Cling cling, String ccHintStr, boolean visible,
+ boolean animate) {
+ final TextView ccHint = (TextView) cling.findViewById(R.id.custom_content_hint);
+ if (ccHint != null) {
+ if (visible && !ccHintStr.isEmpty()) {
+ ccHint.setText(ccHintStr);
+ ccHint.setVisibility(View.VISIBLE);
+ if (animate) {
+ ccHint.setAlpha(0f);
+ ccHint.animate().alpha(1f)
+ .setDuration(SHOW_CLING_DURATION)
+ .start();
+ } else {
+ ccHint.setAlpha(1f);
+ }
+ } else {
+ if (animate) {
+ ccHint.animate().alpha(0f)
+ .setDuration(SHOW_CLING_DURATION)
+ .setListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ ccHint.setVisibility(View.GONE);
+ }
+ })
+ .start();
+ } else {
+ ccHint.setAlpha(0f);
+ ccHint.setVisibility(View.GONE);
+ }
+ }
+ }
+ }
+
+ /** Updates the first run cling custom content hint */
+ public void updateCustomContentHintVisibility() {
+ Cling cling = (Cling) mLauncher.findViewById(R.id.first_run_cling);
+ String ccHintStr = mLauncher.getFirstRunCustomContentHint();
+
+ if (mLauncher.getWorkspace().hasCustomContent()) {
+ // Show the custom content hint if ccHintStr is not empty
+ if (cling != null) {
+ setCustomContentHintVisibility(cling, ccHintStr, true, true);
+ }
+ } else {
+ // Hide the custom content hint
+ if (cling != null) {
+ setCustomContentHintVisibility(cling, ccHintStr, false, true);
+ }
+ }
+ }
+
+ /** Updates the first run cling search bar hint. */
+ public void updateSearchBarHint(String hint) {
+ Cling cling = (Cling) mLauncher.findViewById(R.id.first_run_cling);
+ if (cling != null && cling.getVisibility() == View.VISIBLE && !hint.isEmpty()) {
+ TextView sbHint = (TextView) cling.findViewById(R.id.search_bar_hint);
+ sbHint.setText(hint);
+ sbHint.setVisibility(View.VISIBLE);
+ }
+ }
+
+ public boolean shouldShowFirstRunOrMigrationClings() {
+ SharedPreferences sharedPrefs = mLauncher.getSharedPrefs();
+ return areClingsEnabled() &&
+ !sharedPrefs.getBoolean(FIRST_RUN_CLING_DISMISSED_KEY, false) &&
+ !sharedPrefs.getBoolean(MIGRATION_CLING_DISMISSED_KEY, false);
+ }
+
+ public void removeFirstRunAndMigrationClings() {
+ removeCling(R.id.first_run_cling);
+ removeCling(R.id.migration_cling);
+ }
+
+ /**
+ * Shows the first run cling.
+ *
+ * This flow is mutually exclusive with showMigrationCling, and only runs if this Launcher
+ * package was preinstalled or there is no db to migrate from.
+ */
+ public void showFirstRunCling() {
+ if (!skipCustomClingIfNoAccounts()) {
+ Cling cling = (Cling) mLauncher.findViewById(R.id.first_run_cling);
+ if (cling != null) {
+ String sbHintStr = mLauncher.getFirstRunClingSearchBarHint();
+ String ccHintStr = mLauncher.getFirstRunCustomContentHint();
+ if (!sbHintStr.isEmpty()) {
+ TextView sbHint = (TextView) cling.findViewById(R.id.search_bar_hint);
+ sbHint.setText(sbHintStr);
+ sbHint.setVisibility(View.VISIBLE);
+ }
+ setCustomContentHintVisibility(cling, ccHintStr, true, false);
+ }
+ initCling(R.id.first_run_cling, 0, false, true);
+ } else {
+ removeFirstRunAndMigrationClings();
+ }
+ }
+
+ /**
+ * Shows the migration cling.
+ *
+ * This flow is mutually exclusive with showFirstRunCling, and only runs if this Launcher
+ * package was not preinstalled and there exists a db to migrate from.
+ */
+ public void showMigrationCling() {
+ mLauncher.hideWorkspaceSearchAndHotseat();
+
+ Cling c = initCling(R.id.migration_cling, 0, false, true);
+ c.bringScrimToFront();
+ c.bringToFront();
+ }
+
+ public void showMigrationWorkspaceCling() {
+ // Enable the clings only if they have not been dismissed before
+ if (areClingsEnabled() && !mLauncher.getSharedPrefs().getBoolean(
+ MIGRATION_WORKSPACE_CLING_DISMISSED_KEY, false)) {
+ Cling c = initCling(R.id.migration_workspace_cling, 0, false, true);
+ c.updateMigrationWorkspaceBubblePosition();
+ c.bringScrimToFront();
+ c.bringToFront();
+ } else {
+ removeCling(R.id.migration_workspace_cling);
+ }
+ }
+
+ public void showWorkspaceCling() {
+ // Enable the clings only if they have not been dismissed before
+ if (areClingsEnabled() && !mLauncher.getSharedPrefs().getBoolean(
+ WORKSPACE_CLING_DISMISSED_KEY, false)) {
+ Cling c = initCling(R.id.workspace_cling, 0, false, true);
+ c.updateWorkspaceBubblePosition();
+
+ // Set the focused hotseat app if there is one
+ c.setFocusedHotseatApp(mLauncher.getFirstRunFocusedHotseatAppDrawableId(),
+ mLauncher.getFirstRunFocusedHotseatAppRank(),
+ mLauncher.getFirstRunFocusedHotseatAppComponentName(),
+ mLauncher.getFirstRunFocusedHotseatAppBubbleTitle(),
+ mLauncher.getFirstRunFocusedHotseatAppBubbleDescription());
+ } else {
+ removeCling(R.id.workspace_cling);
+ }
+ }
+
+ public Cling showFoldersCling() {
+ SharedPreferences sharedPrefs = mLauncher.getSharedPrefs();
+ // Enable the clings only if they have not been dismissed before
+ if (areClingsEnabled() &&
+ !sharedPrefs.getBoolean(FOLDER_CLING_DISMISSED_KEY, false) &&
+ !sharedPrefs.getBoolean(Launcher.USER_HAS_MIGRATED, false)) {
+ Cling cling = initCling(R.id.folder_cling, R.id.cling_scrim,
+ true, true);
+ Folder openFolder = mLauncher.getWorkspace().getOpenFolder();
+ if (openFolder != null) {
+ Rect openFolderRect = new Rect();
+ openFolder.getHitRect(openFolderRect);
+ cling.setOpenFolderRect(openFolderRect);
+ openFolder.bringToFront();
+ }
+ return cling;
+ } else {
+ removeCling(R.id.folder_cling);
+ return null;
+ }
+ }
+
+ public static void synchonouslyMarkFirstRunClingDismissed(Context ctx) {
+ SharedPreferences prefs = ctx.getSharedPreferences(
+ LauncherAppState.getSharedPreferencesKey(),Context.MODE_PRIVATE);
+ SharedPreferences.Editor editor = prefs.edit();
+ editor.putBoolean(LauncherClings.FIRST_RUN_CLING_DISMISSED_KEY, true);
+ editor.commit();
+ }
+
+ public void markFolderClingDismissed() {
+ SharedPreferences.Editor editor = mLauncher.getSharedPrefs().edit();
+ editor.putBoolean(LauncherClings.FOLDER_CLING_DISMISSED_KEY, true);
+ editor.apply();
+ }
+
+ /** Removes the cling outright from the DragLayer */
+ private void removeCling(int id) {
+ final View cling = mLauncher.findViewById(id);
+ if (cling != null) {
+ final ViewGroup parent = (ViewGroup) cling.getParent();
+ parent.post(new Runnable() {
+ @Override
+ public void run() {
+ parent.removeView(cling);
+ }
+ });
+ mHideFromAccessibilityHelper.restoreImportantForAccessibility(mLauncher.getDragLayer());
+ }
+ }
+
+ /** Hides the specified Cling */
+ private void dismissCling(final Cling cling, final Runnable postAnimationCb,
+ final String flag, int duration, boolean restoreNavBarVisibilty) {
+ // To catch cases where siblings of top-level views are made invisible, just check whether
+ // the cling is directly set to GONE before dismissing it.
+ if (cling != null && cling.getVisibility() != View.GONE) {
+ final Runnable cleanUpClingCb = new Runnable() {
+ public void run() {
+ cling.cleanup();
+ SharedPreferences.Editor editor = mLauncher.getSharedPrefs().edit();
+ editor.putBoolean(flag, true);
+ editor.apply();
+ if (postAnimationCb != null) {
+ postAnimationCb.run();
+ }
+ }
+ };
+ if (duration <= 0) {
+ cleanUpClingCb.run();
+ } else {
+ cling.hide(duration, cleanUpClingCb);
+ }
+ mHideFromAccessibilityHelper.restoreImportantForAccessibility(mLauncher.getDragLayer());
+
+ if (restoreNavBarVisibilty) {
+ cling.setSystemUiVisibility(cling.getSystemUiVisibility() &
+ ~View.SYSTEM_UI_FLAG_LOW_PROFILE);
+ }
+ }
+ }
+
+ public void dismissFirstRunCling(View v) {
+ Cling cling = (Cling) mLauncher.findViewById(R.id.first_run_cling);
+ Runnable cb = new Runnable() {
+ public void run() {
+ // Show the workspace cling next
+ showWorkspaceCling();
+ }
+ };
+ dismissCling(cling, cb, FIRST_RUN_CLING_DISMISSED_KEY,
+ DISMISS_CLING_DURATION, false);
+
+ // Fade out the search bar for the workspace cling coming up
+ mLauncher.getSearchBar().hideSearchBar(true);
+ }
+
+ private void dismissMigrationCling() {
+ mLauncher.showWorkspaceSearchAndHotseat();
+ Runnable dismissCb = new Runnable() {
+ public void run() {
+ Cling cling = (Cling) mLauncher.findViewById(R.id.migration_cling);
+ Runnable cb = new Runnable() {
+ public void run() {
+ // Show the migration workspace cling next
+ showMigrationWorkspaceCling();
+ }
+ };
+ dismissCling(cling, cb, MIGRATION_CLING_DISMISSED_KEY,
+ DISMISS_CLING_DURATION, true);
+ }
+ };
+ mLauncher.getWorkspace().post(dismissCb);
+ }
+
+ private void dismissAnyWorkspaceCling(Cling cling, String key, View v) {
+ Runnable cb = null;
+ if (v == null) {
+ cb = new Runnable() {
+ public void run() {
+ mLauncher.getWorkspace().enterOverviewMode();
+ }
+ };
+ }
+ dismissCling(cling, cb, key, DISMISS_CLING_DURATION, true);
+
+ // Fade in the search bar
+ mLauncher.getSearchBar().showSearchBar(true);
+ }
+
+ public void dismissMigrationClingCopyApps(View v) {
+ // Copy the shortcuts from the old database
+ LauncherModel model = mLauncher.getModel();
+ model.resetLoadedState(false, true);
+ model.startLoader(false, PagedView.INVALID_RESTORE_PAGE,
+ LauncherModel.LOADER_FLAG_CLEAR_WORKSPACE
+ | LauncherModel.LOADER_FLAG_MIGRATE_SHORTCUTS);
+
+ // Set the flag to skip the folder cling
+ String spKey = LauncherAppState.getSharedPreferencesKey();
+ SharedPreferences sp = mLauncher.getSharedPreferences(spKey, Context.MODE_PRIVATE);
+ SharedPreferences.Editor editor = sp.edit();
+ editor.putBoolean(Launcher.USER_HAS_MIGRATED, true);
+ editor.apply();
+
+ // Disable the migration cling
+ dismissMigrationCling();
+ }
+
+ public void dismissMigrationClingUseDefault(View v) {
+ // Clear the workspace
+ LauncherModel model = mLauncher.getModel();
+ model.resetLoadedState(false, true);
+ model.startLoader(false, PagedView.INVALID_RESTORE_PAGE,
+ LauncherModel.LOADER_FLAG_CLEAR_WORKSPACE);
+
+ // Disable the migration cling
+ dismissMigrationCling();
+ }
+
+ public void dismissMigrationWorkspaceCling(View v) {
+ Cling cling = (Cling) mLauncher.findViewById(R.id.migration_workspace_cling);
+ dismissAnyWorkspaceCling(cling, MIGRATION_WORKSPACE_CLING_DISMISSED_KEY, v);
+ }
+
+ public void dismissWorkspaceCling(View v) {
+ Cling cling = (Cling) mLauncher.findViewById(R.id.workspace_cling);
+ dismissAnyWorkspaceCling(cling, WORKSPACE_CLING_DISMISSED_KEY, v);
+ }
+
+ public void dismissFolderCling(View v) {
+ Cling cling = (Cling) mLauncher.findViewById(R.id.folder_cling);
+ dismissCling(cling, null, FOLDER_CLING_DISMISSED_KEY,
+ DISMISS_CLING_DURATION, true);
+ }
+}
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index e06fe5fb3..9fe0bf3a5 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -48,6 +48,8 @@ import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
import android.provider.BaseColumns;
+import android.text.TextUtils;
+import android.provider.Settings;
import android.util.Log;
import android.util.Pair;
@@ -78,13 +80,21 @@ import java.util.concurrent.atomic.AtomicBoolean;
public class LauncherModel extends BroadcastReceiver {
static final boolean DEBUG_LOADERS = false;
static final String TAG = "Launcher.Model";
+ public static final String SETTINGS_PROTECTED_COMPONENTS = "protected_components";
// true = use a "More Apps" folder for non-workspace apps on upgrade
// false = strew non-workspace apps across the workspace on upgrade
public static final boolean UPGRADE_USE_MORE_APPS_FOLDER = false;
+ public static final int LOADER_FLAG_NONE = 0;
+ public static final int LOADER_FLAG_CLEAR_WORKSPACE = 1 << 0;
+ public static final int LOADER_FLAG_MIGRATE_SHORTCUTS = 1 << 1;
+
private static final int ITEMS_CHUNK = 6; // batch size for the workspace icons
+ private static final long INVALID_SCREEN_ID = -1L;
+
private final boolean mAppsCanBeOnRemoveableStorage;
+ private final boolean mOldContentProviderExists;
private final LauncherAppState mApp;
private final Object mLock = new Object();
@@ -175,8 +185,7 @@ public class LauncherModel extends BroadcastReceiver {
ArrayList<AppInfo> addedApps);
public void bindAppsUpdated(ArrayList<AppInfo> apps);
public void bindComponentsRemoved(ArrayList<String> packageNames,
- ArrayList<AppInfo> appInfos,
- boolean matchPackageNamesOnly);
+ ArrayList<AppInfo> appInfos);
public void bindPackagesUpdated(ArrayList<Object> widgetsAndShortcuts);
public void bindSearchablesChanged();
public void onPageBoundSynchronously(int page);
@@ -188,16 +197,16 @@ public class LauncherModel extends BroadcastReceiver {
}
LauncherModel(LauncherAppState app, IconCache iconCache, AppFilter appFilter) {
- final Context context = app.getContext();
+ Context context = app.getContext();
+ ContentResolver contentResolver = context.getContentResolver();
mAppsCanBeOnRemoveableStorage = Environment.isExternalStorageRemovable();
+ mOldContentProviderExists = (contentResolver.acquireContentProviderClient(
+ LauncherSettings.Favorites.OLD_CONTENT_URI) != null);
mApp = app;
mBgAllAppsList = new AllAppsList(iconCache, appFilter);
mIconCache = iconCache;
- mDefaultIcon = Utilities.createIconBitmap(
- mIconCache.getFullResDefaultActivityIcon(), context);
-
final Resources res = context.getResources();
Configuration config = res.getConfiguration();
mPreviousConfigMcc = config.mcc;
@@ -228,6 +237,10 @@ public class LauncherModel extends BroadcastReceiver {
}
}
+ boolean canMigrateFromOldLauncherDb(Launcher launcher) {
+ return mOldContentProviderExists && !launcher.isLauncherPreinstalled() ;
+ }
+
static boolean findNextAvailableIconSpaceInScreen(ArrayList<ItemInfo> items, int[] xy,
long screen) {
LauncherAppState app = LauncherAppState.getInstance();
@@ -289,14 +302,58 @@ public class LauncherModel extends BroadcastReceiver {
return null;
}
- public void addAndBindAddedApps(final Context context, final ArrayList<ItemInfo> workspaceApps,
- final ArrayList<AppInfo> allAppsApps) {
- Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;
- addAndBindAddedApps(context, workspaceApps, cb, allAppsApps);
+ public void addAppsToAllApps(final Context ctx, final ArrayList<AppInfo> allAppsApps) {
+ final Callbacks callbacks = mCallbacks != null ? mCallbacks.get() : null;
+
+ if (allAppsApps == null) {
+ throw new RuntimeException("allAppsApps must not be null");
+ }
+ if (allAppsApps.isEmpty()) {
+ return;
+ }
+
+ final ArrayList<AppInfo> restoredAppsFinal = new ArrayList<AppInfo>();
+ Iterator<AppInfo> iter = allAppsApps.iterator();
+ while (iter.hasNext()) {
+ ItemInfo a = iter.next();
+ if (LauncherModel.appWasRestored(ctx, a.getIntent())) {
+ restoredAppsFinal.add((AppInfo) a);
+ }
+ }
+
+ // Process the newly added applications and add them to the database first
+ Runnable r = new Runnable() {
+ public void run() {
+ runOnMainThread(new Runnable() {
+ public void run() {
+ Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;
+ if (callbacks == cb && cb != null) {
+ if (!restoredAppsFinal.isEmpty()) {
+ for (AppInfo info : restoredAppsFinal) {
+ final Intent intent = info.getIntent();
+ if (intent != null) {
+ mIconCache.deletePreloadedIcon(intent.getComponent());
+ }
+ }
+ callbacks.bindAppsUpdated(restoredAppsFinal);
+ }
+ callbacks.bindAppsAdded(null, null, null, allAppsApps);
+ }
+ }
+ });
+ }
+ };
+ runOnWorkerThread(r);
}
- public void addAndBindAddedApps(final Context context, final ArrayList<ItemInfo> workspaceApps,
- final Callbacks callbacks, final ArrayList<AppInfo> allAppsApps) {
- if (workspaceApps.isEmpty() && allAppsApps.isEmpty()) {
+
+ public void addAndBindAddedWorkspaceApps(final Context context,
+ final ArrayList<ItemInfo> workspaceApps) {
+ final Callbacks callbacks = mCallbacks != null ? mCallbacks.get() : null;
+
+ if (workspaceApps == null) {
+ throw new RuntimeException("workspaceApps and allAppsApps must not be null");
+ }
+ if (workspaceApps.isEmpty()) {
return;
}
// Process the newly added applications and add them to the database first
@@ -304,6 +361,7 @@ public class LauncherModel extends BroadcastReceiver {
public void run() {
final ArrayList<ItemInfo> addedShortcutsFinal = new ArrayList<ItemInfo>();
final ArrayList<Long> addedWorkspaceScreensFinal = new ArrayList<Long>();
+ final ArrayList<AppInfo> restoredAppsFinal = new ArrayList<AppInfo>();
// Get the list of workspace screens. We need to append to this list and
// can not use sBgWorkspaceScreens because loadWorkspace() may not have been
@@ -324,6 +382,11 @@ public class LauncherModel extends BroadcastReceiver {
// Short-circuit this logic if the icon exists somewhere on the workspace
if (LauncherModel.shortcutExists(context, name, launchIntent)) {
+ // Only InstallShortcutReceiver sends us shortcutInfos, ignore them
+ if (a instanceof AppInfo &&
+ LauncherModel.appWasRestored(context, launchIntent)) {
+ restoredAppsFinal.add((AppInfo) a);
+ }
continue;
}
@@ -379,7 +442,7 @@ public class LauncherModel extends BroadcastReceiver {
// Update the workspace screens
updateWorkspaceScreenOrder(context, workspaceScreens);
- if (!addedShortcutsFinal.isEmpty() || !allAppsApps.isEmpty()) {
+ if (!addedShortcutsFinal.isEmpty()) {
runOnMainThread(new Runnable() {
public void run() {
Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;
@@ -398,7 +461,10 @@ public class LauncherModel extends BroadcastReceiver {
}
}
callbacks.bindAppsAdded(addedWorkspaceScreensFinal,
- addNotAnimated, addAnimated, allAppsApps);
+ addNotAnimated, addAnimated, null);
+ if (!restoredAppsFinal.isEmpty()) {
+ callbacks.bindAppsUpdated(restoredAppsFinal);
+ }
}
}
});
@@ -409,6 +475,11 @@ public class LauncherModel extends BroadcastReceiver {
}
public Bitmap getFallbackIcon() {
+ if (mDefaultIcon == null) {
+ final Context context = LauncherAppState.getInstance().getContext();
+ mDefaultIcon = Utilities.createIconBitmap(
+ mIconCache.getFullResDefaultActivityIcon(), context);
+ }
return Bitmap.createBitmap(mDefaultIcon);
}
@@ -504,8 +575,7 @@ public class LauncherModel extends BroadcastReceiver {
if (stackTrace != null) {
e.setStackTrace(stackTrace);
}
- // TODO: something breaks this in the upgrade path
- //throw e;
+ throw e;
}
}
@@ -589,8 +659,9 @@ public class LauncherModel extends BroadcastReceiver {
// as in Workspace.onDrop. Here, we just add/remove them from the list of items
// that are on the desktop, as appropriate
ItemInfo modelItem = sBgItemsIdMap.get(itemId);
- if (modelItem.container == LauncherSettings.Favorites.CONTAINER_DESKTOP ||
- modelItem.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
+ if (modelItem != null &&
+ (modelItem.container == LauncherSettings.Favorites.CONTAINER_DESKTOP ||
+ modelItem.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT)) {
switch (modelItem.itemType) {
case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
@@ -760,6 +831,30 @@ public class LauncherModel extends BroadcastReceiver {
}
/**
+ * Returns true if the shortcuts already exists in the database.
+ * we identify a shortcut by the component name of the intent.
+ */
+ static boolean appWasRestored(Context context, Intent intent) {
+ final ContentResolver cr = context.getContentResolver();
+ final ComponentName component = intent.getComponent();
+ if (component == null) {
+ return false;
+ }
+ String componentName = component.flattenToString();
+ final String where = "intent glob \"*component=" + componentName + "*\" and restored = 1";
+ Cursor c = cr.query(LauncherSettings.Favorites.CONTENT_URI,
+ new String[]{"intent", "restored"}, where, null, null);
+ boolean result = false;
+ try {
+ result = c.moveToFirst();
+ } finally {
+ c.close();
+ }
+ Log.d(TAG, "shortcutWasRestored is " + result + " for " + componentName);
+ return result;
+ }
+
+ /**
* Returns an ItemInfo array containing all the items in the LauncherModel.
* The ItemInfo.id is not set through this function.
*/
@@ -819,6 +914,7 @@ public class LauncherModel extends BroadcastReceiver {
final int screenIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SCREEN);
final int cellXIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLX);
final int cellYIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLY);
+ final int hiddenIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.HIDDEN);
FolderInfo folderInfo = null;
switch (c.getInt(itemTypeIndex)) {
@@ -833,6 +929,7 @@ public class LauncherModel extends BroadcastReceiver {
folderInfo.screenId = c.getInt(screenIndex);
folderInfo.cellX = c.getInt(cellXIndex);
folderInfo.cellY = c.getInt(cellYIndex);
+ folderInfo.hidden = c.getInt(hiddenIndex) > 0;
return folderInfo;
}
@@ -1017,6 +1114,10 @@ public class LauncherModel extends BroadcastReceiver {
* a list of screen ids in the order that they should appear.
*/
void updateWorkspaceScreenOrder(Context context, final ArrayList<Long> screens) {
+ // Log to disk
+ Launcher.addDumpLog(TAG, "11683562 - updateWorkspaceScreenOrder()", true);
+ Launcher.addDumpLog(TAG, "11683562 - screens: " + TextUtils.join(", ", screens), true);
+
final ArrayList<Long> screensCopy = new ArrayList<Long>(screens);
final ContentResolver cr = context.getContentResolver();
final Uri uri = LauncherSettings.WorkspaceScreens.CONTENT_URI;
@@ -1033,18 +1134,23 @@ public class LauncherModel extends BroadcastReceiver {
Runnable r = new Runnable() {
@Override
public void run() {
+ ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
// Clear the table
- cr.delete(uri, null, null);
+ ops.add(ContentProviderOperation.newDelete(uri).build());
int count = screensCopy.size();
- ContentValues[] values = new ContentValues[count];
for (int i = 0; i < count; i++) {
ContentValues v = new ContentValues();
long screenId = screensCopy.get(i);
v.put(LauncherSettings.WorkspaceScreens._ID, screenId);
v.put(LauncherSettings.WorkspaceScreens.SCREEN_RANK, i);
- values[i] = v;
+ ops.add(ContentProviderOperation.newInsert(uri).withValues(v).build());
+ }
+
+ try {
+ cr.applyBatch(LauncherProvider.AUTHORITY, ops);
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
}
- cr.bulkInsert(uri, values);
synchronized (sBgLock) {
sBgWorkspaceScreens.clear();
@@ -1139,15 +1245,29 @@ public class LauncherModel extends BroadcastReceiver {
}
} else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(action)) {
- // First, schedule to add these apps back in.
+ final boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
String[] packages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
- enqueuePackageUpdated(new PackageUpdatedTask(PackageUpdatedTask.OP_ADD, packages));
- // Then, rebind everything.
- startLoaderFromBackground();
+ if (!replacing) {
+ enqueuePackageUpdated(new PackageUpdatedTask(PackageUpdatedTask.OP_ADD, packages));
+ if (mAppsCanBeOnRemoveableStorage) {
+ // Only rebind if we support removable storage. It catches the case where
+ // apps on the external sd card need to be reloaded
+ startLoaderFromBackground();
+ }
+ } else {
+ // If we are replacing then just update the packages in the list
+ enqueuePackageUpdated(new PackageUpdatedTask(PackageUpdatedTask.OP_UPDATE,
+ packages));
+ }
} else if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {
- String[] packages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
- enqueuePackageUpdated(new PackageUpdatedTask(
- PackageUpdatedTask.OP_UNAVAILABLE, packages));
+ final boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
+ if (!replacing) {
+ String[] packages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
+ enqueuePackageUpdated(new PackageUpdatedTask(
+ PackageUpdatedTask.OP_UNAVAILABLE, packages));
+ }
+ // else, we are replacing the packages, so ignore this event and wait for
+ // EXTERNAL_APPLICATIONS_AVAILABLE to update the packages at that time
} else if (Intent.ACTION_LOCALE_CHANGED.equals(action)) {
// If we have changed locale we need to clear out the labels in all apps/workspace.
forceReload();
@@ -1211,7 +1331,7 @@ public class LauncherModel extends BroadcastReceiver {
}
}
if (runLoader) {
- startLoader(false, -1);
+ startLoader(false, PagedView.INVALID_RESTORE_PAGE);
}
}
@@ -1230,6 +1350,10 @@ public class LauncherModel extends BroadcastReceiver {
}
public void startLoader(boolean isLaunching, int synchronousBindPage) {
+ startLoader(isLaunching, synchronousBindPage, LOADER_FLAG_NONE);
+ }
+
+ public void startLoader(boolean isLaunching, int synchronousBindPage, int loadFlags) {
synchronized (mLock) {
if (DEBUG_LOADERS) {
Log.d(TAG, "startLoader isLaunching=" + isLaunching);
@@ -1244,8 +1368,9 @@ public class LauncherModel extends BroadcastReceiver {
// If there is already one running, tell it to stop.
// also, don't downgrade isLaunching if we're already running
isLaunching = isLaunching || stopLoaderLocked();
- mLoaderTask = new LoaderTask(mApp.getContext(), isLaunching);
- if (synchronousBindPage > -1 && mAllAppsLoaded && mWorkspaceLoaded) {
+ mLoaderTask = new LoaderTask(mApp.getContext(), isLaunching, loadFlags);
+ if (synchronousBindPage != PagedView.INVALID_RESTORE_PAGE
+ && mAllAppsLoaded && mWorkspaceLoaded) {
mLoaderTask.runBindSynchronousPage(synchronousBindPage);
} else {
sWorkerThread.setPriority(Thread.NORM_PRIORITY);
@@ -1297,6 +1422,15 @@ public class LauncherModel extends BroadcastReceiver {
} finally {
sc.close();
}
+
+ // Log to disk
+ Launcher.addDumpLog(TAG, "11683562 - loadWorkspaceScreensDb()", true);
+ ArrayList<String> orderedScreensPairs= new ArrayList<String>();
+ for (Integer i : orderedScreens.keySet()) {
+ orderedScreensPairs.add("{ " + i + ": " + orderedScreens.get(i) + " }");
+ }
+ Launcher.addDumpLog(TAG, "11683562 - screens: " +
+ TextUtils.join(", ", orderedScreensPairs), true);
return orderedScreens;
}
@@ -1313,75 +1447,6 @@ public class LauncherModel extends BroadcastReceiver {
return false;
}
- // check & update map of what's occupied; used to discard overlapping/invalid items
- public boolean checkItemPlacement(HashMap<Long, ItemInfo[][]> occupied, ItemInfo item,
- AtomicBoolean deleteOnItemOverlap) {
- LauncherAppState app = LauncherAppState.getInstance();
- DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
-
- long containerIndex = item.screenId;
- if (item.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
- if (occupied.containsKey((long) LauncherSettings.Favorites.CONTAINER_HOTSEAT)) {
- if (occupied.get((long) LauncherSettings.Favorites.CONTAINER_HOTSEAT)
- [(int) item.screenId][0] != null) {
- Log.e(TAG, "Error loading shortcut into hotseat " + item
- + " into position (" + item.screenId + ":" + item.cellX + ","
- + item.cellY + ") occupied by "
- + occupied.get((long) LauncherSettings.Favorites.CONTAINER_HOTSEAT)
- [(int) item.screenId][0]);
- if (occupied.get((long) LauncherSettings.Favorites.CONTAINER_HOTSEAT)
- [(int) item.screenId][0].itemType == LauncherSettings.Favorites.ITEM_TYPE_ALLAPPS) {
- deleteOnItemOverlap.set(true);
- }
- return false;
- } else {
- ItemInfo[][] hotseatItems = occupied.get(
- (long) LauncherSettings.Favorites.CONTAINER_HOTSEAT);
- hotseatItems[(int) item.screenId][0] = item;
- return true;
- }
- } else {
- ItemInfo[][] items = new ItemInfo[(int) grid.numHotseatIcons][1];
- items[(int) item.screenId][0] = item;
- occupied.put((long) LauncherSettings.Favorites.CONTAINER_HOTSEAT, items);
- return true;
- }
- } else if (item.container != LauncherSettings.Favorites.CONTAINER_DESKTOP) {
- // Skip further checking if it is not the hotseat or workspace container
- return true;
- }
-
- int countX = (int) grid.numColumns;
- int countY = (int) grid.numRows;
-
- if (!occupied.containsKey(item.screenId)) {
- ItemInfo[][] items = new ItemInfo[countX + 1][countY + 1];
- occupied.put(item.screenId, items);
- }
-
- ItemInfo[][] screens = occupied.get(item.screenId);
- // Check if any workspace icons overlap with each other
- for (int x = item.cellX; x < (item.cellX+item.spanX); x++) {
- for (int y = item.cellY; y < (item.cellY+item.spanY); y++) {
- if (screens[x][y] != null) {
- Log.e(TAG, "Error loading shortcut " + item
- + " into cell (" + containerIndex + "-" + item.screenId + ":"
- + x + "," + y
- + ") occupied by "
- + screens[x][y]);
- return false;
- }
- }
- }
- for (int x = item.cellX; x < (item.cellX+item.spanX); x++) {
- for (int y = item.cellY; y < (item.cellY+item.spanY); y++) {
- screens[x][y] = item;
- }
- }
-
- return true;
- }
-
/**
* Runnable for the thread that loads the contents of the launcher:
* - workspace icons
@@ -1394,13 +1459,15 @@ public class LauncherModel extends BroadcastReceiver {
private boolean mIsLoadingAndBindingWorkspace;
private boolean mStopped;
private boolean mLoadAndBindStepFinished;
+ private int mFlags;
private HashMap<Object, CharSequence> mLabelCache;
- LoaderTask(Context context, boolean isLaunching) {
+ LoaderTask(Context context, boolean isLaunching, int flags) {
mContext = context;
mIsLaunching = isLaunching;
mLabelCache = new HashMap<Object, CharSequence>();
+ mFlags = flags;
}
boolean isLaunching() {
@@ -1473,7 +1540,7 @@ public class LauncherModel extends BroadcastReceiver {
}
void runBindSynchronousPage(int synchronousBindPage) {
- if (synchronousBindPage < 0) {
+ if (synchronousBindPage == PagedView.INVALID_RESTORE_PAGE) {
// Ensure that we have a valid page index to load synchronously
throw new RuntimeException("Should not call runBindSynchronousPage() without " +
"valid page index");
@@ -1562,7 +1629,7 @@ public class LauncherModel extends BroadcastReceiver {
sBgDbIconCache.clear();
}
- if (AppsCustomizePagedView.DISABLE_ALL_APPS) {
+ if (LauncherAppState.isDisableAllApps()) {
// Ensure that all the applications that are in the system are
// represented on the home screen.
if (!UPGRADE_USE_MORE_APPS_FOLDER || !isUpgrade) {
@@ -1638,16 +1705,90 @@ public class LauncherModel extends BroadcastReceiver {
}
}
if (!added.isEmpty()) {
- Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;
- addAndBindAddedApps(context, added, cb, null);
+ addAndBindAddedWorkspaceApps(context, added);
}
}
- private boolean checkItemDimensions(ItemInfo info) {
+ private boolean checkItemPlacement(HashMap<Long, ItemInfo[][]> occupied, ItemInfo item,
+ AtomicBoolean deleteOnInvalidPlacement) {
LauncherAppState app = LauncherAppState.getInstance();
DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
- return (info.cellX + info.spanX) > (int) grid.numColumns ||
- (info.cellY + info.spanY) > (int) grid.numRows;
+ final int countX = (int) grid.numColumns;
+ final int countY = (int) grid.numRows;
+ long containerIndex = item.screenId;
+ if (item.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
+ // Return early if we detect that an item is under the hotseat button
+ if (mCallbacks == null) {
+ deleteOnInvalidPlacement.set(true);
+ Log.e(TAG, "Error loading shortcut into hotseat " + item
+ + " into position (" + item.screenId + ":" + item.cellX + ","
+ + item.cellY + ") occupied by all apps");
+ return false;
+ }
+ final ItemInfo[][] hotseatItems =
+ occupied.get((long) LauncherSettings.Favorites.CONTAINER_HOTSEAT);
+ if (item.screenId >= grid.numHotseatIcons) {
+ Log.e(TAG, "Error loading shortcut " + item
+ + " into hotseat position " + item.screenId
+ + ", position out of bounds: (0 to " + (grid.numHotseatIcons - 1)
+ + ")");
+ return false;
+ }
+ if (hotseatItems != null) {
+ if (hotseatItems[(int) item.screenId][0] != null) {
+ Log.e(TAG, "Error loading shortcut into hotseat " + item
+ + " into position (" + item.screenId + ":" + item.cellX + ","
+ + item.cellY + ") occupied by "
+ + occupied.get(LauncherSettings.Favorites.CONTAINER_HOTSEAT)
+ [(int) item.screenId][0]);
+ return false;
+ } else {
+ hotseatItems[(int) item.screenId][0] = item;
+ return true;
+ }
+ } else {
+ final ItemInfo[][] items = new ItemInfo[(int) grid.numHotseatIcons][1];
+ items[(int) item.screenId][0] = item;
+ occupied.put((long) LauncherSettings.Favorites.CONTAINER_HOTSEAT, items);
+ return true;
+ }
+ } else if (item.container != LauncherSettings.Favorites.CONTAINER_DESKTOP) {
+ // Skip further checking if it is not the hotseat or workspace container
+ return true;
+ }
+ if (!occupied.containsKey(item.screenId)) {
+ ItemInfo[][] items = new ItemInfo[countX + 1][countY + 1];
+ occupied.put(item.screenId, items);
+ }
+ final ItemInfo[][] screens = occupied.get(item.screenId);
+ if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP &&
+ item.cellX < 0 || item.cellY < 0 ||
+ item.cellX + item.spanX > countX || item.cellY + item.spanY > countY) {
+ Log.e(TAG, "Error loading shortcut " + item
+ + " into cell (" + containerIndex + "-" + item.screenId + ":"
+ + item.cellX + "," + item.cellY
+ + ") out of screen bounds ( " + countX + "x" + countY + ")");
+ return false;
+ }
+ // Check if any workspace icons overlap with each other
+ for (int x = item.cellX; x < (item.cellX+item.spanX); x++) {
+ for (int y = item.cellY; y < (item.cellY+item.spanY); y++) {
+ if (screens[x][y] != null) {
+ Log.e(TAG, "Error loading shortcut " + item
+ + " into cell (" + containerIndex + "-" + item.screenId + ":"
+ + x + "," + y
+ + ") occupied by "
+ + screens[x][y]);
+ return false;
+ }
+ }
+ }
+ for (int x = item.cellX; x < (item.cellX+item.spanX); x++) {
+ for (int y = item.cellY; y < (item.cellY+item.spanY); y++) {
+ screens[x][y] = item;
+ }
+ }
+ return true;
}
/** Clears all the sBg data structures */
@@ -1662,8 +1803,11 @@ public class LauncherModel extends BroadcastReceiver {
}
}
- /** Returns whether this is an upgradge path */
+ /** Returns whether this is an upgrade path */
private boolean loadWorkspace() {
+ // Log to disk
+ Launcher.addDumpLog(TAG, "11683562 - loadWorkspace()", true);
+
final long t = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;
final Context context = mContext;
@@ -1677,16 +1821,33 @@ public class LauncherModel extends BroadcastReceiver {
int countX = (int) grid.numColumns;
int countY = (int) grid.numRows;
- // Make sure the default workspace is loaded, if needed
- LauncherAppState.getLauncherProvider().loadDefaultFavoritesIfNecessary(0);
+ if ((mFlags & LOADER_FLAG_CLEAR_WORKSPACE) != 0) {
+ Launcher.addDumpLog(TAG, "loadWorkspace: resetting launcher database", true);
+ LauncherAppState.getLauncherProvider().deleteDatabase();
+ }
+
+ if ((mFlags & LOADER_FLAG_MIGRATE_SHORTCUTS) != 0) {
+ // append the user's Launcher2 shortcuts
+ Launcher.addDumpLog(TAG, "loadWorkspace: migrating from launcher2", true);
+ LauncherAppState.getLauncherProvider().migrateLauncher2Shortcuts();
+ } else {
+ // Make sure the default workspace is loaded
+ Launcher.addDumpLog(TAG, "loadWorkspace: loading default favorites", false);
+ LauncherAppState.getLauncherProvider().loadDefaultFavoritesIfNecessary(0);
+ }
// Check if we need to do any upgrade-path logic
+ // (Includes having just imported default favorites)
boolean loadedOldDb = LauncherAppState.getLauncherProvider().justLoadedOldDb();
+ // Log to disk
+ Launcher.addDumpLog(TAG, "11683562 - loadedOldDb: " + loadedOldDb, true);
+
synchronized (sBgLock) {
clearSBgDataStructures();
final ArrayList<Long> itemsToRemove = new ArrayList<Long>();
+ final ArrayList<Long> restoredRows = new ArrayList<Long>();
final Uri contentUri = LauncherSettings.Favorites.CONTENT_URI;
if (DEBUG_LOADERS) Log.d(TAG, "loading model from " + contentUri);
final Cursor c = contentResolver.query(contentUri, null, null, null, null);
@@ -1727,8 +1888,11 @@ public class LauncherModel extends BroadcastReceiver {
(LauncherSettings.Favorites.SPANX);
final int spanYIndex = c.getColumnIndexOrThrow(
LauncherSettings.Favorites.SPANY);
- //final int uriIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.URI);
- //final int displayModeIndex = c.getColumnIndexOrThrow(
+ final int restoredIndex = c.getColumnIndexOrThrow(
+ LauncherSettings.Favorites.RESTORED);
+ final int hiddenIndex = c.getColumnIndexOrThrow(
+ LauncherSettings.Favorites.HIDDEN);
+ //final int uriIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.URI); //final int displayModeIndex = c.getColumnIndexOrThrow(
// LauncherSettings.Favorites.DISPLAY_MODE);
ShortcutInfo info;
@@ -1739,9 +1903,10 @@ public class LauncherModel extends BroadcastReceiver {
Intent intent = null;
while (!mStopped && c.moveToNext()) {
- AtomicBoolean deleteOnItemOverlap = new AtomicBoolean(false);
+ AtomicBoolean deleteOnInvalidPlacement = new AtomicBoolean(false);
try {
int itemType = c.getInt(itemTypeIndex);
+ boolean restored = 0 != c.getInt(restoredIndex);
switch (itemType) {
case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
@@ -1754,25 +1919,45 @@ public class LauncherModel extends BroadcastReceiver {
intent = Intent.parseUri(intentDescription, 0);
ComponentName cn = intent.getComponent();
if (cn != null && !isValidPackageComponent(manager, cn)) {
- if (!mAppsCanBeOnRemoveableStorage) {
- // Log the invalid package, and remove it from the db
- Launcher.addDumpLog(TAG, "Invalid package removed: " + cn, true);
- itemsToRemove.add(id);
+ if (restored) {
+ // might be installed later
+ Launcher.addDumpLog(TAG,
+ "package not yet restored: " + cn, true);
} else {
- // If apps can be on external storage, then we just
- // leave them for the user to remove (maybe add
- // visual treatment to it)
- Launcher.addDumpLog(TAG, "Invalid package found: " + cn, true);
+ if (!mAppsCanBeOnRemoveableStorage) {
+ // Log the invalid package, and remove it
+ Launcher.addDumpLog(TAG,
+ "Invalid package removed: " + cn, true);
+ itemsToRemove.add(id);
+ } else {
+ // If apps can be on external storage, then we just
+ // leave them for the user to remove (maybe add
+ // visual treatment to it)
+ Launcher.addDumpLog(TAG,
+ "Invalid package found: " + cn, true);
+ }
+ continue;
}
- continue;
+ } else if (restored) {
+ // no special handling necessary for this restored item
+ restoredRows.add(id);
+ restored = false;
}
} catch (URISyntaxException e) {
- Launcher.addDumpLog(TAG, "Invalid uri: " + intentDescription, true);
+ Launcher.addDumpLog(TAG,
+ "Invalid uri: " + intentDescription, true);
continue;
}
}
- if (itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
+ if (restored) {
+ Launcher.addDumpLog(TAG,
+ "constructing info for partially restored package",
+ true);
+ info = getRestoredItemInfo(c, titleIndex, intent);
+ intent = getRestoredItemIntent(c, context, intent);
+ } else if (itemType ==
+ LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
info = getShortcutInfo(manager, intent, context, c, iconIndex,
titleIndex, mLabelCache);
} else if (itemType == LauncherSettings.Favorites.ITEM_TYPE_ALLAPPS) {
@@ -1806,18 +1991,11 @@ public class LauncherModel extends BroadcastReceiver {
info.cellY = c.getInt(cellYIndex);
info.spanX = 1;
info.spanY = 1;
- // Skip loading items that are out of bounds
- if (container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
- if (checkItemDimensions(info)) {
- Launcher.addDumpLog(TAG, "Skipped loading out of bounds shortcut: "
- + info + ", " + grid.numColumns + "x" + grid.numRows, true);
- continue;
- }
- }
+
// check & update map of what's occupied
- deleteOnItemOverlap.set(false);
- if (!checkItemPlacement(occupied, info, deleteOnItemOverlap)) {
- if (deleteOnItemOverlap.get()) {
+ deleteOnInvalidPlacement.set(false);
+ if (!checkItemPlacement(occupied, info, deleteOnInvalidPlacement)) {
+ if (deleteOnInvalidPlacement.get()) {
itemsToRemove.add(id);
}
break;
@@ -1858,19 +2036,13 @@ public class LauncherModel extends BroadcastReceiver {
folderInfo.cellY = c.getInt(cellYIndex);
folderInfo.spanX = 1;
folderInfo.spanY = 1;
+ folderInfo.hidden = c.getInt(hiddenIndex) > 0;
- // Skip loading items that are out of bounds
- if (container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
- if (checkItemDimensions(folderInfo)) {
- Log.d(TAG, "Skipped loading out of bounds folder");
- continue;
- }
- }
// check & update map of what's occupied
- deleteOnItemOverlap.set(false);
+ deleteOnInvalidPlacement.set(false);
if (!checkItemPlacement(occupied, folderInfo,
- deleteOnItemOverlap)) {
- if (deleteOnItemOverlap.get()) {
+ deleteOnInvalidPlacement)) {
+ if (deleteOnInvalidPlacement.get()) {
itemsToRemove.add(id);
}
break;
@@ -1883,6 +2055,11 @@ public class LauncherModel extends BroadcastReceiver {
break;
}
+ if (restored) {
+ // no special handling required for restored folders
+ restoredRows.add(id);
+ }
+
sBgItemsIdMap.put(folderInfo.id, folderInfo);
sBgFolders.put(folderInfo.id, folderInfo);
break;
@@ -1926,18 +2103,11 @@ public class LauncherModel extends BroadcastReceiver {
}
appWidgetInfo.container = c.getInt(containerIndex);
- // Skip loading items that are out of bounds
- if (container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
- if (checkItemDimensions(appWidgetInfo)) {
- Log.d(TAG, "Skipped loading out of bounds app widget");
- continue;
- }
- }
// check & update map of what's occupied
- deleteOnItemOverlap.set(false);
+ deleteOnInvalidPlacement.set(false);
if (!checkItemPlacement(occupied, appWidgetInfo,
- deleteOnItemOverlap)) {
- if (deleteOnItemOverlap.get()) {
+ deleteOnInvalidPlacement)) {
+ if (deleteOnInvalidPlacement.get()) {
itemsToRemove.add(id);
}
break;
@@ -1957,7 +2127,7 @@ public class LauncherModel extends BroadcastReceiver {
break;
}
} catch (Exception e) {
- Launcher.addDumpLog(TAG, "Desktop items loading interrupted: " + e, true);
+ Launcher.addDumpLog(TAG, "Desktop items loading interrupted", e, true);
}
}
} finally {
@@ -2003,6 +2173,25 @@ public class LauncherModel extends BroadcastReceiver {
}
}
+ if (restoredRows.size() > 0) {
+ ContentProviderClient updater = contentResolver.acquireContentProviderClient(
+ LauncherSettings.Favorites.CONTENT_URI);
+ // Update restored items that no longer require special handling
+ try {
+ StringBuilder selectionBuilder = new StringBuilder();
+ selectionBuilder.append(LauncherSettings.Favorites._ID);
+ selectionBuilder.append(" IN (");
+ selectionBuilder.append(TextUtils.join(", ", restoredRows));
+ selectionBuilder.append(")");
+ ContentValues values = new ContentValues();
+ values.put(LauncherSettings.Favorites.RESTORED, 0);
+ updater.update(LauncherSettings.Favorites.CONTENT_URI,
+ values, selectionBuilder.toString(), null);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Could not update restored rows");
+ }
+ }
+
if (loadedOldDb) {
long maxScreenId = 0;
// If we're importing we use the old screen order.
@@ -2017,6 +2206,10 @@ public class LauncherModel extends BroadcastReceiver {
}
}
Collections.sort(sBgWorkspaceScreens);
+ // Log to disk
+ Launcher.addDumpLog(TAG, "11683562 - maxScreenId: " + maxScreenId, true);
+ Launcher.addDumpLog(TAG, "11683562 - sBgWorkspaceScreens: " +
+ TextUtils.join(", ", sBgWorkspaceScreens), true);
LauncherAppState.getLauncherProvider().updateMaxScreenId(maxScreenId);
updateWorkspaceScreenOrder(context, sBgWorkspaceScreens);
@@ -2033,6 +2226,9 @@ public class LauncherModel extends BroadcastReceiver {
for (Integer i : orderedScreens.keySet()) {
sBgWorkspaceScreens.add(orderedScreens.get(i));
}
+ // Log to disk
+ Launcher.addDumpLog(TAG, "11683562 - sBgWorkspaceScreens: " +
+ TextUtils.join(", ", sBgWorkspaceScreens), true);
// Remove any empty screens
ArrayList<Long> unusedScreens = new ArrayList<Long>(sBgWorkspaceScreens);
@@ -2046,6 +2242,10 @@ public class LauncherModel extends BroadcastReceiver {
// If there are any empty screens remove them, and update.
if (unusedScreens.size() != 0) {
+ // Log to disk
+ Launcher.addDumpLog(TAG, "11683562 - unusedScreens (to be removed): " +
+ TextUtils.join(", ", unusedScreens), true);
+
sBgWorkspaceScreens.removeAll(unusedScreens);
updateWorkspaceScreenOrder(context, sBgWorkspaceScreens);
}
@@ -2077,7 +2277,7 @@ public class LauncherModel extends BroadcastReceiver {
/** Filters the set of items who are directly or indirectly (via another container) on the
* specified screen. */
- private void filterCurrentWorkspaceItems(int currentScreen,
+ private void filterCurrentWorkspaceItems(long currentScreenId,
ArrayList<ItemInfo> allWorkspaceItems,
ArrayList<ItemInfo> currentScreenItems,
ArrayList<ItemInfo> otherScreenItems) {
@@ -2090,12 +2290,6 @@ public class LauncherModel extends BroadcastReceiver {
}
}
- // If we aren't filtering on a screen, then the set of items to load is the full set of
- // items given.
- if (currentScreen < 0) {
- currentScreenItems.addAll(allWorkspaceItems);
- }
-
// Order the set of items by their containers first, this allows use to walk through the
// list sequentially, build up a list of containers that are in the specified screen,
// as well as all items in those containers.
@@ -2108,7 +2302,7 @@ public class LauncherModel extends BroadcastReceiver {
});
for (ItemInfo info : allWorkspaceItems) {
if (info.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
- if (info.screenId == currentScreen) {
+ if (info.screenId == currentScreenId) {
currentScreenItems.add(info);
itemsOnScreen.add(info.id);
} else {
@@ -2129,20 +2323,15 @@ public class LauncherModel extends BroadcastReceiver {
}
/** Filters the set of widgets which are on the specified screen. */
- private void filterCurrentAppWidgets(int currentScreen,
+ private void filterCurrentAppWidgets(long currentScreenId,
ArrayList<LauncherAppWidgetInfo> appWidgets,
ArrayList<LauncherAppWidgetInfo> currentScreenWidgets,
ArrayList<LauncherAppWidgetInfo> otherScreenWidgets) {
- // If we aren't filtering on a screen, then the set of items to load is the full set of
- // widgets given.
- if (currentScreen < 0) {
- currentScreenWidgets.addAll(appWidgets);
- }
for (LauncherAppWidgetInfo widget : appWidgets) {
if (widget == null) continue;
if (widget.container == LauncherSettings.Favorites.CONTAINER_DESKTOP &&
- widget.screenId == currentScreen) {
+ widget.screenId == currentScreenId) {
currentScreenWidgets.add(widget);
} else {
otherScreenWidgets.add(widget);
@@ -2151,23 +2340,18 @@ public class LauncherModel extends BroadcastReceiver {
}
/** Filters the set of folders which are on the specified screen. */
- private void filterCurrentFolders(int currentScreen,
+ private void filterCurrentFolders(long currentScreenId,
HashMap<Long, ItemInfo> itemsIdMap,
HashMap<Long, FolderInfo> folders,
HashMap<Long, FolderInfo> currentScreenFolders,
HashMap<Long, FolderInfo> otherScreenFolders) {
- // If we aren't filtering on a screen, then the set of items to load is the full set of
- // widgets given.
- if (currentScreen < 0) {
- currentScreenFolders.putAll(folders);
- }
for (long id : folders.keySet()) {
ItemInfo info = itemsIdMap.get(id);
FolderInfo folder = folders.get(id);
if (info == null || folder == null) continue;
if (info.container == LauncherSettings.Favorites.CONTAINER_DESKTOP &&
- info.screenId == currentScreen) {
+ info.screenId == currentScreenId) {
currentScreenFolders.put(id, folder);
} else {
otherScreenFolders.put(id, folder);
@@ -2220,8 +2404,11 @@ public class LauncherModel extends BroadcastReceiver {
ArrayList<ComponentName> mHiddenApps = new ArrayList<ComponentName>();
ArrayList<String> mHiddenAppsPackages = new ArrayList<String>();
Context context = mApp.getContext();
- String[] flattened = SettingsProvider.getStringCustomDefault(context,
- SettingsProvider.SETTINGS_UI_DRAWER_HIDDEN_APPS, "").split("\\|");
+ // Since Trebuchet is compiled using the SDK we have to hardcode this string
+ String protectedComponents = Settings.Secure.getString(context.getContentResolver(),
+ SETTINGS_PROTECTED_COMPONENTS);
+ protectedComponents = protectedComponents == null ? "" : protectedComponents;
+ String[] flattened = protectedComponents.split("\\|");
boolean hideShortcuts = SettingsProvider.getBoolean(context,
SettingsProvider.SETTINGS_UI_DRAWER_REMOVE_HIDDEN_APPS_SHORTCUTS,
R.bool.preferences_interface_drawer_remove_hidden_apps_shortcuts_default);
@@ -2251,20 +2438,30 @@ public class LauncherModel extends BroadcastReceiver {
}
}
} else {
+ // Only remove items from folders that aren't hidden
final FolderInfo folder = (FolderInfo)item;
List<ShortcutInfo> shortcuts = folder.contents;
+
int NN = shortcuts.size() - 1;
for (int j = NN; j >= 0; j--) {
ShortcutInfo sci = shortcuts.get(j);
if (sci.intent != null && sci.intent.getComponent() != null) {
- if (mHiddenApps.contains(sci.intent.getComponent())) {
- LauncherModel.deleteItemFromDatabase(mContext, sci);
- folder.remove(sci);
+ if (!folder.hidden){
+ if (mHiddenApps.contains(sci.intent.getComponent())) {
+ LauncherModel.deleteItemFromDatabase(mContext, sci);
+ folder.remove(sci);
+ }
+ } else {
+ if (!mHiddenApps.contains(sci.intent.getComponent())) {
+ LauncherModel.deleteItemFromDatabase(mContext, sci);
+ folder.remove(sci);
+ }
}
+
}
}
- if (folder.contents.size() == 1 /*&& !(folder instanceof LiveFolderInfo)*/) {
+ if (folder.contents.size() == 1 && !folder.hidden) {
ShortcutInfo finalItem = folder.contents.get(0);
finalItem.container = folder.container;
LauncherModel.deleteItemFromDatabase(mContext, folder);
@@ -2382,13 +2579,7 @@ public class LauncherModel extends BroadcastReceiver {
return;
}
- final boolean isLoadingSynchronously = (synchronizeBindPage > -1);
- final int currentScreen = isLoadingSynchronously ? synchronizeBindPage :
- oldCallbacks.getCurrentWorkspaceScreen();
-
- // Load all the items that are on the current page first (and in the process, unbind
- // all the existing workspace items before we call startBinding() below.
- unbindWorkspaceItemsOnMainThread();
+ // Save a copy of all the bg-thread collections
ArrayList<ItemInfo> workspaceItems = new ArrayList<ItemInfo>();
ArrayList<LauncherAppWidgetInfo> appWidgets =
new ArrayList<LauncherAppWidgetInfo>();
@@ -2403,6 +2594,23 @@ public class LauncherModel extends BroadcastReceiver {
orderedScreenIds.addAll(sBgWorkspaceScreens);
}
+ final boolean isLoadingSynchronously =
+ synchronizeBindPage != PagedView.INVALID_RESTORE_PAGE;
+ int currScreen = isLoadingSynchronously ? synchronizeBindPage :
+ oldCallbacks.getCurrentWorkspaceScreen();
+ if (currScreen >= orderedScreenIds.size()) {
+ // There may be no workspace screens (just hotseat items and an empty page).
+ currScreen = PagedView.INVALID_RESTORE_PAGE;
+ }
+ final int currentScreen = currScreen;
+ final long currentScreenId = currentScreen < 0
+ ? INVALID_SCREEN_ID : orderedScreenIds.get(currentScreen);
+
+ // Load all the items that are on the current page first (and in the process, unbind
+ // all the existing workspace items before we call startBinding() below.
+ unbindWorkspaceItemsOnMainThread();
+
+ // Separate the items that are on the current screen, and all the other remaining items
ArrayList<ItemInfo> currentWorkspaceItems = new ArrayList<ItemInfo>();
ArrayList<ItemInfo> otherWorkspaceItems = new ArrayList<ItemInfo>();
ArrayList<LauncherAppWidgetInfo> currentAppWidgets =
@@ -2412,12 +2620,11 @@ public class LauncherModel extends BroadcastReceiver {
HashMap<Long, FolderInfo> currentFolders = new HashMap<Long, FolderInfo>();
HashMap<Long, FolderInfo> otherFolders = new HashMap<Long, FolderInfo>();
- // Separate the items that are on the current screen, and all the other remaining items
- filterCurrentWorkspaceItems(currentScreen, workspaceItems, currentWorkspaceItems,
+ filterCurrentWorkspaceItems(currentScreenId, workspaceItems, currentWorkspaceItems,
otherWorkspaceItems);
- filterCurrentAppWidgets(currentScreen, appWidgets, currentAppWidgets,
+ filterCurrentAppWidgets(currentScreenId, appWidgets, currentAppWidgets,
otherAppWidgets);
- filterCurrentFolders(currentScreen, itemsIdMap, folders, currentFolders,
+ filterCurrentFolders(currentScreenId, itemsIdMap, folders, currentFolders,
otherFolders);
sortWorkspaceItemsSpatially(currentWorkspaceItems);
sortWorkspaceItemsSpatially(otherWorkspaceItems);
@@ -2442,7 +2649,7 @@ public class LauncherModel extends BroadcastReceiver {
r = new Runnable() {
public void run() {
Callbacks callbacks = tryGetCallbacks(oldCallbacks);
- if (callbacks != null) {
+ if (callbacks != null && currentScreen != PagedView.INVALID_RESTORE_PAGE) {
callbacks.onPageBoundSynchronously(currentScreen);
}
}
@@ -2643,6 +2850,7 @@ public class LauncherModel extends BroadcastReceiver {
case OP_ADD:
for (int i=0; i<N; i++) {
if (DEBUG_LOADERS) Log.d(TAG, "mAllAppsList.addPackage " + packages[i]);
+ mIconCache.remove(packages[i]);
mBgAllAppsList.addPackage(context, packages[i]);
}
break;
@@ -2690,14 +2898,14 @@ public class LauncherModel extends BroadcastReceiver {
if (added != null) {
// Ensure that we add all the workspace applications to the db
- Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;
- if (!AppsCustomizePagedView.DISABLE_ALL_APPS) {
- addAndBindAddedApps(context, new ArrayList<ItemInfo>(), cb, added);
- } else {
+ if (LauncherAppState.isDisableAllApps()) {
final ArrayList<ItemInfo> addedInfos = new ArrayList<ItemInfo>(added);
- addAndBindAddedApps(context, addedInfos, cb, added);
+ addAndBindAddedWorkspaceApps(context, addedInfos);
+ } else {
+ addAppsToAllApps(context, added);
}
}
+
if (modified != null) {
final ArrayList<AppInfo> modifiedFinal = modified;
@@ -2723,43 +2931,47 @@ public class LauncherModel extends BroadcastReceiver {
}
});
}
- // If a package has been removed, or an app has been removed as a result of
- // an update (for example), make the removed callback.
- if (mOp == OP_REMOVE || !removedApps.isEmpty()) {
- final boolean packageRemoved = (mOp == OP_REMOVE);
- final ArrayList<String> removedPackageNames =
- new ArrayList<String>(Arrays.asList(packages));
-
- // Update the launcher db to reflect the removal of apps
- if (packageRemoved) {
- for (String pn : removedPackageNames) {
- ArrayList<ItemInfo> infos = getItemInfoForPackageName(pn);
- for (ItemInfo i : infos) {
- deleteItemFromDatabase(context, i);
- }
- }
- // Remove any queued items from the install queue
- String spKey = LauncherAppState.getSharedPreferencesKey();
- SharedPreferences sp =
- context.getSharedPreferences(spKey, Context.MODE_PRIVATE);
- InstallShortcutReceiver.removeFromInstallQueue(sp, removedPackageNames);
- } else {
- for (AppInfo a : removedApps) {
- ArrayList<ItemInfo> infos =
- getItemInfoForComponentName(a.componentName);
- for (ItemInfo i : infos) {
- deleteItemFromDatabase(context, i);
- }
+ final ArrayList<String> removedPackageNames =
+ new ArrayList<String>();
+ if (mOp == OP_REMOVE) {
+ // Mark all packages in the broadcast to be removed
+ removedPackageNames.addAll(Arrays.asList(packages));
+ } else if (mOp == OP_UPDATE) {
+ // Mark disabled packages in the broadcast to be removed
+ final PackageManager pm = context.getPackageManager();
+ for (int i=0; i<N; i++) {
+ if (isPackageDisabled(pm, packages[i])) {
+ removedPackageNames.add(packages[i]);
}
}
-
+ }
+ // Remove all the components associated with this package
+ for (String pn : removedPackageNames) {
+ ArrayList<ItemInfo> infos = getItemInfoForPackageName(pn);
+ for (ItemInfo i : infos) {
+ deleteItemFromDatabase(context, i);
+ }
+ }
+ // Remove all the specific components
+ for (AppInfo a : removedApps) {
+ ArrayList<ItemInfo> infos = getItemInfoForComponentName(a.componentName);
+ for (ItemInfo i : infos) {
+ deleteItemFromDatabase(context, i);
+ }
+ }
+ if (!removedPackageNames.isEmpty() || !removedApps.isEmpty()) {
+ // Remove any queued items from the install queue
+ String spKey = LauncherAppState.getSharedPreferencesKey();
+ SharedPreferences sp =
+ context.getSharedPreferences(spKey, Context.MODE_PRIVATE);
+ InstallShortcutReceiver.removeFromInstallQueue(sp, removedPackageNames);
+ // Call the components-removed callback
mHandler.post(new Runnable() {
public void run() {
Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;
if (callbacks == cb && cb != null) {
- callbacks.bindComponentsRemoved(removedPackageNames,
- removedApps, packageRemoved);
+ callbacks.bindComponentsRemoved(removedPackageNames, removedApps);
}
}
});
@@ -2801,19 +3013,27 @@ public class LauncherModel extends BroadcastReceiver {
return widgetsAndShortcuts;
}
- private boolean isValidPackageComponent(PackageManager pm, ComponentName cn) {
+ private static boolean isPackageDisabled(PackageManager pm, String packageName) {
+ try {
+ PackageInfo pi = pm.getPackageInfo(packageName, 0);
+ return !pi.applicationInfo.enabled;
+ } catch (NameNotFoundException e) {
+ // Fall through
+ }
+ return false;
+ }
+
+ public static boolean isValidPackageComponent(PackageManager pm, ComponentName cn) {
if (cn == null) {
return false;
}
+ if (isPackageDisabled(pm, cn.getPackageName())) {
+ return false;
+ }
try {
- // Skip if the application is disabled
- PackageInfo pi = pm.getPackageInfo(cn.getPackageName(), 0);
- if (!pi.applicationInfo.enabled) {
- return false;
- }
-
// Check the activity
+ PackageInfo pi = pm.getPackageInfo(cn.getPackageName(), 0);
return (pm.getActivityInfo(cn, 0) != null);
} catch (NameNotFoundException e) {
return false;
@@ -2821,6 +3041,41 @@ public class LauncherModel extends BroadcastReceiver {
}
/**
+ * Make an ShortcutInfo object for a restored application or shortcut item that points
+ * to a package that is not yet installed on the system.
+ */
+ public ShortcutInfo getRestoredItemInfo(Cursor cursor, int titleIndex, Intent intent) {
+ final ShortcutInfo info = new ShortcutInfo();
+ if (cursor != null) {
+ info.title = cursor.getString(titleIndex);
+ } else {
+ info.title = "";
+ }
+ info.setIcon(mIconCache.getIcon(intent, info.title.toString()));
+ info.itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
+ info.restoredIntent = intent;
+ return info;
+ }
+
+ /**
+ * Make an Intent object for a restored application or shortcut item that points
+ * to the market page for the item.
+ */
+ private Intent getRestoredItemIntent(Cursor c, Context context, Intent intent) {
+ final boolean debug = false;
+ ComponentName componentName = intent.getComponent();
+ Intent marketIntent = new Intent(Intent.ACTION_VIEW);
+ Uri marketUri = new Uri.Builder()
+ .scheme("market")
+ .authority("details")
+ .appendQueryParameter("id", componentName.getPackageName())
+ .build();
+ if (debug) Log.d(TAG, "manufactured intent uri: " + marketUri.toString());
+ marketIntent.setData(marketUri);
+ return marketIntent;
+ }
+
+ /**
* This is called from the code that adds shortcuts from the intent receiver. This
* doesn't have a Cursor, but
*/
@@ -2983,6 +3238,10 @@ public class LauncherModel extends BroadcastReceiver {
Intent.ACTION_MAIN.equals(intent.getAction()) && name != null) {
return true;
}
+ // placeholder shortcuts get special treatment, let them through too.
+ if (info.getRestoredIntent() != null) {
+ return true;
+ }
}
return false;
}
diff --git a/src/com/android/launcher3/LauncherPreferencesBackupHelper.java b/src/com/android/launcher3/LauncherPreferencesBackupHelper.java
new file mode 100644
index 000000000..6f9c05c88
--- /dev/null
+++ b/src/com/android/launcher3/LauncherPreferencesBackupHelper.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3;
+
+import android.app.backup.BackupDataInputStream;
+import android.app.backup.SharedPreferencesBackupHelper;
+import android.content.Context;
+import android.util.Log;
+
+public class LauncherPreferencesBackupHelper extends SharedPreferencesBackupHelper {
+
+ private static final String TAG = "LauncherPreferencesBackupHelper";
+ private static final boolean VERBOSE = LauncherBackupAgentHelper.VERBOSE;
+
+ private final boolean mRestoreEnabled;
+
+ public LauncherPreferencesBackupHelper(Context context, String sharedPreferencesKey,
+ boolean restoreEnabled) {
+ super(context, sharedPreferencesKey);
+ mRestoreEnabled = restoreEnabled;
+ }
+
+ @Override
+ public void restoreEntity(BackupDataInputStream data) {
+ if (mRestoreEnabled) {
+ if (VERBOSE) Log.v(TAG, "restoring preferences");
+ super.restoreEntity(data);
+ }
+ }
+}
diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java
index 359a40323..9a2cb5070 100644
--- a/src/com/android/launcher3/LauncherProvider.java
+++ b/src/com/android/launcher3/LauncherProvider.java
@@ -22,13 +22,17 @@ import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProviderInfo;
import android.content.ComponentName;
import android.content.ContentProvider;
+import android.content.ContentProviderOperation;
+import android.content.ContentProviderResult;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
+import android.content.OperationApplicationException;
import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
+import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.content.res.TypedArray;
@@ -48,6 +52,7 @@ import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
+import android.util.SparseArray;
import android.util.Xml;
import com.android.launcher3.LauncherSettings.Favorites;
@@ -56,12 +61,12 @@ import com.android.launcher3.config.ProviderConfig;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
+import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
-import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
-import java.util.concurrent.atomic.AtomicBoolean;
public class LauncherProvider extends ContentProvider {
private static final String TAG = "Launcher.LauncherProvider";
@@ -69,11 +74,14 @@ public class LauncherProvider extends ContentProvider {
private static final String DATABASE_NAME = "launcher.db";
- private static final int DATABASE_VERSION = 17;
+ private static final int DATABASE_VERSION = 20;
static final String OLD_AUTHORITY = "com.android.launcher2.settings";
static final String AUTHORITY = ProviderConfig.AUTHORITY;
+ // Should we attempt to load anything from the com.android.launcher2 provider?
+ static final boolean IMPORT_LAUNCHER2_DATABASE = false;
+
static final String TABLE_FAVORITES = "favorites";
static final String TABLE_WORKSPACE_SCREENS = "workspaceScreens";
static final String PARAMETER_NOTIFY = "notify";
@@ -106,6 +114,10 @@ public class LauncherProvider extends ContentProvider {
return true;
}
+ public boolean wasNewDbCreated() {
+ return mOpenHelper.wasNewDbCreated();
+ }
+
@Override
public String getType(Uri uri) {
SqlArguments args = new SqlArguments(uri, null, null);
@@ -133,9 +145,13 @@ public class LauncherProvider extends ContentProvider {
private static long dbInsertAndCheck(DatabaseHelper helper,
SQLiteDatabase db, String table, String nullColumnHack, ContentValues values) {
- if (!values.containsKey(LauncherSettings.Favorites._ID)) {
+ if (values == null) {
+ throw new RuntimeException("Error: attempting to insert null values");
+ }
+ if (!values.containsKey(LauncherSettings.BaseLauncherColumns._ID)) {
throw new RuntimeException("Error: attempting to add item without specifying an id");
}
+ helper.checkId(table, values);
return db.insert(table, nullColumnHack, values);
}
@@ -184,6 +200,20 @@ public class LauncherProvider extends ContentProvider {
}
@Override
+ public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations)
+ throws OperationApplicationException {
+ SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+ db.beginTransaction();
+ try {
+ ContentProviderResult[] result = super.applyBatch(operations);
+ db.setTransactionSuccessful();
+ return result;
+ } finally {
+ db.endTransaction();
+ }
+ }
+
+ @Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
SqlArguments args = new SqlArguments(uri, selection, selectionArgs);
@@ -266,15 +296,22 @@ public class LauncherProvider extends ContentProvider {
SharedPreferences sp = getContext().getSharedPreferences(spKey, Context.MODE_PRIVATE);
if (sp.getBoolean(EMPTY_DATABASE_CREATED, false)) {
+ Log.d(TAG, "loading default workspace");
int workspaceResId = origWorkspaceResId;
// Use default workspace resource if none provided
if (workspaceResId == 0) {
TelephonyManager tm = (TelephonyManager) getContext().getSystemService(Context.TELEPHONY_SERVICE);
if (tm.getPhoneType() == TelephonyManager.PHONE_TYPE_NONE) {
- workspaceResId = sp.getInt(DEFAULT_WORKSPACE_RESOURCE_ID, R.xml.default_workspace_no_telephony);
+ if (areGAppsInstalled()) {
+ workspaceResId = sp.getInt(DEFAULT_WORKSPACE_RESOURCE_ID,
+ R.xml.default_workspace_no_telephony_gapps);
+ } else {
+ workspaceResId = sp.getInt(DEFAULT_WORKSPACE_RESOURCE_ID,
+ R.xml.default_workspace_no_telephony);
+ }
} else {
- workspaceResId = sp.getInt(DEFAULT_WORKSPACE_RESOURCE_ID, R.xml.default_workspace);
+ workspaceResId = sp.getInt(DEFAULT_WORKSPACE_RESOURCE_ID, getDefaultWorkspaceResourceId());
}
}
@@ -291,10 +328,59 @@ public class LauncherProvider extends ContentProvider {
}
}
+ private boolean areGAppsInstalled() {
+ PackageManager pm = getContext().getPackageManager();
+ try {
+ PackageInfo info = pm.getPackageInfo("com.google.android.gsf",PackageManager.GET_META_DATA);
+ } catch (PackageManager.NameNotFoundException e) {
+ return false;
+ }
+ return true;
+ }
+
+ public void migrateLauncher2Shortcuts() {
+ mOpenHelper.migrateLauncher2Shortcuts(mOpenHelper.getWritableDatabase(),
+ LauncherSettings.Favorites.OLD_CONTENT_URI);
+ }
+
+ private int getDefaultWorkspaceResourceId() {
+ if (LauncherAppState.isDisableAllApps()) {
+ if (areGAppsInstalled()){
+ return R.xml.default_workspace_no_all_apps_gapps;
+ } else {
+ return R.xml.default_workspace_no_all_apps;
+ }
+ } else {
+ if (areGAppsInstalled()){
+ return R.xml.default_workspace_gapps;
+ } else {
+ return R.xml.default_workspace;
+ }
+ }
+ }
+
private static interface ContentValuesCallback {
public void onRow(ContentValues values);
}
+ private static boolean shouldImportLauncher2Database(Context context) {
+ boolean isTablet = context.getResources().getBoolean(R.bool.is_tablet);
+
+ // We don't import the old databse for tablets, as the grid size has changed.
+ return !isTablet && IMPORT_LAUNCHER2_DATABASE;
+ }
+
+ public void deleteDatabase() {
+ // Are you sure? (y/n)
+ final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+ final File dbFile = new File(db.getPath());
+ mOpenHelper.close();
+ if (dbFile.exists()) {
+ SQLiteDatabase.deleteDatabase(dbFile);
+ }
+ mOpenHelper = new DatabaseHelper(getContext());
+ }
+
private static class DatabaseHelper extends SQLiteOpenHelper {
private static final String TAG_FAVORITES = "favorites";
private static final String TAG_FAVORITE = "favorite";
@@ -311,6 +397,8 @@ public class LauncherProvider extends ContentProvider {
private long mMaxItemId = -1;
private long mMaxScreenId = -1;
+ private boolean mNewDbCreated = false;
+
DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
mContext = context;
@@ -326,6 +414,10 @@ public class LauncherProvider extends ContentProvider {
}
}
+ public boolean wasNewDbCreated() {
+ return mNewDbCreated;
+ }
+
/**
* Send notification that we've deleted the {@link AppWidgetHost},
* probably as part of the initial database creation. The receiver may
@@ -343,6 +435,7 @@ public class LauncherProvider extends ContentProvider {
mMaxItemId = 1;
mMaxScreenId = 0;
+ mNewDbCreated = true;
db.execSQL("CREATE TABLE favorites (" +
"_id INTEGER PRIMARY KEY," +
@@ -364,7 +457,9 @@ public class LauncherProvider extends ContentProvider {
"uri TEXT," +
"displayMode INTEGER," +
"appWidgetProvider TEXT," +
- "modified INTEGER NOT NULL DEFAULT 0" +
+ "modified INTEGER NOT NULL DEFAULT 0," +
+ "restored INTEGER NOT NULL DEFAULT 0," +
+ "hidden INTEGER DEFAULT 0" +
");");
addWorkspacesTable(db);
@@ -374,32 +469,38 @@ public class LauncherProvider extends ContentProvider {
sendAppWidgetResetNotify();
}
- // Try converting the old database
- ContentValuesCallback permuteScreensCb = new ContentValuesCallback() {
- public void onRow(ContentValues values) {
- int container = values.getAsInteger(LauncherSettings.Favorites.CONTAINER);
- if (container == Favorites.CONTAINER_DESKTOP) {
- int screen = values.getAsInteger(LauncherSettings.Favorites.SCREEN);
- screen = (int) upgradeLauncherDb_permuteScreens(screen);
- values.put(LauncherSettings.Favorites.SCREEN, screen);
+ if (shouldImportLauncher2Database(mContext)) {
+ // Try converting the old database
+ ContentValuesCallback permuteScreensCb = new ContentValuesCallback() {
+ public void onRow(ContentValues values) {
+ int container = values.getAsInteger(LauncherSettings.Favorites.CONTAINER);
+ if (container == Favorites.CONTAINER_DESKTOP) {
+ int screen = values.getAsInteger(LauncherSettings.Favorites.SCREEN);
+ screen = (int) upgradeLauncherDb_permuteScreens(screen);
+ values.put(LauncherSettings.Favorites.SCREEN, screen);
+ }
+ }
+ };
+ Uri uri = Uri.parse("content://" + Settings.AUTHORITY +
+ "/old_favorites?notify=true");
+ if (!convertDatabase(db, uri, permuteScreensCb, true)) {
+ // Try and upgrade from the Launcher2 db
+ uri = LauncherSettings.Favorites.OLD_CONTENT_URI;
+ if (!convertDatabase(db, uri, permuteScreensCb, false)) {
+ // If we fail, then set a flag to load the default workspace
+ setFlagEmptyDbCreated();
+ return;
}
}
- };
- Uri uri = Uri.parse("content://" + Settings.AUTHORITY +
- "/old_favorites?notify=true");
- if (!convertDatabase(db, uri, permuteScreensCb, true)) {
- // Try and upgrade from the Launcher2 db
- uri = LauncherSettings.Favorites.OLD_CONTENT_URI;
- if (!convertDatabase(db, uri, permuteScreensCb, false)) {
- // If we fail, then set a flag to load the default workspace
- setFlagEmptyDbCreated();
- return;
- }
+ // Right now, in non-default workspace cases, we want to run the final
+ // upgrade code (ie. to fix workspace screen indices -> ids, etc.), so
+ // set that flag too.
+ setFlagJustLoadedOldDb();
+ } else {
+ // Fresh and clean launcher DB.
+ mMaxItemId = initializeMaxItemId(db);
+ setFlagEmptyDbCreated();
}
- // Right now, in non-default workspace cases, we want to run the final
- // upgrade code (ie. to fix workspace screen indices -> ids, etc.), so
- // set that flag too.
- setFlagJustLoadedOldDb();
}
private void addWorkspacesTable(SQLiteDatabase db) {
@@ -670,7 +771,6 @@ public class LauncherProvider extends ContentProvider {
}
}
-
if (version < 15) {
db.beginTransaction();
try {
@@ -747,7 +847,6 @@ public class LauncherProvider extends ContentProvider {
}
}
-
// Artificially inflate the version to make sure we're fully up to date
// after a possible 10.2-Trebuchet migration
@@ -755,6 +854,37 @@ public class LauncherProvider extends ContentProvider {
version = 17;
}
+ if (version < 18) {
+ db.beginTransaction();
+ try {
+ // Insert new column for holding restore status
+ db.execSQL("ALTER TABLE favorites " +
+ "ADD COLUMN restored INTEGER NOT NULL DEFAULT 0;");
+ db.setTransactionSuccessful();
+ version = 18;
+ } catch (SQLException ex) {
+ // Old version remains, which means we wipe old data
+ Log.e(TAG, ex.getMessage(), ex);
+ } finally {
+ db.endTransaction();
+ }
+ }
+
+ if (version < 19) {
+ // We use the db version upgrade here to identify users who may not have seen
+ // clings yet (because they weren't available), but for whom the clings are now
+ // available (tablet users). Because one of the possible cling flows (migration)
+ // is very destructive (wipes out workspaces), we want to prevent this from showing
+ // until clear data. We do so by marking that the clings have been shown.
+ LauncherClings.synchonouslyMarkFirstRunClingDismissed(mContext);
+ version = 19;
+ }
+
+ if (oldVersion < 20) {
+ db.execSQL("ALTER TABLE favorites ADD hidden INTEGER DEFAULT 0");
+ version = 20;
+ }
+
if (version != DATABASE_VERSION) {
Log.w(TAG, "Destroying all old data.");
db.execSQL("DROP TABLE IF EXISTS " + TABLE_FAVORITES);
@@ -917,6 +1047,15 @@ public class LauncherProvider extends ContentProvider {
mMaxItemId = id + 1;
}
+ public void checkId(String table, ContentValues values) {
+ long id = values.getAsLong(LauncherSettings.BaseLauncherColumns._ID);
+ if (table == LauncherProvider.TABLE_WORKSPACE_SCREENS) {
+ mMaxScreenId = Math.max(id, mMaxScreenId);
+ } else {
+ mMaxItemId = Math.max(id, mMaxItemId);
+ }
+ }
+
private long initializeMaxItemId(SQLiteDatabase db) {
Cursor c = db.rawQuery("SELECT MAX(_id) FROM favorites", null);
@@ -947,10 +1086,14 @@ public class LauncherProvider extends ContentProvider {
throw new RuntimeException("Error: max screen id was not initialized");
}
mMaxScreenId += 1;
+ // Log to disk
+ Launcher.addDumpLog(TAG, "11683562 - generateNewScreenId(): " + mMaxScreenId, true);
return mMaxScreenId;
}
public void updateMaxScreenId(long maxScreenId) {
+ // Log to disk
+ Launcher.addDumpLog(TAG, "11683562 - updateMaxScreenId(): " + maxScreenId, true);
mMaxScreenId = maxScreenId;
}
@@ -971,6 +1114,8 @@ public class LauncherProvider extends ContentProvider {
throw new RuntimeException("Error: could not query max screen id");
}
+ // Log to disk
+ Launcher.addDumpLog(TAG, "11683562 - initializeMaxScreenId(): " + id, true);
return id;
}
@@ -1102,10 +1247,6 @@ public class LauncherProvider extends ContentProvider {
final int depth = parser.getDepth();
- final HashMap<Long, ItemInfo[][]> occupied = new HashMap<Long, ItemInfo[][]>();
- LauncherModel model = LauncherAppState.getInstance().getModel();
- AtomicBoolean deleteItem = new AtomicBoolean();
-
int type;
while (((type = parser.next()) != XmlPullParser.END_TAG ||
parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {
@@ -1129,7 +1270,6 @@ public class LauncherProvider extends ContentProvider {
// recursively load some more favorites, why not?
i += loadFavorites(db, resId);
added = false;
- mMaxItemId = -1;
} else {
Log.w(TAG, String.format("Skipping <include workspace=0x%08x>", resId));
}
@@ -1158,18 +1298,6 @@ public class LauncherProvider extends ContentProvider {
values.put(LauncherSettings.Favorites.CELLX, x);
values.put(LauncherSettings.Favorites.CELLY, y);
- ItemInfo info = new ItemInfo();
- info.container = container;
- info.spanX = a.getInt(R.styleable.Favorite_spanX, 1);
- info.spanY = a.getInt(R.styleable.Favorite_spanY, 1);
- info.cellX = a.getInt(R.styleable.Favorite_x, 0);
- info.cellY = a.getInt(R.styleable.Favorite_y, 0);
- info.screenId = a.getInt(R.styleable.Favorite_screen, 0);
-
- if (!model.checkItemPlacement(occupied, info, deleteItem)) {
- continue;
- }
-
if (LOGD) {
final String title = a.getString(R.styleable.Favorite_title);
final String pkg = a.getString(R.styleable.Favorite_packageName);
@@ -1256,22 +1384,7 @@ public class LauncherProvider extends ContentProvider {
added = false;
}
}
- if (added) {
- i++;
- } else {
- long containerIndex = info.screenId;
- if (info.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
- occupied.get((long) LauncherSettings.Favorites.CONTAINER_HOTSEAT)
- [(int) info.screenId][0] = null;
- } else {
- ItemInfo[][] screens = occupied.get(info.screenId);
- for (int gridX = info.cellX; gridX < (info.cellX+info.spanX); gridX++) {
- for (int gridY = info.cellY; gridY < (info.cellY+info.spanY); gridY++) {
- screens[gridX][gridY] = null;
- }
- }
- }
- }
+ if (added) i++;
a.recycle();
}
} catch (XmlPullParserException e) {
@@ -1511,6 +1624,273 @@ public class LauncherProvider extends ContentProvider {
}
return id;
}
+
+ public void migrateLauncher2Shortcuts(SQLiteDatabase db, Uri uri) {
+ final ContentResolver resolver = mContext.getContentResolver();
+ Cursor c = null;
+ int count = 0;
+ int curScreen = 0;
+
+ try {
+ c = resolver.query(uri, null, null, null, "title ASC");
+ } catch (Exception e) {
+ // Ignore
+ }
+
+ // We already have a favorites database in the old provider
+ if (c != null) {
+ try {
+ if (c.getCount() > 0) {
+ final int idIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites._ID);
+ final int intentIndex
+ = c.getColumnIndexOrThrow(LauncherSettings.Favorites.INTENT);
+ final int titleIndex
+ = c.getColumnIndexOrThrow(LauncherSettings.Favorites.TITLE);
+ final int iconTypeIndex
+ = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON_TYPE);
+ final int iconIndex
+ = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON);
+ final int iconPackageIndex
+ = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON_PACKAGE);
+ final int iconResourceIndex
+ = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON_RESOURCE);
+ final int containerIndex
+ = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CONTAINER);
+ final int itemTypeIndex
+ = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ITEM_TYPE);
+ final int screenIndex
+ = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SCREEN);
+ final int cellXIndex
+ = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLX);
+ final int cellYIndex
+ = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLY);
+ final int uriIndex
+ = c.getColumnIndexOrThrow(LauncherSettings.Favorites.URI);
+ final int displayModeIndex
+ = c.getColumnIndexOrThrow(LauncherSettings.Favorites.DISPLAY_MODE);
+
+ int i = 0;
+ int curX = 0;
+ int curY = 0;
+
+ final LauncherAppState app = LauncherAppState.getInstance();
+ final DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
+ final int width = (int) grid.numColumns;
+ final int height = (int) grid.numRows;
+ final int hotseatWidth = (int) grid.numHotseatIcons;
+ PackageManager pm = mContext.getPackageManager();
+
+ final HashSet<String> seenIntents = new HashSet<String>(c.getCount());
+
+ final ArrayList<ContentValues> shortcuts = new ArrayList<ContentValues>();
+ final ArrayList<ContentValues> folders = new ArrayList<ContentValues>();
+ final SparseArray<ContentValues> hotseat = new SparseArray<ContentValues>();
+
+ while (c.moveToNext()) {
+ final int itemType = c.getInt(itemTypeIndex);
+ if (itemType != Favorites.ITEM_TYPE_APPLICATION
+ && itemType != Favorites.ITEM_TYPE_SHORTCUT
+ && itemType != Favorites.ITEM_TYPE_FOLDER) {
+ continue;
+ }
+
+ final int cellX = c.getInt(cellXIndex);
+ final int cellY = c.getInt(cellYIndex);
+ final int screen = c.getInt(screenIndex);
+ int container = c.getInt(containerIndex);
+ final String intentStr = c.getString(intentIndex);
+ Launcher.addDumpLog(TAG, "migrating \""
+ + c.getString(titleIndex) + "\" ("
+ + cellX + "," + cellY + "@"
+ + LauncherSettings.Favorites.containerToString(container)
+ + "/" + screen
+ + "): " + intentStr, true);
+
+ if (itemType != Favorites.ITEM_TYPE_FOLDER) {
+
+ final Intent intent;
+ final ComponentName cn;
+ try {
+ intent = Intent.parseUri(intentStr, 0);
+ } catch (URISyntaxException e) {
+ // bogus intent?
+ Launcher.addDumpLog(TAG,
+ "skipping invalid intent uri", true);
+ continue;
+ }
+
+ cn = intent.getComponent();
+ if (TextUtils.isEmpty(intentStr)) {
+ // no intent? no icon
+ Launcher.addDumpLog(TAG, "skipping empty intent", true);
+ continue;
+ } else if (cn != null &&
+ !LauncherModel.isValidPackageComponent(pm, cn)) {
+ // component no longer exists.
+ Launcher.addDumpLog(TAG, "skipping item whose component " +
+ "no longer exists.", true);
+ continue;
+ } else if (container ==
+ LauncherSettings.Favorites.CONTAINER_DESKTOP) {
+ // Dedupe icons directly on the workspace
+
+ // Canonicalize
+ // the Play Store sets the package parameter, but Launcher
+ // does not, so we clear that out to keep them the same
+ intent.setPackage(null);
+ final String key = intent.toUri(0);
+ if (seenIntents.contains(key)) {
+ Launcher.addDumpLog(TAG, "skipping duplicate", true);
+ continue;
+ } else {
+ seenIntents.add(key);
+ }
+ }
+ }
+
+ ContentValues values = new ContentValues(c.getColumnCount());
+ values.put(LauncherSettings.Favorites._ID, c.getInt(idIndex));
+ values.put(LauncherSettings.Favorites.INTENT, intentStr);
+ values.put(LauncherSettings.Favorites.TITLE, c.getString(titleIndex));
+ values.put(LauncherSettings.Favorites.ICON_TYPE,
+ c.getInt(iconTypeIndex));
+ values.put(LauncherSettings.Favorites.ICON, c.getBlob(iconIndex));
+ values.put(LauncherSettings.Favorites.ICON_PACKAGE,
+ c.getString(iconPackageIndex));
+ values.put(LauncherSettings.Favorites.ICON_RESOURCE,
+ c.getString(iconResourceIndex));
+ values.put(LauncherSettings.Favorites.ITEM_TYPE, itemType);
+ values.put(LauncherSettings.Favorites.APPWIDGET_ID, -1);
+ values.put(LauncherSettings.Favorites.URI, c.getString(uriIndex));
+ values.put(LauncherSettings.Favorites.DISPLAY_MODE,
+ c.getInt(displayModeIndex));
+
+ if (container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
+ hotseat.put(screen, values);
+ }
+
+ if (container != LauncherSettings.Favorites.CONTAINER_DESKTOP) {
+ // In a folder or in the hotseat, preserve position
+ values.put(LauncherSettings.Favorites.SCREEN, screen);
+ values.put(LauncherSettings.Favorites.CELLX, cellX);
+ values.put(LauncherSettings.Favorites.CELLY, cellY);
+ } else {
+ // For items contained directly on one of the workspace screen,
+ // we'll determine their location (screen, x, y) in a second pass.
+ }
+
+ values.put(LauncherSettings.Favorites.CONTAINER, container);
+
+ if (itemType != Favorites.ITEM_TYPE_FOLDER) {
+ shortcuts.add(values);
+ } else {
+ folders.add(values);
+ }
+ }
+
+ // Now that we have all the hotseat icons, let's go through them left-right
+ // and assign valid locations for them in the new hotseat
+ final int N = hotseat.size();
+ for (int idx=0; idx<N; idx++) {
+ int hotseatX = hotseat.keyAt(idx);
+ ContentValues values = hotseat.valueAt(idx);
+
+ if (hotseatX == grid.hotseatAllAppsRank) {
+ // let's drop this in the next available hole in the hotseat
+ while (++hotseatX < hotseatWidth) {
+ if (hotseat.get(hotseatX) == null) {
+ // found a spot! move it here
+ values.put(LauncherSettings.Favorites.SCREEN,
+ hotseatX);
+ break;
+ }
+ }
+ }
+ if (hotseatX >= hotseatWidth) {
+ // no room for you in the hotseat? it's off to the desktop with you
+ values.put(LauncherSettings.Favorites.CONTAINER,
+ Favorites.CONTAINER_DESKTOP);
+ }
+ }
+
+ final ArrayList<ContentValues> allItems = new ArrayList<ContentValues>();
+ // Folders first
+ allItems.addAll(folders);
+ // Then shortcuts
+ allItems.addAll(shortcuts);
+
+ // Layout all the folders
+ for (ContentValues values: allItems) {
+ if (values.getAsInteger(LauncherSettings.Favorites.CONTAINER) !=
+ LauncherSettings.Favorites.CONTAINER_DESKTOP) {
+ // Hotseat items and folder items have already had their
+ // location information set. Nothing to be done here.
+ continue;
+ }
+ values.put(LauncherSettings.Favorites.SCREEN, curScreen);
+ values.put(LauncherSettings.Favorites.CELLX, curX);
+ values.put(LauncherSettings.Favorites.CELLY, curY);
+ curX = (curX + 1) % width;
+ if (curX == 0) {
+ curY = (curY + 1);
+ }
+ // Leave the last row of icons blank on every screen
+ if (curY == height - 1) {
+ curScreen = (int) generateNewScreenId();
+ curY = 0;
+ }
+ }
+
+ if (allItems.size() > 0) {
+ db.beginTransaction();
+ try {
+ for (ContentValues row: allItems) {
+ if (row == null) continue;
+ if (dbInsertAndCheck(this, db, TABLE_FAVORITES, null, row)
+ < 0) {
+ return;
+ } else {
+ count++;
+ }
+ }
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ }
+ }
+
+ db.beginTransaction();
+ try {
+ for (i=0; i<=curScreen; i++) {
+ final ContentValues values = new ContentValues();
+ values.put(LauncherSettings.WorkspaceScreens._ID, i);
+ values.put(LauncherSettings.WorkspaceScreens.SCREEN_RANK, i);
+ if (dbInsertAndCheck(this, db, TABLE_WORKSPACE_SCREENS, null, values)
+ < 0) {
+ return;
+ }
+ }
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ }
+ }
+ } finally {
+ c.close();
+ }
+ }
+
+ Launcher.addDumpLog(TAG, "migrated " + count + " icons from Launcher2 into "
+ + (curScreen+1) + " screens", true);
+
+ // ensure that new screens are created to hold these icons
+ setFlagJustLoadedOldDb();
+
+ // Update max IDs; very important since we just grabbed IDs from another database
+ mMaxItemId = initializeMaxItemId(db);
+ mMaxScreenId = initializeMaxScreenId(db);
+ if (LOGD) Log.d(TAG, "mMaxItemId: " + mMaxItemId + " mMaxScreenId: " + mMaxScreenId);
+ }
}
/**
diff --git a/src/com/android/launcher3/LauncherScroller.java b/src/com/android/launcher3/LauncherScroller.java
new file mode 100644
index 000000000..3bd0a78c4
--- /dev/null
+++ b/src/com/android/launcher3/LauncherScroller.java
@@ -0,0 +1,559 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3;
+
+import android.animation.TimeInterpolator;
+import android.content.Context;
+import android.hardware.SensorManager;
+import android.os.Build;
+import android.util.FloatMath;
+import android.view.ViewConfiguration;
+import android.view.animation.AnimationUtils;
+import android.view.animation.Interpolator;
+
+/**
+ * This class differs from the framework {@link android.widget.Scroller} in that
+ * you can modify the Interpolator post-construction.
+ */
+public class LauncherScroller {
+ private int mMode;
+
+ private int mStartX;
+ private int mStartY;
+ private int mFinalX;
+ private int mFinalY;
+
+ private int mMinX;
+ private int mMaxX;
+ private int mMinY;
+ private int mMaxY;
+
+ private int mCurrX;
+ private int mCurrY;
+ private long mStartTime;
+ private int mDuration;
+ private float mDurationReciprocal;
+ private float mDeltaX;
+ private float mDeltaY;
+ private boolean mFinished;
+ private TimeInterpolator mInterpolator;
+ private boolean mFlywheel;
+
+ private float mVelocity;
+ private float mCurrVelocity;
+ private int mDistance;
+
+ private float mFlingFriction = ViewConfiguration.getScrollFriction();
+
+ private static final int DEFAULT_DURATION = 250;
+ private static final int SCROLL_MODE = 0;
+ private static final int FLING_MODE = 1;
+
+ private static float DECELERATION_RATE = (float) (Math.log(0.78) / Math.log(0.9));
+ private static final float INFLEXION = 0.35f; // Tension lines cross at (INFLEXION, 1)
+ private static final float START_TENSION = 0.5f;
+ private static final float END_TENSION = 1.0f;
+ private static final float P1 = START_TENSION * INFLEXION;
+ private static final float P2 = 1.0f - END_TENSION * (1.0f - INFLEXION);
+
+ private static final int NB_SAMPLES = 100;
+ private static final float[] SPLINE_POSITION = new float[NB_SAMPLES + 1];
+ private static final float[] SPLINE_TIME = new float[NB_SAMPLES + 1];
+
+ private float mDeceleration;
+ private final float mPpi;
+
+ // A context-specific coefficient adjusted to physical values.
+ private float mPhysicalCoeff;
+
+ static {
+ float x_min = 0.0f;
+ float y_min = 0.0f;
+ for (int i = 0; i < NB_SAMPLES; i++) {
+ final float alpha = (float) i / NB_SAMPLES;
+
+ float x_max = 1.0f;
+ float x, tx, coef;
+ while (true) {
+ x = x_min + (x_max - x_min) / 2.0f;
+ coef = 3.0f * x * (1.0f - x);
+ tx = coef * ((1.0f - x) * P1 + x * P2) + x * x * x;
+ if (Math.abs(tx - alpha) < 1E-5) break;
+ if (tx > alpha) x_max = x;
+ else x_min = x;
+ }
+ SPLINE_POSITION[i] = coef * ((1.0f - x) * START_TENSION + x) + x * x * x;
+
+ float y_max = 1.0f;
+ float y, dy;
+ while (true) {
+ y = y_min + (y_max - y_min) / 2.0f;
+ coef = 3.0f * y * (1.0f - y);
+ dy = coef * ((1.0f - y) * START_TENSION + y) + y * y * y;
+ if (Math.abs(dy - alpha) < 1E-5) break;
+ if (dy > alpha) y_max = y;
+ else y_min = y;
+ }
+ SPLINE_TIME[i] = coef * ((1.0f - y) * P1 + y * P2) + y * y * y;
+ }
+ SPLINE_POSITION[NB_SAMPLES] = SPLINE_TIME[NB_SAMPLES] = 1.0f;
+
+ // This controls the viscous fluid effect (how much of it)
+ sViscousFluidScale = 8.0f;
+ // must be set to 1.0 (used in viscousFluid())
+ sViscousFluidNormalize = 1.0f;
+ sViscousFluidNormalize = 1.0f / viscousFluid(1.0f);
+
+ }
+
+ private static float sViscousFluidScale;
+ private static float sViscousFluidNormalize;
+
+ public void setInterpolator(TimeInterpolator interpolator) {
+ mInterpolator = interpolator;
+ }
+
+ /**
+ * Create a Scroller with the default duration and interpolator.
+ */
+ public LauncherScroller(Context context) {
+ this(context, null);
+ }
+
+ /**
+ * Create a Scroller with the specified interpolator. If the interpolator is
+ * null, the default (viscous) interpolator will be used. "Flywheel" behavior will
+ * be in effect for apps targeting Honeycomb or newer.
+ */
+ public LauncherScroller(Context context, Interpolator interpolator) {
+ this(context, interpolator,
+ context.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.HONEYCOMB);
+ }
+
+ /**
+ * Create a Scroller with the specified interpolator. If the interpolator is
+ * null, the default (viscous) interpolator will be used. Specify whether or
+ * not to support progressive "flywheel" behavior in flinging.
+ */
+ public LauncherScroller(Context context, Interpolator interpolator, boolean flywheel) {
+ mFinished = true;
+ mInterpolator = interpolator;
+ mPpi = context.getResources().getDisplayMetrics().density * 160.0f;
+ mDeceleration = computeDeceleration(ViewConfiguration.getScrollFriction());
+ mFlywheel = flywheel;
+
+ mPhysicalCoeff = computeDeceleration(0.84f); // look and feel tuning
+ }
+
+ /**
+ * The amount of friction applied to flings. The default value
+ * is {@link ViewConfiguration#getScrollFriction}.
+ *
+ * @param friction A scalar dimension-less value representing the coefficient of
+ * friction.
+ */
+ public final void setFriction(float friction) {
+ mDeceleration = computeDeceleration(friction);
+ mFlingFriction = friction;
+ }
+
+ private float computeDeceleration(float friction) {
+ return SensorManager.GRAVITY_EARTH // g (m/s^2)
+ * 39.37f // inch/meter
+ * mPpi // pixels per inch
+ * friction;
+ }
+
+ /**
+ *
+ * Returns whether the scroller has finished scrolling.
+ *
+ * @return True if the scroller has finished scrolling, false otherwise.
+ */
+ public final boolean isFinished() {
+ return mFinished;
+ }
+
+ /**
+ * Force the finished field to a particular value.
+ *
+ * @param finished The new finished value.
+ */
+ public final void forceFinished(boolean finished) {
+ mFinished = finished;
+ }
+
+ /**
+ * Returns how long the scroll event will take, in milliseconds.
+ *
+ * @return The duration of the scroll in milliseconds.
+ */
+ public final int getDuration() {
+ return mDuration;
+ }
+
+ /**
+ * Returns the current X offset in the scroll.
+ *
+ * @return The new X offset as an absolute distance from the origin.
+ */
+ public final int getCurrX() {
+ return mCurrX;
+ }
+
+ /**
+ * Returns the current Y offset in the scroll.
+ *
+ * @return The new Y offset as an absolute distance from the origin.
+ */
+ public final int getCurrY() {
+ return mCurrY;
+ }
+
+ /**
+ * Returns the current velocity.
+ *
+ * @return The original velocity less the deceleration. Result may be
+ * negative.
+ */
+ public float getCurrVelocity() {
+ return mMode == FLING_MODE ?
+ mCurrVelocity : mVelocity - mDeceleration * timePassed() / 2000.0f;
+ }
+
+ /**
+ * Returns the start X offset in the scroll.
+ *
+ * @return The start X offset as an absolute distance from the origin.
+ */
+ public final int getStartX() {
+ return mStartX;
+ }
+
+ /**
+ * Returns the start Y offset in the scroll.
+ *
+ * @return The start Y offset as an absolute distance from the origin.
+ */
+ public final int getStartY() {
+ return mStartY;
+ }
+
+ /**
+ * Returns where the scroll will end. Valid only for "fling" scrolls.
+ *
+ * @return The final X offset as an absolute distance from the origin.
+ */
+ public final int getFinalX() {
+ return mFinalX;
+ }
+
+ /**
+ * Returns where the scroll will end. Valid only for "fling" scrolls.
+ *
+ * @return The final Y offset as an absolute distance from the origin.
+ */
+ public final int getFinalY() {
+ return mFinalY;
+ }
+
+ /**
+ * Call this when you want to know the new location. If it returns true,
+ * the animation is not yet finished.
+ */
+ public boolean computeScrollOffset() {
+ if (mFinished) {
+ return false;
+ }
+
+ int timePassed = (int)(AnimationUtils.currentAnimationTimeMillis() - mStartTime);
+
+ if (timePassed < mDuration) {
+ switch (mMode) {
+ case SCROLL_MODE:
+ float x = timePassed * mDurationReciprocal;
+
+ if (mInterpolator == null)
+ x = viscousFluid(x);
+ else
+ x = mInterpolator.getInterpolation(x);
+
+ mCurrX = mStartX + Math.round(x * mDeltaX);
+ mCurrY = mStartY + Math.round(x * mDeltaY);
+ break;
+ case FLING_MODE:
+ final float t = (float) timePassed / mDuration;
+ final int index = (int) (NB_SAMPLES * t);
+ float distanceCoef = 1.f;
+ float velocityCoef = 0.f;
+ if (index < NB_SAMPLES) {
+ final float t_inf = (float) index / NB_SAMPLES;
+ final float t_sup = (float) (index + 1) / NB_SAMPLES;
+ final float d_inf = SPLINE_POSITION[index];
+ final float d_sup = SPLINE_POSITION[index + 1];
+ velocityCoef = (d_sup - d_inf) / (t_sup - t_inf);
+ distanceCoef = d_inf + (t - t_inf) * velocityCoef;
+ }
+
+ mCurrVelocity = velocityCoef * mDistance / mDuration * 1000.0f;
+
+ mCurrX = mStartX + Math.round(distanceCoef * (mFinalX - mStartX));
+ // Pin to mMinX <= mCurrX <= mMaxX
+ mCurrX = Math.min(mCurrX, mMaxX);
+ mCurrX = Math.max(mCurrX, mMinX);
+
+ mCurrY = mStartY + Math.round(distanceCoef * (mFinalY - mStartY));
+ // Pin to mMinY <= mCurrY <= mMaxY
+ mCurrY = Math.min(mCurrY, mMaxY);
+ mCurrY = Math.max(mCurrY, mMinY);
+
+ if (mCurrX == mFinalX && mCurrY == mFinalY) {
+ mFinished = true;
+ }
+
+ break;
+ }
+ }
+ else {
+ mCurrX = mFinalX;
+ mCurrY = mFinalY;
+ mFinished = true;
+ }
+ return true;
+ }
+
+ /**
+ * Start scrolling by providing a starting point and the distance to travel.
+ * The scroll will use the default value of 250 milliseconds for the
+ * duration.
+ *
+ * @param startX Starting horizontal scroll offset in pixels. Positive
+ * numbers will scroll the content to the left.
+ * @param startY Starting vertical scroll offset in pixels. Positive numbers
+ * will scroll the content up.
+ * @param dx Horizontal distance to travel. Positive numbers will scroll the
+ * content to the left.
+ * @param dy Vertical distance to travel. Positive numbers will scroll the
+ * content up.
+ */
+ public void startScroll(int startX, int startY, int dx, int dy) {
+ startScroll(startX, startY, dx, dy, DEFAULT_DURATION);
+ }
+
+ /**
+ * Start scrolling by providing a starting point, the distance to travel,
+ * and the duration of the scroll.
+ *
+ * @param startX Starting horizontal scroll offset in pixels. Positive
+ * numbers will scroll the content to the left.
+ * @param startY Starting vertical scroll offset in pixels. Positive numbers
+ * will scroll the content up.
+ * @param dx Horizontal distance to travel. Positive numbers will scroll the
+ * content to the left.
+ * @param dy Vertical distance to travel. Positive numbers will scroll the
+ * content up.
+ * @param duration Duration of the scroll in milliseconds.
+ */
+ public void startScroll(int startX, int startY, int dx, int dy, int duration) {
+ mMode = SCROLL_MODE;
+ mFinished = false;
+ mDuration = duration;
+ mStartTime = AnimationUtils.currentAnimationTimeMillis();
+ mStartX = startX;
+ mStartY = startY;
+ mFinalX = startX + dx;
+ mFinalY = startY + dy;
+ mDeltaX = dx;
+ mDeltaY = dy;
+ mDurationReciprocal = 1.0f / (float) mDuration;
+ }
+
+ /**
+ * Start scrolling based on a fling gesture. The distance travelled will
+ * depend on the initial velocity of the fling.
+ *
+ * @param startX Starting point of the scroll (X)
+ * @param startY Starting point of the scroll (Y)
+ * @param velocityX Initial velocity of the fling (X) measured in pixels per
+ * second.
+ * @param velocityY Initial velocity of the fling (Y) measured in pixels per
+ * second
+ * @param minX Minimum X value. The scroller will not scroll past this
+ * point.
+ * @param maxX Maximum X value. The scroller will not scroll past this
+ * point.
+ * @param minY Minimum Y value. The scroller will not scroll past this
+ * point.
+ * @param maxY Maximum Y value. The scroller will not scroll past this
+ * point.
+ */
+ public void fling(int startX, int startY, int velocityX, int velocityY,
+ int minX, int maxX, int minY, int maxY) {
+ // Continue a scroll or fling in progress
+ if (mFlywheel && !mFinished) {
+ float oldVel = getCurrVelocity();
+
+ float dx = (float) (mFinalX - mStartX);
+ float dy = (float) (mFinalY - mStartY);
+ float hyp = FloatMath.sqrt(dx * dx + dy * dy);
+
+ float ndx = dx / hyp;
+ float ndy = dy / hyp;
+
+ float oldVelocityX = ndx * oldVel;
+ float oldVelocityY = ndy * oldVel;
+ if (Math.signum(velocityX) == Math.signum(oldVelocityX) &&
+ Math.signum(velocityY) == Math.signum(oldVelocityY)) {
+ velocityX += oldVelocityX;
+ velocityY += oldVelocityY;
+ }
+ }
+
+ mMode = FLING_MODE;
+ mFinished = false;
+
+ float velocity = FloatMath.sqrt(velocityX * velocityX + velocityY * velocityY);
+
+ mVelocity = velocity;
+ mDuration = getSplineFlingDuration(velocity);
+ mStartTime = AnimationUtils.currentAnimationTimeMillis();
+ mStartX = startX;
+ mStartY = startY;
+
+ float coeffX = velocity == 0 ? 1.0f : velocityX / velocity;
+ float coeffY = velocity == 0 ? 1.0f : velocityY / velocity;
+
+ double totalDistance = getSplineFlingDistance(velocity);
+ mDistance = (int) (totalDistance * Math.signum(velocity));
+
+ mMinX = minX;
+ mMaxX = maxX;
+ mMinY = minY;
+ mMaxY = maxY;
+
+ mFinalX = startX + (int) Math.round(totalDistance * coeffX);
+ // Pin to mMinX <= mFinalX <= mMaxX
+ mFinalX = Math.min(mFinalX, mMaxX);
+ mFinalX = Math.max(mFinalX, mMinX);
+
+ mFinalY = startY + (int) Math.round(totalDistance * coeffY);
+ // Pin to mMinY <= mFinalY <= mMaxY
+ mFinalY = Math.min(mFinalY, mMaxY);
+ mFinalY = Math.max(mFinalY, mMinY);
+ }
+
+ private double getSplineDeceleration(float velocity) {
+ return Math.log(INFLEXION * Math.abs(velocity) / (mFlingFriction * mPhysicalCoeff));
+ }
+
+ private int getSplineFlingDuration(float velocity) {
+ final double l = getSplineDeceleration(velocity);
+ final double decelMinusOne = DECELERATION_RATE - 1.0;
+ return (int) (1000.0 * Math.exp(l / decelMinusOne));
+ }
+
+ private double getSplineFlingDistance(float velocity) {
+ final double l = getSplineDeceleration(velocity);
+ final double decelMinusOne = DECELERATION_RATE - 1.0;
+ return mFlingFriction * mPhysicalCoeff * Math.exp(DECELERATION_RATE / decelMinusOne * l);
+ }
+
+ static float viscousFluid(float x)
+ {
+ x *= sViscousFluidScale;
+ if (x < 1.0f) {
+ x -= (1.0f - (float)Math.exp(-x));
+ } else {
+ float start = 0.36787944117f; // 1/e == exp(-1)
+ x = 1.0f - (float)Math.exp(1.0f - x);
+ x = start + x * (1.0f - start);
+ }
+ x *= sViscousFluidNormalize;
+ return x;
+ }
+
+ /**
+ * Stops the animation. Contrary to {@link #forceFinished(boolean)},
+ * aborting the animating cause the scroller to move to the final x and y
+ * position
+ *
+ * @see #forceFinished(boolean)
+ */
+ public void abortAnimation() {
+ mCurrX = mFinalX;
+ mCurrY = mFinalY;
+ mFinished = true;
+ }
+
+ /**
+ * Extend the scroll animation. This allows a running animation to scroll
+ * further and longer, when used with {@link #setFinalX(int)} or {@link #setFinalY(int)}.
+ *
+ * @param extend Additional time to scroll in milliseconds.
+ * @see #setFinalX(int)
+ * @see #setFinalY(int)
+ */
+ public void extendDuration(int extend) {
+ int passed = timePassed();
+ mDuration = passed + extend;
+ mDurationReciprocal = 1.0f / mDuration;
+ mFinished = false;
+ }
+
+ /**
+ * Returns the time elapsed since the beginning of the scrolling.
+ *
+ * @return The elapsed time in milliseconds.
+ */
+ public int timePassed() {
+ return (int)(AnimationUtils.currentAnimationTimeMillis() - mStartTime);
+ }
+
+ /**
+ * Sets the final position (X) for this scroller.
+ *
+ * @param newX The new X offset as an absolute distance from the origin.
+ * @see #extendDuration(int)
+ * @see #setFinalY(int)
+ */
+ public void setFinalX(int newX) {
+ mFinalX = newX;
+ mDeltaX = mFinalX - mStartX;
+ mFinished = false;
+ }
+
+ /**
+ * Sets the final position (Y) for this scroller.
+ *
+ * @param newY The new Y offset as an absolute distance from the origin.
+ * @see #extendDuration(int)
+ * @see #setFinalX(int)
+ */
+ public void setFinalY(int newY) {
+ mFinalY = newY;
+ mDeltaY = mFinalY - mStartY;
+ mFinished = false;
+ }
+
+ /**
+ * @hide
+ */
+ public boolean isScrollingInDirection(float xvel, float yvel) {
+ return !mFinished && Math.signum(xvel) == Math.signum(mFinalX - mStartX) &&
+ Math.signum(yvel) == Math.signum(mFinalY - mStartY);
+ }
+}
diff --git a/src/com/android/launcher3/LauncherSettings.java b/src/com/android/launcher3/LauncherSettings.java
index 1d161d097..034ffbaa3 100644
--- a/src/com/android/launcher3/LauncherSettings.java
+++ b/src/com/android/launcher3/LauncherSettings.java
@@ -40,6 +40,11 @@ class LauncherSettings {
static final String TITLE = "title";
/**
+ * Folder Hidden status
+ */
+ static final String HIDDEN = "hidden";
+
+ /**
* The Intent URL of the gesture, describing what it points to. This
* value is given to {@link android.content.Intent#parseUri(String, int)} to create
* an Intent that can be launched.
@@ -171,6 +176,14 @@ class LauncherSettings {
static final int CONTAINER_DESKTOP = -100;
static final int CONTAINER_HOTSEAT = -101;
+ static final String containerToString(int container) {
+ switch (container) {
+ case CONTAINER_DESKTOP: return "desktop";
+ case CONTAINER_HOTSEAT: return "hotseat";
+ default: return String.valueOf(container);
+ }
+ }
+
/**
* The screen holding the favorite (if container is CONTAINER_DESKTOP)
* <P>Type: INTEGER</P>
@@ -280,5 +293,11 @@ class LauncherSettings {
* @see android.provider.LiveFolders#DISPLAY_MODE_LIST
*/
static final String DISPLAY_MODE = "displayMode";
+
+ /**
+ * Boolean indicating that his item was restored and not yet successfully bound.
+ * <P>Type: INTEGER</P>
+ */
+ static final String RESTORED = "restored";
}
}
diff --git a/src/com/android/launcher3/LauncherWallpaperPickerActivity.java b/src/com/android/launcher3/LauncherWallpaperPickerActivity.java
new file mode 100644
index 000000000..10fe013ee
--- /dev/null
+++ b/src/com/android/launcher3/LauncherWallpaperPickerActivity.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3;
+
+import android.content.Intent;
+
+public class LauncherWallpaperPickerActivity extends WallpaperPickerActivity {
+ @Override
+ public void startActivityForResultSafely(Intent intent, int requestCode) {
+ Utilities.startActivityForResultSafely(this, intent, requestCode);
+ }
+ @Override
+ public boolean enableRotation() {
+ return Utilities.isRotationEnabled(this);
+ }
+}
diff --git a/src/com/android/launcher3/Lists.java b/src/com/android/launcher3/Lists.java
new file mode 100644
index 000000000..51f5dc272
--- /dev/null
+++ b/src/com/android/launcher3/Lists.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3;
+
+import java.util.ArrayList;
+import java.util.Collections;
+
+/**
+ * Provides static methods for creating {@code List} instances easily, and other
+ * utility methods for working with lists.
+ */
+public class Lists {
+
+ /**
+ * Creates an empty {@code ArrayList} instance.
+ *
+ * <p><b>Note:</b> if you only need an <i>immutable</i> empty List, use
+ * {@link Collections#emptyList} instead.
+ *
+ * @return a newly-created, initially-empty {@code ArrayList}
+ */
+ public static <E> ArrayList<E> newArrayList() {
+ return new ArrayList<E>();
+ }
+
+ /**
+ * Creates a resizable {@code ArrayList} instance containing the given
+ * elements.
+ *
+ * <p><b>Note:</b> due to a bug in javac 1.5.0_06, we cannot support the
+ * following:
+ *
+ * <p>{@code List<Base> list = Lists.newArrayList(sub1, sub2);}
+ *
+ * <p>where {@code sub1} and {@code sub2} are references to subtypes of
+ * {@code Base}, not of {@code Base} itself. To get around this, you must
+ * use:
+ *
+ * <p>{@code List<Base> list = Lists.<Base>newArrayList(sub1, sub2);}
+ *
+ * @param elements the elements that the list should contain, in order
+ * @return a newly-created {@code ArrayList} containing those elements
+ */
+ public static <E> ArrayList<E> newArrayList(E... elements) {
+ int capacity = (elements.length * 110) / 100 + 5;
+ ArrayList<E> list = new ArrayList<E>(capacity);
+ Collections.addAll(list, elements);
+ return list;
+ }
+}
diff --git a/src/com/android/launcher3/LockWallpaperPickerActivity.java b/src/com/android/launcher3/LockWallpaperPickerActivity.java
deleted file mode 100644
index 483568480..000000000
--- a/src/com/android/launcher3/LockWallpaperPickerActivity.java
+++ /dev/null
@@ -1,1600 +0,0 @@
-/*
- * Copyright (C) 2014 The CyanogenMod Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3;
-
-import android.animation.Animator;
-import android.animation.LayoutTransition;
-import android.app.ActionBar;
-import android.app.Activity;
-import android.app.WallpaperInfo;
-import android.app.WallpaperManager;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.res.AssetManager;
-import android.content.res.Resources;
-import android.database.Cursor;
-import android.graphics.Bitmap;
-import android.graphics.Bitmap.CompressFormat;
-import android.graphics.BitmapFactory;
-import android.graphics.BitmapRegionDecoder;
-import android.graphics.Canvas;
-import android.graphics.Matrix;
-import android.graphics.Paint;
-import android.graphics.Point;
-import android.graphics.PorterDuff;
-import android.graphics.Rect;
-import android.graphics.RectF;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.LevelListDrawable;
-import android.net.Uri;
-import android.os.AsyncTask;
-import android.os.Bundle;
-import android.provider.MediaStore;
-import android.provider.ThemesContract.ThemesColumns;
-import android.util.Log;
-import android.util.Pair;
-import android.view.ActionMode;
-import android.view.Display;
-import android.view.LayoutInflater;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.ViewGroup;
-import android.view.ViewTreeObserver;
-import android.view.ViewTreeObserver.OnGlobalLayoutListener;
-import android.view.animation.AccelerateInterpolator;
-import android.view.animation.DecelerateInterpolator;
-import android.widget.BaseAdapter;
-import android.widget.FrameLayout;
-import android.widget.HorizontalScrollView;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.ListAdapter;
-
-import com.android.gallery3d.common.Utils;
-import com.android.launcher3.WallpaperCropActivity.BitmapCropTask;
-import com.android.launcher3.WallpaperCropActivity.OnBitmapCroppedHandler;
-import com.android.photos.BitmapRegionTileSource;
-
-import java.io.BufferedInputStream;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-
-public class LockWallpaperPickerActivity extends WallpaperCropActivity {
- static final String TAG = LockWallpaperPickerActivity.class.getSimpleName();
-
- public static final int IMAGE_PICK = 5;
- public static final int PICK_WALLPAPER_THIRD_PARTY_ACTIVITY = 6;
- public static final int PICK_LIVE_WALLPAPER = 7;
- private static final String TEMP_WALLPAPER_TILES = "TEMP_KEYGUARD_WALLPAPER_TILES";
-
- private View mSelectedThumb;
- private boolean mIgnoreNextTap;
- private OnClickListener mThumbnailOnClickListener;
-
- private LinearLayout mWallpapersView;
- private View mWallpaperStrip;
-
- private ActionMode.Callback mActionModeCallback;
- private ActionMode mActionMode;
-
- private View.OnLongClickListener mLongClickListener;
-
- ArrayList<Uri> mTempWallpaperTiles = new ArrayList<Uri>();
- private SavedWallpaperImages mSavedImages;
-
- public static class PickImageInfo extends WallpaperTileInfo {
- @Override
- public void onClick(WallpaperCropActivity a) {
- Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
- intent.setType("image/*");
- Utilities.startActivityForResultSafely(((LockWallpaperPickerActivity)a), intent, IMAGE_PICK);
- }
- }
-
- public static class UserDesktopWallpaperInfo extends WallpaperTileInfo {
- @Override
- public void onClick(WallpaperCropActivity a) {
- WallpaperManager am = WallpaperManager.getInstance(a);
- am.clearKeyguardWallpaper();
- a.setResult(RESULT_OK);
- a.finish();
- }
- }
-
- public static class UriWallpaperInfo extends WallpaperTileInfo {
- private Uri mUri;
- public UriWallpaperInfo(Uri uri) {
- mUri = uri;
- }
- @Override
- public void onClick(WallpaperCropActivity a) {
- CropView v = a.getCropView();
- int rotation = WallpaperCropActivity.getRotationFromExif(a, mUri);
- v.setTileSource(new BitmapRegionTileSource(a, mUri, 1024, rotation), null);
- v.setTouchEnabled(true);
- }
- @Override
- public void onSave(final WallpaperCropActivity a) {
- boolean finishActivityWhenDone = true;
- OnBitmapCroppedHandler h = new OnBitmapCroppedHandler() {
- public void onBitmapCropped(byte[] imageBytes) {
- Point thumbSize = getDefaultThumbnailSize(a.getResources());
- Bitmap thumb = createThumbnail(
- thumbSize, null, null, imageBytes, null, 0, 0, true);
- a.getSavedImages().writeImage(thumb, imageBytes);
- }
- };
- ((LockWallpaperPickerActivity)a).cropImageAndSetWallpaper(mUri, h, finishActivityWhenDone);
- }
- @Override
- public boolean isSelectable() {
- return true;
- }
- @Override
- public boolean isNamelessWallpaper() {
- return true;
- }
- }
-
- /**
- * For themes which have regular wallpapers
- */
- public static class ThemeWallpaperInfo extends WallpaperTileInfo {
- String mPackageName;
- boolean mIsLegacy;
- Drawable mThumb;
- Context mContext;
-
- public ThemeWallpaperInfo(Context context, String packageName, boolean legacy, Drawable thumb) {
- this.mContext = context;
- this.mPackageName = packageName;
- this.mIsLegacy = legacy;
- this.mThumb = thumb;
- }
-
- @Override
- public void onClick(WallpaperCropActivity a) {
- CropView v = a.getCropView();
- try {
- BitmapRegionTileSource source = null;
- if (mIsLegacy) {
- final PackageManager pm = a.getPackageManager();
- PackageInfo pi = pm.getPackageInfo(mPackageName, 0);
- Resources res = a.getPackageManager().getResourcesForApplication(mPackageName);
- int resId = pi.legacyThemeInfos[0].wallpaperResourceId;
-
- int rotation = WallpaperCropActivity.getRotationFromExif(res, resId);
- source = new BitmapRegionTileSource(
- res, a, resId, 1024, rotation);
- } else {
- Resources res = a.getPackageManager().getResourcesForApplication(mPackageName);
- if (res == null) {
- return;
- }
-
- int rotation = 0;
- source = new BitmapRegionTileSource(
- res, a, "wallpapers", 1024, rotation, true);
- }
- v.setTileSource(source, null);
- v.setTouchEnabled(true);
- } catch (NameNotFoundException e) {
- }
- }
-
- @Override
- public void onSave(WallpaperCropActivity a) {
- ((LockWallpaperPickerActivity)a).cropImageAndSetWallpaper(
- "wallpapers",
- mPackageName,
- mIsLegacy,
- true);
- }
-
- @Override
- public boolean isNamelessWallpaper() {
- return true;
- }
-
- @Override
- public boolean isSelectable() {
- return true;
- }
- }
-
- /**
- * For themes that have LOCKSCREEN wallpapers
- */
- public static class ThemeLockWallpaperInfo extends WallpaperTileInfo {
- String mPackageName;
- Drawable mThumb;
- Context mContext;
-
- public ThemeLockWallpaperInfo(Context context, String packageName, Drawable thumb) {
- this.mContext = context;
- this.mPackageName = packageName;
- this.mThumb = thumb;
- }
-
- @Override
- public void onClick(WallpaperCropActivity a) {
- CropView v = a.getCropView();
- try {
- BitmapRegionTileSource source = null;
- Resources res = a.getPackageManager().getResourcesForApplication(mPackageName);
- if (res == null) {
- return;
- }
-
- int rotation = 0;
- source = new BitmapRegionTileSource(
- res, a, "lockscreen", 1024, rotation, true);
- v.setTileSource(source, null);
- v.setTouchEnabled(true);
- } catch (NameNotFoundException e) {
- }
- }
-
- @Override
- public void onSave(WallpaperCropActivity a) {
- ((LockWallpaperPickerActivity)a).cropImageAndSetWallpaper(
- "lockscreen",
- mPackageName,
- false,
- true);
- }
-
- @Override
- public boolean isNamelessWallpaper() {
- return true;
- }
-
- @Override
- public boolean isSelectable() {
- return true;
- }
- }
-
- public static class ResourceWallpaperInfo extends WallpaperTileInfo {
- private Resources mResources;
- private int mResId;
- private Drawable mThumb;
-
- public ResourceWallpaperInfo(Resources res, int resId, Drawable thumb) {
- mResources = res;
- mResId = resId;
- mThumb = thumb;
- }
- @Override
- public void onClick(WallpaperCropActivity a) {
- int rotation = WallpaperCropActivity.getRotationFromExif(mResources, mResId);
- BitmapRegionTileSource source = new BitmapRegionTileSource(
- mResources, a, mResId, 1024, rotation);
- CropView v = a.getCropView();
- v.setTileSource(source, null);
- Point wallpaperSize = WallpaperCropActivity.getDefaultWallpaperSize(
- a.getResources(), a.getWindowManager());
- RectF crop = WallpaperCropActivity.getMaxCropRect(
- source.getImageWidth(), source.getImageHeight(),
- wallpaperSize.x, wallpaperSize.y, false);
- v.setScale(wallpaperSize.x / crop.width());
- v.setTouchEnabled(false);
- }
- @Override
- public void onSave(WallpaperCropActivity a) {
- boolean finishActivityWhenDone = true;
- ((LockWallpaperPickerActivity)a).cropImageAndSetWallpaper(mResources, mResId, finishActivityWhenDone);
- }
- @Override
- public boolean isSelectable() {
- return true;
- }
- @Override
- public boolean isNamelessWallpaper() {
- return true;
- }
- }
-
- protected void cropImageAndSetWallpaper(String path, String packageName, final boolean legacy,
- final boolean finishActivityWhenDone) {
-
- Point outSize = new Point();
- getWindowManager().getDefaultDisplay().getSize(outSize);
-
- final int outWidth = outSize.x;
- final int outHeight = outSize.y;
- Runnable onEndCrop = new Runnable() {
- public void run() {
- if (finishActivityWhenDone) {
- setResult(Activity.RESULT_OK);
- finish();
- }
- }
- };
-
- RectF cropRect = new RectF(mCropView.getCrop());
- BitmapCropTask cropTask = null;
- try {
- if (legacy) {
- final PackageManager pm = getPackageManager();
- PackageInfo pi = pm.getPackageInfo(packageName, 0);
- Resources res = getPackageManager().getResourcesForApplication(packageName);
- int resId = pi.legacyThemeInfos[0].wallpaperResourceId;
- cropTask = new BitmapCropTask(this, res, resId,
- cropRect, 0, outWidth, outHeight, true, false, onEndCrop);
- } else {
- Resources res = getPackageManager().getResourcesForApplication(packageName);
- if (res == null) {
- return;
- }
- cropTask = new BitmapCropTask(this, res, path, cropRect,
- 0, outWidth, outHeight, true, false, onEndCrop);
- }
- } catch (NameNotFoundException e) {
- return;
- }
-
- if (cropTask != null) {
- cropTask.execute();
- }
- }
-
- @Override
- protected void cropImageAndSetWallpaper(Uri uri,
- OnBitmapCroppedHandler onBitmapCroppedHandler, final boolean finishActivityWhenDone) {
- // Get the crop
- boolean ltr = mCropView.getLayoutDirection() == View.LAYOUT_DIRECTION_LTR;
-
- Point minDims = new Point();
- Point maxDims = new Point();
- Display d = getWindowManager().getDefaultDisplay();
- d.getCurrentSizeRange(minDims, maxDims);
-
- Point displaySize = new Point();
- d.getSize(displaySize);
-
- int maxDim = Math.max(maxDims.x, maxDims.y);
- final int minDim = Math.min(minDims.x, minDims.y);
- int defaultWallpaperWidth;
- if (isScreenLarge(getResources())) {
- defaultWallpaperWidth = (int) (maxDim *
- wallpaperTravelToScreenWidthRatio(maxDim, minDim));
- } else {
- defaultWallpaperWidth = Math.max((int)
- (minDim * WALLPAPER_SCREENS_SPAN), maxDim);
- }
-
- boolean isPortrait = displaySize.x < displaySize.y;
- int portraitHeight;
- if (isPortrait) {
- portraitHeight = mCropView.getHeight();
- } else {
- // TODO: how to actually get the proper portrait height?
- // This is not quite right:
- portraitHeight = Math.max(maxDims.x, maxDims.y);
- }
- if (android.os.Build.VERSION.SDK_INT >=
- android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) {
- Point realSize = new Point();
- d.getRealSize(realSize);
- portraitHeight = Math.max(realSize.x, realSize.y);
- }
- // Get the crop
- RectF cropRect = mCropView.getCrop();
- int cropRotation = mCropView.getImageRotation();
- float cropScale = mCropView.getWidth() / (float) cropRect.width();
-
- Point inSize = mCropView.getSourceDimensions();
- Matrix rotateMatrix = new Matrix();
- rotateMatrix.setRotate(cropRotation);
- float[] rotatedInSize = new float[] { inSize.x, inSize.y };
- rotateMatrix.mapPoints(rotatedInSize);
- rotatedInSize[0] = Math.abs(rotatedInSize[0]);
- rotatedInSize[1] = Math.abs(rotatedInSize[1]);
-
- // ADJUST CROP WIDTH
- // Extend the crop all the way to the right, for parallax
- // (or all the way to the left, in RTL)
- float extraSpace = ltr ? rotatedInSize[0] - cropRect.right : cropRect.left;
- // Cap the amount of extra width
- float maxExtraSpace = defaultWallpaperWidth / cropScale - cropRect.width();
- extraSpace = Math.min(extraSpace, maxExtraSpace);
-
- if (ltr) {
- cropRect.right += extraSpace;
- } else {
- cropRect.left -= extraSpace;
- }
-
- // ADJUST CROP HEIGHT
- if (isPortrait) {
- cropRect.bottom = cropRect.top + portraitHeight / cropScale;
- } else { // LANDSCAPE
- float extraPortraitHeight =
- portraitHeight / cropScale - cropRect.height();
- float expandHeight =
- Math.min(Math.min(rotatedInSize[1] - cropRect.bottom, cropRect.top),
- extraPortraitHeight / 2);
- cropRect.top -= expandHeight;
- cropRect.bottom += expandHeight;
- }
- final int outWidth = (int) Math.round(cropRect.width() * cropScale);
- final int outHeight = (int) Math.round(cropRect.height() * cropScale);
-
- Runnable onEndCrop = new Runnable() {
- public void run() {
- updateWallpaperDimensions(outWidth, outHeight);
- if (finishActivityWhenDone) {
- setResult(Activity.RESULT_OK);
- finish();
- }
- }
- };
- BitmapCropTask cropTask = new BitmapCropTask(this, uri,
- cropRect, cropRotation, outWidth, outHeight, true, false, onEndCrop);
- if (onBitmapCroppedHandler != null) {
- cropTask.setOnBitmapCropped(onBitmapCroppedHandler);
- }
- cropTask.execute();
- }
-
- @Override
- protected void setWallpaper(String filePath, final boolean finishActivityWhenDone) {
- int rotation = getRotationFromExif(filePath);
- BitmapCropTask cropTask = new BitmapCropTask(
- this, filePath, null, rotation, 0, 0, true, false, null);
- final Point bounds = cropTask.getImageBounds();
- Runnable onEndCrop = new Runnable() {
- public void run() {
- updateWallpaperDimensions(bounds.x, bounds.y);
- if (finishActivityWhenDone) {
- setResult(Activity.RESULT_OK);
- finish();
- }
- }
- };
- cropTask.setOnEndRunnable(onEndCrop);
- cropTask.setNoCrop(true);
- cropTask.execute();
- }
-
- protected static class BitmapCropTask extends AsyncTask<Void, Void, Boolean> {
- Uri mInUri = null;
- Context mContext;
- String mInFilePath;
- byte[] mInImageBytes;
- int mInResId = 0;
- InputStream mInStream;
- RectF mCropBounds = null;
- int mOutWidth, mOutHeight;
- int mRotation;
- String mOutputFormat = "jpg"; // for now
- boolean mSetWallpaper;
- boolean mSaveCroppedBitmap;
- Bitmap mCroppedBitmap;
- Runnable mOnEndRunnable;
- Resources mResources;
- OnBitmapCroppedHandler mOnBitmapCroppedHandler;
- boolean mNoCrop;
- boolean mImageFromAsset;
-
- public BitmapCropTask(Context c, Resources res , String assetPath,
- RectF cropBounds, int rotation, int outWidth, int outHeight,
- boolean setWallpaper, boolean saveCroppedBitmap, Runnable onEndRunnable) {
- mContext = c;
- mResources = res;
- mInFilePath = assetPath;
- mImageFromAsset = true;
- init(cropBounds, rotation,
- outWidth, outHeight, setWallpaper, saveCroppedBitmap, onEndRunnable);
- }
-
- public BitmapCropTask(Context c, String filePath,
- RectF cropBounds, int rotation, int outWidth, int outHeight,
- boolean setWallpaper, boolean saveCroppedBitmap, Runnable onEndRunnable) {
- mContext = c;
- mInFilePath = filePath;
- init(cropBounds, rotation,
- outWidth, outHeight, setWallpaper, saveCroppedBitmap, onEndRunnable);
- }
-
- public BitmapCropTask(byte[] imageBytes,
- RectF cropBounds, int rotation, int outWidth, int outHeight,
- boolean setWallpaper, boolean saveCroppedBitmap, Runnable onEndRunnable) {
- mInImageBytes = imageBytes;
- init(cropBounds, rotation,
- outWidth, outHeight, setWallpaper, saveCroppedBitmap, onEndRunnable);
- }
-
- public BitmapCropTask(Context c, Uri inUri,
- RectF cropBounds, int rotation, int outWidth, int outHeight,
- boolean setWallpaper, boolean saveCroppedBitmap, Runnable onEndRunnable) {
- mContext = c;
- mInUri = inUri;
- init(cropBounds, rotation,
- outWidth, outHeight, setWallpaper, saveCroppedBitmap, onEndRunnable);
- }
-
- public BitmapCropTask(Context c, Resources res, int inResId,
- RectF cropBounds, int rotation, int outWidth, int outHeight,
- boolean setWallpaper, boolean saveCroppedBitmap, Runnable onEndRunnable) {
- mContext = c;
- mInResId = inResId;
- mResources = res;
- init(cropBounds, rotation,
- outWidth, outHeight, setWallpaper, saveCroppedBitmap, onEndRunnable);
- }
-
- private void init(RectF cropBounds, int rotation, int outWidth, int outHeight,
- boolean setWallpaper, boolean saveCroppedBitmap, Runnable onEndRunnable) {
- mCropBounds = cropBounds;
- mRotation = rotation;
- mOutWidth = outWidth;
- mOutHeight = outHeight;
- mSetWallpaper = setWallpaper;
- mSaveCroppedBitmap = saveCroppedBitmap;
- mOnEndRunnable = onEndRunnable;
- }
-
- public void setOnBitmapCropped(OnBitmapCroppedHandler handler) {
- mOnBitmapCroppedHandler = handler;
- }
-
- public void setNoCrop(boolean value) {
- mNoCrop = value;
- }
-
- public void setOnEndRunnable(Runnable onEndRunnable) {
- mOnEndRunnable = onEndRunnable;
- }
-
- // Helper to setup input stream
- private void regenerateInputStream() {
- if (mInUri == null && mInResId == 0 && mInFilePath == null && mInImageBytes == null && !mImageFromAsset) {
- Log.w(TAG, "cannot read original file, no input URI, resource ID, or " +
- "image byte array given");
- } else {
- Utils.closeSilently(mInStream);
- try {
- if (mImageFromAsset) {
- AssetManager am = mResources.getAssets();
- String[] pathImages = am.list(mInFilePath);
- if (pathImages == null || pathImages.length == 0) {
- throw new IOException("did not find any images in path: " + mInFilePath);
- }
- InputStream is = am.open(mInFilePath + File.separator + pathImages[0]);
- mInStream = new BufferedInputStream(is);
- } else if (mInUri != null) {
- mInStream = new BufferedInputStream(
- mContext.getContentResolver().openInputStream(mInUri));
- } else if (mInFilePath != null) {
- mInStream = mContext.openFileInput(mInFilePath);
- } else if (mInImageBytes != null) {
- mInStream = new BufferedInputStream(
- new ByteArrayInputStream(mInImageBytes));
- } else {
- mInStream = new BufferedInputStream(
- mResources.openRawResource(mInResId));
- }
- } catch (FileNotFoundException e) {
- Log.w(TAG, "cannot read file: " + mInUri.toString(), e);
- } catch (IOException e) {
- Log.w(TAG, "cannot read file: " + mInUri.toString(), e);
- }
- }
- }
-
- public Point getImageBounds() {
- regenerateInputStream();
- if (mInStream != null) {
- BitmapFactory.Options options = new BitmapFactory.Options();
- options.inJustDecodeBounds = true;
- BitmapFactory.decodeStream(mInStream, null, options);
- if (options.outWidth != 0 && options.outHeight != 0) {
- return new Point(options.outWidth, options.outHeight);
- }
- }
- return null;
- }
-
- public void setCropBounds(RectF cropBounds) {
- mCropBounds = cropBounds;
- }
-
- public Bitmap getCroppedBitmap() {
- return mCroppedBitmap;
- }
- public boolean cropBitmap() {
- boolean failure = false;
-
- regenerateInputStream();
-
- WallpaperManager wallpaperManager = null;
- if (mSetWallpaper) {
- wallpaperManager = WallpaperManager.getInstance(mContext.getApplicationContext());
- }
- if (mSetWallpaper && mNoCrop && mInStream != null) {
- try {
- wallpaperManager.setKeyguardStream(mInStream);
- } catch (IOException e) {
- Log.w(TAG, "cannot write stream to wallpaper", e);
- failure = true;
- }
- return !failure;
- }
- if (mInStream != null) {
- // Find crop bounds (scaled to original image size)
- Rect roundedTrueCrop = new Rect();
- Matrix rotateMatrix = new Matrix();
- Matrix inverseRotateMatrix = new Matrix();
- if (mRotation > 0) {
- rotateMatrix.setRotate(mRotation);
- inverseRotateMatrix.setRotate(-mRotation);
-
- mCropBounds.roundOut(roundedTrueCrop);
- mCropBounds = new RectF(roundedTrueCrop);
-
- Point bounds = getImageBounds();
-
- float[] rotatedBounds = new float[] { bounds.x, bounds.y };
- rotateMatrix.mapPoints(rotatedBounds);
- rotatedBounds[0] = Math.abs(rotatedBounds[0]);
- rotatedBounds[1] = Math.abs(rotatedBounds[1]);
-
- mCropBounds.offset(-rotatedBounds[0]/2, -rotatedBounds[1]/2);
- inverseRotateMatrix.mapRect(mCropBounds);
- mCropBounds.offset(bounds.x/2, bounds.y/2);
-
- regenerateInputStream();
- }
-
- mCropBounds.roundOut(roundedTrueCrop);
-
- if (roundedTrueCrop.width() <= 0 || roundedTrueCrop.height() <= 0) {
- Log.w(TAG, "crop has bad values for full size image");
- failure = true;
- return false;
- }
-
- // See how much we're reducing the size of the image
- int scaleDownSampleSize = Math.min(roundedTrueCrop.width() / mOutWidth,
- roundedTrueCrop.height() / mOutHeight);
-
- // Attempt to open a region decoder
- BitmapRegionDecoder decoder = null;
- try {
- decoder = BitmapRegionDecoder.newInstance(mInStream, true);
- } catch (IOException e) {
- Log.w(TAG, "cannot open region decoder for file: " + mInUri.toString(), e);
- }
-
- Bitmap crop = null;
- if (decoder != null) {
- // Do region decoding to get crop bitmap
- BitmapFactory.Options options = new BitmapFactory.Options();
- if (scaleDownSampleSize > 1) {
- options.inSampleSize = scaleDownSampleSize;
- }
- crop = decoder.decodeRegion(roundedTrueCrop, options);
- decoder.recycle();
- }
-
- if (crop == null) {
- // BitmapRegionDecoder has failed, try to crop in-memory
- regenerateInputStream();
- Bitmap fullSize = null;
- if (mInStream != null) {
- BitmapFactory.Options options = new BitmapFactory.Options();
- if (scaleDownSampleSize > 1) {
- options.inSampleSize = scaleDownSampleSize;
- }
- fullSize = BitmapFactory.decodeStream(mInStream, null, options);
- }
- if (fullSize != null) {
- mCropBounds.left /= scaleDownSampleSize;
- mCropBounds.top /= scaleDownSampleSize;
- mCropBounds.bottom /= scaleDownSampleSize;
- mCropBounds.right /= scaleDownSampleSize;
- mCropBounds.roundOut(roundedTrueCrop);
-
- crop = Bitmap.createBitmap(fullSize, roundedTrueCrop.left,
- roundedTrueCrop.top, roundedTrueCrop.width(),
- roundedTrueCrop.height());
- }
- }
-
- if (crop == null) {
- Log.w(TAG, "cannot decode file: " + mInUri.toString());
- failure = true;
- return false;
- }
- if (mOutWidth > 0 && mOutHeight > 0 || mRotation > 0) {
- float[] dimsAfter = new float[] { crop.getWidth(), crop.getHeight() };
- rotateMatrix.mapPoints(dimsAfter);
- dimsAfter[0] = Math.abs(dimsAfter[0]);
- dimsAfter[1] = Math.abs(dimsAfter[1]);
-
- if (!(mOutWidth > 0 && mOutHeight > 0)) {
- mOutWidth = Math.round(dimsAfter[0]);
- mOutHeight = Math.round(dimsAfter[1]);
- }
-
- RectF cropRect = new RectF(0, 0, dimsAfter[0], dimsAfter[1]);
- RectF returnRect = new RectF(0, 0, mOutWidth, mOutHeight);
-
- Matrix m = new Matrix();
- if (mRotation == 0) {
- m.setRectToRect(cropRect, returnRect, Matrix.ScaleToFit.FILL);
- } else {
- Matrix m1 = new Matrix();
- m1.setTranslate(-crop.getWidth() / 2f, -crop.getHeight() / 2f);
- Matrix m2 = new Matrix();
- m2.setRotate(mRotation);
- Matrix m3 = new Matrix();
- m3.setTranslate(dimsAfter[0] / 2f, dimsAfter[1] / 2f);
- Matrix m4 = new Matrix();
- m4.setRectToRect(cropRect, returnRect, Matrix.ScaleToFit.FILL);
-
- Matrix c1 = new Matrix();
- c1.setConcat(m2, m1);
- Matrix c2 = new Matrix();
- c2.setConcat(m4, m3);
- m.setConcat(c2, c1);
- }
-
- Bitmap tmp = Bitmap.createBitmap((int) returnRect.width(),
- (int) returnRect.height(), Bitmap.Config.ARGB_8888);
- if (tmp != null) {
- Canvas c = new Canvas(tmp);
- Paint p = new Paint();
- p.setFilterBitmap(true);
- c.drawBitmap(crop, m, p);
- crop = tmp;
- }
- }
-
- if (mSaveCroppedBitmap) {
- mCroppedBitmap = crop;
- }
-
- // Get output compression format
- CompressFormat cf =
- convertExtensionToCompressFormat(getFileExtension(mOutputFormat));
-
- // Compress to byte array
- ByteArrayOutputStream tmpOut = new ByteArrayOutputStream(2048);
- if (crop.compress(cf, DEFAULT_COMPRESS_QUALITY, tmpOut)) {
- // If we need to set to the wallpaper, set it
- if (mSetWallpaper && wallpaperManager != null) {
- try {
- byte[] outByteArray = tmpOut.toByteArray();
- wallpaperManager.setKeyguardStream(new ByteArrayInputStream(outByteArray));
- if (mOnBitmapCroppedHandler != null) {
- mOnBitmapCroppedHandler.onBitmapCropped(outByteArray);
- }
- } catch (IOException e) {
- Log.w(TAG, "cannot write stream to wallpaper", e);
- failure = true;
- }
- }
- } else {
- Log.w(TAG, "cannot compress bitmap");
- failure = true;
- }
- } else {
- Log.w(TAG, "could not complete crop task because input stream is null");
- }
- return !failure; // True if any of the operations failed
- }
-
- @Override
- protected Boolean doInBackground(Void... params) {
- return cropBitmap();
- }
-
- @Override
- protected void onPostExecute(Boolean result) {
- if (mOnEndRunnable != null) {
- mOnEndRunnable.run();
- }
- }
- }
-
- @Override
- protected void setWallpaperStripYOffset(int offset) {
- mWallpaperStrip.setPadding(0, 0, 0, offset);
- }
-
- // called by onCreate; this is subclassed to overwrite WallpaperCropActivity
- protected void init() {
- setContentView(R.layout.wallpaper_picker);
-
- mCropView = (CropView) findViewById(R.id.cropView);
- mWallpaperStrip = findViewById(R.id.wallpaper_strip);
- mCropView.setTouchCallback(new CropView.TouchCallback() {
- LauncherViewPropertyAnimator mAnim;
- @Override
- public void onTouchDown() {
- if (mAnim != null) {
- mAnim.cancel();
- }
- if (mWallpaperStrip.getAlpha() == 1f) {
- mIgnoreNextTap = true;
- }
- mAnim = new LauncherViewPropertyAnimator(mWallpaperStrip);
- mAnim.alpha(0f)
- .setDuration(150)
- .addListener(new Animator.AnimatorListener() {
- public void onAnimationStart(Animator animator) { }
- public void onAnimationEnd(Animator animator) {
- mWallpaperStrip.setVisibility(View.INVISIBLE);
- }
- public void onAnimationCancel(Animator animator) { }
- public void onAnimationRepeat(Animator animator) { }
- });
- mAnim.setInterpolator(new AccelerateInterpolator(0.75f));
- mAnim.start();
- }
- @Override
- public void onTouchUp() {
- mIgnoreNextTap = false;
- }
- @Override
- public void onTap() {
- boolean ignoreTap = mIgnoreNextTap;
- mIgnoreNextTap = false;
- if (!ignoreTap) {
- if (mAnim != null) {
- mAnim.cancel();
- }
- mWallpaperStrip.setVisibility(View.VISIBLE);
- mAnim = new LauncherViewPropertyAnimator(mWallpaperStrip);
- mAnim.alpha(1f)
- .setDuration(150)
- .setInterpolator(new DecelerateInterpolator(0.75f));
- mAnim.start();
- }
- }
- });
-
- mThumbnailOnClickListener = new OnClickListener() {
- public void onClick(View v) {
- if (mActionMode != null) {
- // When CAB is up, clicking toggles the item instead
- if (v.isLongClickable()) {
- mLongClickListener.onLongClick(v);
- }
- return;
- }
- WallpaperTileInfo info = (WallpaperTileInfo) v.getTag();
- if (info.isSelectable()) {
- if (mSelectedThumb != null) {
- mSelectedThumb.setSelected(false);
- mSelectedThumb = null;
- }
- mSelectedThumb = v;
- v.setSelected(true);
- // TODO: Remove this once the accessibility framework and
- // services have better support for selection state.
- v.announceForAccessibility(
- getString(R.string.announce_selection, v.getContentDescription()));
- }
- info.onClick(LockWallpaperPickerActivity.this);
- }
- };
- mLongClickListener = new View.OnLongClickListener() {
- // Called when the user long-clicks on someView
- public boolean onLongClick(View view) {
- CheckableFrameLayout c = (CheckableFrameLayout) view;
- c.toggle();
-
- if (mActionMode != null) {
- mActionMode.invalidate();
- } else {
- // Start the CAB using the ActionMode.Callback defined below
- mActionMode = startActionMode(mActionModeCallback);
- int childCount = mWallpapersView.getChildCount();
- for (int i = 0; i < childCount; i++) {
- mWallpapersView.getChildAt(i).setSelected(false);
- }
- }
- return true;
- }
- };
-
- mWallpapersView = (LinearLayout) findViewById(R.id.wallpaper_list);
-
- // Add a tile for the Gallery
- LinearLayout masterWallpaperList = (LinearLayout) findViewById(R.id.master_wallpaper_list);
- FrameLayout pickImageTile = (FrameLayout) getLayoutInflater().
- inflate(R.layout.wallpaper_picker_image_picker_item, masterWallpaperList, false);
- setWallpaperItemPaddingToZero(pickImageTile);
- masterWallpaperList.addView(pickImageTile, 0);
-
- // Add tile for clear image
- FrameLayout clearImageTile = (FrameLayout) getLayoutInflater().
- inflate(R.layout.wallpaper_picker_clear, masterWallpaperList, false);
- setWallpaperItemPaddingToZero(clearImageTile);
- masterWallpaperList.addView(clearImageTile, 0);
-
- // theme LOCKSCREEN wallpapers
- ArrayList<ThemeLockWallpaperInfo> themeLockWallpapers = findThemeLockWallpapers();
- ThemeLockWallpapersAdapter tla = new ThemeLockWallpapersAdapter(this, themeLockWallpapers);
- populateWallpapersFromAdapter(mWallpapersView, tla, false, true);
-
- // theme wallpapers
- ArrayList<ThemeWallpaperInfo> themeWallpapers = findThemeWallpapers();
- ThemeWallpapersAdapter ta = new ThemeWallpapersAdapter(this, themeWallpapers);
- populateWallpapersFromAdapter(mWallpapersView, ta, false, true);
-
- // Populate the saved wallpapers
- mSavedImages = new SavedWallpaperImages(this);
- mSavedImages.loadThumbnailsAndImageIdList();
- populateWallpapersFromAdapter(mWallpapersView, mSavedImages, true, true);
-
- // Make its background the last photo taken on external storage
- Bitmap lastPhoto = getThumbnailOfLastPhoto();
- if (lastPhoto != null) {
- ImageView galleryThumbnailBg =
- (ImageView) pickImageTile.findViewById(R.id.wallpaper_image);
- galleryThumbnailBg.setImageBitmap(getThumbnailOfLastPhoto());
- int colorOverlay = getResources().getColor(R.color.wallpaper_picker_translucent_gray);
- galleryThumbnailBg.setColorFilter(colorOverlay, PorterDuff.Mode.SRC_ATOP);
- }
-
- PickImageInfo pickImageInfo = new PickImageInfo();
- pickImageTile.setTag(pickImageInfo);
- pickImageInfo.setView(pickImageTile);
- pickImageTile.setOnClickListener(mThumbnailOnClickListener);
- pickImageInfo.setView(pickImageTile);
-
- UserDesktopWallpaperInfo clearImageInfo = new UserDesktopWallpaperInfo();
- clearImageTile.setTag(clearImageInfo);
- clearImageInfo.setView(clearImageTile);
- clearImageTile.setOnClickListener(mThumbnailOnClickListener);
- clearImageInfo.setView(clearImageTile);
-
- updateTileIndices();
-
- // Update the scroll for RTL
- initializeScrollForRtl();
-
- // Create smooth layout transitions for when items are deleted
- final LayoutTransition transitioner = new LayoutTransition();
- transitioner.setDuration(200);
- transitioner.setStartDelay(LayoutTransition.CHANGE_DISAPPEARING, 0);
- transitioner.setAnimator(LayoutTransition.DISAPPEARING, null);
- mWallpapersView.setLayoutTransition(transitioner);
-
- // Action bar
- // Show the custom action bar view
- final ActionBar actionBar = getActionBar();
- actionBar.setCustomView(R.layout.actionbar_set_wallpaper);
- actionBar.getCustomView().setOnClickListener(
- new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- if (mSelectedThumb != null) {
- WallpaperTileInfo info = (WallpaperTileInfo) mSelectedThumb.getTag();
- info.onSave(LockWallpaperPickerActivity.this);
- }
- }
- });
-
- // CAB for deleting items
- mActionModeCallback = new ActionMode.Callback() {
- // Called when the action mode is created; startActionMode() was called
- @Override
- public boolean onCreateActionMode(ActionMode mode, Menu menu) {
- // Inflate a menu resource providing context menu items
- MenuInflater inflater = mode.getMenuInflater();
- inflater.inflate(R.menu.cab_delete_wallpapers, menu);
- return true;
- }
-
- private int numCheckedItems() {
- int childCount = mWallpapersView.getChildCount();
- int numCheckedItems = 0;
- for (int i = 0; i < childCount; i++) {
- CheckableFrameLayout c = (CheckableFrameLayout) mWallpapersView.getChildAt(i);
- if (c.isChecked()) {
- numCheckedItems++;
- }
- }
- return numCheckedItems;
- }
-
- // Called each time the action mode is shown. Always called after onCreateActionMode,
- // but may be called multiple times if the mode is invalidated.
- @Override
- public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
- int numCheckedItems = numCheckedItems();
- if (numCheckedItems == 0) {
- mode.finish();
- return true;
- } else {
- mode.setTitle(getResources().getQuantityString(
- R.plurals.number_of_items_selected, numCheckedItems, numCheckedItems));
- return true;
- }
- }
-
- // Called when the user selects a contextual menu item
- @Override
- public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
- int itemId = item.getItemId();
- if (itemId == R.id.menu_delete) {
- int childCount = mWallpapersView.getChildCount();
- ArrayList<View> viewsToRemove = new ArrayList<View>();
- for (int i = 0; i < childCount; i++) {
- CheckableFrameLayout c =
- (CheckableFrameLayout) mWallpapersView.getChildAt(i);
- if (c.isChecked()) {
- WallpaperTileInfo info = (WallpaperTileInfo) c.getTag();
- info.onDelete(LockWallpaperPickerActivity.this);
- viewsToRemove.add(c);
- }
- }
- for (View v : viewsToRemove) {
- mWallpapersView.removeView(v);
- }
- updateTileIndices();
- mode.finish(); // Action picked, so close the CAB
- return true;
- } else {
- return false;
- }
- }
-
- // Called when the user exits the action mode
- @Override
- public void onDestroyActionMode(ActionMode mode) {
- int childCount = mWallpapersView.getChildCount();
- for (int i = 0; i < childCount; i++) {
- CheckableFrameLayout c = (CheckableFrameLayout) mWallpapersView.getChildAt(i);
- c.setChecked(false);
- }
- mSelectedThumb.setSelected(true);
- mActionMode = null;
- }
- };
- }
-
- private void initializeScrollForRtl() {
- final HorizontalScrollView scroll =
- (HorizontalScrollView) findViewById(R.id.wallpaper_scroll_container);
-
- if (scroll.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) {
- final ViewTreeObserver observer = scroll.getViewTreeObserver();
- observer.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
- public void onGlobalLayout() {
- LinearLayout masterWallpaperList =
- (LinearLayout) findViewById(R.id.master_wallpaper_list);
- scroll.scrollTo(masterWallpaperList.getWidth(), 0);
- scroll.getViewTreeObserver().removeOnGlobalLayoutListener(this);
- }
- });
- }
- }
-
- public boolean enableRotation() {
- return super.enableRotation() || Launcher.sForceEnableRotation;
- }
-
- protected Bitmap getThumbnailOfLastPhoto() {
- Cursor cursor = MediaStore.Images.Media.query(getContentResolver(),
- MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
- new String[] { MediaStore.Images.ImageColumns._ID,
- MediaStore.Images.ImageColumns.DATE_TAKEN},
- null, null, MediaStore.Images.ImageColumns.DATE_TAKEN + " DESC LIMIT 1");
- Bitmap thumb = null;
- if (cursor != null) {
- if (cursor.moveToFirst()) {
- int id = cursor.getInt(0);
- thumb = MediaStore.Images.Thumbnails.getThumbnail(getContentResolver(),
- id, MediaStore.Images.Thumbnails.MINI_KIND, null);
- }
- cursor.close();
- }
- return thumb;
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- return super.onCreateOptionsMenu(menu);
- }
-
- @Override
- public boolean onPrepareOptionsMenu(Menu menu) {
- return super.onPrepareOptionsMenu(menu);
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- // Handle presses on the action bar items
- switch (item.getItemId()) {
- default:
- return super.onOptionsItemSelected(item);
- }
- }
-
- protected void onStop() {
- super.onStop();
- mWallpaperStrip = findViewById(R.id.wallpaper_strip);
- if (mWallpaperStrip.getAlpha() < 1f) {
- mWallpaperStrip.setAlpha(1f);
- mWallpaperStrip.setVisibility(View.VISIBLE);
- }
- }
-
- @Override
- protected void onDestroy() {
- mWallpapersView.removeAllViews();
- super.onDestroy();
- }
-
- protected void onSaveInstanceState(Bundle outState) {
- outState.putParcelableArrayList(TEMP_WALLPAPER_TILES, mTempWallpaperTiles);
- }
-
- protected void onRestoreInstanceState(Bundle savedInstanceState) {
- ArrayList<Uri> uris = savedInstanceState.getParcelableArrayList(TEMP_WALLPAPER_TILES);
- for (Uri uri : uris) {
- addTemporaryWallpaperTile(uri);
- }
- }
-
- private void populateWallpapersFromAdapter(ViewGroup parent, BaseAdapter adapter,
- boolean addLongPressHandler, boolean selectFirstTile) {
- for (int i = 0; i < adapter.getCount(); i++) {
- FrameLayout thumbnail = (FrameLayout) adapter.getView(i, null, parent);
- parent.addView(thumbnail, i);
- WallpaperTileInfo info = (WallpaperTileInfo) adapter.getItem(i);
- thumbnail.setTag(info);
- info.setView(thumbnail);
- if (addLongPressHandler) {
- addLongPressHandler(thumbnail);
- }
- thumbnail.setOnClickListener(mThumbnailOnClickListener);
- if (i == 0 && selectFirstTile) {
- mThumbnailOnClickListener.onClick(thumbnail);
- }
- }
- }
-
- private void updateTileIndices() {
- LinearLayout masterWallpaperList = (LinearLayout) findViewById(R.id.master_wallpaper_list);
- final int childCount = masterWallpaperList.getChildCount();
- final Resources res = getResources();
-
- // Do two passes; the first pass gets the total number of tiles
- int numTiles = 0;
- for (int passNum = 0; passNum < 2; passNum++) {
- int tileIndex = 0;
- for (int i = 0; i < childCount; i++) {
- View child = masterWallpaperList.getChildAt(i);
- LinearLayout subList;
-
- int subListStart;
- int subListEnd;
- if (child.getTag() instanceof WallpaperTileInfo) {
- subList = masterWallpaperList;
- subListStart = i;
- subListEnd = i + 1;
- } else { // if (child instanceof LinearLayout) {
- subList = (LinearLayout) child;
- subListStart = 0;
- subListEnd = subList.getChildCount();
- }
-
- for (int j = subListStart; j < subListEnd; j++) {
- WallpaperTileInfo info = (WallpaperTileInfo) subList.getChildAt(j).getTag();
- if (info.isNamelessWallpaper()) {
- if (passNum == 0) {
- numTiles++;
- } else {
- CharSequence label = res.getString(
- R.string.wallpaper_accessibility_name, ++tileIndex, numTiles);
- info.onIndexUpdated(label);
- }
- }
- }
- }
- }
- }
-
- private static Point getDefaultThumbnailSize(Resources res) {
- return new Point(res.getDimensionPixelSize(R.dimen.wallpaperThumbnailWidth),
- res.getDimensionPixelSize(R.dimen.wallpaperThumbnailHeight));
- }
-
- private static Bitmap createThumbnail(Point size, Context context, Uri uri, byte[] imageBytes,
- Resources res, int resId, int rotation, boolean leftAligned) {
- int width = size.x;
- int height = size.y;
-
- BitmapCropTask cropTask;
- if (uri != null) {
- cropTask = new BitmapCropTask(
- context, uri, null, rotation, width, height, false, true, null);
- } else if (imageBytes != null) {
- cropTask = new BitmapCropTask(
- imageBytes, null, rotation, width, height, false, true, null);
- } else {
- cropTask = new BitmapCropTask(
- context, res, resId, null, rotation, width, height, false, true, null);
- }
- Point bounds = cropTask.getImageBounds();
- if (bounds == null || bounds.x == 0 || bounds.y == 0) {
- return null;
- }
-
- Matrix rotateMatrix = new Matrix();
- rotateMatrix.setRotate(rotation);
- float[] rotatedBounds = new float[] { bounds.x, bounds.y };
- rotateMatrix.mapPoints(rotatedBounds);
- rotatedBounds[0] = Math.abs(rotatedBounds[0]);
- rotatedBounds[1] = Math.abs(rotatedBounds[1]);
-
- RectF cropRect = WallpaperCropActivity.getMaxCropRect(
- (int) rotatedBounds[0], (int) rotatedBounds[1], width, height, leftAligned);
- cropTask.setCropBounds(cropRect);
-
- if (cropTask.cropBitmap()) {
- return cropTask.getCroppedBitmap();
- } else {
- return null;
- }
- }
-
- private void addTemporaryWallpaperTile(Uri uri) {
- mTempWallpaperTiles.add(uri);
- // Add a tile for the image picked from Gallery
- FrameLayout pickedImageThumbnail = (FrameLayout) getLayoutInflater().
- inflate(R.layout.wallpaper_picker_item, mWallpapersView, false);
- setWallpaperItemPaddingToZero(pickedImageThumbnail);
-
- // Load the thumbnail
- ImageView image = (ImageView) pickedImageThumbnail.findViewById(R.id.wallpaper_image);
- Point defaultSize = getDefaultThumbnailSize(this.getResources());
- int rotation = WallpaperCropActivity.getRotationFromExif(this, uri);
- Bitmap thumb = createThumbnail(defaultSize, this, uri, null, null, 0, rotation, false);
- if (thumb != null) {
- image.setImageBitmap(thumb);
- Drawable thumbDrawable = image.getDrawable();
- thumbDrawable.setDither(true);
- } else {
- Log.e(TAG, "Error loading thumbnail for uri=" + uri);
- }
- mWallpapersView.addView(pickedImageThumbnail, 0);
-
- UriWallpaperInfo info = new UriWallpaperInfo(uri);
- pickedImageThumbnail.setTag(info);
- info.setView(pickedImageThumbnail);
- addLongPressHandler(pickedImageThumbnail);
- updateTileIndices();
- pickedImageThumbnail.setOnClickListener(mThumbnailOnClickListener);
- mThumbnailOnClickListener.onClick(pickedImageThumbnail);
- }
-
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- if (requestCode == IMAGE_PICK && resultCode == RESULT_OK) {
- if (data != null && data.getData() != null) {
- Uri uri = data.getData();
- addTemporaryWallpaperTile(uri);
- }
- } else if (requestCode == PICK_WALLPAPER_THIRD_PARTY_ACTIVITY) {
- setResult(RESULT_OK);
- finish();
- }
- }
-
- static void setWallpaperItemPaddingToZero(FrameLayout frameLayout) {
- frameLayout.setPadding(0, 0, 0, 0);
- frameLayout.setForeground(new ZeroPaddingDrawable(frameLayout.getForeground()));
- }
-
- private void addLongPressHandler(View v) {
- v.setOnLongClickListener(mLongClickListener);
- }
-
- private ArrayList<ThemeWallpaperInfo> findThemeWallpapers() {
- ArrayList<ThemeWallpaperInfo> themeWallpapers =
- new ArrayList<ThemeWallpaperInfo>();
- ContentResolver cr = getContentResolver();
- String[] projection = { ThemesColumns.PKG_NAME, ThemesColumns.IS_LEGACY_THEME };
- String selection = ThemesColumns.MODIFIES_LAUNCHER + "=? AND " +
- ThemesColumns.PKG_NAME + "!=?";
- String[] selectoinArgs = {"1", "default"};
- String sortOrder = null;
- Cursor c = cr.query(ThemesColumns.CONTENT_URI, projection, selection,
- selectoinArgs, sortOrder);
- if (c != null) {
- Bitmap bmp;
- while (c.moveToNext()) {
- String pkgName = c.getString(c.getColumnIndexOrThrow(ThemesColumns.PKG_NAME));
- boolean isLegacy = c.getInt(c.getColumnIndexOrThrow(
- ThemesColumns.IS_LEGACY_THEME)) == 1;
- bmp = getThemeWallpaper(this, "wallpapers", pkgName, isLegacy, true /* thumb*/);
- themeWallpapers.add(
- new ThemeWallpaperInfo(this, pkgName, isLegacy,
- new BitmapDrawable(getResources(), bmp)));
- if (bmp != null) {
- Log.d("", String.format("Loaded bitmap of size %dx%d for %s",
- bmp.getWidth(), bmp.getHeight(), pkgName));
- }
- }
- c.close();
- }
- return themeWallpapers;
- }
-
- private ArrayList<ThemeLockWallpaperInfo> findThemeLockWallpapers() {
- ArrayList<ThemeLockWallpaperInfo> themeWallpapers =
- new ArrayList<ThemeLockWallpaperInfo>();
- ContentResolver cr = getContentResolver();
- String[] projection = { ThemesColumns.PKG_NAME };
- String selection = ThemesColumns.MODIFIES_LOCKSCREEN + "=? AND " +
- ThemesColumns.PKG_NAME + "!=?";
- String[] selectoinArgs = {"1", "default"};
- String sortOrder = null;
- Cursor c = cr.query(ThemesColumns.CONTENT_URI, projection, selection,
- selectoinArgs, sortOrder);
- if (c != null) {
- Bitmap bmp;
- while (c.moveToNext()) {
- String pkgName = c.getString(c.getColumnIndexOrThrow(ThemesColumns.PKG_NAME));
- bmp = getThemeWallpaper(this, "lockscreen", pkgName, false, true /* thumb*/);
- themeWallpapers.add(
- new ThemeLockWallpaperInfo(this, pkgName,
- new BitmapDrawable(getResources(), bmp)));
- if (bmp != null) {
- Log.d("", String.format("Loaded bitmap of size %dx%d for %s",
- bmp.getWidth(), bmp.getHeight(), pkgName));
- }
- }
- c.close();
- }
- return themeWallpapers;
- }
-
- public Pair<ApplicationInfo, Integer> getWallpaperArrayResourceId() {
- // Context.getPackageName() may return the "original" package name,
- // com.android.launcher3; Resources needs the real package name,
- // com.android.launcher3. So we ask Resources for what it thinks the
- // package name should be.
- final String packageName = getResources().getResourcePackageName(R.array.wallpapers);
- try {
- ApplicationInfo info = getPackageManager().getApplicationInfo(packageName, 0);
- return new Pair<ApplicationInfo, Integer>(info, R.array.wallpapers);
- } catch (PackageManager.NameNotFoundException e) {
- return null;
- }
- }
-
- public CropView getCropView() {
- return mCropView;
- }
-
- public SavedWallpaperImages getSavedImages() {
- return mSavedImages;
- }
-
- static class ZeroPaddingDrawable extends LevelListDrawable {
- public ZeroPaddingDrawable(Drawable d) {
- super();
- addLevel(0, 0, d);
- setLevel(0);
- }
-
- @Override
- public boolean getPadding(Rect padding) {
- padding.set(0, 0, 0, 0);
- return true;
- }
- }
-
- private static class ThemeLockWallpapersAdapter extends BaseAdapter implements ListAdapter {
- private LayoutInflater mLayoutInflater;
- private ArrayList<ThemeLockWallpaperInfo> mWallpapers;
-
- ThemeLockWallpapersAdapter(Activity activity, ArrayList<ThemeLockWallpaperInfo> wallpapers) {
- mLayoutInflater = activity.getLayoutInflater();
- mWallpapers = wallpapers;
- }
-
- public int getCount() {
- return mWallpapers.size();
- }
-
- public ThemeLockWallpaperInfo getItem(int position) {
- return mWallpapers.get(position);
- }
-
- public long getItemId(int position) {
- return position;
- }
-
- public View getView(int position, View convertView, ViewGroup parent) {
- Drawable thumb = mWallpapers.get(position).mThumb;
- if (thumb == null) {
- Log.e(TAG, "Error decoding thumbnail for wallpaper #" + position);
- }
- return createImageTileView(mLayoutInflater, position, convertView, parent, thumb);
- }
- }
-
- private static class ThemeWallpapersAdapter extends BaseAdapter implements ListAdapter {
- private LayoutInflater mLayoutInflater;
- private ArrayList<ThemeWallpaperInfo> mWallpapers;
-
- ThemeWallpapersAdapter(Activity activity, ArrayList<ThemeWallpaperInfo> wallpapers) {
- mLayoutInflater = activity.getLayoutInflater();
- mWallpapers = wallpapers;
- }
-
- public int getCount() {
- return mWallpapers.size();
- }
-
- public ThemeWallpaperInfo getItem(int position) {
- return mWallpapers.get(position);
- }
-
- public long getItemId(int position) {
- return position;
- }
-
- public View getView(int position, View convertView, ViewGroup parent) {
- Drawable thumb = mWallpapers.get(position).mThumb;
- if (thumb == null) {
- Log.e(TAG, "Error decoding thumbnail for wallpaper #" + position);
- }
- return createImageTileView(mLayoutInflater, position, convertView, parent, thumb);
- }
- }
-
- public static View createImageTileView(LayoutInflater layoutInflater, int position,
- View convertView, ViewGroup parent, Drawable thumb) {
- View view;
-
- if (convertView == null) {
- view = layoutInflater.inflate(R.layout.wallpaper_picker_item, parent, false);
- } else {
- view = convertView;
- }
-
- setWallpaperItemPaddingToZero((FrameLayout) view);
-
- ImageView image = (ImageView) view.findViewById(R.id.wallpaper_image);
-
- if (thumb != null) {
- image.setImageDrawable(thumb);
- thumb.setDither(true);
- }
-
- return view;
- }
-
- private static Bitmap getThemeWallpaper(Context context, String path, String pkgName,
- boolean legacyTheme, boolean thumb) {
- if (legacyTheme) {
- return getLegacyThemeWallpaper(context, pkgName, thumb);
- }
- InputStream is = null;
- try {
- Resources res = context.getPackageManager().getResourcesForApplication(pkgName);
- if (res == null) {
- return null;
- }
-
- AssetManager am = res.getAssets();
- String[] wallpapers = am.list(path);
- if (wallpapers == null || wallpapers.length == 0) {
- return null;
- }
- is = am.open(path + File.separator + wallpapers[0]);
-
- BitmapFactory.Options bounds = new BitmapFactory.Options();
- bounds.inJustDecodeBounds = true;
- BitmapFactory.decodeStream(is, null, bounds);
- if ((bounds.outWidth == -1) || (bounds.outHeight == -1))
- return null;
-
- int originalSize = (bounds.outHeight > bounds.outWidth) ? bounds.outHeight
- : bounds.outWidth;
- Point outSize;
-
- if (thumb) {
- outSize = getDefaultThumbnailSize(context.getResources());
- } else {
- outSize = getDefaultWallpaperSize(res, ((Activity) context).getWindowManager());
- }
- int thumbSampleSize = (outSize.y > outSize.x) ? outSize.y : outSize.x;
-
- BitmapFactory.Options opts = new BitmapFactory.Options();
- opts.inSampleSize = originalSize / thumbSampleSize;
- return BitmapFactory.decodeStream(is, null, opts);
- } catch (IOException e) {
- return null;
- } catch (NameNotFoundException e) {
- return null;
- } catch (OutOfMemoryError e) {
- return null;
- } finally {
- if (is != null) {
- try {
- is.close();
- } catch (IOException e) {
- }
- }
- }
- }
-
- private static Bitmap getLegacyThemeWallpaper(Context context, String pkgName, boolean thumb) {
- try {
- final PackageManager pm = context.getPackageManager();
- PackageInfo pi = pm.getPackageInfo(pkgName, 0);
- Resources res = context.getPackageManager().getResourcesForApplication(pkgName);
-
- if (pi == null || res == null) {
- return null;
- }
- int resId = pi.legacyThemeInfos[0].wallpaperResourceId;
-
- BitmapFactory.Options opts = new BitmapFactory.Options();
- opts.inJustDecodeBounds = true;
- BitmapFactory.decodeResource(res, resId, opts);
- if ((opts.outWidth == -1) || (opts.outHeight == -1))
- return null;
-
- int originalSize = (opts.outHeight > opts.outWidth) ? opts.outHeight
- : opts.outWidth;
- Point outSize;
- if (thumb) {
- outSize = getDefaultThumbnailSize(context.getResources());
- } else {
- outSize = getDefaultWallpaperSize(res, ((Activity) context).getWindowManager());
- }
- int thumbSampleSize = (outSize.y > outSize.x) ? outSize.y : outSize.x;
-
- opts.inJustDecodeBounds = false;
- opts.inSampleSize = originalSize / thumbSampleSize;
-
- return BitmapFactory.decodeResource(res, resId, opts);
- } catch (NameNotFoundException e) {
- return null;
- } catch (OutOfMemoryError e1) {
- return null;
- }
- }
-}
diff --git a/src/com/android/launcher3/OnAlarmListener.java b/src/com/android/launcher3/OnAlarmListener.java
new file mode 100644
index 000000000..b5ef83e83
--- /dev/null
+++ b/src/com/android/launcher3/OnAlarmListener.java
@@ -0,0 +1,5 @@
+package com.android.launcher3;
+
+public interface OnAlarmListener {
+ public void onAlarm(Alarm alarm);
+}
diff --git a/src/com/android/launcher3/OverviewSettingsPanel.java b/src/com/android/launcher3/OverviewSettingsPanel.java
new file mode 100644
index 000000000..4466c15de
--- /dev/null
+++ b/src/com/android/launcher3/OverviewSettingsPanel.java
@@ -0,0 +1,233 @@
+package com.android.launcher3;
+
+import android.content.res.Resources;
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.graphics.drawable.AnimationDrawable;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.ImageView;
+import android.widget.ListView;
+import com.android.launcher3.list.PinnedHeaderListView;
+import com.android.launcher3.list.SettingsPinnedHeaderAdapter;
+
+public class OverviewSettingsPanel {
+ public static final String ANDROID_SETTINGS = "com.android.settings";
+ public static final String ANDROID_PROTECTED_APPS =
+ "com.android.settings.applications.ProtectedAppsActivity";
+ public static final String THEME_SETTINGS =
+ "com.android.settings.Settings$ThemeSettingsActivity";
+ public static final int HOME_SETTINGS_POSITION = 0;
+ public static final int DRAWER_SETTINGS_POSITION = 1;
+
+ private Launcher mLauncher;
+ private View mOverviewPanel;
+ private SettingsPinnedHeaderAdapter mSettingsAdapter;
+ private PinnedHeaderListView mListView;
+ private String[] mValues;
+
+ OverviewSettingsPanel(Launcher launcher, View overviewPanel) {
+ mLauncher = launcher;
+ mOverviewPanel = overviewPanel;
+ }
+
+ // One time initialization of the SettingsPinnedHeaderAdapter
+ public void initializeAdapter() {
+ // Settings pane Listview
+ mListView = (PinnedHeaderListView) mLauncher
+ .findViewById(R.id.settings_home_screen_listview);
+ mListView.setOverScrollMode(ListView.OVER_SCROLL_NEVER);
+ Resources res = mLauncher.getResources();
+ String[] headers = new String[] {
+ res.getString(R.string.home_screen_settings),
+ res.getString(R.string.drawer_settings),
+ res.getString(R.string.app_settings)};
+
+ String[] values;
+ if(mLauncher.isGelIntegrationSupported()) {
+ values = new String[]{
+ res.getString(R.string.home_screen_search_text),
+ res.getString(R.string.search_screen_left_text),
+ res.getString(R.string.scroll_effect_text),
+ res.getString(R.string.icon_labels),
+ res.getString(R.string.scrolling_wallpaper),
+ res.getString(R.string.grid_size_text)};
+ } else {
+ values = new String[]{
+ res.getString(R.string.home_screen_search_text),
+ res.getString(R.string.scroll_effect_text),
+ res.getString(R.string.icon_labels),
+ res.getString(R.string.scrolling_wallpaper),
+ res.getString(R.string.grid_size_text)};
+ }
+
+ mValues = values;
+
+ String[] valuesDrawer = new String[] {
+ res.getString(R.string.scroll_effect_text),
+ res.getString(R.string.drawer_sorting_text),
+ res.getString(R.string.icon_labels)};
+
+ String[] valuesApp = new String[] {
+ res.getString(R.string.larger_icons_text),
+ res.getString(R.string.protected_app_settings)};
+
+
+ mSettingsAdapter = new SettingsPinnedHeaderAdapter(mLauncher);
+ mSettingsAdapter.setHeaders(headers);
+ mSettingsAdapter.addPartition(false, true);
+ mSettingsAdapter.addPartition(false, true);
+ mSettingsAdapter.addPartition(false, true);
+ mSettingsAdapter.mPinnedHeaderCount = headers.length;
+
+ mSettingsAdapter.changeCursor(0, createCursor(headers[0], values));
+ mSettingsAdapter.changeCursor(1, createCursor(headers[1], valuesDrawer));
+ mSettingsAdapter.changeCursor(2, createCursor(headers[2], valuesApp));
+ mListView.setAdapter(mSettingsAdapter);
+ }
+
+ private Cursor createCursor(String header, String[] values) {
+ MatrixCursor cursor = new MatrixCursor(new String[]{"_id", header});
+ int count = values.length;
+ for (int i = 0; i < count; i++) {
+ cursor.addRow(new Object[]{i, values[i]});
+ }
+ return cursor;
+ }
+
+ // One time View setup
+ public void initializeViews() {
+ mOverviewPanel.setAlpha(0f);
+ mOverviewPanel
+ .setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+ | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
+ ((SlidingUpPanelLayout) mOverviewPanel)
+ .setPanelSlideListener(new SettingsSimplePanelSlideListener());
+
+ //Quick Settings Buttons
+ View widgetButton = mLauncher.findViewById(R.id.widget_button);
+ widgetButton.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View arg0) {
+ if (!mLauncher.getWorkspace().isSwitchingState()) {
+ mLauncher.showAllApps(true, AppsCustomizePagedView.ContentType.Widgets, true);
+ }
+ }
+ });
+ widgetButton.setOnTouchListener(mLauncher.getHapticFeedbackTouchListener());
+
+ View wallpaperButton = mLauncher.findViewById(R.id.wallpaper_button);
+ wallpaperButton.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View arg0) {
+ if (!mLauncher.getWorkspace().isSwitchingState()) {
+ mLauncher.startWallpaper();
+ }
+ }
+ });
+ wallpaperButton.setOnTouchListener(mLauncher.getHapticFeedbackTouchListener());
+
+ View themesButton = mLauncher.findViewById(R.id.themes_button);
+ themesButton.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View arg0) {
+ if (!mLauncher.getWorkspace().isSwitchingState()) {
+ mLauncher.startThemeSettings();
+ }
+ }
+ });
+ themesButton.setOnTouchListener(mLauncher.getHapticFeedbackTouchListener());
+
+ View defaultScreenButton = mLauncher.findViewById(R.id.default_screen_button);
+ defaultScreenButton.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View arg0) {
+ if (!mLauncher.getWorkspace().isSwitchingState()) {
+ mLauncher.getWorkspace().onClickDefaultScreenButton();
+ }
+ }
+ });
+
+ defaultScreenButton.setOnTouchListener(mLauncher.getHapticFeedbackTouchListener());
+
+ //Handle
+ View v = mOverviewPanel.findViewById(R.id.settings_pane_header);
+ ((SlidingUpPanelLayout) mOverviewPanel).setEnableDragViewTouchEvents(true);
+ ((SlidingUpPanelLayout) mOverviewPanel).setDragView(v);
+ v.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (((SlidingUpPanelLayout) mOverviewPanel).isExpanded()) {
+ ((SlidingUpPanelLayout) mOverviewPanel).collapsePane();
+ } else {
+ ((SlidingUpPanelLayout) mOverviewPanel).expandPane();
+ }
+ }
+ });
+ }
+
+ public void update() {
+ Resources res = mLauncher.getResources();
+ View widgetButton = mOverviewPanel.findViewById(R.id.widget_button);
+ View wallpaperButton = mOverviewPanel
+ .findViewById(R.id.wallpaper_button);
+ View themesButton = mOverviewPanel.findViewById(R.id.themes_button);
+ View defaultHomePanel = mOverviewPanel.findViewById(R.id.default_screen_button);
+
+ boolean isAllAppsVisible = mLauncher.isAllAppsVisible();
+
+ PagedView pagedView = !isAllAppsVisible ? mLauncher.getWorkspace()
+ : mLauncher.getAppsCustomizeContent();
+
+ defaultHomePanel.setVisibility((pagedView.getPageCount() > 1) ?
+ View.VISIBLE : View.GONE);
+
+ if (mLauncher.isAllAppsVisible()) {
+ mSettingsAdapter.changeCursor(0, createCursor(res
+ .getString(R.string.home_screen_settings), new String[]{}));
+ } else {
+ mSettingsAdapter.changeCursor(0, createCursor(res
+ .getString(R.string.home_screen_settings), mValues));
+ }
+
+ // Make sure overview panel is drawn above apps customize and collapsed
+ mOverviewPanel.bringToFront();
+ mOverviewPanel.invalidate();
+
+ ((SlidingUpPanelLayout) mOverviewPanel).setPanelHeight(isAllAppsVisible ?
+ res.getDimensionPixelSize(R.dimen.settings_pane_handle)
+ : res.getDimensionPixelSize(R.dimen.sliding_panel_padding));
+
+ ((SlidingUpPanelLayout) mOverviewPanel).collapsePane();
+ }
+
+ public void notifyDataSetInvalidated() {
+ mSettingsAdapter.notifyDataSetInvalidated();
+ }
+
+
+ class SettingsSimplePanelSlideListener extends SlidingUpPanelLayout.SimplePanelSlideListener {
+ ImageView mAnimatedArrow;
+
+ public SettingsSimplePanelSlideListener() {
+ super();
+ mAnimatedArrow = (ImageView) mOverviewPanel.findViewById(R.id.settings_drag_arrow);
+ }
+
+ @Override
+ public void onPanelCollapsed(View panel) {
+ mAnimatedArrow.setBackgroundResource(R.drawable.transition_arrow_reverse);
+
+ AnimationDrawable frameAnimation = (AnimationDrawable) mAnimatedArrow.getBackground();
+ frameAnimation.start();
+ }
+
+ @Override
+ public void onPanelExpanded(View panel) {
+ mAnimatedArrow.setBackgroundResource(R.drawable.transition_arrow);
+
+ AnimationDrawable frameAnimation = (AnimationDrawable) mAnimatedArrow.getBackground();
+ frameAnimation.start();
+ }
+ }
+}
diff --git a/src/com/android/launcher3/PageIndicator.java b/src/com/android/launcher3/PageIndicator.java
index 08e5f721a..62ea03bcc 100644
--- a/src/com/android/launcher3/PageIndicator.java
+++ b/src/com/android/launcher3/PageIndicator.java
@@ -16,22 +16,12 @@
package com.android.launcher3;
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
import android.animation.LayoutTransition;
-import android.animation.TimeInterpolator;
-import android.content.ComponentName;
import android.content.Context;
-import android.content.res.Configuration;
-import android.content.res.Resources;
import android.content.res.TypedArray;
import android.util.AttributeSet;
-import android.util.Log;
import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
import android.widget.LinearLayout;
-import com.android.launcher3.R;
import java.util.ArrayList;
diff --git a/src/com/android/launcher3/PageIndicatorMarker.java b/src/com/android/launcher3/PageIndicatorMarker.java
index b1025d6fe..f012db74b 100644
--- a/src/com/android/launcher3/PageIndicatorMarker.java
+++ b/src/com/android/launcher3/PageIndicatorMarker.java
@@ -16,17 +16,11 @@
package com.android.launcher3;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.LayoutTransition;
import android.content.Context;
import android.content.res.Resources;
import android.util.AttributeSet;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ImageView;
import android.widget.FrameLayout;
-import com.android.launcher3.R;
+import android.widget.ImageView;
public class PageIndicatorMarker extends FrameLayout {
@SuppressWarnings("unused")
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index 6463e203d..7f145aea2 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -32,7 +32,6 @@ import android.graphics.Rect;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
-import android.support.v4.view.accessibility.AccessibilityEventCompat;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
@@ -47,8 +46,13 @@ import android.view.ViewParent;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityNodeInfo;
-import android.view.animation.*;
import android.widget.Scroller;
+import android.view.animation.AccelerateDecelerateInterpolator;
+import android.view.animation.AccelerateInterpolator;
+import android.view.animation.AnimationUtils;
+import android.view.animation.DecelerateInterpolator;
+import android.view.animation.Interpolator;
+import android.view.animation.LinearInterpolator;
import java.lang.reflect.Array;
import java.util.ArrayList;
@@ -120,8 +124,10 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
protected int mNextPage = INVALID_PAGE;
protected int mMaxScrollX;
- protected Scroller mScroller;
+ protected LauncherScroller mScroller;
+ private Interpolator mDefaultInterpolator;
private VelocityTracker mVelocityTracker;
+ private int mPageSpacing = 0;
private float mParentDownMotionX;
private float mParentDownMotionY;
@@ -150,12 +156,12 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
protected int mTouchState = TOUCH_STATE_REST;
protected boolean mForceScreenScrolled = false;
+
protected OnLongClickListener mLongClickListener;
protected int mTouchSlop;
private int mPagingTouchSlop;
private int mMaximumVelocity;
- protected int mPageSpacing;
protected int mPageLayoutPaddingTop;
protected int mPageLayoutPaddingBottom;
protected int mPageLayoutPaddingLeft;
@@ -255,20 +261,16 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
private int DELETE_SLIDE_IN_SIDE_PAGE_DURATION = 250;
private int DRAG_TO_DELETE_FADE_OUT_DURATION = 350;
+ protected boolean mEnforceRealBounds = false;
// Drop to delete
private View mDeleteDropTarget;
- private boolean mAutoComputePageSpacing = false;
- private boolean mRecomputePageSpacing = false;
-
// Bouncer
private boolean mTopAlignPageWhenShrinkingForBouncer = false;
protected final Rect mInsets = new Rect();
- protected int mFirstChildLeft;
-
- private Runnable mDelayedSnapToPageRunnable;
+ protected Runnable mDelayedSnapToPageRunnable;
// Relating to the scroll and overscroll effects
protected static float CAMERA_DISTANCE = 6500;
@@ -296,10 +298,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.PagedView, defStyle, 0);
- setPageSpacing(a.getDimensionPixelSize(R.styleable.PagedView_pageSpacing, 0));
- if (mPageSpacing < 0) {
- mAutoComputePageSpacing = mRecomputePageSpacing = true;
- }
+
mPageLayoutPaddingTop = a.getDimensionPixelSize(
R.styleable.PagedView_pageLayoutPaddingTop, 0);
mPageLayoutPaddingBottom = a.getDimensionPixelSize(
@@ -325,7 +324,8 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
protected void init() {
mDirtyPageContent = new ArrayList<Boolean>();
mDirtyPageContent.ensureCapacity(32);
- mScroller = new Scroller(getContext(), new ScrollInterpolator());
+ mScroller = new LauncherScroller(getContext());
+ setDefaultInterpolator(new ScrollInterpolator());
mCurrentPage = 0;
mCenterPagesVertically = true;
@@ -345,6 +345,11 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
setOnHierarchyChangeListener(this);
}
+ protected void setDefaultInterpolator(Interpolator interpolator) {
+ mDefaultInterpolator = interpolator;
+ mScroller.setInterpolator(mDefaultInterpolator);
+ }
+
protected void onAttachedToWindow() {
super.onAttachedToWindow();
@@ -460,6 +465,10 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
return new PageIndicator.PageMarkerResources();
}
+ /**
+ * Add a page change listener which will be called when a page is _finished_ listening.
+ *
+ */
public void setPageSwitchListener(PageSwitchListener pageSwitchListener) {
mPageSwitchListener = pageSwitchListener;
if (mPageSwitchListener != null) {
@@ -524,33 +533,42 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
}
scrollTo(newX, 0);
mScroller.setFinalX(newX);
- mScroller.forceFinished(true);
+ forceFinishScroller();
}
/**
* Called during AllApps/Home transitions to avoid unnecessary work. When that other animation
- * ends, {@link #resumeScrolling()} should be called, along with
- * {@link #updateCurrentPageScroll()} to correctly set the final state and re-enable scrolling.
+ * {@link #updateCurrentPageScroll()} should be called, to correctly set the final state and
+ * re-enable scrolling.
*/
- void pauseScrolling() {
- mScroller.forceFinished(true);
+ void stopScrolling() {
+ mCurrentPage = getNextPage();
+ notifyPageSwitchListener();
+ forceFinishScroller();
}
- /**
- * Enables scrolling again.
- * @see #pauseScrolling()
- */
- void resumeScrolling() {
+ private void abortScrollerAnimation(boolean resetNextPage) {
+ mScroller.abortAnimation();
+ // We need to clean up the next page here to avoid computeScrollHelper from
+ // updating current page on the pass.
+ if (resetNextPage) {
+ mNextPage = INVALID_PAGE;
+ }
}
+
+ private void forceFinishScroller() {
+ mScroller.forceFinished(true);
+ // We need to clean up the next page here to avoid computeScrollHelper from
+ // updating current page on the pass.
+ mNextPage = INVALID_PAGE;
+ }
+
/**
* Sets the current page.
*/
void setCurrentPage(int currentPage) {
if (!mScroller.isFinished()) {
- mScroller.abortAnimation();
- // We need to clean up the next page here to avoid computeScrollHelper from
- // updating current page on the pass.
- mNextPage = INVALID_PAGE;
+ abortScrollerAnimation(true);
}
// don't introduce any checks like mCurrentPage == currentPage here-- if we change the
// the default
@@ -571,12 +589,23 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
void setRestorePage(int restorePage) {
mRestorePage = restorePage;
}
+ int getRestorePage() {
+ return mRestorePage;
+ }
+ /**
+ * Should be called whenever the page changes. In the case of a scroll, we wait until the page
+ * has settled.
+ */
protected void notifyPageSwitchListener() {
if (mPageSwitchListener != null) {
- mPageSwitchListener.onPageSwitch(getPageAt(mCurrentPage), mCurrentPage);
+ mPageSwitchListener.onPageSwitch(getPageAt(getNextPage()), getNextPage());
}
+ updatePageIndicator();
+ }
+
+ private void updatePageIndicator() {
// Update the page indicator (when we aren't reordering)
if (mPageIndicator != null && !isReordering(false)) {
mPageIndicator.setActiveMarker(getNextPage());
@@ -635,7 +664,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
@Override
public void scrollTo(int x, int y) {
// In free scroll mode, we clamp the scrollX
- if (mFreeScroll) {
+ if (mFreeScroll || mEnforceRealBounds) {
x = Math.min(x, mFreeScrollMaxScrollX);
x = Math.max(x, mFreeScrollMinScrollX);
}
@@ -688,6 +717,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
AccessibilityEvent.obtain(AccessibilityEvent.TYPE_VIEW_SCROLLED);
ev.setItemCount(getChildCount());
ev.setFromIndex(mCurrentPage);
+ ev.setToIndex(getNextPage());
final int action;
if (getNextPage() >= mCurrentPage) {
@@ -796,16 +826,16 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
- // NOTE: We multiply by 1.5f to account for the fact that depending on the offset of the
+ // NOTE: We multiply by 2f to account for the fact that depending on the offset of the
// viewport, we can be at most one and a half screens offset once we scale down
DisplayMetrics dm = getResources().getDisplayMetrics();
- int maxSize = Math.max(dm.widthPixels, dm.heightPixels + mInsets.top + mInsets.bottom);
+ int maxSize = Math.max(dm.widthPixels + mInsets.left + mInsets.right,
+ dm.heightPixels + mInsets.top + mInsets.bottom);
- int parentWidthSize, parentHeightSize;
+ int parentWidthSize = (int) (2f * maxSize);
+ int parentHeightSize = (int) (2f * maxSize);
int scaledWidthSize, scaledHeightSize;
if (mUseMinScale) {
- parentWidthSize = (int) (1.5f * maxSize);
- parentHeightSize = maxSize;
scaledWidthSize = (int) (parentWidthSize / mMinScale);
scaledHeightSize = (int) (parentHeightSize / mMinScale);
} else {
@@ -865,21 +895,17 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
childHeightMode = MeasureSpec.EXACTLY;
}
- childWidth = widthSize - horizontalPadding;
- childHeight = heightSize - verticalPadding - mInsets.top - mInsets.bottom;
+ childWidth = getViewportWidth() - horizontalPadding
+ - mInsets.left - mInsets.right;
+ childHeight = getViewportHeight() - verticalPadding
+ - mInsets.top - mInsets.bottom;
mNormalChildHeight = childHeight;
-
} else {
childWidthMode = MeasureSpec.EXACTLY;
childHeightMode = MeasureSpec.EXACTLY;
- if (mUseMinScale) {
- childWidth = getViewportWidth();
- childHeight = getViewportHeight();
- } else {
- childWidth = widthSize - getPaddingLeft() - getPaddingRight();
- childHeight = heightSize - getPaddingTop() - getPaddingBottom();
- }
+ childWidth = getViewportWidth() - mInsets.left - mInsets.right;
+ childHeight = getViewportHeight();
}
final int childWidthMeasureSpec =
@@ -890,30 +916,6 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
}
}
setMeasuredDimension(scaledWidthSize, scaledHeightSize);
-
- if (childCount > 0) {
- // Calculate the variable page spacing if necessary
- if (mAutoComputePageSpacing && mRecomputePageSpacing) {
- // The gap between pages in the PagedView should be equal to the gap from the page
- // to the edge of the screen (so it is not visible in the current screen). To
- // account for unequal padding on each side of the paged view, we take the maximum
- // of the left/right gap and use that as the gap between each page.
- int offset = (getViewportWidth() - getChildWidth(0)) / 2;
- int spacing = Math.max(offset, widthSize - offset -
- getChildAt(0).getMeasuredWidth());
- setPageSpacing(spacing);
- mRecomputePageSpacing = false;
- }
- }
- }
-
- public void setPageSpacing(int pageSpacing) {
- mPageSpacing = pageSpacing;
- requestLayout();
- }
-
- protected int getFirstChildLeft() {
- return mFirstChildLeft;
}
@Override
@@ -941,7 +943,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
int verticalPadding = getPaddingTop() + getPaddingBottom();
- int childLeft = mFirstChildLeft = offsetX + (screenWidth - getChildWidth(startIndex)) / 2;
+ int childLeft = offsetX + (screenWidth - getChildWidth(startIndex)) / 2;
if (mPageScrolls == null || getChildCount() != mChildCountOnLastLayout) {
mPageScrolls = new int[getChildCount()];
}
@@ -967,14 +969,12 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
child.layout(childLeft, childTop,
childLeft + child.getMeasuredWidth(), childTop + childHeight);
- // We assume the left and right padding are equal, and hence center the pages
- // horizontally
int scrollOffset = (getViewportWidth() - childWidth) / 2;
mPageScrolls[i] = childLeft - scrollOffset - offsetX;
if (i != endIndex - delta) {
childLeft += childWidth + scrollOffset;
- int nextScrollOffset = (getViewportWidth() - getChildWidth(i + delta)) / 2;
+ int nextScrollOffset = (getViewportWidth() - getChildWidth(i + delta)) /2;
childLeft += nextScrollOffset;
}
}
@@ -1044,6 +1044,11 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
mFadeInAdjacentScreens = fade;
}
+ public void setPageSpacing(int pageSpacing) {
+ mPageSpacing = pageSpacing;
+ requestLayout();
+ }
+
protected void screenScrolled(int screenCenter) {
boolean isInOverscroll = mOverScrollX < 0 || mOverScrollX > mMaxScrollX;
// Apply transition effect and adjacent screen fade if enabled
@@ -1136,7 +1141,6 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
// This ensures that when children are added, they get the correct transforms / alphas
// in accordance with any scroll effects.
mForceScreenScrolled = true;
- mRecomputePageSpacing = true;
updateFreescrollBounds();
invalidate();
}
@@ -1254,22 +1258,22 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
@Override
protected void dispatchDraw(Canvas canvas) {
- int halfScreenSize = getViewportWidth() / 2;
- // mOverScrollX is equal to getScrollX() when we're within the normal scroll range.
- // Otherwise it is equal to the scaled overscroll position.
- int screenCenter = mOverScrollX + halfScreenSize;
-
- if (screenCenter != mLastScreenCenter || mForceScreenScrolled) {
- // set mForceScreenScrolled before calling screenScrolled so that screenScrolled can
- // set it for the next frame
- mForceScreenScrolled = false;
- screenScrolled(screenCenter);
- mLastScreenCenter = screenCenter;
- }
-
// Find out which screens are visible; as an optimization we only call draw on them
final int pageCount = getChildCount();
if (pageCount > 0) {
+ int halfScreenSize = getViewportWidth() / 2;
+ // mOverScrollX is equal to getScrollX() when we're within the normal scroll range.
+ // Otherwise it is equal to the scaled overscroll position.
+ int screenCenter = mOverScrollX + halfScreenSize;
+
+ if (screenCenter != mLastScreenCenter || mForceScreenScrolled) {
+ // set mForceScreenScrolled before calling screenScrolled so that screenScrolled can
+ // set it for the next frame
+ mForceScreenScrolled = false;
+ screenScrolled(screenCenter);
+ mLastScreenCenter = screenCenter;
+ }
+
getVisiblePages(mTempVisiblePagesRange);
final int leftScreen = mTempVisiblePagesRange[0];
final int rightScreen = mTempVisiblePagesRange[1];
@@ -1405,24 +1409,22 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
* Return true if a tap at (x, y) should trigger a flip to the previous page.
*/
protected boolean hitsPreviousPage(float x, float y) {
- int offset = (getViewportWidth() - getChildWidth(mCurrentPage)) / 2;
if (isLayoutRtl()) {
return (x > (getViewportOffsetX() + getViewportWidth() -
- offset + mPageSpacing));
+ getPaddingRight() - mPageSpacing));
}
- return (x < getViewportOffsetX() + offset - mPageSpacing);
+ return (x < getViewportOffsetX() + getPaddingLeft() + mPageSpacing);
}
/**
* Return true if a tap at (x, y) should trigger a flip to the next page.
*/
protected boolean hitsNextPage(float x, float y) {
- int offset = (getViewportWidth() - getChildWidth(mCurrentPage)) / 2;
if (isLayoutRtl()) {
- return (x < getViewportOffsetX() + offset - mPageSpacing);
+ return (x < getViewportOffsetX() + getPaddingLeft() + mPageSpacing);
}
return (x > (getViewportOffsetX() + getViewportWidth() -
- offset + mPageSpacing));
+ getPaddingRight() - mPageSpacing));
}
/** Returns whether x and y originated within the buffered viewport */
@@ -1498,10 +1500,14 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
* being flinged.
*/
final int xDist = Math.abs(mScroller.getFinalX() - mScroller.getCurrX());
- final boolean finishedScrolling = (mScroller.isFinished() || xDist < mTouchSlop);
+ final boolean finishedScrolling = (mScroller.isFinished() || xDist < mTouchSlop / 3);
+
if (finishedScrolling) {
mTouchState = TOUCH_STATE_REST;
- mScroller.abortAnimation();
+ if (!mScroller.isFinished() && !mFreeScroll) {
+ setCurrentPage(getNextPage());
+ pageEndMoving();
+ }
} else {
if (isTouchPointInViewportWithBuffer((int) mDownMotionX, (int) mDownMotionY)) {
mTouchState = TOUCH_STATE_SCROLLING;
@@ -1613,8 +1619,21 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
protected float getScrollProgress(int screenCenter, View v, int page) {
final int halfScreenSize = getViewportWidth() / 2;
- int totalDistance = v.getMeasuredWidth() + mPageSpacing;
int delta = screenCenter - (getScrollForPage(page) + halfScreenSize);
+ int count = getChildCount();
+
+ final int totalDistance;
+
+ int adjacentPage = page + 1;
+ if ((delta < 0 && !isLayoutRtl()) || (delta > 0 && isLayoutRtl())) {
+ adjacentPage = page - 1;
+ }
+
+ if (adjacentPage < 0 || adjacentPage > count - 1) {
+ totalDistance = v.getMeasuredWidth() + mPageSpacing;
+ } else {
+ totalDistance = Math.abs(getScrollForPage(adjacentPage) - getScrollForPage(page));
+ }
float scrollProgress = delta / (totalDistance * 1.0f);
scrollProgress = Math.min(scrollProgress, getMaxScrollProgress());
@@ -1637,9 +1656,15 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
return 0;
} else {
View child = getChildAt(index);
- int scrollOffset = (getViewportWidth() - child.getMeasuredWidth()) / 2;
+
+ int scrollOffset = 0;
+ LayoutParams lp = (LayoutParams) child.getLayoutParams();
+ if (!lp.isFullScreenPage) {
+ scrollOffset = isLayoutRtl() ? getPaddingRight() : getPaddingLeft();
+ }
+
int baselineX = mPageScrolls[index] + scrollOffset + getViewportOffsetX();
- return (int) (child.getX() - baselineX);
+ return (int) (child.getLeft() - baselineX);
}
}
@@ -1712,11 +1737,11 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
}
protected void enableFreeScroll() {
- setEnableFreeScroll(true, -1);
+ setEnableFreeScroll(true);
}
- protected void disableFreeScroll(int snapPage) {
- setEnableFreeScroll(false, snapPage);
+ protected void disableFreeScroll() {
+ setEnableFreeScroll(false);
}
void updateFreescrollBounds() {
@@ -1730,16 +1755,10 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
}
}
- private void setEnableFreeScroll(boolean freeScroll, int snapPage) {
+ private void setEnableFreeScroll(boolean freeScroll) {
mFreeScroll = freeScroll;
- if (snapPage == -1) {
- snapPage = getPageNearestToCenterOfScreen();
- }
-
- if (!mFreeScroll) {
- snapToPage(snapPage);
- } else {
+ if (mFreeScroll) {
updateFreescrollBounds();
getOverviewModePages(mTempVisiblePagesRange);
if (getCurrentPage() < mTempVisiblePagesRange[0]) {
@@ -1799,7 +1818,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
* will be false if being flinged.
*/
if (!mScroller.isFinished()) {
- mScroller.abortAnimation();
+ abortScrollerAnimation(false);
}
// Remember where the motion event started
@@ -1925,7 +1944,9 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
addView(mDragView, pageUnderPointIndex);
onAddView(mDragView, pageUnderPointIndex);
mSidePageHoverIndex = -1;
- mPageIndicator.setActiveMarker(getNextPage());
+ if (mPageIndicator != null) {
+ mPageIndicator.setActiveMarker(getNextPage());
+ }
}
};
postDelayed(mSidePageHoverRunnable, REORDERING_SIDE_PAGE_HOVER_TIMEOUT);
@@ -1985,29 +2006,31 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
snapToPageWithVelocity(finalPage, velocityX);
} else {
snapToDestination();
- } } else if (mTouchState == TOUCH_STATE_PREV_PAGE) {
- // at this point we have not moved beyond the touch slop
- // (otherwise mTouchState would be TOUCH_STATE_SCROLLING), so
- // we can just page
- int nextPage = Math.max(0, mCurrentPage - 1);
- if (nextPage != mCurrentPage) {
- snapToPage(nextPage);
- } else {
- snapToDestination();
}
} else {
if (!mScroller.isFinished()) {
- mScroller.abortAnimation();
+ abortScrollerAnimation(true);
}
float scaleX = getScaleX();
int vX = (int) (-velocityX * scaleX);
int initialScrollX = (int) (getScrollX() * scaleX);
+ mScroller.setInterpolator(mDefaultInterpolator);
mScroller.fling(initialScrollX,
getScrollY(), vX, 0, Integer.MIN_VALUE, Integer.MAX_VALUE, 0, 0);
invalidate();
}
+ } else if (mTouchState == TOUCH_STATE_PREV_PAGE) {
+ // at this point we have not moved beyond the touch slop
+ // (otherwise mTouchState would be TOUCH_STATE_SCROLLING), so
+ // we can just page
+ int nextPage = Math.max(0, mCurrentPage - 1);
+ if (nextPage != mCurrentPage) {
+ snapToPage(nextPage);
+ } else {
+ snapToDestination();
+ }
} else if (mTouchState == TOUCH_STATE_NEXT_PAGE) {
// at this point we have not moved beyond the touch slop
// (otherwise mTouchState would be TOUCH_STATE_SCROLLING), so
@@ -2267,27 +2290,33 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
}
protected void snapToPageImmediately(int whichPage) {
- snapToPage(whichPage, PAGE_SNAP_ANIMATION_DURATION, true);
+ snapToPage(whichPage, PAGE_SNAP_ANIMATION_DURATION, true, null);
}
protected void snapToPage(int whichPage, int duration) {
- snapToPage(whichPage, duration, false);
+ snapToPage(whichPage, duration, false, null);
}
- protected void snapToPage(int whichPage, int duration, boolean immediate) {
+ protected void snapToPage(int whichPage, int duration, TimeInterpolator interpolator) {
+ snapToPage(whichPage, duration, false, interpolator);
+ }
+
+ protected void snapToPage(int whichPage, int duration, boolean immediate,
+ TimeInterpolator interpolator) {
whichPage = Math.max(0, Math.min(whichPage, getPageCount() - 1));
int newX = getScrollForPage(whichPage);
final int sX = mUnboundedScrollX;
final int delta = newX - sX;
- snapToPage(whichPage, delta, duration, immediate);
+ snapToPage(whichPage, delta, duration, immediate, interpolator);
}
protected void snapToPage(int whichPage, int delta, int duration) {
- snapToPage(whichPage, delta, duration, false);
+ snapToPage(whichPage, delta, duration, false, null);
}
- protected void snapToPage(int whichPage, int delta, int duration, boolean immediate) {
+ protected void snapToPage(int whichPage, int delta, int duration, boolean immediate,
+ TimeInterpolator interpolator) {
mNextPage = whichPage;
View focusedChild = getFocusedChild();
if (focusedChild != null && whichPage != mCurrentPage &&
@@ -2306,11 +2335,18 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
}
if (!mScroller.isFinished()) {
- mScroller.abortAnimation();
+ abortScrollerAnimation(false);
}
+
+ if (interpolator != null) {
+ mScroller.setInterpolator(interpolator);
+ } else {
+ mScroller.setInterpolator(mDefaultInterpolator);
+ }
+
mScroller.startScroll(mUnboundedScrollX, 0, delta, 0, duration);
- notifyPageSwitchListener();
+ updatePageIndicator();
// Trigger a compute() to finish switching pages if necessary
if (immediate) {
@@ -2469,8 +2505,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
if (mContentIsRefreshable) {
// Force all scrolling-related behavior to end
- mScroller.forceFinished(true);
- mNextPage = INVALID_PAGE;
+ forceFinishScroller();
// Update all the pages
syncPages();
@@ -2565,7 +2600,8 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
mDragView = getChildAt(dragViewIndex);
mDragView.animate().scaleX(1.15f).scaleY(1.15f).setDuration(100).start();
mDragViewBaselineLeft = mDragView.getLeft();
- disableFreeScroll(-1);
+ snapToPage(getPageNearestToCenterOfScreen());
+ disableFreeScroll();
onStartReordering();
return true;
}
@@ -2597,7 +2633,6 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
mPostReorderingPreZoomInRunnable = new Runnable() {
public void run() {
onCompleteRunnable.run();
- enableFreeScroll();
};
};
diff --git a/src/com/android/launcher3/PagedViewIcon.java b/src/com/android/launcher3/PagedViewIcon.java
index 785725852..01e41078b 100644
--- a/src/com/android/launcher3/PagedViewIcon.java
+++ b/src/com/android/launcher3/PagedViewIcon.java
@@ -20,6 +20,7 @@ import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Region;
+import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.widget.TextView;
@@ -64,17 +65,22 @@ public class PagedViewIcon extends TextView {
// Ensure we are using the right text size
LauncherAppState app = LauncherAppState.getInstance();
DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
- setTextSize(TypedValue.COMPLEX_UNIT_SP, grid.iconTextSize);
+ setTextSize(TypedValue.COMPLEX_UNIT_PX, grid.allAppsIconTextSizePx);
mTextColor = getCurrentTextColor();
mIsTextVisible = mTextColor != getResources().getColor(android.R.color.transparent);
}
public void applyFromApplicationInfo(AppInfo info, boolean scaleUp,
PagedViewIcon.PressedCallback cb) {
+ LauncherAppState app = LauncherAppState.getInstance();
+ DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
+
mIcon = info.iconBitmap;
mPressedCallback = cb;
- setCompoundDrawables(null, Utilities.createIconDrawable(mIcon),
- null, null);
+ Drawable icon = Utilities.createIconDrawable(mIcon);
+ icon.setBounds(0, 0, grid.allAppsIconSizePx, grid.allAppsIconSizePx);
+ setCompoundDrawables(null, icon, null, null);
+ setCompoundDrawablePadding(grid.iconDrawablePaddingPx);
setText(info.title);
setTag(info);
}
diff --git a/src/com/android/launcher3/PagedViewIconCache.java b/src/com/android/launcher3/PagedViewIconCache.java
index 8d8924b7e..93887ea23 100644
--- a/src/com/android/launcher3/PagedViewIconCache.java
+++ b/src/com/android/launcher3/PagedViewIconCache.java
@@ -16,17 +16,17 @@
package com.android.launcher3;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-
import android.appwidget.AppWidgetProviderInfo;
import android.content.ComponentName;
import android.content.pm.ComponentInfo;
import android.content.pm.ResolveInfo;
import android.graphics.Bitmap;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+
/**
* Simple cache mechanism for PagedView outlines.
*/
diff --git a/src/com/android/launcher3/PagedViewWidget.java b/src/com/android/launcher3/PagedViewWidget.java
index 45320a484..db4aeb940 100644
--- a/src/com/android/launcher3/PagedViewWidget.java
+++ b/src/com/android/launcher3/PagedViewWidget.java
@@ -30,8 +30,6 @@ import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
-import com.android.launcher3.R;
-
/**
* The linear layout used strictly for the widget/wallpaper tab of the customization tray
*/
@@ -84,11 +82,11 @@ public class PagedViewWidget extends LinearLayout {
DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
TextView name = (TextView) findViewById(R.id.widget_name);
if (name != null) {
- name.setTextSize(TypedValue.COMPLEX_UNIT_SP, grid.iconTextSize);
+ name.setTextSize(TypedValue.COMPLEX_UNIT_PX, grid.iconTextSizePx);
}
TextView dims = (TextView) findViewById(R.id.widget_dims);
if (dims != null) {
- dims.setTextSize(TypedValue.COMPLEX_UNIT_SP, grid.iconTextSize);
+ dims.setTextSize(TypedValue.COMPLEX_UNIT_PX, grid.iconTextSizePx);
}
}
diff --git a/src/com/android/launcher3/PreloadReceiver.java b/src/com/android/launcher3/PreloadReceiver.java
index 75e5c98bc..ca25746eb 100644
--- a/src/com/android/launcher3/PreloadReceiver.java
+++ b/src/com/android/launcher3/PreloadReceiver.java
@@ -19,6 +19,7 @@ package com.android.launcher3;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
+import android.os.AsyncTask;
import android.text.TextUtils;
import android.util.Log;
@@ -39,12 +40,12 @@ public class PreloadReceiver extends BroadcastReceiver {
if (LOGD) {
Log.d(TAG, "workspace name: " + name + " id: " + workspaceResId);
}
- new Thread(new Runnable() {
- @Override
- public void run() {
+ new AsyncTask<Void, Void, Void>() {
+ public Void doInBackground(Void ... args) {
provider.loadDefaultFavoritesIfNecessary(workspaceResId);
+ return null;
}
- }).start();
+ }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void) null);
}
}
}
diff --git a/src/com/android/launcher3/RampUpScroller.java b/src/com/android/launcher3/RampUpScroller.java
deleted file mode 100644
index 89eb5798e..000000000
--- a/src/com/android/launcher3/RampUpScroller.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3;
-
-import android.view.animation.AccelerateInterpolator;
-import android.view.animation.AnimationUtils;
-import android.view.animation.Interpolator;
-
-/**
- * Scroller that gradually reaches a target velocity.
- */
-class RampUpScroller {
- private final Interpolator mInterpolator;
- private final long mRampUpTime;
-
- private long mStartTime;
- private long mDeltaTime;
- private float mTargetVelocityX;
- private float mTargetVelocityY;
- private int mDeltaX;
- private int mDeltaY;
-
- /**
- * Creates a new ramp-up scroller that reaches full velocity after a
- * specified duration.
- *
- * @param rampUpTime Duration before the scroller reaches target velocity.
- */
- public RampUpScroller(long rampUpTime) {
- mInterpolator = new AccelerateInterpolator();
- mRampUpTime = rampUpTime;
- }
-
- /**
- * Starts the scroller at the current animation time.
- */
- public void start() {
- mStartTime = AnimationUtils.currentAnimationTimeMillis();
- mDeltaTime = mStartTime;
- }
-
- /**
- * Computes the current scroll deltas. This usually only be called after
- * starting the scroller with {@link #start()}.
- *
- * @see #getDeltaX()
- * @see #getDeltaY()
- */
- public void computeScrollDelta() {
- final long currentTime = AnimationUtils.currentAnimationTimeMillis();
- final long elapsedSinceStart = currentTime - mStartTime;
- final float scale;
- if (elapsedSinceStart < mRampUpTime) {
- scale = mInterpolator.getInterpolation((float) elapsedSinceStart / mRampUpTime);
- } else {
- scale = 1f;
- }
-
- final long elapsedSinceDelta = currentTime - mDeltaTime;
- mDeltaTime = currentTime;
-
- mDeltaX = (int) (elapsedSinceDelta * scale * mTargetVelocityX);
- mDeltaY = (int) (elapsedSinceDelta * scale * mTargetVelocityY);
- }
-
- /**
- * Sets the target velocity for this scroller.
- *
- * @param x The target X velocity in pixels per millisecond.
- * @param y The target Y velocity in pixels per millisecond.
- */
- public void setTargetVelocity(float x, float y) {
- mTargetVelocityX = x;
- mTargetVelocityY = y;
- }
-
- /**
- * @return The target X velocity for this scroller.
- */
- public float getTargetVelocityX() {
- return mTargetVelocityX;
- }
-
- /**
- * @return The target Y velocity for this scroller.
- */
- public float getTargetVelocityY() {
- return mTargetVelocityY;
- }
-
- /**
- * The distance traveled in the X-coordinate computed by the last call to
- * {@link #computeScrollDelta()}.
- */
- public int getDeltaX() {
- return mDeltaX;
- }
-
- /**
- * The distance traveled in the Y-coordinate computed by the last call to
- * {@link #computeScrollDelta()}.
- */
- public int getDeltaY() {
- return mDeltaY;
- }
-}
diff --git a/src/com/android/launcher3/ScrimView.java b/src/com/android/launcher3/ScrimView.java
index 6831fe3d4..68200fe64 100644
--- a/src/com/android/launcher3/ScrimView.java
+++ b/src/com/android/launcher3/ScrimView.java
@@ -17,11 +17,8 @@
package com.android.launcher3;
import android.content.Context;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
import android.graphics.Rect;
import android.util.AttributeSet;
-import android.view.View;
import android.widget.FrameLayout;
public class ScrimView extends FrameLayout implements Insettable {
diff --git a/src/com/android/launcher3/SearchDropTargetBar.java b/src/com/android/launcher3/SearchDropTargetBar.java
index 15452070c..d38c61209 100644
--- a/src/com/android/launcher3/SearchDropTargetBar.java
+++ b/src/com/android/launcher3/SearchDropTargetBar.java
@@ -69,6 +69,11 @@ public class SearchDropTargetBar extends FrameLayout implements DragController.D
dragController.setFlingToDeleteDropTarget(mDeleteDropTarget);
mInfoDropTarget.setLauncher(launcher);
mDeleteDropTarget.setLauncher(launcher);
+
+ setupQSB(launcher);
+ }
+
+ public void setupQSB(Launcher launcher) {
mQSBSearchBar = launcher.getQsbBar();
if (mEnableDropDownDropTargets) {
mQSBSearchBarAnim = LauncherAnimUtils.ofFloat(mQSBSearchBar, "translationY", 0,
@@ -188,7 +193,7 @@ public class SearchDropTargetBar extends FrameLayout implements DragController.D
// Animate out the QSB search bar, and animate in the drop target bar
prepareStartAnimation(mDropTargetBar);
mDropTargetBarAnim.start();
- if (!mIsSearchBarHidden) {
+ if (!mIsSearchBarHidden || mQSBSearchBar.getAlpha() > 0f) {
prepareStartAnimation(mQSBSearchBar);
mQSBSearchBarAnim.start();
}
@@ -204,7 +209,7 @@ public class SearchDropTargetBar extends FrameLayout implements DragController.D
// Restore the QSB search bar, and animate out the drop target bar
prepareStartAnimation(mDropTargetBar);
mDropTargetBarAnim.reverse();
- if (!mIsSearchBarHidden) {
+ if (!mIsSearchBarHidden || mQSBSearchBar.getAlpha() < 1f) {
prepareStartAnimation(mQSBSearchBar);
mQSBSearchBarAnim.reverse();
}
diff --git a/src/com/android/launcher3/ShortcutInfo.java b/src/com/android/launcher3/ShortcutInfo.java
index 0998eec2b..a13aaa911 100644
--- a/src/com/android/launcher3/ShortcutInfo.java
+++ b/src/com/android/launcher3/ShortcutInfo.java
@@ -20,9 +20,9 @@ import android.content.ComponentName;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.PackageInfo;
import android.graphics.Bitmap;
import android.util.Log;
@@ -64,6 +64,12 @@ class ShortcutInfo extends ItemInfo {
long firstInstallTime;
int flags = 0;
+ /**
+ * If this shortcut is a placeholder, then intent will be a market intent for the package, and
+ * this will hold the original intent from the database. Otherwise, null.
+ */
+ Intent restoredIntent;
+
ShortcutInfo() {
itemType = LauncherSettings.BaseLauncherColumns.ITEM_TYPE_SHORTCUT;
}
@@ -71,7 +77,29 @@ class ShortcutInfo extends ItemInfo {
protected Intent getIntent() {
return intent;
}
-
+
+ protected Intent getRestoredIntent() {
+ return restoredIntent;
+ }
+
+ /**
+ * Overwrite placeholder data with restored data, or do nothing if this is not a placeholder.
+ */
+ public void restore() {
+ if (restoredIntent != null) {
+ intent = restoredIntent;
+ restoredIntent = null;
+ }
+ }
+
+
+ ShortcutInfo(Intent intent, CharSequence title, Bitmap icon) {
+ this();
+ this.intent = intent;
+ this.title = title;
+ mIcon = icon;
+ }
+
public ShortcutInfo(Context context, ShortcutInfo info) {
super(info);
title = info.title.toString();
diff --git a/src/com/android/launcher3/SlidingUpPanelLayout.java b/src/com/android/launcher3/SlidingUpPanelLayout.java
new file mode 100644
index 000000000..52deeb355
--- /dev/null
+++ b/src/com/android/launcher3/SlidingUpPanelLayout.java
@@ -0,0 +1,1315 @@
+package com.android.launcher3;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.os.Build;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.support.v4.view.MotionEventCompat;
+import android.support.v4.view.ViewCompat;
+import android.support.v4.widget.ViewDragHelper;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.MotionEvent;
+import android.view.SoundEffectConstants;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.animation.Animation;
+import android.view.animation.TranslateAnimation;
+
+public class SlidingUpPanelLayout extends ViewGroup {
+ private static final String TAG = SlidingUpPanelLayout.class.getSimpleName();
+
+ /**
+ * Default peeking out panel height
+ */
+ private static final int DEFAULT_PANEL_HEIGHT = 68; // dp;
+
+ /**
+ * Default height of the shadow above the peeking out panel
+ */
+ private static final int DEFAULT_SHADOW_HEIGHT = 4; // dp;
+
+ /**
+ * If no fade color is given by default it will fade to 80% gray.
+ */
+ private static final int DEFAULT_FADE_COLOR = 0x99000000;
+
+ /**
+ * Default Minimum velocity that will be detected as a fling
+ */
+ private static final int DEFAULT_MIN_FLING_VELOCITY = 400; // dips per second
+ /**
+ * Default is set to false because that is how it was written
+ */
+ private static final boolean DEFAULT_OVERLAY_FLAG = false;
+ /**
+ * Default attributes for layout
+ */
+ private static final int[] DEFAULT_ATTRS = new int[] {
+ android.R.attr.gravity
+ };
+
+ /**
+ * Minimum velocity that will be detected as a fling
+ */
+ private int mMinFlingVelocity = DEFAULT_MIN_FLING_VELOCITY;
+
+ /**
+ * The fade color used for the panel covered by the slider. 0 = no fading.
+ */
+ private int mCoveredFadeColor = DEFAULT_FADE_COLOR;
+
+ /**
+ * Default paralax length of the main view
+ */
+ private static final int DEFAULT_PARALAX_OFFSET = 0;
+
+ /**
+ * The paint used to dim the main layout when sliding
+ */
+ private final Paint mCoveredFadePaint = new Paint();
+
+ /**
+ * Drawable used to draw the shadow between panes.
+ */
+ private final Drawable mShadowDrawable;
+
+ /**
+ * The size of the overhang in pixels.
+ */
+ private int mPanelHeight = -1;
+
+ /**
+ * The size of the shadow in pixels.
+ */
+ private int mShadowHeight = -1;
+
+ /**
+ * Paralax offset
+ */
+ private int mParalaxOffset = -1;
+
+ /**
+ * True if the collapsed panel should be dragged up.
+ */
+ private boolean mIsSlidingUp;
+
+ /**
+ * True if a panel can slide with the current measurements
+ */
+ private boolean mCanSlide;
+
+ /**
+ * Panel overlays the windows instead of putting it underneath it.
+ */
+ private boolean mOverlayContent = DEFAULT_OVERLAY_FLAG;
+
+ /**
+ * If provided, the panel can be dragged by only this view. Otherwise, the entire panel can be
+ * used for dragging.
+ */
+ private View mDragView;
+
+ /**
+ * If provided, the panel can be dragged by only this view. Otherwise, the entire panel can be
+ * used for dragging.
+ */
+ private int mDragViewResId = -1;
+
+ /**
+ * The child view that can slide, if any.
+ */
+ private View mSlideableView;
+
+ /**
+ * The main view
+ */
+ private View mMainView;
+
+ /**
+ * Current state of the slideable view.
+ */
+ private enum SlideState {
+ EXPANDED,
+ COLLAPSED,
+ ANCHORED
+ }
+ private SlideState mSlideState = SlideState.COLLAPSED;
+
+ /**
+ * How far the panel is offset from its expanded position.
+ * range [0, 1] where 0 = expanded, 1 = collapsed.
+ */
+ private float mSlideOffset;
+
+ /**
+ * How far in pixels the slideable panel may move.
+ */
+ private int mSlideRange;
+
+ /**
+ * A panel view is locked into internal scrolling or another condition that
+ * is preventing a drag.
+ */
+ private boolean mIsUnableToDrag;
+
+ /**
+ * Flag indicating that sliding feature is enabled\disabled
+ */
+ private boolean mIsSlidingEnabled;
+
+ /**
+ * Flag indicating if a drag view can have its own touch events. If set
+ * to true, a drag view can scroll horizontally and have its own click listener.
+ *
+ * Default is set to false.
+ */
+ private boolean mIsUsingDragViewTouchEvents;
+
+ /**
+ * Threshold to tell if there was a scroll touch event.
+ */
+ private final int mScrollTouchSlop;
+
+ private float mInitialMotionX;
+ private float mInitialMotionY;
+ private float mAnchorPoint = 0.f;
+ private TranslateAnimation mAnimation;
+
+ private PanelSlideListener mPanelSlideListener;
+
+ private final ViewDragHelper mDragHelper;
+
+ /**
+ * Stores whether or not the pane was expanded the last time it was slideable.
+ * If expand/collapse operations are invoked this state is modified. Used by
+ * instance state save/restore.
+ */
+ private boolean mFirstLayout = true;
+
+ private final Rect mTmpRect = new Rect();
+
+ /**
+ * Listener for monitoring events about sliding panes.
+ */
+ public interface PanelSlideListener {
+ /**
+ * Called when a sliding pane's position changes.
+ * @param panel The child view that was moved
+ * @param slideOffset The new offset of this sliding pane within its range, from 0-1
+ */
+ public void onPanelSlide(View panel, float slideOffset);
+ /**
+ * Called when a sliding pane becomes slid completely collapsed. The pane may or may not
+ * be interactive at this point depending on if it's shown or hidden
+ * @param panel The child view that was slid to an collapsed position, revealing other panes
+ */
+ public void onPanelCollapsed(View panel);
+
+ /**
+ * Called when a sliding pane becomes slid completely expanded. The pane is now guaranteed
+ * to be interactive. It may now obscure other views in the layout.
+ * @param panel The child view that was slid to a expanded position
+ */
+ public void onPanelExpanded(View panel);
+
+ public void onPanelAnchored(View panel);
+ }
+
+ /**
+ * No-op stubs for {@link PanelSlideListener}. If you only want to implement a subset
+ * of the listener methods you can extend this instead of implement the full interface.
+ */
+ public static class SimplePanelSlideListener implements PanelSlideListener {
+ @Override
+ public void onPanelSlide(View panel, float slideOffset) {
+ }
+ @Override
+ public void onPanelCollapsed(View panel) {
+ }
+ @Override
+ public void onPanelExpanded(View panel) {
+ }
+ @Override
+ public void onPanelAnchored(View panel) {
+ }
+ }
+
+ public SlidingUpPanelLayout(Context context) {
+ this(context, null);
+ }
+
+ public SlidingUpPanelLayout(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public SlidingUpPanelLayout(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ if (attrs != null) {
+ TypedArray defAttrs = context.obtainStyledAttributes(attrs, DEFAULT_ATTRS);
+
+ if (defAttrs != null) {
+ int gravity = defAttrs.getInt(0, Gravity.NO_GRAVITY);
+ if (gravity != Gravity.TOP && gravity != Gravity.BOTTOM) {
+ throw new IllegalArgumentException("gravity must be set to either top or bottom");
+ }
+ mIsSlidingUp = gravity == Gravity.BOTTOM;
+ }
+
+ defAttrs.recycle();
+
+ TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SlidingUpPanelLayout);
+
+ if (ta != null) {
+ mPanelHeight = ta.getDimensionPixelSize(R.styleable.SlidingUpPanelLayout_panelHeight, -1);
+ mShadowHeight = ta.getDimensionPixelSize(R.styleable.SlidingUpPanelLayout_shadowHeight, -1);
+ mParalaxOffset = ta.getDimensionPixelSize(R.styleable.SlidingUpPanelLayout_paralaxOffset, -1);
+
+ mMinFlingVelocity = ta.getInt(R.styleable.SlidingUpPanelLayout_flingVelocity, DEFAULT_MIN_FLING_VELOCITY);
+ mCoveredFadeColor = ta.getColor(R.styleable.SlidingUpPanelLayout_fadeColor, DEFAULT_FADE_COLOR);
+
+ mDragViewResId = ta.getResourceId(R.styleable.SlidingUpPanelLayout_dragView, -1);
+
+ mOverlayContent = ta.getBoolean(R.styleable.SlidingUpPanelLayout_overlay,DEFAULT_OVERLAY_FLAG);
+ }
+
+ ta.recycle();
+ }
+
+ final float density = context.getResources().getDisplayMetrics().density;
+ if (mPanelHeight == -1) {
+ mPanelHeight = (int) (DEFAULT_PANEL_HEIGHT * density + 0.5f);
+ }
+ if (mShadowHeight == -1) {
+ mShadowHeight = (int) (DEFAULT_SHADOW_HEIGHT * density + 0.5f);
+ }
+ if (mParalaxOffset == -1) {
+ mParalaxOffset = (int) (DEFAULT_PARALAX_OFFSET * density);
+ }
+ // If the shadow height is zero, don't show the shadow
+ if (mShadowHeight > 0) {
+ if (mIsSlidingUp) {
+ mShadowDrawable = getResources().getDrawable(R.drawable.above_shadow);
+ } else {
+ mShadowDrawable = getResources().getDrawable(R.drawable.below_shadow);
+ }
+
+ } else {
+ mShadowDrawable = null;
+ }
+
+ setWillNotDraw(false);
+
+ mDragHelper = ViewDragHelper.create(this, 0.5f, new DragHelperCallback());
+ mDragHelper.setMinVelocity(mMinFlingVelocity * density);
+
+ mCanSlide = true;
+ mIsSlidingEnabled = true;
+
+ ViewConfiguration vc = ViewConfiguration.get(context);
+ mScrollTouchSlop = vc.getScaledTouchSlop();
+ }
+
+ /**
+ * Set the Drag View after the view is inflated
+ */
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ if (mDragViewResId != -1) {
+ mDragView = findViewById(mDragViewResId);
+ }
+ }
+
+ /**
+ * Set the color used to fade the pane covered by the sliding pane out when the pane
+ * will become fully covered in the expanded state.
+ *
+ * @param color An ARGB-packed color value
+ */
+ public void setCoveredFadeColor(int color) {
+ mCoveredFadeColor = color;
+ invalidate();
+ }
+
+ /**
+ * @return The ARGB-packed color value used to fade the fixed pane
+ */
+ public int getCoveredFadeColor() {
+ return mCoveredFadeColor;
+ }
+
+ /**
+ * Set sliding enabled flag
+ * @param enabled flag value
+ */
+ public void setSlidingEnabled(boolean enabled) {
+ mIsSlidingEnabled = enabled;
+ }
+
+ /**
+ * Set the collapsed panel height in pixels
+ *
+ * @param val A height in pixels
+ */
+ public void setPanelHeight(int val) {
+ mPanelHeight = val;
+ requestLayout();
+ }
+
+ /**
+ * @return The current collapsed panel height
+ */
+ public int getPanelHeight() {
+ return mPanelHeight;
+ }
+
+ /**
+ * @return The current paralax offset
+ */
+ public int getCurrentParalaxOffset() {
+ int offset = (int)(mParalaxOffset * (1 - mSlideOffset));
+ return mIsSlidingUp ? -offset : offset;
+ }
+
+ /**
+ * Sets the panel slide listener
+ * @param listener
+ */
+ public void setPanelSlideListener(PanelSlideListener listener) {
+ mPanelSlideListener = listener;
+ }
+
+ /**
+ * Set the draggable view portion. Use to null, to allow the whole panel to be draggable
+ *
+ * @param dragView A view that will be used to drag the panel.
+ */
+ public void setDragView(View dragView) {
+ mDragView = dragView;
+ }
+
+ /**
+ * Set an anchor point where the panel can stop during sliding
+ *
+ * @param anchorPoint A value between 0 and 1, determining the position of the anchor point
+ * starting from the top of the layout.
+ */
+ public void setAnchorPoint(float anchorPoint) {
+ if (anchorPoint > 0 && anchorPoint < 1)
+ mAnchorPoint = anchorPoint;
+ }
+
+ /**
+ * Sets whether or not the panel overlays the content
+ * @param overlayed
+ */
+ public void setOverlayed(boolean overlayed) {
+ mOverlayContent = overlayed;
+ }
+
+ /**
+ * Check if the panel is set as an overlay.
+ */
+ public boolean isOverlayed() {
+ return mOverlayContent;
+ }
+
+ void dispatchOnPanelSlide(View panel) {
+ if (mPanelSlideListener != null) {
+ mPanelSlideListener.onPanelSlide(panel, mSlideOffset);
+ }
+ }
+
+ void dispatchOnPanelExpanded(View panel) {
+ if (mPanelSlideListener != null) {
+ mPanelSlideListener.onPanelExpanded(panel);
+ }
+ sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
+ }
+
+ void dispatchOnPanelCollapsed(View panel) {
+ if (mPanelSlideListener != null) {
+ mPanelSlideListener.onPanelCollapsed(panel);
+ }
+ sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
+ }
+
+ void dispatchOnPanelAnchored(View panel) {
+ if (mPanelSlideListener != null) {
+ mPanelSlideListener.onPanelAnchored(panel);
+ }
+ sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
+ }
+
+ void updateObscuredViewVisibility() {
+ if (getChildCount() == 0) {
+ return;
+ }
+ final int leftBound = getPaddingLeft();
+ final int rightBound = getWidth() - getPaddingRight();
+ final int topBound = getPaddingTop();
+ final int bottomBound = getHeight() - getPaddingBottom();
+ final int left;
+ final int right;
+ final int top;
+ final int bottom;
+ if (mSlideableView != null && hasOpaqueBackground(mSlideableView)) {
+ left = mSlideableView.getLeft();
+ right = mSlideableView.getRight();
+ top = mSlideableView.getTop();
+ bottom = mSlideableView.getBottom();
+ } else {
+ left = right = top = bottom = 0;
+ }
+ View child = getChildAt(0);
+ final int clampedChildLeft = Math.max(leftBound, child.getLeft());
+ final int clampedChildTop = Math.max(topBound, child.getTop());
+ final int clampedChildRight = Math.min(rightBound, child.getRight());
+ final int clampedChildBottom = Math.min(bottomBound, child.getBottom());
+ final int vis;
+ if (clampedChildLeft >= left && clampedChildTop >= top &&
+ clampedChildRight <= right && clampedChildBottom <= bottom) {
+ vis = INVISIBLE;
+ } else {
+ vis = VISIBLE;
+ }
+ child.setVisibility(vis);
+ }
+
+ void setAllChildrenVisible() {
+ for (int i = 0, childCount = getChildCount(); i < childCount; i++) {
+ final View child = getChildAt(i);
+ if (child.getVisibility() == INVISIBLE) {
+ child.setVisibility(VISIBLE);
+ }
+ }
+ }
+
+ private static boolean hasOpaqueBackground(View v) {
+ final Drawable bg = v.getBackground();
+ if (bg != null) {
+ return bg.getOpacity() == PixelFormat.OPAQUE;
+ }
+ return false;
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ mFirstLayout = true;
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ mFirstLayout = true;
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
+ final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
+ final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
+ final int heightSize = MeasureSpec.getSize(heightMeasureSpec);
+
+ if (widthMode != MeasureSpec.EXACTLY) {
+ throw new IllegalStateException("Width must have an exact value or MATCH_PARENT");
+ } else if (heightMode != MeasureSpec.EXACTLY) {
+ throw new IllegalStateException("Height must have an exact value or MATCH_PARENT");
+ }
+
+ int layoutHeight = heightSize - getPaddingTop() - getPaddingBottom();
+ int panelHeight = mPanelHeight;
+
+ final int childCount = getChildCount();
+
+ if (childCount > 2) {
+ Log.e(TAG, "onMeasure: More than two child views are not supported.");
+ } else if (getChildAt(1).getVisibility() == GONE) {
+ panelHeight = 0;
+ }
+
+ // We'll find the current one below.
+ mSlideableView = null;
+ mCanSlide = false;
+
+ // First pass. Measure based on child LayoutParams width/height.
+ for (int i = 0; i < childCount; i++) {
+ final View child = getChildAt(i);
+ final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+
+ int height = layoutHeight;
+ if (child.getVisibility() == GONE) {
+ lp.dimWhenOffset = false;
+ continue;
+ }
+
+ if (i == 1) {
+ lp.slideable = true;
+ lp.dimWhenOffset = true;
+ mSlideableView = child;
+ mCanSlide = true;
+ } else {
+ if (!mOverlayContent) {
+ height -= panelHeight;
+ }
+ mMainView = child;
+ }
+
+ int childWidthSpec;
+ if (lp.width == LayoutParams.WRAP_CONTENT) {
+ childWidthSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.AT_MOST);
+ } else if (lp.width == LayoutParams.MATCH_PARENT) {
+ childWidthSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY);
+ } else {
+ childWidthSpec = MeasureSpec.makeMeasureSpec(lp.width, MeasureSpec.EXACTLY);
+ }
+
+ int childHeightSpec;
+ if (lp.height == LayoutParams.WRAP_CONTENT) {
+ childHeightSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST);
+ } else if (lp.height == LayoutParams.MATCH_PARENT) {
+ childHeightSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
+ } else {
+ childHeightSpec = MeasureSpec.makeMeasureSpec(lp.height, MeasureSpec.EXACTLY);
+ }
+
+ child.measure(childWidthSpec, childHeightSpec);
+ }
+
+ setMeasuredDimension(widthSize, heightSize);
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int l, int t, int r, int b) {
+ final int paddingLeft = getPaddingLeft();
+ final int paddingTop = getPaddingTop();
+ final int slidingTop = getSlidingTop();
+
+ final int childCount = getChildCount();
+
+ if (mFirstLayout) {
+ switch (mSlideState) {
+ case EXPANDED:
+ mSlideOffset = mCanSlide ? 0.f : 1.f;
+ break;
+ case ANCHORED:
+ mSlideOffset = mCanSlide ? mAnchorPoint : 1.f;
+ break;
+ default:
+ mSlideOffset = 1.f;
+ break;
+ }
+ }
+
+ for (int i = 0; i < childCount; i++) {
+ final View child = getChildAt(i);
+
+ if (child.getVisibility() == GONE) {
+ continue;
+ }
+
+ final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+ final int childHeight = child.getMeasuredHeight();
+
+ if (lp.slideable) {
+ mSlideRange = childHeight - mPanelHeight;
+ }
+
+ int childTop;
+ if (mIsSlidingUp) {
+ childTop = lp.slideable ? slidingTop + (int) (mSlideRange * mSlideOffset) : paddingTop;
+ } else {
+ childTop = lp.slideable ? slidingTop - (int) (mSlideRange * mSlideOffset) : paddingTop;
+ if (!lp.slideable && !mOverlayContent) {
+ childTop += mPanelHeight;
+ }
+ }
+ final int childBottom = childTop + childHeight;
+ final int childLeft = paddingLeft;
+ final int childRight = childLeft + child.getMeasuredWidth();
+
+ child.layout(childLeft, childTop, childRight, childBottom);
+ }
+
+ if (mFirstLayout) {
+ updateObscuredViewVisibility();
+ }
+
+ mFirstLayout = false;
+ }
+
+ @Override
+ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+ super.onSizeChanged(w, h, oldw, oldh);
+ // Recalculate sliding panes and their details
+ if (h != oldh) {
+ mFirstLayout = true;
+ }
+ }
+
+ /**
+ * Set if the drag view can have its own touch events. If set
+ * to true, a drag view can scroll horizontally and have its own click listener.
+ *
+ * Default is set to false.
+ */
+ public void setEnableDragViewTouchEvents(boolean enabled) {
+ mIsUsingDragViewTouchEvents = enabled;
+ }
+
+ @Override
+ public boolean onInterceptTouchEvent(MotionEvent ev) {
+ final int action = MotionEventCompat.getActionMasked(ev);
+
+ if (mAnimation != null || !mCanSlide || !mIsSlidingEnabled || (mIsUnableToDrag && action != MotionEvent.ACTION_DOWN)) {
+ mDragHelper.cancel();
+ return super.onInterceptTouchEvent(ev);
+ }
+
+ if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) {
+ mDragHelper.cancel();
+ return false;
+ }
+
+ final float x = ev.getX();
+ final float y = ev.getY();
+ boolean interceptTap = false;
+
+ switch (action) {
+ case MotionEvent.ACTION_DOWN: {
+ mIsUnableToDrag = false;
+ mInitialMotionX = x;
+ mInitialMotionY = y;
+ if (isDragViewUnder((int) x, (int) y) && !mIsUsingDragViewTouchEvents) {
+ interceptTap = true;
+ }
+ break;
+ }
+
+ case MotionEvent.ACTION_MOVE: {
+ final float adx = Math.abs(x - mInitialMotionX);
+ final float ady = Math.abs(y - mInitialMotionY);
+ final int dragSlop = mDragHelper.getTouchSlop();
+
+ // Handle any horizontal scrolling on the drag view.
+ if (mIsUsingDragViewTouchEvents) {
+ if (adx > mScrollTouchSlop && ady < mScrollTouchSlop) {
+ return super.onInterceptTouchEvent(ev);
+ }
+ // Intercept the touch if the drag view has any vertical scroll.
+ // onTouchEvent will determine if the view should drag vertically.
+ else if (ady > mScrollTouchSlop) {
+ interceptTap = isDragViewUnder((int) x, (int) y);
+ }
+ }
+
+ if ((ady > dragSlop && adx > ady) || !isDragViewUnder((int) x, (int) y)) {
+ mDragHelper.cancel();
+ mIsUnableToDrag = true;
+ return false;
+ }
+ break;
+ }
+ }
+
+ final boolean interceptForDrag = mDragHelper.shouldInterceptTouchEvent(ev);
+
+ return interceptForDrag;
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent ev) {
+ if (!mCanSlide || !mIsSlidingEnabled || mAnimation != null) {
+ return super.onTouchEvent(ev);
+ }
+
+ mDragHelper.processTouchEvent(ev);
+
+ final int action = ev.getAction();
+ boolean wantTouchEvents = true;
+
+ switch (action & MotionEventCompat.ACTION_MASK) {
+ case MotionEvent.ACTION_DOWN: {
+ final float x = ev.getX();
+ final float y = ev.getY();
+
+ //Fix to allow both SettingPanel Drag and Workspace Drag
+ if (mSlideState == SlideState.COLLAPSED) {
+ if (y < mSlideableView.getTop()) {
+ return false;
+ }
+ }
+
+ mInitialMotionX = x;
+ mInitialMotionY = y;
+ break;
+ }
+
+ case MotionEvent.ACTION_UP: {
+ final float x = ev.getX();
+ final float y = ev.getY();
+ final float dx = x - mInitialMotionX;
+ final float dy = y - mInitialMotionY;
+ final int slop = mDragHelper.getTouchSlop();
+ View dragView = mDragView != null ? mDragView : mSlideableView;
+ if (dx * dx + dy * dy < slop * slop &&
+ isDragViewUnder((int) x, (int) y)) {
+ dragView.playSoundEffect(SoundEffectConstants.CLICK);
+ if (!isExpanded() && !isAnchored()) {
+ expandPane(mAnchorPoint);
+ } else {
+ collapsePane();
+ }
+ break;
+ }
+ break;
+ }
+ }
+
+ return wantTouchEvents;
+ }
+
+ private boolean isDragViewUnder(int x, int y) {
+ View dragView = mDragView != null ? mDragView : mSlideableView;
+ if (dragView == null) return false;
+ int[] viewLocation = new int[2];
+ dragView.getLocationOnScreen(viewLocation);
+ int[] parentLocation = new int[2];
+ this.getLocationOnScreen(parentLocation);
+ int screenX = parentLocation[0] + x;
+ int screenY = parentLocation[1] + y;
+ return screenX >= viewLocation[0] && screenX < viewLocation[0] + dragView.getWidth() &&
+ screenY >= viewLocation[1] && screenY < viewLocation[1] + dragView.getHeight();
+ }
+
+ private boolean expandPane(View pane, int initialVelocity, float mSlideOffset) {
+ if (mFirstLayout || smoothSlideTo(mSlideOffset, initialVelocity)) {
+ return true;
+ }
+ return false;
+ }
+
+ private boolean collapsePane(View pane, int initialVelocity) {
+ if (mFirstLayout || smoothSlideTo(1.f, initialVelocity)) {
+ return true;
+ }
+ return false;
+ }
+
+ private int getSlidingTop() {
+ if (mSlideableView != null) {
+ return mIsSlidingUp
+ ? getMeasuredHeight() - getPaddingBottom() - mSlideableView.getMeasuredHeight()
+ : getPaddingTop();
+ }
+
+ return getMeasuredHeight() - getPaddingBottom();
+ }
+
+ /**
+ * Collapse the sliding pane if it is currently slideable. If first layout
+ * has already completed this will animate.
+ *
+ * @return true if the pane was slideable and is now collapsed/in the process of collapsing
+ */
+ public boolean collapsePane() {
+ return collapsePane(mSlideableView, 0);
+ }
+
+ /**
+ * Expand the sliding pane if it is currently slideable. If first layout
+ * has already completed this will animate.
+ *
+ * @return true if the pane was slideable and is now expanded/in the process of expading
+ */
+ public boolean expandPane() {
+ return expandPane(0);
+ }
+
+ /**
+ * Partially expand the sliding pane up to a specific offset
+ *
+ * @param mSlideOffset Value between 0 and 1, where 0 is completely expanded.
+ * @return true if the pane was slideable and is now expanded/in the process of expading
+ */
+ public boolean expandPane(float mSlideOffset) {
+ if (!isPaneVisible()) {
+ showPane();
+ }
+ return expandPane(mSlideableView, 0, mSlideOffset);
+ }
+
+ /**
+ * Check if the layout is completely expanded.
+ *
+ * @return true if sliding panels are completely expanded
+ */
+ public boolean isExpanded() {
+ return mSlideState == SlideState.EXPANDED;
+ }
+
+ /**
+ * Check if the layout is anchored in an intermediate point.
+ *
+ * @return true if sliding panels are anchored
+ */
+ public boolean isAnchored() {
+ return mSlideState == SlideState.ANCHORED;
+ }
+
+ /**
+ * Check if the content in this layout cannot fully fit side by side and therefore
+ * the content pane can be slid back and forth.
+ *
+ * @return true if content in this layout can be expanded
+ */
+ public boolean isSlideable() {
+ return mCanSlide;
+ }
+
+ public boolean isPaneVisible() {
+ if (getChildCount() < 2) {
+ return false;
+ }
+ View slidingPane = getChildAt(1);
+ return slidingPane.getVisibility() == View.VISIBLE;
+ }
+
+ public void showPane() {
+ if (getChildCount() < 2) {
+ return;
+ }
+ final View slidingPane = getChildAt(1);
+ mAnimation = new TranslateAnimation(0, 0, (mIsSlidingUp ? 1 : -1) * getPanelHeight(), 0);
+ mAnimation.setDuration(400);
+ mAnimation.setAnimationListener(new Animation.AnimationListener() {
+ @Override
+ public void onAnimationStart(Animation animation) {
+ slidingPane.setVisibility(View.VISIBLE);
+ }
+
+ @Override
+ public void onAnimationEnd(Animation animation) {
+ requestLayout();
+ mAnimation = null;
+ }
+
+ @Override
+ public void onAnimationRepeat(Animation animation) {
+ }
+ });
+ slidingPane.startAnimation(mAnimation);
+ }
+
+ public void hidePane() {
+ if (mSlideableView == null) {
+ return;
+ }
+ mAnimation = new TranslateAnimation(0, 0, 0, (mIsSlidingUp ? 1 : -1) * getPanelHeight());
+ mAnimation.setDuration(500);
+ mAnimation.setAnimationListener(new Animation.AnimationListener() {
+ @Override
+ public void onAnimationStart(Animation animation) {
+
+ }
+
+ @Override
+ public void onAnimationEnd(Animation animation) {
+ mSlideableView.setVisibility(View.GONE);
+ requestLayout();
+ mAnimation = null;
+ }
+
+ @Override
+ public void onAnimationRepeat(Animation animation) {
+
+ }
+ });
+ mSlideableView.startAnimation(mAnimation);
+ }
+
+ private void onPanelDragged(int newTop) {
+ final int topBound = getSlidingTop();
+ mSlideOffset = mIsSlidingUp
+ ? (float) (newTop - topBound) / mSlideRange
+ : (float) (topBound - newTop) / mSlideRange;
+ dispatchOnPanelSlide(mSlideableView);
+
+ if (mParalaxOffset > 0) {
+ int mainViewOffset = getCurrentParalaxOffset();
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
+ mMainView.setTranslationY(mainViewOffset);
+ } else {
+ mMainView.animate().translationY(mainViewOffset);
+ }
+ }
+ }
+
+ @Override
+ protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
+ final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+ boolean result;
+ final int save = canvas.save(Canvas.CLIP_SAVE_FLAG);
+
+ boolean drawScrim = false;
+
+ if (mCanSlide && !lp.slideable && mSlideableView != null) {
+ // Clip against the slider; no sense drawing what will immediately be covered,
+ // Unless the panel is set to overlay content
+ if (!mOverlayContent) {
+ canvas.getClipBounds(mTmpRect);
+ if (mIsSlidingUp) {
+ mTmpRect.bottom = Math.min(mTmpRect.bottom, mSlideableView.getTop());
+ } else {
+ mTmpRect.top = Math.max(mTmpRect.top, mSlideableView.getBottom());
+ }
+ canvas.clipRect(mTmpRect);
+ }
+ if (mSlideOffset < 1) {
+ drawScrim = true;
+ }
+ }
+
+ result = super.drawChild(canvas, child, drawingTime);
+ canvas.restoreToCount(save);
+
+ if (drawScrim) {
+ final int baseAlpha = (mCoveredFadeColor & 0xff000000) >>> 24;
+ final int imag = (int) (baseAlpha * (1 - mSlideOffset));
+ final int color = imag << 24 | (mCoveredFadeColor & 0xffffff);
+ mCoveredFadePaint.setColor(color);
+ canvas.drawRect(mTmpRect, mCoveredFadePaint);
+ }
+
+ return result;
+ }
+
+ /**
+ * Smoothly animate mDraggingPane to the target X position within its range.
+ *
+ * @param slideOffset position to animate to
+ * @param velocity initial velocity in case of fling, or 0.
+ */
+ boolean smoothSlideTo(float slideOffset, int velocity) {
+ if (!mCanSlide) {
+ // Nothing to do.
+ return false;
+ }
+
+ final int topBound = getSlidingTop();
+ int y = mIsSlidingUp
+ ? (int) (topBound + slideOffset * mSlideRange)
+ : (int) (topBound - slideOffset * mSlideRange);
+
+ if (mDragHelper.smoothSlideViewTo(mSlideableView, mSlideableView.getLeft(), y)) {
+ setAllChildrenVisible();
+ ViewCompat.postInvalidateOnAnimation(this);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public void computeScroll() {
+ if (mDragHelper.continueSettling(true)) {
+ if (!mCanSlide) {
+ mDragHelper.abort();
+ return;
+ }
+
+ ViewCompat.postInvalidateOnAnimation(this);
+ }
+ }
+
+ @Override
+ public void draw(Canvas c) {
+ super.draw(c);
+
+ if (mSlideableView == null) {
+ // No need to draw a shadow if we don't have one.
+ return;
+ }
+
+ final int right = mSlideableView.getRight();
+ final int top;
+ final int bottom;
+ if (mIsSlidingUp) {
+ top = mSlideableView.getTop() - mShadowHeight;
+ bottom = mSlideableView.getTop();
+ } else {
+ top = mSlideableView.getBottom();
+ bottom = mSlideableView.getBottom() + mShadowHeight;
+ }
+ final int left = mSlideableView.getLeft();
+
+ if (mShadowDrawable != null) {
+ mShadowDrawable.setBounds(left, top, right, bottom);
+ mShadowDrawable.draw(c);
+ }
+ }
+
+ /**
+ * Tests scrollability within child views of v given a delta of dx.
+ *
+ * @param v View to test for horizontal scrollability
+ * @param checkV Whether the view v passed should itself be checked for scrollability (true),
+ * or just its children (false).
+ * @param dx Delta scrolled in pixels
+ * @param x X coordinate of the active touch point
+ * @param y Y coordinate of the active touch point
+ * @return true if child views of v can be scrolled by delta of dx.
+ */
+ protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) {
+ if (v instanceof ViewGroup) {
+ final ViewGroup group = (ViewGroup) v;
+ final int scrollX = v.getScrollX();
+ final int scrollY = v.getScrollY();
+ final int count = group.getChildCount();
+ // Count backwards - let topmost views consume scroll distance first.
+ for (int i = count - 1; i >= 0; i--) {
+ final View child = group.getChildAt(i);
+ if (x + scrollX >= child.getLeft() && x + scrollX < child.getRight() &&
+ y + scrollY >= child.getTop() && y + scrollY < child.getBottom() &&
+ canScroll(child, true, dx, x + scrollX - child.getLeft(),
+ y + scrollY - child.getTop())) {
+ return true;
+ }
+ }
+ }
+ return checkV && ViewCompat.canScrollHorizontally(v, -dx);
+ }
+
+
+ @Override
+ protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
+ return new LayoutParams();
+ }
+
+ @Override
+ protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
+ return p instanceof MarginLayoutParams
+ ? new LayoutParams((MarginLayoutParams) p)
+ : new LayoutParams(p);
+ }
+
+ @Override
+ protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
+ return p instanceof LayoutParams && super.checkLayoutParams(p);
+ }
+
+ @Override
+ public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
+ return new LayoutParams(getContext(), attrs);
+ }
+
+ @Override
+ protected Parcelable onSaveInstanceState() {
+ Parcelable superState = super.onSaveInstanceState();
+
+ SavedState ss = new SavedState(superState);
+ ss.mSlideState = mSlideState;
+
+ return ss;
+ }
+
+ @Override
+ protected void onRestoreInstanceState(Parcelable state) {
+ SavedState ss = (SavedState) state;
+ super.onRestoreInstanceState(ss.getSuperState());
+ mSlideState = ss.mSlideState;
+ }
+
+ private class DragHelperCallback extends ViewDragHelper.Callback {
+
+ @Override
+ public boolean tryCaptureView(View child, int pointerId) {
+ if (mIsUnableToDrag) {
+ return false;
+ }
+
+ return ((LayoutParams) child.getLayoutParams()).slideable;
+ }
+
+ @Override
+ public void onViewDragStateChanged(int state) {
+ int anchoredTop = (int)(mAnchorPoint*mSlideRange);
+
+ if (mDragHelper.getViewDragState() == ViewDragHelper.STATE_IDLE) {
+ if (mSlideOffset == 0) {
+ if (mSlideState != SlideState.EXPANDED) {
+ updateObscuredViewVisibility();
+ dispatchOnPanelExpanded(mSlideableView);
+ mSlideState = SlideState.EXPANDED;
+ }
+ } else if (mSlideOffset == (float)anchoredTop/(float)mSlideRange) {
+ if (mSlideState != SlideState.ANCHORED) {
+ updateObscuredViewVisibility();
+ dispatchOnPanelAnchored(mSlideableView);
+ mSlideState = SlideState.ANCHORED;
+ }
+ } else if (mSlideState != SlideState.COLLAPSED) {
+ dispatchOnPanelCollapsed(mSlideableView);
+ mSlideState = SlideState.COLLAPSED;
+ }
+ }
+ }
+
+ @Override
+ public void onViewCaptured(View capturedChild, int activePointerId) {
+ // Make all child views visible in preparation for sliding things around
+ setAllChildrenVisible();
+ }
+
+ @Override
+ public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
+ onPanelDragged(top);
+ invalidate();
+ }
+
+ @Override
+ public void onViewReleased(View releasedChild, float xvel, float yvel) {
+ int top = mIsSlidingUp
+ ? getSlidingTop()
+ : getSlidingTop() - mSlideRange;
+
+ if (mAnchorPoint != 0) {
+ int anchoredTop;
+ float anchorOffset;
+ if (mIsSlidingUp) {
+ anchoredTop = (int)(mAnchorPoint*mSlideRange);
+ anchorOffset = (float)anchoredTop/(float)mSlideRange;
+ } else {
+ anchoredTop = mPanelHeight - (int)(mAnchorPoint*mSlideRange);
+ anchorOffset = (float)(mPanelHeight - anchoredTop)/(float)mSlideRange;
+ }
+
+ if (yvel > 0 || (yvel == 0 && mSlideOffset >= (1f+anchorOffset)/2)) {
+ top += mSlideRange;
+ } else if (yvel == 0 && mSlideOffset < (1f+anchorOffset)/2
+ && mSlideOffset >= anchorOffset/2) {
+ top += mSlideRange * mAnchorPoint;
+ }
+
+ } else if (yvel > 0 || (yvel == 0 && mSlideOffset > 0.5f)) {
+ top += mSlideRange;
+ }
+
+ mDragHelper.settleCapturedViewAt(releasedChild.getLeft(), top);
+ invalidate();
+ }
+
+ @Override
+ public int getViewVerticalDragRange(View child) {
+ return mSlideRange;
+ }
+
+ @Override
+ public int clampViewPositionVertical(View child, int top, int dy) {
+ final int topBound;
+ final int bottomBound;
+ if (mIsSlidingUp) {
+ topBound = getSlidingTop();
+ bottomBound = topBound + mSlideRange;
+ } else {
+ bottomBound = getPaddingTop();
+ topBound = bottomBound - mSlideRange;
+ }
+
+ return Math.min(Math.max(top, topBound), bottomBound);
+ }
+ }
+
+ public static class LayoutParams extends ViewGroup.MarginLayoutParams {
+ private static final int[] ATTRS = new int[] {
+ android.R.attr.layout_weight
+ };
+
+ /**
+ * True if this pane is the slideable pane in the layout.
+ */
+ boolean slideable;
+
+ /**
+ * True if this view should be drawn dimmed
+ * when it's been offset from its default position.
+ */
+ boolean dimWhenOffset;
+
+ Paint dimPaint;
+
+ public LayoutParams() {
+ super(MATCH_PARENT, MATCH_PARENT);
+ }
+
+ public LayoutParams(int width, int height) {
+ super(width, height);
+ }
+
+ public LayoutParams(android.view.ViewGroup.LayoutParams source) {
+ super(source);
+ }
+
+ public LayoutParams(MarginLayoutParams source) {
+ super(source);
+ }
+
+ public LayoutParams(LayoutParams source) {
+ super(source);
+ }
+
+ public LayoutParams(Context c, AttributeSet attrs) {
+ super(c, attrs);
+
+ final TypedArray a = c.obtainStyledAttributes(attrs, ATTRS);
+ a.recycle();
+ }
+
+ }
+
+ static class SavedState extends BaseSavedState {
+ SlideState mSlideState;
+
+ SavedState(Parcelable superState) {
+ super(superState);
+ }
+
+ private SavedState(Parcel in) {
+ super(in);
+ try {
+ mSlideState = Enum.valueOf(SlideState.class, in.readString());
+ } catch (IllegalArgumentException e) {
+ mSlideState = SlideState.COLLAPSED;
+ }
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ super.writeToParcel(out, flags);
+ out.writeString(mSlideState.toString());
+ }
+
+ public static final Parcelable.Creator<SavedState> CREATOR =
+ new Parcelable.Creator<SavedState>() {
+ @Override
+ public SavedState createFromParcel(Parcel in) {
+ return new SavedState(in);
+ }
+
+ @Override
+ public SavedState[] newArray(int size) {
+ return new SavedState[size];
+ }
+ };
+ }
+}
diff --git a/src/com/android/launcher3/SmoothPagedView.java b/src/com/android/launcher3/SmoothPagedView.java
index a45dbbf6e..4e331aa2c 100644
--- a/src/com/android/launcher3/SmoothPagedView.java
+++ b/src/com/android/launcher3/SmoothPagedView.java
@@ -19,7 +19,6 @@ package com.android.launcher3;
import android.content.Context;
import android.util.AttributeSet;
import android.view.animation.Interpolator;
-import android.widget.Scroller;
public abstract class SmoothPagedView extends PagedView {
private static final float SMOOTHING_SPEED = 0.75f;
@@ -52,8 +51,6 @@ public abstract class SmoothPagedView extends PagedView {
}
public float getInterpolation(float t) {
- // _o(t) = t * t * ((tension + 1) * t + tension)
- // o(t) = _o(t - 1) + 1
t -= 1.0f;
return t * t * ((mTension + 1) * t + mTension) + 1.0f;
}
@@ -102,7 +99,7 @@ public abstract class SmoothPagedView extends PagedView {
mBaseLineFlingVelocity = 2500.0f;
mFlingVelocityInfluence = 0.4f;
mScrollInterpolator = new OvershootInterpolator();
- mScroller = new Scroller(getContext(), mScrollInterpolator);
+ setDefaultInterpolator(mScrollInterpolator);
}
}
diff --git a/src/com/android/launcher3/ThemeChangedReceiver.java b/src/com/android/launcher3/ThemeChangedReceiver.java
new file mode 100644
index 000000000..c7a98c5ab
--- /dev/null
+++ b/src/com/android/launcher3/ThemeChangedReceiver.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2014 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+import static com.android.launcher3.WidgetPreviewLoader.CacheDb.DB_NAME;
+
+import java.io.File;
+import java.util.ArrayList;
+
+public class ThemeChangedReceiver extends BroadcastReceiver {
+ private static final String EXTRA_COMPONENTS = "components";
+
+ public static final String MODIFIES_ICONS = "mods_icons";
+ public static final String MODIFIES_FONTS = "mods_fonts";
+ public static final String MODIFIES_OVERLAYS = "mods_overlays";
+
+ public void onReceive(Context context, Intent intent) {
+ // components is a string array of the components that changed
+ ArrayList<String> components = intent.getStringArrayListExtra(EXTRA_COMPONENTS);
+ if (isInterestingThemeChange(components)) {
+ LauncherAppState app = LauncherAppState.getInstance();
+ clearWidgetPreviewCache(context);
+ app.recreateWidgetPreviewDb();
+ app.getIconCache().flush();
+ app.getModel().forceReload();
+ }
+ }
+
+ /**
+ * We consider this an "interesting" theme change if it modifies icons, overlays, or fonts.
+ * @param components
+ * @return
+ */
+ private boolean isInterestingThemeChange(ArrayList<String> components) {
+ if (components != null) {
+ for (String component : components) {
+ if (component.equals(MODIFIES_ICONS) ||
+ component.equals(MODIFIES_FONTS) ||
+ component.equals(MODIFIES_OVERLAYS)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+
+ /**
+ * Normally we could use context.deleteDatabase() but this db is in cache/ so we'll
+ * manually delete it and the journal ourselves.
+ *
+ * @param context
+ */
+ private void clearWidgetPreviewCache(Context context) {
+ File[] files = context.getCacheDir().listFiles();
+ if (files != null) {
+ for (File f : files) {
+ if (!f.isDirectory() && f.getName().startsWith(DB_NAME)) f.delete();
+ }
+ }
+ }
+}
diff --git a/src/com/android/launcher3/TransitionEffectsFragment.java b/src/com/android/launcher3/TransitionEffectsFragment.java
new file mode 100644
index 000000000..88c6481d7
--- /dev/null
+++ b/src/com/android/launcher3/TransitionEffectsFragment.java
@@ -0,0 +1,220 @@
+package com.android.launcher3;
+
+import android.animation.Animator;
+import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
+import android.app.Fragment;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Color;
+import android.graphics.drawable.AnimationDrawable;
+import android.os.Bundle;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.ListView;
+import android.widget.ScrollView;
+import android.widget.TextView;
+import com.android.launcher3.settings.SettingsProvider;
+
+public class TransitionEffectsFragment extends Fragment {
+ public static final String PAGE_OR_DRAWER_SCROLL_SELECT = "pageOrDrawer";
+ public static final String SELECTED_TRANSITION_EFFECT = "selectedTransitionEffect";
+ public static final String TRANSITION_EFFECTS_FRAGMENT = "transitionEffectsFragment";
+ ImageView mTransitionIcon;
+ ListView mListView;
+ View mCurrentSelection;
+ ScrollView mScrollView;
+
+ String[] mTransitionStates;
+ TypedArray mTransitionDrawables;
+ String mCurrentState;
+ int mCurrentPosition;
+ boolean mPageOrDrawer;
+ String mSettingsProviderValue;
+ int mPreferenceValue;
+
+ OnClickListener mSettingsItemListener = new OnClickListener() {
+
+ @Override
+ public void onClick(View v) {
+ if (mCurrentPosition == (Integer) v.getTag()) {
+ return;
+ }
+ mCurrentPosition = (Integer) v.getTag();
+ mCurrentState = mTransitionStates[mCurrentPosition];
+
+ setCleared(mCurrentSelection);
+ setSelected(v);
+ mCurrentSelection = v;
+
+ new Thread(new Runnable() {
+ public void run() {
+ mTransitionIcon.post(new Runnable() {
+ public void run() {
+ setImageViewToEffect();
+ }
+ });
+ }
+ }).start();
+
+ ((TransitionsArrayAdapter) mListView.getAdapter()).notifyDataSetChanged();
+ }
+ };
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ View v = inflater.inflate(R.layout.settings_transitions_screen, container, false);
+
+ mPageOrDrawer = getArguments().getBoolean(PAGE_OR_DRAWER_SCROLL_SELECT);
+
+ mSettingsProviderValue = mPageOrDrawer ?
+ SettingsProvider.SETTINGS_UI_DRAWER_SCROLLING_TRANSITION_EFFECT
+ : SettingsProvider.SETTINGS_UI_HOMESCREEN_SCROLLING_TRANSITION_EFFECT;
+ mPreferenceValue = mPageOrDrawer ? R.string.preferences_interface_drawer_scrolling_transition_effect
+ : R.string.preferences_interface_homescreen_scrolling_transition_effect;
+
+ mTransitionIcon = (ImageView) v.findViewById(R.id.settings_transition_image);
+ mListView = (ListView) v.findViewById(R.id.settings_transitions_list);
+ mScrollView = (ScrollView) v.findViewById(R.id.scroll_view);
+ TextView title = (TextView) v.findViewById(R.id.transition_effect_title);
+ title.setText(getResources().getString(R.string.scroll_effect_text));
+ LinearLayout titleLayout = (LinearLayout) v.findViewById(R.id.transition_title);
+ titleLayout.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ setEffect();
+ }
+ });
+
+ String[] titles = getResources().getStringArray(
+ R.array.transition_effect_entries);
+ mListView.setAdapter(new TransitionsArrayAdapter(getActivity(),
+ R.layout.settings_pane_list_item, titles));
+
+ mTransitionStates = getResources().getStringArray(
+ R.array.transition_effect_values);
+ mTransitionDrawables = getResources().obtainTypedArray(
+ R.array.transition_effect_drawables);
+
+ mCurrentState = SettingsProvider.getString(getActivity(),
+ mSettingsProviderValue, mPreferenceValue);
+ mCurrentPosition = mapEffectToPosition(mCurrentState);
+
+ mListView.setSelection(mCurrentPosition);
+
+ return v;
+ }
+
+ public void setEffect() {
+ ((Launcher) getActivity()).setTransitionEffect(mPageOrDrawer, mCurrentState);
+ }
+
+ private int mapEffectToPosition(String effect) {
+ int length = mTransitionStates.length;
+ for (int i = 0; i < length; i++) {
+ if (effect.equals(mTransitionStates[i])) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ private void setImageViewToEffect() {
+ mTransitionIcon.setBackgroundResource(mTransitionDrawables
+ .getResourceId(mCurrentPosition, R.drawable.transition_none));
+
+ AnimationDrawable frameAnimation = (AnimationDrawable) mTransitionIcon.getBackground();
+ frameAnimation.start();
+ }
+
+ private void setSelected(View v) {
+ v.setBackgroundColor(Color.WHITE);
+ TextView t = (TextView) v.findViewById(R.id.item_name);
+ t.setTextColor(getResources().getColor(R.color.settings_bg_color));
+ }
+
+ private void setCleared(View v) {
+ v.setBackgroundColor(getResources().getColor(R.color.settings_bg_color));
+ TextView t = (TextView) v.findViewById(R.id.item_name);
+ t.setTextColor(Color.WHITE);
+ }
+
+ @Override
+ public Animator onCreateAnimator(int transit, boolean enter, int nextAnim) {
+ if (enter) {
+ DisplayMetrics displaymetrics = new DisplayMetrics();
+ getActivity().getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
+ int width = displaymetrics.widthPixels;
+ final ObjectAnimator anim = ObjectAnimator.ofFloat(this, "translationX", width, 0);
+
+ final View darkPanel = ((Launcher) getActivity()).getDarkPanel();
+ darkPanel.setVisibility(View.VISIBLE);
+ ObjectAnimator anim2 = ObjectAnimator.ofFloat(
+ darkPanel , "alpha", 0.0f, 0.3f);
+ anim2.start();
+
+ anim.addListener(new Animator.AnimatorListener() {
+ @Override
+ public void onAnimationStart(Animator arg0) {}
+ @Override
+ public void onAnimationRepeat(Animator arg0) {}
+ @Override
+ public void onAnimationEnd(Animator arg0) {
+ darkPanel.setVisibility(View.GONE);
+ setImageViewToEffect();
+ }
+ @Override
+ public void onAnimationCancel(Animator arg0) {}
+ });
+
+ return anim;
+ } else {
+ return super.onCreateAnimator(transit, enter, nextAnim);
+ }
+ }
+
+ private class TransitionsArrayAdapter extends ArrayAdapter<String> {
+ Context mContext;
+ String[] titles;
+
+ public TransitionsArrayAdapter(Context context, int textViewResourceId,
+ String[] objects) {
+ super(context, textViewResourceId, objects);
+
+ mContext = context;
+ titles = objects;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ LayoutInflater inflater = (LayoutInflater) mContext
+ .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ convertView = inflater.inflate(R.layout.settings_pane_list_item,
+ parent, false);
+ TextView textView = (TextView) convertView
+ .findViewById(R.id.item_name);
+ textView.setText(titles[position]);
+ // Set Selected State
+ if (position == mCurrentPosition) {
+ mCurrentSelection = convertView;
+ setSelected(mCurrentSelection);
+ }
+
+ convertView.setOnClickListener(mSettingsItemListener);
+ convertView.setTag(position);
+ return convertView;
+ }
+ }
+}
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index 282e47516..cbc978585 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -21,14 +21,21 @@ import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
-import android.graphics.*;
+import android.graphics.Bitmap;
+import android.graphics.BlurMaskFilter;
+import android.graphics.Canvas;
+import android.graphics.ColorMatrix;
+import android.graphics.ColorMatrixColorFilter;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.PaintFlagsDrawFilter;
+import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.PaintDrawable;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.View;
-import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
@@ -36,7 +43,7 @@ import java.util.ArrayList;
/**
* Various utilities shared amongst the Launcher's classes.
*/
-final class Utilities {
+public final class Utilities {
private static final String TAG = "Launcher.Utilities";
private static int sIconWidth = -1;
@@ -51,8 +58,6 @@ final class Utilities {
private static final Rect sOldBounds = new Rect();
private static final Canvas sCanvas = new Canvas();
- private static Typeface sTypeface;
-
static {
sCanvas.setDrawFilter(new PaintFlagsDrawFilter(Paint.DITHER_FLAG,
Paint.FILTER_BITMAP_FLAG));
@@ -60,6 +65,12 @@ final class Utilities {
static int sColors[] = { 0xffff0000, 0xff00ff00, 0xff0000ff };
static int sColorIndex = 0;
+
+ // To turn on these properties, type
+ // adb shell setprop log.tag.PROPERTY_NAME [VERBOSE | SUPPRESS]
+ static final String FORCE_ENABLE_ROTATION_PROPERTY = "launcher_force_rotate";
+ public static boolean sForceEnableRotation = isPropertyEnabled(FORCE_ENABLE_ROTATION_PROPERTY);
+
/**
* Returns a FastBitmapDrawable with the icon, accurately sized.
*/
@@ -77,6 +88,16 @@ final class Utilities {
icon.setBounds(0, 0, sIconTextureWidth, sIconTextureHeight);
}
+ private static boolean isPropertyEnabled(String propertyName) {
+ return Log.isLoggable(propertyName, Log.VERBOSE);
+ }
+
+ public static boolean isRotationEnabled(Context c) {
+ boolean enableRotation = sForceEnableRotation ||
+ c.getResources().getBoolean(R.bool.allow_rotation);
+ return enableRotation;
+ }
+
/**
* Returns a bitmap suitable for the all apps view. Used to convert pre-ICS
* icon bitmaps that are stored in the database (which were 74x74 pixels at hdpi size)
@@ -103,15 +124,10 @@ final class Utilities {
}
}
- static Bitmap createIconBitmap(Drawable icon, Context context) {
- return createIconBitmap(icon, context, null, null, null, 1f);
- }
-
/**
* Returns a bitmap suitable for the all apps view.
*/
- static Bitmap createIconBitmap(Drawable icon, Context context, Drawable iconBack,
- Drawable iconMask, Drawable iconUpon, float scale) {
+ public static Bitmap createIconBitmap(Drawable icon, Context context) {
synchronized (sCanvas) { // we share the statics :-(
if (sIconWidth == -1) {
initStatics(context);
@@ -148,7 +164,7 @@ final class Utilities {
int textureWidth = sIconTextureWidth;
int textureHeight = sIconTextureHeight;
- Bitmap bitmap = Bitmap.createBitmap(textureWidth, textureHeight,
+ final Bitmap bitmap = Bitmap.createBitmap(textureWidth, textureHeight,
Bitmap.Config.ARGB_8888);
final Canvas canvas = sCanvas;
canvas.setBitmap(bitmap);
@@ -169,29 +185,7 @@ final class Utilities {
sOldBounds.set(icon.getBounds());
icon.setBounds(left, top, left+width, top+height);
- canvas.save();
- canvas.scale(scale, scale, width / 2, height/2);
icon.draw(canvas);
- canvas.restore();
- if (iconMask != null) {
- iconMask.setBounds(icon.getBounds());
- ((BitmapDrawable) iconMask).getPaint().setXfermode(
- new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
- iconMask.draw(canvas);
- }
- if (iconBack != null) {
- canvas.setBitmap(null);
- Bitmap finalBitmap = Bitmap.createBitmap(textureWidth, textureHeight,
- Bitmap.Config.ARGB_8888);
- canvas.setBitmap(finalBitmap);
- iconBack.setBounds(icon.getBounds());
- iconBack.draw(canvas);
- canvas.drawBitmap(bitmap, null, icon.getBounds(), null);
- bitmap = finalBitmap;
- }
- if (iconUpon != null) {
- iconUpon.draw(canvas);
- }
icon.setBounds(sOldBounds);
canvas.setBitmap(null);
@@ -224,27 +218,6 @@ final class Utilities {
}
/**
- * Generates the default icon typeface for use in icons.
- *
- * @param familyName May be null. The name of the font family.
- * @param style The style (normal, bold, italic) of the typeface. e.g. NORMAL, BOLD, ITALIC, BOLD_ITALIC
- */
- static void generateTypeface(String familyName, int style) {
- sTypeface = Typeface.create(familyName, style);
- }
-
- /**
- * Applies the default icon typeface to a textview.
- *
- * @param textView View to apply typeface to.
- */
- static void applyTypeface(TextView textView) {
- if (sTypeface != null) {
- textView.setTypeface(sTypeface);
- }
- }
-
- /**
* Given a coordinate relative to the descendant, find the coordinate in a parent view's
* coordinates.
*
diff --git a/src/com/android/launcher3/WallpaperChangedReceiver.java b/src/com/android/launcher3/WallpaperChangedReceiver.java
new file mode 100644
index 000000000..2d5612f12
--- /dev/null
+++ b/src/com/android/launcher3/WallpaperChangedReceiver.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+public class WallpaperChangedReceiver extends BroadcastReceiver {
+ public void onReceive(Context context, Intent data) {
+ LauncherAppState.setApplicationContext(context.getApplicationContext());
+ LauncherAppState appState = LauncherAppState.getInstance();
+ appState.onWallpaperChanged();
+ }
+}
diff --git a/src/com/android/launcher3/WidgetPreviewLoader.java b/src/com/android/launcher3/WidgetPreviewLoader.java
index 07b4f6f0a..3db0b51ad 100644
--- a/src/com/android/launcher3/WidgetPreviewLoader.java
+++ b/src/com/android/launcher3/WidgetPreviewLoader.java
@@ -4,11 +4,13 @@ import android.appwidget.AppWidgetProviderInfo;
import android.content.ComponentName;
import android.content.ContentValues;
import android.content.Context;
+import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteDiskIOException;
import android.database.sqlite.SQLiteOpenHelper;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
@@ -100,6 +102,7 @@ class BitmapFactoryOptionsCache extends SoftReferenceThreadLocal<BitmapFactory.O
public class WidgetPreviewLoader {
static final String TAG = "WidgetPreviewLoader";
+ static final String ANDROID_INCREMENTAL_VERSION_NAME_KEY = "android.incremental.version";
private int mPreviewBitmapWidth;
private int mPreviewBitmapHeight;
@@ -147,6 +150,26 @@ public class WidgetPreviewLoader {
mDb = app.getWidgetPreviewCacheDb();
mLoadedPreviews = new HashMap<String, WeakReference<Bitmap>>();
mUnusedBitmaps = new ArrayList<SoftReference<Bitmap>>();
+
+ SharedPreferences sp = context.getSharedPreferences(
+ LauncherAppState.getSharedPreferencesKey(), Context.MODE_PRIVATE);
+ final String lastVersionName = sp.getString(ANDROID_INCREMENTAL_VERSION_NAME_KEY, null);
+ final String versionName = android.os.Build.VERSION.INCREMENTAL;
+ if (!versionName.equals(lastVersionName)) {
+ // clear all the previews whenever the system version changes, to ensure that previews
+ // are up-to-date for any apps that might have been updated with the system
+ clearDb();
+
+ SharedPreferences.Editor editor = sp.edit();
+ editor.putString(ANDROID_INCREMENTAL_VERSION_NAME_KEY, versionName);
+ editor.commit();
+ }
+ }
+
+ public void recreateDb() {
+ LauncherAppState app = LauncherAppState.getInstance();
+ app.recreateWidgetPreviewDb();
+ mDb = app.getWidgetPreviewCacheDb();
}
public void setPreviewSize(int previewWidth, int previewHeight,
@@ -331,7 +354,20 @@ public class WidgetPreviewLoader {
preview.compress(Bitmap.CompressFormat.PNG, 100, stream);
values.put(CacheDb.COLUMN_PREVIEW_BITMAP, stream.toByteArray());
values.put(CacheDb.COLUMN_SIZE, mSize);
- db.insert(CacheDb.TABLE_NAME, null, values);
+ try {
+ db.insert(CacheDb.TABLE_NAME, null, values);
+ } catch (SQLiteDiskIOException e) {
+ recreateDb();
+ }
+ }
+
+ private void clearDb() {
+ SQLiteDatabase db = mDb.getWritableDatabase();
+ // Delete everything
+ try {
+ db.delete(CacheDb.TABLE_NAME, null, null);
+ } catch (SQLiteDiskIOException e) {
+ }
}
public static void removePackageFromDb(final CacheDb cacheDb, final String packageName) {
@@ -341,13 +377,17 @@ public class WidgetPreviewLoader {
new AsyncTask<Void, Void, Void>() {
public Void doInBackground(Void ... args) {
SQLiteDatabase db = cacheDb.getWritableDatabase();
- db.delete(CacheDb.TABLE_NAME,
- CacheDb.COLUMN_NAME + " LIKE ? OR " +
- CacheDb.COLUMN_NAME + " LIKE ?", // SELECT query
- new String[] {
- WIDGET_PREFIX + packageName + "/%",
- SHORTCUT_PREFIX + packageName + "/%"} // args to SELECT query
- );
+ try {
+ db.delete(CacheDb.TABLE_NAME,
+ CacheDb.COLUMN_NAME + " LIKE ? OR " +
+ CacheDb.COLUMN_NAME + " LIKE ?", // SELECT query
+ new String[] {
+ WIDGET_PREFIX + packageName + "/%",
+ SHORTCUT_PREFIX + packageName + "/%"
+ } // args to SELECT query
+ );
+ } catch (SQLiteDiskIOException e) {
+ }
synchronized(sInvalidPackages) {
sInvalidPackages.remove(packageName);
}
@@ -360,9 +400,12 @@ public class WidgetPreviewLoader {
new AsyncTask<Void, Void, Void>() {
public Void doInBackground(Void ... args) {
SQLiteDatabase db = cacheDb.getWritableDatabase();
- db.delete(CacheDb.TABLE_NAME,
- CacheDb.COLUMN_NAME + " = ? ", // SELECT query
- new String[] { objectName }); // args to SELECT query
+ try {
+ db.delete(CacheDb.TABLE_NAME,
+ CacheDb.COLUMN_NAME + " = ? ", // SELECT query
+ new String[] { objectName }); // args to SELECT query
+ } catch (SQLiteDiskIOException e) {
+ }
return null;
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void) null);
@@ -374,14 +417,20 @@ public class WidgetPreviewLoader {
CacheDb.COLUMN_SIZE + " = ?";
}
SQLiteDatabase db = mDb.getReadableDatabase();
- Cursor result = db.query(CacheDb.TABLE_NAME,
- new String[] { CacheDb.COLUMN_PREVIEW_BITMAP }, // cols to return
- mCachedSelectQuery, // select query
- new String[] { name, mSize }, // args to select query
- null,
- null,
- null,
- null);
+ Cursor result;
+ try {
+ result = db.query(CacheDb.TABLE_NAME,
+ new String[] { CacheDb.COLUMN_PREVIEW_BITMAP }, // cols to return
+ mCachedSelectQuery, // select query
+ new String[] { name, mSize }, // args to select query
+ null,
+ null,
+ null,
+ null);
+ } catch (SQLiteDiskIOException e) {
+ recreateDb();
+ return null;
+ }
if (result.getCount() > 0) {
result.moveToFirst();
byte[] blob = result.getBlob(0);
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 37bd8aa73..7e3584115 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -22,6 +22,7 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.LayoutTransition;
import android.animation.ObjectAnimator;
+import android.animation.PropertyValuesHolder;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
@@ -30,7 +31,6 @@ import android.appwidget.AppWidgetHostView;
import android.appwidget.AppWidgetProviderInfo;
import android.content.ComponentName;
import android.content.Context;
-import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.content.res.TypedArray;
@@ -43,6 +43,7 @@ import android.graphics.Rect;
import android.graphics.Region.Op;
import android.graphics.drawable.Drawable;
import android.net.Uri;
+import android.os.AsyncTask;
import android.os.IBinder;
import android.os.Parcelable;
import android.support.v4.view.ViewCompat;
@@ -55,6 +56,8 @@ import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityManager;
+import android.view.animation.Animation;
+import android.view.animation.AnimationUtils;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
import android.widget.TextView;
@@ -62,6 +65,7 @@ import android.widget.TextView;
import com.android.launcher3.FolderIcon.FolderRingAnimator;
import com.android.launcher3.Launcher.CustomContentCallbacks;
import com.android.launcher3.LauncherSettings.Favorites;
+import com.android.launcher3.backup.BackupProtos;
import com.android.launcher3.settings.SettingsProvider;
import java.util.ArrayList;
@@ -87,6 +91,9 @@ public class Workspace extends SmoothPagedView
private static final int CHILDREN_OUTLINE_FADE_OUT_DURATION = 375;
private static final int CHILDREN_OUTLINE_FADE_IN_DURATION = 100;
+ protected static final int SNAP_OFF_EMPTY_SCREEN_DURATION = 400;
+ protected static final int FADE_EMPTY_SCREEN_DURATION = 150;
+
private static final int BACKGROUND_FADE_OUT_DURATION = 350;
private static final int ADJACENT_SCREEN_DROP_DURATION = 300;
private static final int FLING_THRESHOLD_VELOCITY = 500;
@@ -119,14 +126,15 @@ public class Workspace extends SmoothPagedView
private ShortcutAndWidgetContainer mDragSourceInternal;
private static boolean sAccessibilityEnabled;
- // The screen ids used for the empty screens always present to the left/right.
- private final static long EXTRA_EMPTY_SCREEN_LEFT_ID = -201;
- private final static long EXTRA_EMPTY_SCREEN_RIGHT_ID = -202;
+ // The screen id used for the empty screen always present to the right.
+ private final static long EXTRA_EMPTY_SCREEN_ID = -201;
private final static long CUSTOM_CONTENT_SCREEN_ID = -301;
private HashMap<Long, CellLayout> mWorkspaceScreens = new HashMap<Long, CellLayout>();
private ArrayList<Long> mScreenOrder = new ArrayList<Long>();
+ private Runnable mRemoveEmptyScreenRunnable;
+
/**
* CellInfo for the cell that is currently being dragged
*/
@@ -177,7 +185,6 @@ public class Workspace extends SmoothPagedView
private SpringLoadedDragController mSpringLoadedDragController;
private float mSpringLoadedShrinkFactor;
private float mOverviewModeShrinkFactor;
- private int mOverviewModePageOffset;
// State variable that indicates whether the pages are small (ie when you're
// in all apps or customize mode)
@@ -206,7 +213,12 @@ public class Workspace extends SmoothPagedView
private boolean mWorkspaceFadeInAdjacentScreens;
WallpaperOffsetInterpolator mWallpaperOffset;
+
private boolean mScrollWallpaper;
+ private boolean mWallpaperIsLiveWallpaper;
+ private int mNumPagesForWallpaperParallax;
+ private float mLastSetWallpaperOffsetSteps = 0;
+
private Runnable mDelayedResizeRunnable;
private Point mDisplaySize = new Point();
@@ -214,7 +226,7 @@ public class Workspace extends SmoothPagedView
// Variables relating to the creation of user folders by hovering shortcuts over shortcuts
private static final int FOLDER_CREATION_TIMEOUT = 0;
- private static final int REORDER_TIMEOUT = 250;
+ public static final int REORDER_TIMEOUT = 350;
private final Alarm mFolderCreationAlarm = new Alarm();
private final Alarm mReorderAlarm = new Alarm();
private FolderRingAnimator mDragFolderRingAnimator = null;
@@ -325,16 +337,17 @@ public class Workspace extends SmoothPagedView
mLauncher = (Launcher) context;
final Resources res = getResources();
+
mFadeInAdjacentScreens = false;
mWallpaperManager = WallpaperManager.getInstance(context);
+ LauncherAppState app = LauncherAppState.getInstance();
+ DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.Workspace, defStyle, 0);
mSpringLoadedShrinkFactor =
res.getInteger(R.integer.config_workspaceSpringLoadShrinkPercentage) / 100.0f;
- mOverviewModeShrinkFactor =
- res.getInteger(R.integer.config_workspaceOverviewShrinkPercentage) / 100.0f;
- mOverviewModePageOffset = res.getDimensionPixelSize(R.dimen.overview_mode_page_offset);
+ mOverviewModeShrinkFactor = grid.getOverviewModeScale();
mCameraDistance = res.getInteger(R.integer.config_cameraDistance);
mDefaultPage = a.getInt(R.styleable.Workspace_defaultScreen, 1);
mDefaultScreenId = SettingsProvider.getLongCustomDefault(context,
@@ -354,6 +367,14 @@ public class Workspace extends SmoothPagedView
@Override
public void setInsets(Rect insets) {
mInsets.set(insets);
+
+ CellLayout customScreen = getScreenWithId(CUSTOM_CONTENT_SCREEN_ID);
+ if (customScreen != null) {
+ View customContent = customScreen.getShortcutsAndWidgets().getChildAt(0);
+ if (customContent instanceof Insettable) {
+ ((Insettable) customContent).setInsets(mInsets);
+ }
+ }
}
// estimate the size of a widget with spans hSpan, vSpan. return MAX_VALUE for each
@@ -399,7 +420,7 @@ public class Workspace extends SmoothPagedView
@Override
public void run() {
if (mIsDragOccuring) {
- addExtraEmptyScreensOnDrag();
+ addExtraEmptyScreenOnDrag();
}
}
});
@@ -414,11 +435,6 @@ public class Workspace extends SmoothPagedView
InstallShortcutReceiver.disableAndFlushInstallQueue(getContext());
UninstallShortcutReceiver.disableAndFlushUninstallQueue(getContext());
- // Disable all layout transitions before removing left extra pages to ensure that we don't get
- // the transition animations competing with us changing the scroll when we remove it
- disableLayoutTransitions();
- removeExtraEmptyScreens();
- enableLayoutTransitions();
mDragSourceInternal = null;
mLauncher.onInteractionEnd();
}
@@ -438,9 +454,7 @@ public class Workspace extends SmoothPagedView
setClipToPadding(false);
setChildrenDrawnWithCacheEnabled(true);
- // This is a bit of a hack to account for the fact that we translate the workspace
- // up a bit, and still need to draw the background covering the whole screen.
- setMinScale(mOverviewModeShrinkFactor - 0.2f);
+ setMinScale(mOverviewModeShrinkFactor);
setupLayoutTransition();
final Resources res = getResources();
@@ -456,6 +470,9 @@ public class Workspace extends SmoothPagedView
mMaxDistanceForFolderCreation = (0.55f * grid.iconSizePx);
mFlingThresholdVelocity = (int) (FLING_THRESHOLD_VELOCITY * mDensity);
+
+ // Set the wallpaper dimensions when Launcher starts up
+ setWallpaperDimension();
}
private void setupLayoutTransition() {
@@ -550,7 +567,7 @@ public class Workspace extends SmoothPagedView
public long insertNewWorkspaceScreenBeforeEmptyScreen(long screenId) {
// Find the index to insert this view into. If the empty screen exists, then
// insert it before that.
- int insertIndex = mScreenOrder.indexOf(EXTRA_EMPTY_SCREEN_RIGHT_ID);
+ int insertIndex = mScreenOrder.indexOf(EXTRA_EMPTY_SCREEN_ID);
if (insertIndex < 0) {
insertIndex = mScreenOrder.size();
}
@@ -562,6 +579,10 @@ public class Workspace extends SmoothPagedView
}
public long insertNewWorkspaceScreen(long screenId, int insertIndex) {
+ // Log to disk
+ Launcher.addDumpLog(TAG, "11683562 - insertNewWorkspaceScreen(): " + screenId +
+ " at index: " + insertIndex, true);
+
if (mWorkspaceScreens.containsKey(screenId)) {
throw new RuntimeException("Screen id " + screenId + " already exists!");
}
@@ -585,9 +606,10 @@ public class Workspace extends SmoothPagedView
return screenId;
}
- public void createCustomContentPage() {
+ public void createCustomContentContainer() {
CellLayout customScreen = (CellLayout)
mLauncher.getLayoutInflater().inflate(R.layout.workspace_screen, null);
+ customScreen.disableBackground();
mWorkspaceScreens.put(CUSTOM_CONTENT_SCREEN_ID, customScreen);
mScreenOrder.add(0, CUSTOM_CONTENT_SCREEN_ID);
@@ -598,7 +620,7 @@ public class Workspace extends SmoothPagedView
addFullScreenPage(customScreen);
// Update the custom content hint
- mLauncher.updateCustomContentHintVisibility();
+ mLauncher.getLauncherClings().updateCustomContentHintVisibility();
if (mRestorePage != INVALID_RESTORE_PAGE) {
mRestorePage = mRestorePage + 1;
} else {
@@ -624,7 +646,7 @@ public class Workspace extends SmoothPagedView
mCustomContentCallbacks = null;
// Update the custom content hint
- mLauncher.updateCustomContentHintVisibility();
+ mLauncher.getLauncherClings().updateCustomContentHintVisibility();
if (mRestorePage != INVALID_RESTORE_PAGE) {
mRestorePage = mRestorePage - 1;
} else {
@@ -648,6 +670,12 @@ public class Workspace extends SmoothPagedView
if (customContent instanceof Insettable) {
((Insettable)customContent).setInsets(mInsets);
}
+
+ // Verify that the child is removed from any existing parent.
+ if (customContent.getParent() instanceof ViewGroup) {
+ ViewGroup parent = (ViewGroup) customContent.getParent();
+ parent.removeView(customContent);
+ }
customScreen.removeAllViews();
customScreen.addViewToCellLayout(customContent, 0, 0, lp, true);
mCustomContentDescription = description;
@@ -655,89 +683,172 @@ public class Workspace extends SmoothPagedView
mCustomContentCallbacks = callbacks;
}
- public void addExtraEmptyScreensOnDrag() {
- boolean addLeftScreen = true;
- boolean addRightScreen = true;
+ public void addExtraEmptyScreenOnDrag() {
+ // Log to disk
+ Launcher.addDumpLog(TAG, "11683562 - addExtraEmptyScreenOnDrag()", true);
+
+ boolean lastChildOnScreen = false;
+ boolean childOnFinalScreen = false;
+
+ // Cancel any pending removal of empty screen
+ mRemoveEmptyScreenRunnable = null;
if (mDragSourceInternal != null) {
if (mDragSourceInternal.getChildCount() == 1) {
- CellLayout cl = (CellLayout) mDragSourceInternal.getParent();
- addLeftScreen = indexOfChild(cl) != 0;
- addRightScreen = indexOfChild(cl) != getChildCount() - 1;
+ lastChildOnScreen = true;
+ }
+ CellLayout cl = (CellLayout) mDragSourceInternal.getParent();
+ if (indexOfChild(cl) == getChildCount() - 1) {
+ childOnFinalScreen = true;
}
}
- if (addLeftScreen && !mWorkspaceScreens.containsKey(EXTRA_EMPTY_SCREEN_LEFT_ID)) {
- insertNewWorkspaceScreen(EXTRA_EMPTY_SCREEN_LEFT_ID, 0);
- setCurrentPage(getCurrentPage() + 1);
+ // If this is the last item on the final screen
+ if (lastChildOnScreen && childOnFinalScreen) {
+ return;
}
- if (addRightScreen && !mWorkspaceScreens.containsKey(EXTRA_EMPTY_SCREEN_RIGHT_ID)) {
- insertNewWorkspaceScreen(EXTRA_EMPTY_SCREEN_RIGHT_ID);
+ if (!mWorkspaceScreens.containsKey(EXTRA_EMPTY_SCREEN_ID)) {
+ insertNewWorkspaceScreen(EXTRA_EMPTY_SCREEN_ID);
}
}
public boolean addExtraEmptyScreen() {
- if (!mWorkspaceScreens.containsKey(EXTRA_EMPTY_SCREEN_RIGHT_ID)) {
- insertNewWorkspaceScreen(EXTRA_EMPTY_SCREEN_RIGHT_ID);
+ // Log to disk
+ Launcher.addDumpLog(TAG, "11683562 - addExtraEmptyScreen()", true);
+
+ if (!mWorkspaceScreens.containsKey(EXTRA_EMPTY_SCREEN_ID)) {
+ insertNewWorkspaceScreen(EXTRA_EMPTY_SCREEN_ID);
return true;
}
return false;
}
- public void removeExtraEmptyScreenLeft() {
- if (hasExtraEmptyScreenLeft()) {
- CellLayout cl = mWorkspaceScreens.get(EXTRA_EMPTY_SCREEN_LEFT_ID);
- mWorkspaceScreens.remove(EXTRA_EMPTY_SCREEN_LEFT_ID);
- mScreenOrder.remove(EXTRA_EMPTY_SCREEN_LEFT_ID);
- setCurrentPage(mCurrentPage - 1);
- removeView(cl);
- }
- }
+ private void convertFinalScreenToEmptyScreenIfNecessary() {
+ // Log to disk
+ Launcher.addDumpLog(TAG, "11683562 - convertFinalScreenToEmptyScreenIfNecessary()", true);
- public void removeExtraEmptyScreenRight() {
- if (hasExtraEmptyScreenRight()) {
- CellLayout cl = mWorkspaceScreens.get(EXTRA_EMPTY_SCREEN_RIGHT_ID);
- mWorkspaceScreens.remove(EXTRA_EMPTY_SCREEN_RIGHT_ID);
- mScreenOrder.remove(EXTRA_EMPTY_SCREEN_RIGHT_ID);
- removeView(cl);
+ if (hasExtraEmptyScreen() || mScreenOrder.size() == 0) return;
+ long finalScreenId = mScreenOrder.get(mScreenOrder.size() - 1);
+
+ if (finalScreenId == CUSTOM_CONTENT_SCREEN_ID) return;
+ CellLayout finalScreen = mWorkspaceScreens.get(finalScreenId);
+
+ // If the final screen is empty, convert it to the extra empty screen
+ if (finalScreen.getShortcutsAndWidgets().getChildCount() == 0 &&
+ !finalScreen.isDropPending()) {
+ mWorkspaceScreens.remove(finalScreenId);
+ mScreenOrder.remove(finalScreenId);
+
+ // if this is the last non-custom content screen, convert it to the empty screen
+ mWorkspaceScreens.put(EXTRA_EMPTY_SCREEN_ID, finalScreen);
+ mScreenOrder.add(EXTRA_EMPTY_SCREEN_ID);
+
+ // Update the model if we have changed any screens
+ mLauncher.getModel().updateWorkspaceScreenOrder(mLauncher, mScreenOrder);
+ Launcher.addDumpLog(TAG, "11683562 - extra empty screen: " + finalScreenId, true);
}
}
- public void removeExtraEmptyScreens() {
- removeExtraEmptyScreenLeft();
- removeExtraEmptyScreenRight();
+ public void removeExtraEmptyScreen(final boolean animate, final Runnable onComplete) {
+ removeExtraEmptyScreen(animate, onComplete, 0, false);
}
- public boolean hasExtraEmptyScreenLeft() {
- return mWorkspaceScreens.containsKey(EXTRA_EMPTY_SCREEN_LEFT_ID) && getChildCount() - numCustomPages() > 1;
- }
+ public void removeExtraEmptyScreen(final boolean animate, final Runnable onComplete,
+ final int delay, final boolean stripEmptyScreens) {
+ // Log to disk
+ Launcher.addDumpLog(TAG, "11683562 - removeExtraEmptyScreen()", true);
+ if (delay > 0) {
+ postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ removeExtraEmptyScreen(animate, onComplete, 0, stripEmptyScreens);
+ }
+
+ }, delay);
+ return;
+ }
- public boolean hasExtraEmptyScreenRight() {
- return mWorkspaceScreens.containsKey(EXTRA_EMPTY_SCREEN_RIGHT_ID) && getChildCount() - numCustomPages() > 1;
+ convertFinalScreenToEmptyScreenIfNecessary();
+ if (hasExtraEmptyScreen()) {
+ int emptyIndex = mScreenOrder.indexOf(EXTRA_EMPTY_SCREEN_ID);
+ if (getNextPage() == emptyIndex) {
+ snapToPage(getNextPage() - 1, SNAP_OFF_EMPTY_SCREEN_DURATION);
+ fadeAndRemoveEmptyScreen(SNAP_OFF_EMPTY_SCREEN_DURATION, FADE_EMPTY_SCREEN_DURATION,
+ onComplete, stripEmptyScreens);
+ } else {
+ fadeAndRemoveEmptyScreen(0, FADE_EMPTY_SCREEN_DURATION,
+ onComplete, stripEmptyScreens);
+ }
+ return;
+ } else if (stripEmptyScreens) {
+ // If we're not going to strip the empty screens after removing
+ // the extra empty screen, do it right away.
+ stripEmptyScreens();
+ }
+
+ if (onComplete != null) {
+ onComplete.run();
+ }
}
- public boolean hasExtraEmptyScreens() {
- return hasExtraEmptyScreenLeft() || hasExtraEmptyScreenRight();
+ private void fadeAndRemoveEmptyScreen(int delay, int duration, final Runnable onComplete,
+ final boolean stripEmptyScreens) {
+ // Log to disk
+ // XXX: Do we need to update LM workspace screens below?
+ Launcher.addDumpLog(TAG, "11683562 - fadeAndRemoveEmptyScreen()", true);
+ PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 0f);
+ PropertyValuesHolder bgAlpha = PropertyValuesHolder.ofFloat("backgroundAlpha", 0f);
+
+ final CellLayout cl = mWorkspaceScreens.get(EXTRA_EMPTY_SCREEN_ID);
+
+ mRemoveEmptyScreenRunnable = new Runnable() {
+ @Override
+ public void run() {
+ if (hasExtraEmptyScreen()) {
+ mWorkspaceScreens.remove(EXTRA_EMPTY_SCREEN_ID);
+ mScreenOrder.remove(EXTRA_EMPTY_SCREEN_ID);
+ removeView(cl);
+ if (stripEmptyScreens) {
+ stripEmptyScreens();
+ }
+ }
+ }
+ };
+
+ ObjectAnimator oa = ObjectAnimator.ofPropertyValuesHolder(cl, alpha, bgAlpha);
+ oa.setDuration(duration);
+ oa.setStartDelay(delay);
+ oa.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (mRemoveEmptyScreenRunnable != null) {
+ mRemoveEmptyScreenRunnable.run();
+ }
+ if (onComplete != null) {
+ onComplete.run();
+ }
+ }
+ });
+ oa.start();
}
- public int numExtraEmptyScreens() {
- return (hasExtraEmptyScreenLeft() ? 1 : 0) + (hasExtraEmptyScreenRight() ? 1 : 0);
+ public boolean hasExtraEmptyScreen() {
+ int nScreens = getChildCount();
+ nScreens = nScreens - numCustomPages();
+ return mWorkspaceScreens.containsKey(EXTRA_EMPTY_SCREEN_ID) && nScreens > 1;
}
- public long commitExtraEmptyScreen(long screenId) {
- int index = getPageIndexForScreenId(screenId);
- CellLayout cl = mWorkspaceScreens.get(screenId);
- mWorkspaceScreens.remove(screenId);
- mScreenOrder.remove(screenId);
+ public long commitExtraEmptyScreen() {
+ // Log to disk
+ Launcher.addDumpLog(TAG, "11683562 - commitExtraEmptyScreen()", true);
+ int index = getPageIndexForScreenId(EXTRA_EMPTY_SCREEN_ID);
+ CellLayout cl = mWorkspaceScreens.get(EXTRA_EMPTY_SCREEN_ID);
+ mWorkspaceScreens.remove(EXTRA_EMPTY_SCREEN_ID);
+ mScreenOrder.remove(EXTRA_EMPTY_SCREEN_ID);
long newId = LauncherAppState.getLauncherProvider().generateNewScreenId();
mWorkspaceScreens.put(newId, cl);
-
- if (screenId == EXTRA_EMPTY_SCREEN_LEFT_ID) {
- mScreenOrder.add(numCustomPages(), newId);
- } else {
- mScreenOrder.add(newId);
- }
+ mScreenOrder.add(newId);
// Update the page indicator marker
if (getPageIndicator() != null) {
@@ -782,6 +893,14 @@ public class Workspace extends SmoothPagedView
}
public void stripEmptyScreens() {
+ // Log to disk
+ Launcher.addDumpLog(TAG, "11683562 - stripEmptyScreens()", true);
+
+ if (mLauncher.isWorkspaceLoading()) {
+ // Don't strip empty screens if the workspace is still loading
+ Launcher.addDumpLog(TAG, " - workspace loading, skip", true);
+ return;
+ }
if (isPageMoving()) {
mStripScreensOnPageStopMoving = true;
return;
@@ -802,6 +921,7 @@ public class Workspace extends SmoothPagedView
int pageShift = 0;
for (Long id: removeScreens) {
+ Launcher.addDumpLog(TAG, "11683562 - removing id: " + id, true);
CellLayout cl = mWorkspaceScreens.get(id);
mWorkspaceScreens.remove(id);
mScreenOrder.remove(id);
@@ -813,8 +933,9 @@ public class Workspace extends SmoothPagedView
removeView(cl);
} else {
// if this is the last non-custom content screen, convert it to the empty screen
- mWorkspaceScreens.put(EXTRA_EMPTY_SCREEN_RIGHT_ID, cl);
- mScreenOrder.add(EXTRA_EMPTY_SCREEN_RIGHT_ID);
+ mRemoveEmptyScreenRunnable = null;
+ mWorkspaceScreens.put(EXTRA_EMPTY_SCREEN_ID, cl);
+ mScreenOrder.add(EXTRA_EMPTY_SCREEN_ID);
}
}
@@ -864,6 +985,8 @@ public class Workspace extends SmoothPagedView
*/
void addInScreen(View child, long container, long screenId, int x, int y, int spanX, int spanY,
boolean insert, boolean computeXYFromRank) {
+ //Reload settings
+ reloadSettings();
if (container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
if (getScreenWithId(screenId) == null) {
Log.e(TAG, "Skipping child, screenId " + screenId + " not found");
@@ -872,7 +995,7 @@ public class Workspace extends SmoothPagedView
return;
}
}
- if (screenId == EXTRA_EMPTY_SCREEN_LEFT_ID || screenId == EXTRA_EMPTY_SCREEN_RIGHT_ID) {
+ if (screenId == EXTRA_EMPTY_SCREEN_ID) {
// This should never happen
throw new RuntimeException("Screen id should not be EXTRA_EMPTY_SCREEN_ID");
}
@@ -921,7 +1044,9 @@ public class Workspace extends SmoothPagedView
}
// Get the canonical child id to uniquely represent this view in this screen
- int childId = LauncherModel.getCellLayoutChildId(container, screenId, x, y, spanX, spanY);
+ ItemInfo info = (ItemInfo) child.getTag();
+ int childId = mLauncher.getViewIdForItem(info);
+
boolean markCellsAsOccupied = !(child instanceof Folder);
if (!layout.addViewToCellLayout(child, insert ? 0 : -1, childId, lp, markCellsAsOccupied)) {
// TODO: This branch occurs when the workspace is adding views
@@ -1115,6 +1240,10 @@ public class Workspace extends SmoothPagedView
mDelayedResizeRunnable = null;
}
+ if (mDelayedSnapToPageRunnable != null) {
+ mDelayedSnapToPageRunnable.run();
+ mDelayedSnapToPageRunnable = null;
+ }
if (mStripScreensOnPageStopMoving) {
stripEmptyScreens();
mStripScreensOnPageStopMoving = false;
@@ -1124,16 +1253,18 @@ public class Workspace extends SmoothPagedView
@Override
protected void notifyPageSwitchListener() {
super.notifyPageSwitchListener();
- Launcher.setScreen(mCurrentPage);
+ Launcher.setScreen(getNextPage());
- if (hasCustomContent() && getNextPage() == 0 && !mCustomContentShowing) {
+ int ccIndex = getPageIndexForScreenId(CUSTOM_CONTENT_SCREEN_ID);
+ if (hasCustomContent() && getNextPage() == ccIndex && !mCustomContentShowing) {
mCustomContentShowing = true;
+
if (mCustomContentCallbacks != null) {
mCustomContentCallbacks.onShow();
mCustomContentShowTime = System.currentTimeMillis();
mLauncher.updateVoiceButtonProxyVisible(false);
}
- } else if (hasCustomContent() && getNextPage() != 0 && mCustomContentShowing) {
+ } else if (hasCustomContent() && getNextPage() != ccIndex && mCustomContentShowing) {
mCustomContentShowing = false;
if (mCustomContentCallbacks != null) {
mCustomContentCallbacks.onHide();
@@ -1151,10 +1282,44 @@ public class Workspace extends SmoothPagedView
}
protected void setWallpaperDimension() {
- String spKey = WallpaperCropActivity.getSharedPreferencesKey();
- SharedPreferences sp = mLauncher.getSharedPreferences(spKey, Context.MODE_PRIVATE);
- WallpaperPickerActivity.suggestWallpaperDimension(mLauncher.getResources(),
- sp, mLauncher.getWindowManager(), mWallpaperManager);
+ new AsyncTask<Void, Void, Void>() {
+ public Void doInBackground(Void ... args) {
+ String spKey = WallpaperCropActivity.getSharedPreferencesKey();
+ SharedPreferences sp =
+ mLauncher.getSharedPreferences(spKey, Context.MODE_MULTI_PROCESS);
+ LauncherWallpaperPickerActivity.suggestWallpaperDimension(mLauncher.getResources(),
+ sp, mLauncher.getWindowManager(), mWallpaperManager);
+ return null;
+ }
+ }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void) null);
+ }
+
+ protected void snapToPage(int whichPage, Runnable r) {
+ snapToPage(whichPage, SLOW_PAGE_SNAP_ANIMATION_DURATION, r);
+ }
+
+ @Override
+ protected void snapToPage(int whichPage, int delta, int duration, boolean immediate,
+ TimeInterpolator interpolator) {
+ super.snapToPage(whichPage, delta, duration, immediate, interpolator);
+
+ // Trigger onCustomContentLaunch if we have just snapped to the custom page.
+ int customPageIndex = getPageIndexForScreenId(CUSTOM_CONTENT_SCREEN_ID);
+ if (hasCustomContent() && whichPage == customPageIndex && !mCustomContentShowing) {
+ if(!isInOverviewMode()) {
+ mCustomContentShowing = true;
+ // Start Google Now and register the gesture to return to Trebuchet
+ mLauncher.onCustomContentLaunch();
+ }
+ }
+ }
+
+ protected void snapToPage(int whichPage, int duration, Runnable r) {
+ if (mDelayedSnapToPageRunnable != null) {
+ mDelayedSnapToPageRunnable.run();
+ }
+ mDelayedSnapToPageRunnable = r;
+ snapToPage(whichPage, duration);
}
protected void snapToScreenId(long screenId, Runnable r) {
@@ -1228,9 +1393,11 @@ public class Workspace extends SmoothPagedView
}
// Exclude the leftmost page
- int firstIndex = numCustomPages() + (hasExtraEmptyScreenLeft() ? 1 : 0);
- // Exclude the last extra empty screen
- int lastIndex = getChildCount() - 1 - (hasExtraEmptyScreenRight() ? 1 : 0);
+ int emptyExtraPages = numEmptyScreensToIgnore();
+ int firstIndex = numCustomPages();
+ // Exclude the last extra empty screen (if we have > MIN_PARALLAX_PAGE_SPAN pages)
+ int lastIndex = getChildCount() - 1 - emptyExtraPages;
+
if (isLayoutRtl()) {
int temp = firstIndex;
firstIndex = lastIndex;
@@ -1245,16 +1412,21 @@ public class Workspace extends SmoothPagedView
// TODO: do different behavior if it's a live wallpaper?
// Sometimes the left parameter of the pages is animated during a layout transition;
// this parameter offsets it to keep the wallpaper from animating as well
- int offsetForLayoutTransitionAnimation = isLayoutRtl() ?
- getPageAt(getChildCount() - 1).getLeft() - getFirstChildLeft() : 0;
int adjustedScroll =
- getScrollX() - firstPageScrollX - offsetForLayoutTransitionAnimation;
+ getScrollX() - firstPageScrollX - getLayoutTransitionOffsetForPage(0);
float offset = Math.min(1, adjustedScroll / (float) scrollRange);
offset = Math.max(0, offset);
// Don't use up all the wallpaper parallax until you have at least
// MIN_PARALLAX_PAGE_SPAN pages
int numScrollingPages = getNumScreensExcludingEmptyAndCustom();
- int parallaxPageSpan = Math.max(MIN_PARALLAX_PAGE_SPAN, numScrollingPages - 1);
+ int parallaxPageSpan;
+ if (mWallpaperIsLiveWallpaper) {
+ parallaxPageSpan = numScrollingPages - 1;
+ } else {
+ parallaxPageSpan = Math.max(MIN_PARALLAX_PAGE_SPAN, numScrollingPages - 1);
+ }
+ mNumPagesForWallpaperParallax = parallaxPageSpan;
+
// On RTL devices, push the wallpaper offset to the right if we don't have enough
// pages (ie if numScrollingPages < MIN_PARALLAX_PAGE_SPAN)
int padding = isLayoutRtl() ? parallaxPageSpan - numScrollingPages + 1 : 0;
@@ -1262,8 +1434,17 @@ public class Workspace extends SmoothPagedView
}
}
+ private int numEmptyScreensToIgnore() {
+ int numScrollingPages = getChildCount() - numCustomPages();
+ if (numScrollingPages >= MIN_PARALLAX_PAGE_SPAN && hasExtraEmptyScreen()) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+
private int getNumScreensExcludingEmptyAndCustom() {
- int numScrollingPages = getChildCount() - numExtraEmptyScreens() - numCustomPages();
+ int numScrollingPages = getChildCount() - numEmptyScreensToIgnore() - numCustomPages();
return numScrollingPages;
}
@@ -1289,7 +1470,11 @@ public class Workspace extends SmoothPagedView
private void setWallpaperOffsetSteps() {
// Set wallpaper offset steps (1 / (number of screens - 1))
- mWallpaperManager.setWallpaperOffsetSteps(1.0f / (getChildCount() - 1), 1.0f);
+ float xOffset = 1.0f / mNumPagesForWallpaperParallax;
+ if (xOffset != mLastSetWallpaperOffsetSteps) {
+ mWallpaperManager.setWallpaperOffsetSteps(xOffset, 1.0f);
+ mLastSetWallpaperOffsetSteps = xOffset;
+ }
}
public void setFinalX(float x) {
@@ -1430,18 +1615,12 @@ public class Workspace extends SmoothPagedView
mState == State.NORMAL &&
!mIsSwitchingState &&
!isInOverscroll) {
- for (int i = 0; i < getChildCount(); i++) {
+ for (int i = numCustomPages(); i < getChildCount(); i++) {
CellLayout child = (CellLayout) getChildAt(i);
if (child != null) {
float scrollProgress = getScrollProgress(screenCenter, child, i);
float alpha = 1 - Math.abs(scrollProgress);
child.getShortcutsAndWidgets().setAlpha(alpha);
- if (!mIsDragOccuring && !mShowOutlines) {
- child.setBackgroundAlphaMultiplier(
- backgroundAlphaInterpolator(Math.abs(scrollProgress)));
- } else {
- child.setBackgroundAlphaMultiplier(1f);
- }
}
}
}
@@ -1584,7 +1763,7 @@ public class Workspace extends SmoothPagedView
cl.setOverscrollTransformsDirty(true);
}
} else {
- if (mOverscrollTransformsSet) {
+ if (mOverscrollTransformsSet && getChildCount() > 0) {
mOverscrollTransformsSet = false;
((CellLayout) getChildAt(0)).resetOverscrollTransforms();
((CellLayout) getChildAt(getChildCount() - 1)).resetOverscrollTransforms();
@@ -1631,6 +1810,31 @@ public class Workspace extends SmoothPagedView
} else {
mWallpaperOffset.syncWithScroll();
}
+
+ // Update wallpaper dimensions if they were changed since last onResume
+ // (we also always set the wallpaper dimensions in the constructor)
+ if (LauncherAppState.getInstance().hasWallpaperChangedSinceLastCheck()) {
+ setWallpaperDimension();
+ }
+ mWallpaperIsLiveWallpaper = mWallpaperManager.getWallpaperInfo() != null;
+ // Force the wallpaper offset steps to be set again, because another app might have changed
+ // them
+ mLastSetWallpaperOffsetSteps = 0f;
+
+ moveAwayFromCustomContentIfRequired();
+ }
+
+ public void moveAwayFromCustomContentIfRequired() {
+ // Never resume to the custom page if GEL integration is enabled.
+ int customPageIndex = getPageIndexForScreenId(CUSTOM_CONTENT_SCREEN_ID);
+ // mCustomContentShowing can be lost if the Activity is recreated,
+ // So make sure it is set to the right value.
+ mCustomContentShowing = mCustomContentShowing
+ || (customPageIndex == getCurrentPage()
+ && hasCustomContent());
+ if (mCustomContentShowing && mLauncher.isGelIntegrationEnabled()) {
+ moveToScreen((customPageIndex + 1), true);
+ }
}
@Override
@@ -1640,6 +1844,8 @@ public class Workspace extends SmoothPagedView
mWallpaperOffset.jumpToFinal();
}
super.onLayout(changed, left, top, right, bottom);
+
+ moveAwayFromCustomContentIfRequired();
}
@Override
@@ -1900,7 +2106,7 @@ public class Workspace extends SmoothPagedView
mDefaultScreenId = getScreenIdForPageIndex(getPageNearestToCenterOfScreen());
- exitOverviewMode(getPageNearestToCenterOfScreen(), true);
+ updateDefaultScreenButton();
SettingsProvider.get(mLauncher).edit()
.putLong(SettingsProvider.SETTINGS_UI_HOMESCREEN_DEFAULT_SCREEN_ID, mDefaultScreenId)
@@ -1972,6 +2178,9 @@ public class Workspace extends SmoothPagedView
}
private void enableOverviewMode(boolean enable, int snapPage, boolean animated) {
+ //Check to see if Settings need to taken
+ reloadSettings();
+
State finalState = Workspace.State.OVERVIEW;
if (!enable) {
finalState = Workspace.State.NORMAL;
@@ -1993,14 +2202,32 @@ public class Workspace extends SmoothPagedView
}
int getOverviewModeTranslationY() {
- int childHeight = getNormalChildHeight();
+ LauncherAppState app = LauncherAppState.getInstance();
+ DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
+ Rect overviewBar = grid.getOverviewModeButtonBarRect();
+
+ int availableHeight = getViewportHeight();
+ int scaledHeight = (int) (mOverviewModeShrinkFactor * getNormalChildHeight());
+ int offsetFromTopEdge = (availableHeight - scaledHeight) / 2;
+ int offsetToCenterInOverview = (availableHeight - mInsets.top - overviewBar.height()
+ - scaledHeight) / 2;
+
+ return -offsetFromTopEdge + mInsets.top + offsetToCenterInOverview;
+ }
+
+ float getOverviewModeScaleY() {
+ float childHeight = getNormalChildHeight();
int viewPortHeight = getViewportHeight();
- int scaledChildHeight = (int) (mOverviewModeShrinkFactor * childHeight);
- int offset = (viewPortHeight - scaledChildHeight) / 2;
- int offsetDelta = mOverviewModePageOffset - offset + mInsets.top;
+ Resources res = getResources();
+ int top = res.getDimensionPixelSize(R.dimen.overview_panel_top_padding);
+ top += res.getDimensionPixelSize(R.dimen.sliding_panel_padding);
+ top += res.getDimensionPixelSize(R.dimen.overview_scaling_padding);
- return offsetDelta;
+ float scaledChildHeight = viewPortHeight - top;
+
+ float scale = scaledChildHeight / childHeight;
+ return scale;
}
boolean shouldVoiceButtonProxyBeVisible() {
@@ -2069,16 +2296,16 @@ public class Workspace extends SmoothPagedView
mNewScale = 1.0f;
if (oldStateIsOverview) {
- disableFreeScroll(snapPage);
- } else if (stateIsOverview) {
- enableFreeScroll();
+ disableFreeScroll();
+ } else if (stateIsOverview){
+ updateFreescrollBounds();
}
if (state != State.NORMAL) {
if (stateIsSpringLoaded) {
mNewScale = mSpringLoadedShrinkFactor;
} else if (stateIsOverview) {
- mNewScale = mOverviewModeShrinkFactor;
+ mNewScale = getOverviewModeScaleY();
} else if (stateIsSmall){
mNewScale = mOverviewModeShrinkFactor - 0.3f;
}
@@ -2096,11 +2323,23 @@ public class Workspace extends SmoothPagedView
duration = getResources().getInteger(R.integer.config_appsCustomizeWorkspaceShrinkTime);
}
+ if (snapPage == -1) {
+ snapPage = getPageNearestToCenterOfScreen();
+ }
+ snapToPage(snapPage, duration, mZoomInInterpolator);
+
for (int i = 0; i < getChildCount(); i++) {
final CellLayout cl = (CellLayout) getChildAt(i);
- boolean isCurrentPage = (i == getNextPage());
+ boolean isCurrentPage = (i == snapPage);
float initialAlpha = cl.getShortcutsAndWidgets().getAlpha();
- float finalAlpha = stateIsSmall ? 0f : 1f;
+ float finalAlpha;
+ if (stateIsSmall) {
+ finalAlpha = 0f;
+ } else if (stateIsNormal && mWorkspaceFadeInAdjacentScreens) {
+ finalAlpha = (i == snapPage || i < numCustomPages()) ? 1f : 0f;
+ } else {
+ finalAlpha = 1f;
+ }
if (stateIsOverview) {
cl.setVisibility(VISIBLE);
@@ -2146,6 +2385,7 @@ public class Workspace extends SmoothPagedView
final View searchBar = mLauncher.getQsbBar();
final View overviewPanel = mLauncher.getOverviewPanel();
final View hotseat = mLauncher.getHotseat();
+ final View pageIndicator = getPageIndicator();
if (animated) {
anim.setDuration(duration);
LauncherViewPropertyAnimator scale = new LauncherViewPropertyAnimator(this);
@@ -2188,36 +2428,43 @@ public class Workspace extends SmoothPagedView
}
}
}
- ObjectAnimator pageIndicatorAlpha = null;
- if (getPageIndicator() != null) {
- pageIndicatorAlpha = ObjectAnimator.ofFloat(getPageIndicator(), "alpha",
- finalHotseatAndPageIndicatorAlpha);
- }
- ObjectAnimator hotseatAlpha = ObjectAnimator.ofFloat(hotseat, "alpha",
- finalHotseatAndPageIndicatorAlpha);
- ObjectAnimator searchBarAlpha = null;
- if (mShowSearchBar) {
- searchBarAlpha = ObjectAnimator.ofFloat(searchBar,
- "alpha", finalSearchBarAlpha);
+ Animator pageIndicatorAlpha = null;
+ if (pageIndicator != null) {
+ pageIndicatorAlpha = new LauncherViewPropertyAnimator(pageIndicator)
+ .alpha(finalHotseatAndPageIndicatorAlpha).withLayer();
+ pageIndicatorAlpha.addListener(new AlphaUpdateListener(pageIndicator));
+ } else {
+ // create a dummy animation so we don't need to do null checks later
+ pageIndicatorAlpha = ValueAnimator.ofFloat(0, 0);
}
- ObjectAnimator overviewPanelAlpha = ObjectAnimator.ofFloat(overviewPanel,
- "alpha", finalOverviewPanelAlpha);
- overviewPanelAlpha.addListener(new AlphaUpdateListener(overviewPanel));
+ Animator hotseatAlpha = new LauncherViewPropertyAnimator(hotseat)
+ .alpha(finalHotseatAndPageIndicatorAlpha).withLayer();
hotseatAlpha.addListener(new AlphaUpdateListener(hotseat));
+
+ Animator searchBarAlpha = new LauncherViewPropertyAnimator(searchBar)
+ .alpha(finalSearchBarAlpha).withLayer();
if (mShowSearchBar) searchBarAlpha.addListener(new AlphaUpdateListener(searchBar));
+ Animator overviewPanelAlpha = new LauncherViewPropertyAnimator(overviewPanel)
+ .alpha(finalOverviewPanelAlpha).withLayer();
+ overviewPanelAlpha.addListener(new AlphaUpdateListener(overviewPanel));
+
if (workspaceToOverview) {
+ pageIndicatorAlpha.setInterpolator(new DecelerateInterpolator(2));
hotseatAlpha.setInterpolator(new DecelerateInterpolator(2));
+ overviewPanelAlpha.setInterpolator(null);
} else if (overviewToWorkspace) {
+ pageIndicatorAlpha.setInterpolator(null);
+ hotseatAlpha.setInterpolator(null);
overviewPanelAlpha.setInterpolator(new DecelerateInterpolator(2));
}
+ searchBarAlpha.setInterpolator(null);
- if (getPageIndicator() != null) {
- pageIndicatorAlpha.addListener(new AlphaUpdateListener(getPageIndicator()));
- }
-
- anim.play(overviewPanelAlpha);
+ overviewPanel.setAlpha(finalOverviewPanelAlpha);
+ AlphaUpdateListener.updateVisibility(overviewPanel);
+ Animation animation = AnimationUtils.loadAnimation(mLauncher, R.anim.drop_down);
+ overviewPanel.startAnimation(animation);
anim.play(hotseatAlpha);
if (mShowSearchBar) anim.play(searchBarAlpha);
anim.play(pageIndicatorAlpha);
@@ -2227,9 +2474,9 @@ public class Workspace extends SmoothPagedView
AlphaUpdateListener.updateVisibility(overviewPanel);
hotseat.setAlpha(finalHotseatAndPageIndicatorAlpha);
AlphaUpdateListener.updateVisibility(hotseat);
- if (getPageIndicator() != null) {
- getPageIndicator().setAlpha(finalHotseatAndPageIndicatorAlpha);
- AlphaUpdateListener.updateVisibility(getPageIndicator());
+ if (pageIndicator != null) {
+ pageIndicator.setAlpha(finalHotseatAndPageIndicatorAlpha);
+ AlphaUpdateListener.updateVisibility(pageIndicator);
}
if (mShowSearchBar) {
searchBar.setAlpha(finalSearchBarAlpha);
@@ -2347,7 +2594,9 @@ public class Workspace extends SmoothPagedView
void hideCustomContentIfNecessary() {
boolean hide = mState != Workspace.State.NORMAL;
if (hide && hasCustomContent()) {
+ disableLayoutTransitions();
mWorkspaceScreens.get(CUSTOM_CONTENT_SCREEN_ID).setVisibility(INVISIBLE);
+ enableLayoutTransitions();
}
}
@@ -2363,6 +2612,11 @@ public class Workspace extends SmoothPagedView
final CellLayout cl = (CellLayout) getChildAt(i);
cl.setShortcutAndWidgetAlpha(1f);
}
+ } else {
+ for (int i = 0; i < numCustomPages(); i++) {
+ final CellLayout cl = (CellLayout) getChildAt(i);
+ cl.setShortcutAndWidgetAlpha(1f);
+ }
}
showCustomContentIfNecessary();
}
@@ -2548,10 +2802,21 @@ public class Workspace extends SmoothPagedView
if (child instanceof BubbleTextView) {
BubbleTextView icon = (BubbleTextView) child;
icon.clearPressedOrFocusedBackground();
+ } else if (child instanceof FolderIcon) {
+ // Dismiss the folder cling if we haven't already
+ mLauncher.getLauncherClings().markFolderClingDismissed();
}
- mDragController.startDrag(b, dragLayerX, dragLayerY, source, child.getTag(),
+ if (child.getTag() == null || !(child.getTag() instanceof ItemInfo)) {
+ String msg = "Drag started with a view that has no tag set. This "
+ + "will cause a crash (issue 11627249) down the line. "
+ + "View: " + child + " tag: " + child.getTag();
+ throw new IllegalStateException(msg);
+ }
+
+ DragView dv = mDragController.startDrag(b, dragLayerX, dragLayerY, source, child.getTag(),
DragController.DRAG_ACTION_MOVE, dragVisualizeOffset, dragRect, scale);
+ dv.setIntrinsicIconScaleFactor(source.getIntrinsicIconScaleFactor());
if (child.getParent() instanceof ShortcutAndWidgetContainer) {
mDragSourceInternal = (ShortcutAndWidgetContainer) child.getParent();
@@ -2623,17 +2888,18 @@ public class Workspace extends SmoothPagedView
mTargetCell);
float distance = dropTargetLayout.getDistanceFromCell(mDragViewVisualCenter[0],
mDragViewVisualCenter[1], mTargetCell);
- if (willCreateUserFolder((ItemInfo) d.dragInfo, dropTargetLayout,
- mTargetCell, distance, true)) {
+ if (mCreateUserFolderOnDrop && willCreateUserFolder((ItemInfo) d.dragInfo,
+ dropTargetLayout, mTargetCell, distance, true)) {
return true;
}
- if (willAddToExistingUserFolder((ItemInfo) d.dragInfo, dropTargetLayout,
- mTargetCell, distance)) {
+
+ if (mAddToExistingFolderOnDrop && willAddToExistingUserFolder((ItemInfo) d.dragInfo,
+ dropTargetLayout, mTargetCell, distance)) {
return true;
}
int[] resultSpan = new int[2];
- mTargetCell = dropTargetLayout.createArea((int) mDragViewVisualCenter[0],
+ mTargetCell = dropTargetLayout.performReorder((int) mDragViewVisualCenter[0],
(int) mDragViewVisualCenter[1], minSpanX, minSpanY, spanX, spanY,
null, mTargetCell, resultSpan, CellLayout.MODE_ACCEPT_DROP);
boolean foundCell = mTargetCell[0] >= 0 && mTargetCell[1] >= 0;
@@ -2648,8 +2914,8 @@ public class Workspace extends SmoothPagedView
}
long screenId = getIdForScreen(dropTargetLayout);
- if (screenId == EXTRA_EMPTY_SCREEN_LEFT_ID || screenId == EXTRA_EMPTY_SCREEN_RIGHT_ID) {
- commitExtraEmptyScreen(screenId);
+ if (screenId == EXTRA_EMPTY_SCREEN_ID) {
+ commitExtraEmptyScreen();
}
return true;
@@ -2831,13 +3097,13 @@ public class Workspace extends SmoothPagedView
// cell also contains a shortcut, then create a folder with the two shortcuts.
if (!mInScrollArea && createUserFolderIfNecessary(cell, container,
dropTargetLayout, mTargetCell, distance, false, d.dragView, null)) {
- stripEmptyScreens();
+ removeExtraEmptyScreen(true, null, 0, true);
return;
}
if (addToExistingFolderIfNecessary(cell, dropTargetLayout, mTargetCell,
distance, d, false)) {
- stripEmptyScreens();
+ removeExtraEmptyScreen(true, null, 0, true);
return;
}
@@ -2852,7 +3118,7 @@ public class Workspace extends SmoothPagedView
}
int[] resultSpan = new int[2];
- mTargetCell = dropTargetLayout.createArea((int) mDragViewVisualCenter[0],
+ mTargetCell = dropTargetLayout.performReorder((int) mDragViewVisualCenter[0],
(int) mDragViewVisualCenter[1], minSpanX, minSpanY, spanX, spanY, cell,
mTargetCell, resultSpan, CellLayout.MODE_ON_DROP);
@@ -2892,8 +3158,6 @@ public class Workspace extends SmoothPagedView
lp.cellHSpan = item.spanX;
lp.cellVSpan = item.spanY;
lp.isLockedToGrid = true;
- cell.setId(LauncherModel.getCellLayoutChildId(container, mDragInfo.screenId,
- mTargetCell[0], mTargetCell[1], mDragInfo.spanX, mDragInfo.spanY));
if (container != LauncherSettings.Favorites.CONTAINER_HOTSEAT &&
cell instanceof LauncherAppWidgetHostView) {
@@ -2946,7 +3210,7 @@ public class Workspace extends SmoothPagedView
if (finalResizeRunnable != null) {
finalResizeRunnable.run();
}
- stripEmptyScreens();
+ removeExtraEmptyScreen(true, null, 0, true);
}
};
mAnimatingViewIntoPlace = true;
@@ -3035,13 +3299,11 @@ public class Workspace extends SmoothPagedView
display.getCurrentSizeRange(smallestSize, largestSize);
int countX = (int) grid.numColumns;
int countY = (int) grid.numRows;
- int constrainedLongEdge = largestSize.y;
- int constrainedShortEdge = smallestSize.y;
if (orientation == CellLayout.LANDSCAPE) {
if (mLandscapeCellLayoutMetrics == null) {
Rect padding = grid.getWorkspacePadding(CellLayout.LANDSCAPE);
- int width = constrainedLongEdge - padding.left - padding.right;
- int height = constrainedShortEdge - padding.top - padding.bottom;
+ int width = largestSize.x - padding.left - padding.right;
+ int height = smallestSize.y - padding.top - padding.bottom;
mLandscapeCellLayoutMetrics = new Rect();
mLandscapeCellLayoutMetrics.set(
grid.calculateCellWidth(width, countX),
@@ -3051,8 +3313,8 @@ public class Workspace extends SmoothPagedView
} else if (orientation == CellLayout.PORTRAIT) {
if (mPortraitCellLayoutMetrics == null) {
Rect padding = grid.getWorkspacePadding(CellLayout.PORTRAIT);
- int width = constrainedShortEdge - padding.left - padding.right;
- int height = constrainedLongEdge - padding.top - padding.bottom;
+ int width = smallestSize.x - padding.left - padding.right;
+ int height = largestSize.y - padding.top - padding.bottom;
mPortraitCellLayoutMetrics = new Rect();
mPortraitCellLayoutMetrics.set(
grid.calculateCellWidth(width, countX),
@@ -3437,6 +3699,11 @@ public class Workspace extends SmoothPagedView
&& !mReorderAlarm.alarmPending() && (mLastReorderX != reorderX ||
mLastReorderY != reorderY)) {
+ int[] resultSpan = new int[2];
+ mDragTargetLayout.performReorder((int) mDragViewVisualCenter[0],
+ (int) mDragViewVisualCenter[1], minSpanX, minSpanY, item.spanX, item.spanY,
+ child, mTargetCell, resultSpan, CellLayout.MODE_SHOW_REORDER_HINT);
+
// Otherwise, if we aren't adding to or creating a folder and there's no pending
// reorder, then we schedule a reorder
ReorderAlarmListener listener = new ReorderAlarmListener(mDragViewVisualCenter,
@@ -3541,7 +3808,7 @@ public class Workspace extends SmoothPagedView
mLastReorderX = mTargetCell[0];
mLastReorderY = mTargetCell[1];
- mTargetCell = mDragTargetLayout.createArea((int) mDragViewVisualCenter[0],
+ mTargetCell = mDragTargetLayout.performReorder((int) mDragViewVisualCenter[0],
(int) mDragViewVisualCenter[1], minSpanX, minSpanY, spanX, spanY,
child, mTargetCell, resultSpan, CellLayout.MODE_DRAG_OVER);
@@ -3597,7 +3864,13 @@ public class Workspace extends SmoothPagedView
final Runnable exitSpringLoadedRunnable = new Runnable() {
@Override
public void run() {
- mLauncher.exitSpringLoadedDragModeDelayed(true, false, null);
+ removeExtraEmptyScreen(false, new Runnable() {
+ @Override
+ public void run() {
+ mLauncher.exitSpringLoadedDragModeDelayed(true,
+ Launcher.EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT, null);
+ }
+ });
}
};
@@ -3645,7 +3918,7 @@ public class Workspace extends SmoothPagedView
minSpanY = item.minSpanY;
}
int[] resultSpan = new int[2];
- mTargetCell = cellLayout.createArea((int) mDragViewVisualCenter[0],
+ mTargetCell = cellLayout.performReorder((int) mDragViewVisualCenter[0],
(int) mDragViewVisualCenter[1], minSpanX, minSpanY, info.spanX, info.spanY,
null, mTargetCell, resultSpan, CellLayout.MODE_ON_DROP_EXTERNAL);
@@ -3738,7 +4011,7 @@ public class Workspace extends SmoothPagedView
if (touchXY != null) {
// when dragging and dropping, just find the closest free spot
- mTargetCell = cellLayout.createArea((int) mDragViewVisualCenter[0],
+ mTargetCell = cellLayout.performReorder((int) mDragViewVisualCenter[0],
(int) mDragViewVisualCenter[1], 1, 1, 1, 1,
null, mTargetCell, null, CellLayout.MODE_ON_DROP_EXTERNAL);
} else {
@@ -3759,7 +4032,7 @@ public class Workspace extends SmoothPagedView
// the correct final location.
setFinalTransitionTransform(cellLayout);
mLauncher.getDragLayer().animateViewIntoPosition(d.dragView, view,
- exitSpringLoadedRunnable);
+ exitSpringLoadedRunnable, this);
resetTransitionTransform(cellLayout);
}
}
@@ -3834,7 +4107,7 @@ public class Workspace extends SmoothPagedView
external, scalePreview);
Resources res = mLauncher.getResources();
- int duration = res.getInteger(R.integer.config_dropAnimMaxDuration) - 200;
+ final int duration = res.getInteger(R.integer.config_dropAnimMaxDuration) - 200;
// In the case where we've prebound the widget, we remove it from the DragLayer
if (finalView instanceof AppWidgetHostView && external) {
@@ -3910,8 +4183,8 @@ public class Workspace extends SmoothPagedView
return mDragInfo;
}
- public int getRestorePage() {
- return getNextPage() - numCustomPages() - (hasExtraEmptyScreenLeft() ? 1 : 0);
+ public int getCurrentPageOffsetFromCustomContent() {
+ return getNextPage() - numCustomPages();
}
/**
@@ -3932,7 +4205,6 @@ public class Workspace extends SmoothPagedView
// hardware layers on children are enabled on startup, but should be disabled until
// needed
updateChildrenLayersEnabled(false);
- setWallpaperDimension();
}
/**
@@ -3942,11 +4214,11 @@ public class Workspace extends SmoothPagedView
final boolean isFlingToDelete, final boolean success) {
if (mDeferDropAfterUninstall) {
mDeferredAction = new Runnable() {
- public void run() {
- onDropCompleted(target, d, isFlingToDelete, success);
- mDeferredAction = null;
- }
- };
+ public void run() {
+ onDropCompleted(target, d, isFlingToDelete, success);
+ mDeferredAction = null;
+ }
+ };
return;
}
@@ -3964,7 +4236,7 @@ public class Workspace extends SmoothPagedView
// If we move the item to anything not on the Workspace, check if any empty
// screens need to be removed. If we dropped back on the workspace, this will
// be done post drop animation.
- stripEmptyScreens();
+ removeExtraEmptyScreen(true, null, 0, true);
}
} else if (mDragInfo != null && target != null && (!(target instanceof InfoDropTarget))) {
CellLayout cellLayout;
@@ -3973,7 +4245,13 @@ public class Workspace extends SmoothPagedView
} else {
cellLayout = getScreenWithId(mDragInfo.screenId);
}
- cellLayout.onDropChild(mDragInfo.cell);
+ if (cellLayout == null && LauncherAppState.isDogfoodBuild()) {
+ throw new RuntimeException("Invalid state: cellLayout == null in "
+ + "Workspace#onDropCompleted. Please file a bug. ");
+ }
+ if (cellLayout != null) {
+ cellLayout.onDropChild(mDragInfo.cell);
+ }
}
if ((d.cancelled || target instanceof InfoDropTarget || (beingCalledAfterUninstall && !mUninstallSuccessful))
&& mDragInfo.cell != null) {
@@ -4144,11 +4422,26 @@ public class Workspace extends SmoothPagedView
}
@Override
+ public float getIntrinsicIconScaleFactor() {
+ return 1f;
+ }
+
+ @Override
public boolean supportsFlingToDelete() {
return true;
}
@Override
+ public boolean supportsAppInfoDropTarget() {
+ return false;
+ }
+
+ @Override
+ public boolean supportsDeleteDropTarget() {
+ return true;
+ }
+
+ @Override
public void onFlingToDelete(DragObject d, int x, int y, PointF vec) {
// Do nothing
}
@@ -4491,29 +4784,53 @@ public class Workspace extends SmoothPagedView
stripEmptyScreens();
}
+ private void updateShortcut(HashMap<ComponentName, AppInfo> appsMap, ItemInfo info,
+ View child) {
+ if (info.getIntent() == null) {
+ // it's the all-apps shortcut, don't crash!
+ return;
+ }
+ ComponentName cn = info.getIntent().getComponent();
+ if (info.getRestoredIntent() != null) {
+ cn = info.getRestoredIntent().getComponent();
+ }
+ if (cn != null) {
+ AppInfo appInfo = appsMap.get(cn);
+ if ((appInfo != null) && LauncherModel.isShortcutInfoUpdateable(info)) {
+ ShortcutInfo shortcutInfo = (ShortcutInfo) info;
+ BubbleTextView shortcut = (BubbleTextView) child;
+ shortcutInfo.restore();
+ shortcutInfo.updateIcon(mIconCache);
+ shortcutInfo.title = appInfo.title.toString();
+ shortcut.applyFromShortcutInfo(shortcutInfo, mIconCache);
+ }
+ }
+ }
+
void updateShortcuts(ArrayList<AppInfo> apps) {
+ // Create a map of the apps to test against
+ final HashMap<ComponentName, AppInfo> appsMap = new HashMap<ComponentName, AppInfo>();
+ for (AppInfo ai : apps) {
+ appsMap.put(ai.componentName, ai);
+ }
+
ArrayList<ShortcutAndWidgetContainer> childrenLayouts = getAllShortcutAndWidgetContainers();
for (ShortcutAndWidgetContainer layout: childrenLayouts) {
- int childCount = layout.getChildCount();
- for (int j = 0; j < childCount; j++) {
- final View view = layout.getChildAt(j);
- Object tag = view.getTag();
-
- if (LauncherModel.isShortcutInfoUpdateable((ItemInfo) tag)) {
- ShortcutInfo info = (ShortcutInfo) tag;
-
- final Intent intent = info.intent;
- final ComponentName name = intent.getComponent();
- final int appCount = apps.size();
- for (int k = 0; k < appCount; k++) {
- AppInfo app = apps.get(k);
- if (app.componentName.equals(name)) {
- BubbleTextView shortcut = (BubbleTextView) view;
- info.updateIcon(mIconCache);
- info.title = app.title.toString();
- shortcut.applyFromShortcutInfo(info, mIconCache);
- }
+ // Update all the children shortcuts
+ final HashMap<ItemInfo, View> children = new HashMap<ItemInfo, View>();
+ for (int j = 0; j < layout.getChildCount(); j++) {
+ View v = layout.getChildAt(j);
+ ItemInfo info = (ItemInfo) v.getTag();
+ if (info instanceof FolderInfo && v instanceof FolderIcon) {
+ FolderIcon folder = (FolderIcon) v;
+ ArrayList<View> folderChildren = folder.getFolder().getItemsInReadingOrder();
+ for (View fv : folderChildren) {
+ info = (ItemInfo) fv.getTag();
+ updateShortcut(appsMap, info, fv);
}
+ folder.invalidate();
+ } else if (info instanceof ShortcutInfo) {
+ updateShortcut(appsMap, info, v);
}
}
}
@@ -4534,7 +4851,15 @@ public class Workspace extends SmoothPagedView
}
void moveToDefaultScreen(boolean animate) {
- moveToScreen(getPageIndexForScreenId(mDefaultScreenId), animate);
+ // Do not use the custom page or index -1 as default,
+ // if GEL integration is enabled.
+ int idx = getPageIndexForScreenId(mDefaultScreenId);
+ int ccIndex = getPageIndexForScreenId(CUSTOM_CONTENT_SCREEN_ID);
+ if(hasCustomContent() && (idx == ccIndex || idx == -1)
+ && mLauncher.isGelIntegrationEnabled()) {
+ idx = 1;
+ }
+ moveToScreen(idx, animate);
}
void moveToCustomContentScreen(boolean animate) {
@@ -4550,12 +4875,13 @@ public class Workspace extends SmoothPagedView
child.requestFocus();
}
}
+ exitWidgetResizeMode();
}
@Override
protected PageIndicator.PageMarkerResources getPageIndicatorMarker(int pageIndex) {
long screenId = getScreenIdForPageIndex(pageIndex);
- if (screenId == EXTRA_EMPTY_SCREEN_LEFT_ID || screenId == EXTRA_EMPTY_SCREEN_RIGHT_ID) {
+ if (screenId == EXTRA_EMPTY_SCREEN_ID) {
int count = mScreenOrder.size() - numCustomPages();
if (count > 1) {
return new PageIndicator.PageMarkerResources(R.drawable.ic_pageindicator_current,
@@ -4592,4 +4918,45 @@ public class Workspace extends SmoothPagedView
public void getLocationInDragLayer(int[] loc) {
mLauncher.getDragLayer().getLocationInDragLayer(this, loc);
}
+
+ private void reloadSettings() {
+ mShowSearchBar = SettingsProvider.getBoolean(mLauncher, SettingsProvider.SETTINGS_UI_HOMESCREEN_SEARCH,
+ R.bool.preferences_interface_homescreen_search_default);
+ mShowOutlines = SettingsProvider.getBoolean(mLauncher,
+ SettingsProvider.SETTINGS_UI_HOMESCREEN_SCROLLING_PAGE_OUTLINES,
+ R.bool.preferences_interface_homescreen_scrolling_page_outlines_default);
+ mHideIconLabels = SettingsProvider.getBoolean(mLauncher,
+ SettingsProvider.SETTINGS_UI_HOMESCREEN_HIDE_ICON_LABELS,
+ R.bool.preferences_interface_homescreen_hide_icon_labels_default);
+ mWorkspaceFadeInAdjacentScreens = SettingsProvider.getBoolean(mLauncher,
+ SettingsProvider.SETTINGS_UI_HOMESCREEN_SCROLLING_FADE_ADJACENT,
+ R.bool.preferences_interface_homescreen_scrolling_fade_adjacent_default);
+ TransitionEffect.setFromString(this, SettingsProvider.getString(mLauncher,
+ SettingsProvider.SETTINGS_UI_HOMESCREEN_SCROLLING_TRANSITION_EFFECT,
+ R.string.preferences_interface_homescreen_scrolling_transition_effect));
+
+ mScrollWallpaper = SettingsProvider.getBoolean(mLauncher,
+ SettingsProvider.SETTINGS_UI_HOMESCREEN_SCROLLING_WALLPAPER_SCROLL,
+ R.bool.preferences_interface_homescreen_scrolling_wallpaper_scroll_default);
+
+ if (!mScrollWallpaper) {
+ if (mWindowToken != null) mWallpaperManager.setWallpaperOffsets(mWindowToken, 0f, 0.5f);
+ } else {
+ mWallpaperOffset.syncWithScroll();
+ }
+ }
+
+ public boolean getShowSearchBar() {
+ return mShowSearchBar;
+ }
+
+ public boolean getHideIconLables() {
+ return mHideIconLabels;
+ }
+
+ @Override
+ public void scrollTo(int x, int y) {
+ mEnforceRealBounds = isInOverviewMode();
+ super.scrollTo(x, y);
+ }
}
diff --git a/src/com/android/launcher3/list/AutoScrollListView.java b/src/com/android/launcher3/list/AutoScrollListView.java
new file mode 100644
index 000000000..66336bc71
--- /dev/null
+++ b/src/com/android/launcher3/list/AutoScrollListView.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.list;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.ListView;
+
+/**
+ * A ListView that can be asked to scroll (smoothly or otherwise) to a specific
+ * position. This class takes advantage of similar functionality that exists
+ * in {@link ListView} and enhances it.
+ */
+public class AutoScrollListView extends ListView {
+
+ /**
+ * Position the element at about 1/3 of the list height
+ */
+ private static final float PREFERRED_SELECTION_OFFSET_FROM_TOP = 0.33f;
+
+ private int mRequestedScrollPosition = -1;
+ private boolean mSmoothScrollRequested;
+
+ public AutoScrollListView(Context context) {
+ super(context);
+ }
+
+ public AutoScrollListView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public AutoScrollListView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ /**
+ * Brings the specified position to view by optionally performing a jump-scroll maneuver:
+ * first it jumps to some position near the one requested and then does a smooth
+ * scroll to the requested position. This creates an impression of full smooth
+ * scrolling without actually traversing the entire list. If smooth scrolling is
+ * not requested, instantly positions the requested item at a preferred offset.
+ */
+ public void requestPositionToScreen(int position, boolean smoothScroll) {
+ mRequestedScrollPosition = position;
+ mSmoothScrollRequested = smoothScroll;
+ requestLayout();
+ }
+
+ @Override
+ protected void layoutChildren() {
+ super.layoutChildren();
+ if (mRequestedScrollPosition == -1) {
+ return;
+ }
+
+ final int position = mRequestedScrollPosition;
+ mRequestedScrollPosition = -1;
+
+ int firstPosition = getFirstVisiblePosition() + 1;
+ int lastPosition = getLastVisiblePosition();
+ if (position >= firstPosition && position <= lastPosition) {
+ return; // Already on screen
+ }
+
+ final int offset = (int) (getHeight() * PREFERRED_SELECTION_OFFSET_FROM_TOP);
+ if (!mSmoothScrollRequested) {
+ setSelectionFromTop(position, offset);
+
+ // Since we have changed the scrolling position, we need to redo child layout
+ // Calling "requestLayout" in the middle of a layout pass has no effect,
+ // so we call layoutChildren explicitly
+ super.layoutChildren();
+
+ } else {
+ // We will first position the list a couple of screens before or after
+ // the new selection and then scroll smoothly to it.
+ int twoScreens = (lastPosition - firstPosition) * 2;
+ int preliminaryPosition;
+ if (position < firstPosition) {
+ preliminaryPosition = position + twoScreens;
+ if (preliminaryPosition >= getCount()) {
+ preliminaryPosition = getCount() - 1;
+ }
+ if (preliminaryPosition < firstPosition) {
+ setSelection(preliminaryPosition);
+ super.layoutChildren();
+ }
+ } else {
+ preliminaryPosition = position - twoScreens;
+ if (preliminaryPosition < 0) {
+ preliminaryPosition = 0;
+ }
+ if (preliminaryPosition > lastPosition) {
+ setSelection(preliminaryPosition);
+ super.layoutChildren();
+ }
+ }
+
+
+ smoothScrollToPositionFromTop(position, offset);
+ }
+ }
+}
diff --git a/src/com/android/launcher3/list/CompositeCursorAdapter.java b/src/com/android/launcher3/list/CompositeCursorAdapter.java
new file mode 100644
index 000000000..b1ddb67fb
--- /dev/null
+++ b/src/com/android/launcher3/list/CompositeCursorAdapter.java
@@ -0,0 +1,532 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.list;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+
+import java.util.ArrayList;
+
+/**
+ * A general purpose adapter that is composed of multiple cursors. It just
+ * appends them in the order they are added.
+ */
+public abstract class CompositeCursorAdapter extends BaseAdapter {
+
+ private static final int INITIAL_CAPACITY = 2;
+
+ public static class Partition {
+ boolean showIfEmpty;
+ boolean hasHeader;
+
+ Cursor cursor;
+ int idColumnIndex;
+ int count;
+
+ public Partition(boolean showIfEmpty, boolean hasHeader) {
+ this.showIfEmpty = showIfEmpty;
+ this.hasHeader = hasHeader;
+ }
+
+ /**
+ * True if the directory should be shown even if no contacts are found.
+ */
+ public boolean getShowIfEmpty() {
+ return showIfEmpty;
+ }
+
+ public boolean getHasHeader() {
+ return hasHeader;
+ }
+ }
+
+ private final Context mContext;
+ private ArrayList<Partition> mPartitions;
+ private int mCount = 0;
+ private boolean mCacheValid = true;
+ private boolean mNotificationsEnabled = true;
+ private boolean mNotificationNeeded;
+
+ public CompositeCursorAdapter(Context context) {
+ this(context, INITIAL_CAPACITY);
+ }
+
+ public CompositeCursorAdapter(Context context, int initialCapacity) {
+ mContext = context;
+ mPartitions = new ArrayList<Partition>();
+ }
+
+ public Context getContext() {
+ return mContext;
+ }
+
+ /**
+ * Registers a partition. The cursor for that partition can be set later.
+ * Partitions should be added in the order they are supposed to appear in the
+ * list.
+ */
+ public void addPartition(boolean showIfEmpty, boolean hasHeader) {
+ addPartition(new Partition(showIfEmpty, hasHeader));
+ }
+
+ public void addPartition(Partition partition) {
+ mPartitions.add(partition);
+ invalidate();
+ notifyDataSetChanged();
+ }
+
+ public void addPartition(int location, Partition partition) {
+ mPartitions.add(location, partition);
+ invalidate();
+ notifyDataSetChanged();
+ }
+
+ public void removePartition(int partitionIndex) {
+ Cursor cursor = mPartitions.get(partitionIndex).cursor;
+ if (cursor != null && !cursor.isClosed()) {
+ cursor.close();
+ }
+ mPartitions.remove(partitionIndex);
+ invalidate();
+ notifyDataSetChanged();
+ }
+
+ /**
+ * Removes cursors for all partitions.
+ */
+ // TODO: Is this really what this is supposed to do? Just remove the cursors? Not close them?
+ // Not remove the partitions themselves? Isn't this leaking?
+
+ public void clearPartitions() {
+ for (Partition partition : mPartitions) {
+ partition.cursor = null;
+ }
+ invalidate();
+ notifyDataSetChanged();
+ }
+
+ /**
+ * Closes all cursors and removes all partitions.
+ */
+ public void close() {
+ for (Partition partition : mPartitions) {
+ Cursor cursor = partition.cursor;
+ if (cursor != null && !cursor.isClosed()) {
+ cursor.close();
+ }
+ }
+ mPartitions.clear();
+ invalidate();
+ notifyDataSetChanged();
+ }
+
+ public void setHasHeader(int partitionIndex, boolean flag) {
+ mPartitions.get(partitionIndex).hasHeader = flag;
+ invalidate();
+ }
+
+ public void setShowIfEmpty(int partitionIndex, boolean flag) {
+ mPartitions.get(partitionIndex).showIfEmpty = flag;
+ invalidate();
+ }
+
+ public Partition getPartition(int partitionIndex) {
+ return mPartitions.get(partitionIndex);
+ }
+
+ protected void invalidate() {
+ mCacheValid = false;
+ }
+
+ public int getPartitionCount() {
+ return mPartitions.size();
+ }
+
+ protected void ensureCacheValid() {
+ if (mCacheValid) {
+ return;
+ }
+
+ mCount = 0;
+ for (Partition partition : mPartitions) {
+ Cursor cursor = partition.cursor;
+ int count = cursor != null ? cursor.getCount() : 0;
+ if (partition.hasHeader) {
+ if (count != 0 || partition.showIfEmpty) {
+ count++;
+ }
+ }
+ partition.count = count;
+ mCount += count;
+ }
+
+ mCacheValid = true;
+ }
+
+ /**
+ * Returns true if the specified partition was configured to have a header.
+ */
+ public boolean hasHeader(int partition) {
+ return mPartitions.get(partition).hasHeader;
+ }
+
+ /**
+ * Returns the total number of list items in all partitions.
+ */
+ public int getCount() {
+ ensureCacheValid();
+ return mCount;
+ }
+
+ /**
+ * Returns the cursor for the given partition
+ */
+ public Cursor getCursor(int partition) {
+ return mPartitions.get(partition).cursor;
+ }
+
+ /**
+ * Changes the cursor for an individual partition.
+ */
+ public void changeCursor(int partition, Cursor cursor) {
+ Cursor prevCursor = mPartitions.get(partition).cursor;
+ if (prevCursor != cursor) {
+ if (prevCursor != null && !prevCursor.isClosed()) {
+ prevCursor.close();
+ }
+ mPartitions.get(partition).cursor = cursor;
+ if (cursor != null) {
+ mPartitions.get(partition).idColumnIndex = cursor.getColumnIndex("_id");
+ }
+ invalidate();
+ notifyDataSetChanged();
+ }
+ }
+
+ /**
+ * Returns true if the specified partition has no cursor or an empty cursor.
+ */
+ public boolean isPartitionEmpty(int partition) {
+ Cursor cursor = mPartitions.get(partition).cursor;
+ return cursor == null || cursor.getCount() == 0;
+ }
+
+ /**
+ * Given a list position, returns the index of the corresponding partition.
+ */
+ public int getPartitionForPosition(int position) {
+ ensureCacheValid();
+ int start = 0;
+ for (int i = 0, n = mPartitions.size(); i < n; i++) {
+ int end = start + mPartitions.get(i).count;
+ if (position >= start && position < end) {
+ return i;
+ }
+ start = end;
+ }
+ return -1;
+ }
+
+ /**
+ * Given a list position, return the offset of the corresponding item in its
+ * partition. The header, if any, will have offset -1.
+ */
+ public int getOffsetInPartition(int position) {
+ ensureCacheValid();
+ int start = 0;
+ for (Partition partition : mPartitions) {
+ int end = start + partition.count;
+ if (position >= start && position < end) {
+ int offset = position - start;
+ if (partition.hasHeader) {
+ offset--;
+ }
+ return offset;
+ }
+ start = end;
+ }
+ return -1;
+ }
+
+ /**
+ * Returns the first list position for the specified partition.
+ */
+ public int getPositionForPartition(int partition) {
+ ensureCacheValid();
+ int position = 0;
+ for (int i = 0; i < partition; i++) {
+ position += mPartitions.get(i).count;
+ }
+ return position;
+ }
+
+ @Override
+ public int getViewTypeCount() {
+ return getItemViewTypeCount() + 1;
+ }
+
+ /**
+ * Returns the overall number of item view types across all partitions. An
+ * implementation of this method needs to ensure that the returned count is
+ * consistent with the values returned by {@link #getItemViewType(int,int)}.
+ */
+ public int getItemViewTypeCount() {
+ return 1;
+ }
+
+ /**
+ * Returns the view type for the list item at the specified position in the
+ * specified partition.
+ */
+ protected int getItemViewType(int partition, int position) {
+ return 1;
+ }
+
+ @Override
+ public int getItemViewType(int position) {
+ ensureCacheValid();
+ int start = 0;
+ for (int i = 0, n = mPartitions.size(); i < n; i++) {
+ int end = start + mPartitions.get(i).count;
+ if (position >= start && position < end) {
+ int offset = position - start;
+ if (mPartitions.get(i).hasHeader) {
+ offset--;
+ }
+ if (offset == -1) {
+ return IGNORE_ITEM_VIEW_TYPE;
+ } else {
+ return getItemViewType(i, offset);
+ }
+ }
+ start = end;
+ }
+
+ throw new ArrayIndexOutOfBoundsException(position);
+ }
+
+ public View getView(int position, View convertView, ViewGroup parent) {
+ ensureCacheValid();
+ int start = 0;
+ for (int i = 0, n = mPartitions.size(); i < n; i++) {
+ int end = start + mPartitions.get(i).count;
+ if (position >= start && position < end) {
+ int offset = position - start;
+ if (mPartitions.get(i).hasHeader) {
+ offset--;
+ }
+ View view;
+ if (offset == -1) {
+ view = getHeaderView(i, mPartitions.get(i).cursor, convertView, parent);
+ } else {
+ if (!mPartitions.get(i).cursor.moveToPosition(offset)) {
+ throw new IllegalStateException("Couldn't move cursor to position "
+ + offset);
+ }
+ view = getView(i, mPartitions.get(i).cursor, offset, convertView, parent);
+ }
+ if (view == null) {
+ throw new NullPointerException("View should not be null, partition: " + i
+ + " position: " + offset);
+ }
+ return view;
+ }
+ start = end;
+ }
+
+ throw new ArrayIndexOutOfBoundsException(position);
+ }
+
+ /**
+ * Returns the header view for the specified partition, creating one if needed.
+ */
+ protected View getHeaderView(int partition, Cursor cursor, View convertView,
+ ViewGroup parent) {
+ View view = convertView != null
+ ? convertView
+ : newHeaderView(mContext, partition, cursor, parent);
+ bindHeaderView(view, partition, cursor);
+ return view;
+ }
+
+ /**
+ * Creates the header view for the specified partition.
+ */
+ protected View newHeaderView(Context context, int partition, Cursor cursor,
+ ViewGroup parent) {
+ return null;
+ }
+
+ /**
+ * Binds the header view for the specified partition.
+ */
+ protected void bindHeaderView(View view, int partition, Cursor cursor) {
+ }
+
+ /**
+ * Returns an item view for the specified partition, creating one if needed.
+ */
+ protected View getView(int partition, Cursor cursor, int position, View convertView,
+ ViewGroup parent) {
+ View view;
+ if (convertView != null) {
+ view = convertView;
+ } else {
+ view = newView(mContext, partition, cursor, position, parent);
+ }
+ bindView(view, partition, cursor, position);
+ return view;
+ }
+
+ /**
+ * Creates an item view for the specified partition and position. Position
+ * corresponds directly to the current cursor position.
+ */
+ protected abstract View newView(Context context, int partition, Cursor cursor, int position,
+ ViewGroup parent);
+
+ /**
+ * Binds an item view for the specified partition and position. Position
+ * corresponds directly to the current cursor position.
+ */
+ protected abstract void bindView(View v, int partition, Cursor cursor, int position);
+
+ /**
+ * Returns a pre-positioned cursor for the specified list position.
+ */
+ public Object getItem(int position) {
+ ensureCacheValid();
+ int start = 0;
+ for (Partition mPartition : mPartitions) {
+ int end = start + mPartition.count;
+ if (position >= start && position < end) {
+ int offset = position - start;
+ if (mPartition.hasHeader) {
+ offset--;
+ }
+ if (offset == -1) {
+ return null;
+ }
+ Cursor cursor = mPartition.cursor;
+ cursor.moveToPosition(offset);
+ return cursor;
+ }
+ start = end;
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns the item ID for the specified list position.
+ */
+ public long getItemId(int position) {
+ ensureCacheValid();
+ int start = 0;
+ for (Partition mPartition : mPartitions) {
+ int end = start + mPartition.count;
+ if (position >= start && position < end) {
+ int offset = position - start;
+ if (mPartition.hasHeader) {
+ offset--;
+ }
+ if (offset == -1) {
+ return 0;
+ }
+ if (mPartition.idColumnIndex == -1) {
+ return 0;
+ }
+
+ Cursor cursor = mPartition.cursor;
+ if (cursor == null || cursor.isClosed() || !cursor.moveToPosition(offset)) {
+ return 0;
+ }
+ return cursor.getLong(mPartition.idColumnIndex);
+ }
+ start = end;
+ }
+
+ return 0;
+ }
+
+ /**
+ * Returns false if any partition has a header.
+ */
+ @Override
+ public boolean areAllItemsEnabled() {
+ for (Partition mPartition : mPartitions) {
+ if (mPartition.hasHeader) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Returns true for all items except headers.
+ */
+ @Override
+ public boolean isEnabled(int position) {
+ ensureCacheValid();
+ int start = 0;
+ for (int i = 0, n = mPartitions.size(); i < n; i++) {
+ int end = start + mPartitions.get(i).count;
+ if (position >= start && position < end) {
+ int offset = position - start;
+ if (mPartitions.get(i).hasHeader && offset == 0) {
+ return false;
+ } else {
+ return isEnabled(i, offset);
+ }
+ }
+ start = end;
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns true if the item at the specified offset of the specified
+ * partition is selectable and clickable.
+ */
+ protected boolean isEnabled(int partition, int position) {
+ return true;
+ }
+
+ /**
+ * Enable or disable data change notifications. It may be a good idea to
+ * disable notifications before making changes to several partitions at once.
+ */
+ public void setNotificationsEnabled(boolean flag) {
+ mNotificationsEnabled = flag;
+ if (flag && mNotificationNeeded) {
+ notifyDataSetChanged();
+ }
+ }
+
+ @Override
+ public void notifyDataSetChanged() {
+ if (mNotificationsEnabled) {
+ mNotificationNeeded = false;
+ super.notifyDataSetChanged();
+ } else {
+ mNotificationNeeded = true;
+ }
+ }
+}
diff --git a/src/com/android/launcher3/list/PinnedHeaderListAdapter.java b/src/com/android/launcher3/list/PinnedHeaderListAdapter.java
new file mode 100644
index 000000000..c15e87a46
--- /dev/null
+++ b/src/com/android/launcher3/list/PinnedHeaderListAdapter.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.list;
+
+import android.content.Context;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+
+/**
+ * A subclass of {@link CompositeCursorAdapter} that manages pinned partition headers.
+ */
+public abstract class PinnedHeaderListAdapter extends CompositeCursorAdapter
+ implements PinnedHeaderListView.PinnedHeaderAdapter {
+
+ public static final int PARTITION_HEADER_TYPE = 0;
+
+ private boolean mPinnedPartitionHeadersEnabled;
+ private boolean mHeaderVisibility[];
+
+ public PinnedHeaderListAdapter(Context context) {
+ super(context);
+ }
+
+ public PinnedHeaderListAdapter(Context context, int initialCapacity) {
+ super(context, initialCapacity);
+ }
+
+ public boolean getPinnedPartitionHeadersEnabled() {
+ return mPinnedPartitionHeadersEnabled;
+ }
+
+ public void setPinnedPartitionHeadersEnabled(boolean flag) {
+ this.mPinnedPartitionHeadersEnabled = flag;
+ }
+
+ @Override
+ public int getPinnedHeaderCount() {
+ if (mPinnedPartitionHeadersEnabled) {
+ return getPartitionCount();
+ } else {
+ return 0;
+ }
+ }
+
+ protected boolean isPinnedPartitionHeaderVisible(int partition) {
+ return getPinnedPartitionHeadersEnabled() && hasHeader(partition)
+ && !isPartitionEmpty(partition);
+ }
+
+ /**
+ * The default implementation creates the same type of view as a normal
+ * partition header.
+ */
+ @Override
+ public View getPinnedHeaderView(int partition, View convertView, ViewGroup parent) {
+ if (hasHeader(partition)) {
+ View view = null;
+ if (convertView != null) {
+ Integer headerType = (Integer)convertView.getTag();
+ if (headerType != null && headerType == PARTITION_HEADER_TYPE) {
+ view = convertView;
+ }
+ }
+ if (view == null) {
+ view = newHeaderView(getContext(), partition, null, parent);
+ view.setTag(PARTITION_HEADER_TYPE);
+ view.setFocusable(false);
+ view.setEnabled(false);
+ }
+ bindHeaderView(view, partition, getCursor(partition));
+ view.setLayoutDirection(parent.getLayoutDirection());
+ return view;
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public void configurePinnedHeaders(PinnedHeaderListView listView) {
+ if (!getPinnedPartitionHeadersEnabled()) {
+ return;
+ }
+
+ int size = getPartitionCount();
+ boolean unCached = false;
+ // Cache visibility bits, because we will need them several times later on
+ if (mHeaderVisibility == null || mHeaderVisibility.length != size) {
+ mHeaderVisibility = new boolean[size];
+ unCached = true;
+ }
+ for (int i = 0; i < size; i++) {
+ boolean visible = isPinnedPartitionHeaderVisible(i);
+ mHeaderVisibility[i] = visible;
+ if (!visible) {
+ listView.setHeaderInvisible(i, true);
+ }
+ }
+
+ int headerViewsCount = listView.getHeaderViewsCount();
+
+ // Starting at the top, find and pin headers for partitions preceding the visible one(s)
+ int maxTopHeader = -1;
+ int topHeaderHeight = 0;
+ for (int i = 0; i < size; i++) {
+ if (mHeaderVisibility[i]) {
+ int position = listView.getPositionAt(topHeaderHeight) - headerViewsCount;
+ int partition = getPartitionForPosition(position);
+ if (i > partition) {
+ break;
+ }
+
+ if (!unCached){
+ listView.setHeaderPinnedAtTop(i, topHeaderHeight, false);
+ topHeaderHeight += listView.getPinnedHeaderHeight(i);
+ maxTopHeader = i;
+ }
+
+ }
+ }
+
+ // Starting at the bottom, find and pin headers for partitions following the visible one(s)
+ /*int maxBottomHeader = size;
+ int bottomHeaderHeight = 0;
+ int listHeight = listView.getHeight();
+ for (int i = size; --i > maxTopHeader;) {
+ if (mHeaderVisibility[i]) {
+ int position = listView.getPositionAt(listHeight - bottomHeaderHeight)
+ - headerViewsCount;
+ if (position < 0) {
+ break;
+ }
+
+ int partition = getPartitionForPosition(position - 1);
+ if (partition == -1 || i <= partition) {
+ break;
+ }
+
+ int height = listView.getPinnedHeaderHeight(i);
+ bottomHeaderHeight += height;
+
+ listView.setHeaderPinnedAtBottom(i, listHeight - bottomHeaderHeight, false);
+ maxBottomHeader = i;
+ }
+ }
+
+ // Headers in between the top-pinned and bottom-pinned should be hidden
+ for (int i = maxTopHeader + 1; i < maxBottomHeader; i++) {
+ if (mHeaderVisibility[i]) {
+ listView.setHeaderInvisible(i, isPartitionEmpty(i));
+ }
+ }*/
+ }
+
+ @Override
+ public int getScrollPositionForHeader(int viewIndex) {
+ return getPositionForPartition(viewIndex);
+ }
+}
diff --git a/src/com/android/launcher3/list/PinnedHeaderListView.java b/src/com/android/launcher3/list/PinnedHeaderListView.java
new file mode 100644
index 000000000..30688fea3
--- /dev/null
+++ b/src/com/android/launcher3/list/PinnedHeaderListView.java
@@ -0,0 +1,565 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.list;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AbsListView;
+import android.widget.AbsListView.OnScrollListener;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemSelectedListener;
+import android.widget.ListAdapter;
+
+/**
+ * A ListView that maintains a header pinned at the top of the list. The
+ * pinned header can be pushed up and dissolved as needed.
+ */
+public class PinnedHeaderListView extends AutoScrollListView
+ implements OnScrollListener, OnItemSelectedListener {
+
+ /**
+ * Adapter interface. The list adapter must implement this interface.
+ */
+ public interface PinnedHeaderAdapter {
+
+ /**
+ * Returns the overall number of pinned headers, visible or not.
+ */
+ int getPinnedHeaderCount();
+
+ /**
+ * Creates or updates the pinned header view.
+ */
+ View getPinnedHeaderView(int viewIndex, View convertView, ViewGroup parent);
+
+ /**
+ * Configures the pinned headers to match the visible list items. The
+ * adapter should call {@link PinnedHeaderListView#setHeaderPinnedAtTop},
+ * {@link PinnedHeaderListView#setHeaderPinnedAtBottom},
+ * {@link PinnedHeaderListView#setFadingHeader} or
+ * {@link PinnedHeaderListView#setHeaderInvisible}, for each header that
+ * needs to change its position or visibility.
+ */
+ void configurePinnedHeaders(PinnedHeaderListView listView);
+
+ /**
+ * Returns the list position to scroll to if the pinned header is touched.
+ * Return -1 if the list does not need to be scrolled.
+ */
+ int getScrollPositionForHeader(int viewIndex);
+ }
+
+ private static final int MAX_ALPHA = 255;
+ private static final int TOP = 0;
+ private static final int BOTTOM = 1;
+ private static final int FADING = 2;
+
+ private static final int DEFAULT_ANIMATION_DURATION = 20;
+
+ private static final int DEFAULT_SMOOTH_SCROLL_DURATION = 100;
+
+ private static final class PinnedHeader {
+ View view;
+ boolean visible;
+ int y;
+ int height;
+ int alpha;
+ int state;
+
+ boolean animating;
+ boolean targetVisible;
+ int sourceY;
+ int targetY;
+ long targetTime;
+ }
+
+ private PinnedHeaderAdapter mAdapter;
+ private int mSize;
+ private PinnedHeader[] mHeaders;
+ private RectF mBounds = new RectF();
+ private Rect mClipRect = new Rect();
+ private OnScrollListener mOnScrollListener;
+ private OnItemSelectedListener mOnItemSelectedListener;
+ private int mScrollState;
+
+ private boolean mScrollToSectionOnHeaderTouch = false;
+ private boolean mHeaderTouched = false;
+
+ private int mAnimationDuration = DEFAULT_ANIMATION_DURATION;
+ private boolean mAnimating;
+ private long mAnimationTargetTime;
+ private int mHeaderPaddingStart;
+ private int mHeaderWidth;
+
+ public PinnedHeaderListView(Context context) {
+ this(context, null, android.R.attr.listViewStyle);
+ }
+
+ public PinnedHeaderListView(Context context, AttributeSet attrs) {
+ this(context, attrs, android.R.attr.listViewStyle);
+ }
+
+ public PinnedHeaderListView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ super.setOnScrollListener(this);
+ super.setOnItemSelectedListener(this);
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int l, int t, int r, int b) {
+ super.onLayout(changed, l, t, r, b);
+ mHeaderPaddingStart = getPaddingStart();
+ mHeaderWidth = r - l - mHeaderPaddingStart - getPaddingEnd();
+ }
+
+ public void setPinnedHeaderAnimationDuration(int duration) {
+ mAnimationDuration = duration;
+ }
+
+ @Override
+ public void setAdapter(ListAdapter adapter) {
+ mAdapter = (PinnedHeaderAdapter)adapter;
+ super.setAdapter(adapter);
+ }
+
+ @Override
+ public void setOnScrollListener(OnScrollListener onScrollListener) {
+ mOnScrollListener = onScrollListener;
+ super.setOnScrollListener(this);
+ }
+
+ @Override
+ public void setOnItemSelectedListener(OnItemSelectedListener listener) {
+ mOnItemSelectedListener = listener;
+ super.setOnItemSelectedListener(this);
+ }
+
+ public void setScrollToSectionOnHeaderTouch(boolean value) {
+ mScrollToSectionOnHeaderTouch = value;
+ }
+
+ @Override
+ public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
+ int totalItemCount) {
+ if (mAdapter != null) {
+ int count = mAdapter.getPinnedHeaderCount();
+ if (count != mSize) {
+ mSize = count;
+ if (mHeaders == null) {
+ mHeaders = new PinnedHeader[mSize];
+ } else if (mHeaders.length < mSize) {
+ PinnedHeader[] headers = mHeaders;
+ mHeaders = new PinnedHeader[mSize];
+ System.arraycopy(headers, 0, mHeaders, 0, headers.length);
+ }
+ }
+
+ for (int i = 0; i < mSize; i++) {
+ if (mHeaders[i] == null) {
+ mHeaders[i] = new PinnedHeader();
+ }
+ mHeaders[i].view = mAdapter.getPinnedHeaderView(i, mHeaders[i].view, this);
+ }
+
+ mAnimationTargetTime = System.currentTimeMillis() + mAnimationDuration;
+ mAdapter.configurePinnedHeaders(this);
+ invalidateIfAnimating();
+
+ }
+ if (mOnScrollListener != null) {
+ mOnScrollListener.onScroll(this, firstVisibleItem, visibleItemCount, totalItemCount);
+ }
+ }
+
+ @Override
+ protected float getTopFadingEdgeStrength() {
+ // Disable vertical fading at the top when the pinned header is present
+ return mSize > 0 ? 0 : super.getTopFadingEdgeStrength();
+ }
+
+ @Override
+ public void onScrollStateChanged(AbsListView view, int scrollState) {
+ mScrollState = scrollState;
+ if (mOnScrollListener != null) {
+ mOnScrollListener.onScrollStateChanged(this, scrollState);
+ }
+ }
+
+ /**
+ * Ensures that the selected item is positioned below the top-pinned headers
+ * and above the bottom-pinned ones.
+ */
+ @Override
+ public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
+ int height = getHeight();
+
+ int windowTop = 0;
+ int windowBottom = height;
+
+ for (int i = 0; i < mSize; i++) {
+ PinnedHeader header = mHeaders[i];
+ if (header.visible) {
+ if (header.state == TOP) {
+ windowTop = header.y + header.height;
+ } else if (header.state == BOTTOM) {
+ windowBottom = header.y;
+ break;
+ }
+ }
+ }
+
+ View selectedView = getSelectedView();
+ if (selectedView != null) {
+ if (selectedView.getTop() < windowTop) {
+ setSelectionFromTop(position, windowTop);
+ } else if (selectedView.getBottom() > windowBottom) {
+ setSelectionFromTop(position, windowBottom - selectedView.getHeight());
+ }
+ }
+
+ if (mOnItemSelectedListener != null) {
+ mOnItemSelectedListener.onItemSelected(parent, view, position, id);
+ }
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView<?> parent) {
+ if (mOnItemSelectedListener != null) {
+ mOnItemSelectedListener.onNothingSelected(parent);
+ }
+ }
+
+ public int getPinnedHeaderHeight(int viewIndex) {
+ ensurePinnedHeaderLayout(viewIndex);
+ return mHeaders[viewIndex].view.getHeight();
+ }
+
+ /**
+ * Set header to be pinned at the top.
+ *
+ * @param viewIndex index of the header view
+ * @param y is position of the header in pixels.
+ * @param animate true if the transition to the new coordinate should be animated
+ */
+ public void setHeaderPinnedAtTop(int viewIndex, int y, boolean animate) {
+ ensurePinnedHeaderLayout(viewIndex);
+ PinnedHeader header = mHeaders[viewIndex];
+ header.visible = true;
+ header.y = y;
+ header.state = TOP;
+
+ // TODO perhaps we should animate at the top as well
+ header.animating = false;
+ }
+
+ /**
+ * Set header to be pinned at the bottom.
+ *
+ * @param viewIndex index of the header view
+ * @param y is position of the header in pixels.
+ * @param animate true if the transition to the new coordinate should be animated
+ */
+ public void setHeaderPinnedAtBottom(int viewIndex, int y, boolean animate) {
+ ensurePinnedHeaderLayout(viewIndex);
+ PinnedHeader header = mHeaders[viewIndex];
+ header.state = BOTTOM;
+ if (header.animating) {
+ header.targetTime = mAnimationTargetTime;
+ header.sourceY = header.y;
+ header.targetY = y;
+ } else if (animate && (header.y != y || !header.visible)) {
+ if (header.visible) {
+ header.sourceY = header.y;
+ } else {
+ header.visible = true;
+ header.sourceY = y + header.height;
+ }
+ header.animating = true;
+ header.targetVisible = true;
+ header.targetTime = mAnimationTargetTime;
+ header.targetY = y;
+ } else {
+ header.visible = true;
+ header.y = y;
+ }
+ }
+
+ /**
+ * Set header to be pinned at the top of the first visible item.
+ *
+ * @param viewIndex index of the header view
+ * @param position is position of the header in pixels.
+ */
+ public void setFadingHeader(int viewIndex, int position, boolean fade) {
+ ensurePinnedHeaderLayout(viewIndex);
+
+ View child = getChildAt(position - getFirstVisiblePosition());
+ if (child == null) return;
+
+ PinnedHeader header = mHeaders[viewIndex];
+ header.visible = true;
+ header.state = FADING;
+ header.alpha = MAX_ALPHA;
+ header.animating = false;
+
+ int top = getTotalTopPinnedHeaderHeight();
+ header.y = top;
+ if (fade) {
+ int bottom = child.getBottom() - top;
+ int headerHeight = header.height;
+ if (bottom < headerHeight) {
+ int portion = bottom - headerHeight;
+ header.alpha = MAX_ALPHA * (headerHeight + portion) / headerHeight;
+ header.y = top + portion;
+ }
+ }
+ }
+
+ /**
+ * Makes header invisible.
+ *
+ * @param viewIndex index of the header view
+ * @param animate true if the transition to the new coordinate should be animated
+ */
+ public void setHeaderInvisible(int viewIndex, boolean animate) {
+ PinnedHeader header = mHeaders[viewIndex];
+ if (header.visible && (animate || header.animating) && header.state == BOTTOM) {
+ header.sourceY = header.y;
+ if (!header.animating) {
+ header.visible = true;
+ header.targetY = getBottom() + header.height;
+ }
+ header.animating = true;
+ header.targetTime = mAnimationTargetTime;
+ header.targetVisible = false;
+ } else {
+ header.visible = false;
+ }
+ }
+
+ private void ensurePinnedHeaderLayout(int viewIndex) {
+ View view = mHeaders[viewIndex].view;
+ if (view.isLayoutRequested()) {
+ int widthSpec = View.MeasureSpec.makeMeasureSpec(mHeaderWidth, View.MeasureSpec.EXACTLY);
+ int heightSpec;
+ ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
+ if (layoutParams != null && layoutParams.height > 0) {
+ heightSpec = View.MeasureSpec
+ .makeMeasureSpec(layoutParams.height, View.MeasureSpec.EXACTLY);
+ } else {
+ heightSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
+ }
+ view.measure(widthSpec, heightSpec);
+ int height = view.getMeasuredHeight();
+ mHeaders[viewIndex].height = height;
+ view.layout(0, 0, mHeaderWidth, height);
+ }
+ }
+
+ /**
+ * Returns the sum of heights of headers pinned to the top.
+ */
+ public int getTotalTopPinnedHeaderHeight() {
+ for (int i = mSize; --i >= 0;) {
+ PinnedHeader header = mHeaders[i];
+ if (header.visible && header.state == TOP) {
+ return header.y + header.height;
+ }
+ }
+ return 0;
+ }
+
+ /**
+ * Returns the list item position at the specified y coordinate.
+ */
+ public int getPositionAt(int y) {
+ do {
+ int position = pointToPosition(getPaddingLeft() + 1, y);
+ if (position != -1) {
+ return position;
+ }
+ // If position == -1, we must have hit a separator. Let's examine
+ // a nearby pixel
+ y--;
+ } while (y > 0);
+ return 0;
+ }
+
+ @Override
+ public boolean onInterceptTouchEvent(MotionEvent ev) {
+ mHeaderTouched = false;
+ if (super.onInterceptTouchEvent(ev)) {
+ return true;
+ }
+
+ if (mScrollState == SCROLL_STATE_IDLE) {
+ final int y = (int)ev.getY();
+ final int x = (int)ev.getX();
+ for (int i = mSize; --i >= 0;) {
+ PinnedHeader header = mHeaders[i];
+ // For RTL layouts, this also takes into account that the scrollbar is on the left
+ // side.
+ final int padding = getPaddingLeft();
+ if (header.visible && header.y <= y && header.y + header.height > y &&
+ x >= padding && padding + mHeaderWidth >= x) {
+ mHeaderTouched = true;
+ if (mScrollToSectionOnHeaderTouch &&
+ ev.getAction() == MotionEvent.ACTION_DOWN) {
+ return smoothScrollToPartition(i);
+ } else {
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent ev) {
+ if (mHeaderTouched) {
+ if (ev.getAction() == MotionEvent.ACTION_UP) {
+ mHeaderTouched = false;
+ }
+ return true;
+ }
+ return super.onTouchEvent(ev);
+ };
+
+ private boolean smoothScrollToPartition(int partition) {
+ final int position = mAdapter.getScrollPositionForHeader(partition);
+ if (position == -1) {
+ return false;
+ }
+
+ int offset = 0;
+ for (int i = 0; i < partition; i++) {
+ PinnedHeader header = mHeaders[i];
+ if (header.visible) {
+ offset += header.height;
+ }
+ }
+ smoothScrollToPositionFromTop(position + getHeaderViewsCount(), offset,
+ DEFAULT_SMOOTH_SCROLL_DURATION);
+ return true;
+ }
+
+ private void invalidateIfAnimating() {
+ mAnimating = false;
+ for (int i = 0; i < mSize; i++) {
+ if (mHeaders[i].animating) {
+ mAnimating = true;
+ invalidate();
+ return;
+ }
+ }
+ }
+
+ @Override
+ protected void dispatchDraw(Canvas canvas) {
+ long currentTime = mAnimating ? System.currentTimeMillis() : 0;
+
+ int top = 0;
+ int bottom = getBottom();
+ boolean hasVisibleHeaders = false;
+ for (int i = 0; i < mSize; i++) {
+ PinnedHeader header = mHeaders[i];
+ if (header.visible) {
+ hasVisibleHeaders = true;
+ if (header.state == BOTTOM && header.y < bottom) {
+ bottom = header.y;
+ } else if (header.state == TOP || header.state == FADING) {
+ int newTop = header.y + header.height;
+ if (newTop > top) {
+ top = newTop;
+ }
+ }
+ }
+ }
+
+ if (hasVisibleHeaders) {
+ canvas.save();
+ mClipRect.set(0, top, getWidth(), bottom);
+ canvas.clipRect(mClipRect);
+ }
+
+ super.dispatchDraw(canvas);
+
+ if (hasVisibleHeaders) {
+ canvas.restore();
+
+ // First draw top headers, then the bottom ones to handle the Z axis correctly
+ for (int i = mSize; --i >= 0;) {
+ PinnedHeader header = mHeaders[i];
+ if (header.visible && (header.state == TOP || header.state == FADING)) {
+ drawHeader(canvas, header, currentTime);
+ }
+ }
+
+ for (int i = 0; i < mSize; i++) {
+ PinnedHeader header = mHeaders[i];
+ if (header.visible && header.state == BOTTOM) {
+ drawHeader(canvas, header, currentTime);
+ }
+ }
+ }
+
+ invalidateIfAnimating();
+ }
+
+ private void drawHeader(Canvas canvas, PinnedHeader header, long currentTime) {
+ if (header.animating) {
+ int timeLeft = (int)(header.targetTime - currentTime);
+ if (timeLeft <= 0) {
+ header.y = header.targetY;
+ header.visible = header.targetVisible;
+ header.animating = false;
+ } else {
+ header.y = header.targetY + (header.sourceY - header.targetY) * timeLeft
+ / mAnimationDuration;
+ }
+ }
+ if (header.visible) {
+ View view = header.view;
+ int saveCount = canvas.save();
+ canvas.translate(isLayoutRtl() ?
+ getWidth() - mHeaderPaddingStart - mHeaderWidth : mHeaderPaddingStart,
+ header.y);
+ if (header.state == FADING) {
+ mBounds.set(0, 0, mHeaderWidth, view.getHeight());
+ canvas.saveLayerAlpha(mBounds, header.alpha, Canvas.ALL_SAVE_FLAG);
+ }
+ view.draw(canvas);
+ canvas.restoreToCount(saveCount);
+ }
+ }
+
+ /**
+ * Note: this is a reimplementation of View.isLayoutRtl() since that is currently hidden api.
+ */
+ public boolean isLayoutRtl() {
+ return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
+ }
+}
diff --git a/src/com/android/launcher3/list/SettingsPinnedHeaderAdapter.java b/src/com/android/launcher3/list/SettingsPinnedHeaderAdapter.java
new file mode 100644
index 000000000..805b51e37
--- /dev/null
+++ b/src/com/android/launcher3/list/SettingsPinnedHeaderAdapter.java
@@ -0,0 +1,373 @@
+package com.android.launcher3.list;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.database.Cursor;
+import android.graphics.Typeface;
+import android.util.TypedValue;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+import android.widget.Toast;
+import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.Launcher;
+import com.android.launcher3.OverviewSettingsPanel;
+import com.android.launcher3.AppsCustomizePagedView;
+import com.android.launcher3.R;
+
+import com.android.launcher3.settings.SettingsProvider;
+import android.view.View.OnClickListener;
+import android.content.SharedPreferences;
+
+public class SettingsPinnedHeaderAdapter extends PinnedHeaderListAdapter {
+ private Launcher mLauncher;
+ private Context mContext;
+
+ public SettingsPinnedHeaderAdapter(Context context) {
+ super(context);
+ mLauncher = (Launcher) context;
+ mContext = context;
+ }
+
+ private String[] mHeaders;
+ public int mPinnedHeaderCount;
+
+ public void setHeaders(String[] headers) {
+ this.mHeaders = headers;
+ }
+
+ @Override
+ protected View newHeaderView(Context context, int partition, Cursor cursor,
+ ViewGroup parent) {
+ LayoutInflater inflater = LayoutInflater.from(context);
+ return inflater.inflate(R.layout.settings_pane_list_header, null);
+ }
+
+ @Override
+ protected void bindHeaderView(View view, int partition, Cursor cursor) {
+ TextView textView = (TextView) view.findViewById(R.id.item_name);
+ textView.setText(mHeaders[partition]);
+ textView.setTypeface(textView.getTypeface(), Typeface.BOLD);
+
+ textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16);
+ }
+
+ @Override
+ protected View newView(Context context, int partition, Cursor cursor, int position,
+ ViewGroup parent) {
+ LayoutInflater inflater = LayoutInflater.from(context);
+ return inflater.inflate(R.layout.settings_pane_list_item, null);
+ }
+
+ @Override
+ protected void bindView(View v, int partition, Cursor cursor, int position) {
+ TextView text = (TextView)v.findViewById(R.id.item_name);
+ String title = cursor.getString(1);
+ text.setText(title);
+
+ Resources res = mLauncher.getResources();
+
+ if (title.equals(res
+ .getString(R.string.home_screen_search_text))) {
+ boolean current = mLauncher.shouldShowSearchBar();
+ String state = current ? res.getString(
+ R.string.setting_state_on) : res.getString(
+ R.string.setting_state_off);
+ ((TextView) v.findViewById(R.id.item_state)).setText(state);
+ } else if (title.equals(res
+ .getString(R.string.drawer_sorting_text))) {
+ updateDrawerSortSettingsItem(v);
+ } else if (title.equals(res
+ .getString(R.string.scroll_effect_text)) &&
+ partition == OverviewSettingsPanel.DRAWER_SETTINGS_POSITION) {
+ String state = mLauncher.getAppsCustomizeTransitionEffect();
+ state = mapEffectToValue(state);
+ ((TextView) v.findViewById(R.id.item_state)).setText(state);
+ } else if (title.equals(res
+ .getString(R.string.scroll_effect_text)) &&
+ partition == OverviewSettingsPanel.HOME_SETTINGS_POSITION) {
+ String state = mLauncher.getWorkspaceTransitionEffect();
+ state = mapEffectToValue(state);
+ ((TextView) v.findViewById(R.id.item_state)).setText(state);
+ } else if (title.equals(res
+ .getString(R.string.larger_icons_text))) {
+ boolean current = SettingsProvider
+ .getBoolean(
+ mContext,
+ SettingsProvider.SETTINGS_UI_GENERAL_ICONS_LARGE,
+ R.bool.preferences_interface_general_icons_large_default);
+ String state = current ? res.getString(
+ R.string.setting_state_on) : res.getString(
+ R.string.setting_state_off);
+ ((TextView) v.findViewById(R.id.item_state)).setText(state);
+ } else if (title.equals(res
+ .getString(R.string.icon_labels)) &&
+ partition == OverviewSettingsPanel.HOME_SETTINGS_POSITION) {
+ boolean current = mLauncher.shouldHideWorkspaceIconLables();
+ String state = current ? res.getString(
+ R.string.icon_labels_hide) : res.getString(
+ R.string.icon_labels_show);
+ ((TextView) v.findViewById(R.id.item_state)).setText(state);
+ } else if (title.equals(res
+ .getString(R.string.icon_labels)) &&
+ partition == OverviewSettingsPanel.DRAWER_SETTINGS_POSITION) {
+ boolean current = SettingsProvider
+ .getBoolean(
+ mContext,
+ SettingsProvider.SETTINGS_UI_DRAWER_HIDE_ICON_LABELS,
+ R.bool.preferences_interface_drawer_hide_icon_labels_default);
+ String state = current ? res.getString(
+ R.string.icon_labels_hide) : res.getString(
+ R.string.icon_labels_show);
+ ((TextView) v.findViewById(R.id.item_state)).setText(state);
+ } else if (title.equals(res
+ .getString(R.string.search_screen_left_text))) {
+ boolean current = SettingsProvider
+ .getBoolean(
+ mContext,
+ SettingsProvider.SETTINGS_UI_HOMESCREEN_SEARCH_SCREEN_LEFT,
+ R.bool.preferences_interface_homescreen_search_screen_left_default);
+ String state = current ? res.getString(
+ R.string.setting_state_on) : res.getString(
+ R.string.setting_state_off);
+ ((TextView) v.findViewById(R.id.item_state)).setText(state);
+ } else if (title.equals(res.getString(R.string.scrolling_wallpaper))) {
+ boolean current = SettingsProvider
+ .getBoolean(
+ mContext,
+ SettingsProvider.SETTINGS_UI_HOMESCREEN_SCROLLING_WALLPAPER_SCROLL,
+ R.bool.preferences_interface_homescreen_scrolling_wallpaper_scroll_default);
+ String state = current ? res.getString(
+ R.string.setting_state_on) : res.getString(
+ R.string.setting_state_off);
+ ((TextView) v.findViewById(R.id.item_state)).setText(state);
+ } else if (title.equals(res.getString(R.string.grid_size_text))) {
+ updateDynamicGridSizeSettingsItem(v);
+ } else {
+ ((TextView) v.findViewById(R.id.item_state)).setText("");
+ }
+
+ v.setTag(partition);
+ v.setOnClickListener(mSettingsItemListener);
+ }
+
+ @Override
+ public View getPinnedHeaderView(int viewIndex, View convertView, ViewGroup parent) {
+ LayoutInflater inflater = LayoutInflater.from(getContext());
+ View view = inflater.inflate(R.layout.settings_pane_list_header, parent, false);
+ view.setFocusable(false);
+ view.setEnabled(false);
+ bindHeaderView(view, viewIndex, null);
+ return view;
+ }
+
+ @Override
+ public int getPinnedHeaderCount() {
+ return mPinnedHeaderCount;
+ }
+
+ public void updateDrawerSortSettingsItem(View v) {
+ String state = "";
+ switch (mLauncher.getAppsCustomizeContentSortMode()) {
+ case Title:
+ state = mLauncher.getResources().getString(R.string.sort_mode_title);
+ break;
+ case LaunchCount:
+ state = mLauncher.getResources().getString(
+ R.string.sort_mode_launch_count);
+ break;
+ case InstallTime:
+ state = mLauncher.getResources().getString(
+ R.string.sort_mode_install_time);
+ break;
+ }
+ ((TextView) v.findViewById(R.id.item_state)).setText(state);
+ }
+
+ public void updateDynamicGridSizeSettingsItem(View v) {
+ DeviceProfile.GridSize gridSize = DeviceProfile.GridSize.getModeForValue(
+ SettingsProvider.getIntCustomDefault(mLauncher,
+ SettingsProvider.SETTINGS_UI_DYNAMIC_GRID_SIZE, 0));
+ String state = "";
+
+ switch (gridSize) {
+ case Comfortable:
+ state = mLauncher.getResources().getString(R.string.grid_size_comfortable);
+ break;
+ case Cozy:
+ state = mLauncher.getResources().getString(R.string.grid_size_cozy);
+ break;
+ case Condensed:
+ state = mLauncher.getResources().getString(R.string.grid_size_condensed);
+ break;
+ case Custom:
+ int rows = SettingsProvider.getIntCustomDefault(mLauncher,
+ SettingsProvider.SETTINGS_UI_HOMESCREEN_ROWS, 0);
+ int columns = SettingsProvider.getIntCustomDefault(mLauncher,
+ SettingsProvider.SETTINGS_UI_HOMESCREEN_COLUMNS, 0);
+ state = rows + " " + "\u00d7" + " " + columns;
+ break;
+ }
+ ((TextView) v.findViewById(R.id.item_state)).setText(state);
+ }
+
+ private String mapEffectToValue(String effect) {
+ final String[] titles = mLauncher.getResources().getStringArray(
+ R.array.transition_effect_entries);
+ final String[] values = mLauncher.getResources().getStringArray(
+ R.array.transition_effect_values);
+
+ int length = values.length;
+ for (int i = 0; i < length; i++) {
+ if (effect.equals(values[i])) {
+ return titles[i];
+ }
+ }
+ return "";
+ }
+
+ OnClickListener mSettingsItemListener = new OnClickListener() {
+
+ @Override
+ public void onClick(View v) {
+ // TODO Auto-generated method stub
+ String value = ((TextView) v.findViewById(R.id.item_name)).getText().toString();
+ Resources res = mLauncher.getResources();
+
+ // Handle toggles or launch pickers
+ if (value.equals(res
+ .getString(R.string.home_screen_search_text))) {
+ onSettingsBooleanChanged(
+ v,
+ SettingsProvider.SETTINGS_UI_HOMESCREEN_SEARCH,
+ R.bool.preferences_interface_homescreen_search_default);
+ mLauncher.updateDynamicGrid();
+ } else if (value.equals(res
+ .getString(R.string.drawer_sorting_text))) {
+ onClickTransitionEffectButton();
+ } else if (value.equals(res
+ .getString(R.string.scroll_effect_text)) &&
+ ((Integer)v.getTag() == OverviewSettingsPanel.DRAWER_SETTINGS_POSITION)) {
+ mLauncher.onClickTransitionEffectButton(v, true);
+ } else if (value.equals(res
+ .getString(R.string.scroll_effect_text)) &&
+ ((Integer)v.getTag() == OverviewSettingsPanel.HOME_SETTINGS_POSITION)) {
+ mLauncher.onClickTransitionEffectButton(v, false);
+ } else if (value.equals(res
+ .getString(R.string.larger_icons_text))) {
+ onSettingsBooleanChanged(
+ v,
+ SettingsProvider.SETTINGS_UI_GENERAL_ICONS_LARGE,
+ R.bool.preferences_interface_general_icons_large_default);
+ mLauncher.updateDynamicGrid();
+ } else if (value.equals(res
+ .getString(R.string.icon_labels)) &&
+ ((Integer)v.getTag() == OverviewSettingsPanel.HOME_SETTINGS_POSITION)) {
+ onIconLabelsBooleanChanged(
+ v,
+ SettingsProvider.SETTINGS_UI_HOMESCREEN_HIDE_ICON_LABELS,
+ R.bool.preferences_interface_homescreen_hide_icon_labels_default);
+ mLauncher.updateDynamicGrid();
+ } else if (value.equals(res
+ .getString(R.string.icon_labels)) &&
+ ((Integer)v.getTag() == OverviewSettingsPanel.DRAWER_SETTINGS_POSITION)) {
+ onIconLabelsBooleanChanged(
+ v,
+ SettingsProvider.SETTINGS_UI_DRAWER_HIDE_ICON_LABELS,
+ R.bool.preferences_interface_drawer_hide_icon_labels_default);
+ mLauncher.updateDynamicGrid();
+ } else if (value.equals(res.getString(R.string.protected_app_settings))) {
+ Intent intent = new Intent();
+ intent.setClassName(OverviewSettingsPanel.ANDROID_SETTINGS,
+ OverviewSettingsPanel.ANDROID_PROTECTED_APPS);
+ mLauncher.startActivity(intent);
+ } else if (value.equals(res.getString(R.string.protected_app_settings))) {
+
+ } else if (value.equals(res
+ .getString(R.string.scrolling_wallpaper))) {
+ onSettingsBooleanChanged(
+ v,
+ SettingsProvider.SETTINGS_UI_HOMESCREEN_SCROLLING_WALLPAPER_SCROLL,
+ R.bool.preferences_interface_homescreen_scrolling_wallpaper_scroll_default);
+ mLauncher.updateDynamicGrid();
+ } else if (value.equals(res
+ .getString(R.string.search_screen_left_text)) &&
+ ((Integer)v.getTag() == OverviewSettingsPanel.HOME_SETTINGS_POSITION)) {
+
+ boolean current = SettingsProvider.getBoolean(mContext,
+ SettingsProvider.SETTINGS_UI_HOMESCREEN_SEARCH_SCREEN_LEFT,
+ R.bool.preferences_interface_homescreen_search_screen_left_default);
+
+ // If GEL integration is not supported, do not allow the user to turn it on.
+ if(!current && !mLauncher.isGelIntegrationSupported()) {
+ Toast.makeText(mLauncher.getApplicationContext(),
+ res.getString(R.string.search_screen_left_unsupported_toast),
+ Toast.LENGTH_SHORT).show();
+ } else {
+ onSettingsBooleanChanged(
+ v,
+ SettingsProvider.SETTINGS_UI_HOMESCREEN_SEARCH_SCREEN_LEFT,
+ R.bool.preferences_interface_homescreen_search_screen_left_default);
+ mLauncher.updateDynamicGrid();
+ }
+ } else if (value.equals(res
+ .getString(R.string.grid_size_text))) {
+ mLauncher.onClickDynamicGridSizeButton();
+ }
+
+ View defaultHome = mLauncher.findViewById(R.id.default_home_screen_panel);
+ defaultHome.setVisibility(getCursor(0).getCount() > 1 ? View.VISIBLE : View.GONE);
+ }
+ };
+
+ private void onSettingsBooleanChanged(View v, String key, int res) {
+ boolean current = SettingsProvider.getBoolean(
+ mContext, key, res);
+
+ // Set new state
+ SharedPreferences sharedPref = SettingsProvider
+ .get(mContext);
+ sharedPref.edit().putBoolean(key, !current).commit();
+ sharedPref.edit()
+ .putBoolean(SettingsProvider.SETTINGS_CHANGED, true)
+ .commit();
+
+ String state = current ? mLauncher.getResources().getString(
+ R.string.setting_state_off) : mLauncher.getResources().getString(
+ R.string.setting_state_on);
+ ((TextView) v.findViewById(R.id.item_state)).setText(state);
+ }
+
+ private void onIconLabelsBooleanChanged(View v, String key, int res) {
+ boolean current = SettingsProvider.getBoolean(
+ mContext, key, res);
+
+ // Set new state
+ SharedPreferences sharedPref = SettingsProvider
+ .get(mContext);
+ sharedPref.edit().putBoolean(key, !current).commit();
+ sharedPref.edit()
+ .putBoolean(SettingsProvider.SETTINGS_CHANGED, true)
+ .commit();
+
+ String state = current ? mLauncher.getResources().getString(
+ R.string.icon_labels_show) : mLauncher.getResources().getString(
+ R.string.icon_labels_hide);
+ ((TextView) v.findViewById(R.id.item_state)).setText(state);
+ }
+
+ private void onClickTransitionEffectButton() {
+ int sort = SettingsProvider.getIntCustomDefault(mLauncher,
+ SettingsProvider.SETTINGS_UI_DRAWER_SORT_MODE, 0);
+
+ sort = (sort + 1) % AppsCustomizePagedView.SortMode.values().length;
+ mLauncher.getAppsCustomizeContent().setSortMode(
+ AppsCustomizePagedView.SortMode.getModeForValue(sort));
+
+ SettingsProvider.putInt(mLauncher, SettingsProvider.SETTINGS_UI_DRAWER_SORT_MODE, sort);
+
+ notifyDataSetChanged();
+ }
+}
diff --git a/src/com/android/launcher3/settings/FontStylePreference.java b/src/com/android/launcher3/settings/FontStylePreference.java
deleted file mode 100644
index 50df4b280..000000000
--- a/src/com/android/launcher3/settings/FontStylePreference.java
+++ /dev/null
@@ -1,142 +0,0 @@
-package com.android.launcher3.settings;
-
-import android.app.AlertDialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.graphics.Typeface;
-import android.preference.ListPreference;
-import android.text.TextUtils;
-import android.util.AttributeSet;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.*;
-import com.android.launcher3.R;
-
-import java.util.Arrays;
-import java.util.List;
-
-public class FontStylePreference extends ListPreference {
- private String mValue;
- public int mClickedDialogEntryIndex;
- private boolean mValueSet;
-
- public FontStylePreference(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
- if (getEntries() == null || getEntryValues() == null) {
- throw new IllegalStateException(
- "ListPreference requires an entries array and an entryValues array.");
- }
-
- mClickedDialogEntryIndex = getValueIndex();
- builder.setSingleChoiceItems(new FontStyleAdapter(getContext()), mClickedDialogEntryIndex,
- new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- mClickedDialogEntryIndex = which;
-
- /*
- * Clicking on an item simulates the positive button
- * click, and dismisses the dialog.
- */
- FontStylePreference.this.onClick(dialog, DialogInterface.BUTTON_POSITIVE);
- dialog.dismiss();
- }
- });
-
- /*
- * The typical interaction for list-based dialogs is to have
- * click-on-an-item dismiss the dialog instead of the user having to
- * press 'Ok'.
- */
- builder.setPositiveButton(null, null);
- }
-
- @Override
- protected void onDialogClosed(boolean positiveResult) {
- super.onDialogClosed(positiveResult);
-
- if (positiveResult && mClickedDialogEntryIndex >= 0 && getEntryValues() != null) {
- String value = getEntryValues()[mClickedDialogEntryIndex].toString();
- if (callChangeListener(value)) {
- setValue(value);
- }
- }
- }
-
- @Override
- protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
- setValue(restoreValue ? getPersistedString(mValue) : (String) defaultValue);
- }
-
- /**
- * Sets the value of the key. This should be one of the entries in
- * {@link #getEntryValues()}.
- *
- * @param value The value to set for the key.
- */
- @Override
- public void setValue(String value) {
- // Always persist/notify the first time.
- final boolean changed = !TextUtils.equals(mValue, value);
- if (changed || !mValueSet) {
- mValue = value;
- mValueSet = true;
- persistString(value);
- if (changed) {
- notifyChanged();
- }
- }
- }
-
- /**
- * Returns the value of the key. This should be one of the entries in
- * {@link #getEntryValues()}.
- *
- * @return The value of the key.
- */
- @Override
- public String getValue() {
- return mValue;
- }
-
- private int getValueIndex() {
- return findIndexOfValue(mValue);
- }
-
- private class FontStyleAdapter extends ArrayAdapter<CharSequence> {
- private LayoutInflater mInflater;
- private List<CharSequence> mEntries;
- private List<CharSequence> mValues;
-
- public FontStyleAdapter(Context context) {
- super(context, -1, getEntryValues());
-
- mInflater = LayoutInflater.from(context);
- mEntries = Arrays.asList(getEntries());
- mValues = Arrays.asList(getEntryValues());
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- CheckedTextView textView;
-
- if (convertView == null) {
- textView = (CheckedTextView) mInflater.inflate(R.layout.list_item_checkable, parent, false);
- } else {
- textView = (CheckedTextView) convertView;
- }
-
- if (textView != null) {
- textView.setText(mEntries.get(position));
- textView.setTag(mValues.get(position));
- textView.setTypeface(Typeface.create((String) mValues.get(position), Typeface.NORMAL));
- }
-
- return textView;
- }
- }
-}
diff --git a/src/com/android/launcher3/settings/HiddenAppsActivity.java b/src/com/android/launcher3/settings/HiddenAppsActivity.java
deleted file mode 100644
index 57ea7bc36..000000000
--- a/src/com/android/launcher3/settings/HiddenAppsActivity.java
+++ /dev/null
@@ -1,302 +0,0 @@
-package com.android.launcher3.settings;
-
-import android.app.ListActivity;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.graphics.drawable.Drawable;
-import android.os.AsyncTask;
-import android.os.Bundle;
-import android.util.Log;
-import android.util.SparseBooleanArray;
-import android.view.LayoutInflater;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.Window;
-import android.widget.ArrayAdapter;
-import android.widget.ImageView;
-import android.widget.ListView;
-import android.widget.TextView;
-
-import com.android.launcher3.R;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.concurrent.ConcurrentHashMap;
-
-public class HiddenAppsActivity extends ListActivity {
-
- private boolean mSaved;
-
- private static final int MENU_RESET = 0;
-
- private PackageManager mPackageManager;
-
- private AppsAdapter mAppsAdapter;
-
- protected void onCreate(Bundle savedInstanceState) {
- requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
- super.onCreate(savedInstanceState);
-
- setTitle(R.string.hidden_apps_title);
- setContentView(R.layout.hidden_apps_list);
-
- getActionBar().setDisplayHomeAsUpEnabled(true);
- setProgressBarIndeterminateVisibility(true);
- setProgressBarIndeterminate(true);
-
- mPackageManager = getPackageManager();
- mAppsAdapter = new AppsAdapter(this, R.layout.hidden_apps_list_item);
- mAppsAdapter.setNotifyOnChange(true);
-
- setListAdapter(mAppsAdapter);
-
- AsyncTask<Void, Void, List<AppEntry>> refreshAppsTask = new AsyncTask<Void, Void, List<AppEntry>>() {
-
- @Override
- protected void onPostExecute(List<AppEntry> apps) {
- mAppsAdapter.clear();
- mAppsAdapter.addAll(apps);
- restoreCheckedItems();
- setProgressBarIndeterminateVisibility(false);
- setProgressBarIndeterminate(false);
- }
-
- @Override
- protected List<AppEntry> doInBackground(Void... params) {
- return refreshApps();
- }
- };
- refreshAppsTask.execute(null, null, null);
- }
-
- @Override
- public void onPause() {
- super.onPause();
- save();
- }
-
- private void save() {
- if (mSaved) {
- return;
- }
- String string = "";
-
- SparseBooleanArray checked = getListView().getCheckedItemPositions();
-
- AppsAdapter listAdapter = (AppsAdapter) getListAdapter();
- for (int i = 0; i < checked.size(); i++) {
- if (checked.valueAt(i)) {
- AppEntry app = listAdapter.getItem(checked.keyAt(i));
- if (!string.isEmpty())
- string += "|";
- string += app.componentName.flattenToString();
- }
- }
-
- SharedPreferences.Editor editor = SettingsProvider.get(this).edit();
- editor.putString(SettingsProvider.SETTINGS_UI_DRAWER_HIDDEN_APPS, string);
- editor.putBoolean(SettingsProvider.SETTINGS_CHANGED, true);
- editor.apply();
-
- mSaved = true;
- }
-
- private void restoreCheckedItems() {
- List<ComponentName> apps = new ArrayList<ComponentName>();
- String[] flattened = SettingsProvider.getStringCustomDefault(this,
- SettingsProvider.SETTINGS_UI_DRAWER_HIDDEN_APPS, "").split("\\|");
- for (String flat : flattened) {
- apps.add(ComponentName.unflattenFromString(flat));
- }
-
- AppsAdapter listAdapter = (AppsAdapter) getListAdapter();
-
- for (int i = 0; i < listAdapter.getCount(); i++) {
- AppEntry info = listAdapter.getItem(i);
- if (apps.contains(info.componentName)) {
- getListView().setItemChecked(i, true);
- }
- }
-
- mSaved = true;
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- menu.add(0, MENU_RESET, 0, R.string.menu_hidden_apps_delete)
- .setShowAsActionFlags(MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
-
- return true;
- }
-
- private void reset() {
- for (int i = 0; i < getListView().getCount(); i++) {
- getListView().setItemChecked(i, false);
- }
-
- mSaved = false;
- }
-
- private List<AppEntry> refreshApps() {
- Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
- mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
- List<ResolveInfo> apps = mPackageManager.queryIntentActivities(mainIntent, 0);
- Collections.sort(apps, new ResolveInfo.DisplayNameComparator(mPackageManager));
- List<AppEntry> appEntries = new ArrayList<AppEntry>(apps.size());
- for (ResolveInfo info : apps) {
- appEntries.add(new AppEntry(info));
- }
- return appEntries;
- }
-
- @Override
- public boolean onMenuItemSelected(int featureId, MenuItem item) {
- if (item.getItemId() == android.R.id.home) {
- finish();
- return true;
- } else if (item.getItemId() == MENU_RESET) {
- reset();
- return true;
- }
- return super.onMenuItemSelected(featureId, item);
- }
-
- @Override
- protected void onListItemClick(ListView l, View v, int position, long id) {
- mSaved = false;
- }
-
- private final class AppEntry {
-
- public final ComponentName componentName;
- public final String title;
-
- public AppEntry(ResolveInfo info) {
- componentName = new ComponentName(info.activityInfo.packageName, info.activityInfo.name);
- title = info.loadLabel(mPackageManager).toString();
- }
- }
-
- /**
- * App view holder used to reuse the views inside the list.
- */
- private static class AppViewHolder {
- public final TextView title;
- public final ImageView icon;
-
- public AppViewHolder(View parentView) {
- icon = (ImageView) parentView.findViewById(R.id.icon);
- title = (TextView) parentView.findViewById(R.id.title);
- }
- }
-
- public class AppsAdapter extends ArrayAdapter<AppEntry> {
-
- private final LayoutInflater mInflator;
-
- private ConcurrentHashMap<String, Drawable> mIcons;
- private Drawable mDefaultImg;
- private List<AppEntry> mApps;
-
- public AppsAdapter(Context context, int textViewResourceId) {
- super(context, textViewResourceId);
-
- mApps = new ArrayList<AppEntry>();
-
- mInflator = LayoutInflater.from(context);
-
- // set the default icon till the actual app icon is loaded in async
- // task
- mDefaultImg = context.getResources().getDrawable(android.R.mipmap.sym_def_app_icon);
- mIcons = new ConcurrentHashMap<String, Drawable>();
- }
-
- @Override
- public View getView(final int position, View convertView, ViewGroup parent) {
- AppViewHolder viewHolder;
-
- if (convertView == null) {
- convertView = mInflator.inflate(R.layout.hidden_apps_list_item, parent, false);
- viewHolder = new AppViewHolder(convertView);
- convertView.setTag(viewHolder);
- } else {
- viewHolder = (AppViewHolder) convertView.getTag();
- }
-
- AppEntry app = getItem(position);
-
- viewHolder.title.setText(app.title);
-
- Drawable icon = mIcons.get(app.componentName.getPackageName());
- viewHolder.icon.setImageDrawable(icon != null ? icon : mDefaultImg);
-
- return convertView;
- }
-
- @Override
- public boolean hasStableIds() {
- return true;
- }
-
- @Override
- public void notifyDataSetChanged() {
- super.notifyDataSetChanged();
- // If we have new items, we have to load their icons
- // If items were deleted, remove them from our mApps
- List<AppEntry> newApps = new ArrayList<AppEntry>(getCount());
- List<AppEntry> oldApps = new ArrayList<AppEntry>(getCount());
- for (int i = 0; i < getCount(); i++) {
- AppEntry app = getItem(i);
- if (mApps.contains(app)) {
- oldApps.add(app);
- } else {
- newApps.add(app);
- }
- }
-
- if (newApps.size() > 0) {
- new LoadIconsTask().execute(newApps.toArray(new AppEntry[] {}));
- newApps.addAll(oldApps);
- mApps = newApps;
- } else {
- mApps = oldApps;
- }
- }
-
- /**
- * An asynchronous task to load the icons of the installed applications.
- */
- private class LoadIconsTask extends AsyncTask<AppEntry, Void, Void> {
- @Override
- protected Void doInBackground(AppEntry... apps) {
- for (AppEntry app : apps) {
- try {
- if (mIcons.containsKey(app.componentName.getPackageName())) {
- continue;
- }
- Drawable icon = mPackageManager.getApplicationIcon(app.componentName
- .getPackageName());
- mIcons.put(app.componentName.getPackageName(), icon);
- publishProgress();
- } catch (PackageManager.NameNotFoundException e) {
- // ignored; app will show up with default image
- }
- }
-
- return null;
- }
-
- @Override
- protected void onProgressUpdate(Void... progress) {
- notifyDataSetChanged();
- }
- }
- }
-}
diff --git a/src/com/android/launcher3/settings/SettingsActivity.java b/src/com/android/launcher3/settings/SettingsActivity.java
deleted file mode 100644
index dbbf95f52..000000000
--- a/src/com/android/launcher3/settings/SettingsActivity.java
+++ /dev/null
@@ -1,274 +0,0 @@
-/*
- * Copyright (C) 2013 The CyanogenMod Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3.settings;
-
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.os.Bundle;
-import android.preference.*;
-import android.text.TextUtils;
-import android.view.MenuItem;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ArrayAdapter;
-import android.widget.ImageView;
-import android.widget.ListAdapter;
-import android.widget.TextView;
-import com.android.launcher3.R;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class SettingsActivity extends PreferenceActivity
- implements SharedPreferences.OnSharedPreferenceChangeListener {
- private static final String TAG = "Launcher3.SettingsActivity";
-
- private SharedPreferences mSettings;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- mSettings = getSharedPreferences(SettingsProvider.SETTINGS_KEY,
- Context.MODE_PRIVATE);
-
- getActionBar().setDisplayHomeAsUpEnabled(true);
- }
-
- @Override
- public SharedPreferences getSharedPreferences(String name, int mode) {
- return super.getSharedPreferences(SettingsProvider.SETTINGS_KEY,
- Context.MODE_PRIVATE);
- }
-
- @Override
- protected void onResume() {
- super.onResume();
- mSettings.registerOnSharedPreferenceChangeListener(this);
- }
-
- @Override
- protected void onPause() {
- super.onPause();
- mSettings.unregisterOnSharedPreferenceChangeListener(this);
- }
-
- @Override
- public boolean isValidFragment(String fragmentName) {
- return true;
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- onBackPressed();
- finish();
- return true;
- default:
- break;
- }
- return super.onOptionsItemSelected(item);
- }
-
- @Override
- public void onBuildHeaders(List<Header> target) {
- loadHeadersFromResource(R.xml.preferences_headers, target);
- updateHeaders(target);
- }
-
- private void updateHeaders(List<Header> headers) {
- int i = 0;
- while (i < headers.size()) {
- Header header = headers.get(i);
-
- // Version preference
- if (header.id == R.id.preferences_application_version) {
- header.title = getString(R.string.cm_application_name) + " " + getString(R.string.application_version);
- }
-
- // Increment if not removed
- if (headers.get(i) == header) {
- i++;
- }
- }
- }
-
- @Override
- public void setListAdapter(ListAdapter adapter) {
- if (adapter == null) {
- super.setListAdapter(null);
- } else {
- List<Header> headers = getHeadersFromAdapter(adapter);
- super.setListAdapter(new HeaderAdapter(this, headers));
- }
- }
-
- @Override
- public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
- SharedPreferences.Editor editor = mSettings.edit();
- editor.putBoolean(SettingsProvider.SETTINGS_CHANGED, true);
- editor.commit();
- }
-
- private List<Header> getHeadersFromAdapter(ListAdapter adapter) {
- List<Header> headers = new ArrayList<Header>();
- int count = adapter.getCount();
- for (int i = 0; i < count; i++) {
- headers.add((Header)adapter.getItem(i));
- }
- return headers;
- }
-
- public static class HomescreenFragment extends PreferenceFragment {
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- addPreferencesFromResource(R.xml.preferences_homescreen);
- }
- }
-
- public static class GeneralFragment extends PreferenceFragment {
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- addPreferencesFromResource(R.xml.preferences_general);
- }
- }
-
- public static class DrawerFragment extends PreferenceFragment {
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- addPreferencesFromResource(R.xml.preferences_drawer);
- }
- }
-
- private static class HeaderAdapter extends ArrayAdapter<Header> {
- private static final int HEADER_TYPE_NORMAL = 0;
- private static final int HEADER_TYPE_CATEGORY = 1;
-
- private static final int HEADER_TYPE_COUNT = HEADER_TYPE_CATEGORY + 1;
-
- private static class HeaderViewHolder {
- ImageView icon;
- TextView title;
- TextView summary;
- }
-
- private LayoutInflater mInflater;
-
- static int getHeaderType(Header header) {
- if (header.id == R.id.preferences_application_section) {
- return HEADER_TYPE_CATEGORY;
- } else {
- return HEADER_TYPE_NORMAL;
- }
- }
-
- @Override
- public int getItemViewType(int position) {
- Header header = getItem(position);
- return getHeaderType(header);
- }
-
- @Override
- public boolean areAllItemsEnabled() {
- return false; // because of categories
- }
-
- @Override
- public boolean isEnabled(int position) {
- return getItemViewType(position) != HEADER_TYPE_CATEGORY;
- }
-
- @Override
- public int getViewTypeCount() {
- return HEADER_TYPE_COUNT;
- }
-
- @Override
- public boolean hasStableIds() {
- return true;
- }
-
- public HeaderAdapter(Context context, List<Header> objects) {
- super(context, 0, objects);
-
- mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- HeaderViewHolder holder;
- Header header = getItem(position);
- int headerType = getHeaderType(header);
- View view = null;
-
- if (convertView == null) {
- holder = new HeaderViewHolder();
- switch (headerType) {
- case HEADER_TYPE_CATEGORY:
- view = new TextView(getContext(), null,
- android.R.attr.listSeparatorTextViewStyle);
- holder.title = (TextView) view;
- break;
-
- case HEADER_TYPE_NORMAL:
- view = mInflater.inflate(
- R.layout.preference_header_item, parent,
- false);
- holder.icon = (ImageView) view.findViewById(android.R.id.icon);
- holder.title = (TextView)
- view.findViewById(android.R.id.title);
- holder.summary = (TextView)
- view.findViewById(android.R.id.summary);
- break;
- }
- view.setTag(holder);
- } else {
- view = convertView;
- holder = (HeaderViewHolder) view.getTag();
- }
-
- // All view fields must be updated every time, because the view may be recycled
- switch (headerType) {
- case HEADER_TYPE_CATEGORY:
- holder.title.setText(header.getTitle(getContext().getResources()));
- break;
-
- case HEADER_TYPE_NORMAL:
- holder.icon.setImageResource(header.iconRes);
- holder.title.setText(header.getTitle(getContext().getResources()));
- CharSequence summary = header.getSummary(getContext().getResources());
- if (!TextUtils.isEmpty(summary)) {
- holder.summary.setVisibility(View.VISIBLE);
- holder.summary.setText(summary);
- } else {
- holder.summary.setVisibility(View.GONE);
- }
- break;
- }
-
- return view;
- }
- }
-}
diff --git a/src/com/android/launcher3/settings/SettingsProvider.java b/src/com/android/launcher3/settings/SettingsProvider.java
index abf4e1b67..32329ab83 100644
--- a/src/com/android/launcher3/settings/SettingsProvider.java
+++ b/src/com/android/launcher3/settings/SettingsProvider.java
@@ -26,21 +26,24 @@ public final class SettingsProvider {
public static final String SETTINGS_UI_HOMESCREEN_DEFAULT_SCREEN_ID = "ui_homescreen_default_screen_id";
public static final String SETTINGS_UI_HOMESCREEN_SEARCH = "ui_homescreen_search";
+ public static final String SETTINGS_UI_HOMESCREEN_SEARCH_SCREEN_LEFT = "ui_homescreen_search_screen_left";
public static final String SETTINGS_UI_HOMESCREEN_HIDE_ICON_LABELS = "ui_homescreen_general_hide_icon_labels";
public static final String SETTINGS_UI_HOMESCREEN_SCROLLING_TRANSITION_EFFECT = "ui_homescreen_scrolling_transition_effect";
public static final String SETTINGS_UI_HOMESCREEN_SCROLLING_WALLPAPER_SCROLL = "ui_homescreen_scrolling_wallpaper_scroll";
public static final String SETTINGS_UI_HOMESCREEN_SCROLLING_PAGE_OUTLINES = "ui_homescreen_scrolling_page_outlines";
public static final String SETTINGS_UI_HOMESCREEN_SCROLLING_FADE_ADJACENT = "ui_homescreen_scrolling_fade_adjacent";
+ public static final String SETTINGS_UI_DYNAMIC_GRID_SIZE = "ui_dynamic_grid_size";
+ public static final String SETTINGS_UI_HOMESCREEN_ROWS = "ui_homescreen_rows";
+ public static final String SETTINGS_UI_HOMESCREEN_COLUMNS = "ui_homescreen_columns";
public static final String SETTINGS_UI_DRAWER_SCROLLING_TRANSITION_EFFECT = "ui_drawer_scrolling_transition_effect";
public static final String SETTINGS_UI_DRAWER_SCROLLING_FADE_ADJACENT = "ui_drawer_scrolling_fade_adjacent";
- public static final String SETTINGS_UI_DRAWER_HIDDEN_APPS = "ui_drawer_hidden_apps";
public static final String SETTINGS_UI_DRAWER_REMOVE_HIDDEN_APPS_SHORTCUTS = "ui_drawer_remove_hidden_apps_shortcuts";
public static final String SETTINGS_UI_DRAWER_REMOVE_HIDDEN_APPS_WIDGETS = "ui_drawer_remove_hidden_apps_widgets";
public static final String SETTINGS_UI_DRAWER_HIDE_ICON_LABELS = "ui_drawer_hide_icon_labels";
public static final String SETTINGS_UI_GENERAL_ICONS_LARGE = "ui_general_icons_large";
- public static final String SETTINGS_UI_GENERAL_ICONS_TEXT_FONT_FAMILY = "ui_general_icons_text_font";
- public static final String SETTINGS_UI_GENERAL_ICONS_TEXT_FONT_STYLE = "ui_general_icons_text_font_style";
- public static final String SETTINGS_UI_GENERAL_ICONS_ICON_PACK = "ui_general_iconpack";
+ public static final String SETTINGS_UI_DRAWER_SORT_MODE = "ui_drawer_sort_mode";
+
+ public static final String SETTINGS_HOME_LAST_APP = "home_last_app";
public static SharedPreferences get(Context context) {
return context.getSharedPreferences(SETTINGS_KEY, Context.MODE_MULTI_PROCESS);
@@ -81,4 +84,8 @@ public final class SettingsProvider {
public static void putString(Context context, String key, String value) {
get(context).edit().putString(key, value).commit();
}
+
+ public static void putInt(Context context, String key, int value) {
+ get(context).edit().putInt(key, value).commit();
+ }
}
diff --git a/src/com/android/photos/BitmapRegionTileSource.java b/src/com/android/photos/BitmapRegionTileSource.java
deleted file mode 100644
index 4d1a84ed7..000000000
--- a/src/com/android/photos/BitmapRegionTileSource.java
+++ /dev/null
@@ -1,288 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.photos;
-
-import android.annotation.TargetApi;
-import android.content.Context;
-import android.content.res.AssetManager;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.Bitmap.Config;
-import android.graphics.BitmapFactory;
-import android.graphics.BitmapRegionDecoder;
-import android.graphics.Canvas;
-import android.graphics.Rect;
-import android.net.Uri;
-import android.os.Build;
-import android.os.Build.VERSION_CODES;
-import android.util.Log;
-
-import com.android.gallery3d.common.BitmapUtils;
-import com.android.gallery3d.glrenderer.BasicTexture;
-import com.android.gallery3d.glrenderer.BitmapTexture;
-import com.android.photos.views.TiledImageRenderer;
-
-import java.io.BufferedInputStream;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * A {@link com.android.photos.views.TiledImageRenderer.TileSource} using
- * {@link BitmapRegionDecoder} to wrap a local file
- */
-@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1)
-public class BitmapRegionTileSource implements TiledImageRenderer.TileSource {
-
- private static final String TAG = "BitmapRegionTileSource";
-
- private static final boolean REUSE_BITMAP =
- Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN;
- private static final int GL_SIZE_LIMIT = 2048;
- // This must be no larger than half the size of the GL_SIZE_LIMIT
- // due to decodePreview being allowed to be up to 2x the size of the target
- private static final int MAX_PREVIEW_SIZE = 1024;
-
- BitmapRegionDecoder mDecoder;
- int mWidth;
- int mHeight;
- int mTileSize;
- private BasicTexture mPreview;
- private final int mRotation;
-
- // For use only by getTile
- private Rect mWantRegion = new Rect();
- private Rect mOverlapRegion = new Rect();
- private BitmapFactory.Options mOptions;
- private Canvas mCanvas;
-
- public BitmapRegionTileSource(Context context, String path, int previewSize, int rotation) {
- this(null, context, path, null, 0, previewSize, rotation, false);
- }
-
- public BitmapRegionTileSource(Resources res, Context context, String path, int previewSize, int rotation, boolean assetPath) {
- this(res, context, path, null, 0, previewSize, rotation, assetPath);
- }
-
- public BitmapRegionTileSource(Context context, Uri uri, int previewSize, int rotation) {
- this(null, context, null, uri, 0, previewSize, rotation, false);
- }
-
- public BitmapRegionTileSource(Resources res,
- Context context, int resId, int previewSize, int rotation) {
- this(res, context, null, null, resId, previewSize, rotation, false);
- }
-
- private BitmapRegionTileSource(Resources res,
- Context context, String path, Uri uri, int resId, int previewSize, int rotation, boolean assetPath) {
- mTileSize = TiledImageRenderer.suggestedTileSize(context);
- mRotation = rotation;
- try {
- if (path != null && !assetPath) {
- mDecoder = BitmapRegionDecoder.newInstance(path, true);
- } else if (path != null && res != null && assetPath) {
- AssetManager am = res.getAssets();
- String[] pathImages = am.list(path);
- if (pathImages == null || pathImages.length == 0) {
- throw new IOException("did not find any images in path: " + path);
- }
- InputStream is = am.open(path + File.separator + pathImages[0]);
- BufferedInputStream bis = new BufferedInputStream(is);
- mDecoder = BitmapRegionDecoder.newInstance(bis, true);
- } else if (uri != null) {
- InputStream is = context.getContentResolver().openInputStream(uri);
- BufferedInputStream bis = new BufferedInputStream(is);
- mDecoder = BitmapRegionDecoder.newInstance(bis, true);
- } else {
- InputStream is = res.openRawResource(resId);
- BufferedInputStream bis = new BufferedInputStream(is);
- mDecoder = BitmapRegionDecoder.newInstance(bis, true);
- }
- mWidth = mDecoder.getWidth();
- mHeight = mDecoder.getHeight();
- } catch (IOException e) {
- Log.w("BitmapRegionTileSource", "ctor failed", e);
- }
- mOptions = new BitmapFactory.Options();
- mOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;
- mOptions.inPreferQualityOverSpeed = true;
- mOptions.inTempStorage = new byte[16 * 1024];
- if (previewSize != 0) {
- previewSize = Math.min(previewSize, MAX_PREVIEW_SIZE);
- // Although this is the same size as the Bitmap that is likely already
- // loaded, the lifecycle is different and interactions are on a different
- // thread. Thus to simplify, this source will decode its own bitmap.
- Bitmap preview = decodePreview(res, context, path, uri, resId, previewSize, assetPath);
- if (preview.getWidth() <= GL_SIZE_LIMIT && preview.getHeight() <= GL_SIZE_LIMIT) {
- mPreview = new BitmapTexture(preview);
- } else {
- Log.w(TAG, String.format(
- "Failed to create preview of apropriate size! "
- + " in: %dx%d, out: %dx%d",
- mWidth, mHeight,
- preview.getWidth(), preview.getHeight()));
- }
- }
- }
-
- @Override
- public int getTileSize() {
- return mTileSize;
- }
-
- @Override
- public int getImageWidth() {
- return mWidth;
- }
-
- @Override
- public int getImageHeight() {
- return mHeight;
- }
-
- @Override
- public BasicTexture getPreview() {
- return mPreview;
- }
-
- @Override
- public int getRotation() {
- return mRotation;
- }
-
- @Override
- public Bitmap getTile(int level, int x, int y, Bitmap bitmap) {
- int tileSize = getTileSize();
- if (!REUSE_BITMAP) {
- return getTileWithoutReusingBitmap(level, x, y, tileSize);
- }
-
- int t = tileSize << level;
- mWantRegion.set(x, y, x + t, y + t);
-
- if (bitmap == null) {
- bitmap = Bitmap.createBitmap(tileSize, tileSize, Bitmap.Config.ARGB_8888);
- }
-
- mOptions.inSampleSize = (1 << level);
- mOptions.inBitmap = bitmap;
-
- try {
- bitmap = mDecoder.decodeRegion(mWantRegion, mOptions);
- } finally {
- if (mOptions.inBitmap != bitmap && mOptions.inBitmap != null) {
- mOptions.inBitmap = null;
- }
- }
-
- if (bitmap == null) {
- Log.w("BitmapRegionTileSource", "fail in decoding region");
- }
- return bitmap;
- }
-
- private Bitmap getTileWithoutReusingBitmap(
- int level, int x, int y, int tileSize) {
-
- int t = tileSize << level;
- mWantRegion.set(x, y, x + t, y + t);
-
- mOverlapRegion.set(0, 0, mWidth, mHeight);
-
- mOptions.inSampleSize = (1 << level);
- Bitmap bitmap = mDecoder.decodeRegion(mOverlapRegion, mOptions);
-
- if (bitmap == null) {
- Log.w(TAG, "fail in decoding region");
- }
-
- if (mWantRegion.equals(mOverlapRegion)) {
- return bitmap;
- }
-
- Bitmap result = Bitmap.createBitmap(tileSize, tileSize, Config.ARGB_8888);
- if (mCanvas == null) {
- mCanvas = new Canvas();
- }
- mCanvas.setBitmap(result);
- mCanvas.drawBitmap(bitmap,
- (mOverlapRegion.left - mWantRegion.left) >> level,
- (mOverlapRegion.top - mWantRegion.top) >> level, null);
- mCanvas.setBitmap(null);
- return result;
- }
-
- /**
- * Note that the returned bitmap may have a long edge that's longer
- * than the targetSize, but it will always be less than 2x the targetSize
- */
- private Bitmap decodePreview(
- Resources res, Context context, String file, Uri uri, int resId, int targetSize, boolean assetPath) {
- float scale = (float) targetSize / Math.max(mWidth, mHeight);
- mOptions.inSampleSize = BitmapUtils.computeSampleSizeLarger(scale);
- mOptions.inJustDecodeBounds = false;
-
- Bitmap result = null;
- if (file != null && res != null && assetPath) {
- try {
- AssetManager am = res.getAssets();
- String[] pathImages = am.list(file);
- if (pathImages == null || pathImages.length == 0) {
- throw new IOException("did not find any images in path: " + file);
- }
- InputStream is = am.open(file + File.separator + pathImages[0]);
- BufferedInputStream bis = new BufferedInputStream(is);
- result = BitmapFactory.decodeStream(bis, null, mOptions);
- } catch (IOException e) {
- Log.w("BitmapRegionTileSource", "getting preview failed", e);
- }
- } else if (file != null) {
- result = BitmapFactory.decodeFile(file, mOptions);
- } else if (uri != null) {
- try {
- InputStream is = context.getContentResolver().openInputStream(uri);
- BufferedInputStream bis = new BufferedInputStream(is);
- result = BitmapFactory.decodeStream(bis, null, mOptions);
- } catch (IOException e) {
- Log.w("BitmapRegionTileSource", "getting preview failed", e);
- }
- } else {
- result = BitmapFactory.decodeResource(res, resId, mOptions);
- }
- if (result == null) {
- return null;
- }
-
- // We need to resize down if the decoder does not support inSampleSize
- // or didn't support the specified inSampleSize (some decoders only do powers of 2)
- scale = (float) targetSize / (float) (Math.max(result.getWidth(), result.getHeight()));
-
- if (scale <= 0.5) {
- result = BitmapUtils.resizeBitmapByScale(result, scale, true);
- }
- return ensureGLCompatibleBitmap(result);
- }
-
- private static Bitmap ensureGLCompatibleBitmap(Bitmap bitmap) {
- if (bitmap == null || bitmap.getConfig() != null) {
- return bitmap;
- }
- Bitmap newBitmap = bitmap.copy(Config.ARGB_8888, false);
- bitmap.recycle();
- return newBitmap;
- }
-}
diff --git a/src/org/cyanogenmod/trebuchet/TrebuchetLauncher.java b/src/org/cyanogenmod/trebuchet/TrebuchetLauncher.java
new file mode 100644
index 000000000..3c5e6a70b
--- /dev/null
+++ b/src/org/cyanogenmod/trebuchet/TrebuchetLauncher.java
@@ -0,0 +1,331 @@
+/*
+ * Copyright (C) 2014 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.cyanogenmod.trebuchet;
+
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.res.Resources;
+import android.graphics.Color;
+import android.graphics.PorterDuff;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.util.Log;
+import android.util.SparseArray;
+import android.view.animation.AccelerateInterpolator;
+import android.widget.ImageView;
+
+import com.android.launcher.home.Home;
+import com.android.launcher3.Launcher;
+import com.android.launcher3.R;
+
+import org.cyanogenmod.trebuchet.home.HomeUtils;
+import org.cyanogenmod.trebuchet.home.HomeWrapper;
+
+import java.lang.Override;
+
+public class TrebuchetLauncher extends Launcher {
+
+ private static final String TAG = "TrebuchetLauncher";
+
+ private static final boolean DEBUG = false;
+ private static final float MIN_PROGRESS = 0;
+ private static final float MAX_PROGRESS = 1;
+
+
+ private static class HomeAppStub {
+ private final int mUid;
+ private final ComponentName mComponentName;
+ private final HomeWrapper mInstance;
+
+ private HomeAppStub(int uid, ComponentName componentName, Context context)
+ throws SecurityException, ReflectiveOperationException {
+ super();
+ mUid = uid;
+ mComponentName = componentName;
+
+ // Load a new instance of the Home app
+ ClassLoader classloader = context.getClassLoader();
+ Class<?> homeInterface = classloader.loadClass(Home.class.getName());
+ Class<?> homeClazz = classloader.loadClass(mComponentName.getClassName());
+ mInstance = new HomeWrapper(context, homeInterface, homeClazz.newInstance());
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((mComponentName == null) ? 0 : mComponentName.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ HomeAppStub other = (HomeAppStub) obj;
+ if (mComponentName == null) {
+ if (other.mComponentName != null)
+ return false;
+ } else if (!mComponentName.equals(other.mComponentName))
+ return false;
+ return true;
+ }
+ }
+
+ private BroadcastReceiver mPackageReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ // Obtain the current instance or a new one if the current instance not exists
+ boolean invalidate = false;
+ String action = intent.getAction();
+ if (action.equals(Intent.ACTION_PACKAGE_CHANGED) ||
+ action.equals(Intent.ACTION_PACKAGE_REPLACED) ||
+ action.equals(Intent.ACTION_PACKAGE_RESTARTED)) {
+ if (mCurrentHomeApp != null && intent.getIntExtra(Intent.EXTRA_UID, -1)
+ == mCurrentHomeApp.mUid) {
+ // The current Home app has changed or restarted. Invalidate the current
+ // one to be sure we will get all the new changes (if any)
+ if (DEBUG) Log.d(TAG, "Home package has changed. Invalidate layout.");
+ invalidate = true;
+ }
+ }
+ obtainCurrentHomeAppStubLocked(invalidate);
+ }
+ };
+
+ private CustomContentCallbacks mCustomContentCallbacks = new CustomContentCallbacks() {
+ @Override
+ public void onShow() {
+ if (mCurrentHomeApp != null) {
+ mCurrentHomeApp.mInstance.onShow();
+ }
+ }
+
+ @Override
+ public void onScrollProgressChanged(float progress) {
+ updateQsbBarColorState(progress);
+ if (mCurrentHomeApp != null) {
+ mCurrentHomeApp.mInstance.onScrollProgressChanged(progress);
+ }
+ }
+
+ @Override
+ public void onHide() {
+ if (mCurrentHomeApp != null) {
+ mCurrentHomeApp.mInstance.onHide();
+ }
+ }
+ };
+
+ private HomeAppStub mCurrentHomeApp;
+ private AccelerateInterpolator mQSBAlphaInterpolator;
+
+ private QSBScroller mQsbScroller;
+ private int mQsbInitialAlphaState;
+ private int mQsbEndAlphaState;
+ private int mQsbButtonsEndColorFilter;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mQSBAlphaInterpolator = new AccelerateInterpolator();
+
+ // Set QsbBar color state
+ final Resources res = getResources();
+ mQsbInitialAlphaState = res.getInteger(R.integer.qsb_initial_alpha_state);
+ mQsbEndAlphaState = res.getInteger(R.integer.qsb_end_alpha_state);
+ mQsbButtonsEndColorFilter = res.getInteger(R.integer.qsb_buttons_end_colorfilter);
+ updateQsbBarColorState(MIN_PROGRESS);
+
+ // Obtain the user-defined Home app or a valid one
+ obtainCurrentHomeAppStubLocked(true);
+
+ // Register this class to listen for new/deleted packages
+ IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
+ filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+ filter.addAction(Intent.ACTION_PACKAGE_FULLY_REMOVED);
+ filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
+ filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
+ filter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
+ filter.addDataScheme("package");
+ registerReceiver(mPackageReceiver, filter);
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+
+ // Unregister services
+ unregisterReceiver(mPackageReceiver);
+ }
+
+ @Override
+ protected void onResume() {
+ if (mCurrentHomeApp != null) {
+ mCurrentHomeApp.mInstance.onResume();
+ }
+ super.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ if (mCurrentHomeApp != null) {
+ mCurrentHomeApp.mInstance.onPause();
+ }
+ super.onPause();
+ }
+
+ @Override
+ protected boolean hasCustomContentToLeft() {
+ return mCurrentHomeApp != null && super.hasCustomContentToLeft();
+ }
+
+ @Override
+ protected void invalidateHasCustomContentToLeft() {
+ invalidateHomeStub();
+ super.invalidateHasCustomContentToLeft();
+ }
+
+ @Override
+ protected void populateCustomContentContainer() {
+ if (mCurrentHomeApp != null) {
+ mQsbScroller = addToCustomContentPage(mCurrentHomeApp.mInstance.createCustomView(),
+ mCustomContentCallbacks, mCurrentHomeApp.mInstance.getName());
+ }
+ }
+
+ @Override
+ protected boolean hasCustomSearchSupport() {
+ return hasCustomContentToLeft() && mCurrentHomeApp.mInstance.isOperationSupported(
+ Home.FLAG_OP_CUSTOM_SEARCH);
+ }
+
+ @Override
+ protected void requestSearch(int mode) {
+ if (!hasCustomSearchSupport()) {
+ return;
+ }
+ mCurrentHomeApp.mInstance.onRequestSearch(mode);
+ }
+
+ private synchronized void obtainCurrentHomeAppStubLocked(boolean invalidate) {
+ if (DEBUG) Log.d(TAG, "obtainCurrentHomeAppStubLocked called (" + invalidate + ")");
+
+ SparseArray<ComponentName> packages = HomeUtils.getInstalledHomePackages(this);
+ if (!invalidate && mCurrentHomeApp != null &&
+ packages.get(mCurrentHomeApp.mUid) != null) {
+ // We still have a valid Home app
+ return;
+ }
+
+ // We don't have a valid Home app, so we need to destroy the current the custom content
+ destroyHomeStub();
+
+ // Return the default valid home app
+ int size = packages.size();
+ for (int i = 0; i < size; i++) {
+ int key = packages.keyAt(i);
+ ComponentName pkg = packages.get(key);
+ String qualifiedPkg = pkg.toShortString();
+ Context ctx = HomeUtils.createNewHomePackageContext(this, pkg);
+ if (ctx == null) {
+ // We failed to create a valid context. Will try with the next package
+ continue;
+ }
+ try {
+ mCurrentHomeApp = new HomeAppStub(key, pkg, ctx);
+ } catch (ReflectiveOperationException ex) {
+ if (!DEBUG) {
+ Log.w(TAG, "Cannot instantiate home package: " + qualifiedPkg + ". Ignored.");
+ } else {
+ Log.w(TAG, "Cannot instantiate home package: " + qualifiedPkg +
+ ". Ignored.", ex);
+ }
+ } catch (SecurityException ex) {
+ if (!DEBUG) {
+ Log.w(TAG, "Home package is insecure: " + qualifiedPkg + ". Ignored.");
+ } else {
+ Log.w(TAG, "Home package is insecure: " + qualifiedPkg + ". Ignored.", ex);
+ }
+ }
+
+ // Notify home app that is going to be used
+ if (mCurrentHomeApp != null) {
+ mCurrentHomeApp.mInstance.onStart();
+ }
+ }
+
+ // Don't have a valid package. Anyway notify the launcher that custom content has changed
+ invalidateHasCustomContentToLeft();
+ }
+
+ private void invalidateHomeStub() {
+ if (mCurrentHomeApp != null) {
+ mCurrentHomeApp.mInstance.onInvalidate();
+ if (DEBUG) Log.d(TAG, "Home package " + mCurrentHomeApp.mComponentName.toShortString()
+ + " was invalidated.");
+ }
+ }
+
+ private void destroyHomeStub() {
+ if (mCurrentHomeApp != null) {
+ mCurrentHomeApp.mInstance.onInvalidate();
+ mCurrentHomeApp.mInstance.onDestroy();
+ if (DEBUG) Log.d(TAG, "Home package " + mCurrentHomeApp.mComponentName.toShortString()
+ + " was destroyed.");
+ }
+ mQsbScroller = null;
+ mCurrentHomeApp = null;
+ }
+
+ private void updateQsbBarColorState(float progress) {
+ if (getQsbBar() != null) {
+ float interpolation = mQSBAlphaInterpolator.getInterpolation(progress);
+
+ // Background alpha
+ int alphaInterpolation = (int)(mQsbInitialAlphaState +
+ (interpolation * (mQsbEndAlphaState - mQsbInitialAlphaState)));
+ Drawable background = getQsbBar().getBackground();
+ if (background != null) {
+ background.setAlpha(alphaInterpolation);
+ }
+
+ // Buttons color filter
+ int colorInterpolation = (int)(255 - (interpolation * mQsbButtonsEndColorFilter));
+ int color = Color.rgb(colorInterpolation, colorInterpolation,colorInterpolation);
+ ImageView voiceButton = getQsbBarVoiceButton();
+ if (voiceButton != null) {
+ if (progress > 0) {
+ voiceButton.setColorFilter(color, PorterDuff.Mode.SRC_IN);
+ }
+ }
+ ImageView searchButton = getQsbBarSearchButton();
+ if (searchButton != null) {
+ if (progress > 0) {
+ searchButton.setColorFilter(color, PorterDuff.Mode.SRC_IN);
+ }
+ }
+ }
+ }
+}
diff --git a/src/org/cyanogenmod/trebuchet/home/HomeUtils.java b/src/org/cyanogenmod/trebuchet/home/HomeUtils.java
new file mode 100644
index 000000000..63bf5ff60
--- /dev/null
+++ b/src/org/cyanogenmod/trebuchet/home/HomeUtils.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2014 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.cyanogenmod.trebuchet.home;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.os.Bundle;
+import android.util.Log;
+import android.util.SparseArray;
+
+import com.android.launcher.home.Home;
+
+import java.util.List;
+
+public class HomeUtils {
+
+ private static final String TAG = "HomeUtils";
+
+ // FIXME For now for security reason we will only support known Home apps
+ private static final String[] WELL_KNOWN_HOME_APP_PKGS =
+ {
+ "org.cyanogenmod.launcher.home"
+ };
+
+
+ public static final SparseArray<ComponentName> getInstalledHomePackages(Context context) {
+ // A Home app should:
+ // - declare the use of Home.PERMISSION_HOME_APP permission.
+ // - define the home stub class through the Home.METADATA_HOME_STUB metadata
+ SparseArray<ComponentName> installedHomePackages = new SparseArray<ComponentName>();
+
+ PackageManager packageManager = context.getPackageManager();
+
+ List<PackageInfo> installedPackages = packageManager.getInstalledPackages(
+ PackageManager.GET_PERMISSIONS);
+ for (PackageInfo pkg : installedPackages) {
+ boolean hasHomeAppPermission = false;
+ if (pkg.requestedPermissions != null) {
+ for (String perm : pkg.requestedPermissions) {
+ if (perm.equals(Home.PERMISSION_HOME_APP)) {
+ hasHomeAppPermission = true;
+ break;
+ }
+ }
+ }
+ if (hasHomeAppPermission) {
+ try {
+ ApplicationInfo appInfo = packageManager.getApplicationInfo(pkg.packageName,
+ PackageManager.GET_META_DATA);
+ Bundle metadata = appInfo.metaData;
+ if (metadata != null && metadata.containsKey(Home.METADATA_HOME_STUB)) {
+ String homeStub = metadata.getString(Home.METADATA_HOME_STUB);
+ installedHomePackages.put(appInfo.uid,
+ new ComponentName(pkg.packageName, homeStub));
+ }
+ } catch (NameNotFoundException ex) {
+ // Ignored. The package doesn't exists ¿?
+ }
+ }
+ }
+
+ // FIXME For now we only support known Home apps. Remove this checks when
+ // Trebuchet allows Home apps through the full Home Host Protocol
+ if (installedHomePackages.size() > 0) {
+ for (String pkg : WELL_KNOWN_HOME_APP_PKGS) {
+ int i = installedHomePackages.size() - 1;
+ boolean isWellKnownPkg = false;
+ for (; i >= 0; i--) {
+ int key = installedHomePackages.keyAt(i);
+ if (installedHomePackages.get(key).getPackageName().equals(pkg)) {
+ isWellKnownPkg = true;
+ break;
+ }
+ }
+ if (!isWellKnownPkg) {
+ installedHomePackages.removeAt(i);
+ }
+ }
+ }
+
+ return installedHomePackages;
+ }
+
+ public static Context createNewHomePackageContext(Context ctx, ComponentName pkg) {
+ // Create a new context package for the current user
+ try {
+ return ctx.createPackageContext(pkg.getPackageName(),
+ Context.CONTEXT_IGNORE_SECURITY | Context.CONTEXT_INCLUDE_CODE);
+ } catch (NameNotFoundException ex) {
+ Log.e(TAG, "Failed to load a home package context. Package not found.", ex);
+ }
+ return null;
+ }
+}
diff --git a/src/org/cyanogenmod/trebuchet/home/HomeWrapper.java b/src/org/cyanogenmod/trebuchet/home/HomeWrapper.java
new file mode 100644
index 000000000..df8b6cae6
--- /dev/null
+++ b/src/org/cyanogenmod/trebuchet/home/HomeWrapper.java
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2014 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.cyanogenmod.trebuchet.home;
+
+import android.content.Context;
+import android.util.Base64;
+import android.util.SparseArray;
+import android.view.View;
+
+import com.android.launcher.home.Home;
+
+import java.lang.reflect.Method;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+public class HomeWrapper {
+
+ private static final int M_ID_ONSTART = 0;
+ private static final int M_ID_ONDESTROY = 1;
+ private static final int M_ID_ONRESUME = 2;
+ private static final int M_ID_ONPAUSE = 3;
+ private static final int M_ID_ONSHOW = 4;
+ private static final int M_ID_ONSCROLLPROGRESSCHANGED = 5;
+ private static final int M_ID_ONHIDE = 6;
+ private static final int M_ID_ONINVALIDATE = 7;
+ private static final int M_ID_ONREQUESTSEARCH = 8;
+ private static final int M_ID_CREATECUSTOMVIEW = 9;
+ private static final int M_ID_GETNAME = 10;
+ private static final int M_ID_GETNOTIFICATIONFLAGS = 11;
+ private static final int M_ID_GETOPERATIONFLAGS = 12;
+ private static final int M_LAST_ID = M_ID_GETOPERATIONFLAGS + 1;
+
+ private final Context mContext;
+ private final Class<?> mClass;
+ private final Object mInstance;
+
+ private final SparseArray<Method> cachedMethods;
+
+ private final int mNotificationFlags;
+ private final int mOperationFlags;
+
+ public HomeWrapper(Context context, Class<?> cls, Object instance) throws SecurityException {
+ super();
+ mContext = context;
+ mClass = cls;
+ mInstance = instance;
+ cachedMethods = new SparseArray<Method>(M_LAST_ID);
+
+ final String sha1 = createDigest(cls);
+ if (!sha1.equals(Home.SIGNATURE)) {
+ throw new SecurityException("The remote Home app doesn't implement " +
+ "the current Home Host Protocol. Signature: " + sha1);
+ }
+
+ // Obtain the app flags
+ mNotificationFlags = getNotificationFlags();
+ mOperationFlags = getOperationFlags();
+ }
+
+ /** @see Home#onStart(Context) **/
+ public void onStart() {
+ invokeVoidContextMethod(M_ID_ONSTART, "onStart");
+ }
+
+ /** @see Home#onDestroy(Context) **/
+ public void onDestroy() {
+ invokeVoidContextMethod(M_ID_ONDESTROY, "onDestroy");
+ }
+
+ /** @see Home#onResume(Context) **/
+ public void onResume() {
+ if (!isNotificationSupported(Home.FLAG_NOTIFY_ON_RESUME)) {
+ return;
+ }
+ invokeVoidContextMethod(M_ID_ONRESUME, "onResume");
+ }
+
+ /** @see Home#onPause(Context) **/
+ public void onPause() {
+ if (!isNotificationSupported(Home.FLAG_NOTIFY_ON_PAUSE)) {
+ return;
+ }
+ invokeVoidContextMethod(M_ID_ONPAUSE, "onPause");
+ }
+
+ /** @see Home#onShow(Context) **/
+ public void onShow() {
+ if (!isNotificationSupported(Home.FLAG_NOTIFY_ON_SHOW)) {
+ return;
+ }
+ invokeVoidContextMethod(M_ID_ONSHOW, "onShow");
+ }
+
+ /** @see Home#onScrollProgressChanged(Context, float) **/
+ public void onScrollProgressChanged(float progress) {
+ if (!isNotificationSupported(Home.FLAG_NOTIFY_ON_SCROLL_PROGRESS_CHANGED)) {
+ return;
+ }
+ try {
+ Method method = cachedMethods.get(M_ID_ONSCROLLPROGRESSCHANGED);
+ if (method == null) {
+ method = mClass.getMethod("onScrollProgressChanged", Context.class, float.class);
+ }
+ method.invoke(mInstance, mContext, progress);
+ } catch (ReflectiveOperationException ex) {
+ throw new SecurityException(ex);
+ }
+ }
+
+ /** @see Home#onHide(Context) **/
+ public void onHide() {
+ if (!isNotificationSupported(Home.FLAG_NOTIFY_ON_HIDE)) {
+ return;
+ }
+ invokeVoidContextMethod(M_ID_ONHIDE, "onHide");
+ }
+
+ /** @see Home#onInvalidate(Context) **/
+ public void onInvalidate() {
+ invokeVoidContextMethod(M_ID_ONINVALIDATE, "onInvalidate");
+ }
+
+ /**
+ * @see Home#onRequestSearch(Context, int)
+ */
+ public void onRequestSearch(int mode) {
+ try {
+ Method method = cachedMethods.get(M_ID_ONREQUESTSEARCH);
+ if (method == null) {
+ method = mClass.getMethod("onRequestSearch", Context.class, int.class);
+ }
+ method.invoke(mInstance, mContext, mode);
+ } catch (ReflectiveOperationException ex) {
+ throw new SecurityException(ex);
+ }
+ }
+
+ /** @see Home#createCustomView(Context) **/
+ public View createCustomView() {
+ try {
+ Method method = cachedMethods.get(M_ID_CREATECUSTOMVIEW);
+ if (method == null) {
+ method = mClass.getMethod("createCustomView", Context.class);
+ }
+ return (View) method.invoke(mInstance, mContext);
+ } catch (ReflectiveOperationException ex) {
+ throw new SecurityException(ex);
+ }
+ }
+
+ /** @see Home#getName(Context) **/
+ public String getName() {
+ try {
+ Method method = cachedMethods.get(M_ID_GETNAME);
+ if (method == null) {
+ method = mClass.getMethod("getName", Context.class);
+ }
+ return (String) method.invoke(mInstance, mContext);
+ } catch (ReflectiveOperationException ex) {
+ throw new SecurityException(ex);
+ }
+ }
+
+ /** @see Home#getNotificationFlags() **/
+ private int getNotificationFlags() {
+ try {
+ Method method = cachedMethods.get(M_ID_GETNOTIFICATIONFLAGS);
+ if (method == null) {
+ method = mClass.getMethod("getNotificationFlags");
+ }
+ return (Integer) method.invoke(mInstance);
+ } catch (ReflectiveOperationException ex) {
+ return 0;
+ }
+ }
+
+ /** @see Home#getOperationFlags() **/
+ private int getOperationFlags() {
+ try {
+ Method method = cachedMethods.get(M_ID_GETOPERATIONFLAGS);
+ if (method == null) {
+ method = mClass.getMethod("getOperationFlags");
+ }
+ return (Integer) method.invoke(mInstance);
+ } catch (ReflectiveOperationException ex) {
+ return 0;
+ }
+ }
+
+ private void invokeVoidContextMethod(int methodId, String methodName) {
+ try {
+ Method method = cachedMethods.get(methodId);
+ if (method == null) {
+ method = mClass.getMethod(methodName, Context.class);
+ }
+ method.invoke(mInstance, mContext);
+ } catch (ReflectiveOperationException ex) {
+ throw new SecurityException(ex);
+ }
+ }
+
+ private final String createDigest(Class<?> cls) throws SecurityException {
+ try {
+ MessageDigest digest = MessageDigest.getInstance("SHA1");
+ Method[] methods = cls.getDeclaredMethods();
+ for (Method method : methods) {
+ digest.update(method.toString().getBytes());
+ }
+ return new String(Base64.encode(digest.digest(), Base64.NO_WRAP));
+ } catch (NoSuchAlgorithmException ex) {
+ throw new SecurityException(ex);
+ }
+ }
+
+ public boolean isNotificationSupported(int flag) {
+ return (mNotificationFlags & flag) == flag;
+ }
+
+ public boolean isOperationSupported(int flag) {
+ return (mOperationFlags & flag) == flag;
+ }
+}
diff --git a/update_gallery_files.py b/update_gallery_files.py
index ef4e8c933..738d225eb 100644
--- a/update_gallery_files.py
+++ b/update_gallery_files.py
@@ -49,6 +49,6 @@ for file_path in files.split():
dir = os.path.dirname(file_path)
if file_path.find('exif') != -1 or file_path.find('common') != -1:
file_path = 'gallerycommon/' + file_path
- cmd = 'cp %s/%s %s/' % (gallery_dir, file_path, dir)
+ cmd = 'cp %s/%s WallpaperPicker/%s/' % (gallery_dir, file_path, dir)
print cmd
os.system(cmd)
diff --git a/update_system_wallpaper_cropper.py b/update_system_wallpaper_cropper.py
new file mode 100644
index 000000000..44cbcc967
--- /dev/null
+++ b/update_system_wallpaper_cropper.py
@@ -0,0 +1,58 @@
+# This script is used to push the most up-to-date files from
+# Launcher into frameworks' version of the WallpaperCropActivity
+# (and supporting files)
+# The framework versions have some small modifications that are
+# necessary so do this with care
+import os
+import sys
+src_dir = "WallpaperPicker/src/"
+files = """
+src/android/util/Pools.java
+com/android/gallery3d/util/IntArray.java
+com/android/gallery3d/common/Utils.java
+com/android/gallery3d/exif/ByteBufferInputStream.java
+com/android/gallery3d/exif/CountedDataInputStream.java
+com/android/gallery3d/exif/ExifData.java
+com/android/gallery3d/exif/ExifInterface.java
+com/android/gallery3d/exif/ExifInvalidFormatException.java
+com/android/gallery3d/exif/ExifModifier.java
+com/android/gallery3d/exif/ExifOutputStream.java
+com/android/gallery3d/exif/ExifParser.java
+com/android/gallery3d/exif/ExifReader.java
+com/android/gallery3d/exif/ExifTag.java
+com/android/gallery3d/exif/IfdData.java
+com/android/gallery3d/exif/IfdId.java
+com/android/gallery3d/exif/JpegHeader.java
+com/android/gallery3d/exif/OrderedDataOutputStream.java
+com/android/gallery3d/exif/Rational.java
+com/android/gallery3d/glrenderer/BasicTexture.java
+com/android/gallery3d/glrenderer/BitmapTexture.java
+com/android/gallery3d/glrenderer/GLCanvas.java
+com/android/gallery3d/glrenderer/GLES20Canvas.java
+com/android/gallery3d/glrenderer/GLES20IdImpl.java
+com/android/gallery3d/glrenderer/GLId.java
+com/android/gallery3d/glrenderer/GLPaint.java
+com/android/gallery3d/glrenderer/RawTexture.java
+com/android/gallery3d/glrenderer/Texture.java
+com/android/gallery3d/glrenderer/UploadedTexture.java
+com/android/photos/BitmapRegionTileSource.java
+com/android/photos/views/BlockingGLTextureView.java
+com/android/photos/views/TiledImageRenderer.java
+com/android/photos/views/TiledImageView.java
+com/android/gallery3d/common/BitmapUtils.java
+com/android/launcher3/CropView.java
+com/android/launcher3/WallpaperCropActivity.java
+"""
+
+if len(sys.argv) != 2:
+ print "Usage: python update_sytem_wallpaper_cropper.py <framework_dir>"
+ exit()
+framework_dir = sys.argv[1] + "/packages/WallpaperCropper"
+for file_path in files.split():
+ file_path = src_dir + file_path
+ dir = os.path.dirname(file_path)
+ dir = dir.replace("launcher3", "wallpapercropper")
+ dir = dir.replace(src_dir, "src/")
+ cmd = 'cp %s %s/%s' % (file_path, framework_dir, dir)
+ print cmd
+ os.system(cmd)
diff --git a/util/com/android/launcher3/DecoderRing.java b/util/com/android/launcher3/DecoderRing.java
index 1d9e0defb..86431d9b7 100644
--- a/util/com/android/launcher3/DecoderRing.java
+++ b/util/com/android/launcher3/DecoderRing.java
@@ -34,159 +34,283 @@ import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.System;
+import java.util.LinkedList;
+import java.util.List;
import java.util.zip.CRC32;
+import javax.xml.bind.DatatypeConverter;
+
+
/**
- * Commandline utility for decoding protos written to the android logs during debugging.
+ * Commandline utility for decoding Launcher3 backup protocol buffers.
*
- * base64 -D icon.log > icon.bin
- * java -classpath $ANDROID_HOST_OUT/framework/protoutil.jar:$ANDROID_HOST_OUT/../common/obj/JAVA_LIBRARIES/host-libprotobuf-java-2.3.0-nano_intermediates/javalib.jar \
- * com.android.launcher3.DecoderRing -i icon.bin
+ * <P>When using com.android.internal.backup.LocalTransport, the file names are base64-encoded Key
+ * protocol buffers with a prefix, that have been base64-encoded again by the transport:
+ * <pre>
+ * echo "TDpDQUlnL0pxVTVnOD0=" | launcher_protoutil -k
+ * </pre>
*
- * TODO: write a wrapper to setup the classpath
+ * <P>This tool understands these file names and will use the embedded Key to detect the type and
+ * extract the payload automatically:
+ * <pre>
+ * launcher_protoutil /tmp/TDpDQUlnL0pxVTVnOD0=
+ * </pre>
+ *
+ * <P>With payload debugging enabled, base64-encoded protocol buffers will be written to the logs.
+ * Copy the encoded snippet from the log, and specify the type explicitly, with the Logs flags:
+ * <pre>
+ * echo "CAEYLiCJ9JKsDw==" | launcher_protoutil -L -k
+ * </pre>
+ * For backup payloads it is more convenient to copy the log snippet to a file:
+ * <pre>
+ * launcher_protoutil -L -f favorite.log
+ * </pre>
*/
class DecoderRing {
+
+ public static final String STANDARD_IN = "**stdin**";
+
+ private static Class[] TYPES = {
+ Key.class,
+ Favorite.class,
+ Screen.class,
+ Resource.class,
+ Widget.class
+ };
+ static final int ICON_TYPE_BITMAP = 1;
+
public static void main(String[ ] args)
throws Exception {
- File source = null;
- Class type = Key.class;
+ Class defaultType = null;
+ boolean extractImages = false;
+ boolean fromLogs = false;
int skip = 0;
+ List<File> files = new LinkedList<File>();
+ boolean verbose = false;
for (int i = 0; i < args.length; i++) {
if ("-k".equals(args[i])) {
- type = Key.class;
+ defaultType = Key.class;
} else if ("-f".equals(args[i])) {
- type = Favorite.class;
+ defaultType = Favorite.class;
} else if ("-j".equals(args[i])) {
- type = Journal.class;
+ defaultType = Journal.class;
} else if ("-i".equals(args[i])) {
- type = Resource.class;
+ defaultType = Resource.class;
} else if ("-s".equals(args[i])) {
- type = Screen.class;
+ defaultType = Screen.class;
} else if ("-w".equals(args[i])) {
- type = Widget.class;
+ defaultType = Widget.class;
} else if ("-S".equals(args[i])) {
if ((i + 1) < args.length) {
skip = Integer.valueOf(args[++i]);
} else {
usage(args);
}
+ } else if ("-x".equals(args[i])) {
+ extractImages = true;
+ } else if ("-v".equals(args[i])) {
+ verbose = true;
+ } else if ("-L".equals(args[i])) {
+ fromLogs = true;
} else if (args[i] != null && !args[i].startsWith("-")) {
- source = new File(args[i]);
+ files.add(new File(args[i]));
} else {
System.err.println("Unsupported flag: " + args[i]);
usage(args);
}
}
+ if (defaultType == null && files.isEmpty()) {
+ // can't infer file type without the key
+ usage(args);
+ }
- // read in the bytes
- ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
- BufferedInputStream input = null;
- if (source == null) {
- input = new BufferedInputStream(System.in);
- } else {
- try {
- input = new BufferedInputStream(new FileInputStream(source));
- } catch (FileNotFoundException e) {
- System.err.println("failed to open file: " + source + ", " + e);
- System.exit(1);
- }
+ if (files.size() > 1 && defaultType != null) {
+ System.err.println("Explicit type ignored for multiple files.");
+ defaultType = null;
}
- byte[] buffer = new byte[1024];
- try {
- while (input.available() > 0) {
- int n = input.read(buffer);
- int offset = 0;
- if (skip > 0) {
- offset = Math.min(skip, n);
- n -= offset;
- skip -= offset;
- }
- if (n > 0) {
- byteStream.write(buffer, offset, n);
+
+ if (files.isEmpty()) {
+ files.add(new File(STANDARD_IN));
+ }
+
+ for (File source : files) {
+ Class type = null;
+ if (defaultType == null) {
+ Key key = decodeKey(source.getName().getBytes(), fromLogs);
+ if (key != null) {
+ type = TYPES[key.type];
+ if (verbose) {
+ System.err.println(source.getName() + " is a " + type.getSimpleName());
+ System.out.println(key.toString());
+ }
}
+ } else {
+ type = defaultType;
}
- } catch (IOException e) {
- System.err.println("failed to read input: " + e);
- System.exit(1);
- }
- System.err.println("read this many bytes: " + byteStream.size());
- MessageNano proto = null;
- if (type == Key.class) {
- Key key = new Key();
+ // read in the bytes
+ ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
+ BufferedInputStream input = null;
+ if (source.getName() == STANDARD_IN) {
+ input = new BufferedInputStream(System.in);
+ } else {
+ try {
+ input = new BufferedInputStream(new FileInputStream(source));
+ } catch (FileNotFoundException e) {
+ System.err.println("failed to open file: " + source + ", " + e);
+ System.exit(1);
+ }
+ }
+ byte[] buffer = new byte[1024];
try {
- key = Key.parseFrom(byteStream.toByteArray());
- } catch (InvalidProtocolBufferNanoException e) {
- System.err.println("failed to parse proto: " + e);
+ while (input.available() > 0) {
+ int n = input.read(buffer);
+ int offset = 0;
+ if (skip > 0) {
+ offset = Math.min(skip, n);
+ n -= offset;
+ skip -= offset;
+ }
+ if (n > 0) {
+ byteStream.write(buffer, offset, n);
+ }
+ }
+ } catch (IOException e) {
+ System.err.println("failed to read input: " + e);
System.exit(1);
}
- // keys are self-checked
- if (key.checksum != checkKey(key)) {
- System.err.println("key ckecksum failed");
- System.exit(1);
+
+ MessageNano proto = null;
+ byte[] payload = byteStream.toByteArray();
+ if (type == Key.class) {
+ proto = decodeKey(payload, fromLogs);
+ } else if (type != null) {
+ proto = decodeBackupData(payload, type, fromLogs);
}
- proto = key;
- } else {
- // other types are wrapped in a checksum message
- CheckedMessage wrapper = new CheckedMessage();
- try {
- MessageNano.mergeFrom(wrapper, byteStream.toByteArray());
- } catch (InvalidProtocolBufferNanoException e) {
- System.err.println("failed to parse wrapper: " + e);
- System.exit(1);
+
+ // Generic string output
+ if (proto != null) {
+ System.out.println(proto.toString());
}
- CRC32 checksum = new CRC32();
- checksum.update(wrapper.payload);
- if (wrapper.checksum != checksum.getValue()) {
- System.err.println("wrapper ckecksum failed");
- System.exit(1);
+
+ if (extractImages) {
+ String prefix = "stdin";
+ if (source != null) {
+ prefix = source.getName();
+ }
+ // save off the icon bits in a file for inspection
+ if (proto instanceof Resource) {
+ Resource icon = (Resource) proto;
+ writeImageData(icon.data, prefix + ".png");
+ }
+
+ // save off the icon bits in a file for inspection
+ if (proto instanceof Favorite) {
+ Favorite favorite = (Favorite) proto;
+ if (favorite.iconType == ICON_TYPE_BITMAP) {
+ writeImageData(favorite.icon, prefix + ".png");
+ }
+ }
+
+ // save off the widget icon and preview bits in files for inspection
+ if (proto instanceof Widget) {
+ Widget widget = (Widget) proto;
+ if (widget.icon != null) {
+ writeImageData(widget.icon.data, prefix + "_icon.png");
+ }
+ if (widget.preview != null) {
+ writeImageData(widget.preview.data, prefix + "_preview.png");
+ }
+ }
}
- // decode the actual message
- proto = (MessageNano) type.newInstance();
- try {
- MessageNano.mergeFrom(proto, wrapper.payload);
- } catch (InvalidProtocolBufferNanoException e) {
- System.err.println("failed to parse proto: " + e);
- System.exit(1);
+ }
+ System.exit(0);
+ }
+
+ // In logcat, backup data is base64 encoded, but in localtransport files it is raw
+ private static MessageNano decodeBackupData(byte[] payload, Class type, boolean fromLogs)
+ throws InstantiationException, IllegalAccessException {
+ MessageNano proto;// other types are wrapped in a checksum message
+ CheckedMessage wrapper = new CheckedMessage();
+ try {
+ if (fromLogs) {
+ payload = DatatypeConverter.parseBase64Binary(new String(payload));
}
+ MessageNano.mergeFrom(wrapper, payload);
+ } catch (InvalidProtocolBufferNanoException e) {
+ System.err.println("failed to parse wrapper: " + e);
+ System.exit(1);
}
- // Generic string output
- System.out.println(proto.toString());
+ CRC32 checksum = new CRC32();
+ checksum.update(wrapper.payload);
+ if (wrapper.checksum != checksum.getValue()) {
+ System.err.println("wrapper checksum failed");
+ System.exit(1);
+ }
- // save off the icon bits in a file for inspection
- if (proto instanceof Resource) {
- Resource icon = (Resource) proto;
- final String path = "icon.webp";
- FileOutputStream iconFile = new FileOutputStream(path);
- iconFile.write(icon.data);
- iconFile.close();
- System.err.println("wrote " + path);
+ // decode the actual message
+ proto = (MessageNano) type.newInstance();
+ try {
+ MessageNano.mergeFrom(proto, wrapper.payload);
+ } catch (InvalidProtocolBufferNanoException e) {
+ System.err.println("failed to parse proto: " + e);
+ System.exit(1);
}
+ return proto;
+ }
- // save off the widget icon and preview bits in files for inspection
- if (proto instanceof Widget) {
- Widget widget = (Widget) proto;
- if (widget.icon != null) {
- final String path = "widget_icon.webp";
- FileOutputStream iconFile = new FileOutputStream(path);
- iconFile.write(widget.icon.data);
- iconFile.close();
- System.err.println("wrote " + path);
- }
- if (widget.preview != null) {
- final String path = "widget_preview.webp";
- FileOutputStream iconFile = new FileOutputStream(path);
- iconFile.write(widget.preview.data);
- iconFile.close();
- System.err.println("wrote " + path);
+ // In logcat, keys are base64 encoded with no prefix.
+ // The localtransport adds a prefix and the base64 encodes the whole thing again.
+ private static Key decodeKey(byte[] payload, boolean fromLogs) {
+ Key key = new Key();
+ try {
+ String encodedKey = new String(payload);
+ if (!fromLogs) {
+ byte[] rawKey = DatatypeConverter.parseBase64Binary(encodedKey);
+ if (rawKey[0] != 'L' || rawKey[1] != ':') {
+ System.err.println(encodedKey + " is not a launcher backup key.");
+ return null;
+ }
+ encodedKey = new String(rawKey, 2, rawKey.length - 2);
}
+ byte[] keyProtoData = DatatypeConverter.parseBase64Binary(encodedKey);
+ key = Key.parseFrom(keyProtoData);
+ } catch (InvalidProtocolBufferNanoException protoException) {
+ System.err.println("failed to extract key from filename: " + protoException);
+ return null;
+ } catch (IllegalArgumentException base64Exception) {
+ System.err.println("failed to extract key from filename: " + base64Exception);
+ return null;
}
- // success
- System.exit(0);
+ // keys are self-checked
+ if (key.checksum != checkKey(key)) {
+ System.err.println("key ckecksum failed");
+ return null;
+ }
+ return key;
+ }
+
+ private static void writeImageData(byte[] data, String path) {
+ FileOutputStream iconFile = null;
+ try {
+ iconFile = new FileOutputStream(path);
+ iconFile.write(data);
+ System.err.println("wrote " + path);
+ } catch (IOException e) {
+ System.err.println("failed to write image file: " + e);
+ } finally {
+ if (iconFile != null) {
+ try {
+ iconFile.close();
+ } catch (IOException e) {
+ System.err.println("failed to close the image file: " + e);
+ }
+ }
+ }
}
private static long checkKey(Key key) {
@@ -201,13 +325,16 @@ class DecoderRing {
}
private static void usage(String[] args) {
- System.err.println("DecoderRing type [input]");
+ System.err.println("launcher_protoutil [-x] [-S b] [-k|-f|-i|-s|-w] [filename]");
System.err.println("\t-k\tdecode a key");
System.err.println("\t-f\tdecode a favorite");
System.err.println("\t-i\tdecode a icon");
System.err.println("\t-s\tdecode a screen");
System.err.println("\t-w\tdecode a widget");
- System.err.println("\t-s b\tskip b bytes");
+ System.err.println("\t-S b\tskip b bytes");
+ System.err.println("\t-x\textract image data to files");
+ System.err.println("\t-v\tprint key type data, as well as payload");
+ System.err.println("\t-l\texpect data from logcat, instead of the local transport");
System.err.println("\tfilename\tread from filename, not stdin");
System.exit(1);
}
diff --git a/util/etc/launcher_protoutil b/util/etc/launcher_protoutil
new file mode 100644
index 000000000..833b5835e
--- /dev/null
+++ b/util/etc/launcher_protoutil
@@ -0,0 +1,83 @@
+#!/bin/bash
+#
+# Copyright (C) 2013 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Set up prog to be the path of this script, including following symlinks,
+# and set up progdir to be the fully-qualified pathname of its directory.
+prog="$0"
+while [ -h "${prog}" ]; do
+ newProg=`/bin/ls -ld "${prog}"`
+ newProg=`expr "${newProg}" : ".* -> \(.*\)$"`
+ if expr "x${newProg}" : 'x/' >/dev/null; then
+ prog="${newProg}"
+ else
+ progdir=`dirname "${prog}"`
+ prog="${progdir}/${newProg}"
+ fi
+done
+oldwd=`pwd`
+progdir=`dirname "${prog}"`
+cd "${progdir}"
+progdir=`pwd`
+prog="${progdir}"/`basename "${prog}"`
+cd "${oldwd}"
+
+jarfile=launcher_protoutil_lib.jar
+libdir="$progdir"
+
+if [ ! -r "$libdir/$jarfile" ]; then
+ # set jar location for the Android tree case
+ libdir=`dirname "$progdir"`/framework
+fi
+
+if [ ! -r "$libdir/$jarfile" ]; then
+ echo `basename "$prog"`": can't find $jarfile"
+ exit 1
+fi
+
+# By default, give decoder a max heap size of 1 gig. This can be overridden
+# by using a "-J" option (see below).
+defaultMx="-Xmx1024M"
+
+# The following will extract any initial parameters of the form
+# "-J<stuff>" from the command line and pass them to the Java
+# invocation (instead of to the decoder). This makes it possible for
+# you to add a command-line parameter such as "-JXmx256M" in your
+# scripts, for example. "java" (with no args) and "java -X" give a
+# summary of available options.
+
+javaOpts=""
+
+while expr "x$1" : 'x-J' >/dev/null; do
+ opt=`expr "x$1" : 'x-J\(.*\)'`
+ javaOpts="${javaOpts} -${opt}"
+ if expr "x${opt}" : "xXmx[0-9]" >/dev/null; then
+ defaultMx="no"
+ fi
+ shift
+done
+
+if [ "${defaultMx}" != "no" ]; then
+ javaOpts="${javaOpts} ${defaultMx}"
+fi
+
+if [ "$OSTYPE" = "cygwin" ]; then
+ # For Cygwin, convert the jarfile path into native Windows style.
+ jarpath=`cygpath -w "$libdir/$jarfile"`
+else
+ jarpath="$libdir/$jarfile"
+fi
+
+exec java $javaOpts -jar "$jarpath" "$@"
diff --git a/util/etc/manifest.txt b/util/etc/manifest.txt
new file mode 100644
index 000000000..84842ed53
--- /dev/null
+++ b/util/etc/manifest.txt
@@ -0,0 +1 @@
+Main-Class: com.android.launcher3.DecoderRing