diff options
Diffstat (limited to 'library/main/src/com/android/setupwizardlib/util/ThemeResolver.java')
-rw-r--r-- | library/main/src/com/android/setupwizardlib/util/ThemeResolver.java | 219 |
1 files changed, 219 insertions, 0 deletions
diff --git a/library/main/src/com/android/setupwizardlib/util/ThemeResolver.java b/library/main/src/com/android/setupwizardlib/util/ThemeResolver.java new file mode 100644 index 0000000..14fdc85 --- /dev/null +++ b/library/main/src/com/android/setupwizardlib/util/ThemeResolver.java @@ -0,0 +1,219 @@ +package com.android.setupwizardlib.util; + +import android.app.Activity; +import android.content.Intent; +import androidx.annotation.Nullable; +import androidx.annotation.StyleRes; +import com.android.setupwizardlib.R; + +/** + * A resolver to resolve the theme from a string or an activity intent, setting options like the + * default theme and the oldest supported theme. Apps can share the resolver across the entire + * process by calling {@link #setDefault(ThemeResolver)} in {@link + * android.app.Application#onCreate()}. If an app needs more granular sharing of the theme default + * values, additional instances of {@link ThemeResolver} can be created using the builder. + */ +public class ThemeResolver { + @StyleRes private final int defaultTheme; + @Nullable private final String oldestSupportedTheme; + private final boolean useDayNight; + + @Nullable private static ThemeResolver defaultResolver; + + /** + * Sets the default instance used for the whole process. Can be null to reset the default to the + * preset one. + */ + public static void setDefault(@Nullable ThemeResolver resolver) { + defaultResolver = resolver; + } + + /** + * Returns the default instance, which can be changed using {@link #setDefault(ThemeResolver)}. + */ + public static ThemeResolver getDefault() { + if (defaultResolver == null) { + defaultResolver = + new ThemeResolver.Builder() + .setDefaultTheme(R.style.SuwThemeGlif_DayNight) + .setUseDayNight(true) + .build(); + } + return defaultResolver; + } + + private ThemeResolver( + int defaultTheme, @Nullable String oldestSupportedTheme, boolean useDayNight) { + this.defaultTheme = defaultTheme; + this.oldestSupportedTheme = oldestSupportedTheme; + this.useDayNight = useDayNight; + } + + /** + * Returns the style for the theme specified in the intent extra. If the specified string theme is + * older than the oldest supported theme, the default will be returned instead. Note that the + * default theme is returned without processing -- it may not be a DayNight theme even if {@link + * #useDayNight} is true. + */ + @StyleRes + public int resolve(Intent intent) { + return resolve( + intent.getStringExtra(WizardManagerHelper.EXTRA_THEME), + /* suppressDayNight= */ WizardManagerHelper.isSetupWizardIntent(intent)); + } + + /** + * Returns the style for the given string theme. If the specified string theme is older than the + * oldest supported theme, the default will be returned instead. Note that the default theme is + * returned without processing -- it may not be a DayNight theme even if {@link #useDayNight} is + * true. + */ + @StyleRes + public int resolve(@Nullable String theme) { + return resolve(theme, /* suppressDayNight= */ false); + } + + @StyleRes + private int resolve(@Nullable String theme, boolean suppressDayNight) { + int themeResource = + useDayNight && !suppressDayNight ? getDayNightThemeRes(theme) : getThemeRes(theme); + if (themeResource == 0) { + return defaultTheme; + } + + if (oldestSupportedTheme != null && compareThemes(theme, oldestSupportedTheme) < 0) { + return defaultTheme; + } + return themeResource; + } + + /** Reads the theme from the intent, and applies the resolved theme to the activity. */ + public void applyTheme(Activity activity) { + activity.setTheme(resolve(activity.getIntent())); + } + + /** + * Returns the corresponding DayNight theme resource ID for the given string theme. DayNight + * themes are themes that will be either light or dark depending on the system setting. For + * example, the string {@link WizardManagerHelper#THEME_GLIF_LIGHT} will return + * {@code @style/SuwThemeGlif.DayNight}. + */ + @StyleRes + private static int getDayNightThemeRes(@Nullable String theme) { + if (theme != null) { + switch (theme) { + case WizardManagerHelper.THEME_GLIF_V3_LIGHT: + case WizardManagerHelper.THEME_GLIF_V3: + return R.style.SuwThemeGlifV3_DayNight; + case WizardManagerHelper.THEME_GLIF_V2_LIGHT: + case WizardManagerHelper.THEME_GLIF_V2: + return R.style.SuwThemeGlifV2_DayNight; + case WizardManagerHelper.THEME_GLIF_LIGHT: + case WizardManagerHelper.THEME_GLIF: + return R.style.SuwThemeGlif_DayNight; + case WizardManagerHelper.THEME_MATERIAL_LIGHT: + case WizardManagerHelper.THEME_MATERIAL: + return R.style.SuwThemeMaterial_DayNight; + default: + // fall through + } + } + return 0; + } + + /** + * Returns the theme resource ID for the given string theme. For example, the string {@link + * WizardManagerHelper#THEME_GLIF_LIGHT} will return {@code @style/SuwThemeGlif.Light}. + */ + @StyleRes + private static int getThemeRes(@Nullable String theme) { + if (theme != null) { + switch (theme) { + case WizardManagerHelper.THEME_GLIF_V3_LIGHT: + return R.style.SuwThemeGlifV3_Light; + case WizardManagerHelper.THEME_GLIF_V3: + return R.style.SuwThemeGlifV3; + case WizardManagerHelper.THEME_GLIF_V2_LIGHT: + return R.style.SuwThemeGlifV2_Light; + case WizardManagerHelper.THEME_GLIF_V2: + return R.style.SuwThemeGlifV2; + case WizardManagerHelper.THEME_GLIF_LIGHT: + return R.style.SuwThemeGlif_Light; + case WizardManagerHelper.THEME_GLIF: + return R.style.SuwThemeGlif; + case WizardManagerHelper.THEME_MATERIAL_LIGHT: + return R.style.SuwThemeMaterial_Light; + case WizardManagerHelper.THEME_MATERIAL: + return R.style.SuwThemeMaterial; + default: + // fall through + } + } + return 0; + } + + /** Compares whether the versions of {@code theme1} and {@code theme2} to check which is newer. */ + private static int compareThemes(String theme1, String theme2) { + return Integer.valueOf(getThemeVersion(theme1)).compareTo(getThemeVersion(theme2)); + } + + /** + * Returns the version of the theme. The absolute number of the theme version is not defined, but + * a larger number in the version indicates a newer theme. + */ + private static int getThemeVersion(String theme) { + if (theme != null) { + switch (theme) { + case WizardManagerHelper.THEME_GLIF_V3_LIGHT: + case WizardManagerHelper.THEME_GLIF_V3: + return 4; + case WizardManagerHelper.THEME_GLIF_V2_LIGHT: + case WizardManagerHelper.THEME_GLIF_V2: + return 3; + case WizardManagerHelper.THEME_GLIF_LIGHT: + case WizardManagerHelper.THEME_GLIF: + return 2; + case WizardManagerHelper.THEME_MATERIAL_LIGHT: + case WizardManagerHelper.THEME_MATERIAL: + return 1; + default: + // fall through + } + } + return -1; + } + + /** Builder class for {@link ThemeResolver}. */ + public static class Builder { + @StyleRes private int defaultTheme = R.style.SuwThemeGlif_DayNight; + @Nullable private String oldestSupportedTheme = null; + private boolean useDayNight = true; + + public Builder() {} + + public Builder(ThemeResolver themeResolver) { + this.defaultTheme = themeResolver.defaultTheme; + this.oldestSupportedTheme = themeResolver.oldestSupportedTheme; + this.useDayNight = themeResolver.useDayNight; + } + + public Builder setDefaultTheme(@StyleRes int defaultTheme) { + this.defaultTheme = defaultTheme; + return this; + } + + public Builder setOldestSupportedTheme(String oldestSupportedTheme) { + this.oldestSupportedTheme = oldestSupportedTheme; + return this; + } + + public Builder setUseDayNight(boolean useDayNight) { + this.useDayNight = useDayNight; + return this; + } + + public ThemeResolver build() { + return new ThemeResolver(defaultTheme, oldestSupportedTheme, useDayNight); + } + } +} |