1 /*
2  * Copyright (c) 2021 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/semi_modal/semi_modal_element.h"
17 
18 #include "core/components/flex/flex_element.h"
19 #include "core/components/flex/flex_item_element.h"
20 #include "core/components/semi_modal/render_semi_modal.h"
21 
22 namespace OHOS::Ace {
23 namespace {
24 
25 const auto BACKGROUND_COLOR_DEFAULT = Color::WHITE;
26 constexpr uint32_t COLUMN_CHILD_MIN = 2;
27 
28 } // namespace
29 
AnimateToFullWindow(int32_t duration)30 void SemiModalElement::AnimateToFullWindow(int32_t duration)
31 {
32     auto render = AceType::DynamicCast<RenderSemiModal>(GetRenderNode());
33     if (!render) {
34         LOGE("Animate full window failed. render is null");
35         return;
36     }
37     render->AnimateToFullWindow(duration);
38 }
39 
GetBackgroundColor() const40 const Color& SemiModalElement::GetBackgroundColor() const
41 {
42     auto boxElement = GetFirstChild();
43     if (!boxElement) {
44         LOGE("Get background color failed. box element is null");
45         return BACKGROUND_COLOR_DEFAULT;
46     }
47     auto boxRender = AceType::DynamicCast<RenderBox>(boxElement->GetRenderNode());
48     if (!boxRender) {
49         LOGE("Get background color failed. box render is null");
50         return BACKGROUND_COLOR_DEFAULT;
51     }
52     auto decoration = boxRender->GetBackDecoration();
53     if (!decoration) {
54         LOGE("Get background color failed. box decoration is null");
55         return BACKGROUND_COLOR_DEFAULT;
56     }
57     return decoration->GetBackgroundColor();
58 }
59 
IsFullWindow() const60 bool SemiModalElement::IsFullWindow() const
61 {
62     return fullWindow_;
63 }
64 
SetFullWindow(bool fullWindow)65 void SemiModalElement::SetFullWindow(bool fullWindow)
66 {
67     fullWindow_ = fullWindow;
68 }
69 
UpdateSystemBarHeight(double statusBar,double navigationBar)70 void SemiModalElement::UpdateSystemBarHeight(double statusBar, double navigationBar)
71 {
72     auto box = GetFirstChild();
73     if (!box) {
74         LOGE("Update system bar failed. box is null.");
75         return;
76     }
77     auto column = box->GetFirstChild();
78     UpdateStatusBarHeight(column, statusBar);
79     UpdateNavigationBarHeight(column, navigationBar);
80 }
81 
UpdateStatusBarHeight(const RefPtr<Element> & column,double height)82 void SemiModalElement::UpdateStatusBarHeight(const RefPtr<Element>& column, double height)
83 {
84     auto renderSemi = AceType::DynamicCast<RenderSemiModal>(GetRenderNode());
85     if (!renderSemi) {
86         LOGE("Update status bar failed. RenderSemi is null.");
87         return;
88     }
89     renderSemi->OnStatusBarHeightChanged(Dimension(height, DimensionUnit::VP));
90     if (!column) {
91         LOGE("Update status bar failed. column is null.");
92         return;
93     }
94     auto dragBarElement = column->GetFirstChild();
95     if (!dragBarElement) {
96         LOGE("Update status bar failed. drag bar element is null.");
97         return;
98     }
99     auto dragBarRender = AceType::DynamicCast<RenderDragBar>(dragBarElement->GetRenderNode());
100     if (!dragBarRender) {
101         LOGE("Update status bar failed. drag bar render is null.");
102         return;
103     }
104     dragBarRender->SetStatusBarHeight(height);
105 }
106 
UpdateNavigationBarHeight(const RefPtr<Element> & column,double height)107 void SemiModalElement::UpdateNavigationBarHeight(const RefPtr<Element>& column, double height)
108 {
109     auto renderSemi = AceType::DynamicCast<RenderSemiModal>(GetRenderNode());
110     if (!renderSemi) {
111         LOGE("Update navigation bar failed. RenderSemi is null.");
112         return;
113     }
114     renderSemi->OnNavigationBarHeightChanged(Dimension(height, DimensionUnit::VP));
115     if (!column) {
116         LOGE("Update navigation bar failed. column is null.");
117         return;
118     }
119     auto navigationElement = column->GetLastChild();
120     if (!navigationElement) {
121         LOGE("Update navigation bar failed. navigation element is null.");
122         return;
123     }
124     auto navigationRender = AceType::DynamicCast<RenderBoxBase>(navigationElement->GetRenderNode());
125     if (!navigationRender) {
126         LOGE("Update navigation bar failed. navigation render is null.");
127         return;
128     }
129     auto context = context_.Upgrade();
130     if (!context) {
131         LOGE("Update navigation bar failed. context is null.");
132         return;
133     }
134     navigationRender->SetHeight(context->NormalizeToPx(Dimension(height, DimensionUnit::VP)));
135 }
136 
GetOverlayElement() const137 RefPtr<OverlayElement> SemiModalElement::GetOverlayElement() const
138 {
139     auto box = AceType::DynamicCast<BoxElement>(GetFirstChild());
140     if (!box) {
141         LOGE("Get overlay element failed. Box element is null!");
142         return RefPtr<OverlayElement>();
143     }
144     auto column = AceType::DynamicCast<ColumnElement>(box->GetFirstChild());
145     if (!column || column->GetChildren().size() < COLUMN_CHILD_MIN) {
146         // column should has more than 2 child
147         LOGE("Get overlay element failed. Column is null or child size error!");
148         return RefPtr<OverlayElement>();
149     }
150     // Get second child
151     auto secondItr = std::next(column->GetChildren().begin());
152     auto flexItem = AceType::DynamicCast<FlexItemElement>(*secondItr);
153     if (!flexItem) {
154         LOGE("Get overlay element failed. FlexItemElement is null!");
155         return RefPtr<OverlayElement>();
156     }
157     auto clip = flexItem->GetFirstChild();
158     if (!clip) {
159         LOGE("Get overlay element failed. clip is null!");
160         return RefPtr<OverlayElement>();
161     }
162     auto stack = clip->GetFirstChild();
163     if (!stack) {
164         return RefPtr<OverlayElement>();
165     }
166     auto child = stack->GetChildren();
167     if (child.size() > 1) {
168         auto it = child.begin();
169         it++;
170         return AceType::DynamicCast<OverlayElement>(*it);
171     }
172     return RefPtr<OverlayElement>();
173 }
174 
GetStageElement() const175 RefPtr<StageElement> SemiModalElement::GetStageElement() const
176 {
177     auto box = AceType::DynamicCast<BoxElement>(GetFirstChild());
178     if (!box) {
179         LOGE("Get stage element failed. Box element is null!");
180         return RefPtr<StageElement>();
181     }
182     auto column = AceType::DynamicCast<ColumnElement>(box->GetFirstChild());
183     if (!column || column->GetChildren().size() < COLUMN_CHILD_MIN) {
184         // column should has more than 2 child
185         LOGE("Get stage element failed. Column is null or child size error!");
186         return RefPtr<StageElement>();
187     }
188     // Get second child
189     auto secondItr = std::next(column->GetChildren().begin());
190     auto flexItem = AceType::DynamicCast<FlexItemElement>(*secondItr);
191     if (!flexItem) {
192         LOGE("Get stage element failed. FlexItemElement is null!");
193         return RefPtr<StageElement>();
194     }
195     auto clip = flexItem->GetFirstChild();
196     if (!clip) {
197         LOGE("Get stage element failed. clip is null!");
198         return RefPtr<StageElement>();
199     }
200     auto stack = clip->GetFirstChild();
201     if (!stack) {
202         return RefPtr<StageElement>();
203     }
204     return AceType::DynamicCast<StageElement>(stack->GetFirstChild());
205 }
206 
AnimateToExitApp() const207 void SemiModalElement::AnimateToExitApp() const
208 {
209     auto renderSemi = AceType::DynamicCast<RenderSemiModal>(GetRenderNode());
210     if (!renderSemi) {
211         LOGE("Animate To Exit failed. RenderSemi is null.");
212         return;
213     }
214     renderSemi->AnimateToExitApp();
215 }
216 
217 } // namespace OHOS::Ace