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
1781393d6dc5767f7784a00958095614a37bf1a91aGil Dobjanschipackage com.android.videoeditor.widgets;
18ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
1981393d6dc5767f7784a00958095614a37bf1a91aGil Dobjanschiimport com.android.videoeditor.service.VideoEditorProject;
2081393d6dc5767f7784a00958095614a37bf1a91aGil Dobjanschiimport com.android.videoeditor.util.StringUtils;
2181393d6dc5767f7784a00958095614a37bf1a91aGil Dobjanschiimport com.android.videoeditor.R;
22ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
23ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport android.content.Context;
24ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport android.content.res.Resources;
25ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport android.graphics.Canvas;
26ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport android.graphics.Paint;
27ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport android.util.AttributeSet;
28ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport android.util.DisplayMetrics;
29ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport android.view.Display;
30ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport android.view.View;
31ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschiimport android.view.WindowManager;
32ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
33ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi/**
34ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi * The view which displays the scroll position
35ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi */
36ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschipublic class PlayheadView extends View {
37ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    // Instance variables
38ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    private final Paint mLinePaint;
39ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    private final Paint mTextPaint;
40ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    private final int mTicksHeight;
41b4ddbe1ea0baa8159808661ea7382be80716febeShih-chia Cheng    // Timeline text size.
42b4ddbe1ea0baa8159808661ea7382be80716febeShih-chia Cheng    private final float mTimeTextSize;
43ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    private final int mScreenWidth;
44ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    private final ScrollViewListener mScrollListener;
45ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    private int mScrollX;
46ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    private VideoEditorProject mProject;
47ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
48ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    public PlayheadView(Context context, AttributeSet attrs, int defStyle) {
49ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        super(context, attrs, defStyle);
50ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
51ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        final Resources resources = context.getResources();
52ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
53ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        // Prepare the Paint used to draw the tick marks
54ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        mLinePaint = new Paint();
55ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        mLinePaint.setColor(resources.getColor(R.color.playhead_tick_color));
56ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        mLinePaint.setStrokeWidth(2);
57ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        mLinePaint.setStyle(Paint.Style.STROKE);
58ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
59ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        // Prepare the Paint used to draw the text
60ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        mTextPaint = new Paint();
61ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        mTextPaint.setAntiAlias(true);
62ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        mTextPaint.setColor(resources.getColor(R.color.playhead_tick_color));
63b4ddbe1ea0baa8159808661ea7382be80716febeShih-chia Cheng        mTimeTextSize = resources.getDimension(R.dimen.playhead_layout_text_size);
64b4ddbe1ea0baa8159808661ea7382be80716febeShih-chia Cheng        mTextPaint.setTextSize(mTimeTextSize);
65ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
66ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        // The ticks height
67ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        mTicksHeight = (int)resources.getDimension(R.dimen.playhead_tick_height);
68ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
69ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        // Get the screen width
70ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        final Display display = ((WindowManager)context.getSystemService(
71ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                Context.WINDOW_SERVICE)).getDefaultDisplay();
72ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        final DisplayMetrics metrics = new DisplayMetrics();
73ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        display.getMetrics(metrics);
74ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        mScreenWidth = metrics.widthPixels;
75ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
76ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        // Listen to scroll events and repaint this view as needed
77ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        mScrollListener = new ScrollViewListener() {
78b4ddbe1ea0baa8159808661ea7382be80716febeShih-chia Cheng
79b4ddbe1ea0baa8159808661ea7382be80716febeShih-chia Cheng            @Override
80ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            public void onScrollBegin(View view, int scrollX, int scrollY, boolean appScroll) {
81ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            }
82ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
83b4ddbe1ea0baa8159808661ea7382be80716febeShih-chia Cheng            @Override
84ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            public void onScrollProgress(View view, int scrollX, int scrollY, boolean appScroll) {
85ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                mScrollX = scrollX;
86687e4b49e5c9cbfe17e9a147072d7a6f7d9e5caeGil Dobjanschi                invalidate();
87ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            }
88ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
89b4ddbe1ea0baa8159808661ea7382be80716febeShih-chia Cheng            @Override
90ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            public void onScrollEnd(View view, int scrollX, int scrollY, boolean appScroll) {
91ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                mScrollX = scrollX;
92ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                invalidate();
93ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            }
94ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        };
95ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    }
96ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
97ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    public PlayheadView(Context context, AttributeSet attrs) {
98ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        this(context, attrs, 0);
99ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    }
100ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
101ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    public PlayheadView(Context context) {
102ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        this(context, null, 0);
103ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    }
104ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
105ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    @Override
106ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    protected void onAttachedToWindow() {
107ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        final TimelineHorizontalScrollView scrollView =
108ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            (TimelineHorizontalScrollView)((View)getParent()).getParent();
109ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        mScrollX = scrollView.getScrollX();
110ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        scrollView.addScrollListener(mScrollListener);
111ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    }
112ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
113ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    @Override
114ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    protected void onDetachedFromWindow() {
115ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        final TimelineHorizontalScrollView scrollView =
116ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            (TimelineHorizontalScrollView)((View)getParent()).getParent();
117ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        scrollView.removeScrollListener(mScrollListener);
118ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    }
119ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
120ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    /**
121ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     * @param project The project
122ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi     */
123ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    public void setProject(VideoEditorProject project) {
124ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        mProject = project;
125ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    }
126ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
127ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    @Override
128ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    protected void onDraw(Canvas canvas) {
129ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        super.onDraw(canvas);
130ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
131ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        if (mProject == null) {
132ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            return;
133ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        }
134ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
135ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        final long durationMs = mProject.computeDuration();
136ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        final long durationSec = durationMs / 1000;
137b4ddbe1ea0baa8159808661ea7382be80716febeShih-chia Cheng        final int y = (int) -mTextPaint.getFontMetrics().top;
138b4ddbe1ea0baa8159808661ea7382be80716febeShih-chia Cheng        // We only draw the origin when there is nothing on the timeline.
139ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        if (durationMs == 0 || durationSec == 0) {
140ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            final String timeText = StringUtils.getSimpleTimestampAsString(getContext(), 0);
141b4ddbe1ea0baa8159808661ea7382be80716febeShih-chia Cheng            int x = (int) ((getWidth() - mTextPaint.measureText(timeText)) / 2);
142b4ddbe1ea0baa8159808661ea7382be80716febeShih-chia Cheng            canvas.drawText(timeText, x, y, mTextPaint);
143ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            return;
144ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        }
145ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
146ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        final int width = getWidth() - mScreenWidth;
147ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        // Compute the number of pixels per second
148b4ddbe1ea0baa8159808661ea7382be80716febeShih-chia Cheng        final int pixelsPerSec = (int) (width / durationSec);
149ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
150ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        // Compute the distance between ticks
151ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        final long tickMs;
152ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        if (pixelsPerSec < 4) {
153ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            tickMs = 240000;
154ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        } else if (pixelsPerSec < 6) {
155ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            tickMs = 120000;
156ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        } else if (pixelsPerSec < 10) {
157ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            tickMs = 60000;
158ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        } else if (pixelsPerSec < 50) {
159ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            tickMs = 10000;
160ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        } else if (pixelsPerSec < 200) {
161ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            tickMs = 5000;
162ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        } else {
163ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            tickMs = 1000;
164ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        }
165ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi
166b4ddbe1ea0baa8159808661ea7382be80716febeShih-chia Cheng        final float spacing = ((float) (width * tickMs) / (float) durationMs);
167ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        final float startX = Math.max(mScrollX - (((mScrollX - (mScreenWidth / 2)) % spacing)),
168ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi                mScreenWidth / 2);
169ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        float startMs = ((tickMs * (startX - (mScreenWidth / 2))) / spacing);
170ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        startMs = Math.round(startMs);
171ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        startMs -= (startMs % tickMs);
172e5aa502ef6ae9572353325df9092da0faa00746bGil Dobjanschi
173e5aa502ef6ae9572353325df9092da0faa00746bGil Dobjanschi        final Context context = getContext();
174b4ddbe1ea0baa8159808661ea7382be80716febeShih-chia Cheng        final float endX = mScrollX + mScreenWidth;
175ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        for (float i = startX; i <= endX; i += spacing, startMs += tickMs) {
176b4ddbe1ea0baa8159808661ea7382be80716febeShih-chia Cheng            final String timeText = StringUtils.getSimpleTimestampAsString(context, (long) startMs);
177b4ddbe1ea0baa8159808661ea7382be80716febeShih-chia Cheng            final int x = (int) (i - mTextPaint.measureText(timeText) / 2);
178b4ddbe1ea0baa8159808661ea7382be80716febeShih-chia Cheng            canvas.drawText(timeText, x, y, mTextPaint);
179ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi            canvas.drawLine(i, 0, i, mTicksHeight, mLinePaint);
180ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi        }
181ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi    }
182ace3cdb462fef9563a0470223c62a7e80e6d587aGil Dobjanschi}
183