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