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