Merge commit '6a651f81b52dcdc6518f1fc138985365feae4bfb' into oc-dr1-dev

Picked up a fudge factor along a the way because of the way that the
rounded edges of oc-dr1 change the imaginary bounds of the triangle.
This should look good though.

Test: visual; runtest systemui
Change-Id: Ie79025c74bfeb136bb7f5ee7fe5604b2c12ab71e
This commit is contained in:
Evan Laird
2017-06-21 18:24:36 -04:00
4 changed files with 123 additions and 6 deletions

View File

@@ -827,4 +827,7 @@
<!-- How far to inset the rounded edges -->
<dimen name="stat_sys_mobile_signal_circle_inset">0.9dp</dimen>
<!-- Width of the hollow triangle for empty signal state -->
<dimen name="mobile_signal_empty_strokewidth">2dp</dimen>
</resources>

View File

@@ -141,7 +141,11 @@ public class CellularTile extends QSTileImpl<SignalState> {
&& mDataController.isMobileDataEnabled();
state.icon = new SignalIcon(cb.mobileSignalIconId);
state.state = Tile.STATE_ACTIVE;
if (cb.airplaneModeEnabled) {
state.state = Tile.STATE_INACTIVE;
} else {
state.state = Tile.STATE_ACTIVE;
}
}
@Override

View File

@@ -21,13 +21,14 @@ import android.annotation.Nullable;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.Path.Direction;
import android.graphics.Path.FillType;
import android.graphics.Path.Op;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.util.LayoutDirection;
@@ -63,6 +64,7 @@ public class SignalDrawable extends Drawable {
private static final int STATE_EMPTY = 1;
private static final int STATE_CUT = 2;
private static final int STATE_CARRIER_CHANGE = 3;
private static final int STATE_AIRPLANE = 4;
private static final long DOT_DELAY = 1000;
@@ -97,6 +99,18 @@ public class SignalDrawable extends Drawable {
// How far the circle defining the corners is inset from the edges
private final float mAppliedCornerInset;
// The easiest way to understand this is as if we set Style.STROKE and draw the triangle,
// but that is only theoretically right. Instead, draw the triangle and clip out a smaller
// one inset by this amount.
private final float mEmptyStrokeWidth;
private static final float INV_TAN = 1f / (float) Math.tan(Math.PI / 8f);
private final float mEmptyDiagInset; // == mEmptyStrokeWidth * INV_TAN
//TODO: This is needed because drawing the triangle is paramterized on the rounded edges.
// We get rounded corners by placing circles at arbitrary points along the legs of the triangle,
// but that means we lose the notion of a triangle being strictly half of its containing square.
// As a result, here's a value to tweak the insets of the cutout for the no-signal icon.
private final float mCutExtraOffset;
private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private final Paint mForegroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private final int mDarkModeBackgroundColor;
@@ -106,6 +120,10 @@ public class SignalDrawable extends Drawable {
private final Path mFullPath = new Path();
private final Path mForegroundPath = new Path();
private final Path mXPath = new Path();
// Cut out when STATE_EMPTY
private final Path mCutPath = new Path();
// Draws the slash when in airplane mode
private final SlashArtist mSlash = new SlashArtist();
private final Handler mHandler;
private float mOldDarkIntensity = -1;
private float mNumLevels = 1;
@@ -126,11 +144,18 @@ public class SignalDrawable extends Drawable {
mLightModeFillColor =
Utils.getDefaultColor(context, R.color.light_mode_icon_color_dual_tone_fill);
mIntrinsicSize = context.getResources().getDimensionPixelSize(R.dimen.signal_icon_size);
// mCutPath parameters
mEmptyStrokeWidth = context.getResources()
.getDimensionPixelSize(R.dimen.mobile_signal_empty_strokewidth);
mEmptyDiagInset = mEmptyStrokeWidth * INV_TAN;
mHandler = new Handler();
setDarkIntensity(0);
mAppliedCornerInset = context.getResources()
.getDimensionPixelSize(R.dimen.stat_sys_mobile_signal_circle_inset);
mCutExtraOffset = mAppliedCornerInset / 2f;
}
public void setIntrinsicSize(int size) {
@@ -224,9 +249,10 @@ public class SignalDrawable extends Drawable {
}
mFullPath.reset();
mFullPath.setFillType(FillType.WINDING);
final float width = getBounds().width();
final float height = getBounds().height();
final float padding = (int) (PAD * width); // Stay on pixel boundary
final float padding = Math.round(PAD * width);
final float cornerRadius = RADIUS_RATIO * height;
// Offset from circle where the hypotenuse meets the circle
final float diagOffset = DIAG_OFFSET_MULTIPLIER * cornerRadius;
@@ -292,10 +318,29 @@ public class SignalDrawable extends Drawable {
mFullPath.rLineTo(0, cut);
}
mPaint.setStyle(mState == STATE_EMPTY ? Style.STROKE : Style.FILL);
mForegroundPaint.setStyle(mState == STATE_EMPTY ? Style.STROKE : Style.FILL);
if (mState == STATE_EMPTY) {
// Cut out a smaller triangle from the center of mFullPath
mCutPath.reset();
mCutPath.setFillType(FillType.WINDING);
mCutPath.moveTo(width - padding - mEmptyStrokeWidth,
height - padding - mEmptyStrokeWidth);
mCutPath.lineTo(width - padding - mEmptyStrokeWidth,
padding + mEmptyDiagInset - mCutExtraOffset);
mCutPath.lineTo(padding + mEmptyDiagInset - mCutExtraOffset,
height - padding - mEmptyStrokeWidth);
mCutPath.lineTo(width - padding - mEmptyStrokeWidth,
height - padding - mEmptyStrokeWidth);
if (mState != STATE_CARRIER_CHANGE) {
// In empty state, draw the full path as the foreground paint
mForegroundPath.set(mFullPath);
mFullPath.reset();
mForegroundPath.op(mCutPath, Path.Op.DIFFERENCE);
} else if (mState == STATE_AIRPLANE) {
// Airplane mode is slashed, full-signal
mForegroundPath.set(mFullPath);
mFullPath.reset();
mSlash.draw((int) height, (int) width, canvas, mForegroundPaint);
} else if (mState != STATE_CARRIER_CHANGE) {
mForegroundPath.reset();
int sigWidth = Math.round(calcFit(mLevel / (mNumLevels - 1)) * (width - 2 * padding));
mForegroundPath.addRect(padding, padding, padding + sigWidth, height - padding,
@@ -405,4 +450,65 @@ public class SignalDrawable extends Drawable {
public static int getEmptyState(int numLevels) {
return (STATE_EMPTY << STATE_SHIFT) | (numLevels << NUM_LEVEL_SHIFT);
}
public static int getAirplaneModeState(int numLevels) {
return (STATE_AIRPLANE << STATE_SHIFT) | (numLevels << NUM_LEVEL_SHIFT);
}
private final class SlashArtist {
// These values are derived in un-rotated (vertical) orientation
private static final float SLASH_WIDTH = 1.8384776f;
private static final float SLASH_HEIGHT = 22f;
private static final float CENTER_X = 10.65f;
private static final float CENTER_Y = 15.869239f;
private static final float SCALE = 24f;
// Bottom is derived during animation
private static final float LEFT = (CENTER_X - (SLASH_WIDTH / 2)) / SCALE;
private static final float TOP = (CENTER_Y - (SLASH_HEIGHT / 2)) / SCALE;
private static final float RIGHT = (CENTER_X + (SLASH_WIDTH / 2)) / SCALE;
private static final float BOTTOM = (CENTER_Y + (SLASH_HEIGHT / 2)) / SCALE;
// Draw the slash washington-monument style; rotate to no-u-turn style
private static final float ROTATION = -45f;
private final Path mPath = new Path();
private final RectF mSlashRect = new RectF();
void draw(int height, int width, @NonNull Canvas canvas, Paint paint) {
Matrix m = new Matrix();
updateRect(
scale(LEFT, width),
scale(TOP, height),
scale(RIGHT, width),
scale(BOTTOM, height));
mPath.reset();
// Draw the slash vertically
mPath.addRect(mSlashRect, Direction.CW);
m.setRotate(ROTATION, width / 2, height / 2);
mPath.transform(m);
canvas.drawPath(mPath, paint);
// Rotate back to vertical, and draw the cut-out rect next to this one
m.setRotate(-ROTATION, width / 2, height / 2);
mPath.transform(m);
m.setTranslate(mSlashRect.width(), 0);
mPath.transform(m);
mPath.addRect(mSlashRect, Direction.CW);
m.setRotate(ROTATION, width / 2, height / 2);
mPath.transform(m);
canvas.clipOutPath(mPath);
}
void updateRect(float left, float top, float right, float bottom) {
mSlashRect.left = left;
mSlashRect.top = top;
mSlashRect.right = right;
mSlashRect.bottom = bottom;
}
private float scale(float frac, int width) {
return frac * width;
}
}
}

View File

@@ -254,6 +254,10 @@ public class MobileSignalController extends SignalController<
@Override
public int getQsCurrentIconId() {
if (mCurrentState.airplaneMode) {
return SignalDrawable.getAirplaneModeState(getNumLevels());
}
return getCurrentIconId();
}