• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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_MENU_MENU_WRAPPER_PATTERN_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_MENU_MENU_WRAPPER_PATTERN_H
18 
19 #include "base/memory/ace_type.h"
20 #include "base/memory/referenced.h"
21 #include "base/subwindow/subwindow_manager.h"
22 #include "base/utils/string_utils.h"
23 #include "base/utils/utils.h"
24 #include "core/components/common/properties/color.h"
25 #include "core/components/common/properties/placement.h"
26 #include "core/components_ng/base/frame_node.h"
27 #include "core/components_ng/pattern/menu/menu_item/menu_item_pattern.h"
28 #include "core/components_ng/pattern/menu/menu_layout_algorithm.h"
29 #include "core/components_ng/pattern/menu/menu_pattern.h"
30 #include "core/components_ng/pattern/menu/wrapper/menu_wrapper_layout_algorithm.h"
31 #include "core/components_ng/pattern/overlay/popup_base_pattern.h"
32 #include "core/components_ng/pattern/pattern.h"
33 #include "core/components_v2/inspector/inspector_constants.h"
34 #include "core/pipeline_ng/ui_task_scheduler.h"
35 
36 namespace OHOS::Ace::NG {
37 
38 enum class MenuStatus {
39     INIT,              // Neither exists in the menuMap_ nor on the tree
40     ON_SHOW_ANIMATION, // Exists in the menuMap_ also exists on the tree
41     SHOW,              // Exists in the menuMap_ also exists on the tree
42     ON_HIDE_ANIMATION, // Exists in the menuMap_ also exists on the tree
43     HIDE               // Exists in the menuMap_ but not on the tree
44 };
45 
46 // has full screen size
47 // used for detecting clicks outside Menu area
48 class MenuWrapperPattern : public PopupBasePattern {
49     DECLARE_ACE_TYPE(MenuWrapperPattern, Pattern);
50 
51 public:
MenuWrapperPattern(int32_t Id)52     explicit MenuWrapperPattern(int32_t Id) : targetId_(Id) {}
53     ~MenuWrapperPattern() override = default;
54 
IsAtomicNode()55     bool IsAtomicNode() const override
56     {
57         return false;
58     }
59 
GetFocusPattern()60     FocusPattern GetFocusPattern() const override
61     {
62         return { FocusType::SCOPE, true };
63     }
64 
CreateLayoutAlgorithm()65     RefPtr<LayoutAlgorithm> CreateLayoutAlgorithm() override
66     {
67         return MakeRefPtr<MenuWrapperLayoutAlgorithm>();
68     }
69 
70     void HandleMouseEvent(const MouseInfo& info, RefPtr<MenuItemPattern>& menuItem);
71 
GetTargetId()72     int32_t GetTargetId() const override
73     {
74         return targetId_;
75     }
76 
77     void HideMenu();
78 
IsHide()79     bool IsHide() const
80     {
81         return menuStatus_ == MenuStatus::ON_HIDE_ANIMATION || menuStatus_ == MenuStatus::HIDE;
82     }
83 
IsContextMenu()84     bool IsContextMenu() const
85     {
86         auto menu = GetMenu();
87         CHECK_NULL_RETURN(menu, false);
88         auto menuPattern = menu->GetPattern<MenuPattern>();
89         CHECK_NULL_RETURN(menuPattern, false);
90         return menuPattern->IsContextMenu();
91     }
92 
GetPreviewMode()93     MenuPreviewMode GetPreviewMode() const
94     {
95         auto menu = GetMenu();
96         CHECK_NULL_RETURN(menu, MenuPreviewMode::NONE);
97         auto menuPattern = menu->GetPattern<MenuPattern>();
98         CHECK_NULL_RETURN(menuPattern, MenuPreviewMode::NONE);
99         return menuPattern->GetPreviewMode();
100     }
101 
IsSelectMenu()102     bool IsSelectMenu() const
103     {
104         auto menu = GetMenu();
105         CHECK_NULL_RETURN(menu, false);
106         auto menuPattern = menu->GetPattern<MenuPattern>();
107         CHECK_NULL_RETURN(menuPattern, false);
108         return menuPattern->IsSelectMenu();
109     }
110 
111     void HideSubMenu();
112     RefPtr<FrameNode> MenuFocusViewShow();
113     void HideStackExpandMenu(const RefPtr<UINode>& subMenu);
114     void GetExpandingMode(const RefPtr<UINode>& subMenu, SubMenuExpandingMode& expandingMode, bool& hasAnimation);
GetMenu()115     RefPtr<FrameNode> GetMenu() const
116     {
117         auto host = GetHost();
118         CHECK_NULL_RETURN(host, nullptr);
119         auto menu = AceType::DynamicCast<FrameNode>(host->GetChildAtIndex(0));
120         CHECK_NULL_RETURN(menu, nullptr);
121         return menu;
122     }
123 
GetHoverImageFlexNode()124     RefPtr<FrameNode> GetHoverImageFlexNode() const
125     {
126         auto host = GetHost();
127         CHECK_NULL_RETURN(host, nullptr);
128         auto node = AceType::DynamicCast<FrameNode>(host->GetChildAtIndex(1));
129         CHECK_NULL_RETURN(node, nullptr);
130         if (node->GetTag() != V2::FLEX_ETS_TAG) {
131             return nullptr;
132         }
133         return node;
134     }
135 
GetHoverImageStackNode()136     RefPtr<FrameNode> GetHoverImageStackNode() const
137     {
138         auto hoverImageFlexNode = GetHoverImageFlexNode();
139         CHECK_NULL_RETURN(hoverImageFlexNode, nullptr);
140         auto node = AceType::DynamicCast<FrameNode>(hoverImageFlexNode->GetChildAtIndex(0));
141         CHECK_NULL_RETURN(node, nullptr);
142         if (node->GetTag() != V2::STACK_ETS_TAG) {
143             return nullptr;
144         }
145         return node;
146     }
147 
GetHoverImagePreview()148     RefPtr<FrameNode> GetHoverImagePreview() const
149     {
150         auto hoverImageStackNode = GetHoverImageStackNode();
151         CHECK_NULL_RETURN(hoverImageStackNode, nullptr);
152         auto node = AceType::DynamicCast<FrameNode>(hoverImageStackNode->GetChildAtIndex(0));
153         CHECK_NULL_RETURN(node, nullptr);
154         if (node->GetTag() != V2::IMAGE_ETS_TAG) {
155             return nullptr;
156         }
157         return node;
158     }
159 
GetHoverImageCustomPreview()160     RefPtr<FrameNode> GetHoverImageCustomPreview() const
161     {
162         auto hoverImageStackNode = GetHoverImageStackNode();
163         CHECK_NULL_RETURN(hoverImageStackNode, nullptr);
164         auto node = AceType::DynamicCast<FrameNode>(hoverImageStackNode->GetChildAtIndex(1));
165         CHECK_NULL_RETURN(node, nullptr);
166         if (node->GetTag() != V2::MENU_PREVIEW_ETS_TAG) {
167             return nullptr;
168         }
169         return node;
170     }
171 
GetPreview()172     RefPtr<FrameNode> GetPreview() const
173     {
174         auto host = GetHost();
175         CHECK_NULL_RETURN(host, nullptr);
176         auto preview = AceType::DynamicCast<FrameNode>(host->GetChildAtIndex(1));
177         CHECK_NULL_RETURN(preview, nullptr);
178         if (preview->GetTag() == V2::FLEX_ETS_TAG) {
179             auto hoverImageCustomPreview = GetHoverImageCustomPreview();
180             CHECK_NULL_RETURN(hoverImageCustomPreview, preview);
181             return hoverImageCustomPreview;
182         }
183         return preview;
184     }
185 
186     // used to obtain the Badge node and delete it.
GetBadgeNode()187     RefPtr<FrameNode> GetBadgeNode() const
188     {
189         auto host = GetHost();
190         CHECK_NULL_RETURN(host, nullptr);
191         for (const auto& child : host->GetChildren()) {
192             auto node = DynamicCast<FrameNode>(child);
193             if (node && node->GetTag() == V2::TEXT_ETS_TAG) {
194                 return node;
195             }
196         }
197         return nullptr;
198     }
199 
200     OffsetT<Dimension> GetAnimationOffset();
201     void SetAniamtinOption(const AnimationOption& animationOption);
202 
SetMenuPlacementAfterLayout(const Placement & placement)203     void SetMenuPlacementAfterLayout(const Placement& placement)
204     {
205         menuPlacement_ = placement;
206     }
207 
SetFirstShow()208     void SetFirstShow()
209     {
210         isFirstShow_ = true;
211     }
212 
SetIsShowHoverImage(bool isShow)213     void SetIsShowHoverImage(bool isShow)
214     {
215         isShowHoverImage_ = isShow;
216     }
217 
GetIsShowHoverImage()218     bool GetIsShowHoverImage() const
219     {
220         return isShowHoverImage_;
221     }
222 
SetIsStopHoverImageAnimation(bool isStop)223     void SetIsStopHoverImageAnimation(bool isStop)
224     {
225         isStopHoverImageAnimation_ = isStop;
226     }
227 
IsStopHoverImageAnimation()228     bool IsStopHoverImageAnimation() const
229     {
230         return isStopHoverImageAnimation_;
231     }
232 
SetIsShowHoverImagePreviewStartDrag(bool isStart)233     void SetIsShowHoverImagePreviewStartDrag(bool isStart)
234     {
235         isShowHoverImagePreviewStartDrag_ = isStart;
236     }
237 
GetIsShowHoverImagePreviewStartDrag()238     bool GetIsShowHoverImagePreviewStartDrag() const
239     {
240         return isShowHoverImagePreviewStartDrag_;
241     }
242 
243     void RegisterMenuCallback(const RefPtr<FrameNode>& menuWrapperNode, const MenuParam& menuParam);
244 
RegisterMenuAppearCallback(const std::function<void ()> & onAppear)245     void RegisterMenuAppearCallback(const std::function<void()>& onAppear)
246     {
247         onAppearCallback_ = onAppear;
248     }
249 
RegisterMenuDisappearCallback(const std::function<void ()> & onDisappear)250     void RegisterMenuDisappearCallback(const std::function<void()>& onDisappear)
251     {
252         onDisappearCallback_ = onDisappear;
253     }
254 
RegisterMenuAboutToAppearCallback(const std::function<void ()> & aboutToAppear)255     void RegisterMenuAboutToAppearCallback(const std::function<void()>& aboutToAppear)
256     {
257         aboutToAppearCallback_ = aboutToAppear;
258     }
259 
RegisterMenuAboutToDisappearCallback(const std::function<void ()> & aboutToDisappear)260     void RegisterMenuAboutToDisappearCallback(const std::function<void()>& aboutToDisappear)
261     {
262         aboutToDisappearCallback_ = aboutToDisappear;
263     }
264 
RegisterMenuStateChangeCallback(const std::function<void (const std::string &)> & callback)265     void RegisterMenuStateChangeCallback(const std::function<void(const std::string&)>& callback)
266     {
267         onStateChangeCallback_ = callback;
268     }
269 
CallMenuAppearCallback()270     void CallMenuAppearCallback()
271     {
272         if (onAppearCallback_) {
273             onAppearCallback_();
274         }
275     }
276 
CallMenuDisappearCallback()277     void CallMenuDisappearCallback()
278     {
279         if (onDisappearCallback_) {
280             onDisappearCallback_();
281         }
282     }
283 
CallMenuAboutToAppearCallback()284     void CallMenuAboutToAppearCallback()
285     {
286         if (aboutToAppearCallback_) {
287             aboutToAppearCallback_();
288         }
289     }
290 
CallMenuAboutToDisappearCallback()291     void CallMenuAboutToDisappearCallback()
292     {
293         if (aboutToDisappearCallback_) {
294             aboutToDisappearCallback_();
295         }
296     }
297 
CallMenuStateChangeCallback(const std::string & value)298     void CallMenuStateChangeCallback(const std::string& value)
299     {
300         if (onStateChangeCallback_) {
301             onStateChangeCallback_(value);
302         }
303     }
304 
GetMenuDisappearCallback()305     const std::function<void()>& GetMenuDisappearCallback()
306     {
307         return onDisappearCallback_;
308     }
309 
IsShow()310     bool IsShow() const
311     {
312         return menuStatus_ == MenuStatus::ON_SHOW_ANIMATION || menuStatus_ == MenuStatus::SHOW;
313     }
314 
SetMenuStatus(MenuStatus value)315     void SetMenuStatus(MenuStatus value)
316     {
317         menuStatus_ = value;
318     }
319 
GetMenuStatus()320     MenuStatus GetMenuStatus() const
321     {
322         return menuStatus_;
323     }
324 
HasTransitionEffect()325     bool HasTransitionEffect() const
326     {
327         return hasTransitionEffect_;
328     }
329 
SetHasTransitionEffect(bool hasTransitionEffect)330     void SetHasTransitionEffect(bool hasTransitionEffect)
331     {
332         hasTransitionEffect_ = hasTransitionEffect;
333     }
334 
335     void SetMenuTransitionEffect(const RefPtr<FrameNode>& menuWrapperNode, const MenuParam& menuParam);
336 
HasPreviewTransitionEffect()337     bool HasPreviewTransitionEffect() const
338     {
339         return hasPreviewTransitionEffect_;
340     }
341 
SetHasPreviewTransitionEffect(bool hasPreviewTransitionEffect)342     void SetHasPreviewTransitionEffect(bool hasPreviewTransitionEffect)
343     {
344         hasPreviewTransitionEffect_ = hasPreviewTransitionEffect;
345     }
346 
HasFoldModeChangedTransition()347     bool HasFoldModeChangedTransition() const
348     {
349         return hasFoldModeChangeTransition_;
350     }
351 
SetHasFoldModeChangedTransition(bool hasTransition)352     void SetHasFoldModeChangedTransition(bool hasTransition)
353     {
354         hasFoldModeChangeTransition_ = hasTransition;
355     }
356 
SetFilterColumnNode(const RefPtr<FrameNode> & columnNode)357     void SetFilterColumnNode(const RefPtr<FrameNode>& columnNode)
358     {
359         filterColumnNode_ = columnNode;
360     }
361 
GetFilterColumnNode()362     RefPtr<FrameNode> GetFilterColumnNode()
363     {
364         return filterColumnNode_;
365     }
366 
367     void DumpInfo() override;
368 
GetDumpInfo()369     MenuDumpInfo GetDumpInfo() const
370     {
371         return dumpInfo_;
372     }
373 
SetDumpInfo(const MenuDumpInfo & dumpInfo)374     void SetDumpInfo(const MenuDumpInfo& dumpInfo)
375     {
376         dumpInfo_.menuPreviewMode = dumpInfo.menuPreviewMode;
377         dumpInfo_.menuType = dumpInfo.menuType;
378         dumpInfo_.enableArrow = dumpInfo.enableArrow;
379         dumpInfo_.targetNode = dumpInfo.targetNode;
380         dumpInfo_.targetOffset = dumpInfo.targetOffset;
381         dumpInfo_.targetSize = dumpInfo.targetSize;
382         dumpInfo_.menuWindowRect = dumpInfo.menuWindowRect;
383         dumpInfo_.wrapperRect = dumpInfo.wrapperRect;
384         dumpInfo_.previewBeginScale = dumpInfo.previewBeginScale;
385         dumpInfo_.previewEndScale = dumpInfo.previewEndScale;
386         dumpInfo_.top = dumpInfo.top;
387         dumpInfo_.bottom = dumpInfo.bottom;
388         dumpInfo_.globalLocation = dumpInfo.globalLocation;
389         dumpInfo_.originPlacement = dumpInfo.originPlacement;
390         dumpInfo_.defaultPlacement = dumpInfo.defaultPlacement;
391         dumpInfo_.finalPosition = dumpInfo.finalPosition;
392         dumpInfo_.finalPlacement = dumpInfo.finalPlacement;
393     }
394 
GetHasCustomRadius()395     bool GetHasCustomRadius() const
396     {
397         return hasCustomRadius_;
398     }
399 
SetHasCustomRadius(bool hasCustomRadius)400     void SetHasCustomRadius(bool hasCustomRadius)
401     {
402         hasCustomRadius_ = hasCustomRadius;
403     }
404 
GetLastTouchItem()405     RefPtr<FrameNode> GetLastTouchItem()
406     {
407         return lastTouchItem_;
408     }
409 
SetLastTouchItem(const RefPtr<FrameNode> & lastTouchItem)410     void SetLastTouchItem(const RefPtr<FrameNode>& lastTouchItem)
411     {
412         lastTouchItem_ = lastTouchItem;
413     }
414 
415     RefPtr<FrameNode> GetMenuChild(const RefPtr<UINode>& node);
416     RefPtr<FrameNode> GetShowedSubMenu();
417     bool IsSelectOverlayCustomMenu(const RefPtr<FrameNode>& menu) const;
418     bool HasStackSubMenu();
419 
IncreaseEmbeddedSubMenuCount()420     int IncreaseEmbeddedSubMenuCount()
421     {
422         return ++embeddedSubMenuCount_;
423     }
424 
DecreaseEmbeddedSubMenuCount()425     int DecreaseEmbeddedSubMenuCount()
426     {
427         return --embeddedSubMenuCount_;
428     }
429 
430     bool HasEmbeddedSubMenu();
431     void UpdateMenuAnimation(const RefPtr<FrameNode>& host);
432     void ClearAllSubMenu();
433     int embeddedSubMenuCount_ = 0;
434     void StopHoverImageToPreviewAnimation();
435 
SetHoverImageToPreviewScale(float scale)436     void SetHoverImageToPreviewScale(float scale)
437     {
438         hoverImageToPreviewScale_ = scale;
439     }
440 
GetHoverImageToPreviewScale()441     float GetHoverImageToPreviewScale() const
442     {
443         return hoverImageToPreviewScale_;
444     }
445 
SetHoverImageToPreviewRate(float rate)446     void SetHoverImageToPreviewRate(float rate)
447     {
448         hoverImageToPreviewRate_ = rate;
449     }
450 
GetHoverImageToPreviewRate()451     float GetHoverImageToPreviewRate() const
452     {
453         return hoverImageToPreviewRate_;
454     }
455 
SetMenuParam(const MenuParam & param)456     void SetMenuParam(const MenuParam& param)
457     {
458         menuParam_ = param;
459     }
460 
GetMenuParam()461     const MenuParam& GetMenuParam() const
462     {
463         return menuParam_;
464     }
465 
SetIsShowFromUser(bool isShow)466     void SetIsShowFromUser(bool isShow)
467     {
468         isShowFromUser_ = isShow;
469     }
470 
GetIsShowFromUser()471     bool GetIsShowFromUser() const
472     {
473         return isShowFromUser_;
474     }
475 
476 protected:
477     void OnTouchEvent(const TouchEventInfo& info);
478     void CheckAndShowAnimation();
479 
480 private:
AvoidKeyboard()481     bool AvoidKeyboard() const override
482     {
483         return false;
484     }
AvoidBottom()485     bool AvoidBottom() const override
486     {
487         return false;
488     }
489     void OnModifyDone() override;
490     void InitFocusEvent();
491     void OnAttachToFrameNode() override;
492     void RegisterOnTouch();
493     bool OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config) override;
494     // mark self and all children no-draggable
495     void MarkWholeSubTreeNoDraggable(const RefPtr<FrameNode>& frameNode);
496     void MarkAllMenuNoDraggable();
497     void SetHotAreas(const RefPtr<LayoutWrapper>& layoutWrapper);
498     void StartShowAnimation();
499     void HandleInteraction(const TouchEventInfo& info);
500     void ChangeTouchItem(const TouchEventInfo& info, TouchType touchType);
501     void ChangeCurMenuItemBgColor();
502     void ClearLastMenuItem();
503     RectF GetMenuZone(RefPtr<UINode>& innerMenuNode);
504     RefPtr<FrameNode> FindTouchedMenuItem(const RefPtr<UINode>& menuNode, const OffsetF& position);
505 
506     void HideMenu(const RefPtr<FrameNode>& menu);
507     void HideMenu(const RefPtr<MenuPattern>& menuPattern, const RefPtr<FrameNode>& menu, const OffsetF& position);
508     void SetExitAnimation(const RefPtr<FrameNode>& host);
509     void SendToAccessibility(const RefPtr<UINode>& subMenu, bool isShow);
510     std::function<void()> onAppearCallback_ = nullptr;
511     std::function<void()> onDisappearCallback_ = nullptr;
512     std::function<void()> aboutToAppearCallback_ = nullptr;
513     std::function<void()> aboutToDisappearCallback_ = nullptr;
514     std::function<void(const std::string&)> onStateChangeCallback_ = nullptr;
515     RefPtr<TouchEventImpl> onTouch_;
516     RefPtr<FrameNode> lastTouchItem_ = nullptr;
517     RefPtr<FrameNode> currentTouchItem_ = nullptr;
518     // menuId in OverlayManager's map
519     int32_t targetId_ = -1;
520 
521     AnimationOption animationOption_;
522     Placement menuPlacement_ = Placement::NONE;
523     bool isFirstShow_ = true;
524     bool isShowInSubWindow_ = true;
525     bool isShowHoverImage_ = false;
526     bool isStopHoverImageAnimation_ = false;
527     bool isShowHoverImagePreviewStartDrag_ = false;
528     MenuStatus menuStatus_ = MenuStatus::INIT;
529     bool hasTransitionEffect_ = false;
530     bool hasPreviewTransitionEffect_ = false;
531     bool hasFoldModeChangeTransition_ = false;
532     RefPtr<FrameNode> filterColumnNode_;
533     MenuDumpInfo dumpInfo_;
534     bool hasCustomRadius_ = false;
535     float hoverImageToPreviewRate_ = -1.0;
536     float hoverImageToPreviewScale_ = -1.0;
537     MenuParam menuParam_;
538     bool isShowFromUser_ = false;
539     int32_t fingerId_ = -1;
540     ACE_DISALLOW_COPY_AND_MOVE(MenuWrapperPattern);
541 };
542 } // namespace OHOS::Ace::NG
543 
544 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_MENU_MENU_WRAPPER_PATTERN_H
545