ea16c8d14282d709878bddd5aa563395f1876456
[platform/core/csapi/tizenfx.git] / src / ElmSharp / ElmSharp / ItemObject.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.Collections.Generic;
19
20 namespace ElmSharp
21 {
22     /// <summary>
23     /// The ItemObject is used to manage the item object.
24     /// </summary>
25     /// <since_tizen> preview </since_tizen>
26     public class ItemObject
27     {
28         private static Dictionary<int, ItemObject> s_IdToItemTable = new Dictionary<int, ItemObject>();
29         private static Dictionary<IntPtr, ItemObject> s_HandleToItemTable = new Dictionary<IntPtr, ItemObject>();
30         private static int s_globalId = 0;
31
32         readonly Dictionary<string, EvasObject> _partContents = new Dictionary<string, EvasObject>();
33         Interop.Evas.SmartCallback _deleteCallback;
34         IntPtr _handle = IntPtr.Zero;
35         Dictionary<SignalData, Interop.Elementary.Elm_Object_Item_Signal_Cb> _signalDatas = new Dictionary<SignalData, Interop.Elementary.Elm_Object_Item_Signal_Cb>();
36         EvasObject _trackObject = null;
37
38         /// <summary>
39         /// Creates and initializes a new instance of the ItemObject class.
40         /// </summary>
41         /// <param name="handle">IntPtr</param>
42         /// <since_tizen> preview </since_tizen>
43         protected ItemObject(IntPtr handle)
44         {
45             _deleteCallback = DeleteCallbackHandler;
46             Id = GetNextId();
47             s_IdToItemTable[Id] = this;
48             Handle = handle;
49         }
50
51         // C# Finalizer was called on GC thread
52         // So, We can't access to EFL object
53         // And When Finalizer was called, Field can be already released.
54         //~ItemObject()
55         //{
56         //    if (Handle != IntPtr.Zero)
57         //        Interop.Elementary.elm_object_item_del(Handle);
58         //}
59
60         /// <summary>
61         /// Gets the ID of the item object.
62         /// </summary>
63         /// <since_tizen> preview </since_tizen>
64         public int Id { get; private set; }
65
66         /// <summary>
67         /// Sets or gets whether the item object is enabled.
68         /// </summary>
69         /// <since_tizen> preview </since_tizen>
70         public bool IsEnabled
71         {
72             get { return !Interop.Elementary.elm_object_item_disabled_get(Handle); }
73             set { Interop.Elementary.elm_object_item_disabled_set(Handle, !value); }
74         }
75
76         /// <summary>
77         /// Gets the track object of the item.
78         /// </summary>
79         /// <since_tizen> preview </since_tizen>
80         public EvasObject TrackObject
81         {
82             get
83             {
84                 if (_trackObject == null || Interop.Elementary.elm_object_item_track_get(Handle) == 0)
85                 {
86                     _trackObject = new ItemEvasObject(Handle);
87                 }
88                 return _trackObject;
89             }
90         }
91
92         /// <summary>
93         /// Sets or gets the style of the item.
94         /// </summary>
95         /// <since_tizen> preview </since_tizen>
96         public virtual string Style
97         {
98             get
99             {
100                 return Interop.Elementary.elm_object_item_style_get(Handle);
101             }
102             set
103             {
104                 Interop.Elementary.elm_object_item_style_set(Handle, value);
105             }
106         }
107
108         internal IntPtr Handle
109         {
110             get
111             {
112                 return _handle;
113             }
114             set
115             {
116                 if (_handle == value)
117                     return;
118
119                 if (_handle != IntPtr.Zero)
120                 {
121                     UnsetDeleteCallback();
122                 }
123                 _handle = value;
124                 SetDeleteCallback();
125                 s_HandleToItemTable[Handle] = this;
126             }
127         }
128
129         /// <summary>
130         /// Deleted will be triggered when the item object is deleted.
131         /// </summary>
132         /// <since_tizen> preview </since_tizen>
133         public event EventHandler Deleted;
134
135         /// <summary>
136         /// Deletes the item object.
137         /// </summary>
138         /// <since_tizen> preview </since_tizen>
139         public void Delete()
140         {
141             Interop.Elementary.elm_object_item_del(Handle);
142             _handle = IntPtr.Zero;
143         }
144
145         /// <summary>
146         /// Sets a content of an object item and deletes the old content.
147         /// </summary>
148         /// <param name="part">The content part name (null for the default content).</param>
149         /// <param name="content">The content of the object item.</param>
150         /// <since_tizen> preview </since_tizen>
151         public void SetPartContent(string part, EvasObject content)
152         {
153             SetPartContent(part, content, false);
154         }
155
156         /// <summary>.
157         /// Sets a content of the object item.
158         /// </summary>
159         /// <param name="part">The content part name (null for the default content)</param>
160         /// <param name="content">The content of the object item.</param>
161         /// <param name="preserveOldContent">Judge whether to delete the old content.</param>
162         /// <since_tizen> preview </since_tizen>
163         public void SetPartContent(string part, EvasObject content, bool preserveOldContent)
164         {
165             IntPtr oldContent = Interop.Elementary.elm_object_item_part_content_unset(Handle, part);
166             if (oldContent != IntPtr.Zero && !preserveOldContent)
167             {
168                 Interop.Evas.evas_object_del(oldContent);
169             }
170             Interop.Elementary.elm_object_item_part_content_set(Handle, part, content);
171             _partContents[part ?? "__default__"] = content;
172         }
173
174         /// <summary>
175         /// Sets the label of the object item.
176         /// </summary>
177         /// <param name="part">The text part name (null for the default label).</param>
178         /// <param name="text">Text of the label.</param>
179         /// <since_tizen> preview </since_tizen>
180         public void SetPartText(string part, string text)
181         {
182             Interop.Elementary.elm_object_item_part_text_set(Handle, part, text);
183         }
184
185         /// <summary>
186         /// Gets the label of the object item.
187         /// </summary>
188         /// <param name="part">The text part name (null for the default label).</param>
189         /// <returns></returns>
190         /// <since_tizen> preview </since_tizen>
191         public string GetPartText(string part)
192         {
193             return Interop.Elementary.elm_object_item_part_text_get(Handle, part);
194         }
195
196         /// <summary>
197         /// Sets the color of the object item.
198         /// </summary>
199         /// <param name="part">The text part name (null for the default label).</param>
200         /// <param name="color">The color.</param>
201         /// <since_tizen> preview </since_tizen>
202         public void SetPartColor(string part, Color color)
203         {
204             Interop.Elementary.elm_object_item_color_class_color_set(Handle, part, color.R * color.A / 255,
205                                                                               color.G * color.A / 255,
206                                                                               color.B * color.A / 255,
207                                                                               color.A);
208         }
209
210         /// <summary>
211         /// Gets the color of the object item.
212         /// </summary>
213         /// <param name="part">The text part name (null for the default label).</param>
214         /// <returns>The color of an object item.</returns>
215         /// <since_tizen> preview </since_tizen>
216         public Color GetPartColor(string part)
217         {
218             int r, g, b, a;
219             Interop.Elementary.elm_object_item_color_class_color_get(Handle, part, out r, out g, out b, out a);
220             return new Color((int)(r / (a / 255.0)), (int)(g / (a / 255.0)), (int)(b / (a / 255.0)), a);
221         }
222
223         /// <summary>
224         /// Deletes the color of the object item.
225         /// </summary>
226         /// <param name="part">The text part name.</param>
227         /// <since_tizen> preview </since_tizen>
228         public void DeletePartColor(string part)
229         {
230             Interop.Elementary.elm_object_item_color_class_del(Handle, part);
231         }
232
233         /// <summary>
234         /// Adds a function for a signal emitted by the object item edje.
235         /// </summary>
236         /// <param name="emission">The signal's name.</param>
237         /// <param name="source">The signal's source.</param>
238         /// <param name="func">The function to be executed when the signal is emitted.</param>
239         /// <since_tizen> preview </since_tizen>
240         public void AddSignalHandler(string emission, string source, Func<string, string, bool> func)
241         {
242             if (emission != null && source != null && func != null)
243             {
244                 var signalData = new SignalData(emission, source, func);
245                 if (!_signalDatas.ContainsKey(signalData))
246                 {
247                     var signalCallback = new Interop.Elementary.Elm_Object_Item_Signal_Cb((d, o, e, s) =>
248                     {
249                         return func(e, s);
250                     });
251                     Interop.Elementary.elm_object_item_signal_callback_add(Handle, emission, source, signalCallback, IntPtr.Zero);
252                 }
253             }
254         }
255
256         /// <summary>
257         /// Removes a signal-triggered function from the object item edje object.
258         /// </summary>
259         /// <param name="emission">The signal's name.</param>
260         /// <param name="source">The signal's source.</param>
261         /// <param name="func">The function to be executed when the signal is emitted.</param>
262         /// <since_tizen> preview </since_tizen>
263         public void RemoveSignalHandler(string emission, string source, Func<string, string, bool> func)
264         {
265             if (emission != null && source != null && func != null)
266             {
267                 var signalData = new SignalData(emission, source, func);
268
269                 Interop.Elementary.Elm_Object_Item_Signal_Cb signalCallback = null;
270                 _signalDatas.TryGetValue(signalData, out signalCallback);
271
272                 if (signalCallback != null)
273                 {
274                     Interop.Elementary.elm_object_item_signal_callback_del(Handle, emission, source, signalCallback);
275                     _signalDatas.Remove(signalData);
276                 }
277             }
278         }
279
280         /// <summary>
281         /// Send a signal to the edje object of the widget item.
282         /// </summary>
283         /// <param name="emission">The signal's name.</param>
284         /// <param name="source">The signal's source.</param>
285         /// <since_tizen> preview </since_tizen>
286         public void EmitSignal(string emission, string source)
287         {
288             Interop.Elementary.elm_object_item_signal_emit(Handle, emission, source);
289         }
290
291         /// <summary>
292         /// Gets the handle of the object item.
293         /// </summary>
294         /// <param name="obj">ItemObject</param>
295         /// <since_tizen> preview </since_tizen>
296         public static implicit operator IntPtr(ItemObject obj)
297         {
298             if (obj == null)
299                 return IntPtr.Zero;
300             return obj.Handle;
301         }
302
303         /// <summary>
304         /// OnInvalidate of the object item.
305         /// </summary>
306         /// <since_tizen> preview </since_tizen>
307         protected virtual void OnInvalidate() { }
308
309         internal static ItemObject GetItemById(int id)
310         {
311             ItemObject value;
312             s_IdToItemTable.TryGetValue(id, out value);
313             return value;
314         }
315
316         internal static ItemObject GetItemByHandle(IntPtr handle)
317         {
318             ItemObject value;
319             s_HandleToItemTable.TryGetValue(handle, out value);
320             return value;
321         }
322
323         void DeleteCallbackHandler(IntPtr data, IntPtr obj, IntPtr info)
324         {
325             Deleted?.Invoke(this, EventArgs.Empty);
326             OnInvalidate();
327             if (s_IdToItemTable.ContainsKey(Id))
328             {
329                 s_IdToItemTable.Remove(Id);
330             }
331             if (s_HandleToItemTable.ContainsKey(_handle))
332             {
333                 s_HandleToItemTable.Remove(_handle);
334             }
335             _partContents.Clear();
336             _handle = IntPtr.Zero;
337         }
338
339         void UnsetDeleteCallback()
340         {
341             Interop.Elementary.elm_object_item_del_cb_set(Handle, null);
342         }
343
344         void SetDeleteCallback()
345         {
346             if (Handle != IntPtr.Zero)
347                 Interop.Elementary.elm_object_item_del_cb_set(Handle, _deleteCallback);
348         }
349
350         static int GetNextId()
351         {
352             return s_globalId++;
353         }
354
355         class SignalData
356         {
357             public string Emission { get; set; }
358             public string Source { get; set; }
359             public Func<string, string, bool> Func { get; set; }
360
361             public SignalData(string emission, string source, Func<string, string, bool> func)
362             {
363                 Emission = emission;
364                 Source = source;
365                 Func = func;
366             }
367
368             /// <summary>
369             /// Indicates whether this instance and a specified object are equal.
370             /// </summary>
371             /// <param name="obj">The object to compare with the current instance.</param>
372             /// <returns>
373             /// true if the object and this instance are of the same type and represent the same value,
374             /// otherwise false.
375             /// </returns>
376             public override bool Equals(object obj)
377             {
378                 SignalData s = obj as SignalData;
379                 if (s == null)
380                 {
381                     return false;
382                 }
383                 return (Emission == s.Emission) && (Source == s.Source) && (Func == s.Func);
384             }
385
386             public override int GetHashCode()
387             {
388                 int hashCode = Emission.GetHashCode();
389                 hashCode ^= Source.GetHashCode();
390                 hashCode ^= Func.GetHashCode();
391                 return hashCode;
392             }
393         }
394
395         class ItemEvasObject : EvasObject
396         {
397             IntPtr _trackHandle = IntPtr.Zero;
398
399             /// <summary>
400             /// Creates and initializes a new instance of the ItemEvasObject class.
401             /// </summary>
402             /// <param name="parent">IntPtr</param>
403             public ItemEvasObject(IntPtr parent) : base()
404             {
405                 _trackHandle = Interop.Elementary.elm_object_item_track(parent);
406                 if (_trackHandle != IntPtr.Zero)
407                 {
408                     Realize(null);
409                 }
410             }
411
412             /// <summary>
413             /// Creates a widget handle.
414             /// </summary>
415             /// <param name="parent">Parent EvasObject.</param>
416             /// <returns>Handle IntPtr.</returns>
417             protected override IntPtr CreateHandle(EvasObject parent)
418             {
419                 return _trackHandle;
420             }
421         }
422     }
423 }