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