• 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/base/inspector_filter.h"
27 #include "core/components_ng/event/event_hub.h"
28 #include "core/components_ng/event/focus_hub.h"
29 #include "core/components_ng/pattern/button/button_event_hub.h"
30 #include "core/components_ng/pattern/button/button_layout_algorithm.h"
31 #include "core/components_ng/pattern/button/button_layout_property.h"
32 #include "core/components_ng/pattern/button/button_model_ng.h"
33 #include "core/components_ng/pattern/pattern.h"
34 #include "core/components_ng/pattern/text/text_layout_property.h"
35 namespace OHOS::Ace::NG {
36 enum class ComponentButtonType { POPUP, BUTTON, STEPPER, NAVIGATION };
37 class ButtonPattern : public Pattern {
38     DECLARE_ACE_TYPE(ButtonPattern, Pattern);
39 
40 public:
41     ButtonPattern() = default;
42 
43     ~ButtonPattern() override = default;
44 
IsAtomicNode()45     bool IsAtomicNode() const override
46     {
47         return false;
48     }
49 
CreateEventHub()50     RefPtr<EventHub> CreateEventHub() override
51     {
52         return MakeRefPtr<ButtonEventHub>();
53     }
54 
CreateLayoutAlgorithm()55     RefPtr<LayoutAlgorithm> CreateLayoutAlgorithm() override
56     {
57         return MakeRefPtr<ButtonLayoutAlgorithm>();
58     }
59 
CreateLayoutProperty()60     RefPtr<LayoutProperty> CreateLayoutProperty() override
61     {
62         return MakeRefPtr<ButtonLayoutProperty>();
63     }
64 
GetFocusPattern()65     FocusPattern GetFocusPattern() const override
66     {
67         if (buttonType_ == ComponentButtonType::POPUP || buttonType_ == ComponentButtonType::STEPPER) {
68             FocusPaintParam focusPaintParam;
69             focusPaintParam.SetPaintColor(focusBorderColor_);
70             return { FocusType::NODE, true, FocusStyleType::INNER_BORDER, focusPaintParam };
71         }
72         if (buttonType_ == ComponentButtonType::NAVIGATION) {
73             FocusPaintParam focusPaintParam;
74             focusPaintParam.SetPaintColor(focusBorderColor_);
75             focusPaintParam.SetPaintWidth(focusBorderWidth_);
76             return { FocusType::NODE, true, FocusStyleType::INNER_BORDER, focusPaintParam };
77         }
78         return { FocusType::NODE, true, FocusStyleType::OUTER_BORDER };
79     }
80 
IsNeedAdjustByAspectRatio()81     bool IsNeedAdjustByAspectRatio() override
82     {
83         auto host = GetHost();
84         CHECK_NULL_RETURN(host, false);
85         auto layoutProperty = host->GetLayoutProperty<ButtonLayoutProperty>();
86         CHECK_NULL_RETURN(host, false);
87         auto isNeedAdjust = layoutProperty->HasAspectRatio() &&
88                layoutProperty->GetType().value_or(ButtonType::CAPSULE) != ButtonType::CIRCLE;
89 
90         return isNeedAdjust;
91     }
92 
SetClickedColor(const Color & color)93     void SetClickedColor(const Color& color)
94     {
95         clickedColor_ = color;
96         isSetClickedColor_ = true;
97     }
98 
SetBlendColor(const std::optional<Color> & blendClickColor,const std::optional<Color> & blendHoverColor)99     void SetBlendColor(const std::optional<Color>& blendClickColor, const std::optional<Color>& blendHoverColor)
100     {
101         blendClickColor_ = blendClickColor;
102         blendHoverColor_ = blendHoverColor;
103     }
104 
SetFocusBorderColor(const Color & color)105     void SetFocusBorderColor(const Color& color)
106     {
107         focusBorderColor_ = color;
108     }
109 
SetFocusBorderWidth(const Dimension & width)110     void SetFocusBorderWidth(const Dimension& width)
111     {
112         focusBorderWidth_ = width;
113     }
114 
setComponentButtonType(const ComponentButtonType & buttonType)115     void setComponentButtonType(const ComponentButtonType& buttonType)
116     {
117         buttonType_ = buttonType;
118     }
119 
ToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter)120     void ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const override
121     {
122         Pattern::ToJsonValue(json, filter);
123         /* no fixed attr below, just return */
124         if (filter.IsFastFilter()) {
125             return;
126         }
127         auto host = GetHost();
128         CHECK_NULL_VOID(host);
129         auto layoutProperty = host->GetLayoutProperty<ButtonLayoutProperty>();
130         CHECK_NULL_VOID(layoutProperty);
131         auto context = PipelineBase::GetCurrentContext();
132         CHECK_NULL_VOID(context);
133         auto buttonTheme = context->GetTheme<ButtonTheme>();
134         CHECK_NULL_VOID(buttonTheme);
135         auto textStyle = buttonTheme->GetTextStyle();
136         auto buttonType = layoutProperty->GetType().value_or(ButtonType::CAPSULE);
137         json->PutExtAttr("type", host->GetTag() == "Toggle" ? "ToggleType.Button" :
138             ConvertButtonTypeToString(buttonType).c_str(), filter);
139         json->PutExtAttr("fontSize",
140             layoutProperty->GetFontSizeValue(layoutProperty->HasLabel() ? textStyle.GetFontSize() : Dimension(0))
141                 .ToString()
142                 .c_str(), filter);
143         json->PutExtAttr("fontWeight",
144         V2::ConvertWrapFontWeightToStirng(layoutProperty->GetFontWeight().value_or(FontWeight::MEDIUM)).c_str(), filter);
145         json->PutExtAttr("fontColor", layoutProperty->GetFontColor()
146                                    .value_or(layoutProperty->HasLabel() ? textStyle.GetTextColor() : Color::BLACK)
147                                    .ColorToString()
148                                    .c_str(), filter);
149         json->PutExtAttr("fontStyle", layoutProperty->GetFontStyle().value_or(Ace::FontStyle::NORMAL) == Ace::FontStyle::NORMAL
150                 ? "FontStyle.Normal"
151                 : "FontStyle.Italic", filter);
152         json->PutExtAttr("label", layoutProperty->GetLabelValue("").c_str(), filter);
153         auto eventHub = host->GetEventHub<ButtonEventHub>();
154         CHECK_NULL_VOID(eventHub);
155         json->PutExtAttr("stateEffect", eventHub->GetStateEffect() ? "true" : "false", filter);
156 
157         auto optionJson = JsonUtil::Create(true);
158         optionJson->Put(
159             "type", ConvertButtonTypeToString(layoutProperty->GetType().value_or(ButtonType::CAPSULE)).c_str());
160         optionJson->Put("stateEffect", eventHub->GetStateEffect() ? "true" : "false");
161         json->PutExtAttr("options", optionJson->ToString().c_str(), filter);
162         ToJsonValueAttribute(json, filter);
163     }
164 
ToJsonValueAttribute(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter)165     void ToJsonValueAttribute(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
166     {
167         auto host = GetHost();
168         CHECK_NULL_VOID(host);
169         auto layoutProperty = host->GetLayoutProperty<ButtonLayoutProperty>();
170         CHECK_NULL_VOID(layoutProperty);
171         auto fontFamilyVector =
172             layoutProperty->GetFontFamily().value_or<std::vector<std::string>>({ "HarmonyOS Sans" });
173         std::string fontFamily;
174         if (!fontFamilyVector.empty()) {
175             fontFamily = fontFamilyVector.at(0);
176             for (uint32_t i = 1; i < fontFamilyVector.size(); ++i) {
177                 fontFamily += ',' + fontFamilyVector.at(i);
178             }
179         }
180         json->PutExtAttr("fontFamily", fontFamily.c_str(), filter);
181         auto fontJsValue = JsonUtil::Create(true);
182         fontJsValue->Put("size", layoutProperty->GetFontSizeValue(Dimension(0)).ToString().c_str());
183         fontJsValue->Put("weight",
184             V2::ConvertWrapFontWeightToStirng(layoutProperty->GetFontWeight().value_or(FontWeight::MEDIUM)).c_str());
185         fontJsValue->Put("family", fontFamily.c_str());
186         fontJsValue->Put(
187             "style", layoutProperty->GetFontStyle().value_or(Ace::FontStyle::NORMAL) == Ace::FontStyle::NORMAL
188                          ? "FontStyle.Normal"
189                          : "FontStyle.Italic");
190         auto labelJsValue = JsonUtil::Create(true);
191         labelJsValue->Put("overflow",
192             V2::ConvertWrapTextOverflowToString(layoutProperty->GetTextOverflow().value_or(TextOverflow::CLIP))
193                 .c_str());
194         labelJsValue->Put("maxLines", std::to_string(layoutProperty->GetMaxLines().value_or(DEFAULT_MAXLINES)).c_str());
195         labelJsValue->Put("minFontSize", layoutProperty->GetMinFontSizeValue(Dimension(0)).ToString().c_str());
196         labelJsValue->Put("maxFontSize", layoutProperty->GetMaxFontSizeValue(Dimension(0)).ToString().c_str());
197         labelJsValue->Put("heightAdaptivePolicy",
198             V2::ConvertWrapTextHeightAdaptivePolicyToString(
199                 layoutProperty->GetHeightAdaptivePolicy().value_or(TextHeightAdaptivePolicy::MAX_LINES_FIRST))
200                 .c_str());
201         labelJsValue->Put("font", fontJsValue->ToString().c_str());
202         json->PutExtAttr("labelStyle", labelJsValue->ToString().c_str(), filter);
203 
204         json->PutExtAttr("buttonStyle",
205             ConvertButtonStyleToString(layoutProperty->GetButtonStyle().value_or(ButtonStyleMode::EMPHASIZE))
206             .c_str(), filter);
207         json->PutExtAttr("controlSize",
208             ConvertControlSizeToString(layoutProperty->GetControlSize().value_or(ControlSize::NORMAL))
209             .c_str(), filter);
210         json->PutExtAttr(
211             "role", ConvertButtonRoleToString(layoutProperty->GetButtonRole().value_or(ButtonRole::NORMAL))
212             .c_str(), filter);
213     }
214 
ConvertButtonRoleToString(ButtonRole buttonRole)215     static std::string ConvertButtonRoleToString(ButtonRole buttonRole)
216     {
217         std::string result;
218         switch (buttonRole) {
219             case ButtonRole::NORMAL:
220                 result = "ButtonRole.NORMAL";
221                 break;
222             case ButtonRole::ERROR:
223                 result = "ButtonRole.ERROR";
224                 break;
225             default:
226                 break;
227         }
228         return result;
229     }
230 
ConvertButtonTypeToString(ButtonType buttonType)231     static std::string ConvertButtonTypeToString(ButtonType buttonType)
232     {
233         std::string result;
234         switch (buttonType) {
235             case ButtonType::NORMAL:
236                 result = "ButtonType.Normal";
237                 break;
238             case ButtonType::CAPSULE:
239                 result = "ButtonType.Capsule";
240                 break;
241             case ButtonType::CIRCLE:
242                 result = "ButtonType.Circle";
243                 break;
244             case ButtonType::ROUNDED_RECTANGLE:
245                 result = "ButtonType.ROUNDED_RECTANGLE";
246                 break;
247             default:
248                 break;
249         }
250         return result;
251     }
252 
ConvertButtonStyleToString(ButtonStyleMode buttonStyle)253     static std::string ConvertButtonStyleToString(ButtonStyleMode buttonStyle)
254     {
255         std::string result;
256         switch (buttonStyle) {
257             case ButtonStyleMode::NORMAL:
258                 result = "ButtonStyleMode.NORMAL";
259                 break;
260             case ButtonStyleMode::EMPHASIZE:
261                 result = "ButtonStyleMode.EMPHASIZED";
262                 break;
263             case ButtonStyleMode::TEXT:
264                 result = "ButtonStyleMode.TEXTUAL";
265                 break;
266             default:
267                 break;
268         }
269         return result;
270     }
271 
ConvertControlSizeToString(ControlSize controlSize)272     static std::string ConvertControlSizeToString(ControlSize controlSize)
273     {
274         std::string result;
275         switch (controlSize) {
276             case ControlSize::SMALL:
277                 result = "ControlSize.SMALL";
278                 break;
279             case ControlSize::NORMAL:
280                 result = "ControlSize.NORMAL";
281                 break;
282             default:
283                 break;
284         }
285         return result;
286     }
287 
SetLocalLocation(const Offset & localLocation)288     void SetLocalLocation(const Offset& localLocation)
289     {
290         localLocation_ = localLocation;
291     }
292 
GetLocalLocation()293     const Offset& GetLocalLocation() const
294     {
295         return localLocation_;
296     }
297 
SetInHover(bool inHover)298     void SetInHover(bool inHover)
299     {
300         isInHover_ = inHover;
301     }
302 
GetIsInHover()303     bool GetIsInHover() const
304     {
305         return isInHover_;
306     }
307 
GetHoverListener()308     RefPtr<InputEvent>& GetHoverListener()
309     {
310         return hoverListener_;
311     }
312 
GetTouchListener()313     RefPtr<TouchEventImpl>& GetTouchListener()
314     {
315         return touchListener_;
316     }
317 
318     void SetBuilderFunc(ButtonMakeCallback&& makeFunc);
319 
GetBuilderId()320     virtual int32_t GetBuilderId() const
321     {
322         return nodeId_;
323     }
324 
325     void SetButtonPress(double xPos, double yPos);
326 
UseContentModifier()327     virtual bool UseContentModifier() const
328     {
329         return contentModifierNode_ != nullptr;
330     }
331 
332     void OnColorConfigurationUpdate() override;
333 
SetSkipColorConfigurationUpdate()334     void SetSkipColorConfigurationUpdate()
335     {
336         isColorUpdateFlag_ = true;
337     }
338 
SetPreFrameSize(const SizeF & frameSize)339     void SetPreFrameSize(const SizeF& frameSize)
340     {
341         preFrameSize_.SetSizeT(frameSize);
342     }
343 
GetPreFrameSize()344     const SizeF& GetPreFrameSize() const
345     {
346         return preFrameSize_;
347     }
348 
SetHasCustomPadding(bool hasCustomPadding)349     void SetHasCustomPadding(bool hasCustomPadding)
350     {
351         hasCustomPadding_ = hasCustomPadding;
352     }
353 
GetHasCustomPadding()354     bool GetHasCustomPadding()
355     {
356         return hasCustomPadding_;
357     }
358 
359 protected:
IsNeedInitClickEventRecorder()360     bool IsNeedInitClickEventRecorder() const override
361     {
362         return true;
363     }
364 
365     void OnModifyDone() override;
366     void OnAfterModifyDone() override;
367     void OnAttachToFrameNode() override;
368     void InitTouchEvent();
369     void InitHoverEvent();
370     void OnTouchDown();
371     void OnTouchUp();
372     void HandleHoverEvent(bool isHover);
373     void HandleBackgroundColor();
374     void HandleEnabled();
375     void InitButtonLabel();
376     void CheckLocalizedBorderRadiuses();
377     Color GetColorFromType(const RefPtr<ButtonTheme>& theme, const int32_t& type);
378     void AnimateTouchAndHover(RefPtr<RenderContext>& renderContext, int32_t typeFrom, int32_t typeTo, int32_t duration,
379         const RefPtr<Curve>& curve);
380     Color clickedColor_;
381 
382 private:
383     static void UpdateTextLayoutProperty(
384         RefPtr<ButtonLayoutProperty>& layoutProperty, RefPtr<TextLayoutProperty>& textLayoutProperty);
385     static void UpdateTextStyle(
386         RefPtr<ButtonLayoutProperty>& layoutProperty, RefPtr<TextLayoutProperty>& textLayoutProperty);
387     static bool NeedAgingUpdateText(RefPtr<ButtonLayoutProperty>& layoutProperty);
388     bool IsNeedToHandleHoverOpacity();
389     static void UpdateTextFontScale(
390         RefPtr<ButtonLayoutProperty>& layoutProperty, RefPtr<TextLayoutProperty>& textLayoutProperty);
391     Color backgroundColor_;
392     Color focusBorderColor_;
393     Color themeBgColor_;
394     Color themeTextColor_;
395     bool isSetClickedColor_ = false;
396     ComponentButtonType buttonType_ = ComponentButtonType::BUTTON;
397     void FireBuilder();
398     RefPtr<FrameNode> BuildContentModifierNode();
399     GestureEventFunc tapEventFunc_;
400     std::optional<ButtonMakeCallback> makeFunc_;
401     RefPtr<FrameNode> contentModifierNode_;
402     std::optional<GestureEventFunc> clickEventFunc_;
403     int32_t nodeId_ = -1;
404     RefPtr<TouchEventImpl> touchListener_;
405     RefPtr<InputEvent> hoverListener_;
406     bool isHover_ = false;
407     bool isPress_ = false;
408 
409     bool isInHover_ = false;
410     Offset localLocation_;
411     Dimension focusBorderWidth_;
412 
413     std::optional<Color> blendClickColor_ = std::nullopt;
414     std::optional<Color> blendHoverColor_ = std::nullopt;
415 
416     bool isColorUpdateFlag_ = false;
417     SizeF preFrameSize_;
418     bool hasCustomPadding_ = false;
419     ACE_DISALLOW_COPY_AND_MOVE(ButtonPattern);
420 };
421 } // namespace OHOS::Ace::NG
422 
423 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_BUTTON_BUTTON_PATTERN_H
424