160 lines
4.7 KiB
Java
160 lines
4.7 KiB
Java
/*
|
|
* Copyright (c) 2020 Hemanth Savarala.
|
|
*
|
|
* Licensed under the GNU General Public License v3
|
|
*
|
|
* This is free software: you can redistribute it and/or modify it under
|
|
* the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation either version 3 of the License, or (at your option) any later version.
|
|
*
|
|
* This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
* See the GNU General Public License for more details.
|
|
*/
|
|
|
|
package code.name.monkey.retromusic.views;
|
|
|
|
import android.content.Context;
|
|
import android.content.res.Resources;
|
|
import android.graphics.Canvas;
|
|
import android.graphics.ColorFilter;
|
|
import android.graphics.Matrix;
|
|
import android.graphics.Outline;
|
|
import android.graphics.Paint;
|
|
import android.graphics.Path;
|
|
import android.graphics.PixelFormat;
|
|
import android.graphics.Rect;
|
|
import android.graphics.drawable.Drawable;
|
|
import android.os.Build;
|
|
import android.view.View;
|
|
|
|
import androidx.annotation.NonNull;
|
|
import androidx.annotation.Nullable;
|
|
import androidx.core.graphics.drawable.DrawableCompat;
|
|
|
|
import code.name.monkey.appthemehelper.ThemeStore;
|
|
import code.name.monkey.retromusic.R;
|
|
|
|
public class PopupBackground extends Drawable {
|
|
|
|
private final int mPaddingEnd;
|
|
|
|
private final int mPaddingStart;
|
|
|
|
@NonNull
|
|
private final Paint mPaint;
|
|
|
|
@NonNull
|
|
private final Path mPath = new Path();
|
|
|
|
@NonNull
|
|
private final Matrix mTempMatrix = new Matrix();
|
|
|
|
public PopupBackground(@NonNull Context context) {
|
|
mPaint = new Paint();
|
|
mPaint.setAntiAlias(true);
|
|
mPaint.setColor(ThemeStore.Companion.accentColor(context));
|
|
mPaint.setStyle(Paint.Style.FILL);
|
|
Resources resources = context.getResources();
|
|
mPaddingStart = resources.getDimensionPixelOffset(R.dimen.afs_md2_popup_padding_start);
|
|
mPaddingEnd = resources.getDimensionPixelOffset(R.dimen.afs_md2_popup_padding_end);
|
|
}
|
|
|
|
private static void pathArcTo(@NonNull Path path, float centerX, float centerY, float radius,
|
|
float startAngle, float sweepAngle) {
|
|
path.arcTo(centerX - radius, centerY - radius, centerX + radius, centerY + radius,
|
|
startAngle, sweepAngle, false);
|
|
}
|
|
|
|
@Override
|
|
public void draw(@NonNull Canvas canvas) {
|
|
canvas.drawPath(mPath, mPaint);
|
|
}
|
|
|
|
@Override
|
|
public int getOpacity() {
|
|
return PixelFormat.TRANSLUCENT;
|
|
}
|
|
|
|
@Override
|
|
public void getOutline(@NonNull Outline outline) {
|
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q && !mPath.isConvex()) {
|
|
// The outline path must be convex before Q, but we may run into floating point error
|
|
// caused by calculation involving sqrt(2) or OEM implementation difference, so in this
|
|
// case we just omit the shadow instead of crashing.
|
|
super.getOutline(outline);
|
|
return;
|
|
}
|
|
outline.setConvexPath(mPath);
|
|
}
|
|
|
|
@Override
|
|
public void setAlpha(int alpha) {
|
|
|
|
}
|
|
|
|
@Override
|
|
public void setColorFilter(@Nullable ColorFilter colorFilter) {
|
|
|
|
}
|
|
|
|
@Override
|
|
public boolean getPadding(@NonNull Rect padding) {
|
|
if (needMirroring()) {
|
|
padding.set(mPaddingEnd, 0, mPaddingStart, 0);
|
|
} else {
|
|
padding.set(mPaddingStart, 0, mPaddingEnd, 0);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public boolean isAutoMirrored() {
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public boolean onLayoutDirectionChanged(int layoutDirection) {
|
|
updatePath();
|
|
return true;
|
|
}
|
|
|
|
|
|
@Override
|
|
protected void onBoundsChange(@NonNull Rect bounds) {
|
|
updatePath();
|
|
}
|
|
|
|
private boolean needMirroring() {
|
|
return DrawableCompat.getLayoutDirection(this) == View.LAYOUT_DIRECTION_RTL;
|
|
}
|
|
|
|
private void updatePath() {
|
|
|
|
mPath.reset();
|
|
|
|
Rect bounds = getBounds();
|
|
float width = bounds.width();
|
|
float height = bounds.height();
|
|
float r = height / 2;
|
|
float sqrt2 = (float) Math.sqrt(2);
|
|
// Ensure we are convex.
|
|
width = Math.max(r + sqrt2 * r, width);
|
|
pathArcTo(mPath, r, r, r, 90, 180);
|
|
float o1X = width - sqrt2 * r;
|
|
pathArcTo(mPath, o1X, r, r, -90, 45f);
|
|
float r2 = r / 5;
|
|
float o2X = width - sqrt2 * r2;
|
|
pathArcTo(mPath, o2X, r, r2, -45, 90);
|
|
pathArcTo(mPath, o1X, r, r, 45f, 45f);
|
|
mPath.close();
|
|
|
|
if (needMirroring()) {
|
|
mTempMatrix.setScale(-1, 1, width / 2, 0);
|
|
} else {
|
|
mTempMatrix.reset();
|
|
}
|
|
mTempMatrix.postTranslate(bounds.left, bounds.top);
|
|
mPath.transform(mTempMatrix);
|
|
}
|
|
} |