From c14fe1e3decfc4f38e4076c9d75490460f3d0527 Mon Sep 17 00:00:00 2001 From: Seunghyun Choi Date: Wed, 8 Mar 2017 19:13:34 +0900 Subject: [PATCH] Add Dialog - This is RFC 22. Change-Id: I666cc946c90ecd25c3985870006825871f4f22a6 Signed-off-by: Seunghyun Choi --- .../DialogImplementation.cs | 378 +++++++++++++++++++++ .../Tizen.Xamarin.Forms.Extension.Renderer.csproj | 3 +- Tizen.Xamarin.Forms.Extension/Dialog.cs | 181 ++++++++++ Tizen.Xamarin.Forms.Extension/IDialog.cs | 34 ++ .../Tizen.Xamarin.Forms.Extension.csproj | 4 +- 5 files changed, 598 insertions(+), 2 deletions(-) create mode 100644 Tizen.Xamarin.Forms.Extension.Renderer/DialogImplementation.cs create mode 100644 Tizen.Xamarin.Forms.Extension/Dialog.cs create mode 100644 Tizen.Xamarin.Forms.Extension/IDialog.cs diff --git a/Tizen.Xamarin.Forms.Extension.Renderer/DialogImplementation.cs b/Tizen.Xamarin.Forms.Extension.Renderer/DialogImplementation.cs new file mode 100644 index 0000000..36f60f7 --- /dev/null +++ b/Tizen.Xamarin.Forms.Extension.Renderer/DialogImplementation.cs @@ -0,0 +1,378 @@ +using System; +using System.ComponentModel; +using System.Runtime.CompilerServices; +using Xamarin.Forms; +using Xamarin.Forms.Platform.Tizen; +using TForms = Xamarin.Forms.Platform.Tizen.Forms; +using EPopup = ElmSharp.Popup; +using Tizen.Xamarin.Forms.Extension.Renderer; + +[assembly: Dependency(typeof(DialogImplementation))] + +namespace Tizen.Xamarin.Forms.Extension.Renderer +{ + class DialogImplementation : IDialog, INotifyPropertyChanged, IDisposable + { + EPopup _control; + View _content; + Button _positive; + Button _neutral; + Button _negative; + string _title; + string _subtitle; + + bool _isDisposed = false; + + bool _isNullable = false; + ElmSharp.Button _nativePositive; + ElmSharp.Button _nativeNeutral; + ElmSharp.Button _nativeNegative; + ElmSharp.EvasObject _nativeContent; + + public event EventHandler Dismissed; + + public event EventHandler OutsideClicked; + + public event EventHandler Shown; + + public event EventHandler BackButtonPressed; + + public event PropertyChangedEventHandler PropertyChanged; + + public DialogImplementation() + { + _control = new EPopup(TForms.Context.MainWindow); + + _control.ShowAnimationFinished += ShowAnimationFinishedHandler; + _control.Dismissed += DismissedHandler; + _control.OutsideClicked += OutsideClickedHandler; + _control.KeyUp += BackButtonPressedHandler; + + PropertyChanged += PropertyChangedHandler; + } + + ~DialogImplementation() + { + Dispose(false); + } + + public View Content + { + get + { + return _content; + } + set + { + _content = value; + OnPropertyChanged(); + } + } + + public Button Positive + { + get + { + return _positive; + } + set + { + _positive = value; + OnPropertyChanged(); + } + } + + public Button Neutral + { + get + { + return _neutral; + } + set + { + _neutral = value; + OnPropertyChanged(); + } + } + + public Button Negative + { + get + { + return _negative; + } + set + { + _negative = value; + OnPropertyChanged(); + } + } + + public string Title + { + get + { + return _title; + } + set + { + _title = value; + OnPropertyChanged(); + } + } + + public string Subtitle + { + get + { + return _subtitle; + } + set + { + _subtitle = value; + OnPropertyChanged(); + } + } + + public void Show() + { + _control.Show(); + } + + public void Hide() + { + _control.Hide(); + } + + public void Dismiss() + { + _control.Dismiss(); + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (_isDisposed) + return; + + if (disposing) + { + PropertyChanged -= PropertyChangedHandler; + + if (_nativePositive != null) + { + _nativePositive.Unrealize(); + _nativePositive = null; + } + if (_nativeNeutral != null) + { + _nativeNeutral.Unrealize(); + _nativeNeutral = null; + } + if (_nativeNegative != null) + { + _nativeNegative.Unrealize(); + _nativeNegative = null; + } + if (_nativeContent != null) + { + _nativeContent.Unrealize(); + _nativeContent = null; + } + + if (_control != null) + { + _control.ShowAnimationFinished -= ShowAnimationFinishedHandler; + _control.Dismissed -= DismissedHandler; + _control.OutsideClicked -= OutsideClickedHandler; + _control.KeyUp -= BackButtonPressedHandler; + + _control.Unrealize(); + _control = null; + } + } + + _isDisposed = true; + } + + void ShowAnimationFinishedHandler(object sender, EventArgs e) + { + Shown?.Invoke(this, EventArgs.Empty); + GrabBackkey(); + } + + void DismissedHandler(object sender, EventArgs e) + { + Dismissed?.Invoke(this, EventArgs.Empty); + UngrabBackKey(); + } + + void OutsideClickedHandler(object sender, EventArgs e) + { + OutsideClicked?.Invoke(this, EventArgs.Empty); + } + + void BackButtonPressedHandler(object sender, ElmSharp.EvasKeyEventArgs e) + { + if (e.KeyName == ElmSharp.EvasKeyEventArgs.PlatformBackButtonName) + { + BackButtonPressed?.Invoke(this, EventArgs.Empty); + } + } + + void PropertyChangedHandler(object sender, PropertyChangedEventArgs e) + { + if (e.PropertyName == Dialog.ContentProperty.PropertyName) + { + UpdateContent(); + } + else if (e.PropertyName == Dialog.PositiveProperty.PropertyName) + { + UpdatePositive(); + } + else if (e.PropertyName == Dialog.NeutralProperty.PropertyName) + { + UpdateNeutral(); + } + else if (e.PropertyName == Dialog.NegativeProperty.PropertyName) + { + UpdateNegative(); + } + else if (e.PropertyName == Dialog.TitleProperty.PropertyName) + { + UpdateTitle(); + } + else if (e.PropertyName == Dialog.SubtitleProperty.PropertyName) + { + UpdateSubtitle(); + } + } + + void OnPropertyChanged([CallerMemberName] string propertyName = null) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + + void UpdateContent() + { + _isNullable = _nativeContent != null ? true : false; + + _nativeContent?.Hide(); + + View contentView = null; + + if (Content.GetType() == typeof(ScrollView)) + { + contentView = new StackLayout + { + Children = + { + Content + } + }; + } + else + { + contentView = Content; + } + + if (contentView != null) + { + contentView.Parent = Application.Current.MainPage; + _nativeContent = Platform.GetOrCreateRenderer(contentView).NativeView; + + var sizeRequest = contentView.Measure(TForms.Context.MainWindow.ScreenSize.Width, TForms.Context.MainWindow.ScreenSize.Height).Request.ToPixel(); + + _nativeContent.MinimumHeight = sizeRequest.Height; + } + else + { + _nativeContent = null; + } + + _control.SetPartContent("default", _nativeContent, _isNullable); + } + + void UpdatePositive() + { + _isNullable = _nativePositive != null ? true : false; + + _nativePositive?.Hide(); + + if (Positive != null) + { + _nativePositive = (ElmSharp.Button)Platform.GetOrCreateRenderer(Positive).NativeView; + _nativePositive.Style = "bottom"; + } + else + { + _nativePositive = null; + } + + _control.SetPartContent("button1", _nativePositive, _isNullable); + } + + void UpdateNeutral() + { + _isNullable = _nativeNeutral != null ? true : false; + + _nativeNeutral?.Hide(); + + if (Neutral != null) + { + _nativeNeutral = (ElmSharp.Button)Platform.GetOrCreateRenderer(Neutral).NativeView; + _nativeNeutral.Style = "bottom"; + } + else + { + _nativeNeutral = null; + } + + _control.SetPartContent("button2", _nativeNeutral, _isNullable); + } + + void UpdateNegative() + { + _isNullable = _nativeNegative != null ? true : false; + + _nativeNegative?.Hide(); + + if (Negative != null) + { + _nativeNegative = (ElmSharp.Button)Platform.GetOrCreateRenderer(Negative).NativeView; + _nativeNegative.Style = "bottom"; + } + else + { + _nativeNegative = null; + } + + _control.SetPartContent("button3", _nativeNegative, _isNullable); + } + + void UpdateTitle() + { + _control.SetPartText("title,text", Title); + } + + void UpdateSubtitle() + { + _control.SetPartText("subtitle,text", Subtitle); + } + + void GrabBackkey() + { + _control.KeyGrab(ElmSharp.EvasKeyEventArgs.PlatformBackButtonName, true); + } + + void UngrabBackKey() + { + _control.KeyUngrab(ElmSharp.EvasKeyEventArgs.PlatformBackButtonName); + } + } +} \ No newline at end of file diff --git a/Tizen.Xamarin.Forms.Extension.Renderer/Tizen.Xamarin.Forms.Extension.Renderer.csproj b/Tizen.Xamarin.Forms.Extension.Renderer/Tizen.Xamarin.Forms.Extension.Renderer.csproj index 6fb1056..51d1927 100755 --- a/Tizen.Xamarin.Forms.Extension.Renderer/Tizen.Xamarin.Forms.Extension.Renderer.csproj +++ b/Tizen.Xamarin.Forms.Extension.Renderer/Tizen.Xamarin.Forms.Extension.Renderer.csproj @@ -45,6 +45,7 @@ + @@ -83,4 +84,4 @@ <_FullFrameworkReferenceAssemblyPaths>$(MSBuildThisFileDirectory) true - + diff --git a/Tizen.Xamarin.Forms.Extension/Dialog.cs b/Tizen.Xamarin.Forms.Extension/Dialog.cs new file mode 100644 index 0000000..ddf8bbe --- /dev/null +++ b/Tizen.Xamarin.Forms.Extension/Dialog.cs @@ -0,0 +1,181 @@ +using System; +using Xamarin.Forms; + +namespace Tizen.Xamarin.Forms.Extension +{ + /// + /// The dialog widget displays its content with a particular direction. + /// + /// + /// + /// var dialog = new Dialog(); + /// dialog.Direction = DialogDirection.Bottom; + /// dialog.Title = "Dialog" + /// + /// var positive = new Button() + /// { + /// Text = "OK" + /// } + /// var negative = new Button() + /// { + /// Text = "Cancel" + /// } + /// negative.Clicked += (s,e)=> + /// { + /// dialog.Dismiss(); + /// } + /// + /// dialog.Positive = positive; + /// dialog.Negative = negative; + /// + /// var label = new Label() + /// { + /// Text = "New Dialog" + /// } + /// + /// dialog.Content = label; + /// + /// dialog.Show(); + /// + /// + /// + public class Dialog : BindableObject + { + public static readonly BindableProperty ContentProperty = BindableProperty.Create(nameof(Content), typeof(View), typeof(Dialog), null); + + public static readonly BindableProperty PositiveProperty = BindableProperty.Create(nameof(Positive), typeof(Button), typeof(Dialog), null); + + public static readonly BindableProperty NeutralProperty = BindableProperty.Create(nameof(Neutral), typeof(Button), typeof(Dialog), null); + + public static readonly BindableProperty NegativeProperty = BindableProperty.Create(nameof(Negative), typeof(Button), typeof(Dialog), null); + + public static readonly BindableProperty TitleProperty = BindableProperty.Create(nameof(Title), typeof(string), typeof(Dialog), null); + + public static readonly BindableProperty SubtitleProperty = BindableProperty.Create(nameof(Subtitle), typeof(string), typeof(Dialog), null); + + IDialog _dialog = null; + + public event EventHandler Dismissed; + + public event EventHandler OutsideClicked; + + public event EventHandler Shown; + + public event EventHandler BackButtonPressed; + + public Dialog() + { + _dialog = DependencyService.Get(DependencyFetchTarget.NewInstance); + if (_dialog == null) + { + throw new Exception("Object reference not set to an instance of a Dialog."); + } + + _dialog.Dismissed += (s, e) => + { + Dismissed?.Invoke(this, EventArgs.Empty); + }; + + _dialog.OutsideClicked += (s, e) => + { + OutsideClicked?.Invoke(this, EventArgs.Empty); + }; + + _dialog.Shown += (s, e) => + { + Shown?.Invoke(this, EventArgs.Empty); + }; + + _dialog.BackButtonPressed += (s, e) => + { + BackButtonPressed?.Invoke(this, EventArgs.Empty); + }; + + SetBinding(ContentProperty, new Binding(nameof(Content), mode: BindingMode.TwoWay, source: _dialog)); + SetBinding(PositiveProperty, new Binding(nameof(Positive), mode: BindingMode.TwoWay, source: _dialog)); + SetBinding(NeutralProperty, new Binding(nameof(Neutral), mode: BindingMode.TwoWay, source: _dialog)); + SetBinding(NegativeProperty, new Binding(nameof(Negative), mode: BindingMode.TwoWay, source: _dialog)); + SetBinding(TitleProperty, new Binding(nameof(Title), mode: BindingMode.TwoWay, source: _dialog)); + SetBinding(SubtitleProperty, new Binding(nameof(Subtitle), mode: BindingMode.TwoWay, source: _dialog)); + } + + /// + /// Gets or sets content view of the Dialog. + /// + public View Content + { + get { return (View)GetValue(ContentProperty); } + set { SetValue(ContentProperty, value); } + } + + /// + /// Gets or sets positive button of the Dialog. + /// + public Button Positive + { + get { return (Button)GetValue(PositiveProperty); } + set { SetValue(PositiveProperty, value); } + } + + /// + /// Gets or sets neutral button of the Dialog. + /// + public Button Neutral + { + get { return (Button)GetValue(NeutralProperty); } + set { SetValue(NeutralProperty, value); } + } + + /// + /// Gets or sets negative button of the Dialog. + /// + public Button Negative + { + get { return (Button)GetValue(NegativeProperty); } + set { SetValue(NegativeProperty, value); } + } + + /// + /// Gets or sets title of the Dialog. + /// + public string Title + { + get { return (string)GetValue(TitleProperty); } + set { SetValue(TitleProperty, value); } + } + + /// + /// Gets or sets subtitle of the Dialog. + /// When Title property value is null, subtitle does not displayed. + /// + public string Subtitle + { + get { return (string)GetValue(SubtitleProperty); } + set { SetValue(SubtitleProperty, value); } + } + + /// + /// Shows the Dialog. + /// + public void Show() + { + _dialog.Show(); + } + + /// + /// Hides the Dialog. + /// + public void Hide() + { + _dialog.Hide(); + } + + /// + /// Dismisses the Dialog. + /// + public void Dismiss() + { + _dialog.Dismiss(); + } + } +} \ No newline at end of file diff --git a/Tizen.Xamarin.Forms.Extension/IDialog.cs b/Tizen.Xamarin.Forms.Extension/IDialog.cs new file mode 100644 index 0000000..f450550 --- /dev/null +++ b/Tizen.Xamarin.Forms.Extension/IDialog.cs @@ -0,0 +1,34 @@ +using System; +using Xamarin.Forms; + +namespace Tizen.Xamarin.Forms.Extension +{ + internal interface IDialog + { + event EventHandler Dismissed; + + event EventHandler OutsideClicked; + + event EventHandler Shown; + + event EventHandler BackButtonPressed; + + View Content { get; set; } + + Button Positive { get; set; } + + Button Neutral { get; set; } + + Button Negative { get; set; } + + string Title { get; set; } + + string Subtitle { get; set; } + + void Show(); + + void Hide(); + + void Dismiss(); + } +} \ No newline at end of file diff --git a/Tizen.Xamarin.Forms.Extension/Tizen.Xamarin.Forms.Extension.csproj b/Tizen.Xamarin.Forms.Extension/Tizen.Xamarin.Forms.Extension.csproj index 21e35e2..6ab4ac5 100644 --- a/Tizen.Xamarin.Forms.Extension/Tizen.Xamarin.Forms.Extension.csproj +++ b/Tizen.Xamarin.Forms.Extension/Tizen.Xamarin.Forms.Extension.csproj @@ -66,6 +66,7 @@ + @@ -75,6 +76,7 @@ + @@ -122,4 +124,4 @@ --> - + -- 2.7.4