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