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