summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Sunny Goyal <sunnygoyal@google.com> 2025-02-13 22:02:30 -0800
committer Sunny Goyal <sunnygoyal@google.com> 2025-02-13 22:38:01 -0800
commit29f9c3d231e15131248ce78083e8db462048f1be (patch)
treeb813be2b0af21720434da1a22732343bb74eda6f
parent1767f094ad55f5461f94750fe4337ace64fe7bb0 (diff)
Merging IconShape with ThemeManager
The order of initialization for IconShape is closely tied to ThemeManager which makes it difficult for change listeners to work. Merging these keeps all the theming information at one place Bug: 381897614 Test: Updated tests Flag: EXEMPT refactor Change-Id: Ie29efa20c3308a24be3e284c1c93ed7444b68d58
-rw-r--r--quickstep/src/com/android/launcher3/uioverrides/PredictedAppIcon.java4
-rw-r--r--src/com/android/launcher3/BubbleTextView.java6
-rw-r--r--src/com/android/launcher3/DeviceProfile.java20
-rw-r--r--src/com/android/launcher3/InvariantDeviceProfile.java10
-rw-r--r--src/com/android/launcher3/dagger/LauncherBaseAppComponent.java2
-rw-r--r--src/com/android/launcher3/dragndrop/DragView.java6
-rw-r--r--src/com/android/launcher3/folder/FolderAnimationManager.java6
-rw-r--r--src/com/android/launcher3/folder/PreviewBackground.java6
-rw-r--r--src/com/android/launcher3/graphics/PreloadIconDrawable.java2
-rw-r--r--src/com/android/launcher3/graphics/ShapeDelegate.kt (renamed from src/com/android/launcher3/graphics/IconShape.kt)103
-rw-r--r--src/com/android/launcher3/graphics/ThemeManager.kt37
-rw-r--r--src/com/android/launcher3/icons/LauncherIconProvider.java10
-rw-r--r--src/com/android/launcher3/icons/LauncherIcons.kt6
-rw-r--r--src/com/android/launcher3/views/ClipIconView.java7
-rw-r--r--tests/multivalentTests/src/com/android/launcher3/FakeInvariantDeviceProfileTest.kt2
-rw-r--r--tests/multivalentTests/src/com/android/launcher3/graphics/ShapeDelegateTest.kt (renamed from tests/multivalentTests/src/com/android/launcher3/graphics/IconShapeTest.kt)16
-rw-r--r--tests/multivalentTests/src/com/android/launcher3/shapes/ShapesProviderTest.kt2
17 files changed, 118 insertions, 127 deletions
diff --git a/quickstep/src/com/android/launcher3/uioverrides/PredictedAppIcon.java b/quickstep/src/com/android/launcher3/uioverrides/PredictedAppIcon.java
index b25f99905d..37b8dc7bd8 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/PredictedAppIcon.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/PredictedAppIcon.java
@@ -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
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index e6b34574a9..03dd943f50 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -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;
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 3b283c3cb0..f34add8d3f 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -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);
diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java
index 4107c8fdea..c2d6df52a3 100644
--- a/src/com/android/launcher3/InvariantDeviceProfile.java
+++ b/src/com/android/launcher3/InvariantDeviceProfile.java
@@ -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) {
diff --git a/src/com/android/launcher3/dagger/LauncherBaseAppComponent.java b/src/com/android/launcher3/dagger/LauncherBaseAppComponent.java
index 35ae68f903..31d0da08db 100644
--- a/src/com/android/launcher3/dagger/LauncherBaseAppComponent.java
+++ b/src/com/android/launcher3/dagger/LauncherBaseAppComponent.java
@@ -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();
diff --git a/src/com/android/launcher3/dragndrop/DragView.java b/src/com/android/launcher3/dragndrop/DragView.java
index 072673d1ea..bff323ceb3 100644
--- a/src/com/android/launcher3/dragndrop/DragView.java
+++ b/src/com/android/launcher3/dragndrop/DragView.java
@@ -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,
diff --git a/src/com/android/launcher3/folder/FolderAnimationManager.java b/src/com/android/launcher3/folder/FolderAnimationManager.java
index 215761083b..d2354c18e1 100644
--- a/src/com/android/launcher3/folder/FolderAnimationManager.java
+++ b/src/com/android/launcher3/folder/FolderAnimationManager.java
@@ -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));
diff --git a/src/com/android/launcher3/folder/PreviewBackground.java b/src/com/android/launcher3/folder/PreviewBackground.java
index 77fa355803..ba8a290392 100644
--- a/src/com/android/launcher3/folder/PreviewBackground.java
+++ b/src/com/android/launcher3/folder/PreviewBackground.java
@@ -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) {
diff --git a/src/com/android/launcher3/graphics/PreloadIconDrawable.java b/src/com/android/launcher3/graphics/PreloadIconDrawable.java
index 50d6d1c4d6..3bd9fb54ca 100644
--- a/src/com/android/launcher3/graphics/PreloadIconDrawable.java
+++ b/src/com/android/launcher3/graphics/PreloadIconDrawable.java
@@ -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)
);
}
diff --git a/src/com/android/launcher3/graphics/IconShape.kt b/src/com/android/launcher3/graphics/ShapeDelegate.kt
index eac34406c2..df0c8f9aa6 100644
--- a/src/com/android/launcher3/graphics/IconShape.kt
+++ b/src/com/android/launcher3/graphics/ShapeDelegate.kt
@@ -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) {
-
- val normalizationScale =
- normalizeAdaptiveIcon(
- AdaptiveIconDrawable(null, ColorDrawable(Color.BLACK)),
- AREA_CALC_SIZE,
- )
-
- var shape: ShapeDelegate = pickBestShape(themeManager.iconState.iconMask)
- private set
-
- var folderShape: ShapeDelegate =
- themeManager.iconState.run {
- if (folderShapeMask == iconMask || folderShapeMask.isEmpty()) shape
- else pickBestShape(folderShapeMask)
- }
- private set
-
- init {
- val changeListener = ThemeChangeListener {
- shape = pickBestShape(themeManager.iconState.iconMask)
- folderShape =
- themeManager.iconState.run {
- if (folderShapeMask == iconMask || folderShapeMask.isEmpty()) shape
- else pickBestShape(folderShapeMask)
- }
+interface ShapeDelegate {
+
+ fun getPath(pathSize: Float = DEFAULT_PATH_SIZE) =
+ Path().apply { addToPath(this, 0f, 0f, pathSize / 2) }
+
+ 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,
+ )
}
- themeManager.addChangeListener(changeListener)
- lifeCycle.addCloseable { themeManager.removeChangeListener(changeListener) }
- }
- interface ShapeDelegate {
- fun getPath(pathSize: Float = DEFAULT_PATH_SIZE) =
- Path().apply { addToPath(this, 0f, 0f, pathSize / 2) }
+ fun drawShape(canvas: Canvas, offsetX: Float, offsetY: Float, radius: Float, paint: Paint)
- 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 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,
+ )
}
}
diff --git a/src/com/android/launcher3/graphics/ThemeManager.kt b/src/com/android/launcher3/graphics/ThemeManager.kt
index e767290d8d..4a0ff8c58c 100644
--- a/src/com/android/launcher3/graphics/ThemeManager.kt
+++ b/src/com/android/launcher3/graphics/ThemeManager.kt
@@ -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"
}
diff --git a/src/com/android/launcher3/icons/LauncherIconProvider.java b/src/com/android/launcher3/icons/LauncherIconProvider.java
index 482360cb0b..836b7d1c00 100644
--- a/src/com/android/launcher3/icons/LauncherIconProvider.java
+++ b/src/com/android/launcher3/icons/LauncherIconProvider.java
@@ -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 {
diff --git a/src/com/android/launcher3/icons/LauncherIcons.kt b/src/com/android/launcher3/icons/LauncherIcons.kt
index d173fd657c..6c018e87eb 100644
--- a/src/com/android/launcher3/icons/LauncherIcons.kt
+++ b/src/com/android/launcher3/icons/LauncherIcons.kt
@@ -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(
diff --git a/src/com/android/launcher3/views/ClipIconView.java b/src/com/android/launcher3/views/ClipIconView.java
index f90a3e4dd1..ddf18dfbaa 100644
--- a/src/com/android/launcher3/views/ClipIconView.java
+++ b/src/com/android/launcher3/views/ClipIconView.java
@@ -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) {
diff --git a/tests/multivalentTests/src/com/android/launcher3/FakeInvariantDeviceProfileTest.kt b/tests/multivalentTests/src/com/android/launcher3/FakeInvariantDeviceProfileTest.kt
index 060c28c8e2..f855c51f8e 100644
--- a/tests/multivalentTests/src/com/android/launcher3/FakeInvariantDeviceProfileTest.kt
+++ b/tests/multivalentTests/src/com/android/launcher3/FakeInvariantDeviceProfileTest.kt
@@ -71,7 +71,7 @@ abstract class FakeInvariantDeviceProfileTest {
inv,
info,
context.appComponent.wmProxy,
- context.appComponent.iconShape,
+ context.appComponent.themeManager,
windowBounds,
SparseArray(),
/*isMultiWindowMode=*/ false,
diff --git a/tests/multivalentTests/src/com/android/launcher3/graphics/IconShapeTest.kt b/tests/multivalentTests/src/com/android/launcher3/graphics/ShapeDelegateTest.kt
index 311676a34b..7e38f0e0ea 100644
--- a/tests/multivalentTests/src/com/android/launcher3/graphics/IconShapeTest.kt
+++ b/tests/multivalentTests/src/com/android/launcher3/graphics/ShapeDelegateTest.kt
@@ -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`() {
diff --git a/tests/multivalentTests/src/com/android/launcher3/shapes/ShapesProviderTest.kt b/tests/multivalentTests/src/com/android/launcher3/shapes/ShapesProviderTest.kt
index 2b8896ec9e..508c9a492d 100644
--- a/tests/multivalentTests/src/com/android/launcher3/shapes/ShapesProviderTest.kt
+++ b/tests/multivalentTests/src/com/android/launcher3/shapes/ShapesProviderTest.kt
@@ -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