Merge "Merging IconShape with ThemeManager" into main
This commit is contained in:
committed by
Android (Google) Code Review
commit
17c250e9d5
@@ -51,7 +51,7 @@ import com.android.launcher3.anim.AnimatedFloat;
|
||||
import com.android.launcher3.anim.AnimatorListeners;
|
||||
import com.android.launcher3.celllayout.CellLayoutLayoutParams;
|
||||
import com.android.launcher3.celllayout.DelegatedCellDrawing;
|
||||
import com.android.launcher3.graphics.IconShape;
|
||||
import com.android.launcher3.graphics.ThemeManager;
|
||||
import com.android.launcher3.icons.FastBitmapDrawable;
|
||||
import com.android.launcher3.icons.IconNormalizer;
|
||||
import com.android.launcher3.icons.LauncherIcons;
|
||||
@@ -142,7 +142,7 @@ public class PredictedAppIcon extends DoubleShadowBubbleTextView {
|
||||
int shadowSize = context.getResources().getDimensionPixelSize(
|
||||
R.dimen.blur_size_thin_outline);
|
||||
mShadowFilter = new BlurMaskFilter(shadowSize, BlurMaskFilter.Blur.OUTER);
|
||||
mShapePath = IconShape.INSTANCE.get(context).getShape().getPath(mNormalizedIconSize);
|
||||
mShapePath = ThemeManager.INSTANCE.get(context).getIconShape().getPath(mNormalizedIconSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -75,8 +75,8 @@ import com.android.launcher3.dot.DotInfo;
|
||||
import com.android.launcher3.dragndrop.DragOptions.PreDragCondition;
|
||||
import com.android.launcher3.dragndrop.DraggableView;
|
||||
import com.android.launcher3.folder.FolderIcon;
|
||||
import com.android.launcher3.graphics.IconShape;
|
||||
import com.android.launcher3.graphics.PreloadIconDrawable;
|
||||
import com.android.launcher3.graphics.ShapeDelegate;
|
||||
import com.android.launcher3.icons.DotRenderer;
|
||||
import com.android.launcher3.icons.FastBitmapDrawable;
|
||||
import com.android.launcher3.icons.IconCache.ItemInfoUpdateReceiver;
|
||||
@@ -724,7 +724,7 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
if (!mForceHideDot && (hasDot() || mDotParams.scale > 0)) {
|
||||
getIconBounds(mDotParams.iconBounds);
|
||||
Utilities.scaleRectAboutCenter(mDotParams.iconBounds,
|
||||
IconShape.INSTANCE.get(getContext()).getNormalizationScale());
|
||||
ShapeDelegate.getNormalizationScale());
|
||||
final int scrollX = getScrollX();
|
||||
final int scrollY = getScrollY();
|
||||
canvas.translate(scrollX, scrollY);
|
||||
@@ -775,7 +775,7 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
getIconBounds(mRunningAppIconBounds);
|
||||
Utilities.scaleRectAboutCenter(
|
||||
mRunningAppIconBounds,
|
||||
IconShape.INSTANCE.get(getContext()).getNormalizationScale());
|
||||
ShapeDelegate.getNormalizationScale());
|
||||
|
||||
final boolean isMinimized = mRunningAppState == RunningAppState.MINIMIZED;
|
||||
final int indicatorTop = mRunningAppIconBounds.bottom + mRunningAppIndicatorTopMargin;
|
||||
|
||||
@@ -52,7 +52,7 @@ import androidx.core.content.res.ResourcesCompat;
|
||||
import com.android.launcher3.CellLayout.ContainerType;
|
||||
import com.android.launcher3.DevicePaddings.DevicePadding;
|
||||
import com.android.launcher3.folder.ClippedFolderIconLayoutRule;
|
||||
import com.android.launcher3.graphics.IconShape;
|
||||
import com.android.launcher3.graphics.ThemeManager;
|
||||
import com.android.launcher3.icons.DotRenderer;
|
||||
import com.android.launcher3.icons.IconNormalizer;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
@@ -388,7 +388,7 @@ public class DeviceProfile {
|
||||
|
||||
/** TODO: Once we fully migrate to staged split, remove "isMultiWindowMode" */
|
||||
DeviceProfile(Context context, InvariantDeviceProfile inv, Info info,
|
||||
WindowManagerProxy wmProxy, IconShape iconShape, WindowBounds windowBounds,
|
||||
WindowManagerProxy wmProxy, ThemeManager themeManager, WindowBounds windowBounds,
|
||||
SparseArray<DotRenderer> dotRendererCache, boolean isMultiWindowMode,
|
||||
boolean transposeLayoutWithOrientation, boolean isMultiDisplay, boolean isGestureMode,
|
||||
@NonNull final ViewScaleProvider viewScaleProvider,
|
||||
@@ -846,8 +846,8 @@ public class DeviceProfile {
|
||||
dimensionOverrideProvider.accept(this);
|
||||
|
||||
// This is done last, after iconSizePx is calculated above.
|
||||
mDotRendererWorkSpace = createDotRenderer(iconShape, iconSizePx, dotRendererCache);
|
||||
mDotRendererAllApps = createDotRenderer(iconShape, allAppsIconSizePx, dotRendererCache);
|
||||
mDotRendererWorkSpace = createDotRenderer(themeManager, iconSizePx, dotRendererCache);
|
||||
mDotRendererAllApps = createDotRenderer(themeManager, allAppsIconSizePx, dotRendererCache);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -869,12 +869,12 @@ public class DeviceProfile {
|
||||
}
|
||||
|
||||
private static DotRenderer createDotRenderer(
|
||||
@NonNull IconShape iconShape, int size, @NonNull SparseArray<DotRenderer> cache) {
|
||||
@NonNull ThemeManager themeManager, int size, @NonNull SparseArray<DotRenderer> cache) {
|
||||
DotRenderer renderer = cache.get(size);
|
||||
if (renderer == null) {
|
||||
renderer = new DotRenderer(
|
||||
size,
|
||||
iconShape.getShape().getPath(DEFAULT_DOT_SIZE),
|
||||
themeManager.getIconShape().getPath(DEFAULT_DOT_SIZE),
|
||||
DEFAULT_DOT_SIZE);
|
||||
cache.put(size, renderer);
|
||||
}
|
||||
@@ -2478,7 +2478,7 @@ public class DeviceProfile {
|
||||
private final InvariantDeviceProfile mInv;
|
||||
private final Info mInfo;
|
||||
private final WindowManagerProxy mWMProxy;
|
||||
private final IconShape mIconShape;
|
||||
private final ThemeManager mThemeManager;
|
||||
|
||||
private WindowBounds mWindowBounds;
|
||||
private boolean mIsMultiDisplay;
|
||||
@@ -2495,12 +2495,12 @@ public class DeviceProfile {
|
||||
private boolean mIsTransientTaskbar;
|
||||
|
||||
public Builder(Context context, InvariantDeviceProfile inv, Info info,
|
||||
WindowManagerProxy wmProxy, IconShape iconShape) {
|
||||
WindowManagerProxy wmProxy, ThemeManager themeManager) {
|
||||
mContext = context;
|
||||
mInv = inv;
|
||||
mInfo = info;
|
||||
mWMProxy = wmProxy;
|
||||
mIconShape = iconShape;
|
||||
mThemeManager = themeManager;
|
||||
mIsTransientTaskbar = info.isTransientTaskbar();
|
||||
}
|
||||
|
||||
@@ -2581,7 +2581,7 @@ public class DeviceProfile {
|
||||
if (mOverrideProvider == null) {
|
||||
mOverrideProvider = DEFAULT_DIMENSION_PROVIDER;
|
||||
}
|
||||
return new DeviceProfile(mContext, mInv, mInfo, mWMProxy, mIconShape,
|
||||
return new DeviceProfile(mContext, mInv, mInfo, mWMProxy, mThemeManager,
|
||||
mWindowBounds, mDotRendererCache,
|
||||
mIsMultiWindowMode, mTransposeLayoutWithOrientation, mIsMultiDisplay,
|
||||
mIsGestureMode, mViewScaleProvider, mOverrideProvider, mIsTransientTaskbar);
|
||||
|
||||
@@ -57,7 +57,7 @@ import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.dagger.ApplicationContext;
|
||||
import com.android.launcher3.dagger.LauncherAppComponent;
|
||||
import com.android.launcher3.dagger.LauncherAppSingleton;
|
||||
import com.android.launcher3.graphics.IconShape;
|
||||
import com.android.launcher3.graphics.ThemeManager;
|
||||
import com.android.launcher3.icons.DotRenderer;
|
||||
import com.android.launcher3.logging.FileLog;
|
||||
import com.android.launcher3.model.DeviceGridState;
|
||||
@@ -136,7 +136,7 @@ public class InvariantDeviceProfile {
|
||||
private final DisplayController mDisplayController;
|
||||
private final WindowManagerProxy mWMProxy;
|
||||
private final LauncherPrefs mPrefs;
|
||||
private final IconShape mIconShape;
|
||||
private final ThemeManager mThemeManager;
|
||||
|
||||
/**
|
||||
* Number of icons per row and column in the workspace.
|
||||
@@ -260,12 +260,12 @@ public class InvariantDeviceProfile {
|
||||
LauncherPrefs prefs,
|
||||
DisplayController dc,
|
||||
WindowManagerProxy wmProxy,
|
||||
IconShape iconShape,
|
||||
ThemeManager themeManager,
|
||||
DaggerSingletonTracker lifeCycle) {
|
||||
mDisplayController = dc;
|
||||
mWMProxy = wmProxy;
|
||||
mPrefs = prefs;
|
||||
mIconShape = iconShape;
|
||||
mThemeManager = themeManager;
|
||||
|
||||
String gridName = prefs.get(GRID_NAME);
|
||||
initGrid(context, gridName);
|
||||
@@ -490,7 +490,7 @@ public class InvariantDeviceProfile {
|
||||
}
|
||||
|
||||
DeviceProfile.Builder newDPBuilder(Context context, Info info) {
|
||||
return new DeviceProfile.Builder(context, this, info, mWMProxy, mIconShape);
|
||||
return new DeviceProfile.Builder(context, this, info, mWMProxy, mThemeManager);
|
||||
}
|
||||
|
||||
public void addOnChangeListener(OnIDPChangeListener listener) {
|
||||
|
||||
@@ -20,7 +20,6 @@ import android.content.Context;
|
||||
|
||||
import com.android.launcher3.InvariantDeviceProfile;
|
||||
import com.android.launcher3.LauncherPrefs;
|
||||
import com.android.launcher3.graphics.IconShape;
|
||||
import com.android.launcher3.graphics.ThemeManager;
|
||||
import com.android.launcher3.icons.LauncherIcons.IconPool;
|
||||
import com.android.launcher3.model.ItemInstallQueue;
|
||||
@@ -57,7 +56,6 @@ public interface LauncherBaseAppComponent {
|
||||
ApiWrapper getApiWrapper();
|
||||
CustomWidgetManager getCustomWidgetManager();
|
||||
DynamicResource getDynamicResource();
|
||||
IconShape getIconShape();
|
||||
InstallSessionHelper getInstallSessionHelper();
|
||||
ItemInstallQueue getItemInstallQueue();
|
||||
RefreshRateTracker getRefreshRateTracker();
|
||||
|
||||
@@ -60,7 +60,7 @@ import androidx.dynamicanimation.animation.SpringForce;
|
||||
import com.android.app.animation.Interpolators;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.graphics.IconShape;
|
||||
import com.android.launcher3.graphics.ThemeManager;
|
||||
import com.android.launcher3.icons.FastBitmapDrawable;
|
||||
import com.android.launcher3.icons.LauncherIcons;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
@@ -274,9 +274,9 @@ public abstract class DragView<T extends Context & ActivityContext> extends Fram
|
||||
Utilities.scaleRectAboutCenter(shrunkBounds, 0.98f);
|
||||
adaptiveIcon.setBounds(shrunkBounds);
|
||||
|
||||
IconShape iconShape = IconShape.INSTANCE.get(getContext());
|
||||
ThemeManager themeManager = ThemeManager.INSTANCE.get(getContext());
|
||||
final Path mask = (adaptiveIcon instanceof FolderAdaptiveIcon
|
||||
? iconShape.getFolderShape() : iconShape.getShape())
|
||||
? themeManager.getFolderShape() : themeManager.getIconShape())
|
||||
.getPath(shrunkBounds);
|
||||
|
||||
mTranslateX = new SpringFloatValue(DragView.this,
|
||||
|
||||
@@ -46,8 +46,8 @@ import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.anim.PropertyResetListener;
|
||||
import com.android.launcher3.apppairs.AppPairIcon;
|
||||
import com.android.launcher3.celllayout.CellLayoutLayoutParams;
|
||||
import com.android.launcher3.graphics.IconShape;
|
||||
import com.android.launcher3.graphics.IconShape.ShapeDelegate;
|
||||
import com.android.launcher3.graphics.ShapeDelegate;
|
||||
import com.android.launcher3.graphics.ThemeManager;
|
||||
import com.android.launcher3.util.Themes;
|
||||
import com.android.launcher3.views.BaseDragLayer;
|
||||
|
||||
@@ -237,7 +237,7 @@ public class FolderAnimationManager {
|
||||
}
|
||||
play(a, getAnimator(mFolder.mFooter, ALPHA, 0, 1f), footerStartDelay, footerAlphaDuration);
|
||||
|
||||
ShapeDelegate shapeDelegate = IconShape.INSTANCE.get(mContext).getFolderShape();
|
||||
ShapeDelegate shapeDelegate = ThemeManager.INSTANCE.get(mContext).getFolderShape();
|
||||
// Create reveal animator for the folder background
|
||||
play(a, shapeDelegate.createRevealAnimator(
|
||||
mFolder, startRect, endRect, finalRadius, !mIsOpening));
|
||||
|
||||
@@ -47,8 +47,8 @@ import com.android.launcher3.CellLayout;
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.celllayout.DelegatedCellDrawing;
|
||||
import com.android.launcher3.graphics.IconShape;
|
||||
import com.android.launcher3.graphics.IconShape.ShapeDelegate;
|
||||
import com.android.launcher3.graphics.ShapeDelegate;
|
||||
import com.android.launcher3.graphics.ThemeManager;
|
||||
import com.android.launcher3.util.Themes;
|
||||
import com.android.launcher3.views.ActivityContext;
|
||||
|
||||
@@ -260,7 +260,7 @@ public class PreviewBackground extends DelegatedCellDrawing {
|
||||
}
|
||||
|
||||
private ShapeDelegate getShape() {
|
||||
return IconShape.INSTANCE.get(mContext).getFolderShape();
|
||||
return ThemeManager.INSTANCE.get(mContext).getFolderShape();
|
||||
}
|
||||
|
||||
public void drawShadow(Canvas canvas) {
|
||||
|
||||
@@ -119,7 +119,7 @@ public class PreloadIconDrawable extends FastBitmapDrawable {
|
||||
IconPalette.getPreloadProgressColor(context, info.bitmap.color),
|
||||
getPreloadColors(context),
|
||||
Utilities.isDarkTheme(context),
|
||||
IconShape.INSTANCE.get(context).getShape().getPath(DEFAULT_PATH_SIZE)
|
||||
ThemeManager.INSTANCE.get(context).getIconShape().getPath(DEFAULT_PATH_SIZE)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
+34
-65
@@ -42,78 +42,38 @@ import androidx.graphics.shapes.rectangle
|
||||
import androidx.graphics.shapes.toPath
|
||||
import androidx.graphics.shapes.transformed
|
||||
import com.android.launcher3.anim.RoundedRectRevealOutlineProvider
|
||||
import com.android.launcher3.dagger.LauncherAppComponent
|
||||
import com.android.launcher3.dagger.LauncherAppSingleton
|
||||
import com.android.launcher3.graphics.ThemeManager.ThemeChangeListener
|
||||
import com.android.launcher3.icons.GraphicsUtils
|
||||
import com.android.launcher3.icons.IconNormalizer.normalizeAdaptiveIcon
|
||||
import com.android.launcher3.util.DaggerSingletonObject
|
||||
import com.android.launcher3.util.DaggerSingletonTracker
|
||||
import com.android.launcher3.views.ClipPathView
|
||||
import javax.inject.Inject
|
||||
|
||||
/** Abstract representation of the shape of an icon shape */
|
||||
@LauncherAppSingleton
|
||||
class IconShape
|
||||
@Inject
|
||||
constructor(private val themeManager: ThemeManager, lifeCycle: DaggerSingletonTracker) {
|
||||
interface ShapeDelegate {
|
||||
|
||||
val normalizationScale =
|
||||
normalizeAdaptiveIcon(
|
||||
AdaptiveIconDrawable(null, ColorDrawable(Color.BLACK)),
|
||||
AREA_CALC_SIZE,
|
||||
)
|
||||
fun getPath(pathSize: Float = DEFAULT_PATH_SIZE) =
|
||||
Path().apply { addToPath(this, 0f, 0f, pathSize / 2) }
|
||||
|
||||
var shape: ShapeDelegate = pickBestShape(themeManager.iconState.iconMask)
|
||||
private set
|
||||
|
||||
var folderShape: ShapeDelegate =
|
||||
themeManager.iconState.run {
|
||||
if (folderShapeMask == iconMask || folderShapeMask.isEmpty()) shape
|
||||
else pickBestShape(folderShapeMask)
|
||||
fun getPath(bounds: Rect) =
|
||||
Path().apply {
|
||||
addToPath(
|
||||
this,
|
||||
bounds.left.toFloat(),
|
||||
bounds.top.toFloat(),
|
||||
// Radius is half of the average size of the icon
|
||||
(bounds.width() + bounds.height()) / 4f,
|
||||
)
|
||||
}
|
||||
private set
|
||||
|
||||
init {
|
||||
val changeListener = ThemeChangeListener {
|
||||
shape = pickBestShape(themeManager.iconState.iconMask)
|
||||
folderShape =
|
||||
themeManager.iconState.run {
|
||||
if (folderShapeMask == iconMask || folderShapeMask.isEmpty()) shape
|
||||
else pickBestShape(folderShapeMask)
|
||||
}
|
||||
}
|
||||
themeManager.addChangeListener(changeListener)
|
||||
lifeCycle.addCloseable { themeManager.removeChangeListener(changeListener) }
|
||||
}
|
||||
fun drawShape(canvas: Canvas, offsetX: Float, offsetY: Float, radius: Float, paint: Paint)
|
||||
|
||||
interface ShapeDelegate {
|
||||
fun getPath(pathSize: Float = DEFAULT_PATH_SIZE) =
|
||||
Path().apply { addToPath(this, 0f, 0f, pathSize / 2) }
|
||||
fun addToPath(path: Path, offsetX: Float, offsetY: Float, radius: Float)
|
||||
|
||||
fun getPath(bounds: Rect) =
|
||||
Path().apply {
|
||||
addToPath(
|
||||
this,
|
||||
bounds.left.toFloat(),
|
||||
bounds.top.toFloat(),
|
||||
// Radius is half of the average size of the icon
|
||||
(bounds.width() + bounds.height()) / 4f,
|
||||
)
|
||||
}
|
||||
|
||||
fun drawShape(canvas: Canvas, offsetX: Float, offsetY: Float, radius: Float, paint: Paint)
|
||||
|
||||
fun addToPath(path: Path, offsetX: Float, offsetY: Float, radius: Float)
|
||||
|
||||
fun <T> createRevealAnimator(
|
||||
target: T,
|
||||
startRect: Rect,
|
||||
endRect: Rect,
|
||||
endRadius: Float,
|
||||
isReversed: Boolean,
|
||||
): ValueAnimator where T : View, T : ClipPathView
|
||||
}
|
||||
fun <T> createRevealAnimator(
|
||||
target: T,
|
||||
startRect: Rect,
|
||||
endRect: Rect,
|
||||
endRadius: Float,
|
||||
isReversed: Boolean,
|
||||
): ValueAnimator where T : View, T : ClipPathView
|
||||
|
||||
class Circle : RoundedSquare(1f) {
|
||||
|
||||
@@ -179,10 +139,15 @@ constructor(private val themeManager: ThemeManager, lifeCycle: DaggerSingletonTr
|
||||
}
|
||||
.createRevealAnimator(target, isReversed)
|
||||
}
|
||||
|
||||
override fun equals(other: Any?) =
|
||||
other is RoundedSquare && other.radiusRatio == radiusRatio
|
||||
|
||||
override fun hashCode() = radiusRatio.hashCode()
|
||||
}
|
||||
|
||||
/** Generic shape delegate with pathString in bounds [0, 0, 100, 100] */
|
||||
class GenericPathShape(pathString: String) : ShapeDelegate {
|
||||
data class GenericPathShape(private val pathString: String) : ShapeDelegate {
|
||||
private val poly =
|
||||
RoundedPolygon(
|
||||
features = SvgPathParser.parseFeatures(pathString),
|
||||
@@ -287,7 +252,6 @@ constructor(private val themeManager: ThemeManager, lifeCycle: DaggerSingletonTr
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmField var INSTANCE = DaggerSingletonObject(LauncherAppComponent::getIconShape)
|
||||
|
||||
const val TAG = "IconShape"
|
||||
const val DEFAULT_PATH_SIZE = 100f
|
||||
@@ -312,7 +276,6 @@ constructor(private val themeManager: ThemeManager, lifeCycle: DaggerSingletonTr
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
fun pickBestShape(shapeStr: String): ShapeDelegate {
|
||||
val baseShape =
|
||||
if (shapeStr.isNotEmpty()) {
|
||||
@@ -332,7 +295,6 @@ constructor(private val themeManager: ThemeManager, lifeCycle: DaggerSingletonTr
|
||||
return pickBestShape(baseShape, shapeStr)
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
fun pickBestShape(baseShape: Path, shapeStr: String): ShapeDelegate {
|
||||
val calcAreaDiff = areaDiffCalculator(baseShape)
|
||||
|
||||
@@ -380,5 +342,12 @@ constructor(private val themeManager: ThemeManager, lifeCycle: DaggerSingletonTr
|
||||
centerY = (bottom - top) / 2,
|
||||
rounding = CornerRounding(cornerR),
|
||||
)
|
||||
|
||||
@JvmStatic
|
||||
val normalizationScale =
|
||||
normalizeAdaptiveIcon(
|
||||
AdaptiveIconDrawable(null, ColorDrawable(Color.BLACK)),
|
||||
AREA_CALC_SIZE,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,7 @@ import com.android.launcher3.LauncherPrefs.Companion.backedUpItem
|
||||
import com.android.launcher3.dagger.ApplicationContext
|
||||
import com.android.launcher3.dagger.LauncherAppComponent
|
||||
import com.android.launcher3.dagger.LauncherAppSingleton
|
||||
import com.android.launcher3.graphics.ShapeDelegate.Companion.pickBestShape
|
||||
import com.android.launcher3.icons.IconThemeController
|
||||
import com.android.launcher3.icons.mono.MonoIconThemeController
|
||||
import com.android.launcher3.shapes.ShapesProvider
|
||||
@@ -46,19 +47,25 @@ constructor(
|
||||
) {
|
||||
|
||||
/** Representation of the current icon state */
|
||||
var iconState = parseIconState()
|
||||
var iconState = parseIconState(null)
|
||||
private set
|
||||
|
||||
var isMonoThemeEnabled
|
||||
set(value) = prefs.put(THEMED_ICONS, value)
|
||||
get() = prefs.get(THEMED_ICONS)
|
||||
|
||||
val themeController: IconThemeController?
|
||||
val themeController
|
||||
get() = iconState.themeController
|
||||
|
||||
val isIconThemeEnabled: Boolean
|
||||
val isIconThemeEnabled
|
||||
get() = themeController != null
|
||||
|
||||
val iconShape
|
||||
get() = iconState.iconShape
|
||||
|
||||
val folderShape
|
||||
get() = iconState.folderShape
|
||||
|
||||
private val listeners = CopyOnWriteArrayList<ThemeChangeListener>()
|
||||
|
||||
init {
|
||||
@@ -80,7 +87,7 @@ constructor(
|
||||
}
|
||||
|
||||
protected fun verifyIconState() {
|
||||
val newState = parseIconState()
|
||||
val newState = parseIconState(iconState)
|
||||
if (newState == iconState) return
|
||||
iconState = newState
|
||||
|
||||
@@ -91,7 +98,7 @@ constructor(
|
||||
|
||||
fun removeChangeListener(listener: ThemeChangeListener) = listeners.remove(listener)
|
||||
|
||||
private fun parseIconState(): IconState {
|
||||
private fun parseIconState(oldState: IconState?): IconState {
|
||||
val shapeModel =
|
||||
prefs.get(PREF_ICON_SHAPE).let { shapeOverride ->
|
||||
ShapesProvider.iconShapes.values.firstOrNull { it.key == shapeOverride }
|
||||
@@ -102,11 +109,27 @@ constructor(
|
||||
CONFIG_ICON_MASK_RES_ID == Resources.ID_NULL -> ""
|
||||
else -> context.resources.getString(CONFIG_ICON_MASK_RES_ID)
|
||||
}
|
||||
|
||||
val iconShape =
|
||||
if (oldState != null && oldState.iconMask == iconMask) oldState.iconShape
|
||||
else pickBestShape(iconMask)
|
||||
|
||||
val folderShapeMask = shapeModel?.folderPathString ?: iconMask
|
||||
val folderShape =
|
||||
when {
|
||||
oldState != null && oldState.folderShapeMask == folderShapeMask ->
|
||||
oldState.folderShape
|
||||
folderShapeMask == iconMask || folderShapeMask.isEmpty() -> iconShape
|
||||
else -> pickBestShape(folderShapeMask)
|
||||
}
|
||||
|
||||
return IconState(
|
||||
iconMask = iconMask,
|
||||
folderShapeMask = shapeModel?.folderPathString ?: iconMask,
|
||||
folderShapeMask = folderShapeMask,
|
||||
themeController = createThemeController(),
|
||||
iconScale = shapeModel?.iconScale ?: 1f,
|
||||
iconShape = iconShape,
|
||||
folderShape = folderShape,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -120,6 +143,8 @@ constructor(
|
||||
val themeController: IconThemeController?,
|
||||
val themeCode: String = themeController?.themeID ?: "no-theme",
|
||||
val iconScale: Float = 1f,
|
||||
val iconShape: ShapeDelegate,
|
||||
val folderShape: ShapeDelegate,
|
||||
) {
|
||||
fun toUniqueId() = "${iconMask.hashCode()},$themeCode"
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.graphics.IconShape;
|
||||
import com.android.launcher3.graphics.ShapeDelegate;
|
||||
import com.android.launcher3.graphics.ThemeManager;
|
||||
import com.android.launcher3.util.ApiWrapper;
|
||||
|
||||
@@ -54,13 +54,13 @@ public class LauncherIconProvider extends IconProvider {
|
||||
private Map<String, ThemeData> mThemedIconMap;
|
||||
|
||||
private final ApiWrapper mApiWrapper;
|
||||
private final IconShape mIconShape;
|
||||
private final ThemeManager mThemeManager;
|
||||
|
||||
public LauncherIconProvider(Context context) {
|
||||
super(context);
|
||||
setIconThemeSupported(ThemeManager.INSTANCE.get(context).isMonoThemeEnabled());
|
||||
mThemeManager = ThemeManager.INSTANCE.get(context);
|
||||
mApiWrapper = ApiWrapper.INSTANCE.get(context);
|
||||
mIconShape = IconShape.INSTANCE.get(context);
|
||||
setIconThemeSupported(mThemeManager.isMonoThemeEnabled());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -91,7 +91,7 @@ public class LauncherIconProvider extends IconProvider {
|
||||
@Override
|
||||
protected Drawable loadAppInfoIcon(ApplicationInfo info, Resources resources, int density) {
|
||||
// Tries to load the round icon res, if the app defines it as an adaptive icon
|
||||
if (mIconShape.getShape() instanceof IconShape.Circle) {
|
||||
if (mThemeManager.getIconShape() instanceof ShapeDelegate.Circle) {
|
||||
int roundIconRes = mApiWrapper.getRoundIconRes(info);
|
||||
if (roundIconRes != 0 && roundIconRes != info.icon) {
|
||||
try {
|
||||
|
||||
@@ -27,7 +27,6 @@ import com.android.launcher3.InvariantDeviceProfile
|
||||
import com.android.launcher3.dagger.ApplicationContext
|
||||
import com.android.launcher3.dagger.LauncherAppSingleton
|
||||
import com.android.launcher3.dagger.LauncherComponentProvider.appComponent
|
||||
import com.android.launcher3.graphics.IconShape
|
||||
import com.android.launcher3.graphics.ThemeManager
|
||||
import com.android.launcher3.pm.UserCache
|
||||
import com.android.launcher3.util.UserIconInfo
|
||||
@@ -46,9 +45,8 @@ class LauncherIcons
|
||||
internal constructor(
|
||||
@ApplicationContext context: Context,
|
||||
idp: InvariantDeviceProfile,
|
||||
themeManager: ThemeManager,
|
||||
private var themeManager: ThemeManager,
|
||||
private var userCache: UserCache,
|
||||
private var iconShape: IconShape,
|
||||
@Assisted private val pool: ConcurrentLinkedQueue<LauncherIcons>,
|
||||
) : BaseIconFactory(context, idp.fillResIconDpi, idp.iconBitmapSize), AutoCloseable {
|
||||
|
||||
@@ -70,7 +68,7 @@ internal constructor(
|
||||
|
||||
public override fun getShapePath(drawable: AdaptiveIconDrawable, iconBounds: Rect): Path {
|
||||
if (!Flags.enableLauncherIconShapes()) return drawable.iconMask
|
||||
return iconShape.shape.getPath(iconBounds)
|
||||
return themeManager.iconShape.getPath(iconBounds)
|
||||
}
|
||||
|
||||
override fun drawAdaptiveIcon(
|
||||
|
||||
@@ -47,7 +47,8 @@ import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.dragndrop.FolderAdaptiveIcon;
|
||||
import com.android.launcher3.graphics.IconShape;
|
||||
import com.android.launcher3.graphics.ShapeDelegate;
|
||||
import com.android.launcher3.graphics.ThemeManager;
|
||||
|
||||
/**
|
||||
* A view used to draw both layers of an {@link AdaptiveIconDrawable}.
|
||||
@@ -174,7 +175,7 @@ public class ClipIconView extends View implements ClipPathView {
|
||||
if (mIsAdaptiveIcon) {
|
||||
if (!isOpening && progress >= shapeProgressStart) {
|
||||
if (mRevealAnimator == null) {
|
||||
mRevealAnimator = IconShape.INSTANCE.get(getContext()).getShape()
|
||||
mRevealAnimator = ThemeManager.INSTANCE.get(getContext()).getIconShape()
|
||||
.createRevealAnimator(this, mStartRevealRect,
|
||||
mOutline, mTaskCornerRadius, !isOpening);
|
||||
mRevealAnimator.addListener(forEndCallback(() -> mRevealAnimator = null));
|
||||
@@ -259,7 +260,7 @@ public class ClipIconView extends View implements ClipPathView {
|
||||
|
||||
if (!isFolderIcon) {
|
||||
Utilities.scaleRectAboutCenter(mStartRevealRect,
|
||||
IconShape.INSTANCE.get(getContext()).getNormalizationScale());
|
||||
ShapeDelegate.getNormalizationScale());
|
||||
}
|
||||
|
||||
if (dp.isLandscape) {
|
||||
|
||||
@@ -71,7 +71,7 @@ abstract class FakeInvariantDeviceProfileTest {
|
||||
inv,
|
||||
info,
|
||||
context.appComponent.wmProxy,
|
||||
context.appComponent.iconShape,
|
||||
context.appComponent.themeManager,
|
||||
windowBounds,
|
||||
SparseArray(),
|
||||
/*isMultiWindowMode=*/ false,
|
||||
|
||||
+8
-8
@@ -28,13 +28,13 @@ import android.view.View
|
||||
import androidx.core.graphics.PathParser
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.launcher3.graphics.IconShape.Circle
|
||||
import com.android.launcher3.graphics.IconShape.Companion.AREA_CALC_SIZE
|
||||
import com.android.launcher3.graphics.IconShape.Companion.AREA_DIFF_THRESHOLD
|
||||
import com.android.launcher3.graphics.IconShape.Companion.areaDiffCalculator
|
||||
import com.android.launcher3.graphics.IconShape.Companion.pickBestShape
|
||||
import com.android.launcher3.graphics.IconShape.GenericPathShape
|
||||
import com.android.launcher3.graphics.IconShape.RoundedSquare
|
||||
import com.android.launcher3.graphics.ShapeDelegate.Circle
|
||||
import com.android.launcher3.graphics.ShapeDelegate.Companion.AREA_CALC_SIZE
|
||||
import com.android.launcher3.graphics.ShapeDelegate.Companion.AREA_DIFF_THRESHOLD
|
||||
import com.android.launcher3.graphics.ShapeDelegate.Companion.areaDiffCalculator
|
||||
import com.android.launcher3.graphics.ShapeDelegate.Companion.pickBestShape
|
||||
import com.android.launcher3.graphics.ShapeDelegate.GenericPathShape
|
||||
import com.android.launcher3.graphics.ShapeDelegate.RoundedSquare
|
||||
import com.android.launcher3.icons.GraphicsUtils
|
||||
import com.android.launcher3.views.ClipPathView
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
@@ -43,7 +43,7 @@ import org.junit.runner.RunWith
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class IconShapeTest {
|
||||
class ShapeDelegateTest {
|
||||
|
||||
@Test
|
||||
fun `areaDiffCalculator increases with outwards shape`() {
|
||||
@@ -22,7 +22,7 @@ import androidx.core.graphics.PathParser
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.launcher3.Flags.FLAG_ENABLE_LAUNCHER_ICON_SHAPES
|
||||
import com.android.launcher3.graphics.IconShape.GenericPathShape
|
||||
import com.android.launcher3.graphics.ShapeDelegate.GenericPathShape
|
||||
import com.android.systemui.shared.Flags.FLAG_NEW_CUSTOMIZATION_PICKER_UI
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
|
||||
Reference in New Issue
Block a user