From 8e963a5a6016d246184ed65906f9d103e92b17e2 Mon Sep 17 00:00:00 2001 From: Sascha Haeberling Date: Tue, 6 Aug 2013 11:43:02 -0700 Subject: This removes all non-Camera stuff from Camera2. Note: Camera2 is a clone of Gallery2 right now. Note 2: I will bring .mk files back later. Change-Id: Ida958654296f5ebaacb6bb0ff59d52a7c37ce6fc --- src/com/android/gallery3d/anim/AlphaAnimation.java | 48 - src/com/android/gallery3d/anim/Animation.java | 92 - .../android/gallery3d/anim/CanvasAnimation.java | 25 - src/com/android/gallery3d/anim/FloatAnimation.java | 40 - .../gallery3d/anim/StateTransitionAnimation.java | 180 -- .../gallery3d/app/AbstractGalleryActivity.java | 343 ---- src/com/android/gallery3d/app/ActivityState.java | 276 --- src/com/android/gallery3d/app/AlbumDataLoader.java | 397 ----- src/com/android/gallery3d/app/AlbumPage.java | 786 --------- src/com/android/gallery3d/app/AlbumPicker.java | 40 - .../android/gallery3d/app/AlbumSetDataLoader.java | 393 ----- src/com/android/gallery3d/app/AlbumSetPage.java | 764 -------- src/com/android/gallery3d/app/AppBridge.java | 72 - src/com/android/gallery3d/app/BatchService.java | 48 - .../gallery3d/app/CommonControllerOverlay.java | 346 ---- src/com/android/gallery3d/app/Config.java | 127 -- .../android/gallery3d/app/ControllerOverlay.java | 56 - src/com/android/gallery3d/app/DialogPicker.java | 41 - src/com/android/gallery3d/app/EyePosition.java | 226 --- src/com/android/gallery3d/app/FilmstripPage.java | 21 - src/com/android/gallery3d/app/FilterUtils.java | 257 --- src/com/android/gallery3d/app/Gallery.java | 274 --- .../android/gallery3d/app/GalleryActionBar.java | 438 ----- src/com/android/gallery3d/app/GalleryApp.java | 41 - src/com/android/gallery3d/app/GalleryAppImpl.java | 127 -- src/com/android/gallery3d/app/GalleryContext.java | 34 - src/com/android/gallery3d/app/LoadingListener.java | 27 - src/com/android/gallery3d/app/Log.java | 53 - src/com/android/gallery3d/app/ManageCachePage.java | 419 ----- src/com/android/gallery3d/app/MovieActivity.java | 263 --- .../gallery3d/app/MovieControllerOverlay.java | 185 -- src/com/android/gallery3d/app/MoviePlayer.java | 525 ------ src/com/android/gallery3d/app/MuteVideo.java | 104 -- src/com/android/gallery3d/app/NotificationIds.java | 22 - .../android/gallery3d/app/OrientationManager.java | 166 -- src/com/android/gallery3d/app/PackagesMonitor.java | 71 - .../gallery3d/app/PanoramaMetadataSupport.java | 93 - .../android/gallery3d/app/PhotoDataAdapter.java | 1133 ------------ src/com/android/gallery3d/app/PhotoPage.java | 1571 ----------------- .../gallery3d/app/PhotoPageBottomControls.java | 137 -- .../gallery3d/app/PhotoPageProgressBar.java | 50 - src/com/android/gallery3d/app/PickerActivity.java | 83 - .../gallery3d/app/SinglePhotoDataAdapter.java | 263 --- src/com/android/gallery3d/app/SinglePhotoPage.java | 21 - .../gallery3d/app/SlideshowDataAdapter.java | 204 --- src/com/android/gallery3d/app/SlideshowPage.java | 366 ---- src/com/android/gallery3d/app/StateManager.java | 339 ---- .../gallery3d/app/StitchingChangeListener.java | 27 - src/com/android/gallery3d/app/TimeBar.java | 266 --- src/com/android/gallery3d/app/TransitionStore.java | 46 - .../gallery3d/app/TrimControllerOverlay.java | 111 -- src/com/android/gallery3d/app/TrimTimeBar.java | 339 ---- src/com/android/gallery3d/app/TrimVideo.java | 337 ---- src/com/android/gallery3d/app/VideoUtils.java | 328 ---- src/com/android/gallery3d/app/Wallpaper.java | 135 -- src/com/android/gallery3d/data/ActionImage.java | 103 -- src/com/android/gallery3d/data/BucketHelper.java | 241 --- .../android/gallery3d/data/BytesBufferPool.java | 91 - .../gallery3d/data/CameraShortcutImage.java | 34 - src/com/android/gallery3d/data/ChangeNotifier.java | 57 - src/com/android/gallery3d/data/ClusterAlbum.java | 143 -- .../android/gallery3d/data/ClusterAlbumSet.java | 159 -- src/com/android/gallery3d/data/ClusterSource.java | 86 - src/com/android/gallery3d/data/Clustering.java | 29 - src/com/android/gallery3d/data/ComboAlbum.java | 103 -- src/com/android/gallery3d/data/ComboAlbumSet.java | 96 - src/com/android/gallery3d/data/ComboSource.java | 55 - .../android/gallery3d/data/ContentListener.java | 21 - src/com/android/gallery3d/data/DataManager.java | 371 ---- src/com/android/gallery3d/data/DataSourceType.java | 45 - src/com/android/gallery3d/data/DecodeUtils.java | 312 ---- src/com/android/gallery3d/data/DownloadCache.java | 370 ---- src/com/android/gallery3d/data/DownloadEntry.java | 72 - src/com/android/gallery3d/data/DownloadUtils.java | 79 - .../android/gallery3d/data/EmptyAlbumImage.java | 34 - src/com/android/gallery3d/data/Exif.java | 48 - src/com/android/gallery3d/data/Face.java | 65 - src/com/android/gallery3d/data/FaceClustering.java | 142 -- .../android/gallery3d/data/FilterDeleteSet.java | 256 --- .../gallery3d/data/FilterEmptyPromptSet.java | 82 - src/com/android/gallery3d/data/FilterSource.java | 94 - src/com/android/gallery3d/data/FilterTypeSet.java | 137 -- .../android/gallery3d/data/ImageCacheRequest.java | 102 -- .../android/gallery3d/data/ImageCacheService.java | 123 -- src/com/android/gallery3d/data/LocalAlbum.java | 325 ---- src/com/android/gallery3d/data/LocalAlbumSet.java | 211 --- src/com/android/gallery3d/data/LocalImage.java | 355 ---- src/com/android/gallery3d/data/LocalMediaItem.java | 109 -- .../android/gallery3d/data/LocalMergeAlbum.java | 257 --- src/com/android/gallery3d/data/LocalSource.java | 275 --- src/com/android/gallery3d/data/LocalVideo.java | 242 --- .../android/gallery3d/data/LocationClustering.java | 316 ---- src/com/android/gallery3d/data/Log.java | 53 - src/com/android/gallery3d/data/MediaDetails.java | 170 -- src/com/android/gallery3d/data/MediaItem.java | 134 -- src/com/android/gallery3d/data/MediaObject.java | 166 -- src/com/android/gallery3d/data/MediaSet.java | 348 ---- src/com/android/gallery3d/data/MediaSource.java | 96 - src/com/android/gallery3d/data/MtpClient.java | 443 ----- .../gallery3d/data/PanoramaMetadataJob.java | 40 - src/com/android/gallery3d/data/Path.java | 241 --- src/com/android/gallery3d/data/PathMatcher.java | 102 -- src/com/android/gallery3d/data/SecureAlbum.java | 206 --- src/com/android/gallery3d/data/SecureSource.java | 56 - .../android/gallery3d/data/SingleItemAlbum.java | 68 - src/com/android/gallery3d/data/SizeClustering.java | 141 -- src/com/android/gallery3d/data/SnailAlbum.java | 44 - src/com/android/gallery3d/data/SnailItem.java | 95 - src/com/android/gallery3d/data/SnailSource.java | 70 - src/com/android/gallery3d/data/TagClustering.java | 95 - src/com/android/gallery3d/data/TimeClustering.java | 439 ----- src/com/android/gallery3d/data/UnlockImage.java | 34 - src/com/android/gallery3d/data/UriImage.java | 298 ---- src/com/android/gallery3d/data/UriSource.java | 95 - .../gallery3d/filtershow/CenteredLinearLayout.java | 51 - .../gallery3d/filtershow/EditorPlaceHolder.java | 82 - .../gallery3d/filtershow/FilterShowActivity.java | 1121 ------------ .../gallery3d/filtershow/cache/ImageLoader.java | 502 ------ .../gallery3d/filtershow/category/Action.java | 186 -- .../filtershow/category/CategoryAdapter.java | 182 -- .../filtershow/category/CategoryPanel.java | 108 -- .../filtershow/category/CategoryTrack.java | 77 - .../filtershow/category/CategoryView.java | 176 -- .../gallery3d/filtershow/category/MainPanel.java | 239 --- .../filtershow/colorpicker/ColorGridDialog.java | 100 -- .../filtershow/colorpicker/ColorListener.java | 21 - .../filtershow/colorpicker/ColorOpacityView.java | 197 --- .../filtershow/colorpicker/ColorPickerDialog.java | 123 -- .../filtershow/colorpicker/ColorRectView.java | 225 --- .../filtershow/colorpicker/ColorValueView.java | 180 -- .../filtershow/colorpicker/RGBListener.java | 21 - .../filtershow/controller/ActionSlider.java | 71 - .../filtershow/controller/BasicParameterInt.java | 113 -- .../filtershow/controller/BasicParameterStyle.java | 111 -- .../filtershow/controller/BasicSlider.java | 87 - .../gallery3d/filtershow/controller/Control.java | 32 - .../filtershow/controller/FilterView.java | 25 - .../gallery3d/filtershow/controller/Parameter.java | 33 - .../controller/ParameterActionAndInt.java | 29 - .../filtershow/controller/ParameterInteger.java | 31 - .../filtershow/controller/ParameterSet.java | 23 - .../filtershow/controller/ParameterStyles.java | 37 - .../filtershow/controller/StyleChooser.java | 88 - .../filtershow/controller/TitledSlider.java | 106 -- .../gallery3d/filtershow/crop/BoundedRect.java | 368 ---- .../gallery3d/filtershow/crop/CropActivity.java | 697 -------- .../filtershow/crop/CropDrawingUtils.java | 168 -- .../gallery3d/filtershow/crop/CropExtras.java | 121 -- .../gallery3d/filtershow/crop/CropMath.java | 260 --- .../gallery3d/filtershow/crop/CropObject.java | 330 ---- .../gallery3d/filtershow/crop/CropView.java | 378 ---- .../filtershow/data/FilterStackDBHelper.java | 101 -- .../filtershow/data/FilterStackSource.java | 197 --- .../filtershow/data/UserPresetsManager.java | 149 -- .../gallery3d/filtershow/editors/BasicEditor.java | 138 -- .../gallery3d/filtershow/editors/Editor.java | 330 ---- .../filtershow/editors/EditorChanSat.java | 227 --- .../gallery3d/filtershow/editors/EditorCrop.java | 168 -- .../gallery3d/filtershow/editors/EditorCurves.java | 56 - .../gallery3d/filtershow/editors/EditorDraw.java | 158 -- .../gallery3d/filtershow/editors/EditorGrad.java | 315 ---- .../gallery3d/filtershow/editors/EditorInfo.java | 23 - .../gallery3d/filtershow/editors/EditorMirror.java | 109 -- .../gallery3d/filtershow/editors/EditorPanel.java | 143 -- .../gallery3d/filtershow/editors/EditorRedEye.java | 65 - .../gallery3d/filtershow/editors/EditorRotate.java | 112 -- .../filtershow/editors/EditorStraighten.java | 103 -- .../filtershow/editors/EditorTinyPlanet.java | 58 - .../filtershow/editors/EditorVignette.java | 53 - .../gallery3d/filtershow/editors/EditorZoom.java | 27 - .../filtershow/editors/ImageOnlyEditor.java | 50 - .../filtershow/editors/ParametricEditor.java | 206 --- .../gallery3d/filtershow/editors/SwapButton.java | 111 -- .../filtershow/filters/BaseFiltersManager.java | 296 ---- .../filtershow/filters/ColorSpaceMatrix.java | 225 --- .../filters/FilterBasicRepresentation.java | 196 --- .../filters/FilterChanSatRepresentation.java | 211 --- .../filters/FilterColorBorderRepresentation.java | 113 -- .../filters/FilterCropRepresentation.java | 179 -- .../filters/FilterCurvesRepresentation.java | 170 -- .../filters/FilterDirectRepresentation.java | 38 - .../filters/FilterDrawRepresentation.java | 171 -- .../filtershow/filters/FilterFxRepresentation.java | 112 -- .../filters/FilterGradRepresentation.java | 497 ------ .../filters/FilterImageBorderRepresentation.java | 91 - .../filters/FilterMirrorRepresentation.java | 190 -- .../gallery3d/filtershow/filters/FilterPoint.java | 21 - .../filters/FilterPointRepresentation.java | 88 - .../filters/FilterRedEyeRepresentation.java | 67 - .../filtershow/filters/FilterRepresentation.java | 262 --- .../filters/FilterRotateRepresentation.java | 190 -- .../filters/FilterStraightenRepresentation.java | 154 -- .../filters/FilterTinyPlanetRepresentation.java | 101 -- .../filters/FilterUserPresetRepresentation.java | 53 - .../filters/FilterVignetteRepresentation.java | 173 -- .../filters/FiltersManagerInterface.java | 21 - .../filtershow/filters/IconUtilities.java | 75 - .../gallery3d/filtershow/filters/ImageFilter.java | 109 -- .../filtershow/filters/ImageFilterBorder.java | 92 - .../filtershow/filters/ImageFilterBwFilter.java | 64 - .../filtershow/filters/ImageFilterChanSat.java | 161 -- .../filtershow/filters/ImageFilterContrast.java | 58 - .../filtershow/filters/ImageFilterCurves.java | 112 -- .../filtershow/filters/ImageFilterDownsample.java | 83 - .../filtershow/filters/ImageFilterDraw.java | 278 --- .../filtershow/filters/ImageFilterEdge.java | 53 - .../filtershow/filters/ImageFilterExposure.java | 56 - .../filtershow/filters/ImageFilterFx.java | 111 -- .../filtershow/filters/ImageFilterGrad.java | 190 -- .../filtershow/filters/ImageFilterHighlights.java | 74 - .../filtershow/filters/ImageFilterHue.java | 64 - .../filtershow/filters/ImageFilterKMeans.java | 95 - .../filtershow/filters/ImageFilterNegative.java | 39 - .../filters/ImageFilterParametricBorder.java | 69 - .../filtershow/filters/ImageFilterRS.java | 260 --- .../filtershow/filters/ImageFilterRedEye.java | 79 - .../filtershow/filters/ImageFilterSaturated.java | 58 - .../filtershow/filters/ImageFilterShadows.java | 58 - .../filtershow/filters/ImageFilterSharpen.java | 107 -- .../filtershow/filters/ImageFilterTinyPlanet.java | 158 -- .../filtershow/filters/ImageFilterVibrance.java | 57 - .../filtershow/filters/ImageFilterVignette.java | 98 -- .../filtershow/filters/ImageFilterWBalance.java | 59 - .../filtershow/filters/RedEyeCandidate.java | 50 - .../filtershow/filters/SimpleImageFilter.java | 37 - .../gallery3d/filtershow/filters/SplineMath.java | 166 -- .../gallery3d/filtershow/filters/convolve3x3.rs | 67 - .../android/gallery3d/filtershow/filters/grad.rs | 121 -- .../android/gallery3d/filtershow/filters/grey.rs | 22 - .../gallery3d/filtershow/filters/saturation.rs | 161 -- .../gallery3d/filtershow/history/HistoryItem.java | 53 - .../filtershow/history/HistoryManager.java | 172 -- .../filtershow/imageshow/ControlPoint.java | 64 - .../filtershow/imageshow/EclipseControl.java | 302 ---- .../filtershow/imageshow/GeometryMathUtils.java | 416 ----- .../filtershow/imageshow/GradControl.java | 274 --- .../gallery3d/filtershow/imageshow/ImageCrop.java | 307 ---- .../filtershow/imageshow/ImageCurves.java | 445 ----- .../gallery3d/filtershow/imageshow/ImageDraw.java | 139 -- .../gallery3d/filtershow/imageshow/ImageGrad.java | 215 --- .../filtershow/imageshow/ImageMirror.java | 78 - .../gallery3d/filtershow/imageshow/ImagePoint.java | 89 - .../filtershow/imageshow/ImageRedEye.java | 137 -- .../filtershow/imageshow/ImageRotate.java | 81 - .../gallery3d/filtershow/imageshow/ImageShow.java | 578 ------ .../filtershow/imageshow/ImageStraighten.java | 260 --- .../filtershow/imageshow/ImageTinyPlanet.java | 174 -- .../filtershow/imageshow/ImageVignette.java | 165 -- .../gallery3d/filtershow/imageshow/Line.java | 26 - .../filtershow/imageshow/MasterImage.java | 581 ------ .../gallery3d/filtershow/imageshow/Oval.java | 29 - .../gallery3d/filtershow/imageshow/Spline.java | 450 ----- .../gallery3d/filtershow/pipeline/Buffer.java | 74 - .../filtershow/pipeline/CacheProcessing.java | 193 -- .../filtershow/pipeline/CachingPipeline.java | 469 ----- .../filtershow/pipeline/FilterEnvironment.java | 178 -- .../pipeline/HighresRenderingRequestTask.java | 90 - .../gallery3d/filtershow/pipeline/ImagePreset.java | 694 -------- .../filtershow/pipeline/ImageSavingTask.java | 125 -- .../filtershow/pipeline/PipelineInterface.java | 31 - .../filtershow/pipeline/ProcessingService.java | 283 --- .../filtershow/pipeline/ProcessingTask.java | 88 - .../pipeline/ProcessingTaskController.java | 97 - .../filtershow/pipeline/RenderingRequest.java | 174 -- .../pipeline/RenderingRequestCaller.java | 21 - .../filtershow/pipeline/RenderingRequestTask.java | 81 - .../filtershow/pipeline/SharedBuffer.java | 77 - .../filtershow/pipeline/SharedPreset.java | 42 - .../filtershow/pipeline/UpdatePreviewTask.java | 79 - .../filtershow/presets/PresetManagementDialog.java | 69 - .../filtershow/presets/UserPresetsAdapter.java | 171 -- .../filtershow/provider/SharedImageProvider.java | 137 -- .../gallery3d/filtershow/state/DragListener.java | 110 -- .../gallery3d/filtershow/state/PanelTrack.java | 37 - .../android/gallery3d/filtershow/state/State.java | 78 - .../gallery3d/filtershow/state/StateAdapter.java | 115 -- .../gallery3d/filtershow/state/StatePanel.java | 44 - .../filtershow/state/StatePanelTrack.java | 351 ---- .../gallery3d/filtershow/state/StateView.java | 291 --- .../gallery3d/filtershow/tools/IconFactory.java | 108 -- .../gallery3d/filtershow/tools/MatrixFit.java | 200 --- .../gallery3d/filtershow/tools/SaveImage.java | 632 ------- .../gallery3d/filtershow/tools/XmpPresets.java | 133 -- .../gallery3d/filtershow/ui/ExportDialog.java | 90 - .../gallery3d/filtershow/ui/FramedTextButton.java | 137 -- .../gallery3d/filtershow/ui/SelectionRenderer.java | 48 - .../android/gallery3d/gadget/LocalPhotoSource.java | 205 --- .../android/gallery3d/gadget/MediaSetSource.java | 233 --- .../gallery3d/gadget/PhotoAppWidgetProvider.java | 139 -- .../gallery3d/gadget/WidgetClickHandler.java | 77 - .../android/gallery3d/gadget/WidgetConfigure.java | 209 --- .../gallery3d/gadget/WidgetDatabaseHelper.java | 309 ---- .../android/gallery3d/gadget/WidgetService.java | 143 -- src/com/android/gallery3d/gadget/WidgetSource.java | 31 - .../gallery3d/gadget/WidgetTypeChooser.java | 59 - src/com/android/gallery3d/gadget/WidgetUtils.java | 80 - .../android/gallery3d/glrenderer/BasicTexture.java | 212 --- .../gallery3d/glrenderer/BitmapTexture.java | 54 - .../gallery3d/glrenderer/CanvasTexture.java | 52 - .../android/gallery3d/glrenderer/ColorTexture.java | 63 - .../android/gallery3d/glrenderer/ExtTexture.java | 60 - .../gallery3d/glrenderer/FadeInTexture.java | 43 - .../gallery3d/glrenderer/FadeOutTexture.java | 42 - .../android/gallery3d/glrenderer/FadeTexture.java | 81 - src/com/android/gallery3d/glrenderer/GLCanvas.java | 217 --- .../android/gallery3d/glrenderer/GLES11Canvas.java | 997 ----------- .../android/gallery3d/glrenderer/GLES11IdImpl.java | 68 - .../android/gallery3d/glrenderer/GLES20Canvas.java | 1009 ----------- .../android/gallery3d/glrenderer/GLES20IdImpl.java | 42 - src/com/android/gallery3d/glrenderer/GLId.java | 33 - src/com/android/gallery3d/glrenderer/GLPaint.java | 41 - .../gallery3d/glrenderer/MultiLineTexture.java | 52 - .../gallery3d/glrenderer/NinePatchChunk.java | 82 - .../gallery3d/glrenderer/NinePatchTexture.java | 424 ----- .../android/gallery3d/glrenderer/RawTexture.java | 73 - .../gallery3d/glrenderer/ResourceTexture.java | 53 - .../gallery3d/glrenderer/StringTexture.java | 88 - src/com/android/gallery3d/glrenderer/Texture.java | 44 - .../gallery3d/glrenderer/TextureUploader.java | 105 -- .../android/gallery3d/glrenderer/TiledTexture.java | 349 ---- .../gallery3d/glrenderer/UploadedTexture.java | 298 ---- src/com/android/gallery3d/ingest/ImportTask.java | 95 - .../android/gallery3d/ingest/IngestActivity.java | 570 ------ .../android/gallery3d/ingest/IngestService.java | 320 ---- .../android/gallery3d/ingest/MtpDeviceIndex.java | 596 ------- src/com/android/gallery3d/ingest/SimpleDate.java | 114 -- .../gallery3d/ingest/adapter/CheckBroker.java | 56 - .../gallery3d/ingest/adapter/MtpAdapter.java | 192 -- .../gallery3d/ingest/adapter/MtpPagerAdapter.java | 102 -- .../gallery3d/ingest/data/BitmapWithMetadata.java | 29 - .../gallery3d/ingest/data/MtpBitmapFetch.java | 106 -- .../android/gallery3d/ingest/ui/DateTileView.java | 107 -- .../gallery3d/ingest/ui/IngestGridView.java | 58 - .../gallery3d/ingest/ui/MtpFullscreenView.java | 115 -- .../android/gallery3d/ingest/ui/MtpImageView.java | 280 --- .../gallery3d/ingest/ui/MtpThumbnailTileView.java | 106 -- .../onetimeinitializer/GalleryWidgetMigrator.java | 169 -- .../gallery3d/provider/GalleryProvider.java | 228 --- .../android/gallery3d/ui/AbstractSlotRenderer.java | 119 -- .../android/gallery3d/ui/ActionModeHandler.java | 501 ------ src/com/android/gallery3d/ui/AlbumLabelMaker.java | 206 --- .../gallery3d/ui/AlbumSetSlidingWindow.java | 549 ------ .../android/gallery3d/ui/AlbumSetSlotRenderer.java | 242 --- .../android/gallery3d/ui/AlbumSlidingWindow.java | 365 ---- .../android/gallery3d/ui/AlbumSlotRenderer.java | 201 --- src/com/android/gallery3d/ui/AnimationTime.java | 45 - src/com/android/gallery3d/ui/BitmapLoader.java | 108 -- src/com/android/gallery3d/ui/BitmapScreenNail.java | 61 - .../android/gallery3d/ui/BitmapTileProvider.java | 103 -- .../gallery3d/ui/CacheStorageUsageInfo.java | 90 - src/com/android/gallery3d/ui/CaptureAnimation.java | 56 - .../gallery3d/ui/DetailsAddressResolver.java | 118 -- src/com/android/gallery3d/ui/DetailsHelper.java | 148 -- .../android/gallery3d/ui/DialogDetailsView.java | 288 --- src/com/android/gallery3d/ui/DownUpDetector.java | 61 - src/com/android/gallery3d/ui/EdgeEffect.java | 443 ----- src/com/android/gallery3d/ui/EdgeView.java | 132 -- src/com/android/gallery3d/ui/FlingScroller.java | 141 -- src/com/android/gallery3d/ui/GLRoot.java | 53 - src/com/android/gallery3d/ui/GLRootView.java | 630 ------- src/com/android/gallery3d/ui/GLView.java | 465 ----- .../android/gallery3d/ui/GestureRecognizer.java | 132 -- src/com/android/gallery3d/ui/Log.java | 54 - .../android/gallery3d/ui/ManageCacheDrawer.java | 116 -- src/com/android/gallery3d/ui/MeasureHelper.java | 65 - src/com/android/gallery3d/ui/MenuExecutor.java | 448 ----- .../android/gallery3d/ui/OrientationSource.java | 22 - src/com/android/gallery3d/ui/Paper.java | 183 -- .../android/gallery3d/ui/PhotoFallbackEffect.java | 179 -- src/com/android/gallery3d/ui/PhotoView.java | 1858 -------------------- src/com/android/gallery3d/ui/PopupList.java | 206 --- .../android/gallery3d/ui/PositionController.java | 1821 ------------------- .../gallery3d/ui/PreparePageFadeoutTexture.java | 85 - src/com/android/gallery3d/ui/ProgressSpinner.java | 80 - src/com/android/gallery3d/ui/RelativePosition.java | 42 - src/com/android/gallery3d/ui/ScreenNail.java | 35 - src/com/android/gallery3d/ui/ScrollBarView.java | 97 - src/com/android/gallery3d/ui/ScrollerHelper.java | 97 - src/com/android/gallery3d/ui/SelectionManager.java | 251 --- src/com/android/gallery3d/ui/SelectionMenu.java | 61 - src/com/android/gallery3d/ui/SlideshowView.java | 163 -- src/com/android/gallery3d/ui/SlotView.java | 788 --------- .../gallery3d/ui/SurfaceTextureScreenNail.java | 142 -- .../android/gallery3d/ui/SynchronizedHandler.java | 41 - src/com/android/gallery3d/ui/TileImageView.java | 786 --------- .../android/gallery3d/ui/TileImageViewAdapter.java | 200 --- src/com/android/gallery3d/ui/TiledScreenNail.java | 218 --- src/com/android/gallery3d/ui/UndoBarView.java | 211 --- .../gallery3d/ui/UserInteractionListener.java | 26 - .../ui/WakeLockHoldingProgressListener.java | 66 - .../android/gallery3d/util/AccessibilityUtils.java | 54 - src/com/android/gallery3d/util/BucketNames.java | 29 - src/com/android/gallery3d/util/CacheManager.java | 82 - src/com/android/gallery3d/util/GalleryUtils.java | 404 ----- src/com/android/gallery3d/util/Holder.java | 29 - src/com/android/gallery3d/util/IdentityCache.java | 78 - src/com/android/gallery3d/util/IntArray.java | 60 - .../gallery3d/util/InterruptableOutputStream.java | 67 - src/com/android/gallery3d/util/JobLimiter.java | 159 -- src/com/android/gallery3d/util/LinkedNode.java | 71 - src/com/android/gallery3d/util/Log.java | 53 - src/com/android/gallery3d/util/MediaSetUtils.java | 66 - .../android/gallery3d/util/MotionEventHelper.java | 120 -- src/com/android/gallery3d/util/Profile.java | 226 --- src/com/android/gallery3d/util/ProfileData.java | 168 -- src/com/android/gallery3d/util/RangeArray.java | 52 - src/com/android/gallery3d/util/RangeBoolArray.java | 49 - src/com/android/gallery3d/util/RangeIntArray.java | 49 - .../android/gallery3d/util/ReverseGeocoder.java | 418 ----- .../android/gallery3d/util/SaveVideoFileInfo.java | 29 - .../android/gallery3d/util/SaveVideoFileUtils.java | 154 -- src/com/android/gallery3d/util/UpdateHelper.java | 59 - 412 files changed, 74774 deletions(-) delete mode 100644 src/com/android/gallery3d/anim/AlphaAnimation.java delete mode 100644 src/com/android/gallery3d/anim/Animation.java delete mode 100644 src/com/android/gallery3d/anim/CanvasAnimation.java delete mode 100644 src/com/android/gallery3d/anim/FloatAnimation.java delete mode 100644 src/com/android/gallery3d/anim/StateTransitionAnimation.java delete mode 100644 src/com/android/gallery3d/app/AbstractGalleryActivity.java delete mode 100644 src/com/android/gallery3d/app/ActivityState.java delete mode 100644 src/com/android/gallery3d/app/AlbumDataLoader.java delete mode 100644 src/com/android/gallery3d/app/AlbumPage.java delete mode 100644 src/com/android/gallery3d/app/AlbumPicker.java delete mode 100644 src/com/android/gallery3d/app/AlbumSetDataLoader.java delete mode 100644 src/com/android/gallery3d/app/AlbumSetPage.java delete mode 100644 src/com/android/gallery3d/app/AppBridge.java delete mode 100644 src/com/android/gallery3d/app/BatchService.java delete mode 100644 src/com/android/gallery3d/app/CommonControllerOverlay.java delete mode 100644 src/com/android/gallery3d/app/Config.java delete mode 100644 src/com/android/gallery3d/app/ControllerOverlay.java delete mode 100644 src/com/android/gallery3d/app/DialogPicker.java delete mode 100644 src/com/android/gallery3d/app/EyePosition.java delete mode 100644 src/com/android/gallery3d/app/FilmstripPage.java delete mode 100644 src/com/android/gallery3d/app/FilterUtils.java delete mode 100644 src/com/android/gallery3d/app/Gallery.java delete mode 100644 src/com/android/gallery3d/app/GalleryActionBar.java delete mode 100644 src/com/android/gallery3d/app/GalleryApp.java delete mode 100644 src/com/android/gallery3d/app/GalleryAppImpl.java delete mode 100644 src/com/android/gallery3d/app/GalleryContext.java delete mode 100644 src/com/android/gallery3d/app/LoadingListener.java delete mode 100644 src/com/android/gallery3d/app/Log.java delete mode 100644 src/com/android/gallery3d/app/ManageCachePage.java delete mode 100644 src/com/android/gallery3d/app/MovieActivity.java delete mode 100644 src/com/android/gallery3d/app/MovieControllerOverlay.java delete mode 100644 src/com/android/gallery3d/app/MoviePlayer.java delete mode 100644 src/com/android/gallery3d/app/MuteVideo.java delete mode 100644 src/com/android/gallery3d/app/NotificationIds.java delete mode 100644 src/com/android/gallery3d/app/OrientationManager.java delete mode 100644 src/com/android/gallery3d/app/PackagesMonitor.java delete mode 100644 src/com/android/gallery3d/app/PanoramaMetadataSupport.java delete mode 100644 src/com/android/gallery3d/app/PhotoDataAdapter.java delete mode 100644 src/com/android/gallery3d/app/PhotoPage.java delete mode 100644 src/com/android/gallery3d/app/PhotoPageBottomControls.java delete mode 100644 src/com/android/gallery3d/app/PhotoPageProgressBar.java delete mode 100644 src/com/android/gallery3d/app/PickerActivity.java delete mode 100644 src/com/android/gallery3d/app/SinglePhotoDataAdapter.java delete mode 100644 src/com/android/gallery3d/app/SinglePhotoPage.java delete mode 100644 src/com/android/gallery3d/app/SlideshowDataAdapter.java delete mode 100644 src/com/android/gallery3d/app/SlideshowPage.java delete mode 100644 src/com/android/gallery3d/app/StateManager.java delete mode 100644 src/com/android/gallery3d/app/StitchingChangeListener.java delete mode 100644 src/com/android/gallery3d/app/TimeBar.java delete mode 100644 src/com/android/gallery3d/app/TransitionStore.java delete mode 100644 src/com/android/gallery3d/app/TrimControllerOverlay.java delete mode 100644 src/com/android/gallery3d/app/TrimTimeBar.java delete mode 100644 src/com/android/gallery3d/app/TrimVideo.java delete mode 100644 src/com/android/gallery3d/app/VideoUtils.java delete mode 100644 src/com/android/gallery3d/app/Wallpaper.java delete mode 100644 src/com/android/gallery3d/data/ActionImage.java delete mode 100644 src/com/android/gallery3d/data/BucketHelper.java delete mode 100644 src/com/android/gallery3d/data/BytesBufferPool.java delete mode 100644 src/com/android/gallery3d/data/CameraShortcutImage.java delete mode 100644 src/com/android/gallery3d/data/ChangeNotifier.java delete mode 100644 src/com/android/gallery3d/data/ClusterAlbum.java delete mode 100644 src/com/android/gallery3d/data/ClusterAlbumSet.java delete mode 100644 src/com/android/gallery3d/data/ClusterSource.java delete mode 100644 src/com/android/gallery3d/data/Clustering.java delete mode 100644 src/com/android/gallery3d/data/ComboAlbum.java delete mode 100644 src/com/android/gallery3d/data/ComboAlbumSet.java delete mode 100644 src/com/android/gallery3d/data/ComboSource.java delete mode 100644 src/com/android/gallery3d/data/ContentListener.java delete mode 100644 src/com/android/gallery3d/data/DataManager.java delete mode 100644 src/com/android/gallery3d/data/DataSourceType.java delete mode 100644 src/com/android/gallery3d/data/DecodeUtils.java delete mode 100644 src/com/android/gallery3d/data/DownloadCache.java delete mode 100644 src/com/android/gallery3d/data/DownloadEntry.java delete mode 100644 src/com/android/gallery3d/data/DownloadUtils.java delete mode 100644 src/com/android/gallery3d/data/EmptyAlbumImage.java delete mode 100644 src/com/android/gallery3d/data/Exif.java delete mode 100644 src/com/android/gallery3d/data/Face.java delete mode 100644 src/com/android/gallery3d/data/FaceClustering.java delete mode 100644 src/com/android/gallery3d/data/FilterDeleteSet.java delete mode 100644 src/com/android/gallery3d/data/FilterEmptyPromptSet.java delete mode 100644 src/com/android/gallery3d/data/FilterSource.java delete mode 100644 src/com/android/gallery3d/data/FilterTypeSet.java delete mode 100644 src/com/android/gallery3d/data/ImageCacheRequest.java delete mode 100644 src/com/android/gallery3d/data/ImageCacheService.java delete mode 100644 src/com/android/gallery3d/data/LocalAlbum.java delete mode 100644 src/com/android/gallery3d/data/LocalAlbumSet.java delete mode 100644 src/com/android/gallery3d/data/LocalImage.java delete mode 100644 src/com/android/gallery3d/data/LocalMediaItem.java delete mode 100644 src/com/android/gallery3d/data/LocalMergeAlbum.java delete mode 100644 src/com/android/gallery3d/data/LocalSource.java delete mode 100644 src/com/android/gallery3d/data/LocalVideo.java delete mode 100644 src/com/android/gallery3d/data/LocationClustering.java delete mode 100644 src/com/android/gallery3d/data/Log.java delete mode 100644 src/com/android/gallery3d/data/MediaDetails.java delete mode 100644 src/com/android/gallery3d/data/MediaItem.java delete mode 100644 src/com/android/gallery3d/data/MediaObject.java delete mode 100644 src/com/android/gallery3d/data/MediaSet.java delete mode 100644 src/com/android/gallery3d/data/MediaSource.java delete mode 100644 src/com/android/gallery3d/data/MtpClient.java delete mode 100644 src/com/android/gallery3d/data/PanoramaMetadataJob.java delete mode 100644 src/com/android/gallery3d/data/Path.java delete mode 100644 src/com/android/gallery3d/data/PathMatcher.java delete mode 100644 src/com/android/gallery3d/data/SecureAlbum.java delete mode 100644 src/com/android/gallery3d/data/SecureSource.java delete mode 100644 src/com/android/gallery3d/data/SingleItemAlbum.java delete mode 100644 src/com/android/gallery3d/data/SizeClustering.java delete mode 100644 src/com/android/gallery3d/data/SnailAlbum.java delete mode 100644 src/com/android/gallery3d/data/SnailItem.java delete mode 100644 src/com/android/gallery3d/data/SnailSource.java delete mode 100644 src/com/android/gallery3d/data/TagClustering.java delete mode 100644 src/com/android/gallery3d/data/TimeClustering.java delete mode 100644 src/com/android/gallery3d/data/UnlockImage.java delete mode 100644 src/com/android/gallery3d/data/UriImage.java delete mode 100644 src/com/android/gallery3d/data/UriSource.java delete mode 100644 src/com/android/gallery3d/filtershow/CenteredLinearLayout.java delete mode 100644 src/com/android/gallery3d/filtershow/EditorPlaceHolder.java delete mode 100644 src/com/android/gallery3d/filtershow/FilterShowActivity.java delete mode 100644 src/com/android/gallery3d/filtershow/cache/ImageLoader.java delete mode 100644 src/com/android/gallery3d/filtershow/category/Action.java delete mode 100644 src/com/android/gallery3d/filtershow/category/CategoryAdapter.java delete mode 100644 src/com/android/gallery3d/filtershow/category/CategoryPanel.java delete mode 100644 src/com/android/gallery3d/filtershow/category/CategoryTrack.java delete mode 100644 src/com/android/gallery3d/filtershow/category/CategoryView.java delete mode 100644 src/com/android/gallery3d/filtershow/category/MainPanel.java delete mode 100644 src/com/android/gallery3d/filtershow/colorpicker/ColorGridDialog.java delete mode 100644 src/com/android/gallery3d/filtershow/colorpicker/ColorListener.java delete mode 100644 src/com/android/gallery3d/filtershow/colorpicker/ColorOpacityView.java delete mode 100644 src/com/android/gallery3d/filtershow/colorpicker/ColorPickerDialog.java delete mode 100644 src/com/android/gallery3d/filtershow/colorpicker/ColorRectView.java delete mode 100644 src/com/android/gallery3d/filtershow/colorpicker/ColorValueView.java delete mode 100644 src/com/android/gallery3d/filtershow/colorpicker/RGBListener.java delete mode 100644 src/com/android/gallery3d/filtershow/controller/ActionSlider.java delete mode 100644 src/com/android/gallery3d/filtershow/controller/BasicParameterInt.java delete mode 100644 src/com/android/gallery3d/filtershow/controller/BasicParameterStyle.java delete mode 100644 src/com/android/gallery3d/filtershow/controller/BasicSlider.java delete mode 100644 src/com/android/gallery3d/filtershow/controller/Control.java delete mode 100644 src/com/android/gallery3d/filtershow/controller/FilterView.java delete mode 100644 src/com/android/gallery3d/filtershow/controller/Parameter.java delete mode 100644 src/com/android/gallery3d/filtershow/controller/ParameterActionAndInt.java delete mode 100644 src/com/android/gallery3d/filtershow/controller/ParameterInteger.java delete mode 100644 src/com/android/gallery3d/filtershow/controller/ParameterSet.java delete mode 100644 src/com/android/gallery3d/filtershow/controller/ParameterStyles.java delete mode 100644 src/com/android/gallery3d/filtershow/controller/StyleChooser.java delete mode 100644 src/com/android/gallery3d/filtershow/controller/TitledSlider.java delete mode 100644 src/com/android/gallery3d/filtershow/crop/BoundedRect.java delete mode 100644 src/com/android/gallery3d/filtershow/crop/CropActivity.java delete mode 100644 src/com/android/gallery3d/filtershow/crop/CropDrawingUtils.java delete mode 100644 src/com/android/gallery3d/filtershow/crop/CropExtras.java delete mode 100644 src/com/android/gallery3d/filtershow/crop/CropMath.java delete mode 100644 src/com/android/gallery3d/filtershow/crop/CropObject.java delete mode 100644 src/com/android/gallery3d/filtershow/crop/CropView.java delete mode 100644 src/com/android/gallery3d/filtershow/data/FilterStackDBHelper.java delete mode 100644 src/com/android/gallery3d/filtershow/data/FilterStackSource.java delete mode 100644 src/com/android/gallery3d/filtershow/data/UserPresetsManager.java delete mode 100644 src/com/android/gallery3d/filtershow/editors/BasicEditor.java delete mode 100644 src/com/android/gallery3d/filtershow/editors/Editor.java delete mode 100644 src/com/android/gallery3d/filtershow/editors/EditorChanSat.java delete mode 100644 src/com/android/gallery3d/filtershow/editors/EditorCrop.java delete mode 100644 src/com/android/gallery3d/filtershow/editors/EditorCurves.java delete mode 100644 src/com/android/gallery3d/filtershow/editors/EditorDraw.java delete mode 100644 src/com/android/gallery3d/filtershow/editors/EditorGrad.java delete mode 100644 src/com/android/gallery3d/filtershow/editors/EditorInfo.java delete mode 100644 src/com/android/gallery3d/filtershow/editors/EditorMirror.java delete mode 100644 src/com/android/gallery3d/filtershow/editors/EditorPanel.java delete mode 100644 src/com/android/gallery3d/filtershow/editors/EditorRedEye.java delete mode 100644 src/com/android/gallery3d/filtershow/editors/EditorRotate.java delete mode 100644 src/com/android/gallery3d/filtershow/editors/EditorStraighten.java delete mode 100644 src/com/android/gallery3d/filtershow/editors/EditorTinyPlanet.java delete mode 100644 src/com/android/gallery3d/filtershow/editors/EditorVignette.java delete mode 100644 src/com/android/gallery3d/filtershow/editors/EditorZoom.java delete mode 100644 src/com/android/gallery3d/filtershow/editors/ImageOnlyEditor.java delete mode 100644 src/com/android/gallery3d/filtershow/editors/ParametricEditor.java delete mode 100644 src/com/android/gallery3d/filtershow/editors/SwapButton.java delete mode 100644 src/com/android/gallery3d/filtershow/filters/BaseFiltersManager.java delete mode 100644 src/com/android/gallery3d/filtershow/filters/ColorSpaceMatrix.java delete mode 100644 src/com/android/gallery3d/filtershow/filters/FilterBasicRepresentation.java delete mode 100644 src/com/android/gallery3d/filtershow/filters/FilterChanSatRepresentation.java delete mode 100644 src/com/android/gallery3d/filtershow/filters/FilterColorBorderRepresentation.java delete mode 100644 src/com/android/gallery3d/filtershow/filters/FilterCropRepresentation.java delete mode 100644 src/com/android/gallery3d/filtershow/filters/FilterCurvesRepresentation.java delete mode 100644 src/com/android/gallery3d/filtershow/filters/FilterDirectRepresentation.java delete mode 100644 src/com/android/gallery3d/filtershow/filters/FilterDrawRepresentation.java delete mode 100644 src/com/android/gallery3d/filtershow/filters/FilterFxRepresentation.java delete mode 100644 src/com/android/gallery3d/filtershow/filters/FilterGradRepresentation.java delete mode 100644 src/com/android/gallery3d/filtershow/filters/FilterImageBorderRepresentation.java delete mode 100644 src/com/android/gallery3d/filtershow/filters/FilterMirrorRepresentation.java delete mode 100644 src/com/android/gallery3d/filtershow/filters/FilterPoint.java delete mode 100644 src/com/android/gallery3d/filtershow/filters/FilterPointRepresentation.java delete mode 100644 src/com/android/gallery3d/filtershow/filters/FilterRedEyeRepresentation.java delete mode 100644 src/com/android/gallery3d/filtershow/filters/FilterRepresentation.java delete mode 100644 src/com/android/gallery3d/filtershow/filters/FilterRotateRepresentation.java delete mode 100644 src/com/android/gallery3d/filtershow/filters/FilterStraightenRepresentation.java delete mode 100644 src/com/android/gallery3d/filtershow/filters/FilterTinyPlanetRepresentation.java delete mode 100644 src/com/android/gallery3d/filtershow/filters/FilterUserPresetRepresentation.java delete mode 100644 src/com/android/gallery3d/filtershow/filters/FilterVignetteRepresentation.java delete mode 100644 src/com/android/gallery3d/filtershow/filters/FiltersManagerInterface.java delete mode 100644 src/com/android/gallery3d/filtershow/filters/IconUtilities.java delete mode 100644 src/com/android/gallery3d/filtershow/filters/ImageFilter.java delete mode 100644 src/com/android/gallery3d/filtershow/filters/ImageFilterBorder.java delete mode 100644 src/com/android/gallery3d/filtershow/filters/ImageFilterBwFilter.java delete mode 100644 src/com/android/gallery3d/filtershow/filters/ImageFilterChanSat.java delete mode 100644 src/com/android/gallery3d/filtershow/filters/ImageFilterContrast.java delete mode 100644 src/com/android/gallery3d/filtershow/filters/ImageFilterCurves.java delete mode 100644 src/com/android/gallery3d/filtershow/filters/ImageFilterDownsample.java delete mode 100644 src/com/android/gallery3d/filtershow/filters/ImageFilterDraw.java delete mode 100644 src/com/android/gallery3d/filtershow/filters/ImageFilterEdge.java delete mode 100644 src/com/android/gallery3d/filtershow/filters/ImageFilterExposure.java delete mode 100644 src/com/android/gallery3d/filtershow/filters/ImageFilterFx.java delete mode 100644 src/com/android/gallery3d/filtershow/filters/ImageFilterGrad.java delete mode 100644 src/com/android/gallery3d/filtershow/filters/ImageFilterHighlights.java delete mode 100644 src/com/android/gallery3d/filtershow/filters/ImageFilterHue.java delete mode 100644 src/com/android/gallery3d/filtershow/filters/ImageFilterKMeans.java delete mode 100644 src/com/android/gallery3d/filtershow/filters/ImageFilterNegative.java delete mode 100644 src/com/android/gallery3d/filtershow/filters/ImageFilterParametricBorder.java delete mode 100644 src/com/android/gallery3d/filtershow/filters/ImageFilterRS.java delete mode 100644 src/com/android/gallery3d/filtershow/filters/ImageFilterRedEye.java delete mode 100644 src/com/android/gallery3d/filtershow/filters/ImageFilterSaturated.java delete mode 100644 src/com/android/gallery3d/filtershow/filters/ImageFilterShadows.java delete mode 100644 src/com/android/gallery3d/filtershow/filters/ImageFilterSharpen.java delete mode 100644 src/com/android/gallery3d/filtershow/filters/ImageFilterTinyPlanet.java delete mode 100644 src/com/android/gallery3d/filtershow/filters/ImageFilterVibrance.java delete mode 100644 src/com/android/gallery3d/filtershow/filters/ImageFilterVignette.java delete mode 100644 src/com/android/gallery3d/filtershow/filters/ImageFilterWBalance.java delete mode 100644 src/com/android/gallery3d/filtershow/filters/RedEyeCandidate.java delete mode 100644 src/com/android/gallery3d/filtershow/filters/SimpleImageFilter.java delete mode 100644 src/com/android/gallery3d/filtershow/filters/SplineMath.java delete mode 100644 src/com/android/gallery3d/filtershow/filters/convolve3x3.rs delete mode 100644 src/com/android/gallery3d/filtershow/filters/grad.rs delete mode 100644 src/com/android/gallery3d/filtershow/filters/grey.rs delete mode 100644 src/com/android/gallery3d/filtershow/filters/saturation.rs delete mode 100644 src/com/android/gallery3d/filtershow/history/HistoryItem.java delete mode 100644 src/com/android/gallery3d/filtershow/history/HistoryManager.java delete mode 100644 src/com/android/gallery3d/filtershow/imageshow/ControlPoint.java delete mode 100644 src/com/android/gallery3d/filtershow/imageshow/EclipseControl.java delete mode 100644 src/com/android/gallery3d/filtershow/imageshow/GeometryMathUtils.java delete mode 100644 src/com/android/gallery3d/filtershow/imageshow/GradControl.java delete mode 100644 src/com/android/gallery3d/filtershow/imageshow/ImageCrop.java delete mode 100644 src/com/android/gallery3d/filtershow/imageshow/ImageCurves.java delete mode 100644 src/com/android/gallery3d/filtershow/imageshow/ImageDraw.java delete mode 100644 src/com/android/gallery3d/filtershow/imageshow/ImageGrad.java delete mode 100644 src/com/android/gallery3d/filtershow/imageshow/ImageMirror.java delete mode 100644 src/com/android/gallery3d/filtershow/imageshow/ImagePoint.java delete mode 100644 src/com/android/gallery3d/filtershow/imageshow/ImageRedEye.java delete mode 100644 src/com/android/gallery3d/filtershow/imageshow/ImageRotate.java delete mode 100644 src/com/android/gallery3d/filtershow/imageshow/ImageShow.java delete mode 100644 src/com/android/gallery3d/filtershow/imageshow/ImageStraighten.java delete mode 100644 src/com/android/gallery3d/filtershow/imageshow/ImageTinyPlanet.java delete mode 100644 src/com/android/gallery3d/filtershow/imageshow/ImageVignette.java delete mode 100644 src/com/android/gallery3d/filtershow/imageshow/Line.java delete mode 100644 src/com/android/gallery3d/filtershow/imageshow/MasterImage.java delete mode 100644 src/com/android/gallery3d/filtershow/imageshow/Oval.java delete mode 100644 src/com/android/gallery3d/filtershow/imageshow/Spline.java delete mode 100644 src/com/android/gallery3d/filtershow/pipeline/Buffer.java delete mode 100644 src/com/android/gallery3d/filtershow/pipeline/CacheProcessing.java delete mode 100644 src/com/android/gallery3d/filtershow/pipeline/CachingPipeline.java delete mode 100644 src/com/android/gallery3d/filtershow/pipeline/FilterEnvironment.java delete mode 100644 src/com/android/gallery3d/filtershow/pipeline/HighresRenderingRequestTask.java delete mode 100644 src/com/android/gallery3d/filtershow/pipeline/ImagePreset.java delete mode 100644 src/com/android/gallery3d/filtershow/pipeline/ImageSavingTask.java delete mode 100644 src/com/android/gallery3d/filtershow/pipeline/PipelineInterface.java delete mode 100644 src/com/android/gallery3d/filtershow/pipeline/ProcessingService.java delete mode 100644 src/com/android/gallery3d/filtershow/pipeline/ProcessingTask.java delete mode 100644 src/com/android/gallery3d/filtershow/pipeline/ProcessingTaskController.java delete mode 100644 src/com/android/gallery3d/filtershow/pipeline/RenderingRequest.java delete mode 100644 src/com/android/gallery3d/filtershow/pipeline/RenderingRequestCaller.java delete mode 100644 src/com/android/gallery3d/filtershow/pipeline/RenderingRequestTask.java delete mode 100644 src/com/android/gallery3d/filtershow/pipeline/SharedBuffer.java delete mode 100644 src/com/android/gallery3d/filtershow/pipeline/SharedPreset.java delete mode 100644 src/com/android/gallery3d/filtershow/pipeline/UpdatePreviewTask.java delete mode 100644 src/com/android/gallery3d/filtershow/presets/PresetManagementDialog.java delete mode 100644 src/com/android/gallery3d/filtershow/presets/UserPresetsAdapter.java delete mode 100644 src/com/android/gallery3d/filtershow/provider/SharedImageProvider.java delete mode 100644 src/com/android/gallery3d/filtershow/state/DragListener.java delete mode 100644 src/com/android/gallery3d/filtershow/state/PanelTrack.java delete mode 100644 src/com/android/gallery3d/filtershow/state/State.java delete mode 100644 src/com/android/gallery3d/filtershow/state/StateAdapter.java delete mode 100644 src/com/android/gallery3d/filtershow/state/StatePanel.java delete mode 100644 src/com/android/gallery3d/filtershow/state/StatePanelTrack.java delete mode 100644 src/com/android/gallery3d/filtershow/state/StateView.java delete mode 100644 src/com/android/gallery3d/filtershow/tools/IconFactory.java delete mode 100644 src/com/android/gallery3d/filtershow/tools/MatrixFit.java delete mode 100644 src/com/android/gallery3d/filtershow/tools/SaveImage.java delete mode 100644 src/com/android/gallery3d/filtershow/tools/XmpPresets.java delete mode 100644 src/com/android/gallery3d/filtershow/ui/ExportDialog.java delete mode 100644 src/com/android/gallery3d/filtershow/ui/FramedTextButton.java delete mode 100644 src/com/android/gallery3d/filtershow/ui/SelectionRenderer.java delete mode 100644 src/com/android/gallery3d/gadget/LocalPhotoSource.java delete mode 100644 src/com/android/gallery3d/gadget/MediaSetSource.java delete mode 100644 src/com/android/gallery3d/gadget/PhotoAppWidgetProvider.java delete mode 100644 src/com/android/gallery3d/gadget/WidgetClickHandler.java delete mode 100644 src/com/android/gallery3d/gadget/WidgetConfigure.java delete mode 100644 src/com/android/gallery3d/gadget/WidgetDatabaseHelper.java delete mode 100644 src/com/android/gallery3d/gadget/WidgetService.java delete mode 100644 src/com/android/gallery3d/gadget/WidgetSource.java delete mode 100644 src/com/android/gallery3d/gadget/WidgetTypeChooser.java delete mode 100644 src/com/android/gallery3d/gadget/WidgetUtils.java delete mode 100644 src/com/android/gallery3d/glrenderer/BasicTexture.java delete mode 100644 src/com/android/gallery3d/glrenderer/BitmapTexture.java delete mode 100644 src/com/android/gallery3d/glrenderer/CanvasTexture.java delete mode 100644 src/com/android/gallery3d/glrenderer/ColorTexture.java delete mode 100644 src/com/android/gallery3d/glrenderer/ExtTexture.java delete mode 100644 src/com/android/gallery3d/glrenderer/FadeInTexture.java delete mode 100644 src/com/android/gallery3d/glrenderer/FadeOutTexture.java delete mode 100644 src/com/android/gallery3d/glrenderer/FadeTexture.java delete mode 100644 src/com/android/gallery3d/glrenderer/GLCanvas.java delete mode 100644 src/com/android/gallery3d/glrenderer/GLES11Canvas.java delete mode 100644 src/com/android/gallery3d/glrenderer/GLES11IdImpl.java delete mode 100644 src/com/android/gallery3d/glrenderer/GLES20Canvas.java delete mode 100644 src/com/android/gallery3d/glrenderer/GLES20IdImpl.java delete mode 100644 src/com/android/gallery3d/glrenderer/GLId.java delete mode 100644 src/com/android/gallery3d/glrenderer/GLPaint.java delete mode 100644 src/com/android/gallery3d/glrenderer/MultiLineTexture.java delete mode 100644 src/com/android/gallery3d/glrenderer/NinePatchChunk.java delete mode 100644 src/com/android/gallery3d/glrenderer/NinePatchTexture.java delete mode 100644 src/com/android/gallery3d/glrenderer/RawTexture.java delete mode 100644 src/com/android/gallery3d/glrenderer/ResourceTexture.java delete mode 100644 src/com/android/gallery3d/glrenderer/StringTexture.java delete mode 100644 src/com/android/gallery3d/glrenderer/Texture.java delete mode 100644 src/com/android/gallery3d/glrenderer/TextureUploader.java delete mode 100644 src/com/android/gallery3d/glrenderer/TiledTexture.java delete mode 100644 src/com/android/gallery3d/glrenderer/UploadedTexture.java delete mode 100644 src/com/android/gallery3d/ingest/ImportTask.java delete mode 100644 src/com/android/gallery3d/ingest/IngestActivity.java delete mode 100644 src/com/android/gallery3d/ingest/IngestService.java delete mode 100644 src/com/android/gallery3d/ingest/MtpDeviceIndex.java delete mode 100644 src/com/android/gallery3d/ingest/SimpleDate.java delete mode 100644 src/com/android/gallery3d/ingest/adapter/CheckBroker.java delete mode 100644 src/com/android/gallery3d/ingest/adapter/MtpAdapter.java delete mode 100644 src/com/android/gallery3d/ingest/adapter/MtpPagerAdapter.java delete mode 100644 src/com/android/gallery3d/ingest/data/BitmapWithMetadata.java delete mode 100644 src/com/android/gallery3d/ingest/data/MtpBitmapFetch.java delete mode 100644 src/com/android/gallery3d/ingest/ui/DateTileView.java delete mode 100644 src/com/android/gallery3d/ingest/ui/IngestGridView.java delete mode 100644 src/com/android/gallery3d/ingest/ui/MtpFullscreenView.java delete mode 100644 src/com/android/gallery3d/ingest/ui/MtpImageView.java delete mode 100644 src/com/android/gallery3d/ingest/ui/MtpThumbnailTileView.java delete mode 100644 src/com/android/gallery3d/onetimeinitializer/GalleryWidgetMigrator.java delete mode 100644 src/com/android/gallery3d/provider/GalleryProvider.java delete mode 100644 src/com/android/gallery3d/ui/AbstractSlotRenderer.java delete mode 100644 src/com/android/gallery3d/ui/ActionModeHandler.java delete mode 100644 src/com/android/gallery3d/ui/AlbumLabelMaker.java delete mode 100644 src/com/android/gallery3d/ui/AlbumSetSlidingWindow.java delete mode 100644 src/com/android/gallery3d/ui/AlbumSetSlotRenderer.java delete mode 100644 src/com/android/gallery3d/ui/AlbumSlidingWindow.java delete mode 100644 src/com/android/gallery3d/ui/AlbumSlotRenderer.java delete mode 100644 src/com/android/gallery3d/ui/AnimationTime.java delete mode 100644 src/com/android/gallery3d/ui/BitmapLoader.java delete mode 100644 src/com/android/gallery3d/ui/BitmapScreenNail.java delete mode 100644 src/com/android/gallery3d/ui/BitmapTileProvider.java delete mode 100644 src/com/android/gallery3d/ui/CacheStorageUsageInfo.java delete mode 100644 src/com/android/gallery3d/ui/CaptureAnimation.java delete mode 100644 src/com/android/gallery3d/ui/DetailsAddressResolver.java delete mode 100644 src/com/android/gallery3d/ui/DetailsHelper.java delete mode 100644 src/com/android/gallery3d/ui/DialogDetailsView.java delete mode 100644 src/com/android/gallery3d/ui/DownUpDetector.java delete mode 100644 src/com/android/gallery3d/ui/EdgeEffect.java delete mode 100644 src/com/android/gallery3d/ui/EdgeView.java delete mode 100644 src/com/android/gallery3d/ui/FlingScroller.java delete mode 100644 src/com/android/gallery3d/ui/GLRoot.java delete mode 100644 src/com/android/gallery3d/ui/GLRootView.java delete mode 100644 src/com/android/gallery3d/ui/GLView.java delete mode 100644 src/com/android/gallery3d/ui/GestureRecognizer.java delete mode 100644 src/com/android/gallery3d/ui/Log.java delete mode 100644 src/com/android/gallery3d/ui/ManageCacheDrawer.java delete mode 100644 src/com/android/gallery3d/ui/MeasureHelper.java delete mode 100644 src/com/android/gallery3d/ui/MenuExecutor.java delete mode 100644 src/com/android/gallery3d/ui/OrientationSource.java delete mode 100644 src/com/android/gallery3d/ui/Paper.java delete mode 100644 src/com/android/gallery3d/ui/PhotoFallbackEffect.java delete mode 100644 src/com/android/gallery3d/ui/PhotoView.java delete mode 100644 src/com/android/gallery3d/ui/PopupList.java delete mode 100644 src/com/android/gallery3d/ui/PositionController.java delete mode 100644 src/com/android/gallery3d/ui/PreparePageFadeoutTexture.java delete mode 100644 src/com/android/gallery3d/ui/ProgressSpinner.java delete mode 100644 src/com/android/gallery3d/ui/RelativePosition.java delete mode 100644 src/com/android/gallery3d/ui/ScreenNail.java delete mode 100644 src/com/android/gallery3d/ui/ScrollBarView.java delete mode 100644 src/com/android/gallery3d/ui/ScrollerHelper.java delete mode 100644 src/com/android/gallery3d/ui/SelectionManager.java delete mode 100644 src/com/android/gallery3d/ui/SelectionMenu.java delete mode 100644 src/com/android/gallery3d/ui/SlideshowView.java delete mode 100644 src/com/android/gallery3d/ui/SlotView.java delete mode 100644 src/com/android/gallery3d/ui/SurfaceTextureScreenNail.java delete mode 100644 src/com/android/gallery3d/ui/SynchronizedHandler.java delete mode 100644 src/com/android/gallery3d/ui/TileImageView.java delete mode 100644 src/com/android/gallery3d/ui/TileImageViewAdapter.java delete mode 100644 src/com/android/gallery3d/ui/TiledScreenNail.java delete mode 100644 src/com/android/gallery3d/ui/UndoBarView.java delete mode 100644 src/com/android/gallery3d/ui/UserInteractionListener.java delete mode 100644 src/com/android/gallery3d/ui/WakeLockHoldingProgressListener.java delete mode 100644 src/com/android/gallery3d/util/AccessibilityUtils.java delete mode 100644 src/com/android/gallery3d/util/BucketNames.java delete mode 100644 src/com/android/gallery3d/util/CacheManager.java delete mode 100644 src/com/android/gallery3d/util/GalleryUtils.java delete mode 100644 src/com/android/gallery3d/util/Holder.java delete mode 100644 src/com/android/gallery3d/util/IdentityCache.java delete mode 100644 src/com/android/gallery3d/util/IntArray.java delete mode 100644 src/com/android/gallery3d/util/InterruptableOutputStream.java delete mode 100644 src/com/android/gallery3d/util/JobLimiter.java delete mode 100644 src/com/android/gallery3d/util/LinkedNode.java delete mode 100644 src/com/android/gallery3d/util/Log.java delete mode 100644 src/com/android/gallery3d/util/MediaSetUtils.java delete mode 100644 src/com/android/gallery3d/util/MotionEventHelper.java delete mode 100644 src/com/android/gallery3d/util/Profile.java delete mode 100644 src/com/android/gallery3d/util/ProfileData.java delete mode 100644 src/com/android/gallery3d/util/RangeArray.java delete mode 100644 src/com/android/gallery3d/util/RangeBoolArray.java delete mode 100644 src/com/android/gallery3d/util/RangeIntArray.java delete mode 100644 src/com/android/gallery3d/util/ReverseGeocoder.java delete mode 100644 src/com/android/gallery3d/util/SaveVideoFileInfo.java delete mode 100644 src/com/android/gallery3d/util/SaveVideoFileUtils.java delete mode 100644 src/com/android/gallery3d/util/UpdateHelper.java (limited to 'src/com/android/gallery3d') diff --git a/src/com/android/gallery3d/anim/AlphaAnimation.java b/src/com/android/gallery3d/anim/AlphaAnimation.java deleted file mode 100644 index f9f4cbd2c..000000000 --- a/src/com/android/gallery3d/anim/AlphaAnimation.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * 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.gallery3d.anim; - -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.glrenderer.GLCanvas; - -public class AlphaAnimation extends CanvasAnimation { - private final float mStartAlpha; - private final float mEndAlpha; - private float mCurrentAlpha; - - public AlphaAnimation(float from, float to) { - mStartAlpha = from; - mEndAlpha = to; - mCurrentAlpha = from; - } - - @Override - public void apply(GLCanvas canvas) { - canvas.multiplyAlpha(mCurrentAlpha); - } - - @Override - public int getCanvasSaveFlags() { - return GLCanvas.SAVE_FLAG_ALPHA; - } - - @Override - protected void onCalculate(float progress) { - mCurrentAlpha = Utils.clamp(mStartAlpha - + (mEndAlpha - mStartAlpha) * progress, 0f, 1f); - } -} diff --git a/src/com/android/gallery3d/anim/Animation.java b/src/com/android/gallery3d/anim/Animation.java deleted file mode 100644 index cc117bbce..000000000 --- a/src/com/android/gallery3d/anim/Animation.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * 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.gallery3d.anim; - -import android.view.animation.Interpolator; - -import com.android.gallery3d.common.Utils; - -// Animation calculates a value according to the current input time. -// -// 1. First we need to use setDuration(int) to set the duration of the -// animation. The duration is in milliseconds. -// 2. Then we should call start(). The actual start time is the first value -// passed to calculate(long). -// 3. Each time we want to get an animation value, we call -// calculate(long currentTimeMillis) to ask the Animation to calculate it. -// The parameter passed to calculate(long) should be nonnegative. -// 4. Use get() to get that value. -// -// In step 3, onCalculate(float progress) is called so subclasses can calculate -// the value according to progress (progress is a value in [0,1]). -// -// Before onCalculate(float) is called, There is an optional interpolator which -// can change the progress value. The interpolator can be set by -// setInterpolator(Interpolator). If the interpolator is used, the value passed -// to onCalculate may be (for example, the overshoot effect). -// -// The isActive() method returns true after the animation start() is called and -// before calculate is passed a value which reaches the duration of the -// animation. -// -// The start() method can be called again to restart the Animation. -// -abstract public class Animation { - private static final long ANIMATION_START = -1; - private static final long NO_ANIMATION = -2; - - private long mStartTime = NO_ANIMATION; - private int mDuration; - private Interpolator mInterpolator; - - public void setInterpolator(Interpolator interpolator) { - mInterpolator = interpolator; - } - - public void setDuration(int duration) { - mDuration = duration; - } - - public void start() { - mStartTime = ANIMATION_START; - } - - public void setStartTime(long time) { - mStartTime = time; - } - - public boolean isActive() { - return mStartTime != NO_ANIMATION; - } - - public void forceStop() { - mStartTime = NO_ANIMATION; - } - - public boolean calculate(long currentTimeMillis) { - if (mStartTime == NO_ANIMATION) return false; - if (mStartTime == ANIMATION_START) mStartTime = currentTimeMillis; - int elapse = (int) (currentTimeMillis - mStartTime); - float x = Utils.clamp((float) elapse / mDuration, 0f, 1f); - Interpolator i = mInterpolator; - onCalculate(i != null ? i.getInterpolation(x) : x); - if (elapse >= mDuration) mStartTime = NO_ANIMATION; - return mStartTime != NO_ANIMATION; - } - - abstract protected void onCalculate(float progress); -} diff --git a/src/com/android/gallery3d/anim/CanvasAnimation.java b/src/com/android/gallery3d/anim/CanvasAnimation.java deleted file mode 100644 index cdc66c6ba..000000000 --- a/src/com/android/gallery3d/anim/CanvasAnimation.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * 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.gallery3d.anim; - -import com.android.gallery3d.glrenderer.GLCanvas; - -public abstract class CanvasAnimation extends Animation { - - public abstract int getCanvasSaveFlags(); - public abstract void apply(GLCanvas canvas); -} diff --git a/src/com/android/gallery3d/anim/FloatAnimation.java b/src/com/android/gallery3d/anim/FloatAnimation.java deleted file mode 100644 index 1294ec2f4..000000000 --- a/src/com/android/gallery3d/anim/FloatAnimation.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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.gallery3d.anim; - -public class FloatAnimation extends Animation { - - private final float mFrom; - private final float mTo; - private float mCurrent; - - public FloatAnimation(float from, float to, int duration) { - mFrom = from; - mTo = to; - mCurrent = from; - setDuration(duration); - } - - @Override - protected void onCalculate(float progress) { - mCurrent = mFrom + (mTo - mFrom) * progress; - } - - public float get() { - return mCurrent; - } -} diff --git a/src/com/android/gallery3d/anim/StateTransitionAnimation.java b/src/com/android/gallery3d/anim/StateTransitionAnimation.java deleted file mode 100644 index bf8a54405..000000000 --- a/src/com/android/gallery3d/anim/StateTransitionAnimation.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * 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. - */ - -package com.android.gallery3d.anim; - -import android.view.animation.AccelerateInterpolator; -import android.view.animation.DecelerateInterpolator; -import android.view.animation.Interpolator; - -import com.android.gallery3d.glrenderer.GLCanvas; -import com.android.gallery3d.glrenderer.RawTexture; -import com.android.gallery3d.ui.GLView; -import com.android.gallery3d.ui.TiledScreenNail; - -public class StateTransitionAnimation extends Animation { - - public static class Spec { - public static final Spec OUTGOING; - public static final Spec INCOMING; - public static final Spec PHOTO_INCOMING; - - private static final Interpolator DEFAULT_INTERPOLATOR = - new DecelerateInterpolator(); - - public int duration = 330; - public float backgroundAlphaFrom = 0; - public float backgroundAlphaTo = 0; - public float backgroundScaleFrom = 0; - public float backgroundScaleTo = 0; - public float contentAlphaFrom = 1; - public float contentAlphaTo = 1; - public float contentScaleFrom = 1; - public float contentScaleTo = 1; - public float overlayAlphaFrom = 0; - public float overlayAlphaTo = 0; - public float overlayScaleFrom = 0; - public float overlayScaleTo = 0; - public Interpolator interpolator = DEFAULT_INTERPOLATOR; - - static { - OUTGOING = new Spec(); - OUTGOING.backgroundAlphaFrom = 0.5f; - OUTGOING.backgroundAlphaTo = 0f; - OUTGOING.backgroundScaleFrom = 1f; - OUTGOING.backgroundScaleTo = 0f; - OUTGOING.contentAlphaFrom = 0.5f; - OUTGOING.contentAlphaTo = 1f; - OUTGOING.contentScaleFrom = 3f; - OUTGOING.contentScaleTo = 1f; - - INCOMING = new Spec(); - INCOMING.overlayAlphaFrom = 1f; - INCOMING.overlayAlphaTo = 0f; - INCOMING.overlayScaleFrom = 1f; - INCOMING.overlayScaleTo = 3f; - INCOMING.contentAlphaFrom = 0f; - INCOMING.contentAlphaTo = 1f; - INCOMING.contentScaleFrom = 0.25f; - INCOMING.contentScaleTo = 1f; - - PHOTO_INCOMING = INCOMING; - } - - private static Spec specForTransition(Transition t) { - switch (t) { - case Outgoing: - return Spec.OUTGOING; - case Incoming: - return Spec.INCOMING; - case PhotoIncoming: - return Spec.PHOTO_INCOMING; - case None: - default: - return null; - } - } - } - - public static enum Transition { None, Outgoing, Incoming, PhotoIncoming } - - private final Spec mTransitionSpec; - private float mCurrentContentScale; - private float mCurrentContentAlpha; - private float mCurrentBackgroundScale; - private float mCurrentBackgroundAlpha; - private float mCurrentOverlayScale; - private float mCurrentOverlayAlpha; - private RawTexture mOldScreenTexture; - - public StateTransitionAnimation(Transition t, RawTexture oldScreen) { - this(Spec.specForTransition(t), oldScreen); - } - - public StateTransitionAnimation(Spec spec, RawTexture oldScreen) { - mTransitionSpec = spec != null ? spec : Spec.OUTGOING; - setDuration(mTransitionSpec.duration); - setInterpolator(mTransitionSpec.interpolator); - mOldScreenTexture = oldScreen; - TiledScreenNail.disableDrawPlaceholder(); - } - - @Override - public boolean calculate(long currentTimeMillis) { - boolean retval = super.calculate(currentTimeMillis); - if (!isActive()) { - if (mOldScreenTexture != null) { - mOldScreenTexture.recycle(); - mOldScreenTexture = null; - } - TiledScreenNail.enableDrawPlaceholder(); - } - return retval; - } - - @Override - protected void onCalculate(float progress) { - mCurrentContentScale = mTransitionSpec.contentScaleFrom - + (mTransitionSpec.contentScaleTo - mTransitionSpec.contentScaleFrom) * progress; - mCurrentContentAlpha = mTransitionSpec.contentAlphaFrom - + (mTransitionSpec.contentAlphaTo - mTransitionSpec.contentAlphaFrom) * progress; - mCurrentBackgroundAlpha = mTransitionSpec.backgroundAlphaFrom - + (mTransitionSpec.backgroundAlphaTo - mTransitionSpec.backgroundAlphaFrom) - * progress; - mCurrentBackgroundScale = mTransitionSpec.backgroundScaleFrom - + (mTransitionSpec.backgroundScaleTo - mTransitionSpec.backgroundScaleFrom) - * progress; - mCurrentOverlayScale = mTransitionSpec.overlayScaleFrom - + (mTransitionSpec.overlayScaleTo - mTransitionSpec.overlayScaleFrom) * progress; - mCurrentOverlayAlpha = mTransitionSpec.overlayAlphaFrom - + (mTransitionSpec.overlayAlphaTo - mTransitionSpec.overlayAlphaFrom) * progress; - } - - private void applyOldTexture(GLView view, GLCanvas canvas, float alpha, float scale, boolean clear) { - if (mOldScreenTexture == null) - return; - if (clear) canvas.clearBuffer(view.getBackgroundColor()); - canvas.save(); - canvas.setAlpha(alpha); - int xOffset = view.getWidth() / 2; - int yOffset = view.getHeight() / 2; - canvas.translate(xOffset, yOffset); - canvas.scale(scale, scale, 1); - mOldScreenTexture.draw(canvas, -xOffset, -yOffset); - canvas.restore(); - } - - public void applyBackground(GLView view, GLCanvas canvas) { - if (mCurrentBackgroundAlpha > 0f) { - applyOldTexture(view, canvas, mCurrentBackgroundAlpha, mCurrentBackgroundScale, true); - } - } - - public void applyContentTransform(GLView view, GLCanvas canvas) { - int xOffset = view.getWidth() / 2; - int yOffset = view.getHeight() / 2; - canvas.translate(xOffset, yOffset); - canvas.scale(mCurrentContentScale, mCurrentContentScale, 1); - canvas.translate(-xOffset, -yOffset); - canvas.setAlpha(mCurrentContentAlpha); - } - - public void applyOverlay(GLView view, GLCanvas canvas) { - if (mCurrentOverlayAlpha > 0f) { - applyOldTexture(view, canvas, mCurrentOverlayAlpha, mCurrentOverlayScale, false); - } - } -} diff --git a/src/com/android/gallery3d/app/AbstractGalleryActivity.java b/src/com/android/gallery3d/app/AbstractGalleryActivity.java deleted file mode 100644 index ac39aa560..000000000 --- a/src/com/android/gallery3d/app/AbstractGalleryActivity.java +++ /dev/null @@ -1,343 +0,0 @@ -/* - * 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.gallery3d.app; - -import android.annotation.TargetApi; -import android.app.Activity; -import android.app.AlertDialog; -import android.content.BroadcastReceiver; -import android.content.ComponentName; -import android.content.Context; -import android.content.DialogInterface; -import android.content.DialogInterface.OnCancelListener; -import android.content.DialogInterface.OnClickListener; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.ServiceConnection; -import android.content.res.Configuration; -import android.os.Bundle; -import android.os.IBinder; -import android.view.Menu; -import android.view.MenuItem; -import android.view.Window; -import android.view.WindowManager; - -import com.android.gallery3d.R; -import com.android.gallery3d.common.ApiHelper; -import com.android.gallery3d.data.DataManager; -import com.android.gallery3d.data.MediaItem; -import com.android.gallery3d.ui.GLRoot; -import com.android.gallery3d.ui.GLRootView; -import com.android.gallery3d.util.LightCycleHelper.PanoramaViewHelper; -import com.android.gallery3d.util.ThreadPool; -import com.android.photos.data.GalleryBitmapPool; - -public class AbstractGalleryActivity extends Activity implements GalleryContext { - @SuppressWarnings("unused") - private static final String TAG = "AbstractGalleryActivity"; - private GLRootView mGLRootView; - private StateManager mStateManager; - private GalleryActionBar mActionBar; - private OrientationManager mOrientationManager; - private TransitionStore mTransitionStore = new TransitionStore(); - private boolean mDisableToggleStatusBar; - private PanoramaViewHelper mPanoramaViewHelper; - - private AlertDialog mAlertDialog = null; - private BroadcastReceiver mMountReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - if (getExternalCacheDir() != null) onStorageReady(); - } - }; - private IntentFilter mMountFilter = new IntentFilter(Intent.ACTION_MEDIA_MOUNTED); - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - mOrientationManager = new OrientationManager(this); - toggleStatusBarByOrientation(); - getWindow().setBackgroundDrawable(null); - mPanoramaViewHelper = new PanoramaViewHelper(this); - mPanoramaViewHelper.onCreate(); - doBindBatchService(); - } - - @Override - protected void onSaveInstanceState(Bundle outState) { - mGLRootView.lockRenderThread(); - try { - super.onSaveInstanceState(outState); - getStateManager().saveState(outState); - } finally { - mGLRootView.unlockRenderThread(); - } - } - - @Override - public void onConfigurationChanged(Configuration config) { - super.onConfigurationChanged(config); - mStateManager.onConfigurationChange(config); - getGalleryActionBar().onConfigurationChanged(); - invalidateOptionsMenu(); - toggleStatusBarByOrientation(); - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - super.onCreateOptionsMenu(menu); - return getStateManager().createOptionsMenu(menu); - } - - @Override - public Context getAndroidContext() { - return this; - } - - @Override - public DataManager getDataManager() { - return ((GalleryApp) getApplication()).getDataManager(); - } - - @Override - public ThreadPool getThreadPool() { - return ((GalleryApp) getApplication()).getThreadPool(); - } - - public synchronized StateManager getStateManager() { - if (mStateManager == null) { - mStateManager = new StateManager(this); - } - return mStateManager; - } - - public GLRoot getGLRoot() { - return mGLRootView; - } - - public OrientationManager getOrientationManager() { - return mOrientationManager; - } - - @Override - public void setContentView(int resId) { - super.setContentView(resId); - mGLRootView = (GLRootView) findViewById(R.id.gl_root_view); - } - - protected void onStorageReady() { - if (mAlertDialog != null) { - mAlertDialog.dismiss(); - mAlertDialog = null; - unregisterReceiver(mMountReceiver); - } - } - - @Override - protected void onStart() { - super.onStart(); - if (getExternalCacheDir() == null) { - OnCancelListener onCancel = new OnCancelListener() { - @Override - public void onCancel(DialogInterface dialog) { - finish(); - } - }; - OnClickListener onClick = new OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - dialog.cancel(); - } - }; - AlertDialog.Builder builder = new AlertDialog.Builder(this) - .setTitle(R.string.no_external_storage_title) - .setMessage(R.string.no_external_storage) - .setNegativeButton(android.R.string.cancel, onClick) - .setOnCancelListener(onCancel); - if (ApiHelper.HAS_SET_ICON_ATTRIBUTE) { - setAlertDialogIconAttribute(builder); - } else { - builder.setIcon(android.R.drawable.ic_dialog_alert); - } - mAlertDialog = builder.show(); - registerReceiver(mMountReceiver, mMountFilter); - } - mPanoramaViewHelper.onStart(); - } - - @TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB) - private static void setAlertDialogIconAttribute( - AlertDialog.Builder builder) { - builder.setIconAttribute(android.R.attr.alertDialogIcon); - } - - @Override - protected void onStop() { - super.onStop(); - if (mAlertDialog != null) { - unregisterReceiver(mMountReceiver); - mAlertDialog.dismiss(); - mAlertDialog = null; - } - mPanoramaViewHelper.onStop(); - } - - @Override - protected void onResume() { - super.onResume(); - mGLRootView.lockRenderThread(); - try { - getStateManager().resume(); - getDataManager().resume(); - } finally { - mGLRootView.unlockRenderThread(); - } - mGLRootView.onResume(); - mOrientationManager.resume(); - } - - @Override - protected void onPause() { - super.onPause(); - mOrientationManager.pause(); - mGLRootView.onPause(); - mGLRootView.lockRenderThread(); - try { - getStateManager().pause(); - getDataManager().pause(); - } finally { - mGLRootView.unlockRenderThread(); - } - GalleryBitmapPool.getInstance().clear(); - MediaItem.getBytesBufferPool().clear(); - } - - @Override - protected void onDestroy() { - super.onDestroy(); - mGLRootView.lockRenderThread(); - try { - getStateManager().destroy(); - } finally { - mGLRootView.unlockRenderThread(); - } - doUnbindBatchService(); - } - - @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { - mGLRootView.lockRenderThread(); - try { - getStateManager().notifyActivityResult( - requestCode, resultCode, data); - } finally { - mGLRootView.unlockRenderThread(); - } - } - - @Override - public void onBackPressed() { - // send the back event to the top sub-state - GLRoot root = getGLRoot(); - root.lockRenderThread(); - try { - getStateManager().onBackPressed(); - } finally { - root.unlockRenderThread(); - } - } - - public GalleryActionBar getGalleryActionBar() { - if (mActionBar == null) { - mActionBar = new GalleryActionBar(this); - } - return mActionBar; - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - GLRoot root = getGLRoot(); - root.lockRenderThread(); - try { - return getStateManager().itemSelected(item); - } finally { - root.unlockRenderThread(); - } - } - - protected void disableToggleStatusBar() { - mDisableToggleStatusBar = true; - } - - // Shows status bar in portrait view, hide in landscape view - private void toggleStatusBarByOrientation() { - if (mDisableToggleStatusBar) return; - - Window win = getWindow(); - if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) { - win.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); - } else { - win.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); - } - } - - public TransitionStore getTransitionStore() { - return mTransitionStore; - } - - public PanoramaViewHelper getPanoramaViewHelper() { - return mPanoramaViewHelper; - } - - protected boolean isFullscreen() { - return (getWindow().getAttributes().flags - & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0; - } - - private BatchService mBatchService; - private boolean mBatchServiceIsBound = false; - private ServiceConnection mBatchServiceConnection = new ServiceConnection() { - public void onServiceConnected(ComponentName className, IBinder service) { - mBatchService = ((BatchService.LocalBinder)service).getService(); - } - - public void onServiceDisconnected(ComponentName className) { - mBatchService = null; - } - }; - - private void doBindBatchService() { - bindService(new Intent(this, BatchService.class), mBatchServiceConnection, Context.BIND_AUTO_CREATE); - mBatchServiceIsBound = true; - } - - private void doUnbindBatchService() { - if (mBatchServiceIsBound) { - // Detach our existing connection. - unbindService(mBatchServiceConnection); - mBatchServiceIsBound = false; - } - } - - public ThreadPool getBatchServiceThreadPoolIfAvailable() { - if (mBatchServiceIsBound && mBatchService != null) { - return mBatchService.getThreadPool(); - } else { - throw new RuntimeException("Batch service unavailable"); - } - } -} diff --git a/src/com/android/gallery3d/app/ActivityState.java b/src/com/android/gallery3d/app/ActivityState.java deleted file mode 100644 index 2f1e0c9d9..000000000 --- a/src/com/android/gallery3d/app/ActivityState.java +++ /dev/null @@ -1,276 +0,0 @@ -/* - * 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.gallery3d.app; - -import android.app.ActionBar; -import android.app.Activity; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.res.Configuration; -import android.os.BatteryManager; -import android.os.Bundle; -import android.view.HapticFeedbackConstants; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; -import android.view.Window; -import android.view.WindowManager; - -import com.android.gallery3d.R; -import com.android.gallery3d.anim.StateTransitionAnimation; -import com.android.gallery3d.glrenderer.RawTexture; -import com.android.gallery3d.ui.GLView; -import com.android.gallery3d.ui.PreparePageFadeoutTexture; -import com.android.gallery3d.util.GalleryUtils; - -abstract public class ActivityState { - protected static final int FLAG_HIDE_ACTION_BAR = 1; - protected static final int FLAG_HIDE_STATUS_BAR = 2; - protected static final int FLAG_SCREEN_ON_WHEN_PLUGGED = 4; - protected static final int FLAG_SCREEN_ON_ALWAYS = 8; - protected static final int FLAG_ALLOW_LOCK_WHILE_SCREEN_ON = 16; - protected static final int FLAG_SHOW_WHEN_LOCKED = 32; - - protected AbstractGalleryActivity mActivity; - protected Bundle mData; - protected int mFlags; - - protected ResultEntry mReceivedResults; - protected ResultEntry mResult; - - protected static class ResultEntry { - public int requestCode; - public int resultCode = Activity.RESULT_CANCELED; - public Intent resultData; - } - - private boolean mDestroyed = false; - private boolean mPlugged = false; - boolean mIsFinishing = false; - - private static final String KEY_TRANSITION_IN = "transition-in"; - - private StateTransitionAnimation.Transition mNextTransition = - StateTransitionAnimation.Transition.None; - private StateTransitionAnimation mIntroAnimation; - private GLView mContentPane; - - protected ActivityState() { - } - - protected void setContentPane(GLView content) { - mContentPane = content; - if (mIntroAnimation != null) { - mContentPane.setIntroAnimation(mIntroAnimation); - mIntroAnimation = null; - } - mContentPane.setBackgroundColor(getBackgroundColor()); - mActivity.getGLRoot().setContentPane(mContentPane); - } - - void initialize(AbstractGalleryActivity activity, Bundle data) { - mActivity = activity; - mData = data; - } - - public Bundle getData() { - return mData; - } - - protected void onBackPressed() { - mActivity.getStateManager().finishState(this); - } - - protected void setStateResult(int resultCode, Intent data) { - if (mResult == null) return; - mResult.resultCode = resultCode; - mResult.resultData = data; - } - - protected void onConfigurationChanged(Configuration config) { - } - - protected void onSaveState(Bundle outState) { - } - - protected void onStateResult(int requestCode, int resultCode, Intent data) { - } - - protected float[] mBackgroundColor; - - protected int getBackgroundColorId() { - return R.color.default_background; - } - - protected float[] getBackgroundColor() { - return mBackgroundColor; - } - - protected void onCreate(Bundle data, Bundle storedState) { - mBackgroundColor = GalleryUtils.intColorToFloatARGBArray( - mActivity.getResources().getColor(getBackgroundColorId())); - } - - protected void clearStateResult() { - } - - BroadcastReceiver mPowerIntentReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - final String action = intent.getAction(); - if (Intent.ACTION_BATTERY_CHANGED.equals(action)) { - boolean plugged = (0 != intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0)); - - if (plugged != mPlugged) { - mPlugged = plugged; - setScreenFlags(); - } - } - } - }; - - private void setScreenFlags() { - final Window win = mActivity.getWindow(); - final WindowManager.LayoutParams params = win.getAttributes(); - if ((0 != (mFlags & FLAG_SCREEN_ON_ALWAYS)) || - (mPlugged && 0 != (mFlags & FLAG_SCREEN_ON_WHEN_PLUGGED))) { - params.flags |= WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON; - } else { - params.flags &= ~WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON; - } - if (0 != (mFlags & FLAG_ALLOW_LOCK_WHILE_SCREEN_ON)) { - params.flags |= WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON; - } else { - params.flags &= ~WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON; - } - if (0 != (mFlags & FLAG_SHOW_WHEN_LOCKED)) { - params.flags |= WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED; - } else { - params.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED; - } - win.setAttributes(params); - } - - protected void transitionOnNextPause(Class outgoing, - Class incoming, StateTransitionAnimation.Transition hint) { - if (outgoing == SinglePhotoPage.class && incoming == AlbumPage.class) { - mNextTransition = StateTransitionAnimation.Transition.Outgoing; - } else if (outgoing == AlbumPage.class && incoming == SinglePhotoPage.class) { - mNextTransition = StateTransitionAnimation.Transition.PhotoIncoming; - } else { - mNextTransition = hint; - } - } - - protected void performHapticFeedback(int feedbackConstant) { - mActivity.getWindow().getDecorView().performHapticFeedback(feedbackConstant, - HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING); - } - - protected void onPause() { - if (0 != (mFlags & FLAG_SCREEN_ON_WHEN_PLUGGED)) { - ((Activity) mActivity).unregisterReceiver(mPowerIntentReceiver); - } - if (mNextTransition != StateTransitionAnimation.Transition.None) { - mActivity.getTransitionStore().put(KEY_TRANSITION_IN, mNextTransition); - PreparePageFadeoutTexture.prepareFadeOutTexture(mActivity, mContentPane); - mNextTransition = StateTransitionAnimation.Transition.None; - } - } - - // should only be called by StateManager - void resume() { - AbstractGalleryActivity activity = mActivity; - ActionBar actionBar = activity.getActionBar(); - if (actionBar != null) { - if ((mFlags & FLAG_HIDE_ACTION_BAR) != 0) { - actionBar.hide(); - } else { - actionBar.show(); - } - int stateCount = mActivity.getStateManager().getStateCount(); - mActivity.getGalleryActionBar().setDisplayOptions(stateCount > 1, true); - // Default behavior, this can be overridden in ActivityState's onResume. - actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD); - } - - activity.invalidateOptionsMenu(); - - setScreenFlags(); - - boolean lightsOut = ((mFlags & FLAG_HIDE_STATUS_BAR) != 0); - mActivity.getGLRoot().setLightsOutMode(lightsOut); - - ResultEntry entry = mReceivedResults; - if (entry != null) { - mReceivedResults = null; - onStateResult(entry.requestCode, entry.resultCode, entry.resultData); - } - - if (0 != (mFlags & FLAG_SCREEN_ON_WHEN_PLUGGED)) { - // we need to know whether the device is plugged in to do this correctly - final IntentFilter filter = new IntentFilter(); - filter.addAction(Intent.ACTION_BATTERY_CHANGED); - activity.registerReceiver(mPowerIntentReceiver, filter); - } - - onResume(); - - // the transition store should be cleared after resume; - mActivity.getTransitionStore().clear(); - } - - // a subclass of ActivityState should override the method to resume itself - protected void onResume() { - RawTexture fade = mActivity.getTransitionStore().get( - PreparePageFadeoutTexture.KEY_FADE_TEXTURE); - mNextTransition = mActivity.getTransitionStore().get( - KEY_TRANSITION_IN, StateTransitionAnimation.Transition.None); - if (mNextTransition != StateTransitionAnimation.Transition.None) { - mIntroAnimation = new StateTransitionAnimation(mNextTransition, fade); - mNextTransition = StateTransitionAnimation.Transition.None; - } - } - - protected boolean onCreateActionBar(Menu menu) { - // TODO: we should return false if there is no menu to show - // this is a workaround for a bug in system - return true; - } - - protected boolean onItemSelected(MenuItem item) { - return false; - } - - protected void onDestroy() { - mDestroyed = true; - } - - boolean isDestroyed() { - return mDestroyed; - } - - public boolean isFinishing() { - return mIsFinishing; - } - - protected MenuInflater getSupportMenuInflater() { - return mActivity.getMenuInflater(); - } -} diff --git a/src/com/android/gallery3d/app/AlbumDataLoader.java b/src/com/android/gallery3d/app/AlbumDataLoader.java deleted file mode 100644 index 28a822830..000000000 --- a/src/com/android/gallery3d/app/AlbumDataLoader.java +++ /dev/null @@ -1,397 +0,0 @@ -/* - * 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.gallery3d.app; - -import android.os.Handler; -import android.os.Message; -import android.os.Process; - -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.data.ContentListener; -import com.android.gallery3d.data.MediaItem; -import com.android.gallery3d.data.MediaObject; -import com.android.gallery3d.data.MediaSet; -import com.android.gallery3d.data.Path; -import com.android.gallery3d.ui.SynchronizedHandler; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.FutureTask; - -public class AlbumDataLoader { - @SuppressWarnings("unused") - private static final String TAG = "AlbumDataAdapter"; - private static final int DATA_CACHE_SIZE = 1000; - - private static final int MSG_LOAD_START = 1; - private static final int MSG_LOAD_FINISH = 2; - private static final int MSG_RUN_OBJECT = 3; - - private static final int MIN_LOAD_COUNT = 32; - private static final int MAX_LOAD_COUNT = 64; - - private final MediaItem[] mData; - private final long[] mItemVersion; - private final long[] mSetVersion; - - public static interface DataListener { - public void onContentChanged(int index); - public void onSizeChanged(int size); - } - - private int mActiveStart = 0; - private int mActiveEnd = 0; - - private int mContentStart = 0; - private int mContentEnd = 0; - - private final MediaSet mSource; - private long mSourceVersion = MediaObject.INVALID_DATA_VERSION; - - private final Handler mMainHandler; - private int mSize = 0; - - private DataListener mDataListener; - private MySourceListener mSourceListener = new MySourceListener(); - private LoadingListener mLoadingListener; - - private ReloadTask mReloadTask; - // the data version on which last loading failed - private long mFailedVersion = MediaObject.INVALID_DATA_VERSION; - - public AlbumDataLoader(AbstractGalleryActivity context, MediaSet mediaSet) { - mSource = mediaSet; - - mData = new MediaItem[DATA_CACHE_SIZE]; - mItemVersion = new long[DATA_CACHE_SIZE]; - mSetVersion = new long[DATA_CACHE_SIZE]; - Arrays.fill(mItemVersion, MediaObject.INVALID_DATA_VERSION); - Arrays.fill(mSetVersion, MediaObject.INVALID_DATA_VERSION); - - mMainHandler = new SynchronizedHandler(context.getGLRoot()) { - @Override - public void handleMessage(Message message) { - switch (message.what) { - case MSG_RUN_OBJECT: - ((Runnable) message.obj).run(); - return; - case MSG_LOAD_START: - if (mLoadingListener != null) mLoadingListener.onLoadingStarted(); - return; - case MSG_LOAD_FINISH: - if (mLoadingListener != null) { - boolean loadingFailed = - (mFailedVersion != MediaObject.INVALID_DATA_VERSION); - mLoadingListener.onLoadingFinished(loadingFailed); - } - return; - } - } - }; - } - - public void resume() { - mSource.addContentListener(mSourceListener); - mReloadTask = new ReloadTask(); - mReloadTask.start(); - } - - public void pause() { - mReloadTask.terminate(); - mReloadTask = null; - mSource.removeContentListener(mSourceListener); - } - - public MediaItem get(int index) { - if (!isActive(index)) { - return mSource.getMediaItem(index, 1).get(0); - } - return mData[index % mData.length]; - } - - public int getActiveStart() { - return mActiveStart; - } - - public boolean isActive(int index) { - return index >= mActiveStart && index < mActiveEnd; - } - - public int size() { - return mSize; - } - - // Returns the index of the MediaItem with the given path or - // -1 if the path is not cached - public int findItem(Path id) { - for (int i = mContentStart; i < mContentEnd; i++) { - MediaItem item = mData[i % DATA_CACHE_SIZE]; - if (item != null && id == item.getPath()) { - return i; - } - } - return -1; - } - - private void clearSlot(int slotIndex) { - mData[slotIndex] = null; - mItemVersion[slotIndex] = MediaObject.INVALID_DATA_VERSION; - mSetVersion[slotIndex] = MediaObject.INVALID_DATA_VERSION; - } - - private void setContentWindow(int contentStart, int contentEnd) { - if (contentStart == mContentStart && contentEnd == mContentEnd) return; - int end = mContentEnd; - int start = mContentStart; - - // We need change the content window before calling reloadData(...) - synchronized (this) { - mContentStart = contentStart; - mContentEnd = contentEnd; - } - long[] itemVersion = mItemVersion; - long[] setVersion = mSetVersion; - if (contentStart >= end || start >= contentEnd) { - for (int i = start, n = end; i < n; ++i) { - clearSlot(i % DATA_CACHE_SIZE); - } - } else { - for (int i = start; i < contentStart; ++i) { - clearSlot(i % DATA_CACHE_SIZE); - } - for (int i = contentEnd, n = end; i < n; ++i) { - clearSlot(i % DATA_CACHE_SIZE); - } - } - if (mReloadTask != null) mReloadTask.notifyDirty(); - } - - public void setActiveWindow(int start, int end) { - if (start == mActiveStart && end == mActiveEnd) return; - - Utils.assertTrue(start <= end - && end - start <= mData.length && end <= mSize); - - int length = mData.length; - mActiveStart = start; - mActiveEnd = end; - - // If no data is visible, keep the cache content - if (start == end) return; - - int contentStart = Utils.clamp((start + end) / 2 - length / 2, - 0, Math.max(0, mSize - length)); - int contentEnd = Math.min(contentStart + length, mSize); - if (mContentStart > start || mContentEnd < end - || Math.abs(contentStart - mContentStart) > MIN_LOAD_COUNT) { - setContentWindow(contentStart, contentEnd); - } - } - - private class MySourceListener implements ContentListener { - @Override - public void onContentDirty() { - if (mReloadTask != null) mReloadTask.notifyDirty(); - } - } - - public void setDataListener(DataListener listener) { - mDataListener = listener; - } - - public void setLoadingListener(LoadingListener listener) { - mLoadingListener = listener; - } - - private T executeAndWait(Callable callable) { - FutureTask task = new FutureTask(callable); - mMainHandler.sendMessage( - mMainHandler.obtainMessage(MSG_RUN_OBJECT, task)); - try { - return task.get(); - } catch (InterruptedException e) { - return null; - } catch (ExecutionException e) { - throw new RuntimeException(e); - } - } - - private static class UpdateInfo { - public long version; - public int reloadStart; - public int reloadCount; - - public int size; - public ArrayList items; - } - - private class GetUpdateInfo implements Callable { - private final long mVersion; - - public GetUpdateInfo(long version) { - mVersion = version; - } - - @Override - public UpdateInfo call() throws Exception { - if (mFailedVersion == mVersion) { - // previous loading failed, return null to pause loading - return null; - } - UpdateInfo info = new UpdateInfo(); - long version = mVersion; - info.version = mSourceVersion; - info.size = mSize; - long setVersion[] = mSetVersion; - for (int i = mContentStart, n = mContentEnd; i < n; ++i) { - int index = i % DATA_CACHE_SIZE; - if (setVersion[index] != version) { - info.reloadStart = i; - info.reloadCount = Math.min(MAX_LOAD_COUNT, n - i); - return info; - } - } - return mSourceVersion == mVersion ? null : info; - } - } - - private class UpdateContent implements Callable { - - private UpdateInfo mUpdateInfo; - - public UpdateContent(UpdateInfo info) { - mUpdateInfo = info; - } - - @Override - public Void call() throws Exception { - UpdateInfo info = mUpdateInfo; - mSourceVersion = info.version; - if (mSize != info.size) { - mSize = info.size; - if (mDataListener != null) mDataListener.onSizeChanged(mSize); - if (mContentEnd > mSize) mContentEnd = mSize; - if (mActiveEnd > mSize) mActiveEnd = mSize; - } - - ArrayList items = info.items; - - mFailedVersion = MediaObject.INVALID_DATA_VERSION; - if ((items == null) || items.isEmpty()) { - if (info.reloadCount > 0) { - mFailedVersion = info.version; - Log.d(TAG, "loading failed: " + mFailedVersion); - } - return null; - } - int start = Math.max(info.reloadStart, mContentStart); - int end = Math.min(info.reloadStart + items.size(), mContentEnd); - - for (int i = start; i < end; ++i) { - int index = i % DATA_CACHE_SIZE; - mSetVersion[index] = info.version; - MediaItem updateItem = items.get(i - info.reloadStart); - long itemVersion = updateItem.getDataVersion(); - if (mItemVersion[index] != itemVersion) { - mItemVersion[index] = itemVersion; - mData[index] = updateItem; - if (mDataListener != null && i >= mActiveStart && i < mActiveEnd) { - mDataListener.onContentChanged(i); - } - } - } - return null; - } - } - - /* - * The thread model of ReloadTask - * * - * [Reload Task] [Main Thread] - * | | - * getUpdateInfo() --> | (synchronous call) - * (wait) <---- getUpdateInfo() - * | | - * Load Data | - * | | - * updateContent() --> | (synchronous call) - * (wait) updateContent() - * | | - * | | - */ - private class ReloadTask extends Thread { - - private volatile boolean mActive = true; - private volatile boolean mDirty = true; - private boolean mIsLoading = false; - - private void updateLoading(boolean loading) { - if (mIsLoading == loading) return; - mIsLoading = loading; - mMainHandler.sendEmptyMessage(loading ? MSG_LOAD_START : MSG_LOAD_FINISH); - } - - @Override - public void run() { - Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); - - boolean updateComplete = false; - while (mActive) { - synchronized (this) { - if (mActive && !mDirty && updateComplete) { - updateLoading(false); - if (mFailedVersion != MediaObject.INVALID_DATA_VERSION) { - Log.d(TAG, "reload pause"); - } - Utils.waitWithoutInterrupt(this); - if (mActive && (mFailedVersion != MediaObject.INVALID_DATA_VERSION)) { - Log.d(TAG, "reload resume"); - } - continue; - } - mDirty = false; - } - updateLoading(true); - long version = mSource.reload(); - UpdateInfo info = executeAndWait(new GetUpdateInfo(version)); - updateComplete = info == null; - if (updateComplete) continue; - if (info.version != version) { - info.size = mSource.getMediaItemCount(); - info.version = version; - } - if (info.reloadCount > 0) { - info.items = mSource.getMediaItem(info.reloadStart, info.reloadCount); - } - executeAndWait(new UpdateContent(info)); - } - updateLoading(false); - } - - public synchronized void notifyDirty() { - mDirty = true; - notifyAll(); - } - - public synchronized void terminate() { - mActive = false; - notifyAll(); - } - } -} diff --git a/src/com/android/gallery3d/app/AlbumPage.java b/src/com/android/gallery3d/app/AlbumPage.java deleted file mode 100644 index 658abbbd4..000000000 --- a/src/com/android/gallery3d/app/AlbumPage.java +++ /dev/null @@ -1,786 +0,0 @@ -/* - * 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.gallery3d.app; - -import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.graphics.Rect; -import android.net.Uri; -import android.os.Bundle; -import android.os.Handler; -import android.os.Message; -import android.provider.MediaStore; -import android.view.HapticFeedbackConstants; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; -import android.widget.Toast; - -import com.android.gallery3d.R; -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.data.DataManager; -import com.android.gallery3d.data.MediaDetails; -import com.android.gallery3d.data.MediaItem; -import com.android.gallery3d.data.MediaObject; -import com.android.gallery3d.data.MediaSet; -import com.android.gallery3d.data.Path; -import com.android.gallery3d.filtershow.crop.CropActivity; -import com.android.gallery3d.filtershow.crop.CropExtras; -import com.android.gallery3d.glrenderer.FadeTexture; -import com.android.gallery3d.glrenderer.GLCanvas; -import com.android.gallery3d.ui.ActionModeHandler; -import com.android.gallery3d.ui.ActionModeHandler.ActionModeListener; -import com.android.gallery3d.ui.AlbumSlotRenderer; -import com.android.gallery3d.ui.DetailsHelper; -import com.android.gallery3d.ui.DetailsHelper.CloseListener; -import com.android.gallery3d.ui.GLRoot; -import com.android.gallery3d.ui.GLView; -import com.android.gallery3d.ui.PhotoFallbackEffect; -import com.android.gallery3d.ui.RelativePosition; -import com.android.gallery3d.ui.SelectionManager; -import com.android.gallery3d.ui.SlotView; -import com.android.gallery3d.ui.SynchronizedHandler; -import com.android.gallery3d.util.Future; -import com.android.gallery3d.util.GalleryUtils; -import com.android.gallery3d.util.MediaSetUtils; - - -public class AlbumPage extends ActivityState implements GalleryActionBar.ClusterRunner, - SelectionManager.SelectionListener, MediaSet.SyncListener, GalleryActionBar.OnAlbumModeSelectedListener { - @SuppressWarnings("unused") - private static final String TAG = "AlbumPage"; - - public static final String KEY_MEDIA_PATH = "media-path"; - public static final String KEY_PARENT_MEDIA_PATH = "parent-media-path"; - public static final String KEY_SET_CENTER = "set-center"; - public static final String KEY_AUTO_SELECT_ALL = "auto-select-all"; - public static final String KEY_SHOW_CLUSTER_MENU = "cluster-menu"; - public static final String KEY_EMPTY_ALBUM = "empty-album"; - public static final String KEY_RESUME_ANIMATION = "resume_animation"; - - private static final int REQUEST_SLIDESHOW = 1; - public static final int REQUEST_PHOTO = 2; - private static final int REQUEST_DO_ANIMATION = 3; - - private static final int BIT_LOADING_RELOAD = 1; - private static final int BIT_LOADING_SYNC = 2; - - private static final float USER_DISTANCE_METER = 0.3f; - - private boolean mIsActive = false; - private AlbumSlotRenderer mAlbumView; - private Path mMediaSetPath; - private String mParentMediaSetString; - private SlotView mSlotView; - - private AlbumDataLoader mAlbumDataAdapter; - - protected SelectionManager mSelectionManager; - - private boolean mGetContent; - private boolean mShowClusterMenu; - - private ActionModeHandler mActionModeHandler; - private int mFocusIndex = 0; - private DetailsHelper mDetailsHelper; - private MyDetailsSource mDetailsSource; - private MediaSet mMediaSet; - private boolean mShowDetails; - private float mUserDistance; // in pixel - private Future mSyncTask = null; - private boolean mLaunchedFromPhotoPage; - private boolean mInCameraApp; - private boolean mInCameraAndWantQuitOnPause; - - private int mLoadingBits = 0; - private boolean mInitialSynced = false; - private int mSyncResult; - private boolean mLoadingFailed; - private RelativePosition mOpenCenter = new RelativePosition(); - - private Handler mHandler; - private static final int MSG_PICK_PHOTO = 0; - - private PhotoFallbackEffect mResumeEffect; - private PhotoFallbackEffect.PositionProvider mPositionProvider = - new PhotoFallbackEffect.PositionProvider() { - @Override - public Rect getPosition(int index) { - Rect rect = mSlotView.getSlotRect(index); - Rect bounds = mSlotView.bounds(); - rect.offset(bounds.left - mSlotView.getScrollX(), - bounds.top - mSlotView.getScrollY()); - return rect; - } - - @Override - public int getItemIndex(Path path) { - int start = mSlotView.getVisibleStart(); - int end = mSlotView.getVisibleEnd(); - for (int i = start; i < end; ++i) { - MediaItem item = mAlbumDataAdapter.get(i); - if (item != null && item.getPath() == path) return i; - } - return -1; - } - }; - - @Override - protected int getBackgroundColorId() { - return R.color.album_background; - } - - private final GLView mRootPane = new GLView() { - private final float mMatrix[] = new float[16]; - - @Override - protected void onLayout( - boolean changed, int left, int top, int right, int bottom) { - - int slotViewTop = mActivity.getGalleryActionBar().getHeight(); - int slotViewBottom = bottom - top; - int slotViewRight = right - left; - - if (mShowDetails) { - mDetailsHelper.layout(left, slotViewTop, right, bottom); - } else { - mAlbumView.setHighlightItemPath(null); - } - - // Set the mSlotView as a reference point to the open animation - mOpenCenter.setReferencePosition(0, slotViewTop); - mSlotView.layout(0, slotViewTop, slotViewRight, slotViewBottom); - GalleryUtils.setViewPointMatrix(mMatrix, - (right - left) / 2, (bottom - top) / 2, -mUserDistance); - } - - @Override - protected void render(GLCanvas canvas) { - canvas.save(GLCanvas.SAVE_FLAG_MATRIX); - canvas.multiplyMatrix(mMatrix, 0); - super.render(canvas); - - if (mResumeEffect != null) { - boolean more = mResumeEffect.draw(canvas); - if (!more) { - mResumeEffect = null; - mAlbumView.setSlotFilter(null); - } - // We want to render one more time even when no more effect - // required. So that the animated thumbnails could be draw - // with declarations in super.render(). - invalidate(); - } - canvas.restore(); - } - }; - - // This are the transitions we want: - // - // +--------+ +------------+ +-------+ +----------+ - // | Camera |---------->| Fullscreen |--->| Album |--->| AlbumSet | - // | View | thumbnail | Photo | up | Page | up | Page | - // +--------+ +------------+ +-------+ +----------+ - // ^ | | ^ | - // | | | | | close - // +----------back--------+ +----back----+ +--back-> app - // - @Override - protected void onBackPressed() { - if (mShowDetails) { - hideDetails(); - } else if (mSelectionManager.inSelectionMode()) { - mSelectionManager.leaveSelectionMode(); - } else { - if(mLaunchedFromPhotoPage) { - mActivity.getTransitionStore().putIfNotPresent( - PhotoPage.KEY_ALBUMPAGE_TRANSITION, - PhotoPage.MSG_ALBUMPAGE_RESUMED); - } - // TODO: fix this regression - // mAlbumView.savePositions(PositionRepository.getInstance(mActivity)); - if (mInCameraApp) { - super.onBackPressed(); - } else { - onUpPressed(); - } - } - } - - private void onUpPressed() { - if (mInCameraApp) { - GalleryUtils.startGalleryActivity(mActivity); - } else if (mActivity.getStateManager().getStateCount() > 1) { - super.onBackPressed(); - } else if (mParentMediaSetString != null) { - Bundle data = new Bundle(getData()); - data.putString(AlbumSetPage.KEY_MEDIA_PATH, mParentMediaSetString); - mActivity.getStateManager().switchState( - this, AlbumSetPage.class, data); - } - } - - private void onDown(int index) { - mAlbumView.setPressedIndex(index); - } - - private void onUp(boolean followedByLongPress) { - if (followedByLongPress) { - // Avoid showing press-up animations for long-press. - mAlbumView.setPressedIndex(-1); - } else { - mAlbumView.setPressedUp(); - } - } - - private void onSingleTapUp(int slotIndex) { - if (!mIsActive) return; - - if (mSelectionManager.inSelectionMode()) { - MediaItem item = mAlbumDataAdapter.get(slotIndex); - if (item == null) return; // Item not ready yet, ignore the click - mSelectionManager.toggle(item.getPath()); - mSlotView.invalidate(); - } else { - // Render transition in pressed state - mAlbumView.setPressedIndex(slotIndex); - mAlbumView.setPressedUp(); - mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_PICK_PHOTO, slotIndex, 0), - FadeTexture.DURATION); - } - } - - private void pickPhoto(int slotIndex) { - pickPhoto(slotIndex, false); - } - - private void pickPhoto(int slotIndex, boolean startInFilmstrip) { - if (!mIsActive) return; - - if (!startInFilmstrip) { - // Launch photos in lights out mode - mActivity.getGLRoot().setLightsOutMode(true); - } - - MediaItem item = mAlbumDataAdapter.get(slotIndex); - if (item == null) return; // Item not ready yet, ignore the click - if (mGetContent) { - onGetContent(item); - } else if (mLaunchedFromPhotoPage) { - TransitionStore transitions = mActivity.getTransitionStore(); - transitions.put( - PhotoPage.KEY_ALBUMPAGE_TRANSITION, - PhotoPage.MSG_ALBUMPAGE_PICKED); - transitions.put(PhotoPage.KEY_INDEX_HINT, slotIndex); - onBackPressed(); - } else { - // Get into the PhotoPage. - // mAlbumView.savePositions(PositionRepository.getInstance(mActivity)); - Bundle data = new Bundle(); - data.putInt(PhotoPage.KEY_INDEX_HINT, slotIndex); - data.putParcelable(PhotoPage.KEY_OPEN_ANIMATION_RECT, - mSlotView.getSlotRect(slotIndex, mRootPane)); - data.putString(PhotoPage.KEY_MEDIA_SET_PATH, - mMediaSetPath.toString()); - data.putString(PhotoPage.KEY_MEDIA_ITEM_PATH, - item.getPath().toString()); - data.putInt(PhotoPage.KEY_ALBUMPAGE_TRANSITION, - PhotoPage.MSG_ALBUMPAGE_STARTED); - data.putBoolean(PhotoPage.KEY_START_IN_FILMSTRIP, - startInFilmstrip); - data.putBoolean(PhotoPage.KEY_IN_CAMERA_ROLL, mMediaSet.isCameraRoll()); - if (startInFilmstrip) { - mActivity.getStateManager().switchState(this, FilmstripPage.class, data); - } else { - mActivity.getStateManager().startStateForResult( - SinglePhotoPage.class, REQUEST_PHOTO, data); - } - } - } - - private void onGetContent(final MediaItem item) { - DataManager dm = mActivity.getDataManager(); - Activity activity = mActivity; - if (mData.getString(Gallery.EXTRA_CROP) != null) { - Uri uri = dm.getContentUri(item.getPath()); - Intent intent = new Intent(CropActivity.CROP_ACTION, uri) - .addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT) - .putExtras(getData()); - if (mData.getParcelable(MediaStore.EXTRA_OUTPUT) == null) { - intent.putExtra(CropExtras.KEY_RETURN_DATA, true); - } - activity.startActivity(intent); - activity.finish(); - } else { - Intent intent = new Intent(null, item.getContentUri()) - .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - activity.setResult(Activity.RESULT_OK, intent); - activity.finish(); - } - } - - public void onLongTap(int slotIndex) { - if (mGetContent) return; - MediaItem item = mAlbumDataAdapter.get(slotIndex); - if (item == null) return; - mSelectionManager.setAutoLeaveSelectionMode(true); - mSelectionManager.toggle(item.getPath()); - mSlotView.invalidate(); - } - - @Override - public void doCluster(int clusterType) { - String basePath = mMediaSet.getPath().toString(); - String newPath = FilterUtils.newClusterPath(basePath, clusterType); - Bundle data = new Bundle(getData()); - data.putString(AlbumSetPage.KEY_MEDIA_PATH, newPath); - if (mShowClusterMenu) { - Context context = mActivity.getAndroidContext(); - data.putString(AlbumSetPage.KEY_SET_TITLE, mMediaSet.getName()); - data.putString(AlbumSetPage.KEY_SET_SUBTITLE, - GalleryActionBar.getClusterByTypeString(context, clusterType)); - } - - // mAlbumView.savePositions(PositionRepository.getInstance(mActivity)); - mActivity.getStateManager().startStateForResult( - AlbumSetPage.class, REQUEST_DO_ANIMATION, data); - } - - @Override - protected void onCreate(Bundle data, Bundle restoreState) { - super.onCreate(data, restoreState); - mUserDistance = GalleryUtils.meterToPixel(USER_DISTANCE_METER); - initializeViews(); - initializeData(data); - mGetContent = data.getBoolean(Gallery.KEY_GET_CONTENT, false); - mShowClusterMenu = data.getBoolean(KEY_SHOW_CLUSTER_MENU, false); - mDetailsSource = new MyDetailsSource(); - Context context = mActivity.getAndroidContext(); - - if (data.getBoolean(KEY_AUTO_SELECT_ALL)) { - mSelectionManager.selectAll(); - } - - mLaunchedFromPhotoPage = - mActivity.getStateManager().hasStateClass(FilmstripPage.class); - mInCameraApp = data.getBoolean(PhotoPage.KEY_APP_BRIDGE, false); - - mHandler = new SynchronizedHandler(mActivity.getGLRoot()) { - @Override - public void handleMessage(Message message) { - switch (message.what) { - case MSG_PICK_PHOTO: { - pickPhoto(message.arg1); - break; - } - default: - throw new AssertionError(message.what); - } - } - }; - } - - @Override - protected void onResume() { - super.onResume(); - mIsActive = true; - - mResumeEffect = mActivity.getTransitionStore().get(KEY_RESUME_ANIMATION); - if (mResumeEffect != null) { - mAlbumView.setSlotFilter(mResumeEffect); - mResumeEffect.setPositionProvider(mPositionProvider); - mResumeEffect.start(); - } - - setContentPane(mRootPane); - - boolean enableHomeButton = (mActivity.getStateManager().getStateCount() > 1) | - mParentMediaSetString != null; - GalleryActionBar actionBar = mActivity.getGalleryActionBar(); - actionBar.setDisplayOptions(enableHomeButton, false); - if (!mGetContent) { - actionBar.enableAlbumModeMenu(GalleryActionBar.ALBUM_GRID_MODE_SELECTED, this); - } - - // Set the reload bit here to prevent it exit this page in clearLoadingBit(). - setLoadingBit(BIT_LOADING_RELOAD); - mLoadingFailed = false; - mAlbumDataAdapter.resume(); - - mAlbumView.resume(); - mAlbumView.setPressedIndex(-1); - mActionModeHandler.resume(); - if (!mInitialSynced) { - setLoadingBit(BIT_LOADING_SYNC); - mSyncTask = mMediaSet.requestSync(this); - } - mInCameraAndWantQuitOnPause = mInCameraApp; - } - - @Override - protected void onPause() { - super.onPause(); - mIsActive = false; - - if (mSelectionManager.inSelectionMode()) { - mSelectionManager.leaveSelectionMode(); - } - mAlbumView.setSlotFilter(null); - mActionModeHandler.pause(); - mAlbumDataAdapter.pause(); - mAlbumView.pause(); - DetailsHelper.pause(); - if (!mGetContent) { - mActivity.getGalleryActionBar().disableAlbumModeMenu(true); - } - - if (mSyncTask != null) { - mSyncTask.cancel(); - mSyncTask = null; - clearLoadingBit(BIT_LOADING_SYNC); - } - } - - @Override - protected void onDestroy() { - super.onDestroy(); - if (mAlbumDataAdapter != null) { - mAlbumDataAdapter.setLoadingListener(null); - } - mActionModeHandler.destroy(); - } - - private void initializeViews() { - mSelectionManager = new SelectionManager(mActivity, false); - mSelectionManager.setSelectionListener(this); - Config.AlbumPage config = Config.AlbumPage.get(mActivity); - mSlotView = new SlotView(mActivity, config.slotViewSpec); - mAlbumView = new AlbumSlotRenderer(mActivity, mSlotView, - mSelectionManager, config.placeholderColor); - mSlotView.setSlotRenderer(mAlbumView); - mRootPane.addComponent(mSlotView); - mSlotView.setListener(new SlotView.SimpleListener() { - @Override - public void onDown(int index) { - AlbumPage.this.onDown(index); - } - - @Override - public void onUp(boolean followedByLongPress) { - AlbumPage.this.onUp(followedByLongPress); - } - - @Override - public void onSingleTapUp(int slotIndex) { - AlbumPage.this.onSingleTapUp(slotIndex); - } - - @Override - public void onLongTap(int slotIndex) { - AlbumPage.this.onLongTap(slotIndex); - } - }); - mActionModeHandler = new ActionModeHandler(mActivity, mSelectionManager); - mActionModeHandler.setActionModeListener(new ActionModeListener() { - @Override - public boolean onActionItemClicked(MenuItem item) { - return onItemSelected(item); - } - }); - } - - private void initializeData(Bundle data) { - mMediaSetPath = Path.fromString(data.getString(KEY_MEDIA_PATH)); - mParentMediaSetString = data.getString(KEY_PARENT_MEDIA_PATH); - mMediaSet = mActivity.getDataManager().getMediaSet(mMediaSetPath); - if (mMediaSet == null) { - Utils.fail("MediaSet is null. Path = %s", mMediaSetPath); - } - mSelectionManager.setSourceMediaSet(mMediaSet); - mAlbumDataAdapter = new AlbumDataLoader(mActivity, mMediaSet); - mAlbumDataAdapter.setLoadingListener(new MyLoadingListener()); - mAlbumView.setModel(mAlbumDataAdapter); - } - - private void showDetails() { - mShowDetails = true; - if (mDetailsHelper == null) { - mDetailsHelper = new DetailsHelper(mActivity, mRootPane, mDetailsSource); - mDetailsHelper.setCloseListener(new CloseListener() { - @Override - public void onClose() { - hideDetails(); - } - }); - } - mDetailsHelper.show(); - } - - private void hideDetails() { - mShowDetails = false; - mDetailsHelper.hide(); - mAlbumView.setHighlightItemPath(null); - mSlotView.invalidate(); - } - - @Override - protected boolean onCreateActionBar(Menu menu) { - GalleryActionBar actionBar = mActivity.getGalleryActionBar(); - MenuInflater inflator = getSupportMenuInflater(); - if (mGetContent) { - inflator.inflate(R.menu.pickup, menu); - int typeBits = mData.getInt(Gallery.KEY_TYPE_BITS, - DataManager.INCLUDE_IMAGE); - actionBar.setTitle(GalleryUtils.getSelectionModePrompt(typeBits)); - } else { - inflator.inflate(R.menu.album, menu); - actionBar.setTitle(mMediaSet.getName()); - - FilterUtils.setupMenuItems(actionBar, mMediaSetPath, true); - - menu.findItem(R.id.action_group_by).setVisible(mShowClusterMenu); - menu.findItem(R.id.action_camera).setVisible( - MediaSetUtils.isCameraSource(mMediaSetPath) - && GalleryUtils.isCameraAvailable(mActivity)); - - } - actionBar.setSubtitle(null); - return true; - } - - private void prepareAnimationBackToFilmstrip(int slotIndex) { - if (mAlbumDataAdapter == null || !mAlbumDataAdapter.isActive(slotIndex)) return; - MediaItem item = mAlbumDataAdapter.get(slotIndex); - if (item == null) return; - TransitionStore transitions = mActivity.getTransitionStore(); - transitions.put(PhotoPage.KEY_INDEX_HINT, slotIndex); - transitions.put(PhotoPage.KEY_OPEN_ANIMATION_RECT, - mSlotView.getSlotRect(slotIndex, mRootPane)); - } - - private void switchToFilmstrip() { - if (mAlbumDataAdapter.size() < 1) return; - int targetPhoto = mSlotView.getVisibleStart(); - prepareAnimationBackToFilmstrip(targetPhoto); - if(mLaunchedFromPhotoPage) { - onBackPressed(); - } else { - pickPhoto(targetPhoto, true); - } - } - - @Override - protected boolean onItemSelected(MenuItem item) { - switch (item.getItemId()) { - case android.R.id.home: { - onUpPressed(); - return true; - } - case R.id.action_cancel: - mActivity.getStateManager().finishState(this); - return true; - case R.id.action_select: - mSelectionManager.setAutoLeaveSelectionMode(false); - mSelectionManager.enterSelectionMode(); - return true; - case R.id.action_group_by: { - mActivity.getGalleryActionBar().showClusterDialog(this); - return true; - } - case R.id.action_slideshow: { - mInCameraAndWantQuitOnPause = false; - Bundle data = new Bundle(); - data.putString(SlideshowPage.KEY_SET_PATH, - mMediaSetPath.toString()); - data.putBoolean(SlideshowPage.KEY_REPEAT, true); - mActivity.getStateManager().startStateForResult( - SlideshowPage.class, REQUEST_SLIDESHOW, data); - return true; - } - case R.id.action_details: { - if (mShowDetails) { - hideDetails(); - } else { - showDetails(); - } - return true; - } - case R.id.action_camera: { - GalleryUtils.startCameraActivity(mActivity); - return true; - } - default: - return false; - } - } - - @Override - protected void onStateResult(int request, int result, Intent data) { - switch (request) { - case REQUEST_SLIDESHOW: { - // data could be null, if there is no images in the album - if (data == null) return; - mFocusIndex = data.getIntExtra(SlideshowPage.KEY_PHOTO_INDEX, 0); - mSlotView.setCenterIndex(mFocusIndex); - break; - } - case REQUEST_PHOTO: { - if (data == null) return; - mFocusIndex = data.getIntExtra(PhotoPage.KEY_RETURN_INDEX_HINT, 0); - mSlotView.makeSlotVisible(mFocusIndex); - break; - } - case REQUEST_DO_ANIMATION: { - mSlotView.startRisingAnimation(); - break; - } - } - } - - @Override - public void onSelectionModeChange(int mode) { - switch (mode) { - case SelectionManager.ENTER_SELECTION_MODE: { - mActionModeHandler.startActionMode(); - performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); - break; - } - case SelectionManager.LEAVE_SELECTION_MODE: { - mActionModeHandler.finishActionMode(); - mRootPane.invalidate(); - break; - } - case SelectionManager.SELECT_ALL_MODE: { - mActionModeHandler.updateSupportedOperation(); - mRootPane.invalidate(); - break; - } - } - } - - @Override - public void onSelectionChange(Path path, boolean selected) { - int count = mSelectionManager.getSelectedCount(); - String format = mActivity.getResources().getQuantityString( - R.plurals.number_of_items_selected, count); - mActionModeHandler.setTitle(String.format(format, count)); - mActionModeHandler.updateSupportedOperation(path, selected); - } - - @Override - public void onSyncDone(final MediaSet mediaSet, final int resultCode) { - Log.d(TAG, "onSyncDone: " + Utils.maskDebugInfo(mediaSet.getName()) + " result=" - + resultCode); - ((Activity) mActivity).runOnUiThread(new Runnable() { - @Override - public void run() { - GLRoot root = mActivity.getGLRoot(); - root.lockRenderThread(); - mSyncResult = resultCode; - try { - if (resultCode == MediaSet.SYNC_RESULT_SUCCESS) { - mInitialSynced = true; - } - clearLoadingBit(BIT_LOADING_SYNC); - showSyncErrorIfNecessary(mLoadingFailed); - } finally { - root.unlockRenderThread(); - } - } - }); - } - - // Show sync error toast when all the following conditions are met: - // (1) both loading and sync are done, - // (2) sync result is error, - // (3) the page is still active, and - // (4) no photo is shown or loading fails. - private void showSyncErrorIfNecessary(boolean loadingFailed) { - if ((mLoadingBits == 0) && (mSyncResult == MediaSet.SYNC_RESULT_ERROR) && mIsActive - && (loadingFailed || (mAlbumDataAdapter.size() == 0))) { - Toast.makeText(mActivity, R.string.sync_album_error, - Toast.LENGTH_LONG).show(); - } - } - - private void setLoadingBit(int loadTaskBit) { - mLoadingBits |= loadTaskBit; - } - - private void clearLoadingBit(int loadTaskBit) { - mLoadingBits &= ~loadTaskBit; - if (mLoadingBits == 0 && mIsActive) { - if (mAlbumDataAdapter.size() == 0) { - Intent result = new Intent(); - result.putExtra(KEY_EMPTY_ALBUM, true); - setStateResult(Activity.RESULT_OK, result); - mActivity.getStateManager().finishState(this); - } - } - } - - private class MyLoadingListener implements LoadingListener { - @Override - public void onLoadingStarted() { - setLoadingBit(BIT_LOADING_RELOAD); - mLoadingFailed = false; - } - - @Override - public void onLoadingFinished(boolean loadingFailed) { - clearLoadingBit(BIT_LOADING_RELOAD); - mLoadingFailed = loadingFailed; - showSyncErrorIfNecessary(loadingFailed); - } - } - - private class MyDetailsSource implements DetailsHelper.DetailsSource { - private int mIndex; - - @Override - public int size() { - return mAlbumDataAdapter.size(); - } - - @Override - public int setIndex() { - Path id = mSelectionManager.getSelected(false).get(0); - mIndex = mAlbumDataAdapter.findItem(id); - return mIndex; - } - - @Override - public MediaDetails getDetails() { - // this relies on setIndex() being called beforehand - MediaObject item = mAlbumDataAdapter.get(mIndex); - if (item != null) { - mAlbumView.setHighlightItemPath(item.getPath()); - return item.getDetails(); - } else { - return null; - } - } - } - - @Override - public void onAlbumModeSelected(int mode) { - if (mode == GalleryActionBar.ALBUM_FILMSTRIP_MODE_SELECTED) { - switchToFilmstrip(); - } - } -} diff --git a/src/com/android/gallery3d/app/AlbumPicker.java b/src/com/android/gallery3d/app/AlbumPicker.java deleted file mode 100644 index 65eb77291..000000000 --- a/src/com/android/gallery3d/app/AlbumPicker.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.app; - -import android.content.Intent; -import android.os.Bundle; - -import com.android.gallery3d.R; -import com.android.gallery3d.data.DataManager; - -public class AlbumPicker extends PickerActivity { - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setTitle(R.string.select_album); - Intent intent = getIntent(); - Bundle extras = intent.getExtras(); - Bundle data = extras == null ? new Bundle() : new Bundle(extras); - - data.putBoolean(Gallery.KEY_GET_ALBUM, true); - data.putString(AlbumSetPage.KEY_MEDIA_PATH, - getDataManager().getTopSetPath(DataManager.INCLUDE_IMAGE)); - getStateManager().startState(AlbumSetPage.class, data); - } -} diff --git a/src/com/android/gallery3d/app/AlbumSetDataLoader.java b/src/com/android/gallery3d/app/AlbumSetDataLoader.java deleted file mode 100644 index cf380f812..000000000 --- a/src/com/android/gallery3d/app/AlbumSetDataLoader.java +++ /dev/null @@ -1,393 +0,0 @@ -/* - * 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.gallery3d.app; - -import android.os.Handler; -import android.os.Message; -import android.os.Process; - -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.data.ContentListener; -import com.android.gallery3d.data.MediaItem; -import com.android.gallery3d.data.MediaObject; -import com.android.gallery3d.data.MediaSet; -import com.android.gallery3d.data.Path; -import com.android.gallery3d.ui.SynchronizedHandler; - -import java.util.Arrays; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.FutureTask; - -public class AlbumSetDataLoader { - @SuppressWarnings("unused") - private static final String TAG = "AlbumSetDataAdapter"; - - private static final int INDEX_NONE = -1; - - private static final int MIN_LOAD_COUNT = 4; - - private static final int MSG_LOAD_START = 1; - private static final int MSG_LOAD_FINISH = 2; - private static final int MSG_RUN_OBJECT = 3; - - public static interface DataListener { - public void onContentChanged(int index); - public void onSizeChanged(int size); - } - - private final MediaSet[] mData; - private final MediaItem[] mCoverItem; - private final int[] mTotalCount; - private final long[] mItemVersion; - private final long[] mSetVersion; - - private int mActiveStart = 0; - private int mActiveEnd = 0; - - private int mContentStart = 0; - private int mContentEnd = 0; - - private final MediaSet mSource; - private long mSourceVersion = MediaObject.INVALID_DATA_VERSION; - private int mSize; - - private DataListener mDataListener; - private LoadingListener mLoadingListener; - private ReloadTask mReloadTask; - - private final Handler mMainHandler; - - private final MySourceListener mSourceListener = new MySourceListener(); - - public AlbumSetDataLoader(AbstractGalleryActivity activity, MediaSet albumSet, int cacheSize) { - mSource = Utils.checkNotNull(albumSet); - mCoverItem = new MediaItem[cacheSize]; - mData = new MediaSet[cacheSize]; - mTotalCount = new int[cacheSize]; - mItemVersion = new long[cacheSize]; - mSetVersion = new long[cacheSize]; - Arrays.fill(mItemVersion, MediaObject.INVALID_DATA_VERSION); - Arrays.fill(mSetVersion, MediaObject.INVALID_DATA_VERSION); - - mMainHandler = new SynchronizedHandler(activity.getGLRoot()) { - @Override - public void handleMessage(Message message) { - switch (message.what) { - case MSG_RUN_OBJECT: - ((Runnable) message.obj).run(); - return; - case MSG_LOAD_START: - if (mLoadingListener != null) mLoadingListener.onLoadingStarted(); - return; - case MSG_LOAD_FINISH: - if (mLoadingListener != null) mLoadingListener.onLoadingFinished(false); - return; - } - } - }; - } - - public void pause() { - mReloadTask.terminate(); - mReloadTask = null; - mSource.removeContentListener(mSourceListener); - } - - public void resume() { - mSource.addContentListener(mSourceListener); - mReloadTask = new ReloadTask(); - mReloadTask.start(); - } - - private void assertIsActive(int index) { - if (index < mActiveStart && index >= mActiveEnd) { - throw new IllegalArgumentException(String.format( - "%s not in (%s, %s)", index, mActiveStart, mActiveEnd)); - } - } - - public MediaSet getMediaSet(int index) { - assertIsActive(index); - return mData[index % mData.length]; - } - - public MediaItem getCoverItem(int index) { - assertIsActive(index); - return mCoverItem[index % mCoverItem.length]; - } - - public int getTotalCount(int index) { - assertIsActive(index); - return mTotalCount[index % mTotalCount.length]; - } - - public int getActiveStart() { - return mActiveStart; - } - - public boolean isActive(int index) { - return index >= mActiveStart && index < mActiveEnd; - } - - public int size() { - return mSize; - } - - // Returns the index of the MediaSet with the given path or - // -1 if the path is not cached - public int findSet(Path id) { - int length = mData.length; - for (int i = mContentStart; i < mContentEnd; i++) { - MediaSet set = mData[i % length]; - if (set != null && id == set.getPath()) { - return i; - } - } - return -1; - } - - private void clearSlot(int slotIndex) { - mData[slotIndex] = null; - mCoverItem[slotIndex] = null; - mTotalCount[slotIndex] = 0; - mItemVersion[slotIndex] = MediaObject.INVALID_DATA_VERSION; - mSetVersion[slotIndex] = MediaObject.INVALID_DATA_VERSION; - } - - private void setContentWindow(int contentStart, int contentEnd) { - if (contentStart == mContentStart && contentEnd == mContentEnd) return; - int length = mCoverItem.length; - - int start = this.mContentStart; - int end = this.mContentEnd; - - mContentStart = contentStart; - mContentEnd = contentEnd; - - if (contentStart >= end || start >= contentEnd) { - for (int i = start, n = end; i < n; ++i) { - clearSlot(i % length); - } - } else { - for (int i = start; i < contentStart; ++i) { - clearSlot(i % length); - } - for (int i = contentEnd, n = end; i < n; ++i) { - clearSlot(i % length); - } - } - mReloadTask.notifyDirty(); - } - - public void setActiveWindow(int start, int end) { - if (start == mActiveStart && end == mActiveEnd) return; - - Utils.assertTrue(start <= end - && end - start <= mCoverItem.length && end <= mSize); - - mActiveStart = start; - mActiveEnd = end; - - int length = mCoverItem.length; - // If no data is visible, keep the cache content - if (start == end) return; - - int contentStart = Utils.clamp((start + end) / 2 - length / 2, - 0, Math.max(0, mSize - length)); - int contentEnd = Math.min(contentStart + length, mSize); - if (mContentStart > start || mContentEnd < end - || Math.abs(contentStart - mContentStart) > MIN_LOAD_COUNT) { - setContentWindow(contentStart, contentEnd); - } - } - - private class MySourceListener implements ContentListener { - @Override - public void onContentDirty() { - mReloadTask.notifyDirty(); - } - } - - public void setModelListener(DataListener listener) { - mDataListener = listener; - } - - public void setLoadingListener(LoadingListener listener) { - mLoadingListener = listener; - } - - private static class UpdateInfo { - public long version; - public int index; - - public int size; - public MediaSet item; - public MediaItem cover; - public int totalCount; - } - - private class GetUpdateInfo implements Callable { - - private final long mVersion; - - public GetUpdateInfo(long version) { - mVersion = version; - } - - private int getInvalidIndex(long version) { - long setVersion[] = mSetVersion; - int length = setVersion.length; - for (int i = mContentStart, n = mContentEnd; i < n; ++i) { - int index = i % length; - if (setVersion[i % length] != version) return i; - } - return INDEX_NONE; - } - - @Override - public UpdateInfo call() throws Exception { - int index = getInvalidIndex(mVersion); - if (index == INDEX_NONE && mSourceVersion == mVersion) return null; - UpdateInfo info = new UpdateInfo(); - info.version = mSourceVersion; - info.index = index; - info.size = mSize; - return info; - } - } - - private class UpdateContent implements Callable { - private final UpdateInfo mUpdateInfo; - - public UpdateContent(UpdateInfo info) { - mUpdateInfo = info; - } - - @Override - public Void call() { - // Avoid notifying listeners of status change after pause - // Otherwise gallery will be in inconsistent state after resume. - if (mReloadTask == null) return null; - UpdateInfo info = mUpdateInfo; - mSourceVersion = info.version; - if (mSize != info.size) { - mSize = info.size; - if (mDataListener != null) mDataListener.onSizeChanged(mSize); - if (mContentEnd > mSize) mContentEnd = mSize; - if (mActiveEnd > mSize) mActiveEnd = mSize; - } - // Note: info.index could be INDEX_NONE, i.e., -1 - if (info.index >= mContentStart && info.index < mContentEnd) { - int pos = info.index % mCoverItem.length; - mSetVersion[pos] = info.version; - long itemVersion = info.item.getDataVersion(); - if (mItemVersion[pos] == itemVersion) return null; - mItemVersion[pos] = itemVersion; - mData[pos] = info.item; - mCoverItem[pos] = info.cover; - mTotalCount[pos] = info.totalCount; - if (mDataListener != null - && info.index >= mActiveStart && info.index < mActiveEnd) { - mDataListener.onContentChanged(info.index); - } - } - return null; - } - } - - private T executeAndWait(Callable callable) { - FutureTask task = new FutureTask(callable); - mMainHandler.sendMessage( - mMainHandler.obtainMessage(MSG_RUN_OBJECT, task)); - try { - return task.get(); - } catch (InterruptedException e) { - return null; - } catch (ExecutionException e) { - throw new RuntimeException(e); - } - } - - // TODO: load active range first - private class ReloadTask extends Thread { - private volatile boolean mActive = true; - private volatile boolean mDirty = true; - private volatile boolean mIsLoading = false; - - private void updateLoading(boolean loading) { - if (mIsLoading == loading) return; - mIsLoading = loading; - mMainHandler.sendEmptyMessage(loading ? MSG_LOAD_START : MSG_LOAD_FINISH); - } - - @Override - public void run() { - Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); - - boolean updateComplete = false; - while (mActive) { - synchronized (this) { - if (mActive && !mDirty && updateComplete) { - if (!mSource.isLoading()) updateLoading(false); - Utils.waitWithoutInterrupt(this); - continue; - } - } - mDirty = false; - updateLoading(true); - - long version = mSource.reload(); - UpdateInfo info = executeAndWait(new GetUpdateInfo(version)); - updateComplete = info == null; - if (updateComplete) continue; - if (info.version != version) { - info.version = version; - info.size = mSource.getSubMediaSetCount(); - - // If the size becomes smaller after reload(), we may - // receive from GetUpdateInfo an index which is too - // big. Because the main thread is not aware of the size - // change until we call UpdateContent. - if (info.index >= info.size) { - info.index = INDEX_NONE; - } - } - if (info.index != INDEX_NONE) { - info.item = mSource.getSubMediaSet(info.index); - if (info.item == null) continue; - info.cover = info.item.getCoverMediaItem(); - info.totalCount = info.item.getTotalMediaItemCount(); - } - executeAndWait(new UpdateContent(info)); - } - updateLoading(false); - } - - public synchronized void notifyDirty() { - mDirty = true; - notifyAll(); - } - - public synchronized void terminate() { - mActive = false; - notifyAll(); - } - } -} - - diff --git a/src/com/android/gallery3d/app/AlbumSetPage.java b/src/com/android/gallery3d/app/AlbumSetPage.java deleted file mode 100644 index dd9d8ec41..000000000 --- a/src/com/android/gallery3d/app/AlbumSetPage.java +++ /dev/null @@ -1,764 +0,0 @@ -/* - * 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.gallery3d.app; - -import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.graphics.Rect; -import android.os.Bundle; -import android.os.Handler; -import android.os.Message; -import android.view.HapticFeedbackConstants; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; -import android.view.View; -import android.view.View.OnClickListener; -import android.widget.Button; -import android.widget.RelativeLayout; -import android.widget.Toast; - -import com.android.gallery3d.R; -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.data.DataManager; -import com.android.gallery3d.data.MediaDetails; -import com.android.gallery3d.data.MediaItem; -import com.android.gallery3d.data.MediaObject; -import com.android.gallery3d.data.MediaSet; -import com.android.gallery3d.data.Path; -import com.android.gallery3d.glrenderer.FadeTexture; -import com.android.gallery3d.glrenderer.GLCanvas; -import com.android.gallery3d.picasasource.PicasaSource; -import com.android.gallery3d.settings.GallerySettings; -import com.android.gallery3d.ui.ActionModeHandler; -import com.android.gallery3d.ui.ActionModeHandler.ActionModeListener; -import com.android.gallery3d.ui.AlbumSetSlotRenderer; -import com.android.gallery3d.ui.DetailsHelper; -import com.android.gallery3d.ui.DetailsHelper.CloseListener; -import com.android.gallery3d.ui.GLRoot; -import com.android.gallery3d.ui.GLView; -import com.android.gallery3d.ui.SelectionManager; -import com.android.gallery3d.ui.SlotView; -import com.android.gallery3d.ui.SynchronizedHandler; -import com.android.gallery3d.util.Future; -import com.android.gallery3d.util.GalleryUtils; -import com.android.gallery3d.util.HelpUtils; - -import java.lang.ref.WeakReference; -import java.util.ArrayList; - -public class AlbumSetPage extends ActivityState implements - SelectionManager.SelectionListener, GalleryActionBar.ClusterRunner, - EyePosition.EyePositionListener, MediaSet.SyncListener { - @SuppressWarnings("unused") - private static final String TAG = "AlbumSetPage"; - - private static final int MSG_PICK_ALBUM = 1; - - public static final String KEY_MEDIA_PATH = "media-path"; - public static final String KEY_SET_TITLE = "set-title"; - public static final String KEY_SET_SUBTITLE = "set-subtitle"; - public static final String KEY_SELECTED_CLUSTER_TYPE = "selected-cluster"; - - private static final int DATA_CACHE_SIZE = 256; - private static final int REQUEST_DO_ANIMATION = 1; - - private static final int BIT_LOADING_RELOAD = 1; - private static final int BIT_LOADING_SYNC = 2; - - private boolean mIsActive = false; - private SlotView mSlotView; - private AlbumSetSlotRenderer mAlbumSetView; - private Config.AlbumSetPage mConfig; - - private MediaSet mMediaSet; - private String mTitle; - private String mSubtitle; - private boolean mShowClusterMenu; - private GalleryActionBar mActionBar; - private int mSelectedAction; - - protected SelectionManager mSelectionManager; - private AlbumSetDataLoader mAlbumSetDataAdapter; - - private boolean mGetContent; - private boolean mGetAlbum; - private ActionModeHandler mActionModeHandler; - private DetailsHelper mDetailsHelper; - private MyDetailsSource mDetailsSource; - private boolean mShowDetails; - private EyePosition mEyePosition; - private Handler mHandler; - - // The eyes' position of the user, the origin is at the center of the - // device and the unit is in pixels. - private float mX; - private float mY; - private float mZ; - - private Future mSyncTask = null; - - private int mLoadingBits = 0; - private boolean mInitialSynced = false; - - private Button mCameraButton; - private boolean mShowedEmptyToastForSelf = false; - - @Override - protected int getBackgroundColorId() { - return R.color.albumset_background; - } - - private final GLView mRootPane = new GLView() { - private final float mMatrix[] = new float[16]; - - @Override - protected void onLayout( - boolean changed, int left, int top, int right, int bottom) { - mEyePosition.resetPosition(); - - int slotViewTop = mActionBar.getHeight() + mConfig.paddingTop; - int slotViewBottom = bottom - top - mConfig.paddingBottom; - int slotViewRight = right - left; - - if (mShowDetails) { - mDetailsHelper.layout(left, slotViewTop, right, bottom); - } else { - mAlbumSetView.setHighlightItemPath(null); - } - - mSlotView.layout(0, slotViewTop, slotViewRight, slotViewBottom); - } - - @Override - protected void render(GLCanvas canvas) { - canvas.save(GLCanvas.SAVE_FLAG_MATRIX); - GalleryUtils.setViewPointMatrix(mMatrix, - getWidth() / 2 + mX, getHeight() / 2 + mY, mZ); - canvas.multiplyMatrix(mMatrix, 0); - super.render(canvas); - canvas.restore(); - } - }; - - @Override - public void onEyePositionChanged(float x, float y, float z) { - mRootPane.lockRendering(); - mX = x; - mY = y; - mZ = z; - mRootPane.unlockRendering(); - mRootPane.invalidate(); - } - - @Override - public void onBackPressed() { - if (mShowDetails) { - hideDetails(); - } else if (mSelectionManager.inSelectionMode()) { - mSelectionManager.leaveSelectionMode(); - } else { - super.onBackPressed(); - } - } - - private void getSlotCenter(int slotIndex, int center[]) { - Rect offset = new Rect(); - mRootPane.getBoundsOf(mSlotView, offset); - Rect r = mSlotView.getSlotRect(slotIndex); - int scrollX = mSlotView.getScrollX(); - int scrollY = mSlotView.getScrollY(); - center[0] = offset.left + (r.left + r.right) / 2 - scrollX; - center[1] = offset.top + (r.top + r.bottom) / 2 - scrollY; - } - - public void onSingleTapUp(int slotIndex) { - if (!mIsActive) return; - - if (mSelectionManager.inSelectionMode()) { - MediaSet targetSet = mAlbumSetDataAdapter.getMediaSet(slotIndex); - if (targetSet == null) return; // Content is dirty, we shall reload soon - mSelectionManager.toggle(targetSet.getPath()); - mSlotView.invalidate(); - } else { - // Show pressed-up animation for the single-tap. - mAlbumSetView.setPressedIndex(slotIndex); - mAlbumSetView.setPressedUp(); - mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_PICK_ALBUM, slotIndex, 0), - FadeTexture.DURATION); - } - } - - private static boolean albumShouldOpenInFilmstrip(MediaSet album) { - int itemCount = album.getMediaItemCount(); - ArrayList list = (itemCount == 1) ? album.getMediaItem(0, 1) : null; - // open in film strip only if there's one item in the album and the item exists - return (list != null && !list.isEmpty()); - } - - WeakReference mEmptyAlbumToast = null; - - private void showEmptyAlbumToast(int toastLength) { - Toast toast; - if (mEmptyAlbumToast != null) { - toast = mEmptyAlbumToast.get(); - if (toast != null) { - toast.show(); - return; - } - } - toast = Toast.makeText(mActivity, R.string.empty_album, toastLength); - mEmptyAlbumToast = new WeakReference(toast); - toast.show(); - } - - private void hideEmptyAlbumToast() { - if (mEmptyAlbumToast != null) { - Toast toast = mEmptyAlbumToast.get(); - if (toast != null) toast.cancel(); - } - } - - private void pickAlbum(int slotIndex) { - if (!mIsActive) return; - - MediaSet targetSet = mAlbumSetDataAdapter.getMediaSet(slotIndex); - if (targetSet == null) return; // Content is dirty, we shall reload soon - if (targetSet.getTotalMediaItemCount() == 0) { - showEmptyAlbumToast(Toast.LENGTH_SHORT); - return; - } - hideEmptyAlbumToast(); - - String mediaPath = targetSet.getPath().toString(); - - Bundle data = new Bundle(getData()); - int[] center = new int[2]; - getSlotCenter(slotIndex, center); - data.putIntArray(AlbumPage.KEY_SET_CENTER, center); - if (mGetAlbum && targetSet.isLeafAlbum()) { - Activity activity = mActivity; - Intent result = new Intent() - .putExtra(AlbumPicker.KEY_ALBUM_PATH, targetSet.getPath().toString()); - activity.setResult(Activity.RESULT_OK, result); - activity.finish(); - } else if (targetSet.getSubMediaSetCount() > 0) { - data.putString(AlbumSetPage.KEY_MEDIA_PATH, mediaPath); - mActivity.getStateManager().startStateForResult( - AlbumSetPage.class, REQUEST_DO_ANIMATION, data); - } else { - if (!mGetContent && albumShouldOpenInFilmstrip(targetSet)) { - data.putParcelable(PhotoPage.KEY_OPEN_ANIMATION_RECT, - mSlotView.getSlotRect(slotIndex, mRootPane)); - data.putInt(PhotoPage.KEY_INDEX_HINT, 0); - data.putString(PhotoPage.KEY_MEDIA_SET_PATH, - mediaPath); - data.putBoolean(PhotoPage.KEY_START_IN_FILMSTRIP, true); - data.putBoolean(PhotoPage.KEY_IN_CAMERA_ROLL, targetSet.isCameraRoll()); - mActivity.getStateManager().startStateForResult( - FilmstripPage.class, AlbumPage.REQUEST_PHOTO, data); - return; - } - data.putString(AlbumPage.KEY_MEDIA_PATH, mediaPath); - - // We only show cluster menu in the first AlbumPage in stack - boolean inAlbum = mActivity.getStateManager().hasStateClass(AlbumPage.class); - data.putBoolean(AlbumPage.KEY_SHOW_CLUSTER_MENU, !inAlbum); - mActivity.getStateManager().startStateForResult( - AlbumPage.class, REQUEST_DO_ANIMATION, data); - } - } - - private void onDown(int index) { - mAlbumSetView.setPressedIndex(index); - } - - private void onUp(boolean followedByLongPress) { - if (followedByLongPress) { - // Avoid showing press-up animations for long-press. - mAlbumSetView.setPressedIndex(-1); - } else { - mAlbumSetView.setPressedUp(); - } - } - - public void onLongTap(int slotIndex) { - if (mGetContent || mGetAlbum) return; - MediaSet set = mAlbumSetDataAdapter.getMediaSet(slotIndex); - if (set == null) return; - mSelectionManager.setAutoLeaveSelectionMode(true); - mSelectionManager.toggle(set.getPath()); - mSlotView.invalidate(); - } - - @Override - public void doCluster(int clusterType) { - String basePath = mMediaSet.getPath().toString(); - String newPath = FilterUtils.switchClusterPath(basePath, clusterType); - Bundle data = new Bundle(getData()); - data.putString(AlbumSetPage.KEY_MEDIA_PATH, newPath); - data.putInt(KEY_SELECTED_CLUSTER_TYPE, clusterType); - mActivity.getStateManager().switchState(this, AlbumSetPage.class, data); - } - - @Override - public void onCreate(Bundle data, Bundle restoreState) { - super.onCreate(data, restoreState); - initializeViews(); - initializeData(data); - Context context = mActivity.getAndroidContext(); - mGetContent = data.getBoolean(Gallery.KEY_GET_CONTENT, false); - mGetAlbum = data.getBoolean(Gallery.KEY_GET_ALBUM, false); - mTitle = data.getString(AlbumSetPage.KEY_SET_TITLE); - mSubtitle = data.getString(AlbumSetPage.KEY_SET_SUBTITLE); - mEyePosition = new EyePosition(context, this); - mDetailsSource = new MyDetailsSource(); - mActionBar = mActivity.getGalleryActionBar(); - mSelectedAction = data.getInt(AlbumSetPage.KEY_SELECTED_CLUSTER_TYPE, - FilterUtils.CLUSTER_BY_ALBUM); - - mHandler = new SynchronizedHandler(mActivity.getGLRoot()) { - @Override - public void handleMessage(Message message) { - switch (message.what) { - case MSG_PICK_ALBUM: { - pickAlbum(message.arg1); - break; - } - default: throw new AssertionError(message.what); - } - } - }; - } - - @Override - public void onDestroy() { - super.onDestroy(); - cleanupCameraButton(); - mActionModeHandler.destroy(); - } - - private boolean setupCameraButton() { - if (!GalleryUtils.isCameraAvailable(mActivity)) return false; - RelativeLayout galleryRoot = (RelativeLayout) ((Activity) mActivity) - .findViewById(R.id.gallery_root); - if (galleryRoot == null) return false; - - mCameraButton = new Button(mActivity); - mCameraButton.setText(R.string.camera_label); - mCameraButton.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.frame_overlay_gallery_camera, 0, 0); - mCameraButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View arg0) { - GalleryUtils.startCameraActivity(mActivity); - } - }); - RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams( - RelativeLayout.LayoutParams.WRAP_CONTENT, - RelativeLayout.LayoutParams.WRAP_CONTENT); - lp.addRule(RelativeLayout.CENTER_IN_PARENT); - galleryRoot.addView(mCameraButton, lp); - return true; - } - - private void cleanupCameraButton() { - if (mCameraButton == null) return; - RelativeLayout galleryRoot = (RelativeLayout) ((Activity) mActivity) - .findViewById(R.id.gallery_root); - if (galleryRoot == null) return; - galleryRoot.removeView(mCameraButton); - mCameraButton = null; - } - - private void showCameraButton() { - if (mCameraButton == null && !setupCameraButton()) return; - mCameraButton.setVisibility(View.VISIBLE); - } - - private void hideCameraButton() { - if (mCameraButton == null) return; - mCameraButton.setVisibility(View.GONE); - } - - private void clearLoadingBit(int loadingBit) { - mLoadingBits &= ~loadingBit; - if (mLoadingBits == 0 && mIsActive) { - if (mAlbumSetDataAdapter.size() == 0) { - // If this is not the top of the gallery folder hierarchy, - // tell the parent AlbumSetPage instance to handle displaying - // the empty album toast, otherwise show it within this - // instance - if (mActivity.getStateManager().getStateCount() > 1) { - Intent result = new Intent(); - result.putExtra(AlbumPage.KEY_EMPTY_ALBUM, true); - setStateResult(Activity.RESULT_OK, result); - mActivity.getStateManager().finishState(this); - } else { - mShowedEmptyToastForSelf = true; - showEmptyAlbumToast(Toast.LENGTH_LONG); - mSlotView.invalidate(); - showCameraButton(); - } - return; - } - } - // Hide the empty album toast if we are in the root instance of - // AlbumSetPage and the album is no longer empty (for instance, - // after a sync is completed and web albums have been synced) - if (mShowedEmptyToastForSelf) { - mShowedEmptyToastForSelf = false; - hideEmptyAlbumToast(); - hideCameraButton(); - } - } - - private void setLoadingBit(int loadingBit) { - mLoadingBits |= loadingBit; - } - - @Override - public void onPause() { - super.onPause(); - mIsActive = false; - mAlbumSetDataAdapter.pause(); - mAlbumSetView.pause(); - mActionModeHandler.pause(); - mEyePosition.pause(); - DetailsHelper.pause(); - // Call disableClusterMenu to avoid receiving callback after paused. - // Don't hide menu here otherwise the list menu will disappear earlier than - // the action bar, which is janky and unwanted behavior. - mActionBar.disableClusterMenu(false); - if (mSyncTask != null) { - mSyncTask.cancel(); - mSyncTask = null; - clearLoadingBit(BIT_LOADING_SYNC); - } - } - - @Override - public void onResume() { - super.onResume(); - mIsActive = true; - setContentPane(mRootPane); - - // Set the reload bit here to prevent it exit this page in clearLoadingBit(). - setLoadingBit(BIT_LOADING_RELOAD); - mAlbumSetDataAdapter.resume(); - - mAlbumSetView.resume(); - mEyePosition.resume(); - mActionModeHandler.resume(); - if (mShowClusterMenu) { - mActionBar.enableClusterMenu(mSelectedAction, this); - } - if (!mInitialSynced) { - setLoadingBit(BIT_LOADING_SYNC); - mSyncTask = mMediaSet.requestSync(AlbumSetPage.this); - } - } - - private void initializeData(Bundle data) { - String mediaPath = data.getString(AlbumSetPage.KEY_MEDIA_PATH); - mMediaSet = mActivity.getDataManager().getMediaSet(mediaPath); - mSelectionManager.setSourceMediaSet(mMediaSet); - mAlbumSetDataAdapter = new AlbumSetDataLoader( - mActivity, mMediaSet, DATA_CACHE_SIZE); - mAlbumSetDataAdapter.setLoadingListener(new MyLoadingListener()); - mAlbumSetView.setModel(mAlbumSetDataAdapter); - } - - private void initializeViews() { - mSelectionManager = new SelectionManager(mActivity, true); - mSelectionManager.setSelectionListener(this); - - mConfig = Config.AlbumSetPage.get(mActivity); - mSlotView = new SlotView(mActivity, mConfig.slotViewSpec); - mAlbumSetView = new AlbumSetSlotRenderer( - mActivity, mSelectionManager, mSlotView, mConfig.labelSpec, - mConfig.placeholderColor); - mSlotView.setSlotRenderer(mAlbumSetView); - mSlotView.setListener(new SlotView.SimpleListener() { - @Override - public void onDown(int index) { - AlbumSetPage.this.onDown(index); - } - - @Override - public void onUp(boolean followedByLongPress) { - AlbumSetPage.this.onUp(followedByLongPress); - } - - @Override - public void onSingleTapUp(int slotIndex) { - AlbumSetPage.this.onSingleTapUp(slotIndex); - } - - @Override - public void onLongTap(int slotIndex) { - AlbumSetPage.this.onLongTap(slotIndex); - } - }); - - mActionModeHandler = new ActionModeHandler(mActivity, mSelectionManager); - mActionModeHandler.setActionModeListener(new ActionModeListener() { - @Override - public boolean onActionItemClicked(MenuItem item) { - return onItemSelected(item); - } - }); - mRootPane.addComponent(mSlotView); - } - - @Override - protected boolean onCreateActionBar(Menu menu) { - Activity activity = mActivity; - final boolean inAlbum = mActivity.getStateManager().hasStateClass(AlbumPage.class); - MenuInflater inflater = getSupportMenuInflater(); - - if (mGetContent) { - inflater.inflate(R.menu.pickup, menu); - int typeBits = mData.getInt( - Gallery.KEY_TYPE_BITS, DataManager.INCLUDE_IMAGE); - mActionBar.setTitle(GalleryUtils.getSelectionModePrompt(typeBits)); - } else if (mGetAlbum) { - inflater.inflate(R.menu.pickup, menu); - mActionBar.setTitle(R.string.select_album); - } else { - inflater.inflate(R.menu.albumset, menu); - boolean wasShowingClusterMenu = mShowClusterMenu; - mShowClusterMenu = !inAlbum; - boolean selectAlbums = !inAlbum && - mActionBar.getClusterTypeAction() == FilterUtils.CLUSTER_BY_ALBUM; - MenuItem selectItem = menu.findItem(R.id.action_select); - selectItem.setTitle(activity.getString( - selectAlbums ? R.string.select_album : R.string.select_group)); - - MenuItem cameraItem = menu.findItem(R.id.action_camera); - cameraItem.setVisible(GalleryUtils.isCameraAvailable(activity)); - - FilterUtils.setupMenuItems(mActionBar, mMediaSet.getPath(), false); - - Intent helpIntent = HelpUtils.getHelpIntent(activity); - - MenuItem helpItem = menu.findItem(R.id.action_general_help); - helpItem.setVisible(helpIntent != null); - if (helpIntent != null) helpItem.setIntent(helpIntent); - - mActionBar.setTitle(mTitle); - mActionBar.setSubtitle(mSubtitle); - if (mShowClusterMenu != wasShowingClusterMenu) { - if (mShowClusterMenu) { - mActionBar.enableClusterMenu(mSelectedAction, this); - } else { - mActionBar.disableClusterMenu(true); - } - } - } - return true; - } - - @Override - protected boolean onItemSelected(MenuItem item) { - Activity activity = mActivity; - switch (item.getItemId()) { - case R.id.action_cancel: - activity.setResult(Activity.RESULT_CANCELED); - activity.finish(); - return true; - case R.id.action_select: - mSelectionManager.setAutoLeaveSelectionMode(false); - mSelectionManager.enterSelectionMode(); - return true; - case R.id.action_details: - if (mAlbumSetDataAdapter.size() != 0) { - if (mShowDetails) { - hideDetails(); - } else { - showDetails(); - } - } else { - Toast.makeText(activity, - activity.getText(R.string.no_albums_alert), - Toast.LENGTH_SHORT).show(); - } - return true; - case R.id.action_camera: { - GalleryUtils.startCameraActivity(activity); - return true; - } - case R.id.action_manage_offline: { - Bundle data = new Bundle(); - String mediaPath = mActivity.getDataManager().getTopSetPath( - DataManager.INCLUDE_ALL); - data.putString(AlbumSetPage.KEY_MEDIA_PATH, mediaPath); - mActivity.getStateManager().startState(ManageCachePage.class, data); - return true; - } - case R.id.action_sync_picasa_albums: { - PicasaSource.requestSync(activity); - return true; - } - case R.id.action_settings: { - activity.startActivity(new Intent(activity, GallerySettings.class)); - return true; - } - default: - return false; - } - } - - @Override - protected void onStateResult(int requestCode, int resultCode, Intent data) { - if (data != null && data.getBooleanExtra(AlbumPage.KEY_EMPTY_ALBUM, false)) { - showEmptyAlbumToast(Toast.LENGTH_SHORT); - } - switch (requestCode) { - case REQUEST_DO_ANIMATION: { - mSlotView.startRisingAnimation(); - } - } - } - - private String getSelectedString() { - int count = mSelectionManager.getSelectedCount(); - int action = mActionBar.getClusterTypeAction(); - int string = action == FilterUtils.CLUSTER_BY_ALBUM - ? R.plurals.number_of_albums_selected - : R.plurals.number_of_groups_selected; - String format = mActivity.getResources().getQuantityString(string, count); - return String.format(format, count); - } - - @Override - public void onSelectionModeChange(int mode) { - switch (mode) { - case SelectionManager.ENTER_SELECTION_MODE: { - mActionBar.disableClusterMenu(true); - mActionModeHandler.startActionMode(); - performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); - break; - } - case SelectionManager.LEAVE_SELECTION_MODE: { - mActionModeHandler.finishActionMode(); - if (mShowClusterMenu) { - mActionBar.enableClusterMenu(mSelectedAction, this); - } - mRootPane.invalidate(); - break; - } - case SelectionManager.SELECT_ALL_MODE: { - mActionModeHandler.updateSupportedOperation(); - mRootPane.invalidate(); - break; - } - } - } - - @Override - public void onSelectionChange(Path path, boolean selected) { - mActionModeHandler.setTitle(getSelectedString()); - mActionModeHandler.updateSupportedOperation(path, selected); - } - - private void hideDetails() { - mShowDetails = false; - mDetailsHelper.hide(); - mAlbumSetView.setHighlightItemPath(null); - mSlotView.invalidate(); - } - - private void showDetails() { - mShowDetails = true; - if (mDetailsHelper == null) { - mDetailsHelper = new DetailsHelper(mActivity, mRootPane, mDetailsSource); - mDetailsHelper.setCloseListener(new CloseListener() { - @Override - public void onClose() { - hideDetails(); - } - }); - } - mDetailsHelper.show(); - } - - @Override - public void onSyncDone(final MediaSet mediaSet, final int resultCode) { - if (resultCode == MediaSet.SYNC_RESULT_ERROR) { - Log.d(TAG, "onSyncDone: " + Utils.maskDebugInfo(mediaSet.getName()) + " result=" - + resultCode); - } - ((Activity) mActivity).runOnUiThread(new Runnable() { - @Override - public void run() { - GLRoot root = mActivity.getGLRoot(); - root.lockRenderThread(); - try { - if (resultCode == MediaSet.SYNC_RESULT_SUCCESS) { - mInitialSynced = true; - } - clearLoadingBit(BIT_LOADING_SYNC); - if (resultCode == MediaSet.SYNC_RESULT_ERROR && mIsActive) { - Log.w(TAG, "failed to load album set"); - } - } finally { - root.unlockRenderThread(); - } - } - }); - } - - private class MyLoadingListener implements LoadingListener { - @Override - public void onLoadingStarted() { - setLoadingBit(BIT_LOADING_RELOAD); - } - - @Override - public void onLoadingFinished(boolean loadingFailed) { - clearLoadingBit(BIT_LOADING_RELOAD); - } - } - - private class MyDetailsSource implements DetailsHelper.DetailsSource { - private int mIndex; - - @Override - public int size() { - return mAlbumSetDataAdapter.size(); - } - - @Override - public int setIndex() { - Path id = mSelectionManager.getSelected(false).get(0); - mIndex = mAlbumSetDataAdapter.findSet(id); - return mIndex; - } - - @Override - public MediaDetails getDetails() { - MediaObject item = mAlbumSetDataAdapter.getMediaSet(mIndex); - if (item != null) { - mAlbumSetView.setHighlightItemPath(item.getPath()); - return item.getDetails(); - } else { - return null; - } - } - } -} diff --git a/src/com/android/gallery3d/app/AppBridge.java b/src/com/android/gallery3d/app/AppBridge.java deleted file mode 100644 index ee55fa6db..000000000 --- a/src/com/android/gallery3d/app/AppBridge.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * 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. - */ -package com.android.gallery3d.app; - -import android.graphics.Rect; -import android.os.Parcel; -import android.os.Parcelable; - -import com.android.gallery3d.ui.ScreenNail; - -// This is the bridge to connect a PhotoPage to the external environment. -public abstract class AppBridge implements Parcelable { - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - } - - ////////////////////////////////////////////////////////////////////////// - // These are requests sent from PhotoPage to the app - ////////////////////////////////////////////////////////////////////////// - - public abstract boolean isPanorama(); - public abstract boolean isStaticCamera(); - public abstract ScreenNail attachScreenNail(); - public abstract void detachScreenNail(); - - // Return true if the tap is consumed. - public abstract boolean onSingleTapUp(int x, int y); - - // This is used to notify that the screen nail will be drawn in full screen - // or not in next draw() call. - public abstract void onFullScreenChanged(boolean full); - - ////////////////////////////////////////////////////////////////////////// - // These are requests send from app to PhotoPage - ////////////////////////////////////////////////////////////////////////// - - public interface Server { - // Set the camera frame relative to GLRootView. - public void setCameraRelativeFrame(Rect frame); - // Switch to the previous or next picture using the capture animation. - // The offset is -1 to switch to the previous picture, 1 to switch to - // the next picture. - public boolean switchWithCaptureAnimation(int offset); - // Enable or disable the swiping gestures (the default is enabled). - public void setSwipingEnabled(boolean enabled); - // Notify that the ScreenNail is changed. - public void notifyScreenNailChanged(); - // Add a new media item to the secure album. - public void addSecureAlbumItem(boolean isVideo, int id); - } - - // If server is null, the services are not available. - public abstract void setServer(Server server); -} diff --git a/src/com/android/gallery3d/app/BatchService.java b/src/com/android/gallery3d/app/BatchService.java deleted file mode 100644 index 564001d5b..000000000 --- a/src/com/android/gallery3d/app/BatchService.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * 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. - */ - -package com.android.gallery3d.app; - -import android.app.Service; -import android.content.Intent; -import android.os.Binder; -import android.os.IBinder; - -import com.android.gallery3d.util.ThreadPool; - -public class BatchService extends Service { - - public class LocalBinder extends Binder { - BatchService getService() { - return BatchService.this; - } - } - - private final IBinder mBinder = new LocalBinder(); - private ThreadPool mThreadPool = new ThreadPool(1, 1); - - @Override - public IBinder onBind(Intent intent) { - return mBinder; - } - - // The threadpool returned by getThreadPool must have only 1 thread - // running at a time, as MenuExecutor (atrociously) depends on this - // guarantee for synchronization. - public ThreadPool getThreadPool() { - return mThreadPool; - } -} diff --git a/src/com/android/gallery3d/app/CommonControllerOverlay.java b/src/com/android/gallery3d/app/CommonControllerOverlay.java deleted file mode 100644 index 9adb4e7a8..000000000 --- a/src/com/android/gallery3d/app/CommonControllerOverlay.java +++ /dev/null @@ -1,346 +0,0 @@ -/* - * 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. - */ - -package com.android.gallery3d.app; - -import android.content.Context; -import android.content.res.Resources; -import android.graphics.Rect; -import android.view.Gravity; -import android.view.KeyEvent; -import android.view.MotionEvent; -import android.view.View; -import android.view.View.OnClickListener; -import android.widget.FrameLayout; -import android.widget.ImageView; -import android.widget.ImageView.ScaleType; -import android.widget.LinearLayout; -import android.widget.ProgressBar; -import android.widget.RelativeLayout; -import android.widget.TextView; - -import com.android.gallery3d.R; - -/** - * The common playback controller for the Movie Player or Video Trimming. - */ -public abstract class CommonControllerOverlay extends FrameLayout implements - ControllerOverlay, - OnClickListener, - TimeBar.Listener { - - protected enum State { - PLAYING, - PAUSED, - ENDED, - ERROR, - LOADING - } - - private static final float ERROR_MESSAGE_RELATIVE_PADDING = 1.0f / 6; - - protected Listener mListener; - - protected final View mBackground; - protected TimeBar mTimeBar; - - protected View mMainView; - protected final LinearLayout mLoadingView; - protected final TextView mErrorView; - protected final ImageView mPlayPauseReplayView; - - protected State mState; - - protected boolean mCanReplay = true; - - public void setSeekable(boolean canSeek) { - mTimeBar.setSeekable(canSeek); - } - - public CommonControllerOverlay(Context context) { - super(context); - - mState = State.LOADING; - // TODO: Move the following layout code into xml file. - LayoutParams wrapContent = - new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); - LayoutParams matchParent = - new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); - - mBackground = new View(context); - mBackground.setBackgroundColor(context.getResources().getColor(R.color.darker_transparent)); - addView(mBackground, matchParent); - - // Depending on the usage, the timeBar can show a single scrubber, or - // multiple ones for trimming. - createTimeBar(context); - addView(mTimeBar, wrapContent); - mTimeBar.setContentDescription( - context.getResources().getString(R.string.accessibility_time_bar)); - mLoadingView = new LinearLayout(context); - mLoadingView.setOrientation(LinearLayout.VERTICAL); - mLoadingView.setGravity(Gravity.CENTER_HORIZONTAL); - ProgressBar spinner = new ProgressBar(context); - spinner.setIndeterminate(true); - mLoadingView.addView(spinner, wrapContent); - TextView loadingText = createOverlayTextView(context); - loadingText.setText(R.string.loading_video); - mLoadingView.addView(loadingText, wrapContent); - addView(mLoadingView, wrapContent); - - mPlayPauseReplayView = new ImageView(context); - mPlayPauseReplayView.setImageResource(R.drawable.ic_vidcontrol_play); - mPlayPauseReplayView.setContentDescription( - context.getResources().getString(R.string.accessibility_play_video)); - mPlayPauseReplayView.setBackgroundResource(R.drawable.bg_vidcontrol); - mPlayPauseReplayView.setScaleType(ScaleType.CENTER); - mPlayPauseReplayView.setFocusable(true); - mPlayPauseReplayView.setClickable(true); - mPlayPauseReplayView.setOnClickListener(this); - addView(mPlayPauseReplayView, wrapContent); - - mErrorView = createOverlayTextView(context); - addView(mErrorView, matchParent); - - RelativeLayout.LayoutParams params = - new RelativeLayout.LayoutParams( - LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); - setLayoutParams(params); - hide(); - } - - abstract protected void createTimeBar(Context context); - - private TextView createOverlayTextView(Context context) { - TextView view = new TextView(context); - view.setGravity(Gravity.CENTER); - view.setTextColor(0xFFFFFFFF); - view.setPadding(0, 15, 0, 15); - return view; - } - - @Override - public void setListener(Listener listener) { - this.mListener = listener; - } - - @Override - public void setCanReplay(boolean canReplay) { - this.mCanReplay = canReplay; - } - - @Override - public View getView() { - return this; - } - - @Override - public void showPlaying() { - mState = State.PLAYING; - showMainView(mPlayPauseReplayView); - } - - @Override - public void showPaused() { - mState = State.PAUSED; - showMainView(mPlayPauseReplayView); - } - - @Override - public void showEnded() { - mState = State.ENDED; - if (mCanReplay) showMainView(mPlayPauseReplayView); - } - - @Override - public void showLoading() { - mState = State.LOADING; - showMainView(mLoadingView); - } - - @Override - public void showErrorMessage(String message) { - mState = State.ERROR; - int padding = (int) (getMeasuredWidth() * ERROR_MESSAGE_RELATIVE_PADDING); - mErrorView.setPadding( - padding, mErrorView.getPaddingTop(), padding, mErrorView.getPaddingBottom()); - mErrorView.setText(message); - showMainView(mErrorView); - } - - @Override - public void setTimes(int currentTime, int totalTime, - int trimStartTime, int trimEndTime) { - mTimeBar.setTime(currentTime, totalTime, trimStartTime, trimEndTime); - } - - public void hide() { - mPlayPauseReplayView.setVisibility(View.INVISIBLE); - mLoadingView.setVisibility(View.INVISIBLE); - mBackground.setVisibility(View.INVISIBLE); - mTimeBar.setVisibility(View.INVISIBLE); - setVisibility(View.INVISIBLE); - setFocusable(true); - requestFocus(); - } - - private void showMainView(View view) { - mMainView = view; - mErrorView.setVisibility(mMainView == mErrorView ? View.VISIBLE : View.INVISIBLE); - mLoadingView.setVisibility(mMainView == mLoadingView ? View.VISIBLE : View.INVISIBLE); - mPlayPauseReplayView.setVisibility( - mMainView == mPlayPauseReplayView ? View.VISIBLE : View.INVISIBLE); - show(); - } - - @Override - public void show() { - updateViews(); - setVisibility(View.VISIBLE); - setFocusable(false); - } - - @Override - public void onClick(View view) { - if (mListener != null) { - if (view == mPlayPauseReplayView) { - if (mState == State.ENDED) { - if (mCanReplay) { - mListener.onReplay(); - } - } else if (mState == State.PAUSED || mState == State.PLAYING) { - mListener.onPlayPause(); - } - } - } - } - - @Override - public boolean onKeyDown(int keyCode, KeyEvent event) { - return super.onKeyDown(keyCode, event); - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - if (super.onTouchEvent(event)) { - return true; - } - return false; - } - - // The paddings of 4 sides which covered by system components. E.g. - // +-----------------+\ - // | Action Bar | insets.top - // +-----------------+/ - // | | - // | Content Area | insets.right = insets.left = 0 - // | | - // +-----------------+\ - // | Navigation Bar | insets.bottom - // +-----------------+/ - // Please see View.fitSystemWindows() for more details. - private final Rect mWindowInsets = new Rect(); - - @Override - protected boolean fitSystemWindows(Rect insets) { - // We don't set the paddings of this View, otherwise, - // the content will get cropped outside window - mWindowInsets.set(insets); - return true; - } - - @Override - protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - Rect insets = mWindowInsets; - int pl = insets.left; // the left paddings - int pr = insets.right; - int pt = insets.top; - int pb = insets.bottom; - - int h = bottom - top; - int w = right - left; - boolean error = mErrorView.getVisibility() == View.VISIBLE; - - int y = h - pb; - // Put both TimeBar and Background just above the bottom system - // component. - // But extend the background to the width of the screen, since we don't - // care if it will be covered by a system component and it looks better. - mBackground.layout(0, y - mTimeBar.getBarHeight(), w, y); - mTimeBar.layout(pl, y - mTimeBar.getPreferredHeight(), w - pr, y); - - // Put the play/pause/next/ previous button in the center of the screen - layoutCenteredView(mPlayPauseReplayView, 0, 0, w, h); - - if (mMainView != null) { - layoutCenteredView(mMainView, 0, 0, w, h); - } - } - - private void layoutCenteredView(View view, int l, int t, int r, int b) { - int cw = view.getMeasuredWidth(); - int ch = view.getMeasuredHeight(); - int cl = (r - l - cw) / 2; - int ct = (b - t - ch) / 2; - view.layout(cl, ct, cl + cw, ct + ch); - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - measureChildren(widthMeasureSpec, heightMeasureSpec); - } - - protected void updateViews() { - mBackground.setVisibility(View.VISIBLE); - mTimeBar.setVisibility(View.VISIBLE); - Resources resources = getContext().getResources(); - int imageResource = R.drawable.ic_vidcontrol_reload; - String contentDescription = resources.getString(R.string.accessibility_reload_video); - if (mState == State.PAUSED) { - imageResource = R.drawable.ic_vidcontrol_play; - contentDescription = resources.getString(R.string.accessibility_play_video); - } else if (mState == State.PLAYING) { - imageResource = R.drawable.ic_vidcontrol_pause; - contentDescription = resources.getString(R.string.accessibility_pause_video); - } - - mPlayPauseReplayView.setImageResource(imageResource); - mPlayPauseReplayView.setContentDescription(contentDescription); - mPlayPauseReplayView.setVisibility( - (mState != State.LOADING && mState != State.ERROR && - !(mState == State.ENDED && !mCanReplay)) - ? View.VISIBLE : View.GONE); - requestLayout(); - } - - // TimeBar listener - - @Override - public void onScrubbingStart() { - mListener.onSeekStart(); - } - - @Override - public void onScrubbingMove(int time) { - mListener.onSeekMove(time); - } - - @Override - public void onScrubbingEnd(int time, int trimStartTime, int trimEndTime) { - mListener.onSeekEnd(time, trimStartTime, trimEndTime); - } -} diff --git a/src/com/android/gallery3d/app/Config.java b/src/com/android/gallery3d/app/Config.java deleted file mode 100644 index 7183acc33..000000000 --- a/src/com/android/gallery3d/app/Config.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * 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.gallery3d.app; - -import android.content.Context; -import android.content.res.Resources; - -import com.android.gallery3d.R; -import com.android.gallery3d.ui.AlbumSetSlotRenderer; -import com.android.gallery3d.ui.SlotView; - -final class Config { - public static class AlbumSetPage { - private static AlbumSetPage sInstance; - - public SlotView.Spec slotViewSpec; - public AlbumSetSlotRenderer.LabelSpec labelSpec; - public int paddingTop; - public int paddingBottom; - public int placeholderColor; - - public static synchronized AlbumSetPage get(Context context) { - if (sInstance == null) { - sInstance = new AlbumSetPage(context); - } - return sInstance; - } - - private AlbumSetPage(Context context) { - Resources r = context.getResources(); - - placeholderColor = r.getColor(R.color.albumset_placeholder); - - slotViewSpec = new SlotView.Spec(); - slotViewSpec.rowsLand = r.getInteger(R.integer.albumset_rows_land); - slotViewSpec.rowsPort = r.getInteger(R.integer.albumset_rows_port); - slotViewSpec.slotGap = r.getDimensionPixelSize(R.dimen.albumset_slot_gap); - slotViewSpec.slotHeightAdditional = 0; - - paddingTop = r.getDimensionPixelSize(R.dimen.albumset_padding_top); - paddingBottom = r.getDimensionPixelSize(R.dimen.albumset_padding_bottom); - - labelSpec = new AlbumSetSlotRenderer.LabelSpec(); - labelSpec.labelBackgroundHeight = r.getDimensionPixelSize( - R.dimen.albumset_label_background_height); - labelSpec.titleOffset = r.getDimensionPixelSize( - R.dimen.albumset_title_offset); - labelSpec.countOffset = r.getDimensionPixelSize( - R.dimen.albumset_count_offset); - labelSpec.titleFontSize = r.getDimensionPixelSize( - R.dimen.albumset_title_font_size); - labelSpec.countFontSize = r.getDimensionPixelSize( - R.dimen.albumset_count_font_size); - labelSpec.leftMargin = r.getDimensionPixelSize( - R.dimen.albumset_left_margin); - labelSpec.titleRightMargin = r.getDimensionPixelSize( - R.dimen.albumset_title_right_margin); - labelSpec.iconSize = r.getDimensionPixelSize( - R.dimen.albumset_icon_size); - labelSpec.backgroundColor = r.getColor( - R.color.albumset_label_background); - labelSpec.titleColor = r.getColor(R.color.albumset_label_title); - labelSpec.countColor = r.getColor(R.color.albumset_label_count); - } - } - - public static class AlbumPage { - private static AlbumPage sInstance; - - public SlotView.Spec slotViewSpec; - public int placeholderColor; - - public static synchronized AlbumPage get(Context context) { - if (sInstance == null) { - sInstance = new AlbumPage(context); - } - return sInstance; - } - - private AlbumPage(Context context) { - Resources r = context.getResources(); - - placeholderColor = r.getColor(R.color.album_placeholder); - - slotViewSpec = new SlotView.Spec(); - slotViewSpec.rowsLand = r.getInteger(R.integer.album_rows_land); - slotViewSpec.rowsPort = r.getInteger(R.integer.album_rows_port); - slotViewSpec.slotGap = r.getDimensionPixelSize(R.dimen.album_slot_gap); - } - } - - public static class ManageCachePage extends AlbumSetPage { - private static ManageCachePage sInstance; - - public final int cachePinSize; - public final int cachePinMargin; - - public static synchronized ManageCachePage get(Context context) { - if (sInstance == null) { - sInstance = new ManageCachePage(context); - } - return sInstance; - } - - public ManageCachePage(Context context) { - super(context); - Resources r = context.getResources(); - cachePinSize = r.getDimensionPixelSize(R.dimen.cache_pin_size); - cachePinMargin = r.getDimensionPixelSize(R.dimen.cache_pin_margin); - } - } -} - diff --git a/src/com/android/gallery3d/app/ControllerOverlay.java b/src/com/android/gallery3d/app/ControllerOverlay.java deleted file mode 100644 index 078f59e28..000000000 --- a/src/com/android/gallery3d/app/ControllerOverlay.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.app; - -import android.view.View; - -public interface ControllerOverlay { - - interface Listener { - void onPlayPause(); - void onSeekStart(); - void onSeekMove(int time); - void onSeekEnd(int time, int trimStartTime, int trimEndTime); - void onShown(); - void onHidden(); - void onReplay(); - } - - void setListener(Listener listener); - - void setCanReplay(boolean canReplay); - - /** - * @return The overlay view that should be added to the player. - */ - View getView(); - - void show(); - - void showPlaying(); - - void showPaused(); - - void showEnded(); - - void showLoading(); - - void showErrorMessage(String message); - - void setTimes(int currentTime, int totalTime, - int trimStartTime, int trimEndTime); -} diff --git a/src/com/android/gallery3d/app/DialogPicker.java b/src/com/android/gallery3d/app/DialogPicker.java deleted file mode 100644 index 7ca86e5b4..000000000 --- a/src/com/android/gallery3d/app/DialogPicker.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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.gallery3d.app; - -import android.content.Intent; -import android.os.Bundle; - -import com.android.gallery3d.util.GalleryUtils; - -public class DialogPicker extends PickerActivity { - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - int typeBits = GalleryUtils.determineTypeBits(this, getIntent()); - setTitle(GalleryUtils.getSelectionModePrompt(typeBits)); - Intent intent = getIntent(); - Bundle extras = intent.getExtras(); - Bundle data = extras == null ? new Bundle() : new Bundle(extras); - - data.putBoolean(Gallery.KEY_GET_CONTENT, true); - data.putString(AlbumSetPage.KEY_MEDIA_PATH, - getDataManager().getTopSetPath(typeBits)); - getStateManager().startState(AlbumSetPage.class, data); - } -} diff --git a/src/com/android/gallery3d/app/EyePosition.java b/src/com/android/gallery3d/app/EyePosition.java deleted file mode 100644 index d99d97b0e..000000000 --- a/src/com/android/gallery3d/app/EyePosition.java +++ /dev/null @@ -1,226 +0,0 @@ -/* - * 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.gallery3d.app; - -import android.content.Context; -import android.hardware.Sensor; -import android.hardware.SensorEvent; -import android.hardware.SensorEventListener; -import android.hardware.SensorManager; -import android.os.SystemClock; -import android.util.FloatMath; -import android.view.Display; -import android.view.Surface; -import android.view.WindowManager; - -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.util.GalleryUtils; - -public class EyePosition { - @SuppressWarnings("unused") - private static final String TAG = "EyePosition"; - - public interface EyePositionListener { - public void onEyePositionChanged(float x, float y, float z); - } - - private static final float GYROSCOPE_THRESHOLD = 0.15f; - private static final float GYROSCOPE_LIMIT = 10f; - private static final int GYROSCOPE_SETTLE_DOWN = 15; - private static final float GYROSCOPE_RESTORE_FACTOR = 0.995f; - - private static final float USER_ANGEL = (float) Math.toRadians(10); - private static final float USER_ANGEL_COS = FloatMath.cos(USER_ANGEL); - private static final float USER_ANGEL_SIN = FloatMath.sin(USER_ANGEL); - private static final float MAX_VIEW_RANGE = (float) 0.5; - private static final int NOT_STARTED = -1; - - private static final float USER_DISTANCE_METER = 0.3f; - - private Context mContext; - private EyePositionListener mListener; - private Display mDisplay; - // The eyes' position of the user, the origin is at the center of the - // device and the unit is in pixels. - private float mX; - private float mY; - private float mZ; - - private final float mUserDistance; // in pixel - private final float mLimit; - private long mStartTime = NOT_STARTED; - private Sensor mSensor; - private PositionListener mPositionListener = new PositionListener(); - - private int mGyroscopeCountdown = 0; - - public EyePosition(Context context, EyePositionListener listener) { - mContext = context; - mListener = listener; - mUserDistance = GalleryUtils.meterToPixel(USER_DISTANCE_METER); - mLimit = mUserDistance * MAX_VIEW_RANGE; - - WindowManager wManager = (WindowManager) mContext - .getSystemService(Context.WINDOW_SERVICE); - mDisplay = wManager.getDefaultDisplay(); - - // The 3D effect where the photo albums fan out in 3D based on angle - // of device tilt is currently disabled. -/* - SensorManager sManager = (SensorManager) mContext - .getSystemService(Context.SENSOR_SERVICE); - mSensor = sManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE); - if (mSensor == null) { - Log.w(TAG, "no gyroscope, use accelerometer instead"); - mSensor = sManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); - } - if (mSensor == null) { - Log.w(TAG, "no sensor available"); - } -*/ - } - - public void resetPosition() { - mStartTime = NOT_STARTED; - mX = mY = 0; - mZ = -mUserDistance; - mListener.onEyePositionChanged(mX, mY, mZ); - } - - /* - * We assume the user is at the following position - * - * /|\ user's eye - * | / - * -G(gravity) | / - * |_/ - * / |/_____\ -Y (-y direction of device) - * user angel - */ - private void onAccelerometerChanged(float gx, float gy, float gz) { - - float x = gx, y = gy, z = gz; - - switch (mDisplay.getRotation()) { - case Surface.ROTATION_90: x = -gy; y= gx; break; - case Surface.ROTATION_180: x = -gx; y = -gy; break; - case Surface.ROTATION_270: x = gy; y = -gx; break; - } - - float temp = x * x + y * y + z * z; - float t = -y /temp; - - float tx = t * x; - float ty = -1 + t * y; - float tz = t * z; - - float length = FloatMath.sqrt(tx * tx + ty * ty + tz * tz); - float glength = FloatMath.sqrt(temp); - - mX = Utils.clamp((x * USER_ANGEL_COS / glength - + tx * USER_ANGEL_SIN / length) * mUserDistance, - -mLimit, mLimit); - mY = -Utils.clamp((y * USER_ANGEL_COS / glength - + ty * USER_ANGEL_SIN / length) * mUserDistance, - -mLimit, mLimit); - mZ = -FloatMath.sqrt( - mUserDistance * mUserDistance - mX * mX - mY * mY); - mListener.onEyePositionChanged(mX, mY, mZ); - } - - private void onGyroscopeChanged(float gx, float gy, float gz) { - long now = SystemClock.elapsedRealtime(); - float distance = (gx > 0 ? gx : -gx) + (gy > 0 ? gy : - gy); - if (distance < GYROSCOPE_THRESHOLD - || distance > GYROSCOPE_LIMIT || mGyroscopeCountdown > 0) { - --mGyroscopeCountdown; - mStartTime = now; - float limit = mUserDistance / 20f; - if (mX > limit || mX < -limit || mY > limit || mY < -limit) { - mX *= GYROSCOPE_RESTORE_FACTOR; - mY *= GYROSCOPE_RESTORE_FACTOR; - mZ = (float) -Math.sqrt( - mUserDistance * mUserDistance - mX * mX - mY * mY); - mListener.onEyePositionChanged(mX, mY, mZ); - } - return; - } - - float t = (now - mStartTime) / 1000f * mUserDistance * (-mZ); - mStartTime = now; - - float x = -gy, y = -gx; - switch (mDisplay.getRotation()) { - case Surface.ROTATION_90: x = -gx; y= gy; break; - case Surface.ROTATION_180: x = gy; y = gx; break; - case Surface.ROTATION_270: x = gx; y = -gy; break; - } - - mX = Utils.clamp((float) (mX + x * t / Math.hypot(mZ, mX)), - -mLimit, mLimit) * GYROSCOPE_RESTORE_FACTOR; - mY = Utils.clamp((float) (mY + y * t / Math.hypot(mZ, mY)), - -mLimit, mLimit) * GYROSCOPE_RESTORE_FACTOR; - - mZ = -FloatMath.sqrt( - mUserDistance * mUserDistance - mX * mX - mY * mY); - mListener.onEyePositionChanged(mX, mY, mZ); - } - - private class PositionListener implements SensorEventListener { - @Override - public void onAccuracyChanged(Sensor sensor, int accuracy) { - } - - @Override - public void onSensorChanged(SensorEvent event) { - switch (event.sensor.getType()) { - case Sensor.TYPE_GYROSCOPE: { - onGyroscopeChanged( - event.values[0], event.values[1], event.values[2]); - break; - } - case Sensor.TYPE_ACCELEROMETER: { - onAccelerometerChanged( - event.values[0], event.values[1], event.values[2]); - } - } - } - } - - public void pause() { - if (mSensor != null) { - SensorManager sManager = (SensorManager) mContext - .getSystemService(Context.SENSOR_SERVICE); - sManager.unregisterListener(mPositionListener); - } - } - - public void resume() { - if (mSensor != null) { - SensorManager sManager = (SensorManager) mContext - .getSystemService(Context.SENSOR_SERVICE); - sManager.registerListener(mPositionListener, - mSensor, SensorManager.SENSOR_DELAY_GAME); - } - - mStartTime = NOT_STARTED; - mGyroscopeCountdown = GYROSCOPE_SETTLE_DOWN; - mX = mY = 0; - mZ = -mUserDistance; - mListener.onEyePositionChanged(mX, mY, mZ); - } -} diff --git a/src/com/android/gallery3d/app/FilmstripPage.java b/src/com/android/gallery3d/app/FilmstripPage.java deleted file mode 100644 index a9726cdc9..000000000 --- a/src/com/android/gallery3d/app/FilmstripPage.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * 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. - */ - -package com.android.gallery3d.app; - -public class FilmstripPage extends PhotoPage { - -} diff --git a/src/com/android/gallery3d/app/FilterUtils.java b/src/com/android/gallery3d/app/FilterUtils.java deleted file mode 100644 index bc28a9cc1..000000000 --- a/src/com/android/gallery3d/app/FilterUtils.java +++ /dev/null @@ -1,257 +0,0 @@ -/* - * 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.gallery3d.app; - -import com.android.gallery3d.R; -import com.android.gallery3d.data.MediaObject; -import com.android.gallery3d.data.Path; - -// This class handles filtering and clustering. -// -// We allow at most only one filter operation at a time (Currently it -// doesn't make sense to use more than one). Also each clustering operation -// can be applied at most once. In addition, there is one more constraint -// ("fixed set constraint") described below. -// -// A clustered album (not including album set) and its base sets are fixed. -// For example, -// -// /cluster/{base_set}/time/7 -// -// This set and all sets inside base_set (recursively) are fixed because -// 1. We can not change this set to use another clustering condition (like -// changing "time" to "location"). -// 2. Neither can we change any set in the base_set. -// The reason is in both cases the 7th set may not exist in the new clustering. -// --------------------- -// newPath operation: create a new path based on a source path and put an extra -// condition on top of it: -// -// T = newFilterPath(S, filterType); -// T = newClusterPath(S, clusterType); -// -// Similar functions can be used to replace the current condition (if there is one). -// -// T = switchFilterPath(S, filterType); -// T = switchClusterPath(S, clusterType); -// -// For all fixed set in the path defined above, if some clusterType and -// filterType are already used, they cannot not be used as parameter for these -// functions. setupMenuItems() makes sure those types cannot be selected. -// -public class FilterUtils { - @SuppressWarnings("unused") - private static final String TAG = "FilterUtils"; - - public static final int CLUSTER_BY_ALBUM = 1; - public static final int CLUSTER_BY_TIME = 2; - public static final int CLUSTER_BY_LOCATION = 4; - public static final int CLUSTER_BY_TAG = 8; - public static final int CLUSTER_BY_SIZE = 16; - public static final int CLUSTER_BY_FACE = 32; - - public static final int FILTER_IMAGE_ONLY = 1; - public static final int FILTER_VIDEO_ONLY = 2; - public static final int FILTER_ALL = 4; - - // These are indices of the return values of getAppliedFilters(). - // The _F suffix means "fixed". - private static final int CLUSTER_TYPE = 0; - private static final int FILTER_TYPE = 1; - private static final int CLUSTER_TYPE_F = 2; - private static final int FILTER_TYPE_F = 3; - private static final int CLUSTER_CURRENT_TYPE = 4; - private static final int FILTER_CURRENT_TYPE = 5; - - public static void setupMenuItems(GalleryActionBar actionBar, Path path, boolean inAlbum) { - int[] result = new int[6]; - getAppliedFilters(path, result); - int ctype = result[CLUSTER_TYPE]; - int ftype = result[FILTER_TYPE]; - int ftypef = result[FILTER_TYPE_F]; - int ccurrent = result[CLUSTER_CURRENT_TYPE]; - int fcurrent = result[FILTER_CURRENT_TYPE]; - - setMenuItemApplied(actionBar, CLUSTER_BY_TIME, - (ctype & CLUSTER_BY_TIME) != 0, (ccurrent & CLUSTER_BY_TIME) != 0); - setMenuItemApplied(actionBar, CLUSTER_BY_LOCATION, - (ctype & CLUSTER_BY_LOCATION) != 0, (ccurrent & CLUSTER_BY_LOCATION) != 0); - setMenuItemApplied(actionBar, CLUSTER_BY_TAG, - (ctype & CLUSTER_BY_TAG) != 0, (ccurrent & CLUSTER_BY_TAG) != 0); - setMenuItemApplied(actionBar, CLUSTER_BY_FACE, - (ctype & CLUSTER_BY_FACE) != 0, (ccurrent & CLUSTER_BY_FACE) != 0); - - actionBar.setClusterItemVisibility(CLUSTER_BY_ALBUM, !inAlbum || ctype == 0); - - setMenuItemApplied(actionBar, R.id.action_cluster_album, ctype == 0, - ccurrent == 0); - - // A filtering is available if it's not applied, and the old filtering - // (if any) is not fixed. - setMenuItemAppliedEnabled(actionBar, R.string.show_images_only, - (ftype & FILTER_IMAGE_ONLY) != 0, - (ftype & FILTER_IMAGE_ONLY) == 0 && ftypef == 0, - (fcurrent & FILTER_IMAGE_ONLY) != 0); - setMenuItemAppliedEnabled(actionBar, R.string.show_videos_only, - (ftype & FILTER_VIDEO_ONLY) != 0, - (ftype & FILTER_VIDEO_ONLY) == 0 && ftypef == 0, - (fcurrent & FILTER_VIDEO_ONLY) != 0); - setMenuItemAppliedEnabled(actionBar, R.string.show_all, - ftype == 0, ftype != 0 && ftypef == 0, fcurrent == 0); - } - - // Gets the filters applied in the path. - private static void getAppliedFilters(Path path, int[] result) { - getAppliedFilters(path, result, false); - } - - private static void getAppliedFilters(Path path, int[] result, boolean underCluster) { - String[] segments = path.split(); - // Recurse into sub media sets. - for (int i = 0; i < segments.length; i++) { - if (segments[i].startsWith("{")) { - String[] sets = Path.splitSequence(segments[i]); - for (int j = 0; j < sets.length; j++) { - Path sub = Path.fromString(sets[j]); - getAppliedFilters(sub, result, underCluster); - } - } - } - - // update current selection - if (segments[0].equals("cluster")) { - // if this is a clustered album, set underCluster to true. - if (segments.length == 4) { - underCluster = true; - } - - int ctype = toClusterType(segments[2]); - result[CLUSTER_TYPE] |= ctype; - result[CLUSTER_CURRENT_TYPE] = ctype; - if (underCluster) { - result[CLUSTER_TYPE_F] |= ctype; - } - } - } - - private static int toClusterType(String s) { - if (s.equals("time")) { - return CLUSTER_BY_TIME; - } else if (s.equals("location")) { - return CLUSTER_BY_LOCATION; - } else if (s.equals("tag")) { - return CLUSTER_BY_TAG; - } else if (s.equals("size")) { - return CLUSTER_BY_SIZE; - } else if (s.equals("face")) { - return CLUSTER_BY_FACE; - } - return 0; - } - - private static void setMenuItemApplied( - GalleryActionBar model, int id, boolean applied, boolean updateTitle) { - model.setClusterItemEnabled(id, !applied); - } - - private static void setMenuItemAppliedEnabled(GalleryActionBar model, int id, boolean applied, boolean enabled, boolean updateTitle) { - model.setClusterItemEnabled(id, enabled); - } - - // Add a specified filter to the path. - public static String newFilterPath(String base, int filterType) { - int mediaType; - switch (filterType) { - case FILTER_IMAGE_ONLY: - mediaType = MediaObject.MEDIA_TYPE_IMAGE; - break; - case FILTER_VIDEO_ONLY: - mediaType = MediaObject.MEDIA_TYPE_VIDEO; - break; - default: /* FILTER_ALL */ - return base; - } - - return "/filter/mediatype/" + mediaType + "/{" + base + "}"; - } - - // Add a specified clustering to the path. - public static String newClusterPath(String base, int clusterType) { - String kind; - switch (clusterType) { - case CLUSTER_BY_TIME: - kind = "time"; - break; - case CLUSTER_BY_LOCATION: - kind = "location"; - break; - case CLUSTER_BY_TAG: - kind = "tag"; - break; - case CLUSTER_BY_SIZE: - kind = "size"; - break; - case CLUSTER_BY_FACE: - kind = "face"; - break; - default: /* CLUSTER_BY_ALBUM */ - return base; - } - - return "/cluster/{" + base + "}/" + kind; - } - - // Change the topmost clustering to the specified type. - public static String switchClusterPath(String base, int clusterType) { - return newClusterPath(removeOneClusterFromPath(base), clusterType); - } - - // Remove the topmost clustering (if any) from the path. - private static String removeOneClusterFromPath(String base) { - boolean[] done = new boolean[1]; - return removeOneClusterFromPath(base, done); - } - - private static String removeOneClusterFromPath(String base, boolean[] done) { - if (done[0]) return base; - - String[] segments = Path.split(base); - if (segments[0].equals("cluster")) { - done[0] = true; - return Path.splitSequence(segments[1])[0]; - } - - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < segments.length; i++) { - sb.append("/"); - if (segments[i].startsWith("{")) { - sb.append("{"); - String[] sets = Path.splitSequence(segments[i]); - for (int j = 0; j < sets.length; j++) { - if (j > 0) { - sb.append(","); - } - sb.append(removeOneClusterFromPath(sets[j], done)); - } - sb.append("}"); - } else { - sb.append(segments[i]); - } - } - return sb.toString(); - } -} diff --git a/src/com/android/gallery3d/app/Gallery.java b/src/com/android/gallery3d/app/Gallery.java deleted file mode 100644 index baef56b44..000000000 --- a/src/com/android/gallery3d/app/Gallery.java +++ /dev/null @@ -1,274 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.app; - -import android.app.Dialog; -import android.content.ContentResolver; -import android.content.DialogInterface; -import android.content.DialogInterface.OnCancelListener; -import android.content.Intent; -import android.net.Uri; -import android.os.Bundle; -import android.view.InputDevice; -import android.view.MotionEvent; -import android.view.View; -import android.view.Window; -import android.view.WindowManager; -import android.widget.Toast; - -import com.android.gallery3d.R; -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.data.DataManager; -import com.android.gallery3d.data.MediaItem; -import com.android.gallery3d.data.MediaSet; -import com.android.gallery3d.data.Path; -import com.android.gallery3d.picasasource.PicasaSource; -import com.android.gallery3d.util.GalleryUtils; - -public final class Gallery extends AbstractGalleryActivity implements OnCancelListener { - public static final String EXTRA_SLIDESHOW = "slideshow"; - public static final String EXTRA_DREAM = "dream"; - public static final String EXTRA_CROP = "crop"; - - public static final String ACTION_REVIEW = "com.android.camera.action.REVIEW"; - public static final String KEY_GET_CONTENT = "get-content"; - public static final String KEY_GET_ALBUM = "get-album"; - public static final String KEY_TYPE_BITS = "type-bits"; - public static final String KEY_MEDIA_TYPES = "mediaTypes"; - public static final String KEY_DISMISS_KEYGUARD = "dismiss-keyguard"; - - private static final String TAG = "Gallery"; - private Dialog mVersionCheckDialog; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - requestWindowFeature(Window.FEATURE_ACTION_BAR); - requestWindowFeature(Window.FEATURE_ACTION_BAR_OVERLAY); - - if (getIntent().getBooleanExtra(KEY_DISMISS_KEYGUARD, false)) { - getWindow().addFlags( - WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD); - } - - setContentView(R.layout.main); - - if (savedInstanceState != null) { - getStateManager().restoreFromState(savedInstanceState); - } else { - initializeByIntent(); - } - } - - private void initializeByIntent() { - Intent intent = getIntent(); - String action = intent.getAction(); - - if (Intent.ACTION_GET_CONTENT.equalsIgnoreCase(action)) { - startGetContent(intent); - } else if (Intent.ACTION_PICK.equalsIgnoreCase(action)) { - // We do NOT really support the PICK intent. Handle it as - // the GET_CONTENT. However, we need to translate the type - // in the intent here. - Log.w(TAG, "action PICK is not supported"); - String type = Utils.ensureNotNull(intent.getType()); - if (type.startsWith("vnd.android.cursor.dir/")) { - if (type.endsWith("/image")) intent.setType("image/*"); - if (type.endsWith("/video")) intent.setType("video/*"); - } - startGetContent(intent); - } else if (Intent.ACTION_VIEW.equalsIgnoreCase(action) - || ACTION_REVIEW.equalsIgnoreCase(action)){ - startViewAction(intent); - } else { - startDefaultPage(); - } - } - - public void startDefaultPage() { - PicasaSource.showSignInReminder(this); - Bundle data = new Bundle(); - data.putString(AlbumSetPage.KEY_MEDIA_PATH, - getDataManager().getTopSetPath(DataManager.INCLUDE_ALL)); - getStateManager().startState(AlbumSetPage.class, data); - mVersionCheckDialog = PicasaSource.getVersionCheckDialog(this); - if (mVersionCheckDialog != null) { - mVersionCheckDialog.setOnCancelListener(this); - } - } - - private void startGetContent(Intent intent) { - Bundle data = intent.getExtras() != null - ? new Bundle(intent.getExtras()) - : new Bundle(); - data.putBoolean(KEY_GET_CONTENT, true); - int typeBits = GalleryUtils.determineTypeBits(this, intent); - data.putInt(KEY_TYPE_BITS, typeBits); - data.putString(AlbumSetPage.KEY_MEDIA_PATH, - getDataManager().getTopSetPath(typeBits)); - getStateManager().startState(AlbumSetPage.class, data); - } - - private String getContentType(Intent intent) { - String type = intent.getType(); - if (type != null) { - return GalleryUtils.MIME_TYPE_PANORAMA360.equals(type) - ? MediaItem.MIME_TYPE_JPEG : type; - } - - Uri uri = intent.getData(); - try { - return getContentResolver().getType(uri); - } catch (Throwable t) { - Log.w(TAG, "get type fail", t); - return null; - } - } - - private void startViewAction(Intent intent) { - Boolean slideshow = intent.getBooleanExtra(EXTRA_SLIDESHOW, false); - if (slideshow) { - getActionBar().hide(); - DataManager manager = getDataManager(); - Path path = manager.findPathByUri(intent.getData(), intent.getType()); - if (path == null || manager.getMediaObject(path) - instanceof MediaItem) { - path = Path.fromString( - manager.getTopSetPath(DataManager.INCLUDE_IMAGE)); - } - Bundle data = new Bundle(); - data.putString(SlideshowPage.KEY_SET_PATH, path.toString()); - data.putBoolean(SlideshowPage.KEY_RANDOM_ORDER, true); - data.putBoolean(SlideshowPage.KEY_REPEAT, true); - if (intent.getBooleanExtra(EXTRA_DREAM, false)) { - data.putBoolean(SlideshowPage.KEY_DREAM, true); - } - getStateManager().startState(SlideshowPage.class, data); - } else { - Bundle data = new Bundle(); - DataManager dm = getDataManager(); - Uri uri = intent.getData(); - String contentType = getContentType(intent); - if (contentType == null) { - Toast.makeText(this, - R.string.no_such_item, Toast.LENGTH_LONG).show(); - finish(); - return; - } - if (uri == null) { - int typeBits = GalleryUtils.determineTypeBits(this, intent); - data.putInt(KEY_TYPE_BITS, typeBits); - data.putString(AlbumSetPage.KEY_MEDIA_PATH, - getDataManager().getTopSetPath(typeBits)); - getStateManager().startState(AlbumSetPage.class, data); - } else if (contentType.startsWith( - ContentResolver.CURSOR_DIR_BASE_TYPE)) { - int mediaType = intent.getIntExtra(KEY_MEDIA_TYPES, 0); - if (mediaType != 0) { - uri = uri.buildUpon().appendQueryParameter( - KEY_MEDIA_TYPES, String.valueOf(mediaType)) - .build(); - } - Path setPath = dm.findPathByUri(uri, null); - MediaSet mediaSet = null; - if (setPath != null) { - mediaSet = (MediaSet) dm.getMediaObject(setPath); - } - if (mediaSet != null) { - if (mediaSet.isLeafAlbum()) { - data.putString(AlbumPage.KEY_MEDIA_PATH, setPath.toString()); - data.putString(AlbumPage.KEY_PARENT_MEDIA_PATH, - dm.getTopSetPath(DataManager.INCLUDE_ALL)); - getStateManager().startState(AlbumPage.class, data); - } else { - data.putString(AlbumSetPage.KEY_MEDIA_PATH, setPath.toString()); - getStateManager().startState(AlbumSetPage.class, data); - } - } else { - startDefaultPage(); - } - } else { - Path itemPath = dm.findPathByUri(uri, contentType); - Path albumPath = dm.getDefaultSetOf(itemPath); - - data.putString(PhotoPage.KEY_MEDIA_ITEM_PATH, itemPath.toString()); - - // TODO: Make the parameter "SingleItemOnly" public so other - // activities can reference it. - boolean singleItemOnly = (albumPath == null) - || intent.getBooleanExtra("SingleItemOnly", false); - if (!singleItemOnly) { - data.putString(PhotoPage.KEY_MEDIA_SET_PATH, albumPath.toString()); - // when FLAG_ACTIVITY_NEW_TASK is set, (e.g. when intent is fired - // from notification), back button should behave the same as up button - // rather than taking users back to the home screen - if (intent.getBooleanExtra(PhotoPage.KEY_TREAT_BACK_AS_UP, false) - || ((intent.getFlags() & Intent.FLAG_ACTIVITY_NEW_TASK) != 0)) { - data.putBoolean(PhotoPage.KEY_TREAT_BACK_AS_UP, true); - } - } - - getStateManager().startState(SinglePhotoPage.class, data); - } - } - } - - @Override - protected void onResume() { - Utils.assertTrue(getStateManager().getStateCount() > 0); - super.onResume(); - if (mVersionCheckDialog != null) { - mVersionCheckDialog.show(); - } - } - - @Override - protected void onPause() { - super.onPause(); - if (mVersionCheckDialog != null) { - mVersionCheckDialog.dismiss(); - } - } - - @Override - public void onCancel(DialogInterface dialog) { - if (dialog == mVersionCheckDialog) { - mVersionCheckDialog = null; - } - } - - @Override - public boolean onGenericMotionEvent(MotionEvent event) { - final boolean isTouchPad = (event.getSource() - & InputDevice.SOURCE_CLASS_POSITION) != 0; - if (isTouchPad) { - float maxX = event.getDevice().getMotionRange(MotionEvent.AXIS_X).getMax(); - float maxY = event.getDevice().getMotionRange(MotionEvent.AXIS_Y).getMax(); - View decor = getWindow().getDecorView(); - float scaleX = decor.getWidth() / maxX; - float scaleY = decor.getHeight() / maxY; - float x = event.getX() * scaleX; - //x = decor.getWidth() - x; // invert x - float y = event.getY() * scaleY; - //y = decor.getHeight() - y; // invert y - MotionEvent touchEvent = MotionEvent.obtain(event.getDownTime(), - event.getEventTime(), event.getAction(), x, y, event.getMetaState()); - return dispatchTouchEvent(touchEvent); - } - return super.onGenericMotionEvent(event); - } -} diff --git a/src/com/android/gallery3d/app/GalleryActionBar.java b/src/com/android/gallery3d/app/GalleryActionBar.java deleted file mode 100644 index 588f5842a..000000000 --- a/src/com/android/gallery3d/app/GalleryActionBar.java +++ /dev/null @@ -1,438 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.app; - -import android.annotation.TargetApi; -import android.app.ActionBar; -import android.app.ActionBar.OnMenuVisibilityListener; -import android.app.ActionBar.OnNavigationListener; -import android.app.Activity; -import android.app.AlertDialog; -import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; -import android.content.res.Resources; -import android.view.LayoutInflater; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.widget.BaseAdapter; -import android.widget.ShareActionProvider; -import android.widget.TextView; -import android.widget.TwoLineListItem; - -import com.android.gallery3d.R; -import com.android.gallery3d.common.ApiHelper; - -import java.util.ArrayList; - -public class GalleryActionBar implements OnNavigationListener { - @SuppressWarnings("unused") - private static final String TAG = "GalleryActionBar"; - - private ClusterRunner mClusterRunner; - private CharSequence[] mTitles; - private ArrayList mActions; - private Context mContext; - private LayoutInflater mInflater; - private AbstractGalleryActivity mActivity; - private ActionBar mActionBar; - private int mCurrentIndex; - private ClusterAdapter mAdapter = new ClusterAdapter(); - - private AlbumModeAdapter mAlbumModeAdapter; - private OnAlbumModeSelectedListener mAlbumModeListener; - private int mLastAlbumModeSelected; - private CharSequence [] mAlbumModes; - public static final int ALBUM_FILMSTRIP_MODE_SELECTED = 0; - public static final int ALBUM_GRID_MODE_SELECTED = 1; - - public interface ClusterRunner { - public void doCluster(int id); - } - - public interface OnAlbumModeSelectedListener { - public void onAlbumModeSelected(int mode); - } - - private static class ActionItem { - public int action; - public boolean enabled; - public boolean visible; - public int spinnerTitle; - public int dialogTitle; - public int clusterBy; - - public ActionItem(int action, boolean applied, boolean enabled, int title, - int clusterBy) { - this(action, applied, enabled, title, title, clusterBy); - } - - public ActionItem(int action, boolean applied, boolean enabled, int spinnerTitle, - int dialogTitle, int clusterBy) { - this.action = action; - this.enabled = enabled; - this.spinnerTitle = spinnerTitle; - this.dialogTitle = dialogTitle; - this.clusterBy = clusterBy; - this.visible = true; - } - } - - private static final ActionItem[] sClusterItems = new ActionItem[] { - new ActionItem(FilterUtils.CLUSTER_BY_ALBUM, true, false, R.string.albums, - R.string.group_by_album), - new ActionItem(FilterUtils.CLUSTER_BY_LOCATION, true, false, - R.string.locations, R.string.location, R.string.group_by_location), - new ActionItem(FilterUtils.CLUSTER_BY_TIME, true, false, R.string.times, - R.string.time, R.string.group_by_time), - new ActionItem(FilterUtils.CLUSTER_BY_FACE, true, false, R.string.people, - R.string.group_by_faces), - new ActionItem(FilterUtils.CLUSTER_BY_TAG, true, false, R.string.tags, - R.string.group_by_tags) - }; - - private class ClusterAdapter extends BaseAdapter { - - @Override - public int getCount() { - return sClusterItems.length; - } - - @Override - public Object getItem(int position) { - return sClusterItems[position]; - } - - @Override - public long getItemId(int position) { - return sClusterItems[position].action; - } - - @Override - public View getView(int position, View convertView, ViewGroup parent) { - if (convertView == null) { - convertView = mInflater.inflate(R.layout.action_bar_text, - parent, false); - } - TextView view = (TextView) convertView; - view.setText(sClusterItems[position].spinnerTitle); - return convertView; - } - } - - private class AlbumModeAdapter extends BaseAdapter { - @Override - public int getCount() { - return mAlbumModes.length; - } - - @Override - public Object getItem(int position) { - return mAlbumModes[position]; - } - - @Override - public long getItemId(int position) { - return position; - } - - @Override - public View getView(int position, View convertView, ViewGroup parent) { - if (convertView == null) { - convertView = mInflater.inflate(R.layout.action_bar_two_line_text, - parent, false); - } - TwoLineListItem view = (TwoLineListItem) convertView; - view.getText1().setText(mActionBar.getTitle()); - view.getText2().setText((CharSequence) getItem(position)); - return convertView; - } - - @Override - public View getDropDownView(int position, View convertView, ViewGroup parent) { - if (convertView == null) { - convertView = mInflater.inflate(R.layout.action_bar_text, - parent, false); - } - TextView view = (TextView) convertView; - view.setText((CharSequence) getItem(position)); - return convertView; - } - } - - public static String getClusterByTypeString(Context context, int type) { - for (ActionItem item : sClusterItems) { - if (item.action == type) { - return context.getString(item.clusterBy); - } - } - return null; - } - - public GalleryActionBar(AbstractGalleryActivity activity) { - mActionBar = activity.getActionBar(); - mContext = activity.getAndroidContext(); - mActivity = activity; - mInflater = ((Activity) mActivity).getLayoutInflater(); - mCurrentIndex = 0; - } - - private void createDialogData() { - ArrayList titles = new ArrayList(); - mActions = new ArrayList(); - for (ActionItem item : sClusterItems) { - if (item.enabled && item.visible) { - titles.add(mContext.getString(item.dialogTitle)); - mActions.add(item.action); - } - } - mTitles = new CharSequence[titles.size()]; - titles.toArray(mTitles); - } - - public int getHeight() { - return mActionBar != null ? mActionBar.getHeight() : 0; - } - - public void setClusterItemEnabled(int id, boolean enabled) { - for (ActionItem item : sClusterItems) { - if (item.action == id) { - item.enabled = enabled; - return; - } - } - } - - public void setClusterItemVisibility(int id, boolean visible) { - for (ActionItem item : sClusterItems) { - if (item.action == id) { - item.visible = visible; - return; - } - } - } - - public int getClusterTypeAction() { - return sClusterItems[mCurrentIndex].action; - } - - public void enableClusterMenu(int action, ClusterRunner runner) { - if (mActionBar != null) { - // Don't set cluster runner until action bar is ready. - mClusterRunner = null; - mActionBar.setListNavigationCallbacks(mAdapter, this); - mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST); - setSelectedAction(action); - mClusterRunner = runner; - } - } - - // The only use case not to hideMenu in this method is to ensure - // all elements disappear at the same time when exiting gallery. - // hideMenu should always be true in all other cases. - public void disableClusterMenu(boolean hideMenu) { - if (mActionBar != null) { - mClusterRunner = null; - if (hideMenu) { - mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD); - } - } - } - - public void onConfigurationChanged() { - if (mActionBar != null && mAlbumModeListener != null) { - OnAlbumModeSelectedListener listener = mAlbumModeListener; - enableAlbumModeMenu(mLastAlbumModeSelected, listener); - } - } - - public void enableAlbumModeMenu(int selected, OnAlbumModeSelectedListener listener) { - if (mActionBar != null) { - if (mAlbumModeAdapter == null) { - // Initialize the album mode options if they haven't been already - Resources res = mActivity.getResources(); - mAlbumModes = new CharSequence[] { - res.getString(R.string.switch_photo_filmstrip), - res.getString(R.string.switch_photo_grid)}; - mAlbumModeAdapter = new AlbumModeAdapter(); - } - mAlbumModeListener = null; - mLastAlbumModeSelected = selected; - mActionBar.setListNavigationCallbacks(mAlbumModeAdapter, this); - mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST); - mActionBar.setSelectedNavigationItem(selected); - mAlbumModeListener = listener; - } - } - - public void disableAlbumModeMenu(boolean hideMenu) { - if (mActionBar != null) { - mAlbumModeListener = null; - if (hideMenu) { - mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD); - } - } - } - - public void showClusterDialog(final ClusterRunner clusterRunner) { - createDialogData(); - final ArrayList actions = mActions; - new AlertDialog.Builder(mContext).setTitle(R.string.group_by).setItems( - mTitles, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - // Need to lock rendering when operations invoked by system UI (main thread) are - // modifying slot data used in GL thread for rendering. - mActivity.getGLRoot().lockRenderThread(); - try { - clusterRunner.doCluster(actions.get(which).intValue()); - } finally { - mActivity.getGLRoot().unlockRenderThread(); - } - } - }).create().show(); - } - - @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH) - private void setHomeButtonEnabled(boolean enabled) { - if (mActionBar != null) mActionBar.setHomeButtonEnabled(enabled); - } - - public void setDisplayOptions(boolean displayHomeAsUp, boolean showTitle) { - if (mActionBar == null) return; - int options = 0; - if (displayHomeAsUp) options |= ActionBar.DISPLAY_HOME_AS_UP; - if (showTitle) options |= ActionBar.DISPLAY_SHOW_TITLE; - - mActionBar.setDisplayOptions(options, - ActionBar.DISPLAY_HOME_AS_UP | ActionBar.DISPLAY_SHOW_TITLE); - mActionBar.setHomeButtonEnabled(displayHomeAsUp); - } - - public void setTitle(String title) { - if (mActionBar != null) mActionBar.setTitle(title); - } - - public void setTitle(int titleId) { - if (mActionBar != null) { - mActionBar.setTitle(mContext.getString(titleId)); - } - } - - public void setSubtitle(String title) { - if (mActionBar != null) mActionBar.setSubtitle(title); - } - - public void show() { - if (mActionBar != null) mActionBar.show(); - } - - public void hide() { - if (mActionBar != null) mActionBar.hide(); - } - - public void addOnMenuVisibilityListener(OnMenuVisibilityListener listener) { - if (mActionBar != null) mActionBar.addOnMenuVisibilityListener(listener); - } - - public void removeOnMenuVisibilityListener(OnMenuVisibilityListener listener) { - if (mActionBar != null) mActionBar.removeOnMenuVisibilityListener(listener); - } - - public boolean setSelectedAction(int type) { - if (mActionBar == null) return false; - - for (int i = 0, n = sClusterItems.length; i < n; i++) { - ActionItem item = sClusterItems[i]; - if (item.action == type) { - mActionBar.setSelectedNavigationItem(i); - mCurrentIndex = i; - return true; - } - } - return false; - } - - @Override - public boolean onNavigationItemSelected(int itemPosition, long itemId) { - if (itemPosition != mCurrentIndex && mClusterRunner != null - || mAlbumModeListener != null) { - // Need to lock rendering when operations invoked by system UI (main thread) are - // modifying slot data used in GL thread for rendering. - mActivity.getGLRoot().lockRenderThread(); - try { - if (mAlbumModeListener != null) { - mAlbumModeListener.onAlbumModeSelected(itemPosition); - } else { - mClusterRunner.doCluster(sClusterItems[itemPosition].action); - } - } finally { - mActivity.getGLRoot().unlockRenderThread(); - } - } - return false; - } - - private Menu mActionBarMenu; - private ShareActionProvider mSharePanoramaActionProvider; - private ShareActionProvider mShareActionProvider; - private Intent mSharePanoramaIntent; - private Intent mShareIntent; - - public void createActionBarMenu(int menuRes, Menu menu) { - mActivity.getMenuInflater().inflate(menuRes, menu); - mActionBarMenu = menu; - - MenuItem item = menu.findItem(R.id.action_share_panorama); - if (item != null) { - mSharePanoramaActionProvider = (ShareActionProvider) - item.getActionProvider(); - mSharePanoramaActionProvider - .setShareHistoryFileName("panorama_share_history.xml"); - mSharePanoramaActionProvider.setShareIntent(mSharePanoramaIntent); - } - - item = menu.findItem(R.id.action_share); - if (item != null) { - mShareActionProvider = (ShareActionProvider) - item.getActionProvider(); - mShareActionProvider - .setShareHistoryFileName("share_history.xml"); - mShareActionProvider.setShareIntent(mShareIntent); - } - } - - public Menu getMenu() { - return mActionBarMenu; - } - - public void setShareIntents(Intent sharePanoramaIntent, Intent shareIntent, - ShareActionProvider.OnShareTargetSelectedListener onShareListener) { - mSharePanoramaIntent = sharePanoramaIntent; - if (mSharePanoramaActionProvider != null) { - mSharePanoramaActionProvider.setShareIntent(sharePanoramaIntent); - } - mShareIntent = shareIntent; - if (mShareActionProvider != null) { - mShareActionProvider.setShareIntent(shareIntent); - mShareActionProvider.setOnShareTargetSelectedListener( - onShareListener); - } - } -} diff --git a/src/com/android/gallery3d/app/GalleryApp.java b/src/com/android/gallery3d/app/GalleryApp.java deleted file mode 100644 index b56b8a82c..000000000 --- a/src/com/android/gallery3d/app/GalleryApp.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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.gallery3d.app; - -import android.content.ContentResolver; -import android.content.Context; -import android.content.res.Resources; -import android.os.Looper; - -import com.android.gallery3d.data.DataManager; -import com.android.gallery3d.data.DownloadCache; -import com.android.gallery3d.data.ImageCacheService; -import com.android.gallery3d.util.ThreadPool; - -public interface GalleryApp { - public DataManager getDataManager(); - - public StitchingProgressManager getStitchingProgressManager(); - public ImageCacheService getImageCacheService(); - public DownloadCache getDownloadCache(); - public ThreadPool getThreadPool(); - - public Context getAndroidContext(); - public Looper getMainLooper(); - public ContentResolver getContentResolver(); - public Resources getResources(); -} diff --git a/src/com/android/gallery3d/app/GalleryAppImpl.java b/src/com/android/gallery3d/app/GalleryAppImpl.java deleted file mode 100644 index 2abdaa0c1..000000000 --- a/src/com/android/gallery3d/app/GalleryAppImpl.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * 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.gallery3d.app; - -import android.app.Application; -import android.content.Context; -import android.os.AsyncTask; - -import com.android.gallery3d.data.DataManager; -import com.android.gallery3d.data.DownloadCache; -import com.android.gallery3d.data.ImageCacheService; -import com.android.gallery3d.gadget.WidgetUtils; -import com.android.gallery3d.picasasource.PicasaSource; -import com.android.gallery3d.util.GalleryUtils; -import com.android.gallery3d.util.LightCycleHelper; -import com.android.gallery3d.util.ThreadPool; -import com.android.gallery3d.util.UsageStatistics; -import com.android.photos.data.MediaCache; - -import java.io.File; - -public class GalleryAppImpl extends Application implements GalleryApp { - - private static final String DOWNLOAD_FOLDER = "download"; - private static final long DOWNLOAD_CAPACITY = 64 * 1024 * 1024; // 64M - - private ImageCacheService mImageCacheService; - private Object mLock = new Object(); - private DataManager mDataManager; - private ThreadPool mThreadPool; - private DownloadCache mDownloadCache; - private StitchingProgressManager mStitchingProgressManager; - - @Override - public void onCreate() { - super.onCreate(); - com.android.camera.Util.initialize(this); - initializeAsyncTask(); - GalleryUtils.initialize(this); - WidgetUtils.initialize(this); - PicasaSource.initialize(this); - UsageStatistics.initialize(this); - MediaCache.initialize(this); - - mStitchingProgressManager = LightCycleHelper.createStitchingManagerInstance(this); - if (mStitchingProgressManager != null) { - mStitchingProgressManager.addChangeListener(getDataManager()); - } - } - - @Override - public Context getAndroidContext() { - return this; - } - - @Override - public synchronized DataManager getDataManager() { - if (mDataManager == null) { - mDataManager = new DataManager(this); - mDataManager.initializeSourceMap(); - } - return mDataManager; - } - - @Override - public StitchingProgressManager getStitchingProgressManager() { - return mStitchingProgressManager; - } - - @Override - public ImageCacheService getImageCacheService() { - // This method may block on file I/O so a dedicated lock is needed here. - synchronized (mLock) { - if (mImageCacheService == null) { - mImageCacheService = new ImageCacheService(getAndroidContext()); - } - return mImageCacheService; - } - } - - @Override - public synchronized ThreadPool getThreadPool() { - if (mThreadPool == null) { - mThreadPool = new ThreadPool(); - } - return mThreadPool; - } - - @Override - public synchronized DownloadCache getDownloadCache() { - if (mDownloadCache == null) { - File cacheDir = new File(getExternalCacheDir(), DOWNLOAD_FOLDER); - - if (!cacheDir.isDirectory()) cacheDir.mkdirs(); - - if (!cacheDir.isDirectory()) { - throw new RuntimeException( - "fail to create: " + cacheDir.getAbsolutePath()); - } - mDownloadCache = new DownloadCache(this, cacheDir, DOWNLOAD_CAPACITY); - } - return mDownloadCache; - } - - private void initializeAsyncTask() { - // AsyncTask class needs to be loaded in UI thread. - // So we load it here to comply the rule. - try { - Class.forName(AsyncTask.class.getName()); - } catch (ClassNotFoundException e) { - } - } -} diff --git a/src/com/android/gallery3d/app/GalleryContext.java b/src/com/android/gallery3d/app/GalleryContext.java deleted file mode 100644 index 06f4fe4d1..000000000 --- a/src/com/android/gallery3d/app/GalleryContext.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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.gallery3d.app; - -import android.content.Context; -import android.content.res.Resources; -import android.os.Looper; - -import com.android.gallery3d.data.DataManager; -import com.android.gallery3d.util.ThreadPool; - -public interface GalleryContext { - public DataManager getDataManager(); - - public Context getAndroidContext(); - - public Looper getMainLooper(); - public Resources getResources(); - public ThreadPool getThreadPool(); -} diff --git a/src/com/android/gallery3d/app/LoadingListener.java b/src/com/android/gallery3d/app/LoadingListener.java deleted file mode 100644 index e94df9307..000000000 --- a/src/com/android/gallery3d/app/LoadingListener.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * 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.gallery3d.app; - -public interface LoadingListener { - public void onLoadingStarted(); - /** - * Called when loading is complete or no further progress can be made. - * - * @param loadingFailed true if data source cannot provide requested data - */ - public void onLoadingFinished(boolean loadingFailed); -} diff --git a/src/com/android/gallery3d/app/Log.java b/src/com/android/gallery3d/app/Log.java deleted file mode 100644 index 07a8ea588..000000000 --- a/src/com/android/gallery3d/app/Log.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * 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.gallery3d.app; - -public class Log { - public static int v(String tag, String msg) { - return android.util.Log.v(tag, msg); - } - public static int v(String tag, String msg, Throwable tr) { - return android.util.Log.v(tag, msg, tr); - } - public static int d(String tag, String msg) { - return android.util.Log.d(tag, msg); - } - public static int d(String tag, String msg, Throwable tr) { - return android.util.Log.d(tag, msg, tr); - } - public static int i(String tag, String msg) { - return android.util.Log.i(tag, msg); - } - public static int i(String tag, String msg, Throwable tr) { - return android.util.Log.i(tag, msg, tr); - } - public static int w(String tag, String msg) { - return android.util.Log.w(tag, msg); - } - public static int w(String tag, String msg, Throwable tr) { - return android.util.Log.w(tag, msg, tr); - } - public static int w(String tag, Throwable tr) { - return android.util.Log.w(tag, tr); - } - public static int e(String tag, String msg) { - return android.util.Log.e(tag, msg); - } - public static int e(String tag, String msg, Throwable tr) { - return android.util.Log.e(tag, msg, tr); - } -} diff --git a/src/com/android/gallery3d/app/ManageCachePage.java b/src/com/android/gallery3d/app/ManageCachePage.java deleted file mode 100644 index 4f5c35819..000000000 --- a/src/com/android/gallery3d/app/ManageCachePage.java +++ /dev/null @@ -1,419 +0,0 @@ -/* - * 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.gallery3d.app; - -import android.app.Activity; -import android.content.res.Configuration; -import android.os.Bundle; -import android.os.Handler; -import android.os.Message; -import android.text.format.Formatter; -import android.view.LayoutInflater; -import android.view.View; -import android.view.View.OnClickListener; -import android.widget.FrameLayout; -import android.widget.ProgressBar; -import android.widget.TextView; -import android.widget.Toast; - -import com.android.gallery3d.R; -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.data.MediaObject; -import com.android.gallery3d.data.MediaSet; -import com.android.gallery3d.data.Path; -import com.android.gallery3d.glrenderer.GLCanvas; -import com.android.gallery3d.ui.CacheStorageUsageInfo; -import com.android.gallery3d.ui.GLRoot; -import com.android.gallery3d.ui.GLView; -import com.android.gallery3d.ui.ManageCacheDrawer; -import com.android.gallery3d.ui.MenuExecutor; -import com.android.gallery3d.ui.SelectionManager; -import com.android.gallery3d.ui.SlotView; -import com.android.gallery3d.ui.SynchronizedHandler; -import com.android.gallery3d.util.Future; -import com.android.gallery3d.util.GalleryUtils; -import com.android.gallery3d.util.ThreadPool.Job; -import com.android.gallery3d.util.ThreadPool.JobContext; - -import java.util.ArrayList; - -public class ManageCachePage extends ActivityState implements - SelectionManager.SelectionListener, MenuExecutor.ProgressListener, - EyePosition.EyePositionListener, OnClickListener { - public static final String KEY_MEDIA_PATH = "media-path"; - - @SuppressWarnings("unused") - private static final String TAG = "ManageCachePage"; - - private static final int DATA_CACHE_SIZE = 256; - private static final int MSG_REFRESH_STORAGE_INFO = 1; - private static final int MSG_REQUEST_LAYOUT = 2; - private static final int PROGRESS_BAR_MAX = 10000; - - private SlotView mSlotView; - private MediaSet mMediaSet; - - protected SelectionManager mSelectionManager; - protected ManageCacheDrawer mSelectionDrawer; - private AlbumSetDataLoader mAlbumSetDataAdapter; - - private EyePosition mEyePosition; - - // The eyes' position of the user, the origin is at the center of the - // device and the unit is in pixels. - private float mX; - private float mY; - private float mZ; - - private int mAlbumCountToMakeAvailableOffline; - private View mFooterContent; - private CacheStorageUsageInfo mCacheStorageInfo; - private Future mUpdateStorageInfo; - private Handler mHandler; - private boolean mLayoutReady = false; - - @Override - protected int getBackgroundColorId() { - return R.color.cache_background; - } - - private GLView mRootPane = new GLView() { - private float mMatrix[] = new float[16]; - - @Override - protected void renderBackground(GLCanvas view) { - view.clearBuffer(getBackgroundColor()); - } - - @Override - protected void onLayout( - boolean changed, int left, int top, int right, int bottom) { - // Hack: our layout depends on other components on the screen. - // We assume the other components will complete before we get a change - // to run a message in main thread. - if (!mLayoutReady) { - mHandler.sendEmptyMessage(MSG_REQUEST_LAYOUT); - return; - } - mLayoutReady = false; - - mEyePosition.resetPosition(); - int slotViewTop = mActivity.getGalleryActionBar().getHeight(); - int slotViewBottom = bottom - top; - - View footer = mActivity.findViewById(R.id.footer); - if (footer != null) { - int location[] = {0, 0}; - footer.getLocationOnScreen(location); - slotViewBottom = location[1]; - } - - mSlotView.layout(0, slotViewTop, right - left, slotViewBottom); - } - - @Override - protected void render(GLCanvas canvas) { - canvas.save(GLCanvas.SAVE_FLAG_MATRIX); - GalleryUtils.setViewPointMatrix(mMatrix, - getWidth() / 2 + mX, getHeight() / 2 + mY, mZ); - canvas.multiplyMatrix(mMatrix, 0); - super.render(canvas); - canvas.restore(); - } - }; - - @Override - public void onEyePositionChanged(float x, float y, float z) { - mRootPane.lockRendering(); - mX = x; - mY = y; - mZ = z; - mRootPane.unlockRendering(); - mRootPane.invalidate(); - } - - private void onDown(int index) { - mSelectionDrawer.setPressedIndex(index); - } - - private void onUp() { - mSelectionDrawer.setPressedIndex(-1); - } - - public void onSingleTapUp(int slotIndex) { - MediaSet targetSet = mAlbumSetDataAdapter.getMediaSet(slotIndex); - if (targetSet == null) return; // Content is dirty, we shall reload soon - - // ignore selection action if the target set does not support cache - // operation (like a local album). - if ((targetSet.getSupportedOperations() - & MediaSet.SUPPORT_CACHE) == 0) { - showToastForLocalAlbum(); - return; - } - - Path path = targetSet.getPath(); - boolean isFullyCached = - (targetSet.getCacheFlag() == MediaObject.CACHE_FLAG_FULL); - boolean isSelected = mSelectionManager.isItemSelected(path); - - if (!isFullyCached) { - // We only count the media sets that will be made available offline - // in this session. - if (isSelected) { - --mAlbumCountToMakeAvailableOffline; - } else { - ++mAlbumCountToMakeAvailableOffline; - } - } - - long sizeOfTarget = targetSet.getCacheSize(); - mCacheStorageInfo.increaseTargetCacheSize( - (isFullyCached ^ isSelected) ? -sizeOfTarget : sizeOfTarget); - refreshCacheStorageInfo(); - - mSelectionManager.toggle(path); - mSlotView.invalidate(); - } - - @Override - public void onCreate(Bundle data, Bundle restoreState) { - super.onCreate(data, restoreState); - mCacheStorageInfo = new CacheStorageUsageInfo(mActivity); - initializeViews(); - initializeData(data); - mEyePosition = new EyePosition(mActivity.getAndroidContext(), this); - mHandler = new SynchronizedHandler(mActivity.getGLRoot()) { - @Override - public void handleMessage(Message message) { - switch (message.what) { - case MSG_REFRESH_STORAGE_INFO: - refreshCacheStorageInfo(); - break; - case MSG_REQUEST_LAYOUT: { - mLayoutReady = true; - removeMessages(MSG_REQUEST_LAYOUT); - mRootPane.requestLayout(); - break; - } - } - } - }; - } - - @Override - public void onConfigurationChanged(Configuration config) { - // We use different layout resources for different configs - initializeFooterViews(); - FrameLayout layout = (FrameLayout) ((Activity) mActivity).findViewById(R.id.footer); - if (layout.getVisibility() == View.VISIBLE) { - layout.removeAllViews(); - layout.addView(mFooterContent); - } - } - - @Override - public void onPause() { - super.onPause(); - mAlbumSetDataAdapter.pause(); - mSelectionDrawer.pause(); - mEyePosition.pause(); - - if (mUpdateStorageInfo != null) { - mUpdateStorageInfo.cancel(); - mUpdateStorageInfo = null; - } - mHandler.removeMessages(MSG_REFRESH_STORAGE_INFO); - - FrameLayout layout = (FrameLayout) ((Activity) mActivity).findViewById(R.id.footer); - layout.removeAllViews(); - layout.setVisibility(View.INVISIBLE); - } - - private Job mUpdateStorageInfoJob = new Job() { - @Override - public Void run(JobContext jc) { - mCacheStorageInfo.loadStorageInfo(jc); - if (!jc.isCancelled()) { - mHandler.sendEmptyMessage(MSG_REFRESH_STORAGE_INFO); - } - return null; - } - }; - - @Override - public void onResume() { - super.onResume(); - setContentPane(mRootPane); - mAlbumSetDataAdapter.resume(); - mSelectionDrawer.resume(); - mEyePosition.resume(); - mUpdateStorageInfo = mActivity.getThreadPool().submit(mUpdateStorageInfoJob); - FrameLayout layout = (FrameLayout) ((Activity) mActivity).findViewById(R.id.footer); - layout.addView(mFooterContent); - layout.setVisibility(View.VISIBLE); - } - - private void initializeData(Bundle data) { - String mediaPath = data.getString(ManageCachePage.KEY_MEDIA_PATH); - mMediaSet = mActivity.getDataManager().getMediaSet(mediaPath); - mSelectionManager.setSourceMediaSet(mMediaSet); - - // We will always be in selection mode in this page. - mSelectionManager.setAutoLeaveSelectionMode(false); - mSelectionManager.enterSelectionMode(); - - mAlbumSetDataAdapter = new AlbumSetDataLoader( - mActivity, mMediaSet, DATA_CACHE_SIZE); - mSelectionDrawer.setModel(mAlbumSetDataAdapter); - } - - private void initializeViews() { - Activity activity = mActivity; - - mSelectionManager = new SelectionManager(mActivity, true); - mSelectionManager.setSelectionListener(this); - - Config.ManageCachePage config = Config.ManageCachePage.get(activity); - mSlotView = new SlotView(mActivity, config.slotViewSpec); - mSelectionDrawer = new ManageCacheDrawer(mActivity, mSelectionManager, mSlotView, - config.labelSpec, config.cachePinSize, config.cachePinMargin); - mSlotView.setSlotRenderer(mSelectionDrawer); - mSlotView.setListener(new SlotView.SimpleListener() { - @Override - public void onDown(int index) { - ManageCachePage.this.onDown(index); - } - - @Override - public void onUp(boolean followedByLongPress) { - ManageCachePage.this.onUp(); - } - - @Override - public void onSingleTapUp(int slotIndex) { - ManageCachePage.this.onSingleTapUp(slotIndex); - } - }); - mRootPane.addComponent(mSlotView); - initializeFooterViews(); - } - - private void initializeFooterViews() { - Activity activity = mActivity; - - LayoutInflater inflater = activity.getLayoutInflater(); - mFooterContent = inflater.inflate(R.layout.manage_offline_bar, null); - - mFooterContent.findViewById(R.id.done).setOnClickListener(this); - refreshCacheStorageInfo(); - } - - @Override - public void onClick(View view) { - Utils.assertTrue(view.getId() == R.id.done); - GLRoot root = mActivity.getGLRoot(); - root.lockRenderThread(); - try { - ArrayList ids = mSelectionManager.getSelected(false); - if (ids.size() == 0) { - onBackPressed(); - return; - } - showToast(); - - MenuExecutor menuExecutor = new MenuExecutor(mActivity, mSelectionManager); - menuExecutor.startAction(R.id.action_toggle_full_caching, - R.string.process_caching_requests, this); - } finally { - root.unlockRenderThread(); - } - } - - private void showToast() { - if (mAlbumCountToMakeAvailableOffline > 0) { - Activity activity = mActivity; - Toast.makeText(activity, activity.getResources().getQuantityString( - R.plurals.make_albums_available_offline, - mAlbumCountToMakeAvailableOffline), - Toast.LENGTH_SHORT).show(); - } - } - - private void showToastForLocalAlbum() { - Activity activity = mActivity; - Toast.makeText(activity, activity.getResources().getString( - R.string.try_to_set_local_album_available_offline), - Toast.LENGTH_SHORT).show(); - } - - private void refreshCacheStorageInfo() { - ProgressBar progressBar = (ProgressBar) mFooterContent.findViewById(R.id.progress); - TextView status = (TextView) mFooterContent.findViewById(R.id.status); - progressBar.setMax(PROGRESS_BAR_MAX); - long totalBytes = mCacheStorageInfo.getTotalBytes(); - long usedBytes = mCacheStorageInfo.getUsedBytes(); - long expectedBytes = mCacheStorageInfo.getExpectedUsedBytes(); - long freeBytes = mCacheStorageInfo.getFreeBytes(); - - Activity activity = mActivity; - if (totalBytes == 0) { - progressBar.setProgress(0); - progressBar.setSecondaryProgress(0); - - // TODO: get the string translated - String label = activity.getString(R.string.free_space_format, "-"); - status.setText(label); - } else { - progressBar.setProgress((int) (usedBytes * PROGRESS_BAR_MAX / totalBytes)); - progressBar.setSecondaryProgress( - (int) (expectedBytes * PROGRESS_BAR_MAX / totalBytes)); - String label = activity.getString(R.string.free_space_format, - Formatter.formatFileSize(activity, freeBytes)); - status.setText(label); - } - } - - @Override - public void onProgressComplete(int result) { - onBackPressed(); - } - - @Override - public void onProgressUpdate(int index) { - } - - @Override - public void onSelectionModeChange(int mode) { - } - - @Override - public void onSelectionChange(Path path, boolean selected) { - } - - @Override - public void onConfirmDialogDismissed(boolean confirmed) { - } - - @Override - public void onConfirmDialogShown() { - } - - @Override - public void onProgressStart() { - } -} diff --git a/src/com/android/gallery3d/app/MovieActivity.java b/src/com/android/gallery3d/app/MovieActivity.java deleted file mode 100644 index 40edbbe4d..000000000 --- a/src/com/android/gallery3d/app/MovieActivity.java +++ /dev/null @@ -1,263 +0,0 @@ -/* - * 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.gallery3d.app; - -import android.annotation.TargetApi; -import android.app.ActionBar; -import android.app.Activity; -import android.content.AsyncQueryHandler; -import android.content.ContentResolver; -import android.content.Intent; -import android.content.pm.ActivityInfo; -import android.database.Cursor; -import android.graphics.Bitmap; -import android.graphics.drawable.BitmapDrawable; -import android.media.AudioManager; -import android.net.Uri; -import android.os.Build; -import android.os.Bundle; -import android.provider.MediaStore; -import android.provider.OpenableColumns; -import android.view.KeyEvent; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.Window; -import android.view.WindowManager; -import android.widget.ShareActionProvider; - -import com.android.gallery3d.R; -import com.android.gallery3d.common.ApiHelper; -import com.android.gallery3d.common.Utils; - -/** - * This activity plays a video from a specified URI. - * - * The client of this activity can pass a logo bitmap in the intent (KEY_LOGO_BITMAP) - * to set the action bar logo so the playback process looks more seamlessly integrated with - * the original activity. - */ -public class MovieActivity extends Activity { - @SuppressWarnings("unused") - private static final String TAG = "MovieActivity"; - public static final String KEY_LOGO_BITMAP = "logo-bitmap"; - public static final String KEY_TREAT_UP_AS_BACK = "treat-up-as-back"; - - private MoviePlayer mPlayer; - private boolean mFinishOnCompletion; - private Uri mUri; - private boolean mTreatUpAsBack; - - @TargetApi(Build.VERSION_CODES.JELLY_BEAN) - private void setSystemUiVisibility(View rootView) { - if (ApiHelper.HAS_VIEW_SYSTEM_UI_FLAG_LAYOUT_STABLE) { - rootView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE - | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN - | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION); - } - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - requestWindowFeature(Window.FEATURE_ACTION_BAR); - requestWindowFeature(Window.FEATURE_ACTION_BAR_OVERLAY); - - setContentView(R.layout.movie_view); - View rootView = findViewById(R.id.movie_view_root); - - setSystemUiVisibility(rootView); - - Intent intent = getIntent(); - initializeActionBar(intent); - mFinishOnCompletion = intent.getBooleanExtra( - MediaStore.EXTRA_FINISH_ON_COMPLETION, true); - mTreatUpAsBack = intent.getBooleanExtra(KEY_TREAT_UP_AS_BACK, false); - mPlayer = new MoviePlayer(rootView, this, intent.getData(), savedInstanceState, - !mFinishOnCompletion) { - @Override - public void onCompletion() { - if (mFinishOnCompletion) { - finish(); - } - } - }; - if (intent.hasExtra(MediaStore.EXTRA_SCREEN_ORIENTATION)) { - int orientation = intent.getIntExtra( - MediaStore.EXTRA_SCREEN_ORIENTATION, - ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); - if (orientation != getRequestedOrientation()) { - setRequestedOrientation(orientation); - } - } - Window win = getWindow(); - WindowManager.LayoutParams winParams = win.getAttributes(); - winParams.buttonBrightness = WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_OFF; - winParams.flags |= WindowManager.LayoutParams.FLAG_FULLSCREEN; - win.setAttributes(winParams); - - // We set the background in the theme to have the launching animation. - // But for the performance (and battery), we remove the background here. - win.setBackgroundDrawable(null); - } - - private void setActionBarLogoFromIntent(Intent intent) { - Bitmap logo = intent.getParcelableExtra(KEY_LOGO_BITMAP); - if (logo != null) { - getActionBar().setLogo( - new BitmapDrawable(getResources(), logo)); - } - } - - private void initializeActionBar(Intent intent) { - mUri = intent.getData(); - final ActionBar actionBar = getActionBar(); - if (actionBar == null) { - return; - } - setActionBarLogoFromIntent(intent); - actionBar.setDisplayOptions( - ActionBar.DISPLAY_HOME_AS_UP, - ActionBar.DISPLAY_HOME_AS_UP); - - String title = intent.getStringExtra(Intent.EXTRA_TITLE); - if (title != null) { - actionBar.setTitle(title); - } else { - // Displays the filename as title, reading the filename from the - // interface: {@link android.provider.OpenableColumns#DISPLAY_NAME}. - AsyncQueryHandler queryHandler = - new AsyncQueryHandler(getContentResolver()) { - @Override - protected void onQueryComplete(int token, Object cookie, - Cursor cursor) { - try { - if ((cursor != null) && cursor.moveToFirst()) { - String displayName = cursor.getString(0); - - // Just show empty title if other apps don't set - // DISPLAY_NAME - actionBar.setTitle((displayName == null) ? "" : - displayName); - } - } finally { - Utils.closeSilently(cursor); - } - } - }; - queryHandler.startQuery(0, null, mUri, - new String[] {OpenableColumns.DISPLAY_NAME}, null, null, - null); - } - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - super.onCreateOptionsMenu(menu); - getMenuInflater().inflate(R.menu.movie, menu); - - // Document says EXTRA_STREAM should be a content: Uri - // So, we only share the video if it's "content:". - MenuItem shareItem = menu.findItem(R.id.action_share); - if (ContentResolver.SCHEME_CONTENT.equals(mUri.getScheme())) { - shareItem.setVisible(true); - ((ShareActionProvider) shareItem.getActionProvider()) - .setShareIntent(createShareIntent()); - } else { - shareItem.setVisible(false); - } - return true; - } - - private Intent createShareIntent() { - Intent intent = new Intent(Intent.ACTION_SEND); - intent.setType("video/*"); - intent.putExtra(Intent.EXTRA_STREAM, mUri); - return intent; - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - int id = item.getItemId(); - if (id == android.R.id.home) { - if (mTreatUpAsBack) { - finish(); - } else { - startActivity(new Intent(this, Gallery.class)); - finish(); - } - return true; - } else if (id == R.id.action_share) { - startActivity(Intent.createChooser(createShareIntent(), - getString(R.string.share))); - return true; - } - return false; - } - - @Override - public void onStart() { - ((AudioManager) getSystemService(AUDIO_SERVICE)) - .requestAudioFocus(null, AudioManager.STREAM_MUSIC, - AudioManager.AUDIOFOCUS_GAIN_TRANSIENT); - super.onStart(); - } - - @Override - protected void onStop() { - ((AudioManager) getSystemService(AUDIO_SERVICE)) - .abandonAudioFocus(null); - super.onStop(); - } - - @Override - public void onPause() { - mPlayer.onPause(); - super.onPause(); - } - - @Override - public void onResume() { - mPlayer.onResume(); - super.onResume(); - } - - @Override - public void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - mPlayer.onSaveInstanceState(outState); - } - - @Override - public void onDestroy() { - mPlayer.onDestroy(); - super.onDestroy(); - } - - @Override - public boolean onKeyDown(int keyCode, KeyEvent event) { - return mPlayer.onKeyDown(keyCode, event) - || super.onKeyDown(keyCode, event); - } - - @Override - public boolean onKeyUp(int keyCode, KeyEvent event) { - return mPlayer.onKeyUp(keyCode, event) - || super.onKeyUp(keyCode, event); - } -} diff --git a/src/com/android/gallery3d/app/MovieControllerOverlay.java b/src/com/android/gallery3d/app/MovieControllerOverlay.java deleted file mode 100644 index f01e619c6..000000000 --- a/src/com/android/gallery3d/app/MovieControllerOverlay.java +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.app; - -import android.content.Context; -import android.os.Handler; -import android.view.KeyEvent; -import android.view.MotionEvent; -import android.view.View; -import android.view.animation.Animation; -import android.view.animation.Animation.AnimationListener; -import android.view.animation.AnimationUtils; -import com.android.gallery3d.R; - -/** - * The playback controller for the Movie Player. - */ -public class MovieControllerOverlay extends CommonControllerOverlay implements - AnimationListener { - - private boolean hidden; - - private final Handler handler; - private final Runnable startHidingRunnable; - private final Animation hideAnimation; - - public MovieControllerOverlay(Context context) { - super(context); - - handler = new Handler(); - startHidingRunnable = new Runnable() { - @Override - public void run() { - startHiding(); - } - }; - - hideAnimation = AnimationUtils.loadAnimation(context, R.anim.player_out); - hideAnimation.setAnimationListener(this); - - hide(); - } - - @Override - protected void createTimeBar(Context context) { - mTimeBar = new TimeBar(context, this); - } - - @Override - public void hide() { - boolean wasHidden = hidden; - hidden = true; - super.hide(); - if (mListener != null && wasHidden != hidden) { - mListener.onHidden(); - } - } - - - @Override - public void show() { - boolean wasHidden = hidden; - hidden = false; - super.show(); - if (mListener != null && wasHidden != hidden) { - mListener.onShown(); - } - maybeStartHiding(); - } - - private void maybeStartHiding() { - cancelHiding(); - if (mState == State.PLAYING) { - handler.postDelayed(startHidingRunnable, 2500); - } - } - - private void startHiding() { - startHideAnimation(mBackground); - startHideAnimation(mTimeBar); - startHideAnimation(mPlayPauseReplayView); - } - - private void startHideAnimation(View view) { - if (view.getVisibility() == View.VISIBLE) { - view.startAnimation(hideAnimation); - } - } - - private void cancelHiding() { - handler.removeCallbacks(startHidingRunnable); - mBackground.setAnimation(null); - mTimeBar.setAnimation(null); - mPlayPauseReplayView.setAnimation(null); - } - - @Override - public void onAnimationStart(Animation animation) { - // Do nothing. - } - - @Override - public void onAnimationRepeat(Animation animation) { - // Do nothing. - } - - @Override - public void onAnimationEnd(Animation animation) { - hide(); - } - - @Override - public boolean onKeyDown(int keyCode, KeyEvent event) { - if (hidden) { - show(); - } - return super.onKeyDown(keyCode, event); - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - if (super.onTouchEvent(event)) { - return true; - } - - if (hidden) { - show(); - return true; - } - switch (event.getAction()) { - case MotionEvent.ACTION_DOWN: - cancelHiding(); - if (mState == State.PLAYING || mState == State.PAUSED) { - mListener.onPlayPause(); - } - break; - case MotionEvent.ACTION_UP: - maybeStartHiding(); - break; - } - return true; - } - - @Override - protected void updateViews() { - if (hidden) { - return; - } - super.updateViews(); - } - - // TimeBar listener - - @Override - public void onScrubbingStart() { - cancelHiding(); - super.onScrubbingStart(); - } - - @Override - public void onScrubbingMove(int time) { - cancelHiding(); - super.onScrubbingMove(time); - } - - @Override - public void onScrubbingEnd(int time, int trimStartTime, int trimEndTime) { - maybeStartHiding(); - super.onScrubbingEnd(time, trimStartTime, trimEndTime); - } -} diff --git a/src/com/android/gallery3d/app/MoviePlayer.java b/src/com/android/gallery3d/app/MoviePlayer.java deleted file mode 100644 index ce9183483..000000000 --- a/src/com/android/gallery3d/app/MoviePlayer.java +++ /dev/null @@ -1,525 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.app; - -import android.annotation.TargetApi; -import android.app.AlertDialog; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.DialogInterface; -import android.content.DialogInterface.OnCancelListener; -import android.content.DialogInterface.OnClickListener; -import android.content.Intent; -import android.content.IntentFilter; -import android.media.AudioManager; -import android.media.MediaPlayer; -import android.net.Uri; -import android.os.Build; -import android.os.Bundle; -import android.os.Handler; -import android.view.KeyEvent; -import android.view.MotionEvent; -import android.view.View; -import android.view.ViewGroup; -import android.widget.VideoView; - -import com.android.gallery3d.R; -import com.android.gallery3d.common.ApiHelper; -import com.android.gallery3d.common.BlobCache; -import com.android.gallery3d.util.CacheManager; -import com.android.gallery3d.util.GalleryUtils; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.DataInputStream; -import java.io.DataOutputStream; - -public class MoviePlayer implements - MediaPlayer.OnErrorListener, MediaPlayer.OnCompletionListener, - ControllerOverlay.Listener { - @SuppressWarnings("unused") - private static final String TAG = "MoviePlayer"; - - private static final String KEY_VIDEO_POSITION = "video-position"; - private static final String KEY_RESUMEABLE_TIME = "resumeable-timeout"; - - // These are constants in KeyEvent, appearing on API level 11. - private static final int KEYCODE_MEDIA_PLAY = 126; - private static final int KEYCODE_MEDIA_PAUSE = 127; - - // Copied from MediaPlaybackService in the Music Player app. - private static final String SERVICECMD = "com.android.music.musicservicecommand"; - private static final String CMDNAME = "command"; - private static final String CMDPAUSE = "pause"; - - private static final long BLACK_TIMEOUT = 500; - - // If we resume the acitivty with in RESUMEABLE_TIMEOUT, we will keep playing. - // Otherwise, we pause the player. - private static final long RESUMEABLE_TIMEOUT = 3 * 60 * 1000; // 3 mins - - private Context mContext; - private final VideoView mVideoView; - private final View mRootView; - private final Bookmarker mBookmarker; - private final Uri mUri; - private final Handler mHandler = new Handler(); - private final AudioBecomingNoisyReceiver mAudioBecomingNoisyReceiver; - private final MovieControllerOverlay mController; - - private long mResumeableTime = Long.MAX_VALUE; - private int mVideoPosition = 0; - private boolean mHasPaused = false; - private int mLastSystemUiVis = 0; - - // If the time bar is being dragged. - private boolean mDragging; - - // If the time bar is visible. - private boolean mShowing; - - private final Runnable mPlayingChecker = new Runnable() { - @Override - public void run() { - if (mVideoView.isPlaying()) { - mController.showPlaying(); - } else { - mHandler.postDelayed(mPlayingChecker, 250); - } - } - }; - - private final Runnable mProgressChecker = new Runnable() { - @Override - public void run() { - int pos = setProgress(); - mHandler.postDelayed(mProgressChecker, 1000 - (pos % 1000)); - } - }; - - public MoviePlayer(View rootView, final MovieActivity movieActivity, - Uri videoUri, Bundle savedInstance, boolean canReplay) { - mContext = movieActivity.getApplicationContext(); - mRootView = rootView; - mVideoView = (VideoView) rootView.findViewById(R.id.surface_view); - mBookmarker = new Bookmarker(movieActivity); - mUri = videoUri; - - mController = new MovieControllerOverlay(mContext); - ((ViewGroup)rootView).addView(mController.getView()); - mController.setListener(this); - mController.setCanReplay(canReplay); - - mVideoView.setOnErrorListener(this); - mVideoView.setOnCompletionListener(this); - mVideoView.setVideoURI(mUri); - mVideoView.setOnTouchListener(new View.OnTouchListener() { - @Override - public boolean onTouch(View v, MotionEvent event) { - mController.show(); - return true; - } - }); - mVideoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { - @Override - public void onPrepared(MediaPlayer player) { - if (!mVideoView.canSeekForward() || !mVideoView.canSeekBackward()) { - mController.setSeekable(false); - } else { - mController.setSeekable(true); - } - setProgress(); - } - }); - - // The SurfaceView is transparent before drawing the first frame. - // This makes the UI flashing when open a video. (black -> old screen - // -> video) However, we have no way to know the timing of the first - // frame. So, we hide the VideoView for a while to make sure the - // video has been drawn on it. - mVideoView.postDelayed(new Runnable() { - @Override - public void run() { - mVideoView.setVisibility(View.VISIBLE); - } - }, BLACK_TIMEOUT); - - setOnSystemUiVisibilityChangeListener(); - // Hide system UI by default - showSystemUi(false); - - mAudioBecomingNoisyReceiver = new AudioBecomingNoisyReceiver(); - mAudioBecomingNoisyReceiver.register(); - - Intent i = new Intent(SERVICECMD); - i.putExtra(CMDNAME, CMDPAUSE); - movieActivity.sendBroadcast(i); - - if (savedInstance != null) { // this is a resumed activity - mVideoPosition = savedInstance.getInt(KEY_VIDEO_POSITION, 0); - mResumeableTime = savedInstance.getLong(KEY_RESUMEABLE_TIME, Long.MAX_VALUE); - mVideoView.start(); - mVideoView.suspend(); - mHasPaused = true; - } else { - final Integer bookmark = mBookmarker.getBookmark(mUri); - if (bookmark != null) { - showResumeDialog(movieActivity, bookmark); - } else { - startVideo(); - } - } - } - - @TargetApi(Build.VERSION_CODES.JELLY_BEAN) - private void setOnSystemUiVisibilityChangeListener() { - if (!ApiHelper.HAS_VIEW_SYSTEM_UI_FLAG_HIDE_NAVIGATION) return; - - // When the user touches the screen or uses some hard key, the framework - // will change system ui visibility from invisible to visible. We show - // the media control and enable system UI (e.g. ActionBar) to be visible at this point - mVideoView.setOnSystemUiVisibilityChangeListener( - new View.OnSystemUiVisibilityChangeListener() { - @Override - public void onSystemUiVisibilityChange(int visibility) { - int diff = mLastSystemUiVis ^ visibility; - mLastSystemUiVis = visibility; - if ((diff & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0 - && (visibility & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0) { - mController.show(); - } - } - }); - } - - @SuppressWarnings("deprecation") - @TargetApi(Build.VERSION_CODES.JELLY_BEAN) - private void showSystemUi(boolean visible) { - if (!ApiHelper.HAS_VIEW_SYSTEM_UI_FLAG_LAYOUT_STABLE) return; - - int flag = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN - | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION - | View.SYSTEM_UI_FLAG_LAYOUT_STABLE; - if (!visible) { - // We used the deprecated "STATUS_BAR_HIDDEN" for unbundling - flag |= View.STATUS_BAR_HIDDEN | View.SYSTEM_UI_FLAG_FULLSCREEN - | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; - } - mVideoView.setSystemUiVisibility(flag); - } - - public void onSaveInstanceState(Bundle outState) { - outState.putInt(KEY_VIDEO_POSITION, mVideoPosition); - outState.putLong(KEY_RESUMEABLE_TIME, mResumeableTime); - } - - private void showResumeDialog(Context context, final int bookmark) { - AlertDialog.Builder builder = new AlertDialog.Builder(context); - builder.setTitle(R.string.resume_playing_title); - builder.setMessage(String.format( - context.getString(R.string.resume_playing_message), - GalleryUtils.formatDuration(context, bookmark / 1000))); - builder.setOnCancelListener(new OnCancelListener() { - @Override - public void onCancel(DialogInterface dialog) { - onCompletion(); - } - }); - builder.setPositiveButton( - R.string.resume_playing_resume, new OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - mVideoView.seekTo(bookmark); - startVideo(); - } - }); - builder.setNegativeButton( - R.string.resume_playing_restart, new OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - startVideo(); - } - }); - builder.show(); - } - - public void onPause() { - mHasPaused = true; - mHandler.removeCallbacksAndMessages(null); - mVideoPosition = mVideoView.getCurrentPosition(); - mBookmarker.setBookmark(mUri, mVideoPosition, mVideoView.getDuration()); - mVideoView.suspend(); - mResumeableTime = System.currentTimeMillis() + RESUMEABLE_TIMEOUT; - } - - public void onResume() { - if (mHasPaused) { - mVideoView.seekTo(mVideoPosition); - mVideoView.resume(); - - // If we have slept for too long, pause the play - if (System.currentTimeMillis() > mResumeableTime) { - pauseVideo(); - } - } - mHandler.post(mProgressChecker); - } - - public void onDestroy() { - mVideoView.stopPlayback(); - mAudioBecomingNoisyReceiver.unregister(); - } - - // This updates the time bar display (if necessary). It is called every - // second by mProgressChecker and also from places where the time bar needs - // to be updated immediately. - private int setProgress() { - if (mDragging || !mShowing) { - return 0; - } - int position = mVideoView.getCurrentPosition(); - int duration = mVideoView.getDuration(); - mController.setTimes(position, duration, 0, 0); - return position; - } - - private void startVideo() { - // For streams that we expect to be slow to start up, show a - // progress spinner until playback starts. - String scheme = mUri.getScheme(); - if ("http".equalsIgnoreCase(scheme) || "rtsp".equalsIgnoreCase(scheme)) { - mController.showLoading(); - mHandler.removeCallbacks(mPlayingChecker); - mHandler.postDelayed(mPlayingChecker, 250); - } else { - mController.showPlaying(); - mController.hide(); - } - - mVideoView.start(); - setProgress(); - } - - private void playVideo() { - mVideoView.start(); - mController.showPlaying(); - setProgress(); - } - - private void pauseVideo() { - mVideoView.pause(); - mController.showPaused(); - } - - // Below are notifications from VideoView - @Override - public boolean onError(MediaPlayer player, int arg1, int arg2) { - mHandler.removeCallbacksAndMessages(null); - // VideoView will show an error dialog if we return false, so no need - // to show more message. - mController.showErrorMessage(""); - return false; - } - - @Override - public void onCompletion(MediaPlayer mp) { - mController.showEnded(); - onCompletion(); - } - - public void onCompletion() { - } - - // Below are notifications from ControllerOverlay - @Override - public void onPlayPause() { - if (mVideoView.isPlaying()) { - pauseVideo(); - } else { - playVideo(); - } - } - - @Override - public void onSeekStart() { - mDragging = true; - } - - @Override - public void onSeekMove(int time) { - mVideoView.seekTo(time); - } - - @Override - public void onSeekEnd(int time, int start, int end) { - mDragging = false; - mVideoView.seekTo(time); - setProgress(); - } - - @Override - public void onShown() { - mShowing = true; - setProgress(); - showSystemUi(true); - } - - @Override - public void onHidden() { - mShowing = false; - showSystemUi(false); - } - - @Override - public void onReplay() { - startVideo(); - } - - // Below are key events passed from MovieActivity. - public boolean onKeyDown(int keyCode, KeyEvent event) { - - // Some headsets will fire off 7-10 events on a single click - if (event.getRepeatCount() > 0) { - return isMediaKey(keyCode); - } - - switch (keyCode) { - case KeyEvent.KEYCODE_HEADSETHOOK: - case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: - if (mVideoView.isPlaying()) { - pauseVideo(); - } else { - playVideo(); - } - return true; - case KEYCODE_MEDIA_PAUSE: - if (mVideoView.isPlaying()) { - pauseVideo(); - } - return true; - case KEYCODE_MEDIA_PLAY: - if (!mVideoView.isPlaying()) { - playVideo(); - } - return true; - case KeyEvent.KEYCODE_MEDIA_PREVIOUS: - case KeyEvent.KEYCODE_MEDIA_NEXT: - // TODO: Handle next / previous accordingly, for now we're - // just consuming the events. - return true; - } - return false; - } - - public boolean onKeyUp(int keyCode, KeyEvent event) { - return isMediaKey(keyCode); - } - - private static boolean isMediaKey(int keyCode) { - return keyCode == KeyEvent.KEYCODE_HEADSETHOOK - || keyCode == KeyEvent.KEYCODE_MEDIA_PREVIOUS - || keyCode == KeyEvent.KEYCODE_MEDIA_NEXT - || keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE - || keyCode == KeyEvent.KEYCODE_MEDIA_PLAY - || keyCode == KeyEvent.KEYCODE_MEDIA_PAUSE; - } - - // We want to pause when the headset is unplugged. - private class AudioBecomingNoisyReceiver extends BroadcastReceiver { - - public void register() { - mContext.registerReceiver(this, - new IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY)); - } - - public void unregister() { - mContext.unregisterReceiver(this); - } - - @Override - public void onReceive(Context context, Intent intent) { - if (mVideoView.isPlaying()) pauseVideo(); - } - } -} - -class Bookmarker { - private static final String TAG = "Bookmarker"; - - private static final String BOOKMARK_CACHE_FILE = "bookmark"; - private static final int BOOKMARK_CACHE_MAX_ENTRIES = 100; - private static final int BOOKMARK_CACHE_MAX_BYTES = 10 * 1024; - private static final int BOOKMARK_CACHE_VERSION = 1; - - private static final int HALF_MINUTE = 30 * 1000; - private static final int TWO_MINUTES = 4 * HALF_MINUTE; - - private final Context mContext; - - public Bookmarker(Context context) { - mContext = context; - } - - public void setBookmark(Uri uri, int bookmark, int duration) { - try { - BlobCache cache = CacheManager.getCache(mContext, - BOOKMARK_CACHE_FILE, BOOKMARK_CACHE_MAX_ENTRIES, - BOOKMARK_CACHE_MAX_BYTES, BOOKMARK_CACHE_VERSION); - - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - DataOutputStream dos = new DataOutputStream(bos); - dos.writeUTF(uri.toString()); - dos.writeInt(bookmark); - dos.writeInt(duration); - dos.flush(); - cache.insert(uri.hashCode(), bos.toByteArray()); - } catch (Throwable t) { - Log.w(TAG, "setBookmark failed", t); - } - } - - public Integer getBookmark(Uri uri) { - try { - BlobCache cache = CacheManager.getCache(mContext, - BOOKMARK_CACHE_FILE, BOOKMARK_CACHE_MAX_ENTRIES, - BOOKMARK_CACHE_MAX_BYTES, BOOKMARK_CACHE_VERSION); - - byte[] data = cache.lookup(uri.hashCode()); - if (data == null) return null; - - DataInputStream dis = new DataInputStream( - new ByteArrayInputStream(data)); - - String uriString = DataInputStream.readUTF(dis); - int bookmark = dis.readInt(); - int duration = dis.readInt(); - - if (!uriString.equals(uri.toString())) { - return null; - } - - if ((bookmark < HALF_MINUTE) || (duration < TWO_MINUTES) - || (bookmark > (duration - HALF_MINUTE))) { - return null; - } - return Integer.valueOf(bookmark); - } catch (Throwable t) { - Log.w(TAG, "getBookmark failed", t); - } - return null; - } -} diff --git a/src/com/android/gallery3d/app/MuteVideo.java b/src/com/android/gallery3d/app/MuteVideo.java deleted file mode 100644 index d3f3aa594..000000000 --- a/src/com/android/gallery3d/app/MuteVideo.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * 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. - */ - -package com.android.gallery3d.app; - -import android.app.Activity; -import android.app.ProgressDialog; -import android.content.Intent; -import android.net.Uri; -import android.os.Handler; -import android.provider.MediaStore; -import android.widget.Toast; - -import com.android.gallery3d.R; -import com.android.gallery3d.data.MediaItem; -import com.android.gallery3d.util.SaveVideoFileInfo; -import com.android.gallery3d.util.SaveVideoFileUtils; - -import java.io.IOException; - -public class MuteVideo { - - private ProgressDialog mMuteProgress; - - private String mFilePath = null; - private Uri mUri = null; - private SaveVideoFileInfo mDstFileInfo = null; - private Activity mActivity = null; - private final Handler mHandler = new Handler(); - - final String TIME_STAMP_NAME = "'MUTE'_yyyyMMdd_HHmmss"; - - public MuteVideo(String filePath, Uri uri, Activity activity) { - mUri = uri; - mFilePath = filePath; - mActivity = activity; - } - - public void muteInBackground() { - mDstFileInfo = SaveVideoFileUtils.getDstMp4FileInfo(TIME_STAMP_NAME, - mActivity.getContentResolver(), mUri, - mActivity.getString(R.string.folder_download)); - - showProgressDialog(); - new Thread(new Runnable() { - @Override - public void run() { - try { - VideoUtils.startMute(mFilePath, mDstFileInfo); - SaveVideoFileUtils.insertContent( - mDstFileInfo, mActivity.getContentResolver(), mUri); - } catch (IOException e) { - Toast.makeText(mActivity, mActivity.getString(R.string.video_mute_err), - Toast.LENGTH_SHORT).show(); - } - // After muting is done, trigger the UI changed. - mHandler.post(new Runnable() { - @Override - public void run() { - Toast.makeText(mActivity.getApplicationContext(), - mActivity.getString(R.string.save_into, - mDstFileInfo.mFolderName), - Toast.LENGTH_SHORT) - .show(); - - if (mMuteProgress != null) { - mMuteProgress.dismiss(); - mMuteProgress = null; - - // Show the result only when the activity not - // stopped. - Intent intent = new Intent(android.content.Intent.ACTION_VIEW); - intent.setDataAndType(Uri.fromFile(mDstFileInfo.mFile), "video/*"); - intent.putExtra(MediaStore.EXTRA_FINISH_ON_COMPLETION, false); - mActivity.startActivity(intent); - } - } - }); - } - }).start(); - } - - private void showProgressDialog() { - mMuteProgress = new ProgressDialog(mActivity); - mMuteProgress.setTitle(mActivity.getString(R.string.muting)); - mMuteProgress.setMessage(mActivity.getString(R.string.please_wait)); - mMuteProgress.setCancelable(false); - mMuteProgress.setCanceledOnTouchOutside(false); - mMuteProgress.show(); - } -} diff --git a/src/com/android/gallery3d/app/NotificationIds.java b/src/com/android/gallery3d/app/NotificationIds.java deleted file mode 100644 index d697d854b..000000000 --- a/src/com/android/gallery3d/app/NotificationIds.java +++ /dev/null @@ -1,22 +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.gallery3d.app; - -public class NotificationIds { - public static final int INGEST_NOTIFICATION_SCANNING = 10; - public static final int INGEST_NOTIFICATION_IMPORTING = 11; -} diff --git a/src/com/android/gallery3d/app/OrientationManager.java b/src/com/android/gallery3d/app/OrientationManager.java deleted file mode 100644 index f2f632c9f..000000000 --- a/src/com/android/gallery3d/app/OrientationManager.java +++ /dev/null @@ -1,166 +0,0 @@ -/* - * 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. - */ - -package com.android.gallery3d.app; - -import android.app.Activity; -import android.content.ContentResolver; -import android.content.Context; -import android.content.pm.ActivityInfo; -import android.content.res.Configuration; -import android.provider.Settings; -import android.view.OrientationEventListener; -import android.view.Surface; - -import com.android.gallery3d.common.ApiHelper; -import com.android.gallery3d.ui.OrientationSource; - -public class OrientationManager implements OrientationSource { - private static final String TAG = "OrientationManager"; - - // Orientation hysteresis amount used in rounding, in degrees - private static final int ORIENTATION_HYSTERESIS = 5; - - private Activity mActivity; - private MyOrientationEventListener mOrientationListener; - // If the framework orientation is locked. - private boolean mOrientationLocked = false; - - // This is true if "Settings -> Display -> Rotation Lock" is checked. We - // don't allow the orientation to be unlocked if the value is true. - private boolean mRotationLockedSetting = false; - - public OrientationManager(Activity activity) { - mActivity = activity; - mOrientationListener = new MyOrientationEventListener(activity); - } - - public void resume() { - ContentResolver resolver = mActivity.getContentResolver(); - mRotationLockedSetting = Settings.System.getInt( - resolver, Settings.System.ACCELEROMETER_ROTATION, 0) != 1; - mOrientationListener.enable(); - } - - public void pause() { - mOrientationListener.disable(); - } - - //////////////////////////////////////////////////////////////////////////// - // Orientation handling - // - // We can choose to lock the framework orientation or not. If we lock the - // framework orientation, we calculate a a compensation value according to - // current device orientation and send it to listeners. If we don't lock - // the framework orientation, we always set the compensation value to 0. - //////////////////////////////////////////////////////////////////////////// - - // Lock the framework orientation to the current device orientation - public void lockOrientation() { - if (mOrientationLocked) return; - mOrientationLocked = true; - if (ApiHelper.HAS_ORIENTATION_LOCK) { - mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED); - } else { - mActivity.setRequestedOrientation(calculateCurrentScreenOrientation()); - } - } - - // Unlock the framework orientation, so it can change when the device - // rotates. - public void unlockOrientation() { - if (!mOrientationLocked) return; - mOrientationLocked = false; - Log.d(TAG, "unlock orientation"); - mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR); - } - - private int calculateCurrentScreenOrientation() { - int displayRotation = getDisplayRotation(); - // Display rotation >= 180 means we need to use the REVERSE landscape/portrait - boolean standard = displayRotation < 180; - if (mActivity.getResources().getConfiguration().orientation - == Configuration.ORIENTATION_LANDSCAPE) { - return standard - ? ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE - : ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE; - } else { - if (displayRotation == 90 || displayRotation == 270) { - // If displayRotation = 90 or 270 then we are on a landscape - // device. On landscape devices, portrait is a 90 degree - // clockwise rotation from landscape, so we need - // to flip which portrait we pick as display rotation is counter clockwise - standard = !standard; - } - return standard - ? ActivityInfo.SCREEN_ORIENTATION_PORTRAIT - : ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT; - } - } - - // This listens to the device orientation, so we can update the compensation. - private class MyOrientationEventListener extends OrientationEventListener { - public MyOrientationEventListener(Context context) { - super(context); - } - - @Override - public void onOrientationChanged(int orientation) { - // We keep the last known orientation. So if the user first orient - // the camera then point the camera to floor or sky, we still have - // the correct orientation. - if (orientation == ORIENTATION_UNKNOWN) return; - orientation = roundOrientation(orientation, 0); - } - } - - @Override - public int getDisplayRotation() { - return getDisplayRotation(mActivity); - } - - @Override - public int getCompensation() { - return 0; - } - - private static int roundOrientation(int orientation, int orientationHistory) { - boolean changeOrientation = false; - if (orientationHistory == OrientationEventListener.ORIENTATION_UNKNOWN) { - changeOrientation = true; - } else { - int dist = Math.abs(orientation - orientationHistory); - dist = Math.min(dist, 360 - dist); - changeOrientation = (dist >= 45 + ORIENTATION_HYSTERESIS); - } - if (changeOrientation) { - return ((orientation + 45) / 90 * 90) % 360; - } - return orientationHistory; - } - - private static int getDisplayRotation(Activity activity) { - int rotation = activity.getWindowManager().getDefaultDisplay() - .getRotation(); - switch (rotation) { - case Surface.ROTATION_0: return 0; - case Surface.ROTATION_90: return 90; - case Surface.ROTATION_180: return 180; - case Surface.ROTATION_270: return 270; - } - return 0; - } -} diff --git a/src/com/android/gallery3d/app/PackagesMonitor.java b/src/com/android/gallery3d/app/PackagesMonitor.java deleted file mode 100644 index 9b2412f1b..000000000 --- a/src/com/android/gallery3d/app/PackagesMonitor.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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.gallery3d.app; - -import android.app.IntentService; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.preference.PreferenceManager; - -import com.android.gallery3d.picasasource.PicasaSource; -import com.android.gallery3d.util.LightCycleHelper; - -public class PackagesMonitor extends BroadcastReceiver { - public static final String KEY_PACKAGES_VERSION = "packages-version"; - - public synchronized static int getPackagesVersion(Context context) { - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); - return prefs.getInt(KEY_PACKAGES_VERSION, 1); - } - - @Override - public void onReceive(final Context context, final Intent intent) { - intent.setClass(context, AsyncService.class); - context.startService(intent); - } - - public static class AsyncService extends IntentService { - public AsyncService() { - super("GalleryPackagesMonitorAsync"); - } - - @Override - protected void onHandleIntent(Intent intent) { - onReceiveAsync(this, intent); - } - } - - // Runs in a background thread. - private static void onReceiveAsync(Context context, Intent intent) { - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); - - int version = prefs.getInt(KEY_PACKAGES_VERSION, 1); - prefs.edit().putInt(KEY_PACKAGES_VERSION, version + 1).commit(); - - String action = intent.getAction(); - String packageName = intent.getData().getSchemeSpecificPart(); - if (Intent.ACTION_PACKAGE_ADDED.equals(action)) { - PicasaSource.onPackageAdded(context, packageName); - } else if (Intent.ACTION_PACKAGE_REMOVED.equals(action)) { - PicasaSource.onPackageRemoved(context, packageName); - } else if (Intent.ACTION_PACKAGE_CHANGED.equals(action)) { - PicasaSource.onPackageChanged(context, packageName); - } - } -} diff --git a/src/com/android/gallery3d/app/PanoramaMetadataSupport.java b/src/com/android/gallery3d/app/PanoramaMetadataSupport.java deleted file mode 100644 index ba0c9e71a..000000000 --- a/src/com/android/gallery3d/app/PanoramaMetadataSupport.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * 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. - */ -package com.android.gallery3d.app; - -import com.android.gallery3d.data.MediaObject; -import com.android.gallery3d.data.MediaObject.PanoramaSupportCallback; -import com.android.gallery3d.data.PanoramaMetadataJob; -import com.android.gallery3d.util.Future; -import com.android.gallery3d.util.FutureListener; -import com.android.gallery3d.util.LightCycleHelper; -import com.android.gallery3d.util.LightCycleHelper.PanoramaMetadata; - -import java.util.ArrayList; - -/** - * This class breaks out the off-thread panorama support checks so that the - * complexity can be shared between UriImage and LocalImage, which need to - * support panoramas. - */ -public class PanoramaMetadataSupport implements FutureListener { - private Object mLock = new Object(); - private Future mGetPanoMetadataTask; - private PanoramaMetadata mPanoramaMetadata; - private ArrayList mCallbacksWaiting; - private MediaObject mMediaObject; - - public PanoramaMetadataSupport(MediaObject mediaObject) { - mMediaObject = mediaObject; - } - - public void getPanoramaSupport(GalleryApp app, PanoramaSupportCallback callback) { - synchronized (mLock) { - if (mPanoramaMetadata != null) { - callback.panoramaInfoAvailable(mMediaObject, mPanoramaMetadata.mUsePanoramaViewer, - mPanoramaMetadata.mIsPanorama360); - } else { - if (mCallbacksWaiting == null) { - mCallbacksWaiting = new ArrayList(); - mGetPanoMetadataTask = app.getThreadPool().submit( - new PanoramaMetadataJob(app.getAndroidContext(), - mMediaObject.getContentUri()), this); - - } - mCallbacksWaiting.add(callback); - } - } - } - - public void clearCachedValues() { - synchronized (mLock) { - if (mPanoramaMetadata != null) { - mPanoramaMetadata = null; - } else if (mGetPanoMetadataTask != null) { - mGetPanoMetadataTask.cancel(); - for (PanoramaSupportCallback cb : mCallbacksWaiting) { - cb.panoramaInfoAvailable(mMediaObject, false, false); - } - mGetPanoMetadataTask = null; - mCallbacksWaiting = null; - } - } - } - - @Override - public void onFutureDone(Future future) { - synchronized (mLock) { - mPanoramaMetadata = future.get(); - if (mPanoramaMetadata == null) { - // Error getting panorama data from file. Treat as not panorama. - mPanoramaMetadata = LightCycleHelper.NOT_PANORAMA; - } - for (PanoramaSupportCallback cb : mCallbacksWaiting) { - cb.panoramaInfoAvailable(mMediaObject, mPanoramaMetadata.mUsePanoramaViewer, - mPanoramaMetadata.mIsPanorama360); - } - mGetPanoMetadataTask = null; - mCallbacksWaiting = null; - } - } -} diff --git a/src/com/android/gallery3d/app/PhotoDataAdapter.java b/src/com/android/gallery3d/app/PhotoDataAdapter.java deleted file mode 100644 index fd3a7cf73..000000000 --- a/src/com/android/gallery3d/app/PhotoDataAdapter.java +++ /dev/null @@ -1,1133 +0,0 @@ -/* - * 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.gallery3d.app; - -import android.graphics.Bitmap; -import android.graphics.BitmapRegionDecoder; -import android.os.Handler; -import android.os.Message; - -import com.android.gallery3d.common.BitmapUtils; -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.data.ContentListener; -import com.android.gallery3d.data.LocalMediaItem; -import com.android.gallery3d.data.MediaItem; -import com.android.gallery3d.data.MediaObject; -import com.android.gallery3d.data.MediaSet; -import com.android.gallery3d.data.Path; -import com.android.gallery3d.glrenderer.TiledTexture; -import com.android.gallery3d.ui.PhotoView; -import com.android.gallery3d.ui.ScreenNail; -import com.android.gallery3d.ui.SynchronizedHandler; -import com.android.gallery3d.ui.TileImageViewAdapter; -import com.android.gallery3d.ui.TiledScreenNail; -import com.android.gallery3d.util.Future; -import com.android.gallery3d.util.FutureListener; -import com.android.gallery3d.util.MediaSetUtils; -import com.android.gallery3d.util.ThreadPool; -import com.android.gallery3d.util.ThreadPool.Job; -import com.android.gallery3d.util.ThreadPool.JobContext; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.FutureTask; - -public class PhotoDataAdapter implements PhotoPage.Model { - @SuppressWarnings("unused") - private static final String TAG = "PhotoDataAdapter"; - - private static final int MSG_LOAD_START = 1; - private static final int MSG_LOAD_FINISH = 2; - private static final int MSG_RUN_OBJECT = 3; - private static final int MSG_UPDATE_IMAGE_REQUESTS = 4; - - private static final int MIN_LOAD_COUNT = 16; - private static final int DATA_CACHE_SIZE = 256; - private static final int SCREEN_NAIL_MAX = PhotoView.SCREEN_NAIL_MAX; - private static final int IMAGE_CACHE_SIZE = 2 * SCREEN_NAIL_MAX + 1; - - private static final int BIT_SCREEN_NAIL = 1; - private static final int BIT_FULL_IMAGE = 2; - - // sImageFetchSeq is the fetching sequence for images. - // We want to fetch the current screennail first (offset = 0), the next - // screennail (offset = +1), then the previous screennail (offset = -1) etc. - // After all the screennail are fetched, we fetch the full images (only some - // of them because of we don't want to use too much memory). - private static ImageFetch[] sImageFetchSeq; - - private static class ImageFetch { - int indexOffset; - int imageBit; - public ImageFetch(int offset, int bit) { - indexOffset = offset; - imageBit = bit; - } - } - - static { - int k = 0; - sImageFetchSeq = new ImageFetch[1 + (IMAGE_CACHE_SIZE - 1) * 2 + 3]; - sImageFetchSeq[k++] = new ImageFetch(0, BIT_SCREEN_NAIL); - - for (int i = 1; i < IMAGE_CACHE_SIZE; ++i) { - sImageFetchSeq[k++] = new ImageFetch(i, BIT_SCREEN_NAIL); - sImageFetchSeq[k++] = new ImageFetch(-i, BIT_SCREEN_NAIL); - } - - sImageFetchSeq[k++] = new ImageFetch(0, BIT_FULL_IMAGE); - sImageFetchSeq[k++] = new ImageFetch(1, BIT_FULL_IMAGE); - sImageFetchSeq[k++] = new ImageFetch(-1, BIT_FULL_IMAGE); - } - - private final TileImageViewAdapter mTileProvider = new TileImageViewAdapter(); - - // PhotoDataAdapter caches MediaItems (data) and ImageEntries (image). - // - // The MediaItems are stored in the mData array, which has DATA_CACHE_SIZE - // entries. The valid index range are [mContentStart, mContentEnd). We keep - // mContentEnd - mContentStart <= DATA_CACHE_SIZE, so we can use - // (i % DATA_CACHE_SIZE) as index to the array. - // - // The valid MediaItem window size (mContentEnd - mContentStart) may be - // smaller than DATA_CACHE_SIZE because we only update the window and reload - // the MediaItems when there are significant changes to the window position - // (>= MIN_LOAD_COUNT). - private final MediaItem mData[] = new MediaItem[DATA_CACHE_SIZE]; - private int mContentStart = 0; - private int mContentEnd = 0; - - // The ImageCache is a Path-to-ImageEntry map. It only holds the - // ImageEntries in the range of [mActiveStart, mActiveEnd). We also keep - // mActiveEnd - mActiveStart <= IMAGE_CACHE_SIZE. Besides, the - // [mActiveStart, mActiveEnd) range must be contained within - // the [mContentStart, mContentEnd) range. - private HashMap mImageCache = - new HashMap(); - private int mActiveStart = 0; - private int mActiveEnd = 0; - - // mCurrentIndex is the "center" image the user is viewing. The change of - // mCurrentIndex triggers the data loading and image loading. - private int mCurrentIndex; - - // mChanges keeps the version number (of MediaItem) about the images. If any - // of the version number changes, we notify the view. This is used after a - // database reload or mCurrentIndex changes. - private final long mChanges[] = new long[IMAGE_CACHE_SIZE]; - // mPaths keeps the corresponding Path (of MediaItem) for the images. This - // is used to determine the item movement. - private final Path mPaths[] = new Path[IMAGE_CACHE_SIZE]; - - private final Handler mMainHandler; - private final ThreadPool mThreadPool; - - private final PhotoView mPhotoView; - private final MediaSet mSource; - private ReloadTask mReloadTask; - - private long mSourceVersion = MediaObject.INVALID_DATA_VERSION; - private int mSize = 0; - private Path mItemPath; - private int mCameraIndex; - private boolean mIsPanorama; - private boolean mIsStaticCamera; - private boolean mIsActive; - private boolean mNeedFullImage; - private int mFocusHintDirection = FOCUS_HINT_NEXT; - private Path mFocusHintPath = null; - - public interface DataListener extends LoadingListener { - public void onPhotoChanged(int index, Path item); - } - - private DataListener mDataListener; - - private final SourceListener mSourceListener = new SourceListener(); - private final TiledTexture.Uploader mUploader; - - // The path of the current viewing item will be stored in mItemPath. - // If mItemPath is not null, mCurrentIndex is only a hint for where we - // can find the item. If mItemPath is null, then we use the mCurrentIndex to - // find the image being viewed. cameraIndex is the index of the camera - // preview. If cameraIndex < 0, there is no camera preview. - public PhotoDataAdapter(AbstractGalleryActivity activity, PhotoView view, - MediaSet mediaSet, Path itemPath, int indexHint, int cameraIndex, - boolean isPanorama, boolean isStaticCamera) { - mSource = Utils.checkNotNull(mediaSet); - mPhotoView = Utils.checkNotNull(view); - mItemPath = Utils.checkNotNull(itemPath); - mCurrentIndex = indexHint; - mCameraIndex = cameraIndex; - mIsPanorama = isPanorama; - mIsStaticCamera = isStaticCamera; - mThreadPool = activity.getThreadPool(); - mNeedFullImage = true; - - Arrays.fill(mChanges, MediaObject.INVALID_DATA_VERSION); - - mUploader = new TiledTexture.Uploader(activity.getGLRoot()); - - mMainHandler = new SynchronizedHandler(activity.getGLRoot()) { - @SuppressWarnings("unchecked") - @Override - public void handleMessage(Message message) { - switch (message.what) { - case MSG_RUN_OBJECT: - ((Runnable) message.obj).run(); - return; - case MSG_LOAD_START: { - if (mDataListener != null) { - mDataListener.onLoadingStarted(); - } - return; - } - case MSG_LOAD_FINISH: { - if (mDataListener != null) { - mDataListener.onLoadingFinished(false); - } - return; - } - case MSG_UPDATE_IMAGE_REQUESTS: { - updateImageRequests(); - return; - } - default: throw new AssertionError(); - } - } - }; - - updateSlidingWindow(); - } - - private MediaItem getItemInternal(int index) { - if (index < 0 || index >= mSize) return null; - if (index >= mContentStart && index < mContentEnd) { - return mData[index % DATA_CACHE_SIZE]; - } - return null; - } - - private long getVersion(int index) { - MediaItem item = getItemInternal(index); - if (item == null) return MediaObject.INVALID_DATA_VERSION; - return item.getDataVersion(); - } - - private Path getPath(int index) { - MediaItem item = getItemInternal(index); - if (item == null) return null; - return item.getPath(); - } - - private void fireDataChange() { - // First check if data actually changed. - boolean changed = false; - for (int i = -SCREEN_NAIL_MAX; i <= SCREEN_NAIL_MAX; ++i) { - long newVersion = getVersion(mCurrentIndex + i); - if (mChanges[i + SCREEN_NAIL_MAX] != newVersion) { - mChanges[i + SCREEN_NAIL_MAX] = newVersion; - changed = true; - } - } - - if (!changed) return; - - // Now calculate the fromIndex array. fromIndex represents the item - // movement. It records the index where the picture come from. The - // special value Integer.MAX_VALUE means it's a new picture. - final int N = IMAGE_CACHE_SIZE; - int fromIndex[] = new int[N]; - - // Remember the old path array. - Path oldPaths[] = new Path[N]; - System.arraycopy(mPaths, 0, oldPaths, 0, N); - - // Update the mPaths array. - for (int i = 0; i < N; ++i) { - mPaths[i] = getPath(mCurrentIndex + i - SCREEN_NAIL_MAX); - } - - // Calculate the fromIndex array. - for (int i = 0; i < N; i++) { - Path p = mPaths[i]; - if (p == null) { - fromIndex[i] = Integer.MAX_VALUE; - continue; - } - - // Try to find the same path in the old array - int j; - for (j = 0; j < N; j++) { - if (oldPaths[j] == p) { - break; - } - } - fromIndex[i] = (j < N) ? j - SCREEN_NAIL_MAX : Integer.MAX_VALUE; - } - - mPhotoView.notifyDataChange(fromIndex, -mCurrentIndex, - mSize - 1 - mCurrentIndex); - } - - public void setDataListener(DataListener listener) { - mDataListener = listener; - } - - private void updateScreenNail(Path path, Future future) { - ImageEntry entry = mImageCache.get(path); - ScreenNail screenNail = future.get(); - - if (entry == null || entry.screenNailTask != future) { - if (screenNail != null) screenNail.recycle(); - return; - } - - entry.screenNailTask = null; - - // Combine the ScreenNails if we already have a BitmapScreenNail - if (entry.screenNail instanceof TiledScreenNail) { - TiledScreenNail original = (TiledScreenNail) entry.screenNail; - screenNail = original.combine(screenNail); - } - - if (screenNail == null) { - entry.failToLoad = true; - } else { - entry.failToLoad = false; - entry.screenNail = screenNail; - } - - for (int i = -SCREEN_NAIL_MAX; i <= SCREEN_NAIL_MAX; ++i) { - if (path == getPath(mCurrentIndex + i)) { - if (i == 0) updateTileProvider(entry); - mPhotoView.notifyImageChange(i); - break; - } - } - updateImageRequests(); - updateScreenNailUploadQueue(); - } - - private void updateFullImage(Path path, Future future) { - ImageEntry entry = mImageCache.get(path); - if (entry == null || entry.fullImageTask != future) { - BitmapRegionDecoder fullImage = future.get(); - if (fullImage != null) fullImage.recycle(); - return; - } - - entry.fullImageTask = null; - entry.fullImage = future.get(); - if (entry.fullImage != null) { - if (path == getPath(mCurrentIndex)) { - updateTileProvider(entry); - mPhotoView.notifyImageChange(0); - } - } - updateImageRequests(); - } - - @Override - public void resume() { - mIsActive = true; - TiledTexture.prepareResources(); - - mSource.addContentListener(mSourceListener); - updateImageCache(); - updateImageRequests(); - - mReloadTask = new ReloadTask(); - mReloadTask.start(); - - fireDataChange(); - } - - @Override - public void pause() { - mIsActive = false; - - mReloadTask.terminate(); - mReloadTask = null; - - mSource.removeContentListener(mSourceListener); - - for (ImageEntry entry : mImageCache.values()) { - if (entry.fullImageTask != null) entry.fullImageTask.cancel(); - if (entry.screenNailTask != null) entry.screenNailTask.cancel(); - if (entry.screenNail != null) entry.screenNail.recycle(); - } - mImageCache.clear(); - mTileProvider.clear(); - - mUploader.clear(); - TiledTexture.freeResources(); - } - - private MediaItem getItem(int index) { - if (index < 0 || index >= mSize || !mIsActive) return null; - Utils.assertTrue(index >= mActiveStart && index < mActiveEnd); - - if (index >= mContentStart && index < mContentEnd) { - return mData[index % DATA_CACHE_SIZE]; - } - return null; - } - - private void updateCurrentIndex(int index) { - if (mCurrentIndex == index) return; - mCurrentIndex = index; - updateSlidingWindow(); - - MediaItem item = mData[index % DATA_CACHE_SIZE]; - mItemPath = item == null ? null : item.getPath(); - - updateImageCache(); - updateImageRequests(); - updateTileProvider(); - - if (mDataListener != null) { - mDataListener.onPhotoChanged(index, mItemPath); - } - - fireDataChange(); - } - - private void uploadScreenNail(int offset) { - int index = mCurrentIndex + offset; - if (index < mActiveStart || index >= mActiveEnd) return; - - MediaItem item = getItem(index); - if (item == null) return; - - ImageEntry e = mImageCache.get(item.getPath()); - if (e == null) return; - - ScreenNail s = e.screenNail; - if (s instanceof TiledScreenNail) { - TiledTexture t = ((TiledScreenNail) s).getTexture(); - if (t != null && !t.isReady()) mUploader.addTexture(t); - } - } - - private void updateScreenNailUploadQueue() { - mUploader.clear(); - uploadScreenNail(0); - for (int i = 1; i < IMAGE_CACHE_SIZE; ++i) { - uploadScreenNail(i); - uploadScreenNail(-i); - } - } - - @Override - public void moveTo(int index) { - updateCurrentIndex(index); - } - - @Override - public ScreenNail getScreenNail(int offset) { - int index = mCurrentIndex + offset; - if (index < 0 || index >= mSize || !mIsActive) return null; - Utils.assertTrue(index >= mActiveStart && index < mActiveEnd); - - MediaItem item = getItem(index); - if (item == null) return null; - - ImageEntry entry = mImageCache.get(item.getPath()); - if (entry == null) return null; - - // Create a default ScreenNail if the real one is not available yet, - // except for camera that a black screen is better than a gray tile. - if (entry.screenNail == null && !isCamera(offset)) { - entry.screenNail = newPlaceholderScreenNail(item); - if (offset == 0) updateTileProvider(entry); - } - - return entry.screenNail; - } - - @Override - public void getImageSize(int offset, PhotoView.Size size) { - MediaItem item = getItem(mCurrentIndex + offset); - if (item == null) { - size.width = 0; - size.height = 0; - } else { - size.width = item.getWidth(); - size.height = item.getHeight(); - } - } - - @Override - public int getImageRotation(int offset) { - MediaItem item = getItem(mCurrentIndex + offset); - return (item == null) ? 0 : item.getFullImageRotation(); - } - - @Override - public void setNeedFullImage(boolean enabled) { - mNeedFullImage = enabled; - mMainHandler.sendEmptyMessage(MSG_UPDATE_IMAGE_REQUESTS); - } - - @Override - public boolean isCamera(int offset) { - return mCurrentIndex + offset == mCameraIndex; - } - - @Override - public boolean isPanorama(int offset) { - return isCamera(offset) && mIsPanorama; - } - - @Override - public boolean isStaticCamera(int offset) { - return isCamera(offset) && mIsStaticCamera; - } - - @Override - public boolean isVideo(int offset) { - MediaItem item = getItem(mCurrentIndex + offset); - return (item == null) - ? false - : item.getMediaType() == MediaItem.MEDIA_TYPE_VIDEO; - } - - @Override - public boolean isDeletable(int offset) { - MediaItem item = getItem(mCurrentIndex + offset); - return (item == null) - ? false - : (item.getSupportedOperations() & MediaItem.SUPPORT_DELETE) != 0; - } - - @Override - public int getLoadingState(int offset) { - ImageEntry entry = mImageCache.get(getPath(mCurrentIndex + offset)); - if (entry == null) return LOADING_INIT; - if (entry.failToLoad) return LOADING_FAIL; - if (entry.screenNail != null) return LOADING_COMPLETE; - return LOADING_INIT; - } - - @Override - public ScreenNail getScreenNail() { - return getScreenNail(0); - } - - @Override - public int getImageHeight() { - return mTileProvider.getImageHeight(); - } - - @Override - public int getImageWidth() { - return mTileProvider.getImageWidth(); - } - - @Override - public int getLevelCount() { - return mTileProvider.getLevelCount(); - } - - @Override - public Bitmap getTile(int level, int x, int y, int tileSize) { - return mTileProvider.getTile(level, x, y, tileSize); - } - - @Override - public boolean isEmpty() { - return mSize == 0; - } - - @Override - public int getCurrentIndex() { - return mCurrentIndex; - } - - @Override - public MediaItem getMediaItem(int offset) { - int index = mCurrentIndex + offset; - if (index >= mContentStart && index < mContentEnd) { - return mData[index % DATA_CACHE_SIZE]; - } - return null; - } - - @Override - public void setCurrentPhoto(Path path, int indexHint) { - if (mItemPath == path) return; - mItemPath = path; - mCurrentIndex = indexHint; - updateSlidingWindow(); - updateImageCache(); - fireDataChange(); - - // We need to reload content if the path doesn't match. - MediaItem item = getMediaItem(0); - if (item != null && item.getPath() != path) { - if (mReloadTask != null) mReloadTask.notifyDirty(); - } - } - - @Override - public void setFocusHintDirection(int direction) { - mFocusHintDirection = direction; - } - - @Override - public void setFocusHintPath(Path path) { - mFocusHintPath = path; - } - - private void updateTileProvider() { - ImageEntry entry = mImageCache.get(getPath(mCurrentIndex)); - if (entry == null) { // in loading - mTileProvider.clear(); - } else { - updateTileProvider(entry); - } - } - - private void updateTileProvider(ImageEntry entry) { - ScreenNail screenNail = entry.screenNail; - BitmapRegionDecoder fullImage = entry.fullImage; - if (screenNail != null) { - if (fullImage != null) { - mTileProvider.setScreenNail(screenNail, - fullImage.getWidth(), fullImage.getHeight()); - mTileProvider.setRegionDecoder(fullImage); - } else { - int width = screenNail.getWidth(); - int height = screenNail.getHeight(); - mTileProvider.setScreenNail(screenNail, width, height); - } - } else { - mTileProvider.clear(); - } - } - - private void updateSlidingWindow() { - // 1. Update the image window - int start = Utils.clamp(mCurrentIndex - IMAGE_CACHE_SIZE / 2, - 0, Math.max(0, mSize - IMAGE_CACHE_SIZE)); - int end = Math.min(mSize, start + IMAGE_CACHE_SIZE); - - if (mActiveStart == start && mActiveEnd == end) return; - - mActiveStart = start; - mActiveEnd = end; - - // 2. Update the data window - start = Utils.clamp(mCurrentIndex - DATA_CACHE_SIZE / 2, - 0, Math.max(0, mSize - DATA_CACHE_SIZE)); - end = Math.min(mSize, start + DATA_CACHE_SIZE); - if (mContentStart > mActiveStart || mContentEnd < mActiveEnd - || Math.abs(start - mContentStart) > MIN_LOAD_COUNT) { - for (int i = mContentStart; i < mContentEnd; ++i) { - if (i < start || i >= end) { - mData[i % DATA_CACHE_SIZE] = null; - } - } - mContentStart = start; - mContentEnd = end; - if (mReloadTask != null) mReloadTask.notifyDirty(); - } - } - - private void updateImageRequests() { - if (!mIsActive) return; - - int currentIndex = mCurrentIndex; - MediaItem item = mData[currentIndex % DATA_CACHE_SIZE]; - if (item == null || item.getPath() != mItemPath) { - // current item mismatch - don't request image - return; - } - - // 1. Find the most wanted request and start it (if not already started). - Future task = null; - for (int i = 0; i < sImageFetchSeq.length; i++) { - int offset = sImageFetchSeq[i].indexOffset; - int bit = sImageFetchSeq[i].imageBit; - if (bit == BIT_FULL_IMAGE && !mNeedFullImage) continue; - task = startTaskIfNeeded(currentIndex + offset, bit); - if (task != null) break; - } - - // 2. Cancel everything else. - for (ImageEntry entry : mImageCache.values()) { - if (entry.screenNailTask != null && entry.screenNailTask != task) { - entry.screenNailTask.cancel(); - entry.screenNailTask = null; - entry.requestedScreenNail = MediaObject.INVALID_DATA_VERSION; - } - if (entry.fullImageTask != null && entry.fullImageTask != task) { - entry.fullImageTask.cancel(); - entry.fullImageTask = null; - entry.requestedFullImage = MediaObject.INVALID_DATA_VERSION; - } - } - } - - private class ScreenNailJob implements Job { - private MediaItem mItem; - - public ScreenNailJob(MediaItem item) { - mItem = item; - } - - @Override - public ScreenNail run(JobContext jc) { - // We try to get a ScreenNail first, if it fails, we fallback to get - // a Bitmap and then wrap it in a BitmapScreenNail instead. - ScreenNail s = mItem.getScreenNail(); - if (s != null) return s; - - // If this is a temporary item, don't try to get its bitmap because - // it won't be available. We will get its bitmap after a data reload. - if (isTemporaryItem(mItem)) { - return newPlaceholderScreenNail(mItem); - } - - Bitmap bitmap = mItem.requestImage(MediaItem.TYPE_THUMBNAIL).run(jc); - if (jc.isCancelled()) return null; - if (bitmap != null) { - bitmap = BitmapUtils.rotateBitmap(bitmap, - mItem.getRotation() - mItem.getFullImageRotation(), true); - } - return bitmap == null ? null : new TiledScreenNail(bitmap); - } - } - - private class FullImageJob implements Job { - private MediaItem mItem; - - public FullImageJob(MediaItem item) { - mItem = item; - } - - @Override - public BitmapRegionDecoder run(JobContext jc) { - if (isTemporaryItem(mItem)) { - return null; - } - return mItem.requestLargeImage().run(jc); - } - } - - // Returns true if we think this is a temporary item created by Camera. A - // temporary item is an image or a video whose data is still being - // processed, but an incomplete entry is created first in MediaProvider, so - // we can display them (in grey tile) even if they are not saved to disk - // yet. When the image or video data is actually saved, we will get - // notification from MediaProvider, reload data, and show the actual image - // or video data. - private boolean isTemporaryItem(MediaItem mediaItem) { - // Must have camera to create a temporary item. - if (mCameraIndex < 0) return false; - // Must be an item in camera roll. - if (!(mediaItem instanceof LocalMediaItem)) return false; - LocalMediaItem item = (LocalMediaItem) mediaItem; - if (item.getBucketId() != MediaSetUtils.CAMERA_BUCKET_ID) return false; - // Must have no size, but must have width and height information - if (item.getSize() != 0) return false; - if (item.getWidth() == 0) return false; - if (item.getHeight() == 0) return false; - // Must be created in the last 10 seconds. - if (item.getDateInMs() - System.currentTimeMillis() > 10000) return false; - return true; - } - - // Create a default ScreenNail when a ScreenNail is needed, but we don't yet - // have one available (because the image data is still being saved, or the - // Bitmap is still being loaded. - private ScreenNail newPlaceholderScreenNail(MediaItem item) { - int width = item.getWidth(); - int height = item.getHeight(); - return new TiledScreenNail(width, height); - } - - // Returns the task if we started the task or the task is already started. - private Future startTaskIfNeeded(int index, int which) { - if (index < mActiveStart || index >= mActiveEnd) return null; - - ImageEntry entry = mImageCache.get(getPath(index)); - if (entry == null) return null; - MediaItem item = mData[index % DATA_CACHE_SIZE]; - Utils.assertTrue(item != null); - long version = item.getDataVersion(); - - if (which == BIT_SCREEN_NAIL && entry.screenNailTask != null - && entry.requestedScreenNail == version) { - return entry.screenNailTask; - } else if (which == BIT_FULL_IMAGE && entry.fullImageTask != null - && entry.requestedFullImage == version) { - return entry.fullImageTask; - } - - if (which == BIT_SCREEN_NAIL && entry.requestedScreenNail != version) { - entry.requestedScreenNail = version; - entry.screenNailTask = mThreadPool.submit( - new ScreenNailJob(item), - new ScreenNailListener(item)); - // request screen nail - return entry.screenNailTask; - } - if (which == BIT_FULL_IMAGE && entry.requestedFullImage != version - && (item.getSupportedOperations() - & MediaItem.SUPPORT_FULL_IMAGE) != 0) { - entry.requestedFullImage = version; - entry.fullImageTask = mThreadPool.submit( - new FullImageJob(item), - new FullImageListener(item)); - // request full image - return entry.fullImageTask; - } - return null; - } - - private void updateImageCache() { - HashSet toBeRemoved = new HashSet(mImageCache.keySet()); - for (int i = mActiveStart; i < mActiveEnd; ++i) { - MediaItem item = mData[i % DATA_CACHE_SIZE]; - if (item == null) continue; - Path path = item.getPath(); - ImageEntry entry = mImageCache.get(path); - toBeRemoved.remove(path); - if (entry != null) { - if (Math.abs(i - mCurrentIndex) > 1) { - if (entry.fullImageTask != null) { - entry.fullImageTask.cancel(); - entry.fullImageTask = null; - } - entry.fullImage = null; - entry.requestedFullImage = MediaObject.INVALID_DATA_VERSION; - } - if (entry.requestedScreenNail != item.getDataVersion()) { - // This ScreenNail is outdated, we want to update it if it's - // still a placeholder. - if (entry.screenNail instanceof TiledScreenNail) { - TiledScreenNail s = (TiledScreenNail) entry.screenNail; - s.updatePlaceholderSize( - item.getWidth(), item.getHeight()); - } - } - } else { - entry = new ImageEntry(); - mImageCache.put(path, entry); - } - } - - // Clear the data and requests for ImageEntries outside the new window. - for (Path path : toBeRemoved) { - ImageEntry entry = mImageCache.remove(path); - if (entry.fullImageTask != null) entry.fullImageTask.cancel(); - if (entry.screenNailTask != null) entry.screenNailTask.cancel(); - if (entry.screenNail != null) entry.screenNail.recycle(); - } - - updateScreenNailUploadQueue(); - } - - private class FullImageListener - implements Runnable, FutureListener { - private final Path mPath; - private Future mFuture; - - public FullImageListener(MediaItem item) { - mPath = item.getPath(); - } - - @Override - public void onFutureDone(Future future) { - mFuture = future; - mMainHandler.sendMessage( - mMainHandler.obtainMessage(MSG_RUN_OBJECT, this)); - } - - @Override - public void run() { - updateFullImage(mPath, mFuture); - } - } - - private class ScreenNailListener - implements Runnable, FutureListener { - private final Path mPath; - private Future mFuture; - - public ScreenNailListener(MediaItem item) { - mPath = item.getPath(); - } - - @Override - public void onFutureDone(Future future) { - mFuture = future; - mMainHandler.sendMessage( - mMainHandler.obtainMessage(MSG_RUN_OBJECT, this)); - } - - @Override - public void run() { - updateScreenNail(mPath, mFuture); - } - } - - private static class ImageEntry { - public BitmapRegionDecoder fullImage; - public ScreenNail screenNail; - public Future screenNailTask; - public Future fullImageTask; - public long requestedScreenNail = MediaObject.INVALID_DATA_VERSION; - public long requestedFullImage = MediaObject.INVALID_DATA_VERSION; - public boolean failToLoad = false; - } - - private class SourceListener implements ContentListener { - @Override - public void onContentDirty() { - if (mReloadTask != null) mReloadTask.notifyDirty(); - } - } - - private T executeAndWait(Callable callable) { - FutureTask task = new FutureTask(callable); - mMainHandler.sendMessage( - mMainHandler.obtainMessage(MSG_RUN_OBJECT, task)); - try { - return task.get(); - } catch (InterruptedException e) { - return null; - } catch (ExecutionException e) { - throw new RuntimeException(e); - } - } - - private static class UpdateInfo { - public long version; - public boolean reloadContent; - public Path target; - public int indexHint; - public int contentStart; - public int contentEnd; - - public int size; - public ArrayList items; - } - - private class GetUpdateInfo implements Callable { - - private boolean needContentReload() { - for (int i = mContentStart, n = mContentEnd; i < n; ++i) { - if (mData[i % DATA_CACHE_SIZE] == null) return true; - } - MediaItem current = mData[mCurrentIndex % DATA_CACHE_SIZE]; - return current == null || current.getPath() != mItemPath; - } - - @Override - public UpdateInfo call() throws Exception { - // TODO: Try to load some data in first update - UpdateInfo info = new UpdateInfo(); - info.version = mSourceVersion; - info.reloadContent = needContentReload(); - info.target = mItemPath; - info.indexHint = mCurrentIndex; - info.contentStart = mContentStart; - info.contentEnd = mContentEnd; - info.size = mSize; - return info; - } - } - - private class UpdateContent implements Callable { - UpdateInfo mUpdateInfo; - - public UpdateContent(UpdateInfo updateInfo) { - mUpdateInfo = updateInfo; - } - - @Override - public Void call() throws Exception { - UpdateInfo info = mUpdateInfo; - mSourceVersion = info.version; - - if (info.size != mSize) { - mSize = info.size; - if (mContentEnd > mSize) mContentEnd = mSize; - if (mActiveEnd > mSize) mActiveEnd = mSize; - } - - mCurrentIndex = info.indexHint; - updateSlidingWindow(); - - if (info.items != null) { - int start = Math.max(info.contentStart, mContentStart); - int end = Math.min(info.contentStart + info.items.size(), mContentEnd); - int dataIndex = start % DATA_CACHE_SIZE; - for (int i = start; i < end; ++i) { - mData[dataIndex] = info.items.get(i - info.contentStart); - if (++dataIndex == DATA_CACHE_SIZE) dataIndex = 0; - } - } - - // update mItemPath - MediaItem current = mData[mCurrentIndex % DATA_CACHE_SIZE]; - mItemPath = current == null ? null : current.getPath(); - - updateImageCache(); - updateTileProvider(); - updateImageRequests(); - - if (mDataListener != null) { - mDataListener.onPhotoChanged(mCurrentIndex, mItemPath); - } - - fireDataChange(); - return null; - } - } - - private class ReloadTask extends Thread { - private volatile boolean mActive = true; - private volatile boolean mDirty = true; - - private boolean mIsLoading = false; - - private void updateLoading(boolean loading) { - if (mIsLoading == loading) return; - mIsLoading = loading; - mMainHandler.sendEmptyMessage(loading ? MSG_LOAD_START : MSG_LOAD_FINISH); - } - - @Override - public void run() { - while (mActive) { - synchronized (this) { - if (!mDirty && mActive) { - updateLoading(false); - Utils.waitWithoutInterrupt(this); - continue; - } - } - mDirty = false; - UpdateInfo info = executeAndWait(new GetUpdateInfo()); - updateLoading(true); - long version = mSource.reload(); - if (info.version != version) { - info.reloadContent = true; - info.size = mSource.getMediaItemCount(); - } - if (!info.reloadContent) continue; - info.items = mSource.getMediaItem( - info.contentStart, info.contentEnd); - - int index = MediaSet.INDEX_NOT_FOUND; - - // First try to focus on the given hint path if there is one. - if (mFocusHintPath != null) { - index = findIndexOfPathInCache(info, mFocusHintPath); - mFocusHintPath = null; - } - - // Otherwise try to see if the currently focused item can be found. - if (index == MediaSet.INDEX_NOT_FOUND) { - MediaItem item = findCurrentMediaItem(info); - if (item != null && item.getPath() == info.target) { - index = info.indexHint; - } else { - index = findIndexOfTarget(info); - } - } - - // The image has been deleted. Focus on the next image (keep - // mCurrentIndex unchanged) or the previous image (decrease - // mCurrentIndex by 1). In page mode we want to see the next - // image, so we focus on the next one. In film mode we want the - // later images to shift left to fill the empty space, so we - // focus on the previous image (so it will not move). In any - // case the index needs to be limited to [0, mSize). - if (index == MediaSet.INDEX_NOT_FOUND) { - index = info.indexHint; - int focusHintDirection = mFocusHintDirection; - if (index == (mCameraIndex + 1)) { - focusHintDirection = FOCUS_HINT_NEXT; - } - if (focusHintDirection == FOCUS_HINT_PREVIOUS - && index > 0) { - index--; - } - } - - // Don't change index if mSize == 0 - if (mSize > 0) { - if (index >= mSize) index = mSize - 1; - } - - info.indexHint = index; - - executeAndWait(new UpdateContent(info)); - } - } - - public synchronized void notifyDirty() { - mDirty = true; - notifyAll(); - } - - public synchronized void terminate() { - mActive = false; - notifyAll(); - } - - private MediaItem findCurrentMediaItem(UpdateInfo info) { - ArrayList items = info.items; - int index = info.indexHint - info.contentStart; - return index < 0 || index >= items.size() ? null : items.get(index); - } - - private int findIndexOfTarget(UpdateInfo info) { - if (info.target == null) return info.indexHint; - ArrayList items = info.items; - - // First, try to find the item in the data just loaded - if (items != null) { - int i = findIndexOfPathInCache(info, info.target); - if (i != MediaSet.INDEX_NOT_FOUND) return i; - } - - // Not found, find it in mSource. - return mSource.getIndexOfItem(info.target, info.indexHint); - } - - private int findIndexOfPathInCache(UpdateInfo info, Path path) { - ArrayList items = info.items; - for (int i = 0, n = items.size(); i < n; ++i) { - MediaItem item = items.get(i); - if (item != null && item.getPath() == path) { - return i + info.contentStart; - } - } - return MediaSet.INDEX_NOT_FOUND; - } - } -} diff --git a/src/com/android/gallery3d/app/PhotoPage.java b/src/com/android/gallery3d/app/PhotoPage.java deleted file mode 100644 index 7a71e9109..000000000 --- a/src/com/android/gallery3d/app/PhotoPage.java +++ /dev/null @@ -1,1571 +0,0 @@ -/* - * 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.gallery3d.app; - -import android.annotation.TargetApi; -import android.app.ActionBar.OnMenuVisibilityListener; -import android.app.Activity; -import android.content.ActivityNotFoundException; -import android.content.Context; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.content.res.Configuration; -import android.graphics.Rect; -import android.net.Uri; -import android.nfc.NfcAdapter; -import android.nfc.NfcAdapter.CreateBeamUrisCallback; -import android.nfc.NfcEvent; -import android.os.Bundle; -import android.os.Handler; -import android.os.Message; -import android.os.SystemClock; -import android.view.Menu; -import android.view.MenuItem; -import android.widget.RelativeLayout; -import android.widget.ShareActionProvider; -import android.widget.Toast; - -import com.android.camera.CameraActivity; -import com.android.camera.ProxyLauncher; -import com.android.gallery3d.R; -import com.android.gallery3d.common.ApiHelper; -import com.android.gallery3d.data.ComboAlbum; -import com.android.gallery3d.data.DataManager; -import com.android.gallery3d.data.FilterDeleteSet; -import com.android.gallery3d.data.FilterSource; -import com.android.gallery3d.data.LocalImage; -import com.android.gallery3d.data.MediaDetails; -import com.android.gallery3d.data.MediaItem; -import com.android.gallery3d.data.MediaObject; -import com.android.gallery3d.data.MediaObject.PanoramaSupportCallback; -import com.android.gallery3d.data.MediaSet; -import com.android.gallery3d.data.Path; -import com.android.gallery3d.data.SecureAlbum; -import com.android.gallery3d.data.SecureSource; -import com.android.gallery3d.data.SnailAlbum; -import com.android.gallery3d.data.SnailItem; -import com.android.gallery3d.data.SnailSource; -import com.android.gallery3d.filtershow.FilterShowActivity; -import com.android.gallery3d.filtershow.crop.CropActivity; -import com.android.gallery3d.picasasource.PicasaSource; -import com.android.gallery3d.ui.DetailsHelper; -import com.android.gallery3d.ui.DetailsHelper.CloseListener; -import com.android.gallery3d.ui.DetailsHelper.DetailsSource; -import com.android.gallery3d.ui.GLView; -import com.android.gallery3d.ui.MenuExecutor; -import com.android.gallery3d.ui.PhotoView; -import com.android.gallery3d.ui.SelectionManager; -import com.android.gallery3d.ui.SynchronizedHandler; -import com.android.gallery3d.util.GalleryUtils; -import com.android.gallery3d.util.UsageStatistics; - -public abstract class PhotoPage extends ActivityState implements - PhotoView.Listener, AppBridge.Server, ShareActionProvider.OnShareTargetSelectedListener, - PhotoPageBottomControls.Delegate, GalleryActionBar.OnAlbumModeSelectedListener { - private static final String TAG = "PhotoPage"; - - private static final int MSG_HIDE_BARS = 1; - private static final int MSG_ON_FULL_SCREEN_CHANGED = 4; - private static final int MSG_UPDATE_ACTION_BAR = 5; - private static final int MSG_UNFREEZE_GLROOT = 6; - private static final int MSG_WANT_BARS = 7; - private static final int MSG_REFRESH_BOTTOM_CONTROLS = 8; - private static final int MSG_ON_CAMERA_CENTER = 9; - private static final int MSG_ON_PICTURE_CENTER = 10; - private static final int MSG_REFRESH_IMAGE = 11; - private static final int MSG_UPDATE_PHOTO_UI = 12; - private static final int MSG_UPDATE_PROGRESS = 13; - private static final int MSG_UPDATE_DEFERRED = 14; - private static final int MSG_UPDATE_SHARE_URI = 15; - private static final int MSG_UPDATE_PANORAMA_UI = 16; - - private static final int HIDE_BARS_TIMEOUT = 3500; - private static final int UNFREEZE_GLROOT_TIMEOUT = 250; - - private static final int REQUEST_SLIDESHOW = 1; - private static final int REQUEST_CROP = 2; - private static final int REQUEST_CROP_PICASA = 3; - private static final int REQUEST_EDIT = 4; - private static final int REQUEST_PLAY_VIDEO = 5; - private static final int REQUEST_TRIM = 6; - - public static final String KEY_MEDIA_SET_PATH = "media-set-path"; - public static final String KEY_MEDIA_ITEM_PATH = "media-item-path"; - public static final String KEY_INDEX_HINT = "index-hint"; - public static final String KEY_OPEN_ANIMATION_RECT = "open-animation-rect"; - public static final String KEY_APP_BRIDGE = "app-bridge"; - public static final String KEY_TREAT_BACK_AS_UP = "treat-back-as-up"; - public static final String KEY_START_IN_FILMSTRIP = "start-in-filmstrip"; - public static final String KEY_RETURN_INDEX_HINT = "return-index-hint"; - public static final String KEY_SHOW_WHEN_LOCKED = "show_when_locked"; - public static final String KEY_IN_CAMERA_ROLL = "in_camera_roll"; - - public static final String KEY_ALBUMPAGE_TRANSITION = "albumpage-transition"; - public static final int MSG_ALBUMPAGE_NONE = 0; - public static final int MSG_ALBUMPAGE_STARTED = 1; - public static final int MSG_ALBUMPAGE_RESUMED = 2; - public static final int MSG_ALBUMPAGE_PICKED = 4; - - public static final String ACTION_NEXTGEN_EDIT = "action_nextgen_edit"; - public static final String ACTION_SIMPLE_EDIT = "action_simple_edit"; - - private GalleryApp mApplication; - private SelectionManager mSelectionManager; - - private PhotoView mPhotoView; - private PhotoPage.Model mModel; - private DetailsHelper mDetailsHelper; - private boolean mShowDetails; - - // mMediaSet could be null if there is no KEY_MEDIA_SET_PATH supplied. - // E.g., viewing a photo in gmail attachment - private FilterDeleteSet mMediaSet; - - // The mediaset used by camera launched from secure lock screen. - private SecureAlbum mSecureAlbum; - - private int mCurrentIndex = 0; - private Handler mHandler; - private boolean mShowBars = true; - private volatile boolean mActionBarAllowed = true; - private GalleryActionBar mActionBar; - private boolean mIsMenuVisible; - private boolean mHaveImageEditor; - private PhotoPageBottomControls mBottomControls; - private PhotoPageProgressBar mProgressBar; - private MediaItem mCurrentPhoto = null; - private MenuExecutor mMenuExecutor; - private boolean mIsActive; - private boolean mShowSpinner; - private String mSetPathString; - // This is the original mSetPathString before adding the camera preview item. - private String mOriginalSetPathString; - private AppBridge mAppBridge; - private SnailItem mScreenNailItem; - private SnailAlbum mScreenNailSet; - private OrientationManager mOrientationManager; - private boolean mTreatBackAsUp; - private boolean mStartInFilmstrip; - private boolean mHasCameraScreennailOrPlaceholder = false; - private boolean mRecenterCameraOnResume = true; - - // These are only valid after the panorama callback - private boolean mIsPanorama; - private boolean mIsPanorama360; - - private long mCameraSwitchCutoff = 0; - private boolean mSkipUpdateCurrentPhoto = false; - private static final long CAMERA_SWITCH_CUTOFF_THRESHOLD_MS = 300; - - private static final long DEFERRED_UPDATE_MS = 250; - private boolean mDeferredUpdateWaiting = false; - private long mDeferUpdateUntil = Long.MAX_VALUE; - - // The item that is deleted (but it can still be undeleted before commiting) - private Path mDeletePath; - private boolean mDeleteIsFocus; // whether the deleted item was in focus - - private Uri[] mNfcPushUris = new Uri[1]; - - private final MyMenuVisibilityListener mMenuVisibilityListener = - new MyMenuVisibilityListener(); - private UpdateProgressListener mProgressListener; - - private final PanoramaSupportCallback mUpdatePanoramaMenuItemsCallback = new PanoramaSupportCallback() { - @Override - public void panoramaInfoAvailable(MediaObject mediaObject, boolean isPanorama, - boolean isPanorama360) { - if (mediaObject == mCurrentPhoto) { - mHandler.obtainMessage(MSG_UPDATE_PANORAMA_UI, isPanorama360 ? 1 : 0, 0, - mediaObject).sendToTarget(); - } - } - }; - - private final PanoramaSupportCallback mRefreshBottomControlsCallback = new PanoramaSupportCallback() { - @Override - public void panoramaInfoAvailable(MediaObject mediaObject, boolean isPanorama, - boolean isPanorama360) { - if (mediaObject == mCurrentPhoto) { - mHandler.obtainMessage(MSG_REFRESH_BOTTOM_CONTROLS, isPanorama ? 1 : 0, isPanorama360 ? 1 : 0, - mediaObject).sendToTarget(); - } - } - }; - - private final PanoramaSupportCallback mUpdateShareURICallback = new PanoramaSupportCallback() { - @Override - public void panoramaInfoAvailable(MediaObject mediaObject, boolean isPanorama, - boolean isPanorama360) { - if (mediaObject == mCurrentPhoto) { - mHandler.obtainMessage(MSG_UPDATE_SHARE_URI, isPanorama360 ? 1 : 0, 0, mediaObject) - .sendToTarget(); - } - } - }; - - public static interface Model extends PhotoView.Model { - public void resume(); - public void pause(); - public boolean isEmpty(); - public void setCurrentPhoto(Path path, int indexHint); - } - - private class MyMenuVisibilityListener implements OnMenuVisibilityListener { - @Override - public void onMenuVisibilityChanged(boolean isVisible) { - mIsMenuVisible = isVisible; - refreshHidingMessage(); - } - } - - private class UpdateProgressListener implements StitchingChangeListener { - - @Override - public void onStitchingResult(Uri uri) { - sendUpdate(uri, MSG_REFRESH_IMAGE); - } - - @Override - public void onStitchingQueued(Uri uri) { - sendUpdate(uri, MSG_UPDATE_PROGRESS); - } - - @Override - public void onStitchingProgress(Uri uri, final int progress) { - sendUpdate(uri, MSG_UPDATE_PROGRESS); - } - - private void sendUpdate(Uri uri, int message) { - MediaObject currentPhoto = mCurrentPhoto; - boolean isCurrentPhoto = currentPhoto instanceof LocalImage - && currentPhoto.getContentUri().equals(uri); - if (isCurrentPhoto) { - mHandler.sendEmptyMessage(message); - } - } - }; - - @Override - protected int getBackgroundColorId() { - return R.color.photo_background; - } - - private final GLView mRootPane = new GLView() { - @Override - protected void onLayout( - boolean changed, int left, int top, int right, int bottom) { - mPhotoView.layout(0, 0, right - left, bottom - top); - if (mShowDetails) { - mDetailsHelper.layout(left, mActionBar.getHeight(), right, bottom); - } - } - }; - - @Override - public void onCreate(Bundle data, Bundle restoreState) { - super.onCreate(data, restoreState); - mActionBar = mActivity.getGalleryActionBar(); - mSelectionManager = new SelectionManager(mActivity, false); - mMenuExecutor = new MenuExecutor(mActivity, mSelectionManager); - - mPhotoView = new PhotoView(mActivity); - mPhotoView.setListener(this); - mRootPane.addComponent(mPhotoView); - mApplication = (GalleryApp) ((Activity) mActivity).getApplication(); - mOrientationManager = mActivity.getOrientationManager(); - mActivity.getGLRoot().setOrientationSource(mOrientationManager); - - mHandler = new SynchronizedHandler(mActivity.getGLRoot()) { - @Override - public void handleMessage(Message message) { - switch (message.what) { - case MSG_HIDE_BARS: { - hideBars(); - break; - } - case MSG_REFRESH_BOTTOM_CONTROLS: { - if (mCurrentPhoto == message.obj && mBottomControls != null) { - mIsPanorama = message.arg1 == 1; - mIsPanorama360 = message.arg2 == 1; - mBottomControls.refresh(); - } - break; - } - case MSG_ON_FULL_SCREEN_CHANGED: { - if (mAppBridge != null) { - mAppBridge.onFullScreenChanged(message.arg1 == 1); - } - break; - } - case MSG_UPDATE_ACTION_BAR: { - updateBars(); - break; - } - case MSG_WANT_BARS: { - wantBars(); - break; - } - case MSG_UNFREEZE_GLROOT: { - mActivity.getGLRoot().unfreeze(); - break; - } - case MSG_UPDATE_DEFERRED: { - long nextUpdate = mDeferUpdateUntil - SystemClock.uptimeMillis(); - if (nextUpdate <= 0) { - mDeferredUpdateWaiting = false; - updateUIForCurrentPhoto(); - } else { - mHandler.sendEmptyMessageDelayed(MSG_UPDATE_DEFERRED, nextUpdate); - } - break; - } - case MSG_ON_CAMERA_CENTER: { - mSkipUpdateCurrentPhoto = false; - boolean stayedOnCamera = false; - if (!mPhotoView.getFilmMode()) { - stayedOnCamera = true; - } else if (SystemClock.uptimeMillis() < mCameraSwitchCutoff && - mMediaSet.getMediaItemCount() > 1) { - mPhotoView.switchToImage(1); - } else { - if (mAppBridge != null) mPhotoView.setFilmMode(false); - stayedOnCamera = true; - } - - if (stayedOnCamera) { - if (mAppBridge == null && mMediaSet.getTotalMediaItemCount() > 1) { - launchCamera(); - /* We got here by swiping from photo 1 to the - placeholder, so make it be the thing that - is in focus when the user presses back from - the camera app */ - mPhotoView.switchToImage(1); - } else { - updateBars(); - updateCurrentPhoto(mModel.getMediaItem(0)); - } - } - break; - } - case MSG_ON_PICTURE_CENTER: { - if (!mPhotoView.getFilmMode() && mCurrentPhoto != null - && (mCurrentPhoto.getSupportedOperations() & MediaObject.SUPPORT_ACTION) != 0) { - mPhotoView.setFilmMode(true); - } - break; - } - case MSG_REFRESH_IMAGE: { - final MediaItem photo = mCurrentPhoto; - mCurrentPhoto = null; - updateCurrentPhoto(photo); - break; - } - case MSG_UPDATE_PHOTO_UI: { - updateUIForCurrentPhoto(); - break; - } - case MSG_UPDATE_PROGRESS: { - updateProgressBar(); - break; - } - case MSG_UPDATE_SHARE_URI: { - if (mCurrentPhoto == message.obj) { - boolean isPanorama360 = message.arg1 != 0; - Uri contentUri = mCurrentPhoto.getContentUri(); - Intent panoramaIntent = null; - if (isPanorama360) { - panoramaIntent = createSharePanoramaIntent(contentUri); - } - Intent shareIntent = createShareIntent(mCurrentPhoto); - - mActionBar.setShareIntents(panoramaIntent, shareIntent, PhotoPage.this); - setNfcBeamPushUri(contentUri); - } - break; - } - case MSG_UPDATE_PANORAMA_UI: { - if (mCurrentPhoto == message.obj) { - boolean isPanorama360 = message.arg1 != 0; - updatePanoramaUI(isPanorama360); - } - break; - } - default: throw new AssertionError(message.what); - } - } - }; - - mSetPathString = data.getString(KEY_MEDIA_SET_PATH); - mOriginalSetPathString = mSetPathString; - setupNfcBeamPush(); - String itemPathString = data.getString(KEY_MEDIA_ITEM_PATH); - Path itemPath = itemPathString != null ? - Path.fromString(data.getString(KEY_MEDIA_ITEM_PATH)) : - null; - mTreatBackAsUp = data.getBoolean(KEY_TREAT_BACK_AS_UP, false); - mStartInFilmstrip = data.getBoolean(KEY_START_IN_FILMSTRIP, false); - boolean inCameraRoll = data.getBoolean(KEY_IN_CAMERA_ROLL, false); - mCurrentIndex = data.getInt(KEY_INDEX_HINT, 0); - if (mSetPathString != null) { - mShowSpinner = true; - mAppBridge = (AppBridge) data.getParcelable(KEY_APP_BRIDGE); - if (mAppBridge != null) { - mShowBars = false; - mHasCameraScreennailOrPlaceholder = true; - mAppBridge.setServer(this); - - // Get the ScreenNail from AppBridge and register it. - int id = SnailSource.newId(); - Path screenNailSetPath = SnailSource.getSetPath(id); - Path screenNailItemPath = SnailSource.getItemPath(id); - mScreenNailSet = (SnailAlbum) mActivity.getDataManager() - .getMediaObject(screenNailSetPath); - mScreenNailItem = (SnailItem) mActivity.getDataManager() - .getMediaObject(screenNailItemPath); - mScreenNailItem.setScreenNail(mAppBridge.attachScreenNail()); - - if (data.getBoolean(KEY_SHOW_WHEN_LOCKED, false)) { - // Set the flag to be on top of the lock screen. - mFlags |= FLAG_SHOW_WHEN_LOCKED; - } - - // Don't display "empty album" action item for capture intents. - if (!mSetPathString.equals("/local/all/0")) { - // Check if the path is a secure album. - if (SecureSource.isSecurePath(mSetPathString)) { - mSecureAlbum = (SecureAlbum) mActivity.getDataManager() - .getMediaSet(mSetPathString); - mShowSpinner = false; - } - mSetPathString = "/filter/empty/{"+mSetPathString+"}"; - } - - // Combine the original MediaSet with the one for ScreenNail - // from AppBridge. - mSetPathString = "/combo/item/{" + screenNailSetPath + - "," + mSetPathString + "}"; - - // Start from the screen nail. - itemPath = screenNailItemPath; - } else if (inCameraRoll && GalleryUtils.isCameraAvailable(mActivity)) { - mSetPathString = "/combo/item/{" + FilterSource.FILTER_CAMERA_SHORTCUT + - "," + mSetPathString + "}"; - mCurrentIndex++; - mHasCameraScreennailOrPlaceholder = true; - } - - MediaSet originalSet = mActivity.getDataManager() - .getMediaSet(mSetPathString); - if (mHasCameraScreennailOrPlaceholder && originalSet instanceof ComboAlbum) { - // Use the name of the camera album rather than the default - // ComboAlbum behavior - ((ComboAlbum) originalSet).useNameOfChild(1); - } - mSelectionManager.setSourceMediaSet(originalSet); - mSetPathString = "/filter/delete/{" + mSetPathString + "}"; - mMediaSet = (FilterDeleteSet) mActivity.getDataManager() - .getMediaSet(mSetPathString); - if (mMediaSet == null) { - Log.w(TAG, "failed to restore " + mSetPathString); - } - if (itemPath == null) { - int mediaItemCount = mMediaSet.getMediaItemCount(); - if (mediaItemCount > 0) { - if (mCurrentIndex >= mediaItemCount) mCurrentIndex = 0; - itemPath = mMediaSet.getMediaItem(mCurrentIndex, 1) - .get(0).getPath(); - } else { - // Bail out, PhotoPage can't load on an empty album - return; - } - } - PhotoDataAdapter pda = new PhotoDataAdapter( - mActivity, mPhotoView, mMediaSet, itemPath, mCurrentIndex, - mAppBridge == null ? -1 : 0, - mAppBridge == null ? false : mAppBridge.isPanorama(), - mAppBridge == null ? false : mAppBridge.isStaticCamera()); - mModel = pda; - mPhotoView.setModel(mModel); - - pda.setDataListener(new PhotoDataAdapter.DataListener() { - - @Override - public void onPhotoChanged(int index, Path item) { - int oldIndex = mCurrentIndex; - mCurrentIndex = index; - - if (mHasCameraScreennailOrPlaceholder) { - if (mCurrentIndex > 0) { - mSkipUpdateCurrentPhoto = false; - } - - if (oldIndex == 0 && mCurrentIndex > 0 - && !mPhotoView.getFilmMode()) { - mPhotoView.setFilmMode(true); - if (mAppBridge != null) { - UsageStatistics.onEvent("CameraToFilmstrip", - UsageStatistics.TRANSITION_SWIPE, null); - } - } else if (oldIndex == 2 && mCurrentIndex == 1) { - mCameraSwitchCutoff = SystemClock.uptimeMillis() + - CAMERA_SWITCH_CUTOFF_THRESHOLD_MS; - mPhotoView.stopScrolling(); - } else if (oldIndex >= 1 && mCurrentIndex == 0) { - mPhotoView.setWantPictureCenterCallbacks(true); - mSkipUpdateCurrentPhoto = true; - } - } - if (!mSkipUpdateCurrentPhoto) { - if (item != null) { - MediaItem photo = mModel.getMediaItem(0); - if (photo != null) updateCurrentPhoto(photo); - } - updateBars(); - } - // Reset the timeout for the bars after a swipe - refreshHidingMessage(); - } - - @Override - public void onLoadingFinished(boolean loadingFailed) { - if (!mModel.isEmpty()) { - MediaItem photo = mModel.getMediaItem(0); - if (photo != null) updateCurrentPhoto(photo); - } else if (mIsActive) { - // We only want to finish the PhotoPage if there is no - // deletion that the user can undo. - if (mMediaSet.getNumberOfDeletions() == 0) { - mActivity.getStateManager().finishState( - PhotoPage.this); - } - } - } - - @Override - public void onLoadingStarted() { - } - }); - } else { - // Get default media set by the URI - MediaItem mediaItem = (MediaItem) - mActivity.getDataManager().getMediaObject(itemPath); - mModel = new SinglePhotoDataAdapter(mActivity, mPhotoView, mediaItem); - mPhotoView.setModel(mModel); - updateCurrentPhoto(mediaItem); - mShowSpinner = false; - } - - mPhotoView.setFilmMode(mStartInFilmstrip && mMediaSet.getMediaItemCount() > 1); - RelativeLayout galleryRoot = (RelativeLayout) ((Activity) mActivity) - .findViewById(mAppBridge != null ? R.id.content : R.id.gallery_root); - if (galleryRoot != null) { - if (mSecureAlbum == null) { - mBottomControls = new PhotoPageBottomControls(this, mActivity, galleryRoot); - } - StitchingProgressManager progressManager = mApplication.getStitchingProgressManager(); - if (progressManager != null) { - mProgressBar = new PhotoPageProgressBar(mActivity, galleryRoot); - mProgressListener = new UpdateProgressListener(); - progressManager.addChangeListener(mProgressListener); - if (mSecureAlbum != null) { - progressManager.addChangeListener(mSecureAlbum); - } - } - } - } - - @Override - public void onPictureCenter(boolean isCamera) { - isCamera = isCamera || (mHasCameraScreennailOrPlaceholder && mAppBridge == null); - mPhotoView.setWantPictureCenterCallbacks(false); - mHandler.removeMessages(MSG_ON_CAMERA_CENTER); - mHandler.removeMessages(MSG_ON_PICTURE_CENTER); - mHandler.sendEmptyMessage(isCamera ? MSG_ON_CAMERA_CENTER : MSG_ON_PICTURE_CENTER); - } - - @Override - public boolean canDisplayBottomControls() { - return mIsActive && !mPhotoView.canUndo(); - } - - @Override - public boolean canDisplayBottomControl(int control) { - if (mCurrentPhoto == null) { - return false; - } - switch(control) { - case R.id.photopage_bottom_control_edit: - return mHaveImageEditor && mShowBars - && !mPhotoView.getFilmMode() - && (mCurrentPhoto.getSupportedOperations() & MediaItem.SUPPORT_EDIT) != 0 - && mCurrentPhoto.getMediaType() == MediaObject.MEDIA_TYPE_IMAGE; - case R.id.photopage_bottom_control_panorama: - return mIsPanorama; - case R.id.photopage_bottom_control_tiny_planet: - return mHaveImageEditor && mShowBars - && mIsPanorama360 && !mPhotoView.getFilmMode(); - default: - return false; - } - } - - @Override - public void onBottomControlClicked(int control) { - switch(control) { - case R.id.photopage_bottom_control_edit: - launchPhotoEditor(); - return; - case R.id.photopage_bottom_control_panorama: - mActivity.getPanoramaViewHelper() - .showPanorama(mCurrentPhoto.getContentUri()); - return; - case R.id.photopage_bottom_control_tiny_planet: - launchTinyPlanet(); - return; - default: - return; - } - } - - @TargetApi(ApiHelper.VERSION_CODES.JELLY_BEAN) - private void setupNfcBeamPush() { - if (!ApiHelper.HAS_SET_BEAM_PUSH_URIS) return; - - NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mActivity); - if (adapter != null) { - adapter.setBeamPushUris(null, mActivity); - adapter.setBeamPushUrisCallback(new CreateBeamUrisCallback() { - @Override - public Uri[] createBeamUris(NfcEvent event) { - return mNfcPushUris; - } - }, mActivity); - } - } - - private void setNfcBeamPushUri(Uri uri) { - mNfcPushUris[0] = uri; - } - - private static Intent createShareIntent(MediaObject mediaObject) { - int type = mediaObject.getMediaType(); - return new Intent(Intent.ACTION_SEND) - .setType(MenuExecutor.getMimeType(type)) - .putExtra(Intent.EXTRA_STREAM, mediaObject.getContentUri()) - .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - } - - private static Intent createSharePanoramaIntent(Uri contentUri) { - return new Intent(Intent.ACTION_SEND) - .setType(GalleryUtils.MIME_TYPE_PANORAMA360) - .putExtra(Intent.EXTRA_STREAM, contentUri) - .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - } - - private void overrideTransitionToEditor() { - ((Activity) mActivity).overridePendingTransition(android.R.anim.fade_in, - android.R.anim.fade_out); - } - - private void launchTinyPlanet() { - // Deep link into tiny planet - MediaItem current = mModel.getMediaItem(0); - Intent intent = new Intent(FilterShowActivity.TINY_PLANET_ACTION); - intent.setClass(mActivity, FilterShowActivity.class); - intent.setDataAndType(current.getContentUri(), current.getMimeType()) - .setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - intent.putExtra(FilterShowActivity.LAUNCH_FULLSCREEN, - mActivity.isFullscreen()); - mActivity.startActivityForResult(intent, REQUEST_EDIT); - overrideTransitionToEditor(); - } - - private void launchCamera() { - Intent intent = new Intent(mActivity, CameraActivity.class) - .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - mRecenterCameraOnResume = false; - mActivity.startActivity(intent); - } - - private void launchPhotoEditor() { - MediaItem current = mModel.getMediaItem(0); - if (current == null || (current.getSupportedOperations() - & MediaObject.SUPPORT_EDIT) == 0) { - return; - } - - Intent intent = new Intent(ACTION_NEXTGEN_EDIT); - - intent.setDataAndType(current.getContentUri(), current.getMimeType()) - .setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - if (mActivity.getPackageManager() - .queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY).size() == 0) { - intent.setAction(Intent.ACTION_EDIT); - } - intent.putExtra(FilterShowActivity.LAUNCH_FULLSCREEN, - mActivity.isFullscreen()); - ((Activity) mActivity).startActivityForResult(Intent.createChooser(intent, null), - REQUEST_EDIT); - overrideTransitionToEditor(); - } - - private void launchSimpleEditor() { - MediaItem current = mModel.getMediaItem(0); - if (current == null || (current.getSupportedOperations() - & MediaObject.SUPPORT_EDIT) == 0) { - return; - } - - Intent intent = new Intent(ACTION_SIMPLE_EDIT); - - intent.setDataAndType(current.getContentUri(), current.getMimeType()) - .setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - if (mActivity.getPackageManager() - .queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY).size() == 0) { - intent.setAction(Intent.ACTION_EDIT); - } - intent.putExtra(FilterShowActivity.LAUNCH_FULLSCREEN, - mActivity.isFullscreen()); - ((Activity) mActivity).startActivityForResult(Intent.createChooser(intent, null), - REQUEST_EDIT); - overrideTransitionToEditor(); - } - - private void requestDeferredUpdate() { - mDeferUpdateUntil = SystemClock.uptimeMillis() + DEFERRED_UPDATE_MS; - if (!mDeferredUpdateWaiting) { - mDeferredUpdateWaiting = true; - mHandler.sendEmptyMessageDelayed(MSG_UPDATE_DEFERRED, DEFERRED_UPDATE_MS); - } - } - - private void updateUIForCurrentPhoto() { - if (mCurrentPhoto == null) return; - - // If by swiping or deletion the user ends up on an action item - // and zoomed in, zoom out so that the context of the action is - // more clear - if ((mCurrentPhoto.getSupportedOperations() & MediaObject.SUPPORT_ACTION) != 0 - && !mPhotoView.getFilmMode()) { - mPhotoView.setWantPictureCenterCallbacks(true); - } - - updateMenuOperations(); - refreshBottomControlsWhenReady(); - if (mShowDetails) { - mDetailsHelper.reloadDetails(); - } - if ((mSecureAlbum == null) - && (mCurrentPhoto.getSupportedOperations() & MediaItem.SUPPORT_SHARE) != 0) { - mCurrentPhoto.getPanoramaSupport(mUpdateShareURICallback); - } - updateProgressBar(); - } - - private void updateCurrentPhoto(MediaItem photo) { - if (mCurrentPhoto == photo) return; - mCurrentPhoto = photo; - if (mPhotoView.getFilmMode()) { - requestDeferredUpdate(); - } else { - updateUIForCurrentPhoto(); - } - } - - private void updateProgressBar() { - if (mProgressBar != null) { - mProgressBar.hideProgress(); - StitchingProgressManager progressManager = mApplication.getStitchingProgressManager(); - if (progressManager != null && mCurrentPhoto instanceof LocalImage) { - Integer progress = progressManager.getProgress(mCurrentPhoto.getContentUri()); - if (progress != null) { - mProgressBar.setProgress(progress); - } - } - } - } - - private void updateMenuOperations() { - Menu menu = mActionBar.getMenu(); - - // it could be null if onCreateActionBar has not been called yet - if (menu == null) return; - - MenuItem item = menu.findItem(R.id.action_slideshow); - if (item != null) { - item.setVisible((mSecureAlbum == null) && canDoSlideShow()); - } - if (mCurrentPhoto == null) return; - - int supportedOperations = mCurrentPhoto.getSupportedOperations(); - if (mSecureAlbum != null) { - supportedOperations &= MediaObject.SUPPORT_DELETE; - } else { - mCurrentPhoto.getPanoramaSupport(mUpdatePanoramaMenuItemsCallback); - if (!mHaveImageEditor) { - supportedOperations &= ~MediaObject.SUPPORT_EDIT; - } - } - MenuExecutor.updateMenuOperation(menu, supportedOperations); - } - - private boolean canDoSlideShow() { - if (mMediaSet == null || mCurrentPhoto == null) { - return false; - } - if (mCurrentPhoto.getMediaType() != MediaObject.MEDIA_TYPE_IMAGE) { - return false; - } - return true; - } - - ////////////////////////////////////////////////////////////////////////// - // Action Bar show/hide management - ////////////////////////////////////////////////////////////////////////// - - private void showBars() { - if (mShowBars) return; - mShowBars = true; - mOrientationManager.unlockOrientation(); - mActionBar.show(); - mActivity.getGLRoot().setLightsOutMode(false); - refreshHidingMessage(); - refreshBottomControlsWhenReady(); - } - - private void hideBars() { - if (!mShowBars) return; - mShowBars = false; - mActionBar.hide(); - mActivity.getGLRoot().setLightsOutMode(true); - mHandler.removeMessages(MSG_HIDE_BARS); - refreshBottomControlsWhenReady(); - } - - private void refreshHidingMessage() { - mHandler.removeMessages(MSG_HIDE_BARS); - if (!mIsMenuVisible && !mPhotoView.getFilmMode()) { - mHandler.sendEmptyMessageDelayed(MSG_HIDE_BARS, HIDE_BARS_TIMEOUT); - } - } - - private boolean canShowBars() { - // No bars if we are showing camera preview. - if (mAppBridge != null && mCurrentIndex == 0 - && !mPhotoView.getFilmMode()) return false; - - // No bars if it's not allowed. - if (!mActionBarAllowed) return false; - - Configuration config = mActivity.getResources().getConfiguration(); - if (config.touchscreen == Configuration.TOUCHSCREEN_NOTOUCH) { - return false; - } - - return true; - } - - private void wantBars() { - if (canShowBars()) showBars(); - } - - private void toggleBars() { - if (mShowBars) { - hideBars(); - } else { - if (canShowBars()) showBars(); - } - } - - private void updateBars() { - if (!canShowBars()) { - hideBars(); - } - } - - @Override - protected void onBackPressed() { - if (mShowDetails) { - hideDetails(); - } else if (mAppBridge == null || !switchWithCaptureAnimation(-1)) { - // We are leaving this page. Set the result now. - setResult(); - if (mStartInFilmstrip && !mPhotoView.getFilmMode()) { - mPhotoView.setFilmMode(true); - } else if (mTreatBackAsUp) { - onUpPressed(); - } else { - super.onBackPressed(); - } - } - } - - private void onUpPressed() { - if ((mStartInFilmstrip || mAppBridge != null) - && !mPhotoView.getFilmMode()) { - mPhotoView.setFilmMode(true); - return; - } - - if (mActivity.getStateManager().getStateCount() > 1) { - setResult(); - super.onBackPressed(); - return; - } - - if (mOriginalSetPathString == null) return; - - if (mAppBridge == null) { - // We're in view mode so set up the stacks on our own. - Bundle data = new Bundle(getData()); - data.putString(AlbumPage.KEY_MEDIA_PATH, mOriginalSetPathString); - data.putString(AlbumPage.KEY_PARENT_MEDIA_PATH, - mActivity.getDataManager().getTopSetPath( - DataManager.INCLUDE_ALL)); - mActivity.getStateManager().switchState(this, AlbumPage.class, data); - } else { - GalleryUtils.startGalleryActivity(mActivity); - } - } - - private void setResult() { - Intent result = null; - result = new Intent(); - result.putExtra(KEY_RETURN_INDEX_HINT, mCurrentIndex); - setStateResult(Activity.RESULT_OK, result); - } - - ////////////////////////////////////////////////////////////////////////// - // AppBridge.Server interface - ////////////////////////////////////////////////////////////////////////// - - @Override - public void setCameraRelativeFrame(Rect frame) { - mPhotoView.setCameraRelativeFrame(frame); - } - - @Override - public boolean switchWithCaptureAnimation(int offset) { - return mPhotoView.switchWithCaptureAnimation(offset); - } - - @Override - public void setSwipingEnabled(boolean enabled) { - mPhotoView.setSwipingEnabled(enabled); - } - - @Override - public void notifyScreenNailChanged() { - mScreenNailItem.setScreenNail(mAppBridge.attachScreenNail()); - mScreenNailSet.notifyChange(); - } - - @Override - public void addSecureAlbumItem(boolean isVideo, int id) { - mSecureAlbum.addMediaItem(isVideo, id); - } - - @Override - protected boolean onCreateActionBar(Menu menu) { - mActionBar.createActionBarMenu(R.menu.photo, menu); - mHaveImageEditor = GalleryUtils.isEditorAvailable(mActivity, "image/*"); - updateMenuOperations(); - mActionBar.setTitle(mMediaSet != null ? mMediaSet.getName() : ""); - return true; - } - - private MenuExecutor.ProgressListener mConfirmDialogListener = - new MenuExecutor.ProgressListener() { - @Override - public void onProgressUpdate(int index) {} - - @Override - public void onProgressComplete(int result) {} - - @Override - public void onConfirmDialogShown() { - mHandler.removeMessages(MSG_HIDE_BARS); - } - - @Override - public void onConfirmDialogDismissed(boolean confirmed) { - refreshHidingMessage(); - } - - @Override - public void onProgressStart() {} - }; - - private void switchToGrid() { - if (mActivity.getStateManager().hasStateClass(AlbumPage.class)) { - onUpPressed(); - } else { - if (mOriginalSetPathString == null) return; - if (mProgressBar != null) { - updateCurrentPhoto(null); - mProgressBar.hideProgress(); - } - Bundle data = new Bundle(getData()); - data.putString(AlbumPage.KEY_MEDIA_PATH, mOriginalSetPathString); - data.putString(AlbumPage.KEY_PARENT_MEDIA_PATH, - mActivity.getDataManager().getTopSetPath( - DataManager.INCLUDE_ALL)); - - // We only show cluster menu in the first AlbumPage in stack - // TODO: Enable this when running from the camera app - boolean inAlbum = mActivity.getStateManager().hasStateClass(AlbumPage.class); - data.putBoolean(AlbumPage.KEY_SHOW_CLUSTER_MENU, !inAlbum - && mAppBridge == null); - - data.putBoolean(PhotoPage.KEY_APP_BRIDGE, mAppBridge != null); - - // Account for live preview being first item - mActivity.getTransitionStore().put(KEY_RETURN_INDEX_HINT, - mAppBridge != null ? mCurrentIndex - 1 : mCurrentIndex); - - if (mHasCameraScreennailOrPlaceholder && mAppBridge != null) { - mActivity.getStateManager().startState(AlbumPage.class, data); - } else { - mActivity.getStateManager().switchState(this, AlbumPage.class, data); - } - } - } - - @Override - protected boolean onItemSelected(MenuItem item) { - if (mModel == null) return true; - refreshHidingMessage(); - MediaItem current = mModel.getMediaItem(0); - - // This is a shield for monkey when it clicks the action bar - // menu when transitioning from filmstrip to camera - if (current instanceof SnailItem) return true; - // TODO: We should check the current photo against the MediaItem - // that the menu was initially created for. We need to fix this - // after PhotoPage being refactored. - if (current == null) { - // item is not ready, ignore - return true; - } - int currentIndex = mModel.getCurrentIndex(); - Path path = current.getPath(); - - DataManager manager = mActivity.getDataManager(); - int action = item.getItemId(); - String confirmMsg = null; - switch (action) { - case android.R.id.home: { - onUpPressed(); - return true; - } - case R.id.action_slideshow: { - Bundle data = new Bundle(); - data.putString(SlideshowPage.KEY_SET_PATH, mMediaSet.getPath().toString()); - data.putString(SlideshowPage.KEY_ITEM_PATH, path.toString()); - data.putInt(SlideshowPage.KEY_PHOTO_INDEX, currentIndex); - data.putBoolean(SlideshowPage.KEY_REPEAT, true); - mActivity.getStateManager().startStateForResult( - SlideshowPage.class, REQUEST_SLIDESHOW, data); - return true; - } - case R.id.action_crop: { - Activity activity = mActivity; - Intent intent = new Intent(CropActivity.CROP_ACTION); - intent.setClass(activity, CropActivity.class); - intent.setDataAndType(manager.getContentUri(path), current.getMimeType()) - .setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - activity.startActivityForResult(intent, PicasaSource.isPicasaImage(current) - ? REQUEST_CROP_PICASA - : REQUEST_CROP); - return true; - } - case R.id.action_trim: { - Intent intent = new Intent(mActivity, TrimVideo.class); - intent.setData(manager.getContentUri(path)); - // We need the file path to wrap this into a RandomAccessFile. - intent.putExtra(KEY_MEDIA_ITEM_PATH, current.getFilePath()); - mActivity.startActivityForResult(intent, REQUEST_TRIM); - return true; - } - case R.id.action_mute: { - MuteVideo muteVideo = new MuteVideo(current.getFilePath(), - manager.getContentUri(path), mActivity); - muteVideo.muteInBackground(); - return true; - } - case R.id.action_edit: { - launchPhotoEditor(); - return true; - } - case R.id.action_simple_edit: { - launchSimpleEditor(); - return true; - } - case R.id.action_details: { - if (mShowDetails) { - hideDetails(); - } else { - showDetails(); - } - return true; - } - case R.id.action_delete: - confirmMsg = mActivity.getResources().getQuantityString( - R.plurals.delete_selection, 1); - case R.id.action_setas: - case R.id.action_rotate_ccw: - case R.id.action_rotate_cw: - case R.id.action_show_on_map: - mSelectionManager.deSelectAll(); - mSelectionManager.toggle(path); - mMenuExecutor.onMenuClicked(item, confirmMsg, mConfirmDialogListener); - return true; - default : - return false; - } - } - - private void hideDetails() { - mShowDetails = false; - mDetailsHelper.hide(); - } - - private void showDetails() { - mShowDetails = true; - if (mDetailsHelper == null) { - mDetailsHelper = new DetailsHelper(mActivity, mRootPane, new MyDetailsSource()); - mDetailsHelper.setCloseListener(new CloseListener() { - @Override - public void onClose() { - hideDetails(); - } - }); - } - mDetailsHelper.show(); - } - - //////////////////////////////////////////////////////////////////////////// - // Callbacks from PhotoView - //////////////////////////////////////////////////////////////////////////// - @Override - public void onSingleTapUp(int x, int y) { - if (mAppBridge != null) { - if (mAppBridge.onSingleTapUp(x, y)) return; - } - - MediaItem item = mModel.getMediaItem(0); - if (item == null || item == mScreenNailItem) { - // item is not ready or it is camera preview, ignore - return; - } - - int supported = item.getSupportedOperations(); - boolean playVideo = ((supported & MediaItem.SUPPORT_PLAY) != 0); - boolean unlock = ((supported & MediaItem.SUPPORT_UNLOCK) != 0); - boolean goBack = ((supported & MediaItem.SUPPORT_BACK) != 0); - boolean launchCamera = ((supported & MediaItem.SUPPORT_CAMERA_SHORTCUT) != 0); - - if (playVideo) { - // determine if the point is at center (1/6) of the photo view. - // (The position of the "play" icon is at center (1/6) of the photo) - int w = mPhotoView.getWidth(); - int h = mPhotoView.getHeight(); - playVideo = (Math.abs(x - w / 2) * 12 <= w) - && (Math.abs(y - h / 2) * 12 <= h); - } - - if (playVideo) { - if (mSecureAlbum == null) { - playVideo(mActivity, item.getPlayUri(), item.getName()); - } else { - mActivity.getStateManager().finishState(this); - } - } else if (goBack) { - onBackPressed(); - } else if (unlock) { - Intent intent = new Intent(mActivity, Gallery.class); - intent.putExtra(Gallery.KEY_DISMISS_KEYGUARD, true); - mActivity.startActivity(intent); - } else if (launchCamera) { - launchCamera(); - } else { - toggleBars(); - } - } - - @Override - public void onActionBarAllowed(boolean allowed) { - mActionBarAllowed = allowed; - mHandler.sendEmptyMessage(MSG_UPDATE_ACTION_BAR); - } - - @Override - public void onActionBarWanted() { - mHandler.sendEmptyMessage(MSG_WANT_BARS); - } - - @Override - public void onFullScreenChanged(boolean full) { - Message m = mHandler.obtainMessage( - MSG_ON_FULL_SCREEN_CHANGED, full ? 1 : 0, 0); - m.sendToTarget(); - } - - // How we do delete/undo: - // - // When the user choose to delete a media item, we just tell the - // FilterDeleteSet to hide that item. If the user choose to undo it, we - // again tell FilterDeleteSet not to hide it. If the user choose to commit - // the deletion, we then actually delete the media item. - @Override - public void onDeleteImage(Path path, int offset) { - onCommitDeleteImage(); // commit the previous deletion - mDeletePath = path; - mDeleteIsFocus = (offset == 0); - mMediaSet.addDeletion(path, mCurrentIndex + offset); - } - - @Override - public void onUndoDeleteImage() { - if (mDeletePath == null) return; - // If the deletion was done on the focused item, we want the model to - // focus on it when it is undeleted. - if (mDeleteIsFocus) mModel.setFocusHintPath(mDeletePath); - mMediaSet.removeDeletion(mDeletePath); - mDeletePath = null; - } - - @Override - public void onCommitDeleteImage() { - if (mDeletePath == null) return; - mMenuExecutor.startSingleItemAction(R.id.action_delete, mDeletePath); - mDeletePath = null; - } - - public void playVideo(Activity activity, Uri uri, String title) { - try { - Intent intent = new Intent(Intent.ACTION_VIEW) - .setDataAndType(uri, "video/*") - .putExtra(Intent.EXTRA_TITLE, title) - .putExtra(MovieActivity.KEY_TREAT_UP_AS_BACK, true); - activity.startActivityForResult(intent, REQUEST_PLAY_VIDEO); - } catch (ActivityNotFoundException e) { - Toast.makeText(activity, activity.getString(R.string.video_err), - Toast.LENGTH_SHORT).show(); - } - } - - private void setCurrentPhotoByIntent(Intent intent) { - if (intent == null) return; - Path path = mApplication.getDataManager() - .findPathByUri(intent.getData(), intent.getType()); - if (path != null) { - Path albumPath = mApplication.getDataManager().getDefaultSetOf(path); - if (!albumPath.equalsIgnoreCase(mOriginalSetPathString)) { - // If the edited image is stored in a different album, we need - // to start a new activity state to show the new image - Bundle data = new Bundle(getData()); - data.putString(KEY_MEDIA_SET_PATH, albumPath.toString()); - data.putString(PhotoPage.KEY_MEDIA_ITEM_PATH, path.toString()); - mActivity.getStateManager().startState(SinglePhotoPage.class, data); - return; - } - mModel.setCurrentPhoto(path, mCurrentIndex); - } - } - - @Override - protected void onStateResult(int requestCode, int resultCode, Intent data) { - if (resultCode == Activity.RESULT_CANCELED) { - // This is a reset, not a canceled - return; - } - if (resultCode == ProxyLauncher.RESULT_USER_CANCELED) { - // Unmap reset vs. canceled - resultCode = Activity.RESULT_CANCELED; - } - mRecenterCameraOnResume = false; - switch (requestCode) { - case REQUEST_EDIT: - setCurrentPhotoByIntent(data); - break; - case REQUEST_CROP: - if (resultCode == Activity.RESULT_OK) { - setCurrentPhotoByIntent(data); - } - break; - case REQUEST_CROP_PICASA: { - if (resultCode == Activity.RESULT_OK) { - Context context = mActivity.getAndroidContext(); - String message = context.getString(R.string.crop_saved, - context.getString(R.string.folder_edited_online_photos)); - Toast.makeText(context, message, Toast.LENGTH_SHORT).show(); - } - break; - } - case REQUEST_SLIDESHOW: { - if (data == null) break; - String path = data.getStringExtra(SlideshowPage.KEY_ITEM_PATH); - int index = data.getIntExtra(SlideshowPage.KEY_PHOTO_INDEX, 0); - if (path != null) { - mModel.setCurrentPhoto(Path.fromString(path), index); - } - } - } - } - - @Override - public void onPause() { - super.onPause(); - mIsActive = false; - - mActivity.getGLRoot().unfreeze(); - mHandler.removeMessages(MSG_UNFREEZE_GLROOT); - - DetailsHelper.pause(); - // Hide the detail dialog on exit - if (mShowDetails) hideDetails(); - if (mModel != null) { - mModel.pause(); - } - mPhotoView.pause(); - mHandler.removeMessages(MSG_HIDE_BARS); - mHandler.removeMessages(MSG_REFRESH_BOTTOM_CONTROLS); - refreshBottomControlsWhenReady(); - mActionBar.removeOnMenuVisibilityListener(mMenuVisibilityListener); - if (mShowSpinner) { - mActionBar.disableAlbumModeMenu(true); - } - onCommitDeleteImage(); - mMenuExecutor.pause(); - if (mMediaSet != null) mMediaSet.clearDeletion(); - } - - @Override - public void onCurrentImageUpdated() { - mActivity.getGLRoot().unfreeze(); - } - - @Override - public void onFilmModeChanged(boolean enabled) { - refreshBottomControlsWhenReady(); - if (mShowSpinner) { - if (enabled) { - mActionBar.enableAlbumModeMenu( - GalleryActionBar.ALBUM_FILMSTRIP_MODE_SELECTED, this); - } else { - mActionBar.disableAlbumModeMenu(true); - } - } - if (enabled) { - mHandler.removeMessages(MSG_HIDE_BARS); - UsageStatistics.onContentViewChanged( - UsageStatistics.COMPONENT_GALLERY, "FilmstripPage"); - } else { - refreshHidingMessage(); - if (mAppBridge == null || mCurrentIndex > 0) { - UsageStatistics.onContentViewChanged( - UsageStatistics.COMPONENT_GALLERY, "SinglePhotoPage"); - } else { - UsageStatistics.onContentViewChanged( - UsageStatistics.COMPONENT_CAMERA, "Unknown"); // TODO - } - } - } - - private void transitionFromAlbumPageIfNeeded() { - TransitionStore transitions = mActivity.getTransitionStore(); - - int albumPageTransition = transitions.get( - KEY_ALBUMPAGE_TRANSITION, MSG_ALBUMPAGE_NONE); - - if (albumPageTransition == MSG_ALBUMPAGE_NONE && mAppBridge != null - && mRecenterCameraOnResume) { - // Generally, resuming the PhotoPage when in Camera should - // reset to the capture mode to allow quick photo taking - mCurrentIndex = 0; - mPhotoView.resetToFirstPicture(); - } else { - int resumeIndex = transitions.get(KEY_INDEX_HINT, -1); - if (resumeIndex >= 0) { - if (mHasCameraScreennailOrPlaceholder) { - // Account for preview/placeholder being the first item - resumeIndex++; - } - if (resumeIndex < mMediaSet.getMediaItemCount()) { - mCurrentIndex = resumeIndex; - mModel.moveTo(mCurrentIndex); - } - } - } - - if (albumPageTransition == MSG_ALBUMPAGE_RESUMED) { - mPhotoView.setFilmMode(mStartInFilmstrip || mAppBridge != null); - } else if (albumPageTransition == MSG_ALBUMPAGE_PICKED) { - mPhotoView.setFilmMode(false); - } - } - - @Override - protected void onResume() { - super.onResume(); - - if (mModel == null) { - mActivity.getStateManager().finishState(this); - return; - } - transitionFromAlbumPageIfNeeded(); - - mActivity.getGLRoot().freeze(); - mIsActive = true; - setContentPane(mRootPane); - - mModel.resume(); - mPhotoView.resume(); - mActionBar.setDisplayOptions( - ((mSecureAlbum == null) && (mSetPathString != null)), false); - mActionBar.addOnMenuVisibilityListener(mMenuVisibilityListener); - refreshBottomControlsWhenReady(); - if (mShowSpinner && mPhotoView.getFilmMode()) { - mActionBar.enableAlbumModeMenu( - GalleryActionBar.ALBUM_FILMSTRIP_MODE_SELECTED, this); - } - if (!mShowBars) { - mActionBar.hide(); - mActivity.getGLRoot().setLightsOutMode(true); - } - boolean haveImageEditor = GalleryUtils.isEditorAvailable(mActivity, "image/*"); - if (haveImageEditor != mHaveImageEditor) { - mHaveImageEditor = haveImageEditor; - updateMenuOperations(); - } - - mRecenterCameraOnResume = true; - mHandler.sendEmptyMessageDelayed(MSG_UNFREEZE_GLROOT, UNFREEZE_GLROOT_TIMEOUT); - } - - @Override - protected void onDestroy() { - if (mAppBridge != null) { - mAppBridge.setServer(null); - mScreenNailItem.setScreenNail(null); - mAppBridge.detachScreenNail(); - mAppBridge = null; - mScreenNailSet = null; - mScreenNailItem = null; - } - mActivity.getGLRoot().setOrientationSource(null); - if (mBottomControls != null) mBottomControls.cleanup(); - - // Remove all pending messages. - mHandler.removeCallbacksAndMessages(null); - super.onDestroy(); - } - - private class MyDetailsSource implements DetailsSource { - - @Override - public MediaDetails getDetails() { - return mModel.getMediaItem(0).getDetails(); - } - - @Override - public int size() { - return mMediaSet != null ? mMediaSet.getMediaItemCount() : 1; - } - - @Override - public int setIndex() { - return mModel.getCurrentIndex(); - } - } - - @Override - public void onAlbumModeSelected(int mode) { - if (mode == GalleryActionBar.ALBUM_GRID_MODE_SELECTED) { - switchToGrid(); - } - } - - @Override - public void refreshBottomControlsWhenReady() { - if (mBottomControls == null) { - return; - } - MediaObject currentPhoto = mCurrentPhoto; - if (currentPhoto == null) { - mHandler.obtainMessage(MSG_REFRESH_BOTTOM_CONTROLS, 0, 0, currentPhoto).sendToTarget(); - } else { - currentPhoto.getPanoramaSupport(mRefreshBottomControlsCallback); - } - } - - private void updatePanoramaUI(boolean isPanorama360) { - Menu menu = mActionBar.getMenu(); - - // it could be null if onCreateActionBar has not been called yet - if (menu == null) { - return; - } - - MenuExecutor.updateMenuForPanorama(menu, isPanorama360, isPanorama360); - - if (isPanorama360) { - MenuItem item = menu.findItem(R.id.action_share); - if (item != null) { - item.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER); - item.setTitle(mActivity.getResources().getString(R.string.share_as_photo)); - } - } else if ((mCurrentPhoto.getSupportedOperations() & MediaObject.SUPPORT_SHARE) != 0) { - MenuItem item = menu.findItem(R.id.action_share); - if (item != null) { - item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); - item.setTitle(mActivity.getResources().getString(R.string.share)); - } - } - } - - @Override - public void onUndoBarVisibilityChanged(boolean visible) { - refreshBottomControlsWhenReady(); - } - - @Override - public boolean onShareTargetSelected(ShareActionProvider source, Intent intent) { - final long timestampMillis = mCurrentPhoto.getDateInMs(); - final String mediaType = getMediaTypeString(mCurrentPhoto); - UsageStatistics.onEvent(UsageStatistics.COMPONENT_GALLERY, - UsageStatistics.ACTION_SHARE, - mediaType, - timestampMillis > 0 - ? System.currentTimeMillis() - timestampMillis - : -1); - return false; - } - - private static String getMediaTypeString(MediaItem item) { - if (item.getMediaType() == MediaObject.MEDIA_TYPE_VIDEO) { - return "Video"; - } else if (item.getMediaType() == MediaObject.MEDIA_TYPE_IMAGE) { - return "Photo"; - } else { - return "Unknown:" + item.getMediaType(); - } - } - -} diff --git a/src/com/android/gallery3d/app/PhotoPageBottomControls.java b/src/com/android/gallery3d/app/PhotoPageBottomControls.java deleted file mode 100644 index 24b8ceb7e..000000000 --- a/src/com/android/gallery3d/app/PhotoPageBottomControls.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * 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. - */ - -package com.android.gallery3d.app; - -import android.content.Context; -import android.view.LayoutInflater; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.ViewGroup; -import android.view.animation.AlphaAnimation; -import android.view.animation.Animation; -import android.widget.RelativeLayout; - -import com.android.gallery3d.R; - -import java.util.HashMap; -import java.util.Map; - -public class PhotoPageBottomControls implements OnClickListener { - public interface Delegate { - public boolean canDisplayBottomControls(); - public boolean canDisplayBottomControl(int control); - public void onBottomControlClicked(int control); - public void refreshBottomControlsWhenReady(); - } - - private Delegate mDelegate; - private ViewGroup mParentLayout; - private ViewGroup mContainer; - - private boolean mContainerVisible = false; - private Map mControlsVisible = new HashMap(); - - private Animation mContainerAnimIn = new AlphaAnimation(0f, 1f); - private Animation mContainerAnimOut = new AlphaAnimation(1f, 0f); - private static final int CONTAINER_ANIM_DURATION_MS = 200; - - private static final int CONTROL_ANIM_DURATION_MS = 150; - private static Animation getControlAnimForVisibility(boolean visible) { - Animation anim = visible ? new AlphaAnimation(0f, 1f) - : new AlphaAnimation(1f, 0f); - anim.setDuration(CONTROL_ANIM_DURATION_MS); - return anim; - } - - public PhotoPageBottomControls(Delegate delegate, Context context, RelativeLayout layout) { - mDelegate = delegate; - mParentLayout = layout; - - LayoutInflater inflater = (LayoutInflater) context - .getSystemService(Context.LAYOUT_INFLATER_SERVICE); - mContainer = (ViewGroup) inflater - .inflate(R.layout.photopage_bottom_controls, mParentLayout, false); - mParentLayout.addView(mContainer); - - for (int i = mContainer.getChildCount() - 1; i >= 0; i--) { - View child = mContainer.getChildAt(i); - child.setOnClickListener(this); - mControlsVisible.put(child, false); - } - - mContainerAnimIn.setDuration(CONTAINER_ANIM_DURATION_MS); - mContainerAnimOut.setDuration(CONTAINER_ANIM_DURATION_MS); - - mDelegate.refreshBottomControlsWhenReady(); - } - - private void hide() { - mContainer.clearAnimation(); - mContainerAnimOut.reset(); - mContainer.startAnimation(mContainerAnimOut); - mContainer.setVisibility(View.INVISIBLE); - } - - private void show() { - mContainer.clearAnimation(); - mContainerAnimIn.reset(); - mContainer.startAnimation(mContainerAnimIn); - mContainer.setVisibility(View.VISIBLE); - } - - public void refresh() { - boolean visible = mDelegate.canDisplayBottomControls(); - boolean containerVisibilityChanged = (visible != mContainerVisible); - if (containerVisibilityChanged) { - if (visible) { - show(); - } else { - hide(); - } - mContainerVisible = visible; - } - if (!mContainerVisible) { - return; - } - for (View control : mControlsVisible.keySet()) { - Boolean prevVisibility = mControlsVisible.get(control); - boolean curVisibility = mDelegate.canDisplayBottomControl(control.getId()); - if (prevVisibility.booleanValue() != curVisibility) { - if (!containerVisibilityChanged) { - control.clearAnimation(); - control.startAnimation(getControlAnimForVisibility(curVisibility)); - } - control.setVisibility(curVisibility ? View.VISIBLE : View.INVISIBLE); - mControlsVisible.put(control, curVisibility); - } - } - // Force a layout change - mContainer.requestLayout(); // Kick framework to draw the control. - } - - public void cleanup() { - mParentLayout.removeView(mContainer); - mControlsVisible.clear(); - } - - @Override - public void onClick(View view) { - if (mContainerVisible && mControlsVisible.get(view).booleanValue()) { - mDelegate.onBottomControlClicked(view.getId()); - } - } -} diff --git a/src/com/android/gallery3d/app/PhotoPageProgressBar.java b/src/com/android/gallery3d/app/PhotoPageProgressBar.java deleted file mode 100644 index 141fea698..000000000 --- a/src/com/android/gallery3d/app/PhotoPageProgressBar.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * 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. - */ -package com.android.gallery3d.app; - -import android.content.Context; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.view.ViewGroup.LayoutParams; -import android.widget.RelativeLayout; - -import com.android.gallery3d.R; - -public class PhotoPageProgressBar { - private ViewGroup mContainer; - private View mProgress; - - public PhotoPageProgressBar(Context context, RelativeLayout parentLayout) { - LayoutInflater inflater = (LayoutInflater) context - .getSystemService(Context.LAYOUT_INFLATER_SERVICE); - mContainer = (ViewGroup) inflater.inflate(R.layout.photopage_progress_bar, parentLayout, - false); - parentLayout.addView(mContainer); - mProgress = mContainer.findViewById(R.id.photopage_progress_foreground); - } - - public void setProgress(int progressPercent) { - mContainer.setVisibility(View.VISIBLE); - LayoutParams layoutParams = mProgress.getLayoutParams(); - layoutParams.width = mContainer.getWidth() * progressPercent / 100; - mProgress.setLayoutParams(layoutParams); - } - - public void hideProgress() { - mContainer.setVisibility(View.INVISIBLE); - } -} diff --git a/src/com/android/gallery3d/app/PickerActivity.java b/src/com/android/gallery3d/app/PickerActivity.java deleted file mode 100644 index d5bb218ea..000000000 --- a/src/com/android/gallery3d/app/PickerActivity.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.app; - -import android.os.Bundle; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.Window; - -import com.android.gallery3d.R; -import com.android.gallery3d.ui.GLRootView; - -public class PickerActivity extends AbstractGalleryActivity - implements OnClickListener { - - public static final String KEY_ALBUM_PATH = "album-path"; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - // We show the picker in two ways. One smaller screen we use a full - // screen window with an action bar. On larger screen we use a dialog. - boolean isDialog = getResources().getBoolean(R.bool.picker_is_dialog); - - if (!isDialog) { - requestWindowFeature(Window.FEATURE_ACTION_BAR); - requestWindowFeature(Window.FEATURE_ACTION_BAR_OVERLAY); - } - - setContentView(R.layout.dialog_picker); - - if (isDialog) { - // In dialog mode, we don't have the action bar to show the - // "cancel" action, so we show an additional "cancel" button. - View view = findViewById(R.id.cancel); - view.setOnClickListener(this); - view.setVisibility(View.VISIBLE); - - // We need this, otherwise the view will be dimmed because it - // is "behind" the dialog. - ((GLRootView) findViewById(R.id.gl_root_view)).setZOrderOnTop(true); - } - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - MenuInflater inflater = getMenuInflater(); - inflater.inflate(R.menu.pickup, menu); - return true; - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - if (item.getItemId() == R.id.action_cancel) { - finish(); - return true; - } - return super.onOptionsItemSelected(item); - } - - @Override - public void onClick(View v) { - if (v.getId() == R.id.cancel) finish(); - } -} diff --git a/src/com/android/gallery3d/app/SinglePhotoDataAdapter.java b/src/com/android/gallery3d/app/SinglePhotoDataAdapter.java deleted file mode 100644 index 00f2fe78f..000000000 --- a/src/com/android/gallery3d/app/SinglePhotoDataAdapter.java +++ /dev/null @@ -1,263 +0,0 @@ -/* - * 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.gallery3d.app; - -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.BitmapRegionDecoder; -import android.graphics.Rect; -import android.os.Handler; -import android.os.Message; - -import com.android.gallery3d.common.BitmapUtils; -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.data.MediaItem; -import com.android.gallery3d.data.Path; -import com.android.gallery3d.ui.BitmapScreenNail; -import com.android.gallery3d.ui.PhotoView; -import com.android.gallery3d.ui.ScreenNail; -import com.android.gallery3d.ui.SynchronizedHandler; -import com.android.gallery3d.ui.TileImageViewAdapter; -import com.android.gallery3d.util.Future; -import com.android.gallery3d.util.FutureListener; -import com.android.gallery3d.util.ThreadPool; - -public class SinglePhotoDataAdapter extends TileImageViewAdapter - implements PhotoPage.Model { - - private static final String TAG = "SinglePhotoDataAdapter"; - private static final int SIZE_BACKUP = 1024; - private static final int MSG_UPDATE_IMAGE = 1; - - private MediaItem mItem; - private boolean mHasFullImage; - private Future mTask; - private Handler mHandler; - - private PhotoView mPhotoView; - private ThreadPool mThreadPool; - private int mLoadingState = LOADING_INIT; - private BitmapScreenNail mBitmapScreenNail; - - public SinglePhotoDataAdapter( - AbstractGalleryActivity activity, PhotoView view, MediaItem item) { - mItem = Utils.checkNotNull(item); - mHasFullImage = (item.getSupportedOperations() & - MediaItem.SUPPORT_FULL_IMAGE) != 0; - mPhotoView = Utils.checkNotNull(view); - mHandler = new SynchronizedHandler(activity.getGLRoot()) { - @Override - @SuppressWarnings("unchecked") - public void handleMessage(Message message) { - Utils.assertTrue(message.what == MSG_UPDATE_IMAGE); - if (mHasFullImage) { - onDecodeLargeComplete((ImageBundle) message.obj); - } else { - onDecodeThumbComplete((Future) message.obj); - } - } - }; - mThreadPool = activity.getThreadPool(); - } - - private static class ImageBundle { - public final BitmapRegionDecoder decoder; - public final Bitmap backupImage; - - public ImageBundle(BitmapRegionDecoder decoder, Bitmap backupImage) { - this.decoder = decoder; - this.backupImage = backupImage; - } - } - - private FutureListener mLargeListener = - new FutureListener() { - @Override - public void onFutureDone(Future future) { - BitmapRegionDecoder decoder = future.get(); - if (decoder == null) return; - int width = decoder.getWidth(); - int height = decoder.getHeight(); - BitmapFactory.Options options = new BitmapFactory.Options(); - options.inSampleSize = BitmapUtils.computeSampleSize( - (float) SIZE_BACKUP / Math.max(width, height)); - Bitmap bitmap = decoder.decodeRegion(new Rect(0, 0, width, height), options); - mHandler.sendMessage(mHandler.obtainMessage( - MSG_UPDATE_IMAGE, new ImageBundle(decoder, bitmap))); - } - }; - - private FutureListener mThumbListener = - new FutureListener() { - @Override - public void onFutureDone(Future future) { - mHandler.sendMessage( - mHandler.obtainMessage(MSG_UPDATE_IMAGE, future)); - } - }; - - @Override - public boolean isEmpty() { - return false; - } - - private void setScreenNail(Bitmap bitmap, int width, int height) { - mBitmapScreenNail = new BitmapScreenNail(bitmap); - setScreenNail(mBitmapScreenNail, width, height); - } - - private void onDecodeLargeComplete(ImageBundle bundle) { - try { - setScreenNail(bundle.backupImage, - bundle.decoder.getWidth(), bundle.decoder.getHeight()); - setRegionDecoder(bundle.decoder); - mPhotoView.notifyImageChange(0); - } catch (Throwable t) { - Log.w(TAG, "fail to decode large", t); - } - } - - private void onDecodeThumbComplete(Future future) { - try { - Bitmap backup = future.get(); - if (backup == null) { - mLoadingState = LOADING_FAIL; - return; - } else { - mLoadingState = LOADING_COMPLETE; - } - setScreenNail(backup, backup.getWidth(), backup.getHeight()); - mPhotoView.notifyImageChange(0); - } catch (Throwable t) { - Log.w(TAG, "fail to decode thumb", t); - } - } - - @Override - public void resume() { - if (mTask == null) { - if (mHasFullImage) { - mTask = mThreadPool.submit( - mItem.requestLargeImage(), mLargeListener); - } else { - mTask = mThreadPool.submit( - mItem.requestImage(MediaItem.TYPE_THUMBNAIL), - mThumbListener); - } - } - } - - @Override - public void pause() { - Future task = mTask; - task.cancel(); - task.waitDone(); - if (task.get() == null) { - mTask = null; - } - if (mBitmapScreenNail != null) { - mBitmapScreenNail.recycle(); - mBitmapScreenNail = null; - } - } - - @Override - public void moveTo(int index) { - throw new UnsupportedOperationException(); - } - - @Override - public void getImageSize(int offset, PhotoView.Size size) { - if (offset == 0) { - size.width = mItem.getWidth(); - size.height = mItem.getHeight(); - } else { - size.width = 0; - size.height = 0; - } - } - - @Override - public int getImageRotation(int offset) { - return (offset == 0) ? mItem.getFullImageRotation() : 0; - } - - @Override - public ScreenNail getScreenNail(int offset) { - return (offset == 0) ? getScreenNail() : null; - } - - @Override - public void setNeedFullImage(boolean enabled) { - // currently not necessary. - } - - @Override - public boolean isCamera(int offset) { - return false; - } - - @Override - public boolean isPanorama(int offset) { - return false; - } - - @Override - public boolean isStaticCamera(int offset) { - return false; - } - - @Override - public boolean isVideo(int offset) { - return mItem.getMediaType() == MediaItem.MEDIA_TYPE_VIDEO; - } - - @Override - public boolean isDeletable(int offset) { - return (mItem.getSupportedOperations() & MediaItem.SUPPORT_DELETE) != 0; - } - - @Override - public MediaItem getMediaItem(int offset) { - return offset == 0 ? mItem : null; - } - - @Override - public int getCurrentIndex() { - return 0; - } - - @Override - public void setCurrentPhoto(Path path, int indexHint) { - // ignore - } - - @Override - public void setFocusHintDirection(int direction) { - // ignore - } - - @Override - public void setFocusHintPath(Path path) { - // ignore - } - - @Override - public int getLoadingState(int offset) { - return mLoadingState; - } -} diff --git a/src/com/android/gallery3d/app/SinglePhotoPage.java b/src/com/android/gallery3d/app/SinglePhotoPage.java deleted file mode 100644 index beb87d358..000000000 --- a/src/com/android/gallery3d/app/SinglePhotoPage.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * 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. - */ - -package com.android.gallery3d.app; - -public class SinglePhotoPage extends PhotoPage { - -} diff --git a/src/com/android/gallery3d/app/SlideshowDataAdapter.java b/src/com/android/gallery3d/app/SlideshowDataAdapter.java deleted file mode 100644 index 7a0fba5fb..000000000 --- a/src/com/android/gallery3d/app/SlideshowDataAdapter.java +++ /dev/null @@ -1,204 +0,0 @@ -/* - * 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.gallery3d.app; - -import android.graphics.Bitmap; - -import com.android.gallery3d.app.SlideshowPage.Slide; -import com.android.gallery3d.data.ContentListener; -import com.android.gallery3d.data.MediaItem; -import com.android.gallery3d.data.MediaObject; -import com.android.gallery3d.data.Path; -import com.android.gallery3d.util.Future; -import com.android.gallery3d.util.FutureListener; -import com.android.gallery3d.util.ThreadPool; -import com.android.gallery3d.util.ThreadPool.Job; -import com.android.gallery3d.util.ThreadPool.JobContext; - -import java.util.LinkedList; -import java.util.concurrent.atomic.AtomicBoolean; - -public class SlideshowDataAdapter implements SlideshowPage.Model { - @SuppressWarnings("unused") - private static final String TAG = "SlideshowDataAdapter"; - - private static final int IMAGE_QUEUE_CAPACITY = 3; - - public interface SlideshowSource { - public void addContentListener(ContentListener listener); - public void removeContentListener(ContentListener listener); - public long reload(); - public MediaItem getMediaItem(int index); - public int findItemIndex(Path path, int hint); - } - - private final SlideshowSource mSource; - - private int mLoadIndex = 0; - private int mNextOutput = 0; - private boolean mIsActive = false; - private boolean mNeedReset; - private boolean mDataReady; - private Path mInitialPath; - - private final LinkedList mImageQueue = new LinkedList(); - - private Future mReloadTask; - private final ThreadPool mThreadPool; - - private long mDataVersion = MediaObject.INVALID_DATA_VERSION; - private final AtomicBoolean mNeedReload = new AtomicBoolean(false); - private final SourceListener mSourceListener = new SourceListener(); - - // The index is just a hint if initialPath is set - public SlideshowDataAdapter(GalleryContext context, SlideshowSource source, int index, - Path initialPath) { - mSource = source; - mInitialPath = initialPath; - mLoadIndex = index; - mNextOutput = index; - mThreadPool = context.getThreadPool(); - } - - private MediaItem loadItem() { - if (mNeedReload.compareAndSet(true, false)) { - long v = mSource.reload(); - if (v != mDataVersion) { - mDataVersion = v; - mNeedReset = true; - return null; - } - } - int index = mLoadIndex; - if (mInitialPath != null) { - index = mSource.findItemIndex(mInitialPath, index); - mInitialPath = null; - } - return mSource.getMediaItem(index); - } - - private class ReloadTask implements Job { - @Override - public Void run(JobContext jc) { - while (true) { - synchronized (SlideshowDataAdapter.this) { - while (mIsActive && (!mDataReady - || mImageQueue.size() >= IMAGE_QUEUE_CAPACITY)) { - try { - SlideshowDataAdapter.this.wait(); - } catch (InterruptedException ex) { - // ignored. - } - continue; - } - } - if (!mIsActive) return null; - mNeedReset = false; - - MediaItem item = loadItem(); - - if (mNeedReset) { - synchronized (SlideshowDataAdapter.this) { - mImageQueue.clear(); - mLoadIndex = mNextOutput; - } - continue; - } - - if (item == null) { - synchronized (SlideshowDataAdapter.this) { - if (!mNeedReload.get()) mDataReady = false; - SlideshowDataAdapter.this.notifyAll(); - } - continue; - } - - Bitmap bitmap = item - .requestImage(MediaItem.TYPE_THUMBNAIL) - .run(jc); - - if (bitmap != null) { - synchronized (SlideshowDataAdapter.this) { - mImageQueue.addLast( - new Slide(item, mLoadIndex, bitmap)); - if (mImageQueue.size() == 1) { - SlideshowDataAdapter.this.notifyAll(); - } - } - } - ++mLoadIndex; - } - } - } - - private class SourceListener implements ContentListener { - @Override - public void onContentDirty() { - synchronized (SlideshowDataAdapter.this) { - mNeedReload.set(true); - mDataReady = true; - SlideshowDataAdapter.this.notifyAll(); - } - } - } - - private synchronized Slide innerNextBitmap() { - while (mIsActive && mDataReady && mImageQueue.isEmpty()) { - try { - wait(); - } catch (InterruptedException t) { - throw new AssertionError(); - } - } - if (mImageQueue.isEmpty()) return null; - mNextOutput++; - this.notifyAll(); - return mImageQueue.removeFirst(); - } - - @Override - public Future nextSlide(FutureListener listener) { - return mThreadPool.submit(new Job() { - @Override - public Slide run(JobContext jc) { - jc.setMode(ThreadPool.MODE_NONE); - return innerNextBitmap(); - } - }, listener); - } - - @Override - public void pause() { - synchronized (this) { - mIsActive = false; - notifyAll(); - } - mSource.removeContentListener(mSourceListener); - mReloadTask.cancel(); - mReloadTask.waitDone(); - mReloadTask = null; - } - - @Override - public synchronized void resume() { - mIsActive = true; - mSource.addContentListener(mSourceListener); - mNeedReload.set(true); - mDataReady = true; - mReloadTask = mThreadPool.submit(new ReloadTask()); - } -} diff --git a/src/com/android/gallery3d/app/SlideshowPage.java b/src/com/android/gallery3d/app/SlideshowPage.java deleted file mode 100644 index 174058dc8..000000000 --- a/src/com/android/gallery3d/app/SlideshowPage.java +++ /dev/null @@ -1,366 +0,0 @@ -/* - * 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.gallery3d.app; - -import android.app.Activity; -import android.content.Intent; -import android.graphics.Bitmap; -import android.os.Bundle; -import android.os.Handler; -import android.os.Message; -import android.view.MotionEvent; - -import com.android.gallery3d.R; -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.data.ContentListener; -import com.android.gallery3d.data.MediaItem; -import com.android.gallery3d.data.MediaObject; -import com.android.gallery3d.data.MediaSet; -import com.android.gallery3d.data.Path; -import com.android.gallery3d.glrenderer.GLCanvas; -import com.android.gallery3d.ui.GLView; -import com.android.gallery3d.ui.SlideshowView; -import com.android.gallery3d.ui.SynchronizedHandler; -import com.android.gallery3d.util.Future; -import com.android.gallery3d.util.FutureListener; - -import java.util.ArrayList; -import java.util.Random; - -public class SlideshowPage extends ActivityState { - private static final String TAG = "SlideshowPage"; - - public static final String KEY_SET_PATH = "media-set-path"; - public static final String KEY_ITEM_PATH = "media-item-path"; - public static final String KEY_PHOTO_INDEX = "photo-index"; - public static final String KEY_RANDOM_ORDER = "random-order"; - public static final String KEY_REPEAT = "repeat"; - public static final String KEY_DREAM = "dream"; - - private static final long SLIDESHOW_DELAY = 3000; // 3 seconds - - private static final int MSG_LOAD_NEXT_BITMAP = 1; - private static final int MSG_SHOW_PENDING_BITMAP = 2; - - public static interface Model { - public void pause(); - - public void resume(); - - public Future nextSlide(FutureListener listener); - } - - public static class Slide { - public Bitmap bitmap; - public MediaItem item; - public int index; - - public Slide(MediaItem item, int index, Bitmap bitmap) { - this.bitmap = bitmap; - this.item = item; - this.index = index; - } - } - - private Handler mHandler; - private Model mModel; - private SlideshowView mSlideshowView; - - private Slide mPendingSlide = null; - private boolean mIsActive = false; - private final Intent mResultIntent = new Intent(); - - @Override - protected int getBackgroundColorId() { - return R.color.slideshow_background; - } - - private final GLView mRootPane = new GLView() { - @Override - protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - mSlideshowView.layout(0, 0, right - left, bottom - top); - } - - @Override - protected boolean onTouch(MotionEvent event) { - if (event.getAction() == MotionEvent.ACTION_UP) { - onBackPressed(); - } - return true; - } - - @Override - protected void renderBackground(GLCanvas canvas) { - canvas.clearBuffer(getBackgroundColor()); - } - }; - - @Override - public void onCreate(Bundle data, Bundle restoreState) { - super.onCreate(data, restoreState); - mFlags |= (FLAG_HIDE_ACTION_BAR | FLAG_HIDE_STATUS_BAR); - if (data.getBoolean(KEY_DREAM)) { - // Dream screensaver only keeps screen on for plugged devices. - mFlags |= FLAG_SCREEN_ON_WHEN_PLUGGED | FLAG_SHOW_WHEN_LOCKED; - } else { - // User-initiated slideshow would always keep screen on. - mFlags |= FLAG_SCREEN_ON_ALWAYS; - } - - mHandler = new SynchronizedHandler(mActivity.getGLRoot()) { - @Override - public void handleMessage(Message message) { - switch (message.what) { - case MSG_SHOW_PENDING_BITMAP: - showPendingBitmap(); - break; - case MSG_LOAD_NEXT_BITMAP: - loadNextBitmap(); - break; - default: throw new AssertionError(); - } - } - }; - initializeViews(); - initializeData(data); - } - - private void loadNextBitmap() { - mModel.nextSlide(new FutureListener() { - @Override - public void onFutureDone(Future future) { - mPendingSlide = future.get(); - mHandler.sendEmptyMessage(MSG_SHOW_PENDING_BITMAP); - } - }); - } - - private void showPendingBitmap() { - // mPendingBitmap could be null, if - // 1.) there is no more items - // 2.) mModel is paused - Slide slide = mPendingSlide; - if (slide == null) { - if (mIsActive) { - mActivity.getStateManager().finishState(SlideshowPage.this); - } - return; - } - - mSlideshowView.next(slide.bitmap, slide.item.getRotation()); - - setStateResult(Activity.RESULT_OK, mResultIntent - .putExtra(KEY_ITEM_PATH, slide.item.getPath().toString()) - .putExtra(KEY_PHOTO_INDEX, slide.index)); - mHandler.sendEmptyMessageDelayed(MSG_LOAD_NEXT_BITMAP, SLIDESHOW_DELAY); - } - - @Override - public void onPause() { - super.onPause(); - mIsActive = false; - mModel.pause(); - mSlideshowView.release(); - - mHandler.removeMessages(MSG_LOAD_NEXT_BITMAP); - mHandler.removeMessages(MSG_SHOW_PENDING_BITMAP); - } - - @Override - public void onResume() { - super.onResume(); - mIsActive = true; - mModel.resume(); - - if (mPendingSlide != null) { - showPendingBitmap(); - } else { - loadNextBitmap(); - } - } - - private void initializeData(Bundle data) { - boolean random = data.getBoolean(KEY_RANDOM_ORDER, false); - - // We only want to show slideshow for images only, not videos. - String mediaPath = data.getString(KEY_SET_PATH); - mediaPath = FilterUtils.newFilterPath(mediaPath, FilterUtils.FILTER_IMAGE_ONLY); - MediaSet mediaSet = mActivity.getDataManager().getMediaSet(mediaPath); - - if (random) { - boolean repeat = data.getBoolean(KEY_REPEAT); - mModel = new SlideshowDataAdapter(mActivity, - new ShuffleSource(mediaSet, repeat), 0, null); - setStateResult(Activity.RESULT_OK, mResultIntent.putExtra(KEY_PHOTO_INDEX, 0)); - } else { - int index = data.getInt(KEY_PHOTO_INDEX); - String itemPath = data.getString(KEY_ITEM_PATH); - Path path = itemPath != null ? Path.fromString(itemPath) : null; - boolean repeat = data.getBoolean(KEY_REPEAT); - mModel = new SlideshowDataAdapter(mActivity, new SequentialSource(mediaSet, repeat), - index, path); - setStateResult(Activity.RESULT_OK, mResultIntent.putExtra(KEY_PHOTO_INDEX, index)); - } - } - - private void initializeViews() { - mSlideshowView = new SlideshowView(); - mRootPane.addComponent(mSlideshowView); - setContentPane(mRootPane); - } - - private static MediaItem findMediaItem(MediaSet mediaSet, int index) { - for (int i = 0, n = mediaSet.getSubMediaSetCount(); i < n; ++i) { - MediaSet subset = mediaSet.getSubMediaSet(i); - int count = subset.getTotalMediaItemCount(); - if (index < count) { - return findMediaItem(subset, index); - } - index -= count; - } - ArrayList list = mediaSet.getMediaItem(index, 1); - return list.isEmpty() ? null : list.get(0); - } - - private static class ShuffleSource implements SlideshowDataAdapter.SlideshowSource { - private static final int RETRY_COUNT = 5; - private final MediaSet mMediaSet; - private final Random mRandom = new Random(); - private int mOrder[] = new int[0]; - private final boolean mRepeat; - private long mSourceVersion = MediaSet.INVALID_DATA_VERSION; - private int mLastIndex = -1; - - public ShuffleSource(MediaSet mediaSet, boolean repeat) { - mMediaSet = Utils.checkNotNull(mediaSet); - mRepeat = repeat; - } - - @Override - public int findItemIndex(Path path, int hint) { - return hint; - } - - @Override - public MediaItem getMediaItem(int index) { - if (!mRepeat && index >= mOrder.length) return null; - if (mOrder.length == 0) return null; - mLastIndex = mOrder[index % mOrder.length]; - MediaItem item = findMediaItem(mMediaSet, mLastIndex); - for (int i = 0; i < RETRY_COUNT && item == null; ++i) { - Log.w(TAG, "fail to find image: " + mLastIndex); - mLastIndex = mRandom.nextInt(mOrder.length); - item = findMediaItem(mMediaSet, mLastIndex); - } - return item; - } - - @Override - public long reload() { - long version = mMediaSet.reload(); - if (version != mSourceVersion) { - mSourceVersion = version; - int count = mMediaSet.getTotalMediaItemCount(); - if (count != mOrder.length) generateOrderArray(count); - } - return version; - } - - private void generateOrderArray(int totalCount) { - if (mOrder.length != totalCount) { - mOrder = new int[totalCount]; - for (int i = 0; i < totalCount; ++i) { - mOrder[i] = i; - } - } - for (int i = totalCount - 1; i > 0; --i) { - Utils.swap(mOrder, i, mRandom.nextInt(i + 1)); - } - if (mOrder[0] == mLastIndex && totalCount > 1) { - Utils.swap(mOrder, 0, mRandom.nextInt(totalCount - 1) + 1); - } - } - - @Override - public void addContentListener(ContentListener listener) { - mMediaSet.addContentListener(listener); - } - - @Override - public void removeContentListener(ContentListener listener) { - mMediaSet.removeContentListener(listener); - } - } - - private static class SequentialSource implements SlideshowDataAdapter.SlideshowSource { - private static final int DATA_SIZE = 32; - - private ArrayList mData = new ArrayList(); - private int mDataStart = 0; - private long mDataVersion = MediaObject.INVALID_DATA_VERSION; - private final MediaSet mMediaSet; - private final boolean mRepeat; - - public SequentialSource(MediaSet mediaSet, boolean repeat) { - mMediaSet = mediaSet; - mRepeat = repeat; - } - - @Override - public int findItemIndex(Path path, int hint) { - return mMediaSet.getIndexOfItem(path, hint); - } - - @Override - public MediaItem getMediaItem(int index) { - int dataEnd = mDataStart + mData.size(); - - if (mRepeat) { - int count = mMediaSet.getMediaItemCount(); - if (count == 0) return null; - index = index % count; - } - if (index < mDataStart || index >= dataEnd) { - mData = mMediaSet.getMediaItem(index, DATA_SIZE); - mDataStart = index; - dataEnd = index + mData.size(); - } - - return (index < mDataStart || index >= dataEnd) ? null : mData.get(index - mDataStart); - } - - @Override - public long reload() { - long version = mMediaSet.reload(); - if (version != mDataVersion) { - mDataVersion = version; - mData.clear(); - } - return mDataVersion; - } - - @Override - public void addContentListener(ContentListener listener) { - mMediaSet.addContentListener(listener); - } - - @Override - public void removeContentListener(ContentListener listener) { - mMediaSet.removeContentListener(listener); - } - } -} diff --git a/src/com/android/gallery3d/app/StateManager.java b/src/com/android/gallery3d/app/StateManager.java deleted file mode 100644 index 53c3fc228..000000000 --- a/src/com/android/gallery3d/app/StateManager.java +++ /dev/null @@ -1,339 +0,0 @@ -/* - * 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.gallery3d.app; - -import android.app.Activity; -import android.content.Intent; -import android.content.res.Configuration; -import android.os.Bundle; -import android.os.Parcelable; -import android.view.Menu; -import android.view.MenuItem; - -import com.android.camera.CameraActivity; -import com.android.gallery3d.anim.StateTransitionAnimation; -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.util.UsageStatistics; - -import java.util.Stack; - -public class StateManager { - @SuppressWarnings("unused") - private static final String TAG = "StateManager"; - private boolean mIsResumed = false; - - private static final String KEY_MAIN = "activity-state"; - private static final String KEY_DATA = "data"; - private static final String KEY_STATE = "bundle"; - private static final String KEY_CLASS = "class"; - - private AbstractGalleryActivity mActivity; - private Stack mStack = new Stack(); - private ActivityState.ResultEntry mResult; - - public StateManager(AbstractGalleryActivity activity) { - mActivity = activity; - } - - public void startState(Class klass, - Bundle data) { - Log.v(TAG, "startState " + klass); - ActivityState state = null; - try { - state = klass.newInstance(); - } catch (Exception e) { - throw new AssertionError(e); - } - if (!mStack.isEmpty()) { - ActivityState top = getTopState(); - top.transitionOnNextPause(top.getClass(), klass, - StateTransitionAnimation.Transition.Incoming); - if (mIsResumed) top.onPause(); - } - - UsageStatistics.onContentViewChanged( - UsageStatistics.COMPONENT_GALLERY, - klass.getSimpleName()); - state.initialize(mActivity, data); - - mStack.push(new StateEntry(data, state)); - state.onCreate(data, null); - if (mIsResumed) state.resume(); - } - - public void startStateForResult(Class klass, - int requestCode, Bundle data) { - Log.v(TAG, "startStateForResult " + klass + ", " + requestCode); - ActivityState state = null; - try { - state = klass.newInstance(); - } catch (Exception e) { - throw new AssertionError(e); - } - state.initialize(mActivity, data); - state.mResult = new ActivityState.ResultEntry(); - state.mResult.requestCode = requestCode; - - if (!mStack.isEmpty()) { - ActivityState as = getTopState(); - as.transitionOnNextPause(as.getClass(), klass, - StateTransitionAnimation.Transition.Incoming); - as.mReceivedResults = state.mResult; - if (mIsResumed) as.onPause(); - } else { - mResult = state.mResult; - } - UsageStatistics.onContentViewChanged(UsageStatistics.COMPONENT_GALLERY, - klass.getSimpleName()); - mStack.push(new StateEntry(data, state)); - state.onCreate(data, null); - if (mIsResumed) state.resume(); - } - - public boolean createOptionsMenu(Menu menu) { - if (mStack.isEmpty()) { - return false; - } else { - return getTopState().onCreateActionBar(menu); - } - } - - public void onConfigurationChange(Configuration config) { - for (StateEntry entry : mStack) { - entry.activityState.onConfigurationChanged(config); - } - } - - public void resume() { - if (mIsResumed) return; - mIsResumed = true; - if (!mStack.isEmpty()) getTopState().resume(); - } - - public void pause() { - if (!mIsResumed) return; - mIsResumed = false; - if (!mStack.isEmpty()) getTopState().onPause(); - } - - public void notifyActivityResult(int requestCode, int resultCode, Intent data) { - getTopState().onStateResult(requestCode, resultCode, data); - } - - public void clearActivityResult() { - if (!mStack.isEmpty()) { - getTopState().clearStateResult(); - } - } - - public int getStateCount() { - return mStack.size(); - } - - public boolean itemSelected(MenuItem item) { - if (!mStack.isEmpty()) { - if (getTopState().onItemSelected(item)) return true; - if (item.getItemId() == android.R.id.home) { - if (mStack.size() > 1) { - getTopState().onBackPressed(); - } - return true; - } - } - return false; - } - - public void onBackPressed() { - if (!mStack.isEmpty()) { - getTopState().onBackPressed(); - } - } - - void finishState(ActivityState state) { - finishState(state, true); - } - - public void clearTasks() { - // Remove all the states that are on top of the bottom PhotoPage state - while (mStack.size() > 1) { - mStack.pop().activityState.onDestroy(); - } - } - - void finishState(ActivityState state, boolean fireOnPause) { - // The finish() request could be rejected (only happens under Monkey), - // If it is rejected, we won't close the last page. - if (mStack.size() == 1) { - Activity activity = (Activity) mActivity.getAndroidContext(); - if (mResult != null) { - activity.setResult(mResult.resultCode, mResult.resultData); - } - activity.finish(); - if (!activity.isFinishing()) { - Log.w(TAG, "finish is rejected, keep the last state"); - return; - } - Log.v(TAG, "no more state, finish activity"); - } - - Log.v(TAG, "finishState " + state); - if (state != mStack.peek().activityState) { - if (state.isDestroyed()) { - Log.d(TAG, "The state is already destroyed"); - return; - } else { - throw new IllegalArgumentException("The stateview to be finished" - + " is not at the top of the stack: " + state + ", " - + mStack.peek().activityState); - } - } - - // Remove the top state. - mStack.pop(); - state.mIsFinishing = true; - ActivityState top = !mStack.isEmpty() ? mStack.peek().activityState : null; - if (mIsResumed && fireOnPause) { - if (top != null) { - state.transitionOnNextPause(state.getClass(), top.getClass(), - StateTransitionAnimation.Transition.Outgoing); - } - state.onPause(); - } - mActivity.getGLRoot().setContentPane(null); - state.onDestroy(); - - if (top != null && mIsResumed) top.resume(); - if (top != null) { - UsageStatistics.onContentViewChanged(UsageStatistics.COMPONENT_GALLERY, - top.getClass().getSimpleName()); - } - } - - public void switchState(ActivityState oldState, - Class klass, Bundle data) { - Log.v(TAG, "switchState " + oldState + ", " + klass); - if (oldState != mStack.peek().activityState) { - throw new IllegalArgumentException("The stateview to be finished" - + " is not at the top of the stack: " + oldState + ", " - + mStack.peek().activityState); - } - // Remove the top state. - mStack.pop(); - if (!data.containsKey(PhotoPage.KEY_APP_BRIDGE)) { - // Do not do the fade out stuff when we are switching camera modes - oldState.transitionOnNextPause(oldState.getClass(), klass, - StateTransitionAnimation.Transition.Incoming); - } - if (mIsResumed) oldState.onPause(); - oldState.onDestroy(); - - // Create new state. - ActivityState state = null; - try { - state = klass.newInstance(); - } catch (Exception e) { - throw new AssertionError(e); - } - state.initialize(mActivity, data); - mStack.push(new StateEntry(data, state)); - state.onCreate(data, null); - if (mIsResumed) state.resume(); - UsageStatistics.onContentViewChanged(UsageStatistics.COMPONENT_GALLERY, - klass.getSimpleName()); - } - - public void destroy() { - Log.v(TAG, "destroy"); - while (!mStack.isEmpty()) { - mStack.pop().activityState.onDestroy(); - } - mStack.clear(); - } - - @SuppressWarnings("unchecked") - public void restoreFromState(Bundle inState) { - Log.v(TAG, "restoreFromState"); - Parcelable list[] = inState.getParcelableArray(KEY_MAIN); - ActivityState topState = null; - for (Parcelable parcelable : list) { - Bundle bundle = (Bundle) parcelable; - Class klass = - (Class) bundle.getSerializable(KEY_CLASS); - - Bundle data = bundle.getBundle(KEY_DATA); - Bundle state = bundle.getBundle(KEY_STATE); - - ActivityState activityState; - try { - Log.v(TAG, "restoreFromState " + klass); - activityState = klass.newInstance(); - } catch (Exception e) { - throw new AssertionError(e); - } - activityState.initialize(mActivity, data); - activityState.onCreate(data, state); - mStack.push(new StateEntry(data, activityState)); - topState = activityState; - } - if (topState != null) { - UsageStatistics.onContentViewChanged(UsageStatistics.COMPONENT_GALLERY, - topState.getClass().getSimpleName()); - } - } - - public void saveState(Bundle outState) { - Log.v(TAG, "saveState"); - - Parcelable list[] = new Parcelable[mStack.size()]; - int i = 0; - for (StateEntry entry : mStack) { - Bundle bundle = new Bundle(); - bundle.putSerializable(KEY_CLASS, entry.activityState.getClass()); - bundle.putBundle(KEY_DATA, entry.data); - Bundle state = new Bundle(); - entry.activityState.onSaveState(state); - bundle.putBundle(KEY_STATE, state); - Log.v(TAG, "saveState " + entry.activityState.getClass()); - list[i++] = bundle; - } - outState.putParcelableArray(KEY_MAIN, list); - } - - public boolean hasStateClass(Class klass) { - for (StateEntry entry : mStack) { - if (klass.isInstance(entry.activityState)) { - return true; - } - } - return false; - } - - public ActivityState getTopState() { - Utils.assertTrue(!mStack.isEmpty()); - return mStack.peek().activityState; - } - - private static class StateEntry { - public Bundle data; - public ActivityState activityState; - - public StateEntry(Bundle data, ActivityState state) { - this.data = data; - this.activityState = state; - } - } -} diff --git a/src/com/android/gallery3d/app/StitchingChangeListener.java b/src/com/android/gallery3d/app/StitchingChangeListener.java deleted file mode 100644 index 0b8c2d6d6..000000000 --- a/src/com/android/gallery3d/app/StitchingChangeListener.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * 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. - */ - -package com.android.gallery3d.app; - -import android.net.Uri; - -public interface StitchingChangeListener { - public void onStitchingQueued(Uri uri); - - public void onStitchingResult(Uri uri); - - public void onStitchingProgress(Uri uri, int progress); -} diff --git a/src/com/android/gallery3d/app/TimeBar.java b/src/com/android/gallery3d/app/TimeBar.java deleted file mode 100644 index 246346a56..000000000 --- a/src/com/android/gallery3d/app/TimeBar.java +++ /dev/null @@ -1,266 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.app; - -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.Canvas; -import android.graphics.Paint; -import android.graphics.Rect; -import android.util.DisplayMetrics; -import android.view.MotionEvent; -import android.view.View; - -import com.android.gallery3d.R; -import com.android.gallery3d.common.Utils; - -/** - * The time bar view, which includes the current and total time, the progress - * bar, and the scrubber. - */ -public class TimeBar extends View { - - public interface Listener { - void onScrubbingStart(); - - void onScrubbingMove(int time); - - void onScrubbingEnd(int time, int start, int end); - } - - // Padding around the scrubber to increase its touch target - private static final int SCRUBBER_PADDING_IN_DP = 10; - - // The total padding, top plus bottom - private static final int V_PADDING_IN_DP = 30; - - private static final int TEXT_SIZE_IN_DP = 14; - - protected final Listener mListener; - - // the bars we use for displaying the progress - protected final Rect mProgressBar; - protected final Rect mPlayedBar; - - protected final Paint mProgressPaint; - protected final Paint mPlayedPaint; - protected final Paint mTimeTextPaint; - - protected final Bitmap mScrubber; - protected int mScrubberPadding; // adds some touch tolerance around the - // scrubber - - protected int mScrubberLeft; - protected int mScrubberTop; - protected int mScrubberCorrection; - protected boolean mScrubbing; - protected boolean mShowTimes; - protected boolean mShowScrubber; - - protected int mTotalTime; - protected int mCurrentTime; - - protected final Rect mTimeBounds; - - protected int mVPaddingInPx; - - public TimeBar(Context context, Listener listener) { - super(context); - mListener = Utils.checkNotNull(listener); - - mShowTimes = true; - mShowScrubber = true; - - mProgressBar = new Rect(); - mPlayedBar = new Rect(); - - mProgressPaint = new Paint(); - mProgressPaint.setColor(0xFF808080); - mPlayedPaint = new Paint(); - mPlayedPaint.setColor(0xFFFFFFFF); - - DisplayMetrics metrics = context.getResources().getDisplayMetrics(); - float textSizeInPx = metrics.density * TEXT_SIZE_IN_DP; - mTimeTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - mTimeTextPaint.setColor(0xFFCECECE); - mTimeTextPaint.setTextSize(textSizeInPx); - mTimeTextPaint.setTextAlign(Paint.Align.CENTER); - - mTimeBounds = new Rect(); - mTimeTextPaint.getTextBounds("0:00:00", 0, 7, mTimeBounds); - - mScrubber = BitmapFactory.decodeResource(getResources(), R.drawable.scrubber_knob); - mScrubberPadding = (int) (metrics.density * SCRUBBER_PADDING_IN_DP); - - mVPaddingInPx = (int) (metrics.density * V_PADDING_IN_DP); - } - - private void update() { - mPlayedBar.set(mProgressBar); - - if (mTotalTime > 0) { - mPlayedBar.right = - mPlayedBar.left + (int) ((mProgressBar.width() * (long) mCurrentTime) / mTotalTime); - } else { - mPlayedBar.right = mProgressBar.left; - } - - if (!mScrubbing) { - mScrubberLeft = mPlayedBar.right - mScrubber.getWidth() / 2; - } - invalidate(); - } - - /** - * @return the preferred height of this view, including invisible padding - */ - public int getPreferredHeight() { - return mTimeBounds.height() + mVPaddingInPx + mScrubberPadding; - } - - /** - * @return the height of the time bar, excluding invisible padding - */ - public int getBarHeight() { - return mTimeBounds.height() + mVPaddingInPx; - } - - public void setTime(int currentTime, int totalTime, - int trimStartTime, int trimEndTime) { - if (mCurrentTime == currentTime && mTotalTime == totalTime) { - return; - } - mCurrentTime = currentTime; - mTotalTime = totalTime; - update(); - } - - private boolean inScrubber(float x, float y) { - int scrubberRight = mScrubberLeft + mScrubber.getWidth(); - int scrubberBottom = mScrubberTop + mScrubber.getHeight(); - return mScrubberLeft - mScrubberPadding < x && x < scrubberRight + mScrubberPadding - && mScrubberTop - mScrubberPadding < y && y < scrubberBottom + mScrubberPadding; - } - - private void clampScrubber() { - int half = mScrubber.getWidth() / 2; - int max = mProgressBar.right - half; - int min = mProgressBar.left - half; - mScrubberLeft = Math.min(max, Math.max(min, mScrubberLeft)); - } - - private int getScrubberTime() { - return (int) ((long) (mScrubberLeft + mScrubber.getWidth() / 2 - mProgressBar.left) - * mTotalTime / mProgressBar.width()); - } - - @Override - protected void onLayout(boolean changed, int l, int t, int r, int b) { - int w = r - l; - int h = b - t; - if (!mShowTimes && !mShowScrubber) { - mProgressBar.set(0, 0, w, h); - } else { - int margin = mScrubber.getWidth() / 3; - if (mShowTimes) { - margin += mTimeBounds.width(); - } - int progressY = (h + mScrubberPadding) / 2; - mScrubberTop = progressY - mScrubber.getHeight() / 2 + 1; - mProgressBar.set( - getPaddingLeft() + margin, progressY, - w - getPaddingRight() - margin, progressY + 4); - } - update(); - } - - @Override - protected void onDraw(Canvas canvas) { - // draw progress bars - canvas.drawRect(mProgressBar, mProgressPaint); - canvas.drawRect(mPlayedBar, mPlayedPaint); - - // draw scrubber and timers - if (mShowScrubber) { - canvas.drawBitmap(mScrubber, mScrubberLeft, mScrubberTop, null); - } - if (mShowTimes) { - canvas.drawText( - stringForTime(mCurrentTime), - mTimeBounds.width() / 2 + getPaddingLeft(), - mTimeBounds.height() + mVPaddingInPx / 2 + mScrubberPadding + 1, - mTimeTextPaint); - canvas.drawText( - stringForTime(mTotalTime), - getWidth() - getPaddingRight() - mTimeBounds.width() / 2, - mTimeBounds.height() + mVPaddingInPx / 2 + mScrubberPadding + 1, - mTimeTextPaint); - } - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - if (mShowScrubber) { - int x = (int) event.getX(); - int y = (int) event.getY(); - - switch (event.getAction()) { - case MotionEvent.ACTION_DOWN: { - mScrubberCorrection = inScrubber(x, y) - ? x - mScrubberLeft - : mScrubber.getWidth() / 2; - mScrubbing = true; - mListener.onScrubbingStart(); - } - // fall-through - case MotionEvent.ACTION_MOVE: { - mScrubberLeft = x - mScrubberCorrection; - clampScrubber(); - mCurrentTime = getScrubberTime(); - mListener.onScrubbingMove(mCurrentTime); - invalidate(); - return true; - } - case MotionEvent.ACTION_CANCEL: - case MotionEvent.ACTION_UP: { - mListener.onScrubbingEnd(getScrubberTime(), 0, 0); - mScrubbing = false; - return true; - } - } - } - return false; - } - - protected String stringForTime(long millis) { - int totalSeconds = (int) millis / 1000; - int seconds = totalSeconds % 60; - int minutes = (totalSeconds / 60) % 60; - int hours = totalSeconds / 3600; - if (hours > 0) { - return String.format("%d:%02d:%02d", hours, minutes, seconds).toString(); - } else { - return String.format("%02d:%02d", minutes, seconds).toString(); - } - } - - public void setSeekable(boolean canSeek) { - mShowScrubber = canSeek; - } - -} diff --git a/src/com/android/gallery3d/app/TransitionStore.java b/src/com/android/gallery3d/app/TransitionStore.java deleted file mode 100644 index aa38ed77e..000000000 --- a/src/com/android/gallery3d/app/TransitionStore.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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. - */ - -package com.android.gallery3d.app; - -import java.util.HashMap; - -public class TransitionStore { - private HashMap mStorage = new HashMap(); - - public void put(Object key, Object value) { - mStorage.put(key, value); - } - - public void putIfNotPresent(Object key, T valueIfNull) { - mStorage.put(key, get(key, valueIfNull)); - } - - @SuppressWarnings("unchecked") - public T get(Object key) { - return (T) mStorage.get(key); - } - - @SuppressWarnings("unchecked") - public T get(Object key, T valueIfNull) { - T value = (T) mStorage.get(key); - return value == null ? valueIfNull : value; - } - - public void clear() { - mStorage.clear(); - } -} diff --git a/src/com/android/gallery3d/app/TrimControllerOverlay.java b/src/com/android/gallery3d/app/TrimControllerOverlay.java deleted file mode 100644 index cae016626..000000000 --- a/src/com/android/gallery3d/app/TrimControllerOverlay.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * 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. - */ - -package com.android.gallery3d.app; - -import android.animation.Animator; -import android.animation.Animator.AnimatorListener; -import android.animation.ObjectAnimator; -import android.content.Context; -import android.view.MotionEvent; -import android.view.View; - -import com.android.gallery3d.common.ApiHelper; - -/** - * The controller for the Trimming Video. - */ -public class TrimControllerOverlay extends CommonControllerOverlay { - - public TrimControllerOverlay(Context context) { - super(context); - } - - @Override - protected void createTimeBar(Context context) { - mTimeBar = new TrimTimeBar(context, this); - } - - private void hidePlayButtonIfPlaying() { - if (mState == State.PLAYING) { - mPlayPauseReplayView.setVisibility(View.INVISIBLE); - } - if (ApiHelper.HAS_OBJECT_ANIMATION) { - mPlayPauseReplayView.setAlpha(1f); - } - } - - @Override - public void showPlaying() { - super.showPlaying(); - if (ApiHelper.HAS_OBJECT_ANIMATION) { - // Add animation to hide the play button while playing. - ObjectAnimator anim = ObjectAnimator.ofFloat(mPlayPauseReplayView, "alpha", 1f, 0f); - anim.setDuration(200); - anim.start(); - anim.addListener(new AnimatorListener() { - @Override - public void onAnimationStart(Animator animation) { - } - - @Override - public void onAnimationEnd(Animator animation) { - hidePlayButtonIfPlaying(); - } - - @Override - public void onAnimationCancel(Animator animation) { - hidePlayButtonIfPlaying(); - } - - @Override - public void onAnimationRepeat(Animator animation) { - } - }); - } else { - hidePlayButtonIfPlaying(); - } - } - - @Override - public void setTimes(int currentTime, int totalTime, int trimStartTime, int trimEndTime) { - mTimeBar.setTime(currentTime, totalTime, trimStartTime, trimEndTime); - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - if (super.onTouchEvent(event)) { - return true; - } - - // The special thing here is that the State.ENDED include both cases of - // the video completed and current == trimEnd. Both request a replay. - switch (event.getAction()) { - case MotionEvent.ACTION_DOWN: - if (mState == State.PLAYING || mState == State.PAUSED) { - mListener.onPlayPause(); - } else if (mState == State.ENDED) { - if (mCanReplay) { - mListener.onReplay(); - } - } - break; - case MotionEvent.ACTION_UP: - break; - } - return true; - } -} diff --git a/src/com/android/gallery3d/app/TrimTimeBar.java b/src/com/android/gallery3d/app/TrimTimeBar.java deleted file mode 100644 index f8dbc749e..000000000 --- a/src/com/android/gallery3d/app/TrimTimeBar.java +++ /dev/null @@ -1,339 +0,0 @@ -/* - * 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. - */ - -package com.android.gallery3d.app; - -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.Canvas; -import android.view.MotionEvent; - -import com.android.gallery3d.R; - -/** - * The trim time bar view, which includes the current and total time, the progress - * bar, and the scrubbers for current time, start and end time for trimming. - */ -public class TrimTimeBar extends TimeBar { - - public static final int SCRUBBER_NONE = 0; - public static final int SCRUBBER_START = 1; - public static final int SCRUBBER_CURRENT = 2; - public static final int SCRUBBER_END = 3; - - private int mPressedThumb = SCRUBBER_NONE; - - // On touch event, the setting order is Scrubber Position -> Time -> - // PlayedBar. At the setTimes(), activity can update the Time directly, then - // PlayedBar will be updated too. - private int mTrimStartScrubberLeft; - private int mTrimEndScrubberLeft; - - private int mTrimStartScrubberTop; - private int mTrimEndScrubberTop; - - private int mTrimStartTime; - private int mTrimEndTime; - - private final Bitmap mTrimStartScrubber; - private final Bitmap mTrimEndScrubber; - public TrimTimeBar(Context context, Listener listener) { - super(context, listener); - - mTrimStartTime = 0; - mTrimEndTime = 0; - mTrimStartScrubberLeft = 0; - mTrimEndScrubberLeft = 0; - mTrimStartScrubberTop = 0; - mTrimEndScrubberTop = 0; - - mTrimStartScrubber = BitmapFactory.decodeResource(getResources(), - R.drawable.text_select_handle_left); - mTrimEndScrubber = BitmapFactory.decodeResource(getResources(), - R.drawable.text_select_handle_right); - // Increase the size of this trimTimeBar, but minimize the scrubber - // touch padding since we have 3 scrubbers now. - mScrubberPadding = 0; - mVPaddingInPx = mVPaddingInPx * 3 / 2; - } - - private int getBarPosFromTime(int time) { - return mProgressBar.left + - (int) ((mProgressBar.width() * (long) time) / mTotalTime); - } - - private int trimStartScrubberTipOffset() { - return mTrimStartScrubber.getWidth() * 3 / 4; - } - - private int trimEndScrubberTipOffset() { - return mTrimEndScrubber.getWidth() / 4; - } - - // Based on all the time info (current, total, trimStart, trimEnd), we - // decide the playedBar size. - private void updatePlayedBarAndScrubberFromTime() { - // According to the Time, update the Played Bar - mPlayedBar.set(mProgressBar); - if (mTotalTime > 0) { - // set playedBar according to the trim time. - mPlayedBar.left = getBarPosFromTime(mTrimStartTime); - mPlayedBar.right = getBarPosFromTime(mCurrentTime); - if (!mScrubbing) { - mScrubberLeft = mPlayedBar.right - mScrubber.getWidth() / 2; - mTrimStartScrubberLeft = mPlayedBar.left - trimStartScrubberTipOffset(); - mTrimEndScrubberLeft = getBarPosFromTime(mTrimEndTime) - - trimEndScrubberTipOffset(); - } - } else { - // If the video is not prepared, just show the scrubber at the end - // of progressBar - mPlayedBar.right = mProgressBar.left; - mScrubberLeft = mProgressBar.left - mScrubber.getWidth() / 2; - mTrimStartScrubberLeft = mProgressBar.left - trimStartScrubberTipOffset(); - mTrimEndScrubberLeft = mProgressBar.right - trimEndScrubberTipOffset(); - } - } - - private void initTrimTimeIfNeeded() { - if (mTotalTime > 0 && mTrimEndTime == 0) { - mTrimEndTime = mTotalTime; - } - } - - private void update() { - initTrimTimeIfNeeded(); - updatePlayedBarAndScrubberFromTime(); - invalidate(); - } - - @Override - public void setTime(int currentTime, int totalTime, - int trimStartTime, int trimEndTime) { - if (mCurrentTime == currentTime && mTotalTime == totalTime - && mTrimStartTime == trimStartTime && mTrimEndTime == trimEndTime) { - return; - } - mCurrentTime = currentTime; - mTotalTime = totalTime; - mTrimStartTime = trimStartTime; - mTrimEndTime = trimEndTime; - update(); - } - - private int whichScrubber(float x, float y) { - if (inScrubber(x, y, mTrimStartScrubberLeft, mTrimStartScrubberTop, mTrimStartScrubber)) { - return SCRUBBER_START; - } else if (inScrubber(x, y, mTrimEndScrubberLeft, mTrimEndScrubberTop, mTrimEndScrubber)) { - return SCRUBBER_END; - } else if (inScrubber(x, y, mScrubberLeft, mScrubberTop, mScrubber)) { - return SCRUBBER_CURRENT; - } - return SCRUBBER_NONE; - } - - private boolean inScrubber(float x, float y, int startX, int startY, Bitmap scrubber) { - int scrubberRight = startX + scrubber.getWidth(); - int scrubberBottom = startY + scrubber.getHeight(); - return startX < x && x < scrubberRight && startY < y && y < scrubberBottom; - } - - private int clampScrubber(int scrubberLeft, int offset, int lowerBound, int upperBound) { - int max = upperBound - offset; - int min = lowerBound - offset; - return Math.min(max, Math.max(min, scrubberLeft)); - } - - private int getScrubberTime(int scrubberLeft, int offset) { - return (int) ((long) (scrubberLeft + offset - mProgressBar.left) - * mTotalTime / mProgressBar.width()); - } - - @Override - protected void onLayout(boolean changed, int l, int t, int r, int b) { - int w = r - l; - int h = b - t; - if (!mShowTimes && !mShowScrubber) { - mProgressBar.set(0, 0, w, h); - } else { - int margin = mScrubber.getWidth() / 3; - if (mShowTimes) { - margin += mTimeBounds.width(); - } - int progressY = h / 4; - int scrubberY = progressY - mScrubber.getHeight() / 2 + 1; - mScrubberTop = scrubberY; - mTrimStartScrubberTop = progressY; - mTrimEndScrubberTop = progressY; - mProgressBar.set( - getPaddingLeft() + margin, progressY, - w - getPaddingRight() - margin, progressY + 4); - } - update(); - } - - @Override - protected void onDraw(Canvas canvas) { - // draw progress bars - canvas.drawRect(mProgressBar, mProgressPaint); - canvas.drawRect(mPlayedBar, mPlayedPaint); - - if (mShowTimes) { - canvas.drawText( - stringForTime(mCurrentTime), - mTimeBounds.width() / 2 + getPaddingLeft(), - mTimeBounds.height() / 2 + mTrimStartScrubberTop, - mTimeTextPaint); - canvas.drawText( - stringForTime(mTotalTime), - getWidth() - getPaddingRight() - mTimeBounds.width() / 2, - mTimeBounds.height() / 2 + mTrimStartScrubberTop, - mTimeTextPaint); - } - - // draw extra scrubbers - if (mShowScrubber) { - canvas.drawBitmap(mScrubber, mScrubberLeft, mScrubberTop, null); - canvas.drawBitmap(mTrimStartScrubber, mTrimStartScrubberLeft, - mTrimStartScrubberTop, null); - canvas.drawBitmap(mTrimEndScrubber, mTrimEndScrubberLeft, - mTrimEndScrubberTop, null); - } - } - - private void updateTimeFromPos() { - mCurrentTime = getScrubberTime(mScrubberLeft, mScrubber.getWidth() / 2); - mTrimStartTime = getScrubberTime(mTrimStartScrubberLeft, trimStartScrubberTipOffset()); - mTrimEndTime = getScrubberTime(mTrimEndScrubberLeft, trimEndScrubberTipOffset()); - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - if (mShowScrubber) { - int x = (int) event.getX(); - int y = (int) event.getY(); - - switch (event.getAction()) { - case MotionEvent.ACTION_DOWN: - mPressedThumb = whichScrubber(x, y); - switch (mPressedThumb) { - case SCRUBBER_NONE: - break; - case SCRUBBER_CURRENT: - mScrubbing = true; - mScrubberCorrection = x - mScrubberLeft; - break; - case SCRUBBER_START: - mScrubbing = true; - mScrubberCorrection = x - mTrimStartScrubberLeft; - break; - case SCRUBBER_END: - mScrubbing = true; - mScrubberCorrection = x - mTrimEndScrubberLeft; - break; - } - if (mScrubbing == true) { - mListener.onScrubbingStart(); - return true; - } - break; - case MotionEvent.ACTION_MOVE: - if (mScrubbing) { - int seekToTime = -1; - int lowerBound = mTrimStartScrubberLeft + trimStartScrubberTipOffset(); - int upperBound = mTrimEndScrubberLeft + trimEndScrubberTipOffset(); - switch (mPressedThumb) { - case SCRUBBER_CURRENT: - mScrubberLeft = x - mScrubberCorrection; - mScrubberLeft = - clampScrubber(mScrubberLeft, - mScrubber.getWidth() / 2, - lowerBound, upperBound); - seekToTime = getScrubberTime(mScrubberLeft, - mScrubber.getWidth() / 2); - break; - case SCRUBBER_START: - mTrimStartScrubberLeft = x - mScrubberCorrection; - // Limit start <= end - if (mTrimStartScrubberLeft > mTrimEndScrubberLeft) { - mTrimStartScrubberLeft = mTrimEndScrubberLeft; - } - lowerBound = mProgressBar.left; - mTrimStartScrubberLeft = - clampScrubber(mTrimStartScrubberLeft, - trimStartScrubberTipOffset(), - lowerBound, upperBound); - seekToTime = getScrubberTime(mTrimStartScrubberLeft, - trimStartScrubberTipOffset()); - break; - case SCRUBBER_END: - mTrimEndScrubberLeft = x - mScrubberCorrection; - upperBound = mProgressBar.right; - mTrimEndScrubberLeft = - clampScrubber(mTrimEndScrubberLeft, - trimEndScrubberTipOffset(), - lowerBound, upperBound); - seekToTime = getScrubberTime(mTrimEndScrubberLeft, - trimEndScrubberTipOffset()); - break; - } - updateTimeFromPos(); - updatePlayedBarAndScrubberFromTime(); - if (seekToTime != -1) { - mListener.onScrubbingMove(seekToTime); - } - invalidate(); - return true; - } - break; - case MotionEvent.ACTION_CANCEL: - case MotionEvent.ACTION_UP: - if (mScrubbing) { - int seekToTime = 0; - switch (mPressedThumb) { - case SCRUBBER_CURRENT: - seekToTime = getScrubberTime(mScrubberLeft, - mScrubber.getWidth() / 2); - break; - case SCRUBBER_START: - seekToTime = getScrubberTime(mTrimStartScrubberLeft, - trimStartScrubberTipOffset()); - mScrubberLeft = mTrimStartScrubberLeft + - trimStartScrubberTipOffset() - mScrubber.getWidth() / 2; - break; - case SCRUBBER_END: - seekToTime = getScrubberTime(mTrimEndScrubberLeft, - trimEndScrubberTipOffset()); - mScrubberLeft = mTrimEndScrubberLeft + - trimEndScrubberTipOffset() - mScrubber.getWidth() / 2; - break; - } - updateTimeFromPos(); - mListener.onScrubbingEnd(seekToTime, - getScrubberTime(mTrimStartScrubberLeft, - trimStartScrubberTipOffset()), - getScrubberTime(mTrimEndScrubberLeft, trimEndScrubberTipOffset())); - mScrubbing = false; - mPressedThumb = SCRUBBER_NONE; - return true; - } - break; - } - } - return false; - } -} diff --git a/src/com/android/gallery3d/app/TrimVideo.java b/src/com/android/gallery3d/app/TrimVideo.java deleted file mode 100644 index 1e7728162..000000000 --- a/src/com/android/gallery3d/app/TrimVideo.java +++ /dev/null @@ -1,337 +0,0 @@ -/* - * 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. - */ - -package com.android.gallery3d.app; - -import android.app.ActionBar; -import android.app.Activity; -import android.app.ProgressDialog; -import android.content.Context; -import android.content.Intent; -import android.media.MediaPlayer; -import android.net.Uri; -import android.os.Bundle; -import android.os.Handler; -import android.provider.MediaStore; -import android.view.View; -import android.view.ViewGroup; -import android.view.Window; -import android.widget.TextView; -import android.widget.Toast; -import android.widget.VideoView; - -import com.android.gallery3d.R; -import com.android.gallery3d.util.SaveVideoFileInfo; -import com.android.gallery3d.util.SaveVideoFileUtils; - -import java.io.File; -import java.io.IOException; - -public class TrimVideo extends Activity implements - MediaPlayer.OnErrorListener, - MediaPlayer.OnCompletionListener, - ControllerOverlay.Listener { - - private VideoView mVideoView; - private TextView mSaveVideoTextView; - private TrimControllerOverlay mController; - private Context mContext; - private Uri mUri; - private final Handler mHandler = new Handler(); - public static final String TRIM_ACTION = "com.android.camera.action.TRIM"; - - public ProgressDialog mProgress; - - private int mTrimStartTime = 0; - private int mTrimEndTime = 0; - private int mVideoPosition = 0; - public static final String KEY_TRIM_START = "trim_start"; - public static final String KEY_TRIM_END = "trim_end"; - public static final String KEY_VIDEO_POSITION = "video_pos"; - private boolean mHasPaused = false; - - private String mSrcVideoPath = null; - private static final String TIME_STAMP_NAME = "'TRIM'_yyyyMMdd_HHmmss"; - private SaveVideoFileInfo mDstFileInfo = null; - - @Override - public void onCreate(Bundle savedInstanceState) { - mContext = getApplicationContext(); - super.onCreate(savedInstanceState); - - requestWindowFeature(Window.FEATURE_ACTION_BAR); - requestWindowFeature(Window.FEATURE_ACTION_BAR_OVERLAY); - - ActionBar actionBar = getActionBar(); - int displayOptions = ActionBar.DISPLAY_SHOW_HOME; - actionBar.setDisplayOptions(0, displayOptions); - displayOptions = ActionBar.DISPLAY_SHOW_CUSTOM; - actionBar.setDisplayOptions(displayOptions, displayOptions); - actionBar.setCustomView(R.layout.trim_menu); - - mSaveVideoTextView = (TextView) findViewById(R.id.start_trim); - mSaveVideoTextView.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View arg0) { - trimVideo(); - } - }); - mSaveVideoTextView.setEnabled(false); - - Intent intent = getIntent(); - mUri = intent.getData(); - mSrcVideoPath = intent.getStringExtra(PhotoPage.KEY_MEDIA_ITEM_PATH); - setContentView(R.layout.trim_view); - View rootView = findViewById(R.id.trim_view_root); - - mVideoView = (VideoView) rootView.findViewById(R.id.surface_view); - - mController = new TrimControllerOverlay(mContext); - ((ViewGroup) rootView).addView(mController.getView()); - mController.setListener(this); - mController.setCanReplay(true); - - mVideoView.setOnErrorListener(this); - mVideoView.setOnCompletionListener(this); - mVideoView.setVideoURI(mUri); - - playVideo(); - } - - @Override - public void onResume() { - super.onResume(); - if (mHasPaused) { - mVideoView.seekTo(mVideoPosition); - mVideoView.resume(); - mHasPaused = false; - } - mHandler.post(mProgressChecker); - } - - @Override - public void onPause() { - mHasPaused = true; - mHandler.removeCallbacksAndMessages(null); - mVideoPosition = mVideoView.getCurrentPosition(); - mVideoView.suspend(); - super.onPause(); - } - - @Override - public void onStop() { - if (mProgress != null) { - mProgress.dismiss(); - mProgress = null; - } - super.onStop(); - } - - @Override - public void onDestroy() { - mVideoView.stopPlayback(); - super.onDestroy(); - } - - private final Runnable mProgressChecker = new Runnable() { - @Override - public void run() { - int pos = setProgress(); - mHandler.postDelayed(mProgressChecker, 200 - (pos % 200)); - } - }; - - @Override - public void onSaveInstanceState(Bundle savedInstanceState) { - savedInstanceState.putInt(KEY_TRIM_START, mTrimStartTime); - savedInstanceState.putInt(KEY_TRIM_END, mTrimEndTime); - savedInstanceState.putInt(KEY_VIDEO_POSITION, mVideoPosition); - super.onSaveInstanceState(savedInstanceState); - } - - @Override - public void onRestoreInstanceState(Bundle savedInstanceState) { - super.onRestoreInstanceState(savedInstanceState); - mTrimStartTime = savedInstanceState.getInt(KEY_TRIM_START, 0); - mTrimEndTime = savedInstanceState.getInt(KEY_TRIM_END, 0); - mVideoPosition = savedInstanceState.getInt(KEY_VIDEO_POSITION, 0); - } - - // This updates the time bar display (if necessary). It is called by - // mProgressChecker and also from places where the time bar needs - // to be updated immediately. - private int setProgress() { - mVideoPosition = mVideoView.getCurrentPosition(); - // If the video position is smaller than the starting point of trimming, - // correct it. - if (mVideoPosition < mTrimStartTime) { - mVideoView.seekTo(mTrimStartTime); - mVideoPosition = mTrimStartTime; - } - // If the position is bigger than the end point of trimming, show the - // replay button and pause. - if (mVideoPosition >= mTrimEndTime && mTrimEndTime > 0) { - if (mVideoPosition > mTrimEndTime) { - mVideoView.seekTo(mTrimEndTime); - mVideoPosition = mTrimEndTime; - } - mController.showEnded(); - mVideoView.pause(); - } - - int duration = mVideoView.getDuration(); - if (duration > 0 && mTrimEndTime == 0) { - mTrimEndTime = duration; - } - mController.setTimes(mVideoPosition, duration, mTrimStartTime, mTrimEndTime); - return mVideoPosition; - } - - private void playVideo() { - mVideoView.start(); - mController.showPlaying(); - setProgress(); - } - - private void pauseVideo() { - mVideoView.pause(); - mController.showPaused(); - } - - - private boolean isModified() { - int delta = mTrimEndTime - mTrimStartTime; - - // Considering that we only trim at sync frame, we don't want to trim - // when the time interval is too short or too close to the origin. - if (delta < 100 || Math.abs(mVideoView.getDuration() - delta) < 100) { - return false; - } else { - return true; - } - } - - private void trimVideo() { - - mDstFileInfo = SaveVideoFileUtils.getDstMp4FileInfo(TIME_STAMP_NAME, - getContentResolver(), mUri, getString(R.string.folder_download)); - final File mSrcFile = new File(mSrcVideoPath); - - showProgressDialog(); - - new Thread(new Runnable() { - @Override - public void run() { - try { - VideoUtils.startTrim(mSrcFile, mDstFileInfo.mFile, - mTrimStartTime, mTrimEndTime); - // Update the database for adding a new video file. - SaveVideoFileUtils.insertContent(mDstFileInfo, - getContentResolver(), mUri); - } catch (IOException e) { - e.printStackTrace(); - } - // After trimming is done, trigger the UI changed. - mHandler.post(new Runnable() { - @Override - public void run() { - Toast.makeText(getApplicationContext(), - getString(R.string.save_into, mDstFileInfo.mFolderName), - Toast.LENGTH_SHORT) - .show(); - // TODO: change trimming into a service to avoid - // this progressDialog and add notification properly. - if (mProgress != null) { - mProgress.dismiss(); - mProgress = null; - // Show the result only when the activity not stopped. - Intent intent = new Intent(android.content.Intent.ACTION_VIEW); - intent.setDataAndType(Uri.fromFile(mDstFileInfo.mFile), "video/*"); - intent.putExtra(MediaStore.EXTRA_FINISH_ON_COMPLETION, false); - startActivity(intent); - finish(); - } - } - }); - } - }).start(); - } - - private void showProgressDialog() { - // create a background thread to trim the video. - // and show the progress. - mProgress = new ProgressDialog(this); - mProgress.setTitle(getString(R.string.trimming)); - mProgress.setMessage(getString(R.string.please_wait)); - // TODO: make this cancelable. - mProgress.setCancelable(false); - mProgress.setCanceledOnTouchOutside(false); - mProgress.show(); - } - - @Override - public void onPlayPause() { - if (mVideoView.isPlaying()) { - pauseVideo(); - } else { - playVideo(); - } - } - - @Override - public void onSeekStart() { - pauseVideo(); - } - - @Override - public void onSeekMove(int time) { - mVideoView.seekTo(time); - } - - @Override - public void onSeekEnd(int time, int start, int end) { - mVideoView.seekTo(time); - mTrimStartTime = start; - mTrimEndTime = end; - setProgress(); - // Enable save if there's modifications - mSaveVideoTextView.setEnabled(isModified()); - } - - @Override - public void onShown() { - } - - @Override - public void onHidden() { - } - - @Override - public void onReplay() { - mVideoView.seekTo(mTrimStartTime); - playVideo(); - } - - @Override - public void onCompletion(MediaPlayer mp) { - mController.showEnded(); - } - - @Override - public boolean onError(MediaPlayer mp, int what, int extra) { - return false; - } -} diff --git a/src/com/android/gallery3d/app/VideoUtils.java b/src/com/android/gallery3d/app/VideoUtils.java deleted file mode 100644 index a3c3ef273..000000000 --- a/src/com/android/gallery3d/app/VideoUtils.java +++ /dev/null @@ -1,328 +0,0 @@ -/* - * 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. - */ - -// Modified example based on mp4parser google code open source project. -// http://code.google.com/p/mp4parser/source/browse/trunk/examples/src/main/java/com/googlecode/mp4parser/ShortenExample.java - -package com.android.gallery3d.app; - -import android.media.MediaCodec.BufferInfo; -import android.media.MediaExtractor; -import android.media.MediaFormat; -import android.media.MediaMetadataRetriever; -import android.media.MediaMuxer; -import android.util.Log; - -import com.android.gallery3d.common.ApiHelper; -import com.android.gallery3d.util.SaveVideoFileInfo; -import com.coremedia.iso.IsoFile; -import com.coremedia.iso.boxes.TimeToSampleBox; -import com.googlecode.mp4parser.authoring.Movie; -import com.googlecode.mp4parser.authoring.Track; -import com.googlecode.mp4parser.authoring.builder.DefaultMp4Builder; -import com.googlecode.mp4parser.authoring.container.mp4.MovieCreator; -import com.googlecode.mp4parser.authoring.tracks.CroppedTrack; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.RandomAccessFile; -import java.nio.ByteBuffer; -import java.nio.channels.FileChannel; -import java.util.Arrays; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; - -public class VideoUtils { - private static final String LOGTAG = "VideoUtils"; - private static final int DEFAULT_BUFFER_SIZE = 1 * 1024 * 1024; - - /** - * Remove the sound track. - */ - public static void startMute(String filePath, SaveVideoFileInfo dstFileInfo) - throws IOException { - if (ApiHelper.HAS_MEDIA_MUXER) { - genVideoUsingMuxer(filePath, dstFileInfo.mFile.getPath(), -1, -1, - false, true); - } else { - startMuteUsingMp4Parser(filePath, dstFileInfo); - } - } - - /** - * Shortens/Crops tracks - */ - public static void startTrim(File src, File dst, int startMs, int endMs) - throws IOException { - if (ApiHelper.HAS_MEDIA_MUXER) { - genVideoUsingMuxer(src.getPath(), dst.getPath(), startMs, endMs, - true, true); - } else { - trimUsingMp4Parser(src, dst, startMs, endMs); - } - } - - private static void startMuteUsingMp4Parser(String filePath, - SaveVideoFileInfo dstFileInfo) throws FileNotFoundException, IOException { - File dst = dstFileInfo.mFile; - File src = new File(filePath); - RandomAccessFile randomAccessFile = new RandomAccessFile(src, "r"); - Movie movie = MovieCreator.build(randomAccessFile.getChannel()); - - // remove all tracks we will create new tracks from the old - List tracks = movie.getTracks(); - movie.setTracks(new LinkedList()); - - for (Track track : tracks) { - if (track.getHandler().equals("vide")) { - movie.addTrack(track); - } - } - writeMovieIntoFile(dst, movie); - randomAccessFile.close(); - } - - private static void writeMovieIntoFile(File dst, Movie movie) - throws IOException { - if (!dst.exists()) { - dst.createNewFile(); - } - - IsoFile out = new DefaultMp4Builder().build(movie); - FileOutputStream fos = new FileOutputStream(dst); - FileChannel fc = fos.getChannel(); - out.getBox(fc); // This one build up the memory. - - fc.close(); - fos.close(); - } - - /** - * @param srcPath the path of source video file. - * @param dstPath the path of destination video file. - * @param startMs starting time in milliseconds for trimming. Set to - * negative if starting from beginning. - * @param endMs end time for trimming in milliseconds. Set to negative if - * no trimming at the end. - * @param useAudio true if keep the audio track from the source. - * @param useVideo true if keep the video track from the source. - * @throws IOException - */ - private static void genVideoUsingMuxer(String srcPath, String dstPath, - int startMs, int endMs, boolean useAudio, boolean useVideo) - throws IOException { - // Set up MediaExtractor to read from the source. - MediaExtractor extractor = new MediaExtractor(); - extractor.setDataSource(srcPath); - - int trackCount = extractor.getTrackCount(); - - // Set up MediaMuxer for the destination. - MediaMuxer muxer; - muxer = new MediaMuxer(dstPath, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4); - - // Set up the tracks and retrieve the max buffer size for selected - // tracks. - HashMap indexMap = new HashMap(trackCount); - int bufferSize = -1; - for (int i = 0; i < trackCount; i++) { - MediaFormat format = extractor.getTrackFormat(i); - String mime = format.getString(MediaFormat.KEY_MIME); - - boolean selectCurrentTrack = false; - - if (mime.startsWith("audio/") && useAudio) { - selectCurrentTrack = true; - } else if (mime.startsWith("video/") && useVideo) { - selectCurrentTrack = true; - } - - if (selectCurrentTrack) { - extractor.selectTrack(i); - int dstIndex = muxer.addTrack(format); - indexMap.put(i, dstIndex); - if (format.containsKey(MediaFormat.KEY_MAX_INPUT_SIZE)) { - int newSize = format.getInteger(MediaFormat.KEY_MAX_INPUT_SIZE); - bufferSize = newSize > bufferSize ? newSize : bufferSize; - } - } - } - - if (bufferSize < 0) { - bufferSize = DEFAULT_BUFFER_SIZE; - } - - // Set up the orientation and starting time for extractor. - MediaMetadataRetriever retrieverSrc = new MediaMetadataRetriever(); - retrieverSrc.setDataSource(srcPath); - String degreesString = retrieverSrc.extractMetadata( - MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION); - if (degreesString != null) { - int degrees = Integer.parseInt(degreesString); - if (degrees >= 0) { - muxer.setOrientationHint(degrees); - } - } - - if (startMs > 0) { - extractor.seekTo(startMs * 1000, MediaExtractor.SEEK_TO_CLOSEST_SYNC); - } - - // Copy the samples from MediaExtractor to MediaMuxer. We will loop - // for copying each sample and stop when we get to the end of the source - // file or exceed the end time of the trimming. - int offset = 0; - int trackIndex = -1; - ByteBuffer dstBuf = ByteBuffer.allocate(bufferSize); - BufferInfo bufferInfo = new BufferInfo(); - - muxer.start(); - while (true) { - bufferInfo.offset = offset; - bufferInfo.size = extractor.readSampleData(dstBuf, offset); - if (bufferInfo.size < 0) { - Log.d(LOGTAG, "Saw input EOS."); - bufferInfo.size = 0; - break; - } else { - bufferInfo.presentationTimeUs = extractor.getSampleTime(); - if (endMs > 0 && bufferInfo.presentationTimeUs > (endMs * 1000)) { - Log.d(LOGTAG, "The current sample is over the trim end time."); - break; - } else { - bufferInfo.flags = extractor.getSampleFlags(); - trackIndex = extractor.getSampleTrackIndex(); - - muxer.writeSampleData(indexMap.get(trackIndex), dstBuf, - bufferInfo); - extractor.advance(); - } - } - } - - muxer.stop(); - muxer.release(); - return; - } - - private static void trimUsingMp4Parser(File src, File dst, int startMs, int endMs) - throws FileNotFoundException, IOException { - RandomAccessFile randomAccessFile = new RandomAccessFile(src, "r"); - Movie movie = MovieCreator.build(randomAccessFile.getChannel()); - - // remove all tracks we will create new tracks from the old - List tracks = movie.getTracks(); - movie.setTracks(new LinkedList()); - - double startTime = startMs / 1000; - double endTime = endMs / 1000; - - boolean timeCorrected = false; - - // Here we try to find a track that has sync samples. Since we can only - // start decoding at such a sample we SHOULD make sure that the start of - // the new fragment is exactly such a frame. - for (Track track : tracks) { - if (track.getSyncSamples() != null && track.getSyncSamples().length > 0) { - if (timeCorrected) { - // This exception here could be a false positive in case we - // have multiple tracks with sync samples at exactly the - // same positions. E.g. a single movie containing multiple - // qualities of the same video (Microsoft Smooth Streaming - // file) - throw new RuntimeException( - "The startTime has already been corrected by" + - " another track with SyncSample. Not Supported."); - } - startTime = correctTimeToSyncSample(track, startTime, false); - endTime = correctTimeToSyncSample(track, endTime, true); - timeCorrected = true; - } - } - - for (Track track : tracks) { - long currentSample = 0; - double currentTime = 0; - long startSample = -1; - long endSample = -1; - - for (int i = 0; i < track.getDecodingTimeEntries().size(); i++) { - TimeToSampleBox.Entry entry = track.getDecodingTimeEntries().get(i); - for (int j = 0; j < entry.getCount(); j++) { - // entry.getDelta() is the amount of time the current sample - // covers. - - if (currentTime <= startTime) { - // current sample is still before the new starttime - startSample = currentSample; - } - if (currentTime <= endTime) { - // current sample is after the new start time and still - // before the new endtime - endSample = currentSample; - } else { - // current sample is after the end of the cropped video - break; - } - currentTime += (double) entry.getDelta() - / (double) track.getTrackMetaData().getTimescale(); - currentSample++; - } - } - movie.addTrack(new CroppedTrack(track, startSample, endSample)); - } - writeMovieIntoFile(dst, movie); - randomAccessFile.close(); - } - - private static double correctTimeToSyncSample(Track track, double cutHere, - boolean next) { - double[] timeOfSyncSamples = new double[track.getSyncSamples().length]; - long currentSample = 0; - double currentTime = 0; - for (int i = 0; i < track.getDecodingTimeEntries().size(); i++) { - TimeToSampleBox.Entry entry = track.getDecodingTimeEntries().get(i); - for (int j = 0; j < entry.getCount(); j++) { - if (Arrays.binarySearch(track.getSyncSamples(), currentSample + 1) >= 0) { - // samples always start with 1 but we start with zero - // therefore +1 - timeOfSyncSamples[Arrays.binarySearch( - track.getSyncSamples(), currentSample + 1)] = currentTime; - } - currentTime += (double) entry.getDelta() - / (double) track.getTrackMetaData().getTimescale(); - currentSample++; - } - } - double previous = 0; - for (double timeOfSyncSample : timeOfSyncSamples) { - if (timeOfSyncSample > cutHere) { - if (next) { - return timeOfSyncSample; - } else { - return previous; - } - } - previous = timeOfSyncSample; - } - return timeOfSyncSamples[timeOfSyncSamples.length - 1]; - } - -} diff --git a/src/com/android/gallery3d/app/Wallpaper.java b/src/com/android/gallery3d/app/Wallpaper.java deleted file mode 100644 index b0a26c236..000000000 --- a/src/com/android/gallery3d/app/Wallpaper.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * 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.gallery3d.app; - -import android.annotation.TargetApi; -import android.app.Activity; -import android.content.Intent; -import android.graphics.Point; -import android.net.Uri; -import android.os.Build; -import android.os.Bundle; -import android.view.Display; - -import com.android.gallery3d.common.ApiHelper; -import com.android.gallery3d.filtershow.crop.CropActivity; -import com.android.gallery3d.filtershow.crop.CropExtras; - -/** - * Wallpaper picker for the gallery application. This just redirects to the - * standard pick action. - */ -public class Wallpaper extends Activity { - @SuppressWarnings("unused") - private static final String TAG = "Wallpaper"; - - private static final String IMAGE_TYPE = "image/*"; - private static final String KEY_STATE = "activity-state"; - private static final String KEY_PICKED_ITEM = "picked-item"; - - private static final int STATE_INIT = 0; - private static final int STATE_PHOTO_PICKED = 1; - - private int mState = STATE_INIT; - private Uri mPickedItem; - - @Override - protected void onCreate(Bundle bundle) { - super.onCreate(bundle); - if (bundle != null) { - mState = bundle.getInt(KEY_STATE); - mPickedItem = (Uri) bundle.getParcelable(KEY_PICKED_ITEM); - } - } - - @Override - protected void onSaveInstanceState(Bundle saveState) { - saveState.putInt(KEY_STATE, mState); - if (mPickedItem != null) { - saveState.putParcelable(KEY_PICKED_ITEM, mPickedItem); - } - } - - @SuppressWarnings("deprecation") - @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2) - private Point getDefaultDisplaySize(Point size) { - Display d = getWindowManager().getDefaultDisplay(); - if (Build.VERSION.SDK_INT >= ApiHelper.VERSION_CODES.HONEYCOMB_MR2) { - d.getSize(size); - } else { - size.set(d.getWidth(), d.getHeight()); - } - return size; - } - - @SuppressWarnings("fallthrough") - @Override - protected void onResume() { - super.onResume(); - Intent intent = getIntent(); - switch (mState) { - case STATE_INIT: { - mPickedItem = intent.getData(); - if (mPickedItem == null) { - Intent request = new Intent(Intent.ACTION_GET_CONTENT) - .setClass(this, DialogPicker.class) - .setType(IMAGE_TYPE); - startActivityForResult(request, STATE_PHOTO_PICKED); - return; - } - mState = STATE_PHOTO_PICKED; - // fall-through - } - case STATE_PHOTO_PICKED: { - int width = getWallpaperDesiredMinimumWidth(); - int height = getWallpaperDesiredMinimumHeight(); - Point size = getDefaultDisplaySize(new Point()); - float spotlightX = (float) size.x / width; - float spotlightY = (float) size.y / height; - Intent request = new Intent(CropActivity.CROP_ACTION) - .setDataAndType(mPickedItem, IMAGE_TYPE) - .addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT) - .putExtra(CropExtras.KEY_OUTPUT_X, width) - .putExtra(CropExtras.KEY_OUTPUT_Y, height) - .putExtra(CropExtras.KEY_ASPECT_X, width) - .putExtra(CropExtras.KEY_ASPECT_Y, height) - .putExtra(CropExtras.KEY_SPOTLIGHT_X, spotlightX) - .putExtra(CropExtras.KEY_SPOTLIGHT_Y, spotlightY) - .putExtra(CropExtras.KEY_SCALE, true) - .putExtra(CropExtras.KEY_SCALE_UP_IF_NEEDED, true) - .putExtra(CropExtras.KEY_SET_AS_WALLPAPER, true); - startActivity(request); - finish(); - } - } - } - - @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { - if (resultCode != RESULT_OK) { - setResult(resultCode); - finish(); - return; - } - mState = requestCode; - if (mState == STATE_PHOTO_PICKED) { - mPickedItem = data.getData(); - } - - // onResume() would be called next - } -} diff --git a/src/com/android/gallery3d/data/ActionImage.java b/src/com/android/gallery3d/data/ActionImage.java deleted file mode 100644 index 58e30b146..000000000 --- a/src/com/android/gallery3d/data/ActionImage.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * 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. - */ - -package com.android.gallery3d.data; - -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.BitmapRegionDecoder; -import android.net.Uri; - -import com.android.gallery3d.app.GalleryApp; -import com.android.gallery3d.common.BitmapUtils; -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.util.ThreadPool.Job; -import com.android.gallery3d.util.ThreadPool.JobContext; - -public class ActionImage extends MediaItem { - @SuppressWarnings("unused") - private static final String TAG = "ActionImage"; - private GalleryApp mApplication; - private int mResourceId; - - public ActionImage(Path path, GalleryApp application, int resourceId) { - super(path, nextVersionNumber()); - mApplication = Utils.checkNotNull(application); - mResourceId = resourceId; - } - - @Override - public Job requestImage(int type) { - return new BitmapJob(type); - } - - @Override - public Job requestLargeImage() { - return null; - } - - private class BitmapJob implements Job { - private int mType; - - protected BitmapJob(int type) { - mType = type; - } - - @Override - public Bitmap run(JobContext jc) { - int targetSize = MediaItem.getTargetSize(mType); - Bitmap bitmap = BitmapFactory.decodeResource(mApplication.getResources(), - mResourceId); - - if (mType == MediaItem.TYPE_MICROTHUMBNAIL) { - bitmap = BitmapUtils.resizeAndCropCenter(bitmap, targetSize, true); - } else { - bitmap = BitmapUtils.resizeDownBySideLength(bitmap, targetSize, true); - } - return bitmap; - } - } - - @Override - public int getSupportedOperations() { - return SUPPORT_ACTION; - } - - @Override - public int getMediaType() { - return MEDIA_TYPE_UNKNOWN; - } - - @Override - public Uri getContentUri() { - return null; - } - - @Override - public String getMimeType() { - return ""; - } - - @Override - public int getWidth() { - return 0; - } - - @Override - public int getHeight() { - return 0; - } -} diff --git a/src/com/android/gallery3d/data/BucketHelper.java b/src/com/android/gallery3d/data/BucketHelper.java deleted file mode 100644 index 3418dafb7..000000000 --- a/src/com/android/gallery3d/data/BucketHelper.java +++ /dev/null @@ -1,241 +0,0 @@ -package com.android.gallery3d.data; - -import android.annotation.TargetApi; -import android.content.ContentResolver; -import android.database.Cursor; -import android.net.Uri; -import android.provider.MediaStore.Files; -import android.provider.MediaStore.Files.FileColumns; -import android.provider.MediaStore.Images; -import android.provider.MediaStore.Images.ImageColumns; -import android.provider.MediaStore.Video; -import android.util.Log; - -import com.android.gallery3d.common.ApiHelper; -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.util.ThreadPool.JobContext; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Comparator; -import java.util.HashMap; - -class BucketHelper { - - private static final String TAG = "BucketHelper"; - private static final String EXTERNAL_MEDIA = "external"; - - // BUCKET_DISPLAY_NAME is a string like "Camera" which is the directory - // name of where an image or video is in. BUCKET_ID is a hash of the path - // name of that directory (see computeBucketValues() in MediaProvider for - // details). MEDIA_TYPE is video, image, audio, etc. - // - // The "albums" are not explicitly recorded in the database, but each image - // or video has the two columns (BUCKET_ID, MEDIA_TYPE). We define an - // "album" to be the collection of images/videos which have the same value - // for the two columns. - // - // The goal of the query (used in loadSubMediaSetsFromFilesTable()) is to - // find all albums, that is, all unique values for (BUCKET_ID, MEDIA_TYPE). - // In the meantime sort them by the timestamp of the latest image/video in - // each of the album. - // - // The order of columns below is important: it must match to the index in - // MediaStore. - private static final String[] PROJECTION_BUCKET = { - ImageColumns.BUCKET_ID, - FileColumns.MEDIA_TYPE, - ImageColumns.BUCKET_DISPLAY_NAME}; - - // The indices should match the above projections. - private static final int INDEX_BUCKET_ID = 0; - private static final int INDEX_MEDIA_TYPE = 1; - private static final int INDEX_BUCKET_NAME = 2; - - // We want to order the albums by reverse chronological order. We abuse the - // "WHERE" parameter to insert a "GROUP BY" clause into the SQL statement. - // The template for "WHERE" parameter is like: - // SELECT ... FROM ... WHERE (%s) - // and we make it look like: - // SELECT ... FROM ... WHERE (1) GROUP BY 1,(2) - // The "(1)" means true. The "1,(2)" means the first two columns specified - // after SELECT. Note that because there is a ")" in the template, we use - // "(2" to match it. - private static final String BUCKET_GROUP_BY = "1) GROUP BY 1,(2"; - - private static final String BUCKET_ORDER_BY = "MAX(datetaken) DESC"; - - // Before HoneyComb there is no Files table. Thus, we need to query the - // bucket info from the Images and Video tables and then merge them - // together. - // - // A bucket can exist in both tables. In this case, we need to find the - // latest timestamp from the two tables and sort ourselves. So we add the - // MAX(date_taken) to the projection and remove the media_type since we - // already know the media type from the table we query from. - private static final String[] PROJECTION_BUCKET_IN_ONE_TABLE = { - ImageColumns.BUCKET_ID, - "MAX(datetaken)", - ImageColumns.BUCKET_DISPLAY_NAME}; - - // We keep the INDEX_BUCKET_ID and INDEX_BUCKET_NAME the same as - // PROJECTION_BUCKET so we can reuse the values defined before. - private static final int INDEX_DATE_TAKEN = 1; - - // When query from the Images or Video tables, we only need to group by BUCKET_ID. - private static final String BUCKET_GROUP_BY_IN_ONE_TABLE = "1) GROUP BY (1"; - - public static BucketEntry[] loadBucketEntries( - JobContext jc, ContentResolver resolver, int type) { - if (ApiHelper.HAS_MEDIA_PROVIDER_FILES_TABLE) { - return loadBucketEntriesFromFilesTable(jc, resolver, type); - } else { - return loadBucketEntriesFromImagesAndVideoTable(jc, resolver, type); - } - } - - private static void updateBucketEntriesFromTable(JobContext jc, - ContentResolver resolver, Uri tableUri, HashMap buckets) { - Cursor cursor = resolver.query(tableUri, PROJECTION_BUCKET_IN_ONE_TABLE, - BUCKET_GROUP_BY_IN_ONE_TABLE, null, null); - if (cursor == null) { - Log.w(TAG, "cannot open media database: " + tableUri); - return; - } - try { - while (cursor.moveToNext()) { - int bucketId = cursor.getInt(INDEX_BUCKET_ID); - int dateTaken = cursor.getInt(INDEX_DATE_TAKEN); - BucketEntry entry = buckets.get(bucketId); - if (entry == null) { - entry = new BucketEntry(bucketId, cursor.getString(INDEX_BUCKET_NAME)); - buckets.put(bucketId, entry); - entry.dateTaken = dateTaken; - } else { - entry.dateTaken = Math.max(entry.dateTaken, dateTaken); - } - } - } finally { - Utils.closeSilently(cursor); - } - } - - private static BucketEntry[] loadBucketEntriesFromImagesAndVideoTable( - JobContext jc, ContentResolver resolver, int type) { - HashMap buckets = new HashMap(64); - if ((type & MediaObject.MEDIA_TYPE_IMAGE) != 0) { - updateBucketEntriesFromTable( - jc, resolver, Images.Media.EXTERNAL_CONTENT_URI, buckets); - } - if ((type & MediaObject.MEDIA_TYPE_VIDEO) != 0) { - updateBucketEntriesFromTable( - jc, resolver, Video.Media.EXTERNAL_CONTENT_URI, buckets); - } - BucketEntry[] entries = buckets.values().toArray(new BucketEntry[buckets.size()]); - Arrays.sort(entries, new Comparator() { - @Override - public int compare(BucketEntry a, BucketEntry b) { - // sorted by dateTaken in descending order - return b.dateTaken - a.dateTaken; - } - }); - return entries; - } - - private static BucketEntry[] loadBucketEntriesFromFilesTable( - JobContext jc, ContentResolver resolver, int type) { - Uri uri = getFilesContentUri(); - - Cursor cursor = resolver.query(uri, - PROJECTION_BUCKET, BUCKET_GROUP_BY, - null, BUCKET_ORDER_BY); - if (cursor == null) { - Log.w(TAG, "cannot open local database: " + uri); - return new BucketEntry[0]; - } - ArrayList buffer = new ArrayList(); - int typeBits = 0; - if ((type & MediaObject.MEDIA_TYPE_IMAGE) != 0) { - typeBits |= (1 << FileColumns.MEDIA_TYPE_IMAGE); - } - if ((type & MediaObject.MEDIA_TYPE_VIDEO) != 0) { - typeBits |= (1 << FileColumns.MEDIA_TYPE_VIDEO); - } - try { - while (cursor.moveToNext()) { - if ((typeBits & (1 << cursor.getInt(INDEX_MEDIA_TYPE))) != 0) { - BucketEntry entry = new BucketEntry( - cursor.getInt(INDEX_BUCKET_ID), - cursor.getString(INDEX_BUCKET_NAME)); - if (!buffer.contains(entry)) { - buffer.add(entry); - } - } - if (jc.isCancelled()) return null; - } - } finally { - Utils.closeSilently(cursor); - } - return buffer.toArray(new BucketEntry[buffer.size()]); - } - - private static String getBucketNameInTable( - ContentResolver resolver, Uri tableUri, int bucketId) { - String selectionArgs[] = new String[] {String.valueOf(bucketId)}; - Uri uri = tableUri.buildUpon() - .appendQueryParameter("limit", "1") - .build(); - Cursor cursor = resolver.query(uri, PROJECTION_BUCKET_IN_ONE_TABLE, - "bucket_id = ?", selectionArgs, null); - try { - if (cursor != null && cursor.moveToNext()) { - return cursor.getString(INDEX_BUCKET_NAME); - } - } finally { - Utils.closeSilently(cursor); - } - return null; - } - - @TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB) - private static Uri getFilesContentUri() { - return Files.getContentUri(EXTERNAL_MEDIA); - } - - public static String getBucketName(ContentResolver resolver, int bucketId) { - if (ApiHelper.HAS_MEDIA_PROVIDER_FILES_TABLE) { - String result = getBucketNameInTable(resolver, getFilesContentUri(), bucketId); - return result == null ? "" : result; - } else { - String result = getBucketNameInTable( - resolver, Images.Media.EXTERNAL_CONTENT_URI, bucketId); - if (result != null) return result; - result = getBucketNameInTable( - resolver, Video.Media.EXTERNAL_CONTENT_URI, bucketId); - return result == null ? "" : result; - } - } - - public static class BucketEntry { - public String bucketName; - public int bucketId; - public int dateTaken; - - public BucketEntry(int id, String name) { - bucketId = id; - bucketName = Utils.ensureNotNull(name); - } - - @Override - public int hashCode() { - return bucketId; - } - - @Override - public boolean equals(Object object) { - if (!(object instanceof BucketEntry)) return false; - BucketEntry entry = (BucketEntry) object; - return bucketId == entry.bucketId; - } - } -} diff --git a/src/com/android/gallery3d/data/BytesBufferPool.java b/src/com/android/gallery3d/data/BytesBufferPool.java deleted file mode 100644 index d2da323fc..000000000 --- a/src/com/android/gallery3d/data/BytesBufferPool.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * 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. - */ - -package com.android.gallery3d.data; - -import com.android.gallery3d.util.ThreadPool.JobContext; - -import java.io.FileDescriptor; -import java.io.FileInputStream; -import java.io.IOException; -import java.util.ArrayList; - -public class BytesBufferPool { - - private static final int READ_STEP = 4096; - - public static class BytesBuffer { - public byte[] data; - public int offset; - public int length; - - private BytesBuffer(int capacity) { - this.data = new byte[capacity]; - } - - // an helper function to read content from FileDescriptor - public void readFrom(JobContext jc, FileDescriptor fd) throws IOException { - FileInputStream fis = new FileInputStream(fd); - length = 0; - try { - int capacity = data.length; - while (true) { - int step = Math.min(READ_STEP, capacity - length); - int rc = fis.read(data, length, step); - if (rc < 0 || jc.isCancelled()) return; - length += rc; - - if (length == capacity) { - byte[] newData = new byte[data.length * 2]; - System.arraycopy(data, 0, newData, 0, data.length); - data = newData; - capacity = data.length; - } - } - } finally { - fis.close(); - } - } - } - - private final int mPoolSize; - private final int mBufferSize; - private final ArrayList mList; - - public BytesBufferPool(int poolSize, int bufferSize) { - mList = new ArrayList(poolSize); - mPoolSize = poolSize; - mBufferSize = bufferSize; - } - - public synchronized BytesBuffer get() { - int n = mList.size(); - return n > 0 ? mList.remove(n - 1) : new BytesBuffer(mBufferSize); - } - - public synchronized void recycle(BytesBuffer buffer) { - if (buffer.data.length != mBufferSize) return; - if (mList.size() < mPoolSize) { - buffer.offset = 0; - buffer.length = 0; - mList.add(buffer); - } - } - - public synchronized void clear() { - mList.clear(); - } -} diff --git a/src/com/android/gallery3d/data/CameraShortcutImage.java b/src/com/android/gallery3d/data/CameraShortcutImage.java deleted file mode 100644 index 865270b4c..000000000 --- a/src/com/android/gallery3d/data/CameraShortcutImage.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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. - */ - -package com.android.gallery3d.data; - -import com.android.gallery3d.R; -import com.android.gallery3d.app.GalleryApp; - -public class CameraShortcutImage extends ActionImage { - @SuppressWarnings("unused") - private static final String TAG = "CameraShortcutImage"; - - public CameraShortcutImage(Path path, GalleryApp application) { - super(path, application, R.drawable.placeholder_camera); - } - - @Override - public int getSupportedOperations() { - return super.getSupportedOperations() | SUPPORT_CAMERA_SHORTCUT; - } -} diff --git a/src/com/android/gallery3d/data/ChangeNotifier.java b/src/com/android/gallery3d/data/ChangeNotifier.java deleted file mode 100644 index 558a8648e..000000000 --- a/src/com/android/gallery3d/data/ChangeNotifier.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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.gallery3d.data; - -import android.net.Uri; - -import com.android.gallery3d.app.GalleryApp; - -import java.util.concurrent.atomic.AtomicBoolean; - -// This handles change notification for media sets. -public class ChangeNotifier { - - private MediaSet mMediaSet; - private AtomicBoolean mContentDirty = new AtomicBoolean(true); - - public ChangeNotifier(MediaSet set, Uri uri, GalleryApp application) { - mMediaSet = set; - application.getDataManager().registerChangeNotifier(uri, this); - } - - public ChangeNotifier(MediaSet set, Uri[] uris, GalleryApp application) { - mMediaSet = set; - for (int i = 0; i < uris.length; i++) { - application.getDataManager().registerChangeNotifier(uris[i], this); - } - } - - // Returns the dirty flag and clear it. - public boolean isDirty() { - return mContentDirty.compareAndSet(true, false); - } - - public void fakeChange() { - onChange(false); - } - - protected void onChange(boolean selfChange) { - if (mContentDirty.compareAndSet(false, true)) { - mMediaSet.notifyContentChanged(); - } - } -} \ No newline at end of file diff --git a/src/com/android/gallery3d/data/ClusterAlbum.java b/src/com/android/gallery3d/data/ClusterAlbum.java deleted file mode 100644 index 8681952bf..000000000 --- a/src/com/android/gallery3d/data/ClusterAlbum.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * 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.gallery3d.data; - -import java.util.ArrayList; - -public class ClusterAlbum extends MediaSet implements ContentListener { - @SuppressWarnings("unused") - private static final String TAG = "ClusterAlbum"; - private ArrayList mPaths = new ArrayList(); - private String mName = ""; - private DataManager mDataManager; - private MediaSet mClusterAlbumSet; - private MediaItem mCover; - - public ClusterAlbum(Path path, DataManager dataManager, - MediaSet clusterAlbumSet) { - super(path, nextVersionNumber()); - mDataManager = dataManager; - mClusterAlbumSet = clusterAlbumSet; - mClusterAlbumSet.addContentListener(this); - } - - public void setCoverMediaItem(MediaItem cover) { - mCover = cover; - } - - @Override - public MediaItem getCoverMediaItem() { - return mCover != null ? mCover : super.getCoverMediaItem(); - } - - void setMediaItems(ArrayList paths) { - mPaths = paths; - } - - ArrayList getMediaItems() { - return mPaths; - } - - public void setName(String name) { - mName = name; - } - - @Override - public String getName() { - return mName; - } - - @Override - public int getMediaItemCount() { - return mPaths.size(); - } - - @Override - public ArrayList getMediaItem(int start, int count) { - return getMediaItemFromPath(mPaths, start, count, mDataManager); - } - - public static ArrayList getMediaItemFromPath( - ArrayList paths, int start, int count, - DataManager dataManager) { - if (start >= paths.size()) { - return new ArrayList(); - } - int end = Math.min(start + count, paths.size()); - ArrayList subset = new ArrayList(paths.subList(start, end)); - final MediaItem[] buf = new MediaItem[end - start]; - ItemConsumer consumer = new ItemConsumer() { - @Override - public void consume(int index, MediaItem item) { - buf[index] = item; - } - }; - dataManager.mapMediaItems(subset, consumer, 0); - ArrayList result = new ArrayList(end - start); - for (int i = 0; i < buf.length; i++) { - result.add(buf[i]); - } - return result; - } - - @Override - protected int enumerateMediaItems(ItemConsumer consumer, int startIndex) { - mDataManager.mapMediaItems(mPaths, consumer, startIndex); - return mPaths.size(); - } - - @Override - public int getTotalMediaItemCount() { - return mPaths.size(); - } - - @Override - public long reload() { - if (mClusterAlbumSet.reload() > mDataVersion) { - mDataVersion = nextVersionNumber(); - } - return mDataVersion; - } - - @Override - public void onContentDirty() { - notifyContentChanged(); - } - - @Override - public int getSupportedOperations() { - return SUPPORT_SHARE | SUPPORT_DELETE | SUPPORT_INFO; - } - - @Override - public void delete() { - ItemConsumer consumer = new ItemConsumer() { - @Override - public void consume(int index, MediaItem item) { - if ((item.getSupportedOperations() & SUPPORT_DELETE) != 0) { - item.delete(); - } - } - }; - mDataManager.mapMediaItems(mPaths, consumer, 0); - } - - @Override - public boolean isLeafAlbum() { - return true; - } -} diff --git a/src/com/android/gallery3d/data/ClusterAlbumSet.java b/src/com/android/gallery3d/data/ClusterAlbumSet.java deleted file mode 100644 index cb212ba36..000000000 --- a/src/com/android/gallery3d/data/ClusterAlbumSet.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * 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.gallery3d.data; - -import android.content.Context; -import android.net.Uri; - -import com.android.gallery3d.app.GalleryApp; - -import java.util.ArrayList; -import java.util.HashSet; - -public class ClusterAlbumSet extends MediaSet implements ContentListener { - @SuppressWarnings("unused") - private static final String TAG = "ClusterAlbumSet"; - private GalleryApp mApplication; - private MediaSet mBaseSet; - private int mKind; - private ArrayList mAlbums = new ArrayList(); - private boolean mFirstReloadDone; - - public ClusterAlbumSet(Path path, GalleryApp application, - MediaSet baseSet, int kind) { - super(path, INVALID_DATA_VERSION); - mApplication = application; - mBaseSet = baseSet; - mKind = kind; - baseSet.addContentListener(this); - } - - @Override - public MediaSet getSubMediaSet(int index) { - return mAlbums.get(index); - } - - @Override - public int getSubMediaSetCount() { - return mAlbums.size(); - } - - @Override - public String getName() { - return mBaseSet.getName(); - } - - @Override - public long reload() { - if (mBaseSet.reload() > mDataVersion) { - if (mFirstReloadDone) { - updateClustersContents(); - } else { - updateClusters(); - mFirstReloadDone = true; - } - mDataVersion = nextVersionNumber(); - } - return mDataVersion; - } - - @Override - public void onContentDirty() { - notifyContentChanged(); - } - - private void updateClusters() { - mAlbums.clear(); - Clustering clustering; - Context context = mApplication.getAndroidContext(); - switch (mKind) { - case ClusterSource.CLUSTER_ALBUMSET_TIME: - clustering = new TimeClustering(context); - break; - case ClusterSource.CLUSTER_ALBUMSET_LOCATION: - clustering = new LocationClustering(context); - break; - case ClusterSource.CLUSTER_ALBUMSET_TAG: - clustering = new TagClustering(context); - break; - case ClusterSource.CLUSTER_ALBUMSET_FACE: - clustering = new FaceClustering(context); - break; - default: /* CLUSTER_ALBUMSET_SIZE */ - clustering = new SizeClustering(context); - break; - } - - clustering.run(mBaseSet); - int n = clustering.getNumberOfClusters(); - DataManager dataManager = mApplication.getDataManager(); - for (int i = 0; i < n; i++) { - Path childPath; - String childName = clustering.getClusterName(i); - if (mKind == ClusterSource.CLUSTER_ALBUMSET_TAG) { - childPath = mPath.getChild(Uri.encode(childName)); - } else if (mKind == ClusterSource.CLUSTER_ALBUMSET_SIZE) { - long minSize = ((SizeClustering) clustering).getMinSize(i); - childPath = mPath.getChild(minSize); - } else { - childPath = mPath.getChild(i); - } - - ClusterAlbum album; - synchronized (DataManager.LOCK) { - album = (ClusterAlbum) dataManager.peekMediaObject(childPath); - if (album == null) { - album = new ClusterAlbum(childPath, dataManager, this); - } - } - album.setMediaItems(clustering.getCluster(i)); - album.setName(childName); - album.setCoverMediaItem(clustering.getClusterCover(i)); - mAlbums.add(album); - } - } - - private void updateClustersContents() { - final HashSet existing = new HashSet(); - mBaseSet.enumerateTotalMediaItems(new MediaSet.ItemConsumer() { - @Override - public void consume(int index, MediaItem item) { - existing.add(item.getPath()); - } - }); - - int n = mAlbums.size(); - - // The loop goes backwards because we may remove empty albums from - // mAlbums. - for (int i = n - 1; i >= 0; i--) { - ArrayList oldPaths = mAlbums.get(i).getMediaItems(); - ArrayList newPaths = new ArrayList(); - int m = oldPaths.size(); - for (int j = 0; j < m; j++) { - Path p = oldPaths.get(j); - if (existing.contains(p)) { - newPaths.add(p); - } - } - mAlbums.get(i).setMediaItems(newPaths); - if (newPaths.isEmpty()) { - mAlbums.remove(i); - } - } - } -} diff --git a/src/com/android/gallery3d/data/ClusterSource.java b/src/com/android/gallery3d/data/ClusterSource.java deleted file mode 100644 index a1f22e57a..000000000 --- a/src/com/android/gallery3d/data/ClusterSource.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * 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.gallery3d.data; - -import com.android.gallery3d.app.GalleryApp; - -class ClusterSource extends MediaSource { - static final int CLUSTER_ALBUMSET_TIME = 0; - static final int CLUSTER_ALBUMSET_LOCATION = 1; - static final int CLUSTER_ALBUMSET_TAG = 2; - static final int CLUSTER_ALBUMSET_SIZE = 3; - static final int CLUSTER_ALBUMSET_FACE = 4; - - static final int CLUSTER_ALBUM_TIME = 0x100; - static final int CLUSTER_ALBUM_LOCATION = 0x101; - static final int CLUSTER_ALBUM_TAG = 0x102; - static final int CLUSTER_ALBUM_SIZE = 0x103; - static final int CLUSTER_ALBUM_FACE = 0x104; - - GalleryApp mApplication; - PathMatcher mMatcher; - - public ClusterSource(GalleryApp application) { - super("cluster"); - mApplication = application; - mMatcher = new PathMatcher(); - mMatcher.add("/cluster/*/time", CLUSTER_ALBUMSET_TIME); - mMatcher.add("/cluster/*/location", CLUSTER_ALBUMSET_LOCATION); - mMatcher.add("/cluster/*/tag", CLUSTER_ALBUMSET_TAG); - mMatcher.add("/cluster/*/size", CLUSTER_ALBUMSET_SIZE); - mMatcher.add("/cluster/*/face", CLUSTER_ALBUMSET_FACE); - - mMatcher.add("/cluster/*/time/*", CLUSTER_ALBUM_TIME); - mMatcher.add("/cluster/*/location/*", CLUSTER_ALBUM_LOCATION); - mMatcher.add("/cluster/*/tag/*", CLUSTER_ALBUM_TAG); - mMatcher.add("/cluster/*/size/*", CLUSTER_ALBUM_SIZE); - mMatcher.add("/cluster/*/face/*", CLUSTER_ALBUM_FACE); - } - - // The names we accept are: - // /cluster/{set}/time /cluster/{set}/time/k - // /cluster/{set}/location /cluster/{set}/location/k - // /cluster/{set}/tag /cluster/{set}/tag/encoded_tag - // /cluster/{set}/size /cluster/{set}/size/min_size - @Override - public MediaObject createMediaObject(Path path) { - int matchType = mMatcher.match(path); - String setsName = mMatcher.getVar(0); - DataManager dataManager = mApplication.getDataManager(); - MediaSet[] sets = dataManager.getMediaSetsFromString(setsName); - switch (matchType) { - case CLUSTER_ALBUMSET_TIME: - case CLUSTER_ALBUMSET_LOCATION: - case CLUSTER_ALBUMSET_TAG: - case CLUSTER_ALBUMSET_SIZE: - case CLUSTER_ALBUMSET_FACE: - return new ClusterAlbumSet(path, mApplication, sets[0], matchType); - case CLUSTER_ALBUM_TIME: - case CLUSTER_ALBUM_LOCATION: - case CLUSTER_ALBUM_TAG: - case CLUSTER_ALBUM_SIZE: - case CLUSTER_ALBUM_FACE: { - MediaSet parent = dataManager.getMediaSet(path.getParent()); - // The actual content in the ClusterAlbum will be filled later - // when the reload() method in the parent is run. - return new ClusterAlbum(path, dataManager, parent); - } - default: - throw new RuntimeException("bad path: " + path); - } - } -} diff --git a/src/com/android/gallery3d/data/Clustering.java b/src/com/android/gallery3d/data/Clustering.java deleted file mode 100644 index 4072bf57b..000000000 --- a/src/com/android/gallery3d/data/Clustering.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * 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.gallery3d.data; - -import java.util.ArrayList; - -public abstract class Clustering { - public abstract void run(MediaSet baseSet); - public abstract int getNumberOfClusters(); - public abstract ArrayList getCluster(int index); - public abstract String getClusterName(int index); - public MediaItem getClusterCover(int index) { - return null; - } -} diff --git a/src/com/android/gallery3d/data/ComboAlbum.java b/src/com/android/gallery3d/data/ComboAlbum.java deleted file mode 100644 index cadd9f8af..000000000 --- a/src/com/android/gallery3d/data/ComboAlbum.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.data; - -import com.android.gallery3d.util.Future; - -import java.util.ArrayList; - -// ComboAlbum combines multiple media sets into one. It lists all media items -// from the input albums. -// This only handles SubMediaSets, not MediaItems. (That's all we need now) -public class ComboAlbum extends MediaSet implements ContentListener { - @SuppressWarnings("unused") - private static final String TAG = "ComboAlbum"; - private final MediaSet[] mSets; - private String mName; - - public ComboAlbum(Path path, MediaSet[] mediaSets, String name) { - super(path, nextVersionNumber()); - mSets = mediaSets; - for (MediaSet set : mSets) { - set.addContentListener(this); - } - mName = name; - } - - @Override - public ArrayList getMediaItem(int start, int count) { - ArrayList items = new ArrayList(); - for (MediaSet set : mSets) { - int size = set.getMediaItemCount(); - if (count < 1) break; - if (start < size) { - int fetchCount = (start + count <= size) ? count : size - start; - ArrayList fetchItems = set.getMediaItem(start, fetchCount); - items.addAll(fetchItems); - count -= fetchItems.size(); - start = 0; - } else { - start -= size; - } - } - return items; - } - - @Override - public int getMediaItemCount() { - int count = 0; - for (MediaSet set : mSets) { - count += set.getMediaItemCount(); - } - return count; - } - - @Override - public boolean isLeafAlbum() { - return true; - } - - @Override - public String getName() { - return mName; - } - - public void useNameOfChild(int i) { - if (i < mSets.length) mName = mSets[i].getName(); - } - - @Override - public long reload() { - boolean changed = false; - for (int i = 0, n = mSets.length; i < n; ++i) { - long version = mSets[i].reload(); - if (version > mDataVersion) changed = true; - } - if (changed) mDataVersion = nextVersionNumber(); - return mDataVersion; - } - - @Override - public void onContentDirty() { - notifyContentChanged(); - } - - @Override - public Future requestSync(SyncListener listener) { - return requestSyncOnMultipleSets(mSets, listener); - } -} diff --git a/src/com/android/gallery3d/data/ComboAlbumSet.java b/src/com/android/gallery3d/data/ComboAlbumSet.java deleted file mode 100644 index 3f3674500..000000000 --- a/src/com/android/gallery3d/data/ComboAlbumSet.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * 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.gallery3d.data; - -import com.android.gallery3d.R; -import com.android.gallery3d.app.GalleryApp; -import com.android.gallery3d.util.Future; - -// ComboAlbumSet combines multiple media sets into one. It lists all sub -// media sets from the input album sets. -// This only handles SubMediaSets, not MediaItems. (That's all we need now) -public class ComboAlbumSet extends MediaSet implements ContentListener { - @SuppressWarnings("unused") - private static final String TAG = "ComboAlbumSet"; - private final MediaSet[] mSets; - private final String mName; - - public ComboAlbumSet(Path path, GalleryApp application, MediaSet[] mediaSets) { - super(path, nextVersionNumber()); - mSets = mediaSets; - for (MediaSet set : mSets) { - set.addContentListener(this); - } - mName = application.getResources().getString( - R.string.set_label_all_albums); - } - - @Override - public MediaSet getSubMediaSet(int index) { - for (MediaSet set : mSets) { - int size = set.getSubMediaSetCount(); - if (index < size) { - return set.getSubMediaSet(index); - } - index -= size; - } - return null; - } - - @Override - public int getSubMediaSetCount() { - int count = 0; - for (MediaSet set : mSets) { - count += set.getSubMediaSetCount(); - } - return count; - } - - @Override - public String getName() { - return mName; - } - - @Override - public boolean isLoading() { - for (int i = 0, n = mSets.length; i < n; ++i) { - if (mSets[i].isLoading()) return true; - } - return false; - } - - @Override - public long reload() { - boolean changed = false; - for (int i = 0, n = mSets.length; i < n; ++i) { - long version = mSets[i].reload(); - if (version > mDataVersion) changed = true; - } - if (changed) mDataVersion = nextVersionNumber(); - return mDataVersion; - } - - @Override - public void onContentDirty() { - notifyContentChanged(); - } - - @Override - public Future requestSync(SyncListener listener) { - return requestSyncOnMultipleSets(mSets, listener); - } -} diff --git a/src/com/android/gallery3d/data/ComboSource.java b/src/com/android/gallery3d/data/ComboSource.java deleted file mode 100644 index 867d47e64..000000000 --- a/src/com/android/gallery3d/data/ComboSource.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * 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.gallery3d.data; - -import com.android.gallery3d.app.GalleryApp; - -class ComboSource extends MediaSource { - private static final int COMBO_ALBUMSET = 0; - private static final int COMBO_ALBUM = 1; - private GalleryApp mApplication; - private PathMatcher mMatcher; - - public ComboSource(GalleryApp application) { - super("combo"); - mApplication = application; - mMatcher = new PathMatcher(); - mMatcher.add("/combo/*", COMBO_ALBUMSET); - mMatcher.add("/combo/*/*", COMBO_ALBUM); - } - - // The only path we accept is "/combo/{set1, set2, ...} and /combo/item/{set1, set2, ...}" - @Override - public MediaObject createMediaObject(Path path) { - String[] segments = path.split(); - if (segments.length < 2) { - throw new RuntimeException("bad path: " + path); - } - - DataManager dataManager = mApplication.getDataManager(); - switch (mMatcher.match(path)) { - case COMBO_ALBUMSET: - return new ComboAlbumSet(path, mApplication, - dataManager.getMediaSetsFromString(segments[1])); - - case COMBO_ALBUM: - return new ComboAlbum(path, - dataManager.getMediaSetsFromString(segments[2]), segments[1]); - } - return null; - } -} diff --git a/src/com/android/gallery3d/data/ContentListener.java b/src/com/android/gallery3d/data/ContentListener.java deleted file mode 100644 index 5e2952685..000000000 --- a/src/com/android/gallery3d/data/ContentListener.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * 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.gallery3d.data; - -public interface ContentListener { - public void onContentDirty(); -} \ No newline at end of file diff --git a/src/com/android/gallery3d/data/DataManager.java b/src/com/android/gallery3d/data/DataManager.java deleted file mode 100644 index 38865e9f1..000000000 --- a/src/com/android/gallery3d/data/DataManager.java +++ /dev/null @@ -1,371 +0,0 @@ -/* - * 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.gallery3d.data; - -import android.content.Context; -import android.database.ContentObserver; -import android.net.Uri; -import android.os.Handler; - -import com.android.gallery3d.app.GalleryApp; -import com.android.gallery3d.app.StitchingChangeListener; -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.data.MediaObject.PanoramaSupportCallback; -import com.android.gallery3d.data.MediaSet.ItemConsumer; -import com.android.gallery3d.data.MediaSource.PathId; -import com.android.gallery3d.picasasource.PicasaSource; - -import java.util.ArrayList; -import java.util.Comparator; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.Map.Entry; -import java.util.WeakHashMap; - -// DataManager manages all media sets and media items in the system. -// -// Each MediaSet and MediaItem has a unique 64 bits id. The most significant -// 32 bits represents its parent, and the least significant 32 bits represents -// the self id. For MediaSet the self id is is globally unique, but for -// MediaItem it's unique only relative to its parent. -// -// To make sure the id is the same when the MediaSet is re-created, a child key -// is provided to obtainSetId() to make sure the same self id will be used as -// when the parent and key are the same. A sequence of child keys is called a -// path. And it's used to identify a specific media set even if the process is -// killed and re-created, so child keys should be stable identifiers. - -public class DataManager implements StitchingChangeListener { - public static final int INCLUDE_IMAGE = 1; - public static final int INCLUDE_VIDEO = 2; - public static final int INCLUDE_ALL = INCLUDE_IMAGE | INCLUDE_VIDEO; - public static final int INCLUDE_LOCAL_ONLY = 4; - public static final int INCLUDE_LOCAL_IMAGE_ONLY = - INCLUDE_LOCAL_ONLY | INCLUDE_IMAGE; - public static final int INCLUDE_LOCAL_VIDEO_ONLY = - INCLUDE_LOCAL_ONLY | INCLUDE_VIDEO; - public static final int INCLUDE_LOCAL_ALL_ONLY = - INCLUDE_LOCAL_ONLY | INCLUDE_IMAGE | INCLUDE_VIDEO; - - // Any one who would like to access data should require this lock - // to prevent concurrency issue. - public static final Object LOCK = new Object(); - - public static DataManager from(Context context) { - GalleryApp app = (GalleryApp) context.getApplicationContext(); - return app.getDataManager(); - } - - private static final String TAG = "DataManager"; - - // This is the path for the media set seen by the user at top level. - private static final String TOP_SET_PATH = "/combo/{/local/all,/picasa/all}"; - - private static final String TOP_IMAGE_SET_PATH = "/combo/{/local/image,/picasa/image}"; - - private static final String TOP_VIDEO_SET_PATH = - "/combo/{/local/video,/picasa/video}"; - - private static final String TOP_LOCAL_SET_PATH = "/local/all"; - - private static final String TOP_LOCAL_IMAGE_SET_PATH = "/local/image"; - - private static final String TOP_LOCAL_VIDEO_SET_PATH = "/local/video"; - - public static final Comparator sDateTakenComparator = - new DateTakenComparator(); - - private static class DateTakenComparator implements Comparator { - @Override - public int compare(MediaItem item1, MediaItem item2) { - return -Utils.compare(item1.getDateInMs(), item2.getDateInMs()); - } - } - - private final Handler mDefaultMainHandler; - - private GalleryApp mApplication; - private int mActiveCount = 0; - - private HashMap mNotifierMap = - new HashMap(); - - - private HashMap mSourceMap = - new LinkedHashMap(); - - public DataManager(GalleryApp application) { - mApplication = application; - mDefaultMainHandler = new Handler(application.getMainLooper()); - } - - public synchronized void initializeSourceMap() { - if (!mSourceMap.isEmpty()) return; - - // the order matters, the UriSource must come last - addSource(new LocalSource(mApplication)); - addSource(new PicasaSource(mApplication)); - addSource(new ComboSource(mApplication)); - addSource(new ClusterSource(mApplication)); - addSource(new FilterSource(mApplication)); - addSource(new SecureSource(mApplication)); - addSource(new UriSource(mApplication)); - addSource(new SnailSource(mApplication)); - - if (mActiveCount > 0) { - for (MediaSource source : mSourceMap.values()) { - source.resume(); - } - } - } - - public String getTopSetPath(int typeBits) { - - switch (typeBits) { - case INCLUDE_IMAGE: return TOP_IMAGE_SET_PATH; - case INCLUDE_VIDEO: return TOP_VIDEO_SET_PATH; - case INCLUDE_ALL: return TOP_SET_PATH; - case INCLUDE_LOCAL_IMAGE_ONLY: return TOP_LOCAL_IMAGE_SET_PATH; - case INCLUDE_LOCAL_VIDEO_ONLY: return TOP_LOCAL_VIDEO_SET_PATH; - case INCLUDE_LOCAL_ALL_ONLY: return TOP_LOCAL_SET_PATH; - default: throw new IllegalArgumentException(); - } - } - - // open for debug - void addSource(MediaSource source) { - if (source == null) return; - mSourceMap.put(source.getPrefix(), source); - } - - // A common usage of this method is: - // synchronized (DataManager.LOCK) { - // MediaObject object = peekMediaObject(path); - // if (object == null) { - // object = createMediaObject(...); - // } - // } - public MediaObject peekMediaObject(Path path) { - return path.getObject(); - } - - public MediaObject getMediaObject(Path path) { - synchronized (LOCK) { - MediaObject obj = path.getObject(); - if (obj != null) return obj; - - MediaSource source = mSourceMap.get(path.getPrefix()); - if (source == null) { - Log.w(TAG, "cannot find media source for path: " + path); - return null; - } - - try { - MediaObject object = source.createMediaObject(path); - if (object == null) { - Log.w(TAG, "cannot create media object: " + path); - } - return object; - } catch (Throwable t) { - Log.w(TAG, "exception in creating media object: " + path, t); - return null; - } - } - } - - public MediaObject getMediaObject(String s) { - return getMediaObject(Path.fromString(s)); - } - - public MediaSet getMediaSet(Path path) { - return (MediaSet) getMediaObject(path); - } - - public MediaSet getMediaSet(String s) { - return (MediaSet) getMediaObject(s); - } - - public MediaSet[] getMediaSetsFromString(String segment) { - String[] seq = Path.splitSequence(segment); - int n = seq.length; - MediaSet[] sets = new MediaSet[n]; - for (int i = 0; i < n; i++) { - sets[i] = getMediaSet(seq[i]); - } - return sets; - } - - // Maps a list of Paths to MediaItems, and invoke consumer.consume() - // for each MediaItem (may not be in the same order as the input list). - // An index number is also passed to consumer.consume() to identify - // the original position in the input list of the corresponding Path (plus - // startIndex). - public void mapMediaItems(ArrayList list, ItemConsumer consumer, - int startIndex) { - HashMap> map = - new HashMap>(); - - // Group the path by the prefix. - int n = list.size(); - for (int i = 0; i < n; i++) { - Path path = list.get(i); - String prefix = path.getPrefix(); - ArrayList group = map.get(prefix); - if (group == null) { - group = new ArrayList(); - map.put(prefix, group); - } - group.add(new PathId(path, i + startIndex)); - } - - // For each group, ask the corresponding media source to map it. - for (Entry> entry : map.entrySet()) { - String prefix = entry.getKey(); - MediaSource source = mSourceMap.get(prefix); - source.mapMediaItems(entry.getValue(), consumer); - } - } - - // The following methods forward the request to the proper object. - public int getSupportedOperations(Path path) { - return getMediaObject(path).getSupportedOperations(); - } - - public void getPanoramaSupport(Path path, PanoramaSupportCallback callback) { - getMediaObject(path).getPanoramaSupport(callback); - } - - public void delete(Path path) { - getMediaObject(path).delete(); - } - - public void rotate(Path path, int degrees) { - getMediaObject(path).rotate(degrees); - } - - public Uri getContentUri(Path path) { - return getMediaObject(path).getContentUri(); - } - - public int getMediaType(Path path) { - return getMediaObject(path).getMediaType(); - } - - public Path findPathByUri(Uri uri, String type) { - if (uri == null) return null; - for (MediaSource source : mSourceMap.values()) { - Path path = source.findPathByUri(uri, type); - if (path != null) return path; - } - return null; - } - - public Path getDefaultSetOf(Path item) { - MediaSource source = mSourceMap.get(item.getPrefix()); - return source == null ? null : source.getDefaultSetOf(item); - } - - // Returns number of bytes used by cached pictures currently downloaded. - public long getTotalUsedCacheSize() { - long sum = 0; - for (MediaSource source : mSourceMap.values()) { - sum += source.getTotalUsedCacheSize(); - } - return sum; - } - - // Returns number of bytes used by cached pictures if all pending - // downloads and removals are completed. - public long getTotalTargetCacheSize() { - long sum = 0; - for (MediaSource source : mSourceMap.values()) { - sum += source.getTotalTargetCacheSize(); - } - return sum; - } - - public void registerChangeNotifier(Uri uri, ChangeNotifier notifier) { - NotifyBroker broker = null; - synchronized (mNotifierMap) { - broker = mNotifierMap.get(uri); - if (broker == null) { - broker = new NotifyBroker(mDefaultMainHandler); - mApplication.getContentResolver() - .registerContentObserver(uri, true, broker); - mNotifierMap.put(uri, broker); - } - } - broker.registerNotifier(notifier); - } - - public void resume() { - if (++mActiveCount == 1) { - for (MediaSource source : mSourceMap.values()) { - source.resume(); - } - } - } - - public void pause() { - if (--mActiveCount == 0) { - for (MediaSource source : mSourceMap.values()) { - source.pause(); - } - } - } - - private static class NotifyBroker extends ContentObserver { - private WeakHashMap mNotifiers = - new WeakHashMap(); - - public NotifyBroker(Handler handler) { - super(handler); - } - - public synchronized void registerNotifier(ChangeNotifier notifier) { - mNotifiers.put(notifier, null); - } - - @Override - public synchronized void onChange(boolean selfChange) { - for(ChangeNotifier notifier : mNotifiers.keySet()) { - notifier.onChange(selfChange); - } - } - } - - @Override - public void onStitchingQueued(Uri uri) { - // Do nothing. - } - - @Override - public void onStitchingResult(Uri uri) { - Path path = findPathByUri(uri, null); - if (path != null) { - MediaObject mediaObject = getMediaObject(path); - if (mediaObject != null) { - mediaObject.clearCachedPanoramaSupport(); - } - } - } - - @Override - public void onStitchingProgress(Uri uri, int progress) { - // Do nothing. - } -} diff --git a/src/com/android/gallery3d/data/DataSourceType.java b/src/com/android/gallery3d/data/DataSourceType.java deleted file mode 100644 index ab534d0c3..000000000 --- a/src/com/android/gallery3d/data/DataSourceType.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * 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.gallery3d.data; - -import com.android.gallery3d.util.MediaSetUtils; - -public final class DataSourceType { - public static final int TYPE_NOT_CATEGORIZED = 0; - public static final int TYPE_LOCAL = 1; - public static final int TYPE_PICASA = 2; - public static final int TYPE_CAMERA = 3; - - private static final Path PICASA_ROOT = Path.fromString("/picasa"); - private static final Path LOCAL_ROOT = Path.fromString("/local"); - - public static int identifySourceType(MediaSet set) { - if (set == null) { - return TYPE_NOT_CATEGORIZED; - } - - Path path = set.getPath(); - if (MediaSetUtils.isCameraSource(path)) return TYPE_CAMERA; - - Path prefix = path.getPrefixPath(); - - if (prefix == PICASA_ROOT) return TYPE_PICASA; - if (prefix == LOCAL_ROOT) return TYPE_LOCAL; - - return TYPE_NOT_CATEGORIZED; - } -} diff --git a/src/com/android/gallery3d/data/DecodeUtils.java b/src/com/android/gallery3d/data/DecodeUtils.java deleted file mode 100644 index fa709157d..000000000 --- a/src/com/android/gallery3d/data/DecodeUtils.java +++ /dev/null @@ -1,312 +0,0 @@ -/* - * 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.gallery3d.data; - -import android.annotation.TargetApi; -import android.graphics.Bitmap; -import android.graphics.Bitmap.Config; -import android.graphics.BitmapFactory; -import android.graphics.BitmapFactory.Options; -import android.graphics.BitmapRegionDecoder; -import android.os.Build; -import android.util.FloatMath; - -import com.android.gallery3d.common.ApiHelper; -import com.android.gallery3d.common.BitmapUtils; -import com.android.gallery3d.common.Utils; -import com.android.photos.data.GalleryBitmapPool; -import com.android.gallery3d.ui.Log; -import com.android.gallery3d.util.ThreadPool.CancelListener; -import com.android.gallery3d.util.ThreadPool.JobContext; - -import java.io.FileDescriptor; -import java.io.FileInputStream; -import java.io.InputStream; - -public class DecodeUtils { - private static final String TAG = "DecodeUtils"; - - private static class DecodeCanceller implements CancelListener { - Options mOptions; - - public DecodeCanceller(Options options) { - mOptions = options; - } - - @Override - public void onCancel() { - mOptions.requestCancelDecode(); - } - } - - @TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB) - public static void setOptionsMutable(Options options) { - if (ApiHelper.HAS_OPTIONS_IN_MUTABLE) options.inMutable = true; - } - - public static Bitmap decode(JobContext jc, FileDescriptor fd, Options options) { - if (options == null) options = new Options(); - jc.setCancelListener(new DecodeCanceller(options)); - setOptionsMutable(options); - return ensureGLCompatibleBitmap( - BitmapFactory.decodeFileDescriptor(fd, null, options)); - } - - public static void decodeBounds(JobContext jc, FileDescriptor fd, - Options options) { - Utils.assertTrue(options != null); - options.inJustDecodeBounds = true; - jc.setCancelListener(new DecodeCanceller(options)); - BitmapFactory.decodeFileDescriptor(fd, null, options); - options.inJustDecodeBounds = false; - } - - public static Bitmap decode(JobContext jc, byte[] bytes, Options options) { - return decode(jc, bytes, 0, bytes.length, options); - } - - public static Bitmap decode(JobContext jc, byte[] bytes, int offset, - int length, Options options) { - if (options == null) options = new Options(); - jc.setCancelListener(new DecodeCanceller(options)); - setOptionsMutable(options); - return ensureGLCompatibleBitmap( - BitmapFactory.decodeByteArray(bytes, offset, length, options)); - } - - public static void decodeBounds(JobContext jc, byte[] bytes, int offset, - int length, Options options) { - Utils.assertTrue(options != null); - options.inJustDecodeBounds = true; - jc.setCancelListener(new DecodeCanceller(options)); - BitmapFactory.decodeByteArray(bytes, offset, length, options); - options.inJustDecodeBounds = false; - } - - public static Bitmap decodeThumbnail( - JobContext jc, String filePath, Options options, int targetSize, int type) { - FileInputStream fis = null; - try { - fis = new FileInputStream(filePath); - FileDescriptor fd = fis.getFD(); - return decodeThumbnail(jc, fd, options, targetSize, type); - } catch (Exception ex) { - Log.w(TAG, ex); - return null; - } finally { - Utils.closeSilently(fis); - } - } - - public static Bitmap decodeThumbnail( - JobContext jc, FileDescriptor fd, Options options, int targetSize, int type) { - if (options == null) options = new Options(); - jc.setCancelListener(new DecodeCanceller(options)); - - options.inJustDecodeBounds = true; - BitmapFactory.decodeFileDescriptor(fd, null, options); - if (jc.isCancelled()) return null; - - int w = options.outWidth; - int h = options.outHeight; - - if (type == MediaItem.TYPE_MICROTHUMBNAIL) { - // We center-crop the original image as it's micro thumbnail. In this case, - // we want to make sure the shorter side >= "targetSize". - float scale = (float) targetSize / Math.min(w, h); - options.inSampleSize = BitmapUtils.computeSampleSizeLarger(scale); - - // For an extremely wide image, e.g. 300x30000, we may got OOM when decoding - // it for TYPE_MICROTHUMBNAIL. So we add a max number of pixels limit here. - final int MAX_PIXEL_COUNT = 640000; // 400 x 1600 - if ((w / options.inSampleSize) * (h / options.inSampleSize) > MAX_PIXEL_COUNT) { - options.inSampleSize = BitmapUtils.computeSampleSize( - FloatMath.sqrt((float) MAX_PIXEL_COUNT / (w * h))); - } - } else { - // For screen nail, we only want to keep the longer side >= targetSize. - float scale = (float) targetSize / Math.max(w, h); - options.inSampleSize = BitmapUtils.computeSampleSizeLarger(scale); - } - - options.inJustDecodeBounds = false; - setOptionsMutable(options); - - Bitmap result = BitmapFactory.decodeFileDescriptor(fd, null, options); - if (result == null) return null; - - // We need to resize down if the decoder does not support inSampleSize - // (For example, GIF images) - float scale = (float) targetSize / (type == MediaItem.TYPE_MICROTHUMBNAIL - ? Math.min(result.getWidth(), result.getHeight()) - : Math.max(result.getWidth(), result.getHeight())); - - if (scale <= 0.5) result = BitmapUtils.resizeBitmapByScale(result, scale, true); - return ensureGLCompatibleBitmap(result); - } - - /** - * Decodes the bitmap from the given byte array if the image size is larger than the given - * requirement. - * - * Note: The returned image may be resized down. However, both width and height must be - * larger than the targetSize. - */ - public static Bitmap decodeIfBigEnough(JobContext jc, byte[] data, - Options options, int targetSize) { - if (options == null) options = new Options(); - jc.setCancelListener(new DecodeCanceller(options)); - - options.inJustDecodeBounds = true; - BitmapFactory.decodeByteArray(data, 0, data.length, options); - if (jc.isCancelled()) return null; - if (options.outWidth < targetSize || options.outHeight < targetSize) { - return null; - } - options.inSampleSize = BitmapUtils.computeSampleSizeLarger( - options.outWidth, options.outHeight, targetSize); - options.inJustDecodeBounds = false; - setOptionsMutable(options); - - return ensureGLCompatibleBitmap( - BitmapFactory.decodeByteArray(data, 0, data.length, options)); - } - - // TODO: This function should not be called directly from - // DecodeUtils.requestDecode(...), since we don't have the knowledge - // if the bitmap will be uploaded to GL. - public 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; - } - - public static BitmapRegionDecoder createBitmapRegionDecoder( - JobContext jc, byte[] bytes, int offset, int length, - boolean shareable) { - if (offset < 0 || length <= 0 || offset + length > bytes.length) { - throw new IllegalArgumentException(String.format( - "offset = %s, length = %s, bytes = %s", - offset, length, bytes.length)); - } - - try { - return BitmapRegionDecoder.newInstance( - bytes, offset, length, shareable); - } catch (Throwable t) { - Log.w(TAG, t); - return null; - } - } - - public static BitmapRegionDecoder createBitmapRegionDecoder( - JobContext jc, String filePath, boolean shareable) { - try { - return BitmapRegionDecoder.newInstance(filePath, shareable); - } catch (Throwable t) { - Log.w(TAG, t); - return null; - } - } - - public static BitmapRegionDecoder createBitmapRegionDecoder( - JobContext jc, FileDescriptor fd, boolean shareable) { - try { - return BitmapRegionDecoder.newInstance(fd, shareable); - } catch (Throwable t) { - Log.w(TAG, t); - return null; - } - } - - public static BitmapRegionDecoder createBitmapRegionDecoder( - JobContext jc, InputStream is, boolean shareable) { - try { - return BitmapRegionDecoder.newInstance(is, shareable); - } catch (Throwable t) { - // We often cancel the creating of bitmap region decoder, - // so just log one line. - Log.w(TAG, "requestCreateBitmapRegionDecoder: " + t); - return null; - } - } - - @TargetApi(Build.VERSION_CODES.HONEYCOMB) - public static Bitmap decodeUsingPool(JobContext jc, byte[] data, int offset, - int length, BitmapFactory.Options options) { - if (options == null) options = new BitmapFactory.Options(); - if (options.inSampleSize < 1) options.inSampleSize = 1; - options.inPreferredConfig = Bitmap.Config.ARGB_8888; - options.inBitmap = (options.inSampleSize == 1) - ? findCachedBitmap(jc, data, offset, length, options) : null; - try { - Bitmap bitmap = decode(jc, data, offset, length, options); - if (options.inBitmap != null && options.inBitmap != bitmap) { - GalleryBitmapPool.getInstance().put(options.inBitmap); - options.inBitmap = null; - } - return bitmap; - } catch (IllegalArgumentException e) { - if (options.inBitmap == null) throw e; - - Log.w(TAG, "decode fail with a given bitmap, try decode to a new bitmap"); - GalleryBitmapPool.getInstance().put(options.inBitmap); - options.inBitmap = null; - return decode(jc, data, offset, length, options); - } - } - - // This is the same as the method above except the source data comes - // from a file descriptor instead of a byte array. - @TargetApi(Build.VERSION_CODES.HONEYCOMB) - public static Bitmap decodeUsingPool(JobContext jc, - FileDescriptor fileDescriptor, Options options) { - if (options == null) options = new BitmapFactory.Options(); - if (options.inSampleSize < 1) options.inSampleSize = 1; - options.inPreferredConfig = Bitmap.Config.ARGB_8888; - options.inBitmap = (options.inSampleSize == 1) - ? findCachedBitmap(jc, fileDescriptor, options) : null; - try { - Bitmap bitmap = DecodeUtils.decode(jc, fileDescriptor, options); - if (options.inBitmap != null && options.inBitmap != bitmap) { - GalleryBitmapPool.getInstance().put(options.inBitmap); - options.inBitmap = null; - } - return bitmap; - } catch (IllegalArgumentException e) { - if (options.inBitmap == null) throw e; - - Log.w(TAG, "decode fail with a given bitmap, try decode to a new bitmap"); - GalleryBitmapPool.getInstance().put(options.inBitmap); - options.inBitmap = null; - return decode(jc, fileDescriptor, options); - } - } - - private static Bitmap findCachedBitmap(JobContext jc, byte[] data, - int offset, int length, Options options) { - decodeBounds(jc, data, offset, length, options); - return GalleryBitmapPool.getInstance().get(options.outWidth, options.outHeight); - } - - private static Bitmap findCachedBitmap(JobContext jc, FileDescriptor fileDescriptor, - Options options) { - decodeBounds(jc, fileDescriptor, options); - return GalleryBitmapPool.getInstance().get(options.outWidth, options.outHeight); - } -} diff --git a/src/com/android/gallery3d/data/DownloadCache.java b/src/com/android/gallery3d/data/DownloadCache.java deleted file mode 100644 index be7820b01..000000000 --- a/src/com/android/gallery3d/data/DownloadCache.java +++ /dev/null @@ -1,370 +0,0 @@ -/* - * 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.gallery3d.data; - -import android.content.ContentValues; -import android.content.Context; -import android.database.Cursor; -import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteOpenHelper; - -import com.android.gallery3d.app.GalleryApp; -import com.android.gallery3d.common.LruCache; -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.data.DownloadEntry.Columns; -import com.android.gallery3d.util.Future; -import com.android.gallery3d.util.FutureListener; -import com.android.gallery3d.util.ThreadPool; -import com.android.gallery3d.util.ThreadPool.CancelListener; -import com.android.gallery3d.util.ThreadPool.Job; -import com.android.gallery3d.util.ThreadPool.JobContext; - -import java.io.File; -import java.net.URL; -import java.util.HashMap; -import java.util.HashSet; - -public class DownloadCache { - private static final String TAG = "DownloadCache"; - private static final int MAX_DELETE_COUNT = 16; - private static final int LRU_CAPACITY = 4; - - private static final String TABLE_NAME = DownloadEntry.SCHEMA.getTableName(); - - private static final String QUERY_PROJECTION[] = {Columns.ID, Columns.DATA}; - private static final String WHERE_HASH_AND_URL = String.format( - "%s = ? AND %s = ?", Columns.HASH_CODE, Columns.CONTENT_URL); - private static final int QUERY_INDEX_ID = 0; - private static final int QUERY_INDEX_DATA = 1; - - private static final String FREESPACE_PROJECTION[] = { - Columns.ID, Columns.DATA, Columns.CONTENT_URL, Columns.CONTENT_SIZE}; - private static final String FREESPACE_ORDER_BY = - String.format("%s ASC", Columns.LAST_ACCESS); - private static final int FREESPACE_IDNEX_ID = 0; - private static final int FREESPACE_IDNEX_DATA = 1; - private static final int FREESPACE_INDEX_CONTENT_URL = 2; - private static final int FREESPACE_INDEX_CONTENT_SIZE = 3; - - private static final String ID_WHERE = Columns.ID + " = ?"; - - private static final String SUM_PROJECTION[] = - {String.format("sum(%s)", Columns.CONTENT_SIZE)}; - private static final int SUM_INDEX_SUM = 0; - - private final LruCache mEntryMap = - new LruCache(LRU_CAPACITY); - private final HashMap mTaskMap = - new HashMap(); - private final File mRoot; - private final GalleryApp mApplication; - private final SQLiteDatabase mDatabase; - private final long mCapacity; - - private long mTotalBytes = 0; - private boolean mInitialized = false; - - public DownloadCache(GalleryApp application, File root, long capacity) { - mRoot = Utils.checkNotNull(root); - mApplication = Utils.checkNotNull(application); - mCapacity = capacity; - mDatabase = new DatabaseHelper(application.getAndroidContext()) - .getWritableDatabase(); - } - - private Entry findEntryInDatabase(String stringUrl) { - long hash = Utils.crc64Long(stringUrl); - String whereArgs[] = {String.valueOf(hash), stringUrl}; - Cursor cursor = mDatabase.query(TABLE_NAME, QUERY_PROJECTION, - WHERE_HASH_AND_URL, whereArgs, null, null, null); - try { - if (cursor.moveToNext()) { - File file = new File(cursor.getString(QUERY_INDEX_DATA)); - long id = cursor.getInt(QUERY_INDEX_ID); - Entry entry = null; - synchronized (mEntryMap) { - entry = mEntryMap.get(stringUrl); - if (entry == null) { - entry = new Entry(id, file); - mEntryMap.put(stringUrl, entry); - } - } - return entry; - } - } finally { - cursor.close(); - } - return null; - } - - public Entry download(JobContext jc, URL url) { - if (!mInitialized) initialize(); - - String stringUrl = url.toString(); - - // First find in the entry-pool - synchronized (mEntryMap) { - Entry entry = mEntryMap.get(stringUrl); - if (entry != null) { - updateLastAccess(entry.mId); - return entry; - } - } - - // Then, find it in database - TaskProxy proxy = new TaskProxy(); - synchronized (mTaskMap) { - Entry entry = findEntryInDatabase(stringUrl); - if (entry != null) { - updateLastAccess(entry.mId); - return entry; - } - - // Finally, we need to download the file .... - // First check if we are downloading it now ... - DownloadTask task = mTaskMap.get(stringUrl); - if (task == null) { // if not, start the download task now - task = new DownloadTask(stringUrl); - mTaskMap.put(stringUrl, task); - task.mFuture = mApplication.getThreadPool().submit(task, task); - } - task.addProxy(proxy); - } - - return proxy.get(jc); - } - - private void updateLastAccess(long id) { - ContentValues values = new ContentValues(); - values.put(Columns.LAST_ACCESS, System.currentTimeMillis()); - mDatabase.update(TABLE_NAME, values, - ID_WHERE, new String[] {String.valueOf(id)}); - } - - private synchronized void freeSomeSpaceIfNeed(int maxDeleteFileCount) { - if (mTotalBytes <= mCapacity) return; - Cursor cursor = mDatabase.query(TABLE_NAME, - FREESPACE_PROJECTION, null, null, null, null, FREESPACE_ORDER_BY); - try { - while (maxDeleteFileCount > 0 - && mTotalBytes > mCapacity && cursor.moveToNext()) { - long id = cursor.getLong(FREESPACE_IDNEX_ID); - String url = cursor.getString(FREESPACE_INDEX_CONTENT_URL); - long size = cursor.getLong(FREESPACE_INDEX_CONTENT_SIZE); - String path = cursor.getString(FREESPACE_IDNEX_DATA); - boolean containsKey; - synchronized (mEntryMap) { - containsKey = mEntryMap.containsKey(url); - } - if (!containsKey) { - --maxDeleteFileCount; - mTotalBytes -= size; - new File(path).delete(); - mDatabase.delete(TABLE_NAME, - ID_WHERE, new String[]{String.valueOf(id)}); - } else { - // skip delete, since it is being used - } - } - } finally { - cursor.close(); - } - } - - private synchronized long insertEntry(String url, File file) { - long size = file.length(); - mTotalBytes += size; - - ContentValues values = new ContentValues(); - String hashCode = String.valueOf(Utils.crc64Long(url)); - values.put(Columns.DATA, file.getAbsolutePath()); - values.put(Columns.HASH_CODE, hashCode); - values.put(Columns.CONTENT_URL, url); - values.put(Columns.CONTENT_SIZE, size); - values.put(Columns.LAST_UPDATED, System.currentTimeMillis()); - return mDatabase.insert(TABLE_NAME, "", values); - } - - private synchronized void initialize() { - if (mInitialized) return; - mInitialized = true; - if (!mRoot.isDirectory()) mRoot.mkdirs(); - if (!mRoot.isDirectory()) { - throw new RuntimeException("cannot create " + mRoot.getAbsolutePath()); - } - - Cursor cursor = mDatabase.query( - TABLE_NAME, SUM_PROJECTION, null, null, null, null, null); - mTotalBytes = 0; - try { - if (cursor.moveToNext()) { - mTotalBytes = cursor.getLong(SUM_INDEX_SUM); - } - } finally { - cursor.close(); - } - if (mTotalBytes > mCapacity) freeSomeSpaceIfNeed(MAX_DELETE_COUNT); - } - - private final class DatabaseHelper extends SQLiteOpenHelper { - public static final String DATABASE_NAME = "download.db"; - public static final int DATABASE_VERSION = 2; - - public DatabaseHelper(Context context) { - super(context, DATABASE_NAME, null, DATABASE_VERSION); - } - - @Override - public void onCreate(SQLiteDatabase db) { - DownloadEntry.SCHEMA.createTables(db); - // Delete old files - for (File file : mRoot.listFiles()) { - if (!file.delete()) { - Log.w(TAG, "fail to remove: " + file.getAbsolutePath()); - } - } - } - - @Override - public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { - //reset everything - DownloadEntry.SCHEMA.dropTables(db); - onCreate(db); - } - } - - public class Entry { - public File cacheFile; - protected long mId; - - Entry(long id, File cacheFile) { - mId = id; - this.cacheFile = Utils.checkNotNull(cacheFile); - } - } - - private class DownloadTask implements Job, FutureListener { - private HashSet mProxySet = new HashSet(); - private Future mFuture; - private final String mUrl; - - public DownloadTask(String url) { - mUrl = Utils.checkNotNull(url); - } - - public void removeProxy(TaskProxy proxy) { - synchronized (mTaskMap) { - Utils.assertTrue(mProxySet.remove(proxy)); - if (mProxySet.isEmpty()) { - mFuture.cancel(); - mTaskMap.remove(mUrl); - } - } - } - - // should be used in synchronized block of mDatabase - public void addProxy(TaskProxy proxy) { - proxy.mTask = this; - mProxySet.add(proxy); - } - - @Override - public void onFutureDone(Future future) { - File file = future.get(); - long id = 0; - if (file != null) { // insert to database - id = insertEntry(mUrl, file); - } - - if (future.isCancelled()) { - Utils.assertTrue(mProxySet.isEmpty()); - return; - } - - synchronized (mTaskMap) { - Entry entry = null; - synchronized (mEntryMap) { - if (file != null) { - entry = new Entry(id, file); - Utils.assertTrue(mEntryMap.put(mUrl, entry) == null); - } - } - for (TaskProxy proxy : mProxySet) { - proxy.setResult(entry); - } - mTaskMap.remove(mUrl); - freeSomeSpaceIfNeed(MAX_DELETE_COUNT); - } - } - - @Override - public File run(JobContext jc) { - // TODO: utilize etag - jc.setMode(ThreadPool.MODE_NETWORK); - File tempFile = null; - try { - URL url = new URL(mUrl); - tempFile = File.createTempFile("cache", ".tmp", mRoot); - // download from url to tempFile - jc.setMode(ThreadPool.MODE_NETWORK); - boolean downloaded = DownloadUtils.requestDownload(jc, url, tempFile); - jc.setMode(ThreadPool.MODE_NONE); - if (downloaded) return tempFile; - } catch (Exception e) { - Log.e(TAG, String.format("fail to download %s", mUrl), e); - } finally { - jc.setMode(ThreadPool.MODE_NONE); - } - if (tempFile != null) tempFile.delete(); - return null; - } - } - - public static class TaskProxy { - private DownloadTask mTask; - private boolean mIsCancelled = false; - private Entry mEntry; - - synchronized void setResult(Entry entry) { - if (mIsCancelled) return; - mEntry = entry; - notifyAll(); - } - - public synchronized Entry get(JobContext jc) { - jc.setCancelListener(new CancelListener() { - @Override - public void onCancel() { - mTask.removeProxy(TaskProxy.this); - synchronized (TaskProxy.this) { - mIsCancelled = true; - TaskProxy.this.notifyAll(); - } - } - }); - while (!mIsCancelled && mEntry == null) { - try { - wait(); - } catch (InterruptedException e) { - Log.w(TAG, "ignore interrupt", e); - } - } - jc.setCancelListener(null); - return mEntry; - } - } -} diff --git a/src/com/android/gallery3d/data/DownloadEntry.java b/src/com/android/gallery3d/data/DownloadEntry.java deleted file mode 100644 index 578523f73..000000000 --- a/src/com/android/gallery3d/data/DownloadEntry.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * 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.gallery3d.data; - -import com.android.gallery3d.common.Entry; -import com.android.gallery3d.common.EntrySchema; - - -@Entry.Table("download") -public class DownloadEntry extends Entry { - public static final EntrySchema SCHEMA = new EntrySchema(DownloadEntry.class); - - public static interface Columns extends Entry.Columns { - public static final String HASH_CODE = "hash_code"; - public static final String CONTENT_URL = "content_url"; - public static final String CONTENT_SIZE = "_size"; - public static final String ETAG = "etag"; - public static final String LAST_ACCESS = "last_access"; - public static final String LAST_UPDATED = "last_updated"; - public static final String DATA = "_data"; - } - - @Column(value = "hash_code", indexed = true) - public long hashCode; - - @Column("content_url") - public String contentUrl; - - @Column("_size") - public long contentSize; - - @Column("etag") - public String eTag; - - @Column(value = "last_access", indexed = true) - public long lastAccessTime; - - @Column(value = "last_updated") - public long lastUpdatedTime; - - @Column("_data") - public String path; - - @Override - public String toString() { - // Note: THIS IS REQUIRED. We used all the fields here. Otherwise, - // ProGuard will remove these UNUSED fields. However, these - // fields are needed to generate database. - return new StringBuilder() - .append("hash_code: ").append(hashCode).append(", ") - .append("content_url").append(contentUrl).append(", ") - .append("_size").append(contentSize).append(", ") - .append("etag").append(eTag).append(", ") - .append("last_access").append(lastAccessTime).append(", ") - .append("last_updated").append(lastUpdatedTime).append(",") - .append("_data").append(path) - .toString(); - } -} diff --git a/src/com/android/gallery3d/data/DownloadUtils.java b/src/com/android/gallery3d/data/DownloadUtils.java deleted file mode 100644 index 137898e91..000000000 --- a/src/com/android/gallery3d/data/DownloadUtils.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * 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.gallery3d.data; - -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.util.ThreadPool.CancelListener; -import com.android.gallery3d.util.ThreadPool.JobContext; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InterruptedIOException; -import java.io.OutputStream; -import java.net.URL; - -public class DownloadUtils { - private static final String TAG = "DownloadService"; - - public static boolean requestDownload(JobContext jc, URL url, File file) { - FileOutputStream fos = null; - try { - fos = new FileOutputStream(file); - return download(jc, url, fos); - } catch (Throwable t) { - return false; - } finally { - Utils.closeSilently(fos); - } - } - - public static void dump(JobContext jc, InputStream is, OutputStream os) - throws IOException { - byte buffer[] = new byte[4096]; - int rc = is.read(buffer, 0, buffer.length); - final Thread thread = Thread.currentThread(); - jc.setCancelListener(new CancelListener() { - @Override - public void onCancel() { - thread.interrupt(); - } - }); - while (rc > 0) { - if (jc.isCancelled()) throw new InterruptedIOException(); - os.write(buffer, 0, rc); - rc = is.read(buffer, 0, buffer.length); - } - jc.setCancelListener(null); - Thread.interrupted(); // consume the interrupt signal - } - - public static boolean download(JobContext jc, URL url, OutputStream output) { - InputStream input = null; - try { - input = url.openStream(); - dump(jc, input, output); - return true; - } catch (Throwable t) { - Log.w(TAG, "fail to download", t); - return false; - } finally { - Utils.closeSilently(input); - } - } -} \ No newline at end of file diff --git a/src/com/android/gallery3d/data/EmptyAlbumImage.java b/src/com/android/gallery3d/data/EmptyAlbumImage.java deleted file mode 100644 index 6f8c37c6b..000000000 --- a/src/com/android/gallery3d/data/EmptyAlbumImage.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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. - */ - -package com.android.gallery3d.data; - -import com.android.gallery3d.R; -import com.android.gallery3d.app.GalleryApp; - -public class EmptyAlbumImage extends ActionImage { - @SuppressWarnings("unused") - private static final String TAG = "EmptyAlbumImage"; - - public EmptyAlbumImage(Path path, GalleryApp application) { - super(path, application, R.drawable.placeholder_empty); - } - - @Override - public int getSupportedOperations() { - return super.getSupportedOperations() | SUPPORT_BACK; - } -} diff --git a/src/com/android/gallery3d/data/Exif.java b/src/com/android/gallery3d/data/Exif.java deleted file mode 100644 index 950e7de18..000000000 --- a/src/com/android/gallery3d/data/Exif.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.data; - -import android.util.Log; - -import com.android.gallery3d.exif.ExifInterface; - -import java.io.IOException; -import java.io.InputStream; - -public class Exif { - private static final String TAG = "CameraExif"; - - // Returns the degrees in clockwise. Values are 0, 90, 180, or 270. - public static int getOrientation(InputStream is) { - if (is == null) { - return 0; - } - ExifInterface exif = new ExifInterface(); - try { - exif.readExif(is); - Integer val = exif.getTagIntValue(ExifInterface.TAG_ORIENTATION); - if (val == null) { - return 0; - } else { - return ExifInterface.getRotationForOrientationValue(val.shortValue()); - } - } catch (IOException e) { - Log.w(TAG, "Failed to read EXIF orientation", e); - return 0; - } - } -} diff --git a/src/com/android/gallery3d/data/Face.java b/src/com/android/gallery3d/data/Face.java deleted file mode 100644 index d2dc22bfc..000000000 --- a/src/com/android/gallery3d/data/Face.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.data; - -import android.graphics.Rect; - -import com.android.gallery3d.common.Utils; - -import java.util.StringTokenizer; - -public class Face implements Comparable { - private String mName; - private String mPersonId; - private Rect mPosition; - - public Face(String name, String personId, String rect) { - mName = name; - mPersonId = personId; - Utils.assertTrue(mName != null && mPersonId != null && rect != null); - StringTokenizer tokenizer = new StringTokenizer(rect); - mPosition = new Rect(); - while (tokenizer.hasMoreElements()) { - mPosition.left = Integer.parseInt(tokenizer.nextToken()); - mPosition.top = Integer.parseInt(tokenizer.nextToken()); - mPosition.right = Integer.parseInt(tokenizer.nextToken()); - mPosition.bottom = Integer.parseInt(tokenizer.nextToken()); - } - } - - public Rect getPosition() { - return mPosition; - } - - public String getName() { - return mName; - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof Face) { - Face face = (Face) obj; - return mPersonId.equals(face.mPersonId); - } - return false; - } - - @Override - public int compareTo(Face another) { - return mName.compareTo(another.mName); - } -} diff --git a/src/com/android/gallery3d/data/FaceClustering.java b/src/com/android/gallery3d/data/FaceClustering.java deleted file mode 100644 index 819915edb..000000000 --- a/src/com/android/gallery3d/data/FaceClustering.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.data; - -import android.content.Context; -import android.graphics.Rect; - -import com.android.gallery3d.R; -import com.android.gallery3d.picasasource.PicasaSource; - -import java.util.ArrayList; -import java.util.TreeMap; - -public class FaceClustering extends Clustering { - @SuppressWarnings("unused") - private static final String TAG = "FaceClustering"; - - private FaceCluster[] mClusters; - private String mUntaggedString; - private Context mContext; - - private class FaceCluster { - ArrayList mPaths = new ArrayList(); - String mName; - MediaItem mCoverItem; - Rect mCoverRegion; - int mCoverFaceIndex; - - public FaceCluster(String name) { - mName = name; - } - - public void add(MediaItem item, int faceIndex) { - Path path = item.getPath(); - mPaths.add(path); - Face[] faces = item.getFaces(); - if (faces != null) { - Face face = faces[faceIndex]; - if (mCoverItem == null) { - mCoverItem = item; - mCoverRegion = face.getPosition(); - mCoverFaceIndex = faceIndex; - } else { - Rect region = face.getPosition(); - if (mCoverRegion.width() < region.width() && - mCoverRegion.height() < region.height()) { - mCoverItem = item; - mCoverRegion = face.getPosition(); - mCoverFaceIndex = faceIndex; - } - } - } - } - - public int size() { - return mPaths.size(); - } - - public MediaItem getCover() { - if (mCoverItem != null) { - if (PicasaSource.isPicasaImage(mCoverItem)) { - return PicasaSource.getFaceItem(mContext, mCoverItem, mCoverFaceIndex); - } else { - return mCoverItem; - } - } - return null; - } - } - - public FaceClustering(Context context) { - mUntaggedString = context.getResources().getString(R.string.untagged); - mContext = context; - } - - @Override - public void run(MediaSet baseSet) { - final TreeMap map = - new TreeMap(); - final FaceCluster untagged = new FaceCluster(mUntaggedString); - - baseSet.enumerateTotalMediaItems(new MediaSet.ItemConsumer() { - @Override - public void consume(int index, MediaItem item) { - Face[] faces = item.getFaces(); - if (faces == null || faces.length == 0) { - untagged.add(item, -1); - return; - } - for (int j = 0; j < faces.length; j++) { - Face face = faces[j]; - FaceCluster cluster = map.get(face); - if (cluster == null) { - cluster = new FaceCluster(face.getName()); - map.put(face, cluster); - } - cluster.add(item, j); - } - } - }); - - int m = map.size(); - mClusters = map.values().toArray(new FaceCluster[m + ((untagged.size() > 0) ? 1 : 0)]); - if (untagged.size() > 0) { - mClusters[m] = untagged; - } - } - - @Override - public int getNumberOfClusters() { - return mClusters.length; - } - - @Override - public ArrayList getCluster(int index) { - return mClusters[index].mPaths; - } - - @Override - public String getClusterName(int index) { - return mClusters[index].mName; - } - - @Override - public MediaItem getClusterCover(int index) { - return mClusters[index].getCover(); - } -} diff --git a/src/com/android/gallery3d/data/FilterDeleteSet.java b/src/com/android/gallery3d/data/FilterDeleteSet.java deleted file mode 100644 index c76412ff8..000000000 --- a/src/com/android/gallery3d/data/FilterDeleteSet.java +++ /dev/null @@ -1,256 +0,0 @@ -/* - * 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. - */ - -package com.android.gallery3d.data; - -import java.util.ArrayList; - -// FilterDeleteSet filters a base MediaSet to remove some deletion items (we -// expect the number to be small). The user can use the following methods to -// add/remove deletion items: -// -// void addDeletion(Path path, int index); -// void removeDelection(Path path); -// void clearDeletion(); -// int getNumberOfDeletions(); -// -public class FilterDeleteSet extends MediaSet implements ContentListener { - @SuppressWarnings("unused") - private static final String TAG = "FilterDeleteSet"; - - private static final int REQUEST_ADD = 1; - private static final int REQUEST_REMOVE = 2; - private static final int REQUEST_CLEAR = 3; - - private static class Request { - int type; // one of the REQUEST_* constants - Path path; - int indexHint; - public Request(int type, Path path, int indexHint) { - this.type = type; - this.path = path; - this.indexHint = indexHint; - } - } - - private static class Deletion { - Path path; - int index; - public Deletion(Path path, int index) { - this.path = path; - this.index = index; - } - } - - // The underlying MediaSet - private final MediaSet mBaseSet; - - // Pending Requests - private ArrayList mRequests = new ArrayList(); - - // Deletions currently in effect, ordered by index - private ArrayList mCurrent = new ArrayList(); - - public FilterDeleteSet(Path path, MediaSet baseSet) { - super(path, INVALID_DATA_VERSION); - mBaseSet = baseSet; - mBaseSet.addContentListener(this); - } - - @Override - public boolean isCameraRoll() { - return mBaseSet.isCameraRoll(); - } - - @Override - public String getName() { - return mBaseSet.getName(); - } - - @Override - public int getMediaItemCount() { - return mBaseSet.getMediaItemCount() - mCurrent.size(); - } - - // Gets the MediaItems whose (post-deletion) index are in the range [start, - // start + count). Because we remove some of the MediaItems, the index need - // to be adjusted. - // - // For example, if there are 12 items in total. The deleted items are 3, 5, - // 10, and the the requested range is [3, 7]: - // - // The original index: 0 1 2 3 4 5 6 7 8 9 A B C - // The deleted items: X X X - // The new index: 0 1 2 3 4 5 6 7 8 9 - // Requested: * * * * * - // - // We need to figure out the [3, 7] actually maps to the original index 4, - // 6, 7, 8, 9. - // - // We can break the MediaItems into segments, each segment other than the - // last one ends in a deleted item. The difference between the new index and - // the original index increases with each segment: - // - // 0 1 2 X (new index = old index) - // 4 X (new index = old index - 1) - // 6 7 8 9 X (new index = old index - 2) - // B C (new index = old index - 3) - // - @Override - public ArrayList getMediaItem(int start, int count) { - if (count <= 0) return new ArrayList(); - - int end = start + count - 1; - int n = mCurrent.size(); - // Find the segment that "start" falls into. Count the number of items - // not yet deleted until it reaches "start". - int i = 0; - for (i = 0; i < n; i++) { - Deletion d = mCurrent.get(i); - if (d.index - i > start) break; - } - // Find the segment that "end" falls into. - int j = i; - for (; j < n; j++) { - Deletion d = mCurrent.get(j); - if (d.index - j > end) break; - } - - // Now get enough to cover deleted items in [start, end] - ArrayList base = mBaseSet.getMediaItem(start + i, count + (j - i)); - - // Remove the deleted items. - for (int m = j - 1; m >= i; m--) { - Deletion d = mCurrent.get(m); - int k = d.index - (start + i); - base.remove(k); - } - return base; - } - - // We apply the pending requests in the mRequests to construct mCurrent in reload(). - @Override - public long reload() { - boolean newData = mBaseSet.reload() > mDataVersion; - synchronized (mRequests) { - if (!newData && mRequests.isEmpty()) { - return mDataVersion; - } - for (int i = 0; i < mRequests.size(); i++) { - Request r = mRequests.get(i); - switch (r.type) { - case REQUEST_ADD: { - // Add the path into mCurrent if there is no duplicate. - int n = mCurrent.size(); - int j; - for (j = 0; j < n; j++) { - if (mCurrent.get(j).path == r.path) break; - } - if (j == n) { - mCurrent.add(new Deletion(r.path, r.indexHint)); - } - break; - } - case REQUEST_REMOVE: { - // Remove the path from mCurrent. - int n = mCurrent.size(); - for (int j = 0; j < n; j++) { - if (mCurrent.get(j).path == r.path) { - mCurrent.remove(j); - break; - } - } - break; - } - case REQUEST_CLEAR: { - mCurrent.clear(); - break; - } - } - } - mRequests.clear(); - } - - if (!mCurrent.isEmpty()) { - // See if the elements in mCurrent can be found in the MediaSet. We - // don't want to search the whole mBaseSet, so we just search a - // small window that contains the index hints (plus some margin). - int minIndex = mCurrent.get(0).index; - int maxIndex = minIndex; - for (int i = 1; i < mCurrent.size(); i++) { - Deletion d = mCurrent.get(i); - minIndex = Math.min(d.index, minIndex); - maxIndex = Math.max(d.index, maxIndex); - } - - int n = mBaseSet.getMediaItemCount(); - int from = Math.max(minIndex - 5, 0); - int to = Math.min(maxIndex + 5, n); - ArrayList items = mBaseSet.getMediaItem(from, to - from); - ArrayList result = new ArrayList(); - for (int i = 0; i < items.size(); i++) { - MediaItem item = items.get(i); - if (item == null) continue; - Path p = item.getPath(); - // Find the matching path in mCurrent, if found move it to result - for (int j = 0; j < mCurrent.size(); j++) { - Deletion d = mCurrent.get(j); - if (d.path == p) { - d.index = from + i; - result.add(d); - mCurrent.remove(j); - break; - } - } - } - mCurrent = result; - } - - mDataVersion = nextVersionNumber(); - return mDataVersion; - } - - private void sendRequest(int type, Path path, int indexHint) { - Request r = new Request(type, path, indexHint); - synchronized (mRequests) { - mRequests.add(r); - } - notifyContentChanged(); - } - - @Override - public void onContentDirty() { - notifyContentChanged(); - } - - public void addDeletion(Path path, int indexHint) { - sendRequest(REQUEST_ADD, path, indexHint); - } - - public void removeDeletion(Path path) { - sendRequest(REQUEST_REMOVE, path, 0 /* unused */); - } - - public void clearDeletion() { - sendRequest(REQUEST_CLEAR, null /* unused */ , 0 /* unused */); - } - - // Returns number of deletions _in effect_ (the number will only gets - // updated after a reload()). - public int getNumberOfDeletions() { - return mCurrent.size(); - } -} diff --git a/src/com/android/gallery3d/data/FilterEmptyPromptSet.java b/src/com/android/gallery3d/data/FilterEmptyPromptSet.java deleted file mode 100644 index b576e06d4..000000000 --- a/src/com/android/gallery3d/data/FilterEmptyPromptSet.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * 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. - */ - -package com.android.gallery3d.data; - -import java.util.ArrayList; - -public class FilterEmptyPromptSet extends MediaSet implements ContentListener { - @SuppressWarnings("unused") - private static final String TAG = "FilterEmptyPromptSet"; - - private ArrayList mEmptyItem; - private MediaSet mBaseSet; - - public FilterEmptyPromptSet(Path path, MediaSet baseSet, MediaItem emptyItem) { - super(path, INVALID_DATA_VERSION); - mEmptyItem = new ArrayList(1); - mEmptyItem.add(emptyItem); - mBaseSet = baseSet; - mBaseSet.addContentListener(this); - } - - @Override - public int getMediaItemCount() { - int itemCount = mBaseSet.getMediaItemCount(); - if (itemCount > 0) { - return itemCount; - } else { - return 1; - } - } - - @Override - public ArrayList getMediaItem(int start, int count) { - int itemCount = mBaseSet.getMediaItemCount(); - if (itemCount > 0) { - return mBaseSet.getMediaItem(start, count); - } else if (start == 0 && count == 1) { - return mEmptyItem; - } else { - throw new ArrayIndexOutOfBoundsException(); - } - } - - @Override - public void onContentDirty() { - notifyContentChanged(); - } - - @Override - public boolean isLeafAlbum() { - return true; - } - - @Override - public boolean isCameraRoll() { - return mBaseSet.isCameraRoll(); - } - - @Override - public long reload() { - return mBaseSet.reload(); - } - - @Override - public String getName() { - return mBaseSet.getName(); - } -} diff --git a/src/com/android/gallery3d/data/FilterSource.java b/src/com/android/gallery3d/data/FilterSource.java deleted file mode 100644 index d689fe336..000000000 --- a/src/com/android/gallery3d/data/FilterSource.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * 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.gallery3d.data; - -import com.android.gallery3d.app.GalleryApp; - -public class FilterSource extends MediaSource { - @SuppressWarnings("unused") - private static final String TAG = "FilterSource"; - private static final int FILTER_BY_MEDIATYPE = 0; - private static final int FILTER_BY_DELETE = 1; - private static final int FILTER_BY_EMPTY = 2; - private static final int FILTER_BY_EMPTY_ITEM = 3; - private static final int FILTER_BY_CAMERA_SHORTCUT = 4; - private static final int FILTER_BY_CAMERA_SHORTCUT_ITEM = 5; - - public static final String FILTER_EMPTY_ITEM = "/filter/empty_prompt"; - public static final String FILTER_CAMERA_SHORTCUT = "/filter/camera_shortcut"; - private static final String FILTER_CAMERA_SHORTCUT_ITEM = "/filter/camera_shortcut_item"; - - private GalleryApp mApplication; - private PathMatcher mMatcher; - private MediaItem mEmptyItem; - private MediaItem mCameraShortcutItem; - - public FilterSource(GalleryApp application) { - super("filter"); - mApplication = application; - mMatcher = new PathMatcher(); - mMatcher.add("/filter/mediatype/*/*", FILTER_BY_MEDIATYPE); - mMatcher.add("/filter/delete/*", FILTER_BY_DELETE); - mMatcher.add("/filter/empty/*", FILTER_BY_EMPTY); - mMatcher.add(FILTER_EMPTY_ITEM, FILTER_BY_EMPTY_ITEM); - mMatcher.add(FILTER_CAMERA_SHORTCUT, FILTER_BY_CAMERA_SHORTCUT); - mMatcher.add(FILTER_CAMERA_SHORTCUT_ITEM, FILTER_BY_CAMERA_SHORTCUT_ITEM); - - mEmptyItem = new EmptyAlbumImage(Path.fromString(FILTER_EMPTY_ITEM), - mApplication); - mCameraShortcutItem = new CameraShortcutImage( - Path.fromString(FILTER_CAMERA_SHORTCUT_ITEM), mApplication); - } - - // The name we accept are: - // /filter/mediatype/k/{set} where k is the media type we want. - // /filter/delete/{set} - @Override - public MediaObject createMediaObject(Path path) { - int matchType = mMatcher.match(path); - DataManager dataManager = mApplication.getDataManager(); - switch (matchType) { - case FILTER_BY_MEDIATYPE: { - int mediaType = mMatcher.getIntVar(0); - String setsName = mMatcher.getVar(1); - MediaSet[] sets = dataManager.getMediaSetsFromString(setsName); - return new FilterTypeSet(path, dataManager, sets[0], mediaType); - } - case FILTER_BY_DELETE: { - String setsName = mMatcher.getVar(0); - MediaSet[] sets = dataManager.getMediaSetsFromString(setsName); - return new FilterDeleteSet(path, sets[0]); - } - case FILTER_BY_EMPTY: { - String setsName = mMatcher.getVar(0); - MediaSet[] sets = dataManager.getMediaSetsFromString(setsName); - return new FilterEmptyPromptSet(path, sets[0], mEmptyItem); - } - case FILTER_BY_EMPTY_ITEM: { - return mEmptyItem; - } - case FILTER_BY_CAMERA_SHORTCUT: { - return new SingleItemAlbum(path, mCameraShortcutItem); - } - case FILTER_BY_CAMERA_SHORTCUT_ITEM: { - return mCameraShortcutItem; - } - default: - throw new RuntimeException("bad path: " + path); - } - } -} diff --git a/src/com/android/gallery3d/data/FilterTypeSet.java b/src/com/android/gallery3d/data/FilterTypeSet.java deleted file mode 100644 index 477ef73ad..000000000 --- a/src/com/android/gallery3d/data/FilterTypeSet.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * 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.gallery3d.data; - -import java.util.ArrayList; - -// FilterTypeSet filters a base MediaSet according to a matching media type. -public class FilterTypeSet extends MediaSet implements ContentListener { - @SuppressWarnings("unused") - private static final String TAG = "FilterTypeSet"; - - private final DataManager mDataManager; - private final MediaSet mBaseSet; - private final int mMediaType; - private final ArrayList mPaths = new ArrayList(); - private final ArrayList mAlbums = new ArrayList(); - - public FilterTypeSet(Path path, DataManager dataManager, MediaSet baseSet, - int mediaType) { - super(path, INVALID_DATA_VERSION); - mDataManager = dataManager; - mBaseSet = baseSet; - mMediaType = mediaType; - mBaseSet.addContentListener(this); - } - - @Override - public String getName() { - return mBaseSet.getName(); - } - - @Override - public MediaSet getSubMediaSet(int index) { - return mAlbums.get(index); - } - - @Override - public int getSubMediaSetCount() { - return mAlbums.size(); - } - - @Override - public int getMediaItemCount() { - return mPaths.size(); - } - - @Override - public ArrayList getMediaItem(int start, int count) { - return ClusterAlbum.getMediaItemFromPath( - mPaths, start, count, mDataManager); - } - - @Override - public long reload() { - if (mBaseSet.reload() > mDataVersion) { - updateData(); - mDataVersion = nextVersionNumber(); - } - return mDataVersion; - } - - @Override - public void onContentDirty() { - notifyContentChanged(); - } - - private void updateData() { - // Albums - mAlbums.clear(); - String basePath = "/filter/mediatype/" + mMediaType; - - for (int i = 0, n = mBaseSet.getSubMediaSetCount(); i < n; i++) { - MediaSet set = mBaseSet.getSubMediaSet(i); - String filteredPath = basePath + "/{" + set.getPath().toString() + "}"; - MediaSet filteredSet = mDataManager.getMediaSet(filteredPath); - filteredSet.reload(); - if (filteredSet.getMediaItemCount() > 0 - || filteredSet.getSubMediaSetCount() > 0) { - mAlbums.add(filteredSet); - } - } - - // Items - mPaths.clear(); - final int total = mBaseSet.getMediaItemCount(); - final Path[] buf = new Path[total]; - - mBaseSet.enumerateMediaItems(new MediaSet.ItemConsumer() { - @Override - public void consume(int index, MediaItem item) { - if (item.getMediaType() == mMediaType) { - if (index < 0 || index >= total) return; - Path path = item.getPath(); - buf[index] = path; - } - } - }); - - for (int i = 0; i < total; i++) { - if (buf[i] != null) { - mPaths.add(buf[i]); - } - } - } - - @Override - public int getSupportedOperations() { - return SUPPORT_SHARE | SUPPORT_DELETE; - } - - @Override - public void delete() { - ItemConsumer consumer = new ItemConsumer() { - @Override - public void consume(int index, MediaItem item) { - if ((item.getSupportedOperations() & SUPPORT_DELETE) != 0) { - item.delete(); - } - } - }; - mDataManager.mapMediaItems(mPaths, consumer, 0); - } -} diff --git a/src/com/android/gallery3d/data/ImageCacheRequest.java b/src/com/android/gallery3d/data/ImageCacheRequest.java deleted file mode 100644 index 6cbc5c5ea..000000000 --- a/src/com/android/gallery3d/data/ImageCacheRequest.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * 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.gallery3d.data; - -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; - -import com.android.gallery3d.app.GalleryApp; -import com.android.gallery3d.common.BitmapUtils; -import com.android.gallery3d.data.BytesBufferPool.BytesBuffer; -import com.android.gallery3d.util.ThreadPool.Job; -import com.android.gallery3d.util.ThreadPool.JobContext; - -abstract class ImageCacheRequest implements Job { - private static final String TAG = "ImageCacheRequest"; - - protected GalleryApp mApplication; - private Path mPath; - private int mType; - private int mTargetSize; - private long mTimeModified; - - public ImageCacheRequest(GalleryApp application, - Path path, long timeModified, int type, int targetSize) { - mApplication = application; - mPath = path; - mType = type; - mTargetSize = targetSize; - mTimeModified = timeModified; - } - - private String debugTag() { - return mPath + "," + mTimeModified + "," + - ((mType == MediaItem.TYPE_THUMBNAIL) ? "THUMB" : - (mType == MediaItem.TYPE_MICROTHUMBNAIL) ? "MICROTHUMB" : "?"); - } - - @Override - public Bitmap run(JobContext jc) { - ImageCacheService cacheService = mApplication.getImageCacheService(); - - BytesBuffer buffer = MediaItem.getBytesBufferPool().get(); - try { - boolean found = cacheService.getImageData(mPath, mTimeModified, mType, buffer); - if (jc.isCancelled()) return null; - if (found) { - BitmapFactory.Options options = new BitmapFactory.Options(); - options.inPreferredConfig = Bitmap.Config.ARGB_8888; - Bitmap bitmap; - if (mType == MediaItem.TYPE_MICROTHUMBNAIL) { - bitmap = DecodeUtils.decodeUsingPool(jc, - buffer.data, buffer.offset, buffer.length, options); - } else { - bitmap = DecodeUtils.decodeUsingPool(jc, - buffer.data, buffer.offset, buffer.length, options); - } - if (bitmap == null && !jc.isCancelled()) { - Log.w(TAG, "decode cached failed " + debugTag()); - } - return bitmap; - } - } finally { - MediaItem.getBytesBufferPool().recycle(buffer); - } - Bitmap bitmap = onDecodeOriginal(jc, mType); - if (jc.isCancelled()) return null; - - if (bitmap == null) { - Log.w(TAG, "decode orig failed " + debugTag()); - return null; - } - - if (mType == MediaItem.TYPE_MICROTHUMBNAIL) { - bitmap = BitmapUtils.resizeAndCropCenter(bitmap, mTargetSize, true); - } else { - bitmap = BitmapUtils.resizeDownBySideLength(bitmap, mTargetSize, true); - } - if (jc.isCancelled()) return null; - - byte[] array = BitmapUtils.compressToBytes(bitmap); - if (jc.isCancelled()) return null; - - cacheService.putImageData(mPath, mTimeModified, mType, array); - return bitmap; - } - - public abstract Bitmap onDecodeOriginal(JobContext jc, int targetSize); -} diff --git a/src/com/android/gallery3d/data/ImageCacheService.java b/src/com/android/gallery3d/data/ImageCacheService.java deleted file mode 100644 index 1c7cb8c5e..000000000 --- a/src/com/android/gallery3d/data/ImageCacheService.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * 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.gallery3d.data; - -import android.content.Context; - -import com.android.gallery3d.common.BlobCache; -import com.android.gallery3d.common.BlobCache.LookupRequest; -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.data.BytesBufferPool.BytesBuffer; -import com.android.gallery3d.util.CacheManager; -import com.android.gallery3d.util.GalleryUtils; - -import java.io.IOException; -import java.nio.ByteBuffer; - -public class ImageCacheService { - @SuppressWarnings("unused") - private static final String TAG = "ImageCacheService"; - - private static final String IMAGE_CACHE_FILE = "imgcache"; - private static final int IMAGE_CACHE_MAX_ENTRIES = 5000; - private static final int IMAGE_CACHE_MAX_BYTES = 200 * 1024 * 1024; - private static final int IMAGE_CACHE_VERSION = 7; - - private BlobCache mCache; - - public ImageCacheService(Context context) { - mCache = CacheManager.getCache(context, IMAGE_CACHE_FILE, - IMAGE_CACHE_MAX_ENTRIES, IMAGE_CACHE_MAX_BYTES, - IMAGE_CACHE_VERSION); - } - - /** - * Gets the cached image data for the given path, - * timeModified and type. - * - * The image data will be stored in buffer.data, started from - * buffer.offset for buffer.length bytes. If the - * buffer.data is not big enough, a new byte array will be allocated and returned. - * - * @return true if the image data is found; false if not found. - */ - public boolean getImageData(Path path, long timeModified, int type, BytesBuffer buffer) { - byte[] key = makeKey(path, timeModified, type); - long cacheKey = Utils.crc64Long(key); - try { - LookupRequest request = new LookupRequest(); - request.key = cacheKey; - request.buffer = buffer.data; - synchronized (mCache) { - if (!mCache.lookup(request)) return false; - } - if (isSameKey(key, request.buffer)) { - buffer.data = request.buffer; - buffer.offset = key.length; - buffer.length = request.length - buffer.offset; - return true; - } - } catch (IOException ex) { - // ignore. - } - return false; - } - - public void putImageData(Path path, long timeModified, int type, byte[] value) { - byte[] key = makeKey(path, timeModified, type); - long cacheKey = Utils.crc64Long(key); - ByteBuffer buffer = ByteBuffer.allocate(key.length + value.length); - buffer.put(key); - buffer.put(value); - synchronized (mCache) { - try { - mCache.insert(cacheKey, buffer.array()); - } catch (IOException ex) { - // ignore. - } - } - } - - public void clearImageData(Path path, long timeModified, int type) { - byte[] key = makeKey(path, timeModified, type); - long cacheKey = Utils.crc64Long(key); - synchronized (mCache) { - try { - mCache.clearEntry(cacheKey); - } catch (IOException ex) { - // ignore. - } - } - } - - private static byte[] makeKey(Path path, long timeModified, int type) { - return GalleryUtils.getBytes(path.toString() + "+" + timeModified + "+" + type); - } - - private static boolean isSameKey(byte[] key, byte[] buffer) { - int n = key.length; - if (buffer.length < n) { - return false; - } - for (int i = 0; i < n; ++i) { - if (key[i] != buffer[i]) { - return false; - } - } - return true; - } -} diff --git a/src/com/android/gallery3d/data/LocalAlbum.java b/src/com/android/gallery3d/data/LocalAlbum.java deleted file mode 100644 index 7b7015af6..000000000 --- a/src/com/android/gallery3d/data/LocalAlbum.java +++ /dev/null @@ -1,325 +0,0 @@ -/* - * 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.gallery3d.data; - -import android.content.ContentResolver; -import android.content.res.Resources; -import android.database.Cursor; -import android.net.Uri; -import android.os.Environment; -import android.provider.MediaStore; -import android.provider.MediaStore.Images; -import android.provider.MediaStore.Images.ImageColumns; -import android.provider.MediaStore.Video; -import android.provider.MediaStore.Video.VideoColumns; - -import com.android.gallery3d.R; -import com.android.gallery3d.app.GalleryApp; -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.util.BucketNames; -import com.android.gallery3d.util.GalleryUtils; -import com.android.gallery3d.util.MediaSetUtils; - -import java.io.File; -import java.util.ArrayList; - -// LocalAlbumSet lists all media items in one bucket on local storage. -// The media items need to be all images or all videos, but not both. -public class LocalAlbum extends MediaSet { - private static final String TAG = "LocalAlbum"; - private static final String[] COUNT_PROJECTION = { "count(*)" }; - - private static final int INVALID_COUNT = -1; - private final String mWhereClause; - private final String mOrderClause; - private final Uri mBaseUri; - private final String[] mProjection; - - private final GalleryApp mApplication; - private final ContentResolver mResolver; - private final int mBucketId; - private final String mName; - private final boolean mIsImage; - private final ChangeNotifier mNotifier; - private final Path mItemPath; - private int mCachedCount = INVALID_COUNT; - - public LocalAlbum(Path path, GalleryApp application, int bucketId, - boolean isImage, String name) { - super(path, nextVersionNumber()); - mApplication = application; - mResolver = application.getContentResolver(); - mBucketId = bucketId; - mName = name; - mIsImage = isImage; - - if (isImage) { - mWhereClause = ImageColumns.BUCKET_ID + " = ?"; - mOrderClause = ImageColumns.DATE_TAKEN + " DESC, " - + ImageColumns._ID + " DESC"; - mBaseUri = Images.Media.EXTERNAL_CONTENT_URI; - mProjection = LocalImage.PROJECTION; - mItemPath = LocalImage.ITEM_PATH; - } else { - mWhereClause = VideoColumns.BUCKET_ID + " = ?"; - mOrderClause = VideoColumns.DATE_TAKEN + " DESC, " - + VideoColumns._ID + " DESC"; - mBaseUri = Video.Media.EXTERNAL_CONTENT_URI; - mProjection = LocalVideo.PROJECTION; - mItemPath = LocalVideo.ITEM_PATH; - } - - mNotifier = new ChangeNotifier(this, mBaseUri, application); - } - - public LocalAlbum(Path path, GalleryApp application, int bucketId, - boolean isImage) { - this(path, application, bucketId, isImage, - BucketHelper.getBucketName( - application.getContentResolver(), bucketId)); - } - - @Override - public boolean isCameraRoll() { - return mBucketId == MediaSetUtils.CAMERA_BUCKET_ID; - } - - @Override - public Uri getContentUri() { - if (mIsImage) { - return MediaStore.Images.Media.EXTERNAL_CONTENT_URI.buildUpon() - .appendQueryParameter(LocalSource.KEY_BUCKET_ID, - String.valueOf(mBucketId)).build(); - } else { - return MediaStore.Video.Media.EXTERNAL_CONTENT_URI.buildUpon() - .appendQueryParameter(LocalSource.KEY_BUCKET_ID, - String.valueOf(mBucketId)).build(); - } - } - - @Override - public ArrayList getMediaItem(int start, int count) { - DataManager dataManager = mApplication.getDataManager(); - Uri uri = mBaseUri.buildUpon() - .appendQueryParameter("limit", start + "," + count).build(); - ArrayList list = new ArrayList(); - GalleryUtils.assertNotInRenderThread(); - Cursor cursor = mResolver.query( - uri, mProjection, mWhereClause, - new String[]{String.valueOf(mBucketId)}, - mOrderClause); - if (cursor == null) { - Log.w(TAG, "query fail: " + uri); - return list; - } - - try { - while (cursor.moveToNext()) { - int id = cursor.getInt(0); // _id must be in the first column - Path childPath = mItemPath.getChild(id); - MediaItem item = loadOrUpdateItem(childPath, cursor, - dataManager, mApplication, mIsImage); - list.add(item); - } - } finally { - cursor.close(); - } - return list; - } - - private static MediaItem loadOrUpdateItem(Path path, Cursor cursor, - DataManager dataManager, GalleryApp app, boolean isImage) { - synchronized (DataManager.LOCK) { - LocalMediaItem item = (LocalMediaItem) dataManager.peekMediaObject(path); - if (item == null) { - if (isImage) { - item = new LocalImage(path, app, cursor); - } else { - item = new LocalVideo(path, app, cursor); - } - } else { - item.updateContent(cursor); - } - return item; - } - } - - // The pids array are sorted by the (path) id. - public static MediaItem[] getMediaItemById( - GalleryApp application, boolean isImage, ArrayList ids) { - // get the lower and upper bound of (path) id - MediaItem[] result = new MediaItem[ids.size()]; - if (ids.isEmpty()) return result; - int idLow = ids.get(0); - int idHigh = ids.get(ids.size() - 1); - - // prepare the query parameters - Uri baseUri; - String[] projection; - Path itemPath; - if (isImage) { - baseUri = Images.Media.EXTERNAL_CONTENT_URI; - projection = LocalImage.PROJECTION; - itemPath = LocalImage.ITEM_PATH; - } else { - baseUri = Video.Media.EXTERNAL_CONTENT_URI; - projection = LocalVideo.PROJECTION; - itemPath = LocalVideo.ITEM_PATH; - } - - ContentResolver resolver = application.getContentResolver(); - DataManager dataManager = application.getDataManager(); - Cursor cursor = resolver.query(baseUri, projection, "_id BETWEEN ? AND ?", - new String[]{String.valueOf(idLow), String.valueOf(idHigh)}, - "_id"); - if (cursor == null) { - Log.w(TAG, "query fail" + baseUri); - return result; - } - try { - int n = ids.size(); - int i = 0; - - while (i < n && cursor.moveToNext()) { - int id = cursor.getInt(0); // _id must be in the first column - - // Match id with the one on the ids list. - if (ids.get(i) > id) { - continue; - } - - while (ids.get(i) < id) { - if (++i >= n) { - return result; - } - } - - Path childPath = itemPath.getChild(id); - MediaItem item = loadOrUpdateItem(childPath, cursor, dataManager, - application, isImage); - result[i] = item; - ++i; - } - return result; - } finally { - cursor.close(); - } - } - - public static Cursor getItemCursor(ContentResolver resolver, Uri uri, - String[] projection, int id) { - return resolver.query(uri, projection, "_id=?", - new String[]{String.valueOf(id)}, null); - } - - @Override - public int getMediaItemCount() { - if (mCachedCount == INVALID_COUNT) { - Cursor cursor = mResolver.query( - mBaseUri, COUNT_PROJECTION, mWhereClause, - new String[]{String.valueOf(mBucketId)}, null); - if (cursor == null) { - Log.w(TAG, "query fail"); - return 0; - } - try { - Utils.assertTrue(cursor.moveToNext()); - mCachedCount = cursor.getInt(0); - } finally { - cursor.close(); - } - } - return mCachedCount; - } - - @Override - public String getName() { - return getLocalizedName(mApplication.getResources(), mBucketId, mName); - } - - @Override - public long reload() { - if (mNotifier.isDirty()) { - mDataVersion = nextVersionNumber(); - mCachedCount = INVALID_COUNT; - } - return mDataVersion; - } - - @Override - public int getSupportedOperations() { - return SUPPORT_DELETE | SUPPORT_SHARE | SUPPORT_INFO; - } - - @Override - public void delete() { - GalleryUtils.assertNotInRenderThread(); - mResolver.delete(mBaseUri, mWhereClause, - new String[]{String.valueOf(mBucketId)}); - } - - @Override - public boolean isLeafAlbum() { - return true; - } - - public static String getLocalizedName(Resources res, int bucketId, - String name) { - if (bucketId == MediaSetUtils.CAMERA_BUCKET_ID) { - return res.getString(R.string.folder_camera); - } else if (bucketId == MediaSetUtils.DOWNLOAD_BUCKET_ID) { - return res.getString(R.string.folder_download); - } else if (bucketId == MediaSetUtils.IMPORTED_BUCKET_ID) { - return res.getString(R.string.folder_imported); - } else if (bucketId == MediaSetUtils.SNAPSHOT_BUCKET_ID) { - return res.getString(R.string.folder_screenshot); - } else if (bucketId == MediaSetUtils.EDITED_ONLINE_PHOTOS_BUCKET_ID) { - return res.getString(R.string.folder_edited_online_photos); - } else { - return name; - } - } - - // Relative path is the absolute path minus external storage path - public static String getRelativePath(int bucketId) { - String relativePath = "/"; - if (bucketId == MediaSetUtils.CAMERA_BUCKET_ID) { - relativePath += BucketNames.CAMERA; - } else if (bucketId == MediaSetUtils.DOWNLOAD_BUCKET_ID) { - relativePath += BucketNames.DOWNLOAD; - } else if (bucketId == MediaSetUtils.IMPORTED_BUCKET_ID) { - relativePath += BucketNames.IMPORTED; - } else if (bucketId == MediaSetUtils.SNAPSHOT_BUCKET_ID) { - relativePath += BucketNames.SCREENSHOTS; - } else if (bucketId == MediaSetUtils.EDITED_ONLINE_PHOTOS_BUCKET_ID) { - relativePath += BucketNames.EDITED_ONLINE_PHOTOS; - } else { - // If the first few cases didn't hit the matching path, do a - // thorough search in the local directories. - File extStorage = Environment.getExternalStorageDirectory(); - String path = GalleryUtils.searchDirForPath(extStorage, bucketId); - if (path == null) { - Log.w(TAG, "Relative path for bucket id: " + bucketId + " is not found."); - relativePath = null; - } else { - relativePath = path.substring(extStorage.getAbsolutePath().length()); - } - } - return relativePath; - } - -} diff --git a/src/com/android/gallery3d/data/LocalAlbumSet.java b/src/com/android/gallery3d/data/LocalAlbumSet.java deleted file mode 100644 index b2b4b8c5d..000000000 --- a/src/com/android/gallery3d/data/LocalAlbumSet.java +++ /dev/null @@ -1,211 +0,0 @@ -/* - * 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.gallery3d.data; - -import android.net.Uri; -import android.os.Handler; -import android.provider.MediaStore.Images; -import android.provider.MediaStore.Video; - -import com.android.gallery3d.R; -import com.android.gallery3d.app.GalleryApp; -import com.android.gallery3d.data.BucketHelper.BucketEntry; -import com.android.gallery3d.util.Future; -import com.android.gallery3d.util.FutureListener; -import com.android.gallery3d.util.MediaSetUtils; -import com.android.gallery3d.util.ThreadPool; -import com.android.gallery3d.util.ThreadPool.JobContext; - -import java.util.ArrayList; -import java.util.Comparator; - -// LocalAlbumSet lists all image or video albums in the local storage. -// The path should be "/local/image", "local/video" or "/local/all" -public class LocalAlbumSet extends MediaSet - implements FutureListener> { - @SuppressWarnings("unused") - private static final String TAG = "LocalAlbumSet"; - - public static final Path PATH_ALL = Path.fromString("/local/all"); - public static final Path PATH_IMAGE = Path.fromString("/local/image"); - public static final Path PATH_VIDEO = Path.fromString("/local/video"); - - private static final Uri[] mWatchUris = - {Images.Media.EXTERNAL_CONTENT_URI, Video.Media.EXTERNAL_CONTENT_URI}; - - private final GalleryApp mApplication; - private final int mType; - private ArrayList mAlbums = new ArrayList(); - private final ChangeNotifier mNotifier; - private final String mName; - private final Handler mHandler; - private boolean mIsLoading; - - private Future> mLoadTask; - private ArrayList mLoadBuffer; - - public LocalAlbumSet(Path path, GalleryApp application) { - super(path, nextVersionNumber()); - mApplication = application; - mHandler = new Handler(application.getMainLooper()); - mType = getTypeFromPath(path); - mNotifier = new ChangeNotifier(this, mWatchUris, application); - mName = application.getResources().getString( - R.string.set_label_local_albums); - } - - private static int getTypeFromPath(Path path) { - String name[] = path.split(); - if (name.length < 2) { - throw new IllegalArgumentException(path.toString()); - } - return getTypeFromString(name[1]); - } - - @Override - public MediaSet getSubMediaSet(int index) { - return mAlbums.get(index); - } - - @Override - public int getSubMediaSetCount() { - return mAlbums.size(); - } - - @Override - public String getName() { - return mName; - } - - private static int findBucket(BucketEntry entries[], int bucketId) { - for (int i = 0, n = entries.length; i < n; ++i) { - if (entries[i].bucketId == bucketId) return i; - } - return -1; - } - - private class AlbumsLoader implements ThreadPool.Job> { - - @Override - @SuppressWarnings("unchecked") - public ArrayList run(JobContext jc) { - // Note: it will be faster if we only select media_type and bucket_id. - // need to test the performance if that is worth - BucketEntry[] entries = BucketHelper.loadBucketEntries( - jc, mApplication.getContentResolver(), mType); - - if (jc.isCancelled()) return null; - - int offset = 0; - // Move camera and download bucket to the front, while keeping the - // order of others. - int index = findBucket(entries, MediaSetUtils.CAMERA_BUCKET_ID); - if (index != -1) { - circularShiftRight(entries, offset++, index); - } - index = findBucket(entries, MediaSetUtils.DOWNLOAD_BUCKET_ID); - if (index != -1) { - circularShiftRight(entries, offset++, index); - } - - ArrayList albums = new ArrayList(); - DataManager dataManager = mApplication.getDataManager(); - for (BucketEntry entry : entries) { - MediaSet album = getLocalAlbum(dataManager, - mType, mPath, entry.bucketId, entry.bucketName); - albums.add(album); - } - return albums; - } - } - - private MediaSet getLocalAlbum( - DataManager manager, int type, Path parent, int id, String name) { - synchronized (DataManager.LOCK) { - Path path = parent.getChild(id); - MediaObject object = manager.peekMediaObject(path); - if (object != null) return (MediaSet) object; - switch (type) { - case MEDIA_TYPE_IMAGE: - return new LocalAlbum(path, mApplication, id, true, name); - case MEDIA_TYPE_VIDEO: - return new LocalAlbum(path, mApplication, id, false, name); - case MEDIA_TYPE_ALL: - Comparator comp = DataManager.sDateTakenComparator; - return new LocalMergeAlbum(path, comp, new MediaSet[] { - getLocalAlbum(manager, MEDIA_TYPE_IMAGE, PATH_IMAGE, id, name), - getLocalAlbum(manager, MEDIA_TYPE_VIDEO, PATH_VIDEO, id, name)}, id); - } - throw new IllegalArgumentException(String.valueOf(type)); - } - } - - @Override - public synchronized boolean isLoading() { - return mIsLoading; - } - - @Override - // synchronized on this function for - // 1. Prevent calling reload() concurrently. - // 2. Prevent calling onFutureDone() and reload() concurrently - public synchronized long reload() { - if (mNotifier.isDirty()) { - if (mLoadTask != null) mLoadTask.cancel(); - mIsLoading = true; - mLoadTask = mApplication.getThreadPool().submit(new AlbumsLoader(), this); - } - if (mLoadBuffer != null) { - mAlbums = mLoadBuffer; - mLoadBuffer = null; - for (MediaSet album : mAlbums) { - album.reload(); - } - mDataVersion = nextVersionNumber(); - } - return mDataVersion; - } - - @Override - public synchronized void onFutureDone(Future> future) { - if (mLoadTask != future) return; // ignore, wait for the latest task - mLoadBuffer = future.get(); - mIsLoading = false; - if (mLoadBuffer == null) mLoadBuffer = new ArrayList(); - mHandler.post(new Runnable() { - @Override - public void run() { - notifyContentChanged(); - } - }); - } - - // For debug only. Fake there is a ContentObserver.onChange() event. - void fakeChange() { - mNotifier.fakeChange(); - } - - // Circular shift the array range from a[i] to a[j] (inclusive). That is, - // a[i] -> a[i+1] -> a[i+2] -> ... -> a[j], and a[j] -> a[i] - private static void circularShiftRight(T[] array, int i, int j) { - T temp = array[j]; - for (int k = j; k > i; k--) { - array[k] = array[k - 1]; - } - array[i] = temp; - } -} diff --git a/src/com/android/gallery3d/data/LocalImage.java b/src/com/android/gallery3d/data/LocalImage.java deleted file mode 100644 index cc70dd457..000000000 --- a/src/com/android/gallery3d/data/LocalImage.java +++ /dev/null @@ -1,355 +0,0 @@ -/* - * 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.gallery3d.data; - -import android.annotation.TargetApi; -import android.content.ContentResolver; -import android.content.ContentValues; -import android.database.Cursor; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.BitmapRegionDecoder; -import android.net.Uri; -import android.os.Build; -import android.provider.MediaStore.Images; -import android.provider.MediaStore.Images.ImageColumns; -import android.provider.MediaStore.MediaColumns; -import android.util.Log; - -import com.android.gallery3d.app.GalleryApp; -import com.android.gallery3d.app.PanoramaMetadataSupport; -import com.android.gallery3d.app.StitchingProgressManager; -import com.android.gallery3d.common.ApiHelper; -import com.android.gallery3d.common.BitmapUtils; -import com.android.gallery3d.exif.ExifInterface; -import com.android.gallery3d.exif.ExifTag; -import com.android.gallery3d.filtershow.tools.SaveImage; -import com.android.gallery3d.util.GalleryUtils; -import com.android.gallery3d.util.ThreadPool.Job; -import com.android.gallery3d.util.ThreadPool.JobContext; -import com.android.gallery3d.util.UpdateHelper; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; - -// LocalImage represents an image in the local storage. -public class LocalImage extends LocalMediaItem { - private static final String TAG = "LocalImage"; - - static final Path ITEM_PATH = Path.fromString("/local/image/item"); - - // Must preserve order between these indices and the order of the terms in - // the following PROJECTION array. - private static final int INDEX_ID = 0; - private static final int INDEX_CAPTION = 1; - private static final int INDEX_MIME_TYPE = 2; - private static final int INDEX_LATITUDE = 3; - private static final int INDEX_LONGITUDE = 4; - private static final int INDEX_DATE_TAKEN = 5; - private static final int INDEX_DATE_ADDED = 6; - private static final int INDEX_DATE_MODIFIED = 7; - private static final int INDEX_DATA = 8; - private static final int INDEX_ORIENTATION = 9; - private static final int INDEX_BUCKET_ID = 10; - private static final int INDEX_SIZE = 11; - private static final int INDEX_WIDTH = 12; - private static final int INDEX_HEIGHT = 13; - - static final String[] PROJECTION = { - ImageColumns._ID, // 0 - ImageColumns.TITLE, // 1 - ImageColumns.MIME_TYPE, // 2 - ImageColumns.LATITUDE, // 3 - ImageColumns.LONGITUDE, // 4 - ImageColumns.DATE_TAKEN, // 5 - ImageColumns.DATE_ADDED, // 6 - ImageColumns.DATE_MODIFIED, // 7 - ImageColumns.DATA, // 8 - ImageColumns.ORIENTATION, // 9 - ImageColumns.BUCKET_ID, // 10 - ImageColumns.SIZE, // 11 - "0", // 12 - "0" // 13 - }; - - static { - updateWidthAndHeightProjection(); - } - - @TargetApi(Build.VERSION_CODES.JELLY_BEAN) - private static void updateWidthAndHeightProjection() { - if (ApiHelper.HAS_MEDIA_COLUMNS_WIDTH_AND_HEIGHT) { - PROJECTION[INDEX_WIDTH] = MediaColumns.WIDTH; - PROJECTION[INDEX_HEIGHT] = MediaColumns.HEIGHT; - } - } - - private final GalleryApp mApplication; - - public int rotation; - - private PanoramaMetadataSupport mPanoramaMetadata = new PanoramaMetadataSupport(this); - - public LocalImage(Path path, GalleryApp application, Cursor cursor) { - super(path, nextVersionNumber()); - mApplication = application; - loadFromCursor(cursor); - } - - public LocalImage(Path path, GalleryApp application, int id) { - super(path, nextVersionNumber()); - mApplication = application; - ContentResolver resolver = mApplication.getContentResolver(); - Uri uri = Images.Media.EXTERNAL_CONTENT_URI; - Cursor cursor = LocalAlbum.getItemCursor(resolver, uri, PROJECTION, id); - if (cursor == null) { - throw new RuntimeException("cannot get cursor for: " + path); - } - try { - if (cursor.moveToNext()) { - loadFromCursor(cursor); - } else { - throw new RuntimeException("cannot find data for: " + path); - } - } finally { - cursor.close(); - } - } - - private void loadFromCursor(Cursor cursor) { - id = cursor.getInt(INDEX_ID); - caption = cursor.getString(INDEX_CAPTION); - mimeType = cursor.getString(INDEX_MIME_TYPE); - latitude = cursor.getDouble(INDEX_LATITUDE); - longitude = cursor.getDouble(INDEX_LONGITUDE); - dateTakenInMs = cursor.getLong(INDEX_DATE_TAKEN); - dateAddedInSec = cursor.getLong(INDEX_DATE_ADDED); - dateModifiedInSec = cursor.getLong(INDEX_DATE_MODIFIED); - filePath = cursor.getString(INDEX_DATA); - rotation = cursor.getInt(INDEX_ORIENTATION); - bucketId = cursor.getInt(INDEX_BUCKET_ID); - fileSize = cursor.getLong(INDEX_SIZE); - width = cursor.getInt(INDEX_WIDTH); - height = cursor.getInt(INDEX_HEIGHT); - } - - @Override - protected boolean updateFromCursor(Cursor cursor) { - UpdateHelper uh = new UpdateHelper(); - id = uh.update(id, cursor.getInt(INDEX_ID)); - caption = uh.update(caption, cursor.getString(INDEX_CAPTION)); - mimeType = uh.update(mimeType, cursor.getString(INDEX_MIME_TYPE)); - latitude = uh.update(latitude, cursor.getDouble(INDEX_LATITUDE)); - longitude = uh.update(longitude, cursor.getDouble(INDEX_LONGITUDE)); - dateTakenInMs = uh.update( - dateTakenInMs, cursor.getLong(INDEX_DATE_TAKEN)); - dateAddedInSec = uh.update( - dateAddedInSec, cursor.getLong(INDEX_DATE_ADDED)); - dateModifiedInSec = uh.update( - dateModifiedInSec, cursor.getLong(INDEX_DATE_MODIFIED)); - filePath = uh.update(filePath, cursor.getString(INDEX_DATA)); - rotation = uh.update(rotation, cursor.getInt(INDEX_ORIENTATION)); - bucketId = uh.update(bucketId, cursor.getInt(INDEX_BUCKET_ID)); - fileSize = uh.update(fileSize, cursor.getLong(INDEX_SIZE)); - width = uh.update(width, cursor.getInt(INDEX_WIDTH)); - height = uh.update(height, cursor.getInt(INDEX_HEIGHT)); - return uh.isUpdated(); - } - - @Override - public Job requestImage(int type) { - return new LocalImageRequest(mApplication, mPath, dateModifiedInSec, - type, filePath); - } - - public static class LocalImageRequest extends ImageCacheRequest { - private String mLocalFilePath; - - LocalImageRequest(GalleryApp application, Path path, long timeModified, - int type, String localFilePath) { - super(application, path, timeModified, type, - MediaItem.getTargetSize(type)); - mLocalFilePath = localFilePath; - } - - @Override - public Bitmap onDecodeOriginal(JobContext jc, final int type) { - BitmapFactory.Options options = new BitmapFactory.Options(); - options.inPreferredConfig = Bitmap.Config.ARGB_8888; - int targetSize = MediaItem.getTargetSize(type); - - // try to decode from JPEG EXIF - if (type == MediaItem.TYPE_MICROTHUMBNAIL) { - ExifInterface exif = new ExifInterface(); - byte[] thumbData = null; - try { - exif.readExif(mLocalFilePath); - thumbData = exif.getThumbnail(); - } catch (FileNotFoundException e) { - Log.w(TAG, "failed to find file to read thumbnail: " + mLocalFilePath); - } catch (IOException e) { - Log.w(TAG, "failed to get thumbnail from: " + mLocalFilePath); - } - if (thumbData != null) { - Bitmap bitmap = DecodeUtils.decodeIfBigEnough( - jc, thumbData, options, targetSize); - if (bitmap != null) return bitmap; - } - } - - return DecodeUtils.decodeThumbnail(jc, mLocalFilePath, options, targetSize, type); - } - } - - @Override - public Job requestLargeImage() { - return new LocalLargeImageRequest(filePath); - } - - public static class LocalLargeImageRequest - implements Job { - String mLocalFilePath; - - public LocalLargeImageRequest(String localFilePath) { - mLocalFilePath = localFilePath; - } - - @Override - public BitmapRegionDecoder run(JobContext jc) { - return DecodeUtils.createBitmapRegionDecoder(jc, mLocalFilePath, false); - } - } - - @Override - public int getSupportedOperations() { - StitchingProgressManager progressManager = mApplication.getStitchingProgressManager(); - if (progressManager != null && progressManager.getProgress(getContentUri()) != null) { - return 0; // doesn't support anything while stitching! - } - int operation = SUPPORT_DELETE | SUPPORT_SHARE | SUPPORT_CROP - | SUPPORT_SETAS | SUPPORT_EDIT | SUPPORT_INFO; - if (BitmapUtils.isSupportedByRegionDecoder(mimeType)) { - operation |= SUPPORT_FULL_IMAGE; - } - - if (BitmapUtils.isRotationSupported(mimeType)) { - operation |= SUPPORT_ROTATE; - } - - if (GalleryUtils.isValidLocation(latitude, longitude)) { - operation |= SUPPORT_SHOW_ON_MAP; - } - return operation; - } - - @Override - public void getPanoramaSupport(PanoramaSupportCallback callback) { - mPanoramaMetadata.getPanoramaSupport(mApplication, callback); - } - - @Override - public void clearCachedPanoramaSupport() { - mPanoramaMetadata.clearCachedValues(); - } - - @Override - public void delete() { - GalleryUtils.assertNotInRenderThread(); - Uri baseUri = Images.Media.EXTERNAL_CONTENT_URI; - ContentResolver contentResolver = mApplication.getContentResolver(); - SaveImage.deleteAuxFiles(contentResolver, getContentUri()); - contentResolver.delete(baseUri, "_id=?", - new String[]{String.valueOf(id)}); - } - - @Override - public void rotate(int degrees) { - GalleryUtils.assertNotInRenderThread(); - Uri baseUri = Images.Media.EXTERNAL_CONTENT_URI; - ContentValues values = new ContentValues(); - int rotation = (this.rotation + degrees) % 360; - if (rotation < 0) rotation += 360; - - if (mimeType.equalsIgnoreCase("image/jpeg")) { - ExifInterface exifInterface = new ExifInterface(); - ExifTag tag = exifInterface.buildTag(ExifInterface.TAG_ORIENTATION, - ExifInterface.getOrientationValueForRotation(rotation)); - if(tag != null) { - exifInterface.setTag(tag); - try { - exifInterface.forceRewriteExif(filePath); - fileSize = new File(filePath).length(); - values.put(Images.Media.SIZE, fileSize); - } catch (FileNotFoundException e) { - Log.w(TAG, "cannot find file to set exif: " + filePath); - } catch (IOException e) { - Log.w(TAG, "cannot set exif data: " + filePath); - } - } else { - Log.w(TAG, "Could not build tag: " + ExifInterface.TAG_ORIENTATION); - } - } - - values.put(Images.Media.ORIENTATION, rotation); - mApplication.getContentResolver().update(baseUri, values, "_id=?", - new String[]{String.valueOf(id)}); - } - - @Override - public Uri getContentUri() { - Uri baseUri = Images.Media.EXTERNAL_CONTENT_URI; - return baseUri.buildUpon().appendPath(String.valueOf(id)).build(); - } - - @Override - public int getMediaType() { - return MEDIA_TYPE_IMAGE; - } - - @Override - public MediaDetails getDetails() { - MediaDetails details = super.getDetails(); - details.addDetail(MediaDetails.INDEX_ORIENTATION, Integer.valueOf(rotation)); - if (MIME_TYPE_JPEG.equals(mimeType)) { - // ExifInterface returns incorrect values for photos in other format. - // For example, the width and height of an webp images is always '0'. - MediaDetails.extractExifInfo(details, filePath); - } - return details; - } - - @Override - public int getRotation() { - return rotation; - } - - @Override - public int getWidth() { - return width; - } - - @Override - public int getHeight() { - return height; - } - - @Override - public String getFilePath() { - return filePath; - } -} diff --git a/src/com/android/gallery3d/data/LocalMediaItem.java b/src/com/android/gallery3d/data/LocalMediaItem.java deleted file mode 100644 index 7e003cd3a..000000000 --- a/src/com/android/gallery3d/data/LocalMediaItem.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * 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.gallery3d.data; - -import android.database.Cursor; - -import com.android.gallery3d.util.GalleryUtils; - -import java.text.DateFormat; -import java.util.Date; - -// -// LocalMediaItem is an abstract class captures those common fields -// in LocalImage and LocalVideo. -// -public abstract class LocalMediaItem extends MediaItem { - - @SuppressWarnings("unused") - private static final String TAG = "LocalMediaItem"; - - // database fields - public int id; - public String caption; - public String mimeType; - public long fileSize; - public double latitude = INVALID_LATLNG; - public double longitude = INVALID_LATLNG; - public long dateTakenInMs; - public long dateAddedInSec; - public long dateModifiedInSec; - public String filePath; - public int bucketId; - public int width; - public int height; - - public LocalMediaItem(Path path, long version) { - super(path, version); - } - - @Override - public long getDateInMs() { - return dateTakenInMs; - } - - @Override - public String getName() { - return caption; - } - - @Override - public void getLatLong(double[] latLong) { - latLong[0] = latitude; - latLong[1] = longitude; - } - - abstract protected boolean updateFromCursor(Cursor cursor); - - public int getBucketId() { - return bucketId; - } - - protected void updateContent(Cursor cursor) { - if (updateFromCursor(cursor)) { - mDataVersion = nextVersionNumber(); - } - } - - @Override - public MediaDetails getDetails() { - MediaDetails details = super.getDetails(); - details.addDetail(MediaDetails.INDEX_PATH, filePath); - details.addDetail(MediaDetails.INDEX_TITLE, caption); - DateFormat formater = DateFormat.getDateTimeInstance(); - details.addDetail(MediaDetails.INDEX_DATETIME, - formater.format(new Date(dateModifiedInSec * 1000))); - details.addDetail(MediaDetails.INDEX_WIDTH, width); - details.addDetail(MediaDetails.INDEX_HEIGHT, height); - - if (GalleryUtils.isValidLocation(latitude, longitude)) { - details.addDetail(MediaDetails.INDEX_LOCATION, new double[] {latitude, longitude}); - } - if (fileSize > 0) details.addDetail(MediaDetails.INDEX_SIZE, fileSize); - return details; - } - - @Override - public String getMimeType() { - return mimeType; - } - - @Override - public long getSize() { - return fileSize; - } -} diff --git a/src/com/android/gallery3d/data/LocalMergeAlbum.java b/src/com/android/gallery3d/data/LocalMergeAlbum.java deleted file mode 100644 index f0b5e5726..000000000 --- a/src/com/android/gallery3d/data/LocalMergeAlbum.java +++ /dev/null @@ -1,257 +0,0 @@ -/* - * 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.gallery3d.data; - -import android.net.Uri; -import android.provider.MediaStore; - -import com.android.gallery3d.common.ApiHelper; - -import java.lang.ref.SoftReference; -import java.util.ArrayList; -import java.util.Comparator; -import java.util.NoSuchElementException; -import java.util.SortedMap; -import java.util.TreeMap; - -// MergeAlbum merges items from two or more MediaSets. It uses a Comparator to -// determine the order of items. The items are assumed to be sorted in the input -// media sets (with the same order that the Comparator uses). -// -// This only handles MediaItems, not SubMediaSets. -public class LocalMergeAlbum extends MediaSet implements ContentListener { - @SuppressWarnings("unused") - private static final String TAG = "LocalMergeAlbum"; - private static final int PAGE_SIZE = 64; - - private final Comparator mComparator; - private final MediaSet[] mSources; - - private FetchCache[] mFetcher; - private int mSupportedOperation; - private int mBucketId; - - // mIndex maps global position to the position of each underlying media sets. - private TreeMap mIndex = new TreeMap(); - - public LocalMergeAlbum( - Path path, Comparator comparator, MediaSet[] sources, int bucketId) { - super(path, INVALID_DATA_VERSION); - mComparator = comparator; - mSources = sources; - mBucketId = bucketId; - for (MediaSet set : mSources) { - set.addContentListener(this); - } - reload(); - } - - @Override - public boolean isCameraRoll() { - if (mSources.length == 0) return false; - for(MediaSet set : mSources) { - if (!set.isCameraRoll()) return false; - } - return true; - } - - private void updateData() { - ArrayList matches = new ArrayList(); - int supported = mSources.length == 0 ? 0 : MediaItem.SUPPORT_ALL; - mFetcher = new FetchCache[mSources.length]; - for (int i = 0, n = mSources.length; i < n; ++i) { - mFetcher[i] = new FetchCache(mSources[i]); - supported &= mSources[i].getSupportedOperations(); - } - mSupportedOperation = supported; - mIndex.clear(); - mIndex.put(0, new int[mSources.length]); - } - - private void invalidateCache() { - for (int i = 0, n = mSources.length; i < n; i++) { - mFetcher[i].invalidate(); - } - mIndex.clear(); - mIndex.put(0, new int[mSources.length]); - } - - @Override - public Uri getContentUri() { - String bucketId = String.valueOf(mBucketId); - if (ApiHelper.HAS_MEDIA_PROVIDER_FILES_TABLE) { - return MediaStore.Files.getContentUri("external").buildUpon() - .appendQueryParameter(LocalSource.KEY_BUCKET_ID, bucketId) - .build(); - } else { - // We don't have a single URL for a merged image before ICS - // So we used the image's URL as a substitute. - return MediaStore.Images.Media.EXTERNAL_CONTENT_URI.buildUpon() - .appendQueryParameter(LocalSource.KEY_BUCKET_ID, bucketId) - .build(); - } - } - - @Override - public String getName() { - return mSources.length == 0 ? "" : mSources[0].getName(); - } - - @Override - public int getMediaItemCount() { - return getTotalMediaItemCount(); - } - - @Override - public ArrayList getMediaItem(int start, int count) { - - // First find the nearest mark position <= start. - SortedMap head = mIndex.headMap(start + 1); - int markPos = head.lastKey(); - int[] subPos = head.get(markPos).clone(); - MediaItem[] slot = new MediaItem[mSources.length]; - - int size = mSources.length; - - // fill all slots - for (int i = 0; i < size; i++) { - slot[i] = mFetcher[i].getItem(subPos[i]); - } - - ArrayList result = new ArrayList(); - - for (int i = markPos; i < start + count; i++) { - int k = -1; // k points to the best slot up to now. - for (int j = 0; j < size; j++) { - if (slot[j] != null) { - if (k == -1 || mComparator.compare(slot[j], slot[k]) < 0) { - k = j; - } - } - } - - // If we don't have anything, all streams are exhausted. - if (k == -1) break; - - // Pick the best slot and refill it. - subPos[k]++; - if (i >= start) { - result.add(slot[k]); - } - slot[k] = mFetcher[k].getItem(subPos[k]); - - // Periodically leave a mark in the index, so we can come back later. - if ((i + 1) % PAGE_SIZE == 0) { - mIndex.put(i + 1, subPos.clone()); - } - } - - return result; - } - - @Override - public int getTotalMediaItemCount() { - int count = 0; - for (MediaSet set : mSources) { - count += set.getTotalMediaItemCount(); - } - return count; - } - - @Override - public long reload() { - boolean changed = false; - for (int i = 0, n = mSources.length; i < n; ++i) { - if (mSources[i].reload() > mDataVersion) changed = true; - } - if (changed) { - mDataVersion = nextVersionNumber(); - updateData(); - invalidateCache(); - } - return mDataVersion; - } - - @Override - public void onContentDirty() { - notifyContentChanged(); - } - - @Override - public int getSupportedOperations() { - return mSupportedOperation; - } - - @Override - public void delete() { - for (MediaSet set : mSources) { - set.delete(); - } - } - - @Override - public void rotate(int degrees) { - for (MediaSet set : mSources) { - set.rotate(degrees); - } - } - - private static class FetchCache { - private MediaSet mBaseSet; - private SoftReference> mCacheRef; - private int mStartPos; - - public FetchCache(MediaSet baseSet) { - mBaseSet = baseSet; - } - - public void invalidate() { - mCacheRef = null; - } - - public MediaItem getItem(int index) { - boolean needLoading = false; - ArrayList cache = null; - if (mCacheRef == null - || index < mStartPos || index >= mStartPos + PAGE_SIZE) { - needLoading = true; - } else { - cache = mCacheRef.get(); - if (cache == null) { - needLoading = true; - } - } - - if (needLoading) { - cache = mBaseSet.getMediaItem(index, PAGE_SIZE); - mCacheRef = new SoftReference>(cache); - mStartPos = index; - } - - if (index < mStartPos || index >= mStartPos + cache.size()) { - return null; - } - - return cache.get(index - mStartPos); - } - } - - @Override - public boolean isLeafAlbum() { - return true; - } -} diff --git a/src/com/android/gallery3d/data/LocalSource.java b/src/com/android/gallery3d/data/LocalSource.java deleted file mode 100644 index a2e3d1443..000000000 --- a/src/com/android/gallery3d/data/LocalSource.java +++ /dev/null @@ -1,275 +0,0 @@ -/* - * 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.gallery3d.data; - -import android.content.ContentProviderClient; -import android.content.ContentUris; -import android.content.UriMatcher; -import android.net.Uri; -import android.provider.MediaStore; - -import com.android.gallery3d.app.Gallery; -import com.android.gallery3d.app.GalleryApp; -import com.android.gallery3d.data.MediaSet.ItemConsumer; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; - -class LocalSource extends MediaSource { - - public static final String KEY_BUCKET_ID = "bucketId"; - - private GalleryApp mApplication; - private PathMatcher mMatcher; - private static final int NO_MATCH = -1; - private final UriMatcher mUriMatcher = new UriMatcher(NO_MATCH); - public static final Comparator sIdComparator = new IdComparator(); - - private static final int LOCAL_IMAGE_ALBUMSET = 0; - private static final int LOCAL_VIDEO_ALBUMSET = 1; - private static final int LOCAL_IMAGE_ALBUM = 2; - private static final int LOCAL_VIDEO_ALBUM = 3; - private static final int LOCAL_IMAGE_ITEM = 4; - private static final int LOCAL_VIDEO_ITEM = 5; - private static final int LOCAL_ALL_ALBUMSET = 6; - private static final int LOCAL_ALL_ALBUM = 7; - - private static final String TAG = "LocalSource"; - - private ContentProviderClient mClient; - - public LocalSource(GalleryApp context) { - super("local"); - mApplication = context; - mMatcher = new PathMatcher(); - mMatcher.add("/local/image", LOCAL_IMAGE_ALBUMSET); - mMatcher.add("/local/video", LOCAL_VIDEO_ALBUMSET); - mMatcher.add("/local/all", LOCAL_ALL_ALBUMSET); - - mMatcher.add("/local/image/*", LOCAL_IMAGE_ALBUM); - mMatcher.add("/local/video/*", LOCAL_VIDEO_ALBUM); - mMatcher.add("/local/all/*", LOCAL_ALL_ALBUM); - mMatcher.add("/local/image/item/*", LOCAL_IMAGE_ITEM); - mMatcher.add("/local/video/item/*", LOCAL_VIDEO_ITEM); - - mUriMatcher.addURI(MediaStore.AUTHORITY, - "external/images/media/#", LOCAL_IMAGE_ITEM); - mUriMatcher.addURI(MediaStore.AUTHORITY, - "external/video/media/#", LOCAL_VIDEO_ITEM); - mUriMatcher.addURI(MediaStore.AUTHORITY, - "external/images/media", LOCAL_IMAGE_ALBUM); - mUriMatcher.addURI(MediaStore.AUTHORITY, - "external/video/media", LOCAL_VIDEO_ALBUM); - mUriMatcher.addURI(MediaStore.AUTHORITY, - "external/file", LOCAL_ALL_ALBUM); - } - - @Override - public MediaObject createMediaObject(Path path) { - GalleryApp app = mApplication; - switch (mMatcher.match(path)) { - case LOCAL_ALL_ALBUMSET: - case LOCAL_IMAGE_ALBUMSET: - case LOCAL_VIDEO_ALBUMSET: - return new LocalAlbumSet(path, mApplication); - case LOCAL_IMAGE_ALBUM: - return new LocalAlbum(path, app, mMatcher.getIntVar(0), true); - case LOCAL_VIDEO_ALBUM: - return new LocalAlbum(path, app, mMatcher.getIntVar(0), false); - case LOCAL_ALL_ALBUM: { - int bucketId = mMatcher.getIntVar(0); - DataManager dataManager = app.getDataManager(); - MediaSet imageSet = (MediaSet) dataManager.getMediaObject( - LocalAlbumSet.PATH_IMAGE.getChild(bucketId)); - MediaSet videoSet = (MediaSet) dataManager.getMediaObject( - LocalAlbumSet.PATH_VIDEO.getChild(bucketId)); - Comparator comp = DataManager.sDateTakenComparator; - return new LocalMergeAlbum( - path, comp, new MediaSet[] {imageSet, videoSet}, bucketId); - } - case LOCAL_IMAGE_ITEM: - return new LocalImage(path, mApplication, mMatcher.getIntVar(0)); - case LOCAL_VIDEO_ITEM: - return new LocalVideo(path, mApplication, mMatcher.getIntVar(0)); - default: - throw new RuntimeException("bad path: " + path); - } - } - - private static int getMediaType(String type, int defaultType) { - if (type == null) return defaultType; - try { - int value = Integer.parseInt(type); - if ((value & (MEDIA_TYPE_IMAGE - | MEDIA_TYPE_VIDEO)) != 0) return value; - } catch (NumberFormatException e) { - Log.w(TAG, "invalid type: " + type, e); - } - return defaultType; - } - - // The media type bit passed by the intent - private static final int MEDIA_TYPE_ALL = 0; - private static final int MEDIA_TYPE_IMAGE = 1; - private static final int MEDIA_TYPE_VIDEO = 4; - - private Path getAlbumPath(Uri uri, int defaultType) { - int mediaType = getMediaType( - uri.getQueryParameter(Gallery.KEY_MEDIA_TYPES), - defaultType); - String bucketId = uri.getQueryParameter(KEY_BUCKET_ID); - int id = 0; - try { - id = Integer.parseInt(bucketId); - } catch (NumberFormatException e) { - Log.w(TAG, "invalid bucket id: " + bucketId, e); - return null; - } - switch (mediaType) { - case MEDIA_TYPE_IMAGE: - return Path.fromString("/local/image").getChild(id); - case MEDIA_TYPE_VIDEO: - return Path.fromString("/local/video").getChild(id); - default: - return Path.fromString("/local/all").getChild(id); - } - } - - @Override - public Path findPathByUri(Uri uri, String type) { - try { - switch (mUriMatcher.match(uri)) { - case LOCAL_IMAGE_ITEM: { - long id = ContentUris.parseId(uri); - return id >= 0 ? LocalImage.ITEM_PATH.getChild(id) : null; - } - case LOCAL_VIDEO_ITEM: { - long id = ContentUris.parseId(uri); - return id >= 0 ? LocalVideo.ITEM_PATH.getChild(id) : null; - } - case LOCAL_IMAGE_ALBUM: { - return getAlbumPath(uri, MEDIA_TYPE_IMAGE); - } - case LOCAL_VIDEO_ALBUM: { - return getAlbumPath(uri, MEDIA_TYPE_VIDEO); - } - case LOCAL_ALL_ALBUM: { - return getAlbumPath(uri, MEDIA_TYPE_ALL); - } - } - } catch (NumberFormatException e) { - Log.w(TAG, "uri: " + uri.toString(), e); - } - return null; - } - - @Override - public Path getDefaultSetOf(Path item) { - MediaObject object = mApplication.getDataManager().getMediaObject(item); - if (object instanceof LocalMediaItem) { - return Path.fromString("/local/all").getChild( - String.valueOf(((LocalMediaItem) object).getBucketId())); - } - return null; - } - - @Override - public void mapMediaItems(ArrayList list, ItemConsumer consumer) { - ArrayList imageList = new ArrayList(); - ArrayList videoList = new ArrayList(); - int n = list.size(); - for (int i = 0; i < n; i++) { - PathId pid = list.get(i); - // We assume the form is: "/local/{image,video}/item/#" - // We don't use mMatcher for efficiency's reason. - Path parent = pid.path.getParent(); - if (parent == LocalImage.ITEM_PATH) { - imageList.add(pid); - } else if (parent == LocalVideo.ITEM_PATH) { - videoList.add(pid); - } - } - // TODO: use "files" table so we can merge the two cases. - processMapMediaItems(imageList, consumer, true); - processMapMediaItems(videoList, consumer, false); - } - - private void processMapMediaItems(ArrayList list, - ItemConsumer consumer, boolean isImage) { - // Sort path by path id - Collections.sort(list, sIdComparator); - int n = list.size(); - for (int i = 0; i < n; ) { - PathId pid = list.get(i); - - // Find a range of items. - ArrayList ids = new ArrayList(); - int startId = Integer.parseInt(pid.path.getSuffix()); - ids.add(startId); - - int j; - for (j = i + 1; j < n; j++) { - PathId pid2 = list.get(j); - int curId = Integer.parseInt(pid2.path.getSuffix()); - if (curId - startId >= MediaSet.MEDIAITEM_BATCH_FETCH_COUNT) { - break; - } - ids.add(curId); - } - - MediaItem[] items = LocalAlbum.getMediaItemById( - mApplication, isImage, ids); - for(int k = i ; k < j; k++) { - PathId pid2 = list.get(k); - consumer.consume(pid2.id, items[k - i]); - } - - i = j; - } - } - - // This is a comparator which compares the suffix number in two Paths. - private static class IdComparator implements Comparator { - @Override - public int compare(PathId p1, PathId p2) { - String s1 = p1.path.getSuffix(); - String s2 = p2.path.getSuffix(); - int len1 = s1.length(); - int len2 = s2.length(); - if (len1 < len2) { - return -1; - } else if (len1 > len2) { - return 1; - } else { - return s1.compareTo(s2); - } - } - } - - @Override - public void resume() { - mClient = mApplication.getContentResolver() - .acquireContentProviderClient(MediaStore.AUTHORITY); - } - - @Override - public void pause() { - mClient.release(); - mClient = null; - } -} diff --git a/src/com/android/gallery3d/data/LocalVideo.java b/src/com/android/gallery3d/data/LocalVideo.java deleted file mode 100644 index 4b8774ca4..000000000 --- a/src/com/android/gallery3d/data/LocalVideo.java +++ /dev/null @@ -1,242 +0,0 @@ -/* - * 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.gallery3d.data; - -import android.content.ContentResolver; -import android.database.Cursor; -import android.graphics.Bitmap; -import android.graphics.BitmapRegionDecoder; -import android.net.Uri; -import android.provider.MediaStore.Video; -import android.provider.MediaStore.Video.VideoColumns; - -import com.android.gallery3d.app.GalleryApp; -import com.android.gallery3d.common.BitmapUtils; -import com.android.gallery3d.util.GalleryUtils; -import com.android.gallery3d.util.ThreadPool.Job; -import com.android.gallery3d.util.ThreadPool.JobContext; -import com.android.gallery3d.util.UpdateHelper; - -// LocalVideo represents a video in the local storage. -public class LocalVideo extends LocalMediaItem { - private static final String TAG = "LocalVideo"; - static final Path ITEM_PATH = Path.fromString("/local/video/item"); - - // Must preserve order between these indices and the order of the terms in - // the following PROJECTION array. - private static final int INDEX_ID = 0; - private static final int INDEX_CAPTION = 1; - private static final int INDEX_MIME_TYPE = 2; - private static final int INDEX_LATITUDE = 3; - private static final int INDEX_LONGITUDE = 4; - private static final int INDEX_DATE_TAKEN = 5; - private static final int INDEX_DATE_ADDED = 6; - private static final int INDEX_DATE_MODIFIED = 7; - private static final int INDEX_DATA = 8; - private static final int INDEX_DURATION = 9; - private static final int INDEX_BUCKET_ID = 10; - private static final int INDEX_SIZE = 11; - private static final int INDEX_RESOLUTION = 12; - - static final String[] PROJECTION = new String[] { - VideoColumns._ID, - VideoColumns.TITLE, - VideoColumns.MIME_TYPE, - VideoColumns.LATITUDE, - VideoColumns.LONGITUDE, - VideoColumns.DATE_TAKEN, - VideoColumns.DATE_ADDED, - VideoColumns.DATE_MODIFIED, - VideoColumns.DATA, - VideoColumns.DURATION, - VideoColumns.BUCKET_ID, - VideoColumns.SIZE, - VideoColumns.RESOLUTION, - }; - - private final GalleryApp mApplication; - - public int durationInSec; - - public LocalVideo(Path path, GalleryApp application, Cursor cursor) { - super(path, nextVersionNumber()); - mApplication = application; - loadFromCursor(cursor); - } - - public LocalVideo(Path path, GalleryApp context, int id) { - super(path, nextVersionNumber()); - mApplication = context; - ContentResolver resolver = mApplication.getContentResolver(); - Uri uri = Video.Media.EXTERNAL_CONTENT_URI; - Cursor cursor = LocalAlbum.getItemCursor(resolver, uri, PROJECTION, id); - if (cursor == null) { - throw new RuntimeException("cannot get cursor for: " + path); - } - try { - if (cursor.moveToNext()) { - loadFromCursor(cursor); - } else { - throw new RuntimeException("cannot find data for: " + path); - } - } finally { - cursor.close(); - } - } - - private void loadFromCursor(Cursor cursor) { - id = cursor.getInt(INDEX_ID); - caption = cursor.getString(INDEX_CAPTION); - mimeType = cursor.getString(INDEX_MIME_TYPE); - latitude = cursor.getDouble(INDEX_LATITUDE); - longitude = cursor.getDouble(INDEX_LONGITUDE); - dateTakenInMs = cursor.getLong(INDEX_DATE_TAKEN); - dateAddedInSec = cursor.getLong(INDEX_DATE_ADDED); - dateModifiedInSec = cursor.getLong(INDEX_DATE_MODIFIED); - filePath = cursor.getString(INDEX_DATA); - durationInSec = cursor.getInt(INDEX_DURATION) / 1000; - bucketId = cursor.getInt(INDEX_BUCKET_ID); - fileSize = cursor.getLong(INDEX_SIZE); - parseResolution(cursor.getString(INDEX_RESOLUTION)); - } - - private void parseResolution(String resolution) { - if (resolution == null) return; - int m = resolution.indexOf('x'); - if (m == -1) return; - try { - int w = Integer.parseInt(resolution.substring(0, m)); - int h = Integer.parseInt(resolution.substring(m + 1)); - width = w; - height = h; - } catch (Throwable t) { - Log.w(TAG, t); - } - } - - @Override - protected boolean updateFromCursor(Cursor cursor) { - UpdateHelper uh = new UpdateHelper(); - id = uh.update(id, cursor.getInt(INDEX_ID)); - caption = uh.update(caption, cursor.getString(INDEX_CAPTION)); - mimeType = uh.update(mimeType, cursor.getString(INDEX_MIME_TYPE)); - latitude = uh.update(latitude, cursor.getDouble(INDEX_LATITUDE)); - longitude = uh.update(longitude, cursor.getDouble(INDEX_LONGITUDE)); - dateTakenInMs = uh.update( - dateTakenInMs, cursor.getLong(INDEX_DATE_TAKEN)); - dateAddedInSec = uh.update( - dateAddedInSec, cursor.getLong(INDEX_DATE_ADDED)); - dateModifiedInSec = uh.update( - dateModifiedInSec, cursor.getLong(INDEX_DATE_MODIFIED)); - filePath = uh.update(filePath, cursor.getString(INDEX_DATA)); - durationInSec = uh.update( - durationInSec, cursor.getInt(INDEX_DURATION) / 1000); - bucketId = uh.update(bucketId, cursor.getInt(INDEX_BUCKET_ID)); - fileSize = uh.update(fileSize, cursor.getLong(INDEX_SIZE)); - return uh.isUpdated(); - } - - @Override - public Job requestImage(int type) { - return new LocalVideoRequest(mApplication, getPath(), dateModifiedInSec, - type, filePath); - } - - public static class LocalVideoRequest extends ImageCacheRequest { - private String mLocalFilePath; - - LocalVideoRequest(GalleryApp application, Path path, long timeModified, - int type, String localFilePath) { - super(application, path, timeModified, type, - MediaItem.getTargetSize(type)); - mLocalFilePath = localFilePath; - } - - @Override - public Bitmap onDecodeOriginal(JobContext jc, int type) { - Bitmap bitmap = BitmapUtils.createVideoThumbnail(mLocalFilePath); - if (bitmap == null || jc.isCancelled()) return null; - return bitmap; - } - } - - @Override - public Job requestLargeImage() { - throw new UnsupportedOperationException("Cannot regquest a large image" - + " to a local video!"); - } - - @Override - public int getSupportedOperations() { - return SUPPORT_DELETE | SUPPORT_SHARE | SUPPORT_PLAY | SUPPORT_INFO | SUPPORT_TRIM | SUPPORT_MUTE; - } - - @Override - public void delete() { - GalleryUtils.assertNotInRenderThread(); - Uri baseUri = Video.Media.EXTERNAL_CONTENT_URI; - mApplication.getContentResolver().delete(baseUri, "_id=?", - new String[]{String.valueOf(id)}); - } - - @Override - public void rotate(int degrees) { - // TODO - } - - @Override - public Uri getContentUri() { - Uri baseUri = Video.Media.EXTERNAL_CONTENT_URI; - return baseUri.buildUpon().appendPath(String.valueOf(id)).build(); - } - - @Override - public Uri getPlayUri() { - return getContentUri(); - } - - @Override - public int getMediaType() { - return MEDIA_TYPE_VIDEO; - } - - @Override - public MediaDetails getDetails() { - MediaDetails details = super.getDetails(); - int s = durationInSec; - if (s > 0) { - details.addDetail(MediaDetails.INDEX_DURATION, GalleryUtils.formatDuration( - mApplication.getAndroidContext(), durationInSec)); - } - return details; - } - - @Override - public int getWidth() { - return width; - } - - @Override - public int getHeight() { - return height; - } - - @Override - public String getFilePath() { - return filePath; - } -} diff --git a/src/com/android/gallery3d/data/LocationClustering.java b/src/com/android/gallery3d/data/LocationClustering.java deleted file mode 100644 index 540322a33..000000000 --- a/src/com/android/gallery3d/data/LocationClustering.java +++ /dev/null @@ -1,316 +0,0 @@ -/* - * 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.gallery3d.data; - -import android.content.Context; -import android.os.Handler; -import android.os.Looper; -import android.util.FloatMath; -import android.widget.Toast; - -import com.android.gallery3d.R; -import com.android.gallery3d.util.GalleryUtils; -import com.android.gallery3d.util.ReverseGeocoder; - -import java.util.ArrayList; - -class LocationClustering extends Clustering { - @SuppressWarnings("unused") - private static final String TAG = "LocationClustering"; - - private static final int MIN_GROUPS = 1; - private static final int MAX_GROUPS = 20; - private static final int MAX_ITERATIONS = 30; - - // If the total distance change is less than this ratio, stop iterating. - private static final float STOP_CHANGE_RATIO = 0.01f; - private Context mContext; - private ArrayList> mClusters; - private ArrayList mNames; - private String mNoLocationString; - private Handler mHandler; - - private static class Point { - public Point(double lat, double lng) { - latRad = Math.toRadians(lat); - lngRad = Math.toRadians(lng); - } - public Point() {} - public double latRad, lngRad; - } - - private static class SmallItem { - Path path; - double lat, lng; - } - - public LocationClustering(Context context) { - mContext = context; - mNoLocationString = mContext.getResources().getString(R.string.no_location); - mHandler = new Handler(Looper.getMainLooper()); - } - - @Override - public void run(MediaSet baseSet) { - final int total = baseSet.getTotalMediaItemCount(); - final SmallItem[] buf = new SmallItem[total]; - // Separate items to two sets: with or without lat-long. - final double[] latLong = new double[2]; - baseSet.enumerateTotalMediaItems(new MediaSet.ItemConsumer() { - @Override - public void consume(int index, MediaItem item) { - if (index < 0 || index >= total) return; - SmallItem s = new SmallItem(); - s.path = item.getPath(); - item.getLatLong(latLong); - s.lat = latLong[0]; - s.lng = latLong[1]; - buf[index] = s; - } - }); - - final ArrayList withLatLong = new ArrayList(); - final ArrayList withoutLatLong = new ArrayList(); - final ArrayList points = new ArrayList(); - for (int i = 0; i < total; i++) { - SmallItem s = buf[i]; - if (s == null) continue; - if (GalleryUtils.isValidLocation(s.lat, s.lng)) { - withLatLong.add(s); - points.add(new Point(s.lat, s.lng)); - } else { - withoutLatLong.add(s); - } - } - - ArrayList> clusters = new ArrayList>(); - - int m = withLatLong.size(); - if (m > 0) { - // cluster the items with lat-long - Point[] pointsArray = new Point[m]; - pointsArray = points.toArray(pointsArray); - int[] bestK = new int[1]; - int[] index = kMeans(pointsArray, bestK); - - for (int i = 0; i < bestK[0]; i++) { - clusters.add(new ArrayList()); - } - - for (int i = 0; i < m; i++) { - clusters.get(index[i]).add(withLatLong.get(i)); - } - } - - ReverseGeocoder geocoder = new ReverseGeocoder(mContext); - mNames = new ArrayList(); - boolean hasUnresolvedAddress = false; - mClusters = new ArrayList>(); - for (ArrayList cluster : clusters) { - String name = generateName(cluster, geocoder); - if (name != null) { - mNames.add(name); - mClusters.add(cluster); - } else { - // move cluster-i to no location cluster - withoutLatLong.addAll(cluster); - hasUnresolvedAddress = true; - } - } - - if (withoutLatLong.size() > 0) { - mNames.add(mNoLocationString); - mClusters.add(withoutLatLong); - } - - if (hasUnresolvedAddress) { - mHandler.post(new Runnable() { - @Override - public void run() { - Toast.makeText(mContext, R.string.no_connectivity, - Toast.LENGTH_LONG).show(); - } - }); - } - } - - private static String generateName(ArrayList items, - ReverseGeocoder geocoder) { - ReverseGeocoder.SetLatLong set = new ReverseGeocoder.SetLatLong(); - - int n = items.size(); - for (int i = 0; i < n; i++) { - SmallItem item = items.get(i); - double itemLatitude = item.lat; - double itemLongitude = item.lng; - - if (set.mMinLatLatitude > itemLatitude) { - set.mMinLatLatitude = itemLatitude; - set.mMinLatLongitude = itemLongitude; - } - if (set.mMaxLatLatitude < itemLatitude) { - set.mMaxLatLatitude = itemLatitude; - set.mMaxLatLongitude = itemLongitude; - } - if (set.mMinLonLongitude > itemLongitude) { - set.mMinLonLatitude = itemLatitude; - set.mMinLonLongitude = itemLongitude; - } - if (set.mMaxLonLongitude < itemLongitude) { - set.mMaxLonLatitude = itemLatitude; - set.mMaxLonLongitude = itemLongitude; - } - } - - return geocoder.computeAddress(set); - } - - @Override - public int getNumberOfClusters() { - return mClusters.size(); - } - - @Override - public ArrayList getCluster(int index) { - ArrayList items = mClusters.get(index); - ArrayList result = new ArrayList(items.size()); - for (int i = 0, n = items.size(); i < n; i++) { - result.add(items.get(i).path); - } - return result; - } - - @Override - public String getClusterName(int index) { - return mNames.get(index); - } - - // Input: n points - // Output: the best k is stored in bestK[0], and the return value is the - // an array which specifies the group that each point belongs (0 to k - 1). - private static int[] kMeans(Point points[], int[] bestK) { - int n = points.length; - - // min and max number of groups wanted - int minK = Math.min(n, MIN_GROUPS); - int maxK = Math.min(n, MAX_GROUPS); - - Point[] center = new Point[maxK]; // center of each group. - Point[] groupSum = new Point[maxK]; // sum of points in each group. - int[] groupCount = new int[maxK]; // number of points in each group. - int[] grouping = new int[n]; // The group assignment for each point. - - for (int i = 0; i < maxK; i++) { - center[i] = new Point(); - groupSum[i] = new Point(); - } - - // The score we want to minimize is: - // (sum of distance from each point to its group center) * sqrt(k). - float bestScore = Float.MAX_VALUE; - // The best group assignment up to now. - int[] bestGrouping = new int[n]; - // The best K up to now. - bestK[0] = 1; - - float lastDistance = 0; - float totalDistance = 0; - - for (int k = minK; k <= maxK; k++) { - // step 1: (arbitrarily) pick k points as the initial centers. - int delta = n / k; - for (int i = 0; i < k; i++) { - Point p = points[i * delta]; - center[i].latRad = p.latRad; - center[i].lngRad = p.lngRad; - } - - for (int iter = 0; iter < MAX_ITERATIONS; iter++) { - // step 2: assign each point to the nearest center. - for (int i = 0; i < k; i++) { - groupSum[i].latRad = 0; - groupSum[i].lngRad = 0; - groupCount[i] = 0; - } - totalDistance = 0; - - for (int i = 0; i < n; i++) { - Point p = points[i]; - float bestDistance = Float.MAX_VALUE; - int bestIndex = 0; - for (int j = 0; j < k; j++) { - float distance = (float) GalleryUtils.fastDistanceMeters( - p.latRad, p.lngRad, center[j].latRad, center[j].lngRad); - // We may have small non-zero distance introduced by - // floating point calculation, so zero out small - // distances less than 1 meter. - if (distance < 1) { - distance = 0; - } - if (distance < bestDistance) { - bestDistance = distance; - bestIndex = j; - } - } - grouping[i] = bestIndex; - groupCount[bestIndex]++; - groupSum[bestIndex].latRad += p.latRad; - groupSum[bestIndex].lngRad += p.lngRad; - totalDistance += bestDistance; - } - - // step 3: calculate new centers - for (int i = 0; i < k; i++) { - if (groupCount[i] > 0) { - center[i].latRad = groupSum[i].latRad / groupCount[i]; - center[i].lngRad = groupSum[i].lngRad / groupCount[i]; - } - } - - if (totalDistance == 0 || (Math.abs(lastDistance - totalDistance) - / totalDistance) < STOP_CHANGE_RATIO) { - break; - } - lastDistance = totalDistance; - } - - // step 4: remove empty groups and reassign group number - int reassign[] = new int[k]; - int realK = 0; - for (int i = 0; i < k; i++) { - if (groupCount[i] > 0) { - reassign[i] = realK++; - } - } - - // step 5: calculate the final score - float score = totalDistance * FloatMath.sqrt(realK); - - if (score < bestScore) { - bestScore = score; - bestK[0] = realK; - for (int i = 0; i < n; i++) { - bestGrouping[i] = reassign[grouping[i]]; - } - if (score == 0) { - break; - } - } - } - return bestGrouping; - } -} diff --git a/src/com/android/gallery3d/data/Log.java b/src/com/android/gallery3d/data/Log.java deleted file mode 100644 index 3384eb66c..000000000 --- a/src/com/android/gallery3d/data/Log.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * 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.gallery3d.data; - -public class Log { - public static int v(String tag, String msg) { - return android.util.Log.v(tag, msg); - } - public static int v(String tag, String msg, Throwable tr) { - return android.util.Log.v(tag, msg, tr); - } - public static int d(String tag, String msg) { - return android.util.Log.d(tag, msg); - } - public static int d(String tag, String msg, Throwable tr) { - return android.util.Log.d(tag, msg, tr); - } - public static int i(String tag, String msg) { - return android.util.Log.i(tag, msg); - } - public static int i(String tag, String msg, Throwable tr) { - return android.util.Log.i(tag, msg, tr); - } - public static int w(String tag, String msg) { - return android.util.Log.w(tag, msg); - } - public static int w(String tag, String msg, Throwable tr) { - return android.util.Log.w(tag, msg, tr); - } - public static int w(String tag, Throwable tr) { - return android.util.Log.w(tag, tr); - } - public static int e(String tag, String msg) { - return android.util.Log.e(tag, msg); - } - public static int e(String tag, String msg, Throwable tr) { - return android.util.Log.e(tag, msg, tr); - } -} diff --git a/src/com/android/gallery3d/data/MediaDetails.java b/src/com/android/gallery3d/data/MediaDetails.java deleted file mode 100644 index cac524b88..000000000 --- a/src/com/android/gallery3d/data/MediaDetails.java +++ /dev/null @@ -1,170 +0,0 @@ -/* - * 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.gallery3d.data; - -import com.android.gallery3d.R; -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.exif.ExifInterface; -import com.android.gallery3d.exif.ExifTag; -import com.android.gallery3d.exif.Rational; - -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map.Entry; -import java.util.TreeMap; - -public class MediaDetails implements Iterable> { - @SuppressWarnings("unused") - private static final String TAG = "MediaDetails"; - - private TreeMap mDetails = new TreeMap(); - private HashMap mUnits = new HashMap(); - - public static final int INDEX_TITLE = 1; - public static final int INDEX_DESCRIPTION = 2; - public static final int INDEX_DATETIME = 3; - public static final int INDEX_LOCATION = 4; - public static final int INDEX_WIDTH = 5; - public static final int INDEX_HEIGHT = 6; - public static final int INDEX_ORIENTATION = 7; - public static final int INDEX_DURATION = 8; - public static final int INDEX_MIMETYPE = 9; - public static final int INDEX_SIZE = 10; - - // for EXIF - public static final int INDEX_MAKE = 100; - public static final int INDEX_MODEL = 101; - public static final int INDEX_FLASH = 102; - public static final int INDEX_FOCAL_LENGTH = 103; - public static final int INDEX_WHITE_BALANCE = 104; - public static final int INDEX_APERTURE = 105; - public static final int INDEX_SHUTTER_SPEED = 106; - public static final int INDEX_EXPOSURE_TIME = 107; - public static final int INDEX_ISO = 108; - - // Put this last because it may be long. - public static final int INDEX_PATH = 200; - - public static class FlashState { - private static int FLASH_FIRED_MASK = 1; - private static int FLASH_RETURN_MASK = 2 | 4; - private static int FLASH_MODE_MASK = 8 | 16; - private static int FLASH_FUNCTION_MASK = 32; - private static int FLASH_RED_EYE_MASK = 64; - private int mState; - - public FlashState(int state) { - mState = state; - } - - public boolean isFlashFired() { - return (mState & FLASH_FIRED_MASK) != 0; - } - } - - public void addDetail(int index, Object value) { - mDetails.put(index, value); - } - - public Object getDetail(int index) { - return mDetails.get(index); - } - - public int size() { - return mDetails.size(); - } - - @Override - public Iterator> iterator() { - return mDetails.entrySet().iterator(); - } - - public void setUnit(int index, int unit) { - mUnits.put(index, unit); - } - - public boolean hasUnit(int index) { - return mUnits.containsKey(index); - } - - public int getUnit(int index) { - return mUnits.get(index); - } - - private static void setExifData(MediaDetails details, ExifTag tag, - int key) { - if (tag != null) { - String value = null; - int type = tag.getDataType(); - if (type == ExifTag.TYPE_UNSIGNED_RATIONAL || type == ExifTag.TYPE_RATIONAL) { - value = String.valueOf(tag.getValueAsRational(0).toDouble()); - } else if (type == ExifTag.TYPE_ASCII) { - value = tag.getValueAsString(); - } else { - value = String.valueOf(tag.forceGetValueAsLong(0)); - } - if (key == MediaDetails.INDEX_FLASH) { - MediaDetails.FlashState state = new MediaDetails.FlashState( - Integer.valueOf(value.toString())); - details.addDetail(key, state); - } else { - details.addDetail(key, value); - } - } - } - - public static void extractExifInfo(MediaDetails details, String filePath) { - - ExifInterface exif = new ExifInterface(); - try { - exif.readExif(filePath); - } catch (FileNotFoundException e) { - Log.w(TAG, "Could not find file to read exif: " + filePath, e); - } catch (IOException e) { - Log.w(TAG, "Could not read exif from file: " + filePath, e); - } - - setExifData(details, exif.getTag(ExifInterface.TAG_FLASH), - MediaDetails.INDEX_FLASH); - setExifData(details, exif.getTag(ExifInterface.TAG_IMAGE_WIDTH), - MediaDetails.INDEX_WIDTH); - setExifData(details, exif.getTag(ExifInterface.TAG_IMAGE_LENGTH), - MediaDetails.INDEX_HEIGHT); - setExifData(details, exif.getTag(ExifInterface.TAG_MAKE), - MediaDetails.INDEX_MAKE); - setExifData(details, exif.getTag(ExifInterface.TAG_MODEL), - MediaDetails.INDEX_MODEL); - setExifData(details, exif.getTag(ExifInterface.TAG_APERTURE_VALUE), - MediaDetails.INDEX_APERTURE); - setExifData(details, exif.getTag(ExifInterface.TAG_ISO_SPEED_RATINGS), - MediaDetails.INDEX_ISO); - setExifData(details, exif.getTag(ExifInterface.TAG_WHITE_BALANCE), - MediaDetails.INDEX_WHITE_BALANCE); - setExifData(details, exif.getTag(ExifInterface.TAG_EXPOSURE_TIME), - MediaDetails.INDEX_EXPOSURE_TIME); - ExifTag focalTag = exif.getTag(ExifInterface.TAG_FOCAL_LENGTH); - if (focalTag != null) { - details.addDetail(MediaDetails.INDEX_FOCAL_LENGTH, - focalTag.getValueAsRational(0).toDouble()); - details.setUnit(MediaDetails.INDEX_FOCAL_LENGTH, R.string.unit_mm); - } - } -} diff --git a/src/com/android/gallery3d/data/MediaItem.java b/src/com/android/gallery3d/data/MediaItem.java deleted file mode 100644 index 59ea86551..000000000 --- a/src/com/android/gallery3d/data/MediaItem.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * 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.gallery3d.data; - -import android.graphics.Bitmap; -import android.graphics.BitmapRegionDecoder; - -import com.android.gallery3d.common.ApiHelper; -import com.android.gallery3d.ui.ScreenNail; -import com.android.gallery3d.util.ThreadPool.Job; - -// MediaItem represents an image or a video item. -public abstract class MediaItem extends MediaObject { - // NOTE: These type numbers are stored in the image cache, so it should not - // not be changed without resetting the cache. - public static final int TYPE_THUMBNAIL = 1; - public static final int TYPE_MICROTHUMBNAIL = 2; - - public static final int CACHED_IMAGE_QUALITY = 95; - - public static final int IMAGE_READY = 0; - public static final int IMAGE_WAIT = 1; - public static final int IMAGE_ERROR = -1; - - public static final String MIME_TYPE_JPEG = "image/jpeg"; - - private static final int BYTESBUFFE_POOL_SIZE = 4; - private static final int BYTESBUFFER_SIZE = 200 * 1024; - - private static int sMicrothumbnailTargetSize = 200; - private static final BytesBufferPool sMicroThumbBufferPool = - new BytesBufferPool(BYTESBUFFE_POOL_SIZE, BYTESBUFFER_SIZE); - - private static int sThumbnailTargetSize = 640; - - // TODO: fix default value for latlng and change this. - public static final double INVALID_LATLNG = 0f; - - public abstract Job requestImage(int type); - public abstract Job requestLargeImage(); - - public MediaItem(Path path, long version) { - super(path, version); - } - - public long getDateInMs() { - return 0; - } - - public String getName() { - return null; - } - - public void getLatLong(double[] latLong) { - latLong[0] = INVALID_LATLNG; - latLong[1] = INVALID_LATLNG; - } - - public String[] getTags() { - return null; - } - - public Face[] getFaces() { - return null; - } - - // The rotation of the full-resolution image. By default, it returns the value of - // getRotation(). - public int getFullImageRotation() { - return getRotation(); - } - - public int getRotation() { - return 0; - } - - public long getSize() { - return 0; - } - - public abstract String getMimeType(); - - public String getFilePath() { - return ""; - } - - // Returns width and height of the media item. - // Returns 0, 0 if the information is not available. - public abstract int getWidth(); - public abstract int getHeight(); - - // This is an alternative for requestImage() in PhotoPage. If this - // is implemented, you don't need to implement requestImage(). - public ScreenNail getScreenNail() { - return null; - } - - public static int getTargetSize(int type) { - switch (type) { - case TYPE_THUMBNAIL: - return sThumbnailTargetSize; - case TYPE_MICROTHUMBNAIL: - return sMicrothumbnailTargetSize; - default: - throw new RuntimeException( - "should only request thumb/microthumb from cache"); - } - } - - public static BytesBufferPool getBytesBufferPool() { - return sMicroThumbBufferPool; - } - - public static void setThumbnailSizes(int size, int microSize) { - sThumbnailTargetSize = size; - if (sMicrothumbnailTargetSize != microSize) { - sMicrothumbnailTargetSize = microSize; - } - } -} diff --git a/src/com/android/gallery3d/data/MediaObject.java b/src/com/android/gallery3d/data/MediaObject.java deleted file mode 100644 index 270d4cf0b..000000000 --- a/src/com/android/gallery3d/data/MediaObject.java +++ /dev/null @@ -1,166 +0,0 @@ -/* - * 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.gallery3d.data; - -import android.net.Uri; - -public abstract class MediaObject { - @SuppressWarnings("unused") - private static final String TAG = "MediaObject"; - public static final long INVALID_DATA_VERSION = -1; - - // These are the bits returned from getSupportedOperations(): - public static final int SUPPORT_DELETE = 1 << 0; - public static final int SUPPORT_ROTATE = 1 << 1; - public static final int SUPPORT_SHARE = 1 << 2; - public static final int SUPPORT_CROP = 1 << 3; - public static final int SUPPORT_SHOW_ON_MAP = 1 << 4; - public static final int SUPPORT_SETAS = 1 << 5; - public static final int SUPPORT_FULL_IMAGE = 1 << 6; - public static final int SUPPORT_PLAY = 1 << 7; - public static final int SUPPORT_CACHE = 1 << 8; - public static final int SUPPORT_EDIT = 1 << 9; - public static final int SUPPORT_INFO = 1 << 10; - public static final int SUPPORT_TRIM = 1 << 11; - public static final int SUPPORT_UNLOCK = 1 << 12; - public static final int SUPPORT_BACK = 1 << 13; - public static final int SUPPORT_ACTION = 1 << 14; - public static final int SUPPORT_CAMERA_SHORTCUT = 1 << 15; - public static final int SUPPORT_MUTE = 1 << 16; - public static final int SUPPORT_ALL = 0xffffffff; - - // These are the bits returned from getMediaType(): - public static final int MEDIA_TYPE_UNKNOWN = 1; - public static final int MEDIA_TYPE_IMAGE = 2; - public static final int MEDIA_TYPE_VIDEO = 4; - public static final int MEDIA_TYPE_ALL = MEDIA_TYPE_IMAGE | MEDIA_TYPE_VIDEO; - - public static final String MEDIA_TYPE_IMAGE_STRING = "image"; - public static final String MEDIA_TYPE_VIDEO_STRING = "video"; - public static final String MEDIA_TYPE_ALL_STRING = "all"; - - // These are flags for cache() and return values for getCacheFlag(): - public static final int CACHE_FLAG_NO = 0; - public static final int CACHE_FLAG_SCREENNAIL = 1; - public static final int CACHE_FLAG_FULL = 2; - - // These are return values for getCacheStatus(): - public static final int CACHE_STATUS_NOT_CACHED = 0; - public static final int CACHE_STATUS_CACHING = 1; - public static final int CACHE_STATUS_CACHED_SCREENNAIL = 2; - public static final int CACHE_STATUS_CACHED_FULL = 3; - - private static long sVersionSerial = 0; - - protected long mDataVersion; - - protected final Path mPath; - - public interface PanoramaSupportCallback { - void panoramaInfoAvailable(MediaObject mediaObject, boolean isPanorama, - boolean isPanorama360); - } - - public MediaObject(Path path, long version) { - path.setObject(this); - mPath = path; - mDataVersion = version; - } - - public Path getPath() { - return mPath; - } - - public int getSupportedOperations() { - return 0; - } - - public void getPanoramaSupport(PanoramaSupportCallback callback) { - callback.panoramaInfoAvailable(this, false, false); - } - - public void clearCachedPanoramaSupport() { - } - - public void delete() { - throw new UnsupportedOperationException(); - } - - public void rotate(int degrees) { - throw new UnsupportedOperationException(); - } - - public Uri getContentUri() { - String className = getClass().getName(); - Log.e(TAG, "Class " + className + "should implement getContentUri."); - Log.e(TAG, "The object was created from path: " + getPath()); - throw new UnsupportedOperationException(); - } - - public Uri getPlayUri() { - throw new UnsupportedOperationException(); - } - - public int getMediaType() { - return MEDIA_TYPE_UNKNOWN; - } - - public MediaDetails getDetails() { - MediaDetails details = new MediaDetails(); - return details; - } - - public long getDataVersion() { - return mDataVersion; - } - - public int getCacheFlag() { - return CACHE_FLAG_NO; - } - - public int getCacheStatus() { - throw new UnsupportedOperationException(); - } - - public long getCacheSize() { - throw new UnsupportedOperationException(); - } - - public void cache(int flag) { - throw new UnsupportedOperationException(); - } - - public static synchronized long nextVersionNumber() { - return ++MediaObject.sVersionSerial; - } - - public static int getTypeFromString(String s) { - if (MEDIA_TYPE_ALL_STRING.equals(s)) return MediaObject.MEDIA_TYPE_ALL; - if (MEDIA_TYPE_IMAGE_STRING.equals(s)) return MediaObject.MEDIA_TYPE_IMAGE; - if (MEDIA_TYPE_VIDEO_STRING.equals(s)) return MediaObject.MEDIA_TYPE_VIDEO; - throw new IllegalArgumentException(s); - } - - public static String getTypeString(int type) { - switch (type) { - case MEDIA_TYPE_IMAGE: return MEDIA_TYPE_IMAGE_STRING; - case MEDIA_TYPE_VIDEO: return MEDIA_TYPE_VIDEO_STRING; - case MEDIA_TYPE_ALL: return MEDIA_TYPE_ALL_STRING; - } - throw new IllegalArgumentException(); - } -} diff --git a/src/com/android/gallery3d/data/MediaSet.java b/src/com/android/gallery3d/data/MediaSet.java deleted file mode 100644 index 683aa6b32..000000000 --- a/src/com/android/gallery3d/data/MediaSet.java +++ /dev/null @@ -1,348 +0,0 @@ -/* - * 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.gallery3d.data; - -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.util.Future; - -import java.util.ArrayList; -import java.util.WeakHashMap; - -// MediaSet is a directory-like data structure. -// It contains MediaItems and sub-MediaSets. -// -// The primary interface are: -// getMediaItemCount(), getMediaItem() and -// getSubMediaSetCount(), getSubMediaSet(). -// -// getTotalMediaItemCount() returns the number of all MediaItems, including -// those in sub-MediaSets. -public abstract class MediaSet extends MediaObject { - @SuppressWarnings("unused") - private static final String TAG = "MediaSet"; - - public static final int MEDIAITEM_BATCH_FETCH_COUNT = 500; - public static final int INDEX_NOT_FOUND = -1; - - public static final int SYNC_RESULT_SUCCESS = 0; - public static final int SYNC_RESULT_CANCELLED = 1; - public static final int SYNC_RESULT_ERROR = 2; - - /** Listener to be used with requestSync(SyncListener). */ - public static interface SyncListener { - /** - * Called when the sync task completed. Completion may be due to normal termination, - * an exception, or cancellation. - * - * @param mediaSet the MediaSet that's done with sync - * @param resultCode one of the SYNC_RESULT_* constants - */ - void onSyncDone(MediaSet mediaSet, int resultCode); - } - - public MediaSet(Path path, long version) { - super(path, version); - } - - public int getMediaItemCount() { - return 0; - } - - // Returns the media items in the range [start, start + count). - // - // The number of media items returned may be less than the specified count - // if there are not enough media items available. The number of - // media items available may not be consistent with the return value of - // getMediaItemCount() because the contents of database may have already - // changed. - public ArrayList getMediaItem(int start, int count) { - return new ArrayList(); - } - - public MediaItem getCoverMediaItem() { - ArrayList items = getMediaItem(0, 1); - if (items.size() > 0) return items.get(0); - for (int i = 0, n = getSubMediaSetCount(); i < n; i++) { - MediaItem cover = getSubMediaSet(i).getCoverMediaItem(); - if (cover != null) return cover; - } - return null; - } - - public int getSubMediaSetCount() { - return 0; - } - - public MediaSet getSubMediaSet(int index) { - throw new IndexOutOfBoundsException(); - } - - public boolean isLeafAlbum() { - return false; - } - - public boolean isCameraRoll() { - return false; - } - - /** - * Method {@link #reload()} may process the loading task in background, this method tells - * its client whether the loading is still in process or not. - */ - public boolean isLoading() { - return false; - } - - public int getTotalMediaItemCount() { - int total = getMediaItemCount(); - for (int i = 0, n = getSubMediaSetCount(); i < n; i++) { - total += getSubMediaSet(i).getTotalMediaItemCount(); - } - return total; - } - - // TODO: we should have better implementation of sub classes - public int getIndexOfItem(Path path, int hint) { - // hint < 0 is handled below - // first, try to find it around the hint - int start = Math.max(0, - hint - MEDIAITEM_BATCH_FETCH_COUNT / 2); - ArrayList list = getMediaItem( - start, MEDIAITEM_BATCH_FETCH_COUNT); - int index = getIndexOf(path, list); - if (index != INDEX_NOT_FOUND) return start + index; - - // try to find it globally - start = start == 0 ? MEDIAITEM_BATCH_FETCH_COUNT : 0; - list = getMediaItem(start, MEDIAITEM_BATCH_FETCH_COUNT); - while (true) { - index = getIndexOf(path, list); - if (index != INDEX_NOT_FOUND) return start + index; - if (list.size() < MEDIAITEM_BATCH_FETCH_COUNT) return INDEX_NOT_FOUND; - start += MEDIAITEM_BATCH_FETCH_COUNT; - list = getMediaItem(start, MEDIAITEM_BATCH_FETCH_COUNT); - } - } - - protected int getIndexOf(Path path, ArrayList list) { - for (int i = 0, n = list.size(); i < n; ++i) { - // item could be null only in ClusterAlbum - MediaObject item = list.get(i); - if (item != null && item.mPath == path) return i; - } - return INDEX_NOT_FOUND; - } - - public abstract String getName(); - - private WeakHashMap mListeners = - new WeakHashMap(); - - // NOTE: The MediaSet only keeps a weak reference to the listener. The - // listener is automatically removed when there is no other reference to - // the listener. - public void addContentListener(ContentListener listener) { - mListeners.put(listener, null); - } - - public void removeContentListener(ContentListener listener) { - mListeners.remove(listener); - } - - // This should be called by subclasses when the content is changed. - public void notifyContentChanged() { - for (ContentListener listener : mListeners.keySet()) { - listener.onContentDirty(); - } - } - - // Reload the content. Return the current data version. reload() should be called - // in the same thread as getMediaItem(int, int) and getSubMediaSet(int). - public abstract long reload(); - - @Override - public MediaDetails getDetails() { - MediaDetails details = super.getDetails(); - details.addDetail(MediaDetails.INDEX_TITLE, getName()); - return details; - } - - // Enumerate all media items in this media set (including the ones in sub - // media sets), in an efficient order. ItemConsumer.consumer() will be - // called for each media item with its index. - public void enumerateMediaItems(ItemConsumer consumer) { - enumerateMediaItems(consumer, 0); - } - - public void enumerateTotalMediaItems(ItemConsumer consumer) { - enumerateTotalMediaItems(consumer, 0); - } - - public static interface ItemConsumer { - void consume(int index, MediaItem item); - } - - // The default implementation uses getMediaItem() for enumerateMediaItems(). - // Subclasses may override this and use more efficient implementations. - // Returns the number of items enumerated. - protected int enumerateMediaItems(ItemConsumer consumer, int startIndex) { - int total = getMediaItemCount(); - int start = 0; - while (start < total) { - int count = Math.min(MEDIAITEM_BATCH_FETCH_COUNT, total - start); - ArrayList items = getMediaItem(start, count); - for (int i = 0, n = items.size(); i < n; i++) { - MediaItem item = items.get(i); - consumer.consume(startIndex + start + i, item); - } - start += count; - } - return total; - } - - // Recursively enumerate all media items under this set. - // Returns the number of items enumerated. - protected int enumerateTotalMediaItems( - ItemConsumer consumer, int startIndex) { - int start = 0; - start += enumerateMediaItems(consumer, startIndex); - int m = getSubMediaSetCount(); - for (int i = 0; i < m; i++) { - start += getSubMediaSet(i).enumerateTotalMediaItems( - consumer, startIndex + start); - } - return start; - } - - /** - * Requests sync on this MediaSet. It returns a Future object that can be used by the caller - * to query the status of the sync. The sync result code is one of the SYNC_RESULT_* constants - * defined in this class and can be obtained by Future.get(). - * - * Subclasses should perform sync on a different thread. - * - * The default implementation here returns a Future stub that does nothing and returns - * SYNC_RESULT_SUCCESS by get(). - */ - public Future requestSync(SyncListener listener) { - listener.onSyncDone(this, SYNC_RESULT_SUCCESS); - return FUTURE_STUB; - } - - private static final Future FUTURE_STUB = new Future() { - @Override - public void cancel() {} - - @Override - public boolean isCancelled() { - return false; - } - - @Override - public boolean isDone() { - return true; - } - - @Override - public Integer get() { - return SYNC_RESULT_SUCCESS; - } - - @Override - public void waitDone() {} - }; - - protected Future requestSyncOnMultipleSets(MediaSet[] sets, SyncListener listener) { - return new MultiSetSyncFuture(sets, listener); - } - - private class MultiSetSyncFuture implements Future, SyncListener { - @SuppressWarnings("hiding") - private static final String TAG = "Gallery.MultiSetSync"; - - private final SyncListener mListener; - private final Future mFutures[]; - - private boolean mIsCancelled = false; - private int mResult = -1; - private int mPendingCount; - - @SuppressWarnings("unchecked") - MultiSetSyncFuture(MediaSet[] sets, SyncListener listener) { - mListener = listener; - mPendingCount = sets.length; - mFutures = new Future[sets.length]; - - synchronized (this) { - for (int i = 0, n = sets.length; i < n; ++i) { - mFutures[i] = sets[i].requestSync(this); - Log.d(TAG, " request sync: " + Utils.maskDebugInfo(sets[i].getName())); - } - } - } - - @Override - public synchronized void cancel() { - if (mIsCancelled) return; - mIsCancelled = true; - for (Future future : mFutures) future.cancel(); - if (mResult < 0) mResult = SYNC_RESULT_CANCELLED; - } - - @Override - public synchronized boolean isCancelled() { - return mIsCancelled; - } - - @Override - public synchronized boolean isDone() { - return mPendingCount == 0; - } - - @Override - public synchronized Integer get() { - waitDone(); - return mResult; - } - - @Override - public synchronized void waitDone() { - try { - while (!isDone()) wait(); - } catch (InterruptedException e) { - Log.d(TAG, "waitDone() interrupted"); - } - } - - // SyncListener callback - @Override - public void onSyncDone(MediaSet mediaSet, int resultCode) { - SyncListener listener = null; - synchronized (this) { - if (resultCode == SYNC_RESULT_ERROR) mResult = SYNC_RESULT_ERROR; - --mPendingCount; - if (mPendingCount == 0) { - listener = mListener; - notifyAll(); - } - Log.d(TAG, "onSyncDone: " + Utils.maskDebugInfo(mediaSet.getName()) - + " #pending=" + mPendingCount); - } - if (listener != null) listener.onSyncDone(MediaSet.this, mResult); - } - } -} diff --git a/src/com/android/gallery3d/data/MediaSource.java b/src/com/android/gallery3d/data/MediaSource.java deleted file mode 100644 index 95901283b..000000000 --- a/src/com/android/gallery3d/data/MediaSource.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * 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.gallery3d.data; - -import android.net.Uri; - -import com.android.gallery3d.data.MediaSet.ItemConsumer; - -import java.util.ArrayList; - -public abstract class MediaSource { - private static final String TAG = "MediaSource"; - private String mPrefix; - - protected MediaSource(String prefix) { - mPrefix = prefix; - } - - public String getPrefix() { - return mPrefix; - } - - public Path findPathByUri(Uri uri, String type) { - return null; - } - - public abstract MediaObject createMediaObject(Path path); - - public void pause() { - } - - public void resume() { - } - - public Path getDefaultSetOf(Path item) { - return null; - } - - public long getTotalUsedCacheSize() { - return 0; - } - - public long getTotalTargetCacheSize() { - return 0; - } - - public static class PathId { - public PathId(Path path, int id) { - this.path = path; - this.id = id; - } - public Path path; - public int id; - } - - // Maps a list of Paths (all belong to this MediaSource) to MediaItems, - // and invoke consumer.consume() for each MediaItem with the given id. - // - // This default implementation uses getMediaObject for each Path. Subclasses - // may override this and provide more efficient implementation (like - // batching the database query). - public void mapMediaItems(ArrayList list, ItemConsumer consumer) { - int n = list.size(); - for (int i = 0; i < n; i++) { - PathId pid = list.get(i); - MediaObject obj; - synchronized (DataManager.LOCK) { - obj = pid.path.getObject(); - if (obj == null) { - try { - obj = createMediaObject(pid.path); - } catch (Throwable th) { - Log.w(TAG, "cannot create media object: " + pid.path, th); - } - } - } - if (obj != null) { - consumer.consume(pid.id, (MediaItem) obj); - } - } - } -} diff --git a/src/com/android/gallery3d/data/MtpClient.java b/src/com/android/gallery3d/data/MtpClient.java deleted file mode 100644 index 737b5b60d..000000000 --- a/src/com/android/gallery3d/data/MtpClient.java +++ /dev/null @@ -1,443 +0,0 @@ -/* - * 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.gallery3d.data; - -import android.annotation.TargetApi; -import android.app.PendingIntent; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.hardware.usb.UsbConstants; -import android.hardware.usb.UsbDevice; -import android.hardware.usb.UsbDeviceConnection; -import android.hardware.usb.UsbInterface; -import android.hardware.usb.UsbManager; -import android.mtp.MtpDevice; -import android.mtp.MtpObjectInfo; -import android.mtp.MtpStorageInfo; -import android.util.Log; - -import com.android.gallery3d.common.ApiHelper; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; - -/** - * This class helps an application manage a list of connected MTP or PTP devices. - * It listens for MTP devices being attached and removed from the USB host bus - * and notifies the application when the MTP device list changes. - */ -@TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB_MR1) -public class MtpClient { - - private static final String TAG = "MtpClient"; - - private static final String ACTION_USB_PERMISSION = - "android.mtp.MtpClient.action.USB_PERMISSION"; - - private final Context mContext; - private final UsbManager mUsbManager; - private final ArrayList mListeners = new ArrayList(); - // mDevices contains all MtpDevices that have been seen by our client, - // so we can inform when the device has been detached. - // mDevices is also used for synchronization in this class. - private final HashMap mDevices = new HashMap(); - // List of MTP devices we should not try to open for which we are currently - // asking for permission to open. - private final ArrayList mRequestPermissionDevices = new ArrayList(); - // List of MTP devices we should not try to open. - // We add devices to this list if the user canceled a permission request or we were - // unable to open the device. - private final ArrayList mIgnoredDevices = new ArrayList(); - - private final PendingIntent mPermissionIntent; - - private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); - UsbDevice usbDevice = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); - String deviceName = usbDevice.getDeviceName(); - - synchronized (mDevices) { - MtpDevice mtpDevice = mDevices.get(deviceName); - - if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)) { - if (mtpDevice == null) { - mtpDevice = openDeviceLocked(usbDevice); - } - if (mtpDevice != null) { - for (Listener listener : mListeners) { - listener.deviceAdded(mtpDevice); - } - } - } else if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) { - if (mtpDevice != null) { - mDevices.remove(deviceName); - mRequestPermissionDevices.remove(deviceName); - mIgnoredDevices.remove(deviceName); - for (Listener listener : mListeners) { - listener.deviceRemoved(mtpDevice); - } - } - } else if (ACTION_USB_PERMISSION.equals(action)) { - mRequestPermissionDevices.remove(deviceName); - boolean permission = intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, - false); - Log.d(TAG, "ACTION_USB_PERMISSION: " + permission); - if (permission) { - if (mtpDevice == null) { - mtpDevice = openDeviceLocked(usbDevice); - } - if (mtpDevice != null) { - for (Listener listener : mListeners) { - listener.deviceAdded(mtpDevice); - } - } - } else { - // so we don't ask for permission again - mIgnoredDevices.add(deviceName); - } - } - } - } - }; - - /** - * An interface for being notified when MTP or PTP devices are attached - * or removed. In the current implementation, only PTP devices are supported. - */ - public interface Listener { - /** - * Called when a new device has been added - * - * @param device the new device that was added - */ - public void deviceAdded(MtpDevice device); - - /** - * Called when a new device has been removed - * - * @param device the device that was removed - */ - public void deviceRemoved(MtpDevice device); - } - - /** - * Tests to see if a {@link android.hardware.usb.UsbDevice} - * supports the PTP protocol (typically used by digital cameras) - * - * @param device the device to test - * @return true if the device is a PTP device. - */ - static public boolean isCamera(UsbDevice device) { - int count = device.getInterfaceCount(); - for (int i = 0; i < count; i++) { - UsbInterface intf = device.getInterface(i); - if (intf.getInterfaceClass() == UsbConstants.USB_CLASS_STILL_IMAGE && - intf.getInterfaceSubclass() == 1 && - intf.getInterfaceProtocol() == 1) { - return true; - } - } - return false; - } - - /** - * MtpClient constructor - * - * @param context the {@link android.content.Context} to use for the MtpClient - */ - public MtpClient(Context context) { - mContext = context; - mUsbManager = (UsbManager)context.getSystemService(Context.USB_SERVICE); - mPermissionIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ACTION_USB_PERMISSION), 0); - IntentFilter filter = new IntentFilter(); - filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED); - filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED); - filter.addAction(ACTION_USB_PERMISSION); - context.registerReceiver(mUsbReceiver, filter); - } - - /** - * Opens the {@link android.hardware.usb.UsbDevice} for an MTP or PTP - * device and return an {@link android.mtp.MtpDevice} for it. - * - * @param usbDevice the device to open - * @return an MtpDevice for the device. - */ - private MtpDevice openDeviceLocked(UsbDevice usbDevice) { - String deviceName = usbDevice.getDeviceName(); - - // don't try to open devices that we have decided to ignore - // or are currently asking permission for - if (isCamera(usbDevice) && !mIgnoredDevices.contains(deviceName) - && !mRequestPermissionDevices.contains(deviceName)) { - if (!mUsbManager.hasPermission(usbDevice)) { - mUsbManager.requestPermission(usbDevice, mPermissionIntent); - mRequestPermissionDevices.add(deviceName); - } else { - UsbDeviceConnection connection = mUsbManager.openDevice(usbDevice); - if (connection != null) { - MtpDevice mtpDevice = new MtpDevice(usbDevice); - if (mtpDevice.open(connection)) { - mDevices.put(usbDevice.getDeviceName(), mtpDevice); - return mtpDevice; - } else { - // so we don't try to open it again - mIgnoredDevices.add(deviceName); - } - } else { - // so we don't try to open it again - mIgnoredDevices.add(deviceName); - } - } - } - return null; - } - - /** - * Closes all resources related to the MtpClient object - */ - public void close() { - mContext.unregisterReceiver(mUsbReceiver); - } - - /** - * Registers a {@link com.android.gallery3d.data.MtpClient.Listener} interface to receive - * notifications when MTP or PTP devices are added or removed. - * - * @param listener the listener to register - */ - public void addListener(Listener listener) { - synchronized (mDevices) { - if (!mListeners.contains(listener)) { - mListeners.add(listener); - } - } - } - - /** - * Unregisters a {@link com.android.gallery3d.data.MtpClient.Listener} interface. - * - * @param listener the listener to unregister - */ - public void removeListener(Listener listener) { - synchronized (mDevices) { - mListeners.remove(listener); - } - } - - /** - * Retrieves an {@link android.mtp.MtpDevice} object for the USB device - * with the given name. - * - * @param deviceName the name of the USB device - * @return the MtpDevice, or null if it does not exist - */ - public MtpDevice getDevice(String deviceName) { - synchronized (mDevices) { - return mDevices.get(deviceName); - } - } - - /** - * Retrieves an {@link android.mtp.MtpDevice} object for the USB device - * with the given ID. - * - * @param id the ID of the USB device - * @return the MtpDevice, or null if it does not exist - */ - public MtpDevice getDevice(int id) { - synchronized (mDevices) { - return mDevices.get(UsbDevice.getDeviceName(id)); - } - } - - /** - * Retrieves a list of all currently connected {@link android.mtp.MtpDevice}. - * - * @return the list of MtpDevices - */ - public List getDeviceList() { - synchronized (mDevices) { - // Query the USB manager since devices might have attached - // before we added our listener. - for (UsbDevice usbDevice : mUsbManager.getDeviceList().values()) { - if (mDevices.get(usbDevice.getDeviceName()) == null) { - openDeviceLocked(usbDevice); - } - } - - return new ArrayList(mDevices.values()); - } - } - - /** - * Retrieves a list of all {@link android.mtp.MtpStorageInfo} - * for the MTP or PTP device with the given USB device name - * - * @param deviceName the name of the USB device - * @return the list of MtpStorageInfo - */ - public List getStorageList(String deviceName) { - MtpDevice device = getDevice(deviceName); - if (device == null) { - return null; - } - int[] storageIds = device.getStorageIds(); - if (storageIds == null) { - return null; - } - - int length = storageIds.length; - ArrayList storageList = new ArrayList(length); - for (int i = 0; i < length; i++) { - MtpStorageInfo info = device.getStorageInfo(storageIds[i]); - if (info == null) { - Log.w(TAG, "getStorageInfo failed"); - } else { - storageList.add(info); - } - } - return storageList; - } - - /** - * Retrieves the {@link android.mtp.MtpObjectInfo} for an object on - * the MTP or PTP device with the given USB device name with the given - * object handle - * - * @param deviceName the name of the USB device - * @param objectHandle handle of the object to query - * @return the MtpObjectInfo - */ - public MtpObjectInfo getObjectInfo(String deviceName, int objectHandle) { - MtpDevice device = getDevice(deviceName); - if (device == null) { - return null; - } - return device.getObjectInfo(objectHandle); - } - - /** - * Deletes an object on the MTP or PTP device with the given USB device name. - * - * @param deviceName the name of the USB device - * @param objectHandle handle of the object to delete - * @return true if the deletion succeeds - */ - public boolean deleteObject(String deviceName, int objectHandle) { - MtpDevice device = getDevice(deviceName); - if (device == null) { - return false; - } - return device.deleteObject(objectHandle); - } - - /** - * Retrieves a list of {@link android.mtp.MtpObjectInfo} for all objects - * on the MTP or PTP device with the given USB device name and given storage ID - * and/or object handle. - * If the object handle is zero, then all objects in the root of the storage unit - * will be returned. Otherwise, all immediate children of the object will be returned. - * If the storage ID is also zero, then all objects on all storage units will be returned. - * - * @param deviceName the name of the USB device - * @param storageId the ID of the storage unit to query, or zero for all - * @param objectHandle the handle of the parent object to query, or zero for the storage root - * @return the list of MtpObjectInfo - */ - public List getObjectList(String deviceName, int storageId, int objectHandle) { - MtpDevice device = getDevice(deviceName); - if (device == null) { - return null; - } - if (objectHandle == 0) { - // all objects in root of storage - objectHandle = 0xFFFFFFFF; - } - int[] handles = device.getObjectHandles(storageId, 0, objectHandle); - if (handles == null) { - return null; - } - - int length = handles.length; - ArrayList objectList = new ArrayList(length); - for (int i = 0; i < length; i++) { - MtpObjectInfo info = device.getObjectInfo(handles[i]); - if (info == null) { - Log.w(TAG, "getObjectInfo failed"); - } else { - objectList.add(info); - } - } - return objectList; - } - - /** - * Returns the data for an object as a byte array. - * - * @param deviceName the name of the USB device containing the object - * @param objectHandle handle of the object to read - * @param objectSize the size of the object (this should match - * {@link android.mtp.MtpObjectInfo#getCompressedSize} - * @return the object's data, or null if reading fails - */ - public byte[] getObject(String deviceName, int objectHandle, int objectSize) { - MtpDevice device = getDevice(deviceName); - if (device == null) { - return null; - } - return device.getObject(objectHandle, objectSize); - } - - /** - * Returns the thumbnail data for an object as a byte array. - * - * @param deviceName the name of the USB device containing the object - * @param objectHandle handle of the object to read - * @return the object's thumbnail, or null if reading fails - */ - public byte[] getThumbnail(String deviceName, int objectHandle) { - MtpDevice device = getDevice(deviceName); - if (device == null) { - return null; - } - return device.getThumbnail(objectHandle); - } - - /** - * Copies the data for an object to a file in external storage. - * - * @param deviceName the name of the USB device containing the object - * @param objectHandle handle of the object to read - * @param destPath path to destination for the file transfer. - * This path should be in the external storage as defined by - * {@link android.os.Environment#getExternalStorageDirectory} - * @return true if the file transfer succeeds - */ - public boolean importFile(String deviceName, int objectHandle, String destPath) { - MtpDevice device = getDevice(deviceName); - if (device == null) { - return false; - } - return device.importFile(objectHandle, destPath); - } -} diff --git a/src/com/android/gallery3d/data/PanoramaMetadataJob.java b/src/com/android/gallery3d/data/PanoramaMetadataJob.java deleted file mode 100644 index ab99d6a81..000000000 --- a/src/com/android/gallery3d/data/PanoramaMetadataJob.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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. - */ - -package com.android.gallery3d.data; - -import android.content.Context; -import android.net.Uri; - -import com.android.gallery3d.util.LightCycleHelper; -import com.android.gallery3d.util.LightCycleHelper.PanoramaMetadata; -import com.android.gallery3d.util.ThreadPool.Job; -import com.android.gallery3d.util.ThreadPool.JobContext; - -public class PanoramaMetadataJob implements Job { - Context mContext; - Uri mUri; - - public PanoramaMetadataJob(Context context, Uri uri) { - mContext = context; - mUri = uri; - } - - @Override - public PanoramaMetadata run(JobContext jc) { - return LightCycleHelper.getPanoramaMetadata(mContext, mUri); - } -} diff --git a/src/com/android/gallery3d/data/Path.java b/src/com/android/gallery3d/data/Path.java deleted file mode 100644 index fcae65e66..000000000 --- a/src/com/android/gallery3d/data/Path.java +++ /dev/null @@ -1,241 +0,0 @@ -/* - * 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.gallery3d.data; - -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.util.IdentityCache; - -import java.lang.ref.WeakReference; -import java.util.ArrayList; - -public class Path { - private static final String TAG = "Path"; - private static Path sRoot = new Path(null, "ROOT"); - - private final Path mParent; - private final String mSegment; - private WeakReference mObject; - private IdentityCache mChildren; - - private Path(Path parent, String segment) { - mParent = parent; - mSegment = segment; - } - - public Path getChild(String segment) { - synchronized (Path.class) { - if (mChildren == null) { - mChildren = new IdentityCache(); - } else { - Path p = mChildren.get(segment); - if (p != null) return p; - } - - Path p = new Path(this, segment); - mChildren.put(segment, p); - return p; - } - } - - public Path getParent() { - synchronized (Path.class) { - return mParent; - } - } - - public Path getChild(int segment) { - return getChild(String.valueOf(segment)); - } - - public Path getChild(long segment) { - return getChild(String.valueOf(segment)); - } - - public void setObject(MediaObject object) { - synchronized (Path.class) { - Utils.assertTrue(mObject == null || mObject.get() == null); - mObject = new WeakReference(object); - } - } - - MediaObject getObject() { - synchronized (Path.class) { - return (mObject == null) ? null : mObject.get(); - } - } - - @Override - // TODO: toString() should be more efficient, will fix it later - public String toString() { - synchronized (Path.class) { - StringBuilder sb = new StringBuilder(); - String[] segments = split(); - for (int i = 0; i < segments.length; i++) { - sb.append("/"); - sb.append(segments[i]); - } - return sb.toString(); - } - } - - public boolean equalsIgnoreCase (String p) { - String path = toString(); - return path.equalsIgnoreCase(p); - } - - public static Path fromString(String s) { - synchronized (Path.class) { - String[] segments = split(s); - Path current = sRoot; - for (int i = 0; i < segments.length; i++) { - current = current.getChild(segments[i]); - } - return current; - } - } - - public String[] split() { - synchronized (Path.class) { - int n = 0; - for (Path p = this; p != sRoot; p = p.mParent) { - n++; - } - String[] segments = new String[n]; - int i = n - 1; - for (Path p = this; p != sRoot; p = p.mParent) { - segments[i--] = p.mSegment; - } - return segments; - } - } - - public static String[] split(String s) { - int n = s.length(); - if (n == 0) return new String[0]; - if (s.charAt(0) != '/') { - throw new RuntimeException("malformed path:" + s); - } - ArrayList segments = new ArrayList(); - int i = 1; - while (i < n) { - int brace = 0; - int j; - for (j = i; j < n; j++) { - char c = s.charAt(j); - if (c == '{') ++brace; - else if (c == '}') --brace; - else if (brace == 0 && c == '/') break; - } - if (brace != 0) { - throw new RuntimeException("unbalanced brace in path:" + s); - } - segments.add(s.substring(i, j)); - i = j + 1; - } - String[] result = new String[segments.size()]; - segments.toArray(result); - return result; - } - - // Splits a string to an array of strings. - // For example, "{foo,bar,baz}" -> {"foo","bar","baz"}. - public static String[] splitSequence(String s) { - int n = s.length(); - if (s.charAt(0) != '{' || s.charAt(n-1) != '}') { - throw new RuntimeException("bad sequence: " + s); - } - ArrayList segments = new ArrayList(); - int i = 1; - while (i < n - 1) { - int brace = 0; - int j; - for (j = i; j < n - 1; j++) { - char c = s.charAt(j); - if (c == '{') ++brace; - else if (c == '}') --brace; - else if (brace == 0 && c == ',') break; - } - if (brace != 0) { - throw new RuntimeException("unbalanced brace in path:" + s); - } - segments.add(s.substring(i, j)); - i = j + 1; - } - String[] result = new String[segments.size()]; - segments.toArray(result); - return result; - } - - public String getPrefix() { - if (this == sRoot) return ""; - return getPrefixPath().mSegment; - } - - public Path getPrefixPath() { - synchronized (Path.class) { - Path current = this; - if (current == sRoot) { - throw new IllegalStateException(); - } - while (current.mParent != sRoot) { - current = current.mParent; - } - return current; - } - } - - public String getSuffix() { - // We don't need lock because mSegment is final. - return mSegment; - } - - // Below are for testing/debugging only - static void clearAll() { - synchronized (Path.class) { - sRoot = new Path(null, ""); - } - } - - static void dumpAll() { - dumpAll(sRoot, "", ""); - } - - static void dumpAll(Path p, String prefix1, String prefix2) { - synchronized (Path.class) { - MediaObject obj = p.getObject(); - Log.d(TAG, prefix1 + p.mSegment + ":" - + (obj == null ? "null" : obj.getClass().getSimpleName())); - if (p.mChildren != null) { - ArrayList childrenKeys = p.mChildren.keys(); - int i = 0, n = childrenKeys.size(); - for (String key : childrenKeys) { - Path child = p.mChildren.get(key); - if (child == null) { - ++i; - continue; - } - Log.d(TAG, prefix2 + "|"); - if (++i < n) { - dumpAll(child, prefix2 + "+-- ", prefix2 + "| "); - } else { - dumpAll(child, prefix2 + "+-- ", prefix2 + " "); - } - } - } - } - } -} diff --git a/src/com/android/gallery3d/data/PathMatcher.java b/src/com/android/gallery3d/data/PathMatcher.java deleted file mode 100644 index 9c6b840d5..000000000 --- a/src/com/android/gallery3d/data/PathMatcher.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * 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.gallery3d.data; - -import java.util.ArrayList; -import java.util.HashMap; - -public class PathMatcher { - public static final int NOT_FOUND = -1; - - private ArrayList mVariables = new ArrayList(); - private Node mRoot = new Node(); - - public PathMatcher() { - mRoot = new Node(); - } - - public void add(String pattern, int kind) { - String[] segments = Path.split(pattern); - Node current = mRoot; - for (int i = 0; i < segments.length; i++) { - current = current.addChild(segments[i]); - } - current.setKind(kind); - } - - public int match(Path path) { - String[] segments = path.split(); - mVariables.clear(); - Node current = mRoot; - for (int i = 0; i < segments.length; i++) { - Node next = current.getChild(segments[i]); - if (next == null) { - next = current.getChild("*"); - if (next != null) { - mVariables.add(segments[i]); - } else { - return NOT_FOUND; - } - } - current = next; - } - return current.getKind(); - } - - public String getVar(int index) { - return mVariables.get(index); - } - - public int getIntVar(int index) { - return Integer.parseInt(mVariables.get(index)); - } - - public long getLongVar(int index) { - return Long.parseLong(mVariables.get(index)); - } - - private static class Node { - private HashMap mMap; - private int mKind = NOT_FOUND; - - Node addChild(String segment) { - if (mMap == null) { - mMap = new HashMap(); - } else { - Node node = mMap.get(segment); - if (node != null) return node; - } - - Node n = new Node(); - mMap.put(segment, n); - return n; - } - - Node getChild(String segment) { - if (mMap == null) return null; - return mMap.get(segment); - } - - void setKind(int kind) { - mKind = kind; - } - - int getKind() { - return mKind; - } - } -} diff --git a/src/com/android/gallery3d/data/SecureAlbum.java b/src/com/android/gallery3d/data/SecureAlbum.java deleted file mode 100644 index 204f848f8..000000000 --- a/src/com/android/gallery3d/data/SecureAlbum.java +++ /dev/null @@ -1,206 +0,0 @@ -/* - * 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. - */ - -package com.android.gallery3d.data; - -import android.content.Context; -import android.database.Cursor; -import android.net.Uri; -import android.provider.MediaStore.Images; -import android.provider.MediaStore.MediaColumns; -import android.provider.MediaStore.Video; - -import com.android.gallery3d.app.GalleryApp; -import com.android.gallery3d.app.StitchingChangeListener; -import com.android.gallery3d.util.MediaSetUtils; - -import java.util.ArrayList; - -// This class lists all media items added by the client. -public class SecureAlbum extends MediaSet implements StitchingChangeListener { - @SuppressWarnings("unused") - private static final String TAG = "SecureAlbum"; - private static final String[] PROJECTION = {MediaColumns._ID}; - private int mMinImageId = Integer.MAX_VALUE; // the smallest id of images - private int mMaxImageId = Integer.MIN_VALUE; // the biggest id in images - private int mMinVideoId = Integer.MAX_VALUE; // the smallest id of videos - private int mMaxVideoId = Integer.MIN_VALUE; // the biggest id of videos - // All the media items added by the client. - private ArrayList mAllItems = new ArrayList(); - // The types of items in mAllItems. True is video and false is image. - private ArrayList mAllItemTypes = new ArrayList(); - private ArrayList mExistingItems = new ArrayList(); - private Context mContext; - private DataManager mDataManager; - private static final Uri[] mWatchUris = - {Images.Media.EXTERNAL_CONTENT_URI, Video.Media.EXTERNAL_CONTENT_URI}; - private final ChangeNotifier mNotifier; - // A placeholder image in the end of secure album. When it is tapped, it - // will take the user to the lock screen. - private MediaItem mUnlockItem; - private boolean mShowUnlockItem; - - public SecureAlbum(Path path, GalleryApp application, MediaItem unlock) { - super(path, nextVersionNumber()); - mContext = application.getAndroidContext(); - mDataManager = application.getDataManager(); - mNotifier = new ChangeNotifier(this, mWatchUris, application); - mUnlockItem = unlock; - mShowUnlockItem = (!isCameraBucketEmpty(Images.Media.EXTERNAL_CONTENT_URI) - || !isCameraBucketEmpty(Video.Media.EXTERNAL_CONTENT_URI)); - } - - public void addMediaItem(boolean isVideo, int id) { - Path pathBase; - if (isVideo) { - pathBase = LocalVideo.ITEM_PATH; - mMinVideoId = Math.min(mMinVideoId, id); - mMaxVideoId = Math.max(mMaxVideoId, id); - } else { - pathBase = LocalImage.ITEM_PATH; - mMinImageId = Math.min(mMinImageId, id); - mMaxImageId = Math.max(mMaxImageId, id); - } - Path path = pathBase.getChild(id); - if (!mAllItems.contains(path)) { - mAllItems.add(path); - mAllItemTypes.add(isVideo); - mNotifier.fakeChange(); - } - } - - // The sequence is stitching items, local media items, and unlock image. - @Override - public ArrayList getMediaItem(int start, int count) { - int existingCount = mExistingItems.size(); - if (start >= existingCount + 1) { - return new ArrayList(); - } - - // Add paths of requested stitching items. - int end = Math.min(start + count, existingCount); - ArrayList subset = new ArrayList(mExistingItems.subList(start, end)); - - // Convert paths to media items. - final MediaItem[] buf = new MediaItem[end - start]; - ItemConsumer consumer = new ItemConsumer() { - @Override - public void consume(int index, MediaItem item) { - buf[index] = item; - } - }; - mDataManager.mapMediaItems(subset, consumer, 0); - ArrayList result = new ArrayList(end - start); - for (int i = 0; i < buf.length; i++) { - result.add(buf[i]); - } - if (mShowUnlockItem) result.add(mUnlockItem); - return result; - } - - @Override - public int getMediaItemCount() { - return (mExistingItems.size() + (mShowUnlockItem ? 1 : 0)); - } - - @Override - public String getName() { - return "secure"; - } - - @Override - public long reload() { - if (mNotifier.isDirty()) { - mDataVersion = nextVersionNumber(); - updateExistingItems(); - } - return mDataVersion; - } - - private ArrayList queryExistingIds(Uri uri, int minId, int maxId) { - ArrayList ids = new ArrayList(); - if (minId == Integer.MAX_VALUE || maxId == Integer.MIN_VALUE) return ids; - - String[] selectionArgs = {String.valueOf(minId), String.valueOf(maxId)}; - Cursor cursor = mContext.getContentResolver().query(uri, PROJECTION, - "_id BETWEEN ? AND ?", selectionArgs, null); - if (cursor == null) return ids; - try { - while (cursor.moveToNext()) { - ids.add(cursor.getInt(0)); - } - } finally { - cursor.close(); - } - return ids; - } - - private boolean isCameraBucketEmpty(Uri baseUri) { - Uri uri = baseUri.buildUpon() - .appendQueryParameter("limit", "1").build(); - String[] selection = {String.valueOf(MediaSetUtils.CAMERA_BUCKET_ID)}; - Cursor cursor = mContext.getContentResolver().query(uri, PROJECTION, - "bucket_id = ?", selection, null); - if (cursor == null) return true; - try { - return (cursor.getCount() == 0); - } finally { - cursor.close(); - } - } - - private void updateExistingItems() { - if (mAllItems.size() == 0) return; - - // Query existing ids. - ArrayList imageIds = queryExistingIds( - Images.Media.EXTERNAL_CONTENT_URI, mMinImageId, mMaxImageId); - ArrayList videoIds = queryExistingIds( - Video.Media.EXTERNAL_CONTENT_URI, mMinVideoId, mMaxVideoId); - - // Construct the existing items list. - mExistingItems.clear(); - for (int i = mAllItems.size() - 1; i >= 0; i--) { - Path path = mAllItems.get(i); - boolean isVideo = mAllItemTypes.get(i); - int id = Integer.parseInt(path.getSuffix()); - if (isVideo) { - if (videoIds.contains(id)) mExistingItems.add(path); - } else { - if (imageIds.contains(id)) mExistingItems.add(path); - } - } - } - - @Override - public boolean isLeafAlbum() { - return true; - } - - @Override - public void onStitchingQueued(Uri uri) { - int id = Integer.parseInt(uri.getLastPathSegment()); - addMediaItem(false, id); - } - - @Override - public void onStitchingResult(Uri uri) { - } - - @Override - public void onStitchingProgress(Uri uri, final int progress) { - } -} diff --git a/src/com/android/gallery3d/data/SecureSource.java b/src/com/android/gallery3d/data/SecureSource.java deleted file mode 100644 index 6bc8cc295..000000000 --- a/src/com/android/gallery3d/data/SecureSource.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * 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. - */ - -package com.android.gallery3d.data; - -import com.android.gallery3d.app.GalleryApp; - -public class SecureSource extends MediaSource { - private GalleryApp mApplication; - private static PathMatcher mMatcher = new PathMatcher(); - private static final int SECURE_ALBUM = 0; - private static final int SECURE_UNLOCK = 1; - - static { - mMatcher.add("/secure/all/*", SECURE_ALBUM); - mMatcher.add("/secure/unlock", SECURE_UNLOCK); - } - - public SecureSource(GalleryApp context) { - super("secure"); - mApplication = context; - } - - public static boolean isSecurePath(String path) { - return (SECURE_ALBUM == mMatcher.match(Path.fromString(path))); - } - - @Override - public MediaObject createMediaObject(Path path) { - switch (mMatcher.match(path)) { - case SECURE_ALBUM: { - DataManager dataManager = mApplication.getDataManager(); - MediaItem unlock = (MediaItem) dataManager.getMediaObject( - "/secure/unlock"); - return new SecureAlbum(path, mApplication, unlock); - } - case SECURE_UNLOCK: - return new UnlockImage(path, mApplication); - default: - throw new RuntimeException("bad path: " + path); - } - } -} diff --git a/src/com/android/gallery3d/data/SingleItemAlbum.java b/src/com/android/gallery3d/data/SingleItemAlbum.java deleted file mode 100644 index a0093e0c3..000000000 --- a/src/com/android/gallery3d/data/SingleItemAlbum.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * 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. - */ - -package com.android.gallery3d.data; - -import java.util.ArrayList; - -public class SingleItemAlbum extends MediaSet { - @SuppressWarnings("unused") - private static final String TAG = "SingleItemAlbum"; - private final MediaItem mItem; - private final String mName; - - public SingleItemAlbum(Path path, MediaItem item) { - super(path, nextVersionNumber()); - mItem = item; - mName = "SingleItemAlbum("+mItem.getClass().getSimpleName()+")"; - } - - @Override - public int getMediaItemCount() { - return 1; - } - - @Override - public ArrayList getMediaItem(int start, int count) { - ArrayList result = new ArrayList(); - - // If [start, start+count) contains the index 0, return the item. - if (start <= 0 && start + count > 0) { - result.add(mItem); - } - - return result; - } - - public MediaItem getItem() { - return mItem; - } - - @Override - public boolean isLeafAlbum() { - return true; - } - - @Override - public String getName() { - return mName; - } - - @Override - public long reload() { - return mDataVersion; - } -} diff --git a/src/com/android/gallery3d/data/SizeClustering.java b/src/com/android/gallery3d/data/SizeClustering.java deleted file mode 100644 index b809c841b..000000000 --- a/src/com/android/gallery3d/data/SizeClustering.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * 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.gallery3d.data; - -import android.content.Context; -import android.content.res.Resources; - -import com.android.gallery3d.R; - -import java.util.ArrayList; - -public class SizeClustering extends Clustering { - @SuppressWarnings("unused") - private static final String TAG = "SizeClustering"; - - private Context mContext; - private ArrayList[] mClusters; - private String[] mNames; - private long mMinSizes[]; - - private static final long MEGA_BYTES = 1024L*1024; - private static final long GIGA_BYTES = 1024L*1024*1024; - - private static final long[] SIZE_LEVELS = { - 0, - 1 * MEGA_BYTES, - 10 * MEGA_BYTES, - 100 * MEGA_BYTES, - 1 * GIGA_BYTES, - 2 * GIGA_BYTES, - 4 * GIGA_BYTES, - }; - - public SizeClustering(Context context) { - mContext = context; - } - - @SuppressWarnings("unchecked") - @Override - public void run(MediaSet baseSet) { - @SuppressWarnings("unchecked") - final ArrayList[] group = new ArrayList[SIZE_LEVELS.length]; - baseSet.enumerateTotalMediaItems(new MediaSet.ItemConsumer() { - @Override - public void consume(int index, MediaItem item) { - // Find the cluster this item belongs to. - long size = item.getSize(); - int i; - for (i = 0; i < SIZE_LEVELS.length - 1; i++) { - if (size < SIZE_LEVELS[i + 1]) { - break; - } - } - - ArrayList list = group[i]; - if (list == null) { - list = new ArrayList(); - group[i] = list; - } - list.add(item.getPath()); - } - }); - - int count = 0; - for (int i = 0; i < group.length; i++) { - if (group[i] != null) { - count++; - } - } - - mClusters = new ArrayList[count]; - mNames = new String[count]; - mMinSizes = new long[count]; - - Resources res = mContext.getResources(); - int k = 0; - // Go through group in the reverse order, so the group with the largest - // size will show first. - for (int i = group.length - 1; i >= 0; i--) { - if (group[i] == null) continue; - - mClusters[k] = group[i]; - if (i == 0) { - mNames[k] = String.format( - res.getString(R.string.size_below), getSizeString(i + 1)); - } else if (i == group.length - 1) { - mNames[k] = String.format( - res.getString(R.string.size_above), getSizeString(i)); - } else { - String minSize = getSizeString(i); - String maxSize = getSizeString(i + 1); - mNames[k] = String.format( - res.getString(R.string.size_between), minSize, maxSize); - } - mMinSizes[k] = SIZE_LEVELS[i]; - k++; - } - } - - private String getSizeString(int index) { - long bytes = SIZE_LEVELS[index]; - if (bytes >= GIGA_BYTES) { - return (bytes / GIGA_BYTES) + "GB"; - } else { - return (bytes / MEGA_BYTES) + "MB"; - } - } - - @Override - public int getNumberOfClusters() { - return mClusters.length; - } - - @Override - public ArrayList getCluster(int index) { - return mClusters[index]; - } - - @Override - public String getClusterName(int index) { - return mNames[index]; - } - - public long getMinSize(int index) { - return mMinSizes[index]; - } -} diff --git a/src/com/android/gallery3d/data/SnailAlbum.java b/src/com/android/gallery3d/data/SnailAlbum.java deleted file mode 100644 index 7bce7a695..000000000 --- a/src/com/android/gallery3d/data/SnailAlbum.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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. - */ - -package com.android.gallery3d.data; - -import java.util.concurrent.atomic.AtomicBoolean; - -// This is a simple MediaSet which contains only one MediaItem -- a SnailItem. -public class SnailAlbum extends SingleItemAlbum { - @SuppressWarnings("unused") - private static final String TAG = "SnailAlbum"; - private AtomicBoolean mDirty = new AtomicBoolean(false); - - public SnailAlbum(Path path, SnailItem item) { - super(path, item); - } - - @Override - public long reload() { - if (mDirty.compareAndSet(true, false)) { - ((SnailItem) getItem()).updateVersion(); - mDataVersion = nextVersionNumber(); - } - return mDataVersion; - } - - public void notifyChange() { - mDirty.set(true); - notifyContentChanged(); - } -} diff --git a/src/com/android/gallery3d/data/SnailItem.java b/src/com/android/gallery3d/data/SnailItem.java deleted file mode 100644 index 3586d2cab..000000000 --- a/src/com/android/gallery3d/data/SnailItem.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * 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. - */ - -package com.android.gallery3d.data; - -import android.graphics.Bitmap; -import android.graphics.BitmapRegionDecoder; - -import com.android.gallery3d.ui.ScreenNail; -import com.android.gallery3d.util.ThreadPool.Job; -import com.android.gallery3d.util.ThreadPool.JobContext; - -// SnailItem is a MediaItem which can provide a ScreenNail. This is -// used so we can show an foreign component (like an -// android.view.View) instead of a Bitmap. -public class SnailItem extends MediaItem { - @SuppressWarnings("unused") - private static final String TAG = "SnailItem"; - private ScreenNail mScreenNail; - - public SnailItem(Path path) { - super(path, nextVersionNumber()); - } - - @Override - public Job requestImage(int type) { - // nothing to return - return new Job() { - @Override - public Bitmap run(JobContext jc) { - return null; - } - }; - } - - @Override - public Job requestLargeImage() { - // nothing to return - return new Job() { - @Override - public BitmapRegionDecoder run(JobContext jc) { - return null; - } - }; - } - - // We do not provide requestImage or requestLargeImage, instead we - // provide a ScreenNail. - @Override - public ScreenNail getScreenNail() { - return mScreenNail; - } - - @Override - public String getMimeType() { - return ""; - } - - // Returns width and height of the media item. - // Returns 0, 0 if the information is not available. - @Override - public int getWidth() { - return 0; - } - - @Override - public int getHeight() { - return 0; - } - - ////////////////////////////////////////////////////////////////////////// - // Extra methods for SnailItem - ////////////////////////////////////////////////////////////////////////// - - public void setScreenNail(ScreenNail screenNail) { - mScreenNail = screenNail; - } - - public void updateVersion() { - mDataVersion = nextVersionNumber(); - } -} diff --git a/src/com/android/gallery3d/data/SnailSource.java b/src/com/android/gallery3d/data/SnailSource.java deleted file mode 100644 index 5c690ccdb..000000000 --- a/src/com/android/gallery3d/data/SnailSource.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * 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. - */ -package com.android.gallery3d.data; - -import com.android.gallery3d.app.GalleryApp; - -public class SnailSource extends MediaSource { - @SuppressWarnings("unused") - private static final String TAG = "SnailSource"; - private static final int SNAIL_ALBUM = 0; - private static final int SNAIL_ITEM = 1; - - private GalleryApp mApplication; - private PathMatcher mMatcher; - private static int sNextId; - - public SnailSource(GalleryApp application) { - super("snail"); - mApplication = application; - mMatcher = new PathMatcher(); - mMatcher.add("/snail/set/*", SNAIL_ALBUM); - mMatcher.add("/snail/item/*", SNAIL_ITEM); - } - - // The only path we accept is "/snail/set/id" and "/snail/item/id" - @Override - public MediaObject createMediaObject(Path path) { - DataManager dataManager = mApplication.getDataManager(); - switch (mMatcher.match(path)) { - case SNAIL_ALBUM: - String itemPath = "/snail/item/" + mMatcher.getVar(0); - SnailItem item = - (SnailItem) dataManager.getMediaObject(itemPath); - return new SnailAlbum(path, item); - case SNAIL_ITEM: { - int id = mMatcher.getIntVar(0); - return new SnailItem(path); - } - } - return null; - } - - // Registers a new SnailAlbum containing a SnailItem and returns the id of - // them. You can obtain the Path of the SnailAlbum and SnailItem associated - // with the id by getSetPath and getItemPath(). - public static synchronized int newId() { - return sNextId++; - } - - public static Path getSetPath(int id) { - return Path.fromString("/snail/set").getChild(id); - } - - public static Path getItemPath(int id) { - return Path.fromString("/snail/item").getChild(id); - } -} diff --git a/src/com/android/gallery3d/data/TagClustering.java b/src/com/android/gallery3d/data/TagClustering.java deleted file mode 100644 index 407ca84c4..000000000 --- a/src/com/android/gallery3d/data/TagClustering.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * 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.gallery3d.data; - -import android.content.Context; - -import com.android.gallery3d.R; - -import java.util.ArrayList; -import java.util.Map; -import java.util.TreeMap; - -public class TagClustering extends Clustering { - @SuppressWarnings("unused") - private static final String TAG = "TagClustering"; - - private ArrayList> mClusters; - private String[] mNames; - private String mUntaggedString; - - public TagClustering(Context context) { - mUntaggedString = context.getResources().getString(R.string.untagged); - } - - @Override - public void run(MediaSet baseSet) { - final TreeMap> map = - new TreeMap>(); - final ArrayList untagged = new ArrayList(); - - baseSet.enumerateTotalMediaItems(new MediaSet.ItemConsumer() { - @Override - public void consume(int index, MediaItem item) { - Path path = item.getPath(); - - String[] tags = item.getTags(); - if (tags == null || tags.length == 0) { - untagged.add(path); - return; - } - for (int j = 0; j < tags.length; j++) { - String key = tags[j]; - ArrayList list = map.get(key); - if (list == null) { - list = new ArrayList(); - map.put(key, list); - } - list.add(path); - } - } - }); - - int m = map.size(); - mClusters = new ArrayList>(); - mNames = new String[m + ((untagged.size() > 0) ? 1 : 0)]; - int i = 0; - for (Map.Entry> entry : map.entrySet()) { - mNames[i++] = entry.getKey(); - mClusters.add(entry.getValue()); - } - if (untagged.size() > 0) { - mNames[i++] = mUntaggedString; - mClusters.add(untagged); - } - } - - @Override - public int getNumberOfClusters() { - return mClusters.size(); - } - - @Override - public ArrayList getCluster(int index) { - return mClusters.get(index); - } - - @Override - public String getClusterName(int index) { - return mNames[index]; - } -} diff --git a/src/com/android/gallery3d/data/TimeClustering.java b/src/com/android/gallery3d/data/TimeClustering.java deleted file mode 100644 index 35cbab1ee..000000000 --- a/src/com/android/gallery3d/data/TimeClustering.java +++ /dev/null @@ -1,439 +0,0 @@ -/* - * 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.gallery3d.data; - -import android.content.Context; -import android.text.format.DateFormat; -import android.text.format.DateUtils; - -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.util.GalleryUtils; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; - -public class TimeClustering extends Clustering { - @SuppressWarnings("unused") - private static final String TAG = "TimeClustering"; - - // If 2 items are greater than 25 miles apart, they will be in different - // clusters. - private static final int GEOGRAPHIC_DISTANCE_CUTOFF_IN_MILES = 20; - - // Do not want to split based on anything under 1 min. - private static final long MIN_CLUSTER_SPLIT_TIME_IN_MS = 60000L; - - // Disregard a cluster split time of anything over 2 hours. - private static final long MAX_CLUSTER_SPLIT_TIME_IN_MS = 7200000L; - - // Try and get around 9 clusters (best-effort for the common case). - private static final int NUM_CLUSTERS_TARGETED = 9; - - // Try and merge 2 clusters if they are both smaller than min cluster size. - // The min cluster size can range from 8 to 15. - private static final int MIN_MIN_CLUSTER_SIZE = 8; - private static final int MAX_MIN_CLUSTER_SIZE = 15; - - // Try and split a cluster if it is bigger than max cluster size. - // The max cluster size can range from 20 to 50. - private static final int MIN_MAX_CLUSTER_SIZE = 20; - private static final int MAX_MAX_CLUSTER_SIZE = 50; - - // Initially put 2 items in the same cluster as long as they are within - // 3 cluster frequencies of each other. - private static int CLUSTER_SPLIT_MULTIPLIER = 3; - - // The minimum change factor in the time between items to consider a - // partition. - // Example: (Item 3 - Item 2) / (Item 2 - Item 1). - private static final int MIN_PARTITION_CHANGE_FACTOR = 2; - - // Make the cluster split time of a large cluster half that of a regular - // cluster. - private static final int PARTITION_CLUSTER_SPLIT_TIME_FACTOR = 2; - - private Context mContext; - private ArrayList mClusters; - private String[] mNames; - private Cluster mCurrCluster; - - private long mClusterSplitTime = - (MIN_CLUSTER_SPLIT_TIME_IN_MS + MAX_CLUSTER_SPLIT_TIME_IN_MS) / 2; - private long mLargeClusterSplitTime = - mClusterSplitTime / PARTITION_CLUSTER_SPLIT_TIME_FACTOR; - private int mMinClusterSize = (MIN_MIN_CLUSTER_SIZE + MAX_MIN_CLUSTER_SIZE) / 2; - private int mMaxClusterSize = (MIN_MAX_CLUSTER_SIZE + MAX_MAX_CLUSTER_SIZE) / 2; - - - private static final Comparator sDateComparator = - new DateComparator(); - - private static class DateComparator implements Comparator { - @Override - public int compare(SmallItem item1, SmallItem item2) { - return -Utils.compare(item1.dateInMs, item2.dateInMs); - } - } - - public TimeClustering(Context context) { - mContext = context; - mClusters = new ArrayList(); - mCurrCluster = new Cluster(); - } - - @Override - public void run(MediaSet baseSet) { - final int total = baseSet.getTotalMediaItemCount(); - final SmallItem[] buf = new SmallItem[total]; - final double[] latLng = new double[2]; - - baseSet.enumerateTotalMediaItems(new MediaSet.ItemConsumer() { - @Override - public void consume(int index, MediaItem item) { - if (index < 0 || index >= total) return; - SmallItem s = new SmallItem(); - s.path = item.getPath(); - s.dateInMs = item.getDateInMs(); - item.getLatLong(latLng); - s.lat = latLng[0]; - s.lng = latLng[1]; - buf[index] = s; - } - }); - - ArrayList items = new ArrayList(total); - for (int i = 0; i < total; i++) { - if (buf[i] != null) { - items.add(buf[i]); - } - } - - Collections.sort(items, sDateComparator); - - int n = items.size(); - long minTime = 0; - long maxTime = 0; - for (int i = 0; i < n; i++) { - long t = items.get(i).dateInMs; - if (t == 0) continue; - if (minTime == 0) { - minTime = maxTime = t; - } else { - minTime = Math.min(minTime, t); - maxTime = Math.max(maxTime, t); - } - } - - setTimeRange(maxTime - minTime, n); - - for (int i = 0; i < n; i++) { - compute(items.get(i)); - } - - compute(null); - - int m = mClusters.size(); - mNames = new String[m]; - for (int i = 0; i < m; i++) { - mNames[i] = mClusters.get(i).generateCaption(mContext); - } - } - - @Override - public int getNumberOfClusters() { - return mClusters.size(); - } - - @Override - public ArrayList getCluster(int index) { - ArrayList items = mClusters.get(index).getItems(); - ArrayList result = new ArrayList(items.size()); - for (int i = 0, n = items.size(); i < n; i++) { - result.add(items.get(i).path); - } - return result; - } - - @Override - public String getClusterName(int index) { - return mNames[index]; - } - - private void setTimeRange(long timeRange, int numItems) { - if (numItems != 0) { - int meanItemsPerCluster = numItems / NUM_CLUSTERS_TARGETED; - // Heuristic to get min and max cluster size - half and double the - // desired items per cluster. - mMinClusterSize = meanItemsPerCluster / 2; - mMaxClusterSize = meanItemsPerCluster * 2; - mClusterSplitTime = timeRange / numItems * CLUSTER_SPLIT_MULTIPLIER; - } - mClusterSplitTime = Utils.clamp(mClusterSplitTime, MIN_CLUSTER_SPLIT_TIME_IN_MS, MAX_CLUSTER_SPLIT_TIME_IN_MS); - mLargeClusterSplitTime = mClusterSplitTime / PARTITION_CLUSTER_SPLIT_TIME_FACTOR; - mMinClusterSize = Utils.clamp(mMinClusterSize, MIN_MIN_CLUSTER_SIZE, MAX_MIN_CLUSTER_SIZE); - mMaxClusterSize = Utils.clamp(mMaxClusterSize, MIN_MAX_CLUSTER_SIZE, MAX_MAX_CLUSTER_SIZE); - } - - private void compute(SmallItem currentItem) { - if (currentItem != null) { - int numClusters = mClusters.size(); - int numCurrClusterItems = mCurrCluster.size(); - boolean geographicallySeparateItem = false; - boolean itemAddedToCurrentCluster = false; - - // Determine if this item should go in the current cluster or be the - // start of a new cluster. - if (numCurrClusterItems == 0) { - mCurrCluster.addItem(currentItem); - } else { - SmallItem prevItem = mCurrCluster.getLastItem(); - if (isGeographicallySeparated(prevItem, currentItem)) { - mClusters.add(mCurrCluster); - geographicallySeparateItem = true; - } else if (numCurrClusterItems > mMaxClusterSize) { - splitAndAddCurrentCluster(); - } else if (timeDistance(prevItem, currentItem) < mClusterSplitTime) { - mCurrCluster.addItem(currentItem); - itemAddedToCurrentCluster = true; - } else if (numClusters > 0 && numCurrClusterItems < mMinClusterSize - && !mCurrCluster.mGeographicallySeparatedFromPrevCluster) { - mergeAndAddCurrentCluster(); - } else { - mClusters.add(mCurrCluster); - } - - // Creating a new cluster and adding the current item to it. - if (!itemAddedToCurrentCluster) { - mCurrCluster = new Cluster(); - if (geographicallySeparateItem) { - mCurrCluster.mGeographicallySeparatedFromPrevCluster = true; - } - mCurrCluster.addItem(currentItem); - } - } - } else { - if (mCurrCluster.size() > 0) { - int numClusters = mClusters.size(); - int numCurrClusterItems = mCurrCluster.size(); - - // The last cluster may potentially be too big or too small. - if (numCurrClusterItems > mMaxClusterSize) { - splitAndAddCurrentCluster(); - } else if (numClusters > 0 && numCurrClusterItems < mMinClusterSize - && !mCurrCluster.mGeographicallySeparatedFromPrevCluster) { - mergeAndAddCurrentCluster(); - } else { - mClusters.add(mCurrCluster); - } - mCurrCluster = new Cluster(); - } - } - } - - private void splitAndAddCurrentCluster() { - ArrayList currClusterItems = mCurrCluster.getItems(); - int numCurrClusterItems = mCurrCluster.size(); - int secondPartitionStartIndex = getPartitionIndexForCurrentCluster(); - if (secondPartitionStartIndex != -1) { - Cluster partitionedCluster = new Cluster(); - for (int j = 0; j < secondPartitionStartIndex; j++) { - partitionedCluster.addItem(currClusterItems.get(j)); - } - mClusters.add(partitionedCluster); - partitionedCluster = new Cluster(); - for (int j = secondPartitionStartIndex; j < numCurrClusterItems; j++) { - partitionedCluster.addItem(currClusterItems.get(j)); - } - mClusters.add(partitionedCluster); - } else { - mClusters.add(mCurrCluster); - } - } - - private int getPartitionIndexForCurrentCluster() { - int partitionIndex = -1; - float largestChange = MIN_PARTITION_CHANGE_FACTOR; - ArrayList currClusterItems = mCurrCluster.getItems(); - int numCurrClusterItems = mCurrCluster.size(); - int minClusterSize = mMinClusterSize; - - // Could be slightly more efficient here but this code seems cleaner. - if (numCurrClusterItems > minClusterSize + 1) { - for (int i = minClusterSize; i < numCurrClusterItems - minClusterSize; i++) { - SmallItem prevItem = currClusterItems.get(i - 1); - SmallItem currItem = currClusterItems.get(i); - SmallItem nextItem = currClusterItems.get(i + 1); - - long timeNext = nextItem.dateInMs; - long timeCurr = currItem.dateInMs; - long timePrev = prevItem.dateInMs; - - if (timeNext == 0 || timeCurr == 0 || timePrev == 0) continue; - - long diff1 = Math.abs(timeNext - timeCurr); - long diff2 = Math.abs(timeCurr - timePrev); - - float change = Math.max(diff1 / (diff2 + 0.01f), diff2 / (diff1 + 0.01f)); - if (change > largestChange) { - if (timeDistance(currItem, prevItem) > mLargeClusterSplitTime) { - partitionIndex = i; - largestChange = change; - } else if (timeDistance(nextItem, currItem) > mLargeClusterSplitTime) { - partitionIndex = i + 1; - largestChange = change; - } - } - } - } - return partitionIndex; - } - - private void mergeAndAddCurrentCluster() { - int numClusters = mClusters.size(); - Cluster prevCluster = mClusters.get(numClusters - 1); - ArrayList currClusterItems = mCurrCluster.getItems(); - int numCurrClusterItems = mCurrCluster.size(); - if (prevCluster.size() < mMinClusterSize) { - for (int i = 0; i < numCurrClusterItems; i++) { - prevCluster.addItem(currClusterItems.get(i)); - } - mClusters.set(numClusters - 1, prevCluster); - } else { - mClusters.add(mCurrCluster); - } - } - - // Returns true if a, b are sufficiently geographically separated. - private static boolean isGeographicallySeparated(SmallItem itemA, SmallItem itemB) { - if (!GalleryUtils.isValidLocation(itemA.lat, itemA.lng) - || !GalleryUtils.isValidLocation(itemB.lat, itemB.lng)) { - return false; - } - - double distance = GalleryUtils.fastDistanceMeters( - Math.toRadians(itemA.lat), - Math.toRadians(itemA.lng), - Math.toRadians(itemB.lat), - Math.toRadians(itemB.lng)); - return (GalleryUtils.toMile(distance) > GEOGRAPHIC_DISTANCE_CUTOFF_IN_MILES); - } - - // Returns the time interval between the two items in milliseconds. - private static long timeDistance(SmallItem a, SmallItem b) { - return Math.abs(a.dateInMs - b.dateInMs); - } -} - -class SmallItem { - Path path; - long dateInMs; - double lat, lng; -} - -class Cluster { - @SuppressWarnings("unused") - private static final String TAG = "Cluster"; - private static final String MMDDYY_FORMAT = "MMddyy"; - - // This is for TimeClustering only. - public boolean mGeographicallySeparatedFromPrevCluster = false; - - private ArrayList mItems = new ArrayList(); - - public Cluster() { - } - - public void addItem(SmallItem item) { - mItems.add(item); - } - - public int size() { - return mItems.size(); - } - - public SmallItem getLastItem() { - int n = mItems.size(); - return (n == 0) ? null : mItems.get(n - 1); - } - - public ArrayList getItems() { - return mItems; - } - - public String generateCaption(Context context) { - int n = mItems.size(); - long minTimestamp = 0; - long maxTimestamp = 0; - - for (int i = 0; i < n; i++) { - long t = mItems.get(i).dateInMs; - if (t == 0) continue; - if (minTimestamp == 0) { - minTimestamp = maxTimestamp = t; - } else { - minTimestamp = Math.min(minTimestamp, t); - maxTimestamp = Math.max(maxTimestamp, t); - } - } - if (minTimestamp == 0) return ""; - - String caption; - String minDay = DateFormat.format(MMDDYY_FORMAT, minTimestamp) - .toString(); - String maxDay = DateFormat.format(MMDDYY_FORMAT, maxTimestamp) - .toString(); - - if (minDay.substring(4).equals(maxDay.substring(4))) { - // The items are from the same year - show at least as - // much granularity as abbrev_all allows. - caption = DateUtils.formatDateRange(context, minTimestamp, - maxTimestamp, DateUtils.FORMAT_ABBREV_ALL); - - // Get a more granular date range string if the min and - // max timestamp are on the same day and from the - // current year. - if (minDay.equals(maxDay)) { - int flags = DateUtils.FORMAT_ABBREV_MONTH | DateUtils.FORMAT_SHOW_DATE; - // Contains the year only if the date does not - // correspond to the current year. - String dateRangeWithOptionalYear = DateUtils.formatDateTime( - context, minTimestamp, flags); - String dateRangeWithYear = DateUtils.formatDateTime( - context, minTimestamp, flags | DateUtils.FORMAT_SHOW_YEAR); - if (!dateRangeWithOptionalYear.equals(dateRangeWithYear)) { - // This means both dates are from the same year - // - show the time. - // Not enough room to display the time range. - // Pick the mid-point. - long midTimestamp = (minTimestamp + maxTimestamp) / 2; - caption = DateUtils.formatDateRange(context, midTimestamp, - midTimestamp, DateUtils.FORMAT_SHOW_TIME | flags); - } - } - } else { - // The items are not from the same year - only show - // month and year. - int flags = DateUtils.FORMAT_NO_MONTH_DAY - | DateUtils.FORMAT_ABBREV_MONTH | DateUtils.FORMAT_SHOW_DATE; - caption = DateUtils.formatDateRange(context, minTimestamp, - maxTimestamp, flags); - } - - return caption; - } -} diff --git a/src/com/android/gallery3d/data/UnlockImage.java b/src/com/android/gallery3d/data/UnlockImage.java deleted file mode 100644 index ed3b485c4..000000000 --- a/src/com/android/gallery3d/data/UnlockImage.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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. - */ - -package com.android.gallery3d.data; - -import com.android.gallery3d.R; -import com.android.gallery3d.app.GalleryApp; - -public class UnlockImage extends ActionImage { - @SuppressWarnings("unused") - private static final String TAG = "UnlockImage"; - - public UnlockImage(Path path, GalleryApp application) { - super(path, application, R.drawable.placeholder_locked); - } - - @Override - public int getSupportedOperations() { - return super.getSupportedOperations() | SUPPORT_UNLOCK; - } -} diff --git a/src/com/android/gallery3d/data/UriImage.java b/src/com/android/gallery3d/data/UriImage.java deleted file mode 100644 index e8875b572..000000000 --- a/src/com/android/gallery3d/data/UriImage.java +++ /dev/null @@ -1,298 +0,0 @@ -/* - * 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.gallery3d.data; - -import android.content.ContentResolver; -import android.graphics.Bitmap; -import android.graphics.Bitmap.Config; -import android.graphics.BitmapFactory.Options; -import android.graphics.BitmapRegionDecoder; -import android.net.Uri; -import android.os.ParcelFileDescriptor; - -import com.android.gallery3d.app.GalleryApp; -import com.android.gallery3d.app.PanoramaMetadataSupport; -import com.android.gallery3d.common.BitmapUtils; -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.util.ThreadPool.CancelListener; -import com.android.gallery3d.util.ThreadPool.Job; -import com.android.gallery3d.util.ThreadPool.JobContext; - -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.InputStream; -import java.net.URI; -import java.net.URL; - -public class UriImage extends MediaItem { - private static final String TAG = "UriImage"; - - private static final int STATE_INIT = 0; - private static final int STATE_DOWNLOADING = 1; - private static final int STATE_DOWNLOADED = 2; - private static final int STATE_ERROR = -1; - - private final Uri mUri; - private final String mContentType; - - private DownloadCache.Entry mCacheEntry; - private ParcelFileDescriptor mFileDescriptor; - private int mState = STATE_INIT; - private int mWidth; - private int mHeight; - private int mRotation; - private PanoramaMetadataSupport mPanoramaMetadata = new PanoramaMetadataSupport(this); - - private GalleryApp mApplication; - - public UriImage(GalleryApp application, Path path, Uri uri, String contentType) { - super(path, nextVersionNumber()); - mUri = uri; - mApplication = Utils.checkNotNull(application); - mContentType = contentType; - } - - @Override - public Job requestImage(int type) { - return new BitmapJob(type); - } - - @Override - public Job requestLargeImage() { - return new RegionDecoderJob(); - } - - private void openFileOrDownloadTempFile(JobContext jc) { - int state = openOrDownloadInner(jc); - synchronized (this) { - mState = state; - if (mState != STATE_DOWNLOADED) { - if (mFileDescriptor != null) { - Utils.closeSilently(mFileDescriptor); - mFileDescriptor = null; - } - } - notifyAll(); - } - } - - private int openOrDownloadInner(JobContext jc) { - String scheme = mUri.getScheme(); - if (ContentResolver.SCHEME_CONTENT.equals(scheme) - || ContentResolver.SCHEME_ANDROID_RESOURCE.equals(scheme) - || ContentResolver.SCHEME_FILE.equals(scheme)) { - try { - if (MIME_TYPE_JPEG.equalsIgnoreCase(mContentType)) { - InputStream is = mApplication.getContentResolver() - .openInputStream(mUri); - mRotation = Exif.getOrientation(is); - Utils.closeSilently(is); - } - mFileDescriptor = mApplication.getContentResolver() - .openFileDescriptor(mUri, "r"); - if (jc.isCancelled()) return STATE_INIT; - return STATE_DOWNLOADED; - } catch (FileNotFoundException e) { - Log.w(TAG, "fail to open: " + mUri, e); - return STATE_ERROR; - } - } else { - try { - URL url = new URI(mUri.toString()).toURL(); - mCacheEntry = mApplication.getDownloadCache().download(jc, url); - if (jc.isCancelled()) return STATE_INIT; - if (mCacheEntry == null) { - Log.w(TAG, "download failed " + url); - return STATE_ERROR; - } - if (MIME_TYPE_JPEG.equalsIgnoreCase(mContentType)) { - InputStream is = new FileInputStream(mCacheEntry.cacheFile); - mRotation = Exif.getOrientation(is); - Utils.closeSilently(is); - } - mFileDescriptor = ParcelFileDescriptor.open( - mCacheEntry.cacheFile, ParcelFileDescriptor.MODE_READ_ONLY); - return STATE_DOWNLOADED; - } catch (Throwable t) { - Log.w(TAG, "download error", t); - return STATE_ERROR; - } - } - } - - private boolean prepareInputFile(JobContext jc) { - jc.setCancelListener(new CancelListener() { - @Override - public void onCancel() { - synchronized (this) { - notifyAll(); - } - } - }); - - while (true) { - synchronized (this) { - if (jc.isCancelled()) return false; - if (mState == STATE_INIT) { - mState = STATE_DOWNLOADING; - // Then leave the synchronized block and continue. - } else if (mState == STATE_ERROR) { - return false; - } else if (mState == STATE_DOWNLOADED) { - return true; - } else /* if (mState == STATE_DOWNLOADING) */ { - try { - wait(); - } catch (InterruptedException ex) { - // ignored. - } - continue; - } - } - // This is only reached for STATE_INIT->STATE_DOWNLOADING - openFileOrDownloadTempFile(jc); - } - } - - private class RegionDecoderJob implements Job { - @Override - public BitmapRegionDecoder run(JobContext jc) { - if (!prepareInputFile(jc)) return null; - BitmapRegionDecoder decoder = DecodeUtils.createBitmapRegionDecoder( - jc, mFileDescriptor.getFileDescriptor(), false); - mWidth = decoder.getWidth(); - mHeight = decoder.getHeight(); - return decoder; - } - } - - private class BitmapJob implements Job { - private int mType; - - protected BitmapJob(int type) { - mType = type; - } - - @Override - public Bitmap run(JobContext jc) { - if (!prepareInputFile(jc)) return null; - int targetSize = MediaItem.getTargetSize(mType); - Options options = new Options(); - options.inPreferredConfig = Config.ARGB_8888; - Bitmap bitmap = DecodeUtils.decodeThumbnail(jc, - mFileDescriptor.getFileDescriptor(), options, targetSize, mType); - - if (jc.isCancelled() || bitmap == null) { - return null; - } - - if (mType == MediaItem.TYPE_MICROTHUMBNAIL) { - bitmap = BitmapUtils.resizeAndCropCenter(bitmap, targetSize, true); - } else { - bitmap = BitmapUtils.resizeDownBySideLength(bitmap, targetSize, true); - } - return bitmap; - } - } - - @Override - public int getSupportedOperations() { - int supported = SUPPORT_EDIT | SUPPORT_SETAS; - if (isSharable()) supported |= SUPPORT_SHARE; - if (BitmapUtils.isSupportedByRegionDecoder(mContentType)) { - supported |= SUPPORT_FULL_IMAGE; - } - return supported; - } - - @Override - public void getPanoramaSupport(PanoramaSupportCallback callback) { - mPanoramaMetadata.getPanoramaSupport(mApplication, callback); - } - - @Override - public void clearCachedPanoramaSupport() { - mPanoramaMetadata.clearCachedValues(); - } - - private boolean isSharable() { - // We cannot grant read permission to the receiver since we put - // the data URI in EXTRA_STREAM instead of the data part of an intent - // And there are issues in MediaUploader and Bluetooth file sender to - // share a general image data. So, we only share for local file. - return ContentResolver.SCHEME_FILE.equals(mUri.getScheme()); - } - - @Override - public int getMediaType() { - return MEDIA_TYPE_IMAGE; - } - - @Override - public Uri getContentUri() { - return mUri; - } - - @Override - public MediaDetails getDetails() { - MediaDetails details = super.getDetails(); - if (mWidth != 0 && mHeight != 0) { - details.addDetail(MediaDetails.INDEX_WIDTH, mWidth); - details.addDetail(MediaDetails.INDEX_HEIGHT, mHeight); - } - if (mContentType != null) { - details.addDetail(MediaDetails.INDEX_MIMETYPE, mContentType); - } - if (ContentResolver.SCHEME_FILE.equals(mUri.getScheme())) { - String filePath = mUri.getPath(); - details.addDetail(MediaDetails.INDEX_PATH, filePath); - MediaDetails.extractExifInfo(details, filePath); - } - return details; - } - - @Override - public String getMimeType() { - return mContentType; - } - - @Override - protected void finalize() throws Throwable { - try { - if (mFileDescriptor != null) { - Utils.closeSilently(mFileDescriptor); - } - } finally { - super.finalize(); - } - } - - @Override - public int getWidth() { - return 0; - } - - @Override - public int getHeight() { - return 0; - } - - @Override - public int getRotation() { - return mRotation; - } -} diff --git a/src/com/android/gallery3d/data/UriSource.java b/src/com/android/gallery3d/data/UriSource.java deleted file mode 100644 index f66bacd7b..000000000 --- a/src/com/android/gallery3d/data/UriSource.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * 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.gallery3d.data; - -import android.content.ContentResolver; -import android.net.Uri; -import android.webkit.MimeTypeMap; - -import com.android.gallery3d.app.GalleryApp; - -import java.io.UnsupportedEncodingException; -import java.net.URLDecoder; -import java.net.URLEncoder; - -class UriSource extends MediaSource { - @SuppressWarnings("unused") - private static final String TAG = "UriSource"; - private static final String IMAGE_TYPE_PREFIX = "image/"; - private static final String IMAGE_TYPE_ANY = "image/*"; - private static final String CHARSET_UTF_8 = "utf-8"; - - private GalleryApp mApplication; - - public UriSource(GalleryApp context) { - super("uri"); - mApplication = context; - } - - @Override - public MediaObject createMediaObject(Path path) { - String segment[] = path.split(); - if (segment.length != 3) { - throw new RuntimeException("bad path: " + path); - } - try { - String uri = URLDecoder.decode(segment[1], CHARSET_UTF_8); - String type = URLDecoder.decode(segment[2], CHARSET_UTF_8); - return new UriImage(mApplication, path, Uri.parse(uri), type); - } catch (UnsupportedEncodingException e) { - throw new AssertionError(e); - } - } - - private String getMimeType(Uri uri) { - if (ContentResolver.SCHEME_FILE.equals(uri.getScheme())) { - String extension = - MimeTypeMap.getFileExtensionFromUrl(uri.toString()); - String type = MimeTypeMap.getSingleton() - .getMimeTypeFromExtension(extension.toLowerCase()); - if (type != null) return type; - } - // Assume the type is image if the type cannot be resolved - // This could happen for "http" URI. - String type = mApplication.getContentResolver().getType(uri); - if (type == null) type = "image/*"; - return type; - } - - @Override - public Path findPathByUri(Uri uri, String type) { - String mimeType = getMimeType(uri); - - // Try to find a most specific type but it has to be started with "image/" - if ((type == null) || (IMAGE_TYPE_ANY.equals(type) - && mimeType.startsWith(IMAGE_TYPE_PREFIX))) { - type = mimeType; - } - - if (type.startsWith(IMAGE_TYPE_PREFIX)) { - try { - return Path.fromString("/uri/" - + URLEncoder.encode(uri.toString(), CHARSET_UTF_8) - + "/" +URLEncoder.encode(type, CHARSET_UTF_8)); - } catch (UnsupportedEncodingException e) { - throw new AssertionError(e); - } - } - // We have no clues that it is an image - return null; - } -} diff --git a/src/com/android/gallery3d/filtershow/CenteredLinearLayout.java b/src/com/android/gallery3d/filtershow/CenteredLinearLayout.java deleted file mode 100644 index bc9342d6f..000000000 --- a/src/com/android/gallery3d/filtershow/CenteredLinearLayout.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * 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. - */ - -package com.android.gallery3d.filtershow; - -import android.content.Context; -import android.content.res.Resources; -import android.content.res.TypedArray; -import android.util.AttributeSet; -import android.util.TypedValue; -import android.widget.LinearLayout; - -import com.android.gallery3d.R; - -public class CenteredLinearLayout extends LinearLayout { - private final int mMaxWidth; - - public CenteredLinearLayout(Context context, AttributeSet attrs) { - super(context, attrs); - TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.CenteredLinearLayout); - mMaxWidth = a.getDimensionPixelSize(R.styleable.CenteredLinearLayout_max_width, 0); - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - int parentWidth = MeasureSpec.getSize(widthMeasureSpec); - int parentHeight = MeasureSpec.getSize(heightMeasureSpec); - Resources r = getContext().getResources(); - float value = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, parentWidth, - r.getDisplayMetrics()); - if (mMaxWidth > 0 && parentWidth > mMaxWidth) { - int measureMode = MeasureSpec.getMode(widthMeasureSpec); - widthMeasureSpec = MeasureSpec.makeMeasureSpec(mMaxWidth, measureMode); - } - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - } - -} diff --git a/src/com/android/gallery3d/filtershow/EditorPlaceHolder.java b/src/com/android/gallery3d/filtershow/EditorPlaceHolder.java deleted file mode 100644 index 95abce114..000000000 --- a/src/com/android/gallery3d/filtershow/EditorPlaceHolder.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.android.gallery3d.filtershow; - -import android.view.View; -import android.view.ViewParent; -import android.widget.FrameLayout; - -import com.android.gallery3d.filtershow.cache.ImageLoader; -import com.android.gallery3d.filtershow.editors.Editor; -import com.android.gallery3d.filtershow.imageshow.ImageShow; - -import java.util.HashMap; -import java.util.Vector; - -public class EditorPlaceHolder { - private static final String LOGTAG = "EditorPlaceHolder"; - - private FilterShowActivity mActivity = null; - private FrameLayout mContainer = null; - private HashMap mEditors = new HashMap(); - private Vector mOldViews = new Vector(); - - public EditorPlaceHolder(FilterShowActivity activity) { - mActivity = activity; - } - - public void setContainer(FrameLayout container) { - mContainer = container; - } - - public void addEditor(Editor c) { - mEditors.put(c.getID(), c); - } - - public boolean contains(int type) { - if (mEditors.get(type) != null) { - return true; - } - return false; - } - - public Editor showEditor(int type) { - Editor editor = mEditors.get(type); - if (editor == null) { - return null; - } - - editor.createEditor(mActivity, mContainer); - editor.getImageShow().bindAsImageLoadListener(); - mContainer.setVisibility(View.VISIBLE); - mContainer.removeAllViews(); - View eview = editor.getTopLevelView(); - ViewParent parent = eview.getParent(); - - if (parent != null && parent instanceof FrameLayout) { - ((FrameLayout) parent).removeAllViews(); - } - - mContainer.addView(eview); - hideOldViews(); - editor.setVisibility(View.VISIBLE); - return editor; - } - - public void setOldViews(Vector views) { - mOldViews = views; - } - - public void hide() { - mContainer.setVisibility(View.GONE); - } - - public void hideOldViews() { - for (View view : mOldViews) { - view.setVisibility(View.GONE); - } - } - - public Editor getEditor(int editorId) { - return mEditors.get(editorId); - } - -} diff --git a/src/com/android/gallery3d/filtershow/FilterShowActivity.java b/src/com/android/gallery3d/filtershow/FilterShowActivity.java deleted file mode 100644 index 4700fccfe..000000000 --- a/src/com/android/gallery3d/filtershow/FilterShowActivity.java +++ /dev/null @@ -1,1121 +0,0 @@ -/* - * 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. - */ - -package com.android.gallery3d.filtershow; - -import android.app.ActionBar; -import android.app.AlertDialog; -import android.app.ProgressDialog; -import android.content.ComponentName; -import android.content.ContentValues; -import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; -import android.content.ServiceConnection; -import android.content.pm.ActivityInfo; -import android.content.res.Configuration; -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.graphics.Rect; -import android.graphics.drawable.Drawable; -import android.net.Uri; -import android.os.AsyncTask; -import android.os.Bundle; -import android.os.Handler; -import android.os.IBinder; -import android.support.v4.app.DialogFragment; -import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentActivity; -import android.support.v4.app.FragmentTransaction; -import android.util.DisplayMetrics; -import android.util.Log; -import android.util.TypedValue; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.ViewPropertyAnimator; -import android.view.WindowManager; -import android.widget.AdapterView; -import android.widget.AdapterView.OnItemClickListener; -import android.widget.FrameLayout; -import android.widget.ShareActionProvider; -import android.widget.ShareActionProvider.OnShareTargetSelectedListener; -import android.widget.Toast; - -import com.android.gallery3d.R; -import com.android.gallery3d.app.PhotoPage; -import com.android.gallery3d.data.LocalAlbum; -import com.android.gallery3d.filtershow.cache.ImageLoader; -import com.android.gallery3d.filtershow.category.Action; -import com.android.gallery3d.filtershow.category.CategoryAdapter; -import com.android.gallery3d.filtershow.category.MainPanel; -import com.android.gallery3d.filtershow.data.UserPresetsManager; -import com.android.gallery3d.filtershow.editors.BasicEditor; -import com.android.gallery3d.filtershow.editors.Editor; -import com.android.gallery3d.filtershow.editors.EditorChanSat; -import com.android.gallery3d.filtershow.editors.EditorCrop; -import com.android.gallery3d.filtershow.editors.EditorDraw; -import com.android.gallery3d.filtershow.editors.EditorGrad; -import com.android.gallery3d.filtershow.editors.EditorManager; -import com.android.gallery3d.filtershow.editors.EditorMirror; -import com.android.gallery3d.filtershow.editors.EditorPanel; -import com.android.gallery3d.filtershow.editors.EditorRedEye; -import com.android.gallery3d.filtershow.editors.EditorRotate; -import com.android.gallery3d.filtershow.editors.EditorStraighten; -import com.android.gallery3d.filtershow.editors.EditorTinyPlanet; -import com.android.gallery3d.filtershow.editors.ImageOnlyEditor; -import com.android.gallery3d.filtershow.filters.FilterRepresentation; -import com.android.gallery3d.filtershow.filters.FilterUserPresetRepresentation; -import com.android.gallery3d.filtershow.filters.FiltersManager; -import com.android.gallery3d.filtershow.filters.ImageFilter; -import com.android.gallery3d.filtershow.history.HistoryItem; -import com.android.gallery3d.filtershow.history.HistoryManager; -import com.android.gallery3d.filtershow.imageshow.ImageShow; -import com.android.gallery3d.filtershow.imageshow.MasterImage; -import com.android.gallery3d.filtershow.imageshow.Spline; -import com.android.gallery3d.filtershow.pipeline.CachingPipeline; -import com.android.gallery3d.filtershow.pipeline.ImagePreset; -import com.android.gallery3d.filtershow.pipeline.ProcessingService; -import com.android.gallery3d.filtershow.presets.PresetManagementDialog; -import com.android.gallery3d.filtershow.presets.UserPresetsAdapter; -import com.android.gallery3d.filtershow.provider.SharedImageProvider; -import com.android.gallery3d.filtershow.state.StateAdapter; -import com.android.gallery3d.filtershow.tools.SaveImage; -import com.android.gallery3d.filtershow.tools.XmpPresets; -import com.android.gallery3d.filtershow.tools.XmpPresets.XMresults; -import com.android.gallery3d.filtershow.ui.ExportDialog; -import com.android.gallery3d.filtershow.ui.FramedTextButton; -import com.android.gallery3d.util.GalleryUtils; -import com.android.gallery3d.util.UsageStatistics; -import com.android.photos.data.GalleryBitmapPool; - -import java.io.File; -import java.lang.ref.WeakReference; -import java.util.ArrayList; -import java.util.Vector; - -public class FilterShowActivity extends FragmentActivity implements OnItemClickListener, - OnShareTargetSelectedListener { - - private String mAction = ""; - MasterImage mMasterImage = null; - - private static final long LIMIT_SUPPORTS_HIGHRES = 134217728; // 128Mb - - public static final String TINY_PLANET_ACTION = "com.android.camera.action.TINY_PLANET"; - public static final String LAUNCH_FULLSCREEN = "launch-fullscreen"; - private ImageShow mImageShow = null; - - private View mSaveButton = null; - - private EditorPlaceHolder mEditorPlaceHolder = new EditorPlaceHolder(this); - - private static final int SELECT_PICTURE = 1; - private static final String LOGTAG = "FilterShowActivity"; - - private boolean mShowingTinyPlanet = false; - private boolean mShowingImageStatePanel = false; - - private final Vector mImageViews = new Vector(); - - private ShareActionProvider mShareActionProvider; - private File mSharedOutputFile = null; - - private boolean mSharingImage = false; - - private WeakReference mSavingProgressDialog; - - private LoadBitmapTask mLoadBitmapTask; - - private Uri mOriginalImageUri = null; - private ImagePreset mOriginalPreset = null; - - private Uri mSelectedImageUri = null; - - private UserPresetsManager mUserPresetsManager = null; - private UserPresetsAdapter mUserPresetsAdapter = null; - private CategoryAdapter mCategoryLooksAdapter = null; - private CategoryAdapter mCategoryBordersAdapter = null; - private CategoryAdapter mCategoryGeometryAdapter = null; - private CategoryAdapter mCategoryFiltersAdapter = null; - private int mCurrentPanel = MainPanel.LOOKS; - - private ProcessingService mBoundService; - private boolean mIsBound = false; - - public ProcessingService getProcessingService() { - return mBoundService; - } - - public boolean isSimpleEditAction() { - return !PhotoPage.ACTION_NEXTGEN_EDIT.equalsIgnoreCase(mAction); - } - - private ServiceConnection mConnection = new ServiceConnection() { - public void onServiceConnected(ComponentName className, IBinder service) { - /* - * This is called when the connection with the service has been - * established, giving us the service object we can use to - * interact with the service. Because we have bound to a explicit - * service that we know is running in our own process, we can - * cast its IBinder to a concrete class and directly access it. - */ - mBoundService = ((ProcessingService.LocalBinder)service).getService(); - mBoundService.setFiltershowActivity(FilterShowActivity.this); - mBoundService.onStart(); - } - - public void onServiceDisconnected(ComponentName className) { - /* - * This is called when the connection with the service has been - * unexpectedly disconnected -- that is, its process crashed. - * Because it is running in our same process, we should never - * see this happen. - */ - mBoundService = null; - } - }; - - void doBindService() { - /* - * Establish a connection with the service. We use an explicit - * class name because we want a specific service implementation that - * we know will be running in our own process (and thus won't be - * supporting component replacement by other applications). - */ - bindService(new Intent(FilterShowActivity.this, ProcessingService.class), - mConnection, Context.BIND_AUTO_CREATE); - mIsBound = true; - } - - void doUnbindService() { - if (mIsBound) { - // Detach our existing connection. - unbindService(mConnection); - mIsBound = false; - } - } - - private void setupPipeline() { - doBindService(); - ImageFilter.setActivityForMemoryToasts(this); - mUserPresetsManager = new UserPresetsManager(this); - mUserPresetsAdapter = new UserPresetsAdapter(this); - mCategoryLooksAdapter = new CategoryAdapter(this); - } - - public void updateUIAfterServiceStarted() { - fillCategories(); - loadMainPanel(); - setDefaultPreset(); - extractXMPData(); - processIntent(); - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - boolean onlyUsePortrait = getResources().getBoolean(R.bool.only_use_portrait); - if (onlyUsePortrait) { - setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); - } - MasterImage.setMaster(mMasterImage); - - clearGalleryBitmapPool(); - setupPipeline(); - - setupMasterImage(); - setDefaultValues(); - fillEditors(); - - loadXML(); - UsageStatistics.onContentViewChanged(UsageStatistics.COMPONENT_EDITOR, "Main"); - UsageStatistics.onEvent(UsageStatistics.COMPONENT_EDITOR, - UsageStatistics.CATEGORY_LIFECYCLE, UsageStatistics.LIFECYCLE_START); - } - - public boolean isShowingImageStatePanel() { - return mShowingImageStatePanel; - } - - public void loadMainPanel() { - if (findViewById(R.id.main_panel_container) == null) { - return; - } - MainPanel panel = new MainPanel(); - FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); - transaction.replace(R.id.main_panel_container, panel, MainPanel.FRAGMENT_TAG); - transaction.commit(); - } - - public void loadEditorPanel(FilterRepresentation representation, - final Editor currentEditor) { - if (representation.getEditorId() == ImageOnlyEditor.ID) { - currentEditor.reflectCurrentFilter(); - return; - } - final int currentId = currentEditor.getID(); - Runnable showEditor = new Runnable() { - @Override - public void run() { - EditorPanel panel = new EditorPanel(); - panel.setEditor(currentId); - FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); - transaction.remove(getSupportFragmentManager().findFragmentByTag(MainPanel.FRAGMENT_TAG)); - transaction.replace(R.id.main_panel_container, panel, MainPanel.FRAGMENT_TAG); - transaction.commit(); - } - }; - Fragment main = getSupportFragmentManager().findFragmentByTag(MainPanel.FRAGMENT_TAG); - boolean doAnimation = false; - if (mShowingImageStatePanel - && getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) { - doAnimation = true; - } - if (doAnimation && main != null && main instanceof MainPanel) { - MainPanel mainPanel = (MainPanel) main; - View container = mainPanel.getView().findViewById(R.id.category_panel_container); - View bottom = mainPanel.getView().findViewById(R.id.bottom_panel); - int panelHeight = container.getHeight() + bottom.getHeight(); - ViewPropertyAnimator anim = mainPanel.getView().animate(); - anim.translationY(panelHeight).start(); - final Handler handler = new Handler(); - handler.postDelayed(showEditor, anim.getDuration()); - } else { - showEditor.run(); - } - } - - private void loadXML() { - setContentView(R.layout.filtershow_activity); - - ActionBar actionBar = getActionBar(); - actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM); - actionBar.setCustomView(R.layout.filtershow_actionbar); - - mSaveButton = actionBar.getCustomView(); - mSaveButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View view) { - saveImage(); - } - }); - - mImageShow = (ImageShow) findViewById(R.id.imageShow); - mImageViews.add(mImageShow); - - setupEditors(); - - mEditorPlaceHolder.hide(); - mImageShow.bindAsImageLoadListener(); - - setupStatePanel(); - } - - public void fillCategories() { - fillLooks(); - loadUserPresets(); - fillBorders(); - fillTools(); - fillEffects(); - } - - public void setupStatePanel() { - MasterImage.getImage().setHistoryManager(mMasterImage.getHistory()); - } - - private void fillEffects() { - FiltersManager filtersManager = FiltersManager.getManager(); - ArrayList filtersRepresentations = filtersManager.getEffects(); - mCategoryFiltersAdapter = new CategoryAdapter(this); - for (FilterRepresentation representation : filtersRepresentations) { - if (representation.getTextId() != 0) { - representation.setName(getString(representation.getTextId())); - } - mCategoryFiltersAdapter.add(new Action(this, representation)); - } - } - - private void fillTools() { - FiltersManager filtersManager = FiltersManager.getManager(); - ArrayList filtersRepresentations = filtersManager.getTools(); - mCategoryGeometryAdapter = new CategoryAdapter(this); - for (FilterRepresentation representation : filtersRepresentations) { - mCategoryGeometryAdapter.add(new Action(this, representation)); - } - } - - private void processIntent() { - Intent intent = getIntent(); - if (intent.getBooleanExtra(LAUNCH_FULLSCREEN, false)) { - getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); - } - - mAction = intent.getAction(); - mSelectedImageUri = intent.getData(); - Uri loadUri = mSelectedImageUri; - if (mOriginalImageUri != null) { - loadUri = mOriginalImageUri; - } - if (loadUri != null) { - startLoadBitmap(loadUri); - } else { - pickImage(); - } - } - - private void setupEditors() { - mEditorPlaceHolder.setContainer((FrameLayout) findViewById(R.id.editorContainer)); - EditorManager.addEditors(mEditorPlaceHolder); - mEditorPlaceHolder.setOldViews(mImageViews); - } - - private void fillEditors() { - mEditorPlaceHolder.addEditor(new EditorChanSat()); - mEditorPlaceHolder.addEditor(new EditorGrad()); - mEditorPlaceHolder.addEditor(new EditorDraw()); - mEditorPlaceHolder.addEditor(new BasicEditor()); - mEditorPlaceHolder.addEditor(new ImageOnlyEditor()); - mEditorPlaceHolder.addEditor(new EditorTinyPlanet()); - mEditorPlaceHolder.addEditor(new EditorRedEye()); - mEditorPlaceHolder.addEditor(new EditorCrop()); - mEditorPlaceHolder.addEditor(new EditorMirror()); - mEditorPlaceHolder.addEditor(new EditorRotate()); - mEditorPlaceHolder.addEditor(new EditorStraighten()); - } - - private void setDefaultValues() { - Resources res = getResources(); - - // TODO: get those values from XML. - FramedTextButton.setTextSize((int) getPixelsFromDip(14)); - FramedTextButton.setTrianglePadding((int) getPixelsFromDip(4)); - FramedTextButton.setTriangleSize((int) getPixelsFromDip(10)); - - Drawable curveHandle = res.getDrawable(R.drawable.camera_crop); - int curveHandleSize = (int) res.getDimension(R.dimen.crop_indicator_size); - Spline.setCurveHandle(curveHandle, curveHandleSize); - Spline.setCurveWidth((int) getPixelsFromDip(3)); - } - - private void startLoadBitmap(Uri uri) { - final View loading = findViewById(R.id.loading); - final View imageShow = findViewById(R.id.imageShow); - imageShow.setVisibility(View.INVISIBLE); - loading.setVisibility(View.VISIBLE); - mShowingTinyPlanet = false; - mLoadBitmapTask = new LoadBitmapTask(); - mLoadBitmapTask.execute(uri); - } - - private void fillBorders() { - FiltersManager filtersManager = FiltersManager.getManager(); - ArrayList borders = filtersManager.getBorders(); - - for (int i = 0; i < borders.size(); i++) { - FilterRepresentation filter = borders.get(i); - filter.setName(getString(R.string.borders)); - if (i == 0) { - filter.setName(getString(R.string.none)); - } - } - - mCategoryBordersAdapter = new CategoryAdapter(this); - for (FilterRepresentation representation : borders) { - if (representation.getTextId() != 0) { - representation.setName(getString(representation.getTextId())); - } - mCategoryBordersAdapter.add(new Action(this, representation, Action.FULL_VIEW)); - } - } - - public UserPresetsAdapter getUserPresetsAdapter() { - return mUserPresetsAdapter; - } - - public CategoryAdapter getCategoryLooksAdapter() { - return mCategoryLooksAdapter; - } - - public CategoryAdapter getCategoryBordersAdapter() { - return mCategoryBordersAdapter; - } - - public CategoryAdapter getCategoryGeometryAdapter() { - return mCategoryGeometryAdapter; - } - - public CategoryAdapter getCategoryFiltersAdapter() { - return mCategoryFiltersAdapter; - } - - public void removeFilterRepresentation(FilterRepresentation filterRepresentation) { - if (filterRepresentation == null) { - return; - } - ImagePreset oldPreset = MasterImage.getImage().getPreset(); - ImagePreset copy = new ImagePreset(oldPreset); - copy.removeFilter(filterRepresentation); - MasterImage.getImage().setPreset(copy, copy.getLastRepresentation(), true); - if (MasterImage.getImage().getCurrentFilterRepresentation() == filterRepresentation) { - FilterRepresentation lastRepresentation = copy.getLastRepresentation(); - MasterImage.getImage().setCurrentFilterRepresentation(lastRepresentation); - } - } - - public void useFilterRepresentation(FilterRepresentation filterRepresentation) { - if (filterRepresentation == null) { - return; - } - if (MasterImage.getImage().getCurrentFilterRepresentation() == filterRepresentation) { - return; - } - ImagePreset oldPreset = MasterImage.getImage().getPreset(); - ImagePreset copy = new ImagePreset(oldPreset); - FilterRepresentation representation = copy.getRepresentation(filterRepresentation); - if (representation == null) { - copy.addFilter(filterRepresentation); - } else if (filterRepresentation.getFilterType() == FilterRepresentation.TYPE_GEOMETRY) { - filterRepresentation = representation; - } else { - if (filterRepresentation.allowsSingleInstanceOnly()) { - // Don't just update the filter representation. Centralize the - // logic in the addFilter(), such that we can keep "None" as - // null. - copy.removeFilter(representation); - copy.addFilter(filterRepresentation); - } - } - MasterImage.getImage().setPreset(copy, filterRepresentation, true); - MasterImage.getImage().setCurrentFilterRepresentation(filterRepresentation); - } - - public void showRepresentation(FilterRepresentation representation) { - if (representation == null) { - return; - } - - useFilterRepresentation(representation); - - // show representation - Editor mCurrentEditor = mEditorPlaceHolder.showEditor(representation.getEditorId()); - loadEditorPanel(representation, mCurrentEditor); - } - - public Editor getEditor(int editorID) { - return mEditorPlaceHolder.getEditor(editorID); - } - - public void setCurrentPanel(int currentPanel) { - mCurrentPanel = currentPanel; - } - - public int getCurrentPanel() { - return mCurrentPanel; - } - - public void updateCategories() { - ImagePreset preset = mMasterImage.getPreset(); - mCategoryLooksAdapter.reflectImagePreset(preset); - mCategoryBordersAdapter.reflectImagePreset(preset); - } - - private class LoadHighresBitmapTask extends AsyncTask { - @Override - protected Boolean doInBackground(Void... params) { - MasterImage master = MasterImage.getImage(); - Rect originalBounds = master.getOriginalBounds(); - if (master.supportsHighRes()) { - int highresPreviewSize = master.getOriginalBitmapLarge().getWidth() * 2; - if (highresPreviewSize > originalBounds.width()) { - highresPreviewSize = originalBounds.width(); - } - Rect bounds = new Rect(); - Bitmap originalHires = ImageLoader.loadOrientedConstrainedBitmap(master.getUri(), - master.getActivity(), highresPreviewSize, - master.getOrientation(), bounds); - master.setOriginalBounds(bounds); - master.setOriginalBitmapHighres(originalHires); - mBoundService.setOriginalBitmapHighres(originalHires); - master.warnListeners(); - } - return true; - } - - @Override - protected void onPostExecute(Boolean result) { - Bitmap highresBitmap = MasterImage.getImage().getOriginalBitmapHighres(); - if (highresBitmap != null) { - float highResPreviewScale = (float) highresBitmap.getWidth() - / (float) MasterImage.getImage().getOriginalBounds().width(); - mBoundService.setHighresPreviewScaleFactor(highResPreviewScale); - } - } - } - - private class LoadBitmapTask extends AsyncTask { - int mBitmapSize; - - public LoadBitmapTask() { - mBitmapSize = getScreenImageSize(); - } - - @Override - protected Boolean doInBackground(Uri... params) { - if (!MasterImage.getImage().loadBitmap(params[0], mBitmapSize)) { - return false; - } - publishProgress(ImageLoader.queryLightCycle360(MasterImage.getImage().getActivity())); - return true; - } - - @Override - protected void onProgressUpdate(Boolean... values) { - super.onProgressUpdate(values); - if (isCancelled()) { - return; - } - if (values[0]) { - mShowingTinyPlanet = true; - } - } - - @Override - protected void onPostExecute(Boolean result) { - MasterImage.setMaster(mMasterImage); - if (isCancelled()) { - return; - } - - if (!result) { - cannotLoadImage(); - } - - if (null == CachingPipeline.getRenderScriptContext()){ - Log.v(LOGTAG,"RenderScript context destroyed during load"); - return; - } - final View loading = findViewById(R.id.loading); - loading.setVisibility(View.GONE); - final View imageShow = findViewById(R.id.imageShow); - imageShow.setVisibility(View.VISIBLE); - - Bitmap largeBitmap = MasterImage.getImage().getOriginalBitmapLarge(); - mBoundService.setOriginalBitmap(largeBitmap); - - float previewScale = (float) largeBitmap.getWidth() - / (float) MasterImage.getImage().getOriginalBounds().width(); - mBoundService.setPreviewScaleFactor(previewScale); - if (!mShowingTinyPlanet) { - mCategoryFiltersAdapter.removeTinyPlanet(); - } - mCategoryLooksAdapter.imageLoaded(); - mCategoryBordersAdapter.imageLoaded(); - mCategoryGeometryAdapter.imageLoaded(); - mCategoryFiltersAdapter.imageLoaded(); - mLoadBitmapTask = null; - - if (mOriginalPreset != null) { - MasterImage.getImage().setLoadedPreset(mOriginalPreset); - MasterImage.getImage().setPreset(mOriginalPreset, - mOriginalPreset.getLastRepresentation(), true); - mOriginalPreset = null; - } - - if (mAction == TINY_PLANET_ACTION) { - showRepresentation(mCategoryFiltersAdapter.getTinyPlanet()); - } - LoadHighresBitmapTask highresLoad = new LoadHighresBitmapTask(); - highresLoad.execute(); - super.onPostExecute(result); - } - - } - - private void clearGalleryBitmapPool() { - (new AsyncTask() { - @Override - protected Void doInBackground(Void... params) { - // Free memory held in Gallery's Bitmap pool. May be O(n) for n bitmaps. - GalleryBitmapPool.getInstance().clear(); - return null; - } - }).execute(); - } - - @Override - protected void onDestroy() { - if (mLoadBitmapTask != null) { - mLoadBitmapTask.cancel(false); - } - mUserPresetsManager.close(); - doUnbindService(); - super.onDestroy(); - } - - // TODO: find a more robust way of handling image size selection - // for high screen densities. - private int getScreenImageSize() { - DisplayMetrics outMetrics = new DisplayMetrics(); - getWindowManager().getDefaultDisplay().getMetrics(outMetrics); - return (int) Math.max(outMetrics.heightPixels, outMetrics.widthPixels); - } - - private void showSavingProgress(String albumName) { - ProgressDialog progress; - if (mSavingProgressDialog != null) { - progress = mSavingProgressDialog.get(); - if (progress != null) { - progress.show(); - return; - } - } - // TODO: Allow cancellation of the saving process - String progressText; - if (albumName == null) { - progressText = getString(R.string.saving_image); - } else { - progressText = getString(R.string.filtershow_saving_image, albumName); - } - progress = ProgressDialog.show(this, "", progressText, true, false); - mSavingProgressDialog = new WeakReference(progress); - } - - private void hideSavingProgress() { - if (mSavingProgressDialog != null) { - ProgressDialog progress = mSavingProgressDialog.get(); - if (progress != null) - progress.dismiss(); - } - } - - public void completeSaveImage(Uri saveUri) { - if (mSharingImage && mSharedOutputFile != null) { - // Image saved, we unblock the content provider - Uri uri = Uri.withAppendedPath(SharedImageProvider.CONTENT_URI, - Uri.encode(mSharedOutputFile.getAbsolutePath())); - ContentValues values = new ContentValues(); - values.put(SharedImageProvider.PREPARE, false); - getContentResolver().insert(uri, values); - } - setResult(RESULT_OK, new Intent().setData(saveUri)); - hideSavingProgress(); - finish(); - } - - @Override - public boolean onShareTargetSelected(ShareActionProvider arg0, Intent arg1) { - // First, let's tell the SharedImageProvider that it will need to wait - // for the image - Uri uri = Uri.withAppendedPath(SharedImageProvider.CONTENT_URI, - Uri.encode(mSharedOutputFile.getAbsolutePath())); - ContentValues values = new ContentValues(); - values.put(SharedImageProvider.PREPARE, true); - getContentResolver().insert(uri, values); - mSharingImage = true; - - // Process and save the image in the background. - showSavingProgress(null); - mImageShow.saveImage(this, mSharedOutputFile); - return true; - } - - private Intent getDefaultShareIntent() { - Intent intent = new Intent(Intent.ACTION_SEND); - intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - intent.setType(SharedImageProvider.MIME_TYPE); - mSharedOutputFile = SaveImage.getNewFile(this, MasterImage.getImage().getUri()); - Uri uri = Uri.withAppendedPath(SharedImageProvider.CONTENT_URI, - Uri.encode(mSharedOutputFile.getAbsolutePath())); - intent.putExtra(Intent.EXTRA_STREAM, uri); - return intent; - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.filtershow_activity_menu, menu); - MenuItem showState = menu.findItem(R.id.showImageStateButton); - if (mShowingImageStatePanel) { - showState.setTitle(R.string.hide_imagestate_panel); - } else { - showState.setTitle(R.string.show_imagestate_panel); - } - mShareActionProvider = (ShareActionProvider) menu.findItem(R.id.menu_share) - .getActionProvider(); - mShareActionProvider.setShareIntent(getDefaultShareIntent()); - mShareActionProvider.setOnShareTargetSelectedListener(this); - - MenuItem undoItem = menu.findItem(R.id.undoButton); - MenuItem redoItem = menu.findItem(R.id.redoButton); - MenuItem resetItem = menu.findItem(R.id.resetHistoryButton); - mMasterImage.getHistory().setMenuItems(undoItem, redoItem, resetItem); - return true; - } - - @Override - public void onPause() { - super.onPause(); - if (mShareActionProvider != null) { - mShareActionProvider.setOnShareTargetSelectedListener(null); - } - } - - @Override - public void onResume() { - super.onResume(); - if (mShareActionProvider != null) { - mShareActionProvider.setOnShareTargetSelectedListener(this); - } - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case R.id.undoButton: { - HistoryManager adapter = mMasterImage.getHistory(); - int position = adapter.undo(); - mMasterImage.onHistoryItemClick(position); - backToMain(); - invalidateViews(); - UsageStatistics.onEvent(UsageStatistics.COMPONENT_EDITOR, - UsageStatistics.CATEGORY_BUTTON_PRESS, "Undo"); - return true; - } - case R.id.redoButton: { - HistoryManager adapter = mMasterImage.getHistory(); - int position = adapter.redo(); - mMasterImage.onHistoryItemClick(position); - invalidateViews(); - UsageStatistics.onEvent(UsageStatistics.COMPONENT_EDITOR, - UsageStatistics.CATEGORY_BUTTON_PRESS, "Redo"); - return true; - } - case R.id.resetHistoryButton: { - resetHistory(); - UsageStatistics.onEvent(UsageStatistics.COMPONENT_EDITOR, - UsageStatistics.CATEGORY_BUTTON_PRESS, "ResetHistory"); - return true; - } - case R.id.showImageStateButton: { - toggleImageStatePanel(); - UsageStatistics.onEvent(UsageStatistics.COMPONENT_EDITOR, - UsageStatistics.CATEGORY_BUTTON_PRESS, - mShowingImageStatePanel ? "ShowPanel" : "HidePanel"); - return true; - } - case R.id.exportFlattenButton: { - showExportOptionsDialog(); - return true; - } - case android.R.id.home: { - saveImage(); - return true; - } - case R.id.manageUserPresets: { - manageUserPresets(); - return true; - } - } - return false; - } - - private void manageUserPresets() { - DialogFragment dialog = new PresetManagementDialog(); - dialog.show(getSupportFragmentManager(), "NoticeDialogFragment"); - } - - private void showExportOptionsDialog() { - DialogFragment dialog = new ExportDialog(); - dialog.show(getSupportFragmentManager(), "ExportDialogFragment"); - } - - public void updateUserPresetsFromAdapter(UserPresetsAdapter adapter) { - ArrayList representations = - adapter.getDeletedRepresentations(); - for (FilterUserPresetRepresentation representation : representations) { - deletePreset(representation.getId()); - } - ArrayList changedRepresentations = - adapter.getChangedRepresentations(); - for (FilterUserPresetRepresentation representation : changedRepresentations) { - updatePreset(representation); - } - adapter.clearDeletedRepresentations(); - adapter.clearChangedRepresentations(); - loadUserPresets(); - } - - public void loadUserPresets() { - mUserPresetsManager.load(); - } - - public void updateUserPresetsFromManager() { - ArrayList presets = mUserPresetsManager.getRepresentations(); - if (presets == null) { - return; - } - if (mCategoryLooksAdapter != null) { - fillLooks(); - } - mUserPresetsAdapter.clear(); - for (int i = 0; i < presets.size(); i++) { - FilterUserPresetRepresentation representation = presets.get(i); - mCategoryLooksAdapter.add( - new Action(this, representation, Action.FULL_VIEW)); - mUserPresetsAdapter.add(new Action(this, representation, Action.FULL_VIEW)); - } - mCategoryLooksAdapter.notifyDataSetInvalidated(); - - } - - public void saveCurrentImagePreset() { - mUserPresetsManager.save(MasterImage.getImage().getPreset()); - } - - private void deletePreset(int id) { - mUserPresetsManager.delete(id); - } - - private void updatePreset(FilterUserPresetRepresentation representation) { - mUserPresetsManager.update(representation); - } - - public void enableSave(boolean enable) { - if (mSaveButton != null) { - mSaveButton.setEnabled(enable); - } - } - - private void fillLooks() { - FiltersManager filtersManager = FiltersManager.getManager(); - ArrayList filtersRepresentations = filtersManager.getLooks(); - - mCategoryLooksAdapter.clear(); - int verticalItemHeight = (int) getResources().getDimension(R.dimen.action_item_height); - mCategoryLooksAdapter.setItemHeight(verticalItemHeight); - for (FilterRepresentation representation : filtersRepresentations) { - mCategoryLooksAdapter.add(new Action(this, representation, Action.FULL_VIEW)); - } - } - - public void setDefaultPreset() { - // Default preset (original) - ImagePreset preset = new ImagePreset(); // empty - mMasterImage.setPreset(preset, preset.getLastRepresentation(), true); - } - - // ////////////////////////////////////////////////////////////////////////////// - // Some utility functions - // TODO: finish the cleanup. - - public void invalidateViews() { - for (ImageShow views : mImageViews) { - views.updateImage(); - } - } - - public void hideImageViews() { - for (View view : mImageViews) { - view.setVisibility(View.GONE); - } - mEditorPlaceHolder.hide(); - } - - // ////////////////////////////////////////////////////////////////////////////// - // imageState panel... - - public void toggleImageStatePanel() { - invalidateOptionsMenu(); - mShowingImageStatePanel = !mShowingImageStatePanel; - Fragment panel = getSupportFragmentManager().findFragmentByTag(MainPanel.FRAGMENT_TAG); - if (panel != null) { - if (panel instanceof EditorPanel) { - EditorPanel editorPanel = (EditorPanel) panel; - editorPanel.showImageStatePanel(mShowingImageStatePanel); - } else if (panel instanceof MainPanel) { - MainPanel mainPanel = (MainPanel) panel; - mainPanel.showImageStatePanel(mShowingImageStatePanel); - } - } - } - - @Override - public void onConfigurationChanged(Configuration newConfig) - { - super.onConfigurationChanged(newConfig); - setDefaultValues(); - loadXML(); - fillCategories(); - loadMainPanel(); - - // mLoadBitmapTask==null implies you have looked at the intent - if (!mShowingTinyPlanet && (mLoadBitmapTask == null)) { - mCategoryFiltersAdapter.removeTinyPlanet(); - } - final View loading = findViewById(R.id.loading); - loading.setVisibility(View.GONE); - } - - public void setupMasterImage() { - - HistoryManager historyManager = new HistoryManager(); - StateAdapter imageStateAdapter = new StateAdapter(this, 0); - MasterImage.reset(); - mMasterImage = MasterImage.getImage(); - mMasterImage.setHistoryManager(historyManager); - mMasterImage.setStateAdapter(imageStateAdapter); - mMasterImage.setActivity(this); - - if (Runtime.getRuntime().maxMemory() > LIMIT_SUPPORTS_HIGHRES) { - mMasterImage.setSupportsHighRes(true); - } else { - mMasterImage.setSupportsHighRes(false); - } - } - - void resetHistory() { - HistoryManager adapter = mMasterImage.getHistory(); - adapter.reset(); - HistoryItem historyItem = adapter.getItem(0); - ImagePreset original = new ImagePreset(historyItem.getImagePreset()); - mMasterImage.setPreset(original, historyItem.getFilterRepresentation(), true); - invalidateViews(); - backToMain(); - } - - public void showDefaultImageView() { - mEditorPlaceHolder.hide(); - mImageShow.setVisibility(View.VISIBLE); - MasterImage.getImage().setCurrentFilter(null); - MasterImage.getImage().setCurrentFilterRepresentation(null); - } - - public void backToMain() { - Fragment currentPanel = getSupportFragmentManager().findFragmentByTag(MainPanel.FRAGMENT_TAG); - if (currentPanel instanceof MainPanel) { - return; - } - loadMainPanel(); - showDefaultImageView(); - } - - @Override - public void onBackPressed() { - Fragment currentPanel = getSupportFragmentManager().findFragmentByTag(MainPanel.FRAGMENT_TAG); - if (currentPanel instanceof MainPanel) { - if (!mImageShow.hasModifications()) { - done(); - } else { - AlertDialog.Builder builder = new AlertDialog.Builder(this); - builder.setMessage(R.string.unsaved).setTitle(R.string.save_before_exit); - builder.setPositiveButton(R.string.save_and_exit, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int id) { - saveImage(); - } - }); - builder.setNegativeButton(R.string.exit, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int id) { - done(); - } - }); - builder.show(); - } - } else { - backToMain(); - } - } - - public void cannotLoadImage() { - Toast.makeText(this, R.string.cannot_load_image, Toast.LENGTH_SHORT).show(); - finish(); - } - - // ////////////////////////////////////////////////////////////////////////////// - - public float getPixelsFromDip(float value) { - Resources r = getResources(); - return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, value, - r.getDisplayMetrics()); - } - - @Override - public void onItemClick(AdapterView parent, View view, int position, - long id) { - mMasterImage.onHistoryItemClick(position); - invalidateViews(); - } - - public void pickImage() { - Intent intent = new Intent(); - intent.setType("image/*"); - intent.setAction(Intent.ACTION_GET_CONTENT); - startActivityForResult(Intent.createChooser(intent, getString(R.string.select_image)), - SELECT_PICTURE); - } - - @Override - public void onActivityResult(int requestCode, int resultCode, Intent data) { - if (resultCode == RESULT_OK) { - if (requestCode == SELECT_PICTURE) { - Uri selectedImageUri = data.getData(); - startLoadBitmap(selectedImageUri); - } - } - } - - - public void saveImage() { - if (mImageShow.hasModifications()) { - // Get the name of the album, to which the image will be saved - File saveDir = SaveImage.getFinalSaveDirectory(this, mSelectedImageUri); - int bucketId = GalleryUtils.getBucketId(saveDir.getPath()); - String albumName = LocalAlbum.getLocalizedName(getResources(), bucketId, null); - showSavingProgress(albumName); - mImageShow.saveImage(this, null); - } else { - done(); - } - } - - - public void done() { - hideSavingProgress(); - if (mLoadBitmapTask != null) { - mLoadBitmapTask.cancel(false); - } - finish(); - } - - private void extractXMPData() { - XMresults res = XmpPresets.extractXMPData( - getBaseContext(), mMasterImage, getIntent().getData()); - if (res == null) - return; - - mOriginalImageUri = res.originalimage; - mOriginalPreset = res.preset; - } - - public Uri getSelectedImageUri() { - return mSelectedImageUri; - } - -} diff --git a/src/com/android/gallery3d/filtershow/cache/ImageLoader.java b/src/com/android/gallery3d/filtershow/cache/ImageLoader.java deleted file mode 100644 index b6c72fd9d..000000000 --- a/src/com/android/gallery3d/filtershow/cache/ImageLoader.java +++ /dev/null @@ -1,502 +0,0 @@ -/* - * 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. - */ - -package com.android.gallery3d.filtershow.cache; - -import android.content.ContentResolver; -import android.content.Context; -import android.content.Intent; -import android.content.res.Resources; -import android.database.Cursor; -import android.database.sqlite.SQLiteException; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.BitmapRegionDecoder; -import android.graphics.Matrix; -import android.graphics.Rect; -import android.net.Uri; -import android.provider.MediaStore; -import android.util.Log; -import android.webkit.MimeTypeMap; - -import com.adobe.xmp.XMPException; -import com.adobe.xmp.XMPMeta; -import com.android.gallery3d.R; -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.exif.ExifInterface; -import com.android.gallery3d.filtershow.imageshow.MasterImage; -import com.android.gallery3d.util.XmpUtilHelper; - -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; - -public final class ImageLoader { - - private static final String LOGTAG = "ImageLoader"; - - public static final String JPEG_MIME_TYPE = "image/jpeg"; - public static final int DEFAULT_COMPRESS_QUALITY = 95; - - public static final int ORI_NORMAL = ExifInterface.Orientation.TOP_LEFT; - public static final int ORI_ROTATE_90 = ExifInterface.Orientation.RIGHT_TOP; - public static final int ORI_ROTATE_180 = ExifInterface.Orientation.BOTTOM_LEFT; - public static final int ORI_ROTATE_270 = ExifInterface.Orientation.RIGHT_BOTTOM; - public static final int ORI_FLIP_HOR = ExifInterface.Orientation.TOP_RIGHT; - public static final int ORI_FLIP_VERT = ExifInterface.Orientation.BOTTOM_RIGHT; - public static final int ORI_TRANSPOSE = ExifInterface.Orientation.LEFT_TOP; - public static final int ORI_TRANSVERSE = ExifInterface.Orientation.LEFT_BOTTOM; - - private static final int BITMAP_LOAD_BACKOUT_ATTEMPTS = 5; - - private ImageLoader() {} - - /** - * Returns the Mime type for a Url. Safe to use with Urls that do not - * come from Gallery's content provider. - */ - public static String getMimeType(Uri src) { - String postfix = MimeTypeMap.getFileExtensionFromUrl(src.toString()); - String ret = null; - if (postfix != null) { - ret = MimeTypeMap.getSingleton().getMimeTypeFromExtension(postfix); - } - return ret; - } - - /** - * Returns the image's orientation flag. Defaults to ORI_NORMAL if no valid - * orientation was found. - */ - public static int getMetadataOrientation(Context context, Uri uri) { - if (uri == null || context == null) { - throw new IllegalArgumentException("bad argument to getOrientation"); - } - - // First try to find orientation data in Gallery's ContentProvider. - Cursor cursor = null; - try { - cursor = context.getContentResolver().query(uri, - new String[] { MediaStore.Images.ImageColumns.ORIENTATION }, - null, null, null); - if (cursor != null && cursor.moveToNext()) { - int ori = cursor.getInt(0); - switch (ori) { - case 90: - return ORI_ROTATE_90; - case 270: - return ORI_ROTATE_270; - case 180: - return ORI_ROTATE_180; - default: - return ORI_NORMAL; - } - } - } catch (SQLiteException e) { - // Do nothing - } catch (IllegalArgumentException e) { - // Do nothing - } finally { - Utils.closeSilently(cursor); - } - - // Fall back to checking EXIF tags in file. - if (ContentResolver.SCHEME_FILE.equals(uri.getScheme())) { - String mimeType = getMimeType(uri); - if (!JPEG_MIME_TYPE.equals(mimeType)) { - return ORI_NORMAL; - } - String path = uri.getPath(); - ExifInterface exif = new ExifInterface(); - try { - exif.readExif(path); - Integer tagval = exif.getTagIntValue(ExifInterface.TAG_ORIENTATION); - if (tagval != null) { - int orientation = tagval; - switch(orientation) { - case ORI_NORMAL: - case ORI_ROTATE_90: - case ORI_ROTATE_180: - case ORI_ROTATE_270: - case ORI_FLIP_HOR: - case ORI_FLIP_VERT: - case ORI_TRANSPOSE: - case ORI_TRANSVERSE: - return orientation; - default: - return ORI_NORMAL; - } - } - } catch (IOException e) { - Log.w(LOGTAG, "Failed to read EXIF orientation", e); - } - } - return ORI_NORMAL; - } - - /** - * Returns the rotation of image at the given URI as one of 0, 90, 180, - * 270. Defaults to 0. - */ - public static int getMetadataRotation(Context context, Uri uri) { - int orientation = getMetadataOrientation(context, uri); - switch(orientation) { - case ORI_ROTATE_90: - return 90; - case ORI_ROTATE_180: - return 180; - case ORI_ROTATE_270: - return 270; - default: - return 0; - } - } - - /** - * Takes an orientation and a bitmap, and returns the bitmap transformed - * to that orientation. - */ - public static Bitmap orientBitmap(Bitmap bitmap, int ori) { - Matrix matrix = new Matrix(); - int w = bitmap.getWidth(); - int h = bitmap.getHeight(); - if (ori == ORI_ROTATE_90 || - ori == ORI_ROTATE_270 || - ori == ORI_TRANSPOSE || - ori == ORI_TRANSVERSE) { - int tmp = w; - w = h; - h = tmp; - } - switch (ori) { - case ORI_ROTATE_90: - matrix.setRotate(90, w / 2f, h / 2f); - break; - case ORI_ROTATE_180: - matrix.setRotate(180, w / 2f, h / 2f); - break; - case ORI_ROTATE_270: - matrix.setRotate(270, w / 2f, h / 2f); - break; - case ORI_FLIP_HOR: - matrix.preScale(-1, 1); - break; - case ORI_FLIP_VERT: - matrix.preScale(1, -1); - break; - case ORI_TRANSPOSE: - matrix.setRotate(90, w / 2f, h / 2f); - matrix.preScale(1, -1); - break; - case ORI_TRANSVERSE: - matrix.setRotate(270, w / 2f, h / 2f); - matrix.preScale(1, -1); - break; - case ORI_NORMAL: - default: - return bitmap; - } - return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), - bitmap.getHeight(), matrix, true); - } - - /** - * Returns the bitmap for the rectangular region given by "bounds" - * if it is a subset of the bitmap stored at uri. Otherwise returns - * null. - */ - public static Bitmap loadRegionBitmap(Context context, Uri uri, BitmapFactory.Options options, - Rect bounds) { - InputStream is = null; - try { - is = context.getContentResolver().openInputStream(uri); - BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(is, false); - Rect r = new Rect(0, 0, decoder.getWidth(), decoder.getHeight()); - // return null if bounds are not entirely within the bitmap - if (!r.contains(bounds)) { - return null; - } - return decoder.decodeRegion(bounds, options); - } catch (FileNotFoundException e) { - Log.e(LOGTAG, "FileNotFoundException for " + uri, e); - } catch (IOException e) { - Log.e(LOGTAG, "FileNotFoundException for " + uri, e); - } finally { - Utils.closeSilently(is); - } - return null; - } - - /** - * Returns the bounds of the bitmap stored at a given Url. - */ - public static Rect loadBitmapBounds(Context context, Uri uri) { - BitmapFactory.Options o = new BitmapFactory.Options(); - loadBitmap(context, uri, o); - return new Rect(0, 0, o.outWidth, o.outHeight); - } - - /** - * Loads a bitmap that has been downsampled using sampleSize from a given url. - */ - public static Bitmap loadDownsampledBitmap(Context context, Uri uri, int sampleSize) { - BitmapFactory.Options options = new BitmapFactory.Options(); - options.inMutable = true; - options.inSampleSize = sampleSize; - return loadBitmap(context, uri, options); - } - - - /** - * Returns the bitmap from the given uri loaded using the given options. - * Returns null on failure. - */ - public static Bitmap loadBitmap(Context context, Uri uri, BitmapFactory.Options o) { - if (uri == null || context == null) { - throw new IllegalArgumentException("bad argument to loadBitmap"); - } - InputStream is = null; - try { - is = context.getContentResolver().openInputStream(uri); - return BitmapFactory.decodeStream(is, null, o); - } catch (FileNotFoundException e) { - Log.e(LOGTAG, "FileNotFoundException for " + uri, e); - } finally { - Utils.closeSilently(is); - } - return null; - } - - /** - * Loads a bitmap at a given URI that is downsampled so that both sides are - * smaller than maxSideLength. The Bitmap's original dimensions are stored - * in the rect originalBounds. - * - * @param uri URI of image to open. - * @param context context whose ContentResolver to use. - * @param maxSideLength max side length of returned bitmap. - * @param originalBounds If not null, set to the actual bounds of the stored bitmap. - * @param useMin use min or max side of the original image - * @return downsampled bitmap or null if this operation failed. - */ - public static Bitmap loadConstrainedBitmap(Uri uri, Context context, int maxSideLength, - Rect originalBounds, boolean useMin) { - if (maxSideLength <= 0 || uri == null || context == null) { - throw new IllegalArgumentException("bad argument to getScaledBitmap"); - } - // Get width and height of stored bitmap - Rect storedBounds = loadBitmapBounds(context, uri); - if (originalBounds != null) { - originalBounds.set(storedBounds); - } - int w = storedBounds.width(); - int h = storedBounds.height(); - - // If bitmap cannot be decoded, return null - if (w <= 0 || h <= 0) { - return null; - } - - // Find best downsampling size - int imageSide = 0; - if (useMin) { - imageSide = Math.min(w, h); - } else { - imageSide = Math.max(w, h); - } - int sampleSize = 1; - while (imageSide > maxSideLength) { - imageSide >>>= 1; - sampleSize <<= 1; - } - - // Make sure sample size is reasonable - if (sampleSize <= 0 || - 0 >= (int) (Math.min(w, h) / sampleSize)) { - return null; - } - return loadDownsampledBitmap(context, uri, sampleSize); - } - - /** - * Loads a bitmap at a given URI that is downsampled so that both sides are - * smaller than maxSideLength. The Bitmap's original dimensions are stored - * in the rect originalBounds. The output is also transformed to the given - * orientation. - * - * @param uri URI of image to open. - * @param context context whose ContentResolver to use. - * @param maxSideLength max side length of returned bitmap. - * @param orientation the orientation to transform the bitmap to. - * @param originalBounds set to the actual bounds of the stored bitmap. - * @return downsampled bitmap or null if this operation failed. - */ - public static Bitmap loadOrientedConstrainedBitmap(Uri uri, Context context, int maxSideLength, - int orientation, Rect originalBounds) { - Bitmap bmap = loadConstrainedBitmap(uri, context, maxSideLength, originalBounds, false); - if (bmap != null) { - bmap = orientBitmap(bmap, orientation); - } - return bmap; - } - - public static Bitmap getScaleOneImageForPreset(Context context, Uri uri, Rect bounds, - Rect destination) { - BitmapFactory.Options options = new BitmapFactory.Options(); - options.inMutable = true; - if (destination != null) { - if (bounds.width() > destination.width()) { - int sampleSize = 1; - int w = bounds.width(); - while (w > destination.width()) { - sampleSize *= 2; - w /= sampleSize; - } - options.inSampleSize = sampleSize; - } - } - Bitmap bmp = loadRegionBitmap(context, uri, options, bounds); - return bmp; - } - - /** - * Loads a bitmap that is downsampled by at least the input sample size. In - * low-memory situations, the bitmap may be downsampled further. - */ - public static Bitmap loadBitmapWithBackouts(Context context, Uri sourceUri, int sampleSize) { - boolean noBitmap = true; - int num_tries = 0; - if (sampleSize <= 0) { - sampleSize = 1; - } - Bitmap bmap = null; - while (noBitmap) { - try { - // Try to decode, downsample if low-memory. - bmap = loadDownsampledBitmap(context, sourceUri, sampleSize); - noBitmap = false; - } catch (java.lang.OutOfMemoryError e) { - // Try with more downsampling before failing for good. - if (++num_tries >= BITMAP_LOAD_BACKOUT_ATTEMPTS) { - throw e; - } - bmap = null; - System.gc(); - sampleSize *= 2; - } - } - return bmap; - } - - /** - * Loads an oriented bitmap that is downsampled by at least the input sample - * size. In low-memory situations, the bitmap may be downsampled further. - */ - public static Bitmap loadOrientedBitmapWithBackouts(Context context, Uri sourceUri, - int sampleSize) { - Bitmap bitmap = loadBitmapWithBackouts(context, sourceUri, sampleSize); - if (bitmap == null) { - return null; - } - int orientation = getMetadataOrientation(context, sourceUri); - bitmap = orientBitmap(bitmap, orientation); - return bitmap; - } - - /** - * Loads bitmap from a resource that may be downsampled in low-memory situations. - */ - public static Bitmap decodeResourceWithBackouts(Resources res, BitmapFactory.Options options, - int id) { - boolean noBitmap = true; - int num_tries = 0; - if (options.inSampleSize < 1) { - options.inSampleSize = 1; - } - // Stopgap fix for low-memory devices. - Bitmap bmap = null; - while (noBitmap) { - try { - // Try to decode, downsample if low-memory. - bmap = BitmapFactory.decodeResource( - res, id, options); - noBitmap = false; - } catch (java.lang.OutOfMemoryError e) { - // Retry before failing for good. - if (++num_tries >= BITMAP_LOAD_BACKOUT_ATTEMPTS) { - throw e; - } - bmap = null; - System.gc(); - options.inSampleSize *= 2; - } - } - return bmap; - } - - public static XMPMeta getXmpObject(Context context) { - try { - InputStream is = context.getContentResolver().openInputStream( - MasterImage.getImage().getUri()); - return XmpUtilHelper.extractXMPMeta(is); - } catch (FileNotFoundException e) { - return null; - } - } - - /** - * Determine if this is a light cycle 360 image - * - * @return true if it is a light Cycle image that is full 360 - */ - public static boolean queryLightCycle360(Context context) { - InputStream is = null; - try { - is = context.getContentResolver().openInputStream(MasterImage.getImage().getUri()); - XMPMeta meta = XmpUtilHelper.extractXMPMeta(is); - if (meta == null) { - return false; - } - String namespace = "http://ns.google.com/photos/1.0/panorama/"; - String cropWidthName = "GPano:CroppedAreaImageWidthPixels"; - String fullWidthName = "GPano:FullPanoWidthPixels"; - - if (!meta.doesPropertyExist(namespace, cropWidthName)) { - return false; - } - if (!meta.doesPropertyExist(namespace, fullWidthName)) { - return false; - } - - Integer cropValue = meta.getPropertyInteger(namespace, cropWidthName); - Integer fullValue = meta.getPropertyInteger(namespace, fullWidthName); - - // Definition of a 360: - // GFullPanoWidthPixels == CroppedAreaImageWidthPixels - if (cropValue != null && fullValue != null) { - return cropValue.equals(fullValue); - } - - return false; - } catch (FileNotFoundException e) { - return false; - } catch (XMPException e) { - return false; - } finally { - Utils.closeSilently(is); - } - } -} diff --git a/src/com/android/gallery3d/filtershow/category/Action.java b/src/com/android/gallery3d/filtershow/category/Action.java deleted file mode 100644 index 332ca18b0..000000000 --- a/src/com/android/gallery3d/filtershow/category/Action.java +++ /dev/null @@ -1,186 +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.gallery3d.filtershow.category; - -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.Canvas; -import android.graphics.Matrix; -import android.graphics.Paint; -import android.graphics.Rect; -import android.graphics.RectF; -import android.widget.ArrayAdapter; -import android.widget.ListAdapter; -import com.android.gallery3d.filtershow.filters.FilterUserPresetRepresentation; -import com.android.gallery3d.filtershow.pipeline.RenderingRequest; -import com.android.gallery3d.filtershow.pipeline.RenderingRequestCaller; -import com.android.gallery3d.filtershow.filters.FilterRepresentation; -import com.android.gallery3d.filtershow.imageshow.MasterImage; -import com.android.gallery3d.filtershow.pipeline.ImagePreset; - -public class Action implements RenderingRequestCaller { - - private static final String LOGTAG = "Action"; - private FilterRepresentation mRepresentation; - private String mName; - private Rect mImageFrame; - private Bitmap mImage; - private ArrayAdapter mAdapter; - public static final int FULL_VIEW = 0; - public static final int CROP_VIEW = 1; - private int mType = CROP_VIEW; - private Bitmap mPortraitImage; - private Bitmap mOverlayBitmap; - private Context mContext; - - public Action(Context context, FilterRepresentation representation, int type) { - mContext = context; - setRepresentation(representation); - setType(type); - } - - public Action(Context context, FilterRepresentation representation) { - this(context, representation, CROP_VIEW); - } - - public FilterRepresentation getRepresentation() { - return mRepresentation; - } - - public void setRepresentation(FilterRepresentation representation) { - mRepresentation = representation; - mName = representation.getName(); - } - - public String getName() { - return mName; - } - - public void setName(String name) { - mName = name; - } - - public void setImageFrame(Rect imageFrame, int orientation) { - if (mImageFrame != null && mImageFrame.equals(imageFrame)) { - return; - } - Bitmap bitmap = MasterImage.getImage().getLargeThumbnailBitmap(); - if (bitmap != null) { - mImageFrame = imageFrame; - int w = mImageFrame.width(); - int h = mImageFrame.height(); - if (orientation == CategoryView.VERTICAL - && mType == CROP_VIEW) { - w /= 2; - } - Bitmap bitmapCrop = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); - drawCenteredImage(bitmap, bitmapCrop, true); - - postNewIconRenderRequest(bitmapCrop); - } - } - - public Bitmap getImage() { - return mImage; - } - - public void setImage(Bitmap image) { - mImage = image; - } - - public void setAdapter(ArrayAdapter adapter) { - mAdapter = adapter; - } - - public void setType(int type) { - mType = type; - } - - private void postNewIconRenderRequest(Bitmap bitmap) { - if (bitmap != null && mRepresentation != null) { - ImagePreset preset = new ImagePreset(); - preset.addFilter(mRepresentation); - RenderingRequest.post(mContext, bitmap, - preset, RenderingRequest.ICON_RENDERING, this); - } - } - - private void drawCenteredImage(Bitmap source, Bitmap destination, boolean scale) { - RectF image = new RectF(0, 0, source.getWidth(), source.getHeight()); - int border = 0; - if (!scale) { - border = destination.getWidth() - destination.getHeight(); - if (border < 0) { - border = 0; - } - } - RectF frame = new RectF(border, 0, - destination.getWidth() - border, - destination.getHeight()); - Matrix m = new Matrix(); - m.setRectToRect(frame, image, Matrix.ScaleToFit.CENTER); - image.set(frame); - m.mapRect(image); - m.setRectToRect(image, frame, Matrix.ScaleToFit.FILL); - Canvas canvas = new Canvas(destination); - canvas.drawBitmap(source, m, new Paint(Paint.FILTER_BITMAP_FLAG)); - } - - @Override - public void available(RenderingRequest request) { - mImage = request.getBitmap(); - if (mImage == null) { - return; - } - if (mRepresentation.getOverlayId() != 0 && mOverlayBitmap == null) { - mOverlayBitmap = BitmapFactory.decodeResource( - mContext.getResources(), - mRepresentation.getOverlayId()); - } - if (mOverlayBitmap != null) { - if (getRepresentation().getFilterType() == FilterRepresentation.TYPE_BORDER) { - Canvas canvas = new Canvas(mImage); - canvas.drawBitmap(mOverlayBitmap, new Rect(0, 0, mOverlayBitmap.getWidth(), mOverlayBitmap.getHeight()), - new Rect(0, 0, mImage.getWidth(), mImage.getHeight()), new Paint()); - } else { - Canvas canvas = new Canvas(mImage); - canvas.drawARGB(128, 0, 0, 0); - drawCenteredImage(mOverlayBitmap, mImage, false); - } - } - if (mAdapter != null) { - mAdapter.notifyDataSetChanged(); - } - } - - public void setPortraitImage(Bitmap portraitImage) { - mPortraitImage = portraitImage; - } - - public Bitmap getPortraitImage() { - return mPortraitImage; - } - - public Bitmap getOverlayBitmap() { - return mOverlayBitmap; - } - - public void setOverlayBitmap(Bitmap overlayBitmap) { - mOverlayBitmap = overlayBitmap; - } -} diff --git a/src/com/android/gallery3d/filtershow/category/CategoryAdapter.java b/src/com/android/gallery3d/filtershow/category/CategoryAdapter.java deleted file mode 100644 index 6451c39df..000000000 --- a/src/com/android/gallery3d/filtershow/category/CategoryAdapter.java +++ /dev/null @@ -1,182 +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.gallery3d.filtershow.category; - -import android.content.Context; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ArrayAdapter; -import android.widget.ListView; - -import com.android.gallery3d.filtershow.filters.FilterRepresentation; -import com.android.gallery3d.filtershow.filters.FilterTinyPlanetRepresentation; -import com.android.gallery3d.filtershow.pipeline.ImagePreset; - -public class CategoryAdapter extends ArrayAdapter { - - private static final String LOGTAG = "CategoryAdapter"; - private int mItemHeight; - private View mContainer; - private int mItemWidth = ListView.LayoutParams.MATCH_PARENT; - private int mSelectedPosition; - int mCategory; - private int mOrientation; - - public CategoryAdapter(Context context, int textViewResourceId) { - super(context, textViewResourceId); - mItemHeight = (int) (context.getResources().getDisplayMetrics().density * 100); - } - - public CategoryAdapter(Context context) { - this(context, 0); - } - - public void setItemHeight(int height) { - mItemHeight = height; - } - - public void setItemWidth(int width) { - mItemWidth = width; - } - - @Override - public void add(Action action) { - super.add(action); - action.setAdapter(this); - } - - public void initializeSelection(int category) { - mCategory = category; - mSelectedPosition = -1; - if (category == MainPanel.LOOKS) { - mSelectedPosition = 0; - } - if (category == MainPanel.BORDERS) { - mSelectedPosition = 0; - } - } - - @Override - public View getView(int position, View convertView, ViewGroup parent) { - if (convertView == null) { - convertView = new CategoryView(getContext()); - } - CategoryView view = (CategoryView) convertView; - view.setOrientation(mOrientation); - view.setAction(getItem(position), this); - view.setLayoutParams( - new ListView.LayoutParams(mItemWidth, mItemHeight)); - view.setTag(position); - view.invalidate(); - return view; - } - - public void setSelected(View v) { - int old = mSelectedPosition; - mSelectedPosition = (Integer) v.getTag(); - if (old != -1) { - invalidateView(old); - } - invalidateView(mSelectedPosition); - } - - public boolean isSelected(View v) { - return (Integer) v.getTag() == mSelectedPosition; - } - - private void invalidateView(int position) { - View child = null; - if (mContainer instanceof ListView) { - ListView lv = (ListView) mContainer; - child = lv.getChildAt(position - lv.getFirstVisiblePosition()); - } else { - CategoryTrack ct = (CategoryTrack) mContainer; - child = ct.getChildAt(position); - } - if (child != null) { - child.invalidate(); - } - } - - public void setContainer(View container) { - mContainer = container; - } - - public void imageLoaded() { - notifyDataSetChanged(); - } - - public FilterRepresentation getTinyPlanet() { - for (int i = 0; i < getCount(); i++) { - Action action = getItem(i); - if (action.getRepresentation() != null - && action.getRepresentation() - instanceof FilterTinyPlanetRepresentation) { - return action.getRepresentation(); - } - } - return null; - } - - public void removeTinyPlanet() { - for (int i = 0; i < getCount(); i++) { - Action action = getItem(i); - if (action.getRepresentation() != null - && action.getRepresentation() - instanceof FilterTinyPlanetRepresentation) { - remove(action); - return; - } - } - } - - public void setOrientation(int orientation) { - mOrientation = orientation; - } - - public void reflectImagePreset(ImagePreset preset) { - if (preset == null) { - return; - } - int selected = 0; // if nothing found, select "none" (first element) - FilterRepresentation rep = null; - if (mCategory == MainPanel.LOOKS) { - int pos = preset.getPositionForType(FilterRepresentation.TYPE_FX); - if (pos != -1) { - rep = preset.getFilterRepresentation(pos); - } - } else if (mCategory == MainPanel.BORDERS) { - int pos = preset.getPositionForType(FilterRepresentation.TYPE_BORDER); - if (pos != -1) { - rep = preset.getFilterRepresentation(pos); - } - } - if (rep != null) { - for (int i = 0; i < getCount(); i++) { - if (rep.getName().equalsIgnoreCase( - getItem(i).getRepresentation().getName())) { - selected = i; - break; - } - } - } - if (mSelectedPosition != selected) { - mSelectedPosition = selected; - this.notifyDataSetChanged(); - } - } -} diff --git a/src/com/android/gallery3d/filtershow/category/CategoryPanel.java b/src/com/android/gallery3d/filtershow/category/CategoryPanel.java deleted file mode 100644 index de2481f3f..000000000 --- a/src/com/android/gallery3d/filtershow/category/CategoryPanel.java +++ /dev/null @@ -1,108 +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.gallery3d.filtershow.category; - -import android.app.Activity; -import android.os.Bundle; -import android.support.v4.app.Fragment; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.LinearLayout; -import android.widget.ListView; -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.FilterShowActivity; - -public class CategoryPanel extends Fragment { - - public static final String FRAGMENT_TAG = "CategoryPanel"; - private static final String PARAMETER_TAG = "currentPanel"; - - private int mCurrentAdapter = MainPanel.LOOKS; - private CategoryAdapter mAdapter; - - public void setAdapter(int value) { - mCurrentAdapter = value; - } - - @Override - public void onAttach(Activity activity) { - super.onAttach(activity); - loadAdapter(mCurrentAdapter); - } - - private void loadAdapter(int adapter) { - FilterShowActivity activity = (FilterShowActivity) getActivity(); - switch (adapter) { - case MainPanel.LOOKS: { - mAdapter = activity.getCategoryLooksAdapter(); - mAdapter.initializeSelection(MainPanel.LOOKS); - activity.updateCategories(); - break; - } - case MainPanel.BORDERS: { - mAdapter = activity.getCategoryBordersAdapter(); - mAdapter.initializeSelection(MainPanel.BORDERS); - activity.updateCategories(); - break; - } - case MainPanel.GEOMETRY: { - mAdapter = activity.getCategoryGeometryAdapter(); - mAdapter.initializeSelection(MainPanel.GEOMETRY); - break; - } - case MainPanel.FILTERS: { - mAdapter = activity.getCategoryFiltersAdapter(); - mAdapter.initializeSelection(MainPanel.FILTERS); - break; - } - } - } - - @Override - public void onSaveInstanceState(Bundle state) { - super.onSaveInstanceState(state); - state.putInt(PARAMETER_TAG, mCurrentAdapter); - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - LinearLayout main = (LinearLayout) inflater.inflate( - R.layout.filtershow_category_panel_new, container, - false); - - if (savedInstanceState != null) { - int selectedPanel = savedInstanceState.getInt(PARAMETER_TAG); - loadAdapter(selectedPanel); - } - - View panelView = main.findViewById(R.id.listItems); - if (panelView instanceof CategoryTrack) { - CategoryTrack panel = (CategoryTrack) panelView; - mAdapter.setOrientation(CategoryView.HORIZONTAL); - panel.setAdapter(mAdapter); - mAdapter.setContainer(panel); - } else { - ListView panel = (ListView) main.findViewById(R.id.listItems); - panel.setAdapter(mAdapter); - mAdapter.setContainer(panel); - } - return main; - } - -} diff --git a/src/com/android/gallery3d/filtershow/category/CategoryTrack.java b/src/com/android/gallery3d/filtershow/category/CategoryTrack.java deleted file mode 100644 index ac8245a3b..000000000 --- a/src/com/android/gallery3d/filtershow/category/CategoryTrack.java +++ /dev/null @@ -1,77 +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.gallery3d.filtershow.category; - -import android.content.Context; -import android.content.res.TypedArray; -import android.database.DataSetObserver; -import android.util.AttributeSet; -import android.util.Log; -import android.view.View; -import android.widget.LinearLayout; -import com.android.gallery3d.R; - -public class CategoryTrack extends LinearLayout { - - private CategoryAdapter mAdapter; - private int mElemSize; - private DataSetObserver mDataSetObserver = new DataSetObserver() { - @Override - public void onChanged() { - super.onChanged(); - invalidate(); - } - @Override - public void onInvalidated() { - super.onInvalidated(); - fillContent(); - } - }; - - public CategoryTrack(Context context, AttributeSet attrs) { - super(context, attrs); - TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.CategoryTrack); - mElemSize = a.getDimensionPixelSize(R.styleable.CategoryTrack_iconSize, 0); - } - - public void setAdapter(CategoryAdapter adapter) { - mAdapter = adapter; - mAdapter.registerDataSetObserver(mDataSetObserver); - fillContent(); - } - - public void fillContent() { - removeAllViews(); - mAdapter.setItemWidth(mElemSize); - mAdapter.setItemHeight(LayoutParams.MATCH_PARENT); - int n = mAdapter.getCount(); - for (int i = 0; i < n; i++) { - View view = mAdapter.getView(i, null, this); - addView(view, i); - } - requestLayout(); - } - - @Override - public void invalidate() { - for (int i = 0; i < this.getChildCount(); i++) { - View child = getChildAt(i); - child.invalidate(); - } - } - -} diff --git a/src/com/android/gallery3d/filtershow/category/CategoryView.java b/src/com/android/gallery3d/filtershow/category/CategoryView.java deleted file mode 100644 index c456dc207..000000000 --- a/src/com/android/gallery3d/filtershow/category/CategoryView.java +++ /dev/null @@ -1,176 +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.gallery3d.filtershow.category; - -import android.content.Context; -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Paint; -import android.graphics.Rect; -import android.graphics.Typeface; -import android.view.View; -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.FilterShowActivity; -import com.android.gallery3d.filtershow.filters.FilterRepresentation; -import com.android.gallery3d.filtershow.ui.SelectionRenderer; - -public class CategoryView extends View implements View.OnClickListener { - - private static final String LOGTAG = "CategoryView"; - public static final int VERTICAL = 0; - public static final int HORIZONTAL = 1; - private Paint mPaint = new Paint(); - private Action mAction; - private Rect mTextBounds = new Rect(); - private int mMargin = 16; - private int mTextSize = 32; - private int mTextColor; - private int mBackgroundColor; - private Paint mSelectPaint; - CategoryAdapter mAdapter; - private int mSelectionStroke; - private Paint mBorderPaint; - private int mBorderStroke; - private int mOrientation = VERTICAL; - - public CategoryView(Context context) { - super(context); - setOnClickListener(this); - Resources res = getResources(); - mBackgroundColor = res.getColor(R.color.filtershow_categoryview_background); - mTextColor = res.getColor(R.color.filtershow_categoryview_text); - mSelectionStroke = res.getDimensionPixelSize(R.dimen.thumbnail_margin); - mTextSize = res.getDimensionPixelSize(R.dimen.category_panel_text_size); - mMargin = res.getDimensionPixelOffset(R.dimen.category_panel_margin); - mSelectPaint = new Paint(); - mSelectPaint.setStyle(Paint.Style.FILL); - mSelectPaint.setColor(res.getColor(R.color.filtershow_category_selection)); - mBorderPaint = new Paint(mSelectPaint); - mBorderPaint.setColor(Color.BLACK); - mBorderStroke = mSelectionStroke / 3; - } - - private void computeTextPosition(String text) { - if (text == null) { - return; - } - mPaint.setTextSize(mTextSize); - if (mOrientation == VERTICAL) { - text = text.toUpperCase(); - // TODO: set this in xml - mPaint.setTypeface(Typeface.DEFAULT_BOLD); - } - mPaint.getTextBounds(text, 0, text.length(), mTextBounds); - } - - public void drawText(Canvas canvas, String text) { - if (text == null) { - return; - } - float textWidth = mPaint.measureText(text); - int x = (int) (canvas.getWidth() - textWidth - mMargin); - if (mOrientation == HORIZONTAL) { - x = (int) ((canvas.getWidth() - textWidth) / 2.0f); - } - if (x < 0) { - // If the text takes more than the view width, - // justify to the left. - x = mMargin; - } - int y = canvas.getHeight() - mMargin; - canvas.drawText(text, x, y, mPaint); - } - - @Override - public CharSequence getContentDescription () { - if (mAction != null) { - return mAction.getName(); - } - return null; - } - - @Override - public void onDraw(Canvas canvas) { - canvas.drawColor(mBackgroundColor); - if (mAction != null) { - mPaint.reset(); - mPaint.setAntiAlias(true); - computeTextPosition(mAction.getName()); - if (mAction.getImage() == null) { - mAction.setImageFrame(new Rect(0, 0, getWidth(), getHeight()), mOrientation); - } else { - Bitmap bitmap = mAction.getImage(); - canvas.save(); - Rect clipRect = new Rect(mSelectionStroke, mSelectionStroke, - getWidth() - mSelectionStroke, - getHeight() - 2* mMargin - mTextSize); - int offsetx = 0; - int offsety = 0; - if (mOrientation == HORIZONTAL) { - canvas.clipRect(clipRect); - offsetx = - (bitmap.getWidth() - clipRect.width()) / 2; - offsety = - (bitmap.getHeight() - clipRect.height()) / 2; - } - canvas.drawBitmap(bitmap, offsetx, offsety, mPaint); - canvas.restore(); - if (mAdapter.isSelected(this)) { - if (mOrientation == HORIZONTAL) { - SelectionRenderer.drawSelection(canvas, 0, 0, - getWidth(), getHeight() - mMargin - mTextSize, - mSelectionStroke, mSelectPaint, mBorderStroke, mBorderPaint); - } else { - SelectionRenderer.drawSelection(canvas, 0, 0, - Math.min(bitmap.getWidth(), getWidth()), - Math.min(bitmap.getHeight(), getHeight()), - mSelectionStroke, mSelectPaint, mBorderStroke, mBorderPaint); - } - } - } - mPaint.setColor(mBackgroundColor); - mPaint.setStyle(Paint.Style.STROKE); - mPaint.setStrokeWidth(3); - drawText(canvas, mAction.getName()); - mPaint.setColor(mTextColor); - mPaint.setStyle(Paint.Style.FILL); - mPaint.setStrokeWidth(1); - drawText(canvas, mAction.getName()); - } - } - - public void setAction(Action action, CategoryAdapter adapter) { - mAction = action; - mAdapter = adapter; - invalidate(); - } - - public FilterRepresentation getRepresentation() { - return mAction.getRepresentation(); - } - - @Override - public void onClick(View view) { - FilterShowActivity activity = (FilterShowActivity) getContext(); - activity.showRepresentation(mAction.getRepresentation()); - mAdapter.setSelected(this); - } - - public void setOrientation(int orientation) { - mOrientation = orientation; - } -} diff --git a/src/com/android/gallery3d/filtershow/category/MainPanel.java b/src/com/android/gallery3d/filtershow/category/MainPanel.java deleted file mode 100644 index 9a64ffbf3..000000000 --- a/src/com/android/gallery3d/filtershow/category/MainPanel.java +++ /dev/null @@ -1,239 +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.gallery3d.filtershow.category; - -import android.os.Bundle; -import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentTransaction; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ImageButton; -import android.widget.LinearLayout; - -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.FilterShowActivity; -import com.android.gallery3d.filtershow.state.StatePanel; - -public class MainPanel extends Fragment { - - private static final String LOGTAG = "MainPanel"; - - private LinearLayout mMainView; - private ImageButton looksButton; - private ImageButton bordersButton; - private ImageButton geometryButton; - private ImageButton filtersButton; - - public static final String FRAGMENT_TAG = "MainPanel"; - public static final int LOOKS = 0; - public static final int BORDERS = 1; - public static final int GEOMETRY = 2; - public static final int FILTERS = 3; - - private int mCurrentSelected = -1; - - private void selection(int position, boolean value) { - if (value) { - FilterShowActivity activity = (FilterShowActivity) getActivity(); - activity.setCurrentPanel(position); - } - switch (position) { - case LOOKS: { - looksButton.setSelected(value); - break; - } - case BORDERS: { - bordersButton.setSelected(value); - break; - } - case GEOMETRY: { - geometryButton.setSelected(value); - break; - } - case FILTERS: { - filtersButton.setSelected(value); - break; - } - } - } - - @Override - public void onDestroyView() { - super.onDestroyView(); - if (mMainView != null) { - if (mMainView.getParent() != null) { - ViewGroup parent = (ViewGroup) mMainView.getParent(); - parent.removeView(mMainView); - } - } - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - - mMainView = (LinearLayout) inflater.inflate( - R.layout.filtershow_main_panel, null, false); - - looksButton = (ImageButton) mMainView.findViewById(R.id.fxButton); - bordersButton = (ImageButton) mMainView.findViewById(R.id.borderButton); - geometryButton = (ImageButton) mMainView.findViewById(R.id.geometryButton); - filtersButton = (ImageButton) mMainView.findViewById(R.id.colorsButton); - - looksButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - showPanel(LOOKS); - } - }); - bordersButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - showPanel(BORDERS); - } - }); - geometryButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - showPanel(GEOMETRY); - } - }); - filtersButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - showPanel(FILTERS); - } - }); - - FilterShowActivity activity = (FilterShowActivity) getActivity(); - showImageStatePanel(activity.isShowingImageStatePanel()); - showPanel(activity.getCurrentPanel()); - return mMainView; - } - - private boolean isRightAnimation(int newPos) { - if (newPos < mCurrentSelected) { - return false; - } - return true; - } - - private void setCategoryFragment(CategoryPanel category, boolean fromRight) { - FragmentTransaction transaction = getChildFragmentManager().beginTransaction(); - if (fromRight) { - transaction.setCustomAnimations(R.anim.slide_in_right, R.anim.slide_out_right); - } else { - transaction.setCustomAnimations(R.anim.slide_in_left, R.anim.slide_out_left); - } - transaction.replace(R.id.category_panel_container, category, CategoryPanel.FRAGMENT_TAG); - transaction.commit(); - } - - public void loadCategoryLookPanel() { - if (mCurrentSelected == LOOKS) { - return; - } - boolean fromRight = isRightAnimation(LOOKS); - selection(mCurrentSelected, false); - CategoryPanel categoryPanel = new CategoryPanel(); - categoryPanel.setAdapter(LOOKS); - setCategoryFragment(categoryPanel, fromRight); - mCurrentSelected = LOOKS; - selection(mCurrentSelected, true); - } - - public void loadCategoryBorderPanel() { - if (mCurrentSelected == BORDERS) { - return; - } - boolean fromRight = isRightAnimation(BORDERS); - selection(mCurrentSelected, false); - CategoryPanel categoryPanel = new CategoryPanel(); - categoryPanel.setAdapter(BORDERS); - setCategoryFragment(categoryPanel, fromRight); - mCurrentSelected = BORDERS; - selection(mCurrentSelected, true); - } - - public void loadCategoryGeometryPanel() { - if (mCurrentSelected == GEOMETRY) { - return; - } - boolean fromRight = isRightAnimation(GEOMETRY); - selection(mCurrentSelected, false); - CategoryPanel categoryPanel = new CategoryPanel(); - categoryPanel.setAdapter(GEOMETRY); - setCategoryFragment(categoryPanel, fromRight); - mCurrentSelected = GEOMETRY; - selection(mCurrentSelected, true); - } - - public void loadCategoryFiltersPanel() { - if (mCurrentSelected == FILTERS) { - return; - } - boolean fromRight = isRightAnimation(FILTERS); - selection(mCurrentSelected, false); - CategoryPanel categoryPanel = new CategoryPanel(); - categoryPanel.setAdapter(FILTERS); - setCategoryFragment(categoryPanel, fromRight); - mCurrentSelected = FILTERS; - selection(mCurrentSelected, true); - } - - public void showPanel(int currentPanel) { - switch (currentPanel) { - case LOOKS: { - loadCategoryLookPanel(); - break; - } - case BORDERS: { - loadCategoryBorderPanel(); - break; - } - case GEOMETRY: { - loadCategoryGeometryPanel(); - break; - } - case FILTERS: { - loadCategoryFiltersPanel(); - break; - } - } - } - - public void showImageStatePanel(boolean show) { - if (mMainView.findViewById(R.id.state_panel_container) == null) { - return; - } - FragmentTransaction transaction = getChildFragmentManager().beginTransaction(); - final View container = mMainView.findViewById(R.id.state_panel_container); - if (show) { - container.setVisibility(View.VISIBLE); - StatePanel statePanel = new StatePanel(); - transaction.replace(R.id.state_panel_container, statePanel, StatePanel.FRAGMENT_TAG); - } else { - container.setVisibility(View.GONE); - Fragment statePanel = getChildFragmentManager().findFragmentByTag(StatePanel.FRAGMENT_TAG); - if (statePanel != null) { - transaction.remove(statePanel); - } - } - transaction.commit(); - } -} diff --git a/src/com/android/gallery3d/filtershow/colorpicker/ColorGridDialog.java b/src/com/android/gallery3d/filtershow/colorpicker/ColorGridDialog.java deleted file mode 100644 index dd4df7dc8..000000000 --- a/src/com/android/gallery3d/filtershow/colorpicker/ColorGridDialog.java +++ /dev/null @@ -1,100 +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.gallery3d.filtershow.colorpicker; - -import android.app.Dialog; -import android.content.Context; -import android.graphics.Color; -import android.graphics.drawable.GradientDrawable; -import android.view.View; -import android.view.ViewGroup; -import android.widget.Button; - -import com.android.gallery3d.R; - -import java.util.ArrayList; - -public class ColorGridDialog extends Dialog { - RGBListener mCallback; - private static final String LOGTAG = "ColorGridDialog"; - - public ColorGridDialog(Context context, final RGBListener cl) { - super(context); - mCallback = cl; - setTitle(R.string.color_pick_title); - setContentView(R.layout.filtershow_color_gird); - Button sel = (Button) findViewById(R.id.filtershow_cp_custom); - ArrayList