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 "base/utils/utils.h"
19 #include "core/components/common/properties/shadow_config.h"
20 #include "core/components/declaration/common/declaration_constants.h"
21 #include "core/components_ng/pattern/menu/menu_layout_algorithm.h"
22 #include "core/components_ng/pattern/menu/menu_paint_property.h"
23 #include "core/components_ng/pattern/menu/menu_pattern.h"
24 #include "core/components_ng/pattern/menu/menu_theme.h"
25 #include "core/components_ng/pattern/menu/menu_pattern.h"
26 #include "core/components_ng/pattern/menu/preview/menu_preview_pattern.h"
27 #include "core/components_ng/pattern/menu/wrapper/menu_wrapper_pattern.h"
28 #include "core/components_ng/property/measure_property.h"
29 #include "core/components_ng/property/measure_utils.h"
30 
31 namespace OHOS::Ace::NG {
Measure(LayoutWrapper * layoutWrapper)32 void MenuPreviewLayoutAlgorithm::Measure(LayoutWrapper* layoutWrapper)
33 {
34     UpdateLayoutConstraintForPreview(layoutWrapper);
35     auto layoutConstraint = layoutWrapper->GetLayoutProperty()->CreateChildConstraint();
36     for (const auto& child : layoutWrapper->GetAllChildrenWithBuild()) {
37         child->Measure(layoutConstraint);
38     }
39 
40     LinearLayoutAlgorithm::Measure(layoutWrapper);
41 }
42 
Layout(LayoutWrapper * layoutWrapper)43 void MenuPreviewLayoutAlgorithm::Layout(LayoutWrapper* layoutWrapper)
44 {
45     auto preview = layoutWrapper->GetHostNode();
46     CHECK_NULL_VOID(preview);
47     auto previewPattern = preview->GetPattern<MenuPreviewPattern>();
48     CHECK_NULL_VOID(previewPattern);
49     auto menuWrapper = previewPattern->GetMenuWrapper();
50     CHECK_NULL_VOID(menuWrapper);
51     auto menuWrapperPattern = menuWrapper->GetPattern<MenuWrapperPattern>();
52     CHECK_NULL_VOID(menuWrapperPattern);
53     auto menuNode = menuWrapperPattern->GetMenu();
54     CHECK_NULL_VOID(menuNode);
55     auto menuLayoutAlgorithmWrapper = menuNode->GetLayoutAlgorithm();
56     CHECK_NULL_VOID(menuLayoutAlgorithmWrapper);
57     auto menuLayoutAlgorithm = DynamicCast<MenuLayoutAlgorithm>(menuLayoutAlgorithmWrapper->GetLayoutAlgorithm());
58     CHECK_NULL_VOID(menuLayoutAlgorithm);
59     auto menuPattern = menuNode->GetPattern<MenuPattern>();
60     CHECK_NULL_VOID(menuPattern);
61     if (!menuPattern->HasLaid()) {
62         menuLayoutAlgorithm->Measure(AceType::RawPtr(menuNode));
63         menuLayoutAlgorithm->Layout(AceType::RawPtr(menuNode));
64     }
65     menuPattern->SetHasLaid(false);
66     for (const auto& child : layoutWrapper->GetAllChildrenWithBuild()) {
67         child->Layout();
68     }
69     LinearLayoutAlgorithm::Layout(layoutWrapper);
70 }
71 
UpdateLayoutConstraintForPreview(LayoutWrapper * layoutWrapper)72 void MenuPreviewLayoutAlgorithm::UpdateLayoutConstraintForPreview(LayoutWrapper* layoutWrapper)
73 {
74     auto preview = layoutWrapper->GetHostNode();
75     CHECK_NULL_VOID(preview);
76     auto previewPattern = preview->GetPattern<MenuPreviewPattern>();
77     CHECK_NULL_VOID(previewPattern);
78     auto menuWrapper = previewPattern->GetMenuWrapper();
79     CHECK_NULL_VOID(menuWrapper);
80     auto menuWrapperPattern = menuWrapper->GetPattern<MenuWrapperPattern>();
81     CHECK_NULL_VOID(menuWrapperPattern);
82     auto menuParam = menuWrapperPattern->GetMenuParam();
83     CHECK_NULL_VOID(menuParam.isPreviewContainScale);
84     auto menuNode = menuWrapperPattern->GetMenu();
85     CHECK_NULL_VOID(menuNode);
86     auto menuPattern = menuNode->GetPattern<MenuPattern>();
87     CHECK_NULL_VOID(menuPattern);
88     auto menuWindowRect = menuPattern->GetMenuWindowRect();
89     auto maxWidth = menuWindowRect.Width();
90     auto maxHeight = menuWindowRect.Height();
91     auto targetSize = menuPattern->GetTargetSize();
92     auto isOversize = GreatNotEqual(targetSize.Width(), maxWidth) || GreatNotEqual(targetSize.Height(), maxHeight);
93     if (isOversize) {
94         auto widthDelta = targetSize.Width() - maxWidth;
95         auto heightDelta = targetSize.Height() - maxHeight;
96         if (GreatOrEqual(widthDelta, heightDelta)) {
97             maxHeight = targetSize.Height() * (maxWidth / targetSize.Width());
98         } else {
99             maxWidth = targetSize.Width() * (maxHeight / targetSize.Height());
100         }
101         auto layoutConstraint = layoutWrapper->GetLayoutProperty()->CreateChildConstraint();
102         layoutConstraint.maxSize.SetWidth(maxWidth);
103         layoutConstraint.maxSize.SetHeight(maxHeight);
104         layoutConstraint.selfIdealSize.SetWidth(maxWidth);
105         layoutConstraint.selfIdealSize.SetHeight(maxHeight);
106         layoutWrapper->GetLayoutProperty()->UpdateLayoutConstraint(layoutConstraint);
107     }
108 }
109 } // namespace OHOS::Ace::NG
110