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/interfaces/native/node/theme_modifier.h"
17
18 #include "core/components/common/properties/color.h"
19 #include "core/components_ng/syntax/with_theme_node.h"
20 #include "core/components_ng/token_theme/token_theme.h"
21 #include "core/components_ng/token_theme/token_theme_storage.h"
22 #include "core/pipeline_ng/pipeline_context.h"
23
24 namespace OHOS::Ace::NG {
25 namespace ThemeModifier {
26 namespace {
MapNumberToColorMode(int32_t number)27 ColorMode MapNumberToColorMode(int32_t number)
28 {
29 switch (number) {
30 case 1: // 1 is the ThemeColorMode.LIGHT
31 return ColorMode::LIGHT;
32 case 2: // 2 is the ThemeColorMode.DARK
33 return ColorMode::DARK;
34 default:
35 return ColorMode::COLOR_MODE_UNDEFINED;
36 }
37 return ColorMode::COLOR_MODE_UNDEFINED;
38 }
39
ConvertColorArrayToTokenColors(const ArkUI_Uint32 * colorsArray)40 RefPtr<TokenColors> ConvertColorArrayToTokenColors(const ArkUI_Uint32* colorsArray)
41 {
42 std::vector<Color> colors;
43 colors.reserve(TokenColors::TOTAL_NUMBER);
44 for (int i = 0; i < TokenColors::TOTAL_NUMBER; i++) {
45 colors.push_back(Color(colorsArray[i]));
46 }
47 auto themeColors = AceType::MakeRefPtr<TokenColors>();
48 themeColors->SetColors(std::move(colors));
49 return themeColors;
50 }
51
ConvertResObjArray(const void * resObjs)52 std::vector<RefPtr<ResourceObject>> ConvertResObjArray(const void* resObjs)
53 {
54 auto resourceObjs = *(static_cast<const std::vector<RefPtr<ResourceObject>>*>(resObjs));
55 return resourceObjs;
56 }
57 } // namespace
58
CreateWithThemeNode(ArkUI_Int32 id)59 ArkUINodeHandle CreateWithThemeNode(ArkUI_Int32 id)
60 {
61 TAG_LOGD(AceLogTag::ACE_DEFAULT_DOMAIN, "WithTheme CreateWithThemeNode id:%{public}d", id);
62 auto withThemeNode = WithThemeNode::CreateWithThemeNode(id);
63 withThemeNode->IncRefCount();
64 return reinterpret_cast<ArkUINodeHandle>(OHOS::Ace::AceType::RawPtr(withThemeNode));
65 }
66
GetWithThemeNode(ArkUI_Int32 id)67 ArkUINodeHandle GetWithThemeNode(ArkUI_Int32 id)
68 {
69 auto withThemeNode = WithThemeNode::GetWithThemeNode(id);
70 return reinterpret_cast<ArkUINodeHandle>(OHOS::Ace::AceType::RawPtr(withThemeNode));
71 }
72
CreateTheme(ArkUI_Int32 themeId,const ArkUI_Uint32 * colors,const ArkUI_Uint32 * darkColors,ArkUI_Int32 colorMode,const void * lightResObjs,const void * darkResObjs)73 ArkUINodeHandle CreateTheme(ArkUI_Int32 themeId, const ArkUI_Uint32* colors, const ArkUI_Uint32* darkColors,
74 ArkUI_Int32 colorMode, const void* lightResObjs, const void* darkResObjs)
75 {
76 auto theme = TokenThemeStorage::GetInstance()->CacheGet(themeId);
77 if (!theme) {
78 TAG_LOGD(AceLogTag::ACE_DEFAULT_DOMAIN, "WithTheme CreateTheme themeId:%{public}d colorMode num:%{public}d",
79 themeId, colorMode);
80 ColorMode themeScopeColorMode = MapNumberToColorMode(colorMode);
81 auto themeColors = ConvertColorArrayToTokenColors(colors);
82 auto themeDarkColors = ConvertColorArrayToTokenColors(darkColors);
83 theme = AceType::MakeRefPtr<TokenTheme>(themeId);
84 theme->SetColors(themeColors);
85 theme->SetDarkColors(themeDarkColors);
86 theme->SetColorMode(themeScopeColorMode);
87 auto lightResourceObjs = ConvertResObjArray(lightResObjs);
88 auto darkResourceObjs = ConvertResObjArray(darkResObjs);
89 theme->SetResObjs(std::move(lightResourceObjs));
90 theme->SetDarkResObjs(std::move(darkResourceObjs));
91 TokenThemeStorage::GetInstance()->CacheSet(theme);
92 }
93 return reinterpret_cast<ArkUINodeHandle>(OHOS::Ace::AceType::RawPtr(theme));
94 }
95
CreateThemeScope(ArkUINodeHandle node,ArkUINodeHandle theme)96 void CreateThemeScope(ArkUINodeHandle node, ArkUINodeHandle theme)
97 {
98 RefPtr<WithThemeNode> withThemeNode = AceType::Claim(reinterpret_cast<WithThemeNode*>(node));
99 CHECK_NULL_VOID(withThemeNode);
100 RefPtr<TokenTheme> tokenTheme = AceType::Claim(reinterpret_cast<TokenTheme*>(theme));
101 CHECK_NULL_VOID(tokenTheme);
102 TokenThemeStorage::GetInstance()->StoreThemeScope(withThemeNode->GetId(), tokenTheme->GetId());
103 TAG_LOGD(AceLogTag::ACE_DEFAULT_DOMAIN, "WithTheme CreateThemeScope and notify node:%{public}d theme:%{public}d",
104 withThemeNode->GetId(), tokenTheme->GetId());
105 withThemeNode->NotifyThemeScopeUpdate();
106 }
107
SetDefaultTheme(const ArkUI_Uint32 * colors,ArkUI_Bool isDark,const void * resObjs)108 void SetDefaultTheme(const ArkUI_Uint32* colors, ArkUI_Bool isDark, const void* resObjs)
109 {
110 TAG_LOGD(AceLogTag::ACE_DEFAULT_DOMAIN, "WithTheme SetDefaultTheme isDark:%{public}d", isDark);
111 auto themeColors = ConvertColorArrayToTokenColors(colors);
112 auto resourceObjs = ConvertResObjArray(resObjs);
113 auto theme = AceType::MakeRefPtr<TokenTheme>(0);
114 if (isDark) {
115 theme->SetDarkColors(themeColors);
116 theme->SetDarkResObjs(std::move(resourceObjs));
117 } else {
118 theme->SetColors(themeColors);
119 theme->SetResObjs(std::move(resourceObjs));
120 }
121 auto colorMode = isDark ? ColorMode::DARK : ColorMode::LIGHT;
122 TokenThemeStorage::GetInstance()->SetDefaultTheme(theme, colorMode);
123
124 // global notify if required
125 auto pipelineContext = PipelineContext::GetCurrentContext();
126 CHECK_NULL_VOID(pipelineContext);
127 auto sysColorMode = pipelineContext->GetColorMode();
128 if (sysColorMode != colorMode) {
129 return;
130 }
131 auto rootNode = pipelineContext->GetRootElement();
132 CHECK_NULL_VOID(rootNode);
133 rootNode->UpdateThemeScopeUpdate(0); // 0 means default theme scope id
134 }
135
RemoveFromCache(ArkUI_Int32 themeId)136 void RemoveFromCache(ArkUI_Int32 themeId)
137 {
138 TokenThemeStorage::GetInstance()->CacheRemove(themeId);
139 }
140
SetOnThemeScopeDestroy(ArkUINodeHandle node,void * callback)141 void SetOnThemeScopeDestroy(ArkUINodeHandle node, void* callback)
142 {
143 RefPtr<WithThemeNode> withThemeNode = AceType::Claim(reinterpret_cast<WithThemeNode*>(node));
144 if (callback && withThemeNode) {
145 auto cb = reinterpret_cast<std::function<void()>*>(callback);
146 withThemeNode->SetOnThemeScopeDestroy(std::move(*cb));
147 }
148 }
149
GetThemeScopeId(ArkUINodeHandle node)150 ArkUI_Int32 GetThemeScopeId(ArkUINodeHandle node)
151 {
152 auto ui_node = reinterpret_cast<UINode*>(node);
153 CHECK_NULL_RETURN(ui_node, 0);
154 return ui_node->GetThemeScopeId();
155 }
156 } // namespace ThemeModifier
157 namespace NodeModifier {
GetThemeModifier()158 const ArkUIThemeModifier* GetThemeModifier()
159 {
160 CHECK_INITIALIZED_FIELDS_BEGIN(); // don't move this line
161 static const ArkUIThemeModifier modifier = {
162 .createWithThemeNode = ThemeModifier::CreateWithThemeNode,
163 .getWithThemeNode = ThemeModifier::GetWithThemeNode,
164 .createTheme = ThemeModifier::CreateTheme,
165 .createThemeScope = ThemeModifier::CreateThemeScope,
166 .setDefaultTheme = ThemeModifier::SetDefaultTheme,
167 .removeFromCache = ThemeModifier::RemoveFromCache,
168 .setOnThemeScopeDestroy = ThemeModifier::SetOnThemeScopeDestroy,
169 .getThemeScopeId = ThemeModifier::GetThemeScopeId,
170 };
171 CHECK_INITIALIZED_FIELDS_END(modifier, 0, 0, 0); // don't move this line
172 return &modifier;
173 }
174 } // namespace NodeModifier
175 } // namespace OHOS::Ace::NG