2 * Copyright (c) 2018 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.
18 using System.Collections.Generic;
19 using System.Collections.ObjectModel;
20 using System.Collections.Specialized;
21 using System.ComponentModel;
23 using System.Threading;
24 using System.Threading.Tasks;
25 using Tizen.NUI.Binding.Internals;
26 using Tizen.NUI.Binding;
31 /// A BaseHandle that occupies the entire screen.
33 // [RenderWith(typeof(_PageRenderer))]
34 [EditorBrowsable(EditorBrowsableState.Never)]
35 public class Page : /*VisualElement*/BaseHandle, ILayout, IPageController, IElementConfiguration<Page>, IPaddingElement
40 /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
41 [EditorBrowsable(EditorBrowsableState.Never)]
42 public const string BusySetSignalName = "NUI.BusySet";
47 /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
48 [EditorBrowsable(EditorBrowsableState.Never)]
49 public const string AlertSignalName = "NUI.SendAlert";
54 /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
55 [EditorBrowsable(EditorBrowsableState.Never)]
56 public const string ActionSheetSignalName = "NUI.ShowActionSheet";
58 internal static readonly BindableProperty IgnoresContainerAreaProperty = BindableProperty.Create("IgnoresContainerArea", typeof(bool), typeof(Page), false);
61 /// Identifies the BackgroundImage property.
63 internal static readonly BindableProperty BackgroundImageProperty = BindableProperty.Create("BackgroundImage", typeof(string), typeof(Page), default(string));
66 /// Identifies the IsBusy property.
68 internal static readonly BindableProperty IsBusyProperty = BindableProperty.Create("IsBusy", typeof(bool), typeof(Page), false, propertyChanged: (bo, o, n) => ((Page)bo).OnPageBusyChanged());
71 /// Identifies the Padding property.
73 internal static readonly BindableProperty PaddingProperty = PaddingElement.PaddingProperty;
76 /// Identifies the Title property.
78 internal static readonly BindableProperty TitleProperty = BindableProperty.Create("Title", typeof(string), typeof(Page), null);
81 /// Identifies the Icon property.
83 internal static readonly BindableProperty IconProperty = BindableProperty.Create("Icon", typeof(FileImageSource), typeof(Page), default(FileImageSource));
85 readonly Lazy<PlatformConfigurationRegistry<Page>> _platformConfigurationRegistry;
87 Rectangle _containerArea;
89 bool _containerAreaSet;
93 ReadOnlyCollection<Element> _logicalChildren;
96 /// Creates a new Page element with default values.
98 /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
99 [EditorBrowsable(EditorBrowsableState.Never)]
102 var toolbarItems = new ObservableCollection<ToolbarItem>();
103 toolbarItems.CollectionChanged += OnToolbarItemsCollectionChanged;
104 // ToolbarItems = toolbarItems;
105 InternalChildren.CollectionChanged += InternalChildrenOnCollectionChanged;
106 _platformConfigurationRegistry = new Lazy<PlatformConfigurationRegistry<Page>>(() => new PlatformConfigurationRegistry<Page>(this));
110 /// Identifies the image used as a background for the Page.
112 /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
113 [EditorBrowsable(EditorBrowsableState.Never)]
114 public string BackgroundImage
116 get { return (string)GetValue(BackgroundImageProperty); }
117 set { SetValue(BackgroundImageProperty, value); }
120 internal FileImageSource Icon
122 get { return (FileImageSource)GetValue(IconProperty); }
123 set { SetValue(IconProperty, value); }
127 /// Marks the Page as busy. This will cause the platform specific global activity indicator to show a busy state.
129 /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
130 [EditorBrowsable(EditorBrowsableState.Never)]
133 get { return (bool)GetValue(IsBusyProperty); }
134 set { SetValue(IsBusyProperty, value); }
138 /// The space between the content of the Page and it's border.
140 internal Thickness Padding
142 get { return (Thickness)GetValue(PaddingElement.PaddingProperty); }
143 set { SetValue(PaddingElement.PaddingProperty, value); }
146 Thickness IPaddingElement.PaddingDefaultValueCreator()
148 return default(Thickness);
151 void IPaddingElement.OnPaddingPropertyChanged(Thickness oldValue, Thickness newValue)
153 UpdateChildrenLayout();
157 /// The Page's title.
159 /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
160 [EditorBrowsable(EditorBrowsableState.Never)]
163 get { return (string)GetValue(TitleProperty); }
164 set { SetValue(TitleProperty, value); }
167 internal IList<ToolbarItem> ToolbarItems { get;/* internal set;*/ }
170 /// For internal use.
172 [EditorBrowsable(EditorBrowsableState.Never)]
173 public Rectangle ContainerArea
175 get { return _containerArea; }
178 if (_containerArea == value)
180 _containerAreaSet = true;
181 _containerArea = value;
187 /// For internal use.
189 [EditorBrowsable(EditorBrowsableState.Never)]
190 public bool IgnoresContainerArea
192 get { return (bool)GetValue(IgnoresContainerAreaProperty); }
193 set { SetValue(IgnoresContainerAreaProperty, value); }
197 /// For internal use.
199 [EditorBrowsable(EditorBrowsableState.Never)]
200 public ObservableCollection<Element> InternalChildren { get; } = new ObservableCollection<Element>();
202 internal override ReadOnlyCollection<Element> LogicalChildrenInternal =>
203 _logicalChildren ?? (_logicalChildren = new ReadOnlyCollection<Element>(InternalChildren));
206 /// Raised when the layout of the Page has changed.
208 /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
209 [EditorBrowsable(EditorBrowsableState.Never)]
210 public event EventHandler LayoutChanged;
213 /// ndicates that the Page is about to appear.
215 /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
216 [EditorBrowsable(EditorBrowsableState.Never)]
217 public event EventHandler Appearing;
220 /// Indicates that the Page is about to cease displaying.
222 /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
223 [EditorBrowsable(EditorBrowsableState.Never)]
224 public event EventHandler Disappearing;
227 /// Displays a native platform action sheet, allowing the application user to choose from several buttons.
229 /// <param name="title">Title of the displayed action sheet. Must not be null.</param>
230 /// <param name="cancel">Text to be displayed in the 'Cancel' button. Can be null to hide the cancel action.</param>
231 /// <param name="destruction">Text to be displayed in the 'Destruct' button. Can be null to hide the destructive option.</param>
232 /// <param name="buttons">Text labels for additional buttons. Must not be null.</param>
233 /// <returns>An awaitable Task that displays an action sheet and returns the Text of the button pressed by the user.</returns>
234 /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
235 [EditorBrowsable(EditorBrowsableState.Never)]
236 public Task<string> DisplayActionSheet(string title, string cancel, string destruction, params string[] buttons)
238 var args = new ActionSheetArguments(title, cancel, destruction, buttons);
239 MessagingCenter.Send(this, ActionSheetSignalName, args);
240 return args.Result.Task;
244 /// Presents an alert dialog to the application user with a single cancel button.
246 /// <param name="title">The title of the alert dialog.</param>
247 /// <param name="message">The body text of the alert dialog.</param>
248 /// <param name="cancel">Text to be displayed on the 'Cancel' button.</param>
249 /// <returns></returns>
250 /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
251 [EditorBrowsable(EditorBrowsableState.Never)]
252 public Task DisplayAlert(string title, string message, string cancel)
254 return DisplayAlert(title, message, null, cancel);
258 /// resents an alert dialog to the application user with an accept and a cancel button.
260 /// <param name="title">The title of the alert dialog.</param>
261 /// <param name="message">The body text of the alert dialog.</param>
262 /// <param name="accept">Text to be displayed on the 'Accept' button.</param>
263 /// <param name="cancel">Text to be displayed on the 'Cancel' button.</param>
264 /// <returns></returns>
265 /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
266 [EditorBrowsable(EditorBrowsableState.Never)]
267 public Task<bool> DisplayAlert(string title, string message, string accept, string cancel)
269 if (string.IsNullOrEmpty(cancel))
270 throw new ArgumentNullException("cancel");
272 var args = new AlertArguments(title, message, accept, cancel);
273 MessagingCenter.Send(this, AlertSignalName, args);
274 return args.Result.Task;
278 /// Forces the Page to perform a layout pass.
280 /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
281 [EditorBrowsable(EditorBrowsableState.Never)]
282 public void ForceLayout()
287 /// Calls OnBackButtonPressed().
289 /// <returns></returns>
290 /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
291 [EditorBrowsable(EditorBrowsableState.Never)]
292 public bool SendBackButtonPressed()
294 return OnBackButtonPressed();
298 /// Lays out children Elements into the specified area.
300 /// <param name="x">Left-hand side of layout area.</param>
301 /// <param name="y">Top of layout area.</param>
302 /// <param name="width">Width of layout area.</param>
303 /// <param name="height">Height of layout area.</param>
304 /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
305 [EditorBrowsable(EditorBrowsableState.Never)]
306 protected virtual void LayoutChildren(double x, double y, double width, double height)
308 var area = new Rectangle((int)x, (int)y, (int)width, (int)height);
309 Rectangle originalArea = area;
310 if (_containerAreaSet)
312 area = ContainerArea;
313 area.X += (int)Padding.Left;
314 area.Y += (int)Padding.Right;
315 area.Width -= (int)Padding.HorizontalThickness;
316 area.Height -= (int)Padding.VerticalThickness;
317 area.Width = Math.Max(0, area.Width);
318 area.Height = Math.Max(0, area.Height);
323 /// When overridden, allows application developers to customize behavior immediately prior to the Page becoming visible.
325 /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
326 [EditorBrowsable(EditorBrowsableState.Never)]
327 protected virtual void OnAppearing()
332 /// Application developers can override this method to provide behavior when the back button is pressed.
334 /// <returns>true if consumed</returns>
335 /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
336 [EditorBrowsable(EditorBrowsableState.Never)]
337 protected virtual bool OnBackButtonPressed()
339 var application = RealParent as Application;
341 var canceled = false;
342 EventHandler handler = (sender, args) => { canceled = true; };
343 Navigation.PopModalAsync().ContinueWith(t => { throw t.Exception; }, CancellationToken.None, TaskContinuationOptions.OnlyOnFaulted, TaskScheduler.FromCurrentSynchronizationContext());
349 /// Invoked whenever the binding context of the Page changes. Override this method to add class handling for this event.
351 /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
352 [EditorBrowsable(EditorBrowsableState.Never)]
353 protected override void OnBindingContextChanged()
355 base.OnBindingContextChanged();
359 /// Indicates that the preferred size of a child Element has changed.
361 /// <param name="sender">The object that raised the event.</param>
362 /// <param name="e">The event arguments.</param>
363 /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
364 [EditorBrowsable(EditorBrowsableState.Never)]
365 protected virtual void OnChildMeasureInvalidated(object sender, EventArgs e)
367 InvalidationTrigger trigger = (e as InvalidationEventArgs)?.Trigger ?? InvalidationTrigger.Undefined;
368 OnChildMeasureInvalidated((BaseHandle)sender, trigger);
372 /// When overridden, allows the application developer to customize behavior as the Page disappears.
374 /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
375 [EditorBrowsable(EditorBrowsableState.Never)]
376 protected virtual void OnDisappearing()
381 /// Called when the Page's Parent property has changed.
383 /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
384 [EditorBrowsable(EditorBrowsableState.Never)]
385 protected override void OnParentSet()
391 /// Requests that the children Elements of the Page update their layouts.
393 /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API.
394 [EditorBrowsable(EditorBrowsableState.Never)]
395 protected void UpdateChildrenLayout()
397 if (!ShouldLayoutChildren())
400 double x = Padding.Left;
401 double y = Padding.Top;
403 for (var i = 0; i < LogicalChildren.Count; i++)
405 LayoutChanged?.Invoke(this, EventArgs.Empty);
409 internal virtual void OnChildMeasureInvalidated(BaseHandle child, InvalidationTrigger trigger)
411 var container = this as IPageContainer<Page>;
412 if (container != null)
414 Page page = container.CurrentPage;
422 for (var i = 0; i < LogicalChildren.Count; i++)
424 var v = LogicalChildren[i] as BaseHandle;
434 /// For intarnal use.
436 [EditorBrowsable(EditorBrowsableState.Never)]
437 public void SendAppearing()
445 MessagingCenter.Send(this, BusySetSignalName, true);
448 Appearing?.Invoke(this, EventArgs.Empty);
450 var pageContainer = this as IPageContainer<Page>;
451 pageContainer?.CurrentPage?.SendAppearing();
455 /// For intarnal use.
457 [EditorBrowsable(EditorBrowsableState.Never)]
458 public void SendDisappearing()
463 _hasAppeared = false;
466 MessagingCenter.Send(this, BusySetSignalName, false);
468 var pageContainer = this as IPageContainer<Page>;
469 pageContainer?.CurrentPage?.SendDisappearing();
472 Disappearing?.Invoke(this, EventArgs.Empty);
475 Application FindApplication(Element element)
480 return (element.Parent is Application app) ? app : FindApplication(element.Parent);
483 void InternalChildrenOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
485 if (e.OldItems != null)
487 foreach (BaseHandle item in e.OldItems.OfType<BaseHandle>())
489 OnInternalRemoved(item);
493 if (e.NewItems != null)
495 foreach (BaseHandle item in e.NewItems.OfType<BaseHandle>())
497 OnInternalAdded(item);
502 private void OnInternalAdded(BaseHandle view)
507 private void OnInternalRemoved(BaseHandle view)
509 OnChildRemoved(view);
512 void OnPageBusyChanged()
517 MessagingCenter.Send(this, BusySetSignalName, IsBusy);
520 void OnToolbarItemsCollectionChanged(object sender, NotifyCollectionChangedEventArgs args)
522 if (args.Action != NotifyCollectionChangedAction.Add)
524 foreach (IElement item in args.NewItems)
528 bool ShouldLayoutChildren()
530 if (!LogicalChildren.Any())
535 var container = this as IPageContainer<Page>;
536 if (container?.CurrentPage != null)
542 for (var i = 0; i < LogicalChildren.Count; i++)
544 var v = LogicalChildren[i] as BaseHandle;
555 /// Returns the platform-specific instance of this Page, on which a platform-specific method may be called.
557 /// <typeparam name="T">The platform for which to return an instance.</typeparam>
558 /// <returns>The platform-specific instance of this Page</returns>
559 internal IPlatformElementConfiguration<T, Page> On<T>() where T : IConfigPlatform
561 return _platformConfigurationRegistry.Value.On<T>();