1 /*
2 * Copyright (c) 2023 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/menu/preview/menu_preview_layout_algorithm.h"
17
18 #include "core/components_ng/pattern/menu/menu_pattern.h"
19 #include "core/components_ng/pattern/menu/preview/menu_preview_pattern.h"
20
21 namespace OHOS::Ace::NG {
Measure(LayoutWrapper * layoutWrapper)22 void MenuPreviewLayoutAlgorithm::Measure(LayoutWrapper* layoutWrapper)
23 {
24 UpdateLayoutConstraintForPreview(layoutWrapper);
25 auto layoutConstraint = layoutWrapper->GetLayoutProperty()->CreateChildConstraint();
26 for (const auto& child : layoutWrapper->GetAllChildrenWithBuild()) {
27 child->Measure(layoutConstraint);
28 }
29
30 LinearLayoutAlgorithm::Measure(layoutWrapper);
31 }
32
Layout(LayoutWrapper * layoutWrapper)33 void MenuPreviewLayoutAlgorithm::Layout(LayoutWrapper* layoutWrapper)
34 {
35 auto preview = layoutWrapper->GetHostNode();
36 CHECK_NULL_VOID(preview);
37 auto previewPattern = preview->GetPattern<MenuPreviewPattern>();
38 CHECK_NULL_VOID(previewPattern);
39 auto menuWrapper = previewPattern->GetMenuWrapper();
40 CHECK_NULL_VOID(menuWrapper);
41 auto menuWrapperPattern = menuWrapper->GetPattern<MenuWrapperPattern>();
42 CHECK_NULL_VOID(menuWrapperPattern);
43 auto menuNode = menuWrapperPattern->GetMenu();
44 CHECK_NULL_VOID(menuNode);
45 auto menuLayoutAlgorithmWrapper = menuNode->GetLayoutAlgorithm();
46 CHECK_NULL_VOID(menuLayoutAlgorithmWrapper);
47 auto menuLayoutAlgorithm = DynamicCast<MenuLayoutAlgorithm>(menuLayoutAlgorithmWrapper->GetLayoutAlgorithm());
48 CHECK_NULL_VOID(menuLayoutAlgorithm);
49 auto menuPattern = menuNode->GetPattern<MenuPattern>();
50 CHECK_NULL_VOID(menuPattern);
51 if (!menuPattern->HasLaid()) {
52 menuLayoutAlgorithm->Measure(AceType::RawPtr(menuNode));
53 menuLayoutAlgorithm->Layout(AceType::RawPtr(menuNode));
54 // This is a workaround, because sometimes the dirty will not be marked to the top menu node,
55 // the image size of the hoverScale may change. After the change, the image needs to call layout to send
56 // the measured paint to the rosen paint.
57 LayoutHoverScaleImage(menuWrapperPattern);
58 }
59 menuPattern->SetHasLaid(false);
60 for (const auto& child : layoutWrapper->GetAllChildrenWithBuild()) {
61 child->Layout();
62 }
63 LinearLayoutAlgorithm::Layout(layoutWrapper);
64 }
65
LayoutHoverScaleImage(const RefPtr<MenuWrapperPattern> & wrapperPattern)66 void MenuPreviewLayoutAlgorithm::LayoutHoverScaleImage(const RefPtr<MenuWrapperPattern>& wrapperPattern)
67 {
68 CHECK_NULL_VOID(wrapperPattern);
69 if (!wrapperPattern->GetIsShowHoverImage()) {
70 return;
71 }
72 auto hoverScaleImage = wrapperPattern->GetHoverImagePreview();
73 CHECK_NULL_VOID(hoverScaleImage);
74 hoverScaleImage->Layout();
75 }
76
UpdateLayoutConstraintForPreview(LayoutWrapper * layoutWrapper)77 void MenuPreviewLayoutAlgorithm::UpdateLayoutConstraintForPreview(LayoutWrapper* layoutWrapper)
78 {
79 auto preview = layoutWrapper->GetHostNode();
80 CHECK_NULL_VOID(preview);
81 auto previewPattern = preview->GetPattern<MenuPreviewPattern>();
82 CHECK_NULL_VOID(previewPattern);
83 auto menuWrapper = previewPattern->GetMenuWrapper();
84 CHECK_NULL_VOID(menuWrapper);
85 auto menuWrapperPattern = menuWrapper->GetPattern<MenuWrapperPattern>();
86 CHECK_NULL_VOID(menuWrapperPattern);
87 auto menuParam = menuWrapperPattern->GetMenuParam();
88 CHECK_NULL_VOID(menuParam.isPreviewContainScale);
89 auto menuNode = menuWrapperPattern->GetMenu();
90 CHECK_NULL_VOID(menuNode);
91 auto menuPattern = menuNode->GetPattern<MenuPattern>();
92 CHECK_NULL_VOID(menuPattern);
93 auto menuWindowRect = menuPattern->GetMenuWindowRect();
94 auto maxWidth = menuWindowRect.Width();
95 auto maxHeight = menuWindowRect.Height();
96 auto targetSize = menuPattern->GetTargetSize();
97 auto isOversize = GreatNotEqual(targetSize.Width(), maxWidth) || GreatNotEqual(targetSize.Height(), maxHeight);
98 if (isOversize) {
99 auto widthDelta = targetSize.Width() - maxWidth;
100 auto heightDelta = targetSize.Height() - maxHeight;
101 if (GreatOrEqual(widthDelta, heightDelta)) {
102 maxHeight = targetSize.Height() * (maxWidth / targetSize.Width());
103 } else {
104 maxWidth = targetSize.Width() * (maxHeight / targetSize.Height());
105 }
106 auto layoutConstraint = layoutWrapper->GetLayoutProperty()->CreateChildConstraint();
107 layoutConstraint.maxSize.SetWidth(maxWidth);
108 layoutConstraint.maxSize.SetHeight(maxHeight);
109 layoutConstraint.selfIdealSize.SetWidth(maxWidth);
110 layoutConstraint.selfIdealSize.SetHeight(maxHeight);
111 layoutWrapper->GetLayoutProperty()->UpdateLayoutConstraint(layoutConstraint);
112 }
113 }
114 } // namespace OHOS::Ace::NG
115