• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.android.setupwizardlib.util;
2 
3 import android.app.Activity;
4 import android.content.Intent;
5 import androidx.annotation.Nullable;
6 import androidx.annotation.StyleRes;
7 import com.android.setupwizardlib.R;
8 
9 /**
10  * A resolver to resolve the theme from a string or an activity intent, setting options like the
11  * default theme and the oldest supported theme. Apps can share the resolver across the entire
12  * process by calling {@link #setDefault(ThemeResolver)} in {@link
13  * android.app.Application#onCreate()}. If an app needs more granular sharing of the theme default
14  * values, additional instances of {@link ThemeResolver} can be created using the builder.
15  */
16 public class ThemeResolver {
17   @StyleRes private final int defaultTheme;
18   @Nullable private final String oldestSupportedTheme;
19   private final boolean useDayNight;
20 
21   @Nullable private static ThemeResolver defaultResolver;
22 
23   /**
24    * Sets the default instance used for the whole process. Can be null to reset the default to the
25    * preset one.
26    */
setDefault(@ullable ThemeResolver resolver)27   public static void setDefault(@Nullable ThemeResolver resolver) {
28     defaultResolver = resolver;
29   }
30 
31   /**
32    * Returns the default instance, which can be changed using {@link #setDefault(ThemeResolver)}.
33    */
getDefault()34   public static ThemeResolver getDefault() {
35     if (defaultResolver == null) {
36       defaultResolver =
37           new ThemeResolver.Builder()
38               .setDefaultTheme(R.style.SuwThemeGlif_DayNight)
39               .setUseDayNight(true)
40               .build();
41     }
42     return defaultResolver;
43   }
44 
ThemeResolver( int defaultTheme, @Nullable String oldestSupportedTheme, boolean useDayNight)45   private ThemeResolver(
46       int defaultTheme, @Nullable String oldestSupportedTheme, boolean useDayNight) {
47     this.defaultTheme = defaultTheme;
48     this.oldestSupportedTheme = oldestSupportedTheme;
49     this.useDayNight = useDayNight;
50   }
51 
52   /**
53    * Returns the style for the theme specified in the intent extra. If the specified string theme is
54    * older than the oldest supported theme, the default will be returned instead. Note that the
55    * default theme is returned without processing -- it may not be a DayNight theme even if {@link
56    * #useDayNight} is true.
57    */
58   @StyleRes
resolve(Intent intent)59   public int resolve(Intent intent) {
60     return resolve(
61         intent.getStringExtra(WizardManagerHelper.EXTRA_THEME),
62         /* suppressDayNight= */ WizardManagerHelper.isSetupWizardIntent(intent));
63   }
64 
65   /**
66    * Returns the style for the given string theme. If the specified string theme is older than the
67    * oldest supported theme, the default will be returned instead. Note that the default theme is
68    * returned without processing -- it may not be a DayNight theme even if {@link #useDayNight} is
69    * true.
70    */
71   @StyleRes
resolve(@ullable String theme)72   public int resolve(@Nullable String theme) {
73     return resolve(theme, /* suppressDayNight= */ false);
74   }
75 
76   @StyleRes
resolve(@ullable String theme, boolean suppressDayNight)77   private int resolve(@Nullable String theme, boolean suppressDayNight) {
78     int themeResource =
79         useDayNight && !suppressDayNight ? getDayNightThemeRes(theme) : getThemeRes(theme);
80     if (themeResource == 0) {
81       return defaultTheme;
82     }
83 
84     if (oldestSupportedTheme != null && compareThemes(theme, oldestSupportedTheme) < 0) {
85       return defaultTheme;
86     }
87     return themeResource;
88   }
89 
90   /** Reads the theme from the intent, and applies the resolved theme to the activity. */
applyTheme(Activity activity)91   public void applyTheme(Activity activity) {
92     activity.setTheme(resolve(activity.getIntent()));
93   }
94 
95   /**
96    * Returns the corresponding DayNight theme resource ID for the given string theme. DayNight
97    * themes are themes that will be either light or dark depending on the system setting. For
98    * example, the string {@link WizardManagerHelper#THEME_GLIF_LIGHT} will return
99    * {@code @style/SuwThemeGlif.DayNight}.
100    */
101   @StyleRes
getDayNightThemeRes(@ullable String theme)102   private static int getDayNightThemeRes(@Nullable String theme) {
103     if (theme != null) {
104       switch (theme) {
105         case WizardManagerHelper.THEME_GLIF_V3_LIGHT:
106         case WizardManagerHelper.THEME_GLIF_V3:
107           return R.style.SuwThemeGlifV3_DayNight;
108         case WizardManagerHelper.THEME_GLIF_V2_LIGHT:
109         case WizardManagerHelper.THEME_GLIF_V2:
110           return R.style.SuwThemeGlifV2_DayNight;
111         case WizardManagerHelper.THEME_GLIF_LIGHT:
112         case WizardManagerHelper.THEME_GLIF:
113           return R.style.SuwThemeGlif_DayNight;
114         case WizardManagerHelper.THEME_MATERIAL_LIGHT:
115         case WizardManagerHelper.THEME_MATERIAL:
116           return R.style.SuwThemeMaterial_DayNight;
117         default:
118           // fall through
119       }
120     }
121     return 0;
122   }
123 
124   /**
125    * Returns the theme resource ID for the given string theme. For example, the string {@link
126    * WizardManagerHelper#THEME_GLIF_LIGHT} will return {@code @style/SuwThemeGlif.Light}.
127    */
128   @StyleRes
getThemeRes(@ullable String theme)129   private static int getThemeRes(@Nullable String theme) {
130     if (theme != null) {
131       switch (theme) {
132         case WizardManagerHelper.THEME_GLIF_V3_LIGHT:
133           return R.style.SuwThemeGlifV3_Light;
134         case WizardManagerHelper.THEME_GLIF_V3:
135           return R.style.SuwThemeGlifV3;
136         case WizardManagerHelper.THEME_GLIF_V2_LIGHT:
137           return R.style.SuwThemeGlifV2_Light;
138         case WizardManagerHelper.THEME_GLIF_V2:
139           return R.style.SuwThemeGlifV2;
140         case WizardManagerHelper.THEME_GLIF_LIGHT:
141           return R.style.SuwThemeGlif_Light;
142         case WizardManagerHelper.THEME_GLIF:
143           return R.style.SuwThemeGlif;
144         case WizardManagerHelper.THEME_MATERIAL_LIGHT:
145           return R.style.SuwThemeMaterial_Light;
146         case WizardManagerHelper.THEME_MATERIAL:
147           return R.style.SuwThemeMaterial;
148         default:
149           // fall through
150       }
151     }
152     return 0;
153   }
154 
155   /** Compares whether the versions of {@code theme1} and {@code theme2} to check which is newer. */
compareThemes(String theme1, String theme2)156   private static int compareThemes(String theme1, String theme2) {
157     return Integer.valueOf(getThemeVersion(theme1)).compareTo(getThemeVersion(theme2));
158   }
159 
160   /**
161    * Returns the version of the theme. The absolute number of the theme version is not defined, but
162    * a larger number in the version indicates a newer theme.
163    */
getThemeVersion(String theme)164   private static int getThemeVersion(String theme) {
165     if (theme != null) {
166       switch (theme) {
167         case WizardManagerHelper.THEME_GLIF_V3_LIGHT:
168         case WizardManagerHelper.THEME_GLIF_V3:
169           return 4;
170         case WizardManagerHelper.THEME_GLIF_V2_LIGHT:
171         case WizardManagerHelper.THEME_GLIF_V2:
172           return 3;
173         case WizardManagerHelper.THEME_GLIF_LIGHT:
174         case WizardManagerHelper.THEME_GLIF:
175           return 2;
176         case WizardManagerHelper.THEME_MATERIAL_LIGHT:
177         case WizardManagerHelper.THEME_MATERIAL:
178           return 1;
179         default:
180           // fall through
181       }
182     }
183     return -1;
184   }
185 
186   /** Builder class for {@link ThemeResolver}. */
187   public static class Builder {
188     @StyleRes private int defaultTheme = R.style.SuwThemeGlif_DayNight;
189     @Nullable private String oldestSupportedTheme = null;
190     private boolean useDayNight = true;
191 
Builder()192     public Builder() {}
193 
Builder(ThemeResolver themeResolver)194     public Builder(ThemeResolver themeResolver) {
195       this.defaultTheme = themeResolver.defaultTheme;
196       this.oldestSupportedTheme = themeResolver.oldestSupportedTheme;
197       this.useDayNight = themeResolver.useDayNight;
198     }
199 
setDefaultTheme(@tyleRes int defaultTheme)200     public Builder setDefaultTheme(@StyleRes int defaultTheme) {
201       this.defaultTheme = defaultTheme;
202       return this;
203     }
204 
setOldestSupportedTheme(String oldestSupportedTheme)205     public Builder setOldestSupportedTheme(String oldestSupportedTheme) {
206       this.oldestSupportedTheme = oldestSupportedTheme;
207       return this;
208     }
209 
setUseDayNight(boolean useDayNight)210     public Builder setUseDayNight(boolean useDayNight) {
211       this.useDayNight = useDayNight;
212       return this;
213     }
214 
build()215     public ThemeResolver build() {
216       return new ThemeResolver(defaultTheme, oldestSupportedTheme, useDayNight);
217     }
218   }
219 }
220