• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2024 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_ng/pattern/container_modal/container_modal_pattern.h"
17 
18 #include "base/subwindow/subwindow_manager.h"
19 #include "core/components_ng/pattern/button/button_event_hub.h"
20 #include "core/components_ng/pattern/container_modal/container_modal_theme.h"
21 #include "core/components_ng/pattern/button/button_layout_property.h"
22 #include "core/components_ng/pattern/image/image_layout_property.h"
23 #include "core/components_ng/pattern/linear_layout/linear_layout_property.h"
24 
25 namespace OHOS::Ace::NG {
26 
27 namespace {
28 constexpr int32_t LEFT_SPLIT_BUTTON_INDEX = 0;
29 constexpr int32_t MAX_RECOVER_BUTTON_INDEX = 1;
30 constexpr int32_t MINIMIZE_BUTTON_INDEX = 2;
31 constexpr int32_t CLOSE_BUTTON_INDEX = 3;
32 constexpr int32_t TITLE_POPUP_DURATION = 200;
33 constexpr double MOUSE_MOVE_POPUP_DISTANCE = 5.0; // 5.0px
34 constexpr double MOVE_POPUP_DISTANCE_X = 40.0;    // 40.0px
35 constexpr double MOVE_POPUP_DISTANCE_Y = 20.0;    // 20.0px
36 constexpr double TITLE_POPUP_DISTANCE = 37.0;     // 37vp height of title
37 } // namespace
38 
ShowTitle(bool isShow,bool hasDeco,bool needUpdate)39 void ContainerModalPattern::ShowTitle(bool isShow, bool hasDeco, bool needUpdate)
40 {
41     auto containerNode = GetHost();
42     CHECK_NULL_VOID(containerNode);
43     auto customTitleRow = GetCustomTitleRow();
44     CHECK_NULL_VOID(customTitleRow);
45     auto floatingTitleRow = GetFloatingTitleRow();
46     CHECK_NULL_VOID(floatingTitleRow);
47     if (needUpdate) {
48         TAG_LOGI(AceLogTag::ACE_APPBAR, "title is need update, isFocus_: %{public}d", isFocus_);
49         ChangeCustomTitle(isFocus_);
50         ChangeControlButtons(isFocus_);
51         return;
52     }
53 
54     auto pipelineContext = PipelineContext::GetCurrentContext();
55     CHECK_NULL_VOID(pipelineContext);
56     auto theme = pipelineContext->GetTheme<ContainerModalTheme>();
57     auto stackNode = GetStackNode();
58     CHECK_NULL_VOID(stackNode);
59     auto windowManager = pipelineContext->GetWindowManager();
60     CHECK_NULL_VOID(windowManager);
61     windowMode_ = windowManager->GetWindowMode();
62     hasDeco_ = hasDeco;
63     TAG_LOGI(AceLogTag::ACE_APPBAR, "ShowTitle isShow: %{public}d, windowMode: %{public}d, hasDeco: %{public}d",
64         isShow, windowMode_, hasDeco_);
65     if (!hasDeco_) {
66         isShow = false;
67     }
68 
69     isTitleShow_ = isShow;
70 
71     // update container modal padding and border
72     auto layoutProperty = containerNode->GetLayoutProperty();
73     CHECK_NULL_VOID(layoutProperty);
74     layoutProperty->UpdateAlignment(Alignment::TOP_LEFT);
75     PaddingProperty padding;
76     if (isShow && customTitleSettedShow_) {
77         padding = { CalcLength(CONTENT_PADDING), CalcLength(CONTENT_PADDING), std::nullopt,
78             CalcLength(CONTENT_PADDING), std::nullopt, std::nullopt };
79     }
80     layoutProperty->UpdatePadding(padding);
81     BorderWidthProperty borderWidth;
82     layoutProperty->UpdateBorderWidth(borderWidth);
83 
84     auto renderContext = containerNode->GetRenderContext();
85     CHECK_NULL_VOID(renderContext);
86     renderContext->SetClipToBounds(true);
87     renderContext->UpdateBackgroundColor(GetContainerColor(isFocus_));
88     BorderRadiusProperty borderRadius;
89     borderRadius.SetRadius(isShow ? CONTAINER_OUTER_RADIUS : 0.0_vp);
90     renderContext->UpdateBorderRadius(borderRadius);
91     BorderColorProperty borderColor;
92     borderColor.SetColor(isShow ? CONTAINER_BORDER_COLOR : Color::TRANSPARENT);
93     renderContext->UpdateBorderColor(borderColor);
94 
95     // update stack content border
96     auto stackLayoutProperty = stackNode->GetLayoutProperty();
97     CHECK_NULL_VOID(stackLayoutProperty);
98     stackLayoutProperty->UpdateLayoutWeight(1.0f);
99     auto stackRenderContext = stackNode->GetRenderContext();
100     CHECK_NULL_VOID(stackRenderContext);
101     stackRenderContext->SetClipToBounds(true);
102 
103     auto customTitleLayoutProperty = customTitleRow->GetLayoutProperty();
104     CHECK_NULL_VOID(customTitleLayoutProperty);
105     customTitleLayoutProperty->UpdateVisibility(
106         (isShow && customTitleSettedShow_) ? VisibleType::VISIBLE : VisibleType::GONE);
107     auto floatingLayoutProperty = floatingTitleRow->GetLayoutProperty();
108     CHECK_NULL_VOID(floatingLayoutProperty);
109     floatingLayoutProperty->UpdateVisibility(VisibleType::GONE);
110 
111     auto controlButtonsNode = GetControlButtonRow();
112     CHECK_NULL_VOID(controlButtonsNode);
113     auto controlButtonsLayoutProperty = controlButtonsNode->GetLayoutProperty();
114     CHECK_NULL_VOID(controlButtonsLayoutProperty);
115     AddPanEvent(controlButtonsNode);
116     ChangeFloatingTitle(isFocus_);
117     ChangeControlButtons(isFocus_);
118 
119     auto controlButtonsContext = controlButtonsNode->GetRenderContext();
120     CHECK_NULL_VOID(controlButtonsContext);
121     controlButtonsLayoutProperty->UpdateVisibility(isShow ? VisibleType::VISIBLE : VisibleType::GONE);
122 }
123 
InitContainerEvent()124 void ContainerModalPattern::InitContainerEvent()
125 {
126     bool isChangeTitleStyle = SystemProperties::GetTitleStyleEnabled();
127     if (isChangeTitleStyle) {
128         return;
129     }
130     auto containerNode = GetHost();
131     CHECK_NULL_VOID(containerNode);
132     auto touchEventHub = containerNode->GetOrCreateGestureEventHub();
133     CHECK_NULL_VOID(touchEventHub);
134     auto controlButtonsNode = GetControlButtonRow();
135     CHECK_NULL_VOID(controlButtonsNode);
136     auto controlButtonsLayoutProperty = controlButtonsNode->GetLayoutProperty();
137     CHECK_NULL_VOID(controlButtonsLayoutProperty);
138     auto controlButtonsContext = controlButtonsNode->GetRenderContext();
139     CHECK_NULL_VOID(controlButtonsContext);
140 
141     auto floatingTitleRow = GetFloatingTitleRow();
142     CHECK_NULL_VOID(floatingTitleRow);
143     auto floatingLayoutProperty = floatingTitleRow->GetLayoutProperty();
144     CHECK_NULL_VOID(floatingLayoutProperty);
145     auto floatingContext = floatingTitleRow->GetRenderContext();
146     CHECK_NULL_VOID(floatingContext);
147 
148     auto containerNodeContext = containerNode->GetContext();
149     CHECK_NULL_VOID(containerNodeContext);
150     auto titlePopupDistance = TITLE_POPUP_DISTANCE * containerNodeContext->GetDensity();
151     AnimationOption option;
152     option.SetDuration(TITLE_POPUP_DURATION);
153     option.SetCurve(Curves::EASE_IN_OUT);
154 
155     // init touch event
156     touchEventHub->SetTouchEvent([controlButtonsLayoutProperty, floatingLayoutProperty, controlButtonsContext,
157                                      floatingContext, option, titlePopupDistance,
158                                      weak = WeakClaim(this)](TouchEventInfo& info) {
159         auto container = weak.Upgrade();
160         CHECK_NULL_VOID(container);
161         if (!container->hasDeco_) {
162             return;
163         }
164         if (info.GetChangedTouches().begin()->GetGlobalLocation().GetY() <= titlePopupDistance) {
165             // step1. Record the coordinates of the start of the touch.
166             if (info.GetChangedTouches().begin()->GetTouchType() == TouchType::DOWN) {
167                 container->moveX_ = static_cast<float>(info.GetChangedTouches().begin()->GetGlobalLocation().GetX());
168                 container->moveY_ = static_cast<float>(info.GetChangedTouches().begin()->GetGlobalLocation().GetY());
169                 return;
170             }
171             if (info.GetChangedTouches().begin()->GetTouchType() != TouchType::MOVE ||
172                 !container->CanShowFloatingTitle()) {
173                 return;
174             }
175 
176             // step2. Calculate the coordinates of touch move relative to touch down.
177             auto deltaMoveX = fabs(info.GetChangedTouches().begin()->GetGlobalLocation().GetX() - container->moveX_);
178             auto deltaMoveY = info.GetChangedTouches().begin()->GetGlobalLocation().GetY() - container->moveY_;
179             // step3. If the horizontal distance of the touch move does not exceed 10px and the vertical distance
180             // exceeds 20px, the floating title will be displayed.
181             if (deltaMoveX <= MOVE_POPUP_DISTANCE_X && deltaMoveY >= MOVE_POPUP_DISTANCE_Y) {
182                 controlButtonsContext->OnTransformTranslateUpdate(
183                     { 0.0f, static_cast<float>(-titlePopupDistance), 0.0f });
184                 controlButtonsLayoutProperty->UpdateVisibility(VisibleType::VISIBLE);
185                 AnimationUtils::Animate(option, [controlButtonsContext]() {
186                     controlButtonsContext->OnTransformTranslateUpdate({ 0.0f, 0.0f, 0.0f });
187                 });
188                 floatingContext->OnTransformTranslateUpdate({ 0.0f, static_cast<float>(-titlePopupDistance), 0.0f });
189                 floatingLayoutProperty->UpdateVisibility(
190                     container->floatingTitleSettedShow_ ? VisibleType::VISIBLE : VisibleType::GONE);
191                 AnimationUtils::Animate(option, [floatingContext]() {
192                     floatingContext->OnTransformTranslateUpdate({ 0.0f, 0.0f, 0.0f });
193                 });
194             }
195             return;
196         }
197         if (info.GetChangedTouches().begin()->GetTouchType() != TouchType::DOWN) {
198             return;
199         }
200         if (floatingLayoutProperty->GetVisibilityValue(VisibleType::GONE) != VisibleType::VISIBLE) {
201             return;
202         }
203         // step4. Touch other area to hide floating title.
204         AnimationUtils::Animate(
205             option,
206             [controlButtonsContext, floatingContext, titlePopupDistance]() {
207                 controlButtonsContext->OnTransformTranslateUpdate(
208                     { 0.0f, static_cast<float>(-titlePopupDistance), 0.0f });
209                 floatingContext->OnTransformTranslateUpdate({ 0.0f, static_cast<float>(-titlePopupDistance), 0.0f });
210             },
211             [floatingLayoutProperty, id = Container::CurrentId()]() {
212                 ContainerScope scope(id);
213                 floatingLayoutProperty->UpdateVisibility(VisibleType::GONE);
214             });
215     });
216 
217     // init mouse event
218     auto mouseEventHub = containerNode->GetOrCreateInputEventHub();
219     CHECK_NULL_VOID(mouseEventHub);
220     mouseEventHub->SetMouseEvent([controlButtonsLayoutProperty, floatingLayoutProperty, controlButtonsContext,
221                                      floatingContext, option, titlePopupDistance,
222                                      weak = WeakClaim(this)](MouseInfo& info) {
223         auto container = weak.Upgrade();
224         CHECK_NULL_VOID(container);
225         auto action = info.GetAction();
226         if ((action != MouseAction::MOVE && action != MouseAction::WINDOW_LEAVE) || !container->hasDeco_) {
227             return;
228         }
229         if (info.GetLocalLocation().GetY() <= MOUSE_MOVE_POPUP_DISTANCE && container->CanShowFloatingTitle()) {
230             controlButtonsContext->OnTransformTranslateUpdate({ 0.0f, static_cast<float>(-titlePopupDistance), 0.0f });
231             controlButtonsLayoutProperty->UpdateVisibility(VisibleType::VISIBLE);
232             AnimationUtils::Animate(option, [controlButtonsContext]() {
233                 controlButtonsContext->OnTransformTranslateUpdate({ 0.0f, 0.0f, 0.0f });
234             });
235             floatingContext->OnTransformTranslateUpdate({ 0.0f, static_cast<float>(-titlePopupDistance), 0.0f });
236             floatingLayoutProperty->UpdateVisibility(
237                 container->floatingTitleSettedShow_ ? VisibleType::VISIBLE : VisibleType::GONE);
238             AnimationUtils::Animate(option, [floatingContext]() {
239                 floatingContext->OnTransformTranslateUpdate({ 0.0f, 0.0f, 0.0f });
240             });
241         }
242 
243         if (!container->CanHideFloatingTitle()) {
244             return;
245         }
246         if ((info.GetLocalLocation().GetY() >= titlePopupDistance || action == MouseAction::WINDOW_LEAVE) &&
247             floatingLayoutProperty->GetVisibilityValue(VisibleType::GONE) == VisibleType::VISIBLE) {
248             AnimationUtils::Animate(
249                 option,
250                 [controlButtonsContext, floatingContext, titlePopupDistance]() {
251                     controlButtonsContext->OnTransformTranslateUpdate(
252                         { 0.0f, static_cast<float>(-titlePopupDistance), 0.0f });
253                     floatingContext->OnTransformTranslateUpdate(
254                         { 0.0f, static_cast<float>(-titlePopupDistance), 0.0f });
255                 },
256                 [floatingLayoutProperty]() {
257                     floatingLayoutProperty->UpdateVisibility(VisibleType::GONE);
258                 });
259         }
260     });
261 }
262 
AddPanEvent(const RefPtr<FrameNode> & controlButtonsNode)263 void ContainerModalPattern::AddPanEvent(const RefPtr<FrameNode>& controlButtonsNode)
264 {
265     auto eventHub = controlButtonsNode->GetOrCreateGestureEventHub();
266     CHECK_NULL_VOID(eventHub);
267     PanDirection panDirection;
268     panDirection.type = PanDirection::ALL;
269 
270     if (!panEvent_) {
271         auto pipeline = PipelineContext::GetCurrentContext();
272         CHECK_NULL_VOID(pipeline);
273         auto windowManager = pipeline->GetWindowManager();
274         CHECK_NULL_VOID(windowManager);
275         // touch the title to move the floating window
276         auto panActionStart = [wk = WeakClaim(RawPtr(windowManager))](const GestureEvent& event) {
277             auto windowManager = wk.Upgrade();
278             CHECK_NULL_VOID(windowManager);
279             auto currentWindowMode = windowManager->GetCurrentWindowMaximizeMode();
280             TAG_LOGI(AceLogTag::ACE_APPBAR, "container window pan recognized. currentWindowMode = %{public}d",
281                 currentWindowMode);
282             if ((windowManager->GetCurrentWindowMaximizeMode() != MaximizeMode::MODE_AVOID_SYSTEM_BAR) &&
283                 (event.GetSourceTool() != SourceTool::TOUCHPAD)) {
284                 windowManager->WindowStartMove();
285                 SubwindowManager::GetInstance()->ClearToastInSubwindow();
286             }
287         };
288         panEvent_ = MakeRefPtr<PanEvent>(std::move(panActionStart), nullptr, nullptr, nullptr);
289     }
290     eventHub->AddPanEvent(panEvent_, panDirection, DEFAULT_PAN_FINGER, DEFAULT_PAN_DISTANCE);
291 }
292 
RemovePanEvent(const RefPtr<FrameNode> & controlButtonsNode)293 void ContainerModalPattern::RemovePanEvent(const RefPtr<FrameNode>& controlButtonsNode)
294 {
295     auto eventHub = controlButtonsNode->GetOrCreateGestureEventHub();
296     CHECK_NULL_VOID(eventHub);
297 
298     if (!panEvent_) {
299         return;
300     }
301     eventHub->RemovePanEvent(panEvent_);
302 }
303 
OnWindowActivated()304 void ContainerModalPattern::OnWindowActivated()
305 {
306     WindowFocus(true);
307 }
308 
OnWindowDeactivated()309 void ContainerModalPattern::OnWindowDeactivated()
310 {
311     WindowFocus(false);
312 }
313 
OnWindowForceUnfocused()314 void ContainerModalPattern::OnWindowForceUnfocused() {}
315 
WindowFocus(bool isFocus)316 void ContainerModalPattern::WindowFocus(bool isFocus)
317 {
318     auto pipelineContext = PipelineContext::GetCurrentContext();
319     CHECK_NULL_VOID(pipelineContext);
320     auto theme = pipelineContext->GetTheme<ContainerModalTheme>();
321     isFocus_ = isFocus;
322     auto containerNode = GetHost();
323     CHECK_NULL_VOID(containerNode);
324 
325     // update container modal background
326     auto renderContext = containerNode->GetRenderContext();
327     CHECK_NULL_VOID(renderContext);
328     renderContext->UpdateBackgroundColor(GetContainerColor(isFocus_));
329     BorderColorProperty borderColor;
330     borderColor.SetColor(isFocus ? CONTAINER_BORDER_COLOR : CONTAINER_BORDER_COLOR_LOST_FOCUS);
331     renderContext->UpdateBorderColor(borderColor);
332 
333     ChangeCustomTitle(isFocus);
334     ChangeFloatingTitle(isFocus);
335     ChangeControlButtons(isFocus);
336 }
337 
ChangeCustomTitle(bool isFocus)338 void ContainerModalPattern::ChangeCustomTitle(bool isFocus)
339 {
340     // update custom title label
341     auto customTitleNode = GetCustomTitleNode();
342     CHECK_NULL_VOID(customTitleNode);
343     isFocus ? customTitleNode->FireOnWindowFocusedCallback() : customTitleNode->FireOnWindowUnfocusedCallback();
344 }
345 
ChangeControlButtons(bool isFocus)346 void ContainerModalPattern::ChangeControlButtons(bool isFocus)
347 {
348     auto containerNode = GetHost();
349     CHECK_NULL_VOID(containerNode);
350     auto controlButtonsNode = GetControlButtonRow();
351     CHECK_NULL_VOID(controlButtonsNode);
352 
353     // update leftSplit button
354     auto leftSplitButton =
355         AceType::DynamicCast<FrameNode>(GetTitleItemByIndex(controlButtonsNode, LEFT_SPLIT_BUTTON_INDEX));
356     CHECK_NULL_VOID(leftSplitButton);
357     ChangeTitleButtonIcon(leftSplitButton,
358         isFocus ? InternalResource::ResourceId::CONTAINER_MODAL_WINDOW_SPLIT_LEFT
359                 : InternalResource::ResourceId::CONTAINER_MODAL_WINDOW_DEFOCUS_SPLIT_LEFT,
360         isFocus, false);
361 
362     // hide leftSplit button when window mode is WINDOW_MODE_SPLIT_PRIMARY type or split button can not show
363     bool hideLeftSplit = hideSplitButton_ || windowMode_ == WindowMode::WINDOW_MODE_SPLIT_PRIMARY;
364     leftSplitButton->GetLayoutProperty()->UpdateVisibility(hideLeftSplit ? VisibleType::GONE : VisibleType::VISIBLE);
365 
366     // update maximize button
367     auto maximizeButton =
368         AceType::DynamicCast<FrameNode>(GetTitleItemByIndex(controlButtonsNode, MAX_RECOVER_BUTTON_INDEX));
369     CHECK_NULL_VOID(maximizeButton);
370     auto pipeline = PipelineContext::GetCurrentContext();
371     auto windowManager = pipeline->GetWindowManager();
372     MaximizeMode mode = windowManager->GetCurrentWindowMaximizeMode();
373     InternalResource::ResourceId maxId;
374     if (mode == MaximizeMode::MODE_AVOID_SYSTEM_BAR || windowMode_ == WindowMode::WINDOW_MODE_FULLSCREEN) {
375         maxId = InternalResource::ResourceId::CONTAINER_MODAL_WINDOW_RECOVER;
376     } else {
377         maxId = InternalResource::ResourceId::CONTAINER_MODAL_WINDOW_MAXIMIZE;
378     }
379 
380     ChangeTitleButtonIcon(maximizeButton, maxId, isFocus, false);
381     // update minimize button
382     auto minimizeButton =
383         AceType::DynamicCast<FrameNode>(GetTitleItemByIndex(controlButtonsNode, MINIMIZE_BUTTON_INDEX));
384     CHECK_NULL_VOID(minimizeButton);
385     ChangeTitleButtonIcon(minimizeButton,
386         InternalResource::ResourceId::CONTAINER_MODAL_WINDOW_MINIMIZE, isFocus, false);
387 
388     // update close button
389     auto closeButton = AceType::DynamicCast<FrameNode>(GetTitleItemByIndex(controlButtonsNode, CLOSE_BUTTON_INDEX));
390     CHECK_NULL_VOID(closeButton);
391     ChangeTitleButtonIcon(closeButton,
392         InternalResource::ResourceId::CONTAINER_MODAL_WINDOW_CLOSE, isFocus, true);
393 }
394 
ChangeFloatingTitle(bool isFocus)395 void ContainerModalPattern::ChangeFloatingTitle(bool isFocus)
396 {
397     // update floating custom title label
398     auto customFloatingTitleNode = GetFloatingTitleNode();
399     CHECK_NULL_VOID(customFloatingTitleNode);
400     isFocus ? customFloatingTitleNode->FireOnWindowFocusedCallback()
401             : customFloatingTitleNode->FireOnWindowUnfocusedCallback();
402 }
403 
ChangeTitleButtonIcon(const RefPtr<FrameNode> & buttonNode,InternalResource::ResourceId icon,bool isFocus,bool isCloseBtn)404 void ContainerModalPattern::ChangeTitleButtonIcon(
405     const RefPtr<FrameNode>& buttonNode, InternalResource::ResourceId icon, bool isFocus, bool isCloseBtn)
406 {
407     auto theme = PipelineContext::GetCurrentContext()->GetTheme<ContainerModalTheme>();
408     auto renderContext = buttonNode->GetRenderContext();
409     CHECK_NULL_VOID(renderContext);
410     auto colorType = isFocus ? ControlBtnColorType::NORMAL : ControlBtnColorType::UNFOCUS;
411     auto color = theme->GetControlBtnColor(isCloseBtn, colorType);
412     renderContext->UpdateBackgroundColor(color);
413     auto buttonIcon = AceType::DynamicCast<FrameNode>(buttonNode->GetChildren().front());
414     CHECK_NULL_VOID(buttonIcon);
415     ImageSourceInfo imageSourceInfo;
416     imageSourceInfo.SetResourceId(icon);
417     colorType = isFocus ? ControlBtnColorType::NORMAL_FILL : ControlBtnColorType::UNFOCUS_FILL;
418     color = theme->GetControlBtnColor(isCloseBtn,  colorType);
419     imageSourceInfo.SetFillColor(color);
420     auto imageLayoutProperty = buttonIcon->GetLayoutProperty<ImageLayoutProperty>();
421     imageLayoutProperty->UpdateImageSourceInfo(imageSourceInfo);
422     buttonIcon->MarkModifyDone();
423     buttonNode->MarkModifyDone();
424 }
425 
CanShowFloatingTitle()426 bool ContainerModalPattern::CanShowFloatingTitle()
427 {
428     auto floatingTitleRow = GetFloatingTitleRow();
429     CHECK_NULL_RETURN(floatingTitleRow, false);
430     auto floatingLayoutProperty = floatingTitleRow->GetLayoutProperty();
431     CHECK_NULL_RETURN(floatingLayoutProperty, false);
432 
433     if (windowMode_ != WindowMode::WINDOW_MODE_FULLSCREEN && windowMode_ != WindowMode::WINDOW_MODE_SPLIT_PRIMARY &&
434         windowMode_ != WindowMode::WINDOW_MODE_SPLIT_SECONDARY) {
435         TAG_LOGI(AceLogTag::ACE_APPBAR, "Window is not full screen or split screen, can not show floating title.");
436         return false;
437     }
438 
439     if (floatingLayoutProperty->GetVisibilityValue(VisibleType::GONE) == VisibleType::VISIBLE) {
440         TAG_LOGI(AceLogTag::ACE_APPBAR, "Floating tittle is visible now, no need to show again.");
441         return false;
442     }
443     return true;
444 }
445 
SetAppTitle(const std::string & title)446 void ContainerModalPattern::SetAppTitle(const std::string& title)
447 {
448     TAG_LOGI(AceLogTag::ACE_APPBAR, "SetAppTitle successfully");
449     auto customTitleNode = GetCustomTitleNode();
450     CHECK_NULL_VOID(customTitleNode);
451     customTitleNode->FireAppTitleCallback(title);
452 
453     // call setTitle() callback for backButton bar
454     auto controllButtonRow = GetCustomButtonNode();
455     CHECK_NULL_VOID(controllButtonRow);
456     controllButtonRow->FireAppTitleCallback(title);
457 
458     auto customFloatingTitleNode = GetFloatingTitleNode();
459     CHECK_NULL_VOID(customFloatingTitleNode);
460     customFloatingTitleNode->FireAppTitleCallback(title);
461 }
462 
SetAppIcon(const RefPtr<PixelMap> & icon)463 void ContainerModalPattern::SetAppIcon(const RefPtr<PixelMap>& icon)
464 {
465     CHECK_NULL_VOID(icon);
466     TAG_LOGI(AceLogTag::ACE_APPBAR, "SetAppIcon successfully");
467     auto customTitleNode = GetCustomTitleNode();
468     CHECK_NULL_VOID(customTitleNode);
469     customTitleNode->FireAppIconCallback(icon);
470 
471     auto customFloatingTitleNode = GetFloatingTitleNode();
472     CHECK_NULL_VOID(customFloatingTitleNode);
473     customFloatingTitleNode->FireAppIconCallback(icon);
474 }
475 
SetTitleButtonHide(const RefPtr<FrameNode> & controlButtonsNode,bool hideSplit,bool hideMaximize,bool hideMinimize,bool hideClose)476 void ContainerModalPattern::SetTitleButtonHide(
477     const RefPtr<FrameNode>& controlButtonsNode, bool hideSplit, bool hideMaximize, bool hideMinimize, bool hideClose)
478 {
479     auto leftSplitButton =
480         AceType::DynamicCast<FrameNode>(GetTitleItemByIndex(controlButtonsNode, LEFT_SPLIT_BUTTON_INDEX));
481     CHECK_NULL_VOID(leftSplitButton);
482     leftSplitButton->GetLayoutProperty()->UpdateVisibility(hideSplit ? VisibleType::GONE : VisibleType::VISIBLE);
483     leftSplitButton->MarkDirtyNode();
484 
485     auto maximizeButton =
486         AceType::DynamicCast<FrameNode>(GetTitleItemByIndex(controlButtonsNode, MAX_RECOVER_BUTTON_INDEX));
487     CHECK_NULL_VOID(maximizeButton);
488     maximizeButton->GetLayoutProperty()->UpdateVisibility(hideMaximize ? VisibleType::GONE : VisibleType::VISIBLE);
489     maximizeButton->MarkDirtyNode();
490 
491     auto minimizeButton = AceType::DynamicCast<FrameNode>(
492         GetTitleItemByIndex(controlButtonsNode, MINIMIZE_BUTTON_INDEX));
493     CHECK_NULL_VOID(minimizeButton);
494     minimizeButton->GetLayoutProperty()->UpdateVisibility(hideMinimize ? VisibleType::GONE : VisibleType::VISIBLE);
495     minimizeButton->MarkDirtyNode();
496 
497     auto closeButton = AceType::DynamicCast<FrameNode>(GetTitleItemByIndex(controlButtonsNode, CLOSE_BUTTON_INDEX));
498     CHECK_NULL_VOID(closeButton);
499     closeButton->GetLayoutProperty()->UpdateVisibility(hideClose ? VisibleType::GONE : VisibleType::VISIBLE);
500     closeButton->MarkDirtyNode();
501 }
502 
SetContainerButtonHide(bool hideSplit,bool hideMaximize,bool hideMinimize,bool hideClose)503 void ContainerModalPattern::SetContainerButtonHide(bool hideSplit, bool hideMaximize, bool hideMinimize, bool hideClose)
504 {
505     auto controlButtonsRow = GetControlButtonRow();
506     CHECK_NULL_VOID(controlButtonsRow);
507     SetTitleButtonHide(controlButtonsRow, hideSplit, hideMaximize, hideMinimize, hideClose);
508     hideSplitButton_ = hideSplit;
509     TAG_LOGI(AceLogTag::ACE_APPBAR,
510         "Set containerModal button status successfully, "
511         "hideSplit: %{public}d, hideMaximize: %{public}d, "
512         "hideMinimize: %{public}d, hideClose: %{public}d",
513         hideSplit, hideMaximize, hideMinimize, hideClose);
514 }
515 
SetCloseButtonStatus(bool isEnabled)516 void ContainerModalPattern::SetCloseButtonStatus(bool isEnabled)
517 {
518     auto controlButtonsRow = GetControlButtonRow();
519     CHECK_NULL_VOID(controlButtonsRow);
520 
521     // set closeButton enable or disable
522     auto closeButton = AceType::DynamicCast<FrameNode>(GetTitleItemByIndex(controlButtonsRow, CLOSE_BUTTON_INDEX));
523     CHECK_NULL_VOID(closeButton);
524     auto buttonEvent = closeButton->GetEventHub<ButtonEventHub>();
525     CHECK_NULL_VOID(buttonEvent);
526     buttonEvent->SetEnabled(isEnabled);
527     TAG_LOGI(AceLogTag::ACE_APPBAR, "Set close button status %{public}s", isEnabled ? "enable" : "disable");
528 }
529 
SetWindowContainerColor(const Color & activeColor,const Color & inactiveColor)530 void ContainerModalPattern::SetWindowContainerColor(const Color& activeColor, const Color& inactiveColor)
531 {
532     auto theme = PipelineContext::GetCurrentContext()->GetTheme<ContainerModalTheme>();
533     auto containerNode = GetHost();
534     CHECK_NULL_VOID(containerNode);
535     // update container modal background
536     auto renderContext = containerNode->GetRenderContext();
537     CHECK_NULL_VOID(renderContext);
538     activeColor_ = activeColor;
539     inactiveColor_ = inactiveColor;
540     isCustomColor_ = true;
541     renderContext->UpdateBackgroundColor(GetContainerColor(isFocus_));
542 }
543 
GetContainerColor(bool isFocus)544 Color ContainerModalPattern::GetContainerColor(bool isFocus)
545 {
546     auto theme = PipelineContext::GetCurrentContext()->GetTheme<ContainerModalTheme>();
547     return isCustomColor_ ? (isFocus ? activeColor_ : inactiveColor_) : theme->GetBackGroundColor(isFocus);
548 }
549 
UpdateGestureRowVisible()550 void ContainerModalPattern::UpdateGestureRowVisible()
551 {
552     auto gestureRow = GetGestureRow();
553     CHECK_NULL_VOID(gestureRow);
554     auto customTitleRow = GetCustomTitleRow();
555     CHECK_NULL_VOID(customTitleRow);
556     auto buttonsRow = GetControlButtonRow();
557     CHECK_NULL_VOID(buttonsRow);
558     auto gestureRowProp = gestureRow->GetLayoutProperty();
559     auto customTitleRowProp = customTitleRow->GetLayoutProperty();
560     auto buttonsRowProp = buttonsRow->GetLayoutProperty();
561     if (customTitleRowProp->GetVisibilityValue(VisibleType::VISIBLE) == VisibleType::GONE &&
562         buttonsRowProp->GetVisibilityValue(VisibleType::VISIBLE) == VisibleType::VISIBLE) {
563         gestureRowProp->UpdateVisibility(VisibleType::VISIBLE);
564     } else {
565         gestureRowProp->UpdateVisibility(VisibleType::GONE);
566     }
567 }
568 
SetContainerModalTitleVisible(bool customTitleSettedShow,bool floatingTitleSettedShow)569 void ContainerModalPattern::SetContainerModalTitleVisible(bool customTitleSettedShow, bool floatingTitleSettedShow)
570 {
571     TAG_LOGI(AceLogTag::ACE_APPBAR,
572         "ContainerModal customTitleSettedShow=%{public}d, floatingTitleSettedShow=%{public}d",
573         customTitleSettedShow, floatingTitleSettedShow);
574     customTitleSettedShow_ = customTitleSettedShow;
575     auto customTitleRow = GetCustomTitleRow();
576     CHECK_NULL_VOID(customTitleRow);
577     auto customTitleRowProp = customTitleRow->GetLayoutProperty();
578     if (!customTitleSettedShow) {
579         customTitleRowProp->UpdateVisibility(VisibleType::GONE);
580     } else if (CanShowCustomTitle()) {
581         customTitleRowProp->UpdateVisibility(VisibleType::VISIBLE);
582     }
583     floatingTitleSettedShow_ = floatingTitleSettedShow;
584     auto floatingTitleRow = GetFloatingTitleRow();
585     CHECK_NULL_VOID(floatingTitleRow);
586     auto floatingTitleRowProp = floatingTitleRow->GetLayoutProperty();
587     if (!floatingTitleSettedShow) {
588         floatingTitleRowProp->UpdateVisibility(VisibleType::GONE);
589     }
590 
591     auto buttonsRow = GetControlButtonRow();
592     CHECK_NULL_VOID(buttonsRow);
593     buttonsRow->SetHitTestMode(HitTestMode::HTMTRANSPARENT_SELF);
594     UpdateGestureRowVisible();
595     TrimFloatingWindowLayout();
596 }
597 
GetContainerModalTitleVisible(bool isImmersive)598 bool ContainerModalPattern::GetContainerModalTitleVisible(bool isImmersive)
599 {
600     if (isImmersive) {
601         auto floatingTitleRow = GetFloatingTitleRow();
602         CHECK_NULL_RETURN(floatingTitleRow, false);
603         auto floatingLayoutProperty = floatingTitleRow->GetLayoutProperty();
604         CHECK_NULL_RETURN(floatingLayoutProperty, false);
605         return floatingLayoutProperty->GetVisibilityValue(VisibleType::GONE) == VisibleType::VISIBLE;
606     } else {
607         return isTitleShow_ && customTitleSettedShow_;
608     }
609 }
610 
SetContainerModalTitleHeight(int32_t height)611 void ContainerModalPattern::SetContainerModalTitleHeight(int32_t height)
612 {
613     TAG_LOGI(AceLogTag::ACE_APPBAR, "ContainerModal SetContainerModalTitleHeight height=%{public}d", height);
614     if (height < 0) {
615         height = 0;
616     }
617     titleHeight_ = Dimension(Dimension(height, DimensionUnit::PX).ConvertToVp(), DimensionUnit::VP);
618     auto customTitleRow = GetCustomTitleRow();
619     UpdateRowHeight(customTitleRow, titleHeight_);
620     auto controlButtonsRow = GetControlButtonRow();
621     UpdateRowHeight(controlButtonsRow, titleHeight_);
622     auto gestureRow = GetGestureRow();
623     UpdateRowHeight(gestureRow, titleHeight_);
624     CallButtonsRectChange();
625 }
626 
GetContainerModalTitleHeight()627 int32_t ContainerModalPattern::GetContainerModalTitleHeight()
628 {
629     return static_cast<int32_t>(ceil(titleHeight_.ConvertToPx()));
630 }
631 
GetContainerModalButtonsRect(RectF & containerModal,RectF & buttons)632 bool ContainerModalPattern::GetContainerModalButtonsRect(RectF& containerModal, RectF& buttons)
633 {
634     auto column = GetColumnNode();
635     CHECK_NULL_RETURN(column, false);
636     auto columnRect = column->GetGeometryNode()->GetFrameRect();
637     containerModal = columnRect;
638     if (columnRect.Width() == 0) {
639         TAG_LOGW(AceLogTag::ACE_APPBAR, "Get rect of buttons failed, the rect is measuring.");
640         return false;
641     }
642 
643     auto controlButtonsRow = GetControlButtonRow();
644     CHECK_NULL_RETURN(controlButtonsRow, false);
645     auto controlButtonsRowLayoutProperty = controlButtonsRow->GetLayoutProperty();
646     CHECK_NULL_RETURN(controlButtonsRowLayoutProperty, false);
647     if (controlButtonsRowLayoutProperty->GetVisibilityValue(VisibleType::VISIBLE) != VisibleType::VISIBLE) {
648         TAG_LOGW(AceLogTag::ACE_APPBAR, "Get rect of buttons failed, buttonRow are hidden");
649         return false;
650     }
651     auto children = controlButtonsRow->GetChildren();
652     RectF firstButtonRect;
653     RectF lastButtonRect;
654     for (auto& child : children) {
655         auto node = AceType::DynamicCast<FrameNode>(child);
656         if (node->GetLayoutProperty()->GetVisibilityValue(VisibleType::VISIBLE) != VisibleType::VISIBLE) {
657             continue;
658         }
659         auto rect = node->GetGeometryNode()->GetFrameRect();
660         if (firstButtonRect.Width() == 0) {
661             firstButtonRect = rect;
662         }
663         lastButtonRect = rect;
664     }
665     buttons = firstButtonRect.CombineRectT(lastButtonRect);
666     if (buttons.Width() == 0) {
667         TAG_LOGW(AceLogTag::ACE_APPBAR, "Get rect of buttons failed, buttons are hidden");
668         return false;
669     }
670 
671     auto widthByPx = (TITLE_PADDING_START + TITLE_PADDING_END).ConvertToPx() + buttons.Width();
672     auto isRtl = AceApplicationInfo::GetInstance().IsRightToLeft();
673     if (isRtl) {
674         buttons.SetLeft(0);
675     } else {
676         buttons.SetLeft(containerModal.Width() - widthByPx);
677     }
678     buttons.SetTop(0);
679     buttons.SetWidth(widthByPx);
680     buttons.SetHeight(titleHeight_.ConvertToPx());
681     return true;
682 }
683 
SubscribeContainerModalButtonsRectChange(std::function<void (RectF & containerModal,RectF & buttons)> && callback)684 void ContainerModalPattern::SubscribeContainerModalButtonsRectChange(
685     std::function<void(RectF& containerModal, RectF& buttons)>&& callback)
686 {
687     controlButtonsRectChangeCallback_ = std::move(callback);
688 }
689 
GetWindowPaintRectWithoutMeasureAndLayout(RectInt & rect)690 void ContainerModalPattern::GetWindowPaintRectWithoutMeasureAndLayout(RectInt& rect)
691 {
692     auto host = GetHost();
693     CHECK_NULL_VOID(host);
694     auto layoutProperty = host->GetLayoutProperty();
695     CHECK_NULL_VOID(layoutProperty);
696     auto titleHeight = round(GetCustomTitleHeight().ConvertToPx());
697     auto padding = layoutProperty->CreatePaddingAndBorder();
698     rect.SetRect(padding.Offset().GetX(), padding.Offset().GetY() + titleHeight, rect.Width() - padding.Width(),
699         rect.Height() - padding.Height() - titleHeight);
700 }
701 
GetWindowPaintRectWithoutMeasureAndLayout(Rect & rect,bool isContainerModal)702 void ContainerModalPattern::GetWindowPaintRectWithoutMeasureAndLayout(Rect& rect, bool isContainerModal)
703 {
704     auto host = GetHost();
705     CHECK_NULL_VOID(host);
706     auto layoutProperty = host->GetLayoutProperty();
707     CHECK_NULL_VOID(layoutProperty);
708     auto titleHeight = GetCustomTitleHeight().ConvertToPx();
709     auto padding = layoutProperty->CreatePaddingAndBorder();
710     rect.SetRect(
711         padding.Offset().GetX(),
712         isContainerModal ? padding.Offset().GetY() + titleHeight : padding.Offset().GetY(),
713         rect.Width() - padding.Width(),
714         rect.Height() - padding.Height() - titleHeight);
715 }
716 
CallButtonsRectChange()717 void ContainerModalPattern::CallButtonsRectChange()
718 {
719     RectF containerModal;
720     RectF buttons;
721     GetContainerModalButtonsRect(containerModal, buttons);
722     NotifyButtonsRectChange(containerModal, buttons);
723     CHECK_NULL_VOID(controlButtonsRectChangeCallback_);
724     if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_FIFTEEN)) {
725         if (isInitButtonsRect_ && buttonsRect_ == buttons) {
726             return;
727         }
728         isInitButtonsRect_ = true;
729     }
730     buttonsRect_ = buttons;
731     auto taskExecutor = Container::CurrentTaskExecutor();
732     CHECK_NULL_VOID(taskExecutor);
733     taskExecutor->PostTask(
734         [containerModal, buttons, cb = controlButtonsRectChangeCallback_]() mutable {
735             if (cb) {
736                 cb(containerModal, buttons);
737             }
738         },
739         TaskExecutor::TaskType::JS, "ArkUIContainerModalButtonsRectChange");
740 }
741 
InitTitle()742 void ContainerModalPattern::InitTitle()
743 {
744     auto pipeline = PipelineContext::GetCurrentContext();
745     CHECK_NULL_VOID(pipeline);
746     auto themeManager = pipeline->GetThemeManager();
747     CHECK_NULL_VOID(themeManager);
748     auto themeConstants = themeManager->GetThemeConstants();
749     CHECK_NULL_VOID(themeConstants);
750     auto id = pipeline->GetWindowManager()->GetAppIconId();
751     auto pixelMap = themeConstants->GetPixelMap(id);
752     if (pixelMap) {
753         RefPtr<PixelMap> icon = PixelMap::CreatePixelMap(&pixelMap);
754         SetAppIcon(icon);
755     } else {
756         TAG_LOGW(AceLogTag::ACE_APPBAR, "Cannot get pixelmap, try media path."); // use themeConstants GetMediaPath
757     }
758     SetAppTitle(themeConstants->GetString(pipeline->GetWindowManager()->GetAppLabelId()));
759 }
760 
Init()761 void ContainerModalPattern::Init()
762 {
763     InitContainerColor();
764     InitContainerEvent();
765     InitTitle();
766     InitLayoutProperty();
767 }
768 
InitContainerColor()769 void ContainerModalPattern::InitContainerColor()
770 {
771     auto pipelineContext = PipelineContext::GetCurrentContext();
772     CHECK_NULL_VOID(pipelineContext);
773     auto theme = pipelineContext->GetTheme<ContainerModalTheme>();
774     activeColor_ = theme->GetBackGroundColor(true);
775     inactiveColor_ = theme->GetBackGroundColor(false);
776 }
777 
OnColorConfigurationUpdate()778 void ContainerModalPattern::OnColorConfigurationUpdate()
779 {
780     WindowFocus(isFocus_);
781 }
782 
InitLayoutProperty()783 void ContainerModalPattern::InitLayoutProperty()
784 {
785     auto containerModal = GetHost();
786     CHECK_NULL_VOID(containerModal);
787     auto column = GetColumnNode();
788     CHECK_NULL_VOID(column);
789     auto stack = GetStackNode();
790     CHECK_NULL_VOID(stack);
791     auto content = GetContentNode();
792     CHECK_NULL_VOID(content);
793     auto buttonsRow = GetControlButtonRow();
794     CHECK_NULL_VOID(buttonsRow);
795     auto contentProperty = content->GetLayoutProperty();
796     CHECK_NULL_VOID(contentProperty);
797     auto buttonsRowProperty = buttonsRow->GetLayoutProperty<LinearLayoutProperty>();
798     CHECK_NULL_VOID(buttonsRowProperty);
799     containerModal->GetLayoutProperty()->UpdateMeasureType(MeasureType::MATCH_PARENT);
800     column->GetLayoutProperty()->UpdateMeasureType(MeasureType::MATCH_PARENT);
801     stack->GetLayoutProperty()->UpdateMeasureType(MeasureType::MATCH_PARENT);
802     contentProperty->UpdateMeasureType(MeasureType::MATCH_CONTENT);
803     contentProperty->UpdateUserDefinedIdealSize(
804         CalcSize(CalcLength(1.0, DimensionUnit::PERCENT), CalcLength(1.0, DimensionUnit::PERCENT)));
805     buttonsRowProperty->UpdateMeasureType(MeasureType::MATCH_PARENT);
806     auto buttonHeight = (CONTAINER_TITLE_HEIGHT == titleHeight_) ? CONTAINER_TITLE_HEIGHT : titleHeight_;
807     buttonsRowProperty->UpdateUserDefinedIdealSize(
808         CalcSize(CalcLength(1.0, DimensionUnit::PERCENT), CalcLength(buttonHeight)));
809     buttonsRowProperty->UpdateMainAxisAlign(FlexAlign::FLEX_END);
810     buttonsRowProperty->UpdateCrossAxisAlign(FlexAlign::CENTER);
811 
812     InitTitleRowLayoutProperty(GetCustomTitleRow(), false);
813     InitTitleRowLayoutProperty(GetFloatingTitleRow(), true);
814     InitButtonsLayoutProperty();
815 
816     containerModal->MarkModifyDone();
817 }
818 
InitTitleRowLayoutProperty(RefPtr<FrameNode> titleRow,bool isFloating)819 void ContainerModalPattern::InitTitleRowLayoutProperty(RefPtr<FrameNode> titleRow, bool isFloating)
820 {
821     CHECK_NULL_VOID(titleRow);
822     auto titleRowProperty = titleRow->GetLayoutProperty<LinearLayoutProperty>();
823     CHECK_NULL_VOID(titleRowProperty);
824     titleRowProperty->UpdateMeasureType(MeasureType::MATCH_PARENT);
825     auto rowHeight = CONTAINER_TITLE_HEIGHT;
826     if (!isFloating) {
827         rowHeight = (CONTAINER_TITLE_HEIGHT == titleHeight_) ? CONTAINER_TITLE_HEIGHT : titleHeight_;
828     }
829     titleRowProperty->UpdateUserDefinedIdealSize(
830         CalcSize(CalcLength(1.0, DimensionUnit::PERCENT), CalcLength(rowHeight)));
831     titleRowProperty->UpdateMainAxisAlign(FlexAlign::FLEX_START);
832     titleRowProperty->UpdateCrossAxisAlign(FlexAlign::CENTER);
833     auto isRtl = AceApplicationInfo::GetInstance().IsRightToLeft();
834     PaddingProperty padding;
835     auto sidePadding = isRtl ? &padding.left : &padding.right;
836     *sidePadding = GetControlButtonRowWidth();
837     titleRowProperty->UpdatePadding(padding);
838 }
839 
InitAllTitleRowLayoutProperty()840 void ContainerModalPattern::InitAllTitleRowLayoutProperty()
841 {
842     auto containerModal = GetHost();
843     CHECK_NULL_VOID(containerModal);
844     auto customTitleRow = GetCustomTitleRow();
845     CHECK_NULL_VOID(customTitleRow);
846     auto floatingTitleRow = GetFloatingTitleRow();
847     CHECK_NULL_VOID(floatingTitleRow);
848     InitTitleRowLayoutProperty(customTitleRow, false);
849     customTitleRow->MarkModifyDone();
850     customTitleRow->MarkDirtyNode(NG::PROPERTY_UPDATE_MEASURE);
851     InitTitleRowLayoutProperty(floatingTitleRow, true);
852     floatingTitleRow->MarkModifyDone();
853     floatingTitleRow->MarkDirtyNode(NG::PROPERTY_UPDATE_MEASURE);
854 }
855 
GetControlButtonRowWidth()856 CalcLength ContainerModalPattern::GetControlButtonRowWidth()
857 {
858     auto row = GetControlButtonRow();
859     // default
860     int32_t buttonNum = 0;
861     const auto& children = row->GetChildren();
862     for (const auto& child : children) {
863         auto childButton = AceType::DynamicCast<FrameNode>(child);
864         if (childButton && childButton->IsVisible()) {
865             buttonNum++;
866         }
867     }
868     return CalcLength(TITLE_ELEMENT_MARGIN_HORIZONTAL * (buttonNum - 1) + TITLE_BUTTON_SIZE * buttonNum +
869                       TITLE_PADDING_START + TITLE_PADDING_END);
870 }
871 
InitColumnTouchTestFunc()872 void ContainerModalPattern::InitColumnTouchTestFunc()
873 {
874     auto column = GetColumnNode();
875     CHECK_NULL_VOID(column);
876     auto eventHub = column->GetOrCreateGestureEventHub();
877     bool defaultResEnable = enableContainerModalCustomGesture_;
878     auto func = [defaultResEnable](const std::vector<TouchTestInfo>& touchInfo) -> TouchResult {
879         TouchResult touchRes;
880         TouchResult defaultRes;
881         touchRes.strategy = TouchTestStrategy::FORWARD_COMPETITION;
882         defaultRes.strategy = TouchTestStrategy::DEFAULT;
883         defaultRes.id = "";
884         if (defaultResEnable) {
885             return defaultRes;
886         }
887         for (auto info : touchInfo) {
888             if (info.id.compare(CONTAINER_MODAL_STACK_ID) == 0) {
889                 touchRes.id = info.id;
890                 return touchRes;
891             }
892         }
893         return defaultRes;
894     };
895     eventHub->SetOnTouchTestFunc(func);
896 }
897 
InitButtonsLayoutProperty()898 void ContainerModalPattern::InitButtonsLayoutProperty()
899 {
900     auto buttonsRow = GetControlButtonRow();
901     CHECK_NULL_VOID(buttonsRow);
902     auto isRtl = AceApplicationInfo::GetInstance().IsRightToLeft();
903     auto buttons = buttonsRow->GetChildren();
904     for (uint64_t index = 0; index < buttons.size(); index++) {
905         auto space = (index == buttons.size() - 1) ? TITLE_PADDING_END : TITLE_ELEMENT_MARGIN_HORIZONTAL;
906         MarginProperty margin;
907         if (isRtl) {
908             margin.left = CalcLength(space);
909             margin.right = CalcLength();
910         } else {
911             margin.left = CalcLength();
912             margin.right = CalcLength(space);
913         }
914         auto button = AceType::DynamicCast<FrameNode>(buttonsRow->GetChildAtIndex(index));
915         CHECK_NULL_VOID(button);
916         auto layoutProp = button->GetLayoutProperty<ButtonLayoutProperty>();
917         layoutProp->UpdateMargin(margin);
918         button->MarkModifyDone();
919         button->MarkDirtyNode();
920     }
921 }
922 
OnLanguageConfigurationUpdate()923 void ContainerModalPattern::OnLanguageConfigurationUpdate()
924 {
925     InitTitle();
926     InitLayoutProperty();
927 }
928 
GetCustomTitleHeight()929 Dimension ContainerModalPattern::GetCustomTitleHeight()
930 {
931     auto customTitleRow = GetCustomTitleRow();
932     Dimension zeroHeight;
933     CHECK_NULL_RETURN(customTitleRow, zeroHeight);
934     auto property = customTitleRow->GetLayoutProperty();
935     if (property->GetVisibilityValue(VisibleType::VISIBLE) != VisibleType::VISIBLE) {
936         return zeroHeight;
937     }
938     return titleHeight_;
939 }
940 
CanShowCustomTitle()941 bool ContainerModalPattern::CanShowCustomTitle()
942 {
943     auto buttonsRow = GetControlButtonRow();
944     CHECK_NULL_RETURN(buttonsRow, false);
945     auto visibility = buttonsRow->GetLayoutProperty()->GetVisibilityValue(VisibleType::GONE);
946     return visibility == VisibleType::VISIBLE;
947 }
948 
TrimFloatingWindowLayout()949 void ContainerModalPattern::TrimFloatingWindowLayout()
950 {
951     if (windowMode_ != WindowMode::WINDOW_MODE_FLOATING) {
952         return;
953     }
954     auto stack = GetStackNode();
955     CHECK_NULL_VOID(stack);
956     auto host = GetHost();
957     CHECK_NULL_VOID(host);
958     auto hostProp = host->GetLayoutProperty();
959     PaddingProperty padding;
960     auto customtitleRow = GetCustomTitleRow();
961     CHECK_NULL_VOID(customtitleRow);
962     auto customTitleRowProp = customtitleRow->GetLayoutProperty();
963     if (customTitleRowProp->GetVisibilityValue(VisibleType::GONE) == VisibleType::VISIBLE) {
964         padding = { CalcLength(CONTENT_PADDING), CalcLength(CONTENT_PADDING), std::nullopt,
965             CalcLength(CONTENT_PADDING), std::nullopt, std::nullopt };
966     }
967     hostProp->UpdatePadding(padding);
968 }
969 
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,const DirtySwapConfig & config)970 bool ContainerModalPattern::OnDirtyLayoutWrapperSwap(
971     const RefPtr<LayoutWrapper>& dirty,
972     const DirtySwapConfig& config)
973 {
974     CallButtonsRectChange();
975 
976     auto considerFloatingWindow = false;
977     CallSetContainerWindow(considerFloatingWindow);
978 
979     return false;
980 }
981 
CallSetContainerWindow(bool considerFloatingWindow)982 void ContainerModalPattern::CallSetContainerWindow(bool considerFloatingWindow)
983 {
984     auto pipelineContext = PipelineContext::GetCurrentContext();
985     CHECK_NULL_VOID(pipelineContext);
986     auto curWindowRect = pipelineContext->GetCurrentWindowRect();
987     auto isContainerModal = pipelineContext->GetWindowModal() == WindowModal::CONTAINER_MODAL;
988     GetWindowPaintRectWithoutMeasureAndLayout(curWindowRect, isContainerModal);
989 
990     auto borderRadius = 0.0_vp;
991     if (considerFloatingWindow) {
992         auto windowManager = pipelineContext->GetWindowManager();
993         CHECK_NULL_VOID(windowManager);
994         bool isFloatingWindow = windowManager->GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING;
995         borderRadius = (isFloatingWindow && isTitleShow_) ? CONTAINER_OUTER_RADIUS : 0.0_vp;
996     } else {
997         borderRadius = isTitleShow_ ? CONTAINER_OUTER_RADIUS : 0.0_vp;
998     }
999     auto borderRadiusValue = borderRadius.ConvertToPx();
1000 
1001     auto expectRect = RRect::MakeRect(curWindowRect);
1002     expectRect.SetRectWithSimpleRadius(curWindowRect, borderRadiusValue, borderRadiusValue);
1003     if (windowPaintRect_ == expectRect) {
1004         return;
1005     }
1006 
1007     // set container window show state to RS
1008     pipelineContext->SetContainerWindow(isTitleShow_, expectRect);
1009     windowPaintRect_ = expectRect;
1010 }
1011 
UpdateRowHeight(const RefPtr<FrameNode> & row,Dimension height)1012 void ContainerModalPattern::UpdateRowHeight(const RefPtr<FrameNode>& row, Dimension height)
1013 {
1014     CHECK_NULL_VOID(row);
1015     auto layoutProperty = row->GetLayoutProperty<LinearLayoutProperty>();
1016     CHECK_NULL_VOID(layoutProperty);
1017     layoutProperty->UpdateUserDefinedIdealSize(CalcSize(CalcLength(1.0, DimensionUnit::PERCENT), CalcLength(height)));
1018     row->MarkModifyDone();
1019     row->MarkDirtyNode();
1020 }
1021 
EnableContainerModalCustomGesture(RefPtr<PipelineContext> pipeline,bool enable)1022 void ContainerModalPattern::EnableContainerModalCustomGesture(RefPtr<PipelineContext> pipeline, bool enable)
1023 {
1024     CHECK_NULL_VOID(pipeline);
1025     if (!pipeline || pipeline->GetWindowModal() != WindowModal::CONTAINER_MODAL) {
1026         return;
1027     }
1028     auto rootNode = pipeline->GetRootElement();
1029     CHECK_NULL_VOID(rootNode);
1030     auto containerNode = AceType::DynamicCast<FrameNode>(rootNode->GetChildren().front());
1031     CHECK_NULL_VOID(containerNode);
1032     auto containerPattern = containerNode->GetPattern<ContainerModalPattern>();
1033     CHECK_NULL_VOID(containerPattern);
1034     containerPattern->SetEnableContainerModalCustomGesture(enable);
1035     containerPattern->InitColumnTouchTestFunc();
1036 }
1037 } // namespace OHOS::Ace::NG