Release 4.0.0-preview1-00267
[platform/core/csapi/tizenfx.git] / src / ElmSharp / ElmSharp / SmartEvent.cs
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 using System;
18 using System.ComponentModel;
19 using System.Collections.Generic;
20 using System.Linq;
21
22 namespace ElmSharp
23 {
24     /// <summary>
25     /// It inherits <see cref="IInvalidatable"/>.
26     /// The event with TEventArgs for <see cref="EvasObject"/>.
27     /// EvasObject can elect SmartEvent occurring inside of them to be reported back to their users via delegates.
28     /// This way, you can extend EvasObject's own <see cref="EvasObjectEvent"/>.
29     /// They are defined by an event string, which identifies them uniquely.
30     /// </summary>
31     /// <typeparam name="TEventArgs">The parameter for the event.</typeparam>
32     public class SmartEvent<TEventArgs> : IInvalidatable where TEventArgs : EventArgs
33     {
34         /// <summary>
35         /// The delegate for creating smart event item args.
36         /// </summary>
37         /// <param name="data">The item data.</param>
38         /// <param name="obj">The sender obj.</param>
39         /// <param name="info">The item sender obj.</param>
40         /// <returns>Return smart event item args.</returns>
41         public delegate TEventArgs SmartEventInfoParser(IntPtr data, IntPtr obj, IntPtr info);
42
43         private EvasObject _sender;
44         private readonly string _eventName;
45         private IntPtr _handle;
46         private readonly SmartEventInfoParser _parser;
47         private readonly List<NativeCallback> _nativeCallbacks = new List<NativeCallback>();
48
49         /// <summary>
50         /// Creates and initializes a new instance of the SmartEvent class.
51         /// </summary>
52         /// <param name="sender">The source of the event.</param>
53         /// <param name="eventName">The event name.</param>
54         /// <param name="parser">The event parameter.</param>
55         public SmartEvent(EvasObject sender, string eventName, SmartEventInfoParser parser) : this(sender, sender.Handle, eventName, parser)
56         {
57         }
58
59         /// <summary>
60         /// reates and initializes a new instance of the SmartEvent class.
61         /// </summary>
62         /// <param name="sender">The source of the event.</param>
63         /// <param name="handle">Teh event handler.</param>
64         /// <param name="eventName">The event name.</param>
65         /// <param name="parser">The event parser.</param>
66         [EditorBrowsableAttribute(EditorBrowsableState.Never)]
67         public SmartEvent(EvasObject sender, IntPtr handle, string eventName, SmartEventInfoParser parser)
68         {
69             _sender = sender;
70             _eventName = eventName;
71             _handle = handle;
72             _parser = parser;
73             sender.AddToEventLifeTracker(this);
74         }
75
76         /// <summary>
77         /// Creates and initializes a new instance of the SmartEvent class.
78         /// </summary>
79         /// <param name="sender">The source of the event.</param>
80         /// <param name="eventName">The event name.</param>
81         public SmartEvent(EvasObject sender, string eventName) : this(sender, eventName, null)
82         {
83         }
84
85         /// <summary>
86         /// Destroy the SmartEvent object.
87         /// </summary>
88         ~SmartEvent()
89         {
90             Dispose(false);
91         }
92
93         private struct NativeCallback
94         {
95             public Interop.Evas.SmartCallback callback;
96             public EventHandler<TEventArgs> eventHandler;
97         }
98
99         /// <summary>
100         /// Adds or removes delegate for event.
101         /// </summary>
102         public event EventHandler<TEventArgs> On
103         {
104             add
105             {
106                 if (_handle == IntPtr.Zero)
107                 {
108                     return;
109                 }
110                 EventHandler<TEventArgs> handler = value;
111                 var cb = new Interop.Evas.SmartCallback((d, o, e) =>
112                 {
113                     TEventArgs ea = _parser == null ? (TEventArgs)EventArgs.Empty : _parser(d, o, e);
114                     handler(_sender, ea);
115                 });
116                 _nativeCallbacks.Add(new NativeCallback { callback = cb, eventHandler = handler });
117                 int i = _nativeCallbacks.Count - 1;
118                 Interop.Evas.evas_object_smart_callback_add(_handle, _eventName, _nativeCallbacks[i].callback, IntPtr.Zero);
119             }
120
121             remove
122             {
123                 if (_handle == IntPtr.Zero)
124                 {
125                     return;
126                 }
127                 EventHandler<TEventArgs> handler = value;
128                 var callbacks = _nativeCallbacks.Where(cb => cb.eventHandler == handler);
129                 foreach (var cb in callbacks)
130                 {
131                     Interop.Evas.evas_object_smart_callback_del(_handle, _eventName, cb.callback);
132                 }
133             }
134         }
135
136         /// <summary>
137         /// Destroy current object
138         /// </summary>
139         public void Dispose()
140         {
141             Dispose(true);
142             GC.SuppressFinalize(this);
143         }
144
145         /// <summary>
146         /// Make current instance invalidate.
147         /// </summary>
148         public void MakeInvalidate()
149         {
150             _sender = null;
151             _handle = IntPtr.Zero;
152         }
153
154         /// <summary>
155         /// Releases all resources currently used by this instance.
156         /// </summary>
157         /// <param name="disposing">
158         /// true if managed resources should be disposed
159         /// otherwise, false.
160         /// </param>
161         protected virtual void Dispose(bool disposing)
162         {
163             if (disposing)
164             {
165                 // Place holder to dispose managed state (managed objects).
166             }
167             if (_handle != IntPtr.Zero)
168             {
169                 foreach (var cb in _nativeCallbacks)
170                 {
171                     Interop.Evas.evas_object_smart_callback_del(_handle, _eventName, cb.callback);
172                 }
173             }
174             _nativeCallbacks.Clear();
175         }
176     }
177
178     /// <summary>
179     /// It inherits <see cref="IInvalidatable"/>.
180     /// EvasObject can elect SmartEvent occurring inside of them to be reported back to their users via delegates.
181     /// This way, you can extend EvasObject's own <see cref="EvasObjectEvent"/>.
182     /// They are defined by an event string, which identifies them uniquely.
183     /// </summary>
184     public class SmartEvent : IInvalidatable
185     {
186         private SmartEvent<EventArgs> _smartEvent;
187
188         private event EventHandler _handlers;
189
190         /// <summary>
191         /// Creates and initializes a new instance of the SmartEvent class.
192         /// </summary>
193         /// <param name="sender">The source of the event.</param>
194         /// <param name="eventName">The event name.</param>
195         public SmartEvent(EvasObject sender, string eventName) : this(sender, sender.RealHandle, eventName)
196         {
197         }
198
199         /// <summary>
200         /// Creates and initializes a new instance of the SmartEvent class.
201         /// </summary>
202         /// <param name="sender">The source of the event.</param>
203         /// <param name="handle">The event handler.</param>
204         /// <param name="eventName">The event name.</param>
205         [EditorBrowsableAttribute(EditorBrowsableState.Never)]
206         public SmartEvent(EvasObject sender, IntPtr handle, string eventName)
207         {
208             _smartEvent = new SmartEvent<EventArgs>(sender, handle, eventName, null);
209         }
210
211         /// <summary>
212         /// Destroy the SmartEvent object.
213         /// </summary>
214         ~SmartEvent()
215         {
216             Dispose(false);
217         }
218
219         /// <summary>
220         /// Adds or removes delegate for event.
221         /// </summary>
222         public event EventHandler On
223         {
224             add
225             {
226                 if (_handlers == null)
227                 {
228                     _smartEvent.On += SendEvent;
229                 }
230                 _handlers += value;
231             }
232
233             remove
234             {
235                 _handlers -= value;
236                 if (_handlers == null)
237                 {
238                     _smartEvent.On -= SendEvent;
239                 }
240             }
241         }
242
243         private void SendEvent(object sender, EventArgs e)
244         {
245             _handlers?.Invoke(sender, e);
246         }
247
248         /// <summary>
249         /// Destroy current object
250         /// </summary>
251         public void Dispose()
252         {
253             Dispose(true);
254             GC.SuppressFinalize(this);
255         }
256
257         /// <summary>
258         /// Make current instance invalidate.
259         /// </summary>
260         public void MakeInvalidate()
261         {
262             _smartEvent.MakeInvalidate();
263         }
264
265         /// <summary>
266         /// Releases all resources currently used by this instance.
267         /// </summary>
268         /// <param name="disposing">
269         /// true if managed resources should be disposed
270         /// otherwise, false.
271         /// </param>
272         protected virtual void Dispose(bool disposing)
273         {
274             if (disposing)
275             {
276                 // Place holder to dispose managed state (managed objects).
277                 _smartEvent.Dispose();
278             }
279         }
280     }
281 }