1209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Chang/*
2209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Chang * Copyright (C) 2011 The Android Open Source Project
3209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Chang *
4209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Chang * Licensed under the Apache License, Version 2.0 (the "License");
5209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Chang * you may not use this file except in compliance with the License.
6209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Chang * You may obtain a copy of the License at
7209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Chang *
8209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Chang *      http://www.apache.org/licenses/LICENSE-2.0
9209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Chang *
10209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Chang * Unless required by applicable law or agreed to in writing, software
11209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Chang * distributed under the License is distributed on an "AS IS" BASIS,
12209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Chang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Chang * See the License for the specific language governing permissions and
14209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Chang * limitations under the License.
15209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Chang */
16209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Chang
17209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Changpackage com.android.gallery3d.app;
18209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Chang
19209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Changimport android.content.Context;
20209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Changimport android.graphics.Bitmap;
21209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Changimport android.graphics.BitmapFactory;
22209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Changimport android.graphics.Canvas;
23209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Changimport android.graphics.Paint;
24209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Changimport android.graphics.Rect;
25209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Changimport android.util.DisplayMetrics;
26209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Changimport android.view.MotionEvent;
27209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Changimport android.view.View;
28209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Chang
292b3ee0ea07246b859a5b75d8a6102a7cce7ec838Owen Linimport com.android.gallery3d.R;
302b3ee0ea07246b859a5b75d8a6102a7cce7ec838Owen Linimport com.android.gallery3d.common.Utils;
312b3ee0ea07246b859a5b75d8a6102a7cce7ec838Owen Lin
32209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Chang/**
333f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu * The time bar view, which includes the current and total time, the progress
343f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu * bar, and the scrubber.
35209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Chang */
36209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Changpublic class TimeBar extends View {
37209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Chang
383f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    public interface Listener {
393f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        void onScrubbingStart();
40209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Chang
413f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        void onScrubbingMove(int time);
42209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Chang
433f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        void onScrubbingEnd(int time, int start, int end);
443f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    }
45209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Chang
463f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    // Padding around the scrubber to increase its touch target
473f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    private static final int SCRUBBER_PADDING_IN_DP = 10;
48209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Chang
493f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    // The total padding, top plus bottom
503f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    private static final int V_PADDING_IN_DP = 30;
51209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Chang
523f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    private static final int TEXT_SIZE_IN_DP = 14;
53209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Chang
543f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    protected final Listener mListener;
55209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Chang
563f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    // the bars we use for displaying the progress
573f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    protected final Rect mProgressBar;
583f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    protected final Rect mPlayedBar;
59209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Chang
609f59a5fa0302f80cd5bd540e864de091fb5703dfTeng-Hui Zhu    protected final Paint mProgressPaint;
619f59a5fa0302f80cd5bd540e864de091fb5703dfTeng-Hui Zhu    protected final Paint mPlayedPaint;
629f59a5fa0302f80cd5bd540e864de091fb5703dfTeng-Hui Zhu    protected final Paint mTimeTextPaint;
63209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Chang
643f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    protected final Bitmap mScrubber;
653f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    protected int mScrubberPadding; // adds some touch tolerance around the
663f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu                                    // scrubber
67209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Chang
683f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    protected int mScrubberLeft;
693f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    protected int mScrubberTop;
703f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    protected int mScrubberCorrection;
713f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    protected boolean mScrubbing;
723f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    protected boolean mShowTimes;
733f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    protected boolean mShowScrubber;
74209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Chang
753f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    protected int mTotalTime;
763f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    protected int mCurrentTime;
77209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Chang
783f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    protected final Rect mTimeBounds;
79209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Chang
803f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    protected int mVPaddingInPx;
81209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Chang
823f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    public TimeBar(Context context, Listener listener) {
833f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        super(context);
843f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mListener = Utils.checkNotNull(listener);
85209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Chang
863f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mShowTimes = true;
873f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mShowScrubber = true;
88209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Chang
893f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mProgressBar = new Rect();
903f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mPlayedBar = new Rect();
91209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Chang
923f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mProgressPaint = new Paint();
933f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mProgressPaint.setColor(0xFF808080);
943f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mPlayedPaint = new Paint();
953f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mPlayedPaint.setColor(0xFFFFFFFF);
96209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Chang
973f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        DisplayMetrics metrics = context.getResources().getDisplayMetrics();
983f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        float textSizeInPx = metrics.density * TEXT_SIZE_IN_DP;
993f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mTimeTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
1003f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mTimeTextPaint.setColor(0xFFCECECE);
1013f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mTimeTextPaint.setTextSize(textSizeInPx);
1023f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mTimeTextPaint.setTextAlign(Paint.Align.CENTER);
103209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Chang
1043f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mTimeBounds = new Rect();
1053f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mTimeTextPaint.getTextBounds("0:00:00", 0, 7, mTimeBounds);
106209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Chang
1073f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mScrubber = BitmapFactory.decodeResource(getResources(), R.drawable.scrubber_knob);
1083f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mScrubberPadding = (int) (metrics.density * SCRUBBER_PADDING_IN_DP);
109209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Chang
1103f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mVPaddingInPx = (int) (metrics.density * V_PADDING_IN_DP);
111209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Chang    }
112209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Chang
1133f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    private void update() {
1143f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mPlayedBar.set(mProgressBar);
1153f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu
1163f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        if (mTotalTime > 0) {
1173f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu            mPlayedBar.right =
1183f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu                    mPlayedBar.left + (int) ((mProgressBar.width() * (long) mCurrentTime) / mTotalTime);
1193f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        } else {
1203f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu            mPlayedBar.right = mProgressBar.left;
1213f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        }
1223f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu
1233f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        if (!mScrubbing) {
1243f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu            mScrubberLeft = mPlayedBar.right - mScrubber.getWidth() / 2;
1253f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        }
1263f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        invalidate();
127209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Chang    }
1283f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu
1293f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    /**
1303f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu     * @return the preferred height of this view, including invisible padding
1313f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu     */
1323f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    public int getPreferredHeight() {
1333f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        return mTimeBounds.height() + mVPaddingInPx + mScrubberPadding;
134209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Chang    }
1353f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu
1363f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    /**
1373f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu     * @return the height of the time bar, excluding invisible padding
1383f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu     */
1393f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    public int getBarHeight() {
1403f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        return mTimeBounds.height() + mVPaddingInPx;
141209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Chang    }
1423f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu
1433f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    public void setTime(int currentTime, int totalTime,
1443f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu            int trimStartTime, int trimEndTime) {
1453f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        if (mCurrentTime == currentTime && mTotalTime == totalTime) {
1463f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu            return;
1473f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        }
1483f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mCurrentTime = currentTime;
1493f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mTotalTime = totalTime;
1503f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        update();
151209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Chang    }
152209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Chang
1533f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    private boolean inScrubber(float x, float y) {
1543f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        int scrubberRight = mScrubberLeft + mScrubber.getWidth();
1553f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        int scrubberBottom = mScrubberTop + mScrubber.getHeight();
1563f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        return mScrubberLeft - mScrubberPadding < x && x < scrubberRight + mScrubberPadding
1573f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu                && mScrubberTop - mScrubberPadding < y && y < scrubberBottom + mScrubberPadding;
1583f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    }
159209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Chang
1609f59a5fa0302f80cd5bd540e864de091fb5703dfTeng-Hui Zhu    private void clampScrubber() {
1613f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        int half = mScrubber.getWidth() / 2;
1623f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        int max = mProgressBar.right - half;
1633f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        int min = mProgressBar.left - half;
1643f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        mScrubberLeft = Math.min(max, Math.max(min, mScrubberLeft));
1653f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    }
166209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Chang
1679f59a5fa0302f80cd5bd540e864de091fb5703dfTeng-Hui Zhu    private int getScrubberTime() {
1683f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        return (int) ((long) (mScrubberLeft + mScrubber.getWidth() / 2 - mProgressBar.left)
1693f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu                * mTotalTime / mProgressBar.width());
170209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Chang    }
1713f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu
1723f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    @Override
1733f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    protected void onLayout(boolean changed, int l, int t, int r, int b) {
1743f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        int w = r - l;
1753f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        int h = b - t;
1763f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        if (!mShowTimes && !mShowScrubber) {
1773f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu            mProgressBar.set(0, 0, w, h);
1783f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        } else {
1793f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu            int margin = mScrubber.getWidth() / 3;
1803f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu            if (mShowTimes) {
1813f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu                margin += mTimeBounds.width();
1823f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu            }
1833f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu            int progressY = (h + mScrubberPadding) / 2;
1843f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu            mScrubberTop = progressY - mScrubber.getHeight() / 2 + 1;
1853f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu            mProgressBar.set(
1863f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu                    getPaddingLeft() + margin, progressY,
1873f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu                    w - getPaddingRight() - margin, progressY + 4);
1883f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        }
1893f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        update();
190209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Chang    }
1913f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu
1923f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    @Override
1933f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    protected void onDraw(Canvas canvas) {
1943f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        // draw progress bars
1953f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        canvas.drawRect(mProgressBar, mProgressPaint);
1963f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        canvas.drawRect(mPlayedBar, mPlayedPaint);
1973f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu
1983f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        // draw scrubber and timers
1993f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        if (mShowScrubber) {
2003f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu            canvas.drawBitmap(mScrubber, mScrubberLeft, mScrubberTop, null);
201bcca048557ff3637b7d1cce2893cfc095111ebddOwen Lin        }
2023f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        if (mShowTimes) {
2033f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu            canvas.drawText(
2043f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu                    stringForTime(mCurrentTime),
2053f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu                            mTimeBounds.width() / 2 + getPaddingLeft(),
2063f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu                            mTimeBounds.height() + mVPaddingInPx / 2 + mScrubberPadding + 1,
2073f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu                    mTimeTextPaint);
2083f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu            canvas.drawText(
2093f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu                    stringForTime(mTotalTime),
2103f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu                            getWidth() - getPaddingRight() - mTimeBounds.width() / 2,
2113f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu                            mTimeBounds.height() + mVPaddingInPx / 2 + mScrubberPadding + 1,
2123f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu                    mTimeTextPaint);
213bcca048557ff3637b7d1cce2893cfc095111ebddOwen Lin        }
2143f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    }
2153f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu
2163f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    @Override
2173f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    public boolean onTouchEvent(MotionEvent event) {
2183f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        if (mShowScrubber) {
2193f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu            int x = (int) event.getX();
2203f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu            int y = (int) event.getY();
2213f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu
2223f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu            switch (event.getAction()) {
2233f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu                case MotionEvent.ACTION_DOWN: {
2243f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu                    mScrubberCorrection = inScrubber(x, y)
2253f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu                            ? x - mScrubberLeft
2263f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu                            : mScrubber.getWidth() / 2;
2273f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu                    mScrubbing = true;
2283f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu                    mListener.onScrubbingStart();
2293f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu                }
2303f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu                // fall-through
2313f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu                case MotionEvent.ACTION_MOVE: {
2323f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu                    mScrubberLeft = x - mScrubberCorrection;
2333f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu                    clampScrubber();
2343f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu                    mCurrentTime = getScrubberTime();
2353f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu                    mListener.onScrubbingMove(mCurrentTime);
2363f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu                    invalidate();
2373f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu                    return true;
2383f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu                }
2393f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu                case MotionEvent.ACTION_CANCEL:
2403f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu                case MotionEvent.ACTION_UP: {
2413f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu                    mListener.onScrubbingEnd(getScrubberTime(), 0, 0);
2423f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu                    mScrubbing = false;
2433f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu                    return true;
2443f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu                }
2453f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu            }
246bcca048557ff3637b7d1cce2893cfc095111ebddOwen Lin        }
2473f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        return false;
248209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Chang    }
2493f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu
2503f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu    protected String stringForTime(long millis) {
2513f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        int totalSeconds = (int) millis / 1000;
2523f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        int seconds = totalSeconds % 60;
2533f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        int minutes = (totalSeconds / 60) % 60;
2543f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        int hours = totalSeconds / 3600;
2553f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        if (hours > 0) {
2563f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu            return String.format("%d:%02d:%02d", hours, minutes, seconds).toString();
2573f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        } else {
2583f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu            return String.format("%02d:%02d", minutes, seconds).toString();
2593f1f1baf3a674927e25cd5cd885fb372796bd3a0Teng-Hui Zhu        }
260209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Chang    }
261209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Chang
262e8b4b34cb77b179f397641e2f4572e4aa6be1943ztenghui    public void setSeekable(boolean canSeek) {
263e8b4b34cb77b179f397641e2f4572e4aa6be1943ztenghui        mShowScrubber = canSeek;
264e8b4b34cb77b179f397641e2f4572e4aa6be1943ztenghui    }
265e8b4b34cb77b179f397641e2f4572e4aa6be1943ztenghui
266209a9163d4e8cee0bfe162ae598ef40e6051479cChih-Chung Chang}
267