1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.gallery3d.gadget;
18
19import android.app.Activity;
20import android.appwidget.AppWidgetManager;
21import android.content.Intent;
22import android.content.res.Resources;
23import android.graphics.Bitmap;
24import android.net.Uri;
25import android.os.Bundle;
26import android.util.Log;
27import android.widget.RemoteViews;
28
29import com.android.gallery3d.R;
30import com.android.gallery3d.app.AlbumPicker;
31import com.android.gallery3d.app.DialogPicker;
32import com.android.gallery3d.app.GalleryApp;
33import com.android.gallery3d.common.ApiHelper;
34import com.android.gallery3d.data.DataManager;
35import com.android.gallery3d.data.LocalAlbum;
36import com.android.gallery3d.data.MediaSet;
37import com.android.gallery3d.data.Path;
38import com.android.gallery3d.filtershow.FilterShowActivity;
39import com.android.gallery3d.filtershow.crop.CropExtras;
40
41public class WidgetConfigure extends Activity {
42    @SuppressWarnings("unused")
43    private static final String TAG = "WidgetConfigure";
44
45    public static final String KEY_WIDGET_TYPE = "widget-type";
46    private static final String KEY_PICKED_ITEM = "picked-item";
47
48    private static final int REQUEST_WIDGET_TYPE = 1;
49    private static final int REQUEST_CHOOSE_ALBUM = 2;
50    private static final int REQUEST_CROP_IMAGE = 3;
51    private static final int REQUEST_GET_PHOTO = 4;
52
53    public static final int RESULT_ERROR = RESULT_FIRST_USER;
54
55    // Scale up the widget size since we only specified the minimized
56    // size of the gadget. The real size could be larger.
57    // Note: There is also a limit on the size of data that can be
58    // passed in Binder's transaction.
59    private static float WIDGET_SCALE_FACTOR = 1.5f;
60    private static int MAX_WIDGET_SIDE = 360;
61
62    private int mAppWidgetId = -1;
63    private Uri mPickedItem;
64
65    @Override
66    protected void onCreate(Bundle savedState) {
67        super.onCreate(savedState);
68        mAppWidgetId = getIntent().getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
69
70        if (mAppWidgetId == -1) {
71            setResult(Activity.RESULT_CANCELED);
72            finish();
73            return;
74        }
75
76        if (savedState == null) {
77            if (ApiHelper.HAS_REMOTE_VIEWS_SERVICE) {
78                Intent intent = new Intent(this, WidgetTypeChooser.class);
79                startActivityForResult(intent, REQUEST_WIDGET_TYPE);
80            } else { // Choose the photo type widget
81                setWidgetType(new Intent()
82                        .putExtra(KEY_WIDGET_TYPE, R.id.widget_type_photo));
83            }
84        } else {
85            mPickedItem = savedState.getParcelable(KEY_PICKED_ITEM);
86        }
87    }
88
89    protected void onSaveInstanceStates(Bundle outState) {
90        super.onSaveInstanceState(outState);
91        outState.putParcelable(KEY_PICKED_ITEM, mPickedItem);
92    }
93
94    private void updateWidgetAndFinish(WidgetDatabaseHelper.Entry entry) {
95        AppWidgetManager manager = AppWidgetManager.getInstance(this);
96        RemoteViews views = PhotoAppWidgetProvider.buildWidget(this, mAppWidgetId, entry);
97        manager.updateAppWidget(mAppWidgetId, views);
98        setResult(RESULT_OK, new Intent().putExtra(
99                AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId));
100        finish();
101    }
102
103    @Override
104    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
105        if (resultCode != RESULT_OK) {
106            setResult(resultCode, new Intent().putExtra(
107                    AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId));
108            finish();
109            return;
110        }
111
112        if (requestCode == REQUEST_WIDGET_TYPE) {
113            setWidgetType(data);
114        } else if (requestCode == REQUEST_CHOOSE_ALBUM) {
115            setChoosenAlbum(data);
116        } else if (requestCode == REQUEST_GET_PHOTO) {
117            setChoosenPhoto(data);
118        } else if (requestCode == REQUEST_CROP_IMAGE) {
119            setPhotoWidget(data);
120        } else {
121            throw new AssertionError("unknown request: " + requestCode);
122        }
123    }
124
125    private void setPhotoWidget(Intent data) {
126        // Store the cropped photo in our database
127        Bitmap bitmap = (Bitmap) data.getParcelableExtra("data");
128        WidgetDatabaseHelper helper = new WidgetDatabaseHelper(this);
129        try {
130            helper.setPhoto(mAppWidgetId, mPickedItem, bitmap);
131            updateWidgetAndFinish(helper.getEntry(mAppWidgetId));
132        } finally {
133            helper.close();
134        }
135    }
136
137    private void setChoosenPhoto(Intent data) {
138        Resources res = getResources();
139
140        float width = res.getDimension(R.dimen.appwidget_width);
141        float height = res.getDimension(R.dimen.appwidget_height);
142
143        // We try to crop a larger image (by scale factor), but there is still
144        // a bound on the binder limit.
145        float scale = Math.min(WIDGET_SCALE_FACTOR,
146                MAX_WIDGET_SIDE / Math.max(width, height));
147
148        int widgetWidth = Math.round(width * scale);
149        int widgetHeight = Math.round(height * scale);
150
151        mPickedItem = data.getData();
152        Intent request = new Intent(FilterShowActivity.CROP_ACTION, mPickedItem)
153                .putExtra(CropExtras.KEY_OUTPUT_X, widgetWidth)
154                .putExtra(CropExtras.KEY_OUTPUT_Y, widgetHeight)
155                .putExtra(CropExtras.KEY_ASPECT_X, widgetWidth)
156                .putExtra(CropExtras.KEY_ASPECT_Y, widgetHeight)
157                .putExtra(CropExtras.KEY_SCALE_UP_IF_NEEDED, true)
158                .putExtra(CropExtras.KEY_SCALE, true)
159                .putExtra(CropExtras.KEY_RETURN_DATA, true);
160        startActivityForResult(request, REQUEST_CROP_IMAGE);
161    }
162
163    private void setChoosenAlbum(Intent data) {
164        String albumPath = data.getStringExtra(AlbumPicker.KEY_ALBUM_PATH);
165        WidgetDatabaseHelper helper = new WidgetDatabaseHelper(this);
166        try {
167            String relativePath = null;
168            GalleryApp galleryApp = (GalleryApp) getApplicationContext();
169            DataManager manager = galleryApp.getDataManager();
170            Path path = Path.fromString(albumPath);
171            MediaSet mediaSet = (MediaSet) manager.getMediaObject(path);
172            if (mediaSet instanceof LocalAlbum) {
173                int bucketId = Integer.parseInt(path.getSuffix());
174                // If the chosen album is a local album, find relative path
175                // Otherwise, leave the relative path field empty
176                relativePath = LocalAlbum.getRelativePath(bucketId);
177                Log.i(TAG, "Setting widget, album path: " + albumPath
178                        + ", relative path: " + relativePath);
179            }
180            helper.setWidget(mAppWidgetId,
181                    WidgetDatabaseHelper.TYPE_ALBUM, albumPath, relativePath);
182            updateWidgetAndFinish(helper.getEntry(mAppWidgetId));
183        } finally {
184            helper.close();
185        }
186    }
187
188    private void setWidgetType(Intent data) {
189        int widgetType = data.getIntExtra(KEY_WIDGET_TYPE, R.id.widget_type_shuffle);
190        if (widgetType == R.id.widget_type_album) {
191            Intent intent = new Intent(this, AlbumPicker.class);
192            startActivityForResult(intent, REQUEST_CHOOSE_ALBUM);
193        } else if (widgetType == R.id.widget_type_shuffle) {
194            WidgetDatabaseHelper helper = new WidgetDatabaseHelper(this);
195            try {
196                helper.setWidget(mAppWidgetId, WidgetDatabaseHelper.TYPE_SHUFFLE, null, null);
197                updateWidgetAndFinish(helper.getEntry(mAppWidgetId));
198            } finally {
199                helper.close();
200            }
201        } else {
202            // Explicitly send the intent to the DialogPhotoPicker
203            Intent request = new Intent(this, DialogPicker.class)
204                    .setAction(Intent.ACTION_GET_CONTENT)
205                    .setType("image/*");
206            startActivityForResult(request, REQUEST_GET_PHOTO);
207        }
208    }
209}
210