FilterShowActivity.java revision 34cfdfcd1867fff67fffbbac7a8e942485f08ea1
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.app.ActionBar; 20import android.app.AlertDialog; 21import android.app.ProgressDialog; 22import android.content.ComponentName; 23import android.content.ContentValues; 24import android.content.Context; 25import android.content.DialogInterface; 26import android.content.Intent; 27import android.content.ServiceConnection; 28import android.content.pm.ActivityInfo; 29import android.content.res.Configuration; 30import android.content.res.Resources; 31import android.graphics.Bitmap; 32import android.graphics.Matrix; 33import android.graphics.Point; 34import android.graphics.Rect; 35import android.graphics.RectF; 36import android.graphics.drawable.ColorDrawable; 37import android.graphics.drawable.Drawable; 38import android.net.Uri; 39import android.os.AsyncTask; 40import android.os.Bundle; 41import android.os.CancellationSignal; 42import android.os.Handler; 43import android.os.IBinder; 44import android.support.v4.app.DialogFragment; 45import android.support.v4.app.Fragment; 46import android.support.v4.app.FragmentActivity; 47import android.support.v4.app.FragmentTransaction; 48import android.util.DisplayMetrics; 49import android.util.Log; 50import android.util.TypedValue; 51import android.view.Menu; 52import android.view.MenuItem; 53import android.view.MotionEvent; 54import android.view.View; 55import android.view.View.OnClickListener; 56import android.view.ViewPropertyAnimator; 57import android.view.WindowManager; 58import android.widget.AdapterView; 59import android.widget.AdapterView.OnItemClickListener; 60import android.widget.FrameLayout; 61import android.widget.ShareActionProvider; 62import android.widget.ShareActionProvider.OnShareTargetSelectedListener; 63import android.widget.Toast; 64 65import com.android.gallery3d.R; 66import com.android.gallery3d.app.PhotoPage; 67import com.android.gallery3d.data.LocalAlbum; 68import com.android.gallery3d.filtershow.cache.ImageLoader; 69import com.android.gallery3d.filtershow.category.Action; 70import com.android.gallery3d.filtershow.category.CategoryAdapter; 71import com.android.gallery3d.filtershow.category.CategorySelected; 72import com.android.gallery3d.filtershow.category.CategoryView; 73import com.android.gallery3d.filtershow.category.MainPanel; 74import com.android.gallery3d.filtershow.category.SwipableView; 75import com.android.gallery3d.filtershow.data.UserPresetsManager; 76import com.android.gallery3d.filtershow.editors.BasicEditor; 77import com.android.gallery3d.filtershow.editors.Editor; 78import com.android.gallery3d.filtershow.editors.EditorChanSat; 79import com.android.gallery3d.filtershow.editors.EditorColorBorder; 80import com.android.gallery3d.filtershow.editors.EditorCrop; 81import com.android.gallery3d.filtershow.editors.EditorDraw; 82import com.android.gallery3d.filtershow.editors.EditorGrad; 83import com.android.gallery3d.filtershow.editors.EditorManager; 84import com.android.gallery3d.filtershow.editors.EditorMirror; 85import com.android.gallery3d.filtershow.editors.EditorPanel; 86import com.android.gallery3d.filtershow.editors.EditorRedEye; 87import com.android.gallery3d.filtershow.editors.EditorRotate; 88import com.android.gallery3d.filtershow.editors.EditorStraighten; 89import com.android.gallery3d.filtershow.editors.EditorTinyPlanet; 90import com.android.gallery3d.filtershow.editors.ImageOnlyEditor; 91import com.android.gallery3d.filtershow.filters.FilterMirrorRepresentation; 92import com.android.gallery3d.filtershow.filters.FilterRepresentation; 93import com.android.gallery3d.filtershow.filters.FilterRotateRepresentation; 94import com.android.gallery3d.filtershow.filters.FilterUserPresetRepresentation; 95import com.android.gallery3d.filtershow.filters.FiltersManager; 96import com.android.gallery3d.filtershow.filters.ImageFilter; 97import com.android.gallery3d.filtershow.history.HistoryItem; 98import com.android.gallery3d.filtershow.history.HistoryManager; 99import com.android.gallery3d.filtershow.imageshow.ImageShow; 100import com.android.gallery3d.filtershow.imageshow.MasterImage; 101import com.android.gallery3d.filtershow.imageshow.Spline; 102import com.android.gallery3d.filtershow.info.InfoPanel; 103import com.android.gallery3d.filtershow.pipeline.CachingPipeline; 104import com.android.gallery3d.filtershow.pipeline.ImagePreset; 105import com.android.gallery3d.filtershow.pipeline.ProcessingService; 106import com.android.gallery3d.filtershow.presets.PresetManagementDialog; 107import com.android.gallery3d.filtershow.presets.UserPresetsAdapter; 108import com.android.gallery3d.filtershow.provider.SharedImageProvider; 109import com.android.gallery3d.filtershow.state.StateAdapter; 110import com.android.gallery3d.filtershow.tools.SaveImage; 111import com.android.gallery3d.filtershow.tools.XmpPresets; 112import com.android.gallery3d.filtershow.tools.XmpPresets.XMresults; 113import com.android.gallery3d.filtershow.ui.ExportDialog; 114import com.android.gallery3d.filtershow.ui.FramedTextButton; 115import com.android.gallery3d.util.GalleryUtils; 116import com.android.gallery3d.util.PrintJob; 117import com.android.gallery3d.util.UsageStatistics; 118import com.android.photos.data.GalleryBitmapPool; 119 120import java.io.File; 121import java.io.FileDescriptor; 122import java.io.FileOutputStream; 123import java.lang.ref.WeakReference; 124import java.util.ArrayList; 125import java.util.Vector; 126 127public class FilterShowActivity extends FragmentActivity implements OnItemClickListener, 128 OnShareTargetSelectedListener { 129 130 private String mAction = ""; 131 MasterImage mMasterImage = null; 132 133 private static final long LIMIT_SUPPORTS_HIGHRES = 134217728; // 128Mb 134 135 public static final String TINY_PLANET_ACTION = "com.android.camera.action.TINY_PLANET"; 136 public static final String LAUNCH_FULLSCREEN = "launch-fullscreen"; 137 private ImageShow mImageShow = null; 138 139 private View mSaveButton = null; 140 141 private EditorPlaceHolder mEditorPlaceHolder = new EditorPlaceHolder(this); 142 private Editor mCurrentEditor = null; 143 144 private static final int SELECT_PICTURE = 1; 145 private static final String LOGTAG = "FilterShowActivity"; 146 147 private boolean mShowingTinyPlanet = false; 148 private boolean mShowingImageStatePanel = false; 149 private boolean mShowingVersionsPanel = false; 150 private boolean mShowingInformationPanel = false; 151 152 private final Vector<ImageShow> mImageViews = new Vector<ImageShow>(); 153 154 private ShareActionProvider mShareActionProvider; 155 private File mSharedOutputFile = null; 156 157 private boolean mSharingImage = false; 158 159 private WeakReference<ProgressDialog> mSavingProgressDialog; 160 161 private LoadBitmapTask mLoadBitmapTask; 162 163 private Uri mOriginalImageUri = null; 164 private ImagePreset mOriginalPreset = null; 165 166 private Uri mSelectedImageUri = null; 167 168 private ArrayList<Action> mActions = new ArrayList<Action>(); 169 private UserPresetsManager mUserPresetsManager = null; 170 private UserPresetsAdapter mUserPresetsAdapter = null; 171 private CategoryAdapter mCategoryLooksAdapter = null; 172 private CategoryAdapter mCategoryBordersAdapter = null; 173 private CategoryAdapter mCategoryGeometryAdapter = null; 174 private CategoryAdapter mCategoryFiltersAdapter = null; 175 private CategoryAdapter mCategoryVersionsAdapter = null; 176 private int mCurrentPanel = MainPanel.LOOKS; 177 private Vector<FilterUserPresetRepresentation> mVersions = 178 new Vector<FilterUserPresetRepresentation>(); 179 private int mVersionsCounter = 0; 180 181 private boolean mHandlingSwipeButton = false; 182 private View mHandledSwipeView = null; 183 private float mHandledSwipeViewLastDelta = 0; 184 private float mSwipeStartX = 0; 185 private float mSwipeStartY = 0; 186 187 private ProcessingService mBoundService; 188 private boolean mIsBound = false; 189 190 public ProcessingService getProcessingService() { 191 return mBoundService; 192 } 193 194 public boolean isSimpleEditAction() { 195 return !PhotoPage.ACTION_NEXTGEN_EDIT.equalsIgnoreCase(mAction); 196 } 197 198 private ServiceConnection mConnection = new ServiceConnection() { 199 @Override 200 public void onServiceConnected(ComponentName className, IBinder service) { 201 /* 202 * This is called when the connection with the service has been 203 * established, giving us the service object we can use to 204 * interact with the service. Because we have bound to a explicit 205 * service that we know is running in our own process, we can 206 * cast its IBinder to a concrete class and directly access it. 207 */ 208 mBoundService = ((ProcessingService.LocalBinder)service).getService(); 209 mBoundService.setFiltershowActivity(FilterShowActivity.this); 210 mBoundService.onStart(); 211 } 212 213 @Override 214 public void onServiceDisconnected(ComponentName className) { 215 /* 216 * This is called when the connection with the service has been 217 * unexpectedly disconnected -- that is, its process crashed. 218 * Because it is running in our same process, we should never 219 * see this happen. 220 */ 221 mBoundService = null; 222 } 223 }; 224 225 void doBindService() { 226 /* 227 * Establish a connection with the service. We use an explicit 228 * class name because we want a specific service implementation that 229 * we know will be running in our own process (and thus won't be 230 * supporting component replacement by other applications). 231 */ 232 bindService(new Intent(FilterShowActivity.this, ProcessingService.class), 233 mConnection, Context.BIND_AUTO_CREATE); 234 mIsBound = true; 235 } 236 237 void doUnbindService() { 238 if (mIsBound) { 239 // Detach our existing connection. 240 unbindService(mConnection); 241 mIsBound = false; 242 } 243 } 244 245 private void setupPipeline() { 246 doBindService(); 247 ImageFilter.setActivityForMemoryToasts(this); 248 mUserPresetsManager = new UserPresetsManager(this); 249 mUserPresetsAdapter = new UserPresetsAdapter(this); 250 } 251 252 public void updateUIAfterServiceStarted() { 253 fillCategories(); 254 loadMainPanel(); 255 extractXMPData(); 256 processIntent(); 257 } 258 259 @Override 260 public void onCreate(Bundle savedInstanceState) { 261 super.onCreate(savedInstanceState); 262 263 boolean onlyUsePortrait = getResources().getBoolean(R.bool.only_use_portrait); 264 if (onlyUsePortrait) { 265 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); 266 } 267 MasterImage.setMaster(mMasterImage); 268 269 clearGalleryBitmapPool(); 270 setupPipeline(); 271 272 setupMasterImage(); 273 setDefaultValues(); 274 fillEditors(); 275 276 loadXML(); 277 UsageStatistics.onContentViewChanged(UsageStatistics.COMPONENT_EDITOR, "Main"); 278 UsageStatistics.onEvent(UsageStatistics.COMPONENT_EDITOR, 279 UsageStatistics.CATEGORY_LIFECYCLE, UsageStatistics.LIFECYCLE_START); 280 } 281 282 public boolean isShowingImageStatePanel() { 283 return mShowingImageStatePanel; 284 } 285 286 public void loadMainPanel() { 287 if (findViewById(R.id.main_panel_container) == null) { 288 return; 289 } 290 MainPanel panel = new MainPanel(); 291 FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); 292 transaction.replace(R.id.main_panel_container, panel, MainPanel.FRAGMENT_TAG); 293 transaction.commit(); 294 } 295 296 public void loadEditorPanel(FilterRepresentation representation, 297 final Editor currentEditor) { 298 if (representation.getEditorId() == ImageOnlyEditor.ID) { 299 currentEditor.reflectCurrentFilter(); 300 return; 301 } 302 final int currentId = currentEditor.getID(); 303 Runnable showEditor = new Runnable() { 304 @Override 305 public void run() { 306 EditorPanel panel = new EditorPanel(); 307 panel.setEditor(currentId); 308 FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); 309 transaction.remove(getSupportFragmentManager().findFragmentByTag(MainPanel.FRAGMENT_TAG)); 310 transaction.replace(R.id.main_panel_container, panel, MainPanel.FRAGMENT_TAG); 311 transaction.commit(); 312 } 313 }; 314 Fragment main = getSupportFragmentManager().findFragmentByTag(MainPanel.FRAGMENT_TAG); 315 boolean doAnimation = false; 316 if (mShowingImageStatePanel 317 && getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) { 318 doAnimation = true; 319 } 320 if (doAnimation && main != null && main instanceof MainPanel) { 321 MainPanel mainPanel = (MainPanel) main; 322 View container = mainPanel.getView().findViewById(R.id.category_panel_container); 323 View bottom = mainPanel.getView().findViewById(R.id.bottom_panel); 324 int panelHeight = container.getHeight() + bottom.getHeight(); 325 ViewPropertyAnimator anim = mainPanel.getView().animate(); 326 anim.translationY(panelHeight).start(); 327 final Handler handler = new Handler(); 328 handler.postDelayed(showEditor, anim.getDuration()); 329 } else { 330 showEditor.run(); 331 } 332 } 333 334 public void hideInformationPanel() { 335 FrameLayout infoLayout = (FrameLayout) findViewById(R.id.central_panel_container); 336 infoLayout.setVisibility(View.GONE); 337 Fragment fragment = getSupportFragmentManager().findFragmentByTag(InfoPanel.FRAGMENT_TAG); 338 if (fragment != null) { 339 FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); 340 transaction.remove(fragment); 341 transaction.commit(); 342 } 343 mShowingInformationPanel = false; 344 } 345 346 public void toggleInformationPanel() { 347 mShowingInformationPanel = !mShowingInformationPanel; 348 if (!mShowingInformationPanel) { 349 hideInformationPanel(); 350 showDefaultImageView(); 351 return; 352 } 353 FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); 354 transaction.setCustomAnimations(R.anim.slide_in_right, R.anim.slide_out_left); 355 FrameLayout infoLayout = (FrameLayout) findViewById(R.id.central_panel_container); 356 infoLayout.setVisibility(View.VISIBLE); 357 mEditorPlaceHolder.hide(); 358 mImageShow.setVisibility(View.GONE); 359 360 InfoPanel panel = new InfoPanel(); 361 transaction.replace(R.id.central_panel_container, panel, InfoPanel.FRAGMENT_TAG); 362 transaction.commit(); 363 } 364 365 private void loadXML() { 366 setContentView(R.layout.filtershow_activity); 367 368 ActionBar actionBar = getActionBar(); 369 actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM); 370 actionBar.setCustomView(R.layout.filtershow_actionbar); 371 actionBar.setBackgroundDrawable(new ColorDrawable( 372 getResources().getColor(R.color.background_screen))); 373 374 mSaveButton = actionBar.getCustomView(); 375 mSaveButton.setOnClickListener(new OnClickListener() { 376 @Override 377 public void onClick(View view) { 378 saveImage(); 379 } 380 }); 381 382 mImageShow = (ImageShow) findViewById(R.id.imageShow); 383 mImageViews.add(mImageShow); 384 385 setupEditors(); 386 387 mEditorPlaceHolder.hide(); 388 mImageShow.attach(); 389 390 setupStatePanel(); 391 } 392 393 public void fillCategories() { 394 fillLooks(); 395 loadUserPresets(); 396 fillBorders(); 397 fillTools(); 398 fillEffects(); 399 fillVersions(); 400 } 401 402 public void setupStatePanel() { 403 MasterImage.getImage().setHistoryManager(mMasterImage.getHistory()); 404 } 405 406 private void fillVersions() { 407 if (mCategoryVersionsAdapter != null) { 408 mCategoryVersionsAdapter.clear(); 409 } 410 mCategoryVersionsAdapter = new CategoryAdapter(this); 411 mCategoryVersionsAdapter.setShowAddButton(true); 412 } 413 414 public void registerAction(Action action) { 415 if (mActions.contains(action)) { 416 return; 417 } 418 mActions.add(action); 419 } 420 421 private void loadActions() { 422 for (int i = 0; i < mActions.size(); i++) { 423 Action action = mActions.get(i); 424 action.setImageFrame(new Rect(0, 0, 96, 96), 0); 425 } 426 } 427 428 public void updateVersions() { 429 mCategoryVersionsAdapter.clear(); 430 FilterUserPresetRepresentation originalRep = new FilterUserPresetRepresentation( 431 getString(R.string.filtershow_version_original), new ImagePreset(), -1); 432 mCategoryVersionsAdapter.add( 433 new Action(this, originalRep, Action.FULL_VIEW)); 434 ImagePreset current = new ImagePreset(MasterImage.getImage().getPreset()); 435 FilterUserPresetRepresentation currentRep = new FilterUserPresetRepresentation( 436 getString(R.string.filtershow_version_current), current, -1); 437 mCategoryVersionsAdapter.add( 438 new Action(this, currentRep, Action.FULL_VIEW)); 439 if (mVersions.size() > 0) { 440 mCategoryVersionsAdapter.add(new Action(this, Action.SPACER)); 441 } 442 for (FilterUserPresetRepresentation rep : mVersions) { 443 mCategoryVersionsAdapter.add( 444 new Action(this, rep, Action.FULL_VIEW, true)); 445 } 446 mCategoryVersionsAdapter.notifyDataSetInvalidated(); 447 } 448 449 public void addCurrentVersion() { 450 ImagePreset current = new ImagePreset(MasterImage.getImage().getPreset()); 451 mVersionsCounter++; 452 FilterUserPresetRepresentation rep = new FilterUserPresetRepresentation( 453 "" + mVersionsCounter, current, -1); 454 mVersions.add(rep); 455 updateVersions(); 456 } 457 458 public void removeVersion(Action action) { 459 mVersions.remove(action.getRepresentation()); 460 updateVersions(); 461 } 462 463 public void removeLook(Action action) { 464 FilterUserPresetRepresentation rep = 465 (FilterUserPresetRepresentation) action.getRepresentation(); 466 if (rep == null) { 467 return; 468 } 469 mUserPresetsManager.delete(rep.getId()); 470 updateUserPresetsFromManager(); 471 } 472 473 private void fillEffects() { 474 FiltersManager filtersManager = FiltersManager.getManager(); 475 ArrayList<FilterRepresentation> filtersRepresentations = filtersManager.getEffects(); 476 if (mCategoryFiltersAdapter != null) { 477 mCategoryFiltersAdapter.clear(); 478 } 479 mCategoryFiltersAdapter = new CategoryAdapter(this); 480 for (FilterRepresentation representation : filtersRepresentations) { 481 if (representation.getTextId() != 0) { 482 representation.setName(getString(representation.getTextId())); 483 } 484 mCategoryFiltersAdapter.add(new Action(this, representation)); 485 } 486 } 487 488 private void fillTools() { 489 FiltersManager filtersManager = FiltersManager.getManager(); 490 ArrayList<FilterRepresentation> filtersRepresentations = filtersManager.getTools(); 491 if (mCategoryGeometryAdapter != null) { 492 mCategoryGeometryAdapter.clear(); 493 } 494 mCategoryGeometryAdapter = new CategoryAdapter(this); 495 for (FilterRepresentation representation : filtersRepresentations) { 496 mCategoryGeometryAdapter.add(new Action(this, representation)); 497 } 498 } 499 500 private void processIntent() { 501 Intent intent = getIntent(); 502 if (intent.getBooleanExtra(LAUNCH_FULLSCREEN, false)) { 503 getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); 504 } 505 506 mAction = intent.getAction(); 507 mSelectedImageUri = intent.getData(); 508 Uri loadUri = mSelectedImageUri; 509 if (mOriginalImageUri != null) { 510 loadUri = mOriginalImageUri; 511 } 512 if (loadUri != null) { 513 startLoadBitmap(loadUri); 514 } else { 515 pickImage(); 516 } 517 } 518 519 private void setupEditors() { 520 mEditorPlaceHolder.setContainer((FrameLayout) findViewById(R.id.editorContainer)); 521 EditorManager.addEditors(mEditorPlaceHolder); 522 mEditorPlaceHolder.setOldViews(mImageViews); 523 } 524 525 private void fillEditors() { 526 mEditorPlaceHolder.addEditor(new EditorChanSat()); 527 mEditorPlaceHolder.addEditor(new EditorGrad()); 528 mEditorPlaceHolder.addEditor(new EditorDraw()); 529 mEditorPlaceHolder.addEditor(new EditorColorBorder()); 530 mEditorPlaceHolder.addEditor(new BasicEditor()); 531 mEditorPlaceHolder.addEditor(new ImageOnlyEditor()); 532 mEditorPlaceHolder.addEditor(new EditorTinyPlanet()); 533 mEditorPlaceHolder.addEditor(new EditorRedEye()); 534 mEditorPlaceHolder.addEditor(new EditorCrop()); 535 mEditorPlaceHolder.addEditor(new EditorMirror()); 536 mEditorPlaceHolder.addEditor(new EditorRotate()); 537 mEditorPlaceHolder.addEditor(new EditorStraighten()); 538 } 539 540 private void setDefaultValues() { 541 Resources res = getResources(); 542 543 // TODO: get those values from XML. 544 FramedTextButton.setTextSize((int) getPixelsFromDip(14)); 545 FramedTextButton.setTrianglePadding((int) getPixelsFromDip(4)); 546 FramedTextButton.setTriangleSize((int) getPixelsFromDip(10)); 547 548 Drawable curveHandle = res.getDrawable(R.drawable.camera_crop); 549 int curveHandleSize = (int) res.getDimension(R.dimen.crop_indicator_size); 550 Spline.setCurveHandle(curveHandle, curveHandleSize); 551 Spline.setCurveWidth((int) getPixelsFromDip(3)); 552 } 553 554 private void startLoadBitmap(Uri uri) { 555 final View loading = findViewById(R.id.loading); 556 final View imageShow = findViewById(R.id.imageShow); 557 imageShow.setVisibility(View.INVISIBLE); 558 loading.setVisibility(View.VISIBLE); 559 mShowingTinyPlanet = false; 560 mLoadBitmapTask = new LoadBitmapTask(); 561 mLoadBitmapTask.execute(uri); 562 } 563 564 private void fillBorders() { 565 FiltersManager filtersManager = FiltersManager.getManager(); 566 ArrayList<FilterRepresentation> borders = filtersManager.getBorders(); 567 568 for (int i = 0; i < borders.size(); i++) { 569 FilterRepresentation filter = borders.get(i); 570 filter.setName(getString(R.string.borders)); 571 if (i == 0) { 572 filter.setName(getString(R.string.none)); 573 } 574 } 575 576 if (mCategoryBordersAdapter != null) { 577 mCategoryBordersAdapter.clear(); 578 } 579 mCategoryBordersAdapter = new CategoryAdapter(this); 580 for (FilterRepresentation representation : borders) { 581 if (representation.getTextId() != 0) { 582 representation.setName(getString(representation.getTextId())); 583 } 584 mCategoryBordersAdapter.add(new Action(this, representation, Action.FULL_VIEW)); 585 } 586 } 587 588 public UserPresetsAdapter getUserPresetsAdapter() { 589 return mUserPresetsAdapter; 590 } 591 592 public CategoryAdapter getCategoryLooksAdapter() { 593 return mCategoryLooksAdapter; 594 } 595 596 public CategoryAdapter getCategoryBordersAdapter() { 597 return mCategoryBordersAdapter; 598 } 599 600 public CategoryAdapter getCategoryGeometryAdapter() { 601 return mCategoryGeometryAdapter; 602 } 603 604 public CategoryAdapter getCategoryFiltersAdapter() { 605 return mCategoryFiltersAdapter; 606 } 607 608 public CategoryAdapter getCategoryVersionsAdapter() { 609 return mCategoryVersionsAdapter; 610 } 611 612 public void removeFilterRepresentation(FilterRepresentation filterRepresentation) { 613 if (filterRepresentation == null) { 614 return; 615 } 616 ImagePreset oldPreset = MasterImage.getImage().getPreset(); 617 ImagePreset copy = new ImagePreset(oldPreset); 618 copy.removeFilter(filterRepresentation); 619 MasterImage.getImage().setPreset(copy, copy.getLastRepresentation(), true); 620 if (MasterImage.getImage().getCurrentFilterRepresentation() == filterRepresentation) { 621 FilterRepresentation lastRepresentation = copy.getLastRepresentation(); 622 MasterImage.getImage().setCurrentFilterRepresentation(lastRepresentation); 623 } 624 } 625 626 public void useFilterRepresentation(FilterRepresentation filterRepresentation) { 627 if (filterRepresentation == null) { 628 return; 629 } 630 if (!(filterRepresentation instanceof FilterRotateRepresentation) 631 && !(filterRepresentation instanceof FilterMirrorRepresentation) 632 && MasterImage.getImage().getCurrentFilterRepresentation() == filterRepresentation) { 633 return; 634 } 635 if (filterRepresentation instanceof FilterUserPresetRepresentation 636 || filterRepresentation instanceof FilterRotateRepresentation 637 || filterRepresentation instanceof FilterMirrorRepresentation) { 638 MasterImage.getImage().onNewLook(filterRepresentation); 639 } 640 ImagePreset oldPreset = MasterImage.getImage().getPreset(); 641 ImagePreset copy = new ImagePreset(oldPreset); 642 FilterRepresentation representation = copy.getRepresentation(filterRepresentation); 643 if (representation == null) { 644 filterRepresentation = filterRepresentation.copy(); 645 copy.addFilter(filterRepresentation); 646 } else { 647 if (filterRepresentation.allowsSingleInstanceOnly()) { 648 // Don't just update the filter representation. Centralize the 649 // logic in the addFilter(), such that we can keep "None" as 650 // null. 651 if (!representation.equals(filterRepresentation)) { 652 // Only do this if the filter isn't the same 653 // (state panel clicks can lead us here) 654 copy.removeFilter(representation); 655 copy.addFilter(filterRepresentation); 656 } 657 } 658 } 659 MasterImage.getImage().setPreset(copy, filterRepresentation, true); 660 MasterImage.getImage().setCurrentFilterRepresentation(filterRepresentation); 661 } 662 663 public void showRepresentation(FilterRepresentation representation) { 664 if (representation == null) { 665 return; 666 } 667 668 if (representation instanceof FilterRotateRepresentation) { 669 FilterRotateRepresentation r = (FilterRotateRepresentation) representation; 670 r.rotateCW(); 671 } 672 if (representation instanceof FilterMirrorRepresentation) { 673 FilterMirrorRepresentation r = (FilterMirrorRepresentation) representation; 674 r.cycle(); 675 } 676 useFilterRepresentation(representation); 677 678 // show representation 679 if (mCurrentEditor != null) { 680 mCurrentEditor.detach(); 681 } 682 mCurrentEditor = mEditorPlaceHolder.showEditor(representation.getEditorId()); 683 loadEditorPanel(representation, mCurrentEditor); 684 hideInformationPanel(); 685 } 686 687 public Editor getEditor(int editorID) { 688 return mEditorPlaceHolder.getEditor(editorID); 689 } 690 691 public void setCurrentPanel(int currentPanel) { 692 mCurrentPanel = currentPanel; 693 } 694 695 public int getCurrentPanel() { 696 return mCurrentPanel; 697 } 698 699 public void updateCategories() { 700 ImagePreset preset = mMasterImage.getPreset(); 701 mCategoryLooksAdapter.reflectImagePreset(preset); 702 mCategoryBordersAdapter.reflectImagePreset(preset); 703 } 704 705 public View getMainStatePanelContainer(int id) { 706 return findViewById(id); 707 } 708 709 private class LoadHighresBitmapTask extends AsyncTask<Void, Void, Boolean> { 710 @Override 711 protected Boolean doInBackground(Void... params) { 712 MasterImage master = MasterImage.getImage(); 713 Rect originalBounds = master.getOriginalBounds(); 714 if (master.supportsHighRes()) { 715 int highresPreviewSize = master.getOriginalBitmapLarge().getWidth() * 2; 716 if (highresPreviewSize > originalBounds.width()) { 717 highresPreviewSize = originalBounds.width(); 718 } 719 Rect bounds = new Rect(); 720 Bitmap originalHires = ImageLoader.loadOrientedConstrainedBitmap(master.getUri(), 721 master.getActivity(), highresPreviewSize, 722 master.getOrientation(), bounds); 723 master.setOriginalBounds(bounds); 724 master.setOriginalBitmapHighres(originalHires); 725 mBoundService.setOriginalBitmapHighres(originalHires); 726 master.warnListeners(); 727 } 728 return true; 729 } 730 731 @Override 732 protected void onPostExecute(Boolean result) { 733 Bitmap highresBitmap = MasterImage.getImage().getOriginalBitmapHighres(); 734 if (highresBitmap != null) { 735 float highResPreviewScale = (float) highresBitmap.getWidth() 736 / (float) MasterImage.getImage().getOriginalBounds().width(); 737 mBoundService.setHighresPreviewScaleFactor(highResPreviewScale); 738 } 739 MasterImage.getImage().warnListeners(); 740 } 741 } 742 743 public void stopLoadingIndicator() { 744 final View loading = findViewById(R.id.loading); 745 loading.setVisibility(View.GONE); 746 } 747 748 private class LoadBitmapTask extends AsyncTask<Uri, Boolean, Boolean> { 749 int mBitmapSize; 750 751 public LoadBitmapTask() { 752 mBitmapSize = getScreenImageSize(); 753 } 754 755 @Override 756 protected Boolean doInBackground(Uri... params) { 757 if (!MasterImage.getImage().loadBitmap(params[0], mBitmapSize)) { 758 return false; 759 } 760 publishProgress(ImageLoader.queryLightCycle360(MasterImage.getImage().getActivity())); 761 return true; 762 } 763 764 @Override 765 protected void onProgressUpdate(Boolean... values) { 766 super.onProgressUpdate(values); 767 if (isCancelled()) { 768 return; 769 } 770 if (values[0]) { 771 mShowingTinyPlanet = true; 772 } 773 } 774 775 @Override 776 protected void onPostExecute(Boolean result) { 777 MasterImage.setMaster(mMasterImage); 778 if (isCancelled()) { 779 return; 780 } 781 782 if (!result) { 783 if (!mOriginalImageUri.equals(mSelectedImageUri)) { 784 mOriginalImageUri = mSelectedImageUri; 785 mOriginalPreset = null; 786 Toast.makeText(FilterShowActivity.this, 787 R.string.cannot_edit_original, Toast.LENGTH_SHORT).show(); 788 startLoadBitmap(mOriginalImageUri); 789 } else { 790 cannotLoadImage(); 791 } 792 return; 793 } 794 795 if (null == CachingPipeline.getRenderScriptContext()){ 796 Log.v(LOGTAG,"RenderScript context destroyed during load"); 797 return; 798 } 799 final View imageShow = findViewById(R.id.imageShow); 800 imageShow.setVisibility(View.VISIBLE); 801 802 803 Bitmap largeBitmap = MasterImage.getImage().getOriginalBitmapLarge(); 804 mBoundService.setOriginalBitmap(largeBitmap); 805 806 float previewScale = (float) largeBitmap.getWidth() 807 / (float) MasterImage.getImage().getOriginalBounds().width(); 808 mBoundService.setPreviewScaleFactor(previewScale); 809 if (!mShowingTinyPlanet) { 810 mCategoryFiltersAdapter.removeTinyPlanet(); 811 } 812 mCategoryLooksAdapter.imageLoaded(); 813 mCategoryBordersAdapter.imageLoaded(); 814 mCategoryGeometryAdapter.imageLoaded(); 815 mCategoryFiltersAdapter.imageLoaded(); 816 mLoadBitmapTask = null; 817 818 MasterImage.getImage().warnListeners(); 819 loadActions(); 820 821 if (mOriginalPreset != null) { 822 MasterImage.getImage().setLoadedPreset(mOriginalPreset); 823 MasterImage.getImage().setPreset(mOriginalPreset, 824 mOriginalPreset.getLastRepresentation(), true); 825 mOriginalPreset = null; 826 } else { 827 setDefaultPreset(); 828 } 829 830 MasterImage.getImage().resetGeometryImages(true); 831 832 if (mAction == TINY_PLANET_ACTION) { 833 showRepresentation(mCategoryFiltersAdapter.getTinyPlanet()); 834 } 835 LoadHighresBitmapTask highresLoad = new LoadHighresBitmapTask(); 836 highresLoad.execute(); 837 MasterImage.getImage().warnListeners(); 838 super.onPostExecute(result); 839 } 840 841 } 842 843 private void clearGalleryBitmapPool() { 844 (new AsyncTask<Void, Void, Void>() { 845 @Override 846 protected Void doInBackground(Void... params) { 847 // Free memory held in Gallery's Bitmap pool. May be O(n) for n bitmaps. 848 GalleryBitmapPool.getInstance().clear(); 849 return null; 850 } 851 }).execute(); 852 } 853 854 @Override 855 protected void onDestroy() { 856 if (mLoadBitmapTask != null) { 857 mLoadBitmapTask.cancel(false); 858 } 859 mUserPresetsManager.close(); 860 doUnbindService(); 861 super.onDestroy(); 862 } 863 864 // TODO: find a more robust way of handling image size selection 865 // for high screen densities. 866 private int getScreenImageSize() { 867 DisplayMetrics outMetrics = new DisplayMetrics(); 868 getWindowManager().getDefaultDisplay().getMetrics(outMetrics); 869 return Math.max(outMetrics.heightPixels, outMetrics.widthPixels); 870 } 871 872 private void showSavingProgress(String albumName) { 873 ProgressDialog progress; 874 if (mSavingProgressDialog != null) { 875 progress = mSavingProgressDialog.get(); 876 if (progress != null) { 877 progress.show(); 878 return; 879 } 880 } 881 // TODO: Allow cancellation of the saving process 882 String progressText; 883 if (albumName == null) { 884 progressText = getString(R.string.saving_image); 885 } else { 886 progressText = getString(R.string.filtershow_saving_image, albumName); 887 } 888 progress = ProgressDialog.show(this, "", progressText, true, false); 889 mSavingProgressDialog = new WeakReference<ProgressDialog>(progress); 890 } 891 892 private void hideSavingProgress() { 893 if (mSavingProgressDialog != null) { 894 ProgressDialog progress = mSavingProgressDialog.get(); 895 if (progress != null) 896 progress.dismiss(); 897 } 898 } 899 900 public void completeSaveImage(Uri saveUri) { 901 if (mSharingImage && mSharedOutputFile != null) { 902 // Image saved, we unblock the content provider 903 Uri uri = Uri.withAppendedPath(SharedImageProvider.CONTENT_URI, 904 Uri.encode(mSharedOutputFile.getAbsolutePath())); 905 ContentValues values = new ContentValues(); 906 values.put(SharedImageProvider.PREPARE, false); 907 getContentResolver().insert(uri, values); 908 } 909 setResult(RESULT_OK, new Intent().setData(saveUri)); 910 hideSavingProgress(); 911 finish(); 912 } 913 914 @Override 915 public boolean onShareTargetSelected(ShareActionProvider arg0, Intent arg1) { 916 // First, let's tell the SharedImageProvider that it will need to wait 917 // for the image 918 Uri uri = Uri.withAppendedPath(SharedImageProvider.CONTENT_URI, 919 Uri.encode(mSharedOutputFile.getAbsolutePath())); 920 ContentValues values = new ContentValues(); 921 values.put(SharedImageProvider.PREPARE, true); 922 getContentResolver().insert(uri, values); 923 mSharingImage = true; 924 925 // Process and save the image in the background. 926 showSavingProgress(null); 927 mImageShow.saveImage(this, mSharedOutputFile); 928 return true; 929 } 930 931 private Intent getDefaultShareIntent() { 932 Intent intent = new Intent(Intent.ACTION_SEND); 933 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); 934 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); 935 intent.setType(SharedImageProvider.MIME_TYPE); 936 mSharedOutputFile = SaveImage.getNewFile(this, MasterImage.getImage().getUri()); 937 Uri uri = Uri.withAppendedPath(SharedImageProvider.CONTENT_URI, 938 Uri.encode(mSharedOutputFile.getAbsolutePath())); 939 intent.putExtra(Intent.EXTRA_STREAM, uri); 940 return intent; 941 } 942 943 @Override 944 public boolean onCreateOptionsMenu(Menu menu) { 945 getMenuInflater().inflate(R.menu.filtershow_activity_menu, menu); 946 MenuItem showState = menu.findItem(R.id.showImageStateButton); 947 if (mShowingImageStatePanel) { 948 showState.setTitle(R.string.hide_imagestate_panel); 949 } else { 950 showState.setTitle(R.string.show_imagestate_panel); 951 } 952 mShareActionProvider = (ShareActionProvider) menu.findItem(R.id.menu_share) 953 .getActionProvider(); 954 mShareActionProvider.setShareIntent(getDefaultShareIntent()); 955 mShareActionProvider.setOnShareTargetSelectedListener(this); 956 957 MenuItem undoItem = menu.findItem(R.id.undoButton); 958 MenuItem redoItem = menu.findItem(R.id.redoButton); 959 MenuItem resetItem = menu.findItem(R.id.resetHistoryButton); 960 mMasterImage.getHistory().setMenuItems(undoItem, redoItem, resetItem); 961 return true; 962 } 963 964 @Override 965 public void onPause() { 966 super.onPause(); 967 if (mShareActionProvider != null) { 968 mShareActionProvider.setOnShareTargetSelectedListener(null); 969 } 970 } 971 972 @Override 973 public void onResume() { 974 super.onResume(); 975 if (mShareActionProvider != null) { 976 mShareActionProvider.setOnShareTargetSelectedListener(this); 977 } 978 } 979 980 @Override 981 public boolean onOptionsItemSelected(MenuItem item) { 982 switch (item.getItemId()) { 983 case R.id.undoButton: { 984 HistoryManager adapter = mMasterImage.getHistory(); 985 int position = adapter.undo(); 986 mMasterImage.onHistoryItemClick(position); 987 backToMain(); 988 invalidateViews(); 989 UsageStatistics.onEvent(UsageStatistics.COMPONENT_EDITOR, 990 UsageStatistics.CATEGORY_BUTTON_PRESS, "Undo"); 991 return true; 992 } 993 case R.id.redoButton: { 994 HistoryManager adapter = mMasterImage.getHistory(); 995 int position = adapter.redo(); 996 mMasterImage.onHistoryItemClick(position); 997 invalidateViews(); 998 UsageStatistics.onEvent(UsageStatistics.COMPONENT_EDITOR, 999 UsageStatistics.CATEGORY_BUTTON_PRESS, "Redo"); 1000 return true; 1001 } 1002 case R.id.resetHistoryButton: { 1003 resetHistory(); 1004 UsageStatistics.onEvent(UsageStatistics.COMPONENT_EDITOR, 1005 UsageStatistics.CATEGORY_BUTTON_PRESS, "ResetHistory"); 1006 return true; 1007 } 1008 case R.id.showImageStateButton: { 1009 toggleImageStatePanel(); 1010 UsageStatistics.onEvent(UsageStatistics.COMPONENT_EDITOR, 1011 UsageStatistics.CATEGORY_BUTTON_PRESS, 1012 mShowingImageStatePanel ? "ShowPanel" : "HidePanel"); 1013 return true; 1014 } 1015 case R.id.exportFlattenButton: { 1016 showExportOptionsDialog(); 1017 return true; 1018 } 1019 case android.R.id.home: { 1020 saveImage(); 1021 return true; 1022 } 1023 case R.id.manageUserPresets: { 1024 manageUserPresets(); 1025 return true; 1026 } 1027 case R.id.showInfoPanel: { 1028 toggleInformationPanel(); 1029 return true; 1030 } 1031 case R.id.printButton: { 1032 print(); 1033 return true; 1034 } 1035 } 1036 return false; 1037 } 1038 1039 public void print() { 1040 Bitmap bitmap = MasterImage.getImage().getHighresImage(); 1041 PrintJob.printBitmap(this, "ImagePrint", bitmap); 1042 } 1043 1044 public void addNewPreset() { 1045 DialogFragment dialog = new PresetManagementDialog(); 1046 dialog.show(getSupportFragmentManager(), "NoticeDialogFragment"); 1047 } 1048 1049 private void manageUserPresets() { 1050 DialogFragment dialog = new PresetManagementDialog(); 1051 dialog.show(getSupportFragmentManager(), "NoticeDialogFragment"); 1052 } 1053 1054 private void showExportOptionsDialog() { 1055 DialogFragment dialog = new ExportDialog(); 1056 dialog.show(getSupportFragmentManager(), "ExportDialogFragment"); 1057 } 1058 1059 public void updateUserPresetsFromAdapter(UserPresetsAdapter adapter) { 1060 ArrayList<FilterUserPresetRepresentation> representations = 1061 adapter.getDeletedRepresentations(); 1062 for (FilterUserPresetRepresentation representation : representations) { 1063 deletePreset(representation.getId()); 1064 } 1065 ArrayList<FilterUserPresetRepresentation> changedRepresentations = 1066 adapter.getChangedRepresentations(); 1067 for (FilterUserPresetRepresentation representation : changedRepresentations) { 1068 updatePreset(representation); 1069 } 1070 adapter.clearDeletedRepresentations(); 1071 adapter.clearChangedRepresentations(); 1072 loadUserPresets(); 1073 } 1074 1075 public void loadUserPresets() { 1076 mUserPresetsManager.load(); 1077 updateUserPresetsFromManager(); 1078 } 1079 1080 public void updateUserPresetsFromManager() { 1081 ArrayList<FilterUserPresetRepresentation> presets = mUserPresetsManager.getRepresentations(); 1082 if (presets == null) { 1083 return; 1084 } 1085 if (mCategoryLooksAdapter != null) { 1086 fillLooks(); 1087 } 1088 if (presets.size() > 0) { 1089 mCategoryLooksAdapter.add(new Action(this, Action.SPACER)); 1090 } 1091 mUserPresetsAdapter.clear(); 1092 for (int i = 0; i < presets.size(); i++) { 1093 FilterUserPresetRepresentation representation = presets.get(i); 1094 mCategoryLooksAdapter.add( 1095 new Action(this, representation, Action.FULL_VIEW, true)); 1096 mUserPresetsAdapter.add(new Action(this, representation, Action.FULL_VIEW)); 1097 } 1098 if (presets.size() > 0) { 1099 mCategoryLooksAdapter.add(new Action(this, Action.ADD_ACTION)); 1100 } 1101 mCategoryLooksAdapter.notifyDataSetChanged(); 1102 mCategoryLooksAdapter.notifyDataSetInvalidated(); 1103 } 1104 1105 public void saveCurrentImagePreset(String name) { 1106 mUserPresetsManager.save(MasterImage.getImage().getPreset(), name); 1107 } 1108 1109 private void deletePreset(int id) { 1110 mUserPresetsManager.delete(id); 1111 } 1112 1113 private void updatePreset(FilterUserPresetRepresentation representation) { 1114 mUserPresetsManager.update(representation); 1115 } 1116 1117 public void enableSave(boolean enable) { 1118 if (mSaveButton != null) { 1119 mSaveButton.setEnabled(enable); 1120 } 1121 } 1122 1123 private void fillLooks() { 1124 FiltersManager filtersManager = FiltersManager.getManager(); 1125 ArrayList<FilterRepresentation> filtersRepresentations = filtersManager.getLooks(); 1126 1127 if (mCategoryLooksAdapter != null) { 1128 mCategoryLooksAdapter.clear(); 1129 } 1130 mCategoryLooksAdapter = new CategoryAdapter(this); 1131 int verticalItemHeight = (int) getResources().getDimension(R.dimen.action_item_height); 1132 mCategoryLooksAdapter.setItemHeight(verticalItemHeight); 1133 for (FilterRepresentation representation : filtersRepresentations) { 1134 mCategoryLooksAdapter.add(new Action(this, representation, Action.FULL_VIEW)); 1135 } 1136 if (mUserPresetsManager.getRepresentations() == null 1137 || mUserPresetsManager.getRepresentations().size() == 0) { 1138 mCategoryLooksAdapter.add(new Action(this, Action.ADD_ACTION)); 1139 } 1140 1141 Fragment panel = getSupportFragmentManager().findFragmentByTag(MainPanel.FRAGMENT_TAG); 1142 if (panel != null) { 1143 if (panel instanceof MainPanel) { 1144 MainPanel mainPanel = (MainPanel) panel; 1145 mainPanel.loadCategoryLookPanel(true); 1146 } 1147 } 1148 } 1149 1150 public void setDefaultPreset() { 1151 // Default preset (original) 1152 ImagePreset preset = new ImagePreset(); // empty 1153 mMasterImage.setPreset(preset, preset.getLastRepresentation(), true); 1154 } 1155 1156 // ////////////////////////////////////////////////////////////////////////////// 1157 // Some utility functions 1158 // TODO: finish the cleanup. 1159 1160 public void invalidateViews() { 1161 for (ImageShow views : mImageViews) { 1162 views.updateImage(); 1163 } 1164 } 1165 1166 public void hideImageViews() { 1167 for (View view : mImageViews) { 1168 view.setVisibility(View.GONE); 1169 } 1170 mEditorPlaceHolder.hide(); 1171 } 1172 1173 // ////////////////////////////////////////////////////////////////////////////// 1174 // imageState panel... 1175 1176 public void toggleImageStatePanel() { 1177 invalidateOptionsMenu(); 1178 mShowingImageStatePanel = !mShowingImageStatePanel; 1179 Fragment panel = getSupportFragmentManager().findFragmentByTag(MainPanel.FRAGMENT_TAG); 1180 if (panel != null) { 1181 if (panel instanceof EditorPanel) { 1182 EditorPanel editorPanel = (EditorPanel) panel; 1183 editorPanel.showImageStatePanel(mShowingImageStatePanel); 1184 } else if (panel instanceof MainPanel) { 1185 MainPanel mainPanel = (MainPanel) panel; 1186 mainPanel.showImageStatePanel(mShowingImageStatePanel); 1187 } 1188 } 1189 } 1190 1191 public void toggleVersionsPanel() { 1192 mShowingVersionsPanel = !mShowingVersionsPanel; 1193 Fragment panel = getSupportFragmentManager().findFragmentByTag(MainPanel.FRAGMENT_TAG); 1194 if (panel != null && panel instanceof MainPanel) { 1195 MainPanel mainPanel = (MainPanel) panel; 1196 mainPanel.loadCategoryVersionsPanel(); 1197 } 1198 } 1199 1200 @Override 1201 public void onConfigurationChanged(Configuration newConfig) 1202 { 1203 super.onConfigurationChanged(newConfig); 1204 setDefaultValues(); 1205 loadXML(); 1206 fillCategories(); 1207 loadMainPanel(); 1208 1209 mShowingInformationPanel = false; 1210 1211 // mLoadBitmapTask==null implies you have looked at the intent 1212 if (!mShowingTinyPlanet && (mLoadBitmapTask == null)) { 1213 mCategoryFiltersAdapter.removeTinyPlanet(); 1214 } 1215 stopLoadingIndicator(); 1216 } 1217 1218 public void setupMasterImage() { 1219 1220 HistoryManager historyManager = new HistoryManager(); 1221 StateAdapter imageStateAdapter = new StateAdapter(this, 0); 1222 MasterImage.reset(); 1223 mMasterImage = MasterImage.getImage(); 1224 mMasterImage.setHistoryManager(historyManager); 1225 mMasterImage.setStateAdapter(imageStateAdapter); 1226 mMasterImage.setActivity(this); 1227 mMasterImage.setFirstLoad(true); 1228 1229 if (Runtime.getRuntime().maxMemory() > LIMIT_SUPPORTS_HIGHRES) { 1230 mMasterImage.setSupportsHighRes(true); 1231 } else { 1232 mMasterImage.setSupportsHighRes(false); 1233 } 1234 } 1235 1236 void resetHistory() { 1237 HistoryManager adapter = mMasterImage.getHistory(); 1238 adapter.reset(); 1239 HistoryItem historyItem = adapter.getItem(0); 1240 ImagePreset original = new ImagePreset(historyItem.getImagePreset()); 1241 mMasterImage.setPreset(original, historyItem.getFilterRepresentation(), true); 1242 invalidateViews(); 1243 backToMain(); 1244 } 1245 1246 public void showDefaultImageView() { 1247 hideInformationPanel(); 1248 mEditorPlaceHolder.hide(); 1249 mImageShow.setVisibility(View.VISIBLE); 1250 MasterImage.getImage().setCurrentFilter(null); 1251 MasterImage.getImage().setCurrentFilterRepresentation(null); 1252 } 1253 1254 public void backToMain() { 1255 Fragment currentPanel = getSupportFragmentManager().findFragmentByTag(MainPanel.FRAGMENT_TAG); 1256 if (currentPanel instanceof MainPanel) { 1257 return; 1258 } 1259 loadMainPanel(); 1260 showDefaultImageView(); 1261 } 1262 1263 @Override 1264 public void onBackPressed() { 1265 Fragment currentPanel = getSupportFragmentManager().findFragmentByTag(MainPanel.FRAGMENT_TAG); 1266 if (currentPanel instanceof MainPanel) { 1267 if (!mImageShow.hasModifications()) { 1268 done(); 1269 } else { 1270 AlertDialog.Builder builder = new AlertDialog.Builder(this); 1271 builder.setMessage(R.string.unsaved).setTitle(R.string.save_before_exit); 1272 builder.setPositiveButton(R.string.save_and_exit, new DialogInterface.OnClickListener() { 1273 @Override 1274 public void onClick(DialogInterface dialog, int id) { 1275 saveImage(); 1276 } 1277 }); 1278 builder.setNegativeButton(R.string.exit, new DialogInterface.OnClickListener() { 1279 @Override 1280 public void onClick(DialogInterface dialog, int id) { 1281 done(); 1282 } 1283 }); 1284 builder.show(); 1285 } 1286 } else { 1287 backToMain(); 1288 } 1289 } 1290 1291 public void cannotLoadImage() { 1292 Toast.makeText(this, R.string.cannot_load_image, Toast.LENGTH_SHORT).show(); 1293 finish(); 1294 } 1295 1296 // ////////////////////////////////////////////////////////////////////////////// 1297 1298 public float getPixelsFromDip(float value) { 1299 Resources r = getResources(); 1300 return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, value, 1301 r.getDisplayMetrics()); 1302 } 1303 1304 @Override 1305 public void onItemClick(AdapterView<?> parent, View view, int position, 1306 long id) { 1307 mMasterImage.onHistoryItemClick(position); 1308 invalidateViews(); 1309 } 1310 1311 public void pickImage() { 1312 Intent intent = new Intent(); 1313 intent.setType("image/*"); 1314 intent.setAction(Intent.ACTION_GET_CONTENT); 1315 startActivityForResult(Intent.createChooser(intent, getString(R.string.select_image)), 1316 SELECT_PICTURE); 1317 } 1318 1319 @Override 1320 public void onActivityResult(int requestCode, int resultCode, Intent data) { 1321 if (resultCode == RESULT_OK) { 1322 if (requestCode == SELECT_PICTURE) { 1323 Uri selectedImageUri = data.getData(); 1324 startLoadBitmap(selectedImageUri); 1325 } 1326 } 1327 } 1328 1329 1330 public void saveImage() { 1331 if (mImageShow.hasModifications()) { 1332 // Get the name of the album, to which the image will be saved 1333 File saveDir = SaveImage.getFinalSaveDirectory(this, mSelectedImageUri); 1334 int bucketId = GalleryUtils.getBucketId(saveDir.getPath()); 1335 String albumName = LocalAlbum.getLocalizedName(getResources(), bucketId, null); 1336 showSavingProgress(albumName); 1337 mImageShow.saveImage(this, null); 1338 } else { 1339 done(); 1340 } 1341 } 1342 1343 1344 public void done() { 1345 hideSavingProgress(); 1346 if (mLoadBitmapTask != null) { 1347 mLoadBitmapTask.cancel(false); 1348 } 1349 finish(); 1350 } 1351 1352 private void extractXMPData() { 1353 XMresults res = XmpPresets.extractXMPData( 1354 getBaseContext(), mMasterImage, getIntent().getData()); 1355 if (res == null) 1356 return; 1357 1358 mOriginalImageUri = res.originalimage; 1359 mOriginalPreset = res.preset; 1360 } 1361 1362 public Uri getSelectedImageUri() { 1363 return mSelectedImageUri; 1364 } 1365 1366 public void setHandlesSwipeForView(View view, float startX, float startY) { 1367 if (view != null) { 1368 mHandlingSwipeButton = true; 1369 } else { 1370 mHandlingSwipeButton = false; 1371 } 1372 mHandledSwipeView = view; 1373 int[] location = new int[2]; 1374 view.getLocationInWindow(location); 1375 mSwipeStartX = location[0] + startX; 1376 mSwipeStartY = location[1] + startY; 1377 } 1378 1379 public boolean dispatchTouchEvent (MotionEvent ev) { 1380 if (mHandlingSwipeButton) { 1381 int direction = CategoryView.HORIZONTAL; 1382 if (mHandledSwipeView instanceof CategoryView) { 1383 direction = ((CategoryView) mHandledSwipeView).getOrientation(); 1384 } 1385 if (ev.getActionMasked() == MotionEvent.ACTION_MOVE) { 1386 float delta = ev.getY() - mSwipeStartY; 1387 float distance = mHandledSwipeView.getHeight(); 1388 if (direction == CategoryView.VERTICAL) { 1389 delta = ev.getX() - mSwipeStartX; 1390 mHandledSwipeView.setTranslationX(delta); 1391 distance = mHandledSwipeView.getWidth(); 1392 } else { 1393 mHandledSwipeView.setTranslationY(delta); 1394 } 1395 delta = Math.abs(delta); 1396 float transparency = Math.min(1, delta / distance); 1397 mHandledSwipeView.setAlpha(1.f - transparency); 1398 mHandledSwipeViewLastDelta = delta; 1399 } 1400 if (ev.getActionMasked() == MotionEvent.ACTION_CANCEL 1401 || ev.getActionMasked() == MotionEvent.ACTION_UP) { 1402 mHandledSwipeView.setTranslationX(0); 1403 mHandledSwipeView.setTranslationY(0); 1404 mHandledSwipeView.setAlpha(1.f); 1405 mHandlingSwipeButton = false; 1406 float distance = mHandledSwipeView.getHeight(); 1407 if (direction == CategoryView.VERTICAL) { 1408 distance = mHandledSwipeView.getWidth(); 1409 } 1410 if (mHandledSwipeViewLastDelta > distance) { 1411 ((SwipableView) mHandledSwipeView).delete(); 1412 } 1413 } 1414 return true; 1415 } 1416 return super.dispatchTouchEvent(ev); 1417 } 1418 1419 public Point mHintTouchPoint = new Point(); 1420 1421 public Point hintTouchPoint(View view) { 1422 int location[] = new int[2]; 1423 view.getLocationOnScreen(location); 1424 int x = mHintTouchPoint.x - location[0]; 1425 int y = mHintTouchPoint.y - location[1]; 1426 return new Point(x, y); 1427 } 1428 1429 public void startTouchAnimation(View target, float x, float y) { 1430 final CategorySelected hint = 1431 (CategorySelected) findViewById(R.id.categorySelectedIndicator); 1432 int location[] = new int[2]; 1433 target.getLocationOnScreen(location); 1434 mHintTouchPoint.x = (int) (location[0] + x); 1435 mHintTouchPoint.y = (int) (location[1] + y); 1436 int locationHint[] = new int[2]; 1437 ((View)hint.getParent()).getLocationOnScreen(locationHint); 1438 int dx = (int) (x - (hint.getWidth())/2); 1439 int dy = (int) (y - (hint.getHeight())/2); 1440 hint.setTranslationX(location[0] - locationHint[0] + dx); 1441 hint.setTranslationY(location[1] - locationHint[1] + dy); 1442 hint.setVisibility(View.VISIBLE); 1443 hint.animate().scaleX(2).scaleY(2).alpha(0).withEndAction(new Runnable() { 1444 @Override 1445 public void run() { 1446 hint.setVisibility(View.INVISIBLE); 1447 hint.setScaleX(1); 1448 hint.setScaleY(1); 1449 hint.setAlpha(1); 1450 } 1451 }); 1452 } 1453} 1454