Skip to content
This repository has been archived by the owner on Dec 28, 2023. It is now read-only.

Add ContentPopup #276

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/Tizen.Wearable.CircularUI.Forms.Renderer/CircularUI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ public static void Init()
{
if (IsInitialized) return;
IsInitialized = true;
ContentPopup.RendererFunc = () => new ContentPopupRenderer();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

where this technique come from?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

come from me 😉

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
ContentPopup.RendererFunc = () => new ContentPopupRenderer();
ContentPopup.CreateRenderer = () => new ContentPopupRenderer();

}

public static void Init(string apiKey)
Expand Down
143 changes: 143 additions & 0 deletions src/Tizen.Wearable.CircularUI.Forms.Renderer/ContentPopupRenderer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
*
* Licensed under the Flora License, Version 1.1 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://floralicense.org/license/
*
* 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 Tizen.Wearable.CircularUI.Forms;
using Tizen.Wearable.CircularUI.Forms.Renderer;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Tizen;
using XForms = Xamarin.Forms.Forms;

[assembly: ExportRenderer(typeof(ContentPopup), typeof(ContentPopupRenderer))]

namespace Tizen.Wearable.CircularUI.Forms.Renderer
{
public class ContentPopupRenderer : IContentPopupRenderer
{
ElmSharp.Popup _popup;
ContentPopup _element;

public void SetElement(Element element)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
public void SetElement(Element element)
public void SetElement(ContentPopup element)

Because it is ContentPopupRenderer

{
element.Parent = Application.Current.Parent;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Set only if no parent

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed.

element.PropertyChanged += OnElementPropertyChanged;

_element = element as ContentPopup;

UpdateContent();
UpdateIsShow();
}

public ContentPopupRenderer()
{
_popup = new ElmSharp.Popup(XForms.NativeParent);
_popup.Style = "circle";

_popup.BackButtonPressed += OnBackButtonPressed;
_popup.Dismissed += OnDismissed;
}

~ContentPopupRenderer()
{
Dispose(false);
}

public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}

public void Dismiss()
{
_popup?.Hide();
_popup?.Dismiss();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should not use Dismiss, because it destroy popup

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed.

}

public void Show()
{
_popup?.Show();
}

protected void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == ContentPopup.ContentProperty.PropertyName)
{
UpdateContent();
}
if (e.PropertyName == ContentPopup.IsShowProperty.PropertyName)
{
UpdateIsShow();
}
}

protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if (_popup != null)
{
_popup.BackButtonPressed -= OnBackButtonPressed;
_popup.Dismissed -= OnDismissed;
_popup.Unrealize();
_popup = null;
}
if (_element != null)
{
_element.PropertyChanged -= OnElementPropertyChanged;
_element = null;
}
}
}

void OnBackButtonPressed(object sender, EventArgs e)
{
_element.SendBackButtonPressed();
}

void OnDismissed(object sender, EventArgs e)
{
_element.SendDismissed();
Dispose();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you dispose it?

}

void UpdateContent()
{
if (_element.Content != null)
{
var renderer = Platform.GetOrCreateRenderer(_element.Content);
(renderer as LayoutRenderer)?.RegisterOnLayoutUpdated();
var native = renderer.NativeView;
var sizeRequest = _element.Content.Measure(XForms.NativeParent.Geometry.Width, XForms.NativeParent.Geometry.Height).Request.ToPixel();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need it

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed.

native.MinimumHeight = sizeRequest.Height;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Content should be always fullscreen size

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed.

_popup.SetContent(native, false);
}
else
{
_popup.SetContent(null, false);
}
}

void UpdateIsShow()
{
if (_element.IsShow)
Show();
else
Dismiss();
}
}
}
135 changes: 135 additions & 0 deletions src/Tizen.Wearable.CircularUI.Forms/ContentPopup.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
*
* Licensed under the Flora License, Version 1.1 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://floralicense.org/license/
*
* 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 Xamarin.Forms;

namespace Tizen.Wearable.CircularUI.Forms
{
/// <summary>
/// The ContentPopup is a Popup, which allows you to customize the View to be displayed.
/// </summary>
/// <since_tizen> 4 </since_tizen>
public class ContentPopup : Element, IDisposable
{
IContentPopupRenderer _renderer;

/// <summary>
/// For internal use.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
public static Func<IContentPopupRenderer> RendererFunc { get; set; } = null;

/// <summary>
/// BindableProperty. Identifies the Content bindable property.
/// </summary>
/// <since_tizen> 4 </since_tizen>
public static readonly BindableProperty ContentProperty = BindableProperty.Create(nameof(Content), typeof(View), typeof(ContentPopup), null);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to update parent

void UpdateContent() 
{
    OnChildAdded(Content);
}
               // it is method of Element
		protected virtual void OnChildAdded(Element child)
		{
			child.Parent = this;

			child.ApplyBindings(skipBindingContext: false, fromBindingContextChanged: true);

			ChildAdded?.Invoke(this, new ElementEventArgs(child));

			OnDescendantAdded(child);
			foreach (Element element in child.Descendants())
				OnDescendantAdded(element);
		}

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed.


/// <summary>
/// BindableProperty. Identifies the IsShow bindable property.
/// </summary>
/// <since_tizen> 4 </since_tizen>
public static readonly BindableProperty IsShowProperty = BindableProperty.Create(nameof(IsShow), typeof(bool), typeof(ContentPopup), false, propertyChanged:(b, o, n) => ((ContentPopup)b).UpdateRenderer());

/// <summary>
/// Occurs when the device's back button is pressed.
/// </summary>
/// <since_tizen> 4 </since_tizen>
public event EventHandler BackButtonPressed;

/// <summary>
/// Occurs when the popup is dismissed.
/// </summary>
/// <since_tizen> 4 </since_tizen>
public event EventHandler Dismissed;

/// <summary>
/// Gets or sets content view of the Popup.
/// </summary>
/// <since_tizen> 4 </since_tizen>
public View Content
{
get { return (View)GetValue(ContentProperty); }
set { SetValue(ContentProperty, value); }
}

/// <summary>
/// Gets or sets the popup is shown.
/// </summary>
/// <since_tizen> 4 </since_tizen>
public bool IsShow
{
get { return (bool)GetValue(IsShowProperty); }
set { SetValue(IsShowProperty, value); }
}

/// <summary>
/// Shows the popup.
/// </summary>
/// <since_tizen> 4 </since_tizen>
public void Show()
Copy link
Collaborator

@myroot myroot Apr 26, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about rename to Open?
and How about return Task that indicate closing timing

        TaskCompletionSource<bool> _tcsForDismiss;
        public Task Open()
        {
            IsShow = true;
            _tcsForDismiss = new TaskCompletionSource<bool>();
            return _tcsForDismiss.Task;
        }

        public void SendDismissed()
        {
            Dismissed?.Invoke(this, EventArgs.Empty);
            _tcsForDismiss?.TrySetResult(true);
        }

If you provide Task we can easily use

  using (var popup = new ContentPopup()) {
     poup.Content = new StackLayout { ... };
     _ = await popup.Open();
  }

{
IsShow = true;
}

/// <summary>
/// Dismisses the popup.
/// </summary>
/// <since_tizen> 4 </since_tizen>
public void Dismiss()
{
IsShow = false;
}

/// <summary>
/// For internal use.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
public void SendDismissed()
{
Dismissed?.Invoke(this, EventArgs.Empty);
}

/// <summary>
/// For internal use.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
public void SendBackButtonPressed()
{
BackButtonPressed?.Invoke(this, EventArgs.Empty);
}

void UpdateRenderer()
{
if (_renderer == null)
{
_renderer = RendererFunc();
_renderer.SetElement(this);
}
}

public void Dispose()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use Dispose pattern

        public void Dispose()
        {
            Dispose(true);
        }

        protected virtual void Dispose(bool disposing)
        {
                if (disposing && _renderer != null)
                {
                        _renderer.Dispose();
                        _renderer = null;
                }
        }

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed.

{
if (_renderer != null)
{
_renderer.Dispose();
_renderer = null;
}
}
}
}
44 changes: 44 additions & 0 deletions src/Tizen.Wearable.CircularUI.Forms/IContentPopupRenderer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
*
* Licensed under the Flora License, Version 1.1 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://floralicense.org/license/
*
* 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 Xamarin.Forms;

namespace Tizen.Wearable.CircularUI.Forms
{
/// <summary>
/// Base interface for ContentPopup renderer.
/// </summary>
/// <since_tizen> 4 </since_tizen>
public interface IContentPopupRenderer : IDisposable
{
/// <summary>
/// Shows the popup.
/// </summary>
void Show();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No more need

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed.


/// <summary>
/// Dismisses the popup.
/// </summary>
void Dismiss();

/// <summary>
/// Sets the Element associated with this renderer.
/// </summary>
/// <param name="element">New element.</param>
void SetElement(Element element);
}
}
2 changes: 1 addition & 1 deletion src/Tizen.Wearable.CircularUI.Forms/ITwoButtonPopup.cs
100755 → 100644
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved
* Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
*
* Licensed under the Flora License, Version 1.1 (the "License");
* you may not use this file except in compliance with the License.
Expand Down
43 changes: 43 additions & 0 deletions test/WearableUIGallery/WearableUIGallery/TC/TCContentPopup.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage
x:Class="WearableUIGallery.TC.TCContentPopupTest"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:WearableUIGallery"
xmlns:w="clr-namespace:Tizen.Wearable.CircularUI.Forms;assembly=Tizen.Wearable.CircularUI.Forms"
w:CircleSurfaceEffectBehavior.RotaryFocusObject="{x:Reference myscroller}">
<ContentPage.Behaviors>
<w:CircleSurfaceEffectBehavior/>
</ContentPage.Behaviors>
<ContentPage.Content>
<w:CircleScrollView x:Name="myscroller" Orientation="Vertical">
<StackLayout Padding="0,50,0,50">
<Label
x:Name="label1"
HorizontalOptions="CenterAndExpand"
Text="ContentPopup test"
VerticalOptions="Start" />
<Button
AutomationId="dismisstest1"
x:Name="button1"
Clicked="OnContentPopupDismissBackKeyClicked"
FontSize="Small"
HeightRequest="50"
HorizontalOptions="Center"
Text="Dismiss test 1"
VerticalOptions="CenterAndExpand"
WidthRequest="300" />
<Button
AutomationId="dismisstest2"
x:Name="button2"
Clicked="OnContentPopupDismissButtonClicked"
FontSize="Small"
HeightRequest="50"
HorizontalOptions="Center"
Text="Dismiss test 2"
VerticalOptions="CenterAndExpand"
WidthRequest="300" />
</StackLayout>
</w:CircleScrollView>
</ContentPage.Content>
</ContentPage>
Loading