1 /*
2  * Copyright (c) 2021 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 "frameworks/bridge/common/dom/dom_switch.h"
17 
18 #include "base/i18n/localization.h"
19 #include "frameworks/bridge/common/utils/utils.h"
20 
21 namespace OHOS::Ace::Framework {
22 namespace {
23 
24 constexpr Dimension BOX_HOVER_RADIUS = 8.0_vp;
25 
26 } // namespace
27 
DOMSwitch(NodeId nodeId,const std::string & nodeName)28 DOMSwitch::DOMSwitch(NodeId nodeId, const std::string& nodeName) : DOMNode(nodeId, nodeName)
29 {
30     switchChild_ = AceType::MakeRefPtr<SwitchComponent>(nullptr);
31     switchChild_->SetTextOn(Localization::GetInstance()->GetEntryLetters("switch.on"));
32     switchChild_->SetTextOff(Localization::GetInstance()->GetEntryLetters("switch.off"));
33 }
34 
InitializeStyle()35 void DOMSwitch::InitializeStyle()
36 {
37     ResetInitializedStyle();
38 }
39 
ResetInitializedStyle()40 void DOMSwitch::ResetInitializedStyle()
41 {
42     RefPtr<SwitchTheme> theme = GetTheme<SwitchTheme>();
43     if (theme) {
44         switchChild_->ApplyTheme(theme);
45     }
46     switchChild_->SetTextOn(Localization::GetInstance()->GetEntryLetters("switch.on"));
47     switchChild_->SetTextOff(Localization::GetInstance()->GetEntryLetters("switch.off"));
48 }
49 
SetSpecializedAttr(const std::pair<std::string,std::string> & attr)50 bool DOMSwitch::SetSpecializedAttr(const std::pair<std::string, std::string>& attr)
51 {
52     static const LinearMapNode<void (*)(const std::string&, SwitchComponent&, std::string&, std::string&)>
53         switchAttrOperators[] = {
54             { DOM_CHECKED, [](const std::string& val, SwitchComponent& textSwitch, std::string& textOn,
55                                std::string& textOff) { textSwitch.SetValue(StringToBool(val)); } },
56             { DOM_DISABLED, [](const std::string& val, SwitchComponent& textSwitch, std::string& textOn,
57                                 std::string& textOff) { textSwitch.SetDisabled(StringToBool(val)); } },
58             { DOM_SHOW_TEXT, [](const std::string& val, SwitchComponent& textSwitch, std::string& textOn,
59                                  std::string& textOff) { textSwitch.SetShowText(StringToBool(val)); } },
60             { DOM_TEXT_OFF,
61                 [](const std::string& val, SwitchComponent& textSwitch, std::string& textOn, std::string& textOff) {
62                     textSwitch.SetTextOff(val);
63                     textOff = val;
64                 } },
65             { DOM_TEXT_ON,
66                 [](const std::string& val, SwitchComponent& textSwitch, std::string& textOn, std::string& textOff) {
67                     textSwitch.SetTextOn(val);
68                     textOn = val;
69                 } },
70         };
71     auto operatorIter = BinarySearchFindIndex(
72         switchAttrOperators, ArraySize(switchAttrOperators), attr.first.c_str());
73     if (operatorIter != -1) {
74         switchAttrOperators[operatorIter].value(attr.second, *switchChild_, textOn_, textOff_);
75         return true;
76     }
77     return false;
78 }
79 
SetSpecializedStyle(const std::pair<std::string,std::string> & style)80 bool DOMSwitch::SetSpecializedStyle(const std::pair<std::string, std::string>& style)
81 {
82     static const LinearMapNode<void (*)(const std::string&, const DOMSwitch&, SwitchComponent&, TextStyle&)>
83         switchTextOperators[] = {
84             { DOM_TEXT_ALLOW_SCALE, [](const std::string& val, const DOMSwitch& node, SwitchComponent& textSwitch,
85                                     TextStyle& textStyle) { textStyle.SetAllowScale(StringToBool(val)); } },
86             { DOM_TEXT_FONT_FAMILY,
87                 [](const std::string& val, const DOMSwitch& node, SwitchComponent& textSwitch, TextStyle& textStyle) {
88                     textStyle.SetFontFamilies(node.ParseFontFamilies(val));
89                 } },
90             { DOM_TEXT_FONT_SIZE, [](const std::string& val, const DOMSwitch& node, SwitchComponent& textSwitch,
91                                   TextStyle& textStyle) { textStyle.SetFontSize(node.ParseDimension(val)); } },
92             { DOM_TEXT_FONT_STYLE, [](const std::string& val, const DOMSwitch& node, SwitchComponent& textSwitch,
93                                    TextStyle& textStyle) { textStyle.SetFontStyle(ConvertStrToFontStyle(val)); } },
94             { DOM_TEXT_FONT_WEIGHT, [](const std::string& val, const DOMSwitch& node, SwitchComponent& textSwitch,
95                                     TextStyle& textStyle) { textStyle.SetFontWeight(ConvertStrToFontWeight(val)); } },
96             { DOM_TEXT_LETTER_SPACING,
97                 [](const std::string& val, const DOMSwitch& node, SwitchComponent& textSwitch, TextStyle& textStyle) {
98                     textStyle.SetLetterSpacing(node.ParseDimension(val)); } },
99             { DOM_TEXT_DECORATION,
100                 [](const std::string& val, const DOMSwitch& node, SwitchComponent& textSwitch, TextStyle& textStyle) {
101                     textStyle.SetTextDecoration(ConvertStrToTextDecoration(val));
102                 } },
103             { DOM_TEXT_PADDING, [](const std::string& val, const DOMSwitch& node, SwitchComponent& textSwitch,
104                                 TextStyle& textStyle) { textSwitch.SetTextPadding(node.ParseDimension(val)); } },
105             { DOM_TEXT_OFF_COLOR, [](const std::string& val, const DOMSwitch& node, SwitchComponent& textSwitch,
106                                   TextStyle& textStyle) { textSwitch.SetTextColorOff(node.ParseColor(val)); } },
107             { DOM_TEXT_ON_COLOR, [](const std::string& val, const DOMSwitch& node, SwitchComponent& textSwitch,
108                                  TextStyle& textStyle) { textSwitch.SetTextColorOn(node.ParseColor(val)); } },
109         };
110     auto operatorIter = BinarySearchFindIndex(switchTextOperators, ArraySize(switchTextOperators), style.first.c_str());
111     if (operatorIter != -1) {
112         switchTextOperators[operatorIter].value(style.second, *this, *switchChild_, textStyle_);
113         return true;
114     }
115     return false;
116 }
117 
AddSpecializedEvent(int32_t pageId,const std::string & event)118 bool DOMSwitch::AddSpecializedEvent(int32_t pageId, const std::string& event)
119 {
120     if (event == DOM_CHANGE) {
121         changeEvent_ = EventMarker(GetNodeIdForEvent(), event, pageId);
122         switchChild_->SetChangeEvent(changeEvent_);
123         return true;
124     } else if (event == DOM_CLICK) {
125         EventMarker eventMarker(GetNodeIdForEvent(), event, pageId);
126         eventMarker.SetCatchMode(false);
127         switchChild_->SetClickEvent(eventMarker);
128     } else if (event == DOM_CATCH_BUBBLE_CLICK) {
129         EventMarker eventMarker(GetNodeIdForEvent(), event, pageId);
130         eventMarker.SetCatchMode(true);
131         switchChild_->SetClickEvent(eventMarker);
132     }
133     return false;
134 }
135 
PrepareCheckedListener()136 void DOMSwitch::PrepareCheckedListener()
137 {
138     auto weak = AceType::WeakClaim(this);
139     auto checkableChangeCallback = [weak](const std::string& checked) {
140         auto domNode = weak.Upgrade();
141         if (!domNode) {
142             return;
143         }
144         bool isChecked = checked.find("\"checked\":true") != std::string::npos;
145         std::string checkedString = isChecked ? "true" : "false";
146         domNode->SetSpecializedAttr(std::make_pair(DOM_CHECKED, checkedString));
147         domNode->OnChecked(isChecked);
148     };
149     auto checkableChangeMarker = BackEndEventManager<void(const std::string&)>::GetInstance().GetAvailableMarker();
150     BackEndEventManager<void(const std::string&)>::GetInstance().BindBackendEvent(
151         checkableChangeMarker, checkableChangeCallback);
152     switchChild_->SetDomChangeEvent(checkableChangeMarker);
153 }
154 
PrepareSpecializedComponent()155 void DOMSwitch::PrepareSpecializedComponent()
156 {
157     if (boxComponent_) {
158         boxComponent_->SetMouseAnimationType(HoverAnimationType::OPACITY);
159         if (!boxComponent_->GetBackDecoration()) {
160             RefPtr<Decoration> backDecoration = AceType::MakeRefPtr<Decoration>();
161             backDecoration->SetBorderRadius(Radius(BOX_HOVER_RADIUS));
162             boxComponent_->SetBackDecoration(backDecoration);
163         }
164     }
165     if (HasCheckedPseudo()) {
166         PrepareCheckedListener();
167     }
168     switchChild_->SetTextDirection(IsRightToLeft() ? TextDirection::RTL : TextDirection::LTR);
169     switchChild_->SetTextStyle(textStyle_);
170     if (!textOn_.empty()) {
171         switchChild_->SetTextOn(textOn_);
172     }
173     if (!textOff_.empty()) {
174         switchChild_->SetTextOff(textOff_);
175     }
176     RefPtr<SwitchTheme> theme = GetTheme<SwitchTheme>();
177     if (switchChild_->GetShowText()) {
178         return;
179     }
180     if (boxComponent_ && boxComponent_->GetHeightDimension().Value() < 0.0 && theme) {
181         boxComponent_->SetHeight(theme->GetHeight().Value(), theme->GetHeight().Unit());
182     }
183     if (boxComponent_ && boxComponent_->GetWidthDimension().Value() < 0.0 && theme) {
184         boxComponent_->SetWidth(theme->GetWidth().Value(), theme->GetWidth().Unit());
185     }
186 #ifndef WEARABLE_PRODUCT
187     if (declaration_) {
188         auto& multimodalAttr =
189             static_cast<CommonMultimodalAttribute&>(declaration_->GetAttribute(AttributeTag::COMMON_MULTIMODAL_ATTR));
190         if (multimodalAttr.IsValid() && !multimodalAttr.IsUnavailable() && multimodalAttr.scene == SceneLabel::SWITCH) {
191             switchChild_->SetMultimodalProperties(multimodalAttr);
192         }
193     }
194 #endif
195 }
196 
197 } // namespace OHOS::Ace::Framework
198