• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/button/toggle_button_pattern.h"
17 
18 #include "base/memory/ace_type.h"
19 #include "base/utils/utils.h"
20 #include "core/components/button/button_theme.h"
21 #include "core/components/common/properties/color.h"
22 #include "core/components/toggle/toggle_theme.h"
23 #include "core/components_ng/base/ui_node.h"
24 #include "core/components_ng/pattern/button/toggle_button_paint_property.h"
25 #include "core/components_ng/pattern/text/text_layout_property.h"
26 #include "core/components_ng/property/property.h"
27 #include "core/pipeline/pipeline_base.h"
28 
29 namespace OHOS::Ace::NG {
30 
OnAttachToFrameNode()31 void ToggleButtonPattern::OnAttachToFrameNode()
32 {
33     InitParameters();
34 }
35 
InitParameters()36 void ToggleButtonPattern::InitParameters()
37 {
38     auto pipeline = PipelineBase::GetCurrentContext();
39     CHECK_NULL_VOID(pipeline);
40     auto toggleTheme = pipeline->GetTheme<ToggleTheme>();
41     CHECK_NULL_VOID(toggleTheme);
42     checkedColor_ = toggleTheme->GetCheckedColor();
43     unCheckedColor_ = toggleTheme->GetBackgroundColor();
44     textMargin_ = toggleTheme->GetTextMargin();
45     buttonMargin_ = toggleTheme->GetButtonMargin();
46     buttonHeight_ = toggleTheme->GetButtonHeight();
47     buttonRadius_ = toggleTheme->GetButtonRadius();
48     textFontSize_ = toggleTheme->GetTextFontSize();
49     textColor_ = toggleTheme->GetTextColor();
50     disabledAlpha_ = toggleTheme->GetDisabledAlpha();
51     auto buttonTheme = pipeline->GetTheme<ButtonTheme>();
52     CHECK_NULL_VOID(buttonTheme);
53     clickedColor_ = buttonTheme->GetClickedColor();
54 }
55 
OnModifyDone()56 void ToggleButtonPattern::OnModifyDone()
57 {
58     auto host = GetHost();
59     CHECK_NULL_VOID(host);
60 
61     auto layoutProperty = host->GetLayoutProperty();
62     CHECK_NULL_VOID(layoutProperty);
63     if (layoutProperty->GetPositionProperty()) {
64         layoutProperty->UpdateAlignment(
65             layoutProperty->GetPositionProperty()->GetAlignment().value_or(Alignment::CENTER));
66     } else {
67         layoutProperty->UpdateAlignment(Alignment::CENTER);
68     }
69 
70     auto buttonPaintProperty = GetPaintProperty<ToggleButtonPaintProperty>();
71     CHECK_NULL_VOID(buttonPaintProperty);
72     if (!isOn_.has_value()) {
73         isOn_ = buttonPaintProperty->GetIsOnValue();
74     }
75     bool changed = false;
76     if (buttonPaintProperty->HasIsOn()) {
77         bool isOn = buttonPaintProperty->GetIsOnValue();
78         changed = isOn ^ isOn_.value();
79         isOn_ = isOn;
80     }
81     const auto& renderContext = host->GetRenderContext();
82     CHECK_NULL_VOID(renderContext);
83 
84     if (isOn_.value()) {
85         auto selectedColor = buttonPaintProperty->GetSelectedColor().value_or(checkedColor_);
86         renderContext->UpdateBackgroundColor(selectedColor);
87     } else {
88         auto bgColor = buttonPaintProperty->GetBackgroundColor().value_or(unCheckedColor_);
89         renderContext->UpdateBackgroundColor(bgColor);
90     }
91 
92     if (changed) {
93         auto toggleButtonEventHub = GetEventHub<ToggleButtonEventHub>();
94         CHECK_NULL_VOID(toggleButtonEventHub);
95         toggleButtonEventHub->UpdateChangeEvent(isOn_.value());
96     }
97     InitButtonAndText();
98     HandleEnabled();
99     InitTouchEvent();
100     InitHoverEvent();
101     InitOnKeyEvent();
102 }
103 
HandleEnabled()104 void ToggleButtonPattern::HandleEnabled()
105 {
106     auto host = GetHost();
107     CHECK_NULL_VOID(host);
108     auto eventHub = host->GetEventHub<EventHub>();
109     CHECK_NULL_VOID(eventHub);
110     auto enabled = eventHub->IsEnabled();
111     auto renderContext = host->GetRenderContext();
112     CHECK_NULL_VOID(renderContext);
113     auto pipeline = PipelineBase::GetCurrentContext();
114     CHECK_NULL_VOID(pipeline);
115     auto theme = pipeline->GetTheme<ToggleTheme>();
116     CHECK_NULL_VOID(theme);
117     auto backgroundColor = renderContext->GetBackgroundColor().value_or(theme->GetCheckedColor());
118     if (!enabled) {
119         if (host->GetFirstChild()) {
120             auto textNode = DynamicCast<FrameNode>(host->GetFirstChild());
121             CHECK_NULL_VOID(textNode);
122             auto textLayoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
123             CHECK_NULL_VOID(textLayoutProperty);
124             auto color = textLayoutProperty->GetTextColorValue(textColor_);
125             textLayoutProperty->UpdateTextColor(color.BlendOpacity(disabledAlpha_));
126         }
127         renderContext->OnBackgroundColorUpdate(backgroundColor.BlendOpacity(disabledAlpha_));
128     } else {
129         renderContext->OnBackgroundColorUpdate(backgroundColor);
130     }
131 }
132 
InitClickEvent()133 void ToggleButtonPattern::InitClickEvent()
134 {
135     if (clickListener_) {
136         return;
137     }
138     auto host = GetHost();
139     CHECK_NULL_VOID(host);
140     auto gesture = host->GetOrCreateGestureEventHub();
141     CHECK_NULL_VOID(gesture);
142     auto clickCallback = [weak = WeakClaim(this)](GestureEvent& info) {
143         auto buttonPattern = weak.Upgrade();
144         buttonPattern->OnClick();
145     };
146     clickListener_ = MakeRefPtr<ClickEvent>(std::move(clickCallback));
147     gesture->AddClickEvent(clickListener_);
148 }
149 
OnClick()150 void ToggleButtonPattern::OnClick()
151 {
152     auto host = GetHost();
153     CHECK_NULL_VOID(host);
154     auto paintProperty = host->GetPaintProperty<ToggleButtonPaintProperty>();
155     CHECK_NULL_VOID(paintProperty);
156     bool isLastSelected = false;
157     if (paintProperty->HasIsOn()) {
158         isLastSelected = paintProperty->GetIsOnValue();
159     }
160     const auto& renderContext = host->GetRenderContext();
161     CHECK_NULL_VOID(renderContext);
162     Color selectedColor;
163     auto buttonPaintProperty = host->GetPaintProperty<ToggleButtonPaintProperty>();
164     CHECK_NULL_VOID(buttonPaintProperty);
165     if (isLastSelected) {
166         selectedColor = buttonPaintProperty->GetBackgroundColor().value_or(unCheckedColor_);
167     } else {
168         selectedColor = buttonPaintProperty->GetSelectedColor().value_or(checkedColor_);
169     }
170     paintProperty->UpdateIsOn(!isLastSelected);
171     isOn_ = !isLastSelected;
172     renderContext->UpdateBackgroundColor(selectedColor);
173     auto buttonEventHub = GetEventHub<ToggleButtonEventHub>();
174     CHECK_NULL_VOID(buttonEventHub);
175     buttonEventHub->UpdateChangeEvent(!isLastSelected);
176     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
177 }
178 
InitButtonAndText()179 void ToggleButtonPattern::InitButtonAndText()
180 {
181     auto host = GetHost();
182     CHECK_NULL_VOID(host);
183     auto layoutProperty = host->GetLayoutProperty<ButtonLayoutProperty>();
184     CHECK_NULL_VOID(layoutProperty);
185     if ((!layoutProperty->GetCalcLayoutConstraint() ||
186             !layoutProperty->GetCalcLayoutConstraint()->selfIdealSize->Height().has_value())) {
187         layoutProperty->UpdateUserDefinedIdealSize(CalcSize(std::nullopt, CalcLength(buttonHeight_)));
188     }
189     auto renderContext = host->GetRenderContext();
190     CHECK_NULL_VOID(renderContext);
191     if (!renderContext->HasBorderRadius()) {
192         renderContext->UpdateBorderRadius({ buttonRadius_, buttonRadius_, buttonRadius_, buttonRadius_ });
193     }
194     if (!host->GetFirstChild()) {
195         return;
196     }
197     auto textNode = DynamicCast<FrameNode>(host->GetFirstChild());
198     CHECK_NULL_VOID(textNode);
199     auto textLayoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
200     CHECK_NULL_VOID(textLayoutProperty);
201     if (!textLayoutProperty->HasFontSize()) {
202         textLayoutProperty->UpdateFontSize(textFontSize_);
203     } else {
204         layoutProperty->UpdateFontSize(textLayoutProperty->GetFontSizeValue(textFontSize_));
205     }
206     layoutProperty->UpdateLabel(textLayoutProperty->GetContentValue(""));
207     textLayoutProperty->UpdateTextColor(textColor_);
208 
209     if (!textLayoutProperty->GetMarginProperty()) {
210         MarginProperty margin;
211         margin.left = CalcLength(textMargin_.ConvertToPx());
212         margin.right = CalcLength(textMargin_.ConvertToPx());
213         textLayoutProperty->UpdateMargin(margin);
214     }
215     textNode->MarkModifyDone();
216     textNode->MarkDirtyNode();
217 }
218 
InitOnKeyEvent()219 void ToggleButtonPattern::InitOnKeyEvent()
220 {
221     auto host = GetHost();
222     CHECK_NULL_VOID(host);
223     auto focusHub = host->GetOrCreateFocusHub();
224     auto onKeyEvent = [wp = WeakClaim(this)](const KeyEvent& event) -> bool {
225         auto pattern = wp.Upgrade();
226         if (!pattern) {
227             return false;
228         }
229         return pattern->OnKeyEvent(event);
230     };
231     focusHub->SetOnKeyEventInternal(std::move(onKeyEvent));
232 }
233 
OnKeyEvent(const KeyEvent & event)234 bool ToggleButtonPattern::OnKeyEvent(const KeyEvent& event)
235 {
236     if (event.action != KeyAction::DOWN) {
237         return false;
238     }
239     if (event.code == KeyCode::KEY_SPACE || event.code == KeyCode::KEY_ENTER) {
240         OnClick();
241         return true;
242     }
243     return false;
244 }
245 
ProvideRestoreInfo()246 std::string ToggleButtonPattern::ProvideRestoreInfo()
247 {
248     auto jsonObj = JsonUtil::Create(true);
249     jsonObj->Put("IsOn", isOn_.value_or(false));
250     return jsonObj->ToString();
251 }
252 
OnRestoreInfo(const std::string & restoreInfo)253 void ToggleButtonPattern::OnRestoreInfo(const std::string& restoreInfo)
254 {
255     auto toggleButtonPaintProperty = GetPaintProperty<ToggleButtonPaintProperty>();
256     CHECK_NULL_VOID(toggleButtonPaintProperty);
257     auto info = JsonUtil::ParseJsonString(restoreInfo);
258     if (!info->IsValid() || !info->IsObject()) {
259         return;
260     }
261     auto jsonIsOn = info->GetValue("IsOn");
262     toggleButtonPaintProperty->UpdateIsOn(jsonIsOn->GetBool());
263     OnModifyDone();
264 }
265 } // namespace OHOS::Ace::NG
266