bool isHorizontal = (ScrollingDirection == Direction.Horizontal);
- float viewScreenPosition = (isHorizontal? ScreenPosition.X : ScreenPosition.Y);
- float childScreenPosition = (isHorizontal? child.ScreenPosition.X : child.ScreenPosition.Y);
- float scrollPosition = (isHorizontal? ScrollPosition.X : ScrollPosition.Y);
- float viewSize = (isHorizontal? SizeWidth : SizeHeight);
- float childSize = (isHorizontal? child.SizeWidth : child.SizeHeight);
+ float viewScreenPosition = (isHorizontal ? ScreenPosition.X : ScreenPosition.Y);
+ float childScreenPosition = (isHorizontal ? child.ScreenPosition.X : child.ScreenPosition.Y);
+ float scrollPosition = (isHorizontal ? ScrollPosition.X : ScrollPosition.Y);
+ float viewSize = (isHorizontal ? SizeWidth : SizeHeight);
+ float childSize = (isHorizontal ? child.SizeWidth : child.SizeHeight);
if (viewScreenPosition > childScreenPosition ||
viewScreenPosition + viewSize < childScreenPosition + childSize)
StopOverShootingShadowAnimation();
StopScroll();
- if (mPanGestureDetector != null)
+ if (type == DisposeTypes.Explicit)
{
- mPanGestureDetector.Detected -= OnPanGestureDetected;
- mPanGestureDetector.Dispose();
+ mPanGestureDetector?.Dispose();
mPanGestureDetector = null;
- }
- if (propertyNotification != null)
- {
ContentContainer?.RemovePropertyNotification(propertyNotification);
- propertyNotification.Notified -= OnPropertyChanged;
- propertyNotification.Dispose();
+ propertyNotification?.Dispose();
propertyNotification = null;
}
-
- if (type == DisposeTypes.Explicit)
- {
-
- }
base.Dispose(type);
}
var checkFinalTargetPosition = BoundScrollPosition(checkChildTargetPosition);
handled = !((int)checkFinalTargetPosition == 0 || -(int)checkFinalTargetPosition == (int)maxScrollDistance);
// If you propagate a gesture event, return;
- if(!handled)
+ if (!handled)
{
return handled;
}
{
bool isHorizontal = (ScrollingDirection == Direction.Horizontal);
float targetPosition = -(ScrollingDirection == Direction.Horizontal ? ContentContainer.CurrentPosition.X : ContentContainer.CurrentPosition.Y);
- float stepDistance = (stepScrollDistance != 0? stepScrollDistance : (isHorizontal ? Size.Width * 0.25f : Size.Height * 0.25f));
+ float stepDistance = (stepScrollDistance != 0 ? stepScrollDistance : (isHorizontal ? Size.Width * 0.25f : Size.Height * 0.25f));
bool forward = ((isHorizontal && direction == View.FocusDirection.Right) ||
(!isHorizontal && direction == View.FocusDirection.Down) ||
{
private DaliEventHandler<object, NotifyEventArgs> propertyNotificationNotifyEventHandler;
- private NotifyEventCallbackDelegate propertyNotificationNotifyEventCallbackDelegate;
+ private NotifyEventCallbackDelegate propertyNotificationNotifyEventCallback;
/// <summary>
/// Create a instance of PropertyNotification.
{
add
{
- // Restricted to only one listener
if (propertyNotificationNotifyEventHandler == null)
{
- propertyNotificationNotifyEventHandler += value;
-
- propertyNotificationNotifyEventCallbackDelegate = new NotifyEventCallbackDelegate(OnPropertyNotificationNotify);
- this.NotifySignal().Connect(propertyNotificationNotifyEventCallbackDelegate);
+ propertyNotificationNotifyEventCallback = OnPropertyNotificationNotify;
+ using PropertyNotifySignal signal = new PropertyNotifySignal(Interop.PropertyNotification.NotifySignal(SwigCPtr), false);
+ signal?.Connect(propertyNotificationNotifyEventCallback);
}
+ propertyNotificationNotifyEventHandler += value;
}
-
remove
{
- if (propertyNotificationNotifyEventHandler != null)
+ propertyNotificationNotifyEventHandler -= value;
+ if (propertyNotificationNotifyEventHandler == null)
{
- this.NotifySignal().Disconnect(propertyNotificationNotifyEventCallbackDelegate);
+ using PropertyNotifySignal signal = new PropertyNotifySignal(Interop.PropertyNotification.NotifySignal(SwigCPtr), false);
+ if (signal?.Empty() == false)
+ {
+ signal?.Disconnect(propertyNotificationNotifyEventCallback);
+ if (signal?.Empty() == true)
+ {
+ propertyNotificationNotifyEventCallback = null;
+ }
+ }
}
-
- propertyNotificationNotifyEventHandler -= value;
}
}
}
/// <summary>
- /// Connects to this signal to be notified when the notification has occurred.
+ /// override it to clean-up your own resources.
/// </summary>
- /// <returns>A signal object to Connect() with</returns>
- internal PropertyNotifySignal NotifySignal()
+ /// <param name="type"></param>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ protected override void Dispose(DisposeTypes type)
{
- PropertyNotifySignal ret = new PropertyNotifySignal(Interop.PropertyNotification.NotifySignal(SwigCPtr), false);
- if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
- return ret;
+ if (disposed)
+ {
+ return;
+ }
+
+ if (type == DisposeTypes.Explicit)
+ {
+ //Called by User
+ //Release your own managed resources here.
+ //You should release all of your own disposable objects here.
+ }
+
+ //Release your own unmanaged resources here.
+ //You should not access any managed member here except static instance.
+ //because the execution order of Finalizes is non-deterministic.
+
+ if (HasBody())
+ {
+ if (propertyNotificationNotifyEventCallback != null)
+ {
+ using PropertyNotifySignal signal = new PropertyNotifySignal(Interop.PropertyNotification.NotifySignal(SwigCPtr), false);
+ signal?.Disconnect(propertyNotificationNotifyEventCallback);
+ propertyNotificationNotifyEventCallback = null;
+ }
+ }
+ base.Dispose(type);
}
/// This will not be public opened.
// Callback for PropertyNotification NotifySignal
private void OnPropertyNotificationNotify(IntPtr propertyNotification)
{
- NotifyEventArgs e = new NotifyEventArgs();
- e.PropertyNotification = GetPropertyNotificationFromPtr(propertyNotification);
+ if (IsNativeHandleInvalid())
+ {
+ if (this.Disposed)
+ {
+ if (propertyNotificationNotifyEventHandler != null)
+ {
+ var process = global::System.Diagnostics.Process.GetCurrentProcess().Id;
+ var thread = global::System.Threading.Thread.CurrentThread.ManagedThreadId;
+ var me = this.GetType().FullName;
+
+ Tizen.Log.Error("NUI", $"Error! NUI's native dali object is already disposed. " +
+ $"OR the native dali object handle of NUI becomes null! \n" +
+ $" process:{process} thread:{thread}, isDisposed:{this.Disposed}, isDisposeQueued:{this.IsDisposeQueued}, me:{me}\n");
+ }
+ }
+ else
+ {
+ if (this.IsDisposeQueued)
+ {
+ var process = global::System.Diagnostics.Process.GetCurrentProcess().Id;
+ var thread = global::System.Threading.Thread.CurrentThread.ManagedThreadId;
+ var me = this.GetType().FullName;
+
+ //in this case, this object is ready to be disposed waiting on DisposeQueue, so event callback should not be invoked!
+ Tizen.Log.Error("NUI", "in this case, the View object is ready to be disposed waiting on DisposeQueue, so event callback should not be invoked! just return here! \n" +
+ $"process:{process} thread:{thread}, isDisposed:{this.Disposed}, isDisposeQueued:{this.IsDisposeQueued}, me:{me}\n");
+ return;
+ }
+ }
+ }
if (propertyNotificationNotifyEventHandler != null)
{
+ NotifyEventArgs e = new NotifyEventArgs();
+ e.PropertyNotification = GetPropertyNotificationFromPtr(propertyNotification);
+
//here we send all data to user event handlers
propertyNotificationNotifyEventHandler(this, e);
}
if (detectedEventHandler == null)
{
detectedCallback = OnPanGestureDetected;
- DetectedSignal().Connect(detectedCallback);
+ using PanGestureDetectedSignal signal = new PanGestureDetectedSignal(Interop.PanGestureDetector.DetectedSignal(SwigCPtr), false);
+ signal?.Connect(detectedCallback);
}
-
detectedEventHandler += value;
}
-
remove
{
detectedEventHandler -= value;
-
- if (detectedEventHandler == null && DetectedSignal().Empty() == false)
+ if (detectedEventHandler == null)
{
- DetectedSignal().Disconnect(detectedCallback);
+ using PanGestureDetectedSignal signal = new PanGestureDetectedSignal(Interop.PanGestureDetector.DetectedSignal(SwigCPtr), false);
+ if (signal?.Empty() == false)
+ {
+ signal?.Disconnect(detectedCallback);
+ if (signal?.Empty() == true)
+ {
+ detectedCallback = null;
+ }
+ }
}
}
}
return ret;
}
- internal PanGestureDetectedSignal DetectedSignal()
+ /// <summary>
+ /// override it to clean-up your own resources.
+ /// </summary>
+ /// <param name="type"></param>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ protected override void Dispose(DisposeTypes type)
{
- PanGestureDetectedSignal ret = new PanGestureDetectedSignal(Interop.PanGestureDetector.DetectedSignal(SwigCPtr), false);
- if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
- return ret;
+ if (disposed)
+ {
+ return;
+ }
+
+ if (type == DisposeTypes.Explicit)
+ {
+ //Called by User
+ //Release your own managed resources here.
+ //You should release all of your own disposable objects here.
+ }
+
+ //Release your own unmanaged resources here.
+ //You should not access any managed member here except static instance.
+ //because the execution order of Finalizes is non-deterministic.
+
+ if (HasBody())
+ {
+ if (detectedCallback != null)
+ {
+ using PanGestureDetectedSignal signal = new PanGestureDetectedSignal(Interop.PanGestureDetector.DetectedSignal(GetBaseHandleCPtrHandleRef), false);
+ signal?.Disconnect(detectedCallback);
+ detectedCallback = null;
+ }
+ }
+ base.Dispose(type);
}
/// This will not be public opened.
[EditorBrowsable(EditorBrowsableState.Never)]
protected override void ReleaseSwigCPtr(System.Runtime.InteropServices.HandleRef swigCPtr)
{
- if (detectedCallback != null)
- {
- DetectedSignal().Disconnect(detectedCallback);
- }
-
Interop.PanGestureDetector.DeletePanGestureDetector(swigCPtr);
}
private void OnPanGestureDetected(IntPtr actor, IntPtr panGesture)
{
+ if (IsNativeHandleInvalid())
+ {
+ if (this.Disposed)
+ {
+ if (detectedEventHandler != null)
+ {
+ var process = global::System.Diagnostics.Process.GetCurrentProcess().Id;
+ var thread = global::System.Threading.Thread.CurrentThread.ManagedThreadId;
+ var me = this.GetType().FullName;
+
+ Tizen.Log.Error("NUI", $"Error! NUI's native dali object is already disposed. " +
+ $"OR the native dali object handle of NUI becomes null! \n" +
+ $" process:{process} thread:{thread}, isDisposed:{this.Disposed}, isDisposeQueued:{this.IsDisposeQueued}, me:{me}\n");
+ }
+ }
+ else
+ {
+ if (this.IsDisposeQueued)
+ {
+ var process = global::System.Diagnostics.Process.GetCurrentProcess().Id;
+ var thread = global::System.Threading.Thread.CurrentThread.ManagedThreadId;
+ var me = this.GetType().FullName;
+
+ //in this case, this object is ready to be disposed waiting on DisposeQueue, so event callback should not be invoked!
+ Tizen.Log.Error("NUI", "in this case, the View object is ready to be disposed waiting on DisposeQueue, so event callback should not be invoked! just return here! \n" +
+ $"process:{process} thread:{thread}, isDisposed:{this.Disposed}, isDisposeQueued:{this.IsDisposeQueued}, me:{me}\n");
+ return;
+ }
+ }
+ }
+
if (detectedEventHandler != null)
{
DetectedEventArgs e = new DetectedEventArgs();
using global::System;
using Tizen.NUI.BaseComponents;
using System.Collections.Generic;
+using Tizen.NUI.Components;
namespace Tizen.NUI.Samples
{
public void Activate()
{
+ //test case 1: checking dispose without "-=" of event.
DisposeWithoutUnsubscribedEventTest();
- AnimationDisposeTest();
+
+ //test case 2: checking Animation class dispose.
+ //AnimationDisposeTest();
}
public void Deactivate()
{
}
}
+ private void AddManyScrollableBases()
+ {
+ tlog.Fatal(tag, $"AddManyScrollableBases()");
+
+ for (int i = 0; i < NUMBER_OF_VIEW; i++)
+ {
+ var child = new ScrollableBase()
+ {
+ Size = new Size(60, 60),
+ Position = new Position(rand.Next(MIN_POSITION, MAX_POSITION), rand.Next(MIN_POSITION, MAX_POSITION)),
+ BackgroundColor = new Color((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble(), 1),
+ };
+
+ rootView.Add(child);
+ child.Relayout += Child_Relayout;
+ child.RemovedFromWindow += Child_RemovedFromWindow;
+ child.AddedToWindow += Child_AddedToWindow;
+ child.WheelEvent += Child_WheelEvent;
+ child.HoverEvent += Child_HoverEvent;
+ child.InterceptTouchEvent += Child_InterceptTouchEvent;
+ child.TouchEvent += Child_TouchEvent;
+ child.ResourcesLoaded += Child_ResourcesLoaded;
+ child.KeyEvent += Child_KeyEvent;
+ child.FocusLost += Child_FocusLost;
+ child.FocusGained += Child_FocusGained;
+ }
+ }
+
+
private void Child_FocusGained(object sender, EventArgs e)
{
if (++cnt % (NUMBER_OF_VIEW * 3) == 1)
toggle = !toggle;
if (toggle)
{
- AddManyObject();
+ //test case 1: checking ImageView object dispose.
+ //AddManyObject();
+
+ //test case 2: checking ScrollableBase object dispose.
+ AddManyScrollableBases();
}
else
{