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 #include "core/components/container_modal/container_modal_element.h"
17
18 #include "base/memory/ace_type.h"
19 #include "core/components/box/box_element.h"
20 #include "core/components/box/render_box.h"
21 #include "core/components/clip/clip_element.h"
22 #include "core/components/clip/render_clip.h"
23 #include "core/components/container_modal/container_modal_constants.h"
24 #include "core/components/container_modal/render_container_modal.h"
25 #include "core/components/flex/flex_element.h"
26 #include "core/components/padding/render_padding.h"
27 #include "core/gestures/tap_gesture.h"
28 #include "core/pipeline/base/render_node.h"
29
30 namespace OHOS::Ace {
31 namespace {
32
33 constexpr uint32_t COLUMN_CHILD_NUM = 2;
34 constexpr uint32_t TITLE_POSITION = 1;
35 constexpr uint32_t SPLIT_BUTTON_POSITION = 2;
36 constexpr uint32_t TITLE_POPUP_TIME = 200; // 200ms
37 constexpr double MOUSE_MOVE_POPUP_DISTANCE = 5.0; // 5.0px
38 constexpr double MOVE_POPUP_DISTANCE_X = 10.0; // 10.0px
39 constexpr double MOVE_POPUP_DISTANCE_Y = 20.0; // 20.0px
40 constexpr double TITLE_POPUP_DISTANCE = 37.0; // 37vp height of title
41
42 } // namespace
43
GetStackElement() const44 RefPtr<StackElement> ContainerModalElement::GetStackElement() const
45 {
46 auto containerBox = AceType::DynamicCast<BoxElement>(GetFirstChild());
47 if (!containerBox) {
48 LOGE("Get stack element failed, container box element is null!");
49 return {};
50 }
51
52 // The first stack is not what we need.
53 auto stackElement = AceType::DynamicCast<StackElement>(containerBox->GetFirstChild());
54 if (!stackElement) {
55 LOGE("Get stack element failed, stack element is null!");
56 return {};
57 }
58
59 auto column = AceType::DynamicCast<ColumnElement>(stackElement->GetFirstChild());
60 if (!column || column->GetChildren().size() != COLUMN_CHILD_NUM) {
61 // column should have 2 children, title and content.
62 LOGE("Get stack element failed, column is null or child size error!");
63 return {};
64 }
65
66 // Get second child : content
67 auto clip = AceType::DynamicCast<ClipElement>(column->GetLastChild());
68 if (!clip) {
69 LOGE("Get stack element failed, clip element is null!");
70 return {};
71 }
72
73 auto contentBox = AceType::DynamicCast<BoxElement>(clip->GetFirstChild());
74 if (!contentBox) {
75 LOGE("Get stack element failed, content box element is null!");
76 return {};
77 }
78
79 auto stack = contentBox->GetFirstChild();
80 if (!stack || !AceType::InstanceOf<StackElement>(stack)) {
81 LOGE("Get stack element failed, stack is null or type error!");
82 return {};
83 }
84
85 return AceType::DynamicCast<StackElement>(stack);
86 }
87
GetOverlayElement() const88 RefPtr<OverlayElement> ContainerModalElement::GetOverlayElement() const
89 {
90 auto stack = GetStackElement();
91 if (!stack) {
92 LOGE("Get overlay element failed, stack element is null");
93 return {};
94 }
95
96 for (const auto& child : stack->GetChildren()) {
97 if (child && AceType::InstanceOf<OverlayElement>(child)) {
98 return AceType::DynamicCast<OverlayElement>(child);
99 }
100 }
101 LOGE("Get overlay element failed, all children of stack element do not meet the requirements");
102 return {};
103 }
104
GetStageElement() const105 RefPtr<StageElement> ContainerModalElement::GetStageElement() const
106 {
107 auto stack = GetStackElement();
108 if (!stack) {
109 LOGE("Get stage element failed, stack element is null");
110 return {};
111 }
112 for (const auto& child : stack->GetChildren()) {
113 if (child && AceType::InstanceOf<StageElement>(child)) {
114 return AceType::DynamicCast<StageElement>(child);
115 }
116 }
117 LOGE("Get stage element failed, all children of stack element do not meet the requirements");
118 return {};
119 }
120
ShowTitle(bool isShow,bool hasDeco,bool needUpdate)121 void ContainerModalElement::ShowTitle(bool isShow, bool hasDeco, bool needUpdate)
122 {
123 auto containerBox = AceType::DynamicCast<BoxElement>(GetFirstChild());
124 if (!containerBox) {
125 LOGE("ContainerModalElement showTitle failed, container box element is null!");
126 return;
127 }
128 auto context = context_.Upgrade();
129 if (!context) {
130 LOGE("ContainerModalElement showTitle failed, context is null.");
131 return;
132 }
133 windowMode_ = context->GetWindowManager()->GetWindowMode();
134 hasDeco_ = hasDeco;
135 LOGI("ShowTitle isShow: %{public}d, windowMode: %{public}d, hasDeco: %{public}d", isShow, windowMode_, hasDeco_);
136 if (!hasDeco_) {
137 isShow = false;
138 }
139
140 // set container window show state to RS
141 context->SetContainerWindow(isShow);
142
143 // full screen need to hide border and padding.
144 auto containerRenderBox = AceType::DynamicCast<RenderBox>(containerBox->GetRenderNode());
145 if (containerRenderBox) {
146 auto containerDecoration = containerRenderBox->GetBackDecoration();
147 Edge padding = Edge();
148 Border outerBorder = Border();
149 if (isShow) {
150 outerBorder.SetBorderRadius(Radius(CONTAINER_OUTER_RADIUS));
151 outerBorder.SetColor(CONTAINER_BORDER_COLOR);
152 outerBorder.SetWidth(CONTAINER_BORDER_WIDTH);
153 padding = Edge(CONTENT_PADDING, Dimension(0.0), CONTENT_PADDING, CONTENT_PADDING);
154 }
155 containerDecoration->SetBorder(outerBorder);
156 containerRenderBox->SetBackDecoration(containerDecoration);
157 containerRenderBox->SetPadding(padding);
158 }
159
160 auto stackElement = AceType::DynamicCast<StackElement>(containerBox->GetFirstChild());
161 if (!stackElement) {
162 LOGE("ContainerModalElement showTitle failed, stack element is null!");
163 return;
164 }
165
166 auto column = AceType::DynamicCast<ColumnElement>(stackElement->GetFirstChild());
167 if (!column || column->GetChildren().size() != COLUMN_CHILD_NUM) {
168 // column should have 2 children, title and content.
169 LOGE("ContainerModalElement showTitle failed, column element is null or children size error!");
170 return;
171 }
172
173 // full screen need to hide content border radius.
174 auto clip = AceType::DynamicCast<ClipElement>(column->GetLastChild());
175 if (!clip) {
176 LOGE("ContainerModalElement showTitle failed, clip element is null!");
177 return;
178 }
179 if (!contentBox_) {
180 contentBox_ = AceType::DynamicCast<BoxElement>(clip->GetFirstChild());
181 }
182 auto renderClip = AceType::DynamicCast<RenderClip>(clip->GetRenderNode());
183 if (renderClip) {
184 isShow ? renderClip->SetClipRadius(Radius(CONTAINER_INNER_RADIUS)) : renderClip->SetClipRadius(Radius(0.0));
185 }
186
187 // Get first child : title
188 auto display = AceType::DynamicCast<DisplayElement>(column->GetFirstChild());
189 if (!display) {
190 LOGE("ContainerModalElement showTitle failed,, display element is null.");
191 return;
192 }
193 auto renderDisplay = AceType::DynamicCast<RenderDisplay>(display->GetRenderNode());
194 if (renderDisplay) {
195 renderDisplay->UpdateVisibleType(isShow ? VisibleType::VISIBLE : VisibleType::GONE);
196 }
197 ChangeFloatingTitleIcon();
198
199 // hide floating title anyway.
200 if (floatingTitleDisplay_) {
201 floatingTitleDisplay_->UpdateVisibleType(VisibleType::GONE);
202 }
203 }
204
PerformBuild()205 void ContainerModalElement::PerformBuild()
206 {
207 SoleChildElement::PerformBuild();
208 if (!controller_) {
209 controller_ = CREATE_ANIMATOR(context_);
210 controller_->SetDuration(TITLE_POPUP_TIME);
211 controller_->SetFillMode(FillMode::FORWARDS);
212 auto translateY = AceType::MakeRefPtr<CurveAnimation<DimensionOffset>>(
213 DimensionOffset(Dimension(), Dimension(-TITLE_POPUP_DISTANCE * density_)),
214 DimensionOffset(Dimension(), Dimension()), Curves::FRICTION);
215 TweenOption option;
216 option.SetTranslateAnimations(AnimationType::TRANSLATE_Y, translateY);
217 auto containerBox = AceType::DynamicCast<BoxElement>(GetFirstChild());
218 if (!containerBox) {
219 LOGE("ContainerModalElement PerformBuild failed, container box element is null!");
220 return;
221 }
222
223 auto stackElement = AceType::DynamicCast<StackElement>(containerBox->GetFirstChild());
224 if (!stackElement) {
225 LOGE("ContainerModalElement PerformBuild failed, stack element is null!");
226 return;
227 }
228 auto column = AceType::DynamicCast<ColumnElement>(stackElement->GetFirstChild());
229 if (!column || column->GetChildren().size() != COLUMN_CHILD_NUM) {
230 // column should have 2 children, title and content.
231 LOGE("ContainerModalElement PerformBuild failed, column element is null or children size error!");
232 return;
233 }
234
235 auto titleDisplay = AceType::DynamicCast<DisplayElement>(column->GetFirstChild());
236 if (titleDisplay && titleDisplay->GetFirstChild()) {
237 titleBox_ = AceType::DynamicCast<BoxElement>(titleDisplay->GetFirstChild()->GetFirstChild());
238 }
239
240 auto tween = AceType::DynamicCast<TweenElement>(stackElement->GetLastChild());
241 if (!tween) {
242 LOGE("ContainerModalElement PerformBuild failed, tween element is null.");
243 return;
244 }
245 if (tween->GetContentElement()) {
246 floatingTitleBox_ = AceType::DynamicCast<BoxElement>(tween->GetContentElement()->GetFirstChild());
247 }
248
249 auto display = AceType::DynamicCast<DisplayElement>(tween->GetFirstChild());
250 if (display && !floatingTitleDisplay_) {
251 floatingTitleDisplay_ = AceType::DynamicCast<RenderDisplay>(display->GetRenderNode());
252 if (floatingTitleDisplay_) {
253 floatingTitleDisplay_->UpdateVisibleType(VisibleType::GONE);
254 }
255 }
256 tween->SetController(controller_);
257 tween->SetOption(option);
258 tween->ApplyKeyframes();
259 }
260
261 ChangeTitleIcon();
262
263 // The first time it starts up, it needs to hide title if mode as follows.
264 windowMode_ = context_.Upgrade()->GetWindowManager()->GetWindowMode();
265 ShowTitle(windowMode_ == WindowMode::WINDOW_MODE_FLOATING, hasDeco_);
266 }
267
FlushReload()268 void ContainerModalElement::FlushReload()
269 {
270 auto containerBox = AceType::DynamicCast<BoxElement>(GetFirstChild());
271 if (!containerBox) {
272 LOGE("ContainerModalElement WindowFocus failed, container box element is null!");
273 return;
274 }
275 auto containerRenderBox = AceType::DynamicCast<RenderBox>(containerBox->GetRenderNode());
276 if (containerRenderBox) {
277 auto containerDecoration = containerRenderBox->GetBackDecoration();
278 containerDecoration->SetBackgroundColor(
279 windowFocus_ ? CONTAINER_BACKGROUND_COLOR : CONTAINER_BACKGROUND_COLOR_LOST_FOCUS);
280 auto border = containerDecoration->GetBorder();
281 border.SetColor(windowFocus_ ? CONTAINER_BORDER_COLOR : CONTAINER_BORDER_COLOR_LOST_FOCUS);
282 containerDecoration->SetBorder(border);
283 containerRenderBox->SetBackDecoration(containerDecoration);
284 }
285 if (windowMode_ == WindowMode::WINDOW_MODE_FULLSCREEN || windowMode_ == WindowMode::WINDOW_MODE_SPLIT_PRIMARY ||
286 windowMode_ == WindowMode::WINDOW_MODE_SPLIT_SECONDARY) {
287 ChangeFloatingTitleIcon(windowFocus_);
288 return;
289 }
290 ChangeTitleIcon(windowFocus_);
291 }
292
Update()293 void ContainerModalElement::Update()
294 {
295 RenderElement::Update();
296
297 containerModalComponent_ = AceType::DynamicCast<ContainerModalComponent>(component_);
298 if (!containerModalComponent_) {
299 LOGE("ContainerModalElement update failed, container modal component is null.");
300 return;
301 }
302 auto containerBox = AceType::DynamicCast<BoxComponent>(containerModalComponent_->GetChild());
303 if (!containerBox) {
304 LOGE("ContainerModalElement update failed, container box component is null.");
305 return;
306 }
307 auto context = context_.Upgrade();
308 if (context) {
309 density_ = (float)context->GetDensity();
310 }
311
312 containerBox->SetOnTouchDownId([weak = WeakClaim(this), context = context_](const TouchEventInfo& info) {
313 auto containerElement = weak.Upgrade();
314 auto pipeline = context.Upgrade();
315 if (!pipeline || !containerElement || !containerElement->hasDeco_) {
316 return;
317 }
318 auto viewScale = pipeline->GetViewScale();
319 if (info.GetChangedTouches().begin()->GetGlobalLocation().GetY() * viewScale <=
320 (TITLE_POPUP_DISTANCE * containerElement->density_)) {
321 containerElement->moveX_ = info.GetChangedTouches().begin()->GetGlobalLocation().GetX() * viewScale;
322 containerElement->moveY_ = info.GetChangedTouches().begin()->GetGlobalLocation().GetY() * viewScale;
323 return;
324 }
325
326 // touch other area to hide floating title
327 if (containerElement->CanHideFloatingTitle()) {
328 containerElement->controller_->AddStopListener([weak] {
329 auto container = weak.Upgrade();
330 if (container && container->floatingTitleDisplay_) {
331 container->floatingTitleDisplay_->UpdateVisibleType(VisibleType::GONE);
332 }
333 });
334 containerElement->controller_->Backward();
335 }
336 });
337
338 // touch top to pop-up title bar.
339 containerBox->SetOnTouchMoveId([weak = WeakClaim(this), context = context_](const TouchEventInfo& info) {
340 auto containerElement = weak.Upgrade();
341 auto pipeline = context.Upgrade();
342 if (!pipeline || !containerElement || !containerElement->hasDeco_ ||
343 !containerElement->CanShowFloatingTitle()) {
344 return;
345 }
346 auto viewScale = pipeline->GetViewScale();
347 if (info.GetChangedTouches().begin()->GetGlobalLocation().GetY() * viewScale >
348 (TITLE_POPUP_DISTANCE * containerElement->density_)) {
349 return;
350 }
351 auto deltaMoveX =
352 fabs(info.GetChangedTouches().begin()->GetGlobalLocation().GetX() * viewScale - containerElement->moveX_);
353 auto deltaMoveY =
354 info.GetChangedTouches().begin()->GetGlobalLocation().GetY() * viewScale - containerElement->moveY_;
355 if (deltaMoveX <= MOVE_POPUP_DISTANCE_X && deltaMoveY >= MOVE_POPUP_DISTANCE_Y) {
356 containerElement->floatingTitleDisplay_->UpdateVisibleType(VisibleType::VISIBLE);
357 containerElement->controller_->ClearStopListeners();
358 containerElement->controller_->AddStopListener([weak] {
359 auto container = weak.Upgrade();
360 container->SetTitleAccessibilityNodeOffset();
361 });
362 containerElement->controller_->Forward();
363 }
364 });
365
366 // mouse move top to pop up title bar and move other area to hide title bar.
367 containerBox->SetOnMouseId([weak = WeakClaim(this), context = context_](MouseInfo& info) {
368 auto containerElement = weak.Upgrade();
369 auto pipeline = context.Upgrade();
370 if (!pipeline || !containerElement || !containerElement->hasDeco_ || info.GetAction() != MouseAction::MOVE) {
371 return;
372 }
373 auto viewScale = pipeline->GetViewScale();
374 if (info.GetLocalLocation().GetY() * viewScale <= MOUSE_MOVE_POPUP_DISTANCE &&
375 containerElement->CanShowFloatingTitle()) {
376 containerElement->floatingTitleDisplay_->UpdateVisibleType(VisibleType::VISIBLE);
377 containerElement->controller_->ClearStopListeners();
378 containerElement->controller_->AddStopListener([weak] {
379 auto container = weak.Upgrade();
380 container->SetTitleAccessibilityNodeOffset();
381 });
382 containerElement->controller_->Forward();
383 }
384 if (info.GetLocalLocation().GetY() * viewScale > (TITLE_POPUP_DISTANCE * containerElement->density_) &&
385 containerElement->CanHideFloatingTitle()) {
386 containerElement->controller_->AddStopListener([weak] {
387 auto container = weak.Upgrade();
388 if (container && container->floatingTitleDisplay_) {
389 container->floatingTitleDisplay_->UpdateVisibleType(VisibleType::GONE);
390 }
391 });
392 containerElement->controller_->Backward();
393 }
394 });
395 }
396
CanShowFloatingTitle()397 bool ContainerModalElement::CanShowFloatingTitle()
398 {
399 if (!floatingTitleDisplay_ || !controller_) {
400 LOGI("Show floating title failed, floatingTitleDisplay or controller is null.");
401 return false;
402 }
403 if (windowMode_ != WindowMode::WINDOW_MODE_FULLSCREEN && windowMode_ != WindowMode::WINDOW_MODE_SPLIT_PRIMARY &&
404 windowMode_ != WindowMode::WINDOW_MODE_SPLIT_SECONDARY) {
405 LOGI("Window is not full screen or split screen, can not show floating title.");
406 return false;
407 }
408 if (floatingTitleDisplay_->GetVisible()) {
409 LOGI("Floating tittle is visible now, no need to show again.");
410 return false;
411 }
412 return true;
413 }
414
CanHideFloatingTitle()415 bool ContainerModalElement::CanHideFloatingTitle()
416 {
417 if (!floatingTitleDisplay_ || !controller_) {
418 LOGI("Hide floating title failed, floatingTitleDisplay or controller is null.");
419 return false;
420 }
421 if (!floatingTitleDisplay_->GetVisible()) {
422 LOGI("Hide floating title failed, title is not visible.");
423 return false;
424 }
425 return true;
426 }
427
ChangeFloatingTitleIcon(bool isFocus)428 void ContainerModalElement::ChangeFloatingTitleIcon(bool isFocus)
429 {
430 if (!floatingTitleBox_ || !containerModalComponent_) {
431 LOGE("ChangeFloatingTitleIcon failed.");
432 return;
433 }
434 auto renderFloatingTitleBox = AceType::DynamicCast<RenderBox>(floatingTitleBox_->GetRenderNode());
435 if (!renderFloatingTitleBox) {
436 LOGE("ChangeFloatingTitleIcon failed, render floating title box is null.");
437 return;
438 }
439 auto backDecoration = renderFloatingTitleBox->GetBackDecoration();
440 backDecoration->SetBackgroundColor(isFocus ? CONTAINER_BACKGROUND_COLOR : CONTAINER_BACKGROUND_COLOR_LOST_FOCUS);
441 renderFloatingTitleBox->SetBackDecoration(backDecoration);
442
443 auto rowElement = AceType::DynamicCast<RowElement>(floatingTitleBox_->GetFirstChild());
444 if (!rowElement) {
445 LOGE("ChangeFloatingTitleIcon failed, row element is null.");
446 return;
447 }
448 RefPtr<RenderPadding> splitButton = nullptr;
449 if (!containerModalComponent_->GetSplitButtonHide()) {
450 auto renderRow = AceType::DynamicCast<RenderFlex>(rowElement->GetRenderNode());
451 if (!renderRow) {
452 LOGE("ChangeFloatingTitleIcon failed, renderRow is null.");
453 return;
454 }
455 auto iterator = renderRow->GetChildren().begin();
456 std::advance(iterator, SPLIT_BUTTON_POSITION);
457 splitButton = AceType::DynamicCast<RenderPadding>(*iterator);
458 }
459
460 auto floatingTitleChildrenRow = AceType::MakeRefPtr<RowComponent>(FlexAlign::FLEX_START, FlexAlign::CENTER,
461 containerModalComponent_->BuildTitleChildren(true, isFocus, windowMode_ == WindowMode::WINDOW_MODE_FULLSCREEN));
462 floatingTitleChildrenRow->SetUpdateType(UpdateType::REBUILD);
463 rowElement->SetUpdateComponent(floatingTitleChildrenRow);
464
465 if (splitButton) {
466 splitButton->SetHidden(windowMode_ == WindowMode::WINDOW_MODE_SPLIT_PRIMARY);
467 }
468 }
469
ChangeTitleIcon(bool isFocus)470 void ContainerModalElement::ChangeTitleIcon(bool isFocus)
471 {
472 if (!titleBox_ || !containerModalComponent_) {
473 LOGE("ChangeTitleIcon failed.");
474 return;
475 }
476 auto rowElement = AceType::DynamicCast<RowElement>(titleBox_->GetFirstChild());
477 if (!rowElement) {
478 LOGE("ChangeTitleIcon failed, row element is null.");
479 return;
480 }
481 auto titleChildrenRow = AceType::MakeRefPtr<RowComponent>(
482 FlexAlign::FLEX_START, FlexAlign::CENTER, containerModalComponent_->BuildTitleChildren(false, isFocus));
483 titleChildrenRow->SetUpdateType(UpdateType::REBUILD);
484 rowElement->SetUpdateComponent(titleChildrenRow);
485 }
486
WindowFocus(bool isFocus)487 void ContainerModalElement::WindowFocus(bool isFocus)
488 {
489 windowFocus_ = isFocus;
490 FlushReload();
491 }
492
SetAppBgColor(const Color & color)493 void ContainerModalElement::SetAppBgColor(const Color& color)
494 {
495 if (!contentBox_) {
496 LOGE("SetAppBgColor failed, contentBox_ is nullptr.");
497 return;
498 }
499 auto renderContentBox = AceType::DynamicCast<RenderBox>(contentBox_->GetRenderNode());
500 if (!renderContentBox) {
501 LOGE("SetAppBgColor failed, renderContentBox is nullptr.");
502 return;
503 }
504 auto backDecoration = renderContentBox->GetBackDecoration();
505 backDecoration->SetBackgroundColor(color);
506 renderContentBox->SetBackDecoration(backDecoration);
507 }
508
SetTitleButtonHide(bool hideSplit,bool hideMaximize,bool hideMinimize)509 void ContainerModalElement::SetTitleButtonHide(bool hideSplit, bool hideMaximize, bool hideMinimize)
510 {
511 if (!titleBox_ || !floatingTitleBox_ || !containerModalComponent_) {
512 LOGE("titleBox_ floatingTitleBox_ or containerModalComponent_ is null.");
513 return;
514 }
515 auto rowElement = AceType::DynamicCast<RowElement>(titleBox_->GetFirstChild());
516 if (!rowElement) {
517 LOGE("row element is null.");
518 return;
519 }
520 auto floatingRowElement = AceType::DynamicCast<RowElement>(floatingTitleBox_->GetFirstChild());
521 if (!floatingRowElement) {
522 LOGE("floating row element is null.");
523 return;
524 }
525 containerModalComponent_->SetTitleButtonHide(hideSplit, hideMaximize, hideMinimize);
526
527 auto titleChildrenRow = AceType::MakeRefPtr<RowComponent>(
528 FlexAlign::FLEX_START, FlexAlign::CENTER, containerModalComponent_->BuildTitleChildren(false, windowFocus_));
529 titleChildrenRow->SetUpdateType(UpdateType::REBUILD);
530 rowElement->SetUpdateComponent(titleChildrenRow);
531
532 auto floatingTitleChildrenRow = AceType::MakeRefPtr<RowComponent>(
533 FlexAlign::FLEX_START, FlexAlign::CENTER, containerModalComponent_->BuildTitleChildren(true, windowFocus_));
534 floatingTitleChildrenRow->SetUpdateType(UpdateType::REBUILD);
535 floatingRowElement->SetUpdateComponent(floatingTitleChildrenRow);
536 }
537
SetAppTitle(const std::string & title)538 void ContainerModalElement::SetAppTitle(const std::string& title)
539 {
540 CHECK_NULL_VOID(containerModalComponent_);
541 auto textComponent = containerModalComponent_->GetTitleLabel();
542 CHECK_NULL_VOID(textComponent);
543 if (textComponent->GetData() == title) {
544 LOGI("set same title, skip, title is %{public}s", title.c_str());
545 return;
546 }
547 textComponent->SetData(title);
548 bool isFloatingTitle = windowMode_ != WindowMode::WINDOW_MODE_FLOATING;
549 auto renderTitle = GetTitleRender(isFloatingTitle);
550 CHECK_NULL_VOID(renderTitle);
551 renderTitle->Update(textComponent);
552 renderTitle->MarkNeedRender();
553 LOGI("set app title successfully, title:%{public}s, isFloatingTitle:%{public}d", title.c_str(),
554 static_cast<int>(isFloatingTitle));
555 }
556
SetAppIcon(const RefPtr<PixelMap> & icon)557 void ContainerModalElement::SetAppIcon(const RefPtr<PixelMap>& icon)
558 {
559 CHECK_NULL_VOID(containerModalComponent_);
560 auto imageComponent = containerModalComponent_->GetTitleIcon();
561 CHECK_NULL_VOID(imageComponent);
562 imageComponent->SetSrc("");
563 imageComponent->SetPixmap(icon);
564 bool isFloatingTitle = windowMode_ != WindowMode::WINDOW_MODE_FLOATING;
565 auto renderIcon = GetIconRender(isFloatingTitle);
566 CHECK_NULL_VOID(renderIcon);
567 renderIcon->Update(imageComponent);
568 renderIcon->MarkNeedRender();
569 LOGI("set app icon successfully, isFloatingTitle:%{public}d", static_cast<int>(isFloatingTitle));
570 }
571
GetTitleRender(bool isFloatingTitle)572 RefPtr<RenderText> ContainerModalElement::GetTitleRender(bool isFloatingTitle)
573 {
574 auto titleBoxElement = isFloatingTitle ? floatingTitleBox_ : titleBox_;
575 CHECK_NULL_RETURN(titleBoxElement, nullptr);
576 auto rowElement = AceType::DynamicCast<RowElement>(titleBoxElement->GetFirstChild());
577 CHECK_NULL_RETURN(rowElement, nullptr);
578 auto renderRow = AceType::DynamicCast<RenderFlex>(rowElement->GetRenderNode());
579 CHECK_NULL_RETURN(renderRow, nullptr);
580 const auto& children = renderRow->GetChildren();
581 if (children.size() <= TITLE_POSITION) {
582 LOGW("row children size is wrong");
583 return nullptr;
584 }
585 auto iterator = renderRow->GetChildren().begin();
586 std::advance(iterator, TITLE_POSITION);
587 auto title = AceType::DynamicCast<RenderText>(*iterator);
588 return title;
589 }
590
GetIconRender(bool isFloatingTitle)591 RefPtr<RenderImage> ContainerModalElement::GetIconRender(bool isFloatingTitle)
592 {
593 auto titleBoxElement = isFloatingTitle ? floatingTitleBox_ : titleBox_;
594 CHECK_NULL_RETURN(titleBoxElement, nullptr);
595 auto rowElement = AceType::DynamicCast<RowElement>(titleBoxElement->GetFirstChild());
596 CHECK_NULL_RETURN(rowElement, nullptr);
597 auto renderRow = AceType::DynamicCast<RenderFlex>(rowElement->GetRenderNode());
598 CHECK_NULL_RETURN(renderRow, nullptr);
599 auto renderPadding = AceType::DynamicCast<RenderPadding>(renderRow->GetFirstChild());
600 CHECK_NULL_RETURN(renderPadding, nullptr);
601 auto icon = AceType::DynamicCast<RenderImage>(renderPadding->GetFirstChild());
602 return icon;
603 }
604
SetTitleAccessibilityNodeOffset()605 void ContainerModalElement::SetTitleAccessibilityNodeOffset()
606 {
607 CHECK_NULL_VOID(floatingTitleBox_);
608 auto floatingTitleBoxRender = AceType::DynamicCast<RenderBox>(floatingTitleBox_->GetRenderNode());
609 if (floatingTitleBoxRender) {
610 auto accessibilityNode = floatingTitleBoxRender->GetAccessibilityNode().Upgrade();
611 if (accessibilityNode) {
612 Offset globalOffset =
613 (floatingTitleBoxRender->GetGlobalOffsetExternal() + floatingTitleBoxRender->GetMargin().GetOffset()) *
614 floatingTitleBoxRender->GetContext().Upgrade()->GetViewScale();
615 Offset transformOffset(
616 globalOffset.GetX() - accessibilityNode->GetLeft(), globalOffset.GetY() - accessibilityNode->GetTop());
617 accessibilityNode->AddOffsetForChildren(transformOffset);
618 }
619 }
620 }
621
622 } // namespace OHOS::Ace
623