MediaItemView.java revision 77a3d89eaf839df50c2f3b4ddb0819ed974726b6
1ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi/*
2ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * Copyright (C) 2010 The Android Open Source Project
3ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi *
4ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * Licensed under the Apache License, Version 2.0 (the "License");
5ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * you may not use this file except in compliance with the License.
6ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * You may obtain a copy of the License at
7ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi *
8ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi *      http://www.apache.org/licenses/LICENSE-2.0
9ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi *
10ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * Unless required by applicable law or agreed to in writing, software
11ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * distributed under the License is distributed on an "AS IS" BASIS,
12ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * See the License for the specific language governing permissions and
14ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * limitations under the License.
15ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi */
16ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
17ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschipackage com.google.videoeditor.widgets;
18ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
19ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport com.google.videoeditor.R;
20ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport com.google.videoeditor.service.ApiService;
21ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport com.google.videoeditor.service.MovieMediaItem;
22ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
23ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport android.content.Context;
24ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport android.graphics.Bitmap;
25ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport android.graphics.Canvas;
26ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport android.graphics.Point;
27ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport android.graphics.Rect;
28ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport android.graphics.drawable.Drawable;
29ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport android.util.AttributeSet;
30ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport android.util.DisplayMetrics;
31ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport android.util.Log;
32ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport android.view.Display;
33ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport android.view.GestureDetector;
34ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport android.view.MotionEvent;
35ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport android.view.View;
36ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport android.view.WindowManager;
37ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
38ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi/**
39ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * Media item preview view
40ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi */
41ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschipublic class MediaItemView extends View {
42ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    // Logging
43ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    private static final String TAG = "MediaItemView";
44ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
45ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    // Reasons for requesting thumbnails
46ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    private static final int REASON_SCROLL_END = 1;
47ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    private static final int REASON_REFRESH = 2;
48ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    private static final int REASON_PROGRESS_END = 3;
49ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    private static final int REASON_NEED_THUMBNAILS = 4;
50ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    private static final int REASON_PLAYBACK = 5;
51ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
52ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    private static Drawable mAddTransitionDrawable;
5377a3d89eaf839df50c2f3b4ddb0819ed974726b6Gil Dobjanschi    private static Drawable mEmptyFrameDrawable;
54ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
55ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    // Instance variables
56ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    private final GestureDetector mGestureDetector;
57ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    private final ScrollViewListener mScrollListener;
58ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    private final Rect mProgressDestRect;
59ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
60ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    private boolean mIsScrolling;
61ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    private boolean mWaitForThumbnailsAfterScroll;
62ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    private int mScrollX, mScrollingX;
63ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    private int mStart, mEnd;
64ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    private int mStartOffset, mEndOffset;
65ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    private int mRequestedStartOffset, mRequestedEndOffset;
66ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    private long mRequestedStartMs, mRequestedEndMs;
67ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    private int mRequestedCount;
68ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    private int mScreenWidth;
69ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    private String mProjectPath;
70ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    private Bitmap[] mBitmaps;
71ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    private ItemSimpleGestureListener mGestureListener;
72ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    private int mProgress;
73ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    private int[] mLeftState, mRightState;
74ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    private boolean mIsTrimming;
75ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    private boolean mIsPlaying;
7677a3d89eaf839df50c2f3b4ddb0819ed974726b6Gil Dobjanschi    private int mThumbnailWidth, mThumbnailHeight;
77ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
78ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    /**
79ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * Shadow builder for the media item
80ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     */
81ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    private class MediaItemShadowBuilder extends DragShadowBuilder {
82ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        // Instance variables
83ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        private final Drawable mFrame;
84ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
85ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        /*
86ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi         * {@inheritDoc}
87ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi         */
88ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        public MediaItemShadowBuilder(View view) {
89ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            super(view);
90ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
91ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            mFrame = view.getContext().getResources().getDrawable(R.drawable.timeline_item_pressed);
92ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        }
93ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
94ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        /*
95ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi         * {@inheritDoc}
96ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi         */
97ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        @Override
98ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint) {
99ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            shadowSize.set(getShadowWidth(), getShadowHeight());
100ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            shadowTouchPoint.set(shadowSize.x / 2, shadowSize.y);
101ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        }
102ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
103ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        /*
104ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi         * {@inheritDoc}
105ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi         */
106ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        @Override
107ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        public void onDrawShadow(Canvas canvas) {
108ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            //super.onDrawShadow(canvas);
109ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            mFrame.setBounds(0, 0, getShadowWidth(), getShadowHeight());
110ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            mFrame.draw(canvas);
111ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
112ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            if (mBitmaps != null && mBitmaps.length > 0) {
113ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                final View view = getView();
114ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                canvas.drawBitmap(mBitmaps[0], view.getPaddingLeft(), view.getPaddingTop(), null);
115ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            }
116ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        }
117ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    }
118ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
119ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    /*
120ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * {@inheritDoc}
121ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     */
122ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    public MediaItemView(Context context, AttributeSet attrs, int defStyle) {
123ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        super(context, attrs, defStyle);
124ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
125ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        // Setup the gesture listener
126ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        mGestureDetector = new GestureDetector(context,
127ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                new GestureDetector.SimpleOnGestureListener() {
128ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                    /*
129ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                     * {@inheritDoc}
130ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                     */
131ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                    @Override
132ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                    public boolean onSingleTapConfirmed(MotionEvent e) {
133ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                        if (mGestureListener == null) {
134ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                            return false;
135ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                        }
136ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
137ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                        if (hasAddTransition()) {
138ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                            final MovieMediaItem mediaItem = (MovieMediaItem)getTag();
139ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                            if (mediaItem.getBeginTransition() == null &&
140ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                                    e.getX() < mAddTransitionDrawable.getIntrinsicWidth() +
141ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                                    getPaddingLeft()) {
142ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                                return mGestureListener.onSingleTapConfirmed(MediaItemView.this,
143ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                                        ItemSimpleGestureListener.LEFT_AREA, e);
144ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                            } else if (mediaItem.getEndTransition() == null &&
145ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                                    e.getX() >= getWidth() - getPaddingRight() -
146ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                                    mAddTransitionDrawable.getIntrinsicWidth()) {
147ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                                return mGestureListener.onSingleTapConfirmed(MediaItemView.this,
148ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                                        ItemSimpleGestureListener.RIGHT_AREA, e);
149ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                            } else {
150ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                                return mGestureListener.onSingleTapConfirmed(MediaItemView.this,
151ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                                        ItemSimpleGestureListener.CENTER_AREA, e);
152ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                            }
153ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                        } else {
154ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                            return mGestureListener.onSingleTapConfirmed(MediaItemView.this,
155ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                                    ItemSimpleGestureListener.CENTER_AREA, e);
156ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                        }
157ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                    }
158ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
159ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                    /*
160ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                     * {@inheritDoc}
161ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                     */
162ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                    @Override
163ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                    public void onLongPress (MotionEvent e) {
164ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                        if (mGestureListener != null) {
165ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                            mGestureListener.onLongPress(MediaItemView.this, e);
166ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                        }
167ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                    }
168ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                });
169ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
170ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        mScrollListener = new ScrollViewListener() {
171ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            /*
172ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi             * {@inheritDoc}
173ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi             */
174ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            public void onScrollBegin(View view, int scrollX, int scrollY, boolean appScroll) {
175ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                mIsScrolling = true;
176ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            }
177ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
178ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            /*
179ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi             * {@inheritDoc}
180ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi             */
181ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            public void onScrollProgress(View view, int scrollX, int scrollY, boolean appScroll) {
182ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                mScrollingX = scrollX;
18377a3d89eaf839df50c2f3b4ddb0819ed974726b6Gil Dobjanschi                invalidate();
184ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            }
185ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
186ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            /*
187ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi             * {@inheritDoc}
188ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi             */
189ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            public void onScrollEnd(View view, int scrollX, int scrollY, boolean appScroll) {
190ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                mIsScrolling = false;
191ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                mScrollX = scrollX;
192ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                mScrollingX = scrollX;
19377a3d89eaf839df50c2f3b4ddb0819ed974726b6Gil Dobjanschi
194ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                if (requestThumbnails(REASON_SCROLL_END)) {
195ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                    invalidate();
196ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                }
197ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            }
198ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        };
199ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
200ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        // Prepare the bitmap rectangles
201ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        final ProgressBar progressBar = ProgressBar.getProgressBar(context);
202ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        final int layoutHeight = (int)(getResources().getDimension(R.dimen.media_layout_height) -
203ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            getResources().getDimension(R.dimen.media_layout_padding));
204ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        mProgressDestRect = new Rect(getPaddingLeft(),
205ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                layoutHeight - progressBar.getHeight() - getPaddingBottom(), 0,
206ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                layoutHeight - getPaddingBottom());
207ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
208ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        // Initialize the progress value
209ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        mProgress = -1;
210ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
211ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        if (mAddTransitionDrawable == null) {
212ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            mAddTransitionDrawable = getResources().getDrawable(
213ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                    R.drawable.add_transition_selector);
214ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        }
215ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
21677a3d89eaf839df50c2f3b4ddb0819ed974726b6Gil Dobjanschi        if (mEmptyFrameDrawable == null) {
21777a3d89eaf839df50c2f3b4ddb0819ed974726b6Gil Dobjanschi            mEmptyFrameDrawable = getResources().getDrawable(R.drawable.timeline_loading);
21877a3d89eaf839df50c2f3b4ddb0819ed974726b6Gil Dobjanschi        }
21977a3d89eaf839df50c2f3b4ddb0819ed974726b6Gil Dobjanschi
220ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        // Get the screen width
221ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        final Display display = ((WindowManager)context.getSystemService(
222ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                Context.WINDOW_SERVICE)).getDefaultDisplay();
223ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        final DisplayMetrics metrics = new DisplayMetrics();
224ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        display.getMetrics(metrics);
225ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        mScreenWidth = metrics.widthPixels;
226ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
227ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        mRequestedStartMs = -1;
228ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        mRequestedEndMs = -1;
229ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
230ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        mLeftState = View.EMPTY_STATE_SET;
231ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        mRightState = View.EMPTY_STATE_SET;
232ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    }
233ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
234ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    /*
235ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * {@inheritDoc}
236ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     */
237ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    public MediaItemView(Context context, AttributeSet attrs) {
238ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        this(context, attrs, 0);
239ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    }
240ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
241ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    /*
242ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * {@inheritDoc}
243ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     */
244ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    public MediaItemView(Context context) {
245ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        this(context, null, 0);
246ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    }
247ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
248ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    /*
249ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * {@inheritDoc}
250ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     */
251ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    @Override
252ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    protected void onAttachedToWindow() {
253ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        // Add the horizontal scroll view listener
254ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        final TimelineHorizontalScrollView scrollView =
255ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                (TimelineHorizontalScrollView)((View)((View)getParent()).getParent()).getParent();
256ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        mScrollingX = mScrollX = scrollView.getScrollX();
257ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        scrollView.addScrollListener(mScrollListener);
258ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    }
259ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
260ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    /*
261ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * {@inheritDoc}
262ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     */
263ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    @Override
264ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    protected void onDetachedFromWindow() {
265ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        final TimelineHorizontalScrollView scrollView =
266ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            (TimelineHorizontalScrollView)((View)((View)getParent()).getParent()).getParent();
267ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        scrollView.removeScrollListener(mScrollListener);
268ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
269ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        // Release the current set of bitmaps
270ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        releaseBitmaps();
271ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    }
272ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
273ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    /**
274ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * @return The shadow builder
275ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     */
276ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    public DragShadowBuilder getShadowBuilder() {
277ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        return new MediaItemShadowBuilder(this);
278ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    }
279ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
280ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    /**
281ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * @return The shadow width
282ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     */
283ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    public int getShadowWidth() {
284ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        final int thumbnailHeight = getHeight() - getPaddingTop() - getPaddingBottom();
285ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        final MovieMediaItem mediaItem = (MovieMediaItem)getTag();
286ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        final int thumbnailWidth = (thumbnailHeight * mediaItem.getWidth()) /
287ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            mediaItem.getHeight();
288ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        return thumbnailWidth + getPaddingLeft() + getPaddingRight();
289ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    }
290ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
291ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    /**
292ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * @return The shadow height
293ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     */
294ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    public int getShadowHeight() {
295ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        return getHeight();
296ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    }
297ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
298ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    /**
299ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * @param projectPath The project path
300ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     */
301ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    public void setProjectPath(String projectPath) {
302ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        mProjectPath = projectPath;
303ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    }
304ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
305ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    /**
306ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * @param listener The gesture listener
307ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     */
308ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    public void setGestureListener(ItemSimpleGestureListener listener) {
309ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        mGestureListener = listener;
310ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    }
311ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
312ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    /**
31303699548e6f627af79aac4fd0d233f10e53841d0Gil Dobjanschi     * The view has been layout out
31403699548e6f627af79aac4fd0d233f10e53841d0Gil Dobjanschi     *
31503699548e6f627af79aac4fd0d233f10e53841d0Gil Dobjanschi     * @param oldLeft The old left position
31603699548e6f627af79aac4fd0d233f10e53841d0Gil Dobjanschi     * @param oldRight The old right position
317ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     */
31877a3d89eaf839df50c2f3b4ddb0819ed974726b6Gil Dobjanschi    public void onLayoutPerformed(int oldLeft, int oldRight) {
31977a3d89eaf839df50c2f3b4ddb0819ed974726b6Gil Dobjanschi        // Compute the thumbnail width and height
32077a3d89eaf839df50c2f3b4ddb0819ed974726b6Gil Dobjanschi        final MovieMediaItem mediaItem = (MovieMediaItem)getTag();
32177a3d89eaf839df50c2f3b4ddb0819ed974726b6Gil Dobjanschi        mThumbnailHeight = getHeight() - getPaddingTop() - getPaddingBottom();
32277a3d89eaf839df50c2f3b4ddb0819ed974726b6Gil Dobjanschi        mThumbnailWidth = (mThumbnailHeight * mediaItem.getWidth()) / mediaItem.getHeight();
32377a3d89eaf839df50c2f3b4ddb0819ed974726b6Gil Dobjanschi
324ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        releaseBitmapsAndClear();
325ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
326ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        if (!mIsScrolling && !mIsTrimming && mProgress < 0) {
327ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            requestThumbnails(REASON_REFRESH);
328ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        }
329ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    }
330ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
331ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    /**
332ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * @param progress The progress
333ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     */
334ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    public void setProgress(int progress) {
335ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        if (progress == 0) {
336ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            mProgress = progress;
337ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            // Release the current set of bitmaps. New content is being generated.
338ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            releaseBitmapsAndClear();
339ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        } else if (progress == 100) {
340ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            // Request the preview bitmaps
341ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            requestThumbnails(REASON_PROGRESS_END);
342ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            mProgress = -1;
343ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        } else {
344ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            mProgress = progress;
345ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        }
346ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
347ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        invalidate();
348ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    }
349ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
350ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    /**
351ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * @return True if generation is in progress
352ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     */
353ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    public boolean isInProgress() {
354ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        return (mProgress >= 0);
355ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    }
356ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
357ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    /**
358ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * A view enters or exits the trimming mode
359ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     *
360ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * @param trimmingView The view which is being trimmed
361ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * @param trimming true if trimming
362ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     */
363ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    public void setTrimMode(View trimmingView, boolean trimming) {
364ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        mIsTrimming = trimming;
365ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
366ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        if (trimmingView == this) {
367ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            // Redraw the control to hide the "Add transition" areas
368ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            invalidate();
369ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        }
370ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    }
371ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
372ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    /**
373ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * A view enters or exits the playback mode
374ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     *
375ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * @param playback true if playback is in progress
376ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     */
377ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    public void setPlaybackMode(boolean playback) {
378ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        mIsPlaying = playback;
379ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    }
380ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
381ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    /**
382ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * Set the bitmaps
383ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     *
384ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * @param bitmaps The array of bitmaps
385ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * @param startMs The start time
386ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * @param endMs The end time
387ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     *
388ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * @return true if the bitmap array is used
389ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     */
390ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    public boolean setBitmaps(Bitmap[] bitmaps, long startMs, long endMs) {
391ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        if (mProgress >= 0) {
392ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            if (Log.isLoggable(TAG, Log.VERBOSE)) {
393ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                Log.v(TAG, "Ignore thumbnails: progress is displayed");
394ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            }
395ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
396ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            mWaitForThumbnailsAfterScroll = false;
397ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            return false;
398ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        } else if (startMs != mRequestedStartMs || endMs != mRequestedEndMs) {
399ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            // Old request
400ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            if (Log.isLoggable(TAG, Log.VERBOSE)) {
401ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                Log.v(TAG, "Ignore thumbnails: " + startMs + "ms to: " + endMs + "ms, have: " +
402ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                        mRequestedStartMs + "ms to: " + mRequestedEndMs + "ms");
403ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            }
404ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            // Do not use this set of bitmaps
405ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            return false;
406ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        }
407ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
408ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        // Release the current set of bitmaps
409ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        releaseBitmaps();
410ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
411ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        mWaitForThumbnailsAfterScroll = false;
412ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
413ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        mStartOffset = mRequestedStartOffset;
414ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        mEndOffset = mRequestedEndOffset;
415ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        if (Log.isLoggable(TAG, Log.VERBOSE)) {
416ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            final MovieMediaItem mediaItem = (MovieMediaItem)getTag();
417ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            Log.v(TAG, "Using thumbnails: " + bitmaps.length + ", from: "+ startMs +
418ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                    "ms to: " + endMs + "ms, between: " + mStartOffset + " and " + mEndOffset +
419ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                    ", thumbnail width: " + bitmaps[0].getWidth() + ", id: " + mediaItem.getId());
420ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        }
421ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
422ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        mBitmaps = bitmaps;
423ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        invalidate();
424ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
425ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        return true;
426ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    }
427ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
428ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    /*
429ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * {@inheritDoc}
430ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     */
431ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    @Override
432ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    protected void onDraw(Canvas canvas) {
433ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        super.onDraw(canvas);
434ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
435ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        if (mProgress >= 0) {
436ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            ProgressBar.getProgressBar(getContext()).draw(canvas, mProgress,
437ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                    mProgressDestRect, getPaddingLeft(), getWidth() - getPaddingRight());
438ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        } else if (mIsPlaying || mIsTrimming || mIsScrolling || mWaitForThumbnailsAfterScroll) {
43977a3d89eaf839df50c2f3b4ddb0819ed974726b6Gil Dobjanschi            drawThumbnails(canvas);
440ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        } else if (mBitmaps != null) {
441ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            final int paddingTop = getPaddingTop();
442ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            // Do not draw in the padding area
443ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            canvas.clipRect(getPaddingLeft(), paddingTop, getWidth() - getPaddingRight(),
444ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                    getHeight() - getPaddingBottom());
445ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
446ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            // Draw the bitmaps
447ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            int offsetX = mStartOffset;
448ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            for (int i = 0; i < mBitmaps.length; i++) {
449ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                canvas.drawBitmap(mBitmaps[i], offsetX, paddingTop, null);
450ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                offsetX += mBitmaps[i].getWidth();
451ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            }
452ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
453ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            if (isSelected()) {
454ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                drawAddTransitions(canvas);
455ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            }
456ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        } else { // Not scrolling
45777a3d89eaf839df50c2f3b4ddb0819ed974726b6Gil Dobjanschi            drawThumbnails(canvas);
45877a3d89eaf839df50c2f3b4ddb0819ed974726b6Gil Dobjanschi
459ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            requestThumbnails(REASON_NEED_THUMBNAILS);
460ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
461ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            if (isSelected()) {
462ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                drawAddTransitions(canvas);
463ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            }
464ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        }
465ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    }
466ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
467ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    /**
468ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * Draw while scrolling
469ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     *
470ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * @param canvas The canvas
471ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     */
47277a3d89eaf839df50c2f3b4ddb0819ed974726b6Gil Dobjanschi    private void drawThumbnails(Canvas canvas) {
473ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        int start = getLeft() + getPaddingLeft() - mScrollingX;
474ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        int end = getRight() - getPaddingRight() - mScrollingX;
475ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
476ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        if (start >= mScreenWidth || end < 0 || start == end) {
477ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            return;
478ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        }
479ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
480ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        // Clip it to the screen
481ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        if (end > mScreenWidth) {
482ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            end = mScreenWidth;
483ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        }
484ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
485ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        // Convert to local coordinates
486ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        end -= start - getPaddingLeft();
487ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        if (start < 0) {
488ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            start = -start;
48977a3d89eaf839df50c2f3b4ddb0819ed974726b6Gil Dobjanschi            final int off = start % mThumbnailWidth;
490ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            if (off > 0) {
491ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                start = start - off + getPaddingLeft();
492ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            } else {
493ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            }
494ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
495ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            if (start < getPaddingLeft()) {
496ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                start = getPaddingLeft();
497ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            }
498ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        } else {
499ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            start = getPaddingLeft();
500ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        }
501ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
502ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        final int paddingTop = getPaddingTop();
503ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        // Do not draw in the padding area
504ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        canvas.clipRect(getPaddingLeft(), paddingTop, getWidth() - getPaddingRight(),
505ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                getHeight() - getPaddingBottom());
50677a3d89eaf839df50c2f3b4ddb0819ed974726b6Gil Dobjanschi
50777a3d89eaf839df50c2f3b4ddb0819ed974726b6Gil Dobjanschi        if (mBitmaps == null || mBitmaps.length == 0) {
50877a3d89eaf839df50c2f3b4ddb0819ed974726b6Gil Dobjanschi            while (start < end) {
50977a3d89eaf839df50c2f3b4ddb0819ed974726b6Gil Dobjanschi                // Draw a frame placeholder
51077a3d89eaf839df50c2f3b4ddb0819ed974726b6Gil Dobjanschi                mEmptyFrameDrawable.setBounds(start, paddingTop,
51177a3d89eaf839df50c2f3b4ddb0819ed974726b6Gil Dobjanschi                        start + mThumbnailWidth, paddingTop + mThumbnailHeight);
51277a3d89eaf839df50c2f3b4ddb0819ed974726b6Gil Dobjanschi                mEmptyFrameDrawable.draw(canvas);
51377a3d89eaf839df50c2f3b4ddb0819ed974726b6Gil Dobjanschi                start += mThumbnailWidth;
514ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            }
51577a3d89eaf839df50c2f3b4ddb0819ed974726b6Gil Dobjanschi        } else {
51677a3d89eaf839df50c2f3b4ddb0819ed974726b6Gil Dobjanschi            Bitmap bitmap;
51777a3d89eaf839df50c2f3b4ddb0819ed974726b6Gil Dobjanschi            while (start < end) {
51877a3d89eaf839df50c2f3b4ddb0819ed974726b6Gil Dobjanschi                if (start >= mStartOffset && start < mEndOffset) {
51977a3d89eaf839df50c2f3b4ddb0819ed974726b6Gil Dobjanschi                    bitmap = mBitmaps[Math.min((start - mStartOffset) / mThumbnailWidth,
52077a3d89eaf839df50c2f3b4ddb0819ed974726b6Gil Dobjanschi                            mBitmaps.length - 1)];
52177a3d89eaf839df50c2f3b4ddb0819ed974726b6Gil Dobjanschi                    canvas.drawBitmap(bitmap, start, paddingTop, null);
52277a3d89eaf839df50c2f3b4ddb0819ed974726b6Gil Dobjanschi                } else {
52377a3d89eaf839df50c2f3b4ddb0819ed974726b6Gil Dobjanschi                    // Draw a frame placeholder
52477a3d89eaf839df50c2f3b4ddb0819ed974726b6Gil Dobjanschi                    mEmptyFrameDrawable.setBounds(start, paddingTop,
52577a3d89eaf839df50c2f3b4ddb0819ed974726b6Gil Dobjanschi                            start + mThumbnailWidth, paddingTop + mThumbnailHeight);
52677a3d89eaf839df50c2f3b4ddb0819ed974726b6Gil Dobjanschi                    mEmptyFrameDrawable.draw(canvas);
52777a3d89eaf839df50c2f3b4ddb0819ed974726b6Gil Dobjanschi                }
528ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
52977a3d89eaf839df50c2f3b4ddb0819ed974726b6Gil Dobjanschi                start += mThumbnailWidth;
53077a3d89eaf839df50c2f3b4ddb0819ed974726b6Gil Dobjanschi            }
531ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        }
532ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
533ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        if (isSelected()) {
534ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            drawAddTransitions(canvas);
535ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        }
536ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    }
537ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
538ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    /**
539ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * Draw the "Add transition" area at the beginning and end of the media item"
540ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     *
541ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * @param canvas Draw on this canvas
542ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     */
543ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    private void drawAddTransitions(Canvas canvas) {
544ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        if (hasAddTransition()) {
545ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            final MovieMediaItem mediaItem = (MovieMediaItem)getTag();
546ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            if (mediaItem.getBeginTransition() == null) {
547ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                mAddTransitionDrawable.setState(mLeftState);
548ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                mAddTransitionDrawable.setBounds(getPaddingLeft(), getPaddingTop(),
549ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                        mAddTransitionDrawable.getIntrinsicWidth() + getPaddingLeft(),
550ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                        getPaddingTop() + mAddTransitionDrawable.getIntrinsicHeight());
551ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                mAddTransitionDrawable.draw(canvas);
552ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            }
553ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
554ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            if (mediaItem.getEndTransition() == null) {
555ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                mAddTransitionDrawable.setState(mRightState);
556ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                mAddTransitionDrawable.setBounds(
557ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                        getWidth() - getPaddingRight() -
558ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                        mAddTransitionDrawable.getIntrinsicWidth(),
559ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                        getPaddingTop(), getWidth() - getPaddingRight(),
560ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                        getPaddingTop() + mAddTransitionDrawable.getIntrinsicHeight());
561ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                mAddTransitionDrawable.draw(canvas);
562ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            }
563ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        }
564ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    }
565ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
566ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    /**
567ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * @return true if the "Add transition" areas exist
568ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     */
569ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    private boolean hasAddTransition() {
570ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        if (mIsTrimming) {
571ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            return false;
572ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        }
573ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
574ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        return (getWidth() - getPaddingLeft() - getPaddingRight() >=
575ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                2 * mAddTransitionDrawable.getIntrinsicWidth());
576ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    }
577ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
578ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    /*
579ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * {@inheritDoc}
580ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     */
581ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    @Override
582ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    public boolean onTouchEvent(MotionEvent ev) {
583ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        // Let the gesture detector inspect all events.
584ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        mGestureDetector.onTouchEvent(ev);
585ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        super.onTouchEvent(ev);
586ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
587ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        switch (ev.getAction()) {
588ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            case MotionEvent.ACTION_DOWN: {
589ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                if (isSelected() && hasAddTransition()) {
590ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                    final MovieMediaItem mediaItem = (MovieMediaItem)getTag();
591ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                    if (ev.getX() < mAddTransitionDrawable.getIntrinsicWidth() +
592ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                            getPaddingLeft()) {
593ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                        if (mediaItem.getBeginTransition() == null) {
594ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                            mLeftState = View.PRESSED_WINDOW_FOCUSED_STATE_SET;
595ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                            mRightState = View.EMPTY_STATE_SET;
596ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                        } else {
597ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                            mRightState = View.EMPTY_STATE_SET;
598ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                            mLeftState = View.EMPTY_STATE_SET;
599ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                        }
600ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                    } else if (ev.getX() >= getWidth() - getPaddingRight() -
601ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                            mAddTransitionDrawable.getIntrinsicWidth()) {
602ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                        if (mediaItem.getEndTransition() == null) {
603ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                            mRightState = View.PRESSED_WINDOW_FOCUSED_STATE_SET;
604ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                            mLeftState = View.EMPTY_STATE_SET;
605ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                        } else {
606ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                            mRightState = View.EMPTY_STATE_SET;
607ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                            mLeftState = View.EMPTY_STATE_SET;
608ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                        }
609ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                    } else {
610ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                        mRightState = View.EMPTY_STATE_SET;
611ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                        mLeftState = View.EMPTY_STATE_SET;
612ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                    }
613ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                } else {
614ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                    mRightState = View.EMPTY_STATE_SET;
615ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                    mLeftState = View.EMPTY_STATE_SET;
616ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                }
617ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
618ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                invalidate();
619ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                break;
620ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            }
621ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
622ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            case MotionEvent.ACTION_UP:
623ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            case MotionEvent.ACTION_CANCEL: {
624ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                mRightState = View.EMPTY_STATE_SET;
625ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                mLeftState = View.EMPTY_STATE_SET;
626ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
627ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                invalidate();
628ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                break;
629ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            }
630ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
631ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            default: {
632ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                break;
633ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            }
634ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        }
635ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
636ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        return true;
637ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    }
638ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
639ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    /**
640ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * Request thumbnails if necessary
641ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     *
642ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * @param reason The reason for the request
643ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     *
644ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * @return true if the bitmaps are already available
645ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     */
646ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    private boolean requestThumbnails(int reason) {
647ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        int start, end;
648ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        if (reason == REASON_PLAYBACK) {
649ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            start = getLeft() + getPaddingLeft() - mScrollingX;
650ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            end = getRight() - getPaddingRight() - mScrollingX;
651ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        } else {
652ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            start = getLeft() + getPaddingLeft() - mScrollX;
653ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            end = getRight() - getPaddingRight() - mScrollX;
654ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        }
655ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
656ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        if (start >= mScreenWidth || end < 0 || start == end) {
657ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            if (Log.isLoggable(TAG, Log.VERBOSE)) {
658ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                final MovieMediaItem mediaItem = (MovieMediaItem)getTag();
659ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                Log.v(TAG, "MediaItem view is off screen: " + mediaItem.getId() +
660ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                        " " + start + " to " + end);
661ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            }
662ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
663ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            releaseBitmapsAndClear();
664ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            return false;
665ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        }
666ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
667ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        // Clip it to the screen
668ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        if (end > mScreenWidth) {
669ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            end = mScreenWidth;
670ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        }
671ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
672ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        // Convert to local coordinates
673ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        end -= start - getPaddingLeft();
674ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        if (start < 0) {
675ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            start = -start;
676ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        } else {
677ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            start = getPaddingLeft();
678ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        }
679ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
680ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        boolean result = false;
681ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        if (start != mStart || mEnd != end) {
682ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            // Compute the thumbnail width
683ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            final MovieMediaItem mediaItem = (MovieMediaItem)getTag();
684ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            final long durationMs = mediaItem.getAppTimelineDuration();
685ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            final int viewWidth = getWidth() - getPaddingLeft() - getPaddingRight();
686ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
687ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            // Compute the start offset
688ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            final long startMs;
689ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            // Adjust the start to be a thumbnail boundary
69077a3d89eaf839df50c2f3b4ddb0819ed974726b6Gil Dobjanschi            final int off = (start % mThumbnailWidth);
691ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            int startOffset;
692ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            if (off > 0) {
693ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                startOffset = start - off + getPaddingLeft();
694ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            } else {
695ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                startOffset = start;
696ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            }
697ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            if (startOffset <= getPaddingLeft()) {
698ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                startOffset = getPaddingLeft();
699ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                startMs = mediaItem.getAppBoundaryBeginTime();
700ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            } else {
701ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                startMs = mediaItem.getAppBoundaryBeginTime()
702ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                        + ((startOffset * durationMs) / viewWidth);
703ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            }
704ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
705ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            // Compute the end offset
706ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            final long endMs;
707ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            int endOffset = end;
708ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            if (endOffset > getWidth() - getPaddingRight()) {
709ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                endOffset = getWidth() - getPaddingRight();
710ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                endMs = mediaItem.getAppBoundaryEndTime();
711ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            } else {
712ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                endMs = Math.min(mediaItem.getAppBoundaryBeginTime()
713ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                        + ((endOffset * durationMs) / viewWidth),
714ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                        mediaItem.getAppBoundaryEndTime());
715ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            }
716ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
717ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            if (startOffset < endOffset) {
718ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                // Compute the thumbnail count
71977a3d89eaf839df50c2f3b4ddb0819ed974726b6Gil Dobjanschi                final int count = ((endOffset - startOffset) / mThumbnailWidth) + 1;
72077a3d89eaf839df50c2f3b4ddb0819ed974726b6Gil Dobjanschi
721ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                if (startMs >= mRequestedStartMs && endMs <= mRequestedEndMs &&
722ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                        count <= mRequestedCount && startOffset >= mRequestedStartOffset &&
723ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                        endOffset <= mRequestedEndOffset) {
724ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
725ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                        Log.v(TAG, "Inclusive new from: " + startMs + "ms to: " + endMs +
726ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                                "ms, count: " + count + ", rendered between: " +
727ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                                    startOffset + " and " + endOffset + ", old: " +
728ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                                mRequestedStartMs + "ms to " + mRequestedEndMs +
729ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                                "ms, count: " + mRequestedCount + ", rendered between: " +
730ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                                mRequestedStartOffset + " and " + mRequestedEndOffset +
731ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                                ", id: " + mediaItem.getId());
732ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                    }
733ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
734ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                    // The new interval is included in the one we already requested
735ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                    if (mBitmaps != null) {
736ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                        result = true;
737ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                    }
73877a3d89eaf839df50c2f3b4ddb0819ed974726b6Gil Dobjanschi                } else if (mIsPlaying) {
73977a3d89eaf839df50c2f3b4ddb0819ed974726b6Gil Dobjanschi                    // Do not request thumbnails during playback
740ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                } else {
741ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                    mWaitForThumbnailsAfterScroll = reason == REASON_SCROLL_END;
742ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
743ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                        Log.v(TAG, "Request thumbnails: " + count + " thumbnails from: " +
744ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                                startMs + "ms to: " + endMs + "ms, rendered between: " +
745ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                                startOffset + " and " + endOffset + ", wait for scroll: " +
746ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                                mWaitForThumbnailsAfterScroll + ", id: " + mediaItem.getId());
747ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                    }
748ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
749ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                    // Request the thumbnails
750ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                    ApiService.getMediaItemThumbnails(getContext(), mProjectPath,
75177a3d89eaf839df50c2f3b4ddb0819ed974726b6Gil Dobjanschi                            mediaItem.getId(), mThumbnailWidth, mThumbnailHeight, startMs, endMs,
752ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                            count);
753ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
754ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                    mRequestedStartMs = startMs;
755ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                    mRequestedEndMs = endMs;
756ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                    mRequestedCount = count;
757ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                    mRequestedStartOffset = startOffset;
758ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                    mRequestedEndOffset = endOffset;
759ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                }
760ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            } else {
761ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                if (Log.isLoggable(TAG, Log.VERBOSE)) {
762ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                    Log.v(TAG, "View is too small for thumbnails: " +
763ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                            startOffset + " and " + endOffset + ", view width: " + viewWidth);
764ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                }
765ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            }
766ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
767ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            mStart = start;
768ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            mEnd = end;
769ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        } else if (mBitmaps != null) {
770ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            result = true;
771ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        }
772ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
773ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        return result;
774ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    }
775ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
776ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    /**
777ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * Recycle all the bitmaps
778ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     */
779ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    private void releaseBitmaps() {
780ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        if (mBitmaps != null) {
781ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            for (int i = 0; i < mBitmaps.length; i++) {
782ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                mBitmaps[i].recycle();
783ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            }
784ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
785ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            mStartOffset = -1;
786ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            mEndOffset = -1;
787ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        }
788ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    }
789ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
790ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    /**
791ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * Recycle the bitmaps and reset the pending request. This method
792ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * invalidates any pending request by reseting the pending request
793ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * parameters.
794ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     */
795ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    private void releaseBitmapsAndClear() {
796ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        if (Log.isLoggable(TAG, Log.VERBOSE)) {
797ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            final MovieMediaItem mediaItem = (MovieMediaItem)getTag();
798ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            Log.v(TAG, "releaseBitmapsAndClear: " + mediaItem.getId() + " " +
799ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                    mRequestedStartMs + "ms to: " +
800ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                    mRequestedEndMs + "ms, between: " + mStartOffset + " and " + mEndOffset);
801ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        }
802ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
803ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        // Release the current set of bitmaps
804ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        if (mBitmaps != null) {
805ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            for (int i = 0; i < mBitmaps.length; i++) {
806ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                mBitmaps[i].recycle();
807ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            }
808ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
809ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            mBitmaps = null;
810ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
811ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            mStartOffset = -1;
812ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            mEndOffset = -1;
813ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        }
814ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
815ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        mRequestedStartMs = -1;
816ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        mRequestedEndMs = -1;
817ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        mRequestedCount = 0;
818ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        mRequestedStartOffset = -1;
819ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        mRequestedEndOffset = -1;
820ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
821ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        mStart = 0;
822ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        mEnd = 0;
823ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
824ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        mWaitForThumbnailsAfterScroll = false;
825ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    }
826ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi}
827