blob: 27aaed2ebc780f064c6d5e285e0acf13efce8ce0 [file] [log] [blame]
Yuli Huang6a12ad72011-09-12 22:25:30 +08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.gallery3d.photoeditor;
18
19import android.app.Activity;
Yuli Huang6a12ad72011-09-12 22:25:30 +080020import android.content.Intent;
Yuli Huangae70ae42011-10-01 02:05:06 +080021import android.graphics.Bitmap;
Yuli Huang6a12ad72011-09-12 22:25:30 +080022import android.net.Uri;
23import android.os.Bundle;
Yuli Huang6a12ad72011-09-12 22:25:30 +080024
25import com.android.gallery3d.R;
26
27/**
Yuli Huangae70ae42011-10-01 02:05:06 +080028 * Main activity of the photo editor that opens a photo and prepares tools for photo editing.
Yuli Huang6a12ad72011-09-12 22:25:30 +080029 */
30public class PhotoEditor extends Activity {
31
Yuli Huang90b7a7a2011-11-09 15:10:45 +080032 private static final String SAVE_URI_KEY = "save_uri";
33
Yuli Huang915d5832011-10-05 00:01:02 +080034 private Uri sourceUri;
35 private Uri saveUri;
Yuli Huang6a12ad72011-09-12 22:25:30 +080036 private FilterStack filterStack;
Yuli Huangae70ae42011-10-01 02:05:06 +080037 private ActionBar actionBar;
Yuli Huangf963bc22011-11-10 16:50:31 +080038 private EffectsBar effectsBar;
Yuli Huangd67ec742012-03-07 01:18:08 +080039 private Toolbar toolbar;
Yuli Huang6a12ad72011-09-12 22:25:30 +080040
41 @Override
42 public void onCreate(Bundle savedInstanceState) {
43 super.onCreate(savedInstanceState);
44 setContentView(R.layout.photoeditor_main);
45
46 Intent intent = getIntent();
Yuli Huang915d5832011-10-05 00:01:02 +080047 if (Intent.ACTION_EDIT.equalsIgnoreCase(intent.getAction())) {
48 sourceUri = intent.getData();
49 }
Yuli Huang6a12ad72011-09-12 22:25:30 +080050
Yuli Huangd67ec742012-03-07 01:18:08 +080051 toolbar = (Toolbar) findViewById(R.id.toolbar);
Yuli Huangae70ae42011-10-01 02:05:06 +080052 actionBar = (ActionBar) findViewById(R.id.action_bar);
53 filterStack = new FilterStack((PhotoView) findViewById(R.id.photo_view),
54 new FilterStack.StackListener() {
Yuli Huang6a12ad72011-09-12 22:25:30 +080055
Yuli Huangae70ae42011-10-01 02:05:06 +080056 @Override
57 public void onStackChanged(boolean canUndo, boolean canRedo) {
Yuli Huangb5c54b62011-10-18 12:42:50 +080058 actionBar.updateButtons(canUndo, canRedo);
Yuli Huangae70ae42011-10-01 02:05:06 +080059 }
Yuli Huang738e82e2011-11-04 16:39:50 +080060 }, savedInstanceState);
Yuli Huang90b7a7a2011-11-09 15:10:45 +080061 if (savedInstanceState != null) {
62 saveUri = savedInstanceState.getParcelable(SAVE_URI_KEY);
63 actionBar.updateSave(saveUri == null);
64 }
Yuli Huangae70ae42011-10-01 02:05:06 +080065
Yuli Huangf963bc22011-11-10 16:50:31 +080066 // Effects-bar is initially disabled until photo is successfully loaded.
67 effectsBar = (EffectsBar) findViewById(R.id.effects_bar);
Yuli Huangae70ae42011-10-01 02:05:06 +080068 effectsBar.initialize(filterStack);
Yuli Huangf963bc22011-11-10 16:50:31 +080069 effectsBar.setEnabled(false);
Yuli Huangae70ae42011-10-01 02:05:06 +080070
Yuli Huangf963bc22011-11-10 16:50:31 +080071 actionBar.setClickRunnable(R.id.undo_button, createUndoRedoRunnable(true));
72 actionBar.setClickRunnable(R.id.redo_button, createUndoRedoRunnable(false));
73 actionBar.setClickRunnable(R.id.save_button, createSaveRunnable());
74 actionBar.setClickRunnable(R.id.share_button, createShareRunnable());
75 actionBar.setClickRunnable(R.id.action_bar_back, createBackRunnable());
Yuli Huangae70ae42011-10-01 02:05:06 +080076 }
77
Yuli Huangae70ae42011-10-01 02:05:06 +080078 private void openPhoto() {
Yuli Huang5cac6d52012-03-12 16:34:41 +080079 toolbar.showSpinner();
Yuli Huangae70ae42011-10-01 02:05:06 +080080 LoadScreennailTask.Callback callback = new LoadScreennailTask.Callback() {
Yuli Huang6a12ad72011-09-12 22:25:30 +080081
82 @Override
Yuli Huangae70ae42011-10-01 02:05:06 +080083 public void onComplete(final Bitmap result) {
84 filterStack.setPhotoSource(result, new OnDoneCallback() {
85
86 @Override
87 public void onDone() {
Yuli Huang5cac6d52012-03-12 16:34:41 +080088 toolbar.dismissSpinner();
Yuli Huangf963bc22011-11-10 16:50:31 +080089 effectsBar.setEnabled(result != null);
Yuli Huangae70ae42011-10-01 02:05:06 +080090 }
91 });
92 }
93 };
Yuli Huang915d5832011-10-05 00:01:02 +080094 new LoadScreennailTask(this, callback).execute(sourceUri);
Yuli Huangae70ae42011-10-01 02:05:06 +080095 }
96
Yuli Huangf963bc22011-11-10 16:50:31 +080097 private Runnable createUndoRedoRunnable(final boolean undo) {
Yuli Huangae70ae42011-10-01 02:05:06 +080098 return new Runnable() {
99
100 @Override
101 public void run() {
102 effectsBar.exit(new Runnable() {
103
104 @Override
105 public void run() {
Yuli Huang5cac6d52012-03-12 16:34:41 +0800106 toolbar.showSpinner();
Yuli Huangae70ae42011-10-01 02:05:06 +0800107 OnDoneCallback callback = new OnDoneCallback() {
108
109 @Override
110 public void onDone() {
Yuli Huang5cac6d52012-03-12 16:34:41 +0800111 toolbar.dismissSpinner();
Yuli Huangae70ae42011-10-01 02:05:06 +0800112 }
113 };
114 if (undo) {
115 filterStack.undo(callback);
116 } else {
117 filterStack.redo(callback);
118 }
119 }
120 });
121 }
122 };
123 }
124
Yuli Huangf963bc22011-11-10 16:50:31 +0800125 private Runnable createSaveRunnable() {
Yuli Huangae70ae42011-10-01 02:05:06 +0800126 return new Runnable() {
127
128 @Override
129 public void run() {
130 effectsBar.exit(new Runnable() {
131
132 @Override
133 public void run() {
Yuli Huang5cac6d52012-03-12 16:34:41 +0800134 toolbar.showSpinner();
Yuli Huang738e82e2011-11-04 16:39:50 +0800135 filterStack.getOutputBitmap(new OnDoneBitmapCallback() {
Yuli Huangae70ae42011-10-01 02:05:06 +0800136
137 @Override
138 public void onDone(Bitmap bitmap) {
139 SaveCopyTask.Callback callback = new SaveCopyTask.Callback() {
140
141 @Override
142 public void onComplete(Uri result) {
Yuli Huang5cac6d52012-03-12 16:34:41 +0800143 toolbar.dismissSpinner();
Yuli Huang915d5832011-10-05 00:01:02 +0800144 saveUri = result;
Yuli Huang90b7a7a2011-11-09 15:10:45 +0800145 actionBar.updateSave(saveUri == null);
Yuli Huangae70ae42011-10-01 02:05:06 +0800146 }
147 };
Yuli Huang915d5832011-10-05 00:01:02 +0800148 new SaveCopyTask(PhotoEditor.this, sourceUri, callback).execute(
149 bitmap);
Yuli Huangae70ae42011-10-01 02:05:06 +0800150 }
151 });
152 }
153 });
154 }
155 };
156 }
157
Yuli Huangf963bc22011-11-10 16:50:31 +0800158 private Runnable createShareRunnable() {
Yuli Huang915d5832011-10-05 00:01:02 +0800159 return new Runnable() {
160
161 @Override
162 public void run() {
163 effectsBar.exit(new Runnable() {
164
165 @Override
166 public void run() {
167 if (saveUri != null) {
168 Intent intent = new Intent(Intent.ACTION_SEND);
169 intent.putExtra(Intent.EXTRA_STREAM, saveUri);
170 intent.setType("image/*");
171 startActivity(intent);
172 }
173 }
174 });
175 }
176 };
177 }
178
Yuli Huangf963bc22011-11-10 16:50:31 +0800179 private Runnable createBackRunnable() {
Yuli Huangae70ae42011-10-01 02:05:06 +0800180 return new Runnable() {
181
182 @Override
183 public void run() {
184 // Exit effects or go back to the previous activity on pressing back button.
185 if (!effectsBar.exit(null)) {
Yuli Huang2f61a1c2012-05-03 15:59:23 +0800186 // Pop-up a dialog if there are unsaved changes.
Yuli Huangb5c54b62011-10-18 12:42:50 +0800187 if (actionBar.canSave()) {
Yuli Huang2f61a1c2012-05-03 15:59:23 +0800188 new YesCancelDialogBuilder(PhotoEditor.this, new Runnable() {
Yuli Huang6a12ad72011-09-12 22:25:30 +0800189
190 @Override
191 public void run() {
Yuli Huangf50ce2b2012-05-02 00:50:56 +0800192 // Discard unsaved photo for the result.
Yuli Huang6a12ad72011-09-12 22:25:30 +0800193 finish();
194 }
Yuli Huang2f61a1c2012-05-03 15:59:23 +0800195 }, R.string.discard_unsaved_photo).show();
Yuli Huangae70ae42011-10-01 02:05:06 +0800196 } else {
Yuli Huangf50ce2b2012-05-02 00:50:56 +0800197 setResult(RESULT_OK, new Intent().setData(saveUri));
Yuli Huangae70ae42011-10-01 02:05:06 +0800198 finish();
Yuli Huang6a12ad72011-09-12 22:25:30 +0800199 }
200 }
201 }
Yuli Huangae70ae42011-10-01 02:05:06 +0800202 };
Yuli Huang6a12ad72011-09-12 22:25:30 +0800203 }
204
205 @Override
Yuli Huang738e82e2011-11-04 16:39:50 +0800206 protected void onSaveInstanceState(Bundle outState) {
207 super.onSaveInstanceState(outState);
208 filterStack.saveStacks(outState);
Yuli Huang90b7a7a2011-11-09 15:10:45 +0800209 outState.putParcelable(SAVE_URI_KEY, saveUri);
Yuli Huang738e82e2011-11-04 16:39:50 +0800210 }
211
212 @Override
Yuli Huang6a12ad72011-09-12 22:25:30 +0800213 public void onBackPressed() {
Yuli Huangb5c54b62011-10-18 12:42:50 +0800214 actionBar.clickBack();
Yuli Huang6a12ad72011-09-12 22:25:30 +0800215 }
216
217 @Override
218 protected void onPause() {
Yuli Huang6a12ad72011-09-12 22:25:30 +0800219 super.onPause();
220 filterStack.onPause();
Yuli Huang3235a3e2011-11-14 22:38:16 +0800221 // Dismiss any running progress dialog as all operations are paused.
Yuli Huang5cac6d52012-03-12 16:34:41 +0800222 toolbar.dismissSpinner();
Yuli Huang6a12ad72011-09-12 22:25:30 +0800223 }
224
225 @Override
226 protected void onResume() {
227 super.onResume();
228 filterStack.onResume();
Yuli Huangae70ae42011-10-01 02:05:06 +0800229 openPhoto();
Yuli Huang6a12ad72011-09-12 22:25:30 +0800230 }
231}