1597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei/* 2597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei * Copyright (C) 2017 The Android Open Source Project 3597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei * 4597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei * Licensed under the Apache License, Version 2.0 (the "License"); 5597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei * you may not use this file except in compliance with the License. 6597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei * You may obtain a copy of the License at 7597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei * 8597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei * http://www.apache.org/licenses/LICENSE-2.0 9597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei * 10597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei * Unless required by applicable law or agreed to in writing, software 11597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei * distributed under the License is distributed on an "AS IS" BASIS, 12597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei * See the License for the specific language governing permissions and 14597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei * limitations under the License. 15597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei */ 16597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei 17597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyuleipackage com.android.settingslib.graph; 18597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei 19597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyuleiimport android.annotation.Nullable; 20597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyuleiimport android.content.Context; 21597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyuleiimport android.content.res.Resources; 22597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyuleiimport android.content.res.TypedArray; 23597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyuleiimport android.graphics.Canvas; 24597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyuleiimport android.graphics.Color; 25597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyuleiimport android.graphics.ColorFilter; 26597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyuleiimport android.graphics.Paint; 27d783c8af01098a36a36bfa4f8c5fed370cfb3654Evan Lairdimport android.graphics.Paint.Style; 28597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyuleiimport android.graphics.Path; 296a600b8f628ddfbcaddc8dc281684b8edf294005Jason Monkimport android.graphics.Path.Direction; 306a600b8f628ddfbcaddc8dc281684b8edf294005Jason Monkimport android.graphics.Path.FillType; 31d783c8af01098a36a36bfa4f8c5fed370cfb3654Evan Lairdimport android.graphics.Path.Op; 326f4179c3b8788456095ec79fd35e7c1a3d0589a0Evan Lairdimport android.graphics.Rect; 33597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyuleiimport android.graphics.RectF; 34597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyuleiimport android.graphics.Typeface; 35597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyuleiimport android.graphics.drawable.Drawable; 3658be7a675b7aa505255f0c91fee755f8290e8363Jason Monkimport android.util.TypedValue; 3758be7a675b7aa505255f0c91fee755f8290e8363Jason Monk 38597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyuleiimport com.android.settingslib.R; 39597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyuleiimport com.android.settingslib.Utils; 40597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei 41597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyuleipublic class BatteryMeterDrawableBase extends Drawable { 42597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei 436a600b8f628ddfbcaddc8dc281684b8edf294005Jason Monk private static final float ASPECT_RATIO = .58f; 44597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei public static final String TAG = BatteryMeterDrawableBase.class.getSimpleName(); 45706d9684afb4d46541521d290aa99c08531a5f4cEvan Laird private static final float RADIUS_RATIO = 1.0f / 17f; 46597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei 47597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei protected final Context mContext; 48ff5bd948b0b5fc2122b4fe9dafe5245a2c05694cjackqdyulei protected final Paint mFramePaint; 49ff5bd948b0b5fc2122b4fe9dafe5245a2c05694cjackqdyulei protected final Paint mBatteryPaint; 50ff5bd948b0b5fc2122b4fe9dafe5245a2c05694cjackqdyulei protected final Paint mWarningTextPaint; 51ff5bd948b0b5fc2122b4fe9dafe5245a2c05694cjackqdyulei protected final Paint mTextPaint; 52ff5bd948b0b5fc2122b4fe9dafe5245a2c05694cjackqdyulei protected final Paint mBoltPaint; 53ff5bd948b0b5fc2122b4fe9dafe5245a2c05694cjackqdyulei protected final Paint mPlusPaint; 54d783c8af01098a36a36bfa4f8c5fed370cfb3654Evan Laird protected final Paint mPowersavePaint; 55d94a9388e81a395f74a91dfa2997c35d7c6df574jackqdyulei protected float mButtonHeightFraction; 56597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei 576aa6e6e640ddaea3272144aee68762dd17674773Dan Sandler private int mLevel = -1; 58ff5bd948b0b5fc2122b4fe9dafe5245a2c05694cjackqdyulei private boolean mCharging; 596aa6e6e640ddaea3272144aee68762dd17674773Dan Sandler private boolean mPowerSaveEnabled; 6081905164906b49ac4c5d84761088e9164fd9877cEvan Laird protected boolean mPowerSaveAsColorError = true; 616aa6e6e640ddaea3272144aee68762dd17674773Dan Sandler private boolean mShowPercent; 62597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei 63597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei private static final boolean SINGLE_DIGIT_PERCENT = false; 64597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei 65597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei private static final int FULL = 96; 66597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei 67597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei private static final float BOLT_LEVEL_THRESHOLD = 0.3f; // opaque bolt below this fraction 68597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei 69597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei private final int[] mColors; 70597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei private final int mIntrinsicWidth; 71597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei private final int mIntrinsicHeight; 72597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei 73597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei private float mSubpixelSmoothingLeft; 74597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei private float mSubpixelSmoothingRight; 75597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei private float mTextHeight, mWarningTextHeight; 76597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei private int mIconTint = Color.WHITE; 77d866b8aa0341e960399c425b021b4a6aedfa5b9eJason Monk private float mOldDarkIntensity = -1f; 78597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei 79597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei private int mHeight; 80597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei private int mWidth; 81597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei private String mWarningString; 82597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei private final int mCriticalLevel; 83597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei private int mChargeColor; 84597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei private final float[] mBoltPoints; 85597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei private final Path mBoltPath = new Path(); 86597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei private final float[] mPlusPoints; 87597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei private final Path mPlusPath = new Path(); 88597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei 896f4179c3b8788456095ec79fd35e7c1a3d0589a0Evan Laird private final Rect mPadding = new Rect(); 90597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei private final RectF mFrame = new RectF(); 91597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei private final RectF mButtonFrame = new RectF(); 92597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei private final RectF mBoltFrame = new RectF(); 93597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei private final RectF mPlusFrame = new RectF(); 94597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei 95597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei private final Path mShapePath = new Path(); 96d783c8af01098a36a36bfa4f8c5fed370cfb3654Evan Laird private final Path mOutlinePath = new Path(); 97597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei private final Path mTextPath = new Path(); 98597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei 99597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei public BatteryMeterDrawableBase(Context context, int frameColor) { 100597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mContext = context; 101597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei final Resources res = context.getResources(); 102597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei TypedArray levels = res.obtainTypedArray(R.array.batterymeter_color_levels); 103597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei TypedArray colors = res.obtainTypedArray(R.array.batterymeter_color_values); 104597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei 105597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei final int N = levels.length(); 106597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mColors = new int[2 * N]; 107af68d729738a028da585ddf0f82128fee7587d79jackqdyulei for (int i = 0; i < N; i++) { 108597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mColors[2 * i] = levels.getInt(i, 0); 10958be7a675b7aa505255f0c91fee755f8290e8363Jason Monk if (colors.getType(i) == TypedValue.TYPE_ATTRIBUTE) { 1107c8564e6adb259ddf8c5626c8f59079e2e32cb79Jason Monk mColors[2 * i + 1] = Utils.getColorAttr(context, colors.getThemeAttributeId(i, 0)); 11158be7a675b7aa505255f0c91fee755f8290e8363Jason Monk } else { 11258be7a675b7aa505255f0c91fee755f8290e8363Jason Monk mColors[2 * i + 1] = colors.getColor(i, 0); 11358be7a675b7aa505255f0c91fee755f8290e8363Jason Monk } 114597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei } 115597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei levels.recycle(); 116597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei colors.recycle(); 1176aa6e6e640ddaea3272144aee68762dd17674773Dan Sandler 118597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mWarningString = context.getString(R.string.battery_meter_very_low_overlay_symbol); 119597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mCriticalLevel = mContext.getResources().getInteger( 120597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei com.android.internal.R.integer.config_criticalBatteryWarningLevel); 121597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mButtonHeightFraction = context.getResources().getFraction( 122597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei R.fraction.battery_button_height_fraction, 1, 1); 123597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mSubpixelSmoothingLeft = context.getResources().getFraction( 124597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei R.fraction.battery_subpixel_smoothing_left, 1, 1); 125597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mSubpixelSmoothingRight = context.getResources().getFraction( 126597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei R.fraction.battery_subpixel_smoothing_right, 1, 1); 127597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei 128597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mFramePaint = new Paint(Paint.ANTI_ALIAS_FLAG); 129597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mFramePaint.setColor(frameColor); 130597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mFramePaint.setDither(true); 131597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mFramePaint.setStrokeWidth(0); 132597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mFramePaint.setStyle(Paint.Style.FILL_AND_STROKE); 133597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei 134597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mBatteryPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 135597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mBatteryPaint.setDither(true); 136597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mBatteryPaint.setStrokeWidth(0); 137597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mBatteryPaint.setStyle(Paint.Style.FILL_AND_STROKE); 138597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei 139597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 140597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei Typeface font = Typeface.create("sans-serif-condensed", Typeface.BOLD); 141597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mTextPaint.setTypeface(font); 142597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mTextPaint.setTextAlign(Paint.Align.CENTER); 143597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei 144597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mWarningTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 145597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei font = Typeface.create("sans-serif", Typeface.BOLD); 146597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mWarningTextPaint.setTypeface(font); 147597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mWarningTextPaint.setTextAlign(Paint.Align.CENTER); 148597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei if (mColors.length > 1) { 149597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mWarningTextPaint.setColor(mColors[1]); 150597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei } 151597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei 1528af93cb2403372eaee0e705aec409d09227cb5edDaniel Nishi mChargeColor = Utils.getDefaultColor(mContext, R.color.meter_consumed_color); 153597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei 154597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mBoltPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 155597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mBoltPaint.setColor(Utils.getDefaultColor(mContext, R.color.batterymeter_bolt_color)); 1566aa6e6e640ddaea3272144aee68762dd17674773Dan Sandler mBoltPoints = loadPoints(res, R.array.batterymeter_bolt_points); 157597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei 1589eb4610db728a051b6725d7efb76790e9e1f3520Evan Laird mPlusPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 1599eb4610db728a051b6725d7efb76790e9e1f3520Evan Laird mPlusPaint.setColor(Utils.getDefaultColor(mContext, R.color.batterymeter_plus_color)); 1606aa6e6e640ddaea3272144aee68762dd17674773Dan Sandler mPlusPoints = loadPoints(res, R.array.batterymeter_plus_points); 161597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei 162d783c8af01098a36a36bfa4f8c5fed370cfb3654Evan Laird mPowersavePaint = new Paint(Paint.ANTI_ALIAS_FLAG); 163d783c8af01098a36a36bfa4f8c5fed370cfb3654Evan Laird mPowersavePaint.setColor(mPlusPaint.getColor()); 164d783c8af01098a36a36bfa4f8c5fed370cfb3654Evan Laird mPowersavePaint.setStyle(Style.STROKE); 165d783c8af01098a36a36bfa4f8c5fed370cfb3654Evan Laird mPowersavePaint.setStrokeWidth(context.getResources() 166d783c8af01098a36a36bfa4f8c5fed370cfb3654Evan Laird .getDimensionPixelSize(R.dimen.battery_powersave_outline_thickness)); 167d783c8af01098a36a36bfa4f8c5fed370cfb3654Evan Laird 168597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mIntrinsicWidth = context.getResources().getDimensionPixelSize(R.dimen.battery_width); 169597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mIntrinsicHeight = context.getResources().getDimensionPixelSize(R.dimen.battery_height); 170597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei } 171597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei 172597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei @Override 173597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei public int getIntrinsicHeight() { 174597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei return mIntrinsicHeight; 175597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei } 176597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei 177597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei @Override 178597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei public int getIntrinsicWidth() { 179597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei return mIntrinsicWidth; 180597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei } 181597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei 1826aa6e6e640ddaea3272144aee68762dd17674773Dan Sandler public void setShowPercent(boolean show) { 1836aa6e6e640ddaea3272144aee68762dd17674773Dan Sandler mShowPercent = show; 184597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei postInvalidate(); 185597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei } 186597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei 187ff5bd948b0b5fc2122b4fe9dafe5245a2c05694cjackqdyulei public void setCharging(boolean val) { 188ff5bd948b0b5fc2122b4fe9dafe5245a2c05694cjackqdyulei mCharging = val; 1896aa6e6e640ddaea3272144aee68762dd17674773Dan Sandler postInvalidate(); 190597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei } 191597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei 192ff5bd948b0b5fc2122b4fe9dafe5245a2c05694cjackqdyulei public boolean getCharging() { 193ff5bd948b0b5fc2122b4fe9dafe5245a2c05694cjackqdyulei return mCharging; 194ff5bd948b0b5fc2122b4fe9dafe5245a2c05694cjackqdyulei } 195ff5bd948b0b5fc2122b4fe9dafe5245a2c05694cjackqdyulei 1966aa6e6e640ddaea3272144aee68762dd17674773Dan Sandler public void setBatteryLevel(int val) { 1976aa6e6e640ddaea3272144aee68762dd17674773Dan Sandler mLevel = val; 1986aa6e6e640ddaea3272144aee68762dd17674773Dan Sandler postInvalidate(); 1996aa6e6e640ddaea3272144aee68762dd17674773Dan Sandler } 2006aa6e6e640ddaea3272144aee68762dd17674773Dan Sandler 201ff5bd948b0b5fc2122b4fe9dafe5245a2c05694cjackqdyulei public int getBatteryLevel() { 202ff5bd948b0b5fc2122b4fe9dafe5245a2c05694cjackqdyulei return mLevel; 203ff5bd948b0b5fc2122b4fe9dafe5245a2c05694cjackqdyulei } 204ff5bd948b0b5fc2122b4fe9dafe5245a2c05694cjackqdyulei 2056aa6e6e640ddaea3272144aee68762dd17674773Dan Sandler public void setPowerSave(boolean val) { 2066aa6e6e640ddaea3272144aee68762dd17674773Dan Sandler mPowerSaveEnabled = val; 2076aa6e6e640ddaea3272144aee68762dd17674773Dan Sandler postInvalidate(); 208597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei } 209597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei 2109eb4610db728a051b6725d7efb76790e9e1f3520Evan Laird protected void setPowerSaveAsColorError(boolean asError) { 2119eb4610db728a051b6725d7efb76790e9e1f3520Evan Laird mPowerSaveAsColorError = asError; 2129eb4610db728a051b6725d7efb76790e9e1f3520Evan Laird } 2139eb4610db728a051b6725d7efb76790e9e1f3520Evan Laird 2146aa6e6e640ddaea3272144aee68762dd17674773Dan Sandler // an approximation of View.postInvalidate() 2156aa6e6e640ddaea3272144aee68762dd17674773Dan Sandler protected void postInvalidate() { 2166aa6e6e640ddaea3272144aee68762dd17674773Dan Sandler unscheduleSelf(this::invalidateSelf); 2176aa6e6e640ddaea3272144aee68762dd17674773Dan Sandler scheduleSelf(this::invalidateSelf, 0); 2186aa6e6e640ddaea3272144aee68762dd17674773Dan Sandler } 2196aa6e6e640ddaea3272144aee68762dd17674773Dan Sandler 2206aa6e6e640ddaea3272144aee68762dd17674773Dan Sandler private static float[] loadPoints(Resources res, int pointArrayRes) { 2216aa6e6e640ddaea3272144aee68762dd17674773Dan Sandler final int[] pts = res.getIntArray(pointArrayRes); 222597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei int maxX = 0, maxY = 0; 223597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei for (int i = 0; i < pts.length; i += 2) { 224597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei maxX = Math.max(maxX, pts[i]); 225597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei maxY = Math.max(maxY, pts[i + 1]); 226597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei } 227597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei final float[] ptsF = new float[pts.length]; 228597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei for (int i = 0; i < pts.length; i += 2) { 229597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei ptsF[i] = (float) pts[i] / maxX; 230597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei ptsF[i + 1] = (float) pts[i + 1] / maxY; 231597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei } 232597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei return ptsF; 233597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei } 234597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei 235597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei @Override 236597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei public void setBounds(int left, int top, int right, int bottom) { 237597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei super.setBounds(left, top, right, bottom); 2386f4179c3b8788456095ec79fd35e7c1a3d0589a0Evan Laird updateSize(); 2396f4179c3b8788456095ec79fd35e7c1a3d0589a0Evan Laird } 2406f4179c3b8788456095ec79fd35e7c1a3d0589a0Evan Laird 2416f4179c3b8788456095ec79fd35e7c1a3d0589a0Evan Laird private void updateSize() { 2426f4179c3b8788456095ec79fd35e7c1a3d0589a0Evan Laird final Rect bounds = getBounds(); 2436f4179c3b8788456095ec79fd35e7c1a3d0589a0Evan Laird 2446f4179c3b8788456095ec79fd35e7c1a3d0589a0Evan Laird mHeight = (bounds.bottom - mPadding.bottom) - (bounds.top + mPadding.top); 2456f4179c3b8788456095ec79fd35e7c1a3d0589a0Evan Laird mWidth = (bounds.right - mPadding.right) - (bounds.left + mPadding.left); 246597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mWarningTextPaint.setTextSize(mHeight * 0.75f); 247597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mWarningTextHeight = -mWarningTextPaint.getFontMetrics().ascent; 248597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei } 249597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei 2506f4179c3b8788456095ec79fd35e7c1a3d0589a0Evan Laird @Override 2516f4179c3b8788456095ec79fd35e7c1a3d0589a0Evan Laird public boolean getPadding(Rect padding) { 2526f4179c3b8788456095ec79fd35e7c1a3d0589a0Evan Laird if (mPadding.left == 0 2536f4179c3b8788456095ec79fd35e7c1a3d0589a0Evan Laird && mPadding.top == 0 2546f4179c3b8788456095ec79fd35e7c1a3d0589a0Evan Laird && mPadding.right == 0 2556f4179c3b8788456095ec79fd35e7c1a3d0589a0Evan Laird && mPadding.bottom == 0) { 2566f4179c3b8788456095ec79fd35e7c1a3d0589a0Evan Laird return super.getPadding(padding); 2576f4179c3b8788456095ec79fd35e7c1a3d0589a0Evan Laird } 2586f4179c3b8788456095ec79fd35e7c1a3d0589a0Evan Laird 2596f4179c3b8788456095ec79fd35e7c1a3d0589a0Evan Laird padding.set(mPadding); 2606f4179c3b8788456095ec79fd35e7c1a3d0589a0Evan Laird return true; 2616f4179c3b8788456095ec79fd35e7c1a3d0589a0Evan Laird } 2626f4179c3b8788456095ec79fd35e7c1a3d0589a0Evan Laird 2636f4179c3b8788456095ec79fd35e7c1a3d0589a0Evan Laird public void setPadding(int left, int top, int right, int bottom) { 2646f4179c3b8788456095ec79fd35e7c1a3d0589a0Evan Laird mPadding.left = left; 2656f4179c3b8788456095ec79fd35e7c1a3d0589a0Evan Laird mPadding.top = top; 2666f4179c3b8788456095ec79fd35e7c1a3d0589a0Evan Laird mPadding.right = right; 2676f4179c3b8788456095ec79fd35e7c1a3d0589a0Evan Laird mPadding.bottom = bottom; 2686f4179c3b8788456095ec79fd35e7c1a3d0589a0Evan Laird 2696f4179c3b8788456095ec79fd35e7c1a3d0589a0Evan Laird updateSize(); 2706f4179c3b8788456095ec79fd35e7c1a3d0589a0Evan Laird } 2716f4179c3b8788456095ec79fd35e7c1a3d0589a0Evan Laird 272597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei private int getColorForLevel(int percent) { 273597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei int thresh, color = 0; 274597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei for (int i = 0; i < mColors.length; i += 2) { 275597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei thresh = mColors[i]; 276597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei color = mColors[i + 1]; 277597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei if (percent <= thresh) { 278597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei 279597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei // Respect tinting for "normal" level 280597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei if (i == mColors.length - 2) { 281597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei return mIconTint; 282597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei } else { 283597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei return color; 284597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei } 285597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei } 286597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei } 287597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei return color; 288597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei } 289597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei 290597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei public void setColors(int fillColor, int backgroundColor) { 291597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mIconTint = fillColor; 292597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mFramePaint.setColor(backgroundColor); 293597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mBoltPaint.setColor(fillColor); 294597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mChargeColor = fillColor; 295597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei invalidateSelf(); 296597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei } 297597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei 2986f4179c3b8788456095ec79fd35e7c1a3d0589a0Evan Laird protected int batteryColorForLevel(int level) { 299d783c8af01098a36a36bfa4f8c5fed370cfb3654Evan Laird return (mCharging || (mPowerSaveEnabled && mPowerSaveAsColorError)) 300d783c8af01098a36a36bfa4f8c5fed370cfb3654Evan Laird ? mChargeColor 301d783c8af01098a36a36bfa4f8c5fed370cfb3654Evan Laird : getColorForLevel(level); 3026f4179c3b8788456095ec79fd35e7c1a3d0589a0Evan Laird } 3036f4179c3b8788456095ec79fd35e7c1a3d0589a0Evan Laird 304597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei @Override 305597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei public void draw(Canvas c) { 306597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei final int level = mLevel; 30798b7fdbd5c11af30afdf147d0c4cc44fe4ef240ajackqdyulei final Rect bounds = getBounds(); 308597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei 309597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei if (level == -1) return; 310597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei 311597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei float drawFrac = (float) level / 100f; 312597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei final int height = mHeight; 313d94a9388e81a395f74a91dfa2997c35d7c6df574jackqdyulei final int width = (int) (getAspectRatio() * mHeight); 3146f4179c3b8788456095ec79fd35e7c1a3d0589a0Evan Laird final int px = (mWidth - width) / 2; 3156a600b8f628ddfbcaddc8dc281684b8edf294005Jason Monk final int buttonHeight = Math.round(height * mButtonHeightFraction); 31698b7fdbd5c11af30afdf147d0c4cc44fe4ef240ajackqdyulei final int left = mPadding.left + bounds.left; 31798b7fdbd5c11af30afdf147d0c4cc44fe4ef240ajackqdyulei final int top = bounds.bottom - mPadding.bottom - height; 318597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei 31998b7fdbd5c11af30afdf147d0c4cc44fe4ef240ajackqdyulei mFrame.set(left, top, width + left, height + top); 320597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mFrame.offset(px, 0); 321597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei 322597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei // button-frame: area above the battery body 323597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mButtonFrame.set( 324706d9684afb4d46541521d290aa99c08531a5f4cEvan Laird mFrame.left + Math.round(width * 0.28f), 325597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mFrame.top, 326706d9684afb4d46541521d290aa99c08531a5f4cEvan Laird mFrame.right - Math.round(width * 0.28f), 327597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mFrame.top + buttonHeight); 328597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei 329597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei // frame: battery body area 330597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mFrame.top += buttonHeight; 331597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei 332597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei // set the battery charging color 3336f4179c3b8788456095ec79fd35e7c1a3d0589a0Evan Laird mBatteryPaint.setColor(batteryColorForLevel(level)); 334597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei 335597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei if (level >= FULL) { 336597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei drawFrac = 1f; 337597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei } else if (level <= mCriticalLevel) { 338597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei drawFrac = 0f; 339597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei } 340597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei 341597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei final float levelTop = drawFrac == 1f ? mButtonFrame.top 342597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei : (mFrame.top + (mFrame.height() * (1f - drawFrac))); 343597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei 344597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei // define the battery shape 345597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mShapePath.reset(); 346d783c8af01098a36a36bfa4f8c5fed370cfb3654Evan Laird mOutlinePath.reset(); 347d94a9388e81a395f74a91dfa2997c35d7c6df574jackqdyulei final float radius = getRadiusRatio() * (mFrame.height() + buttonHeight); 3486a600b8f628ddfbcaddc8dc281684b8edf294005Jason Monk mShapePath.setFillType(FillType.WINDING); 3496a600b8f628ddfbcaddc8dc281684b8edf294005Jason Monk mShapePath.addRoundRect(mFrame, radius, radius, Direction.CW); 3506a600b8f628ddfbcaddc8dc281684b8edf294005Jason Monk mShapePath.addRect(mButtonFrame, Direction.CW); 351d783c8af01098a36a36bfa4f8c5fed370cfb3654Evan Laird mOutlinePath.addRoundRect(mFrame, radius, radius, Direction.CW); 352d783c8af01098a36a36bfa4f8c5fed370cfb3654Evan Laird Path p = new Path(); 353d783c8af01098a36a36bfa4f8c5fed370cfb3654Evan Laird p.addRect(mButtonFrame, Direction.CW); 354d783c8af01098a36a36bfa4f8c5fed370cfb3654Evan Laird mOutlinePath.op(p, Op.XOR); 355597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei 356ff5bd948b0b5fc2122b4fe9dafe5245a2c05694cjackqdyulei if (mCharging) { 357597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei // define the bolt shape 358706d9684afb4d46541521d290aa99c08531a5f4cEvan Laird // Shift right by 1px for maximal bolt-goodness 359706d9684afb4d46541521d290aa99c08531a5f4cEvan Laird final float bl = mFrame.left + mFrame.width() / 4f + 1; 360597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei final float bt = mFrame.top + mFrame.height() / 6f; 361706d9684afb4d46541521d290aa99c08531a5f4cEvan Laird final float br = mFrame.right - mFrame.width() / 4f + 1; 362597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei final float bb = mFrame.bottom - mFrame.height() / 10f; 363597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei if (mBoltFrame.left != bl || mBoltFrame.top != bt 364597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei || mBoltFrame.right != br || mBoltFrame.bottom != bb) { 365597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mBoltFrame.set(bl, bt, br, bb); 366597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mBoltPath.reset(); 367597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mBoltPath.moveTo( 368597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mBoltFrame.left + mBoltPoints[0] * mBoltFrame.width(), 369597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mBoltFrame.top + mBoltPoints[1] * mBoltFrame.height()); 370597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei for (int i = 2; i < mBoltPoints.length; i += 2) { 371597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mBoltPath.lineTo( 372597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mBoltFrame.left + mBoltPoints[i] * mBoltFrame.width(), 373597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mBoltFrame.top + mBoltPoints[i + 1] * mBoltFrame.height()); 374597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei } 375597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mBoltPath.lineTo( 376597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mBoltFrame.left + mBoltPoints[0] * mBoltFrame.width(), 377597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mBoltFrame.top + mBoltPoints[1] * mBoltFrame.height()); 378597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei } 379597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei 380597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei float boltPct = (mBoltFrame.bottom - levelTop) / (mBoltFrame.bottom - mBoltFrame.top); 381597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei boltPct = Math.min(Math.max(boltPct, 0), 1); 382597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei if (boltPct <= BOLT_LEVEL_THRESHOLD) { 383597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei // draw the bolt if opaque 384597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei c.drawPath(mBoltPath, mBoltPaint); 385597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei } else { 386597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei // otherwise cut the bolt out of the overall shape 387597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mShapePath.op(mBoltPath, Path.Op.DIFFERENCE); 388597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei } 389597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei } else if (mPowerSaveEnabled) { 390597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei // define the plus shape 391597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei final float pw = mFrame.width() * 2 / 3; 392597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei final float pl = mFrame.left + (mFrame.width() - pw) / 2; 393597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei final float pt = mFrame.top + (mFrame.height() - pw) / 2; 394597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei final float pr = mFrame.right - (mFrame.width() - pw) / 2; 395597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei final float pb = mFrame.bottom - (mFrame.height() - pw) / 2; 396597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei if (mPlusFrame.left != pl || mPlusFrame.top != pt 397597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei || mPlusFrame.right != pr || mPlusFrame.bottom != pb) { 398597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mPlusFrame.set(pl, pt, pr, pb); 399597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mPlusPath.reset(); 400597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mPlusPath.moveTo( 401597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mPlusFrame.left + mPlusPoints[0] * mPlusFrame.width(), 402597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mPlusFrame.top + mPlusPoints[1] * mPlusFrame.height()); 403597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei for (int i = 2; i < mPlusPoints.length; i += 2) { 404597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mPlusPath.lineTo( 405597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mPlusFrame.left + mPlusPoints[i] * mPlusFrame.width(), 406597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mPlusFrame.top + mPlusPoints[i + 1] * mPlusFrame.height()); 407597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei } 408597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mPlusPath.lineTo( 409597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mPlusFrame.left + mPlusPoints[0] * mPlusFrame.width(), 410597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mPlusFrame.top + mPlusPoints[1] * mPlusFrame.height()); 411597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei } 412597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei 4136596266aa4503d63d64f2102a1acb03a346dc90bEvan Laird // Always cut out of the whole shape, and sometimes filled colorError 4146596266aa4503d63d64f2102a1acb03a346dc90bEvan Laird mShapePath.op(mPlusPath, Path.Op.DIFFERENCE); 4156596266aa4503d63d64f2102a1acb03a346dc90bEvan Laird if (mPowerSaveAsColorError) { 416597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei c.drawPath(mPlusPath, mPlusPaint); 417597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei } 418597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei } 419597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei 420597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei // compute percentage text 421597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei boolean pctOpaque = false; 422597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei float pctX = 0, pctY = 0; 423597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei String pctText = null; 424ff5bd948b0b5fc2122b4fe9dafe5245a2c05694cjackqdyulei if (!mCharging && !mPowerSaveEnabled && level > mCriticalLevel && mShowPercent) { 425597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mTextPaint.setColor(getColorForLevel(level)); 426597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mTextPaint.setTextSize(height * 427597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei (SINGLE_DIGIT_PERCENT ? 0.75f 428597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei : (mLevel == 100 ? 0.38f : 0.5f))); 429597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mTextHeight = -mTextPaint.getFontMetrics().ascent; 430597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei pctText = String.valueOf(SINGLE_DIGIT_PERCENT ? (level / 10) : level); 4315466c8f22aecb61e7b520997198878830cd103bbjackqdyulei pctX = mWidth * 0.5f + left; 4325466c8f22aecb61e7b520997198878830cd103bbjackqdyulei pctY = (mHeight + mTextHeight) * 0.47f + top; 433597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei pctOpaque = levelTop > pctY; 434597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei if (!pctOpaque) { 435597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mTextPath.reset(); 436597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mTextPaint.getTextPath(pctText, 0, pctText.length(), pctX, pctY, mTextPath); 437597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei // cut the percentage text out of the overall shape 438597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mShapePath.op(mTextPath, Path.Op.DIFFERENCE); 439597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei } 440597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei } 441597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei 442597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei // draw the battery shape background 443597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei c.drawPath(mShapePath, mFramePaint); 444597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei 445597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei // draw the battery shape, clipped to charging level 446597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mFrame.top = levelTop; 447003db4e4d1c8a11b65d5b44f8bf5851294047911Derek Sollenberger c.save(); 448003db4e4d1c8a11b65d5b44f8bf5851294047911Derek Sollenberger c.clipRect(mFrame); 449597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei c.drawPath(mShapePath, mBatteryPaint); 450003db4e4d1c8a11b65d5b44f8bf5851294047911Derek Sollenberger c.restore(); 451597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei 452ff5bd948b0b5fc2122b4fe9dafe5245a2c05694cjackqdyulei if (!mCharging && !mPowerSaveEnabled) { 453597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei if (level <= mCriticalLevel) { 454597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei // draw the warning text 4555466c8f22aecb61e7b520997198878830cd103bbjackqdyulei final float x = mWidth * 0.5f + left; 4565466c8f22aecb61e7b520997198878830cd103bbjackqdyulei final float y = (mHeight + mWarningTextHeight) * 0.48f + top; 457597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei c.drawText(mWarningString, x, y, mWarningTextPaint); 458597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei } else if (pctOpaque) { 459597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei // draw the percentage text 460597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei c.drawText(pctText, pctX, pctY, mTextPaint); 461597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei } 462597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei } 463d783c8af01098a36a36bfa4f8c5fed370cfb3654Evan Laird 464d783c8af01098a36a36bfa4f8c5fed370cfb3654Evan Laird // Draw the powersave outline last 465d783c8af01098a36a36bfa4f8c5fed370cfb3654Evan Laird if (!mCharging && mPowerSaveEnabled && mPowerSaveAsColorError) { 466d783c8af01098a36a36bfa4f8c5fed370cfb3654Evan Laird c.drawPath(mOutlinePath, mPowersavePaint); 467d783c8af01098a36a36bfa4f8c5fed370cfb3654Evan Laird } 468597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei } 469597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei 470597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei // Some stuff required by Drawable. 471597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei @Override 472597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei public void setAlpha(int alpha) { 473597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei } 474597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei 475597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei @Override 476597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei public void setColorFilter(@Nullable ColorFilter colorFilter) { 477597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mFramePaint.setColorFilter(colorFilter); 478597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mBatteryPaint.setColorFilter(colorFilter); 479597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mWarningTextPaint.setColorFilter(colorFilter); 480597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mBoltPaint.setColorFilter(colorFilter); 481597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei mPlusPaint.setColorFilter(colorFilter); 482597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei } 483597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei 484597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei @Override 485597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei public int getOpacity() { 486597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei return 0; 487597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei } 488ff5bd948b0b5fc2122b4fe9dafe5245a2c05694cjackqdyulei 489ff5bd948b0b5fc2122b4fe9dafe5245a2c05694cjackqdyulei public int getCriticalLevel() { 490ff5bd948b0b5fc2122b4fe9dafe5245a2c05694cjackqdyulei return mCriticalLevel; 491ff5bd948b0b5fc2122b4fe9dafe5245a2c05694cjackqdyulei } 492d94a9388e81a395f74a91dfa2997c35d7c6df574jackqdyulei 493d94a9388e81a395f74a91dfa2997c35d7c6df574jackqdyulei protected float getAspectRatio() { 494d94a9388e81a395f74a91dfa2997c35d7c6df574jackqdyulei return ASPECT_RATIO; 495d94a9388e81a395f74a91dfa2997c35d7c6df574jackqdyulei } 496d94a9388e81a395f74a91dfa2997c35d7c6df574jackqdyulei 497d94a9388e81a395f74a91dfa2997c35d7c6df574jackqdyulei protected float getRadiusRatio() { 498d94a9388e81a395f74a91dfa2997c35d7c6df574jackqdyulei return RADIUS_RATIO; 499d94a9388e81a395f74a91dfa2997c35d7c6df574jackqdyulei } 500597b10f6db2401f7685191f96e3aaedcbccc56b0jackqdyulei} 501