1 /*
2  * Copyright (c) 2022 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/pattern/navigation/bar_item_pattern.h"
17 #include "core/components_ng/pattern/image/image_pattern.h"
18 #include "core/components_ng/pattern/text/text_pattern.h"
19 #include "core/components_ng/pattern/image/image_layout_property.h"
20 
21 namespace OHOS::Ace::NG {
22 
OnModifyDone()23 void BarItemPattern::OnModifyDone()
24 {
25     Pattern::OnModifyDone();
26     auto host = GetHost();
27     CHECK_NULL_VOID(host);
28     auto gesture = host->GetOrCreateGestureEventHub();
29     CHECK_NULL_VOID(gesture);
30     CHECK_NULL_VOID(!clickListener_);
31     auto clickCallback = [weak = WeakClaim(this)](GestureEvent& /* info */) {
32         auto pattern = weak.Upgrade();
33         CHECK_NULL_VOID(pattern);
34         auto eventHub = pattern->GetEventHub<BarItemEventHub>();
35         CHECK_NULL_VOID(eventHub);
36         eventHub->FireItemAction();
37         pattern->UpdateBarItemActiveStatusResource();
38     };
39     if (clickListener_) {
40         gesture->RemoveClickEvent(clickListener_);
41     }
42     clickListener_ = MakeRefPtr<ClickEvent>(std::move(clickCallback));
43     gesture->AddClickEvent(clickListener_);
44 }
45 
UpdateSymbolDefaultEffect(RefPtr<TextLayoutProperty> symbolProperty,bool isActive)46 void UpdateSymbolDefaultEffect(RefPtr<TextLayoutProperty> symbolProperty, bool isActive)
47 {
48     CHECK_NULL_VOID(symbolProperty);
49     auto symbolEffectOptions = SymbolEffectOptions(SymbolEffectType::BOUNCE);
50     symbolEffectOptions.SetIsTxtActive(isActive);
51     symbolEffectOptions.SetIsTxtActiveSource(0);
52     symbolProperty->UpdateSymbolEffectOptions(symbolEffectOptions);
53 }
54 
UpdateSymbolBarButton(const RefPtr<BarItemNode> & barItemNode,const RefPtr<FrameNode> & iconNode,const Color & iconColor,std::function<void (WeakPtr<NG::FrameNode>)> & symbol,ImageSourceInfo & info)55 void UpdateSymbolBarButton(const RefPtr<BarItemNode>& barItemNode, const RefPtr<FrameNode>& iconNode,
56     const Color& iconColor, std::function<void(WeakPtr<NG::FrameNode>)>& symbol, ImageSourceInfo& info)
57 {
58     auto theme = NavigationGetTheme();
59     CHECK_NULL_VOID(theme);
60     auto iconSize = theme->GetToolbarIconSize();
61     if (symbol != nullptr) {
62         // symbol -> symbol
63         auto symbolProperty = iconNode->GetLayoutProperty<TextLayoutProperty>();
64         CHECK_NULL_VOID(symbolProperty);
65         symbolProperty->UpdateSymbolColorList({iconColor});
66         // User-defined color overrides the default color of the theme
67         symbol(AccessibilityManager::WeakClaim(AccessibilityManager::RawPtr(iconNode)));
68         UpdateSymbolDefaultEffect(symbolProperty, false);
69         symbolProperty->UpdateFontSize(iconSize);
70         iconNode->MarkModifyDone();
71         iconNode->MarkDirtyNode();
72     } else {
73         // symbol -> image
74         barItemNode->RemoveChild(iconNode);
75         auto iconNodeNew = FrameNode::CreateFrameNode(V2::IMAGE_ETS_TAG,
76             ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<ImagePattern>());
77         auto imageLayoutProperty = iconNodeNew->GetLayoutProperty<ImageLayoutProperty>();
78         CHECK_NULL_VOID(imageLayoutProperty);
79         imageLayoutProperty->UpdateImageSourceInfo(info);
80         imageLayoutProperty->UpdateUserDefinedIdealSize(CalcSize(CalcLength(iconSize), CalcLength(iconSize)));
81         iconNodeNew->MarkModifyDone();
82         iconNodeNew->MarkDirtyNode();
83         barItemNode->SetIconNode(iconNodeNew);
84         barItemNode->AddChild(iconNodeNew);
85     }
86 }
87 
UpdateImageBarButton(const RefPtr<BarItemNode> & barItemNode,const RefPtr<FrameNode> & iconNode,const Color & iconColor,std::function<void (WeakPtr<NG::FrameNode>)> & symbol,ImageSourceInfo & info)88 void UpdateImageBarButton(const RefPtr<BarItemNode>& barItemNode, const RefPtr<FrameNode>& iconNode,
89     const Color& iconColor, std::function<void(WeakPtr<NG::FrameNode>)>& symbol, ImageSourceInfo& info)
90 {
91     auto theme = NavigationGetTheme();
92     CHECK_NULL_VOID(theme);
93     auto iconSize = theme->GetToolbarIconSize();
94     if (symbol != nullptr) {
95         // image -> symbol
96         barItemNode->RemoveChild(iconNode);
97         auto iconNodeNew = FrameNode::GetOrCreateFrameNode(V2::SYMBOL_ETS_TAG,
98             ElementRegister::GetInstance()->MakeUniqueId(), []() { return AceType::MakeRefPtr<TextPattern>(); });
99         CHECK_NULL_VOID(iconNodeNew);
100         auto symbolProperty = iconNodeNew->GetLayoutProperty<TextLayoutProperty>();
101         CHECK_NULL_VOID(symbolProperty);
102         auto symbolEffectOptions = symbolProperty->GetSymbolEffectOptionsValue(SymbolEffectOptions());
103         symbolEffectOptions.SetEffectType(SymbolEffectType::BOUNCE);
104         symbolEffectOptions.SetIsTxtActive(true);
105         symbolEffectOptions.SetIsTxtActiveSource(0);
106         symbolProperty->UpdateSymbolEffectOptions(symbolEffectOptions);
107         symbolProperty->UpdateSymbolColorList({ iconColor });
108         symbol(AccessibilityManager::WeakClaim(AccessibilityManager::RawPtr(iconNodeNew)));
109         symbolProperty->UpdateFontSize(iconSize);
110         UpdateSymbolDefaultEffect(symbolProperty, false);
111         iconNodeNew->MarkModifyDone();
112         iconNodeNew->MarkDirtyNode();
113         barItemNode->SetIconNode(iconNodeNew);
114         barItemNode->AddChild(iconNodeNew);
115     } else {
116         // image -> image
117         auto imageLayoutProperty = iconNode->GetLayoutProperty<ImageLayoutProperty>();
118         CHECK_NULL_VOID(imageLayoutProperty);
119         imageLayoutProperty->UpdateImageSourceInfo(info);
120         iconNode->MarkModifyDone();
121         iconNode->MarkDirtyNode();
122     }
123 }
124 
UpdateSymbolEffect(const RefPtr<FrameNode> & iconNode)125 void UpdateSymbolEffect(const RefPtr<FrameNode>& iconNode)
126 {
127     auto symbolProperty = iconNode->GetLayoutProperty<TextLayoutProperty>();
128     CHECK_NULL_VOID(symbolProperty);
129     auto symbolEffectOptions = symbolProperty->GetSymbolEffectOptionsValue(SymbolEffectOptions());
130     symbolEffectOptions.SetEffectType(SymbolEffectType::BOUNCE);
131     symbolEffectOptions.SetIsTxtActive(true);
132     symbolEffectOptions.SetIsTxtActiveSource(0);
133     symbolProperty->UpdateSymbolEffectOptions(symbolEffectOptions);
134     iconNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
135 }
136 
UpdateBarItemActiveStatusResource()137 void BarItemPattern::UpdateBarItemActiveStatusResource()
138 {
139     auto theme = NavigationGetTheme();
140     CHECK_NULL_VOID(theme);
141 
142     auto barItemNode = AceType::DynamicCast<BarItemNode>(GetHost());
143     CHECK_NULL_VOID(barItemNode);
144     auto status = GetToolbarItemStatus();
145     auto iconStatus = GetCurrentIconStatus();
146 
147     auto iconNode = DynamicCast<FrameNode>(barItemNode->GetIconNode());
148     CHECK_NULL_VOID(iconNode);
149 
150     if (iconNode->GetTag() == V2::SYMBOL_ETS_TAG) {
151         UpdateSymbolEffect(iconNode);
152     }
153 
154     auto textNode = DynamicCast<FrameNode>(barItemNode->GetTextNode());
155     CHECK_NULL_VOID(textNode);
156     auto textLayoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
157     CHECK_NULL_VOID(textLayoutProperty);
158 
159     ImageSourceInfo info;
160     ToolbarIconStatus barIconStatus;
161     Color textColor;
162     Color iconColor;
163     std::function<void(WeakPtr<NG::FrameNode>)> symbol;
164     if (iconStatus == ToolbarIconStatus::INITIAL) {
165         info = GetActiveIconImageSourceInfo();
166         barIconStatus = ToolbarIconStatus::ACTIVE;
167         textColor = theme->GetToolBarItemActiveFontColor();
168         symbol = GetActiveIconSymbol();
169         iconColor = theme->GetToolbarActiveIconColor();
170     }
171     if (iconStatus == ToolbarIconStatus::ACTIVE) {
172         info = GetInitialIconImageSourceInfo();
173         barIconStatus = ToolbarIconStatus::INITIAL;
174         textColor = theme->GetToolBarItemFontColor();
175         symbol = GetInitialIconSymbol();
176         iconColor = theme->GetToolbarIconColor();
177     }
178 
179     if (status == NavToolbarItemStatus::ACTIVE) {
180         if (iconNode->GetTag() == V2::SYMBOL_ETS_TAG) {
181             UpdateSymbolBarButton(barItemNode, iconNode, iconColor, symbol, info);
182         } else {
183             UpdateImageBarButton(barItemNode, iconNode, iconColor, symbol, info);
184         }
185         barItemNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
186         barItemNode->MarkDirtyNode();
187         textLayoutProperty->UpdateTextColor(textColor);
188         textNode->MarkModifyDone();
189         textNode->MarkDirtyNode();
190         SetCurrentIconStatus(barIconStatus);
191     }
192 }
193 
ToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const194 void BarItemPattern::ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
195 {
196     Pattern::ToJsonValue(json, filter);
197 
198     /* no fixed attr below, just return */
199     if (filter.IsFastFilter()) {
200         return;
201     }
202 
203     auto barItemNode = AceType::DynamicCast<BarItemNode>(GetHost());
204     CHECK_NULL_VOID(barItemNode);
205     auto textNode = AceType::DynamicCast<FrameNode>(barItemNode->GetTextNode());
206     CHECK_NULL_VOID(textNode);
207     auto textLayoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
208     CHECK_NULL_VOID(textLayoutProperty);
209     json->PutExtAttr("label", textLayoutProperty->GetContentValue("").c_str(), filter);
210 }
211 } // namespace OHOS::Ace::NG
212