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/navigator/render_navigator.h"
17 
18 #include "base/log/event_report.h"
19 #include "core/components/page/page_target.h"
20 
21 namespace OHOS::Ace {
22 
RenderNavigator()23 RenderNavigator::RenderNavigator()
24 {
25     Initialize();
26 }
27 
Create()28 RefPtr<RenderNode> RenderNavigator::Create()
29 {
30     return AceType::MakeRefPtr<RenderNavigator>();
31 }
32 
Initialize()33 void RenderNavigator::Initialize()
34 {
35     auto wp = AceType::WeakClaim(this);
36     clickRecognizer_ = AceType::MakeRefPtr<ClickRecognizer>();
37     clickRecognizer_->SetOnClick([wp](const ClickInfo& info) {
38         LOGI("navigator OnClick called");
39         auto navigator = wp.Upgrade();
40         if (!navigator) {
41             return;
42         }
43         const auto context = navigator->GetContext().Upgrade();
44         if (context && context->GetIsDeclarative()) {
45             navigator->HandleClickEvent(info);
46         } else {
47             navigator->HandleClickEvent();
48         }
49         navigator->NavigatePage();
50     });
51 }
52 
HandleClickEvent(const ClickInfo & info)53 void RenderNavigator::HandleClickEvent(const ClickInfo& info)
54 {
55     if (onClickWithInfo_) {
56         onClickWithInfo_(info);
57     }
58 }
59 
HandleClickEvent()60 void RenderNavigator::HandleClickEvent()
61 {
62     if (onClick_) {
63         onClick_();
64     }
65 }
66 
NavigatePage()67 void RenderNavigator::NavigatePage()
68 {
69     auto pipelineContext = GetContext().Upgrade();
70     if (!pipelineContext) {
71         LOGE("pipelineContext is null");
72         return;
73     }
74 
75     pipelineContext->NavigatePage(
76         static_cast<uint8_t>(type_), PageTarget(uri_, targetContainer_, useSubStage_), params_);
77 }
78 
Update(const RefPtr<Component> & component)79 void RenderNavigator::Update(const RefPtr<Component>& component)
80 {
81     const RefPtr<NavigatorComponent> navigator = AceType::DynamicCast<NavigatorComponent>(component);
82     if (!navigator) {
83         LOGE("Update error, navigator component is null");
84         EventReport::SendRenderException(RenderExcepType::RENDER_COMPONENT_ERR);
85         return;
86     }
87 
88     uri_ = navigator->GetUri();
89     params_ = navigator->GetParams();
90     type_ = navigator->GetType();
91     active_ = navigator->GetActive();
92     isDefHeight_ = navigator->IsDefHeight();
93     isDefWidth_ = navigator->IsDefWidth();
94     onClickWithInfo_ = AceAsyncEvent<void(const ClickInfo&)>::Create(navigator->GetClickedEventId(), context_);
95     onClick_ = AceAsyncEvent<void()>::Create(navigator->GetClickedEventId(), context_);
96     LOGI("navigator Update uri = %{public}s type = %{public}d", uri_.c_str(), type_);
97 
98     if (active_ == true) {
99         NavigatePage();
100     }
101     SetAccessibilityClickImpl();
102     MarkNeedLayout();
103 }
104 
PerformLayout()105 void RenderNavigator::PerformLayout()
106 {
107     if (!GetChildren().empty()) {
108         LayoutParam innerLayout = GetLayoutParam();
109         auto child = GetChildren().front();
110         child->Layout(innerLayout);
111         Size maxSize = innerLayout.GetMaxSize();
112         double maxWidth = maxSize.Width();
113         double maxHeight = maxSize.Height();
114         if (!isDefHeight_) {
115             maxHeight = child->GetLayoutSize().Height();
116         }
117         if (!isDefWidth_) {
118             maxWidth = child->GetLayoutSize().Width();
119         }
120         SetLayoutSize(Size(maxWidth, maxHeight));
121         child->SetPosition(Alignment::GetAlignPosition(GetLayoutSize(), child->GetLayoutSize(), Alignment::CENTER));
122     } else {
123         SetLayoutSize(GetLayoutParam().GetMaxSize());
124     }
125 }
126 
OnTouchTestHit(const Offset & coordinateOffset,const TouchRestrict & touchRestrict,TouchTestResult & result)127 void RenderNavigator::OnTouchTestHit(
128     const Offset& coordinateOffset, const TouchRestrict& touchRestrict, TouchTestResult& result)
129 {
130     if (!clickRecognizer_) {
131         return;
132     }
133     clickRecognizer_->SetCoordinateOffset(coordinateOffset);
134     result.emplace_back(clickRecognizer_);
135 }
136 
SetAccessibilityClickImpl()137 void RenderNavigator::SetAccessibilityClickImpl()
138 {
139     auto accessibilityNode = accessibilityNode_.Upgrade();
140     if (accessibilityNode) {
141         auto weakPtr = AceType::WeakClaim(AceType::RawPtr(clickRecognizer_));
142         accessibilityNode->AddSupportAction(AceAction::ACTION_CLICK);
143         accessibilityNode->SetClickableState(true);
144         accessibilityNode->SetActionClickImpl([weakPtr]() {
145             auto click = weakPtr.Upgrade();
146             if (click) {
147                 click->OnAccepted();
148             }
149         });
150     }
151 }
152 
153 } // namespace OHOS::Ace
154