/*
* Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
*
* 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 System.Linq;
namespace ElmSharp
{
///
/// It inherits .
/// The event with TEventArgs for .
/// EvasObject can elect the SmartEvent occurring inside them, to be reported back to their users via delegates.
/// This way, you can extend EvasObject's own .
/// They are defined by an event string, which identifies them uniquely.
///
/// The parameter for the event.
/// preview
public class SmartEvent : IInvalidatable where TEventArgs : EventArgs
{
///
/// The delegate for creating smart event item arguments.
///
/// The item data.
/// The sender object.
/// The item sender object.
/// Return smart event item args.
/// preview
public delegate TEventArgs SmartEventInfoParser(IntPtr data, IntPtr obj, IntPtr info);
private EvasObject _sender;
private readonly string _eventName;
private IntPtr _handle;
private readonly SmartEventInfoParser _parser;
private readonly List _nativeCallbacks = new List();
///
/// Creates and initializes a new instance of the SmartEvent class.
///
/// The source of the event.
/// The event name.
/// The event parameter.
/// preview
public SmartEvent(EvasObject sender, string eventName, SmartEventInfoParser parser) : this(sender, sender.Handle, eventName, parser)
{
}
///
/// Creates and initializes a new instance of the SmartEvent class.
///
/// The source of the event.
/// Teh event handler.
/// The event name.
/// The event parser.
/// preview
[EditorBrowsableAttribute(EditorBrowsableState.Never)]
public SmartEvent(EvasObject sender, IntPtr handle, string eventName, SmartEventInfoParser parser)
{
_sender = sender;
_eventName = eventName;
_handle = handle;
_parser = parser;
sender.AddToEventLifeTracker(this);
}
///
/// Creates and initializes a new instance of the SmartEvent class.
///
/// The source of the event.
/// The event name.
/// preview
public SmartEvent(EvasObject sender, string eventName) : this(sender, eventName, null)
{
}
///
/// Destroys the SmartEvent object.
///
~SmartEvent()
{
Dispose(false);
}
private struct NativeCallback
{
public Interop.Evas.SmartCallback callback;
public EventHandler eventHandler;
}
///
/// Adds or removes a delegate for the event.
///
/// preview
public event EventHandler On
{
add
{
if (_handle == IntPtr.Zero)
{
return;
}
EventHandler handler = value;
var cb = new Interop.Evas.SmartCallback((d, o, e) =>
{
TEventArgs ea = _parser == null ? (TEventArgs)EventArgs.Empty : _parser(d, o, e);
handler(_sender, ea);
});
_nativeCallbacks.Add(new NativeCallback { callback = cb, eventHandler = handler });
int i = _nativeCallbacks.Count - 1;
Interop.Evas.evas_object_smart_callback_add(_handle, _eventName, _nativeCallbacks[i].callback, IntPtr.Zero);
}
remove
{
if (_handle == IntPtr.Zero)
{
return;
}
EventHandler handler = value;
var callbacks = _nativeCallbacks.Where(cb => cb.eventHandler == handler);
foreach (var cb in callbacks)
{
Interop.Evas.evas_object_smart_callback_del(_handle, _eventName, cb.callback);
}
}
}
///
/// Destroys the current object.
///
/// preview
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
///
/// Makes the current instance invalidate.
///
/// preview
public void MakeInvalidate()
{
_sender = null;
_handle = IntPtr.Zero;
}
///
/// Releases all the resources currently used by this instance.
///
///
/// true if the managed resources should be disposed,
/// otherwise false.
///
/// preview
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
_sender.RemoveFromEventLifeTracker(this);
}
if (_handle != IntPtr.Zero)
{
foreach (var cb in _nativeCallbacks)
{
Interop.Evas.evas_object_smart_callback_del(_handle, _eventName, cb.callback);
}
}
_nativeCallbacks.Clear();
}
}
///
/// It inherits .
/// EvasObject can elect the SmartEvent occurring inside them, to be reported back to their users via delegates.
/// This way, you can extend EvasObject's own .
/// They are defined by an event string, which identifies them uniquely.
///
/// preview
public class SmartEvent : IInvalidatable
{
private SmartEvent _smartEvent;
private event EventHandler _handlers;
///
/// Creates and initializes a new instance of the SmartEvent class.
///
/// The source of the event.
/// The event name.
/// preview
public SmartEvent(EvasObject sender, string eventName) : this(sender, sender.RealHandle, eventName)
{
}
///
/// Creates and initializes a new instance of the SmartEvent class.
///
/// The source of the event.
/// The event handler.
/// The event name.
/// preview
[EditorBrowsableAttribute(EditorBrowsableState.Never)]
public SmartEvent(EvasObject sender, IntPtr handle, string eventName)
{
_smartEvent = new SmartEvent(sender, handle, eventName, null);
}
///
/// Destroys the SmartEvent object.
///
~SmartEvent()
{
Dispose(false);
}
///
/// Adds or removes a delegate for the event.
///
/// preview
public event EventHandler On
{
add
{
if (_handlers == null)
{
_smartEvent.On += SendEvent;
}
_handlers += value;
}
remove
{
_handlers -= value;
if (_handlers == null)
{
_smartEvent.On -= SendEvent;
}
}
}
private void SendEvent(object sender, EventArgs e)
{
_handlers?.Invoke(sender, e);
}
///
/// Destroys the current object.
///
/// preview
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
///
/// Makes the current instance invalidate.
///
/// preview
public void MakeInvalidate()
{
_smartEvent.MakeInvalidate();
}
///
/// Releases all the resources currently used by this instance.
///
///
/// true if the managed resources should be disposed,
/// otherwise false.
///
/// preview
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
// Place holder to dispose managed state (managed objects).
_smartEvent.Dispose();
}
}
}
}