FilterShowActivity.java revision 12c7c8ed14ca9dff9de64e121282f1970cbe7ae4
1a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen/*
2a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen * Copyright (C) 2012 The Android Open Source Project
3a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen *
4a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen * Licensed under the Apache License, Version 2.0 (the "License");
5a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen * you may not use this file except in compliance with the License.
6a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen * You may obtain a copy of the License at
7a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen *
8a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen *      http://www.apache.org/licenses/LICENSE-2.0
9a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen *
10a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen * Unless required by applicable law or agreed to in writing, software
11a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen * distributed under the License is distributed on an "AS IS" BASIS,
12a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen * See the License for the specific language governing permissions and
14a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen * limitations under the License.
15a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen */
16a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen
17a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissenpackage com.android.gallery3d.filtershow;
18a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen
19a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissenimport android.annotation.TargetApi;
20a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissenimport android.app.ActionBar;
21a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissenimport android.app.Activity;
22a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissenimport android.app.ProgressDialog;
23a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissenimport android.app.WallpaperManager;
24a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissenimport android.content.ContentValues;
25a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissenimport android.content.Context;
26a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissenimport android.content.Intent;
27b1cf03160fa7e7bc6e5cf138db07a7e1ab2ecb26Marco Nelissenimport android.content.res.Configuration;
28d5fa8d5dcdf8742f03fdc165f7529d7627b0eb01Marco Nelissenimport android.content.res.Resources;
29b1cf03160fa7e7bc6e5cf138db07a7e1ab2ecb26Marco Nelissenimport android.graphics.Bitmap;
30b1cf03160fa7e7bc6e5cf138db07a7e1ab2ecb26Marco Nelissenimport android.graphics.BitmapFactory;
31b1cf03160fa7e7bc6e5cf138db07a7e1ab2ecb26Marco Nelissenimport android.graphics.Color;
32b1cf03160fa7e7bc6e5cf138db07a7e1ab2ecb26Marco Nelissenimport android.graphics.Point;
33b1cf03160fa7e7bc6e5cf138db07a7e1ab2ecb26Marco Nelissenimport android.graphics.drawable.BitmapDrawable;
34b1cf03160fa7e7bc6e5cf138db07a7e1ab2ecb26Marco Nelissenimport android.graphics.drawable.Drawable;
35b1cf03160fa7e7bc6e5cf138db07a7e1ab2ecb26Marco Nelissenimport android.net.Uri;
36b1cf03160fa7e7bc6e5cf138db07a7e1ab2ecb26Marco Nelissenimport android.os.AsyncTask;
37d5fa8d5dcdf8742f03fdc165f7529d7627b0eb01Marco Nelissenimport android.os.Bundle;
38b1cf03160fa7e7bc6e5cf138db07a7e1ab2ecb26Marco Nelissenimport android.provider.MediaStore;
39b1cf03160fa7e7bc6e5cf138db07a7e1ab2ecb26Marco Nelissenimport android.util.DisplayMetrics;
40b1cf03160fa7e7bc6e5cf138db07a7e1ab2ecb26Marco Nelissenimport android.util.Log;
41b1cf03160fa7e7bc6e5cf138db07a7e1ab2ecb26Marco Nelissenimport android.util.TypedValue;
42b1cf03160fa7e7bc6e5cf138db07a7e1ab2ecb26Marco Nelissenimport android.view.Display;
43b1cf03160fa7e7bc6e5cf138db07a7e1ab2ecb26Marco Nelissenimport android.view.LayoutInflater;
44b1cf03160fa7e7bc6e5cf138db07a7e1ab2ecb26Marco Nelissenimport android.view.Menu;
45b1cf03160fa7e7bc6e5cf138db07a7e1ab2ecb26Marco Nelissenimport android.view.MenuItem;
46b1cf03160fa7e7bc6e5cf138db07a7e1ab2ecb26Marco Nelissenimport android.view.View;
47d5fa8d5dcdf8742f03fdc165f7529d7627b0eb01Marco Nelissenimport android.view.View.OnClickListener;
48a6cdabf38b29ee98bdb3e874b4e2978dbc409624Marco Nelissenimport android.view.WindowManager;
49a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissenimport android.widget.*;
50cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissenimport android.widget.AdapterView.OnItemClickListener;
51b1cf03160fa7e7bc6e5cf138db07a7e1ab2ecb26Marco Nelissenimport android.widget.ShareActionProvider.OnShareTargetSelectedListener;
52b1cf03160fa7e7bc6e5cf138db07a7e1ab2ecb26Marco Nelissen
53a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissenimport com.android.gallery3d.R;
54a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissenimport com.android.gallery3d.data.LocalAlbum;
55a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissenimport com.android.gallery3d.filtershow.cache.FilteringPipeline;
56a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissenimport com.android.gallery3d.filtershow.cache.ImageLoader;
57a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissenimport com.android.gallery3d.filtershow.editors.BasicEditor;
58a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissenimport com.android.gallery3d.filtershow.editors.EditorDraw;
59a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissenimport com.android.gallery3d.filtershow.editors.EditorManager;
60b1cf03160fa7e7bc6e5cf138db07a7e1ab2ecb26Marco Nelissenimport com.android.gallery3d.filtershow.editors.EditorRedEye;
61b1cf03160fa7e7bc6e5cf138db07a7e1ab2ecb26Marco Nelissenimport com.android.gallery3d.filtershow.editors.ImageOnlyEditor;
62b1cf03160fa7e7bc6e5cf138db07a7e1ab2ecb26Marco Nelissenimport com.android.gallery3d.filtershow.editors.EditorTinyPlanet;
63b1cf03160fa7e7bc6e5cf138db07a7e1ab2ecb26Marco Nelissenimport com.android.gallery3d.filtershow.filters.*;
64b1cf03160fa7e7bc6e5cf138db07a7e1ab2ecb26Marco Nelissenimport com.android.gallery3d.filtershow.imageshow.ImageCrop;
65a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissenimport com.android.gallery3d.filtershow.imageshow.ImageDraw;
66a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissenimport com.android.gallery3d.filtershow.imageshow.ImageFlip;
67a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissenimport com.android.gallery3d.filtershow.imageshow.ImageRedEye;
68a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissenimport com.android.gallery3d.filtershow.imageshow.ImageRotate;
69a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissenimport com.android.gallery3d.filtershow.imageshow.ImageShow;
70a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissenimport com.android.gallery3d.filtershow.imageshow.ImageStraighten;
71a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissenimport com.android.gallery3d.filtershow.imageshow.ImageTinyPlanet;
72a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissenimport com.android.gallery3d.filtershow.imageshow.ImageZoom;
73a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissenimport com.android.gallery3d.filtershow.imageshow.MasterImage;
74a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissenimport com.android.gallery3d.filtershow.presets.ImagePreset;
75a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissenimport com.android.gallery3d.filtershow.provider.SharedImageProvider;
76a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissenimport com.android.gallery3d.filtershow.tools.SaveCopyTask;
77a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissenimport com.android.gallery3d.filtershow.ui.FilterIconButton;
78a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissenimport com.android.gallery3d.filtershow.ui.FramedTextButton;
79a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissenimport com.android.gallery3d.filtershow.ui.Spline;
80a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissenimport com.android.gallery3d.util.GalleryUtils;
81a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen
82a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissenimport java.io.File;
83a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissenimport java.io.IOException;
84a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissenimport java.lang.ref.WeakReference;
85a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissenimport java.util.Vector;
86a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen
87a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen@TargetApi(16)
88a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissenpublic class FilterShowActivity extends Activity implements OnItemClickListener,
89a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        OnShareTargetSelectedListener {
90a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen
917e34bf5af26f8752d4786d3098740cdf51e2438fWonsik Kim    // fields for supporting crop action
927e34bf5af26f8752d4786d3098740cdf51e2438fWonsik Kim    public static final String CROP_ACTION = "com.android.camera.action.CROP";
93b1cf03160fa7e7bc6e5cf138db07a7e1ab2ecb26Marco Nelissen    private CropExtras mCropExtras = null;
94b1cf03160fa7e7bc6e5cf138db07a7e1ab2ecb26Marco Nelissen    MasterImage mMasterImage = null;
95b1cf03160fa7e7bc6e5cf138db07a7e1ab2ecb26Marco Nelissen
96b1cf03160fa7e7bc6e5cf138db07a7e1ab2ecb26Marco Nelissen    public static final String TINY_PLANET_ACTION = "com.android.camera.action.TINY_PLANET";
97b1cf03160fa7e7bc6e5cf138db07a7e1ab2ecb26Marco Nelissen    public static final String LAUNCH_FULLSCREEN = "launch-fullscreen";
98cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen    public static final int MAX_BMAP_IN_INTENT = 990000;
99cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen    private final PanelController mPanelController = new PanelController();
100cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen    private ImageLoader mImageLoader = null;
101cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen    private ImageShow mImageShow = null;
102cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen    private ImageRedEye mImageRedEye = null;
103cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen    private ImageDraw mImageDraw = null;
104cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen    private ImageStraighten mImageStraighten = null;
105cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen    private ImageCrop mImageCrop = null;
106cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen    private ImageRotate mImageRotate = null;
107cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen    private ImageFlip mImageFlip = null;
108cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen    private ImageTinyPlanet mImageTinyPlanet = null;
109cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen
110cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen    private View mListFx = null;
111cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen    private View mListBorders = null;
112cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen    private View mListGeometry = null;
113cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen    private View mListColors = null;
114cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen    private View mListFilterButtons = null;
115cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen    private View mSaveButton = null;
116cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen
117cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen    private ImageButton mFxButton = null;
118cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen    private ImageButton mBorderButton = null;
119cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen    private ImageButton mGeometryButton = null;
120cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen    private ImageButton mColorsButton = null;
121cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen
122cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen    private LinearLayout listColors = null;
123cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen    private LinearLayout listFilters = null;
1247e34bf5af26f8752d4786d3098740cdf51e2438fWonsik Kim    private LinearLayout listBorders = null;
1257e34bf5af26f8752d4786d3098740cdf51e2438fWonsik Kim
1267e34bf5af26f8752d4786d3098740cdf51e2438fWonsik Kim    private EditorPlaceHolder mEditorPlaceHolder = new EditorPlaceHolder(this);
1277e34bf5af26f8752d4786d3098740cdf51e2438fWonsik Kim
1287e34bf5af26f8752d4786d3098740cdf51e2438fWonsik Kim    private static final int SELECT_PICTURE = 1;
1297e34bf5af26f8752d4786d3098740cdf51e2438fWonsik Kim    private static final String LOGTAG = "FilterShowActivity";
1307e34bf5af26f8752d4786d3098740cdf51e2438fWonsik Kim    protected static final boolean ANIMATE_PANELS = true;
1317e34bf5af26f8752d4786d3098740cdf51e2438fWonsik Kim    private static int mImageBorderSize = 4; // in percent
132a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen
133a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen    private boolean mShowingHistoryPanel = false;
134a6cdabf38b29ee98bdb3e874b4e2978dbc409624Marco Nelissen    private boolean mShowingImageStatePanel = false;
135a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen
136a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen    private final Vector<ImageShow> mImageViews = new Vector<ImageShow>();
137a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen    private final Vector<View> mListViews = new Vector<View>();
138a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen    private final Vector<ImageButton> mBottomPanelButtons = new Vector<ImageButton>();
139a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen
140a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen    private ShareActionProvider mShareActionProvider;
141cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen    private File mSharedOutputFile = null;
142cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen
143cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen    private boolean mSharingImage = false;
144cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen
145cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen    private WeakReference<ProgressDialog> mSavingProgressDialog;
146cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen    private static final int SEEK_BAR_MAX = 600;
147cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen
148cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen    private LoadBitmapTask mLoadBitmapTask;
149cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen    private FilterIconButton mNullFxFilter;
150cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen    private FilterIconButton mNullBorderFilter;
151cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen    private int mIconSeedSize = 140;
152cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen
153cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen    @Override
154a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen    public void onCreate(Bundle savedInstanceState) {
155a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        super.onCreate(savedInstanceState);
156a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        setResources();
157a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen
158a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        Resources res = getResources();
159a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        setupMasterImage();
160a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        ImageFilterRS.setRenderScriptContext(this);
161a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen
162a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        ImageShow.setDefaultBackgroundColor(res.getColor(R.color.background_screen));
163a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        // TODO: get those values from XML.
164a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        ImageZoom.setZoomedSize(getPixelsFromDip(256));
165a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        FramedTextButton.setTextSize((int) getPixelsFromDip(14));
166a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        FramedTextButton.setTrianglePadding((int) getPixelsFromDip(4));
167a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        FramedTextButton.setTriangleSize((int) getPixelsFromDip(10));
168a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        ImageShow.setTextSize((int) getPixelsFromDip(12));
169a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        ImageShow.setTextPadding((int) getPixelsFromDip(10));
170a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        ImageShow.setOriginalTextMargin((int) getPixelsFromDip(4));
171a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        ImageShow.setOriginalTextSize((int) getPixelsFromDip(18));
172a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        ImageShow.setOriginalText(res.getString(R.string.original_picture_text));
173a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        mIconSeedSize = res.getDimensionPixelSize(R.dimen.thumbnail_size);
174a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen
175a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        Drawable curveHandle = res.getDrawable(R.drawable.camera_crop);
176a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        int curveHandleSize = (int) res.getDimension(R.dimen.crop_indicator_size);
177a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        Spline.setCurveHandle(curveHandle, curveHandleSize);
178a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        Spline.setCurveWidth((int) getPixelsFromDip(3));
179cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen
180a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        setContentView(R.layout.filtershow_activity);
181a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        ActionBar actionBar = getActionBar();
182a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
183a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        actionBar.setCustomView(R.layout.filtershow_actionbar);
184a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen
185a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        mSaveButton = actionBar.getCustomView();
186a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        mSaveButton.setOnClickListener(new OnClickListener() {
187a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen            @Override
188a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen            public void onClick(View view) {
189a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen                saveImage();
190a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen            }
191a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        });
192a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen
193a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        mImageLoader = new ImageLoader(this, getApplicationContext());
194a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen
195a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        listFilters = (LinearLayout) findViewById(R.id.listFilters);
196a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        listBorders = (LinearLayout) findViewById(R.id.listBorders);
197a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        listColors = (LinearLayout) findViewById(R.id.listColorsFx);
198a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen
199a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        mImageShow = (ImageShow) findViewById(R.id.imageShow);
200a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        mImageStraighten = (ImageStraighten) findViewById(R.id.imageStraighten);
201a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        mImageCrop = (ImageCrop) findViewById(R.id.imageCrop);
202a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        mImageRotate = (ImageRotate) findViewById(R.id.imageRotate);
203a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        mImageFlip = (ImageFlip) findViewById(R.id.imageFlip);
204a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        mImageTinyPlanet = (ImageTinyPlanet) findViewById(R.id.imageTinyPlanet);
205a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        mImageRedEye = (ImageRedEye) findViewById(R.id.imageRedEyes);
206a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        mImageDraw = (ImageDraw) findViewById(R.id.imageDraw);
207
208        mImageCrop.setAspectTextSize((int) getPixelsFromDip(18));
209        ImageCrop.setTouchTolerance((int) getPixelsFromDip(25));
210        ImageCrop.setMinCropSize((int) getPixelsFromDip(55));
211        mImageViews.add(mImageShow);
212        mImageViews.add(mImageStraighten);
213        mImageViews.add(mImageCrop);
214        mImageViews.add(mImageRotate);
215        mImageViews.add(mImageFlip);
216        mImageViews.add(mImageTinyPlanet);
217        mImageViews.add(mImageRedEye);
218
219        mEditorPlaceHolder.setContainer((FrameLayout) findViewById(R.id.editorContainer));
220        mEditorPlaceHolder.addEditor(new EditorDraw());
221        mEditorPlaceHolder.addEditor(new BasicEditor());
222        mEditorPlaceHolder.addEditor(new ImageOnlyEditor());
223        mEditorPlaceHolder.addEditor(new EditorTinyPlanet());
224        mEditorPlaceHolder.addEditor(new EditorRedEye());
225        EditorManager.addEditors(mEditorPlaceHolder);
226        mEditorPlaceHolder.setOldViews(mImageViews);
227        mEditorPlaceHolder.setImageLoader(mImageLoader);
228
229        mEditorPlaceHolder.hide();
230
231        mListFx = findViewById(R.id.fxList);
232        mListBorders = findViewById(R.id.bordersList);
233        mListGeometry = findViewById(R.id.geometryList);
234        mListFilterButtons = findViewById(R.id.filterButtonsList);
235        mListColors = findViewById(R.id.colorsFxList);
236        mListViews.add(mListFx);
237        mListViews.add(mListBorders);
238        mListViews.add(mListGeometry);
239        mListViews.add(mListFilterButtons);
240        mListViews.add(mListColors);
241
242        mFxButton = (ImageButton) findViewById(R.id.fxButton);
243        mBorderButton = (ImageButton) findViewById(R.id.borderButton);
244        mGeometryButton = (ImageButton) findViewById(R.id.geometryButton);
245        mColorsButton = (ImageButton) findViewById(R.id.colorsButton);
246
247        mBottomPanelButtons.add(mFxButton);
248        mBottomPanelButtons.add(mBorderButton);
249        mBottomPanelButtons.add(mGeometryButton);
250        mBottomPanelButtons.add(mColorsButton);
251
252        mImageShow.setImageLoader(mImageLoader);
253        mImageStraighten.setImageLoader(mImageLoader);
254        mImageCrop.setImageLoader(mImageLoader);
255        mImageRotate.setImageLoader(mImageLoader);
256        mImageFlip.setImageLoader(mImageLoader);
257        mImageTinyPlanet.setImageLoader(mImageLoader);
258        mImageRedEye.setImageLoader(mImageLoader);
259        mImageDraw.setImageLoader(mImageLoader);
260
261        mPanelController.setActivity(this);
262        mPanelController.setEditorPlaceHolder(mEditorPlaceHolder);
263
264        mPanelController.addImageView(findViewById(R.id.imageShow));
265        mPanelController.addImageView(findViewById(R.id.imageStraighten));
266        mPanelController.addImageView(findViewById(R.id.imageCrop));
267        mPanelController.addImageView(findViewById(R.id.imageRotate));
268        mPanelController.addImageView(findViewById(R.id.imageFlip));
269        mPanelController.addImageView(findViewById(R.id.imageTinyPlanet));
270        mPanelController.addImageView(findViewById(R.id.imageRedEyes));
271        mPanelController.addImageView(findViewById(R.id.imageDraw));
272
273        mPanelController.addPanel(mFxButton, mListFx, 0);
274        mPanelController.addPanel(mBorderButton, mListBorders, 1);
275
276        mPanelController.addPanel(mGeometryButton, mListGeometry, 2);
277        mPanelController.addComponent(mGeometryButton, findViewById(R.id.straightenButton));
278        mPanelController.addComponent(mGeometryButton, findViewById(R.id.cropButton));
279        mPanelController.addComponent(mGeometryButton, findViewById(R.id.rotateButton));
280        mPanelController.addComponent(mGeometryButton, findViewById(R.id.flipButton));
281        mPanelController.addComponent(mGeometryButton, findViewById(R.id.redEyeButton));
282
283        mPanelController.addPanel(mColorsButton, mListColors, 3);
284
285        Vector<FilterRepresentation> filtersRepresentations = new Vector<FilterRepresentation>();
286        FiltersManager.addFilterRepresentations(filtersRepresentations);
287        for (FilterRepresentation representation : filtersRepresentations) {
288            setupFilterRepresentationButton(representation, listColors, mColorsButton);
289        }
290
291
292        mPanelController.addView(findViewById(R.id.applyEffect));
293        findViewById(R.id.resetOperationsButton).setOnClickListener(
294                createOnClickResetOperationsButton());
295
296        ListView operationsList = (ListView) findViewById(R.id.operationsList);
297        operationsList.setAdapter(mMasterImage.getHistory());
298        operationsList.setOnItemClickListener(this);
299        ListView imageStateList = (ListView) findViewById(R.id.imageStateList);
300        imageStateList.setAdapter(mMasterImage.getState());
301        mImageLoader.setAdapter(mMasterImage.getHistory());
302
303        fillListImages(listFilters);
304        LoadBordersTask loadBorders = new LoadBordersTask(listBorders);
305        loadBorders.execute();
306
307        mPanelController.setRowPanel(findViewById(R.id.secondRowPanel));
308        mPanelController.setUtilityPanel(this, findViewById(R.id.filterButtonsList),
309                findViewById(R.id.panelAccessoryViewList),
310                findViewById(R.id.applyEffect));
311
312        mPanelController.setCurrentPanel(mFxButton);
313        Intent intent = getIntent();
314        if (intent.getBooleanExtra(LAUNCH_FULLSCREEN, false)) {
315            getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
316        }
317
318        if (intent.getData() != null) {
319            startLoadBitmap(intent.getData());
320        } else {
321            pickImage();
322        }
323
324        // Handle behavior for various actions
325        String action = intent.getAction();
326        if (action.equalsIgnoreCase(CROP_ACTION)) {
327            Bundle extras = intent.getExtras();
328            if (extras != null) {
329                mCropExtras = new CropExtras(extras.getInt(CropExtras.KEY_OUTPUT_X, 0),
330                        extras.getInt(CropExtras.KEY_OUTPUT_Y, 0),
331                        extras.getBoolean(CropExtras.KEY_SCALE, true) &&
332                                extras.getBoolean(CropExtras.KEY_SCALE_UP_IF_NEEDED, false),
333                        extras.getInt(CropExtras.KEY_ASPECT_X, 0),
334                        extras.getInt(CropExtras.KEY_ASPECT_Y, 0),
335                        extras.getBoolean(CropExtras.KEY_SET_AS_WALLPAPER, false),
336                        extras.getBoolean(CropExtras.KEY_RETURN_DATA, false),
337                        (Uri) extras.getParcelable(MediaStore.EXTRA_OUTPUT),
338                        extras.getString(CropExtras.KEY_OUTPUT_FORMAT),
339                        extras.getBoolean(CropExtras.KEY_SHOW_WHEN_LOCKED, false),
340                        extras.getFloat(CropExtras.KEY_SPOTLIGHT_X),
341                        extras.getFloat(CropExtras.KEY_SPOTLIGHT_Y));
342
343                if (mCropExtras.getShowWhenLocked()) {
344                    getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
345                }
346                mImageShow.getImagePreset().mGeoData.setCropExtras(mCropExtras);
347
348                mImageCrop.setExtras(mCropExtras);
349                String s = getString(R.string.Fixed);
350                mImageCrop.setAspectString(s);
351                mImageCrop.setCropActionFlag(true);
352                mPanelController.setFixedAspect(mCropExtras.getAspectX() > 0
353                        && mCropExtras.getAspectY() > 0);
354            }
355            mPanelController.showComponent(findViewById(R.id.cropButton));
356        } else if (action.equalsIgnoreCase(TINY_PLANET_ACTION)) {
357            mPanelController.showComponent(findViewById(R.id.tinyplanetButton));
358        }
359    }
360
361    private void startLoadBitmap(Uri uri) {
362        final View filters = findViewById(R.id.filtersPanel);
363        final View loading = findViewById(R.id.loading);
364        final View imageShow = findViewById(R.id.imageShow);
365        imageShow.setVisibility(View.INVISIBLE);
366        filters.setVisibility(View.INVISIBLE);
367        loading.setVisibility(View.VISIBLE);
368
369        View tinyPlanetView = findViewById(R.id.tinyplanetButton);
370        if (tinyPlanetView != null) {
371            tinyPlanetView.setVisibility(View.GONE);
372        }
373        mLoadBitmapTask = new LoadBitmapTask(tinyPlanetView);
374        mLoadBitmapTask.execute(uri);
375    }
376
377    private class LoadBordersTask extends AsyncTask<Void, Boolean, Boolean> {
378        Vector<FilterRepresentation> mBorders;
379        LinearLayout mList;
380
381        public LoadBordersTask(LinearLayout list) {
382            mList = list;
383            mBorders = new Vector<FilterRepresentation>();
384        }
385
386        @Override
387        protected Boolean doInBackground(Void... params) {
388            mBorders.add(new FilterImageBorderRepresentation(0));
389            mBorders.add(new FilterImageBorderRepresentation(R.drawable.filtershow_border_4x5));
390            mBorders.add(new FilterImageBorderRepresentation(R.drawable.filtershow_border_brush));
391            mBorders.add(new FilterImageBorderRepresentation(R.drawable.filtershow_border_grunge));
392            mBorders.add(new FilterImageBorderRepresentation(R.drawable.filtershow_border_sumi_e));
393            mBorders.add(new FilterImageBorderRepresentation(R.drawable.filtershow_border_tape));
394            mBorders.add(new FilterColorBorderRepresentation(Color.BLACK, mImageBorderSize, 0));
395            mBorders.add(new FilterColorBorderRepresentation(Color.BLACK, mImageBorderSize, mImageBorderSize));
396            mBorders.add(new FilterColorBorderRepresentation(Color.WHITE, mImageBorderSize, 0));
397            mBorders.add(new FilterColorBorderRepresentation(Color.WHITE, mImageBorderSize, mImageBorderSize));
398            int creamColor = Color.argb(255, 237, 237, 227);
399            mBorders.add(new FilterColorBorderRepresentation(creamColor, mImageBorderSize, 0));
400            mBorders.add(new FilterColorBorderRepresentation(creamColor, mImageBorderSize, mImageBorderSize));
401            return true;
402        }
403
404        @Override
405        protected void onPostExecute(Boolean result) {
406            if (!result) {
407                return;
408            }
409            for (int i = 0; i < mBorders.size(); i++) {
410                FilterRepresentation filter = mBorders.elementAt(i);
411                filter.setName(getString(R.string.borders));
412                if (i == 0) {
413                    filter.setName(getString(R.string.none));
414                }
415                FilterIconButton b = setupFilterRepresentationButton(filter, mList, mBorderButton);
416                if (i == 0) {
417                    mNullBorderFilter = b;
418                    mNullBorderFilter.setSelected(true);
419                }
420            }
421        }
422    }
423
424    private class LoadBitmapTask extends AsyncTask<Uri, Boolean, Boolean> {
425        View mTinyPlanetButton;
426        int mBitmapSize;
427
428        public LoadBitmapTask(View button) {
429            mTinyPlanetButton = button;
430            mBitmapSize = getScreenImageSize();
431        }
432
433        @Override
434        protected Boolean doInBackground(Uri... params) {
435            if (!mImageLoader.loadBitmap(params[0], mBitmapSize)) {
436                return false;
437            }
438            publishProgress(mImageLoader.queryLightCycle360());
439            return true;
440        }
441
442        @Override
443        protected void onProgressUpdate(Boolean... values) {
444            super.onProgressUpdate(values);
445            if (isCancelled()) {
446                return;
447            }
448            if (values[0]) {
449                mTinyPlanetButton.setVisibility(View.VISIBLE);
450            }
451        }
452
453        @Override
454        protected void onPostExecute(Boolean result) {
455
456            if (isCancelled()) {
457                return;
458            }
459
460            if (!result) {
461                cannotLoadImage();
462            }
463
464            final View loading = findViewById(R.id.loading);
465            loading.setVisibility(View.GONE);
466            final View filters = findViewById(R.id.filtersPanel);
467            filters.setVisibility(View.VISIBLE);
468            float y = filters.getY();
469            filters.setY(y + filters.getHeight());
470            filters.animate().setDuration(600).y(y).withLayer().start();
471            final View imageShow = findViewById(R.id.imageShow);
472            imageShow.setVisibility(View.VISIBLE);
473
474            Bitmap largeBitmap = mImageLoader.getOriginalBitmapLarge();
475            FilteringPipeline pipeline = FilteringPipeline.getPipeline();
476            pipeline.setOriginal(largeBitmap);
477            float previewScale = (float) largeBitmap.getWidth() / (float) mImageLoader.getOriginalBounds().width();
478            pipeline.setPreviewScaleFactor(previewScale);
479
480            Bitmap bmap = mImageLoader.getOriginalBitmapSmall();
481            if (bmap != null && bmap.getWidth() > 0 && bmap.getHeight() > 0) {
482                float w = bmap.getWidth();
483                float h = bmap.getHeight();
484                float f = mIconSeedSize / Math.min(w, h);
485                w = w * f;
486                h = h * f;
487                bmap = Bitmap.createScaledBitmap(bmap, (int) w, (int) h, true);
488
489                int num_colors_buttons = listColors.getChildCount();
490                for (int i = 0; i < num_colors_buttons; i++) {
491                    FilterIconButton b = (FilterIconButton) listColors.getChildAt(i);
492
493                    b.setIcon(bmap);
494                }
495                int num_filters_buttons = listFilters.getChildCount();
496                for (int i = 0; i < num_filters_buttons; i++) {
497                    FilterIconButton b = (FilterIconButton) listFilters.getChildAt(i);
498
499                    b.setIcon(bmap);
500                }
501                int num_borders_buttons = listBorders.getChildCount();
502                for (int i = 0; i < num_borders_buttons; i++) {
503                    FilterIconButton b = (FilterIconButton) listBorders.getChildAt(i);
504
505                    b.setIcon(bmap);
506                }
507
508            }
509            mLoadBitmapTask = null;
510            super.onPostExecute(result);
511        }
512
513    }
514
515    @Override
516    protected void onDestroy() {
517        if (mLoadBitmapTask != null) {
518            mLoadBitmapTask.cancel(false);
519        }
520        super.onDestroy();
521    }
522
523    private int translateMainPanel(View viewPanel) {
524        int accessoryPanelWidth = viewPanel.getWidth();
525        int mainViewWidth = findViewById(R.id.mainView).getWidth();
526        int mainPanelWidth = mImageShow.getDisplayedImageBounds().width();
527        if (mainPanelWidth == 0) {
528            mainPanelWidth = mainViewWidth;
529        }
530        int filtersPanelWidth = findViewById(R.id.filtersPanel).getWidth();
531        if (mainPanelWidth < filtersPanelWidth) {
532            mainPanelWidth = filtersPanelWidth;
533        }
534        int leftOver = mainViewWidth - mainPanelWidth - accessoryPanelWidth;
535        if (leftOver < 0) {
536            return -accessoryPanelWidth;
537        }
538        return 0;
539    }
540
541    private int getScreenImageSize() {
542        DisplayMetrics metrics = new DisplayMetrics();
543        Display display = getWindowManager().getDefaultDisplay();
544        Point size = new Point();
545        display.getSize(size);
546        display.getMetrics(metrics);
547        int msize = Math.min(size.x, size.y);
548        return (133 * msize) / metrics.densityDpi;
549    }
550
551    private void showSavingProgress(String albumName) {
552        ProgressDialog progress;
553        if (mSavingProgressDialog != null) {
554            progress = mSavingProgressDialog.get();
555            if (progress != null) {
556                progress.show();
557                return;
558            }
559        }
560        // TODO: Allow cancellation of the saving process
561        String progressText;
562        if (albumName == null) {
563            progressText = getString(R.string.saving_image);
564        } else {
565            progressText = getString(R.string.filtershow_saving_image, albumName);
566        }
567        progress = ProgressDialog.show(this, "", progressText, true, false);
568        mSavingProgressDialog = new WeakReference<ProgressDialog>(progress);
569    }
570
571    private void hideSavingProgress() {
572        if (mSavingProgressDialog != null) {
573            ProgressDialog progress = mSavingProgressDialog.get();
574            if (progress != null)
575                progress.dismiss();
576        }
577    }
578
579    public void completeSaveImage(Uri saveUri) {
580        if (mSharingImage && mSharedOutputFile != null) {
581            // Image saved, we unblock the content provider
582            Uri uri = Uri.withAppendedPath(SharedImageProvider.CONTENT_URI,
583                    Uri.encode(mSharedOutputFile.getAbsolutePath()));
584            ContentValues values = new ContentValues();
585            values.put(SharedImageProvider.PREPARE, false);
586            getContentResolver().insert(uri, values);
587        }
588        setResult(RESULT_OK, new Intent().setData(saveUri));
589        hideSavingProgress();
590        finish();
591    }
592
593    @Override
594    public boolean onShareTargetSelected(ShareActionProvider arg0, Intent arg1) {
595        // First, let's tell the SharedImageProvider that it will need to wait
596        // for the image
597        Uri uri = Uri.withAppendedPath(SharedImageProvider.CONTENT_URI,
598                Uri.encode(mSharedOutputFile.getAbsolutePath()));
599        ContentValues values = new ContentValues();
600        values.put(SharedImageProvider.PREPARE, true);
601        getContentResolver().insert(uri, values);
602        mSharingImage = true;
603
604        // Process and save the image in the background.
605        showSavingProgress(null);
606        mImageShow.saveImage(this, mSharedOutputFile);
607        return true;
608    }
609
610    private Intent getDefaultShareIntent() {
611        Intent intent = new Intent(Intent.ACTION_SEND);
612        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
613        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
614        intent.setType(SharedImageProvider.MIME_TYPE);
615        mSharedOutputFile = SaveCopyTask.getNewFile(this, mImageLoader.getUri());
616        Uri uri = Uri.withAppendedPath(SharedImageProvider.CONTENT_URI,
617                Uri.encode(mSharedOutputFile.getAbsolutePath()));
618        intent.putExtra(Intent.EXTRA_STREAM, uri);
619        return intent;
620    }
621
622    @Override
623    public boolean onCreateOptionsMenu(Menu menu) {
624        getMenuInflater().inflate(R.menu.filtershow_activity_menu, menu);
625        MenuItem showHistory = menu.findItem(R.id.operationsButton);
626        if (mShowingHistoryPanel) {
627            showHistory.setTitle(R.string.hide_history_panel);
628        } else {
629            showHistory.setTitle(R.string.show_history_panel);
630        }
631        MenuItem showState = menu.findItem(R.id.showImageStateButton);
632        if (mShowingImageStatePanel) {
633            showState.setTitle(R.string.hide_imagestate_panel);
634        } else {
635            showState.setTitle(R.string.show_imagestate_panel);
636        }
637        mShareActionProvider = (ShareActionProvider) menu.findItem(R.id.menu_share)
638                .getActionProvider();
639        mShareActionProvider.setShareIntent(getDefaultShareIntent());
640        mShareActionProvider.setOnShareTargetSelectedListener(this);
641
642        MenuItem undoItem = menu.findItem(R.id.undoButton);
643        MenuItem redoItem = menu.findItem(R.id.redoButton);
644        MenuItem resetItem = menu.findItem(R.id.resetHistoryButton);
645        mMasterImage.getHistory().setMenuItems(undoItem, redoItem, resetItem);
646        return true;
647    }
648
649    @Override
650    public void onPause() {
651        super.onPause();
652        if (mShareActionProvider != null) {
653            mShareActionProvider.setOnShareTargetSelectedListener(null);
654        }
655    }
656
657    @Override
658    public void onResume() {
659        super.onResume();
660        if (mShareActionProvider != null) {
661            mShareActionProvider.setOnShareTargetSelectedListener(this);
662        }
663    }
664
665    @Override
666    public boolean onOptionsItemSelected(MenuItem item) {
667        switch (item.getItemId()) {
668            case R.id.undoButton: {
669                HistoryAdapter adapter = mMasterImage.getHistory();
670                int position = adapter.undo();
671                mMasterImage.onHistoryItemClick(position);
672                mImageShow.showToast("Undo");
673                invalidateViews();
674                return true;
675            }
676            case R.id.redoButton: {
677                HistoryAdapter adapter = mMasterImage.getHistory();
678                int position = adapter.redo();
679                mMasterImage.onHistoryItemClick(position);
680                mImageShow.showToast("Redo");
681                invalidateViews();
682                return true;
683            }
684            case R.id.resetHistoryButton: {
685                resetHistory();
686                return true;
687            }
688            case R.id.showImageStateButton: {
689                toggleImageStatePanel();
690                return true;
691            }
692            case R.id.operationsButton: {
693                toggleHistoryPanel();
694                return true;
695            }
696            case android.R.id.home: {
697                saveImage();
698                return true;
699            }
700        }
701        return false;
702    }
703
704    public void enableSave(boolean enable) {
705        if (mSaveButton != null)
706            mSaveButton.setEnabled(enable);
707    }
708
709    public FilterIconButton setupFilterRepresentationButton(FilterRepresentation representation, LinearLayout panel, View button) {
710        LayoutInflater inflater =
711                (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
712        FilterIconButton icon = (FilterIconButton) inflater.inflate(R.layout.filtericonbutton,
713                panel, false);
714        if (representation.getTextId() != 0) {
715            representation.setName(getString(representation.getTextId()));
716        }
717        String text = representation.getName();
718        icon.setup(text, mPanelController, panel);
719        icon.setFilterRepresentation(representation);
720        if (representation instanceof FilterTinyPlanetRepresentation) {
721            // needed to hide tinyplanet on startup
722            icon.setId(R.id.tinyplanetButton);
723        }
724        mPanelController.addComponent(button, icon);
725        panel.addView(icon);
726        return icon;
727    }
728
729    private void fillListImages(LinearLayout listFilters) {
730        // TODO: use listview
731        // TODO: load the filters straight from the filesystem
732
733        FilterFxRepresentation[] fxArray = new FilterFxRepresentation[18];
734        int p = 0;
735
736        int[] drawid = {
737                R.drawable.filtershow_fx_0005_punch,
738                R.drawable.filtershow_fx_0000_vintage,
739                R.drawable.filtershow_fx_0004_bw_contrast,
740                R.drawable.filtershow_fx_0002_bleach,
741                R.drawable.filtershow_fx_0001_instant,
742                R.drawable.filtershow_fx_0007_washout,
743                R.drawable.filtershow_fx_0003_blue_crush,
744                R.drawable.filtershow_fx_0008_washout_color,
745                R.drawable.filtershow_fx_0006_x_process
746        };
747
748        int[] fxNameid = {
749                R.string.ffx_punch,
750                R.string.ffx_vintage,
751                R.string.ffx_bw_contrast,
752                R.string.ffx_bleach,
753                R.string.ffx_instant,
754                R.string.ffx_washout,
755                R.string.ffx_blue_crush,
756                R.string.ffx_washout_color,
757                R.string.ffx_x_process
758        };
759
760        ImagePreset preset = new ImagePreset(getString(R.string.history_original)); // empty
761        preset.setImageLoader(mImageLoader);
762
763        BitmapFactory.Options o = new BitmapFactory.Options();
764        o.inScaled = false;
765
766        for (int i = 0; i < drawid.length; i++) {
767            Bitmap b = BitmapFactory.decodeResource(getResources(), drawid[i], o);
768            FilterFxRepresentation fx = new FilterFxRepresentation(getString(fxNameid[i]), drawid[i], fxNameid[i]);
769            fx.setFxBitmap(b);
770            fxArray[p++] = fx;
771        }
772
773        FilterFxRepresentation nullFx = new FilterFxRepresentation(getString(R.string.none), 0, R.string.none);
774        mNullFxFilter = setupFilterRepresentationButton(nullFx, listFilters, mFxButton);
775        mNullFxFilter.setSelected(true);
776
777        for (int i = 0; i < p; i++) {
778            setupFilterRepresentationButton(fxArray[i], listFilters, mFxButton);
779        }
780
781        // Default preset (original)
782        mMasterImage.setPreset(preset, true);
783    }
784
785    // //////////////////////////////////////////////////////////////////////////////
786    // Some utility functions
787    // TODO: finish the cleanup.
788
789    public void showOriginalViews(boolean value) {
790        for (ImageShow views : mImageViews) {
791            views.showOriginal(value);
792        }
793    }
794
795    public void invalidateViews() {
796        for (ImageShow views : mImageViews) {
797            views.invalidate();
798            views.updateImage();
799        }
800    }
801
802    public void hideListViews() {
803        for (View view : mListViews) {
804            view.setVisibility(View.GONE);
805        }
806    }
807
808    public void hideImageViews() {
809        mImageShow.setShowControls(false); // reset
810        for (View view : mImageViews) {
811            view.setVisibility(View.GONE);
812        }
813        mEditorPlaceHolder.hide();
814    }
815
816    public void unselectBottomPanelButtons() {
817        for (ImageButton button : mBottomPanelButtons) {
818            button.setSelected(false);
819        }
820    }
821
822    public void unselectPanelButtons(Vector<ImageButton> buttons) {
823        for (ImageButton button : buttons) {
824            button.setSelected(false);
825        }
826    }
827
828    public void disableFilterButtons() {
829        for (ImageButton b : mBottomPanelButtons) {
830            b.setEnabled(false);
831            b.setClickable(false);
832            b.setAlpha(0.4f);
833        }
834    }
835
836    public void enableFilterButtons() {
837        for (ImageButton b : mBottomPanelButtons) {
838            b.setEnabled(true);
839            b.setClickable(true);
840            b.setAlpha(1.0f);
841        }
842    }
843
844    // //////////////////////////////////////////////////////////////////////////////
845    // imageState panel...
846
847    public boolean isShowingHistoryPanel() {
848        return mShowingHistoryPanel;
849    }
850
851    private void toggleImageStatePanel() {
852        final View view = findViewById(R.id.mainPanel);
853        final View viewList = findViewById(R.id.imageStatePanel);
854
855        if (mShowingHistoryPanel) {
856            findViewById(R.id.historyPanel).setVisibility(View.INVISIBLE);
857            mShowingHistoryPanel = false;
858        }
859
860        int translate = translateMainPanel(viewList);
861        if (!mShowingImageStatePanel) {
862            mShowingImageStatePanel = true;
863            view.animate().setDuration(200).x(translate)
864                    .withLayer().withEndAction(new Runnable() {
865                        @Override
866                        public void run() {
867                            viewList.setAlpha(0);
868                            viewList.setVisibility(View.VISIBLE);
869                            viewList.animate().setDuration(100)
870                                    .alpha(1.0f).start();
871                        }
872                    }).start();
873        } else {
874            mShowingImageStatePanel = false;
875            viewList.setVisibility(View.INVISIBLE);
876            view.animate().setDuration(200).x(0).withLayer()
877                    .start();
878        }
879        invalidateOptionsMenu();
880    }
881
882    @Override
883    public void onConfigurationChanged(Configuration newConfig)
884    {
885        super.onConfigurationChanged(newConfig);
886        setResources();
887        if (mShowingHistoryPanel) {
888            toggleHistoryPanel();
889        }
890    }
891
892    public void setupMasterImage() {
893        HistoryAdapter mHistoryAdapter = new HistoryAdapter(
894                this, R.layout.filtershow_history_operation_row,
895                R.id.rowTextView);
896        ImageStateAdapter mImageStateAdapter = new ImageStateAdapter(this,
897                R.layout.filtershow_imagestate_row);
898
899        MasterImage.reset();
900        mMasterImage = MasterImage.getImage();
901        mMasterImage.setHistoryAdapter(mHistoryAdapter);
902        mMasterImage.setStateAdapter(mImageStateAdapter);
903        mMasterImage.setActivity(this);
904    }
905
906    // //////////////////////////////////////////////////////////////////////////////
907    // history panel...
908
909    public void toggleHistoryPanel() {
910        final View view = findViewById(R.id.mainPanel);
911        final View viewList = findViewById(R.id.historyPanel);
912
913        if (mShowingImageStatePanel) {
914            findViewById(R.id.imageStatePanel).setVisibility(View.INVISIBLE);
915            mShowingImageStatePanel = false;
916        }
917
918        int translate = translateMainPanel(viewList);
919        if (!mShowingHistoryPanel) {
920            mShowingHistoryPanel = true;
921            view.animate().setDuration(200).x(translate)
922                    .withLayer().withEndAction(new Runnable() {
923                        @Override
924                        public void run() {
925                            viewList.setAlpha(0);
926                            viewList.setVisibility(View.VISIBLE);
927                            viewList.animate().setDuration(100)
928                                    .alpha(1.0f).start();
929                        }
930                    }).start();
931        } else {
932            mShowingHistoryPanel = false;
933            viewList.setVisibility(View.INVISIBLE);
934            view.animate().setDuration(200).x(0).withLayer()
935                    .start();
936        }
937        invalidateOptionsMenu();
938    }
939
940    public void dispatchNullFilterClick() {
941        mNullFxFilter.onClick(mNullFxFilter);
942        mNullBorderFilter.onClick(mNullBorderFilter);
943    }
944
945    void resetHistory() {
946        dispatchNullFilterClick();
947        HistoryAdapter adapter = mMasterImage.getHistory();
948        adapter.reset();
949        ImagePreset original = new ImagePreset(adapter.getItem(0));
950        mMasterImage.setPreset(original, true);
951        mPanelController.resetParameters();
952        invalidateViews();
953    }
954
955    // reset button in the history panel.
956    private OnClickListener createOnClickResetOperationsButton() {
957        return new View.OnClickListener() {
958            @Override
959            public void onClick(View v) {
960                resetHistory();
961            }
962        };
963    }
964
965    @Override
966    public void onBackPressed() {
967        if (mPanelController.onBackPressed()) {
968            saveImage();
969        }
970    }
971
972    public void cannotLoadImage() {
973        CharSequence text = getString(R.string.cannot_load_image);
974        Toast toast = Toast.makeText(this, text, Toast.LENGTH_SHORT);
975        toast.show();
976        finish();
977    }
978
979    // //////////////////////////////////////////////////////////////////////////////
980
981    public float getPixelsFromDip(float value) {
982        Resources r = getResources();
983        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, value,
984                r.getDisplayMetrics());
985    }
986
987    @Override
988    public void onItemClick(AdapterView<?> parent, View view, int position,
989            long id) {
990        mMasterImage.onHistoryItemClick(position);
991        invalidateViews();
992    }
993
994    public void pickImage() {
995        Intent intent = new Intent();
996        intent.setType("image/*");
997        intent.setAction(Intent.ACTION_GET_CONTENT);
998        startActivityForResult(Intent.createChooser(intent, getString(R.string.select_image)),
999                SELECT_PICTURE);
1000    }
1001
1002    @Override
1003    public void onActivityResult(int requestCode, int resultCode, Intent data) {
1004        if (resultCode == RESULT_OK) {
1005            if (requestCode == SELECT_PICTURE) {
1006                Uri selectedImageUri = data.getData();
1007                startLoadBitmap(selectedImageUri);
1008            }
1009        }
1010    }
1011
1012    private boolean mSaveToExtraUri = false;
1013    private boolean mSaveAsWallpaper = false;
1014    private boolean mReturnAsExtra = false;
1015    private boolean outputted = false;
1016
1017    public void saveImage() {
1018        if (mCropExtras != null) {
1019            if (mCropExtras.getExtraOutput() != null) {
1020                mSaveToExtraUri = true;
1021                outputted = true;
1022            }
1023            if (mCropExtras.getSetAsWallpaper()) {
1024                mSaveAsWallpaper = true;
1025                outputted = true;
1026            }
1027            if (mCropExtras.getReturnData()) {
1028
1029                mReturnAsExtra = true;
1030                outputted = true;
1031            }
1032
1033            if (outputted) {
1034                mImageShow.getImagePreset().mGeoData.setUseCropExtrasFlag(true);
1035                showSavingProgress(null);
1036                mImageShow.returnFilteredResult(this);
1037            }
1038        }
1039        if (!outputted) {
1040            if (mImageShow.hasModifications()) {
1041                // Get the name of the album, to which the image will be saved
1042                File saveDir = SaveCopyTask.getFinalSaveDirectory(this, mImageLoader.getUri());
1043                int bucketId = GalleryUtils.getBucketId(saveDir.getPath());
1044                String albumName = LocalAlbum.getLocalizedName(getResources(), bucketId, null);
1045                showSavingProgress(albumName);
1046                mImageShow.saveImage(this, null);
1047            } else {
1048                done();
1049            }
1050        }
1051    }
1052
1053    public void onFilteredResult(Bitmap filtered) {
1054        Intent intent = new Intent();
1055        intent.putExtra(CropExtras.KEY_CROPPED_RECT, mImageShow.getImageCropBounds());
1056        if (mSaveToExtraUri) {
1057            mImageShow.saveToUri(filtered, mCropExtras.getExtraOutput(),
1058                    mCropExtras.getOutputFormat(), this);
1059        }
1060        if (mSaveAsWallpaper) {
1061            try {
1062                WallpaperManager.getInstance(this).setBitmap(filtered);
1063            } catch (IOException e) {
1064                Log.w(LOGTAG, "fail to set wall paper", e);
1065            }
1066        }
1067        if (mReturnAsExtra) {
1068            if (filtered != null) {
1069                int bmapSize = filtered.getRowBytes() * filtered.getHeight();
1070                /*
1071                 * Max size of Binder transaction buffer is 1Mb, so constrain
1072                 * Bitmap to be somewhat less than this, otherwise we get
1073                 * TransactionTooLargeExceptions.
1074                 */
1075                if (bmapSize > MAX_BMAP_IN_INTENT) {
1076                    Log.w(LOGTAG, "Bitmap too large to be returned via intent");
1077                } else {
1078                    intent.putExtra(CropExtras.KEY_DATA, filtered);
1079                }
1080            }
1081        }
1082        setResult(RESULT_OK, intent);
1083        if (!mSaveToExtraUri) {
1084            done();
1085        }
1086    }
1087
1088    public void done() {
1089        if (outputted) {
1090            hideSavingProgress();
1091        }
1092        finish();
1093    }
1094
1095    private void setResources() {
1096        ImageFilterBorder filterBorder = (ImageFilterBorder) FiltersManager.getManager().getFilter(ImageFilterBorder.class);
1097        filterBorder.setResources(getResources());
1098    }
1099
1100    static {
1101        System.loadLibrary("jni_filtershow_filters");
1102    }
1103
1104}
1105