1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.videoeditor.widgets;
18
19import com.android.videoeditor.service.VideoEditorProject;
20import com.android.videoeditor.util.StringUtils;
21import com.android.videoeditor.R;
22
23import android.content.Context;
24import android.content.res.Resources;
25import android.graphics.Canvas;
26import android.graphics.Paint;
27import android.util.AttributeSet;
28import android.util.DisplayMetrics;
29import android.view.Display;
30import android.view.View;
31import android.view.WindowManager;
32
33/**
34 * The view which displays the scroll position
35 */
36public class PlayheadView extends View {
37    // Instance variables
38    private final Paint mLinePaint;
39    private final Paint mTextPaint;
40    private final int mTicksHeight;
41    // Timeline text size.
42    private final float mTimeTextSize;
43    private final int mScreenWidth;
44    private final ScrollViewListener mScrollListener;
45    private int mScrollX;
46    private VideoEditorProject mProject;
47
48    public PlayheadView(Context context, AttributeSet attrs, int defStyle) {
49        super(context, attrs, defStyle);
50
51        final Resources resources = context.getResources();
52
53        // Prepare the Paint used to draw the tick marks
54        mLinePaint = new Paint();
55        mLinePaint.setColor(resources.getColor(R.color.playhead_tick_color));
56        mLinePaint.setStrokeWidth(2);
57        mLinePaint.setStyle(Paint.Style.STROKE);
58
59        // Prepare the Paint used to draw the text
60        mTextPaint = new Paint();
61        mTextPaint.setAntiAlias(true);
62        mTextPaint.setColor(resources.getColor(R.color.playhead_tick_color));
63        mTimeTextSize = resources.getDimension(R.dimen.playhead_layout_text_size);
64        mTextPaint.setTextSize(mTimeTextSize);
65
66        // The ticks height
67        mTicksHeight = (int)resources.getDimension(R.dimen.playhead_tick_height);
68
69        // Get the screen width
70        final Display display = ((WindowManager)context.getSystemService(
71                Context.WINDOW_SERVICE)).getDefaultDisplay();
72        final DisplayMetrics metrics = new DisplayMetrics();
73        display.getMetrics(metrics);
74        mScreenWidth = metrics.widthPixels;
75
76        // Listen to scroll events and repaint this view as needed
77        mScrollListener = new ScrollViewListener() {
78
79            @Override
80            public void onScrollBegin(View view, int scrollX, int scrollY, boolean appScroll) {
81            }
82
83            @Override
84            public void onScrollProgress(View view, int scrollX, int scrollY, boolean appScroll) {
85                mScrollX = scrollX;
86                invalidate();
87            }
88
89            @Override
90            public void onScrollEnd(View view, int scrollX, int scrollY, boolean appScroll) {
91                mScrollX = scrollX;
92                invalidate();
93            }
94        };
95    }
96
97    public PlayheadView(Context context, AttributeSet attrs) {
98        this(context, attrs, 0);
99    }
100
101    public PlayheadView(Context context) {
102        this(context, null, 0);
103    }
104
105    @Override
106    protected void onAttachedToWindow() {
107        final TimelineHorizontalScrollView scrollView =
108            (TimelineHorizontalScrollView)((View)getParent()).getParent();
109        mScrollX = scrollView.getScrollX();
110        scrollView.addScrollListener(mScrollListener);
111    }
112
113    @Override
114    protected void onDetachedFromWindow() {
115        final TimelineHorizontalScrollView scrollView =
116            (TimelineHorizontalScrollView)((View)getParent()).getParent();
117        scrollView.removeScrollListener(mScrollListener);
118    }
119
120    /**
121     * @param project The project
122     */
123    public void setProject(VideoEditorProject project) {
124        mProject = project;
125    }
126
127    @Override
128    protected void onDraw(Canvas canvas) {
129        super.onDraw(canvas);
130
131        if (mProject == null) {
132            return;
133        }
134
135        final long durationMs = mProject.computeDuration();
136        final long durationSec = durationMs / 1000;
137        final int y = (int) -mTextPaint.getFontMetrics().top;
138        // We only draw the origin when there is nothing on the timeline.
139        if (durationMs == 0 || durationSec == 0) {
140            final String timeText = StringUtils.getSimpleTimestampAsString(getContext(), 0);
141            int x = (int) ((getWidth() - mTextPaint.measureText(timeText)) / 2);
142            canvas.drawText(timeText, x, y, mTextPaint);
143            return;
144        }
145
146        final int width = getWidth() - mScreenWidth;
147        // Compute the number of pixels per second
148        final int pixelsPerSec = (int) (width / durationSec);
149
150        // Compute the distance between ticks
151        final long tickMs;
152        if (pixelsPerSec < 4) {
153            tickMs = 240000;
154        } else if (pixelsPerSec < 6) {
155            tickMs = 120000;
156        } else if (pixelsPerSec < 10) {
157            tickMs = 60000;
158        } else if (pixelsPerSec < 50) {
159            tickMs = 10000;
160        } else if (pixelsPerSec < 200) {
161            tickMs = 5000;
162        } else {
163            tickMs = 1000;
164        }
165
166        final float spacing = ((float) (width * tickMs) / (float) durationMs);
167        final float startX = Math.max(mScrollX - (((mScrollX - (mScreenWidth / 2)) % spacing)),
168                mScreenWidth / 2);
169        float startMs = ((tickMs * (startX - (mScreenWidth / 2))) / spacing);
170        startMs = Math.round(startMs);
171        startMs -= (startMs % tickMs);
172
173        final Context context = getContext();
174        final float endX = mScrollX + mScreenWidth;
175        for (float i = startX; i <= endX; i += spacing, startMs += tickMs) {
176            final String timeText = StringUtils.getSimpleTimestampAsString(context, (long) startMs);
177            final int x = (int) (i - mTextPaint.measureText(timeText) / 2);
178            canvas.drawText(timeText, x, y, mTextPaint);
179            canvas.drawLine(i, 0, i, mTicksHeight, mLinePaint);
180        }
181    }
182}
183