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