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