1 /*
2  * Copyright (c) 2021-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/hyperlink/render_hyperlink.h"
17 
18 #include "core/components/image/image_component.h"
19 #include "core/components/text/text_component.h"
20 #include "core/pipeline/base/multi_composed_component.h"
21 
22 namespace OHOS::Ace {
23 
RenderHyperlink()24 RenderHyperlink::RenderHyperlink()
25 {
26     Initialize();
27 }
28 
Create()29 RefPtr<RenderNode> RenderHyperlink::Create()
30 {
31     return AceType::MakeRefPtr<RenderHyperlink>();
32 }
33 
Initialize()34 void RenderHyperlink::Initialize()
35 {
36     auto wp = AceType::WeakClaim(this);
37     clickRecognizer_ = AceType::MakeRefPtr<ClickRecognizer>();
38     clickRecognizer_->SetOnClick([wp](const ClickInfo& info) {
39         auto hyperlink = wp.Upgrade();
40         if (!hyperlink) {
41             return;
42         }
43         hyperlink->JumpToAddress();
44     });
45 }
46 
Update(const RefPtr<Component> & component)47 void RenderHyperlink::Update(const RefPtr<Component>& component)
48 {
49     hyperlinkComponent_ = AceType::DynamicCast<HyperlinkComponent>(component);
50     if (!hyperlinkComponent_) {
51         LOGE("update error, hyperlink is null.");
52         return;
53     }
54     address_ = hyperlinkComponent_->GetAddress();
55     color_ = hyperlinkComponent_->GetColor();
56     SetImageChildColor(hyperlinkComponent_);
57     if (!hyperlinkResources_) {
58         hyperlinkResources_ = AceType::MakeRefPtr<HyperlinkResources>(context_);
59         hyperlinkResources_->CreatePlatformResource(context_);
60     }
61     MarkNeedLayout();
62 }
63 
PerformLayout()64 void RenderHyperlink::PerformLayout()
65 {
66     if (!GetChildren().empty()) {
67         const auto& child = GetChildren().front();
68         child->Layout(GetLayoutParam());
69         auto childSize = child->GetLayoutSize();
70         SetLayoutSize(childSize);
71     }
72 }
73 
OnTouchTestHit(const Offset & coordinateOffset,const TouchRestrict & touchRestrict,TouchTestResult & result)74 void RenderHyperlink::OnTouchTestHit(
75     const Offset& coordinateOffset, const TouchRestrict& touchRestrict, TouchTestResult& result)
76 {
77     if (!clickRecognizer_) {
78         return;
79     }
80     clickRecognizer_->SetCoordinateOffset(coordinateOffset);
81     result.emplace_back(clickRecognizer_);
82 }
83 
JumpToAddress()84 void RenderHyperlink::JumpToAddress()
85 {
86 #if defined(PREVIEW)
87     LOGW("[Engine Log] Unable to use the Hyperlink in the Previewer. "
88          "Perform this operation on the emulator or a real device instead.");
89     return;
90 #endif
91     auto context = context_.Upgrade();
92     if (context) {
93         context->HyperlinkStartAbility(address_);
94     }
95 }
96 
SetImageChildColor(const RefPtr<Component> node)97 void RenderHyperlink::SetImageChildColor(const RefPtr<Component> node)
98 {
99     if (node == nullptr) {
100         return;
101     }
102     auto componentGroup = AceType::DynamicCast<ComponentGroup>(node);
103     auto multiComposedComponent = AceType::DynamicCast<MultiComposedComponent>(node);
104     auto composedComponent = AceType::DynamicCast<ComposedComponent>(node);
105     auto singleChildComponent = AceType::DynamicCast<SoleChildComponent>(node);
106     auto imageComponent = AceType::DynamicCast<ImageComponent>(node);
107     auto textComponent = AceType::DynamicCast<TextComponent>(node);
108     if (imageComponent) {
109         imageComponent->SetImageFill(GetColor());
110         return;
111     }
112     if (textComponent) {
113         auto textStyle = textComponent->GetTextStyle();
114         textStyle.SetTextColor(GetColor());
115         textComponent->SetTextStyle(std::move(textStyle));
116         return;
117     }
118     if (componentGroup) {
119         std::list<RefPtr<Component>> children = componentGroup->GetChildren();
120         for (const auto& child : children) {
121             SetImageChildColor(child);
122         }
123     } else if (multiComposedComponent) {
124         std::list<RefPtr<Component>> children = multiComposedComponent->GetChildren();
125         for (const auto& child : children) {
126             SetImageChildColor(child);
127         }
128     } else if (composedComponent) {
129         auto child = composedComponent->GetChild();
130         SetImageChildColor(child);
131     } else if (singleChildComponent) {
132         auto child = singleChildComponent->GetChild();
133         SetImageChildColor(child);
134     }
135 }
136 
HandleMouseEvent(const MouseEvent & event)137 bool RenderHyperlink::HandleMouseEvent(const MouseEvent& event)
138 {
139     return true;
140 }
141 
HandleMouseHoverEvent(MouseState mouseState)142 void RenderHyperlink::HandleMouseHoverEvent(MouseState mouseState)
143 {
144     auto mousestyle = MouseStyle::CreateMouseStyle();
145     auto pipeline = context_.Upgrade();
146     if (!pipeline) {
147         return;
148     }
149     uint32_t windowId = pipeline->GetWindowId();
150     MouseFormat handPointStyle = MouseFormat::HAND_POINTING;
151     MouseFormat defaultStyle = MouseFormat::DEFAULT;
152     if (mouseState == MouseState::HOVER) {
153         mousestyle->SetPointerStyle(windowId, handPointStyle);
154     } else {
155         mousestyle->SetPointerStyle(windowId, defaultStyle);
156     }
157 }
158 
159 } // namespace OHOS::Ace
160