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