1 /* 2 * Copyright (C) 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.customization.model.color; 17 18 import android.content.Context; 19 import android.content.res.Configuration; 20 import android.content.res.Resources; 21 import android.graphics.Color; 22 import android.graphics.PorterDuff; 23 import android.view.View; 24 import android.widget.ImageView; 25 26 import androidx.annotation.ColorInt; 27 import androidx.annotation.Dimension; 28 import androidx.annotation.NonNull; 29 import androidx.annotation.VisibleForTesting; 30 31 import com.android.customization.model.ResourceConstants; 32 import com.android.systemui.monet.Style; 33 import com.android.wallpaper.R; 34 35 import java.util.Collections; 36 import java.util.HashMap; 37 import java.util.Map; 38 39 /** 40 * Represents a preset color available for the user to chose as their theming option. 41 */ 42 public class ColorBundle extends ColorOption { 43 44 private final PreviewInfo mPreviewInfo; 45 ColorBundle(String title, Map<String, String> overlayPackages, boolean isDefault, Style style, int index, PreviewInfo previewInfo)46 @VisibleForTesting ColorBundle(String title, 47 Map<String, String> overlayPackages, boolean isDefault, Style style, int index, 48 PreviewInfo previewInfo) { 49 super(title, overlayPackages, isDefault, style, index); 50 mPreviewInfo = previewInfo; 51 } 52 53 @Override bindThumbnailTile(View view)54 public void bindThumbnailTile(View view) { 55 Resources res = view.getContext().getResources(); 56 int primaryColor = mPreviewInfo.resolvePrimaryColor(res); 57 int secondaryColor = mPreviewInfo.resolveSecondaryColor(res); 58 59 for (int i = 0; i < mPreviewColorIds.length; i++) { 60 ImageView colorPreviewImageView = view.findViewById(mPreviewColorIds[i]); 61 int color = i % 2 == 0 ? primaryColor : secondaryColor; 62 colorPreviewImageView.getDrawable().setColorFilter(color, PorterDuff.Mode.SRC); 63 } 64 view.setContentDescription(getContentDescription(view.getContext())); 65 } 66 67 @Override getPreviewInfo()68 public PreviewInfo getPreviewInfo() { 69 return mPreviewInfo; 70 } 71 72 @Override getLayoutResId()73 public int getLayoutResId() { 74 return R.layout.color_option; 75 } 76 77 @Override getSource()78 public String getSource() { 79 return ColorOptionsProvider.COLOR_SOURCE_PRESET; 80 } 81 82 /** 83 * The preview information of {@link ColorBundle} 84 */ 85 public static class PreviewInfo implements ColorOption.PreviewInfo { 86 @ColorInt 87 public final int secondaryColorLight; 88 @ColorInt public final int secondaryColorDark; 89 // Monet system palette and accent colors 90 @ColorInt public final int primaryColorLight; 91 @ColorInt public final int primaryColorDark; 92 @Dimension 93 public final int bottomSheetCornerRadius; 94 95 @ColorInt private int mOverrideSecondaryColorLight = Color.TRANSPARENT; 96 @ColorInt private int mOverrideSecondaryColorDark = Color.TRANSPARENT; 97 @ColorInt private int mOverridePrimaryColorLight = Color.TRANSPARENT; 98 @ColorInt private int mOverridePrimaryColorDark = Color.TRANSPARENT; 99 PreviewInfo( int secondaryColorLight, int secondaryColorDark, int colorSystemPaletteLight, int primaryColorDark, @Dimension int cornerRadius)100 private PreviewInfo( 101 int secondaryColorLight, int secondaryColorDark, int colorSystemPaletteLight, 102 int primaryColorDark, @Dimension int cornerRadius) { 103 this.secondaryColorLight = secondaryColorLight; 104 this.secondaryColorDark = secondaryColorDark; 105 this.primaryColorLight = colorSystemPaletteLight; 106 this.primaryColorDark = primaryColorDark; 107 this.bottomSheetCornerRadius = cornerRadius; 108 } 109 110 /** 111 * Returns the accent color to be applied corresponding with the current configuration's 112 * UI mode. 113 * @return one of {@link #secondaryColorDark} or {@link #secondaryColorLight} 114 */ 115 @ColorInt resolveSecondaryColor(Resources res)116 public int resolveSecondaryColor(Resources res) { 117 boolean night = (res.getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) 118 == Configuration.UI_MODE_NIGHT_YES; 119 if (mOverrideSecondaryColorDark != Color.TRANSPARENT 120 || mOverrideSecondaryColorLight != Color.TRANSPARENT) { 121 return night ? mOverrideSecondaryColorDark : mOverrideSecondaryColorLight; 122 } 123 return night ? secondaryColorDark : secondaryColorLight; 124 } 125 126 /** 127 * Returns the palette (main) color to be applied corresponding with the current 128 * configuration's UI mode. 129 * @return one of {@link #secondaryColorDark} or {@link #secondaryColorLight} 130 */ 131 @ColorInt resolvePrimaryColor(Resources res)132 public int resolvePrimaryColor(Resources res) { 133 boolean night = (res.getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) 134 == Configuration.UI_MODE_NIGHT_YES; 135 if (mOverridePrimaryColorDark != Color.TRANSPARENT 136 || mOverridePrimaryColorLight != Color.TRANSPARENT) { 137 return night ? mOverridePrimaryColorDark : mOverridePrimaryColorLight; 138 } 139 return night ? primaryColorDark 140 : primaryColorLight; 141 } 142 143 /** 144 * Sets accent colors to override the ones in this bundle 145 */ setOverrideAccentColors(int overrideColorAccentLight, int overrideColorAccentDark)146 public void setOverrideAccentColors(int overrideColorAccentLight, 147 int overrideColorAccentDark) { 148 mOverrideSecondaryColorLight = overrideColorAccentLight; 149 mOverrideSecondaryColorDark = overrideColorAccentDark; 150 } 151 152 /** 153 * Sets palette colors to override the ones in this bundle 154 */ setOverridePaletteColors(int overrideColorPaletteLight, int overrideColorPaletteDark)155 public void setOverridePaletteColors(int overrideColorPaletteLight, 156 int overrideColorPaletteDark) { 157 mOverridePrimaryColorLight = overrideColorPaletteLight; 158 mOverridePrimaryColorDark = overrideColorPaletteDark; 159 } 160 } 161 162 /** 163 * The builder of ColorBundle 164 */ 165 public static class Builder { 166 protected String mTitle; 167 @ColorInt private int mSecondaryColorLight = Color.TRANSPARENT; 168 @ColorInt private int mSecondaryColorDark = Color.TRANSPARENT; 169 // System and Monet colors 170 @ColorInt private int mPrimaryColorLight = Color.TRANSPARENT; 171 @ColorInt private int mPrimaryColorDark = Color.TRANSPARENT; 172 private boolean mIsDefault; 173 private Style mStyle = Style.TONAL_SPOT; 174 private int mIndex; 175 protected Map<String, String> mPackages = new HashMap<>(); 176 177 /** 178 * Builds the ColorBundle 179 * @param context {@link Context} 180 * @return new {@link ColorBundle} object 181 */ build(Context context)182 public ColorBundle build(Context context) { 183 if (mTitle == null) { 184 mTitle = context.getString(R.string.adaptive_color_title); 185 } 186 return new ColorBundle(mTitle, mPackages, mIsDefault, mStyle, mIndex, 187 createPreviewInfo(context)); 188 } 189 190 /** 191 * Creates preview information 192 * @param context the {@link Context} 193 * @return the {@link PreviewInfo} object 194 */ createPreviewInfo(@onNull Context context)195 public PreviewInfo createPreviewInfo(@NonNull Context context) { 196 Resources system = context.getResources().getSystem(); 197 return new PreviewInfo(mSecondaryColorLight, 198 mSecondaryColorDark, mPrimaryColorLight, mPrimaryColorDark, 199 system.getDimensionPixelOffset( 200 system.getIdentifier(ResourceConstants.CONFIG_CORNERRADIUS, "dimen", 201 ResourceConstants.ANDROID_PACKAGE))); 202 } 203 getPackages()204 public Map<String, String> getPackages() { 205 return Collections.unmodifiableMap(mPackages); 206 } 207 208 /** 209 * Gets title of this {@link ColorBundle} object 210 * @return title string 211 */ getTitle()212 public String getTitle() { 213 return mTitle; 214 } 215 216 /** 217 * Sets title of bundle 218 * @param title specified title 219 * @return this of {@link Builder} 220 */ setTitle(String title)221 public Builder setTitle(String title) { 222 mTitle = title; 223 return this; 224 } 225 226 /** 227 * Sets color accent (light) 228 * @param colorSecondaryLight color accent light in {@link ColorInt} 229 * @return this of {@link Builder} 230 */ setColorSecondaryLight(@olorInt int colorSecondaryLight)231 public Builder setColorSecondaryLight(@ColorInt int colorSecondaryLight) { 232 mSecondaryColorLight = colorSecondaryLight; 233 return this; 234 } 235 236 /** 237 * Sets color accent (dark) 238 * @param colorSecondaryDark color accent dark in {@link ColorInt} 239 * @return this of {@link Builder} 240 */ setColorSecondaryDark(@olorInt int colorSecondaryDark)241 public Builder setColorSecondaryDark(@ColorInt int colorSecondaryDark) { 242 mSecondaryColorDark = colorSecondaryDark; 243 return this; 244 } 245 246 /** 247 * Sets color system palette (light) 248 * @param colorPrimaryLight color system palette in {@link ColorInt} 249 * @return this of {@link Builder} 250 */ setColorPrimaryLight(@olorInt int colorPrimaryLight)251 public Builder setColorPrimaryLight(@ColorInt int colorPrimaryLight) { 252 mPrimaryColorLight = colorPrimaryLight; 253 return this; 254 } 255 256 /** 257 * Sets color system palette (dark) 258 * @param colorPrimaryDark color system palette in {@link ColorInt} 259 * @return this of {@link Builder} 260 */ setColorPrimaryDark(@olorInt int colorPrimaryDark)261 public Builder setColorPrimaryDark(@ColorInt int colorPrimaryDark) { 262 mPrimaryColorDark = colorPrimaryDark; 263 return this; 264 } 265 266 /** 267 * Sets overlay package for bundle 268 * @param category the category of bundle 269 * @param packageName tha name of package in the category 270 * @return this of {@link Builder} 271 */ addOverlayPackage(String category, String packageName)272 public Builder addOverlayPackage(String category, String packageName) { 273 mPackages.put(category, packageName); 274 return this; 275 } 276 277 /** 278 * Sets the style of this color seed 279 * @param style color style of {@link Style} 280 * @return this of {@link Builder} 281 */ setStyle(Style style)282 public Builder setStyle(Style style) { 283 mStyle = style; 284 return this; 285 } 286 287 /** 288 * Sets color option index of bundle 289 * @param index color option index 290 * @return this of {@link Builder} 291 */ setIndex(int index)292 public Builder setIndex(int index) { 293 mIndex = index; 294 return this; 295 } 296 297 /** 298 * Sets as default bundle 299 * @return this of {@link Builder} 300 */ asDefault()301 public Builder asDefault() { 302 mIsDefault = true; 303 return this; 304 } 305 } 306 } 307