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