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.ComponentModel;
20 using System.Collections.Generic;
21 using Tizen.NUI.BaseComponents;
23 namespace Tizen.NUI.Components
26 /// AlertDialog class shows a dialog with title, message and action buttons.
28 /// <since_tizen> 9 </since_tizen>
29 public partial class AlertDialog : Control
31 private string title = null;
32 private string message = null;
34 private View titleContent = null;
35 private View content = null;
36 private View actionContent = null;
37 private IEnumerable<View> actionContentViews = null;
39 private View defaultTitleContent = null;
40 private View defaultContent = null;
41 private View defaultActionContent = null;
42 // FIXME: Now AlertDialog.Padding Top and Bottom increases AlertDialog size incorrectly.
43 // Until the bug is fixed, padding view is added after action content.
44 private View defaultActionContentPadding = null;
46 private bool styleApplied = false;
49 /// Creates a new instance of AlertDialog.
51 /// <since_tizen> 9 </since_tizen>
52 public AlertDialog() : base()
58 /// Creates a new instance of AlertDialog.
60 /// <param name="style">Creates AlertDialog by special style defined in UX.</param>
61 /// <since_tizen> 9 </since_tizen>
62 public AlertDialog(string style) : base(style)
68 /// Creates a new instance of AlertDialog.
70 /// <param name="alertDialogStyle">Creates AlertDialog by style customized by user.</param>
71 /// <since_tizen> 9 </since_tizen>
72 public AlertDialog(AlertDialogStyle alertDialogStyle) : base(alertDialogStyle)
78 [EditorBrowsable(EditorBrowsableState.Never)]
79 protected override void Dispose(DisposeTypes type)
86 if (type == DisposeTypes.Explicit)
88 if (titleContent != null)
90 Utility.Dispose(titleContent);
95 Utility.Dispose(content);
98 if (actionContent != null)
100 Utility.Dispose(actionContent);
103 // FIXME: Now AlertDialog.Padding Top and Bottom increases AlertDialog size incorrectly.
104 // Until the bug is fixed, padding view is added after action content.
105 if (defaultActionContentPadding != null)
107 Utility.Dispose(defaultActionContentPadding);
115 /// Applies style to AlertDialog.
117 /// <param name="viewStyle">The style to apply.</param>
118 /// <since_tizen> 9 </since_tizen>
119 public override void ApplyStyle(ViewStyle viewStyle)
121 styleApplied = false;
123 base.ApplyStyle(viewStyle);
125 var alertDialogStyle = viewStyle as AlertDialogStyle;
127 if (alertDialogStyle == null)
132 // Apply Title style.
133 if ((alertDialogStyle.TitleTextLabel != null) && (DefaultTitleContent is TextLabel))
135 ((TextLabel)DefaultTitleContent)?.ApplyStyle(alertDialogStyle.TitleTextLabel);
138 // Apply Message style.
139 if ((alertDialogStyle.MessageTextLabel != null) && (DefaultContent is TextLabel))
141 ((TextLabel)DefaultContent)?.ApplyStyle(alertDialogStyle.MessageTextLabel);
144 // Apply ActionContent style.
145 if (alertDialogStyle.ActionContent != null)
147 DefaultActionContent?.ApplyStyle(alertDialogStyle.ActionContent);
152 // Calculate dialog position and children's positions based on padding sizes.
157 /// Title text of AlertDialog.
158 /// Title text is set to TitleContent's Text if TitleContent is TextLabel.
159 /// If TitleContent's Text is set manually by user, then it is not guaranteed that TitleContent's Text is the same with Title text.
161 /// <since_tizen> 9 </since_tizen>
166 return GetValue(TitleProperty) as string;
170 SetValue(TitleProperty, value);
171 NotifyPropertyChanged();
174 private string InternalTitle
189 if (TitleContent is TextLabel textLabel)
191 textLabel.Text = title;
197 /// Title content of AlertDialog.
198 /// TitleContent is added as a child of AlertDialog automatically.
199 /// Title text is set to TitleContent's Text if TitleContent is TextLabel.
200 /// If TitleContent's Text is set manually by user, then it is not guaranteed that TitleContent's Text is the same with Title text.
202 /// <since_tizen> 9 </since_tizen>
203 public View TitleContent
207 return GetValue(TitleContentProperty) as View;
211 SetValue(TitleContentProperty, value);
212 NotifyPropertyChanged();
215 private View InternalTitleContent
223 if (titleContent == value)
228 if (titleContent != null)
230 Remove(titleContent);
233 titleContent = value;
234 if (titleContent == null)
239 if (titleContent is TextLabel textLabel)
241 textLabel.Text = Title;
249 /// Message text of AlertDialog.
250 /// Message text is set to Content's Text if Content is TextLabel.
251 /// If Content's Text is set manually by user, then it is not guaranteed that Content's Text is the same with Message text.
253 /// <since_tizen> 9 </since_tizen>
254 public string Message
258 return GetValue(MessageProperty) as string;
262 SetValue(MessageProperty, value);
263 NotifyPropertyChanged();
266 private string InternalMessage
274 if (message == value)
281 if (Content is TextLabel textLabel)
283 textLabel.Text = message;
289 /// Content of AlertDialog.
290 /// Content is added as a child of AlertDialog automatically.
291 /// Message text is set to Content's Text if Content is TextLabel.
292 /// If Content's Text is set manually by user, then it is not guaranteed that Content's Text is the same with Message text.
294 /// <since_tizen> 9 </since_tizen>
299 return GetValue(ContentProperty) as View;
303 SetValue(ContentProperty, value);
304 NotifyPropertyChanged();
307 private View InternalContent
315 if (content == value)
331 if (content is TextLabel textLabel)
333 textLabel.Text = message;
341 /// Action views of AlertDialog.
342 /// Action views are added as children of ActionContent.
343 /// When Actions are set, previous Actions are removed from ActionContent.
345 /// <since_tizen> 9 </since_tizen>
346 public IEnumerable<View> Actions
350 return actionContentViews;
354 if (ActionContent == null)
356 actionContentViews = value;
360 if (actionContentViews != null)
362 foreach (var oldAction in actionContentViews)
364 if (ActionContent.Children?.Contains(oldAction) == true)
366 ActionContent.Children.Remove(oldAction);
371 actionContentViews = value;
373 if (actionContentViews == null)
378 foreach (var action in actionContentViews)
380 ActionContent.Add(action);
386 /// Action content of AlertDialog.
387 /// ActionContent is added as a child of AlertDialog automatically.
388 /// Actions are added as children of ActionContent.
390 /// <since_tizen> 9 </since_tizen>
391 public View ActionContent
395 return GetValue(ActionContentProperty) as View;
399 SetValue(ActionContentProperty, value);
400 NotifyPropertyChanged();
403 private View InternalActionContent
407 return actionContent;
411 if (actionContent == value)
416 var oldActionContent = actionContent;
417 actionContent = value;
419 // Add views first before remove previous action content
420 // not to cause Garbage Collector collects views.
421 if ((actionContent != null) && (Actions != null))
423 foreach (var action in Actions)
425 actionContent.Add(action);
429 if (oldActionContent != null)
431 Remove(oldActionContent);
434 if (actionContent == null)
444 /// AccessibilityGetName.
446 [EditorBrowsable(EditorBrowsableState.Never)]
447 protected override string AccessibilityGetName()
449 if (!String.IsNullOrEmpty(Title))
460 /// Initialize AT-SPI object.
462 [EditorBrowsable(EditorBrowsableState.Never)]
463 public override void OnInitialize()
466 SetAccessibilityConstructor(Role.Dialog);
467 AppendAccessibilityAttribute("sub-role", "Alert");
468 Show(); // calls AddPopup()
472 /// Informs AT-SPI bridge about the set of AT-SPI states associated with this object.
474 [EditorBrowsable(EditorBrowsableState.Never)]
475 protected override AccessibilityStates AccessibilityCalculateStates(ulong states)
477 var accessibilityStates = base.AccessibilityCalculateStates(states);
478 FlagSetter(ref accessibilityStates, AccessibilityStates.Modal, true);
479 return accessibilityStates;
484 /// Default title content of AlertDialog.
485 /// If Title is set, then default title content is automatically displayed.
487 [EditorBrowsable(EditorBrowsableState.Never)]
488 protected View DefaultTitleContent
492 if (defaultTitleContent == null)
494 defaultTitleContent = CreateDefaultTitleContent();
497 return defaultTitleContent;
502 /// Default content of AlertDialog.
503 /// If Message is set, then default content is automatically displayed.
505 [EditorBrowsable(EditorBrowsableState.Never)]
506 protected View DefaultContent
510 if (defaultContent == null)
512 defaultContent = CreateDefaultContent();
515 return defaultContent;
520 /// Default action content of AlertDialog.
521 /// If Actions are set, then default action content is automatically displayed.
523 [EditorBrowsable(EditorBrowsableState.Never)]
524 protected View DefaultActionContent
528 if (defaultActionContent == null)
530 defaultActionContent = CreateDefaultActionContent();
533 // FIXME: Now AlertDialog.Padding Top and Bottom increases AlertDialog size incorrectly.
534 // Until the bug is fixed, padding view is added after action content.
535 if (defaultActionContentPadding == null)
537 defaultActionContentPadding = CreateDefaultActionContentPadding();
540 return defaultActionContent;
544 private void Initialize()
546 Layout = new LinearLayout()
548 LinearOrientation = LinearLayout.Orientation.Vertical,
549 LinearAlignment = LinearLayout.Alignment.CenterHorizontal,
552 this.Relayout += OnRelayout;
554 TitleContent = DefaultTitleContent;
556 Content = DefaultContent;
558 ActionContent = DefaultActionContent;
561 private void ResetContent()
563 //To keep the order of TitleContent, Content and ActionContent,
564 //the existing contents are removed and added again.
565 if (titleContent != null)
567 Remove(titleContent);
575 if (actionContent != null)
577 Remove(actionContent);
580 if (titleContent != null)
590 if (actionContent != null)
594 // FIXME: Now AlertDialog.Padding Top and Bottom increases AlertDialog size incorrectly.
595 // Until the bug is fixed, padding view is added after action content.
596 if (actionContent == defaultActionContent)
598 if (defaultActionContentPadding != null)
600 Add(defaultActionContentPadding);
606 private TextLabel CreateDefaultTitleContent()
608 return new TextLabel();
611 private TextLabel CreateDefaultContent()
613 return new TextLabel();
616 private View CreateDefaultActionContent()
620 Layout = new LinearLayout()
622 LinearOrientation = LinearLayout.Orientation.Horizontal,
623 LinearAlignment = LinearLayout.Alignment.Center,
624 // FIXME: This CellPadding value should be written in AlertDialogStyle.
625 // However, if this is called in other place, then flicking issue happens.
626 CellPadding = new Size2D(80, 0),
631 // FIXME: Now AlertDialog.Padding Top and Bottom increases AlertDialog size incorrectly.
632 // Until the bug is fixed, padding view is added after action content.
633 private View CreateDefaultActionContentPadding()
635 var layout = Layout as LinearLayout;
637 if ((layout == null) || (defaultActionContent == null))
642 View paddingView = null;
644 using (Size2D size = new Size2D(defaultActionContent.Size2D.Width, defaultActionContent.Size2D.Height))
646 if (layout.LinearOrientation == LinearLayout.Orientation.Horizontal)
655 paddingView = new View()
657 Size2D = new Size2D(size.Width, size.Height),
664 private void OnRelayout(object sender, EventArgs e)
666 // Calculate dialog position and children's positions based on padding sizes.
670 // Calculate dialog position and children's positions based on padding sizes.
671 private void CalculatePosition()
673 if (styleApplied == false)
679 var parent = GetParent();
682 if ((parent != null) && (parent is View))
684 parentSize = ((View)parent).Size;
688 parentSize = NUIApplication.GetDefaultWindow().Size;
691 Position2D = new Position2D((parentSize.Width - size.Width) / 2, (parentSize.Height - size.Height) / 2);