/* * Copyright(c) 2022 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ using System; using System.ComponentModel; using System.Collections.Generic; using Tizen.NUI.BaseComponents; namespace Tizen.NUI.Components { /// /// AlertDialog class shows a dialog with title, message and action buttons. /// /// 9 public partial class AlertDialog : Control { private string title = null; private string message = null; private View titleContent = null; private View content = null; private View actionContent = null; private IEnumerable actionContentViews = null; private View defaultTitleContent = null; private View defaultContent = null; private View defaultActionContent = null; private bool styleApplied = false; /// /// Creates a new instance of AlertDialog. /// /// 9 public AlertDialog() : base() { Initialize(); } /// /// Creates a new instance of AlertDialog. /// /// Creates AlertDialog by special style defined in UX. /// 9 public AlertDialog(string style) : base(style) { Initialize(); } /// /// Creates a new instance of AlertDialog. /// /// Creates AlertDialog by style customized by user. /// 9 public AlertDialog(AlertDialogStyle alertDialogStyle) : base(alertDialogStyle) { Initialize(); } /// [EditorBrowsable(EditorBrowsableState.Never)] protected override void Dispose(DisposeTypes type) { if (disposed) { return; } if (type == DisposeTypes.Explicit) { if (titleContent != null) { Utility.Dispose(titleContent); } if (content != null) { Utility.Dispose(content); } if (actionContent != null) { Utility.Dispose(actionContent); } } base.Dispose(type); } /// /// Applies style to AlertDialog. /// /// The style to apply. /// 9 public override void ApplyStyle(ViewStyle viewStyle) { styleApplied = false; base.ApplyStyle(viewStyle); var alertDialogStyle = viewStyle as AlertDialogStyle; if (alertDialogStyle == null) { return; } // Apply ItemSpacing. if ((alertDialogStyle.ItemSpacing != null) && (Layout is LinearLayout linearLayout)) { linearLayout.CellPadding = new Size2D(alertDialogStyle.ItemSpacing.Width, alertDialogStyle.ItemSpacing.Height); } // Apply Title style. if ((alertDialogStyle.TitleTextLabel != null) && (DefaultTitleContent is TextLabel)) { ((TextLabel)DefaultTitleContent)?.ApplyStyle(alertDialogStyle.TitleTextLabel); } // Apply Message style. if ((alertDialogStyle.MessageTextLabel != null) && (DefaultContent is TextLabel)) { ((TextLabel)DefaultContent)?.ApplyStyle(alertDialogStyle.MessageTextLabel); } // Apply ActionContent style. if (alertDialogStyle.ActionContent != null) { DefaultActionContent?.ApplyStyle(alertDialogStyle.ActionContent); } styleApplied = true; // Calculate dialog position and children's positions based on padding sizes. CalculatePosition(); } /// /// Title text of AlertDialog. /// Title text is set to TitleContent's Text if TitleContent is TextLabel. /// If TitleContent's Text is set manually by user, then it is not guaranteed that TitleContent's Text is the same with Title text. /// /// 9 public string Title { get { return GetValue(TitleProperty) as string; } set { SetValue(TitleProperty, value); NotifyPropertyChanged(); } } private string InternalTitle { get { return title; } set { if (title == value) { return; } title = value; if (TitleContent is TextLabel textLabel) { textLabel.Text = title; ResetContent(); } } } /// /// Title content of AlertDialog. /// TitleContent is added as a child of AlertDialog automatically. /// Title text is set to TitleContent's Text if TitleContent is TextLabel. /// If TitleContent's Text is set manually by user, then it is not guaranteed that TitleContent's Text is the same with Title text. /// /// 9 public View TitleContent { get { return GetValue(TitleContentProperty) as View; } set { SetValue(TitleContentProperty, value); NotifyPropertyChanged(); } } private View InternalTitleContent { get { return titleContent; } set { if (titleContent == value) { return; } if (titleContent != null) { Remove(titleContent); } titleContent = value; if (titleContent == null) { return; } if (titleContent is TextLabel textLabel) { textLabel.Text = Title; ResetContent(); } } } /// /// Message text of AlertDialog. /// Message text is set to Content's Text if Content is TextLabel. /// If Content's Text is set manually by user, then it is not guaranteed that Content's Text is the same with Message text. /// /// 9 public string Message { get { return GetValue(MessageProperty) as string; } set { SetValue(MessageProperty, value); NotifyPropertyChanged(); } } private string InternalMessage { get { return message; } set { if (message == value) { return; } message = value; if (Content is TextLabel textLabel) { textLabel.Text = message; } ResetContent(); } } /// /// Content of AlertDialog. /// Content is added as a child of AlertDialog automatically. /// Message text is set to Content's Text if Content is TextLabel. /// If Content's Text is set manually by user, then it is not guaranteed that Content's Text is the same with Message text. /// /// 9 public View Content { get { return GetValue(ContentProperty) as View; } set { SetValue(ContentProperty, value); NotifyPropertyChanged(); } } private View InternalContent { get { return content; } set { if (content == value) { return; } if (content != null) { Remove(content); } content = value; if (content == null) { return; } if (content is TextLabel textLabel) { textLabel.Text = message; } ResetContent(); } } /// /// Action views of AlertDialog. /// Action views are added as children of ActionContent. /// When Actions are set, previous Actions are removed from ActionContent. /// /// 9 public IEnumerable Actions { get { return actionContentViews; } set { if (ActionContent == null) { actionContentViews = value; return; } if (actionContentViews != null) { foreach (var oldAction in actionContentViews) { if (ActionContent.Children?.Contains(oldAction) == true) { ActionContent.Children.Remove(oldAction); } } } actionContentViews = value; if (actionContentViews == null) { return; } foreach (var action in actionContentViews) { ActionContent.Add(action); } } } /// /// Action content of AlertDialog. /// ActionContent is added as a child of AlertDialog automatically. /// Actions are added as children of ActionContent. /// /// 9 public View ActionContent { get { return GetValue(ActionContentProperty) as View; } set { SetValue(ActionContentProperty, value); NotifyPropertyChanged(); } } private View InternalActionContent { get { return actionContent; } set { if (actionContent == value) { return; } var oldActionContent = actionContent; actionContent = value; // Add views first before remove previous action content // not to cause Garbage Collector collects views. if ((actionContent != null) && (Actions != null)) { foreach (var action in Actions) { actionContent.Add(action); } } if (oldActionContent != null) { Remove(oldActionContent); } if (actionContent == null) { return; } ResetContent(); } } /// /// Gets accessibility name. /// [EditorBrowsable(EditorBrowsableState.Never)] protected override string AccessibilityGetName() { if (!String.IsNullOrEmpty(Title)) { return Title; } else { return Message; } } /// /// Gets accessibility description. /// [EditorBrowsable(EditorBrowsableState.Never)] protected override string AccessibilityGetDescription() { return Message; } /// /// Initialize AT-SPI object. /// [EditorBrowsable(EditorBrowsableState.Never)] public override void OnInitialize() { base.OnInitialize(); AccessibilityRole = Role.Dialog; Show(); // calls RegisterDefaultLabel(); Hide() will call UnregisterDefaultLabel() } /// /// Informs AT-SPI bridge about the set of AT-SPI states associated with this object. /// [EditorBrowsable(EditorBrowsableState.Never)] protected override AccessibilityStates AccessibilityCalculateStates() { var states = base.AccessibilityCalculateStates(); states[AccessibilityState.Modal] = true; return states; } /// /// Default title content of AlertDialog. /// If Title is set, then default title content is automatically displayed. /// [EditorBrowsable(EditorBrowsableState.Never)] protected View DefaultTitleContent { get { if (defaultTitleContent == null) { defaultTitleContent = CreateDefaultTitleContent(); } return defaultTitleContent; } } /// /// Default content of AlertDialog. /// If Message is set, then default content is automatically displayed. /// [EditorBrowsable(EditorBrowsableState.Never)] protected View DefaultContent { get { if (defaultContent == null) { defaultContent = CreateDefaultContent(); } return defaultContent; } } /// /// Default action content of AlertDialog. /// If Actions are set, then default action content is automatically displayed. /// [EditorBrowsable(EditorBrowsableState.Never)] protected View DefaultActionContent { get { if (defaultActionContent == null) { defaultActionContent = CreateDefaultActionContent(); } return defaultActionContent; } } private void Initialize() { var alertDialogStyle = ViewStyle as AlertDialogStyle; Layout = new LinearLayout() { LinearOrientation = LinearLayout.Orientation.Vertical, HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center, }; if (styleApplied && (alertDialogStyle != null) && (alertDialogStyle.ItemSpacing != null) && (Layout is LinearLayout linearLayout)) { linearLayout.CellPadding = new Size2D(alertDialogStyle.ItemSpacing.Width, alertDialogStyle.ItemSpacing.Height); } this.Relayout += OnRelayout; TitleContent = DefaultTitleContent; Content = DefaultContent; ActionContent = DefaultActionContent; } private void ResetContent() { //To keep the order of TitleContent, Content and ActionContent, //the existing contents are removed and added again. if (titleContent != null) { Remove(titleContent); } if (content != null) { Remove(content); } if (actionContent != null) { Remove(actionContent); } if (titleContent != null) { var textLabel = titleContent as TextLabel; if (textLabel == null) { Add(titleContent); } else if (!String.IsNullOrEmpty(textLabel.Text)) { Add(titleContent); } } if (content != null) { var textLabel = content as TextLabel; if (textLabel == null) { Add(content); } else if (!String.IsNullOrEmpty(textLabel.Text)) { Add(content); } } if (actionContent != null) { Add(actionContent); } } private TextLabel CreateDefaultTitleContent() { return new TextLabel(); } private TextLabel CreateDefaultContent() { return new TextLabel(); } private View CreateDefaultActionContent() { var view = new View() { Layout = new FlexLayout() { Direction = FlexLayout.FlexDirection.Row, WrapType = FlexLayout.FlexWrapType.NoWrap, Justification = FlexLayout.FlexJustification.SpaceBetween, }, }; view.ChildAdded += (object sender, ChildAddedEventArgs args) => { // To align action items with space between them, FlexLayout is used. if (view.Layout is FlexLayout) { if (view.ChildCount == 1) { view.Layout = new LinearLayout() { LinearOrientation = LinearLayout.Orientation.Horizontal, HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center, }; } } // To allign 1 action item at the center, LinearLayout is used. else { if (view.ChildCount > 1) { view.Layout = new FlexLayout() { Direction = FlexLayout.FlexDirection.Row, WrapType = FlexLayout.FlexWrapType.NoWrap, Justification = FlexLayout.FlexJustification.SpaceBetween, }; } } }; return view; } private void OnRelayout(object sender, EventArgs e) { // Calculate dialog position and children's positions based on padding sizes. CalculatePosition(); } // Calculate dialog position and children's positions based on padding sizes. private void CalculatePosition() { if (styleApplied == false) { return; } var size = Size2D; var parent = GetParent(); Size2D parentSize; if ((parent != null) && (parent is View)) { parentSize = ((View)parent).Size; } else { parentSize = NUIApplication.GetDefaultWindow().Size; } Position2D = new Position2D((parentSize.Width - size.Width) / 2, (parentSize.Height - size.Height) / 2); } } }