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.Diagnostics.CodeAnalysis;
22 using System.Threading.Tasks;
23 using Tizen.NUI.BaseComponents;
24 using Tizen.NUI.Binding;
26 namespace Tizen.NUI.Components
29 /// The Navigator is a class which navigates pages with stack methods such
32 [EditorBrowsable(EditorBrowsableState.Never)]
33 public class Navigator : Control
35 //This will be replaced with view transition class instance.
36 private Animation _curAnimation = null;
38 //This will be replaced with view transition class instance.
39 private Animation _newAnimation = null;
41 //TODO: Needs to consider how to remove disposed window from dictionary.
42 //Two dictionaries are required to remove disposed navigator from dictionary.
43 private static Dictionary<Window, Navigator> windowNavigator = new Dictionary<Window, Navigator>();
44 private static Dictionary<Navigator, Window> navigatorWindow = new Dictionary<Navigator, Window>();
47 /// Creates a new instance of a Navigator.
49 [EditorBrowsable(EditorBrowsableState.Never)]
50 public Navigator() : base()
55 /// List of pages of Navigator.
57 [EditorBrowsable(EditorBrowsableState.Never)]
58 public List<Page> NavigationPages { get; } = new List<Page>();
61 /// Pushes a page to Navigator.
62 /// If the page is already in Navigator, then it is not pushed.
64 /// <param name="page">The page to push to Navigator.</param>
65 /// <exception cref="ArgumentNullException">Thrown when the argument page is null.</exception>
66 [EditorBrowsable(EditorBrowsableState.Never)]
67 public void Push(Page page)
71 throw new ArgumentNullException(nameof(page), "page should not be null.");
74 //Duplicate page is not pushed.
75 if (NavigationPages.Contains(page)) return;
85 NavigationPages.Add(page);
89 page.InvokeAppearing();
90 curTop.InvokeDisappearing();
92 //TODO: The following transition codes will be replaced with view transition.
96 _curAnimation.Clear();
101 _newAnimation.Stop();
102 _newAnimation.Clear();
105 _curAnimation = new Animation(1000);
106 using (var scaleVec = new Vector3(0.0f, 0.0f, 1.0f))
108 _curAnimation.AnimateTo(curTop, "Scale", scaleVec, 0, 1000);
110 _curAnimation.AnimateTo(curTop, "Opacity", 0.0f, 0, 1000);
111 _curAnimation.EndAction = Animation.EndActions.Discard;
112 _curAnimation.Play();
114 using (var scaleVec = new Vector3(0.0f, 0.0f, 1.0f))
116 using (var scaleProp = new Tizen.NUI.PropertyValue(scaleVec))
118 Tizen.NUI.Object.SetProperty(page.SwigCPtr, Page.Property.SCALE, scaleProp);
121 using (var scaleProp = new Tizen.NUI.PropertyValue(0.0f))
123 Tizen.NUI.Object.SetProperty(page.SwigCPtr, Page.Property.OPACITY, scaleProp);
125 _newAnimation = new Animation(1000);
126 using (var scaleVec = new Vector3(1.0f, 1.0f, 1.0f))
128 _newAnimation.AnimateTo(page, "Scale", scaleVec, 0, 1000);
130 _newAnimation.AnimateTo(page, "Opacity", 1.0f, 0, 1000);
131 _newAnimation.Play();
135 /// Pops the top page from Navigator.
137 /// <returns>The popped page.</returns>
138 /// <exception cref="InvalidOperationException">Thrown when there is no page in Navigator.</exception>
139 [EditorBrowsable(EditorBrowsableState.Never)]
142 if (NavigationPages.Count == 0)
144 throw new InvalidOperationException("There is no page in Navigator.");
149 if (NavigationPages.Count == 1)
155 var newTop = NavigationPages[NavigationPages.Count - 2];
158 newTop.InvokeAppearing();
159 curTop.InvokeDisappearing();
161 //TODO: The following transition codes will be replaced with view transition.
164 _curAnimation.Stop();
165 _curAnimation.Clear();
170 _newAnimation.Stop();
171 _newAnimation.Clear();
174 _curAnimation = new Animation(1000);
175 using (var scaleVec = new Vector3(0.0f, 0.0f, 1.0f))
177 _curAnimation.AnimateTo(curTop, "Scale", scaleVec, 0, 1000);
179 _curAnimation.AnimateTo(curTop, "Opacity", 0.0f, 0, 1000);
180 _curAnimation.Play();
181 _curAnimation.Finished += (object sender, EventArgs e) =>
183 //Removes the current top page after transition is finished.
187 using (var scaleVec = new Vector3(0.0f, 0.0f, 1.0f))
189 using (var scaleProp = new Tizen.NUI.PropertyValue(scaleVec))
191 Tizen.NUI.Object.SetProperty(newTop.SwigCPtr, Page.Property.SCALE, scaleProp);
194 using (var opacityProp = new Tizen.NUI.PropertyValue(0.0f))
196 Tizen.NUI.Object.SetProperty(newTop.SwigCPtr, Page.Property.OPACITY, opacityProp);
198 _newAnimation = new Animation(1000);
199 using (var scaleVec = new Vector3(1.0f, 1.0f, 1.0f))
201 _newAnimation.AnimateTo(newTop, "Scale", scaleVec, 0, 1000);
203 _newAnimation.AnimateTo(newTop, "Opacity", 1.0f, 0, 1000);
204 _newAnimation.Play();
210 /// Inserts a page at the specified index of Navigator.
211 /// If the page is already in Navigator, then it is not inserted.
213 /// <param name="index">The index of Navigator where a page will be inserted.</param>
214 /// <param name="page">The page to insert to Navigator.</param>
215 /// <exception cref="ArgumentOutOfRangeException">Thrown when the argument index is less than 0, or greater than the number of pages.</exception>
216 /// <exception cref="ArgumentNullException">Thrown when the argument page is null.</exception>
217 [EditorBrowsable(EditorBrowsableState.Never)]
218 public void Insert(int index, Page page)
220 if ((index < 0) || (index > NavigationPages.Count))
222 throw new ArgumentOutOfRangeException(nameof(index), "index should be greater than or equal to 0, and less than or equal to the number of pages.");
227 throw new ArgumentNullException(nameof(page), "page should not be null.");
230 //Duplicate page is not pushed.
231 if (NavigationPages.Contains(page)) return;
233 NavigationPages.Insert(index, page);
238 /// Inserts a page to Navigator before an existing page.
239 /// If the page is already in Navigator, then it is not inserted.
241 /// <param name="before">The existing page, before which a page will be inserted.</param>
242 /// <param name="page">The page to insert to Navigator.</param>
243 /// <exception cref="ArgumentNullException">Thrown when the argument before is null.</exception>
244 /// <exception cref="ArgumentNullException">Thrown when the argument page is null.</exception>
245 /// <exception cref="ArgumentException">Thrown when the argument before does not exist in Navigator.</exception>
246 [EditorBrowsable(EditorBrowsableState.Never)]
247 public void InsertBefore(Page before, Page page)
251 throw new ArgumentNullException(nameof(before), "before should not be null.");
256 throw new ArgumentNullException(nameof(page), "page should not be null.");
259 //Find the index of before page.
260 int beforeIndex = NavigationPages.FindIndex(x => x == before);
262 //before does not exist in Navigator.
263 if (beforeIndex == -1)
265 throw new ArgumentException("before does not exist in Navigator.", nameof(before));
268 Insert(beforeIndex, page);
272 /// Removes a page from Navigator.
274 /// <param name="page">The page to remove from Navigator.</param>
275 /// <exception cref="ArgumentNullException">Thrown when the argument page is null.</exception>
276 [EditorBrowsable(EditorBrowsableState.Never)]
277 public void Remove(Page page)
281 throw new ArgumentNullException(nameof(page), "page should not be null.");
284 NavigationPages.Remove(page);
289 /// Removes a page at the specified index of Navigator.
291 /// <param name="index">The index of Navigator where a page will be removed.</param>
292 /// <exception cref="ArgumentOutOfRangeException">Thrown when the index is less than 0, or greater than or equal to the number of pages.</exception>
293 [EditorBrowsable(EditorBrowsableState.Never)]
294 public void RemoveAt(int index)
296 if ((index < 0) || (index >= NavigationPages.Count))
298 throw new ArgumentOutOfRangeException(nameof(index), "index should be greater than or equal to 0, and less than the number of pages.");
301 Remove(NavigationPages[index]);
305 /// Returns the page at the top of Navigator.
307 /// <returns>The page at the top of Navigator.</returns>
308 [EditorBrowsable(EditorBrowsableState.Never)]
311 if (NavigationPages.Count == 0) return null;
313 return NavigationPages[NavigationPages.Count - 1];
317 /// Disposes Navigator and all children on it.
319 /// <param name="type">Dispose type.</param>
320 [EditorBrowsable(EditorBrowsableState.Never)]
321 protected override void Dispose(DisposeTypes type)
328 if (type == DisposeTypes.Explicit)
330 foreach (Page page in NavigationPages)
332 Utility.Dispose(page);
334 NavigationPages.Clear();
338 if (navigatorWindow.TryGetValue(this, out window) == true)
340 navigatorWindow.Remove(this);
341 windowNavigator.Remove(window);
349 /// Returns the default navigator of the given window.
351 /// <returns>The default navigator of the given window.</returns>
352 /// <exception cref="ArgumentNullException">Thrown when the argument window is null.</exception>
353 [EditorBrowsable(EditorBrowsableState.Never)]
354 public static Navigator GetDefaultNavigator(Window window)
358 throw new ArgumentNullException(nameof(window), "window should not be null.");
361 if (windowNavigator.ContainsKey(window) == true)
363 return windowNavigator[window];
366 var defaultNavigator = new Navigator();
367 defaultNavigator.WidthResizePolicy = ResizePolicyType.FillToParent;
368 defaultNavigator.HeightResizePolicy = ResizePolicyType.FillToParent;
369 window.Add(defaultNavigator);
370 windowNavigator.Add(window, defaultNavigator);
371 navigatorWindow.Add(defaultNavigator, window);
373 return defaultNavigator;
377 /// Shows a dialog by pushing a page containing dialog to default navigator.
379 /// <param name="content">The content of Dialog.</param>
380 [EditorBrowsable(EditorBrowsableState.Never)]
381 [SuppressMessage("Microsoft.Reliability",
382 "CA2000:DisposeObjectsBeforeLosingScope",
383 Justification = "The pushed views are added to NavigationPages and are disposed in Navigator.Dispose().")]
384 public static void ShowDialog(View content = null)
386 var window = NUIApplication.GetDefaultWindow();
387 var defaultNavigator = window.GetDefaultNavigator();
389 var dialog = new Dialog(content);
390 SetDialogScrim(dialog);
392 var dialogPage = new Page(dialog);
393 defaultNavigator.Push(dialogPage);
397 /// Shows an alert dialog by pushing a page containing the alert dialog
398 /// to default navigator.
400 /// <param name="titleContent">The title content of AlertDialog.</param>
401 /// <param name="content">The content of AlertDialog.</param>
402 /// <param name="actionContent">The action content of AlertDialog.</param>
403 [EditorBrowsable(EditorBrowsableState.Never)]
404 [SuppressMessage("Microsoft.Reliability",
405 "CA2000:DisposeObjectsBeforeLosingScope",
406 Justification = "The pushed views are added to NavigationPages and are disposed in Navigator.Dispose().")]
407 public static void ShowAlertDialog(View titleContent, View content, View actionContent)
409 var window = NUIApplication.GetDefaultWindow();
410 var defaultNavigator = window.GetDefaultNavigator();
412 var dialog = new AlertDialog(titleContent, content, actionContent);
413 SetDialogScrim(dialog);
415 var dialogPage = new Page(dialog);
416 defaultNavigator.Push(dialogPage);
420 /// Shows an alert dialog by pushing a page containing the alert dialog
421 /// to default navigator.
423 /// <param name="title">The title of AlertDialog.</param>
424 /// <param name="message">The message of AlertDialog.</param>
425 /// <param name="positiveButtonText">The positive button text in the action content of AlertDialog.</param>
426 /// <param name="positiveButtonClickedHandler">The clicked callback of the positive button in the action content of AlertDialog.</param>
427 /// <param name="negativeButtonText">The negative button text in the action content of AlertDialog.</param>
428 /// <param name="negativeButtonClickedHandler">The clicked callback of the negative button in the action content of AlertDialog.</param>
429 [EditorBrowsable(EditorBrowsableState.Never)]
430 [SuppressMessage("Microsoft.Reliability",
431 "CA2000:DisposeObjectsBeforeLosingScope",
432 Justification = "The pushed views are added to NavigationPages and are disposed in Navigator.Dispose().")]
433 public static void ShowAlertDialog(string title = null, string message = null, string positiveButtonText = null, EventHandler<ClickedEventArgs> positiveButtonClickedHandler = null, string negativeButtonText = null, EventHandler<ClickedEventArgs> negativeButtonClickedHandler = null)
435 var window = NUIApplication.GetDefaultWindow();
436 var defaultNavigator = window.GetDefaultNavigator();
438 var dialog = new AlertDialog(title, message, positiveButtonText, positiveButtonClickedHandler, negativeButtonText, negativeButtonClickedHandler);
439 SetDialogScrim(dialog);
441 var dialogPage = new Page(dialog);
442 defaultNavigator.Push(dialogPage);
446 private static void SetDialogScrim(Dialog dialog)
453 var window = NUIApplication.GetDefaultWindow();
454 var defaultNavigator = window.GetDefaultNavigator();
455 var defaultScrim = dialog.Scrim;
457 //Copies default scrim's GUI properties.
458 var scrim = new VisualView();
459 scrim.BackgroundColor = defaultScrim.BackgroundColor;
460 scrim.Size = defaultScrim.Size;
461 scrim.TouchEvent += (object source, View.TouchEventArgs e) =>
463 if (e.Touch.GetState(0) == PointStateType.Up)
465 defaultNavigator.Pop();
471 dialog.Scrim = scrim;
474 } //namespace Tizen.NUI