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