• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "core/components_ng/token_theme/token_theme_storage.h"
17 
18 #include <memory>
19 
20 #include "base/utils/utils.h"
21 #include "base/utils/system_properties.h"
22 #include "core/pipeline_ng/pipeline_context.h"
23 #include "core/common/resource/resource_parse_utils.h"
24 
25 namespace OHOS::Ace::NG {
26 
GetInstance()27 TokenThemeStorage* TokenThemeStorage::GetInstance()
28 {
29     static TokenThemeStorage instance;
30     return &instance;
31 }
32 
33 TokenThemeStorage::TokenThemeStorage() = default;
34 
StoreThemeScope(TokenThemeScopeId themeScopeId,int32_t themeId)35 void TokenThemeStorage::StoreThemeScope(TokenThemeScopeId themeScopeId, int32_t themeId)
36 {
37     themeScopeMap_[themeScopeId] = themeId;
38 }
39 
RemoveThemeScope(TokenThemeScopeId themeScopeId,bool removeToken)40 void TokenThemeStorage::RemoveThemeScope(TokenThemeScopeId themeScopeId, bool removeToken /* = false */)
41 {
42     if (removeToken) {
43         CacheRemove(themeScopeMap_[themeScopeId]);
44     }
45     themeScopeMap_.erase(themeScopeId);
46 }
47 
GetTheme(TokenThemeScopeId themeScopeId)48 const RefPtr<TokenTheme>& TokenThemeStorage::GetTheme(TokenThemeScopeId themeScopeId)
49 {
50     if (themeScopeId == 0) {
51         return GetDefaultTheme();
52     }
53     auto themeId = themeScopeMap_[themeScopeId];
54     return CacheGet(themeId);
55 }
56 
SetDefaultTheme(const RefPtr<TokenTheme> & theme,ColorMode colorMode)57 void TokenThemeStorage::SetDefaultTheme(const RefPtr<TokenTheme>& theme, ColorMode colorMode)
58 {
59     (colorMode == ColorMode::DARK ? defaultDarkTheme_ : defaultLightTheme_) = theme;
60 }
61 
UpdateDefaultThemeBySystemTheme(ColorMode colorMode)62 void TokenThemeStorage::UpdateDefaultThemeBySystemTheme(ColorMode colorMode)
63 {
64     RefPtr<TokenTheme>& theme = colorMode == ColorMode::DARK ? defaultDarkTheme_ : defaultLightTheme_;
65     if (!theme) {
66         return;
67     }
68     auto sysTheme = ObtainSystemTheme();
69     if (!sysTheme) {
70         return;
71     }
72     auto& colorsAvailable = colorMode == ColorMode::DARK ? darkThemeColorsAvailable_ : lightThemeColorsAvailable_;
73     for (size_t i = 0; i < TokenColors::TOTAL_NUMBER; i++) {
74         if (!colorsAvailable[i]) {
75             auto color = sysTheme->Colors()->GetByIndex(i);
76             theme->Colors()->SetColor(i, color);
77             colorsAvailable[i] = true;
78         }
79     }
80 }
81 
GetDefaultTheme()82 const RefPtr<TokenTheme>& TokenThemeStorage::GetDefaultTheme()
83 {
84     auto colorMode = CheckLocalAndSystemColorMode();
85     if (systemTokenThemeCreated_[static_cast<uint32_t>(colorMode)]) {
86         return colorMode == ColorMode::DARK ? defaultDarkTheme_ : defaultLightTheme_;
87     }
88 
89     UpdateDefaultThemeBySystemTheme(colorMode);
90     return colorMode == ColorMode::DARK ? defaultDarkTheme_ : defaultLightTheme_;
91 }
92 
CheckLocalAndSystemColorMode()93 ColorMode TokenThemeStorage::CheckLocalAndSystemColorMode()
94 {
95     auto sysColorMode = Container::CurrentColorMode();
96     auto pipelineContext = NG::PipelineContext::GetCurrentContext();
97     CHECK_NULL_RETURN(pipelineContext, sysColorMode);
98     auto colorMode = pipelineContext->GetLocalColorMode();
99     if (colorMode == ColorMode::COLOR_MODE_UNDEFINED) {
100         colorMode = sysColorMode;
101     }
102     return colorMode;
103 }
104 
CacheClear()105 void TokenThemeStorage::CacheClear()
106 {
107     std::lock_guard<std::mutex> lock(themeCacheMutex_);
108     themeCache_.clear();
109 }
110 
ResetThemeColor(int32_t themeId,RefPtr<TokenTheme> & theme,RefPtr<TokenTheme> & defaultTheme,ColorMode & colorMode)111 void TokenThemeStorage::ResetThemeColor(int32_t themeId, RefPtr<TokenTheme>& theme, RefPtr<TokenTheme>& defaultTheme,
112     ColorMode& colorMode)
113 {
114     auto resObjs = theme->GetResObjs();
115     if (resObjs.size() != TokenColors::TOTAL_NUMBER) {
116         return;
117     }
118     auto tokenColors = theme->Colors();
119     auto defaultColors = defaultTheme ? defaultTheme->Colors() : tokenColors;
120     auto userFlags = themeColorSetByUser_[themeId][(colorMode == ColorMode::DARK)];
121     for (int32_t i = 0; i < TokenColors::TOTAL_NUMBER; i++) {
122         if (!resObjs[i]) {
123             if (userFlags.size() == TokenColors::TOTAL_NUMBER && !userFlags[i]) {
124                 tokenColors->SetColor(i, defaultColors->GetByIndex(i));
125             }
126             continue;
127         }
128         Color colorValue;
129         auto state = ResourceParseUtils::ParseResColor(resObjs[i], colorValue);
130         if (!state) {
131             continue;
132         }
133         tokenColors->SetColor(i, colorValue);
134     }
135 }
136 
CacheResetColor()137 void TokenThemeStorage::CacheResetColor()
138 {
139     if (themeCache_.size() == 0) {
140         return;
141     }
142     auto colorMode = CheckLocalAndSystemColorMode();
143     auto defaultTheme = GetDefaultTheme();
144     if (!defaultTheme) {
145         defaultTheme = CreateSystemTokenTheme(colorMode);
146         SetDefaultTheme(defaultTheme, colorMode);
147         CacheSet(defaultTheme);
148     }
149     std::lock_guard<std::mutex> lock(themeCacheMutex_);
150     for (auto& [themeId, theme] : themeCache_) {
151         LOGD("Theme reset colors with id %{public}d", themeId);
152         if (!theme || (theme->GetColorMode() != ColorMode::COLOR_MODE_UNDEFINED)) {
153             continue;
154         }
155         ResetThemeColor(themeId, theme, defaultTheme, colorMode);
156     }
157 }
158 
CacheSet(const RefPtr<TokenTheme> & theme)159 void TokenThemeStorage::CacheSet(const RefPtr<TokenTheme>& theme)
160 {
161     CHECK_NULL_VOID(theme);
162     std::lock_guard<std::mutex> lock(themeCacheMutex_);
163     themeCache_[theme->GetId()] = theme;
164 }
165 
CacheGet(int32_t themeId)166 const RefPtr<TokenTheme>& TokenThemeStorage::CacheGet(int32_t themeId)
167 {
168     std::lock_guard<std::mutex> lock(themeCacheMutex_);
169     return themeCache_[themeId];
170 }
171 
CacheRemove(int32_t themeId)172 void TokenThemeStorage::CacheRemove(int32_t themeId)
173 {
174     std::lock_guard<std::mutex> lock(themeCacheMutex_);
175     themeCache_.erase(themeId);
176 }
177 
ObtainSystemTheme()178 RefPtr<TokenTheme> TokenThemeStorage::ObtainSystemTheme()
179 {
180     RefPtr<TokenTheme> theme = nullptr;
181     auto colorMode = CheckLocalAndSystemColorMode();
182     systemTokenThemeCreated_[static_cast<uint32_t>(colorMode)] = false;
183     if (colorMode == ColorMode::DARK) {
184         theme = CacheGet(TokenThemeStorage::SYSTEM_THEME_DARK_ID);
185     } else {
186         theme = CacheGet(TokenThemeStorage::SYSTEM_THEME_LIGHT_ID);
187     }
188     if (!theme) {
189         theme = CreateSystemTokenTheme(colorMode);
190         CacheSet(theme);
191     }
192     if (theme) {
193         systemTokenThemeCreated_[static_cast<uint32_t>(colorMode)] = true;
194     }
195     return theme;
196 }
197 
CreateSystemTokenTheme(ColorMode colorMode)198 RefPtr<TokenTheme> TokenThemeStorage::CreateSystemTokenTheme(ColorMode colorMode)
199 {
200     auto container = Container::Current();
201     CHECK_NULL_RETURN(container, nullptr);
202     auto pipelineContext = container->GetPipelineContext();
203     CHECK_NULL_RETURN(pipelineContext, nullptr);
204     auto themeManager = pipelineContext->GetThemeManager();
205     CHECK_NULL_RETURN(themeManager, nullptr);
206     auto themeConstants = themeManager->GetThemeConstants();
207     CHECK_NULL_RETURN(themeConstants, nullptr);
208 
209     auto themeId = colorMode == ColorMode::DARK ?
210         TokenThemeStorage::SYSTEM_THEME_DARK_ID : TokenThemeStorage::SYSTEM_THEME_LIGHT_ID;
211     auto tokenColors = AceType::MakeRefPtr<TokenColors>();
212     auto tokenDarkColors = AceType::MakeRefPtr<TokenColors>();
213     auto tokenTheme = AceType::MakeRefPtr<TokenTheme>(themeId);
214     tokenTheme->SetColors(tokenColors);
215     tokenTheme->SetDarkColors(tokenDarkColors);
216 
217     std::vector<Color> colors;
218     std::vector<Color> darkColors;
219     colors.reserve(TokenColors::TOTAL_NUMBER);
220     darkColors.reserve(TokenColors::TOTAL_NUMBER);
221     for (size_t resId = 0; resId < TokenColors::TOTAL_NUMBER; ++resId) {
222         colors.push_back(themeConstants->GetColor(TokenColors::GetSystemColorResIdByIndex(resId)));
223         darkColors.push_back(themeConstants->GetColor(TokenColors::GetSystemColorResIdByIndex(resId)));
224     }
225     tokenColors->SetColors(std::move(colors));
226     tokenDarkColors->SetColors(std::move(darkColors));
227     return tokenTheme;
228 }
229 
SetIsThemeColorAvailable(bool isDark,int32_t index,bool isColorAvailable)230 void TokenThemeStorage::SetIsThemeColorAvailable(bool isDark, int32_t index, bool isColorAvailable)
231 {
232     if (index >= 0 && index < TokenColors::TOTAL_NUMBER) {
233         auto& colorsAvailable = isDark ? darkThemeColorsAvailable_ : lightThemeColorsAvailable_;
234         colorsAvailable[index] = isColorAvailable;
235     }
236 }
237 
SetIsThemeColorSetByUser(int32_t themeId,bool isDark,int32_t index,bool isColorSetByUser)238 void TokenThemeStorage::SetIsThemeColorSetByUser(int32_t themeId, bool isDark, int32_t index, bool isColorSetByUser)
239 {
240     if (index < 0 || index >= TokenColors::TOTAL_NUMBER) {
241         return;
242     }
243     auto& themeIdMap = themeColorSetByUser_[themeId];
244     if (themeIdMap.find(isDark) == themeIdMap.end()) {
245         themeIdMap[isDark] = std::vector<bool> (TokenColors::TOTAL_NUMBER, false);
246     }
247     themeIdMap[isDark][index] = isColorSetByUser;
248 }
249 } // namespace OHOS::Ace::NG
250