FilterShowActivity.java revision 5b188c94f5895cd166fc29def1e5295498e298c9
1/* 2 * Copyright (C) 2012 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.filtershow; 18 19import android.annotation.TargetApi; 20import android.app.ActionBar; 21import android.app.Activity; 22import android.app.ProgressDialog; 23import android.content.ContentValues; 24import android.content.Intent; 25import android.content.res.Configuration; 26import android.content.res.Resources; 27import android.graphics.Bitmap; 28import android.graphics.BitmapFactory; 29import android.graphics.Color; 30import android.graphics.Point; 31import android.graphics.drawable.Drawable; 32import android.net.Uri; 33import android.os.AsyncTask; 34import android.os.Bundle; 35import android.util.DisplayMetrics; 36import android.util.Log; 37import android.util.TypedValue; 38import android.view.Display; 39import android.view.Menu; 40import android.view.MenuItem; 41import android.view.View; 42import android.view.View.OnClickListener; 43import android.view.WindowManager; 44import android.widget.AdapterView; 45import android.widget.AdapterView.OnItemClickListener; 46import android.widget.ImageButton; 47import android.widget.LinearLayout; 48import android.widget.ListView; 49import android.widget.SeekBar; 50import android.widget.ShareActionProvider; 51import android.widget.ShareActionProvider.OnShareTargetSelectedListener; 52import android.widget.Toast; 53 54import com.android.gallery3d.R; 55import com.android.gallery3d.data.LocalAlbum; 56import com.android.gallery3d.filtershow.cache.ImageLoader; 57import com.android.gallery3d.filtershow.filters.ImageFilter; 58import com.android.gallery3d.filtershow.filters.ImageFilterBorder; 59import com.android.gallery3d.filtershow.filters.ImageFilterBwFilter; 60import com.android.gallery3d.filtershow.filters.ImageFilterContrast; 61import com.android.gallery3d.filtershow.filters.ImageFilterExposure; 62import com.android.gallery3d.filtershow.filters.ImageFilterFx; 63import com.android.gallery3d.filtershow.filters.ImageFilterHue; 64import com.android.gallery3d.filtershow.filters.ImageFilterParametricBorder; 65import com.android.gallery3d.filtershow.filters.ImageFilterRS; 66import com.android.gallery3d.filtershow.filters.ImageFilterSaturated; 67import com.android.gallery3d.filtershow.filters.ImageFilterShadows; 68import com.android.gallery3d.filtershow.filters.ImageFilterTinyPlanet; 69import com.android.gallery3d.filtershow.filters.ImageFilterVibrance; 70import com.android.gallery3d.filtershow.filters.ImageFilterVignette; 71import com.android.gallery3d.filtershow.filters.ImageFilterWBalance; 72import com.android.gallery3d.filtershow.imageshow.ImageBorder; 73import com.android.gallery3d.filtershow.imageshow.ImageCrop; 74import com.android.gallery3d.filtershow.imageshow.ImageFlip; 75import com.android.gallery3d.filtershow.imageshow.ImageRotate; 76import com.android.gallery3d.filtershow.imageshow.ImageShow; 77import com.android.gallery3d.filtershow.imageshow.ImageSmallBorder; 78import com.android.gallery3d.filtershow.imageshow.ImageSmallFilter; 79import com.android.gallery3d.filtershow.imageshow.ImageStraighten; 80import com.android.gallery3d.filtershow.imageshow.ImageTinyPlanet; 81import com.android.gallery3d.filtershow.imageshow.ImageWithIcon; 82import com.android.gallery3d.filtershow.imageshow.ImageZoom; 83import com.android.gallery3d.filtershow.presets.ImagePreset; 84import com.android.gallery3d.filtershow.provider.SharedImageProvider; 85import com.android.gallery3d.filtershow.tools.SaveCopyTask; 86import com.android.gallery3d.filtershow.ui.FramedTextButton; 87import com.android.gallery3d.filtershow.ui.ImageButtonTitle; 88import com.android.gallery3d.filtershow.ui.ImageCurves; 89import com.android.gallery3d.filtershow.ui.Spline; 90import com.android.gallery3d.util.GalleryUtils; 91 92import java.io.File; 93import java.lang.ref.WeakReference; 94import java.util.Vector; 95 96@TargetApi(16) 97public class FilterShowActivity extends Activity implements OnItemClickListener, 98 OnShareTargetSelectedListener { 99 100 public static final String CROP_ACTION = "com.android.camera.action.EDITOR_CROP"; 101 public static final String TINY_PLANET_ACTION = "com.android.camera.action.TINY_PLANET"; 102 public static final String LAUNCH_FULLSCREEN = "launch-fullscreen"; 103 private final PanelController mPanelController = new PanelController(); 104 private ImageLoader mImageLoader = null; 105 private ImageShow mImageShow = null; 106 private ImageCurves mImageCurves = null; 107 private ImageBorder mImageBorders = null; 108 private ImageStraighten mImageStraighten = null; 109 private ImageZoom mImageZoom = null; 110 private ImageCrop mImageCrop = null; 111 private ImageRotate mImageRotate = null; 112 private ImageFlip mImageFlip = null; 113 private ImageTinyPlanet mImageTinyPlanet = null; 114 115 private View mListFx = null; 116 private View mListBorders = null; 117 private View mListGeometry = null; 118 private View mListColors = null; 119 private View mListFilterButtons = null; 120 121 private ImageButton mFxButton = null; 122 private ImageButton mBorderButton = null; 123 private ImageButton mGeometryButton = null; 124 private ImageButton mColorsButton = null; 125 126 private ImageSmallFilter mCurrentImageSmallFilter = null; 127 private static final int SELECT_PICTURE = 1; 128 private static final String LOGTAG = "FilterShowActivity"; 129 protected static final boolean ANIMATE_PANELS = true; 130 private static int mImageBorderSize = 4; // in percent 131 132 private boolean mShowingHistoryPanel = false; 133 private boolean mShowingImageStatePanel = false; 134 135 private final Vector<ImageShow> mImageViews = new Vector<ImageShow>(); 136 private final Vector<View> mListViews = new Vector<View>(); 137 private final Vector<ImageButton> mBottomPanelButtons = new Vector<ImageButton>(); 138 139 private ShareActionProvider mShareActionProvider; 140 private File mSharedOutputFile = null; 141 142 private boolean mSharingImage = false; 143 144 private WeakReference<ProgressDialog> mSavingProgressDialog; 145 private static final int SEEK_BAR_MAX = 600; 146 147 private LoadBitmapTask mLoadBitmapTask; 148 private ImageSmallFilter mNullFxFilter; 149 private ImageSmallFilter mNullBorderFilter; 150 151 @Override 152 public void onCreate(Bundle savedInstanceState) { 153 super.onCreate(savedInstanceState); 154 155 ImageFilterRS.setRenderScriptContext(this); 156 157 ImageShow.setDefaultBackgroundColor(getResources().getColor(R.color.background_screen)); 158 ImageSmallFilter.setDefaultBackgroundColor(getResources().getColor(R.color.background_main_toolbar)); 159 // TODO: get those values from XML. 160 ImageZoom.setZoomedSize(getPixelsFromDip(256)); 161 FramedTextButton.setTextSize((int) getPixelsFromDip(14)); 162 FramedTextButton.setTrianglePadding((int) getPixelsFromDip(4)); 163 FramedTextButton.setTriangleSize((int) getPixelsFromDip(10)); 164 ImageShow.setTextSize((int) getPixelsFromDip(12)); 165 ImageShow.setTextPadding((int) getPixelsFromDip(10)); 166 ImageShow.setOriginalTextMargin((int) getPixelsFromDip(4)); 167 ImageShow.setOriginalTextSize((int) getPixelsFromDip(18)); 168 ImageShow.setOriginalText(getResources().getString(R.string.original_picture_text)); 169 ImageButtonTitle.setTextSize((int) getPixelsFromDip(12)); 170 ImageButtonTitle.setTextPadding((int) getPixelsFromDip(10)); 171 ImageSmallFilter.setMargin((int) getPixelsFromDip(3)); 172 ImageSmallFilter.setTextMargin((int) getPixelsFromDip(4)); 173 Drawable curveHandle = getResources().getDrawable(R.drawable.camera_crop); 174 int curveHandleSize = (int) getResources().getDimension(R.dimen.crop_indicator_size); 175 Spline.setCurveHandle(curveHandle, curveHandleSize); 176 Spline.setCurveWidth((int) getPixelsFromDip(3)); 177 178 setContentView(R.layout.filtershow_activity); 179 ActionBar actionBar = getActionBar(); 180 actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM); 181 actionBar.setCustomView(R.layout.filtershow_actionbar); 182 183 actionBar.getCustomView().setOnClickListener(new OnClickListener() { 184 @Override 185 public void onClick(View view) { 186 saveImage(); 187 } 188 }); 189 190 mImageLoader = new ImageLoader(this, getApplicationContext()); 191 192 LinearLayout listFilters = (LinearLayout) findViewById(R.id.listFilters); 193 LinearLayout listBorders = (LinearLayout) findViewById(R.id.listBorders); 194 LinearLayout listColors = (LinearLayout) findViewById(R.id.listColorsFx); 195 196 mImageShow = (ImageShow) findViewById(R.id.imageShow); 197 mImageCurves = (ImageCurves) findViewById(R.id.imageCurves); 198 mImageBorders = (ImageBorder) findViewById(R.id.imageBorder); 199 mImageStraighten = (ImageStraighten) findViewById(R.id.imageStraighten); 200 mImageZoom = (ImageZoom) findViewById(R.id.imageZoom); 201 mImageCrop = (ImageCrop) findViewById(R.id.imageCrop); 202 mImageRotate = (ImageRotate) findViewById(R.id.imageRotate); 203 mImageFlip = (ImageFlip) findViewById(R.id.imageFlip); 204 mImageTinyPlanet = (ImageTinyPlanet) findViewById(R.id.imageTinyPlanet); 205 206 mImageCrop.setAspectTextSize((int) getPixelsFromDip(18)); 207 ImageCrop.setTouchTolerance((int) getPixelsFromDip(25)); 208 mImageViews.add(mImageShow); 209 mImageViews.add(mImageCurves); 210 mImageViews.add(mImageBorders); 211 mImageViews.add(mImageStraighten); 212 mImageViews.add(mImageZoom); 213 mImageViews.add(mImageCrop); 214 mImageViews.add(mImageRotate); 215 mImageViews.add(mImageFlip); 216 mImageViews.add(mImageTinyPlanet); 217 218 mListFx = findViewById(R.id.fxList); 219 mListBorders = findViewById(R.id.bordersList); 220 mListGeometry = findViewById(R.id.geometryList); 221 mListFilterButtons = findViewById(R.id.filterButtonsList); 222 mListColors = findViewById(R.id.colorsFxList); 223 mListViews.add(mListFx); 224 mListViews.add(mListBorders); 225 mListViews.add(mListGeometry); 226 mListViews.add(mListFilterButtons); 227 mListViews.add(mListColors); 228 229 mFxButton = (ImageButton) findViewById(R.id.fxButton); 230 mBorderButton = (ImageButton) findViewById(R.id.borderButton); 231 mGeometryButton = (ImageButton) findViewById(R.id.geometryButton); 232 mColorsButton = (ImageButton) findViewById(R.id.colorsButton); 233 234 mBottomPanelButtons.add(mFxButton); 235 mBottomPanelButtons.add(mBorderButton); 236 mBottomPanelButtons.add(mGeometryButton); 237 mBottomPanelButtons.add(mColorsButton); 238 239 mImageShow.setImageLoader(mImageLoader); 240 mImageCurves.setImageLoader(mImageLoader); 241 mImageCurves.setMaster(mImageShow); 242 mImageBorders.setImageLoader(mImageLoader); 243 mImageBorders.setMaster(mImageShow); 244 mImageStraighten.setImageLoader(mImageLoader); 245 mImageStraighten.setMaster(mImageShow); 246 mImageZoom.setImageLoader(mImageLoader); 247 mImageZoom.setMaster(mImageShow); 248 mImageCrop.setImageLoader(mImageLoader); 249 mImageCrop.setMaster(mImageShow); 250 mImageRotate.setImageLoader(mImageLoader); 251 mImageRotate.setMaster(mImageShow); 252 mImageFlip.setImageLoader(mImageLoader); 253 mImageFlip.setMaster(mImageShow); 254 mImageTinyPlanet.setImageLoader(mImageLoader); 255 mImageTinyPlanet.setMaster(mImageShow); 256 257 mPanelController.setActivity(this); 258 259 mPanelController.addImageView(findViewById(R.id.imageShow)); 260 mPanelController.addImageView(findViewById(R.id.imageCurves)); 261 mPanelController.addImageView(findViewById(R.id.imageBorder)); 262 mPanelController.addImageView(findViewById(R.id.imageStraighten)); 263 mPanelController.addImageView(findViewById(R.id.imageCrop)); 264 mPanelController.addImageView(findViewById(R.id.imageRotate)); 265 mPanelController.addImageView(findViewById(R.id.imageFlip)); 266 mPanelController.addImageView(findViewById(R.id.imageZoom)); 267 mPanelController.addImageView(findViewById(R.id.imageTinyPlanet)); 268 269 mPanelController.addPanel(mFxButton, mListFx, 0); 270 mPanelController.addPanel(mBorderButton, mListBorders, 1); 271 272 mPanelController.addPanel(mGeometryButton, mListGeometry, 2); 273 mPanelController.addComponent(mGeometryButton, findViewById(R.id.straightenButton)); 274 mPanelController.addComponent(mGeometryButton, findViewById(R.id.cropButton)); 275 mPanelController.addComponent(mGeometryButton, findViewById(R.id.rotateButton)); 276 mPanelController.addComponent(mGeometryButton, findViewById(R.id.flipButton)); 277 278 mPanelController.addPanel(mColorsButton, mListColors, 3); 279 280 int[] recastIDs = { 281 R.id.tinyplanetButton, 282 R.id.vignetteButton, 283 R.id.vibranceButton, 284 R.id.contrastButton, 285 R.id.saturationButton, 286 R.id.bwfilterButton, 287 R.id.wbalanceButton, 288 R.id.hueButton, 289 R.id.exposureButton, 290 R.id.shadowRecoveryButton 291 }; 292 ImageFilter[] filters = { 293 new ImageFilterTinyPlanet(), 294 new ImageFilterVignette(), 295 new ImageFilterVibrance(), 296 new ImageFilterContrast(), 297 new ImageFilterSaturated(), 298 new ImageFilterBwFilter(), 299 new ImageFilterWBalance(), 300 new ImageFilterHue(), 301 new ImageFilterExposure(), 302 new ImageFilterShadows() 303 }; 304 305 for (int i = 0; i < filters.length; i++) { 306 ImageSmallFilter fView = new ImageSmallFilter(this); 307 View v = listColors.findViewById(recastIDs[i]); 308 int pos = listColors.indexOfChild(v); 309 listColors.removeView(v); 310 311 filters[i].setParameter(filters[i].getPreviewParameter()); 312 if (v instanceof ImageButtonTitle) 313 filters[i].setName(((ImageButtonTitle) v).getText()); 314 fView.setImageFilter(filters[i]); 315 fView.setController(this); 316 fView.setImageLoader(mImageLoader); 317 fView.setId(recastIDs[i]); 318 mPanelController.addComponent(mColorsButton, fView); 319 listColors.addView(fView, pos); 320 } 321 322 int[] overlayIDs = { 323 R.id.sharpenButton, 324 R.id.curvesButtonRGB 325 }; 326 int[] overlayBitmaps = { 327 R.drawable.filtershow_button_colors_sharpen, 328 R.drawable.filtershow_button_colors_curve 329 }; 330 int[] overlayNames = { 331 R.string.sharpness, 332 R.string.curvesRGB 333 }; 334 335 for (int i = 0; i < overlayIDs.length; i++) { 336 ImageWithIcon fView = new ImageWithIcon(this); 337 View v = listColors.findViewById(overlayIDs[i]); 338 int pos = listColors.indexOfChild(v); 339 listColors.removeView(v); 340 final int sid = overlayNames[i]; 341 ImageFilterExposure efilter = new ImageFilterExposure() { 342 { 343 mName = getString(sid); 344 } 345 }; 346 efilter.setParameter(-300); 347 Bitmap bitmap = BitmapFactory.decodeResource(getResources(), 348 overlayBitmaps[i]); 349 350 fView.setIcon(bitmap); 351 fView.setImageFilter(efilter); 352 fView.setController(this); 353 fView.setImageLoader(mImageLoader); 354 fView.setId(overlayIDs[i]); 355 mPanelController.addComponent(mColorsButton, fView); 356 listColors.addView(fView, pos); 357 } 358 359 mPanelController.addView(findViewById(R.id.applyEffect)); 360 mPanelController.addView(findViewById(R.id.pickCurvesChannel)); 361 mPanelController.addView(findViewById(R.id.aspect)); 362 findViewById(R.id.resetOperationsButton).setOnClickListener( 363 createOnClickResetOperationsButton()); 364 365 ListView operationsList = (ListView) findViewById(R.id.operationsList); 366 operationsList.setAdapter(mImageShow.getHistory()); 367 operationsList.setOnItemClickListener(this); 368 ListView imageStateList = (ListView) findViewById(R.id.imageStateList); 369 imageStateList.setAdapter(mImageShow.getImageStateAdapter()); 370 mImageLoader.setAdapter(mImageShow.getHistory()); 371 372 fillListImages(listFilters); 373 fillListBorders(listBorders); 374 375 SeekBar seekBar = (SeekBar) findViewById(R.id.filterSeekBar); 376 seekBar.setMax(SEEK_BAR_MAX); 377 378 mImageShow.setSeekBar(seekBar); 379 mImageZoom.setSeekBar(seekBar); 380 mImageTinyPlanet.setSeekBar(seekBar); 381 mPanelController.setRowPanel(findViewById(R.id.secondRowPanel)); 382 mPanelController.setUtilityPanel(this, findViewById(R.id.filterButtonsList), 383 findViewById(R.id.applyEffect), findViewById(R.id.aspect), 384 findViewById(R.id.pickCurvesChannel)); 385 mPanelController.setMasterImage(mImageShow); 386 mPanelController.setCurrentPanel(mFxButton); 387 Intent intent = getIntent(); 388 if (intent.getBooleanExtra(LAUNCH_FULLSCREEN, false)) { 389 getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); 390 } 391 392 if (intent.getData() != null) { 393 startLoadBitmap(intent.getData()); 394 } else { 395 pickImage(); 396 } 397 398 String action = intent.getAction(); 399 if (action.equalsIgnoreCase(CROP_ACTION)) { 400 mPanelController.showComponent(findViewById(R.id.cropButton)); 401 } else if (action.equalsIgnoreCase(TINY_PLANET_ACTION)) { 402 mPanelController.showComponent(findViewById(R.id.tinyplanetButton)); 403 } 404 } 405 406 private void startLoadBitmap(Uri uri) { 407 final View filters = findViewById(R.id.filtersPanel); 408 final View loading = findViewById(R.id.loading); 409 loading.setVisibility(View.VISIBLE); 410 filters.setVisibility(View.INVISIBLE); 411 View tinyPlanetView = findViewById(R.id.tinyplanetButton); 412 if (tinyPlanetView != null) { 413 tinyPlanetView.setVisibility(View.GONE); 414 } 415 mLoadBitmapTask = new LoadBitmapTask(tinyPlanetView); 416 mLoadBitmapTask.execute(uri); 417 } 418 419 private class LoadBitmapTask extends AsyncTask<Uri, Void, Boolean> { 420 View mTinyPlanetButton; 421 int mBitmapSize; 422 423 public LoadBitmapTask(View button) { 424 mTinyPlanetButton = button; 425 mBitmapSize = getScreenImageSize(); 426 } 427 428 @Override 429 protected Boolean doInBackground(Uri... params) { 430 mImageLoader.loadBitmap(params[0], mBitmapSize); 431 publishProgress(); 432 return mImageLoader.queryLightCycle360(); 433 } 434 435 @Override 436 protected void onProgressUpdate(Void... values) { 437 super.onProgressUpdate(values); 438 if (isCancelled()) return; 439 final View filters = findViewById(R.id.filtersPanel); 440 final View loading = findViewById(R.id.loading); 441 loading.setVisibility(View.GONE); 442 filters.setVisibility(View.VISIBLE); 443 } 444 445 @Override 446 protected void onPostExecute(Boolean result) { 447 if (isCancelled()) { 448 return; 449 } 450 if (result) { 451 mTinyPlanetButton.setVisibility(View.VISIBLE); 452 } 453 mLoadBitmapTask = null; 454 super.onPostExecute(result); 455 } 456 457 } 458 459 @Override 460 protected void onDestroy() { 461 if (mLoadBitmapTask != null) { 462 mLoadBitmapTask.cancel(false); 463 } 464 super.onDestroy(); 465 } 466 467 private int translateMainPanel(View viewPanel) { 468 int accessoryPanelWidth = viewPanel.getWidth(); 469 int mainViewWidth = findViewById(R.id.mainView).getWidth(); 470 int mainPanelWidth = mImageShow.getDisplayedImageBounds().width(); 471 if (mainPanelWidth == 0) { 472 mainPanelWidth = mainViewWidth; 473 } 474 int filtersPanelWidth = findViewById(R.id.filtersPanel).getWidth(); 475 if (mainPanelWidth < filtersPanelWidth) { 476 mainPanelWidth = filtersPanelWidth; 477 } 478 int leftOver = mainViewWidth - mainPanelWidth - accessoryPanelWidth; 479 if (leftOver < 0) { 480 return -accessoryPanelWidth; 481 } 482 return 0; 483 } 484 485 private int getScreenImageSize() { 486 DisplayMetrics metrics = new DisplayMetrics(); 487 Display display = getWindowManager().getDefaultDisplay(); 488 Point size = new Point(); 489 display.getSize(size); 490 display.getMetrics(metrics); 491 int msize = Math.min(size.x, size.y); 492 return (133 * msize) / metrics.densityDpi; 493 } 494 495 private void showSavingProgress(String albumName) { 496 ProgressDialog progress; 497 if (mSavingProgressDialog != null) { 498 progress = mSavingProgressDialog.get(); 499 if (progress != null) { 500 progress.show(); 501 return; 502 } 503 } 504 // TODO: Allow cancellation of the saving process 505 String progressText; 506 if (albumName == null) { 507 progressText = getString(R.string.saving_image); 508 } else { 509 progressText = getString(R.string.filtershow_saving_image, albumName); 510 } 511 progress = ProgressDialog.show(this, "", progressText, true, false); 512 mSavingProgressDialog = new WeakReference<ProgressDialog>(progress); 513 } 514 515 private void hideSavingProgress() { 516 if (mSavingProgressDialog != null) { 517 ProgressDialog progress = mSavingProgressDialog.get(); 518 if (progress != null) 519 progress.dismiss(); 520 } 521 } 522 523 public void completeSaveImage(Uri saveUri) { 524 if (mSharingImage && mSharedOutputFile != null) { 525 // Image saved, we unblock the content provider 526 Uri uri = Uri.withAppendedPath(SharedImageProvider.CONTENT_URI, 527 Uri.encode(mSharedOutputFile.getAbsolutePath())); 528 ContentValues values = new ContentValues(); 529 values.put(SharedImageProvider.PREPARE, false); 530 getContentResolver().insert(uri, values); 531 } 532 setResult(RESULT_OK, new Intent().setData(saveUri)); 533 hideSavingProgress(); 534 finish(); 535 } 536 537 @Override 538 public boolean onShareTargetSelected(ShareActionProvider arg0, Intent arg1) { 539 // First, let's tell the SharedImageProvider that it will need to wait 540 // for the image 541 Uri uri = Uri.withAppendedPath(SharedImageProvider.CONTENT_URI, 542 Uri.encode(mSharedOutputFile.getAbsolutePath())); 543 ContentValues values = new ContentValues(); 544 values.put(SharedImageProvider.PREPARE, true); 545 getContentResolver().insert(uri, values); 546 mSharingImage = true; 547 548 // Process and save the image in the background. 549 showSavingProgress(null); 550 mImageShow.saveImage(this, mSharedOutputFile); 551 return true; 552 } 553 554 private Intent getDefaultShareIntent() { 555 Intent intent = new Intent(Intent.ACTION_SEND); 556 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); 557 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); 558 intent.setType(SharedImageProvider.MIME_TYPE); 559 mSharedOutputFile = SaveCopyTask.getNewFile(this, mImageLoader.getUri()); 560 Uri uri = Uri.withAppendedPath(SharedImageProvider.CONTENT_URI, 561 Uri.encode(mSharedOutputFile.getAbsolutePath())); 562 intent.putExtra(Intent.EXTRA_STREAM, uri); 563 return intent; 564 } 565 566 @Override 567 public boolean onCreateOptionsMenu(Menu menu) { 568 getMenuInflater().inflate(R.menu.filtershow_activity_menu, menu); 569 MenuItem showHistory = menu.findItem(R.id.operationsButton); 570 if (mShowingHistoryPanel) { 571 showHistory.setTitle(R.string.hide_history_panel); 572 } else { 573 showHistory.setTitle(R.string.show_history_panel); 574 } 575 MenuItem showState = menu.findItem(R.id.showImageStateButton); 576 if (mShowingImageStatePanel) { 577 showState.setTitle(R.string.hide_imagestate_panel); 578 } else { 579 showState.setTitle(R.string.show_imagestate_panel); 580 } 581 mShareActionProvider = (ShareActionProvider) menu.findItem(R.id.menu_share) 582 .getActionProvider(); 583 mShareActionProvider.setShareIntent(getDefaultShareIntent()); 584 mShareActionProvider.setOnShareTargetSelectedListener(this); 585 586 MenuItem undoItem = menu.findItem(R.id.undoButton); 587 MenuItem redoItem = menu.findItem(R.id.redoButton); 588 MenuItem resetItem = menu.findItem(R.id.resetHistoryButton); 589 mImageShow.getHistory().setMenuItems(undoItem, redoItem, resetItem); 590 return true; 591 } 592 593 @Override 594 public void onPause() { 595 super.onPause(); 596 if (mShareActionProvider != null) { 597 mShareActionProvider.setOnShareTargetSelectedListener(null); 598 } 599 } 600 601 @Override 602 public void onResume() { 603 super.onResume(); 604 if (mShareActionProvider != null) { 605 mShareActionProvider.setOnShareTargetSelectedListener(this); 606 } 607 } 608 609 @Override 610 public boolean onOptionsItemSelected(MenuItem item) { 611 switch (item.getItemId()) { 612 case R.id.undoButton: { 613 HistoryAdapter adapter = mImageShow.getHistory(); 614 int position = adapter.undo(); 615 mImageShow.onItemClick(position); 616 mImageShow.showToast("Undo"); 617 invalidateViews(); 618 return true; 619 } 620 case R.id.redoButton: { 621 HistoryAdapter adapter = mImageShow.getHistory(); 622 int position = adapter.redo(); 623 mImageShow.onItemClick(position); 624 mImageShow.showToast("Redo"); 625 invalidateViews(); 626 return true; 627 } 628 case R.id.resetHistoryButton: { 629 resetHistory(); 630 return true; 631 } 632 case R.id.showImageStateButton: { 633 toggleImageStatePanel(); 634 return true; 635 } 636 case R.id.operationsButton: { 637 toggleHistoryPanel(); 638 return true; 639 } 640 case android.R.id.home: { 641 saveImage(); 642 return true; 643 } 644 } 645 return false; 646 } 647 648 private void fillListImages(LinearLayout listFilters) { 649 // TODO: use listview 650 // TODO: load the filters straight from the filesystem 651 652 ImageFilterFx[] fxArray = new ImageFilterFx[18]; 653 int p = 0; 654 655 int[] drawid = { 656 R.drawable.filtershow_fx_0005_punch, 657 R.drawable.filtershow_fx_0000_vintage, 658 R.drawable.filtershow_fx_0004_bw_contrast, 659 R.drawable.filtershow_fx_0002_bleach, 660 R.drawable.filtershow_fx_0001_instant, 661 R.drawable.filtershow_fx_0007_washout, 662 R.drawable.filtershow_fx_0003_blue_crush, 663 R.drawable.filtershow_fx_0008_washout_color, 664 R.drawable.filtershow_fx_0006_x_process 665 }; 666 667 int[] fxNameid = { 668 R.string.ffx_punch, 669 R.string.ffx_vintage, 670 R.string.ffx_bw_contrast, 671 R.string.ffx_bleach, 672 R.string.ffx_instant, 673 R.string.ffx_washout, 674 R.string.ffx_blue_crush, 675 R.string.ffx_washout_color, 676 R.string.ffx_x_process 677 }; 678 679 ImagePreset preset = new ImagePreset(getString(R.string.history_original)); // empty 680 preset.setImageLoader(mImageLoader); 681 mNullFxFilter = new ImageSmallFilter(this); 682 683 mNullFxFilter.setSelected(true); 684 mCurrentImageSmallFilter = mNullFxFilter; 685 686 mNullFxFilter.setImageFilter(new ImageFilterFx(null, getString(R.string.none))); 687 688 mNullFxFilter.setController(this); 689 mNullFxFilter.setImageLoader(mImageLoader); 690 listFilters.addView(mNullFxFilter); 691 ImageSmallFilter previousFilter = mNullFxFilter; 692 693 BitmapFactory.Options o = new BitmapFactory.Options(); 694 o.inScaled = false; 695 696 for (int i = 0; i < drawid.length; i++) { 697 Bitmap b = BitmapFactory.decodeResource(getResources(), drawid[i], o); 698 fxArray[p++] = new ImageFilterFx(b, getString(fxNameid[i])); 699 } 700 ImageSmallFilter filter; 701 for (int i = 0; i < p; i++) { 702 filter = new ImageSmallFilter(this); 703 filter.setImageFilter(fxArray[i]); 704 filter.setController(this); 705 filter.setNulfilter(mNullFxFilter); 706 filter.setImageLoader(mImageLoader); 707 listFilters.addView(filter); 708 previousFilter = filter; 709 } 710 711 // Default preset (original) 712 mImageShow.setImagePreset(preset); 713 } 714 715 private void fillListBorders(LinearLayout listBorders) { 716 // TODO: use listview 717 // TODO: load the borders straight from the filesystem 718 int p = 0; 719 ImageFilter[] borders = new ImageFilter[12]; 720 borders[p++] = new ImageFilterBorder(null); 721 722 Drawable npd1 = getResources().getDrawable(R.drawable.filtershow_border_4x5); 723 borders[p++] = new ImageFilterBorder(npd1); 724 Drawable npd2 = getResources().getDrawable(R.drawable.filtershow_border_brush); 725 borders[p++] = new ImageFilterBorder(npd2); 726 Drawable npd3 = getResources().getDrawable(R.drawable.filtershow_border_grunge); 727 borders[p++] = new ImageFilterBorder(npd3); 728 Drawable npd4 = getResources().getDrawable(R.drawable.filtershow_border_sumi_e); 729 borders[p++] = new ImageFilterBorder(npd4); 730 Drawable npd5 = getResources().getDrawable(R.drawable.filtershow_border_tape); 731 borders[p++] = new ImageFilterBorder(npd5); 732 borders[p++] = new ImageFilterParametricBorder(Color.BLACK, mImageBorderSize, 0); 733 borders[p++] = new ImageFilterParametricBorder(Color.BLACK, mImageBorderSize, 734 mImageBorderSize); 735 borders[p++] = new ImageFilterParametricBorder(Color.WHITE, mImageBorderSize, 0); 736 borders[p++] = new ImageFilterParametricBorder(Color.WHITE, mImageBorderSize, 737 mImageBorderSize); 738 int creamColor = Color.argb(255, 237, 237, 227); 739 borders[p++] = new ImageFilterParametricBorder(creamColor, mImageBorderSize, 0); 740 borders[p++] = new ImageFilterParametricBorder(creamColor, mImageBorderSize, 741 mImageBorderSize); 742 743 ImageSmallFilter previousFilter = null; 744 for (int i = 0; i < p; i++) { 745 ImageSmallBorder filter = new ImageSmallBorder(this); 746 if (i == 0) { // save the first to reset it 747 mNullBorderFilter = filter; 748 } else { 749 filter.setNulfilter(mNullBorderFilter); 750 } 751 borders[i].setName(getString(R.string.borders)); 752 filter.setImageFilter(borders[i]); 753 filter.setController(this); 754 filter.setBorder(true); 755 filter.setImageLoader(mImageLoader); 756 filter.setShowTitle(false); 757 listBorders.addView(filter); 758 previousFilter = filter; 759 } 760 } 761 762 // ////////////////////////////////////////////////////////////////////////////// 763 // Some utility functions 764 // TODO: finish the cleanup. 765 766 public void showOriginalViews(boolean value) { 767 for (ImageShow views : mImageViews) { 768 views.showOriginal(value); 769 } 770 } 771 772 public void invalidateViews() { 773 for (ImageShow views : mImageViews) { 774 views.invalidate(); 775 views.updateImage(); 776 } 777 } 778 779 public void hideListViews() { 780 for (View view : mListViews) { 781 view.setVisibility(View.GONE); 782 } 783 } 784 785 public void hideImageViews() { 786 mImageShow.setShowControls(false); // reset 787 for (View view : mImageViews) { 788 view.setVisibility(View.GONE); 789 } 790 } 791 792 public void unselectBottomPanelButtons() { 793 for (ImageButton button : mBottomPanelButtons) { 794 button.setSelected(false); 795 } 796 } 797 798 public void unselectPanelButtons(Vector<ImageButton> buttons) { 799 for (ImageButton button : buttons) { 800 button.setSelected(false); 801 } 802 } 803 804 public void disableFilterButtons() { 805 for (ImageButton b : mBottomPanelButtons) { 806 b.setEnabled(false); 807 b.setClickable(false); 808 b.setAlpha(0.4f); 809 } 810 } 811 812 public void enableFilterButtons() { 813 for (ImageButton b : mBottomPanelButtons) { 814 b.setEnabled(true); 815 b.setClickable(true); 816 b.setAlpha(1.0f); 817 } 818 } 819 820 // ////////////////////////////////////////////////////////////////////////////// 821 // imageState panel... 822 823 public boolean isShowingHistoryPanel() { 824 return mShowingHistoryPanel; 825 } 826 827 private void toggleImageStatePanel() { 828 final View view = findViewById(R.id.mainPanel); 829 final View viewList = findViewById(R.id.imageStatePanel); 830 831 if (mShowingHistoryPanel) { 832 findViewById(R.id.historyPanel).setVisibility(View.INVISIBLE); 833 mShowingHistoryPanel = false; 834 } 835 836 int translate = translateMainPanel(viewList); 837 if (!mShowingImageStatePanel) { 838 mShowingImageStatePanel = true; 839 view.animate().setDuration(200).x(translate) 840 .withLayer().withEndAction(new Runnable() { 841 @Override 842 public void run() { 843 viewList.setAlpha(0); 844 viewList.setVisibility(View.VISIBLE); 845 viewList.animate().setDuration(100) 846 .alpha(1.0f).start(); 847 } 848 }).start(); 849 } else { 850 mShowingImageStatePanel = false; 851 viewList.setVisibility(View.INVISIBLE); 852 view.animate().setDuration(200).x(0).withLayer() 853 .start(); 854 } 855 invalidateOptionsMenu(); 856 } 857 858 @Override 859 public void onConfigurationChanged(Configuration newConfig) 860 { 861 super.onConfigurationChanged(newConfig); 862 if (mShowingHistoryPanel) { 863 toggleHistoryPanel(); 864 } 865 } 866 867 // ////////////////////////////////////////////////////////////////////////////// 868 // history panel... 869 870 public void toggleHistoryPanel() { 871 final View view = findViewById(R.id.mainPanel); 872 final View viewList = findViewById(R.id.historyPanel); 873 874 if (mShowingImageStatePanel) { 875 findViewById(R.id.imageStatePanel).setVisibility(View.INVISIBLE); 876 mShowingImageStatePanel = false; 877 } 878 879 int translate = translateMainPanel(viewList); 880 if (!mShowingHistoryPanel) { 881 mShowingHistoryPanel = true; 882 view.animate().setDuration(200).x(translate) 883 .withLayer().withEndAction(new Runnable() { 884 @Override 885 public void run() { 886 viewList.setAlpha(0); 887 viewList.setVisibility(View.VISIBLE); 888 viewList.animate().setDuration(100) 889 .alpha(1.0f).start(); 890 } 891 }).start(); 892 } else { 893 mShowingHistoryPanel = false; 894 viewList.setVisibility(View.INVISIBLE); 895 view.animate().setDuration(200).x(0).withLayer() 896 .start(); 897 } 898 invalidateOptionsMenu(); 899 } 900 901 void resetHistory() { 902 mNullFxFilter.onClick(mNullFxFilter); 903 mNullBorderFilter.onClick(mNullBorderFilter); 904 905 HistoryAdapter adapter = mImageShow.getHistory(); 906 adapter.reset(); 907 ImagePreset original = new ImagePreset(adapter.getItem(0)); 908 mImageShow.setImagePreset(original); 909 mPanelController.resetParameters(); 910 invalidateViews(); 911 } 912 913 // reset button in the history panel. 914 private OnClickListener createOnClickResetOperationsButton() { 915 return new View.OnClickListener() { 916 @Override 917 public void onClick(View v) { 918 919 resetHistory(); 920 } 921 }; 922 } 923 924 @Override 925 public void onBackPressed() { 926 if (mPanelController.onBackPressed()) { 927 saveImage(); 928 } 929 } 930 931 public void cannotLoadImage() { 932 CharSequence text = getString(R.string.cannot_load_image); 933 Toast toast = Toast.makeText(this, text, Toast.LENGTH_SHORT); 934 toast.show(); 935 finish(); 936 } 937 938 // ////////////////////////////////////////////////////////////////////////////// 939 940 public float getPixelsFromDip(float value) { 941 Resources r = getResources(); 942 return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, value, 943 r.getDisplayMetrics()); 944 } 945 946 public void useImagePreset(ImageSmallFilter imageSmallFilter, ImagePreset preset) { 947 if (preset == null) { 948 return; 949 } 950 951 if (mCurrentImageSmallFilter != null) { 952 mCurrentImageSmallFilter.setSelected(false); 953 } 954 mCurrentImageSmallFilter = imageSmallFilter; 955 mCurrentImageSmallFilter.setSelected(true); 956 957 ImagePreset copy = new ImagePreset(preset); 958 mImageShow.setImagePreset(copy); 959 if (preset.isFx()) { 960 // if it's an FX we rest the curve adjustment too 961 mImageCurves.resetCurve(); 962 } 963 invalidateViews(); 964 } 965 966 public void useImageFilter(ImageSmallFilter imageSmallFilter, ImageFilter imageFilter, 967 boolean setBorder) { 968 if (imageFilter == null) { 969 return; 970 } 971 972 if (mCurrentImageSmallFilter != null) { 973 mCurrentImageSmallFilter.setSelected(false); 974 } 975 mCurrentImageSmallFilter = imageSmallFilter; 976 mCurrentImageSmallFilter.setSelected(true); 977 978 ImagePreset oldPreset = mImageShow.getImagePreset(); 979 ImagePreset copy = new ImagePreset(oldPreset); 980 // TODO: use a numerical constant instead. 981 982 copy.add(imageFilter); 983 984 mImageShow.setImagePreset(copy); 985 invalidateViews(); 986 } 987 988 @Override 989 public void onItemClick(AdapterView<?> parent, View view, int position, 990 long id) { 991 mImageShow.onItemClick(position); 992 invalidateViews(); 993 } 994 995 public void pickImage() { 996 Intent intent = new Intent(); 997 intent.setType("image/*"); 998 intent.setAction(Intent.ACTION_GET_CONTENT); 999 startActivityForResult(Intent.createChooser(intent, getString(R.string.select_image)), 1000 SELECT_PICTURE); 1001 } 1002 1003 @Override 1004 public void onActivityResult(int requestCode, int resultCode, Intent data) { 1005 Log.v(LOGTAG, "onActivityResult"); 1006 if (resultCode == RESULT_OK) { 1007 if (requestCode == SELECT_PICTURE) { 1008 Uri selectedImageUri = data.getData(); 1009 startLoadBitmap(selectedImageUri); 1010 } 1011 } 1012 } 1013 1014 public void saveImage() { 1015 if (mImageShow.hasModifications()) { 1016 // Get the name of the album, to which the image will be saved 1017 File saveDir = SaveCopyTask.getFinalSaveDirectory(this, mImageLoader.getUri()); 1018 int bucketId = GalleryUtils.getBucketId(saveDir.getPath()); 1019 String albumName = LocalAlbum.getLocalizedName(getResources(), bucketId, null); 1020 showSavingProgress(albumName); 1021 mImageShow.saveImage(this, null); 1022 } else { 1023 finish(); 1024 } 1025 } 1026 1027 static { 1028 System.loadLibrary("jni_filtershow_filters"); 1029 } 1030 1031} 1032