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/toggle/toggle_model_ng.h"
17
18 #include "base/memory/ace_type.h"
19 #include "base/memory/referenced.h"
20 #include "base/utils/utils.h"
21 #include "core/components_ng/base/frame_node.h"
22 #include "core/components_ng/base/ui_node.h"
23 #include "core/components_ng/base/view_stack_processor.h"
24 #include "core/components_ng/base/view_abstract.h"
25 #include "core/components_ng/pattern/button/toggle_button_model_ng.h"
26 #include "core/components_ng/pattern/button/toggle_button_pattern.h"
27 #include "core/components_ng/pattern/checkbox/checkbox_model_ng.h"
28 #include "core/components_ng/pattern/checkbox/checkbox_pattern.h"
29 #include "core/components_ng/pattern/toggle/switch_paint_property.h"
30 #include "core/components_ng/pattern/toggle/switch_pattern.h"
31 #include "core/components_v2/inspector/inspector_constants.h"
32 #include "core/pipeline/base/element_register.h"
33 #include "core/pipeline_ng/ui_task_scheduler.h"
34 #include "core/components/toggle/toggle_theme.h"
35
36 namespace OHOS::Ace::NG {
37
Create(NG::ToggleType toggleType,bool isOn)38 void ToggleModelNG::Create(NG::ToggleType toggleType, bool isOn)
39 {
40 auto* stack = ViewStackProcessor::GetInstance();
41 int nodeId = stack->ClaimNodeId();
42 auto childFrameNode = FrameNode::GetFrameNode(V2::TOGGLE_ETS_TAG, nodeId);
43 if (!childFrameNode) {
44 switch (toggleType) {
45 case ToggleType::CHECKBOX: {
46 CheckBoxModelNG checkBoxModelNG;
47 CreateCheckbox(nodeId);
48 checkBoxModelNG.SetSelect(isOn);
49 break;
50 }
51 case ToggleType::SWITCH: {
52 CreateSwitch(nodeId);
53 ACE_UPDATE_PAINT_PROPERTY(SwitchPaintProperty, IsOn, isOn);
54 break;
55 }
56 case ToggleType::BUTTON: {
57 CreateButton(nodeId);
58 ToggleButtonModelNG::SetIsOn(isOn);
59 break;
60 }
61 default:
62 break;
63 }
64 return;
65 }
66 auto pattern = childFrameNode->GetPattern();
67 if (AceType::InstanceOf<CheckBoxPattern>(pattern)) {
68 if (toggleType == ToggleType::CHECKBOX) {
69 stack->Push(childFrameNode);
70 CheckBoxModelNG checkBoxModelNG;
71 checkBoxModelNG.SetSelect(isOn);
72 return;
73 }
74 if (toggleType == ToggleType::SWITCH) {
75 auto parentFrame = childFrameNode->GetParent();
76 CHECK_NULL_VOID(parentFrame);
77 auto index = RemoveNode(childFrameNode, nodeId);
78 childFrameNode->SetUndefinedNodeId();
79 CreateSwitch(nodeId);
80 ACE_UPDATE_PAINT_PROPERTY(SwitchPaintProperty, IsOn, isOn);
81 AddNewChild(parentFrame, nodeId, index);
82 return;
83 }
84 auto parentFrame = childFrameNode->GetParent();
85 CHECK_NULL_VOID(parentFrame);
86 auto index = RemoveNode(childFrameNode, nodeId);
87 childFrameNode->SetUndefinedNodeId();
88 CreateButton(nodeId);
89 ToggleButtonModelNG::SetIsOn(isOn);
90 AddNewChild(parentFrame, nodeId, index);
91 return;
92 }
93 if (AceType::InstanceOf<SwitchPattern>(pattern)) {
94 if (toggleType == ToggleType::SWITCH) {
95 stack->Push(childFrameNode);
96 ACE_UPDATE_PAINT_PROPERTY(SwitchPaintProperty, IsOn, isOn);
97 return;
98 }
99 if (toggleType == ToggleType::CHECKBOX) {
100 auto parentFrame = childFrameNode->GetParent();
101 CHECK_NULL_VOID(parentFrame);
102 auto index = RemoveNode(childFrameNode, nodeId);
103 childFrameNode->SetUndefinedNodeId();
104 CheckBoxModelNG checkBoxModelNG;
105 CreateCheckbox(nodeId);
106 checkBoxModelNG.SetSelect(isOn);
107 AddNewChild(parentFrame, nodeId, index);
108 return;
109 }
110 auto parentFrame = childFrameNode->GetParent();
111 CHECK_NULL_VOID(parentFrame);
112 auto index = RemoveNode(childFrameNode, nodeId);
113 childFrameNode->SetUndefinedNodeId();
114 CreateButton(nodeId);
115 ToggleButtonModelNG::SetIsOn(isOn);
116 AddNewChild(parentFrame, nodeId, index);
117 return;
118 }
119 if (AceType::InstanceOf<ToggleButtonPattern>(pattern)) {
120 if (toggleType == ToggleType::BUTTON) {
121 stack->Push(childFrameNode);
122 ToggleButtonModelNG::SetIsOn(isOn);
123 return;
124 }
125 if (toggleType == ToggleType::CHECKBOX) {
126 auto parentFrame = childFrameNode->GetParent();
127 CHECK_NULL_VOID(parentFrame);
128 auto index = RemoveNode(childFrameNode, nodeId);
129 childFrameNode->SetUndefinedNodeId();
130 CheckBoxModelNG checkBoxModelNG;
131 CreateCheckbox(nodeId);
132 checkBoxModelNG.SetSelect(isOn);
133 AddNewChild(parentFrame, nodeId, index);
134 return;
135 }
136 auto parentFrame = childFrameNode->GetParent();
137 CHECK_NULL_VOID(parentFrame);
138 auto index = RemoveNode(childFrameNode, nodeId);
139 childFrameNode->SetUndefinedNodeId();
140 CreateSwitch(nodeId);
141 ACE_UPDATE_PAINT_PROPERTY(SwitchPaintProperty, IsOn, isOn);
142 AddNewChild(parentFrame, nodeId, index);
143 }
144 }
145
SetSelectedColor(const std::optional<Color> & selectedColor)146 void ToggleModelNG::SetSelectedColor(const std::optional<Color>& selectedColor)
147 {
148 auto* stack = ViewStackProcessor::GetInstance();
149 CHECK_NULL_VOID(stack);
150 auto pipeline = PipelineBase::GetCurrentContext();
151 CHECK_NULL_VOID(pipeline);
152 Color color;
153 if (selectedColor.has_value()) {
154 color = selectedColor.value();
155 }
156
157 auto checkboxPattern = stack->GetMainFrameNodePattern<CheckBoxPattern>();
158 if (checkboxPattern) {
159 if (!selectedColor.has_value()) {
160 auto theme = pipeline->GetTheme<CheckboxTheme>();
161 CHECK_NULL_VOID(theme);
162 color = theme->GetActiveColor();
163 }
164 CheckBoxModelNG checkBoxModelNG;
165 checkBoxModelNG.SetSelectedColor(color);
166 return;
167 }
168 auto buttonPattern = stack->GetMainFrameNodePattern<ToggleButtonPattern>();
169 if (buttonPattern) {
170 if (!selectedColor.has_value()) {
171 auto theme = pipeline->GetTheme<ToggleTheme>();
172 CHECK_NULL_VOID(theme);
173 color = theme->GetCheckedColor();
174 }
175 ToggleButtonModelNG::SetSelectedColor(color);
176 return;
177 }
178
179 if (!selectedColor.has_value()) {
180 auto theme = pipeline->GetTheme<SwitchTheme>();
181 CHECK_NULL_VOID(theme);
182 color = theme->GetActiveColor();
183 }
184 ACE_UPDATE_PAINT_PROPERTY(SwitchPaintProperty, SelectedColor, color);
185 }
186
SetSwitchPointColor(const Color & switchPointColor)187 void ToggleModelNG::SetSwitchPointColor(const Color& switchPointColor)
188 {
189 ACE_UPDATE_PAINT_PROPERTY(SwitchPaintProperty, SwitchPointColor, switchPointColor);
190 }
OnChange(ChangeEvent && onChange)191 void ToggleModelNG::OnChange(ChangeEvent&& onChange)
192 {
193 auto* stack = ViewStackProcessor::GetInstance();
194 CHECK_NULL_VOID(stack);
195 auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
196 CHECK_NULL_VOID(frameNode);
197 auto checkboxPattern = stack->GetMainFrameNodePattern<CheckBoxPattern>();
198 if (checkboxPattern) {
199 auto eventHub = frameNode->GetEventHub<CheckBoxEventHub>();
200 CHECK_NULL_VOID(eventHub);
201 eventHub->SetOnChange(std::move(onChange));
202 return;
203 }
204 auto buttonPattern = stack->GetMainFrameNodePattern<ToggleButtonPattern>();
205 if (buttonPattern) {
206 auto eventHub = frameNode->GetEventHub<ToggleButtonEventHub>();
207 CHECK_NULL_VOID(eventHub);
208 eventHub->SetOnChange(std::move(onChange));
209 return;
210 }
211 auto eventHub = frameNode->GetEventHub<SwitchEventHub>();
212 CHECK_NULL_VOID(eventHub);
213 eventHub->SetOnChange(std::move(onChange));
214 }
215
SetWidth(const Dimension & width)216 void ToggleModelNG::SetWidth(const Dimension& width)
217 {
218 NG::ViewAbstract::SetWidth(NG::CalcLength(width));
219 }
220
SetHeight(const Dimension & height)221 void ToggleModelNG::SetHeight(const Dimension& height)
222 {
223 NG::ViewAbstract::SetHeight(NG::CalcLength(height));
224 }
225
SetBackgroundColor(const Color & color)226 void ToggleModelNG::SetBackgroundColor(const Color& color)
227 {
228 ToggleButtonModelNG::SetBackgroundColor(color);
229 }
230
IsToggle()231 bool ToggleModelNG::IsToggle()
232 {
233 return false;
234 }
235
SetPadding(const NG::PaddingPropertyF &,const NG::PaddingProperty & newArgs)236 void ToggleModelNG::SetPadding(const NG::PaddingPropertyF& /*args*/, const NG::PaddingProperty& newArgs)
237 {
238 NG::ViewAbstract::SetPadding(newArgs);
239 }
240
CreateCheckbox(int32_t nodeId)241 void ToggleModelNG::CreateCheckbox(int32_t nodeId)
242 {
243 auto* stack = ViewStackProcessor::GetInstance();
244 auto frameNode = FrameNode::GetOrCreateFrameNode(
245 V2::CHECKBOX_ETS_TAG, nodeId, []() { return AceType::MakeRefPtr<CheckBoxPattern>(); });
246 stack->Push(frameNode);
247 }
248
CreateSwitch(int32_t nodeId)249 void ToggleModelNG::CreateSwitch(int32_t nodeId)
250 {
251 auto* stack = ViewStackProcessor::GetInstance();
252 auto frameNode = FrameNode::GetOrCreateFrameNode(
253 V2::TOGGLE_ETS_TAG, nodeId, []() { return AceType::MakeRefPtr<SwitchPattern>(); });
254 stack->Push(frameNode);
255 }
256
CreateButton(int32_t nodeId)257 void ToggleModelNG::CreateButton(int32_t nodeId)
258 {
259 auto* stack = ViewStackProcessor::GetInstance();
260 auto frameNode = FrameNode::GetOrCreateFrameNode(
261 V2::TOGGLE_ETS_TAG, nodeId, []() { return AceType::MakeRefPtr<ToggleButtonPattern>(); });
262 stack->Push(frameNode);
263 }
264
AddNewChild(const RefPtr<UINode> & parentFrame,int32_t nodeId,int32_t index)265 void ToggleModelNG::AddNewChild(const RefPtr<UINode>& parentFrame, int32_t nodeId, int32_t index)
266 {
267 auto newFrameNode = FrameNode::GetFrameNode(V2::TOGGLE_ETS_TAG, nodeId);
268 parentFrame->AddChild(newFrameNode, index);
269 newFrameNode->MarkModifyDone();
270 }
271
RemoveNode(const RefPtr<FrameNode> & childFrameNode,int32_t nodeId)272 int32_t ToggleModelNG::RemoveNode(const RefPtr<FrameNode>& childFrameNode, int32_t nodeId)
273 {
274 ElementRegister::GetInstance()->RemoveItemSilently(nodeId);
275 auto parentFrame = childFrameNode->GetParent();
276 CHECK_NULL_RETURN(parentFrame, 0);
277 return parentFrame->RemoveChildAndReturnIndex(childFrameNode);
278 }
279
OnChangeEvent(ChangeEvent && onChangeEvent)280 void ToggleModelNG::OnChangeEvent(ChangeEvent&& onChangeEvent)
281 {
282 auto* stack = ViewStackProcessor::GetInstance();
283 CHECK_NULL_VOID(stack);
284 auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
285 CHECK_NULL_VOID(frameNode);
286 auto checkboxPattern = stack->GetMainFrameNodePattern<CheckBoxPattern>();
287 if (checkboxPattern) {
288 auto eventHub = frameNode->GetEventHub<CheckBoxEventHub>();
289 CHECK_NULL_VOID(eventHub);
290 eventHub->SetChangeEvent(std::move(onChangeEvent));
291 return;
292 }
293 auto buttonPattern = stack->GetMainFrameNodePattern<ToggleButtonPattern>();
294 if (buttonPattern) {
295 auto eventHub = frameNode->GetEventHub<ToggleButtonEventHub>();
296 CHECK_NULL_VOID(eventHub);
297 eventHub->SetOnChangeEvent(std::move(onChangeEvent));
298 return;
299 }
300 auto eventHub = frameNode->GetEventHub<SwitchEventHub>();
301 CHECK_NULL_VOID(eventHub);
302 eventHub->SetOnChangeEvent(std::move(onChangeEvent));
303 }
304
SetResponseRegion(const std::vector<DimensionRect> & responseRegion)305 void ToggleModelNG::SetResponseRegion(const std::vector<DimensionRect>& responseRegion)
306 {
307 NG::ViewAbstract::SetResponseRegion(responseRegion);
308 auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
309 CHECK_NULL_VOID(frameNode);
310 auto pattern = frameNode->GetPattern<SwitchPattern>();
311 CHECK_NULL_VOID(pattern);
312 pattern->SetIsUserSetResponseRegion(true);
313 }
314 } // namespace OHOS::Ace::NG
315