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