2 * Copyright(c) 2021 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 Tizen.NUI.BaseComponents;
24 namespace Tizen.NUI.Components
27 /// The Navigator is a class which navigates pages with stack methods such
30 [EditorBrowsable(EditorBrowsableState.Never)]
31 public class Navigator : Control
33 //This will be replaced with view transition class instance.
34 private Animation curAnimation = null;
36 //This will be replaced with view transition class instance.
37 private Animation newAnimation = null;
39 //TODO: Needs to consider how to remove disposed window from dictionary.
40 //Two dictionaries are required to remove disposed navigator from dictionary.
41 private static Dictionary<Window, Navigator> windowNavigator = new Dictionary<Window, Navigator>();
42 private static Dictionary<Navigator, Window> navigatorWindow = new Dictionary<Navigator, Window>();
45 /// Creates a new instance of a Navigator.
47 [EditorBrowsable(EditorBrowsableState.Never)]
48 public Navigator() : base()
50 Layout = new AbsoluteLayout();
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.
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;
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);
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.
164 curAnimation.Clear();
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);
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);
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 [SuppressMessage("Microsoft.Reliability",
381 "CA2000:DisposeObjectsBeforeLosingScope",
382 Justification = "The pushed views are added to NavigationPages and are disposed in Navigator.Dispose().")]
383 public static void ShowDialog(View content = null)
385 var window = NUIApplication.GetDefaultWindow();
386 var defaultNavigator = window.GetDefaultNavigator();
388 var dialog = new Dialog(content);
389 SetDialogScrim(dialog);
391 var dialogPage = new Page(dialog);
392 defaultNavigator.Push(dialogPage);
396 /// Shows an alert dialog by pushing a page containing the alert dialog
397 /// to default navigator.
399 /// <param name="titleContent">The title content of AlertDialog.</param>
400 /// <param name="content">The content of AlertDialog.</param>
401 /// <param name="actionContent">The action content of AlertDialog.</param>
402 [EditorBrowsable(EditorBrowsableState.Never)]
403 [SuppressMessage("Microsoft.Reliability",
404 "CA2000:DisposeObjectsBeforeLosingScope",
405 Justification = "The pushed views are added to NavigationPages and are disposed in Navigator.Dispose().")]
406 public static void ShowAlertDialog(View titleContent, View content, View actionContent)
408 var window = NUIApplication.GetDefaultWindow();
409 var defaultNavigator = window.GetDefaultNavigator();
411 var dialog = new AlertDialog(titleContent, content, actionContent);
412 SetDialogScrim(dialog);
414 var dialogPage = new Page(dialog);
415 defaultNavigator.Push(dialogPage);
419 /// Shows an alert dialog by pushing a page containing the alert dialog
420 /// to default navigator.
422 /// <param name="title">The title of AlertDialog.</param>
423 /// <param name="message">The message of AlertDialog.</param>
424 /// <param name="positiveButtonText">The positive button text in the action content of AlertDialog.</param>
425 /// <param name="positiveButtonClickedHandler">The clicked callback of the positive button in the action content of AlertDialog.</param>
426 /// <param name="negativeButtonText">The negative button text in the action content of AlertDialog.</param>
427 /// <param name="negativeButtonClickedHandler">The clicked callback of the negative button in the action content of AlertDialog.</param>
428 [EditorBrowsable(EditorBrowsableState.Never)]
429 [SuppressMessage("Microsoft.Reliability",
430 "CA2000:DisposeObjectsBeforeLosingScope",
431 Justification = "The pushed views are added to NavigationPages and are disposed in Navigator.Dispose().")]
432 public static void ShowAlertDialog(string title = null, string message = null, string positiveButtonText = null, EventHandler<ClickedEventArgs> positiveButtonClickedHandler = null, string negativeButtonText = null, EventHandler<ClickedEventArgs> negativeButtonClickedHandler = null)
434 var window = NUIApplication.GetDefaultWindow();
435 var defaultNavigator = window.GetDefaultNavigator();
437 var dialog = new AlertDialog(title, message, positiveButtonText, positiveButtonClickedHandler, negativeButtonText, negativeButtonClickedHandler);
438 SetDialogScrim(dialog);
440 var dialogPage = new Page(dialog);
441 defaultNavigator.Push(dialogPage);
445 private static void SetDialogScrim(Dialog dialog)
452 var window = NUIApplication.GetDefaultWindow();
453 var defaultNavigator = window.GetDefaultNavigator();
454 var defaultScrim = dialog.Scrim;
456 //Copies default scrim's GUI properties.
457 var scrim = new VisualView();
458 scrim.BackgroundColor = defaultScrim.BackgroundColor;
459 scrim.Size = defaultScrim.Size;
460 scrim.TouchEvent += (object source, View.TouchEventArgs e) =>
462 if (e.Touch.GetState(0) == PointStateType.Up)
464 defaultNavigator.Pop();
470 dialog.Scrim = scrim;
473 } //namespace Tizen.NUI