• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     CHECK_NULL_VOID(layoutWrapper);
25     UpdateLayoutConstraintForPreview(layoutWrapper);
26     auto layoutProperty = layoutWrapper->GetLayoutProperty();
27     CHECK_NULL_VOID(layoutProperty);
28     auto layoutConstraint = layoutProperty->CreateChildConstraint();
29     for (const auto& child : layoutWrapper->GetAllChildrenWithBuild()) {
30         child->Measure(layoutConstraint);
31     }
32 
33     LinearLayoutAlgorithm::Measure(layoutWrapper);
34 }
35 
Layout(LayoutWrapper * layoutWrapper)36 void MenuPreviewLayoutAlgorithm::Layout(LayoutWrapper* layoutWrapper)
37 {
38     auto preview = layoutWrapper->GetHostNode();
39     CHECK_NULL_VOID(preview);
40     auto previewPattern = preview->GetPattern<MenuPreviewPattern>();
41     CHECK_NULL_VOID(previewPattern);
42     auto menuWrapper = previewPattern->GetMenuWrapper();
43     CHECK_NULL_VOID(menuWrapper);
44     auto menuWrapperPattern = menuWrapper->GetPattern<MenuWrapperPattern>();
45     CHECK_NULL_VOID(menuWrapperPattern);
46     auto menuNode = menuWrapperPattern->GetMenu();
47     CHECK_NULL_VOID(menuNode);
48     auto menuLayoutAlgorithmWrapper = menuNode->GetLayoutAlgorithm();
49     CHECK_NULL_VOID(menuLayoutAlgorithmWrapper);
50     auto menuLayoutAlgorithm = DynamicCast<MenuLayoutAlgorithm>(menuLayoutAlgorithmWrapper->GetLayoutAlgorithm());
51     CHECK_NULL_VOID(menuLayoutAlgorithm);
52     auto menuPattern = menuNode->GetPattern<MenuPattern>();
53     CHECK_NULL_VOID(menuPattern);
54     if (!menuPattern->HasLaid()) {
55         menuLayoutAlgorithm->Measure(AceType::RawPtr(menuNode));
56         menuLayoutAlgorithm->Layout(AceType::RawPtr(menuNode));
57         // This is a workaround, because sometimes the dirty will not be marked to the top menu node,
58         // the image size of the hoverScale may change. After the change, the image needs to call layout to send
59         // the measured paint to the rosen paint.
60         LayoutHoverScaleImage(menuWrapperPattern);
61     }
62     menuPattern->SetHasLaid(false);
63     for (const auto& child : layoutWrapper->GetAllChildrenWithBuild()) {
64         child->Layout();
65     }
66     LinearLayoutAlgorithm::Layout(layoutWrapper);
67 }
68 
LayoutHoverScaleImage(const RefPtr<MenuWrapperPattern> & wrapperPattern)69 void MenuPreviewLayoutAlgorithm::LayoutHoverScaleImage(const RefPtr<MenuWrapperPattern>& wrapperPattern)
70 {
71     CHECK_NULL_VOID(wrapperPattern);
72     if (!wrapperPattern->GetIsShowHoverImage()) {
73         return;
74     }
75     auto hoverScaleImage = wrapperPattern->GetHoverImagePreview();
76     CHECK_NULL_VOID(hoverScaleImage);
77     hoverScaleImage->Layout();
78 }
79 
UpdateLayoutConstraintForPreview(LayoutWrapper * layoutWrapper)80 void MenuPreviewLayoutAlgorithm::UpdateLayoutConstraintForPreview(LayoutWrapper* layoutWrapper)
81 {
82     CHECK_NULL_VOID(layoutWrapper);
83     auto preview = layoutWrapper->GetHostNode();
84     CHECK_NULL_VOID(preview);
85     auto previewPattern = preview->GetPattern<MenuPreviewPattern>();
86     CHECK_NULL_VOID(previewPattern);
87     auto menuWrapper = previewPattern->GetMenuWrapper();
88     CHECK_NULL_VOID(menuWrapper);
89     auto menuWrapperPattern = menuWrapper->GetPattern<MenuWrapperPattern>();
90     CHECK_NULL_VOID(menuWrapperPattern);
91     auto menuNode = menuWrapperPattern->GetMenu();
92     CHECK_NULL_VOID(menuNode);
93     auto menuPattern = menuNode->GetPattern<MenuPattern>();
94     CHECK_NULL_VOID(menuPattern);
95     auto menuParam = menuWrapperPattern->GetMenuParam();
96     if (menuParam.isPreviewContainScale) {
97         auto menuWindowRect = menuPattern->GetMenuWindowRect();
98         auto maxWidth = menuWindowRect.Width();
99         auto maxHeight = menuWindowRect.Height();
100         auto targetSize = menuPattern->GetTargetSize();
101         auto isOversize = GreatNotEqual(targetSize.Width(), maxWidth) || GreatNotEqual(targetSize.Height(), maxHeight);
102         if (!isOversize) {
103             return;
104         }
105         auto widthDelta = targetSize.Width() - maxWidth;
106         auto heightDelta = targetSize.Height() - maxHeight;
107         if (GreatOrEqual(widthDelta, heightDelta)) {
108             maxHeight = targetSize.Height() * (maxWidth / targetSize.Width());
109         } else {
110             maxWidth = targetSize.Width() * (maxHeight / targetSize.Height());
111         }
112         auto layoutProperty = layoutWrapper->GetLayoutProperty();
113         CHECK_NULL_VOID(layoutProperty);
114         auto layoutConstraint = layoutProperty->CreateChildConstraint();
115         layoutConstraint.maxSize.SetWidth(maxWidth);
116         layoutConstraint.maxSize.SetHeight(maxHeight);
117         layoutConstraint.selfIdealSize.SetWidth(maxWidth);
118         layoutConstraint.selfIdealSize.SetHeight(maxHeight);
119         layoutProperty->UpdateLayoutConstraint(layoutConstraint);
120     } else {
121         CheckLayoutConstraint(layoutWrapper, menuParam, menuPattern);
122     }
123 }
124 
CheckLayoutConstraint(LayoutWrapper * layoutWrapper,const MenuParam & menuParam,const RefPtr<MenuPattern> & menuPattern)125 void MenuPreviewLayoutAlgorithm::CheckLayoutConstraint(
126     LayoutWrapper* layoutWrapper, const MenuParam& menuParam, const RefPtr<MenuPattern>& menuPattern)
127 {
128     CHECK_NULL_VOID(menuPattern);
129     CHECK_NULL_VOID(layoutWrapper);
130     auto layoutProperty = layoutWrapper->GetLayoutProperty();
131     CHECK_NULL_VOID(layoutProperty);
132     auto layoutConstraint = layoutProperty->CreateChildConstraint();
133 
134     auto isUpdateContentConstraint = false;
135     // contentRect = windowSize - safeArea - margin
136     if (menuParam.availableLayoutAreaMode.has_value() &&
137         menuParam.availableLayoutAreaMode.value() == AvailableLayoutAreaMode::SAFE_AREA) {
138         auto layoutParam = menuPattern->GetMenuLayoutParam();
139         auto maxWidth = layoutParam.wrapperRect.Width() - layoutParam.leftSecurity - layoutParam.rightSecurity;
140         maxWidth = std::max(maxWidth, 0.0);
141         auto maxHeight = layoutParam.wrapperRect.Height() - layoutParam.topSecurity - layoutParam.bottomSecurity;
142         maxHeight = std::max(maxHeight, 0.0);
143         layoutConstraint.maxSize = { maxWidth, maxHeight };
144         layoutConstraint.percentReference = { maxWidth, maxHeight };
145         isUpdateContentConstraint = true;
146     }
147 
148     if (menuParam.previewScaleMode.value_or(PreviewScaleMode::AUTO) == PreviewScaleMode::MAINTAIN) {
149         layoutConstraint.maxSize = { Infinity<float>(), Infinity<float>() };
150         isUpdateContentConstraint = true;
151     }
152 
153     layoutProperty->UpdateLayoutConstraint(layoutConstraint);
154     if (isUpdateContentConstraint) {
155         layoutProperty->UpdateContentConstraint();
156     }
157 }
158 } // namespace OHOS::Ace::NG
159