summaryrefslogtreecommitdiffstats
path: root/src/com/android/gallery3d/filtershow/FilterShowActivity.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/gallery3d/filtershow/FilterShowActivity.java')
-rw-r--r--src/com/android/gallery3d/filtershow/FilterShowActivity.java1121
1 files changed, 1121 insertions, 0 deletions
diff --git a/src/com/android/gallery3d/filtershow/FilterShowActivity.java b/src/com/android/gallery3d/filtershow/FilterShowActivity.java
new file mode 100644
index 000000000..4700fccfe
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/FilterShowActivity.java
@@ -0,0 +1,1121 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.gallery3d.filtershow;
+
+import android.app.ActionBar;
+import android.app.AlertDialog;
+import android.app.ProgressDialog;
+import android.content.ComponentName;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.content.pm.ActivityInfo;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.support.v4.app.DialogFragment;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentActivity;
+import android.support.v4.app.FragmentTransaction;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.util.TypedValue;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewPropertyAnimator;
+import android.view.WindowManager;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
+import android.widget.FrameLayout;
+import android.widget.ShareActionProvider;
+import android.widget.ShareActionProvider.OnShareTargetSelectedListener;
+import android.widget.Toast;
+
+import com.android.gallery3d.R;
+import com.android.gallery3d.app.PhotoPage;
+import com.android.gallery3d.data.LocalAlbum;
+import com.android.gallery3d.filtershow.cache.ImageLoader;
+import com.android.gallery3d.filtershow.category.Action;
+import com.android.gallery3d.filtershow.category.CategoryAdapter;
+import com.android.gallery3d.filtershow.category.MainPanel;
+import com.android.gallery3d.filtershow.data.UserPresetsManager;
+import com.android.gallery3d.filtershow.editors.BasicEditor;
+import com.android.gallery3d.filtershow.editors.Editor;
+import com.android.gallery3d.filtershow.editors.EditorChanSat;
+import com.android.gallery3d.filtershow.editors.EditorCrop;
+import com.android.gallery3d.filtershow.editors.EditorDraw;
+import com.android.gallery3d.filtershow.editors.EditorGrad;
+import com.android.gallery3d.filtershow.editors.EditorManager;
+import com.android.gallery3d.filtershow.editors.EditorMirror;
+import com.android.gallery3d.filtershow.editors.EditorPanel;
+import com.android.gallery3d.filtershow.editors.EditorRedEye;
+import com.android.gallery3d.filtershow.editors.EditorRotate;
+import com.android.gallery3d.filtershow.editors.EditorStraighten;
+import com.android.gallery3d.filtershow.editors.EditorTinyPlanet;
+import com.android.gallery3d.filtershow.editors.ImageOnlyEditor;
+import com.android.gallery3d.filtershow.filters.FilterRepresentation;
+import com.android.gallery3d.filtershow.filters.FilterUserPresetRepresentation;
+import com.android.gallery3d.filtershow.filters.FiltersManager;
+import com.android.gallery3d.filtershow.filters.ImageFilter;
+import com.android.gallery3d.filtershow.history.HistoryItem;
+import com.android.gallery3d.filtershow.history.HistoryManager;
+import com.android.gallery3d.filtershow.imageshow.ImageShow;
+import com.android.gallery3d.filtershow.imageshow.MasterImage;
+import com.android.gallery3d.filtershow.imageshow.Spline;
+import com.android.gallery3d.filtershow.pipeline.CachingPipeline;
+import com.android.gallery3d.filtershow.pipeline.ImagePreset;
+import com.android.gallery3d.filtershow.pipeline.ProcessingService;
+import com.android.gallery3d.filtershow.presets.PresetManagementDialog;
+import com.android.gallery3d.filtershow.presets.UserPresetsAdapter;
+import com.android.gallery3d.filtershow.provider.SharedImageProvider;
+import com.android.gallery3d.filtershow.state.StateAdapter;
+import com.android.gallery3d.filtershow.tools.SaveImage;
+import com.android.gallery3d.filtershow.tools.XmpPresets;
+import com.android.gallery3d.filtershow.tools.XmpPresets.XMresults;
+import com.android.gallery3d.filtershow.ui.ExportDialog;
+import com.android.gallery3d.filtershow.ui.FramedTextButton;
+import com.android.gallery3d.util.GalleryUtils;
+import com.android.gallery3d.util.UsageStatistics;
+import com.android.photos.data.GalleryBitmapPool;
+
+import java.io.File;
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.Vector;
+
+public class FilterShowActivity extends FragmentActivity implements OnItemClickListener,
+ OnShareTargetSelectedListener {
+
+ private String mAction = "";
+ MasterImage mMasterImage = null;
+
+ private static final long LIMIT_SUPPORTS_HIGHRES = 134217728; // 128Mb
+
+ public static final String TINY_PLANET_ACTION = "com.android.camera.action.TINY_PLANET";
+ public static final String LAUNCH_FULLSCREEN = "launch-fullscreen";
+ private ImageShow mImageShow = null;
+
+ private View mSaveButton = null;
+
+ private EditorPlaceHolder mEditorPlaceHolder = new EditorPlaceHolder(this);
+
+ private static final int SELECT_PICTURE = 1;
+ private static final String LOGTAG = "FilterShowActivity";
+
+ private boolean mShowingTinyPlanet = false;
+ private boolean mShowingImageStatePanel = false;
+
+ private final Vector<ImageShow> mImageViews = new Vector<ImageShow>();
+
+ private ShareActionProvider mShareActionProvider;
+ private File mSharedOutputFile = null;
+
+ private boolean mSharingImage = false;
+
+ private WeakReference<ProgressDialog> mSavingProgressDialog;
+
+ private LoadBitmapTask mLoadBitmapTask;
+
+ private Uri mOriginalImageUri = null;
+ private ImagePreset mOriginalPreset = null;
+
+ private Uri mSelectedImageUri = null;
+
+ private UserPresetsManager mUserPresetsManager = null;
+ private UserPresetsAdapter mUserPresetsAdapter = null;
+ private CategoryAdapter mCategoryLooksAdapter = null;
+ private CategoryAdapter mCategoryBordersAdapter = null;
+ private CategoryAdapter mCategoryGeometryAdapter = null;
+ private CategoryAdapter mCategoryFiltersAdapter = null;
+ private int mCurrentPanel = MainPanel.LOOKS;
+
+ private ProcessingService mBoundService;
+ private boolean mIsBound = false;
+
+ public ProcessingService getProcessingService() {
+ return mBoundService;
+ }
+
+ public boolean isSimpleEditAction() {
+ return !PhotoPage.ACTION_NEXTGEN_EDIT.equalsIgnoreCase(mAction);
+ }
+
+ private ServiceConnection mConnection = new ServiceConnection() {
+ public void onServiceConnected(ComponentName className, IBinder service) {
+ /*
+ * This is called when the connection with the service has been
+ * established, giving us the service object we can use to
+ * interact with the service. Because we have bound to a explicit
+ * service that we know is running in our own process, we can
+ * cast its IBinder to a concrete class and directly access it.
+ */
+ mBoundService = ((ProcessingService.LocalBinder)service).getService();
+ mBoundService.setFiltershowActivity(FilterShowActivity.this);
+ mBoundService.onStart();
+ }
+
+ public void onServiceDisconnected(ComponentName className) {
+ /*
+ * This is called when the connection with the service has been
+ * unexpectedly disconnected -- that is, its process crashed.
+ * Because it is running in our same process, we should never
+ * see this happen.
+ */
+ mBoundService = null;
+ }
+ };
+
+ void doBindService() {
+ /*
+ * Establish a connection with the service. We use an explicit
+ * class name because we want a specific service implementation that
+ * we know will be running in our own process (and thus won't be
+ * supporting component replacement by other applications).
+ */
+ bindService(new Intent(FilterShowActivity.this, ProcessingService.class),
+ mConnection, Context.BIND_AUTO_CREATE);
+ mIsBound = true;
+ }
+
+ void doUnbindService() {
+ if (mIsBound) {
+ // Detach our existing connection.
+ unbindService(mConnection);
+ mIsBound = false;
+ }
+ }
+
+ private void setupPipeline() {
+ doBindService();
+ ImageFilter.setActivityForMemoryToasts(this);
+ mUserPresetsManager = new UserPresetsManager(this);
+ mUserPresetsAdapter = new UserPresetsAdapter(this);
+ mCategoryLooksAdapter = new CategoryAdapter(this);
+ }
+
+ public void updateUIAfterServiceStarted() {
+ fillCategories();
+ loadMainPanel();
+ setDefaultPreset();
+ extractXMPData();
+ processIntent();
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ boolean onlyUsePortrait = getResources().getBoolean(R.bool.only_use_portrait);
+ if (onlyUsePortrait) {
+ setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
+ }
+ MasterImage.setMaster(mMasterImage);
+
+ clearGalleryBitmapPool();
+ setupPipeline();
+
+ setupMasterImage();
+ setDefaultValues();
+ fillEditors();
+
+ loadXML();
+ UsageStatistics.onContentViewChanged(UsageStatistics.COMPONENT_EDITOR, "Main");
+ UsageStatistics.onEvent(UsageStatistics.COMPONENT_EDITOR,
+ UsageStatistics.CATEGORY_LIFECYCLE, UsageStatistics.LIFECYCLE_START);
+ }
+
+ public boolean isShowingImageStatePanel() {
+ return mShowingImageStatePanel;
+ }
+
+ public void loadMainPanel() {
+ if (findViewById(R.id.main_panel_container) == null) {
+ return;
+ }
+ MainPanel panel = new MainPanel();
+ FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
+ transaction.replace(R.id.main_panel_container, panel, MainPanel.FRAGMENT_TAG);
+ transaction.commit();
+ }
+
+ public void loadEditorPanel(FilterRepresentation representation,
+ final Editor currentEditor) {
+ if (representation.getEditorId() == ImageOnlyEditor.ID) {
+ currentEditor.reflectCurrentFilter();
+ return;
+ }
+ final int currentId = currentEditor.getID();
+ Runnable showEditor = new Runnable() {
+ @Override
+ public void run() {
+ EditorPanel panel = new EditorPanel();
+ panel.setEditor(currentId);
+ FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
+ transaction.remove(getSupportFragmentManager().findFragmentByTag(MainPanel.FRAGMENT_TAG));
+ transaction.replace(R.id.main_panel_container, panel, MainPanel.FRAGMENT_TAG);
+ transaction.commit();
+ }
+ };
+ Fragment main = getSupportFragmentManager().findFragmentByTag(MainPanel.FRAGMENT_TAG);
+ boolean doAnimation = false;
+ if (mShowingImageStatePanel
+ && getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
+ doAnimation = true;
+ }
+ if (doAnimation && main != null && main instanceof MainPanel) {
+ MainPanel mainPanel = (MainPanel) main;
+ View container = mainPanel.getView().findViewById(R.id.category_panel_container);
+ View bottom = mainPanel.getView().findViewById(R.id.bottom_panel);
+ int panelHeight = container.getHeight() + bottom.getHeight();
+ ViewPropertyAnimator anim = mainPanel.getView().animate();
+ anim.translationY(panelHeight).start();
+ final Handler handler = new Handler();
+ handler.postDelayed(showEditor, anim.getDuration());
+ } else {
+ showEditor.run();
+ }
+ }
+
+ private void loadXML() {
+ setContentView(R.layout.filtershow_activity);
+
+ ActionBar actionBar = getActionBar();
+ actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
+ actionBar.setCustomView(R.layout.filtershow_actionbar);
+
+ mSaveButton = actionBar.getCustomView();
+ mSaveButton.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ saveImage();
+ }
+ });
+
+ mImageShow = (ImageShow) findViewById(R.id.imageShow);
+ mImageViews.add(mImageShow);
+
+ setupEditors();
+
+ mEditorPlaceHolder.hide();
+ mImageShow.bindAsImageLoadListener();
+
+ setupStatePanel();
+ }
+
+ public void fillCategories() {
+ fillLooks();
+ loadUserPresets();
+ fillBorders();
+ fillTools();
+ fillEffects();
+ }
+
+ public void setupStatePanel() {
+ MasterImage.getImage().setHistoryManager(mMasterImage.getHistory());
+ }
+
+ private void fillEffects() {
+ FiltersManager filtersManager = FiltersManager.getManager();
+ ArrayList<FilterRepresentation> filtersRepresentations = filtersManager.getEffects();
+ mCategoryFiltersAdapter = new CategoryAdapter(this);
+ for (FilterRepresentation representation : filtersRepresentations) {
+ if (representation.getTextId() != 0) {
+ representation.setName(getString(representation.getTextId()));
+ }
+ mCategoryFiltersAdapter.add(new Action(this, representation));
+ }
+ }
+
+ private void fillTools() {
+ FiltersManager filtersManager = FiltersManager.getManager();
+ ArrayList<FilterRepresentation> filtersRepresentations = filtersManager.getTools();
+ mCategoryGeometryAdapter = new CategoryAdapter(this);
+ for (FilterRepresentation representation : filtersRepresentations) {
+ mCategoryGeometryAdapter.add(new Action(this, representation));
+ }
+ }
+
+ private void processIntent() {
+ Intent intent = getIntent();
+ if (intent.getBooleanExtra(LAUNCH_FULLSCREEN, false)) {
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
+ }
+
+ mAction = intent.getAction();
+ mSelectedImageUri = intent.getData();
+ Uri loadUri = mSelectedImageUri;
+ if (mOriginalImageUri != null) {
+ loadUri = mOriginalImageUri;
+ }
+ if (loadUri != null) {
+ startLoadBitmap(loadUri);
+ } else {
+ pickImage();
+ }
+ }
+
+ private void setupEditors() {
+ mEditorPlaceHolder.setContainer((FrameLayout) findViewById(R.id.editorContainer));
+ EditorManager.addEditors(mEditorPlaceHolder);
+ mEditorPlaceHolder.setOldViews(mImageViews);
+ }
+
+ private void fillEditors() {
+ mEditorPlaceHolder.addEditor(new EditorChanSat());
+ mEditorPlaceHolder.addEditor(new EditorGrad());
+ mEditorPlaceHolder.addEditor(new EditorDraw());
+ mEditorPlaceHolder.addEditor(new BasicEditor());
+ mEditorPlaceHolder.addEditor(new ImageOnlyEditor());
+ mEditorPlaceHolder.addEditor(new EditorTinyPlanet());
+ mEditorPlaceHolder.addEditor(new EditorRedEye());
+ mEditorPlaceHolder.addEditor(new EditorCrop());
+ mEditorPlaceHolder.addEditor(new EditorMirror());
+ mEditorPlaceHolder.addEditor(new EditorRotate());
+ mEditorPlaceHolder.addEditor(new EditorStraighten());
+ }
+
+ private void setDefaultValues() {
+ Resources res = getResources();
+
+ // TODO: get those values from XML.
+ FramedTextButton.setTextSize((int) getPixelsFromDip(14));
+ FramedTextButton.setTrianglePadding((int) getPixelsFromDip(4));
+ FramedTextButton.setTriangleSize((int) getPixelsFromDip(10));
+
+ Drawable curveHandle = res.getDrawable(R.drawable.camera_crop);
+ int curveHandleSize = (int) res.getDimension(R.dimen.crop_indicator_size);
+ Spline.setCurveHandle(curveHandle, curveHandleSize);
+ Spline.setCurveWidth((int) getPixelsFromDip(3));
+ }
+
+ private void startLoadBitmap(Uri uri) {
+ final View loading = findViewById(R.id.loading);
+ final View imageShow = findViewById(R.id.imageShow);
+ imageShow.setVisibility(View.INVISIBLE);
+ loading.setVisibility(View.VISIBLE);
+ mShowingTinyPlanet = false;
+ mLoadBitmapTask = new LoadBitmapTask();
+ mLoadBitmapTask.execute(uri);
+ }
+
+ private void fillBorders() {
+ FiltersManager filtersManager = FiltersManager.getManager();
+ ArrayList<FilterRepresentation> borders = filtersManager.getBorders();
+
+ for (int i = 0; i < borders.size(); i++) {
+ FilterRepresentation filter = borders.get(i);
+ filter.setName(getString(R.string.borders));
+ if (i == 0) {
+ filter.setName(getString(R.string.none));
+ }
+ }
+
+ mCategoryBordersAdapter = new CategoryAdapter(this);
+ for (FilterRepresentation representation : borders) {
+ if (representation.getTextId() != 0) {
+ representation.setName(getString(representation.getTextId()));
+ }
+ mCategoryBordersAdapter.add(new Action(this, representation, Action.FULL_VIEW));
+ }
+ }
+
+ public UserPresetsAdapter getUserPresetsAdapter() {
+ return mUserPresetsAdapter;
+ }
+
+ public CategoryAdapter getCategoryLooksAdapter() {
+ return mCategoryLooksAdapter;
+ }
+
+ public CategoryAdapter getCategoryBordersAdapter() {
+ return mCategoryBordersAdapter;
+ }
+
+ public CategoryAdapter getCategoryGeometryAdapter() {
+ return mCategoryGeometryAdapter;
+ }
+
+ public CategoryAdapter getCategoryFiltersAdapter() {
+ return mCategoryFiltersAdapter;
+ }
+
+ public void removeFilterRepresentation(FilterRepresentation filterRepresentation) {
+ if (filterRepresentation == null) {
+ return;
+ }
+ ImagePreset oldPreset = MasterImage.getImage().getPreset();
+ ImagePreset copy = new ImagePreset(oldPreset);
+ copy.removeFilter(filterRepresentation);
+ MasterImage.getImage().setPreset(copy, copy.getLastRepresentation(), true);
+ if (MasterImage.getImage().getCurrentFilterRepresentation() == filterRepresentation) {
+ FilterRepresentation lastRepresentation = copy.getLastRepresentation();
+ MasterImage.getImage().setCurrentFilterRepresentation(lastRepresentation);
+ }
+ }
+
+ public void useFilterRepresentation(FilterRepresentation filterRepresentation) {
+ if (filterRepresentation == null) {
+ return;
+ }
+ if (MasterImage.getImage().getCurrentFilterRepresentation() == filterRepresentation) {
+ return;
+ }
+ ImagePreset oldPreset = MasterImage.getImage().getPreset();
+ ImagePreset copy = new ImagePreset(oldPreset);
+ FilterRepresentation representation = copy.getRepresentation(filterRepresentation);
+ if (representation == null) {
+ copy.addFilter(filterRepresentation);
+ } else if (filterRepresentation.getFilterType() == FilterRepresentation.TYPE_GEOMETRY) {
+ filterRepresentation = representation;
+ } else {
+ if (filterRepresentation.allowsSingleInstanceOnly()) {
+ // Don't just update the filter representation. Centralize the
+ // logic in the addFilter(), such that we can keep "None" as
+ // null.
+ copy.removeFilter(representation);
+ copy.addFilter(filterRepresentation);
+ }
+ }
+ MasterImage.getImage().setPreset(copy, filterRepresentation, true);
+ MasterImage.getImage().setCurrentFilterRepresentation(filterRepresentation);
+ }
+
+ public void showRepresentation(FilterRepresentation representation) {
+ if (representation == null) {
+ return;
+ }
+
+ useFilterRepresentation(representation);
+
+ // show representation
+ Editor mCurrentEditor = mEditorPlaceHolder.showEditor(representation.getEditorId());
+ loadEditorPanel(representation, mCurrentEditor);
+ }
+
+ public Editor getEditor(int editorID) {
+ return mEditorPlaceHolder.getEditor(editorID);
+ }
+
+ public void setCurrentPanel(int currentPanel) {
+ mCurrentPanel = currentPanel;
+ }
+
+ public int getCurrentPanel() {
+ return mCurrentPanel;
+ }
+
+ public void updateCategories() {
+ ImagePreset preset = mMasterImage.getPreset();
+ mCategoryLooksAdapter.reflectImagePreset(preset);
+ mCategoryBordersAdapter.reflectImagePreset(preset);
+ }
+
+ private class LoadHighresBitmapTask extends AsyncTask<Void, Void, Boolean> {
+ @Override
+ protected Boolean doInBackground(Void... params) {
+ MasterImage master = MasterImage.getImage();
+ Rect originalBounds = master.getOriginalBounds();
+ if (master.supportsHighRes()) {
+ int highresPreviewSize = master.getOriginalBitmapLarge().getWidth() * 2;
+ if (highresPreviewSize > originalBounds.width()) {
+ highresPreviewSize = originalBounds.width();
+ }
+ Rect bounds = new Rect();
+ Bitmap originalHires = ImageLoader.loadOrientedConstrainedBitmap(master.getUri(),
+ master.getActivity(), highresPreviewSize,
+ master.getOrientation(), bounds);
+ master.setOriginalBounds(bounds);
+ master.setOriginalBitmapHighres(originalHires);
+ mBoundService.setOriginalBitmapHighres(originalHires);
+ master.warnListeners();
+ }
+ return true;
+ }
+
+ @Override
+ protected void onPostExecute(Boolean result) {
+ Bitmap highresBitmap = MasterImage.getImage().getOriginalBitmapHighres();
+ if (highresBitmap != null) {
+ float highResPreviewScale = (float) highresBitmap.getWidth()
+ / (float) MasterImage.getImage().getOriginalBounds().width();
+ mBoundService.setHighresPreviewScaleFactor(highResPreviewScale);
+ }
+ }
+ }
+
+ private class LoadBitmapTask extends AsyncTask<Uri, Boolean, Boolean> {
+ int mBitmapSize;
+
+ public LoadBitmapTask() {
+ mBitmapSize = getScreenImageSize();
+ }
+
+ @Override
+ protected Boolean doInBackground(Uri... params) {
+ if (!MasterImage.getImage().loadBitmap(params[0], mBitmapSize)) {
+ return false;
+ }
+ publishProgress(ImageLoader.queryLightCycle360(MasterImage.getImage().getActivity()));
+ return true;
+ }
+
+ @Override
+ protected void onProgressUpdate(Boolean... values) {
+ super.onProgressUpdate(values);
+ if (isCancelled()) {
+ return;
+ }
+ if (values[0]) {
+ mShowingTinyPlanet = true;
+ }
+ }
+
+ @Override
+ protected void onPostExecute(Boolean result) {
+ MasterImage.setMaster(mMasterImage);
+ if (isCancelled()) {
+ return;
+ }
+
+ if (!result) {
+ cannotLoadImage();
+ }
+
+ if (null == CachingPipeline.getRenderScriptContext()){
+ Log.v(LOGTAG,"RenderScript context destroyed during load");
+ return;
+ }
+ final View loading = findViewById(R.id.loading);
+ loading.setVisibility(View.GONE);
+ final View imageShow = findViewById(R.id.imageShow);
+ imageShow.setVisibility(View.VISIBLE);
+
+ Bitmap largeBitmap = MasterImage.getImage().getOriginalBitmapLarge();
+ mBoundService.setOriginalBitmap(largeBitmap);
+
+ float previewScale = (float) largeBitmap.getWidth()
+ / (float) MasterImage.getImage().getOriginalBounds().width();
+ mBoundService.setPreviewScaleFactor(previewScale);
+ if (!mShowingTinyPlanet) {
+ mCategoryFiltersAdapter.removeTinyPlanet();
+ }
+ mCategoryLooksAdapter.imageLoaded();
+ mCategoryBordersAdapter.imageLoaded();
+ mCategoryGeometryAdapter.imageLoaded();
+ mCategoryFiltersAdapter.imageLoaded();
+ mLoadBitmapTask = null;
+
+ if (mOriginalPreset != null) {
+ MasterImage.getImage().setLoadedPreset(mOriginalPreset);
+ MasterImage.getImage().setPreset(mOriginalPreset,
+ mOriginalPreset.getLastRepresentation(), true);
+ mOriginalPreset = null;
+ }
+
+ if (mAction == TINY_PLANET_ACTION) {
+ showRepresentation(mCategoryFiltersAdapter.getTinyPlanet());
+ }
+ LoadHighresBitmapTask highresLoad = new LoadHighresBitmapTask();
+ highresLoad.execute();
+ super.onPostExecute(result);
+ }
+
+ }
+
+ private void clearGalleryBitmapPool() {
+ (new AsyncTask<Void, Void, Void>() {
+ @Override
+ protected Void doInBackground(Void... params) {
+ // Free memory held in Gallery's Bitmap pool. May be O(n) for n bitmaps.
+ GalleryBitmapPool.getInstance().clear();
+ return null;
+ }
+ }).execute();
+ }
+
+ @Override
+ protected void onDestroy() {
+ if (mLoadBitmapTask != null) {
+ mLoadBitmapTask.cancel(false);
+ }
+ mUserPresetsManager.close();
+ doUnbindService();
+ super.onDestroy();
+ }
+
+ // TODO: find a more robust way of handling image size selection
+ // for high screen densities.
+ private int getScreenImageSize() {
+ DisplayMetrics outMetrics = new DisplayMetrics();
+ getWindowManager().getDefaultDisplay().getMetrics(outMetrics);
+ return (int) Math.max(outMetrics.heightPixels, outMetrics.widthPixels);
+ }
+
+ private void showSavingProgress(String albumName) {
+ ProgressDialog progress;
+ if (mSavingProgressDialog != null) {
+ progress = mSavingProgressDialog.get();
+ if (progress != null) {
+ progress.show();
+ return;
+ }
+ }
+ // TODO: Allow cancellation of the saving process
+ String progressText;
+ if (albumName == null) {
+ progressText = getString(R.string.saving_image);
+ } else {
+ progressText = getString(R.string.filtershow_saving_image, albumName);
+ }
+ progress = ProgressDialog.show(this, "", progressText, true, false);
+ mSavingProgressDialog = new WeakReference<ProgressDialog>(progress);
+ }
+
+ private void hideSavingProgress() {
+ if (mSavingProgressDialog != null) {
+ ProgressDialog progress = mSavingProgressDialog.get();
+ if (progress != null)
+ progress.dismiss();
+ }
+ }
+
+ public void completeSaveImage(Uri saveUri) {
+ if (mSharingImage && mSharedOutputFile != null) {
+ // Image saved, we unblock the content provider
+ Uri uri = Uri.withAppendedPath(SharedImageProvider.CONTENT_URI,
+ Uri.encode(mSharedOutputFile.getAbsolutePath()));
+ ContentValues values = new ContentValues();
+ values.put(SharedImageProvider.PREPARE, false);
+ getContentResolver().insert(uri, values);
+ }
+ setResult(RESULT_OK, new Intent().setData(saveUri));
+ hideSavingProgress();
+ finish();
+ }
+
+ @Override
+ public boolean onShareTargetSelected(ShareActionProvider arg0, Intent arg1) {
+ // First, let's tell the SharedImageProvider that it will need to wait
+ // for the image
+ Uri uri = Uri.withAppendedPath(SharedImageProvider.CONTENT_URI,
+ Uri.encode(mSharedOutputFile.getAbsolutePath()));
+ ContentValues values = new ContentValues();
+ values.put(SharedImageProvider.PREPARE, true);
+ getContentResolver().insert(uri, values);
+ mSharingImage = true;
+
+ // Process and save the image in the background.
+ showSavingProgress(null);
+ mImageShow.saveImage(this, mSharedOutputFile);
+ return true;
+ }
+
+ private Intent getDefaultShareIntent() {
+ Intent intent = new Intent(Intent.ACTION_SEND);
+ intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
+ intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ intent.setType(SharedImageProvider.MIME_TYPE);
+ mSharedOutputFile = SaveImage.getNewFile(this, MasterImage.getImage().getUri());
+ Uri uri = Uri.withAppendedPath(SharedImageProvider.CONTENT_URI,
+ Uri.encode(mSharedOutputFile.getAbsolutePath()));
+ intent.putExtra(Intent.EXTRA_STREAM, uri);
+ return intent;
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.filtershow_activity_menu, menu);
+ MenuItem showState = menu.findItem(R.id.showImageStateButton);
+ if (mShowingImageStatePanel) {
+ showState.setTitle(R.string.hide_imagestate_panel);
+ } else {
+ showState.setTitle(R.string.show_imagestate_panel);
+ }
+ mShareActionProvider = (ShareActionProvider) menu.findItem(R.id.menu_share)
+ .getActionProvider();
+ mShareActionProvider.setShareIntent(getDefaultShareIntent());
+ mShareActionProvider.setOnShareTargetSelectedListener(this);
+
+ MenuItem undoItem = menu.findItem(R.id.undoButton);
+ MenuItem redoItem = menu.findItem(R.id.redoButton);
+ MenuItem resetItem = menu.findItem(R.id.resetHistoryButton);
+ mMasterImage.getHistory().setMenuItems(undoItem, redoItem, resetItem);
+ return true;
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ if (mShareActionProvider != null) {
+ mShareActionProvider.setOnShareTargetSelectedListener(null);
+ }
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ if (mShareActionProvider != null) {
+ mShareActionProvider.setOnShareTargetSelectedListener(this);
+ }
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case R.id.undoButton: {
+ HistoryManager adapter = mMasterImage.getHistory();
+ int position = adapter.undo();
+ mMasterImage.onHistoryItemClick(position);
+ backToMain();
+ invalidateViews();
+ UsageStatistics.onEvent(UsageStatistics.COMPONENT_EDITOR,
+ UsageStatistics.CATEGORY_BUTTON_PRESS, "Undo");
+ return true;
+ }
+ case R.id.redoButton: {
+ HistoryManager adapter = mMasterImage.getHistory();
+ int position = adapter.redo();
+ mMasterImage.onHistoryItemClick(position);
+ invalidateViews();
+ UsageStatistics.onEvent(UsageStatistics.COMPONENT_EDITOR,
+ UsageStatistics.CATEGORY_BUTTON_PRESS, "Redo");
+ return true;
+ }
+ case R.id.resetHistoryButton: {
+ resetHistory();
+ UsageStatistics.onEvent(UsageStatistics.COMPONENT_EDITOR,
+ UsageStatistics.CATEGORY_BUTTON_PRESS, "ResetHistory");
+ return true;
+ }
+ case R.id.showImageStateButton: {
+ toggleImageStatePanel();
+ UsageStatistics.onEvent(UsageStatistics.COMPONENT_EDITOR,
+ UsageStatistics.CATEGORY_BUTTON_PRESS,
+ mShowingImageStatePanel ? "ShowPanel" : "HidePanel");
+ return true;
+ }
+ case R.id.exportFlattenButton: {
+ showExportOptionsDialog();
+ return true;
+ }
+ case android.R.id.home: {
+ saveImage();
+ return true;
+ }
+ case R.id.manageUserPresets: {
+ manageUserPresets();
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void manageUserPresets() {
+ DialogFragment dialog = new PresetManagementDialog();
+ dialog.show(getSupportFragmentManager(), "NoticeDialogFragment");
+ }
+
+ private void showExportOptionsDialog() {
+ DialogFragment dialog = new ExportDialog();
+ dialog.show(getSupportFragmentManager(), "ExportDialogFragment");
+ }
+
+ public void updateUserPresetsFromAdapter(UserPresetsAdapter adapter) {
+ ArrayList<FilterUserPresetRepresentation> representations =
+ adapter.getDeletedRepresentations();
+ for (FilterUserPresetRepresentation representation : representations) {
+ deletePreset(representation.getId());
+ }
+ ArrayList<FilterUserPresetRepresentation> changedRepresentations =
+ adapter.getChangedRepresentations();
+ for (FilterUserPresetRepresentation representation : changedRepresentations) {
+ updatePreset(representation);
+ }
+ adapter.clearDeletedRepresentations();
+ adapter.clearChangedRepresentations();
+ loadUserPresets();
+ }
+
+ public void loadUserPresets() {
+ mUserPresetsManager.load();
+ }
+
+ public void updateUserPresetsFromManager() {
+ ArrayList<FilterUserPresetRepresentation> presets = mUserPresetsManager.getRepresentations();
+ if (presets == null) {
+ return;
+ }
+ if (mCategoryLooksAdapter != null) {
+ fillLooks();
+ }
+ mUserPresetsAdapter.clear();
+ for (int i = 0; i < presets.size(); i++) {
+ FilterUserPresetRepresentation representation = presets.get(i);
+ mCategoryLooksAdapter.add(
+ new Action(this, representation, Action.FULL_VIEW));
+ mUserPresetsAdapter.add(new Action(this, representation, Action.FULL_VIEW));
+ }
+ mCategoryLooksAdapter.notifyDataSetInvalidated();
+
+ }
+
+ public void saveCurrentImagePreset() {
+ mUserPresetsManager.save(MasterImage.getImage().getPreset());
+ }
+
+ private void deletePreset(int id) {
+ mUserPresetsManager.delete(id);
+ }
+
+ private void updatePreset(FilterUserPresetRepresentation representation) {
+ mUserPresetsManager.update(representation);
+ }
+
+ public void enableSave(boolean enable) {
+ if (mSaveButton != null) {
+ mSaveButton.setEnabled(enable);
+ }
+ }
+
+ private void fillLooks() {
+ FiltersManager filtersManager = FiltersManager.getManager();
+ ArrayList<FilterRepresentation> filtersRepresentations = filtersManager.getLooks();
+
+ mCategoryLooksAdapter.clear();
+ int verticalItemHeight = (int) getResources().getDimension(R.dimen.action_item_height);
+ mCategoryLooksAdapter.setItemHeight(verticalItemHeight);
+ for (FilterRepresentation representation : filtersRepresentations) {
+ mCategoryLooksAdapter.add(new Action(this, representation, Action.FULL_VIEW));
+ }
+ }
+
+ public void setDefaultPreset() {
+ // Default preset (original)
+ ImagePreset preset = new ImagePreset(); // empty
+ mMasterImage.setPreset(preset, preset.getLastRepresentation(), true);
+ }
+
+ // //////////////////////////////////////////////////////////////////////////////
+ // Some utility functions
+ // TODO: finish the cleanup.
+
+ public void invalidateViews() {
+ for (ImageShow views : mImageViews) {
+ views.updateImage();
+ }
+ }
+
+ public void hideImageViews() {
+ for (View view : mImageViews) {
+ view.setVisibility(View.GONE);
+ }
+ mEditorPlaceHolder.hide();
+ }
+
+ // //////////////////////////////////////////////////////////////////////////////
+ // imageState panel...
+
+ public void toggleImageStatePanel() {
+ invalidateOptionsMenu();
+ mShowingImageStatePanel = !mShowingImageStatePanel;
+ Fragment panel = getSupportFragmentManager().findFragmentByTag(MainPanel.FRAGMENT_TAG);
+ if (panel != null) {
+ if (panel instanceof EditorPanel) {
+ EditorPanel editorPanel = (EditorPanel) panel;
+ editorPanel.showImageStatePanel(mShowingImageStatePanel);
+ } else if (panel instanceof MainPanel) {
+ MainPanel mainPanel = (MainPanel) panel;
+ mainPanel.showImageStatePanel(mShowingImageStatePanel);
+ }
+ }
+ }
+
+ @Override
+ public void onConfigurationChanged(Configuration newConfig)
+ {
+ super.onConfigurationChanged(newConfig);
+ setDefaultValues();
+ loadXML();
+ fillCategories();
+ loadMainPanel();
+
+ // mLoadBitmapTask==null implies you have looked at the intent
+ if (!mShowingTinyPlanet && (mLoadBitmapTask == null)) {
+ mCategoryFiltersAdapter.removeTinyPlanet();
+ }
+ final View loading = findViewById(R.id.loading);
+ loading.setVisibility(View.GONE);
+ }
+
+ public void setupMasterImage() {
+
+ HistoryManager historyManager = new HistoryManager();
+ StateAdapter imageStateAdapter = new StateAdapter(this, 0);
+ MasterImage.reset();
+ mMasterImage = MasterImage.getImage();
+ mMasterImage.setHistoryManager(historyManager);
+ mMasterImage.setStateAdapter(imageStateAdapter);
+ mMasterImage.setActivity(this);
+
+ if (Runtime.getRuntime().maxMemory() > LIMIT_SUPPORTS_HIGHRES) {
+ mMasterImage.setSupportsHighRes(true);
+ } else {
+ mMasterImage.setSupportsHighRes(false);
+ }
+ }
+
+ void resetHistory() {
+ HistoryManager adapter = mMasterImage.getHistory();
+ adapter.reset();
+ HistoryItem historyItem = adapter.getItem(0);
+ ImagePreset original = new ImagePreset(historyItem.getImagePreset());
+ mMasterImage.setPreset(original, historyItem.getFilterRepresentation(), true);
+ invalidateViews();
+ backToMain();
+ }
+
+ public void showDefaultImageView() {
+ mEditorPlaceHolder.hide();
+ mImageShow.setVisibility(View.VISIBLE);
+ MasterImage.getImage().setCurrentFilter(null);
+ MasterImage.getImage().setCurrentFilterRepresentation(null);
+ }
+
+ public void backToMain() {
+ Fragment currentPanel = getSupportFragmentManager().findFragmentByTag(MainPanel.FRAGMENT_TAG);
+ if (currentPanel instanceof MainPanel) {
+ return;
+ }
+ loadMainPanel();
+ showDefaultImageView();
+ }
+
+ @Override
+ public void onBackPressed() {
+ Fragment currentPanel = getSupportFragmentManager().findFragmentByTag(MainPanel.FRAGMENT_TAG);
+ if (currentPanel instanceof MainPanel) {
+ if (!mImageShow.hasModifications()) {
+ done();
+ } else {
+ AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ builder.setMessage(R.string.unsaved).setTitle(R.string.save_before_exit);
+ builder.setPositiveButton(R.string.save_and_exit, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int id) {
+ saveImage();
+ }
+ });
+ builder.setNegativeButton(R.string.exit, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int id) {
+ done();
+ }
+ });
+ builder.show();
+ }
+ } else {
+ backToMain();
+ }
+ }
+
+ public void cannotLoadImage() {
+ Toast.makeText(this, R.string.cannot_load_image, Toast.LENGTH_SHORT).show();
+ finish();
+ }
+
+ // //////////////////////////////////////////////////////////////////////////////
+
+ public float getPixelsFromDip(float value) {
+ Resources r = getResources();
+ return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, value,
+ r.getDisplayMetrics());
+ }
+
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position,
+ long id) {
+ mMasterImage.onHistoryItemClick(position);
+ invalidateViews();
+ }
+
+ public void pickImage() {
+ Intent intent = new Intent();
+ intent.setType("image/*");
+ intent.setAction(Intent.ACTION_GET_CONTENT);
+ startActivityForResult(Intent.createChooser(intent, getString(R.string.select_image)),
+ SELECT_PICTURE);
+ }
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (resultCode == RESULT_OK) {
+ if (requestCode == SELECT_PICTURE) {
+ Uri selectedImageUri = data.getData();
+ startLoadBitmap(selectedImageUri);
+ }
+ }
+ }
+
+
+ public void saveImage() {
+ if (mImageShow.hasModifications()) {
+ // Get the name of the album, to which the image will be saved
+ File saveDir = SaveImage.getFinalSaveDirectory(this, mSelectedImageUri);
+ int bucketId = GalleryUtils.getBucketId(saveDir.getPath());
+ String albumName = LocalAlbum.getLocalizedName(getResources(), bucketId, null);
+ showSavingProgress(albumName);
+ mImageShow.saveImage(this, null);
+ } else {
+ done();
+ }
+ }
+
+
+ public void done() {
+ hideSavingProgress();
+ if (mLoadBitmapTask != null) {
+ mLoadBitmapTask.cancel(false);
+ }
+ finish();
+ }
+
+ private void extractXMPData() {
+ XMresults res = XmpPresets.extractXMPData(
+ getBaseContext(), mMasterImage, getIntent().getData());
+ if (res == null)
+ return;
+
+ mOriginalImageUri = res.originalimage;
+ mOriginalPreset = res.preset;
+ }
+
+ public Uri getSelectedImageUri() {
+ return mSelectedImageUri;
+ }
+
+}