• 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 #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_BUTTON_BUTTON_PATTERN_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_BUTTON_BUTTON_PATTERN_H
18 
19 #include <optional>
20 
21 #include "base/memory/referenced.h"
22 #include "base/utils/utils.h"
23 #include "core/common/container.h"
24 #include "core/components/button/button_theme.h"
25 #include "core/components/common/layout/constants.h"
26 #include "core/components_ng/event/event_hub.h"
27 #include "core/components_ng/event/focus_hub.h"
28 #include "core/components_ng/pattern/button/button_event_hub.h"
29 #include "core/components_ng/pattern/button/button_layout_algorithm.h"
30 #include "core/components_ng/pattern/button/button_layout_property.h"
31 #include "core/components_ng/pattern/pattern.h"
32 #include "core/components_ng/pattern/text/text_layout_property.h"
33 namespace OHOS::Ace::NG {
34 enum class ComponentButtonType { POPUP, BUTTON, STEPPER, NAVIGATION };
35 class ButtonPattern : public Pattern {
36     DECLARE_ACE_TYPE(ButtonPattern, Pattern);
37 
38 public:
39     ButtonPattern() = default;
40 
41     ~ButtonPattern() override = default;
42 
IsAtomicNode()43     bool IsAtomicNode() const override
44     {
45         return false;
46     }
47 
CreateEventHub()48     RefPtr<EventHub> CreateEventHub() override
49     {
50         return MakeRefPtr<ButtonEventHub>();
51     }
52 
CreateLayoutAlgorithm()53     RefPtr<LayoutAlgorithm> CreateLayoutAlgorithm() override
54     {
55         return MakeRefPtr<ButtonLayoutAlgorithm>();
56     }
57 
CreateLayoutProperty()58     RefPtr<LayoutProperty> CreateLayoutProperty() override
59     {
60         return MakeRefPtr<ButtonLayoutProperty>();
61     }
62 
GetFocusPattern()63     FocusPattern GetFocusPattern() const override
64     {
65         if (buttonType_ == ComponentButtonType::POPUP || buttonType_ == ComponentButtonType::STEPPER) {
66             FocusPaintParam focusPaintParam;
67             focusPaintParam.SetPaintColor(focusBorderColor_);
68             return { FocusType::NODE, true, FocusStyleType::INNER_BORDER, focusPaintParam };
69         }
70         if (buttonType_ == ComponentButtonType::NAVIGATION) {
71             FocusPaintParam focusPaintParam;
72             focusPaintParam.SetPaintColor(focusBorderColor_);
73             focusPaintParam.SetPaintWidth(focusBorderWidth_);
74             return { FocusType::NODE, true, FocusStyleType::INNER_BORDER, focusPaintParam };
75         }
76         return { FocusType::NODE, true, FocusStyleType::OUTER_BORDER };
77     }
78 
IsNeedAdjustByAspectRatio()79     bool IsNeedAdjustByAspectRatio() override
80     {
81         auto host = GetHost();
82         CHECK_NULL_RETURN(host, false);
83         auto layoutProperty = host->GetLayoutProperty<ButtonLayoutProperty>();
84         CHECK_NULL_RETURN(host, false);
85         return layoutProperty->HasAspectRatio() &&
86                layoutProperty->GetType().value_or(ButtonType::CAPSULE) != ButtonType::CIRCLE;
87     }
88 
SetClickedColor(const Color & color)89     void SetClickedColor(const Color& color)
90     {
91         clickedColor_ = color;
92         isSetClickedColor_ = true;
93     }
94 
SetFocusBorderColor(const Color & color)95     void SetFocusBorderColor(const Color& color)
96     {
97         focusBorderColor_ = color;
98     }
99 
SetFocusBorderWidth(const Dimension & width)100     void SetFocusBorderWidth(const Dimension& width)
101     {
102         focusBorderWidth_ = width;
103     }
104 
setComponentButtonType(const ComponentButtonType & buttonType)105     void setComponentButtonType(const ComponentButtonType& buttonType)
106     {
107         buttonType_ = buttonType;
108     }
109 
ToJsonValue(std::unique_ptr<JsonValue> & json)110     void ToJsonValue(std::unique_ptr<JsonValue>& json) const override
111     {
112         Pattern::ToJsonValue(json);
113         auto host = GetHost();
114         CHECK_NULL_VOID(host);
115         auto layoutProperty = host->GetLayoutProperty<ButtonLayoutProperty>();
116         CHECK_NULL_VOID(layoutProperty);
117         auto context = PipelineBase::GetCurrentContext();
118         CHECK_NULL_VOID(context);
119         auto buttonTheme = context->GetTheme<ButtonTheme>();
120         CHECK_NULL_VOID(buttonTheme);
121         auto textStyle = buttonTheme->GetTextStyle();
122         json->Put(
123             "type", host->GetTag() == "Toggle"
124                         ? "ToggleType.Button"
125                         : ConvertButtonTypeToString(layoutProperty->GetType().value_or(ButtonType::CAPSULE)).c_str());
126         json->Put("fontSize",
127             layoutProperty->GetFontSizeValue(layoutProperty->HasLabel() ? textStyle.GetFontSize() : Dimension(0))
128                 .ToString()
129                 .c_str());
130         json->Put("fontWeight",
131             V2::ConvertWrapFontWeightToStirng(layoutProperty->GetFontWeight().value_or(FontWeight::NORMAL)).c_str());
132         json->Put("fontColor", layoutProperty->GetFontColor()
133                                    .value_or(layoutProperty->HasLabel() ? textStyle.GetTextColor() : Color::BLACK)
134                                    .ColorToString()
135                                    .c_str());
136         auto fontFamilyVector =
137             layoutProperty->GetFontFamily().value_or<std::vector<std::string>>({ "HarmonyOS Sans" });
138         std::string fontFamily = fontFamilyVector.at(0);
139         for (uint32_t i = 1; i < fontFamilyVector.size(); ++i) {
140             fontFamily += ',' + fontFamilyVector.at(i);
141         }
142         json->Put("fontFamily", fontFamily.c_str());
143         json->Put("fontStyle", layoutProperty->GetFontStyle().value_or(Ace::FontStyle::NORMAL) == Ace::FontStyle::NORMAL
144                                    ? "FontStyle.Normal"
145                                    : "FontStyle.Italic");
146         json->Put("label", layoutProperty->GetLabelValue("").c_str());
147         auto eventHub = host->GetEventHub<ButtonEventHub>();
148         CHECK_NULL_VOID(eventHub);
149         json->Put("stateEffect", eventHub->GetStateEffect() ? "true" : "false");
150         auto optionJson = JsonUtil::Create(true);
151         optionJson->Put(
152             "type", ConvertButtonTypeToString(layoutProperty->GetType().value_or(ButtonType::CAPSULE)).c_str());
153         optionJson->Put("stateEffect", eventHub->GetStateEffect() ? "true" : "false");
154         json->Put("options", optionJson->ToString().c_str());
155         auto fontJsValue = JsonUtil::Create(true);
156         fontJsValue->Put("size", layoutProperty->GetFontSizeValue(Dimension(0)).ToString().c_str());
157         fontJsValue->Put("weight",
158             V2::ConvertWrapFontWeightToStirng(layoutProperty->GetFontWeight().value_or(FontWeight::NORMAL)).c_str());
159         fontJsValue->Put("family", fontFamily.c_str());
160         fontJsValue->Put(
161             "style", layoutProperty->GetFontStyle().value_or(Ace::FontStyle::NORMAL) == Ace::FontStyle::NORMAL
162                          ? "FontStyle.Normal"
163                          : "FontStyle.Italic");
164         auto labelJsValue = JsonUtil::Create(true);
165         labelJsValue->Put("overflow",
166             V2::ConvertWrapTextOverflowToString(layoutProperty->GetTextOverflow().value_or(TextOverflow::CLIP))
167                 .c_str());
168         labelJsValue->Put("maxLines", std::to_string(layoutProperty->GetMaxLines().value_or(DEFAULT_MAXLINES)).c_str());
169         labelJsValue->Put("minFontSize", layoutProperty->GetMinFontSizeValue(Dimension(0)).ToString().c_str());
170         labelJsValue->Put("maxFontSize", layoutProperty->GetMaxFontSizeValue(Dimension(0)).ToString().c_str());
171         labelJsValue->Put("heightAdaptivePolicy",
172             V2::ConvertWrapTextHeightAdaptivePolicyToString(
173                 layoutProperty->GetHeightAdaptivePolicy().value_or(TextHeightAdaptivePolicy::MAX_LINES_FIRST))
174                 .c_str());
175         labelJsValue->Put("font", fontJsValue->ToString().c_str());
176         json->Put("labelStyle", labelJsValue->ToString().c_str());
177         json->Put("buttonStyle",
178             ConvertButtonStyleToString(layoutProperty->GetButtonStyle().value_or(ButtonStyleMode::EMPHASIZE)).c_str());
179         json->Put("controlSize",
180             ConvertControlSizeToString(layoutProperty->GetControlSize().value_or(ControlSize::NORMAL)).c_str());
181     }
182 
ConvertButtonTypeToString(ButtonType buttonType)183     static std::string ConvertButtonTypeToString(ButtonType buttonType)
184     {
185         std::string result;
186         switch (buttonType) {
187             case ButtonType::NORMAL:
188                 result = "ButtonType.Normal";
189                 break;
190             case ButtonType::CAPSULE:
191                 result = "ButtonType.Capsule";
192                 break;
193             case ButtonType::CIRCLE:
194                 result = "ButtonType.Circle";
195                 break;
196             default:
197                 break;
198         }
199         return result;
200     }
201 
ConvertButtonStyleToString(ButtonStyleMode buttonStyle)202     static std::string ConvertButtonStyleToString(ButtonStyleMode buttonStyle)
203     {
204         std::string result;
205         switch (buttonStyle) {
206             case ButtonStyleMode::NORMAL:
207                 result = "ButtonStyleMode.NORMAL";
208                 break;
209             case ButtonStyleMode::EMPHASIZE:
210                 result = "ButtonStyleMode.EMPHASIZED";
211                 break;
212             case ButtonStyleMode::TEXT:
213                 result = "ButtonStyleMode.TEXTUAL";
214                 break;
215             default:
216                 break;
217         }
218         return result;
219     }
220 
ConvertControlSizeToString(ControlSize controlSize)221     static std::string ConvertControlSizeToString(ControlSize controlSize)
222     {
223         std::string result;
224         switch (controlSize) {
225             case ControlSize::SMALL:
226                 result = "ControlSize.SMALL";
227                 break;
228             case ControlSize::NORMAL:
229                 result = "ControlSize.NORMAL";
230                 break;
231             default:
232                 break;
233         }
234         return result;
235     }
236 
SetLocalLocation(const Offset & localLocation)237     void SetLocalLocation(const Offset& localLocation)
238     {
239         localLocation_ = localLocation;
240     }
241 
GetLocalLocation()242     const Offset& GetLocalLocation() const
243     {
244         return localLocation_;
245     }
246 
SetInHover(bool inHover)247     void SetInHover(bool inHover)
248     {
249         isInHover_ = inHover;
250     }
251 
GetIsInHover()252     bool GetIsInHover() const
253     {
254         return isInHover_;
255     }
256 
GetHoverListener()257     RefPtr<InputEvent>& GetHoverListener()
258     {
259         return hoverListener_;
260     }
261 
GetTouchListener()262     RefPtr<TouchEventImpl>& GetTouchListener()
263     {
264         return touchListener_;
265     }
266 
267     void OnColorConfigurationUpdate() override;
268 
SetSkipColorConfigurationUpdate()269     void SetSkipColorConfigurationUpdate()
270     {
271         isColorUpdateFlag_ = true;
272     }
273 
SetPreFrameSize(const SizeF & frameSize)274     void SetPreFrameSize(const SizeF& frameSize)
275     {
276         preFrameSize_.SetSizeT(frameSize);
277     }
278 
GetPreFrameSize()279     const SizeF& GetPreFrameSize() const
280     {
281         return preFrameSize_;
282     }
283 
284 protected:
IsNeedInitClickEventRecorder()285     bool IsNeedInitClickEventRecorder() const override
286     {
287         return true;
288     }
289 
290     void OnModifyDone() override;
291     void OnAfterModifyDone() override;
292     void OnAttachToFrameNode() override;
293     void InitTouchEvent();
294     void InitHoverEvent();
295     void OnTouchDown();
296     void OnTouchUp();
297     void HandleHoverEvent(bool isHover);
298     void HandleBackgroundColor();
299     void HandleEnabled();
300     void InitButtonLabel();
301     void AnimateTouchAndHover(RefPtr<RenderContext>& renderContext, int32_t typeFrom, int32_t typeTo,
302         int32_t duration, const RefPtr<Curve>& curve);
303     Color clickedColor_;
304 
305 private:
306     static void UpdateTextLayoutProperty(
307         RefPtr<ButtonLayoutProperty>& layoutProperty, RefPtr<TextLayoutProperty>& textLayoutProperty);
308     static void UpdateTextStyle(
309         RefPtr<ButtonLayoutProperty>& layoutProperty, RefPtr<TextLayoutProperty>& textLayoutProperty);
310     bool IsNeedToHandleHoverOpacity();
311     Color backgroundColor_;
312     Color focusBorderColor_;
313     Color themeBgColor_;
314     Color themeTextColor_;
315     bool isSetClickedColor_ = false;
316     ComponentButtonType buttonType_ = ComponentButtonType::BUTTON;
317 
318     RefPtr<TouchEventImpl> touchListener_;
319     RefPtr<InputEvent> hoverListener_;
320     bool isHover_ = false;
321     bool isPress_ = false;
322 
323     bool isInHover_ = false;
324     Offset localLocation_;
325     Dimension focusBorderWidth_;
326 
327     bool isColorUpdateFlag_ = false;
328     SizeF preFrameSize_;
329     ACE_DISALLOW_COPY_AND_MOVE(ButtonPattern);
330 };
331 } // namespace OHOS::Ace::NG
332 
333 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_BUTTON_BUTTON_PATTERN_H
334