1 /*
2  * Copyright (c) 2022-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_DIALOG_DIALOG_PATTERN_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_DIALOG_DIALOG_PATTERN_H
18 
19 #include <cstdint>
20 #include <functional>
21 
22 #include "base/geometry/ng/offset_t.h"
23 #include "base/geometry/ng/size_t.h"
24 #include "base/memory/ace_type.h"
25 #include "base/memory/referenced.h"
26 #include "core/common/autofill/auto_fill_trigger_state_holder.h"
27 #include "core/components/dialog/dialog_properties.h"
28 #include "core/components/dialog/dialog_theme.h"
29 #include "core/components_ng/manager/focus/focus_view.h"
30 #include "core/components_ng/pattern/dialog/dialog_event_hub.h"
31 #include "core/components_ng/pattern/dialog/dialog_accessibility_property.h"
32 #include "core/components_ng/pattern/dialog/dialog_layout_algorithm.h"
33 #include "core/components_ng/pattern/dialog/dialog_layout_property.h"
34 #include "core/components_ng/pattern/overlay/popup_base_pattern.h"
35 
36 namespace OHOS::Ace::NG {
37 class InspectorFilter;
38 
39 enum class DialogContentNode {
40     TITLE = 0,
41     SUBTITLE,
42     MESSAGE,
43     SHEET,
44     BORDERWIDTH,
45 };
46 enum class DialogDismissReason {
47     DIALOG_PRESS_BACK = 0,
48     DIALOG_TOUCH_OUTSIDE,
49     DIALOG_CLOSE_BUTTON,
50 };
51 class DialogPattern : public PopupBasePattern, public FocusView, public AutoFillTriggerStateHolder {
52     DECLARE_ACE_TYPE(DialogPattern, PopupBasePattern, FocusView, AutoFillTriggerStateHolder);
53 
54 public:
DialogPattern(const RefPtr<DialogTheme> & dialogTheme,const RefPtr<UINode> & customNode)55     DialogPattern(const RefPtr<DialogTheme>& dialogTheme, const RefPtr<UINode>& customNode)
56         : dialogTheme_(dialogTheme), customNode_(customNode)
57     {}
58     ~DialogPattern() override = default;
59 
IsAtomicNode()60     bool IsAtomicNode() const override
61     {
62         return false;
63     }
64 
SetOnWillDismiss(const std::function<void (const int32_t & info)> & onWillDismiss)65     void SetOnWillDismiss(const std::function<void(const int32_t& info)>& onWillDismiss)
66     {
67         onWillDismiss_ = onWillDismiss;
68     }
69 
ShouldDismiss()70     bool ShouldDismiss() const
71     {
72         if (onWillDismiss_) {
73             return true;
74         }
75         return false;
76     }
77 
SetOnWillDismissByNDK(const std::function<bool (const int32_t & info)> & onWillDismissByNDK)78     void SetOnWillDismissByNDK(const std::function<bool(const int32_t& info)>& onWillDismissByNDK)
79     {
80         onWillDismissByNDK_ = onWillDismissByNDK;
81     }
82 
CallDismissInNDK(int reason)83     bool CallDismissInNDK(int reason)
84     {
85         if (onWillDismissByNDK_ && onWillDismissByNDK_(reason)) {
86             return true;
87         }
88         return false;
89     }
90 
CallOnWillDismiss(const int32_t reason)91     void CallOnWillDismiss(const int32_t reason)
92     {
93         if (onWillDismiss_) {
94             onWillDismiss_(reason);
95         }
96     }
97 
CreateLayoutProperty()98     RefPtr<LayoutProperty> CreateLayoutProperty() override
99     {
100         return AceType::MakeRefPtr<DialogLayoutProperty>();
101     }
102 
CreateLayoutAlgorithm()103     RefPtr<LayoutAlgorithm> CreateLayoutAlgorithm() override
104     {
105         return AceType::MakeRefPtr<DialogLayoutAlgorithm>();
106     }
107 
CreateEventHub()108     RefPtr<EventHub> CreateEventHub() override
109     {
110         return MakeRefPtr<DialogEventHub>();
111     }
112 
CreateAccessibilityProperty()113     RefPtr<AccessibilityProperty> CreateAccessibilityProperty() override
114     {
115         return MakeRefPtr<DialogAccessibilityProperty>();
116     }
117 
GetFocusPattern()118     FocusPattern GetFocusPattern() const override
119     {
120         return { FocusType::SCOPE, true };
121     }
122 
GetRouteOfFirstScope()123     std::list<int32_t> GetRouteOfFirstScope() override
124     {
125         if (dialogProperties_.type == DialogType::ALERT_DIALOG || dialogProperties_.type == DialogType::ACTION_SHEET) {
126             return { 0 };
127         }
128         return { 0, 0 };
129     }
130 
131     void BuildChild(const DialogProperties& dialogProperties);
132 
133     void ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const override;
134 
GetTitle()135     const std::string& GetTitle()
136     {
137         return title_;
138     }
139 
GetSubtitle()140     const std::string& GetSubtitle()
141     {
142         return subtitle_;
143     }
144 
GetMessage()145     const std::string& GetMessage()
146     {
147         return message_;
148     }
149 
GetCustomNode()150     RefPtr<UINode> GetCustomNode()
151     {
152         return customNode_.Upgrade();
153     }
154 
SetOpenAnimation(const std::optional<AnimationOption> & openAnimation)155     void SetOpenAnimation(const std::optional<AnimationOption>& openAnimation)
156     {
157         openAnimation_ = openAnimation;
158     }
GetOpenAnimation()159     std::optional<AnimationOption> GetOpenAnimation() const
160     {
161         return openAnimation_;
162     }
163 
SetCloseAnimation(const std::optional<AnimationOption> & closeAnimation)164     void SetCloseAnimation(const std::optional<AnimationOption>& closeAnimation)
165     {
166         closeAnimation_ = closeAnimation;
167     }
GetCloseAnimation()168     std::optional<AnimationOption> GetCloseAnimation() const
169     {
170         return closeAnimation_;
171     }
172 
SetDialogProperties(const DialogProperties & param)173     void SetDialogProperties(const DialogProperties& param)
174     {
175         dialogProperties_ = param;
176         InitHostWindowRect();
177     }
178 
GetDialogProperties()179     const DialogProperties& GetDialogProperties() const
180     {
181         return dialogProperties_;
182     }
183 
184     void OnColorConfigurationUpdate() override;
185 
186     void OnLanguageConfigurationUpdate() override;
187 
188     void DumpInfo() override;
189     void DumpSimplifyInfo(std::unique_ptr<JsonValue>& json) override;
AvoidBottom()190     bool AvoidBottom() const override
191     {
192         return false;
193     }
194 
RegisterDialogDidAppearCallback(std::function<void ()> && onDidAppear)195     void RegisterDialogDidAppearCallback(std::function<void()>&& onDidAppear)
196     {
197         onDidAppearCallback_ = std::move(onDidAppear);
198     }
199 
RegisterDialogDidDisappearCallback(std::function<void ()> && onDidDisappear)200     void RegisterDialogDidDisappearCallback(std::function<void()>&& onDidDisappear)
201     {
202         onDidDisappearCallback_ = std::move(onDidDisappear);
203     }
204 
RegisterDialogWillAppearCallback(std::function<void ()> && onWillAppear)205     void RegisterDialogWillAppearCallback(std::function<void()>&& onWillAppear)
206     {
207         onWillAppearCallback_ = std::move(onWillAppear);
208     }
209 
RegisterDialogWillDisappearCallback(std::function<void ()> && onWillDisappear)210     void RegisterDialogWillDisappearCallback(std::function<void()>&& onWillDisappear)
211     {
212         onWillDisappearCallback_ = std::move(onWillDisappear);
213     }
214 
CallDialogDidAppearCallback()215     void CallDialogDidAppearCallback()
216     {
217         if (onDidAppearCallback_) {
218             onDidAppearCallback_();
219         }
220     }
221 
CallDialogDidDisappearCallback()222     void CallDialogDidDisappearCallback()
223     {
224         if (onDidDisappearCallback_) {
225             onDidDisappearCallback_();
226         }
227     }
228 
CallDialogWillAppearCallback()229     void CallDialogWillAppearCallback()
230     {
231         if (onWillAppearCallback_) {
232             onWillAppearCallback_();
233         }
234     }
235 
CallDialogWillDisappearCallback()236     void CallDialogWillDisappearCallback()
237     {
238         if (onWillDisappearCallback_) {
239             onWillDisappearCallback_();
240         }
241     }
242 
IsUIExtensionSubWindow()243     bool IsUIExtensionSubWindow() const
244     {
245         return isUIExtensionSubWindow_;
246     }
247 
GetHostWindowRect()248     RectF GetHostWindowRect() const
249     {
250         return hostWindowRect_;
251     }
252 
UpdateFoldDisplayModeChangedCallbackId(std::optional<int32_t> id)253     void UpdateFoldDisplayModeChangedCallbackId(std::optional<int32_t> id)
254     {
255         foldDisplayModeChangedCallbackId_ = id;
256     }
257 
HasFoldDisplayModeChangedCallbackId()258     bool HasFoldDisplayModeChangedCallbackId()
259     {
260         return foldDisplayModeChangedCallbackId_.has_value();
261     }
262 
UpdateHoverModeChangedCallbackId(std::optional<int32_t> id)263     void UpdateHoverModeChangedCallbackId(std::optional<int32_t> id)
264     {
265         hoverModeChangedCallbackId_ = id;
266     }
267 
HasHoverModeChangedCallbackId()268     bool HasHoverModeChangedCallbackId()
269     {
270         return hoverModeChangedCallbackId_.has_value();
271     }
272 
GetIsSuitableForAging()273     bool GetIsSuitableForAging()
274     {
275         return isSuitableForElderly_;
276     }
277 
GetFontScaleForElderly()278     float GetFontScaleForElderly()
279     {
280         return fontScaleForElderly_;
281     }
282 
SetIsPickerDialog(bool value)283     void SetIsPickerDialog(bool value)
284     {
285         isPickerDialog_ = value;
286     }
287 
GetIsPickerDialog()288     bool GetIsPickerDialog()
289     {
290         return isPickerDialog_;
291     }
292 
293     void UpdateDeviceOrientation(const DeviceOrientation& deviceOrientation);
294     void InitHostWindowRect();
295     void UpdateFontScale();
296     PipelineContext* GetDialogContext();
297 
GetIsSuitOldMeasure()298     bool GetIsSuitOldMeasure()
299     {
300         return isSuitOldMeasure_;
301     }
302 
SetIsScrollHeightNegative(bool isScrollHeightNegative)303     void SetIsScrollHeightNegative(bool isScrollHeightNegative)
304     {
305         isScrollHeightNegative_ = isScrollHeightNegative;
306     }
307 
TriggerAutoSaveWhenInvisible()308     bool TriggerAutoSaveWhenInvisible() override
309     {
310         return true;
311     }
312 
313     bool IsShowInFreeMultiWindow();
314 
315 private:
AvoidKeyboard()316     bool AvoidKeyboard() const override
317     {
318         return false;
319     }
320     void OnModifyDone() override;
321 
322     void OnAttachToFrameNode() override;
323     void OnDetachFromFrameNode(FrameNode* frameNode) override;
324     void RegisterHoverModeChangeCallback();
325     void OnWindowSizeChanged(int32_t width, int32_t height, WindowSizeChangeReason type) override;
326     void InitClickEvent(const RefPtr<GestureEventHub>& gestureHub);
327     void HandleClick(const GestureEvent& info);
328     void RegisterOnKeyEvent(const RefPtr<FocusHub>& focusHub);
329     bool OnKeyEvent(const KeyEvent& event);
330     void InitFocusEvent(const RefPtr<FocusHub>& focusHub);
331     void HandleBlurEvent();
332     void HandleFocusEvent();
333 
334     void PopDialog(int32_t buttonIdx);
335 
336     // set render context properties of content frame
337     void UpdateContentRenderContext(const RefPtr<FrameNode>& contentNode, const DialogProperties& props);
338     void BuildCustomChild(const DialogProperties& props, const RefPtr<UINode>& customNode);
339     RefPtr<FrameNode> BuildMainTitle(const DialogProperties& dialogProperties);
340     RefPtr<FrameNode> BuildSubTitle(const DialogProperties& dialogProperties);
341     void ParseButtonFontColorAndBgColor(
342         const ButtonInfo& params, std::string& textColor, std::optional<Color>& bgColor);
343     void SetButtonEnabled(const RefPtr<FrameNode>& buttonNode, bool enabled);
344     // update wrapperNode background style
345     void UpdateWrapperBackgroundStyle(const RefPtr<FrameNode>& host, const RefPtr<DialogTheme>& dialogTheme);
346     RefPtr<FrameNode> BuildTitle(const DialogProperties& dialogProperties);
347     RefPtr<FrameNode> BuildContent(const DialogProperties& dialogProperties);
348     RefPtr<FrameNode> CreateDialogScroll(const DialogProperties& dialogProps);
349 
350     void UpdateDialogButtonProperty(RefPtr<FrameNode>& buttonNode, int32_t index, bool isVertical, int32_t length);
351     RefPtr<FrameNode> BuildButtons(const std::vector<ButtonInfo>& buttons, const DialogButtonDirection& direction);
352     void AddButtonAndDivider(
353         const std::vector<ButtonInfo>& buttons, const RefPtr<NG::FrameNode>& container, bool isVertical);
354     RefPtr<FrameNode> CreateDivider(
355         const Dimension& dividerLength, const Dimension& dividerWidth, const Color& color, const Dimension& space);
356     RefPtr<FrameNode> CreateButton(
357         const ButtonInfo& params, int32_t index, bool isCancel = false, bool isVertical = false, int32_t length = 0);
358     RefPtr<FrameNode> CreateButtonText(const std::string& text, const std::string& colorStr);
359     // to close dialog when button is clicked
360     void BindCloseCallBack(const RefPtr<GestureEventHub>& hub, int32_t buttonIdx);
361     // build ActionSheet items
362     RefPtr<FrameNode> BuildSheet(const std::vector<ActionSheetInfo>& sheets);
363     RefPtr<FrameNode> BuildSheetItem(const ActionSheetInfo& item);
364     RefPtr<FrameNode> BuildSheetInfoTitle(const std::string& title);
365     RefPtr<FrameNode> BuildSheetInfoIcon(const std::string& icon);
366     // build actionMenu
367     RefPtr<FrameNode> BuildMenu(const std::vector<ButtonInfo>& buttons, bool hasTitle);
368     void RecordEvent(int32_t btnIndex) const;
369     void ParseBorderRadius(BorderRadiusProperty& raidus);
370     void UpdateSheetIconAndText();
371     void UpdateButtonsProperty();
372     void UpdateNodeContent(const RefPtr<FrameNode>& node, std::string& text);
373     void UpdateAlignmentAndOffset();
374     void DumpBoolProperty();
375     void DumpObjectProperty();
376     void DumpSimplifyBoolProperty(std::unique_ptr<JsonValue>& json);
377     void DumpSimplifyObjectProperty(std::unique_ptr<JsonValue>& json);
378     void DumpSimplifyBorderProperty(std::unique_ptr<JsonValue>& json);
379     void DumpSimplifySizeProperty(std::unique_ptr<JsonValue>& json);
380     void UpdatePropertyForElderly(const std::vector<ButtonInfo>& buttons);
381     bool NeedsButtonDirectionChange(const std::vector<ButtonInfo>& buttons);
382     void OnFontConfigurationUpdate() override;
383     void UpdateTextFontScale();
384     void UpdateTitleTextFontScale();
385     void CheckScrollHeightIsNegative(const RefPtr<UINode>& contentColumn, const DialogProperties& props);
386     RefPtr<DialogTheme> dialogTheme_;
387     WeakPtr<UINode> customNode_;
388     RefPtr<ClickEvent> onClick_;
389 
390     std::optional<AnimationOption> openAnimation_;
391     std::optional<AnimationOption> closeAnimation_;
392     std::optional<int32_t> foldDisplayModeChangedCallbackId_;
393     std::optional<int32_t> hoverModeChangedCallbackId_;
394     bool isFoldStatusChanged_ = false;
395 
396     // XTS inspector values
397     std::string message_;
398     std::string title_;
399     std::string subtitle_;
400     std::function<void(const int32_t& info)> onWillDismiss_;
401     std::function<bool(const int32_t& info)> onWillDismissByNDK_;
402 
403     DialogProperties dialogProperties_;
404     WeakPtr<FrameNode> menuNode_;
405     bool isFirstDefaultFocus_ = true;
406     RefPtr<FrameNode> buttonContainer_;
407     RefPtr<FrameNode> contentColumn_;
408     RefPtr<RenderContext> contentRenderContext_;
409     bool isSuitableForElderly_ = false;
410     bool isPickerDialog_ = false;
411     bool notAdapationAging_ = false;
412     bool isSuitOldMeasure_ = false;
413     bool isScrollHeightNegative_ = false;
414     float fontScaleForElderly_ = 1.0f;
415     DeviceOrientation deviceOrientation_ = DeviceOrientation::PORTRAIT;
416     RefPtr<FrameNode> titleContainer_;
417 
418     ACE_DISALLOW_COPY_AND_MOVE(DialogPattern);
419 
420     std::function<void()> onDidAppearCallback_ = nullptr;
421     std::function<void()> onDidDisappearCallback_ = nullptr;
422     std::function<void()> onWillAppearCallback_ = nullptr;
423     std::function<void()> onWillDisappearCallback_ = nullptr;
424     std::unordered_map<DialogContentNode, RefPtr<FrameNode>> contentNodeMap_;
425     bool isUIExtensionSubWindow_ = false;
426     RectF hostWindowRect_;
427 };
428 } // namespace OHOS::Ace::NG
429 
430 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_DIALOG_DIALOG_PATTERN_H
431