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