2 * Copyright(c) 2020 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 using System.Collections.Generic;
20 using System.ComponentModel;
21 using System.Threading.Tasks;
22 using Tizen.NUI.BaseComponents;
23 using Tizen.NUI.Binding;
25 namespace Tizen.NUI.Components
28 /// The Navigator is a class which navigates pages with stack methods such
31 [EditorBrowsable(EditorBrowsableState.Never)]
32 public class Navigator : Control
34 //This will be replaced with view transition class instance.
35 private Animation _curAnimation = null;
37 //This will be replaced with view transition class instance.
38 private Animation _newAnimation = null;
40 //TODO: Needs to consider how to remove disposed window from dictionary.
41 //Two dictionaries are required to remove disposed navigator from dictionary.
42 private static Dictionary<Window, Navigator> windowNavigator = new Dictionary<Window, Navigator>();
43 private static Dictionary<Navigator, Window> navigatorWindow = new Dictionary<Navigator, Window>();
46 /// Creates a new instance of a Navigator.
48 [EditorBrowsable(EditorBrowsableState.Never)]
49 public Navigator() : base()
54 /// List of pages of Navigator.
56 [EditorBrowsable(EditorBrowsableState.Never)]
57 public List<Page> NavigationPages { get; } = new List<Page>();
60 /// Pushes a page to Navigator.
61 /// If the page is already in Navigator, then it is not pushed.
63 /// <param name="page">The page to push to Navigator.</param>
64 /// <exception cref="ArgumentNullException">Thrown when the argument page is null.</exception>
65 [EditorBrowsable(EditorBrowsableState.Never)]
66 public void Push(Page page)
70 throw new ArgumentNullException(nameof(page), "page should not be null.");
73 //Duplicate page is not pushed.
74 if (NavigationPages.Contains(page)) return;
84 NavigationPages.Add(page);
88 page.InvokeAppearing();
89 curTop.InvokeDisappearing();
91 //TODO: The following transition codes will be replaced with view transition.
95 _curAnimation.Clear();
100 _newAnimation.Stop();
101 _newAnimation.Clear();
104 _curAnimation = new Animation(1000);
105 using (var scaleVec = new Vector3(0.0f, 0.0f, 1.0f))
107 _curAnimation.AnimateTo(curTop, "Scale", scaleVec, 0, 1000);
109 _curAnimation.AnimateTo(curTop, "Opacity", 0.0f, 0, 1000);
110 _curAnimation.EndAction = Animation.EndActions.Discard;
111 _curAnimation.Play();
113 using (var scaleVec = new Vector3(0.0f, 0.0f, 1.0f))
115 using (var scaleProp = new Tizen.NUI.PropertyValue(scaleVec))
117 Tizen.NUI.Object.SetProperty(page.SwigCPtr, Page.Property.SCALE, scaleProp);
120 using (var scaleProp = new Tizen.NUI.PropertyValue(0.0f))
122 Tizen.NUI.Object.SetProperty(page.SwigCPtr, Page.Property.OPACITY, scaleProp);
124 _newAnimation = new Animation(1000);
125 using (var scaleVec = new Vector3(1.0f, 1.0f, 1.0f))
127 _newAnimation.AnimateTo(page, "Scale", scaleVec, 0, 1000);
129 _newAnimation.AnimateTo(page, "Opacity", 1.0f, 0, 1000);
130 _newAnimation.Play();
134 /// Pops the top page from Navigator.
136 /// <returns>The popped page.</returns>
137 /// <exception cref="InvalidOperationException">Thrown when there is no page in Navigator.</exception>
138 [EditorBrowsable(EditorBrowsableState.Never)]
141 if (NavigationPages.Count == 0)
143 throw new InvalidOperationException("There is no page in Navigator.");
148 if (NavigationPages.Count == 1)
154 var newTop = NavigationPages[NavigationPages.Count - 2];
157 newTop.InvokeAppearing();
158 curTop.InvokeDisappearing();
160 //TODO: The following transition codes will be replaced with view transition.
163 _curAnimation.Stop();
164 _curAnimation.Clear();
169 _newAnimation.Stop();
170 _newAnimation.Clear();
173 _curAnimation = new Animation(1000);
174 using (var scaleVec = new Vector3(0.0f, 0.0f, 1.0f))
176 _curAnimation.AnimateTo(curTop, "Scale", scaleVec, 0, 1000);
178 _curAnimation.AnimateTo(curTop, "Opacity", 0.0f, 0, 1000);
179 _curAnimation.Play();
180 _curAnimation.Finished += (object sender, EventArgs e) =>
182 //Removes the current top page after transition is finished.
186 using (var scaleVec = new Vector3(0.0f, 0.0f, 1.0f))
188 using (var scaleProp = new Tizen.NUI.PropertyValue(scaleVec))
190 Tizen.NUI.Object.SetProperty(newTop.SwigCPtr, Page.Property.SCALE, scaleProp);
193 using (var opacityProp = new Tizen.NUI.PropertyValue(0.0f))
195 Tizen.NUI.Object.SetProperty(newTop.SwigCPtr, Page.Property.OPACITY, opacityProp);
197 _newAnimation = new Animation(1000);
198 using (var scaleVec = new Vector3(1.0f, 1.0f, 1.0f))
200 _newAnimation.AnimateTo(newTop, "Scale", scaleVec, 0, 1000);
202 _newAnimation.AnimateTo(newTop, "Opacity", 1.0f, 0, 1000);
203 _newAnimation.Play();
209 /// Inserts a page at the specified index of Navigator.
210 /// If the page is already in Navigator, then it is not inserted.
212 /// <param name="index">The index of Navigator where a page will be inserted.</param>
213 /// <param name="page">The page to insert to Navigator.</param>
214 /// <exception cref="ArgumentOutOfRangeException">Thrown when the argument index is less than 0, or greater than the number of pages.</exception>
215 /// <exception cref="ArgumentNullException">Thrown when the argument page is null.</exception>
216 [EditorBrowsable(EditorBrowsableState.Never)]
217 public void Insert(int index, Page page)
219 if ((index < 0) || (index > NavigationPages.Count))
221 throw new ArgumentOutOfRangeException(nameof(index), "index should be greater than or equal to 0, and less than or equal to the number of pages.");
226 throw new ArgumentNullException(nameof(page), "page should not be null.");
229 //Duplicate page is not pushed.
230 if (NavigationPages.Contains(page)) return;
232 NavigationPages.Insert(index, page);
237 /// Inserts a page to Navigator before an existing page.
238 /// If the page is already in Navigator, then it is not inserted.
240 /// <param name="before">The existing page, before which a page will be inserted.</param>
241 /// <param name="page">The page to insert to Navigator.</param>
242 /// <exception cref="ArgumentNullException">Thrown when the argument before is null.</exception>
243 /// <exception cref="ArgumentNullException">Thrown when the argument page is null.</exception>
244 /// <exception cref="ArgumentException">Thrown when the argument before does not exist in Navigator.</exception>
245 [EditorBrowsable(EditorBrowsableState.Never)]
246 public void InsertBefore(Page before, Page page)
250 throw new ArgumentNullException(nameof(before), "before should not be null.");
255 throw new ArgumentNullException(nameof(page), "page should not be null.");
258 //Find the index of before page.
259 int beforeIndex = NavigationPages.FindIndex(x => x == before);
261 //before does not exist in Navigator.
262 if (beforeIndex == -1)
264 throw new ArgumentException("before does not exist in Navigator.", nameof(before));
267 Insert(beforeIndex, page);
271 /// Removes a page from Navigator.
273 /// <param name="page">The page to remove from Navigator.</param>
274 /// <exception cref="ArgumentNullException">Thrown when the argument page is null.</exception>
275 [EditorBrowsable(EditorBrowsableState.Never)]
276 public void Remove(Page page)
280 throw new ArgumentNullException(nameof(page), "page should not be null.");
283 NavigationPages.Remove(page);
288 /// Removes a page at the specified index of Navigator.
290 /// <param name="index">The index of Navigator where a page will be removed.</param>
291 /// <exception cref="ArgumentOutOfRangeException">Thrown when the index is less than 0, or greater than or equal to the number of pages.</exception>
292 [EditorBrowsable(EditorBrowsableState.Never)]
293 public void RemoveAt(int index)
295 if ((index < 0) || (index >= NavigationPages.Count))
297 throw new ArgumentOutOfRangeException(nameof(index), "index should be greater than or equal to 0, and less than the number of pages.");
300 Remove(NavigationPages[index]);
304 /// Returns the page at the top of Navigator.
306 /// <returns>The page at the top of Navigator.</returns>
307 [EditorBrowsable(EditorBrowsableState.Never)]
310 if (NavigationPages.Count == 0) return null;
312 return NavigationPages[NavigationPages.Count - 1];
316 /// Disposes Navigator and all children on it.
318 /// <param name="type">Dispose type.</param>
319 [EditorBrowsable(EditorBrowsableState.Never)]
320 protected override void Dispose(DisposeTypes type)
327 if (type == DisposeTypes.Explicit)
329 foreach (Page page in NavigationPages)
331 Utility.Dispose(page);
333 NavigationPages.Clear();
337 if (navigatorWindow.TryGetValue(this, out window) == true)
339 navigatorWindow.Remove(this);
340 windowNavigator.Remove(window);
348 /// Returns the default navigator of the given window.
350 /// <returns>The default navigator of the given window.</returns>
351 /// <exception cref="ArgumentNullException">Thrown when the argument window is null.</exception>
352 [EditorBrowsable(EditorBrowsableState.Never)]
353 public static Navigator GetDefaultNavigator(Window window)
357 throw new ArgumentNullException(nameof(window), "window should not be null.");
360 if (windowNavigator.ContainsKey(window) == true)
362 return windowNavigator[window];
365 var defaultNavigator = new Navigator();
366 defaultNavigator.WidthResizePolicy = ResizePolicyType.FillToParent;
367 defaultNavigator.HeightResizePolicy = ResizePolicyType.FillToParent;
368 window.Add(defaultNavigator);
369 windowNavigator.Add(window, defaultNavigator);
370 navigatorWindow.Add(defaultNavigator, window);
372 return defaultNavigator;
376 /// Shows a dialog by pushing a page containing dialog to default navigator.
378 /// <param name="content">The content of Dialog.</param>
379 [EditorBrowsable(EditorBrowsableState.Never)]
380 public static void ShowDialog(View content = null)
382 var window = NUIApplication.GetDefaultWindow();
383 var defaultNavigator = window.GetDefaultNavigator();
385 var dialog = new Dialog(content);
386 SetDialogScrim(dialog);
388 var dialogPage = new Page(dialog);
389 defaultNavigator.Push(dialogPage);
393 /// Shows an alert dialog by pushing a page containing the alert dialog
394 /// to default navigator.
396 /// <param name="titleContent">The title content of AlertDialog.</param>
397 /// <param name="content">The content of AlertDialog.</param>
398 /// <param name="actionContent">The action content of AlertDialog.</param>
399 [EditorBrowsable(EditorBrowsableState.Never)]
400 public static void ShowAlertDialog(View titleContent, View content, View actionContent)
402 var window = NUIApplication.GetDefaultWindow();
403 var defaultNavigator = window.GetDefaultNavigator();
405 var dialog = new AlertDialog(titleContent, content, actionContent);
406 SetDialogScrim(dialog);
408 var dialogPage = new Page(dialog);
409 defaultNavigator.Push(dialogPage);
413 /// Shows an alert dialog by pushing a page containing the alert dialog
414 /// to default navigator.
416 /// <param name="title">The title of AlertDialog.</param>
417 /// <param name="message">The message of AlertDialog.</param>
418 /// <param name="positiveButtonText">The positive button text in the action content of AlertDialog.</param>
419 /// <param name="positiveButtonClickedHandler">The clicked callback of the positive button in the action content of AlertDialog.</param>
420 /// <param name="negativeButtonText">The negative button text in the action content of AlertDialog.</param>
421 /// <param name="negativeButtonClickedHandler">The clicked callback of the negative button in the action content of AlertDialog.</param>
422 [EditorBrowsable(EditorBrowsableState.Never)]
423 public static void ShowAlertDialog(string title = null, string message = null, string positiveButtonText = null, EventHandler<ClickedEventArgs> positiveButtonClickedHandler = null, string negativeButtonText = null, EventHandler<ClickedEventArgs> negativeButtonClickedHandler = null)
425 var window = NUIApplication.GetDefaultWindow();
426 var defaultNavigator = window.GetDefaultNavigator();
428 var dialog = new AlertDialog(title, message, positiveButtonText, positiveButtonClickedHandler, negativeButtonText, negativeButtonClickedHandler);
429 SetDialogScrim(dialog);
431 var dialogPage = new Page(dialog);
432 defaultNavigator.Push(dialogPage);
436 private static void SetDialogScrim(Dialog dialog)
443 var window = NUIApplication.GetDefaultWindow();
444 var defaultNavigator = window.GetDefaultNavigator();
445 var defaultScrim = dialog.Scrim;
447 //Copies default scrim's GUI properties.
448 var scrim = new VisualView();
449 scrim.BackgroundColor = defaultScrim.BackgroundColor;
450 scrim.Size = defaultScrim.Size;
451 scrim.TouchEvent += (object source, View.TouchEventArgs e) =>
453 if (e.Touch.GetState(0) == PointStateType.Up)
455 defaultNavigator.Pop();
461 dialog.Scrim = scrim;
464 } //namespace Tizen.NUI