• 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/button/button_layout_property.h"
21 #include "core/components_ng/pattern/container_modal/container_modal_theme.h"
22 #include "core/components_ng/pattern/container_modal/container_modal_toolbar.h"
23 #include "core/components_ng/pattern/image/image_layout_property.h"
24 #include "core/components_ng/pattern/linear_layout/linear_layout_property.h"
25 
26 namespace OHOS::Ace::NG {
27 
28 namespace {
29 constexpr int32_t LEFT_SPLIT_BUTTON_INDEX = 0;
30 constexpr int32_t MAX_RECOVER_BUTTON_INDEX = 1;
31 constexpr int32_t MINIMIZE_BUTTON_INDEX = 2;
32 constexpr int32_t CLOSE_BUTTON_INDEX = 3;
33 constexpr int32_t TITLE_POPUP_DURATION = 200;
34 constexpr double MOUSE_MOVE_POPUP_DISTANCE = 5.0; // 5.0px
35 constexpr double MOVE_POPUP_DISTANCE_X = 40.0;    // 40.0px
36 constexpr double MOVE_POPUP_DISTANCE_Y = 20.0;    // 20.0px
37 constexpr double TITLE_POPUP_DISTANCE = 37.0;     // 37vp height of title
38 constexpr uint8_t STAGE_BACKGROUND_COLOR_ALPHA = 255;
39 } // namespace
40 
ShowTitle(bool isShow,bool hasDeco,bool needUpdate)41 void ContainerModalPattern::ShowTitle(bool isShow, bool hasDeco, bool needUpdate)
42 {
43     auto containerNode = GetHost();
44     CHECK_NULL_VOID(containerNode);
45     auto customTitleRow = GetCustomTitleRow();
46     CHECK_NULL_VOID(customTitleRow);
47     auto floatingTitleRow = GetFloatingTitleRow();
48     CHECK_NULL_VOID(floatingTitleRow);
49     if (needUpdate) {
50         TAG_LOGI(AceLogTag::ACE_APPBAR, "title is need update, isFocus_: %{public}d", isFocus_);
51         ChangeCustomTitle(isFocus_);
52         ChangeControlButtons(isFocus_);
53         return;
54     }
55 
56     auto pipelineContext = PipelineContext::GetCurrentContextSafelyWithCheck();
57     CHECK_NULL_VOID(pipelineContext);
58     auto theme = pipelineContext->GetTheme<ContainerModalTheme>();
59     auto stackNode = GetStackNode();
60     CHECK_NULL_VOID(stackNode);
61     auto windowManager = pipelineContext->GetWindowManager();
62     CHECK_NULL_VOID(windowManager);
63     windowMode_ = windowManager->GetWindowMode();
64     hasDeco_ = hasDeco;
65     TAG_LOGI(AceLogTag::ACE_APPBAR, "ShowTitle isShow: %{public}d, windowMode: %{public}d, hasDeco: %{public}d",
66         isShow, windowMode_, hasDeco_);
67     if (!hasDeco_) {
68         isShow = false;
69     }
70     isTitleShow_ = isShow;
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, id = Container::CurrentId()]() {
257                     ContainerScope scope(id);
258                     floatingLayoutProperty->UpdateVisibility(VisibleType::GONE);
259                 });
260         }
261     });
262 }
263 
AddPanEvent(const RefPtr<FrameNode> & controlButtonsNode)264 void ContainerModalPattern::AddPanEvent(const RefPtr<FrameNode>& controlButtonsNode)
265 {
266     auto eventHub = controlButtonsNode->GetOrCreateGestureEventHub();
267     CHECK_NULL_VOID(eventHub);
268     PanDirection panDirection;
269     panDirection.type = PanDirection::ALL;
270 
271     if (!panEvent_) {
272         auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
273         CHECK_NULL_VOID(pipeline);
274         auto windowManager = pipeline->GetWindowManager();
275         CHECK_NULL_VOID(windowManager);
276         // touch the title to move the floating window
277         auto panActionStart = [wk = WeakClaim(RawPtr(windowManager))](const GestureEvent& event) {
278             auto windowManager = wk.Upgrade();
279             CHECK_NULL_VOID(windowManager);
280             auto currentWindowMode = windowManager->GetCurrentWindowMaximizeMode();
281             TAG_LOGI(AceLogTag::ACE_APPBAR, "container window pan recognized. currentWindowMode = %{public}d",
282                 currentWindowMode);
283             if ((windowManager->GetCurrentWindowMaximizeMode() != MaximizeMode::MODE_AVOID_SYSTEM_BAR) &&
284                 (event.GetSourceTool() != SourceTool::TOUCHPAD)) {
285                 windowManager->WindowStartMove();
286                 SubwindowManager::GetInstance()->ClearToastInSubwindow();
287             }
288         };
289         panEvent_ = MakeRefPtr<PanEvent>(std::move(panActionStart), nullptr, nullptr, nullptr);
290     }
291     PanDistanceMap distanceMap = { { SourceTool::UNKNOWN, DEFAULT_PAN_DISTANCE.ConvertToPx() },
292         { SourceTool::PEN, DEFAULT_PEN_PAN_DISTANCE.ConvertToPx() } };
293     eventHub->AddPanEvent(panEvent_, panDirection, DEFAULT_PAN_FINGER, distanceMap);
294 }
295 
RemovePanEvent(const RefPtr<FrameNode> & controlButtonsNode)296 void ContainerModalPattern::RemovePanEvent(const RefPtr<FrameNode>& controlButtonsNode)
297 {
298     auto eventHub = controlButtonsNode->GetOrCreateGestureEventHub();
299     CHECK_NULL_VOID(eventHub);
300 
301     if (!panEvent_) {
302         return;
303     }
304     eventHub->RemovePanEvent(panEvent_);
305 }
306 
OnWindowActivated()307 void ContainerModalPattern::OnWindowActivated()
308 {
309     WindowFocus(true);
310 }
311 
OnWindowDeactivated()312 void ContainerModalPattern::OnWindowDeactivated()
313 {
314     WindowFocus(false);
315 }
316 
OnWindowForceUnfocused()317 void ContainerModalPattern::OnWindowForceUnfocused() {}
318 
WindowFocus(bool isFocus)319 void ContainerModalPattern::WindowFocus(bool isFocus)
320 {
321     auto pipelineContext = PipelineContext::GetCurrentContextSafelyWithCheck();
322     CHECK_NULL_VOID(pipelineContext);
323     auto theme = pipelineContext->GetTheme<ContainerModalTheme>();
324     isFocus_ = isFocus;
325     auto containerNode = GetHost();
326     CHECK_NULL_VOID(containerNode);
327 
328     // update container modal background
329     auto renderContext = containerNode->GetRenderContext();
330     CHECK_NULL_VOID(renderContext);
331     renderContext->UpdateBackgroundColor(GetContainerColor(isFocus_));
332     BorderColorProperty borderColor;
333     borderColor.SetColor(isFocus ? CONTAINER_BORDER_COLOR : CONTAINER_BORDER_COLOR_LOST_FOCUS);
334     renderContext->UpdateBorderColor(borderColor);
335 
336     ChangeCustomTitle(isFocus);
337     ChangeFloatingTitle(isFocus);
338     ChangeControlButtons(isFocus);
339     UpdateContainerBgColor();
340 }
341 
ChangeCustomTitle(bool isFocus)342 void ContainerModalPattern::ChangeCustomTitle(bool isFocus)
343 {
344     // update custom title label
345     auto customTitleNode = GetCustomTitleNode();
346     CHECK_NULL_VOID(customTitleNode);
347     isFocus ? customTitleNode->FireOnWindowFocusedCallback() : customTitleNode->FireOnWindowUnfocusedCallback();
348 }
349 
ChangeControlButtons(bool isFocus)350 void ContainerModalPattern::ChangeControlButtons(bool isFocus)
351 {
352     auto containerNode = GetHost();
353     CHECK_NULL_VOID(containerNode);
354     auto controlButtonsNode = GetControlButtonRow();
355     CHECK_NULL_VOID(controlButtonsNode);
356 
357     // update leftSplit button
358     auto leftSplitButton =
359         AceType::DynamicCast<FrameNode>(GetTitleItemByIndex(controlButtonsNode, LEFT_SPLIT_BUTTON_INDEX));
360     CHECK_NULL_VOID(leftSplitButton);
361     ChangeTitleButtonIcon(leftSplitButton,
362         isFocus ? InternalResource::ResourceId::CONTAINER_MODAL_WINDOW_SPLIT_LEFT
363                 : InternalResource::ResourceId::CONTAINER_MODAL_WINDOW_DEFOCUS_SPLIT_LEFT,
364         isFocus, false);
365 
366     // hide leftSplit button when window mode is WINDOW_MODE_SPLIT_PRIMARY type or split button can not show
367     bool hideLeftSplit = hideSplitButton_ || windowMode_ == WindowMode::WINDOW_MODE_SPLIT_PRIMARY;
368     leftSplitButton->GetLayoutProperty()->UpdateVisibility(hideLeftSplit ? VisibleType::GONE : VisibleType::VISIBLE);
369 
370     // update maximize button
371     auto maximizeButton =
372         AceType::DynamicCast<FrameNode>(GetTitleItemByIndex(controlButtonsNode, MAX_RECOVER_BUTTON_INDEX));
373     CHECK_NULL_VOID(maximizeButton);
374     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
375     auto windowManager = pipeline->GetWindowManager();
376     MaximizeMode mode = windowManager->GetCurrentWindowMaximizeMode();
377     InternalResource::ResourceId maxId;
378     if (mode == MaximizeMode::MODE_AVOID_SYSTEM_BAR || windowMode_ == WindowMode::WINDOW_MODE_FULLSCREEN) {
379         maxId = InternalResource::ResourceId::CONTAINER_MODAL_WINDOW_RECOVER;
380     } else {
381         maxId = InternalResource::ResourceId::CONTAINER_MODAL_WINDOW_MAXIMIZE;
382     }
383 
384     ChangeTitleButtonIcon(maximizeButton, maxId, isFocus, false);
385     // update minimize button
386     auto minimizeButton =
387         AceType::DynamicCast<FrameNode>(GetTitleItemByIndex(controlButtonsNode, MINIMIZE_BUTTON_INDEX));
388     CHECK_NULL_VOID(minimizeButton);
389     ChangeTitleButtonIcon(minimizeButton,
390         InternalResource::ResourceId::CONTAINER_MODAL_WINDOW_MINIMIZE, isFocus, false);
391 
392     // update close button
393     auto closeButton = AceType::DynamicCast<FrameNode>(GetTitleItemByIndex(controlButtonsNode, CLOSE_BUTTON_INDEX));
394     CHECK_NULL_VOID(closeButton);
395     ChangeTitleButtonIcon(closeButton,
396         InternalResource::ResourceId::CONTAINER_MODAL_WINDOW_CLOSE, isFocus, true);
397 }
398 
ChangeFloatingTitle(bool isFocus)399 void ContainerModalPattern::ChangeFloatingTitle(bool isFocus)
400 {
401     // update floating custom title label
402     auto customFloatingTitleNode = GetFloatingTitleNode();
403     CHECK_NULL_VOID(customFloatingTitleNode);
404     isFocus ? customFloatingTitleNode->FireOnWindowFocusedCallback()
405             : customFloatingTitleNode->FireOnWindowUnfocusedCallback();
406 }
407 
ChangeTitleButtonIcon(const RefPtr<FrameNode> & buttonNode,InternalResource::ResourceId icon,bool isFocus,bool isCloseBtn)408 void ContainerModalPattern::ChangeTitleButtonIcon(
409     const RefPtr<FrameNode>& buttonNode, InternalResource::ResourceId icon, bool isFocus, bool isCloseBtn)
410 {
411     auto theme = PipelineContext::GetCurrentContextSafelyWithCheck()->GetTheme<ContainerModalTheme>();
412     auto renderContext = buttonNode->GetRenderContext();
413     CHECK_NULL_VOID(renderContext);
414     auto colorType = isFocus ? ControlBtnColorType::NORMAL : ControlBtnColorType::UNFOCUS;
415     auto color = theme->GetControlBtnColor(isCloseBtn, colorType);
416     renderContext->UpdateBackgroundColor(color);
417     auto buttonIcon = AceType::DynamicCast<FrameNode>(buttonNode->GetChildren().front());
418     CHECK_NULL_VOID(buttonIcon);
419     ImageSourceInfo imageSourceInfo;
420     imageSourceInfo.SetResourceId(icon);
421     colorType = isFocus ? ControlBtnColorType::NORMAL_FILL : ControlBtnColorType::UNFOCUS_FILL;
422     color = theme->GetControlBtnColor(isCloseBtn,  colorType);
423     imageSourceInfo.SetFillColor(color);
424     auto imageLayoutProperty = buttonIcon->GetLayoutProperty<ImageLayoutProperty>();
425     imageLayoutProperty->UpdateImageSourceInfo(imageSourceInfo);
426     buttonIcon->MarkModifyDone();
427     buttonNode->MarkModifyDone();
428 }
429 
CanShowFloatingTitle()430 bool ContainerModalPattern::CanShowFloatingTitle()
431 {
432     auto floatingTitleRow = GetFloatingTitleRow();
433     CHECK_NULL_RETURN(floatingTitleRow, false);
434     auto floatingLayoutProperty = floatingTitleRow->GetLayoutProperty();
435     CHECK_NULL_RETURN(floatingLayoutProperty, false);
436 
437     if (windowMode_ != WindowMode::WINDOW_MODE_FULLSCREEN && windowMode_ != WindowMode::WINDOW_MODE_SPLIT_PRIMARY &&
438         windowMode_ != WindowMode::WINDOW_MODE_SPLIT_SECONDARY) {
439         TAG_LOGI(AceLogTag::ACE_APPBAR, "Window is not full screen or split screen, can not show floating title.");
440         return false;
441     }
442 
443     if (floatingLayoutProperty->GetVisibilityValue(VisibleType::GONE) == VisibleType::VISIBLE) {
444         TAG_LOGI(AceLogTag::ACE_APPBAR, "Floating tittle is visible now, no need to show again.");
445         return false;
446     }
447     return true;
448 }
449 
SetAppTitle(const std::string & title)450 void ContainerModalPattern::SetAppTitle(const std::string& title)
451 {
452     TAG_LOGI(AceLogTag::ACE_APPBAR, "SetAppTitle successfully");
453     auto customTitleNode = GetCustomTitleNode();
454     CHECK_NULL_VOID(customTitleNode);
455     customTitleNode->FireAppTitleCallback(title);
456 
457     // call setTitle() callback for backButton bar
458     auto controllButtonRow = GetCustomButtonNode();
459     CHECK_NULL_VOID(controllButtonRow);
460     controllButtonRow->FireAppTitleCallback(title);
461 
462     auto customFloatingTitleNode = GetFloatingTitleNode();
463     CHECK_NULL_VOID(customFloatingTitleNode);
464     customFloatingTitleNode->FireAppTitleCallback(title);
465 }
466 
SetAppIcon(const RefPtr<PixelMap> & icon)467 void ContainerModalPattern::SetAppIcon(const RefPtr<PixelMap>& icon)
468 {
469     CHECK_NULL_VOID(icon);
470     TAG_LOGI(AceLogTag::ACE_APPBAR, "SetAppIcon successfully");
471     auto customTitleNode = GetCustomTitleNode();
472     CHECK_NULL_VOID(customTitleNode);
473     customTitleNode->FireAppIconCallback(icon);
474 
475     auto customFloatingTitleNode = GetFloatingTitleNode();
476     CHECK_NULL_VOID(customFloatingTitleNode);
477     customFloatingTitleNode->FireAppIconCallback(icon);
478 }
479 
SetTitleButtonHide(const RefPtr<FrameNode> & controlButtonsNode,bool hideSplit,bool hideMaximize,bool hideMinimize,bool hideClose)480 void ContainerModalPattern::SetTitleButtonHide(
481     const RefPtr<FrameNode>& controlButtonsNode, bool hideSplit, bool hideMaximize, bool hideMinimize, bool hideClose)
482 {
483     auto leftSplitButton =
484         AceType::DynamicCast<FrameNode>(GetTitleItemByIndex(controlButtonsNode, LEFT_SPLIT_BUTTON_INDEX));
485     CHECK_NULL_VOID(leftSplitButton);
486     leftSplitButton->GetLayoutProperty()->UpdateVisibility(hideSplit ? VisibleType::GONE : VisibleType::VISIBLE);
487     leftSplitButton->MarkDirtyNode();
488 
489     auto maximizeButton =
490         AceType::DynamicCast<FrameNode>(GetTitleItemByIndex(controlButtonsNode, MAX_RECOVER_BUTTON_INDEX));
491     CHECK_NULL_VOID(maximizeButton);
492     maximizeButton->GetLayoutProperty()->UpdateVisibility(hideMaximize ? VisibleType::GONE : VisibleType::VISIBLE);
493     maximizeButton->MarkDirtyNode();
494 
495     auto minimizeButton = AceType::DynamicCast<FrameNode>(
496         GetTitleItemByIndex(controlButtonsNode, MINIMIZE_BUTTON_INDEX));
497     CHECK_NULL_VOID(minimizeButton);
498     minimizeButton->GetLayoutProperty()->UpdateVisibility(hideMinimize ? VisibleType::GONE : VisibleType::VISIBLE);
499     minimizeButton->MarkDirtyNode();
500 
501     auto closeButton = AceType::DynamicCast<FrameNode>(GetTitleItemByIndex(controlButtonsNode, CLOSE_BUTTON_INDEX));
502     CHECK_NULL_VOID(closeButton);
503     closeButton->GetLayoutProperty()->UpdateVisibility(hideClose ? VisibleType::GONE : VisibleType::VISIBLE);
504     closeButton->MarkDirtyNode();
505 }
506 
SetContainerButtonHide(bool hideSplit,bool hideMaximize,bool hideMinimize,bool hideClose)507 void ContainerModalPattern::SetContainerButtonHide(bool hideSplit, bool hideMaximize, bool hideMinimize, bool hideClose)
508 {
509     auto controlButtonsRow = GetControlButtonRow();
510     CHECK_NULL_VOID(controlButtonsRow);
511     SetTitleButtonHide(controlButtonsRow, hideSplit, hideMaximize, hideMinimize, hideClose);
512     hideSplitButton_ = hideSplit;
513     TAG_LOGI(AceLogTag::ACE_APPBAR,
514         "Set containerModal button status successfully, "
515         "hideSplit: %{public}d, hideMaximize: %{public}d, "
516         "hideMinimize: %{public}d, hideClose: %{public}d",
517         hideSplit, hideMaximize, hideMinimize, hideClose);
518 }
519 
SetCloseButtonStatus(bool isEnabled)520 void ContainerModalPattern::SetCloseButtonStatus(bool isEnabled)
521 {
522     auto controlButtonsRow = GetControlButtonRow();
523     CHECK_NULL_VOID(controlButtonsRow);
524 
525     // set closeButton enable or disable
526     auto closeButton = AceType::DynamicCast<FrameNode>(GetTitleItemByIndex(controlButtonsRow, CLOSE_BUTTON_INDEX));
527     CHECK_NULL_VOID(closeButton);
528     auto buttonEvent = closeButton->GetOrCreateEventHub<ButtonEventHub>();
529     CHECK_NULL_VOID(buttonEvent);
530     buttonEvent->SetEnabled(isEnabled);
531     TAG_LOGI(AceLogTag::ACE_APPBAR, "Set close button status %{public}s", isEnabled ? "enable" : "disable");
532 }
533 
SetWindowContainerColor(const Color & activeColor,const Color & inactiveColor)534 void ContainerModalPattern::SetWindowContainerColor(const Color& activeColor, const Color& inactiveColor)
535 {
536     auto theme = PipelineContext::GetCurrentContext()->GetTheme<ContainerModalTheme>();
537     auto containerNode = GetHost();
538     CHECK_NULL_VOID(containerNode);
539     // update container modal background
540     auto renderContext = containerNode->GetRenderContext();
541     CHECK_NULL_VOID(renderContext);
542     activeColor_ = activeColor;
543     inactiveColor_ = inactiveColor;
544     isCustomColor_ = true;
545     renderContext->UpdateBackgroundColor(GetContainerColor(isFocus_));
546 
547     CHECK_NULL_VOID(titleMgr_);
548     if (IsContainerModalTransparent()) {
549         titleMgr_->UpdateTargetNodesBarMargin();
550     } else {
551         titleMgr_->ResetExpandStackNode();
552     }
553 }
554 
GetContainerColor(bool isFocus)555 Color ContainerModalPattern::GetContainerColor(bool isFocus)
556 {
557     auto theme = PipelineContext::GetCurrentContext()->GetTheme<ContainerModalTheme>();
558     return isCustomColor_ ? (isFocus ? activeColor_ : inactiveColor_) : theme->GetBackGroundColor(isFocus);
559 }
560 
UpdateGestureRowVisible()561 void ContainerModalPattern::UpdateGestureRowVisible()
562 {
563     auto gestureRow = GetGestureRow();
564     CHECK_NULL_VOID(gestureRow);
565     auto customTitleRow = GetCustomTitleRow();
566     CHECK_NULL_VOID(customTitleRow);
567     auto buttonsRow = GetControlButtonRow();
568     CHECK_NULL_VOID(buttonsRow);
569     auto gestureRowProp = gestureRow->GetLayoutProperty();
570     auto customTitleRowProp = customTitleRow->GetLayoutProperty();
571     auto buttonsRowProp = buttonsRow->GetLayoutProperty();
572     if (customTitleRowProp->GetVisibilityValue(VisibleType::VISIBLE) == VisibleType::GONE &&
573         buttonsRowProp->GetVisibilityValue(VisibleType::VISIBLE) == VisibleType::VISIBLE) {
574         gestureRowProp->UpdateVisibility(VisibleType::VISIBLE);
575     } else {
576         gestureRowProp->UpdateVisibility(VisibleType::GONE);
577     }
578 }
579 
SetContainerModalTitleVisible(bool customTitleSettedShow,bool floatingTitleSettedShow)580 void ContainerModalPattern::SetContainerModalTitleVisible(bool customTitleSettedShow, bool floatingTitleSettedShow)
581 {
582     TAG_LOGI(AceLogTag::ACE_APPBAR,
583         "ContainerModal customTitleSettedShow=%{public}d, floatingTitleSettedShow=%{public}d",
584         customTitleSettedShow, floatingTitleSettedShow);
585     customTitleSettedShow_ = customTitleSettedShow;
586     auto customTitleRow = GetCustomTitleRow();
587     CHECK_NULL_VOID(customTitleRow);
588     auto customTitleRowProp = customTitleRow->GetLayoutProperty();
589     if (!customTitleSettedShow) {
590         customTitleRowProp->UpdateVisibility(VisibleType::GONE);
591     } else if (CanShowCustomTitle()) {
592         customTitleRowProp->UpdateVisibility(VisibleType::VISIBLE);
593     }
594     floatingTitleSettedShow_ = floatingTitleSettedShow;
595     auto floatingTitleRow = GetFloatingTitleRow();
596     CHECK_NULL_VOID(floatingTitleRow);
597     auto floatingTitleRowProp = floatingTitleRow->GetLayoutProperty();
598     if (!floatingTitleSettedShow) {
599         floatingTitleRowProp->UpdateVisibility(VisibleType::GONE);
600     }
601 
602     auto buttonsRow = GetControlButtonRow();
603     CHECK_NULL_VOID(buttonsRow);
604     buttonsRow->SetHitTestMode(HitTestMode::HTMTRANSPARENT_SELF);
605     UpdateGestureRowVisible();
606     UpdateContainerBgColor();
607     InitColumnTouchTestFunc();
608 
609     CHECK_NULL_VOID(titleMgr_);
610     if (customTitleSettedShow) {
611         titleMgr_->UpdateTargetNodesBarMargin();
612     } else {
613         titleMgr_->ResetExpandStackNode();
614     }
615 
616     titleMgr_->UpdateToolbarShow(isTitleShow_, customTitleSettedShow_);
617     CHECK_NULL_VOID(floatTitleMgr_);
618     floatTitleMgr_->UpdateToolbarShow(isTitleShow_, customTitleSettedShow_);
619 }
620 
GetContainerModalTitleVisible(bool isImmersive)621 bool ContainerModalPattern::GetContainerModalTitleVisible(bool isImmersive)
622 {
623     if (isImmersive) {
624         auto floatingTitleRow = GetFloatingTitleRow();
625         CHECK_NULL_RETURN(floatingTitleRow, false);
626         auto floatingLayoutProperty = floatingTitleRow->GetLayoutProperty();
627         CHECK_NULL_RETURN(floatingLayoutProperty, false);
628         return floatingLayoutProperty->GetVisibilityValue(VisibleType::GONE) == VisibleType::VISIBLE;
629     } else {
630         return isTitleShow_ && customTitleSettedShow_;
631     }
632 }
633 
SetContainerModalTitleHeight(int32_t height)634 void ContainerModalPattern::SetContainerModalTitleHeight(int32_t height)
635 {
636     TAG_LOGI(AceLogTag::ACE_APPBAR, "ContainerModal SetContainerModalTitleHeight height=%{public}d", height);
637     if (height < 0) {
638         height = 0;
639     }
640     titleHeight_ = Dimension(Dimension(height, DimensionUnit::PX).ConvertToVp(), DimensionUnit::VP);
641     SetControlButtonsRowHeight(titleHeight_);
642     SetContainerModalTitleWithoutButtonsHeight(titleHeight_);
643 }
644 
SetContainerModalTitleWithoutButtonsHeight(Dimension height)645 void ContainerModalPattern::SetContainerModalTitleWithoutButtonsHeight(Dimension height)
646 {
647     auto customTitleRow = GetCustomTitleRow();
648     UpdateRowHeight(customTitleRow, height);
649     auto gestureRow = GetGestureRow();
650     UpdateRowHeight(gestureRow, height);
651     if (floatTitleMgr_ != nullptr) {
652         auto floatingTitleRow = GetFloatingTitleRow();
653         CHECK_NULL_VOID(floatingTitleRow);
654         UpdateRowHeight(floatingTitleRow, height);
655     }
656     if (titleMgr_ != nullptr) {
657         titleMgr_->UpdateTargetNodesBarMargin();
658     }
659 }
660 
SetControlButtonsRowHeight(Dimension height)661 void ContainerModalPattern::SetControlButtonsRowHeight(Dimension height)
662 {
663     auto controlButtonsRow = GetControlButtonRow();
664     UpdateRowHeight(controlButtonsRow, height);
665     CallButtonsRectChange();
666 }
667 
GetContainerModalTitleHeight()668 int32_t ContainerModalPattern::GetContainerModalTitleHeight()
669 {
670     return static_cast<int32_t>(ceil(titleHeight_.ConvertToPx()));
671 }
672 
GetContainerModalButtonsRect(RectF & containerModal,RectF & buttons)673 bool ContainerModalPattern::GetContainerModalButtonsRect(RectF& containerModal, RectF& buttons)
674 {
675     auto column = GetColumnNode();
676     CHECK_NULL_RETURN(column, false);
677     auto columnRect = column->GetGeometryNode()->GetFrameRect();
678     containerModal = columnRect;
679     if (columnRect.Width() == 0) {
680         TAG_LOGW(AceLogTag::ACE_APPBAR, "Get rect of buttons failed, the rect is measuring.");
681         return false;
682     }
683 
684     auto controlButtonsRow = GetControlButtonRow();
685     CHECK_NULL_RETURN(controlButtonsRow, false);
686     auto controlButtonsRowLayoutProperty = controlButtonsRow->GetLayoutProperty();
687     CHECK_NULL_RETURN(controlButtonsRowLayoutProperty, false);
688     if (controlButtonsRowLayoutProperty->GetVisibilityValue(VisibleType::VISIBLE) != VisibleType::VISIBLE) {
689         TAG_LOGW(AceLogTag::ACE_APPBAR, "Get rect of buttons failed, buttonRow are hidden");
690         return false;
691     }
692     auto children = controlButtonsRow->GetChildren();
693     RectF firstButtonRect;
694     RectF lastButtonRect;
695     for (auto& child : children) {
696         auto node = AceType::DynamicCast<FrameNode>(child);
697         if (node->GetLayoutProperty()->GetVisibilityValue(VisibleType::VISIBLE) != VisibleType::VISIBLE) {
698             continue;
699         }
700         auto rect = node->GetGeometryNode()->GetFrameRect();
701         if (firstButtonRect.Width() == 0) {
702             firstButtonRect = rect;
703         }
704         lastButtonRect = rect;
705     }
706     buttons = firstButtonRect.CombineRectT(lastButtonRect);
707     if (buttons.Width() == 0) {
708         TAG_LOGW(AceLogTag::ACE_APPBAR, "Get rect of buttons failed, buttons are hidden");
709         return false;
710     }
711 
712     auto widthByPx = (TITLE_PADDING_START + TITLE_PADDING_END).ConvertToPx() + buttons.Width();
713     auto isRtl = AceApplicationInfo::GetInstance().IsRightToLeft();
714     if (isRtl) {
715         buttons.SetLeft(0);
716     } else {
717         buttons.SetLeft(containerModal.Width() - widthByPx);
718     }
719     buttons.SetTop(0);
720     buttons.SetWidth(widthByPx);
721     buttons.SetHeight(titleHeight_.ConvertToPx());
722     return true;
723 }
724 
SubscribeContainerModalButtonsRectChange(std::function<void (RectF & containerModal,RectF & buttons)> && callback)725 void ContainerModalPattern::SubscribeContainerModalButtonsRectChange(
726     std::function<void(RectF& containerModal, RectF& buttons)>&& callback)
727 {
728     controlButtonsRectChangeCallback_ = std::move(callback);
729 }
730 
GetWindowPaintRectWithoutMeasureAndLayout(RectInt & rect)731 void ContainerModalPattern::GetWindowPaintRectWithoutMeasureAndLayout(RectInt& rect)
732 {
733     auto host = GetHost();
734     CHECK_NULL_VOID(host);
735     auto layoutProperty = host->GetLayoutProperty();
736     CHECK_NULL_VOID(layoutProperty);
737     auto titleHeight = round(GetCustomTitleHeight().ConvertToPx());
738     auto padding = layoutProperty->CreatePaddingAndBorder();
739     rect.SetRect(padding.Offset().GetX(), padding.Offset().GetY() + titleHeight, rect.Width() - padding.Width(),
740         rect.Height() - padding.Height() - titleHeight);
741 }
742 
GetWindowPaintRectWithoutMeasureAndLayout(Rect & rect,bool isContainerModal)743 void ContainerModalPattern::GetWindowPaintRectWithoutMeasureAndLayout(Rect& rect, bool isContainerModal)
744 {
745     auto host = GetHost();
746     CHECK_NULL_VOID(host);
747     auto layoutProperty = host->GetLayoutProperty();
748     CHECK_NULL_VOID(layoutProperty);
749     auto titleHeight = GetCustomTitleHeight().ConvertToPx();
750     auto padding = layoutProperty->CreatePaddingAndBorder();
751     rect.SetRect(
752         padding.Offset().GetX(),
753         isContainerModal ? padding.Offset().GetY() + titleHeight : padding.Offset().GetY(),
754         rect.Width() - padding.Width(),
755         rect.Height() - padding.Height() - titleHeight);
756 }
757 
CallButtonsRectChange()758 void ContainerModalPattern::CallButtonsRectChange()
759 {
760     RectF containerModal;
761     RectF buttons;
762     GetContainerModalButtonsRect(containerModal, buttons);
763     NotifyButtonsRectChange(containerModal, buttons);
764     CHECK_NULL_VOID(controlButtonsRectChangeCallback_);
765     if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_FIFTEEN)) {
766         if (isInitButtonsRect_ && buttonsRect_ == buttons) {
767             return;
768         }
769         isInitButtonsRect_ = true;
770     }
771     buttonsRect_ = buttons;
772     auto taskExecutor = Container::CurrentTaskExecutor();
773     CHECK_NULL_VOID(taskExecutor);
774     taskExecutor->PostTask(
775         [containerModal, buttons, cb = controlButtonsRectChangeCallback_]() mutable {
776             if (cb) {
777                 cb(containerModal, buttons);
778             }
779         },
780         TaskExecutor::TaskType::JS, "ArkUIContainerModalButtonsRectChange");
781 }
782 
InitTitle()783 void ContainerModalPattern::InitTitle()
784 {
785     auto pipeline = PipelineContext::GetCurrentContext();
786     CHECK_NULL_VOID(pipeline);
787     auto themeManager = pipeline->GetThemeManager();
788     CHECK_NULL_VOID(themeManager);
789     auto themeConstants = themeManager->GetThemeConstants();
790     CHECK_NULL_VOID(themeConstants);
791     auto id = pipeline->GetWindowManager()->GetAppIconId();
792     auto pixelMap = themeConstants->GetPixelMap(id);
793     if (pixelMap) {
794         RefPtr<PixelMap> icon = PixelMap::CreatePixelMap(&pixelMap);
795         SetAppIcon(icon);
796     } else {
797         TAG_LOGW(AceLogTag::ACE_APPBAR, "Cannot get pixelmap, try media path."); // use themeConstants GetMediaPath
798     }
799     SetAppTitle(themeConstants->GetString(pipeline->GetWindowManager()->GetAppLabelId()));
800 }
801 
Init()802 void ContainerModalPattern::Init()
803 {
804     InitContainerColor();
805     InitContainerEvent();
806     InitTitle();
807     InitLayoutProperty();
808 }
809 
InitContainerColor()810 void ContainerModalPattern::InitContainerColor()
811 {
812     auto pipelineContext = PipelineContext::GetCurrentContext();
813     CHECK_NULL_VOID(pipelineContext);
814     auto theme = pipelineContext->GetTheme<ContainerModalTheme>();
815     activeColor_ = theme->GetBackGroundColor(true);
816     inactiveColor_ = theme->GetBackGroundColor(false);
817 }
818 
OnColorConfigurationUpdate()819 void ContainerModalPattern::OnColorConfigurationUpdate()
820 {
821     WindowFocus(isFocus_);
822 }
823 
InitLayoutProperty()824 void ContainerModalPattern::InitLayoutProperty()
825 {
826     auto containerModal = GetHost();
827     CHECK_NULL_VOID(containerModal);
828     auto column = GetColumnNode();
829     CHECK_NULL_VOID(column);
830     auto stack = GetStackNode();
831     CHECK_NULL_VOID(stack);
832     auto content = GetContentNode();
833     CHECK_NULL_VOID(content);
834     auto buttonsRow = GetControlButtonRow();
835     CHECK_NULL_VOID(buttonsRow);
836     auto contentProperty = content->GetLayoutProperty();
837     CHECK_NULL_VOID(contentProperty);
838     auto buttonsRowProperty = buttonsRow->GetLayoutProperty<LinearLayoutProperty>();
839     CHECK_NULL_VOID(buttonsRowProperty);
840     containerModal->GetLayoutProperty()->UpdateMeasureType(MeasureType::MATCH_PARENT);
841     column->GetLayoutProperty()->UpdateMeasureType(MeasureType::MATCH_PARENT);
842     stack->GetLayoutProperty()->UpdateMeasureType(MeasureType::MATCH_PARENT);
843     contentProperty->UpdateMeasureType(MeasureType::MATCH_CONTENT);
844     contentProperty->UpdateUserDefinedIdealSize(
845         CalcSize(CalcLength(1.0, DimensionUnit::PERCENT), CalcLength(1.0, DimensionUnit::PERCENT)));
846     buttonsRowProperty->UpdateMeasureType(MeasureType::MATCH_PARENT);
847     auto buttonHeight = (CONTAINER_TITLE_HEIGHT == titleHeight_) ? CONTAINER_TITLE_HEIGHT : titleHeight_;
848     buttonsRowProperty->UpdateUserDefinedIdealSize(
849         CalcSize(CalcLength(1.0, DimensionUnit::PERCENT), CalcLength(buttonHeight)));
850     buttonsRowProperty->UpdateMainAxisAlign(FlexAlign::FLEX_END);
851     buttonsRowProperty->UpdateCrossAxisAlign(FlexAlign::CENTER);
852 
853     InitTitleRowLayoutProperty(GetCustomTitleRow(), false);
854     InitTitleRowLayoutProperty(GetFloatingTitleRow(), true);
855     InitButtonsLayoutProperty();
856 
857     containerModal->MarkModifyDone();
858 }
859 
InitTitleRowLayoutProperty(RefPtr<FrameNode> titleRow,bool isFloating)860 void ContainerModalPattern::InitTitleRowLayoutProperty(RefPtr<FrameNode> titleRow, bool isFloating)
861 {
862     CHECK_NULL_VOID(titleRow);
863     auto titleRowProperty = titleRow->GetLayoutProperty<LinearLayoutProperty>();
864     CHECK_NULL_VOID(titleRowProperty);
865     titleRowProperty->UpdateMeasureType(MeasureType::MATCH_PARENT);
866     auto rowHeight = CONTAINER_TITLE_HEIGHT;
867     if (!isFloating || (isFloating && floatTitleMgr_ != nullptr)) {
868         rowHeight = (CONTAINER_TITLE_HEIGHT == titleHeight_) ? CONTAINER_TITLE_HEIGHT : titleHeight_;
869     }
870     titleRowProperty->UpdateUserDefinedIdealSize(
871         CalcSize(CalcLength(1.0, DimensionUnit::PERCENT), CalcLength(rowHeight)));
872     titleRowProperty->UpdateMainAxisAlign(FlexAlign::FLEX_START);
873     titleRowProperty->UpdateCrossAxisAlign(FlexAlign::CENTER);
874     auto isRtl = AceApplicationInfo::GetInstance().IsRightToLeft();
875     PaddingProperty padding;
876     auto sidePadding = isRtl ? &padding.left : &padding.right;
877     *sidePadding = GetControlButtonRowWidth();
878     titleRowProperty->UpdatePadding(padding);
879 }
880 
InitAllTitleRowLayoutProperty()881 void ContainerModalPattern::InitAllTitleRowLayoutProperty()
882 {
883     auto containerModal = GetHost();
884     CHECK_NULL_VOID(containerModal);
885     auto customTitleRow = GetCustomTitleRow();
886     CHECK_NULL_VOID(customTitleRow);
887     auto floatingTitleRow = GetFloatingTitleRow();
888     CHECK_NULL_VOID(floatingTitleRow);
889     InitTitleRowLayoutProperty(customTitleRow, false);
890     customTitleRow->MarkModifyDone();
891     customTitleRow->MarkDirtyNode(NG::PROPERTY_UPDATE_MEASURE);
892     InitTitleRowLayoutProperty(floatingTitleRow, true);
893     floatingTitleRow->MarkModifyDone();
894     floatingTitleRow->MarkDirtyNode(NG::PROPERTY_UPDATE_MEASURE);
895 }
896 
GetControlButtonRowWidth()897 CalcLength ContainerModalPattern::GetControlButtonRowWidth()
898 {
899     auto row = GetControlButtonRow();
900     // default
901     int32_t buttonNum = 0;
902     const auto& children = row->GetChildren();
903     for (const auto& child : children) {
904         auto childButton = AceType::DynamicCast<FrameNode>(child);
905         if (childButton && childButton->IsVisible()) {
906             buttonNum++;
907         }
908     }
909     return CalcLength(TITLE_ELEMENT_MARGIN_HORIZONTAL * (buttonNum - 1) + TITLE_BUTTON_SIZE * buttonNum +
910                       TITLE_PADDING_START + TITLE_PADDING_END);
911 }
912 
InitColumnTouchTestFunc()913 void ContainerModalPattern::InitColumnTouchTestFunc()
914 {
915     auto column = GetColumnNode();
916     CHECK_NULL_VOID(column);
917     auto eventHub = column->GetOrCreateGestureEventHub();
918     if (titleMgr_ && titleMgr_->GetIsUpdateTargetNode() && customTitleSettedShow_) {
919         eventHub->SetOnTouchTestFunc(nullptr);
920         return;
921     }
922     bool defaultResEnable = enableContainerModalCustomGesture_;
923     auto func = [defaultResEnable](const std::vector<TouchTestInfo>& touchInfo) -> TouchResult {
924         TouchResult touchRes;
925         TouchResult defaultRes;
926         touchRes.strategy = TouchTestStrategy::FORWARD_COMPETITION;
927         defaultRes.strategy = TouchTestStrategy::DEFAULT;
928         defaultRes.id = "";
929         if (defaultResEnable) {
930             return defaultRes;
931         }
932         for (auto info : touchInfo) {
933             if (info.id.compare(CONTAINER_MODAL_STACK_ID) == 0) {
934                 touchRes.id = info.id;
935                 return touchRes;
936             }
937         }
938         return defaultRes;
939     };
940     eventHub->SetOnTouchTestFunc(func);
941 }
942 
InitButtonsLayoutProperty()943 void ContainerModalPattern::InitButtonsLayoutProperty()
944 {
945     auto buttonsRow = GetControlButtonRow();
946     CHECK_NULL_VOID(buttonsRow);
947     auto isRtl = AceApplicationInfo::GetInstance().IsRightToLeft();
948     auto buttons = buttonsRow->GetChildren();
949     for (uint64_t index = 0; index < buttons.size(); index++) {
950         auto space = (index == buttons.size() - 1) ? TITLE_PADDING_END : TITLE_ELEMENT_MARGIN_HORIZONTAL;
951         MarginProperty margin;
952         if (isRtl) {
953             margin.left = CalcLength(space);
954             margin.right = CalcLength();
955         } else {
956             margin.left = CalcLength();
957             margin.right = CalcLength(space);
958         }
959         auto button = AceType::DynamicCast<FrameNode>(buttonsRow->GetChildAtIndex(index));
960         CHECK_NULL_VOID(button);
961         auto layoutProp = button->GetLayoutProperty<ButtonLayoutProperty>();
962         layoutProp->UpdateMargin(margin);
963         button->MarkModifyDone();
964         button->MarkDirtyNode();
965     }
966 }
967 
OnLanguageConfigurationUpdate()968 void ContainerModalPattern::OnLanguageConfigurationUpdate()
969 {
970     InitTitle();
971     InitLayoutProperty();
972 }
973 
GetCustomTitleHeight()974 Dimension ContainerModalPattern::GetCustomTitleHeight()
975 {
976     auto customTitleRow = GetCustomTitleRow();
977     Dimension zeroHeight;
978     CHECK_NULL_RETURN(customTitleRow, zeroHeight);
979     auto property = customTitleRow->GetLayoutProperty();
980     if (property->GetVisibilityValue(VisibleType::VISIBLE) != VisibleType::VISIBLE) {
981         return zeroHeight;
982     }
983     return titleHeight_;
984 }
985 
CanShowCustomTitle()986 bool ContainerModalPattern::CanShowCustomTitle()
987 {
988     auto buttonsRow = GetControlButtonRow();
989     CHECK_NULL_RETURN(buttonsRow, false);
990     auto visibility = buttonsRow->GetLayoutProperty()->GetVisibilityValue(VisibleType::GONE);
991     return visibility == VisibleType::VISIBLE;
992 }
993 
IsContainerModalTransparent() const994 bool ContainerModalPattern::IsContainerModalTransparent() const
995 {
996     if (!isCustomColor_) {
997         return false;
998     }
999     return activeColor_.GetAlpha() == 0 && inactiveColor_.GetAlpha() == 0;
1000 }
1001 
TrimFloatingWindowLayout()1002 void ContainerModalPattern::TrimFloatingWindowLayout()
1003 {
1004     if (windowMode_ != WindowMode::WINDOW_MODE_FLOATING) {
1005         return;
1006     }
1007     auto stack = GetStackNode();
1008     CHECK_NULL_VOID(stack);
1009     auto host = GetHost();
1010     CHECK_NULL_VOID(host);
1011     auto hostProp = host->GetLayoutProperty();
1012     PaddingProperty padding;
1013     auto customtitleRow = GetCustomTitleRow();
1014     CHECK_NULL_VOID(customtitleRow);
1015     auto customTitleRowProp = customtitleRow->GetLayoutProperty();
1016     if (customTitleRowProp->GetVisibilityValue(VisibleType::GONE) == VisibleType::VISIBLE) {
1017         padding = { CalcLength(CONTENT_PADDING), CalcLength(CONTENT_PADDING), std::nullopt,
1018             CalcLength(CONTENT_PADDING), std::nullopt, std::nullopt };
1019     }
1020     hostProp->UpdatePadding(padding);
1021 }
1022 
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,const DirtySwapConfig & config)1023 bool ContainerModalPattern::OnDirtyLayoutWrapperSwap(
1024     const RefPtr<LayoutWrapper>& dirty,
1025     const DirtySwapConfig& config)
1026 {
1027     CallButtonsRectChange();
1028 
1029     auto considerFloatingWindow = false;
1030     CallSetContainerWindow(considerFloatingWindow);
1031 
1032     return false;
1033 }
1034 
CallSetContainerWindow(bool considerFloatingWindow)1035 void ContainerModalPattern::CallSetContainerWindow(bool considerFloatingWindow)
1036 {
1037     auto pipelineContext = PipelineContext::GetCurrentContext();
1038     CHECK_NULL_VOID(pipelineContext);
1039     auto curWindowRect = pipelineContext->GetCurrentWindowRect();
1040     auto isContainerModal = pipelineContext->GetWindowModal() == WindowModal::CONTAINER_MODAL;
1041     GetWindowPaintRectWithoutMeasureAndLayout(curWindowRect, isContainerModal);
1042 
1043     auto borderRadius = 0.0_vp;
1044     if (considerFloatingWindow) {
1045         auto windowManager = pipelineContext->GetWindowManager();
1046         CHECK_NULL_VOID(windowManager);
1047         bool isFloatingWindow = windowManager->GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING;
1048         borderRadius = (isFloatingWindow && isTitleShow_) ? CONTAINER_OUTER_RADIUS : 0.0_vp;
1049     } else {
1050         borderRadius = isTitleShow_ ? CONTAINER_OUTER_RADIUS : 0.0_vp;
1051     }
1052     auto borderRadiusValue = borderRadius.ConvertToPx();
1053 
1054     auto expectRect = RRect::MakeRect(curWindowRect);
1055     expectRect.SetRectWithSimpleRadius(curWindowRect, borderRadiusValue, borderRadiusValue);
1056     if (windowPaintRect_ == expectRect) {
1057         return;
1058     }
1059 
1060     // set container window show state to RS
1061     pipelineContext->SetContainerWindow(isTitleShow_, expectRect);
1062     windowPaintRect_ = expectRect;
1063 
1064     CHECK_NULL_VOID(titleMgr_);
1065     titleMgr_->UpdateToolbarShow(isTitleShow_, customTitleSettedShow_);
1066     CHECK_NULL_VOID(floatTitleMgr_);
1067     floatTitleMgr_->UpdateToolbarShow(isTitleShow_, customTitleSettedShow_);
1068 }
1069 
UpdateRowHeight(const RefPtr<FrameNode> & row,Dimension height)1070 void ContainerModalPattern::UpdateRowHeight(const RefPtr<FrameNode>& row, Dimension height)
1071 {
1072     CHECK_NULL_VOID(row);
1073     auto layoutProperty = row->GetLayoutProperty<LinearLayoutProperty>();
1074     CHECK_NULL_VOID(layoutProperty);
1075     layoutProperty->UpdateUserDefinedIdealSize(CalcSize(CalcLength(1.0, DimensionUnit::PERCENT), CalcLength(height)));
1076     row->MarkModifyDone();
1077     row->MarkDirtyNode();
1078 }
1079 
EnableContainerModalCustomGesture(RefPtr<PipelineContext> pipeline,bool enable)1080 void ContainerModalPattern::EnableContainerModalCustomGesture(RefPtr<PipelineContext> pipeline, bool enable)
1081 {
1082     CHECK_NULL_VOID(pipeline);
1083     if (!pipeline || pipeline->GetWindowModal() != WindowModal::CONTAINER_MODAL) {
1084         return;
1085     }
1086     auto rootNode = pipeline->GetRootElement();
1087     CHECK_NULL_VOID(rootNode);
1088     auto containerNode = AceType::DynamicCast<FrameNode>(rootNode->GetChildren().front());
1089     CHECK_NULL_VOID(containerNode);
1090     auto containerPattern = containerNode->GetPattern<ContainerModalPattern>();
1091     CHECK_NULL_VOID(containerPattern);
1092     containerPattern->SetEnableContainerModalCustomGesture(enable);
1093     containerPattern->InitColumnTouchTestFunc();
1094 }
1095 
SetToolbarBuilder(const RefPtr<FrameNode> & parent,std::function<RefPtr<UINode> ()> && builder)1096 void ContainerModalPattern::SetToolbarBuilder(
1097     const RefPtr<FrameNode>& parent, std::function<RefPtr<UINode>()>&& builder)
1098 {
1099     CHECK_NULL_VOID(parent);
1100     if (titleMgr_ == nullptr) {
1101         auto title = GetCustomTitleRow();
1102         titleMgr_ = MakeRefPtr<ContainerModalToolBar>(WeakClaim(this), title, false);
1103     }
1104     if (floatTitleMgr_ == nullptr) {
1105         auto title = GetFloatingTitleRow();
1106         floatTitleMgr_ = MakeRefPtr<ContainerModalToolBar>(WeakClaim(this), title, true);
1107     }
1108 
1109     titleMgr_->SetToolbarBuilder(parent, builder);
1110     floatTitleMgr_->SetToolbarBuilder(parent, builder);
1111 }
1112 
UpdateContainerBgColor()1113 void ContainerModalPattern::UpdateContainerBgColor()
1114 {
1115     if (isCustomColor_) {
1116         return;
1117     }
1118     auto containerModal = GetHost();
1119     CHECK_NULL_VOID(containerModal);
1120     auto containerContext = containerModal->GetRenderContext();
1121     CHECK_NULL_VOID(containerContext);
1122     auto stackNode = GetContentNode();
1123     CHECK_NULL_VOID(stackNode);
1124     auto stackNodeContext = stackNode->GetRenderContext();
1125     CHECK_NULL_VOID(stackNodeContext);
1126     auto backgroundColorOpt = stackNodeContext->GetBackgroundColor();
1127     if (!customTitleSettedShow_ && backgroundColorOpt.has_value() &&
1128         stackNodeContext->GetBackgroundColorValue().GetAlpha() == STAGE_BACKGROUND_COLOR_ALPHA) {
1129         auto pipelineContext = containerModal->GetContextRefPtr();
1130         auto theme = pipelineContext->GetTheme<ContainerModalTheme>();
1131         containerContext->UpdateBackgroundColor(theme->GetWindowJaggedEdgeRenderColor());
1132     } else {
1133         containerContext->UpdateBackgroundColor(GetContainerColor(isFocus_));
1134     }
1135 }
1136 } // namespace OHOS::Ace::NG