ChartSweepView.java revision ab2d8d3a38857b8c155e6c6393c5821f5a341aae
1ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey/* 2ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey * Copyright (C) 2011 The Android Open Source Project 3ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey * 4ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License"); 5ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey * you may not use this file except in compliance with the License. 6ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey * You may obtain a copy of the License at 7ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey * 8ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey * http://www.apache.org/licenses/LICENSE-2.0 9ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey * 10ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey * Unless required by applicable law or agreed to in writing, software 11ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS, 12ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey * See the License for the specific language governing permissions and 14ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey * limitations under the License. 15ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey */ 16ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey 17ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkeypackage com.android.settings.widget; 18ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey 19ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkeyimport android.content.Context; 20ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkeyimport android.graphics.Canvas; 21ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkeyimport android.graphics.Color; 22ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkeyimport android.graphics.Paint; 23ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkeyimport android.graphics.Paint.Style; 24ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkeyimport android.view.MotionEvent; 25ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkeyimport android.view.View; 26ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey 27ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkeyimport com.google.common.base.Preconditions; 28ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey 29ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey/** 30ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey * Sweep across a {@link ChartView} at a specific {@link ChartAxis} value, which 31ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey * a user can drag. 32ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey */ 33ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkeypublic class ChartSweepView extends View { 34ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey 35ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey private final Paint mPaintSweep; 36ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey private final Paint mPaintShadow; 37ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey 38ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey private final ChartAxis mAxis; 39ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey private long mValue; 40ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey 41ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey public interface OnSweepListener { 42ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey public void onSweep(ChartSweepView sweep, boolean sweepDone); 43ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey } 44ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey 45ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey private OnSweepListener mListener; 46ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey 47ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey private boolean mHorizontal; 48ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey private MotionEvent mTracking; 49ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey 50ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey public ChartSweepView(Context context, ChartAxis axis, long value, int color) { 51ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey super(context); 52ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey 53ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey mAxis = Preconditions.checkNotNull(axis, "missing axis"); 54ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey mValue = value; 55ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey 56ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey mPaintSweep = new Paint(); 57ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey mPaintSweep.setColor(color); 58ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey mPaintSweep.setStrokeWidth(3.0f); 59ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey mPaintSweep.setStyle(Style.FILL_AND_STROKE); 60ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey mPaintSweep.setAntiAlias(true); 61ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey 62ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey mPaintShadow = new Paint(); 63ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey mPaintShadow.setColor(Color.BLACK); 64ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey mPaintShadow.setStrokeWidth(6.0f); 65ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey mPaintShadow.setStyle(Style.FILL_AND_STROKE); 66ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey mPaintShadow.setAntiAlias(true); 67ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey 68ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey } 69ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey 70ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey public void addOnSweepListener(OnSweepListener listener) { 71ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey mListener = listener; 72ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey } 73ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey 74ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey private void dispatchOnSweep(boolean sweepDone) { 75ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey if (mListener != null) { 76ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey mListener.onSweep(this, sweepDone); 77ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey } 78ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey } 79ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey 80ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey public ChartAxis getAxis() { 81ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey return mAxis; 82ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey } 83ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey 84ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey public long getValue() { 85ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey return mValue; 86ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey } 87ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey 88ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey public float getPoint() { 89ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey return mAxis.convertToPoint(mValue); 90ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey } 91ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey 92ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey @Override 93ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey public boolean onTouchEvent(MotionEvent event) { 94ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey final View parent = (View) getParent(); 95ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey switch (event.getAction()) { 96ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey case MotionEvent.ACTION_DOWN: { 97ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey mTracking = event.copy(); 98ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey return true; 99ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey } 100ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey case MotionEvent.ACTION_MOVE: { 101ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey if (mHorizontal) { 102ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey setTranslationY(event.getRawY() - mTracking.getRawY()); 103ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey final float point = (getTop() + getTranslationY() + (getHeight() / 2)) 104ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey - parent.getPaddingTop(); 105ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey mValue = mAxis.convertToValue(point); 106ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey dispatchOnSweep(false); 107ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey } else { 108ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey setTranslationX(event.getRawX() - mTracking.getRawX()); 109ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey final float point = (getLeft() + getTranslationX() + (getWidth() / 2)) 110ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey - parent.getPaddingLeft(); 111ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey mValue = mAxis.convertToValue(point); 112ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey dispatchOnSweep(false); 113ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey } 114ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey return true; 115ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey } 116ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey case MotionEvent.ACTION_UP: { 117ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey mTracking = null; 118ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey setTranslationX(0); 119ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey setTranslationY(0); 120ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey requestLayout(); 121ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey dispatchOnSweep(true); 122ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey return true; 123ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey } 124ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey default: { 125ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey return false; 126ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey } 127ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey } 128ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey } 129ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey 130ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey @Override 131ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 132ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey // need at least 50px in each direction for grippies 133ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey // TODO: provide this value through params 134ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey setMeasuredDimension(50, 50); 135ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey } 136ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey 137ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey @Override 138ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey protected void onDraw(Canvas canvas) { 139ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey 140ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey // draw line across larger dimension 141ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey final int width = getWidth(); 142ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey final int height = getHeight(); 143ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey 144ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey mHorizontal = width > height; 145ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey 146ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey if (mHorizontal) { 147ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey final int centerY = height / 2; 148ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey final int endX = width - height; 149ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey 150ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey canvas.drawLine(0, centerY, endX, centerY, mPaintShadow); 151ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey canvas.drawLine(0, centerY, endX, centerY, mPaintSweep); 152ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey canvas.drawCircle(endX, centerY, 4.0f, mPaintShadow); 153ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey canvas.drawCircle(endX, centerY, 4.0f, mPaintSweep); 154ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey } else { 155ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey final int centerX = width / 2; 156ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey final int endY = height - width; 157ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey 158ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey canvas.drawLine(centerX, 0, centerX, endY, mPaintShadow); 159ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey canvas.drawLine(centerX, 0, centerX, endY, mPaintSweep); 160ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey canvas.drawCircle(centerX, endY, 4.0f, mPaintShadow); 161ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey canvas.drawCircle(centerX, endY, 4.0f, mPaintSweep); 162ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey } 163ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey } 164ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey 165ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey} 166