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