FilterShowActivity.java revision 92e2341248e99c691f38820503984bc5e2f18811
1 2package com.android.gallery3d.filtershow; 3 4import android.annotation.TargetApi; 5import android.app.ActionBar; 6import android.app.Activity; 7import android.content.ContentValues; 8import android.content.Intent; 9import android.content.res.Resources; 10import android.graphics.drawable.Drawable; 11import android.net.Uri; 12import android.os.Bundle; 13import android.util.Log; 14import android.util.TypedValue; 15import android.view.Gravity; 16import android.view.Menu; 17import android.view.MenuItem; 18import android.view.MotionEvent; 19import android.view.View; 20import android.view.View.OnClickListener; 21import android.view.View.OnTouchListener; 22import android.widget.AdapterView; 23import android.widget.AdapterView.OnItemClickListener; 24import android.widget.ImageButton; 25import android.widget.LinearLayout; 26import android.widget.ListView; 27import android.widget.SeekBar; 28import android.widget.ShareActionProvider; 29import android.widget.ShareActionProvider.OnShareTargetSelectedListener; 30import android.widget.Toast; 31 32import com.android.gallery3d.R; 33import com.android.gallery3d.filtershow.cache.ImageLoader; 34import com.android.gallery3d.filtershow.filters.ImageFilter; 35import com.android.gallery3d.filtershow.filters.ImageFilterBorder; 36import com.android.gallery3d.filtershow.filters.ImageFilterRS; 37import com.android.gallery3d.filtershow.imageshow.ImageBorder; 38import com.android.gallery3d.filtershow.imageshow.ImageShow; 39import com.android.gallery3d.filtershow.imageshow.ImageSmallFilter; 40import com.android.gallery3d.filtershow.imageshow.ImageStraighten; 41import com.android.gallery3d.filtershow.imageshow.ImageZoom; 42import com.android.gallery3d.filtershow.presets.ImagePreset; 43import com.android.gallery3d.filtershow.presets.ImagePresetBW; 44import com.android.gallery3d.filtershow.presets.ImagePresetBWBlue; 45import com.android.gallery3d.filtershow.presets.ImagePresetBWGreen; 46import com.android.gallery3d.filtershow.presets.ImagePresetBWRed; 47import com.android.gallery3d.filtershow.presets.ImagePresetOld; 48import com.android.gallery3d.filtershow.presets.ImagePresetSaturated; 49import com.android.gallery3d.filtershow.presets.ImagePresetXProcessing; 50import com.android.gallery3d.filtershow.provider.SharedImageProvider; 51import com.android.gallery3d.filtershow.tools.SaveCopyTask; 52import com.android.gallery3d.filtershow.ui.ImageCurves; 53 54import java.io.File; 55import java.util.Vector; 56 57@TargetApi(16) 58public class FilterShowActivity extends Activity implements OnItemClickListener, 59 OnShareTargetSelectedListener { 60 61 private final PanelController mPanelController = new PanelController(); 62 private ImageLoader mImageLoader = null; 63 private ImageShow mImageShow = null; 64 private ImageCurves mImageCurves = null; 65 private ImageBorder mImageBorders = null; 66 private ImageStraighten mImageStraighten = null; 67 private ImageZoom mImageZoom = null; 68 69 private View mListFx = null; 70 private View mListBorders = null; 71 private View mListGeometry = null; 72 private View mListColors = null; 73 private View mListFilterButtons = null; 74 75 private ImageButton mFxButton = null; 76 private ImageButton mBorderButton = null; 77 private ImageButton mGeometryButton = null; 78 private ImageButton mColorsButton = null; 79 80 private static final int SELECT_PICTURE = 1; 81 private static final String LOGTAG = "FilterShowActivity"; 82 protected static final boolean ANIMATE_PANELS = true; 83 84 private boolean mShowingHistoryPanel = false; 85 private boolean mShowingImageStatePanel = false; 86 87 private final Vector<ImageShow> mImageViews = new Vector<ImageShow>(); 88 private final Vector<View> mListViews = new Vector<View>(); 89 private final Vector<ImageButton> mBottomPanelButtons = new Vector<ImageButton>(); 90 91 private ShareActionProvider mShareActionProvider; 92 private File mSharedOutputFile = null; 93 94 private boolean mSharingImage = false; 95 96 @Override 97 public void onCreate(Bundle savedInstanceState) { 98 super.onCreate(savedInstanceState); 99 100 ImageFilterRS.setRenderScriptContext(this); 101 102 setContentView(R.layout.filtershow_activity); 103 ActionBar actionBar = getActionBar(); 104 actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM); 105 actionBar.setCustomView(R.layout.filtershow_actionbar); 106 107 actionBar.getCustomView().setOnClickListener(new OnClickListener() { 108 @Override 109 public void onClick(View view) { 110 saveImage(); 111 } 112 }); 113 114 mImageLoader = new ImageLoader(getApplicationContext()); 115 116 LinearLayout listFilters = (LinearLayout) findViewById(R.id.listFilters); 117 LinearLayout listBorders = (LinearLayout) findViewById(R.id.listBorders); 118 119 mImageShow = (ImageShow) findViewById(R.id.imageShow); 120 mImageCurves = (ImageCurves) findViewById(R.id.imageCurves); 121 mImageBorders = (ImageBorder) findViewById(R.id.imageBorder); 122 mImageStraighten = (ImageStraighten) findViewById(R.id.imageStraighten); 123 mImageZoom = (ImageZoom) findViewById(R.id.imageZoom); 124 125 mImageViews.add(mImageShow); 126 mImageViews.add(mImageCurves); 127 mImageViews.add(mImageBorders); 128 mImageViews.add(mImageStraighten); 129 mImageViews.add(mImageZoom); 130 131 mListFx = findViewById(R.id.fxList); 132 mListBorders = findViewById(R.id.bordersList); 133 mListGeometry = findViewById(R.id.geometryList); 134 mListFilterButtons = findViewById(R.id.filterButtonsList); 135 mListColors = findViewById(R.id.colorsFxList); 136 mListViews.add(mListFx); 137 mListViews.add(mListBorders); 138 mListViews.add(mListGeometry); 139 mListViews.add(mListFilterButtons); 140 mListViews.add(mListColors); 141 142 mFxButton = (ImageButton) findViewById(R.id.fxButton); 143 mBorderButton = (ImageButton) findViewById(R.id.borderButton); 144 mGeometryButton = (ImageButton) findViewById(R.id.geometryButton); 145 mColorsButton = (ImageButton) findViewById(R.id.colorsButton); 146 147 mImageShow.setImageLoader(mImageLoader); 148 mImageCurves.setImageLoader(mImageLoader); 149 mImageCurves.setMaster(mImageShow); 150 mImageBorders.setImageLoader(mImageLoader); 151 mImageBorders.setMaster(mImageShow); 152 mImageStraighten.setImageLoader(mImageLoader); 153 mImageStraighten.setMaster(mImageShow); 154 mImageZoom.setImageLoader(mImageLoader); 155 mImageZoom.setMaster(mImageShow); 156 157 mPanelController.addImageView(findViewById(R.id.imageShow)); 158 mPanelController.addImageView(findViewById(R.id.imageCurves)); 159 mPanelController.addImageView(findViewById(R.id.imageBorder)); 160 mPanelController.addImageView(findViewById(R.id.imageStraighten)); 161 mPanelController.addImageView(findViewById(R.id.imageZoom)); 162 163 mPanelController.addPanel(mFxButton, mListFx, 0); 164 mPanelController.addPanel(mBorderButton, mListBorders, 1); 165 166 mPanelController.addPanel(mGeometryButton, mListGeometry, 2); 167 mPanelController.addComponent(mGeometryButton, findViewById(R.id.straightenButton)); 168 mPanelController.addComponent(mGeometryButton, findViewById(R.id.cropButton)); 169 mPanelController.addComponent(mGeometryButton, findViewById(R.id.rotateButton)); 170 mPanelController.addComponent(mGeometryButton, findViewById(R.id.flipButton)); 171 172 mPanelController.addPanel(mColorsButton, mListColors, 3); 173 mPanelController.addComponent(mColorsButton, findViewById(R.id.vignetteButton)); 174 mPanelController.addComponent(mColorsButton, findViewById(R.id.curvesButtonRGB)); 175 mPanelController.addComponent(mColorsButton, findViewById(R.id.sharpenButton)); 176 mPanelController.addComponent(mColorsButton, findViewById(R.id.vibranceButton)); 177 mPanelController.addComponent(mColorsButton, findViewById(R.id.contrastButton)); 178 mPanelController.addComponent(mColorsButton, findViewById(R.id.saturationButton)); 179 mPanelController.addComponent(mColorsButton, findViewById(R.id.tintButton)); 180 mPanelController.addComponent(mColorsButton, findViewById(R.id.exposureButton)); 181 mPanelController.addComponent(mColorsButton, findViewById(R.id.shadowRecoveryButton)); 182 183 mPanelController.addView(findViewById(R.id.resetEffect)); 184 mPanelController.addView(findViewById(R.id.applyEffect)); 185 186 findViewById(R.id.compareWithOriginalImage).setOnTouchListener(createOnTouchShowOriginalButton()); 187 188 findViewById(R.id.resetOperationsButton).setOnClickListener( 189 createOnClickResetOperationsButton()); 190 191 ListView operationsList = (ListView) findViewById(R.id.operationsList); 192 operationsList.setAdapter(mImageShow.getHistoryAdapter()); 193 operationsList.setOnItemClickListener(this); 194 ListView imageStateList = (ListView) findViewById(R.id.imageStateList); 195 imageStateList.setAdapter(mImageShow.getImageStateAdapter()); 196 mImageLoader.setAdapter((HistoryAdapter) mImageShow.getHistoryAdapter()); 197 198 fillListImages(listFilters); 199 fillListBorders(listBorders); 200 201 SeekBar seekBar = (SeekBar) findViewById(R.id.filterSeekBar); 202 seekBar.setMax(200); 203 mImageShow.setSeekBar(seekBar); 204 mPanelController.setRowPanel(findViewById(R.id.secondRowPanel)); 205 mPanelController.setUtilityPanel(findViewById(R.id.filterButtonsList), 206 findViewById(R.id.compareWithOriginalImage), 207 findViewById(R.id.applyEffect)); 208 mPanelController.setMasterImage(mImageShow); 209 mPanelController.setCurrentPanel(mFxButton); 210 211 Intent intent = getIntent(); 212 String data = intent.getDataString(); 213 if (data != null) { 214 Uri uri = Uri.parse(data); 215 mImageLoader.loadBitmap(uri); 216 } else { 217 pickImage(); 218 } 219 } 220 221 public void completeSaveImage(Uri saveUri) { 222 if (mSharingImage && mSharedOutputFile != null) { 223 // Image saved, we unblock the content provider 224 Uri uri = Uri.withAppendedPath(SharedImageProvider.CONTENT_URI, 225 Uri.encode(mSharedOutputFile.getAbsolutePath())); 226 ContentValues values = new ContentValues(); 227 values.put(SharedImageProvider.PREPARE, false); 228 getContentResolver().insert(uri, values); 229 } 230 setResult(RESULT_OK, new Intent().setData(saveUri)); 231 finish(); 232 } 233 234 @Override 235 public boolean onShareTargetSelected(ShareActionProvider arg0, Intent arg1) { 236 // First, let's tell the SharedImageProvider that it will need to wait 237 // for the image 238 Uri uri = Uri.withAppendedPath(SharedImageProvider.CONTENT_URI, 239 Uri.encode(mSharedOutputFile.getAbsolutePath())); 240 ContentValues values = new ContentValues(); 241 values.put(SharedImageProvider.PREPARE, true); 242 getContentResolver().insert(uri, values); 243 mSharingImage = true; 244 245 // Process and save the image in the background. 246 mImageShow.saveImage(this, mSharedOutputFile); 247 return true; 248 } 249 250 private Intent getDefaultShareIntent() { 251 Intent intent = new Intent(Intent.ACTION_SEND); 252 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); 253 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); 254 intent.setType(SharedImageProvider.MIME_TYPE); 255 mSharedOutputFile = SaveCopyTask.getNewFile(this, mImageLoader.getUri()); 256 Uri uri = Uri.withAppendedPath(SharedImageProvider.CONTENT_URI, 257 Uri.encode(mSharedOutputFile.getAbsolutePath())); 258 intent.putExtra(Intent.EXTRA_STREAM, uri); 259 return intent; 260 } 261 262 @Override 263 public boolean onCreateOptionsMenu(Menu menu) { 264 getMenuInflater().inflate(R.menu.filtershow_activity_menu, menu); 265 MenuItem showHistory = menu.findItem(R.id.operationsButton); 266 if (mShowingHistoryPanel) { 267 showHistory.setTitle(R.string.hide_history_panel); 268 } else { 269 showHistory.setTitle(R.string.show_history_panel); 270 } 271 MenuItem showState = menu.findItem(R.id.showImageStateButton); 272 if (mShowingImageStatePanel) { 273 showState.setTitle(R.string.hide_imagestate_panel); 274 } else { 275 showState.setTitle(R.string.show_imagestate_panel); 276 } 277 mShareActionProvider = (ShareActionProvider) menu.findItem(R.id.menu_share) 278 .getActionProvider(); 279 mShareActionProvider.setShareIntent(getDefaultShareIntent()); 280 mShareActionProvider.setOnShareTargetSelectedListener(this); 281 return true; 282 } 283 284 @Override 285 public boolean onOptionsItemSelected(MenuItem item) { 286 switch (item.getItemId()) { 287 case R.id.undoButton: { 288 HistoryAdapter adapter = (HistoryAdapter) mImageShow 289 .getHistoryAdapter(); 290 int position = adapter.undo(); 291 mImageShow.onItemClick(position); 292 mImageShow.showToast("Undo"); 293 invalidateViews(); 294 return true; 295 } 296 case R.id.redoButton: { 297 HistoryAdapter adapter = (HistoryAdapter) mImageShow 298 .getHistoryAdapter(); 299 int position = adapter.redo(); 300 mImageShow.onItemClick(position); 301 mImageShow.showToast("Redo"); 302 invalidateViews(); 303 return true; 304 } 305 case R.id.resetHistoryButton: { 306 resetHistory(); 307 return true; 308 } 309 case R.id.showImageStateButton: { 310 toggleImageStatePanel(); 311 return true; 312 } 313 case R.id.operationsButton: { 314 toggleHistoryPanel(); 315 return true; 316 } 317 case android.R.id.home: { 318 saveImage(); 319 return true; 320 } 321 } 322 return false; 323 } 324 325 private void fillListImages(LinearLayout listFilters) { 326 // TODO: use listview 327 // TODO: load the filters straight from the filesystem 328 ImagePreset[] preset = new ImagePreset[9]; 329 int p = 0; 330 preset[p++] = new ImagePreset(); 331 preset[p++] = new ImagePresetSaturated(); 332 preset[p++] = new ImagePresetOld(); 333 preset[p++] = new ImagePresetXProcessing(); 334 preset[p++] = new ImagePresetBW(); 335 preset[p++] = new ImagePresetBWRed(); 336 preset[p++] = new ImagePresetBWGreen(); 337 preset[p++] = new ImagePresetBWBlue(); 338 339 for (int i = 0; i < p; i++) { 340 ImageSmallFilter filter = new ImageSmallFilter(getBaseContext()); 341 preset[i].setIsFx(true); 342 filter.setImagePreset(preset[i]); 343 filter.setController(this); 344 filter.setImageLoader(mImageLoader); 345 listFilters.addView(filter); 346 } 347 348 // Default preset (original) 349 mImageShow.setImagePreset(preset[0]); 350 } 351 352 private void fillListBorders(LinearLayout listBorders) { 353 // TODO: use listview 354 // TODO: load the borders straight from the filesystem 355 int p = 0; 356 ImageFilter[] borders = new ImageFilter[8]; 357 borders[p++] = new ImageFilterBorder(null); 358 359 Drawable npd3 = getResources().getDrawable(R.drawable.filtershow_border_film3); 360 borders[p++] = new ImageFilterBorder(npd3); 361 Drawable npd = getResources().getDrawable( 362 R.drawable.filtershow_border_scratch3); 363 borders[p++] = new ImageFilterBorder(npd); 364 Drawable npd2 = getResources().getDrawable(R.drawable.filtershow_border_black); 365 borders[p++] = new ImageFilterBorder(npd2); 366 Drawable npd6 = getResources().getDrawable( 367 R.drawable.filtershow_border_rounded_black); 368 borders[p++] = new ImageFilterBorder(npd6); 369 Drawable npd4 = getResources().getDrawable(R.drawable.filtershow_border_white); 370 borders[p++] = new ImageFilterBorder(npd4); 371 Drawable npd5 = getResources().getDrawable( 372 R.drawable.filtershow_border_rounded_white); 373 borders[p++] = new ImageFilterBorder(npd5); 374 375 for (int i = 0; i < p; i++) { 376 ImageSmallFilter filter = new ImageSmallFilter(getBaseContext()); 377 filter.setImageFilter(borders[i]); 378 filter.setController(this); 379 filter.setImageLoader(mImageLoader); 380 filter.setShowTitle(false); 381 listBorders.addView(filter); 382 } 383 } 384 385 // ////////////////////////////////////////////////////////////////////////////// 386 // Some utility functions 387 // TODO: finish the cleanup. 388 389 public void showOriginalViews(boolean value) { 390 for (ImageShow views : mImageViews) { 391 views.showOriginal(value); 392 } 393 } 394 395 public void invalidateViews() { 396 for (ImageShow views : mImageViews) { 397 views.invalidate(); 398 } 399 } 400 401 public void hideListViews() { 402 for (View view : mListViews) { 403 view.setVisibility(View.GONE); 404 } 405 } 406 407 public void hideImageViews() { 408 mImageShow.setShowControls(false); // reset 409 for (View view : mImageViews) { 410 view.setVisibility(View.GONE); 411 } 412 } 413 414 public void unselectBottomPanelButtons() { 415 for (ImageButton button : mBottomPanelButtons) { 416 button.setSelected(false); 417 } 418 } 419 420 public void unselectPanelButtons(Vector<ImageButton> buttons) { 421 for (ImageButton button : buttons) { 422 button.setSelected(false); 423 } 424 } 425 426 // ////////////////////////////////////////////////////////////////////////////// 427 // Click handlers for the top row buttons 428 429 private OnTouchListener createOnTouchShowOriginalButton() { 430 return new View.OnTouchListener() { 431 @Override 432 public boolean onTouch(View v, MotionEvent event) { 433 boolean show = false; 434 if ((event.getActionMasked() != MotionEvent.ACTION_UP) 435 || (event.getActionMasked() == MotionEvent.ACTION_CANCEL)) { 436 show = true; 437 } 438 showOriginalViews(show); 439 return true; 440 } 441 }; 442 } 443 444 // ////////////////////////////////////////////////////////////////////////////// 445 // imageState panel... 446 447 private void toggleImageStatePanel() { 448 final View view = findViewById(R.id.mainPanel); 449 final View viewList = findViewById(R.id.imageStatePanel); 450 451 if (mShowingHistoryPanel) { 452 findViewById(R.id.historyPanel).setVisibility(View.INVISIBLE); 453 mShowingHistoryPanel = false; 454 } 455 456 if (!mShowingImageStatePanel) { 457 mShowingImageStatePanel = true; 458 view.animate().setDuration(200).x(-viewList.getWidth()) 459 .withLayer().withEndAction(new Runnable() { 460 @Override 461 public void run() { 462 viewList.setAlpha(0); 463 viewList.setVisibility(View.VISIBLE); 464 viewList.animate().setDuration(100) 465 .alpha(1.0f).start(); 466 } 467 }).start(); 468 } else { 469 mShowingImageStatePanel = false; 470 viewList.setVisibility(View.INVISIBLE); 471 view.animate().setDuration(200).x(0).withLayer() 472 .start(); 473 } 474 invalidateOptionsMenu(); 475 } 476 477 // ////////////////////////////////////////////////////////////////////////////// 478 // history panel... 479 480 private void toggleHistoryPanel() { 481 final View view = findViewById(R.id.mainPanel); 482 final View viewList = findViewById(R.id.historyPanel); 483 484 if (mShowingImageStatePanel) { 485 findViewById(R.id.imageStatePanel).setVisibility(View.INVISIBLE); 486 mShowingImageStatePanel = false; 487 } 488 489 if (!mShowingHistoryPanel) { 490 mShowingHistoryPanel = true; 491 view.animate().setDuration(200).x(-viewList.getWidth()) 492 .withLayer().withEndAction(new Runnable() { 493 @Override 494 public void run() { 495 viewList.setAlpha(0); 496 viewList.setVisibility(View.VISIBLE); 497 viewList.animate().setDuration(100) 498 .alpha(1.0f).start(); 499 } 500 }).start(); 501 } else { 502 mShowingHistoryPanel = false; 503 viewList.setVisibility(View.INVISIBLE); 504 view.animate().setDuration(200).x(0).withLayer() 505 .start(); 506 } 507 invalidateOptionsMenu(); 508 } 509 510 private void resetHistory() { 511 HistoryAdapter adapter = (HistoryAdapter) mImageShow 512 .getHistoryAdapter(); 513 adapter.reset(); 514 ImagePreset original = new ImagePreset(adapter.getItem(0)); 515 mImageShow.setImagePreset(original); 516 invalidateViews(); 517 } 518 519 // reset button in the history panel. 520 private OnClickListener createOnClickResetOperationsButton() { 521 return new View.OnClickListener() { 522 @Override 523 public void onClick(View v) { 524 resetHistory(); 525 } 526 }; 527 } 528 529 // ////////////////////////////////////////////////////////////////////////////// 530 531 public float getPixelsFromDip(float value) { 532 Resources r = getResources(); 533 return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, value, 534 r.getDisplayMetrics()); 535 } 536 537 public void useImagePreset(ImagePreset preset) { 538 if (preset == null) { 539 return; 540 } 541 ImagePreset copy = new ImagePreset(preset); 542 mImageShow.setImagePreset(copy); 543 if (preset.isFx()) { 544 // if it's an FX we rest the curve adjustment too 545 mImageCurves.resetCurve(); 546 } 547 invalidateViews(); 548 } 549 550 public void useImageFilter(ImageFilter imageFilter) { 551 if (imageFilter == null) { 552 return; 553 } 554 ImagePreset oldPreset = mImageShow.getImagePreset(); 555 ImagePreset copy = new ImagePreset(oldPreset); 556 // TODO: use a numerical constant instead. 557 if (imageFilter.getName().equalsIgnoreCase("Border")) { 558 copy.remove("Border"); 559 copy.setHistoryName("Border"); 560 } 561 copy.add(imageFilter); 562 mImageShow.setImagePreset(copy); 563 invalidateViews(); 564 } 565 566 @Override 567 public void onItemClick(AdapterView<?> parent, View view, int position, 568 long id) { 569 mImageShow.onItemClick(position); 570 invalidateViews(); 571 } 572 573 public void pickImage() { 574 Intent intent = new Intent(); 575 intent.setType("image/*"); 576 intent.setAction(Intent.ACTION_GET_CONTENT); 577 startActivityForResult(Intent.createChooser(intent, getString(R.string.select_image)), 578 SELECT_PICTURE); 579 } 580 581 @Override 582 public void onActivityResult(int requestCode, int resultCode, Intent data) { 583 Log.v(LOGTAG, "onActivityResult"); 584 if (resultCode == RESULT_OK) { 585 if (requestCode == SELECT_PICTURE) { 586 Uri selectedImageUri = data.getData(); 587 mImageLoader.loadBitmap(selectedImageUri); 588 } 589 } 590 } 591 592 public void saveImage() { 593 Toast toast = Toast.makeText(getBaseContext(), getString(R.string.saving_image), 594 Toast.LENGTH_SHORT); 595 toast.setGravity(Gravity.CENTER, 0, 0); 596 toast.show(); 597 598 mImageShow.saveImage(this, null); 599 } 600 601 static { 602 System.loadLibrary("jni_filtershow_filters"); 603 } 604 605} 606