1f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka/*
2f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka * Copyright (C) 2013 The Android Open Source Project
3f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka *
4f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka * Licensed under the Apache License, Version 2.0 (the "License");
5f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka * you may not use this file except in compliance with the License.
6f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka * You may obtain a copy of the License at
7f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka *
8f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka *      http://www.apache.org/licenses/LICENSE-2.0
9f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka *
10f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka * Unless required by applicable law or agreed to in writing, software
11f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka * distributed under the License is distributed on an "AS IS" BASIS,
12f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka * See the License for the specific language governing permissions and
14f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka * limitations under the License.
15f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka */
16f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka
17748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyalpackage com.android.wallpaperpicker;
18f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka
19f10a4ed72d6b554bd8d9b44465845245fa1235f6Sunny Goyalimport android.annotation.TargetApi;
20f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurkaimport android.app.ActionBar;
21f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurkaimport android.app.Activity;
224428db78eed5d453c3bb376e6e28977c21b1c9ddSunny Goyalimport android.app.WallpaperManager;
237d21299b0f731db1259f7ee22f36548d5b59fbf9Tony Wickhamimport android.content.DialogInterface;
24f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurkaimport android.content.Intent;
2536a594314db8107927ee94762983dad95aad07aeSunny Goyalimport android.content.pm.ActivityInfo;
26f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurkaimport android.content.res.Resources;
272a218b718e5f498a284341532178c84fe3850e63Sunny Goyalimport android.graphics.Bitmap;
28f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurkaimport android.graphics.Matrix;
29f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurkaimport android.graphics.Point;
30f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurkaimport android.graphics.RectF;
314428db78eed5d453c3bb376e6e28977c21b1c9ddSunny Goyalimport android.graphics.drawable.Drawable;
32f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurkaimport android.net.Uri;
33f10a4ed72d6b554bd8d9b44465845245fa1235f6Sunny Goyalimport android.os.Build;
34f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurkaimport android.os.Bundle;
352a218b718e5f498a284341532178c84fe3850e63Sunny Goyalimport android.os.Handler;
362a218b718e5f498a284341532178c84fe3850e63Sunny Goyalimport android.os.HandlerThread;
372a218b718e5f498a284341532178c84fe3850e63Sunny Goyalimport android.os.Message;
38f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurkaimport android.util.Log;
39f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurkaimport android.view.Display;
40f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurkaimport android.view.View;
41f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurkaimport android.widget.Toast;
422a218b718e5f498a284341532178c84fe3850e63Sunny Goyal
43841a502864d307341945eae62569b92cada93e75Sunny Goyalimport com.android.wallpaperpicker.common.CropAndSetWallpaperTask;
44f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurkaimport com.android.gallery3d.common.Utils;
45f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurkaimport com.android.photos.BitmapRegionTileSource;
46f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurkaimport com.android.photos.BitmapRegionTileSource.BitmapSource;
472a218b718e5f498a284341532178c84fe3850e63Sunny Goyalimport com.android.photos.BitmapRegionTileSource.BitmapSource.InBitmapProvider;
482a218b718e5f498a284341532178c84fe3850e63Sunny Goyalimport com.android.photos.views.TiledImageRenderer.TileSource;
49e396f914a5aaedb0607ea62038b80be7556d6c6cTony Wickhamimport com.android.wallpaperpicker.common.DialogUtils;
50841a502864d307341945eae62569b92cada93e75Sunny Goyalimport com.android.wallpaperpicker.common.InputStreamProvider;
512a218b718e5f498a284341532178c84fe3850e63Sunny Goyal
522a218b718e5f498a284341532178c84fe3850e63Sunny Goyalimport java.util.Collections;
532a218b718e5f498a284341532178c84fe3850e63Sunny Goyalimport java.util.Set;
542a218b718e5f498a284341532178c84fe3850e63Sunny Goyalimport java.util.WeakHashMap;
55f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka
56748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyalpublic class WallpaperCropActivity extends Activity implements Handler.Callback {
57748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal    private static final String LOGTAG = "WallpaperCropActivity";
58f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka
592a218b718e5f498a284341532178c84fe3850e63Sunny Goyal    private static final int MSG_LOAD_IMAGE = 1;
602a218b718e5f498a284341532178c84fe3850e63Sunny Goyal
61f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka    protected CropView mCropView;
622a218b718e5f498a284341532178c84fe3850e63Sunny Goyal    protected View mProgressView;
6312d9d42afb5bd750ab52e38cd66f6081f4bd76bfSelim Cinek    protected View mSetWallpaperButton;
64f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka
652a218b718e5f498a284341532178c84fe3850e63Sunny Goyal    private HandlerThread mLoaderThread;
662a218b718e5f498a284341532178c84fe3850e63Sunny Goyal    private Handler mLoaderHandler;
67748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal    private LoadRequest mCurrentLoadRequest;
682a218b718e5f498a284341532178c84fe3850e63Sunny Goyal    private byte[] mTempStorageForDecoding = new byte[16 * 1024];
692a218b718e5f498a284341532178c84fe3850e63Sunny Goyal    // A weak-set of reusable bitmaps
70748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal    private Set<Bitmap> mReusableBitmaps =
712a218b718e5f498a284341532178c84fe3850e63Sunny Goyal            Collections.newSetFromMap(new WeakHashMap<Bitmap, Boolean>());
722a218b718e5f498a284341532178c84fe3850e63Sunny Goyal
737d21299b0f731db1259f7ee22f36548d5b59fbf9Tony Wickham    private final DialogInterface.OnCancelListener mOnDialogCancelListener =
747d21299b0f731db1259f7ee22f36548d5b59fbf9Tony Wickham            new DialogInterface.OnCancelListener() {
757d21299b0f731db1259f7ee22f36548d5b59fbf9Tony Wickham                @Override
767d21299b0f731db1259f7ee22f36548d5b59fbf9Tony Wickham                public void onCancel(DialogInterface dialog) {
777d21299b0f731db1259f7ee22f36548d5b59fbf9Tony Wickham                    showActionBarAndTiles();
787d21299b0f731db1259f7ee22f36548d5b59fbf9Tony Wickham                }
797d21299b0f731db1259f7ee22f36548d5b59fbf9Tony Wickham            };
807d21299b0f731db1259f7ee22f36548d5b59fbf9Tony Wickham
81f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka    @Override
827c34dd41f64c30be2348979b2d6847257498d541Sunny Goyal    public void onCreate(Bundle savedInstanceState) {
83f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        super.onCreate(savedInstanceState);
842a218b718e5f498a284341532178c84fe3850e63Sunny Goyal
852a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        mLoaderThread = new HandlerThread("wallpaper_loader");
862a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        mLoaderThread.start();
872a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        mLoaderHandler = new Handler(mLoaderThread.getLooper(), this);
882a218b718e5f498a284341532178c84fe3850e63Sunny Goyal
89f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        init();
90f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        if (!enableRotation()) {
9136a594314db8107927ee94762983dad95aad07aeSunny Goyal            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
92f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        }
93f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka    }
94f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka
95f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka    protected void init() {
96f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        setContentView(R.layout.wallpaper_cropper);
97f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka
98f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        mCropView = (CropView) findViewById(R.id.cropView);
992a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        mProgressView = findViewById(R.id.loading);
100f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka
101f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        Intent cropIntent = getIntent();
102f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        final Uri imageUri = cropIntent.getData();
103f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka
104f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        if (imageUri == null) {
105f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka            Log.e(LOGTAG, "No URI passed in intent, exiting WallpaperCropActivity");
106f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka            finish();
107f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka            return;
108f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        }
109f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka
110f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        // Action bar
111f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        // Show the custom action bar view
112f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        final ActionBar actionBar = getActionBar();
113f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        actionBar.setCustomView(R.layout.actionbar_set_wallpaper);
114f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        actionBar.getCustomView().setOnClickListener(
115f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                new View.OnClickListener() {
116f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                    @Override
117f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                    public void onClick(View v) {
118d8fbf6b0404846ea043c1468e4d8069c62381011Tony Wickham                        actionBar.hide();
11939d389f406185d91b588c4caf3225749fd2afdcfTony Wickham                        // Never fade on finish because we return to the app that started us (e.g.
12039d389f406185d91b588c4caf3225749fd2afdcfTony Wickham                        // Photos), not the home screen.
12139d389f406185d91b588c4caf3225749fd2afdcfTony Wickham                        cropImageAndSetWallpaper(imageUri, null, false /* shouldFadeOutOnFinish */);
122f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                    }
123f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                });
124c192530433ab03c02462635e9ffbe3781b666e13Michael Jurka        mSetWallpaperButton = findViewById(R.id.set_wallpaper_button);
125f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka
126f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        // Load image in background
127841a502864d307341945eae62569b92cada93e75Sunny Goyal        final BitmapRegionTileSource.InputStreamSource bitmapSource =
128841a502864d307341945eae62569b92cada93e75Sunny Goyal                new BitmapRegionTileSource.InputStreamSource(this, imageUri);
12912d9d42afb5bd750ab52e38cd66f6081f4bd76bfSelim Cinek        mSetWallpaperButton.setEnabled(false);
130f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        Runnable onLoad = new Runnable() {
131f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka            public void run() {
132f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                if (bitmapSource.getLoadingState() != BitmapSource.State.LOADED) {
133748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal                    Toast.makeText(WallpaperCropActivity.this, R.string.wallpaper_load_fail,
134f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                            Toast.LENGTH_LONG).show();
135f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                    finish();
136c192530433ab03c02462635e9ffbe3781b666e13Michael Jurka                } else {
13712d9d42afb5bd750ab52e38cd66f6081f4bd76bfSelim Cinek                    mSetWallpaperButton.setEnabled(true);
138f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                }
139f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka            }
140f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        };
1412a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        setCropViewTileSource(bitmapSource, true, false, null, onLoad);
142f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka    }
143f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka
1441019588c3cbc255dc523161950adc22483777291Sunny Goyal    @Override
1457c34dd41f64c30be2348979b2d6847257498d541Sunny Goyal    public void onDestroy() {
1461019588c3cbc255dc523161950adc22483777291Sunny Goyal        if (mCropView != null) {
1471019588c3cbc255dc523161950adc22483777291Sunny Goyal            mCropView.destroy();
1481019588c3cbc255dc523161950adc22483777291Sunny Goyal        }
1492a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        if (mLoaderThread != null) {
1502a218b718e5f498a284341532178c84fe3850e63Sunny Goyal            mLoaderThread.quit();
1512a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        }
1521019588c3cbc255dc523161950adc22483777291Sunny Goyal        super.onDestroy();
1531019588c3cbc255dc523161950adc22483777291Sunny Goyal    }
1541019588c3cbc255dc523161950adc22483777291Sunny Goyal
1552a218b718e5f498a284341532178c84fe3850e63Sunny Goyal    /**
1562a218b718e5f498a284341532178c84fe3850e63Sunny Goyal     * This is called on {@link #mLoaderThread}
1572a218b718e5f498a284341532178c84fe3850e63Sunny Goyal     */
158748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal    @TargetApi(Build.VERSION_CODES.KITKAT)
1592a218b718e5f498a284341532178c84fe3850e63Sunny Goyal    @Override
1602a218b718e5f498a284341532178c84fe3850e63Sunny Goyal    public boolean handleMessage(Message msg) {
1612a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        if (msg.what == MSG_LOAD_IMAGE) {
1622a218b718e5f498a284341532178c84fe3850e63Sunny Goyal            final LoadRequest req = (LoadRequest) msg.obj;
16336a594314db8107927ee94762983dad95aad07aeSunny Goyal            final boolean loadSuccess;
1642a218b718e5f498a284341532178c84fe3850e63Sunny Goyal
16536a594314db8107927ee94762983dad95aad07aeSunny Goyal            if (req.src == null) {
16636a594314db8107927ee94762983dad95aad07aeSunny Goyal                Drawable defaultWallpaper = WallpaperManager.getInstance(this)
16736a594314db8107927ee94762983dad95aad07aeSunny Goyal                        .getBuiltInDrawable(mCropView.getWidth(), mCropView.getHeight(),
16836a594314db8107927ee94762983dad95aad07aeSunny Goyal                                false, 0.5f, 0.5f);
16936a594314db8107927ee94762983dad95aad07aeSunny Goyal
17036a594314db8107927ee94762983dad95aad07aeSunny Goyal                if (defaultWallpaper == null) {
17136a594314db8107927ee94762983dad95aad07aeSunny Goyal                    loadSuccess = false;
17236a594314db8107927ee94762983dad95aad07aeSunny Goyal                    Log.w(LOGTAG, "Null default wallpaper encountered.");
17336a594314db8107927ee94762983dad95aad07aeSunny Goyal                } else {
17436a594314db8107927ee94762983dad95aad07aeSunny Goyal                    loadSuccess = true;
17536a594314db8107927ee94762983dad95aad07aeSunny Goyal                    req.result = new DrawableTileSource(this,
17636a594314db8107927ee94762983dad95aad07aeSunny Goyal                            defaultWallpaper, DrawableTileSource.MAX_PREVIEW_SIZE);
17736a594314db8107927ee94762983dad95aad07aeSunny Goyal                }
17836a594314db8107927ee94762983dad95aad07aeSunny Goyal            } else {
17936a594314db8107927ee94762983dad95aad07aeSunny Goyal                try {
18036a594314db8107927ee94762983dad95aad07aeSunny Goyal                    req.src.loadInBackground(new InBitmapProvider() {
18136a594314db8107927ee94762983dad95aad07aeSunny Goyal
18236a594314db8107927ee94762983dad95aad07aeSunny Goyal                        @Override
18336a594314db8107927ee94762983dad95aad07aeSunny Goyal                        public Bitmap forPixelCount(int count) {
18436a594314db8107927ee94762983dad95aad07aeSunny Goyal                            Bitmap bitmapToReuse = null;
18536a594314db8107927ee94762983dad95aad07aeSunny Goyal                            // Find the smallest bitmap that satisfies the pixel count limit
18636a594314db8107927ee94762983dad95aad07aeSunny Goyal                            synchronized (mReusableBitmaps) {
18736a594314db8107927ee94762983dad95aad07aeSunny Goyal                                int currentBitmapSize = Integer.MAX_VALUE;
18836a594314db8107927ee94762983dad95aad07aeSunny Goyal                                for (Bitmap b : mReusableBitmaps) {
18936a594314db8107927ee94762983dad95aad07aeSunny Goyal                                    int bitmapSize = b.getWidth() * b.getHeight();
19036a594314db8107927ee94762983dad95aad07aeSunny Goyal                                    if ((bitmapSize >= count) && (bitmapSize < currentBitmapSize)) {
19136a594314db8107927ee94762983dad95aad07aeSunny Goyal                                        bitmapToReuse = b;
19236a594314db8107927ee94762983dad95aad07aeSunny Goyal                                        currentBitmapSize = bitmapSize;
19336a594314db8107927ee94762983dad95aad07aeSunny Goyal                                    }
1942a218b718e5f498a284341532178c84fe3850e63Sunny Goyal                                }
19578dfc60f10acbb915aa08312e6b53f5f1bc4e1c3Sunny Goyal
19636a594314db8107927ee94762983dad95aad07aeSunny Goyal                                if (bitmapToReuse != null) {
19736a594314db8107927ee94762983dad95aad07aeSunny Goyal                                    mReusableBitmaps.remove(bitmapToReuse);
19836a594314db8107927ee94762983dad95aad07aeSunny Goyal                                }
19978dfc60f10acbb915aa08312e6b53f5f1bc4e1c3Sunny Goyal                            }
20036a594314db8107927ee94762983dad95aad07aeSunny Goyal                            return bitmapToReuse;
201d444a550ec1c8992fbac0a036b293fc4759d25c1Selim Cinek                        }
20236a594314db8107927ee94762983dad95aad07aeSunny Goyal                    });
20336a594314db8107927ee94762983dad95aad07aeSunny Goyal                } catch (SecurityException securityException) {
20436a594314db8107927ee94762983dad95aad07aeSunny Goyal                    if (isActivityDestroyed()) {
20536a594314db8107927ee94762983dad95aad07aeSunny Goyal                        // Temporarily granted permissions are revoked when the activity
20636a594314db8107927ee94762983dad95aad07aeSunny Goyal                        // finishes, potentially resulting in a SecurityException here.
20736a594314db8107927ee94762983dad95aad07aeSunny Goyal                        // Even though {@link #isDestroyed} might also return true in different
20836a594314db8107927ee94762983dad95aad07aeSunny Goyal                        // situations where the configuration changes, we are fine with
20936a594314db8107927ee94762983dad95aad07aeSunny Goyal                        // catching these cases here as well.
21036a594314db8107927ee94762983dad95aad07aeSunny Goyal                        return true;
21136a594314db8107927ee94762983dad95aad07aeSunny Goyal                    } else {
21236a594314db8107927ee94762983dad95aad07aeSunny Goyal                        // otherwise it had a different cause and we throw it further
21336a594314db8107927ee94762983dad95aad07aeSunny Goyal                        throw securityException;
214d444a550ec1c8992fbac0a036b293fc4759d25c1Selim Cinek                    }
215f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                }
21636a594314db8107927ee94762983dad95aad07aeSunny Goyal
217748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal                req.result = new BitmapRegionTileSource(WallpaperCropActivity.this, req.src,
21836a594314db8107927ee94762983dad95aad07aeSunny Goyal                        mTempStorageForDecoding);
21936a594314db8107927ee94762983dad95aad07aeSunny Goyal                loadSuccess = req.src.getLoadingState() == BitmapSource.State.LOADED;
220f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka            }
2212a218b718e5f498a284341532178c84fe3850e63Sunny Goyal
2222a218b718e5f498a284341532178c84fe3850e63Sunny Goyal            runOnUiThread(new Runnable() {
2232a218b718e5f498a284341532178c84fe3850e63Sunny Goyal
2242a218b718e5f498a284341532178c84fe3850e63Sunny Goyal                @Override
2252a218b718e5f498a284341532178c84fe3850e63Sunny Goyal                public void run() {
2262a218b718e5f498a284341532178c84fe3850e63Sunny Goyal                    if (req == mCurrentLoadRequest) {
22736a594314db8107927ee94762983dad95aad07aeSunny Goyal                        onLoadRequestComplete(req, loadSuccess);
2282a218b718e5f498a284341532178c84fe3850e63Sunny Goyal                    } else {
2292a218b718e5f498a284341532178c84fe3850e63Sunny Goyal                        addReusableBitmap(req.result);
230f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                    }
231f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                }
2322a218b718e5f498a284341532178c84fe3850e63Sunny Goyal            });
2332a218b718e5f498a284341532178c84fe3850e63Sunny Goyal            return true;
2342a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        }
2352a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        return false;
2362a218b718e5f498a284341532178c84fe3850e63Sunny Goyal    }
2372a218b718e5f498a284341532178c84fe3850e63Sunny Goyal
2382b79967d4a01b851136f32d89e4d45a3919fa8f0Sunny Goyal    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
2394428db78eed5d453c3bb376e6e28977c21b1c9ddSunny Goyal    public boolean isActivityDestroyed() {
240748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 && isDestroyed();
2412b79967d4a01b851136f32d89e4d45a3919fa8f0Sunny Goyal    }
2422b79967d4a01b851136f32d89e4d45a3919fa8f0Sunny Goyal
243748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal    private void addReusableBitmap(TileSource src) {
2442a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        synchronized (mReusableBitmaps) {
245748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT
246748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal                && src instanceof BitmapRegionTileSource) {
2472a218b718e5f498a284341532178c84fe3850e63Sunny Goyal                Bitmap preview = ((BitmapRegionTileSource) src).getBitmap();
2482a218b718e5f498a284341532178c84fe3850e63Sunny Goyal                if (preview != null && preview.isMutable()) {
2492a218b718e5f498a284341532178c84fe3850e63Sunny Goyal                    mReusableBitmaps.add(preview);
250f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                }
251f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka            }
2522a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        }
2532a218b718e5f498a284341532178c84fe3850e63Sunny Goyal    }
2542a218b718e5f498a284341532178c84fe3850e63Sunny Goyal
2557d21299b0f731db1259f7ee22f36548d5b59fbf9Tony Wickham    public DialogInterface.OnCancelListener getOnDialogCancelListener() {
2567d21299b0f731db1259f7ee22f36548d5b59fbf9Tony Wickham        return mOnDialogCancelListener;
2577d21299b0f731db1259f7ee22f36548d5b59fbf9Tony Wickham    }
2587d21299b0f731db1259f7ee22f36548d5b59fbf9Tony Wickham
2597d21299b0f731db1259f7ee22f36548d5b59fbf9Tony Wickham    private void showActionBarAndTiles() {
2607d21299b0f731db1259f7ee22f36548d5b59fbf9Tony Wickham        getActionBar().show();
2617d21299b0f731db1259f7ee22f36548d5b59fbf9Tony Wickham        View wallpaperStrip = findViewById(R.id.wallpaper_strip);
2627d21299b0f731db1259f7ee22f36548d5b59fbf9Tony Wickham        if (wallpaperStrip != null) {
2637d21299b0f731db1259f7ee22f36548d5b59fbf9Tony Wickham            wallpaperStrip.setVisibility(View.VISIBLE);
2647d21299b0f731db1259f7ee22f36548d5b59fbf9Tony Wickham        }
2657d21299b0f731db1259f7ee22f36548d5b59fbf9Tony Wickham    }
2667d21299b0f731db1259f7ee22f36548d5b59fbf9Tony Wickham
2672a218b718e5f498a284341532178c84fe3850e63Sunny Goyal    protected void onLoadRequestComplete(LoadRequest req, boolean success) {
2682a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        mCurrentLoadRequest = null;
2692a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        if (success) {
2702a218b718e5f498a284341532178c84fe3850e63Sunny Goyal            TileSource oldSrc = mCropView.getTileSource();
2712a218b718e5f498a284341532178c84fe3850e63Sunny Goyal            mCropView.setTileSource(req.result, null);
2722a218b718e5f498a284341532178c84fe3850e63Sunny Goyal            mCropView.setTouchEnabled(req.touchEnabled);
2732a218b718e5f498a284341532178c84fe3850e63Sunny Goyal            if (req.moveToLeft) {
2742a218b718e5f498a284341532178c84fe3850e63Sunny Goyal                mCropView.moveToLeft();
2752a218b718e5f498a284341532178c84fe3850e63Sunny Goyal            }
2767bd5e80dc5e26102e59b300dec8dfd8abd9184b4Tony Wickham            if (req.scaleAndOffsetProvider != null) {
27713d3a076ce25c531c450d139b37b3e5bbd6964e1Tony Wickham                TileSource src = req.result;
27813d3a076ce25c531c450d139b37b3e5bbd6964e1Tony Wickham                Point wallpaperSize = WallpaperUtils.getDefaultWallpaperSize(
27913d3a076ce25c531c450d139b37b3e5bbd6964e1Tony Wickham                        getResources(), getWindowManager());
28013d3a076ce25c531c450d139b37b3e5bbd6964e1Tony Wickham                RectF crop = Utils.getMaxCropRect(src.getImageWidth(), src.getImageHeight(),
28113d3a076ce25c531c450d139b37b3e5bbd6964e1Tony Wickham                        wallpaperSize.x, wallpaperSize.y, false /* leftAligned */);
28213d3a076ce25c531c450d139b37b3e5bbd6964e1Tony Wickham                mCropView.setScale(req.scaleAndOffsetProvider.getScale(wallpaperSize, crop));
28313d3a076ce25c531c450d139b37b3e5bbd6964e1Tony Wickham                mCropView.setParallaxOffset(req.scaleAndOffsetProvider.getParallaxOffset(), crop);
2842a218b718e5f498a284341532178c84fe3850e63Sunny Goyal            }
2852a218b718e5f498a284341532178c84fe3850e63Sunny Goyal
2862a218b718e5f498a284341532178c84fe3850e63Sunny Goyal            // Free last image
2872a218b718e5f498a284341532178c84fe3850e63Sunny Goyal            if (oldSrc != null) {
2882a218b718e5f498a284341532178c84fe3850e63Sunny Goyal                // Call yield instead of recycle, as we only want to free GL resource.
2892a218b718e5f498a284341532178c84fe3850e63Sunny Goyal                // We can still reuse the bitmap for decoding any other image.
2902a218b718e5f498a284341532178c84fe3850e63Sunny Goyal                oldSrc.getPreview().yield();
2912a218b718e5f498a284341532178c84fe3850e63Sunny Goyal            }
2922a218b718e5f498a284341532178c84fe3850e63Sunny Goyal            addReusableBitmap(oldSrc);
2932a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        }
2942a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        if (req.postExecute != null) {
2952a218b718e5f498a284341532178c84fe3850e63Sunny Goyal            req.postExecute.run();
2962a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        }
297b5351470a2136a3e680d05133138de67b3d5c6abSunny Goyal        mProgressView.setVisibility(View.GONE);
2982a218b718e5f498a284341532178c84fe3850e63Sunny Goyal    }
2992a218b718e5f498a284341532178c84fe3850e63Sunny Goyal
3004428db78eed5d453c3bb376e6e28977c21b1c9ddSunny Goyal    @TargetApi(Build.VERSION_CODES.KITKAT)
3012a218b718e5f498a284341532178c84fe3850e63Sunny Goyal    public final void setCropViewTileSource(BitmapSource bitmapSource, boolean touchEnabled,
3027bd5e80dc5e26102e59b300dec8dfd8abd9184b4Tony Wickham            boolean moveToLeft, CropViewScaleAndOffsetProvider scaleAndOffsetProvider,
3037bd5e80dc5e26102e59b300dec8dfd8abd9184b4Tony Wickham            Runnable postExecute) {
3042a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        final LoadRequest req = new LoadRequest();
3052a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        req.moveToLeft = moveToLeft;
3062a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        req.src = bitmapSource;
3072a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        req.touchEnabled = touchEnabled;
3082a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        req.postExecute = postExecute;
3097bd5e80dc5e26102e59b300dec8dfd8abd9184b4Tony Wickham        req.scaleAndOffsetProvider = scaleAndOffsetProvider;
3102a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        mCurrentLoadRequest = req;
3112a218b718e5f498a284341532178c84fe3850e63Sunny Goyal
3122a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        // Remove any pending requests
3132a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        mLoaderHandler.removeMessages(MSG_LOAD_IMAGE);
3142a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        Message.obtain(mLoaderHandler, MSG_LOAD_IMAGE, req).sendToTarget();
3152a218b718e5f498a284341532178c84fe3850e63Sunny Goyal
316f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        // We don't want to show the spinner every time we load an image, because that would be
317f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        // annoying; instead, only start showing the spinner if loading the image has taken
318f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        // longer than 1 sec (ie 1000 ms)
3192a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        mProgressView.postDelayed(new Runnable() {
320f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka            public void run() {
3212a218b718e5f498a284341532178c84fe3850e63Sunny Goyal                if (mCurrentLoadRequest == req) {
3222a218b718e5f498a284341532178c84fe3850e63Sunny Goyal                    mProgressView.setVisibility(View.VISIBLE);
323f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                }
324f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka            }
325f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        }, 1000);
326f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka    }
327f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka
3282a218b718e5f498a284341532178c84fe3850e63Sunny Goyal
329f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka    public boolean enableRotation() {
330748dfe025b128ea88ba626c8bfb7da315d5af29cSunny Goyal        return true;
331f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka    }
332f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka
33339d389f406185d91b588c4caf3225749fd2afdcfTony Wickham    public void cropImageAndSetWallpaper(Resources res, int resId, boolean shouldFadeOutOnFinish) {
334f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        // crop this image and scale it down to the default wallpaper size for
335f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        // this device
336841a502864d307341945eae62569b92cada93e75Sunny Goyal        InputStreamProvider streamProvider = InputStreamProvider.fromResource(res, resId);
337f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        Point inSize = mCropView.getSourceDimensions();
3383faa8a34b7c27a0e3b1d85da373a29036a9d1387Sunny Goyal        Point outSize = WallpaperUtils.getDefaultWallpaperSize(getResources(),
339f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                getWindowManager());
340f10a4ed72d6b554bd8d9b44465845245fa1235f6Sunny Goyal        RectF crop = Utils.getMaxCropRect(
341f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                inSize.x, inSize.y, outSize.x, outSize.y, false);
3424428db78eed5d453c3bb376e6e28977c21b1c9ddSunny Goyal        // Passing 0, 0 will cause launcher to revert to using the
3434428db78eed5d453c3bb376e6e28977c21b1c9ddSunny Goyal        // default wallpaper size
34439d389f406185d91b588c4caf3225749fd2afdcfTony Wickham        CropAndFinishHandler onEndCrop = new CropAndFinishHandler(new Point(0, 0),
34539d389f406185d91b588c4caf3225749fd2afdcfTony Wickham                shouldFadeOutOnFinish);
346841a502864d307341945eae62569b92cada93e75Sunny Goyal        CropAndSetWallpaperTask cropTask = new CropAndSetWallpaperTask(
347841a502864d307341945eae62569b92cada93e75Sunny Goyal                streamProvider, this, crop, streamProvider.getRotationFromExif(this),
348841a502864d307341945eae62569b92cada93e75Sunny Goyal                outSize.x, outSize.y, onEndCrop);
3497d21299b0f731db1259f7ee22f36548d5b59fbf9Tony Wickham        DialogUtils.executeCropTaskAfterPrompt(this, cropTask, getOnDialogCancelListener());
350f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka    }
351f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka
352f10a4ed72d6b554bd8d9b44465845245fa1235f6Sunny Goyal    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
3534428db78eed5d453c3bb376e6e28977c21b1c9ddSunny Goyal    public void cropImageAndSetWallpaper(Uri uri,
354841a502864d307341945eae62569b92cada93e75Sunny Goyal            CropAndSetWallpaperTask.OnBitmapCroppedHandler onBitmapCroppedHandler,
35539d389f406185d91b588c4caf3225749fd2afdcfTony Wickham            boolean shouldFadeOutOnFinish) {
356f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        // Get the crop
357f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        boolean ltr = mCropView.getLayoutDirection() == View.LAYOUT_DIRECTION_LTR;
358f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka
359f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        Display d = getWindowManager().getDefaultDisplay();
360f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka
361f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        Point displaySize = new Point();
362f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        d.getSize(displaySize);
363f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        boolean isPortrait = displaySize.x < displaySize.y;
364f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka
3653faa8a34b7c27a0e3b1d85da373a29036a9d1387Sunny Goyal        Point defaultWallpaperSize = WallpaperUtils.getDefaultWallpaperSize(getResources(),
366f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                getWindowManager());
367f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        // Get the crop
368f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        RectF cropRect = mCropView.getCrop();
369b24af13c8359963ecdea420a1b395149e7477f83Selim Cinek
370500dfeb109f614fd42e2cc383c5dcfecaa981b38Selim Cinek        Point inSize = mCropView.getSourceDimensions();
371500dfeb109f614fd42e2cc383c5dcfecaa981b38Selim Cinek
372f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        int cropRotation = mCropView.getImageRotation();
373f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        float cropScale = mCropView.getWidth() / (float) cropRect.width();
374f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka
375f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        Matrix rotateMatrix = new Matrix();
376f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        rotateMatrix.setRotate(cropRotation);
377f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        float[] rotatedInSize = new float[] { inSize.x, inSize.y };
378f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        rotateMatrix.mapPoints(rotatedInSize);
379f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        rotatedInSize[0] = Math.abs(rotatedInSize[0]);
380f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        rotatedInSize[1] = Math.abs(rotatedInSize[1]);
381f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka
3821116efa8af024cb9fcae059c16e23caea984729fSelim Cinek        // due to rounding errors in the cropview renderer the edges can be slightly offset
3831116efa8af024cb9fcae059c16e23caea984729fSelim Cinek        // therefore we ensure that the boundaries are sanely defined
3841116efa8af024cb9fcae059c16e23caea984729fSelim Cinek        cropRect.left = Math.max(0, cropRect.left);
3851116efa8af024cb9fcae059c16e23caea984729fSelim Cinek        cropRect.right = Math.min(rotatedInSize[0], cropRect.right);
3861116efa8af024cb9fcae059c16e23caea984729fSelim Cinek        cropRect.top = Math.max(0, cropRect.top);
3871116efa8af024cb9fcae059c16e23caea984729fSelim Cinek        cropRect.bottom = Math.min(rotatedInSize[1], cropRect.bottom);
3881116efa8af024cb9fcae059c16e23caea984729fSelim Cinek
389f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        // ADJUST CROP WIDTH
390f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        // Extend the crop all the way to the right, for parallax
391f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        // (or all the way to the left, in RTL)
392841a502864d307341945eae62569b92cada93e75Sunny Goyal        float extraSpace = ltr ? rotatedInSize[0] - cropRect.right : cropRect.left;
393f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        // Cap the amount of extra width
394f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        float maxExtraSpace = defaultWallpaperSize.x / cropScale - cropRect.width();
395f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        extraSpace = Math.min(extraSpace, maxExtraSpace);
396f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka
397841a502864d307341945eae62569b92cada93e75Sunny Goyal        if (ltr) {
398841a502864d307341945eae62569b92cada93e75Sunny Goyal            cropRect.right += extraSpace;
399f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        } else {
400841a502864d307341945eae62569b92cada93e75Sunny Goyal            cropRect.left -= extraSpace;
401f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        }
402f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka
403f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        // ADJUST CROP HEIGHT
404f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        if (isPortrait) {
405f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka            cropRect.bottom = cropRect.top + defaultWallpaperSize.y / cropScale;
406f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        } else { // LANDSCAPE
407f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka            float extraPortraitHeight =
408f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                    defaultWallpaperSize.y / cropScale - cropRect.height();
409f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka            float expandHeight =
410f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                    Math.min(Math.min(rotatedInSize[1] - cropRect.bottom, cropRect.top),
411f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka                            extraPortraitHeight / 2);
412f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka            cropRect.top -= expandHeight;
413f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka            cropRect.bottom += expandHeight;
414f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        }
4154428db78eed5d453c3bb376e6e28977c21b1c9ddSunny Goyal
416f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        final int outWidth = (int) Math.round(cropRect.width() * cropScale);
417f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        final int outHeight = (int) Math.round(cropRect.height() * cropScale);
41839d389f406185d91b588c4caf3225749fd2afdcfTony Wickham        CropAndFinishHandler onEndCrop = new CropAndFinishHandler(new Point(outWidth, outHeight),
41939d389f406185d91b588c4caf3225749fd2afdcfTony Wickham                shouldFadeOutOnFinish);
420f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka
421841a502864d307341945eae62569b92cada93e75Sunny Goyal        CropAndSetWallpaperTask cropTask = new CropAndSetWallpaperTask(
422841a502864d307341945eae62569b92cada93e75Sunny Goyal                InputStreamProvider.fromUri(this, uri), this,
4237d21299b0f731db1259f7ee22f36548d5b59fbf9Tony Wickham                cropRect, cropRotation, outWidth, outHeight, onEndCrop) {
4247d21299b0f731db1259f7ee22f36548d5b59fbf9Tony Wickham            @Override
4257d21299b0f731db1259f7ee22f36548d5b59fbf9Tony Wickham            protected void onPreExecute() {
4267d21299b0f731db1259f7ee22f36548d5b59fbf9Tony Wickham                // Give some feedback so user knows something is happening.
4277d21299b0f731db1259f7ee22f36548d5b59fbf9Tony Wickham                mProgressView.setVisibility(View.VISIBLE);
4287d21299b0f731db1259f7ee22f36548d5b59fbf9Tony Wickham            }
4297d21299b0f731db1259f7ee22f36548d5b59fbf9Tony Wickham        };
430f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        if (onBitmapCroppedHandler != null) {
431f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka            cropTask.setOnBitmapCropped(onBitmapCroppedHandler);
432f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka        }
4337d21299b0f731db1259f7ee22f36548d5b59fbf9Tony Wickham        DialogUtils.executeCropTaskAfterPrompt(this, cropTask, getOnDialogCancelListener());
434f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka    }
435f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka
436841a502864d307341945eae62569b92cada93e75Sunny Goyal    public void setBoundsAndFinish(Point bounds, boolean overrideTransition) {
437841a502864d307341945eae62569b92cada93e75Sunny Goyal        WallpaperUtils.saveWallpaperDimensions(bounds.x, bounds.y, this);
438841a502864d307341945eae62569b92cada93e75Sunny Goyal        setResult(Activity.RESULT_OK);
439841a502864d307341945eae62569b92cada93e75Sunny Goyal        finish();
440841a502864d307341945eae62569b92cada93e75Sunny Goyal        if (overrideTransition) {
441841a502864d307341945eae62569b92cada93e75Sunny Goyal            overridePendingTransition(0, R.anim.fade_out);
442841a502864d307341945eae62569b92cada93e75Sunny Goyal        }
443841a502864d307341945eae62569b92cada93e75Sunny Goyal    }
444841a502864d307341945eae62569b92cada93e75Sunny Goyal
445841a502864d307341945eae62569b92cada93e75Sunny Goyal    public class CropAndFinishHandler implements CropAndSetWallpaperTask.OnEndCropHandler {
4464428db78eed5d453c3bb376e6e28977c21b1c9ddSunny Goyal        private final Point mBounds;
44739d389f406185d91b588c4caf3225749fd2afdcfTony Wickham        private boolean mShouldFadeOutOnFinish;
44839d389f406185d91b588c4caf3225749fd2afdcfTony Wickham
44939d389f406185d91b588c4caf3225749fd2afdcfTony Wickham        /**
45039d389f406185d91b588c4caf3225749fd2afdcfTony Wickham         * @param shouldFadeOutOnFinish Whether the wallpaper picker should override the default
45139d389f406185d91b588c4caf3225749fd2afdcfTony Wickham         * exit animation to fade out instead. This should only be set to true if the wallpaper
45239d389f406185d91b588c4caf3225749fd2afdcfTony Wickham         * preview will exactly match the actual wallpaper on the page we are returning to.
45339d389f406185d91b588c4caf3225749fd2afdcfTony Wickham         */
45439d389f406185d91b588c4caf3225749fd2afdcfTony Wickham        public CropAndFinishHandler(Point bounds, boolean shouldFadeOutOnFinish) {
4554428db78eed5d453c3bb376e6e28977c21b1c9ddSunny Goyal            mBounds = bounds;
45639d389f406185d91b588c4caf3225749fd2afdcfTony Wickham            mShouldFadeOutOnFinish = shouldFadeOutOnFinish;
4574428db78eed5d453c3bb376e6e28977c21b1c9ddSunny Goyal        }
4584428db78eed5d453c3bb376e6e28977c21b1c9ddSunny Goyal
4594428db78eed5d453c3bb376e6e28977c21b1c9ddSunny Goyal        @Override
46039d389f406185d91b588c4caf3225749fd2afdcfTony Wickham        public void run(boolean cropSucceeded) {
461841a502864d307341945eae62569b92cada93e75Sunny Goyal            setBoundsAndFinish(mBounds, cropSucceeded && mShouldFadeOutOnFinish);
4624428db78eed5d453c3bb376e6e28977c21b1c9ddSunny Goyal        }
4634428db78eed5d453c3bb376e6e28977c21b1c9ddSunny Goyal    }
4644428db78eed5d453c3bb376e6e28977c21b1c9ddSunny Goyal
4652a218b718e5f498a284341532178c84fe3850e63Sunny Goyal    static class LoadRequest {
4662a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        BitmapSource src;
4672a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        boolean touchEnabled;
4682a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        boolean moveToLeft;
4692a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        Runnable postExecute;
4707bd5e80dc5e26102e59b300dec8dfd8abd9184b4Tony Wickham        CropViewScaleAndOffsetProvider scaleAndOffsetProvider;
4712a218b718e5f498a284341532178c84fe3850e63Sunny Goyal
4722a218b718e5f498a284341532178c84fe3850e63Sunny Goyal        TileSource result;
4732a218b718e5f498a284341532178c84fe3850e63Sunny Goyal    }
4742a218b718e5f498a284341532178c84fe3850e63Sunny Goyal
4757bd5e80dc5e26102e59b300dec8dfd8abd9184b4Tony Wickham    public interface CropViewScaleAndOffsetProvider {
47613d3a076ce25c531c450d139b37b3e5bbd6964e1Tony Wickham        float getScale(Point wallpaperSize, RectF crop);
4777bd5e80dc5e26102e59b300dec8dfd8abd9184b4Tony Wickham        float getParallaxOffset();
4782a218b718e5f498a284341532178c84fe3850e63Sunny Goyal    }
479f1b220be2b401f203cfb490f2e78af32700ef4bbMichael Jurka}
480