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 #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_MENU_MENU_ITEM_PATTERN_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_MENU_MENU_ITEM_PATTERN_H
18 
19 #include "base/memory/referenced.h"
20 #include "base/utils/noncopyable.h"
21 #include "core/components/slider/render_slider.h"
22 #include "core/components_ng/base/view_abstract.h"
23 #include "core/components_ng/event/long_press_event.h"
24 #include "core/components_ng/pattern/menu/menu_item/menu_item_accessibility_property.h"
25 #include "core/components_ng/pattern/menu/menu_item/menu_item_event_hub.h"
26 #include "core/components_ng/pattern/menu/menu_item/menu_item_layout_algorithm.h"
27 #include "core/components_ng/pattern/menu/menu_item/menu_item_layout_property.h"
28 #include "core/components_ng/pattern/menu/menu_item/menu_item_paint_method.h"
29 #include "core/components_ng/pattern/menu/menu_item/menu_item_paint_property.h"
30 #include "core/components_ng/pattern/menu/menu_pattern.h"
31 #include "core/components_ng/pattern/pattern.h"
32 
33 namespace OHOS::Ace::NG {
34 class ACE_EXPORT MenuItemPattern : public Pattern {
35     DECLARE_ACE_TYPE(MenuItemPattern, Pattern);
36 
37 public:
38     MenuItemPattern() = default;
39     ~MenuItemPattern() override = default;
40 
IsAtomicNode()41     bool IsAtomicNode() const override
42     {
43         return false;
44     }
45 
GetFocusPattern()46     FocusPattern GetFocusPattern() const override
47     {
48         return { FocusType::NODE, true, FocusStyleType::INNER_BORDER };
49     }
50 
CreateEventHub()51     RefPtr<EventHub> CreateEventHub() override
52     {
53         return MakeRefPtr<MenuItemEventHub>();
54     }
55 
CreateLayoutProperty()56     RefPtr<LayoutProperty> CreateLayoutProperty() override
57     {
58         return MakeRefPtr<MenuItemLayoutProperty>();
59     }
60 
CreateAccessibilityProperty()61     RefPtr<AccessibilityProperty> CreateAccessibilityProperty() override
62     {
63         return MakeRefPtr<MenuItemAccessibilityProperty>();
64     }
65 
CreateLayoutAlgorithm()66     RefPtr<LayoutAlgorithm> CreateLayoutAlgorithm() override
67     {
68         return MakeRefPtr<MenuItemLayoutAlgorithm>();
69     }
70 
CreateNodePaintMethod()71     RefPtr<NodePaintMethod> CreateNodePaintMethod() override
72     {
73         return MakeRefPtr<MenuItemPaintMethod>();
74     }
75 
CreatePaintProperty()76     RefPtr<PaintProperty> CreatePaintProperty() override
77     {
78         return MakeRefPtr<MenuItemPaintProperty>();
79     }
80 
81     void MarkIsSelected(bool isSelected);
SetSelected(bool isSelected)82     void SetSelected(bool isSelected)
83     {
84         isSelected_ = isSelected;
85         GetHost()->MarkModifyDone();
86     }
87 
IsSelected()88     bool IsSelected() const
89     {
90         return isSelected_;
91     }
92 
SetSubBuilder(const std::function<void ()> & subBuilderFunc)93     void SetSubBuilder(const std::function<void()>& subBuilderFunc)
94     {
95         subBuilderFunc_ = subBuilderFunc;
96     }
97 
GetSubBuilder()98     std::function<void()>& GetSubBuilder()
99     {
100         return subBuilderFunc_;
101     }
102 
IsSubMenuShowed()103     bool IsSubMenuShowed() const
104     {
105         return isSubMenuShowed_;
106     }
107 
SetIsSubMenuShowed(bool isSubMenuShowed)108     void SetIsSubMenuShowed(bool isSubMenuShowed)
109     {
110         isSubMenuShowed_ = isSubMenuShowed;
111     }
112 
IsSubMenuHovered()113     bool IsSubMenuHovered() const
114     {
115         return isSubMenuHovered_;
116     }
117 
SetIsSubMenuHovered(bool isSubMenuHovered)118     void SetIsSubMenuHovered(bool isSubMenuHovered)
119     {
120         isSubMenuHovered_ = isSubMenuHovered;
121     }
122 
123     void AddHoverRegions(const OffsetF& topLeftPoint, const OffsetF& bottomRightPoint);
124 
125     bool IsInHoverRegions(double x, double y);
126 
ClearHoverRegions()127     void ClearHoverRegions()
128     {
129         hoverRegions_.clear();
130     }
131 
ResetWrapperMouseEvent()132     void ResetWrapperMouseEvent()
133     {
134         wrapperMouseEvent_.Reset();
135     }
136 
SetChange()137     void SetChange()
138     {
139         isSelected_ = !isSelected_;
140     }
141 
IsChange()142     bool IsChange() const
143     {
144         return isChanged_;
145     }
146 
147     void CloseMenu();
148 
GetContentNode()149     RefPtr<FrameNode> GetContentNode()
150     {
151         return content_;
152     }
153 
GetLabelNode()154     RefPtr<FrameNode> GetLabelNode()
155     {
156         return label_;
157     }
158 
159     void PlayBgColorAnimation(bool isHoverChange = true);
SetBgBlendColor(const Color & color)160     void SetBgBlendColor(const Color& color)
161     {
162         bgBlendColor_ = color;
163     }
GetBgBlendColor()164     Color GetBgBlendColor() const
165     {
166         return bgBlendColor_;
167     }
168     bool IsDisabled();
169 
170     RefPtr<FrameNode> GetMenu(bool needTopMenu = false);
171     RefPtr<MenuPattern> GetMenuPattern(bool needTopMenu = false);
172     void UpdateTextNodes();
173 
174     void OnAttachToFrameNode() override;
175     void OnModifyDone() override;
176     void OnMountToParentDone() override;
177 
HasSelectIcon()178     bool HasSelectIcon() const
179     {
180         return selectIcon_ != nullptr;
181     }
HasStartIcon()182     bool HasStartIcon() const
183     {
184         return startIcon_ != nullptr;
185     }
186 
SetClickMenuItemId(int32_t id)187     void SetClickMenuItemId(int32_t id)
188     {
189         clickMenuItemId_ = id;
190     }
191 
GetClickMenuItemId()192     int32_t GetClickMenuItemId() const
193     {
194         return clickMenuItemId_;
195     }
196 
SetOnClickAIMenuItem(std::function<void ()> onClickAIMenuItem)197     void SetOnClickAIMenuItem(std::function<void()> onClickAIMenuItem)
198     {
199         onClickAIMenuItem_ = onClickAIMenuItem;
200     }
201 
202     void OnVisibleChange(bool isVisible) override;
203     void InitLongPressEvent();
204     void UpdateNeedDivider(bool need);
SetIndex(int32_t index)205     void SetIndex(int32_t index)
206     {
207         index_ = index;
208     }
209     float GetDividerStroke();
210 
GetExpandingMode()211     SubMenuExpandingMode GetExpandingMode()
212     {
213         return expandingMode_;
214     }
215     bool IsSubMenu();
216     bool IsEmbedded();
SetIsStackSubmenuHeader()217     void SetIsStackSubmenuHeader()
218     {
219         isStackSubmenuHeader_ = true;
220     }
IsStackSubmenuHeader()221     bool IsStackSubmenuHeader()
222     {
223         return isStackSubmenuHeader_;
224     }
225     RefPtr<FrameNode> FindTouchedEmbeddedMenuItem(const OffsetF& position);
226     void OnHover(bool isHover);
227     void NotifyPressStatus(bool isPress);
228 
229 protected:
230     void RegisterOnKeyEvent();
231     void RegisterOnTouch();
232     void OnAfterModifyDone() override;
233     RefPtr<FrameNode> GetMenuWrapper();
234 
235 private:
236 friend class ServiceCollaborationMenuAceHelper;
237     // register menu item's callback
238     void RegisterOnClick();
239     void RegisterOnHover();
240     virtual void OnTouch(const TouchEventInfo& info);
241     virtual bool OnKeyEvent(const KeyEvent& event);
IsCustomMenuItem()242     virtual bool IsCustomMenuItem()
243     {
244         return false;
245     }
246     void OnClick();
247 
248     void RegisterWrapperMouseEvent();
249 
250     void AddSelectIcon(RefPtr<FrameNode>& row);
251     void UpdateIcon(RefPtr<FrameNode>& row, bool isStart);
252     void AddExpandIcon(RefPtr<FrameNode>& row);
253     void AddClickableArea();
254     void UpdateText(RefPtr<FrameNode>& row, RefPtr<MenuLayoutProperty>& menuProperty, bool isLabel);
255     void UpdateTextOverflow(RefPtr<TextLayoutProperty>& textProperty, RefPtr<SelectTheme>& theme);
256     void UpdateFont(RefPtr<MenuLayoutProperty>& menuProperty, RefPtr<SelectTheme>& theme, bool isLabel);
257     void UpdateMaxLinesFromTheme(RefPtr<TextLayoutProperty>& textProperty);
258     void AddStackSubMenuHeader(RefPtr<FrameNode>& menuNode);
259     RefPtr<FrameNode> GetClickableArea();
260     void UpdateDisabledStyle();
261 
262     void ShowSubMenu();
263     void UpdateSubmenuExpandingMode(RefPtr<UINode>& customNode);
264     void ShowSubMenuHelper(const RefPtr<FrameNode>& subMenu);
265     void HideSubMenu();
266     void OnExpandChanged(const RefPtr<FrameNode>& expandableNode);
267     void HideEmbeddedExpandMenu(const RefPtr<FrameNode>& expandableNode);
268     void ShowEmbeddedExpandMenu(const RefPtr<FrameNode>& expandableNode);
269 
270     OffsetF GetSubMenuPosition(const RefPtr<FrameNode>& targetNode);
271 
272     void AddSelfHoverRegion(const RefPtr<FrameNode>& targetNode);
273     void SetAccessibilityAction();
274     bool IsSelectOverlayMenu();
275     void RecordChangeEvent() const;
276     void ParseMenuRadius(MenuParam& param);
277     void ModifyDivider();
278 
279     void InitFocusEvent();
280     void HandleFocusEvent();
281     void HandleBlurEvent();
282 
283     void UpdateSymbolNode(RefPtr<FrameNode>& row, RefPtr<FrameNode>& selectIcon);
284     void UpdateImageNode(RefPtr<FrameNode>& row, RefPtr<FrameNode>& selectIcon);
285     void UpdateSymbolIcon(RefPtr<FrameNode>& row, RefPtr<FrameNode>& iconNode, ImageSourceInfo& iconSrc,
286         std::function<void(WeakPtr<NG::FrameNode>)>& symbol, bool isStart);
287     void UpdateImageIcon(RefPtr<FrameNode>& row, RefPtr<FrameNode>& iconNode, ImageSourceInfo& iconSrc,
288         std::function<void(WeakPtr<NG::FrameNode>)>& symbol, bool isStart);
289     bool UseDefaultThemeIcon(const ImageSourceInfo& imageSourceInfo);
290 
291     std::list<TouchRegion> hoverRegions_;
292 
293     RefPtr<InputEvent> wrapperMouseEvent_;
294 
295     bool isSelected_ = false;
296     bool isSubMenuShowed_ = false;
297     bool isSubMenuHovered_ = false;
298 
299     bool isChanged_ = false;
300     bool isHovered_ = false;
301     bool isExpanded_ = false;
302     int32_t clickMenuItemId_ = -1;
303     std::function<void()> onClickAIMenuItem_ = nullptr;
304     int32_t index_ = 0;
305 
306     std::function<void()> subBuilderFunc_ = nullptr;
307 
308     int32_t subMenuId_ = -1;
309     RefPtr<FrameNode> subMenu_;
310     RefPtr<FrameNode> content_ = nullptr;
311     RefPtr<FrameNode> label_ = nullptr;
312     RefPtr<FrameNode> startIcon_ = nullptr;
313     RefPtr<FrameNode> endIcon_ = nullptr;
314     RefPtr<FrameNode> selectIcon_ = nullptr;
315 
316     RefPtr<FrameNode> embeddedMenu_ = nullptr;
317     RefPtr<FrameNode> clickableArea_ = nullptr;
318     RefPtr<LongPressEvent> longPressEvent_;
319     RefPtr<TouchEventImpl> onTouchEvent_;
320     RefPtr<InputEvent> onHoverEvent_;
321     RefPtr<ClickEvent> onClickEvent_;
322     RefPtr<FrameNode> expandIcon_ = nullptr;
323     std::vector<RefPtr<FrameNode>> expandableItems_;
324     bool onTouchEventSet_ = false;
325     bool onHoverEventSet_ = false;
326     bool onKeyEventSet_ = false;
327     bool onClickEventSet_ = false;
328     SubMenuExpandingMode expandingMode_ = SubMenuExpandingMode::SIDE;
329     bool isStackSubmenuHeader_ = false;
330     bool expandingModeSet_ = false;
331 
332     Color bgBlendColor_ = Color::TRANSPARENT;
333 
334     ACE_DISALLOW_COPY_AND_MOVE(MenuItemPattern);
335 };
336 
337 class CustomMenuItemPattern : public MenuItemPattern {
338     DECLARE_ACE_TYPE(CustomMenuItemPattern, MenuItemPattern);
339 
340 public:
CreateLayoutAlgorithm()341     RefPtr<LayoutAlgorithm> CreateLayoutAlgorithm() override
342     {
343         return MakeRefPtr<BoxLayoutAlgorithm>();
344     }
345     void OnAttachToFrameNode() override;
346 
347 private:
348     void OnTouch(const TouchEventInfo& info) override;
349     void HandleOnChange();
350     bool OnKeyEvent(const KeyEvent& event) override;
IsCustomMenuItem()351     bool IsCustomMenuItem() override
352     {
353         return true;
354     }
355     std::unique_ptr<Offset> lastTouchOffset_;
356 };
357 } // namespace OHOS::Ace::NG
358 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_MENU_MENU_ITEM_PATTERN_H
359