[NUI] Modify the default action of back navigation
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI.Components / Controls / Navigation / Page.cs
1 /*
2  * Copyright(c) 2021 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17 using System;
18 using System.ComponentModel;
19 using Tizen.NUI.Binding;
20
21 namespace Tizen.NUI.Components
22 {
23     /// <summary>
24     /// PageAppearingEventArgs is a class to record <see cref="Page.Appearing"/> event arguments which will be sent to user.
25     /// </summary>
26     /// <since_tizen> 9 </since_tizen>
27     public class PageAppearingEventArgs : EventArgs
28     {
29     }
30
31     /// <summary>
32     /// PageDisappearingEventArgs is a class to record <see cref="Page.Disappearing"/> event arguments which will be sent to user.
33     /// </summary>
34     /// <since_tizen> 9 </since_tizen>
35     public class PageDisappearingEventArgs : EventArgs
36     {
37     }
38
39     /// <summary>
40     /// PageAppearedEventArgs is a class to record <see cref="Page.Appeared"/> event arguments which will be sent to user.
41     /// </summary>
42     /// <since_tizen> 9 </since_tizen>
43     public class PageAppearedEventArgs : EventArgs
44     {
45     }
46
47     /// <summary>
48     /// PageDisappearedEventArgs is a class to record <see cref="Page.Disappeared"/> event arguments which will be sent to user.
49     /// </summary>
50     /// <since_tizen> 9 </since_tizen>
51     public class PageDisappearedEventArgs : EventArgs
52     {
53     }
54
55     /// <summary>
56     /// The Page class is a class which is an element of navigation.
57     /// </summary>
58     /// <since_tizen> 9 </since_tizen>
59     public abstract class Page : Control
60     {
61         /// <summary>
62         /// AppearingTransitionProperty
63         /// </summary>
64         [EditorBrowsable(EditorBrowsableState.Never)]
65         public static readonly BindableProperty AppearingTransitionProperty = BindableProperty.Create(nameof(AppearingTransition), typeof(TransitionBase), typeof(Page), null, propertyChanged: (bindable, oldValue, newValue) =>
66         {
67             var instance = (Page)bindable;
68             if (newValue != null)
69             {
70                 instance.InternalAppearingTransition = newValue as TransitionBase;
71             }
72         },
73         defaultValueCreator: (bindable) =>
74         {
75             var instance = (Page)bindable;
76             return instance.InternalAppearingTransition;
77         });
78
79         /// <summary>
80         /// DisappearingTransitionProperty
81         /// </summary>
82         [EditorBrowsable(EditorBrowsableState.Never)]
83         public static readonly BindableProperty DisappearingTransitionProperty = BindableProperty.Create(nameof(DisappearingTransition), typeof(TransitionBase), typeof(Page), null, propertyChanged: (bindable, oldValue, newValue) =>
84         {
85             var instance = (Page)bindable;
86             if (newValue != null)
87             {
88                 instance.InternalDisappearingTransition = newValue as TransitionBase;
89             }
90         },
91         defaultValueCreator: (bindable) =>
92         {
93             var instance = (Page)bindable;
94             return instance.InternalDisappearingTransition;
95         });
96
97         /// <summary>
98         /// EnableBackNavigationProperty
99         /// </summary>
100         [EditorBrowsable(EditorBrowsableState.Never)]
101         public static readonly BindableProperty EnableBackNavigationProperty = BindableProperty.Create(nameof(EnableBackNavigation), typeof(bool), typeof(Page), default(bool), propertyChanged: (bindable, oldValue, newValue) =>
102         {
103             var instance = (Page)bindable;
104             if (newValue != null)
105             {
106                 instance.InternalEnableBackNavigation = (bool)newValue;
107             }
108         },
109         defaultValueCreator: (bindable) =>
110         {
111             var instance = (Page)bindable;
112             return instance.InternalEnableBackNavigation;
113         });
114
115         /// <inheritdoc/>
116         [EditorBrowsable(EditorBrowsableState.Never)]
117         protected internal BaseComponents.View LastFocusedView = null;
118
119         private Navigator navigator = null;
120
121         // Default transition is Fade.
122         private TransitionBase appearingTransition = null;
123
124         private TransitionBase disappearingTransition = null;
125
126         private bool enableBackNavigation = true;
127
128         /// <summary>
129         /// Creates a new instance of a Page.
130         /// </summary>
131         /// <since_tizen> 9 </since_tizen>
132         public Page() : base()
133         {
134         }
135
136         /// <summary>
137         /// Creates a new instance of a Page with style.
138         /// </summary>
139         /// <param name="style">A style applied to the newly created Page.</param>
140         [EditorBrowsable(EditorBrowsableState.Never)]
141         public Page(ControlStyle style) : base(style)
142         {
143         }
144
145         /// <summary>
146         /// Navigator which has pushed the Page into its stack.
147         /// If this Page has not been pushed into any Navigator, then Navigator is null.
148         /// </summary>
149         /// <since_tizen> 9 </since_tizen>
150         public Navigator Navigator
151         {
152             get
153             {
154                 return navigator;
155             }
156             internal set
157             {
158                 if (navigator == value)
159                 {
160                     return;
161                 }
162
163                 navigator = value;
164             }
165         }
166
167         /// <summary>
168         /// Transition properties for the transition of Views in this page during this page is pushed to Navigator.
169         /// </summary>
170         [EditorBrowsable(EditorBrowsableState.Never)]
171         public TransitionBase AppearingTransition
172         {
173             get
174             {
175                 return GetValue(AppearingTransitionProperty) as TransitionBase;
176             }
177             set
178             {
179                 SetValue(AppearingTransitionProperty, value);
180                 NotifyPropertyChanged();
181             }
182         }
183         private TransitionBase InternalAppearingTransition
184         {
185             set
186             {
187                 appearingTransition = value;
188             }
189             get
190             {
191                 return appearingTransition;
192             }
193         }
194
195         /// <summary>
196         /// Transition properties for the transition of Views in this page during this page is popped from Navigator.
197         /// </summary>
198         [EditorBrowsable(EditorBrowsableState.Never)]
199         public TransitionBase DisappearingTransition
200         {
201             get
202             {
203                 return GetValue(DisappearingTransitionProperty) as TransitionBase;
204             }
205             set
206             {
207                 SetValue(DisappearingTransitionProperty, value);
208                 NotifyPropertyChanged();
209             }
210         }
211         private TransitionBase InternalDisappearingTransition
212         {
213             set
214             {
215                 disappearingTransition = value;
216             }
217             get
218             {
219                 return disappearingTransition;
220             }
221         }
222
223         /// <summary>
224         /// Appearing event is invoked right before the page appears.
225         /// </summary>
226         /// <since_tizen> 9 </since_tizen>
227         public event EventHandler<PageAppearingEventArgs> Appearing;
228
229         /// <summary>
230         /// Disappearing event is invoked right before the page disappears.
231         /// </summary>
232         /// <since_tizen> 9 </since_tizen>
233         public event EventHandler<PageDisappearingEventArgs> Disappearing;
234
235         /// <summary>
236         /// Appeared event is invoked right after the page appears.
237         /// </summary>
238         /// <since_tizen> 9 </since_tizen>
239         public event EventHandler<PageAppearedEventArgs> Appeared;
240
241         /// <summary>
242         /// Disappeared event is invoked right after the page disappears.
243         /// </summary>
244         /// <since_tizen> 9 </since_tizen>
245         public event EventHandler<PageDisappearedEventArgs> Disappeared;
246
247         /// <summary>
248         /// Gets or sets if this page proceeds back navigation when back button or back key is pressed and released.
249         /// Back navigation pops the peek page if Navigator has more than one page.
250         /// If Navigator has only one page, then the current program is exited.
251         /// </summary>
252         [EditorBrowsable(EditorBrowsableState.Never)]
253         public bool EnableBackNavigation
254         {
255             get
256             {
257                 return (bool)GetValue(EnableBackNavigationProperty);
258             }
259             set
260             {
261                 SetValue(EnableBackNavigationProperty, value);
262                 NotifyPropertyChanged();
263             }
264         }
265
266         private bool InternalEnableBackNavigation
267         {
268             set
269             {
270                 enableBackNavigation = value;
271             }
272             get
273             {
274                 return enableBackNavigation;
275             }
276         }
277
278         internal void InvokeAppearing()
279         {
280             Appearing?.Invoke(this, new PageAppearingEventArgs());
281         }
282
283         internal void InvokeDisappearing()
284         {
285             Disappearing?.Invoke(this, new PageDisappearingEventArgs());
286         }
287
288         internal void InvokeAppeared()
289         {
290             Appeared?.Invoke(this, new PageAppearedEventArgs());
291         }
292
293         internal void InvokeDisappeared()
294         {
295             Disappeared?.Invoke(this, new PageDisappearedEventArgs());
296         }
297
298         /// <summary>
299         /// works only when DefaultAlgorithm is enabled.
300         /// to save the currently focused View when disappeared.
301         /// </summary>
302         [EditorBrowsable(EditorBrowsableState.Never)]
303         protected internal virtual void SaveKeyFocus()
304         {
305             if (FocusManager.Instance.IsDefaultAlgorithmEnabled())
306             {
307                 if (this is DialogPage)
308                 {
309                     FocusManager.Instance.ResetFocusFinderRootView();
310                 }
311
312                 var currentFocusedView = FocusManager.Instance.GetCurrentFocusView();
313                 if (currentFocusedView)
314                 {
315                     var findChild = FindDescendantByID(currentFocusedView.ID);
316                     if (findChild)
317                     {
318                         LastFocusedView = findChild;
319                         return;
320                     }
321                 }
322                 LastFocusedView = null;
323             }
324         }
325
326         /// <summary>
327         /// works only when DefaultAlgorithm is enabled.
328         /// to set key focused View when showing.
329         /// </summary>
330         [EditorBrowsable(EditorBrowsableState.Never)]
331         protected internal virtual void RestoreKeyFocus()
332         {
333             if (FocusManager.Instance.IsDefaultAlgorithmEnabled())
334             {
335                 if (LastFocusedView)
336                 {
337                     FocusManager.Instance.SetCurrentFocusView(LastFocusedView);
338                 }
339                 else
340                 {
341                     var temp = new Tizen.NUI.BaseComponents.View()
342                     {
343                         Size = new Size(0.1f, 0.1f, 0.0f),
344                         Position = new Position(0, 0, 0),
345                         Focusable = true,
346                     };
347                     this.Add(temp);
348                     temp.LowerToBottom();
349                     FocusManager.Instance.SetCurrentFocusView(temp);
350                     var focused = FocusManager.Instance.GetNearestFocusableActor(this, temp, Tizen.NUI.BaseComponents.View.FocusDirection.Down);
351                     if (focused)
352                     {
353                         FocusManager.Instance.SetCurrentFocusView(focused);
354                     }
355                     else
356                     {
357                         FocusManager.Instance.ClearFocus();
358                     }
359                     temp.Unparent();
360                     temp.Dispose();
361                 }
362
363                 if (this is DialogPage)
364                 {
365                     FocusManager.Instance.SetFocusFinderRootView(this);
366                 }
367             }
368         }
369
370         /// <summary>
371         /// Called when the back navigation is started.
372         /// Back navigation pops the peek page if Navigator has more than one page.
373         /// If Navigator has only one page, then the current program is exited.
374         /// </summary>
375         /// <param name="eventArgs">The back navigation information.</param>
376         [EditorBrowsable(EditorBrowsableState.Never)]
377         protected virtual void OnBackNavigation(PageBackNavigationEventArgs eventArgs)
378         {
379             if (Navigator.PageCount > 1)
380             {
381                 Navigator.Pop();
382             }
383             else
384             {
385                 NUIApplication.Current?.Exit();
386             }
387         }
388
389         /// <summary>
390         /// Called when the back navigation is required outside Navigator.
391         /// </summary>
392         internal void NavigateBack()
393         {
394             OnBackNavigation(new PageBackNavigationEventArgs());
395         }
396     }
397
398     /// <summary>
399     /// PageBackNavigationEventArgs is a class to record back navigation event arguments which will sent to user.
400     /// </summary>
401     [EditorBrowsable(EditorBrowsableState.Never)]
402     public class PageBackNavigationEventArgs : EventArgs
403     {
404     }
405 }