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