1ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi/* 21910b08fe7305339a8bd87d4eb7bc6e56abbfa29Shih-chia Cheng 3f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang * Copyright (C) 2011 The Android Open Source Project 4ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * 5ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * Licensed under the Apache License, Version 2.0 (the "License"); 6ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * you may not use this file except in compliance with the License. 7ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * You may obtain a copy of the License at 8ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * 9ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * http://www.apache.org/licenses/LICENSE-2.0 10ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * 11ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * Unless required by applicable law or agreed to in writing, software 12ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * distributed under the License is distributed on an "AS IS" BASIS, 13ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * See the License for the specific language governing permissions and 15ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * limitations under the License. 16ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi */ 17ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 1881393d6dc5767f7784a00958095614a37bf1a91aGil Dobjanschipackage com.android.videoeditor.widgets; 19ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 2081393d6dc5767f7784a00958095614a37bf1a91aGil Dobjanschiimport com.android.videoeditor.service.ApiService; 2181393d6dc5767f7784a00958095614a37bf1a91aGil Dobjanschiimport com.android.videoeditor.service.MovieMediaItem; 2281393d6dc5767f7784a00958095614a37bf1a91aGil Dobjanschiimport com.android.videoeditor.R; 23ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 24ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport android.content.Context; 25ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport android.graphics.Bitmap; 26ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport android.graphics.Canvas; 271910b08fe7305339a8bd87d4eb7bc6e56abbfa29Shih-chia Chengimport android.graphics.Color; 281910b08fe7305339a8bd87d4eb7bc6e56abbfa29Shih-chia Chengimport android.graphics.Paint; 29ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport android.graphics.Point; 30ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport android.graphics.Rect; 31ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport android.graphics.drawable.Drawable; 32ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport android.util.AttributeSet; 33ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport android.util.DisplayMetrics; 34ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport android.util.Log; 35f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Changimport android.util.LruCache; 36ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport android.view.Display; 37ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport android.view.GestureDetector; 38ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport android.view.MotionEvent; 39ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport android.view.View; 40ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport android.view.WindowManager; 41ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 42f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Changimport java.util.ArrayList; 43f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Changimport java.util.HashSet; 44f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Changimport java.util.Map; 45f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang 46ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi/** 471910b08fe7305339a8bd87d4eb7bc6e56abbfa29Shih-chia Cheng * Media item preview view on the timeline. This class assumes the media item is always put on a 481910b08fe7305339a8bd87d4eb7bc6e56abbfa29Shih-chia Cheng * MediaLinearLayout and is wrapped with a timeline scroll view. 49ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi */ 50ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschipublic class MediaItemView extends View { 51ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi private static final String TAG = "MediaItemView"; 52ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 53f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang // Static variables 54f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang private static Drawable sAddTransitionDrawable; 55f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang private static Drawable sEmptyFrameDrawable; 56f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang private static ThumbnailCache sThumbnailCache; 57ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 588f2abc8e2ffffd37487a6baae568bd7e11da9439Chih-Chung Chang // Because MediaItemView may be recreated for the same MediaItem (it happens 598f2abc8e2ffffd37487a6baae568bd7e11da9439Chih-Chung Chang // when the device orientation is changed), we use a globally unique 608f2abc8e2ffffd37487a6baae568bd7e11da9439Chih-Chung Chang // generation counter to reject thumbnail results (passed to setBitmap()) 618f2abc8e2ffffd37487a6baae568bd7e11da9439Chih-Chung Chang // requested by a previous incarnation of MediaItemView. 628f2abc8e2ffffd37487a6baae568bd7e11da9439Chih-Chung Chang private static int sGenerationCounter; 638f2abc8e2ffffd37487a6baae568bd7e11da9439Chih-Chung Chang 64ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi // Instance variables 65ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi private final GestureDetector mGestureDetector; 66ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi private final ScrollViewListener mScrollListener; 6724318ced8e2cae0f300bd4360b8bf25d322a0b1cShih-chia Cheng private final Rect mGeneratingEffectProgressDestRect; 68ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 69ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi private boolean mIsScrolling; 70ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi private boolean mIsPlaying; 71ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 7224318ced8e2cae0f300bd4360b8bf25d322a0b1cShih-chia Cheng // Progress of generation of the effect applied on this media item view. 7324318ced8e2cae0f300bd4360b8bf25d322a0b1cShih-chia Cheng // -1 indicates the generation is not in progress. 0-100 indicates the 7424318ced8e2cae0f300bd4360b8bf25d322a0b1cShih-chia Cheng // generation is in progress. Currently only Ken Burns effect is used with 7524318ced8e2cae0f300bd4360b8bf25d322a0b1cShih-chia Cheng // the progress bar. 7624318ced8e2cae0f300bd4360b8bf25d322a0b1cShih-chia Cheng private int mGeneratingEffectProgress; 7724318ced8e2cae0f300bd4360b8bf25d322a0b1cShih-chia Cheng 7824318ced8e2cae0f300bd4360b8bf25d322a0b1cShih-chia Cheng // The scrolled left pixels of this view. 79f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang private int mScrollX; 80ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 81f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang private String mProjectPath; 82f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang private MovieMediaItem mMediaItem; 831910b08fe7305339a8bd87d4eb7bc6e56abbfa29Shih-chia Cheng // Convenient handle to the parent timeline scroll view. 841910b08fe7305339a8bd87d4eb7bc6e56abbfa29Shih-chia Cheng private TimelineHorizontalScrollView mScrollView; 851910b08fe7305339a8bd87d4eb7bc6e56abbfa29Shih-chia Cheng // Convenient handle to the parent timeline linear layout. 861910b08fe7305339a8bd87d4eb7bc6e56abbfa29Shih-chia Cheng private MediaLinearLayout mTimeline; 87f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang private ItemSimpleGestureListener mGestureListener; 88f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang private int[] mLeftState, mRightState; 89ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 9024318ced8e2cae0f300bd4360b8bf25d322a0b1cShih-chia Cheng private int mScreenWidth; 91f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang private int mThumbnailWidth, mThumbnailHeight; 92f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang private int mNumberOfThumbnails; 93f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang private long mBeginTimeMs, mEndTimeMs; 94ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 95f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang private int mGeneration; 96f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang private HashSet<Integer> mPending; 97f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang private ArrayList<Integer> mWantThumbnails; 98ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 99f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang public MediaItemView(Context context, AttributeSet attrs) { 100f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang this(context, attrs, 0); 101f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang } 102ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 103f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang public MediaItemView(Context context) { 104f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang this(context, null, 0); 105ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 106ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 107ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi public MediaItemView(Context context, AttributeSet attrs, int defStyle) { 108ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi super(context, attrs, defStyle); 109ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 110f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang // Initialize static data 111f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang if (sAddTransitionDrawable == null) { 112f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang sAddTransitionDrawable = getResources().getDrawable( 113f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang R.drawable.add_transition_selector); 114f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang sEmptyFrameDrawable = getResources().getDrawable( 115f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang R.drawable.timeline_loading); 116ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 117f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang // Initialize the thumbnail cache, limit the memory usage to 3MB 118f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang sThumbnailCache = new ThumbnailCache(3*1024*1024); 119f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang } 120ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 121f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang // Get the screen width 122f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang final Display display = ((WindowManager)context.getSystemService( 123f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang Context.WINDOW_SERVICE)).getDefaultDisplay(); 124f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang final DisplayMetrics metrics = new DisplayMetrics(); 125f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang display.getMetrics(metrics); 126f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang mScreenWidth = metrics.widthPixels; 12777a3d89eaf839df50c2f3b4ddb0819ed974726b6Gil Dobjanschi 128f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang // Setup our gesture detector and scroll listener 129f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang mGestureDetector = new GestureDetector(context, new MyGestureListener()); 130f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang mScrollListener = new MyScrollViewListener(); 131ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 132f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang // Prepare the progress bar rectangles 133ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi final ProgressBar progressBar = ProgressBar.getProgressBar(context); 134f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang final int layoutHeight = (int)( 135f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang getResources().getDimension(R.dimen.media_layout_height) - 136f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang getResources().getDimension(R.dimen.media_layout_padding)); 13724318ced8e2cae0f300bd4360b8bf25d322a0b1cShih-chia Cheng mGeneratingEffectProgressDestRect = new Rect(getPaddingLeft(), 138ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi layoutHeight - progressBar.getHeight() - getPaddingBottom(), 0, 139ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi layoutHeight - getPaddingBottom()); 140ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 141ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi // Initialize the progress value 14224318ced8e2cae0f300bd4360b8bf25d322a0b1cShih-chia Cheng mGeneratingEffectProgress = -1; 143ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 144f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang // Initialize the "Add transition" indicators state 145f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang mLeftState = View.EMPTY_STATE_SET; 146f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang mRightState = View.EMPTY_STATE_SET; 147ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 148f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang // Initialize the thumbnail indices we want to request 149f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang mWantThumbnails = new ArrayList<Integer>(); 15077a3d89eaf839df50c2f3b4ddb0819ed974726b6Gil Dobjanschi 151f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang // Initialize the set of indices we are waiting 152f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang mPending = new HashSet<Integer>(); 1538f2abc8e2ffffd37487a6baae568bd7e11da9439Chih-Chung Chang 1548f2abc8e2ffffd37487a6baae568bd7e11da9439Chih-Chung Chang // Initialize the generation number 1558f2abc8e2ffffd37487a6baae568bd7e11da9439Chih-Chung Chang mGeneration = sGenerationCounter++; 156f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang } 157ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 158f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang private class MyGestureListener extends GestureDetector.SimpleOnGestureListener { 159f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang @Override 160f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang public boolean onSingleTapConfirmed(MotionEvent e) { 161f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang if (mGestureListener == null) { 162f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang return false; 163f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang } 164ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 165f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang int tappedArea = ItemSimpleGestureListener.CENTER_AREA; 166f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang 16724318ced8e2cae0f300bd4360b8bf25d322a0b1cShih-chia Cheng if (hasSpaceForAddTransitionIcons()) { 168f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang if (mMediaItem.getBeginTransition() == null && 169f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang e.getX() < sAddTransitionDrawable.getIntrinsicWidth() + 170f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang getPaddingLeft()) { 171f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang tappedArea = ItemSimpleGestureListener.LEFT_AREA; 172f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang } else if (mMediaItem.getEndTransition() == null && 173f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang e.getX() >= getWidth() - getPaddingRight() - 174f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang sAddTransitionDrawable.getIntrinsicWidth()) { 175f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang tappedArea = ItemSimpleGestureListener.RIGHT_AREA; 176f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang } 177f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang } 178f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang return mGestureListener.onSingleTapConfirmed( 179f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang MediaItemView.this, tappedArea, e); 180f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang } 181ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 182f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang @Override 183f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang public void onLongPress(MotionEvent e) { 184f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang if (mGestureListener != null) { 185f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang mGestureListener.onLongPress(MediaItemView.this, e); 186f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang } 187f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang } 188ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 189ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 190f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang private class MyScrollViewListener implements ScrollViewListener { 191f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang @Override 192f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang public void onScrollBegin(View view, int scrollX, int scrollY, boolean appScroll) { 193f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang mIsScrolling = true; 194f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang } 195f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang 196f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang @Override 197f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang public void onScrollProgress(View view, int scrollX, int scrollY, boolean appScroll) { 198f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang mScrollX = scrollX; 199f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang invalidate(); 200f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang } 201f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang 202f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang @Override 203f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang public void onScrollEnd(View view, int scrollX, int scrollY, boolean appScroll) { 204f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang mIsScrolling = false; 205f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang mScrollX = scrollX; 206f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang invalidate(); 207f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang } 208ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 209ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 210ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi @Override 211ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi protected void onAttachedToWindow() { 2121910b08fe7305339a8bd87d4eb7bc6e56abbfa29Shih-chia Cheng mMediaItem = (MovieMediaItem) getTag(); 2131910b08fe7305339a8bd87d4eb7bc6e56abbfa29Shih-chia Cheng 2141910b08fe7305339a8bd87d4eb7bc6e56abbfa29Shih-chia Cheng mScrollView = (TimelineHorizontalScrollView) getRootView().findViewById( 2151910b08fe7305339a8bd87d4eb7bc6e56abbfa29Shih-chia Cheng R.id.timeline_scroller); 2161910b08fe7305339a8bd87d4eb7bc6e56abbfa29Shih-chia Cheng mScrollView.addScrollListener(mScrollListener); 217ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi // Add the horizontal scroll view listener 2181910b08fe7305339a8bd87d4eb7bc6e56abbfa29Shih-chia Cheng mScrollX = mScrollView.getScrollX(); 2191910b08fe7305339a8bd87d4eb7bc6e56abbfa29Shih-chia Cheng 2201910b08fe7305339a8bd87d4eb7bc6e56abbfa29Shih-chia Cheng mTimeline = (MediaLinearLayout) getRootView().findViewById(R.id.timeline_media); 221ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 222ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 223ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi @Override 224ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi protected void onDetachedFromWindow() { 2251910b08fe7305339a8bd87d4eb7bc6e56abbfa29Shih-chia Cheng mScrollView.removeScrollListener(mScrollListener); 226f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang // Release the cached bitmaps 227f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang releaseBitmapsAndClear(); 228ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 229ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 230ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi /** 231ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * @return The shadow builder 232ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi */ 233ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi public DragShadowBuilder getShadowBuilder() { 234ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi return new MediaItemShadowBuilder(this); 235ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 236ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 237ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi /** 238f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang * Shadow builder for the media item 239f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang */ 240f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang private class MediaItemShadowBuilder extends DragShadowBuilder { 241f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang private final Drawable mFrame; 242f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang 243f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang public MediaItemShadowBuilder(View view) { 244f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang super(view); 245f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang mFrame = view.getContext().getResources().getDrawable( 246f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang R.drawable.timeline_item_pressed); 247f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang } 248f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang 249f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang @Override 250f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint) { 251f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang shadowSize.set(getShadowWidth(), getShadowHeight()); 252f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang shadowTouchPoint.set(shadowSize.x / 2, shadowSize.y); 253f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang } 254f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang 255f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang @Override 256f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang public void onDrawShadow(Canvas canvas) { 257f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang mFrame.setBounds(0, 0, getShadowWidth(), getShadowHeight()); 258f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang mFrame.draw(canvas); 259f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang 260f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang Bitmap bitmap = getOneThumbnail(); 261f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang if (bitmap != null) { 262f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang final View view = getView(); 263f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang canvas.drawBitmap(bitmap, view.getPaddingLeft(), 264f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang view.getPaddingTop(), null); 265f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang } 266f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang } 267f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang } 268f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang 269f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang /** 270ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * @return The shadow width 271ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi */ 272f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang private int getShadowWidth() { 273ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi final int thumbnailHeight = getHeight() - getPaddingTop() - getPaddingBottom(); 274f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang final int thumbnailWidth = (thumbnailHeight * mMediaItem.getWidth()) / 275f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang mMediaItem.getHeight(); 276ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi return thumbnailWidth + getPaddingLeft() + getPaddingRight(); 277ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 278ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 279ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi /** 280ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * @return The shadow height 281ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi */ 282f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang private int getShadowHeight() { 283ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi return getHeight(); 284ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 285ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 286f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang private Bitmap getOneThumbnail() { 287f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang ThumbnailKey key = new ThumbnailKey(); 288f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang key.mediaItemId = mMediaItem.getId(); 289f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang 290f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang // Find any one cached thumbnail 291f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang for (int i = 0; i < mNumberOfThumbnails; i++) { 292f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang key.index = i; 293f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang Bitmap bitmap = sThumbnailCache.get(key); 294f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang if (bitmap != null) { 295f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang return bitmap; 296f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang } 297f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang } 298f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang 299f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang return null; 300f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang } 301f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang 302ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi /** 303ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * @param projectPath The project path 304ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi */ 305ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi public void setProjectPath(String projectPath) { 306ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi mProjectPath = projectPath; 307ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 308ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 309ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi /** 310ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * @param listener The gesture listener 311ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi */ 312ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi public void setGestureListener(ItemSimpleGestureListener listener) { 313ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi mGestureListener = listener; 314ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 315ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 316ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi /** 317f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang * A view enters or exits the playback mode 31803699548e6f627af79aac4fd0d233f10e53841d0Gil Dobjanschi * 319f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang * @param playback true if playback is in progress 320ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi */ 321f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang public void setPlaybackMode(boolean playback) { 322f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang mIsPlaying = playback; 323f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang invalidate(); 324f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang } 325ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 326f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang /** 32724318ced8e2cae0f300bd4360b8bf25d322a0b1cShih-chia Cheng * Resets the effect generation progress status. 32824318ced8e2cae0f300bd4360b8bf25d322a0b1cShih-chia Cheng */ 32924318ced8e2cae0f300bd4360b8bf25d322a0b1cShih-chia Cheng public void resetGeneratingEffectProgress() { 33024318ced8e2cae0f300bd4360b8bf25d322a0b1cShih-chia Cheng setGeneratingEffectProgress(-1); 33124318ced8e2cae0f300bd4360b8bf25d322a0b1cShih-chia Cheng } 33224318ced8e2cae0f300bd4360b8bf25d322a0b1cShih-chia Cheng 33324318ced8e2cae0f300bd4360b8bf25d322a0b1cShih-chia Cheng /** 33424318ced8e2cae0f300bd4360b8bf25d322a0b1cShih-chia Cheng * Sets the effect generation progress of this view. 335ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi */ 33624318ced8e2cae0f300bd4360b8bf25d322a0b1cShih-chia Cheng public void setGeneratingEffectProgress(int progress) { 337ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi if (progress == 0) { 33824318ced8e2cae0f300bd4360b8bf25d322a0b1cShih-chia Cheng mGeneratingEffectProgress = progress; 339ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi // Release the current set of bitmaps. New content is being generated. 340ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi releaseBitmapsAndClear(); 341ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } else if (progress == 100) { 34224318ced8e2cae0f300bd4360b8bf25d322a0b1cShih-chia Cheng mGeneratingEffectProgress = -1; 343ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } else { 34424318ced8e2cae0f300bd4360b8bf25d322a0b1cShih-chia Cheng mGeneratingEffectProgress = progress; 345ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 346ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 347ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi invalidate(); 348ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 349ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 350ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi /** 35124318ced8e2cae0f300bd4360b8bf25d322a0b1cShih-chia Cheng * The view has been layout out. 352ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * 353f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang * @param oldLeft The old left position 354f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang * @param oldRight The old right position 355ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi */ 356f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang public void onLayoutPerformed(int oldLeft, int oldRight) { 357f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang // Compute the thumbnail width and height 358f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang mThumbnailHeight = getHeight() - getPaddingTop() - getPaddingBottom(); 359f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang mThumbnailWidth = (mThumbnailHeight * mMediaItem.getWidth()) / mMediaItem.getHeight(); 360ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 361b05b86bc5ac360df08b1951998a8f3540e3cae4fChih-Chung Chang // We are not able to display a bitmap with width or height > 2048. 362b05b86bc5ac360df08b1951998a8f3540e3cae4fChih-Chung Chang while (mThumbnailWidth > 2048 || mThumbnailHeight > 2048) { 363b05b86bc5ac360df08b1951998a8f3540e3cae4fChih-Chung Chang mThumbnailHeight /= 2; 364b05b86bc5ac360df08b1951998a8f3540e3cae4fChih-Chung Chang mThumbnailWidth /= 2; 365b05b86bc5ac360df08b1951998a8f3540e3cae4fChih-Chung Chang } 366b05b86bc5ac360df08b1951998a8f3540e3cae4fChih-Chung Chang 367f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang int usableWidth = getWidth() - getPaddingLeft() - getPaddingRight(); 36824318ced8e2cae0f300bd4360b8bf25d322a0b1cShih-chia Cheng // Compute the ceiling of (usableWidth / mThumbnailWidth). 369f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang mNumberOfThumbnails = (usableWidth + mThumbnailWidth - 1) / mThumbnailWidth; 370f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang mBeginTimeMs = mMediaItem.getAppBoundaryBeginTime(); 371f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang mEndTimeMs = mMediaItem.getAppBoundaryEndTime(); 372ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 373f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang releaseBitmapsAndClear(); 374f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang invalidate(); 375ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 376ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 377ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi /** 37824318ced8e2cae0f300bd4360b8bf25d322a0b1cShih-chia Cheng * @return True if the effect generation is in progress 379ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi */ 38024318ced8e2cae0f300bd4360b8bf25d322a0b1cShih-chia Cheng public boolean isGeneratingEffect() { 38124318ced8e2cae0f300bd4360b8bf25d322a0b1cShih-chia Cheng return (mGeneratingEffectProgress >= 0); 382f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang } 383ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 384f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang public boolean setBitmap(Bitmap bitmap, int index, int token) { 385f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang // Ignore results from previous requests 386f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang if (token != mGeneration) { 387ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi return false; 388f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang } 389f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang if (!mPending.contains(index)) { 390f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang Log.e(TAG, "received unasked bitmap, index = " + index); 391ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi return false; 392ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 393f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang if (bitmap == null) { 394f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang Log.w(TAG, "receive null bitmap for index = " + index); 395f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang // We keep this request in mPending, so we won't request it again. 396f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang return false; 397ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 398f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang mPending.remove(index); 399f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang ThumbnailKey key = new ThumbnailKey(mMediaItem.getId(), index); 400f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang sThumbnailCache.put(key, bitmap); 401ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 402ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi invalidate(); 403ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi return true; 404ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 405ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 406ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi @Override 407ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi protected void onDraw(Canvas canvas) { 408ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi super.onDraw(canvas); 40924318ced8e2cae0f300bd4360b8bf25d322a0b1cShih-chia Cheng if (mGeneratingEffectProgress >= 0) { 410f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang ProgressBar.getProgressBar(getContext()).draw( 41124318ced8e2cae0f300bd4360b8bf25d322a0b1cShih-chia Cheng canvas, mGeneratingEffectProgress, mGeneratingEffectProgressDestRect, 412f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang getPaddingLeft(), getWidth() - getPaddingRight()); 413f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang } else { 414ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi // Do not draw in the padding area 415f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang canvas.clipRect(getPaddingLeft(), getPaddingTop(), 416f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang getWidth() - getPaddingRight(), 417ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi getHeight() - getPaddingBottom()); 418ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 419f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang // Draw thumbnails 420f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang drawThumbnails(canvas); 421ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 422f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang // Draw the "Add transition" indicators 423ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi if (isSelected()) { 42424318ced8e2cae0f300bd4360b8bf25d322a0b1cShih-chia Cheng drawAddTransitionIcons(canvas); 4251910b08fe7305339a8bd87d4eb7bc6e56abbfa29Shih-chia Cheng } else if (mTimeline.hasItemSelected()) { 4261910b08fe7305339a8bd87d4eb7bc6e56abbfa29Shih-chia Cheng // Dim myself if some view on the timeline is selected but not me 4271910b08fe7305339a8bd87d4eb7bc6e56abbfa29Shih-chia Cheng // by drawing a transparent black overlay. 4281910b08fe7305339a8bd87d4eb7bc6e56abbfa29Shih-chia Cheng final Paint paint = new Paint(); 4291910b08fe7305339a8bd87d4eb7bc6e56abbfa29Shih-chia Cheng paint.setColor(Color.BLACK); 4301910b08fe7305339a8bd87d4eb7bc6e56abbfa29Shih-chia Cheng paint.setAlpha(192); 4311910b08fe7305339a8bd87d4eb7bc6e56abbfa29Shih-chia Cheng canvas.drawPaint(paint); 432ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 433ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 434f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang // Request thumbnails if things are not moving 4351910b08fe7305339a8bd87d4eb7bc6e56abbfa29Shih-chia Cheng boolean isBusy = mIsPlaying || mTimeline.isTrimming() || mIsScrolling; 436f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang if (!isBusy && !mWantThumbnails.isEmpty()) { 437f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang requestThumbnails(); 438ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 439ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 440ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 441ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 442f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang // Draws the thumbnails, also put unavailable thumbnail indices in 443f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang // mWantThumbnails. 44477a3d89eaf839df50c2f3b4ddb0819ed974726b6Gil Dobjanschi private void drawThumbnails(Canvas canvas) { 445f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang mWantThumbnails.clear(); 446f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang 447f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang // The screen coordinate of the left edge of the usable area. 448f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang int left = getLeft() + getPaddingLeft() - mScrollX; 449f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang // The screen coordinate of the right edge of the usable area. 450f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang int right = getRight() - getPaddingRight() - mScrollX; 451f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang // Return if the usable area is not on screen. 452f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang if (left >= mScreenWidth || right <= 0 || left >= right) { 453ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi return; 454ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 455ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 456f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang // Map [0, mScreenWidth - 1] to the indices of the thumbnail. 457f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang int startIdx = (0 - left) / mThumbnailWidth; 458f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang int endIdx = (mScreenWidth - 1 - left) / mThumbnailWidth; 459ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 460f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang startIdx = clamp(startIdx, 0, mNumberOfThumbnails - 1); 461f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang endIdx = clamp(endIdx, 0, mNumberOfThumbnails - 1); 462ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 463f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang // Prepare variables used in the loop 464f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang ThumbnailKey key = new ThumbnailKey(); 465f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang key.mediaItemId = mMediaItem.getId(); 466f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang int x = getPaddingLeft() + startIdx * mThumbnailWidth; 467f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang int y = getPaddingTop(); 46877a3d89eaf839df50c2f3b4ddb0819ed974726b6Gil Dobjanschi 469b05b86bc5ac360df08b1951998a8f3540e3cae4fChih-Chung Chang // Center the thumbnail vertically 470b05b86bc5ac360df08b1951998a8f3540e3cae4fChih-Chung Chang int spacing = (getHeight() - getPaddingTop() - getPaddingBottom() - 471b05b86bc5ac360df08b1951998a8f3540e3cae4fChih-Chung Chang mThumbnailHeight) / 2; 472b05b86bc5ac360df08b1951998a8f3540e3cae4fChih-Chung Chang y += spacing; 473b05b86bc5ac360df08b1951998a8f3540e3cae4fChih-Chung Chang 474f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang // Loop through the thumbnails on screen and draw it 475f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang for (int i = startIdx; i <= endIdx; i++) { 476f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang key.index = i; 477f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang Bitmap bitmap = sThumbnailCache.get(key); 478f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang if (bitmap == null) { 47977a3d89eaf839df50c2f3b4ddb0819ed974726b6Gil Dobjanschi // Draw a frame placeholder 480f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang sEmptyFrameDrawable.setBounds( 481f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang x, y, x + mThumbnailWidth, y + mThumbnailHeight); 482f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang sEmptyFrameDrawable.draw(canvas); 483f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang if (!mPending.contains(i)) { 484f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang mWantThumbnails.add(Integer.valueOf(i)); 48577a3d89eaf839df50c2f3b4ddb0819ed974726b6Gil Dobjanschi } 486f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang } else { 487f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang canvas.drawBitmap(bitmap, x, y, null); 48877a3d89eaf839df50c2f3b4ddb0819ed974726b6Gil Dobjanschi } 489f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang x += mThumbnailWidth; 490ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 491ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 492ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 493ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi /** 49424318ced8e2cae0f300bd4360b8bf25d322a0b1cShih-chia Cheng * Draws the "Add transition" icons at the beginning and end of the media item. 495ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * 49624318ced8e2cae0f300bd4360b8bf25d322a0b1cShih-chia Cheng * @param canvas Canvas to be drawn 497ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi */ 49824318ced8e2cae0f300bd4360b8bf25d322a0b1cShih-chia Cheng private void drawAddTransitionIcons(Canvas canvas) { 49924318ced8e2cae0f300bd4360b8bf25d322a0b1cShih-chia Cheng if (hasSpaceForAddTransitionIcons()) { 500f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang if (mMediaItem.getBeginTransition() == null) { 501f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang sAddTransitionDrawable.setState(mLeftState); 502f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang sAddTransitionDrawable.setBounds(getPaddingLeft(), getPaddingTop(), 503f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang sAddTransitionDrawable.getIntrinsicWidth() + getPaddingLeft(), 504f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang getPaddingTop() + sAddTransitionDrawable.getIntrinsicHeight()); 505f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang sAddTransitionDrawable.draw(canvas); 506ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 507ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 508f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang if (mMediaItem.getEndTransition() == null) { 509f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang sAddTransitionDrawable.setState(mRightState); 510f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang sAddTransitionDrawable.setBounds( 511ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi getWidth() - getPaddingRight() - 512f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang sAddTransitionDrawable.getIntrinsicWidth(), 513ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi getPaddingTop(), getWidth() - getPaddingRight(), 514f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang getPaddingTop() + sAddTransitionDrawable.getIntrinsicHeight()); 515f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang sAddTransitionDrawable.draw(canvas); 516ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 517ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 518ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 519ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 520ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi /** 52124318ced8e2cae0f300bd4360b8bf25d322a0b1cShih-chia Cheng * @return true if the visible area of this view is big enough to display 52224318ced8e2cae0f300bd4360b8bf25d322a0b1cShih-chia Cheng * "add transition" icons on both sides; false otherwise. 523ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi */ 52424318ced8e2cae0f300bd4360b8bf25d322a0b1cShih-chia Cheng private boolean hasSpaceForAddTransitionIcons() { 5251910b08fe7305339a8bd87d4eb7bc6e56abbfa29Shih-chia Cheng if (mTimeline.isTrimming()) { 526ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi return false; 527ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 528ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 529ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi return (getWidth() - getPaddingLeft() - getPaddingRight() >= 530f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang 2 * sAddTransitionDrawable.getIntrinsicWidth()); 531f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang } 532f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang 53324318ced8e2cae0f300bd4360b8bf25d322a0b1cShih-chia Cheng /** 53424318ced8e2cae0f300bd4360b8bf25d322a0b1cShih-chia Cheng * Clamps the input value v to the range [low, high]. 53524318ced8e2cae0f300bd4360b8bf25d322a0b1cShih-chia Cheng */ 536f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang private static int clamp(int v, int low, int high) { 537f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang return Math.min(Math.max(v, low), high); 538f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang } 539f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang 54024318ced8e2cae0f300bd4360b8bf25d322a0b1cShih-chia Cheng /** 54124318ced8e2cae0f300bd4360b8bf25d322a0b1cShih-chia Cheng * Requests the thumbnails in mWantThumbnails (which is filled by onDraw). 54224318ced8e2cae0f300bd4360b8bf25d322a0b1cShih-chia Cheng */ 543f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang private void requestThumbnails() { 544f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang // Copy mWantThumbnails to an array 545f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang int indices[] = new int[mWantThumbnails.size()]; 546f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang for (int i = 0; i < mWantThumbnails.size(); i++) { 547f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang indices[i] = mWantThumbnails.get(i); 548f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang } 549f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang 550f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang // Put them in the pending set 551f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang mPending.addAll(mWantThumbnails); 552f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang 553f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang ApiService.getMediaItemThumbnails(getContext(), mProjectPath, 554f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang mMediaItem.getId(), mThumbnailWidth, mThumbnailHeight, 555f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang mBeginTimeMs, mEndTimeMs, mNumberOfThumbnails, mGeneration, 556f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang indices); 557ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 558ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 559ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi @Override 560ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi public boolean onTouchEvent(MotionEvent ev) { 561ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi // Let the gesture detector inspect all events. 562ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi mGestureDetector.onTouchEvent(ev); 563ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi super.onTouchEvent(ev); 564ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 565ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi switch (ev.getAction()) { 566ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi case MotionEvent.ACTION_DOWN: { 567f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang mLeftState = View.EMPTY_STATE_SET; 568f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang mRightState = View.EMPTY_STATE_SET; 56924318ced8e2cae0f300bd4360b8bf25d322a0b1cShih-chia Cheng if (isSelected() && hasSpaceForAddTransitionIcons()) { 570f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang if (ev.getX() < sAddTransitionDrawable.getIntrinsicWidth() + 571ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi getPaddingLeft()) { 572f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang if (mMediaItem.getBeginTransition() == null) { 573ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi mLeftState = View.PRESSED_WINDOW_FOCUSED_STATE_SET; 574ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 575ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } else if (ev.getX() >= getWidth() - getPaddingRight() - 576f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang sAddTransitionDrawable.getIntrinsicWidth()) { 577f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang if (mMediaItem.getEndTransition() == null) { 578ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi mRightState = View.PRESSED_WINDOW_FOCUSED_STATE_SET; 579ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 580ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 581ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 582ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi invalidate(); 583ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi break; 584ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 585ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 586ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi case MotionEvent.ACTION_UP: 587ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi case MotionEvent.ACTION_CANCEL: { 588ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi mRightState = View.EMPTY_STATE_SET; 589ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi mLeftState = View.EMPTY_STATE_SET; 590ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi invalidate(); 591ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi break; 592ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 593ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 594ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi default: { 595ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi break; 596ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 597ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 598ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 599ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi return true; 600ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 601ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 602f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang private void releaseBitmapsAndClear() { 603f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang sThumbnailCache.clearForMediaItemId(mMediaItem.getId()); 604f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang mPending.clear(); 6058f2abc8e2ffffd37487a6baae568bd7e11da9439Chih-Chung Chang mGeneration = sGenerationCounter++; 606f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang } 607f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang} 608ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 609f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Changclass ThumbnailKey { 610f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang public String mediaItemId; 611f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang public int index; 612ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 613f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang public ThumbnailKey() { 614f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang } 615ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 616f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang public ThumbnailKey(String id, int idx) { 617f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang mediaItemId = id; 618f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang index = idx; 619f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang } 620ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 621f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang @Override 622f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang public boolean equals(Object o) { 623f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang if (!(o instanceof ThumbnailKey)) { 624f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang return false; 625ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 626f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang ThumbnailKey key = (ThumbnailKey) o; 627f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang return index == key.index && mediaItemId.equals(key.mediaItemId); 628f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang } 629ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 630f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang @Override 631f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang public int hashCode() { 632f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang return mediaItemId.hashCode() ^ index; 633f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang } 634f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang} 635ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 636f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Changclass ThumbnailCache { 637f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang private LruCache<ThumbnailKey, Bitmap> mCache; 638ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 639f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang public ThumbnailCache(int size) { 64024318ced8e2cae0f300bd4360b8bf25d322a0b1cShih-chia Cheng mCache = new LruCache<ThumbnailKey, Bitmap>(size) { 64124318ced8e2cae0f300bd4360b8bf25d322a0b1cShih-chia Cheng @Override 642f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang protected int sizeOf(ThumbnailKey key, Bitmap value) { 643f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang return value.getByteCount(); 644ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 645f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang }; 646ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 647ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 648f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang void put(ThumbnailKey key, Bitmap value) { 649f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang mCache.put(key, value); 650ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 651ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 652f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang Bitmap get(ThumbnailKey key) { 653f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang return mCache.get(key); 654f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang } 655ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi 656f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang void clearForMediaItemId(String id) { 657f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang Map<ThumbnailKey, Bitmap> map = mCache.snapshot(); 658f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang for (ThumbnailKey key : map.keySet()) { 659f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang if (key.mediaItemId.equals(id)) { 660f6b29b560e55392015caebeffbe76f8a1d1ddeb4Chih-Chung Chang mCache.remove(key); 661ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 662ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 663ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi } 664ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi} 665