• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_OVERLAY_SHEET_MANAGER_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_OVERLAY_SHEET_MANAGER_H
18 
19 #include "base/utils/singleton.h"
20 #include "core/components_ng/pattern/overlay/overlay_manager.h"
21 #include "core/pipeline_ng/pipeline_context.h"
22 
23 namespace OHOS::Ace::NG {
24 class State {
25 public:
26     virtual SheetType HandleType(const SheetStyle& sheetStyle) = 0;
27     virtual ~State() = default;
28 };
29 
30 // If the breakpoint is WidthXS, the default style is the bottom style,
31 // and the developer can actively set the modal style.
32 class WidthXSState : public State {
33 public:
HandleType(const SheetStyle & sheetStyle)34     SheetType HandleType(const SheetStyle& sheetStyle) override
35     {
36         if (sheetStyle.sheetType.has_value() &&
37             sheetStyle.sheetType.value() == SheetType::SHEET_CONTENT_COVER) {
38             return sheetStyle.sheetType.value();
39         }
40         SheetType sheetType = SheetType::SHEET_BOTTOM;
41         auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
42         CHECK_NULL_RETURN(pipeline, sheetType);
43         auto sheetTheme = pipeline->GetTheme<SheetTheme>();
44         CHECK_NULL_RETURN(sheetTheme, sheetType);
45         auto sheetThemeType = sheetTheme->GetSheetType();
46         if (sheetThemeType == "popup") {
47             sheetType = SheetType::SHEET_BOTTOM_FREE_WINDOW;
48         }
49         return sheetType;
50     }
51 };
52 
53 // If the breakpoint is WidthXS, the default style is the bottom style,
54 // and the developer can actively set the modal style
55 class WidthSMState : public State {
56 public:
HandleType(const SheetStyle & sheetStyle)57     SheetType HandleType(const SheetStyle& sheetStyle) override
58     {
59         if (sheetStyle.sheetType.has_value() &&
60             sheetStyle.sheetType.value() == SheetType::SHEET_CONTENT_COVER) {
61             return sheetStyle.sheetType.value();
62         }
63         SheetType sheetType = SheetType::SHEET_BOTTOM;
64         auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
65         CHECK_NULL_RETURN(pipeline, sheetType);
66         auto sheetTheme = pipeline->GetTheme<SheetTheme>();
67         CHECK_NULL_RETURN(sheetTheme, sheetType);
68         auto sheetThemeType = sheetTheme->GetSheetType();
69         if (sheetThemeType == "popup") {
70             sheetType = SheetType::SHEET_BOTTOM_FREE_WINDOW;
71         }
72         return sheetType;
73     }
74 };
75 
76 // If the breakpoint is (WidthMD, HeightSM), the default style is the bottom landspace style,
77 // and the developer can actively set the modal or side style.
78 // In particular, when the sheetBottom_ is "center", the style is center.
79 class WidthMDHeightSMState : public State {
80 public:
HandleType(const SheetStyle & sheetStyle)81     SheetType HandleType(const SheetStyle& sheetStyle) override
82     {
83         if (sheetStyle.sheetType.has_value() &&
84             sheetStyle.sheetType.value() == SheetType::SHEET_CONTENT_COVER) {
85             return SheetType::SHEET_CONTENT_COVER;
86         }
87         if (sheetStyle.sheetType.has_value() &&
88             sheetStyle.sheetType.value() == SheetType::SHEET_BOTTOM) {
89             return SheetType::SHEET_BOTTOM;
90         }
91         if (sheetStyle.sheetType.has_value() &&
92             sheetStyle.sheetType.value() == SheetType::SHEET_SIDE) {
93             return SheetType::SHEET_SIDE;
94         }
95         SheetType sheetType = SheetType::SHEET_BOTTOMLANDSPACE;
96         auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
97         CHECK_NULL_RETURN(pipeline, sheetType);
98         auto sheetTheme = pipeline->GetTheme<SheetTheme>();
99         CHECK_NULL_RETURN(sheetTheme, sheetType);
100         if (sheetTheme->GetSheetBottomType() == "center") {
101             sheetType = SheetType::SHEET_CENTER;
102         }
103         if (sheetTheme->GetSheetType() == "popup") {
104             sheetType = sheetStyle.sheetType.has_value() ?
105                 sheetStyle.sheetType.value() : SheetType::SHEET_CENTER;
106         }
107         return sheetType;
108     }
109 };
110 
111 // If the breakpoint is (WidthMD, HeightMD/HeightLG), the default style is the center style.
112 // The version is later than API 14, and developers can set all style.
113 // The version is lower than API14, the center style will take effect when the developer sets the popup style.
114 class WidthMDHeightMDOrLGState : public State {
115 public:
HandleType(const SheetStyle & sheetStyle)116     SheetType HandleType(const SheetStyle& sheetStyle) override
117     {
118         if (sheetStyle.sheetType.has_value()) {
119             if (!AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_FOURTEEN) &&
120                 sheetStyle.sheetType.value() == SheetType::SHEET_POPUP) {
121                 return SheetType::SHEET_CENTER;
122             }
123             return sheetStyle.sheetType.value();
124         }
125         return SheetType::SHEET_CENTER;
126     }
127 };
128 
129 // When the breakpoint is greater than or equal to WidthLG,
130 // the style that takes effect by default is determined from sheetTheme.
131 // And developers can set all style.
132 class WidthLGState : public State {
133 public:
HandleType(const SheetStyle & sheetStyle)134     SheetType HandleType(const SheetStyle& sheetStyle) override
135     {
136         if (sheetStyle.sheetType.has_value()) {
137             return sheetStyle.sheetType.value();
138         }
139         SheetType sheetType = SheetType::SHEET_POPUP;
140         auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
141         CHECK_NULL_RETURN(pipeline, sheetType);
142         auto sheetTheme = pipeline->GetTheme<SheetTheme>();
143         CHECK_NULL_RETURN(sheetTheme, sheetType);
144         auto sheetThemeType = sheetTheme->GetSheetType();
145         if (sheetThemeType == "auto") {
146             sheetType = SheetType::SHEET_CENTER;
147         } else if (sheetThemeType == "popup") {
148             sheetType = SheetType::SHEET_POPUP;
149         } else if (sheetThemeType == "center") {
150             sheetType = SheetType::SHEET_CENTER;
151         }
152         return sheetType;
153     }
154 };
155 
156 class ACE_FORCE_EXPORT SheetManager : public Singleton<SheetManager> {
157     DECLARE_SINGLETON(SheetManager);
158 public:
159     static RefPtr<OverlayManager> FindPageNodeOverlay(
160         const RefPtr<FrameNode>& targetNode, bool isShow, bool isStartByUIContext = false);
161     static RefPtr<OverlayManager> GetOverlayFromPage(int32_t rootNodeId, RootNodeType rootNodeType);
162 
163     int32_t OpenBindSheetByUIContext(const RefPtr<NG::FrameNode>& sheetContentNode,
164          std::function<void()>&& titleBuildFunc, NG::SheetStyle& sheetStyle,
165         std::function<void()>&& onAppear, std::function<void()>&& onDisappear, std::function<void()>&& shouldDismiss,
166         std::function<void(const int32_t info)>&& onWillDismiss, std::function<void()>&& onWillAppear,
167         std::function<void()>&& onWillDisappear, std::function<void(const float)>&& onHeightDidChange,
168         std::function<void(const float)>&& onDetentsDidChange, std::function<void(const float)>&& onWidthDidChange,
169         std::function<void(const float)>&& onTypeDidChange, std::function<void()>&& sheetSpringBack,
170         int32_t currentInstanceId, int32_t targetId);
171     int32_t UpdateBindSheetByUIContext(
172         const RefPtr<NG::FrameNode>& sheetContentNode, const NG::SheetStyle& sheetStyle, bool isPartialUpdate,
173         int32_t currentInstanceId);
174     int32_t CloseBindSheetByUIContext(const RefPtr<NG::FrameNode>& sheetContentNode, int32_t currentInstanceId);
CleanBindSheetMap(int32_t instanceId,int32_t sheetContentNodeId)175     void CleanBindSheetMap(int32_t instanceId, int32_t sheetContentNodeId)
176     {
177         overlayManagerMap_.erase(SheetContentKey(instanceId, sheetContentNodeId));
178         targetIdMap_.erase(SheetContentKey(instanceId, sheetContentNodeId));
179     }
180 
SetDismissSheet(int32_t dismissId)181     void SetDismissSheet(int32_t dismissId)
182     {
183         sheetDismissId_ = dismissId;
184     }
185 
GetDismissSheet()186     int32_t GetDismissSheet()
187     {
188         return sheetDismissId_;
189     }
190 
SetFocusSheetId(const std::optional<int32_t> & id)191     void SetFocusSheetId(const std::optional<int32_t>& id)
192     {
193         sheetFocusId_ = id;
194     }
195 
GetFocusSheetId()196     std::optional<int32_t> GetFocusSheetId() const
197     {
198         return sheetFocusId_;
199     }
200 
201     bool RemoveSheetByESC();
202 
203     void DeleteOverlayForWindowScene(int32_t rootNodeId, RootNodeType rootNodeType);
204 
205     void CloseSheetInSubWindow(const SheetKey& sheetKey);
206     static void SetMaskInteractive(const RefPtr<FrameNode>& maskNode, bool isInteractive);
207     void RegisterDestroyCallback(const RefPtr<FrameNode>& targetNode, NG::SheetStyle& sheetStyle,
208         const int32_t containerId);
209     std::unique_ptr<State> CreateBreakPointState(WidthBreakpoint width,
210         HeightBreakpoint height);
211 
212 private:
213     struct SheetContentKey {
SheetContentKeySheetContentKey214         SheetContentKey() {}
SheetContentKeySheetContentKey215         SheetContentKey(int32_t inputInstanceId, int32_t inputContentNodeId)
216             : instanceId(inputInstanceId), contentNodeId(inputContentNodeId) {}
217         int32_t instanceId;
218         int32_t contentNodeId;
219         bool operator<(const SheetContentKey& other) const {
220             if (instanceId == other.instanceId) {
221                 return contentNodeId < other.contentNodeId;
222             }
223             return instanceId < other.instanceId;
224         }
225     };
226 
227     int32_t sheetDismissId_ = 0;
228     std::optional<int32_t> sheetFocusId_;
229     std::map<SheetContentKey, RefPtr<OverlayManager>> overlayManagerMap_;
230     // Value:  The uniqueId of the FrameNode to which BindSheet is attached
231     std::map<SheetContentKey, int32_t> targetIdMap_;
232 };
233 } // namespace OHOS::Ace::NG
234 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_OVERLAY_SHEET_MANAGER_H
235