Merge "Add missing methods to ContextPopup" into tizen
[platform/core/csapi/tizenfx.git] / src / ElmSharp / ElmSharp / EvasObject.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 using System.Diagnostics;
20
21 namespace ElmSharp
22 {
23     public abstract class EvasObject
24     {
25         private IntPtr _realHandle = IntPtr.Zero;
26         internal IntPtr Handle { get; set; }
27         internal EvasObject Parent { get; set; }
28         internal IntPtr RealHandle
29         {
30             get
31             {
32                 return _realHandle == IntPtr.Zero ? Handle : _realHandle;
33             }
34             set
35             {
36                 _realHandle = value;
37             }
38         }
39
40         EvasObjectEvent _deleted;
41         EvasObjectEvent<EvasKeyEventArgs> _keyup;
42         EvasObjectEvent<EvasKeyEventArgs> _keydown;
43         EvasObjectEvent _moved;
44         EvasObjectEvent _resized;
45         EvasObjectEvent _renderPost;
46
47         readonly HashSet<IInvalidatable> _eventStore = new HashSet<IInvalidatable>();
48
49         protected EvasObject(EvasObject parent) : this()
50         {
51             Debug.Assert(parent == null || parent.IsRealized);
52             Realize(parent);
53         }
54
55         protected EvasObject()
56         {
57             OnInstantiated();
58         }
59
60         // C# Finalizer was called on GC thread
61         // So, We can't access to EFL object
62         // And When Finalizer was called, Field can be already released.
63         //~EvasObject()
64         //{
65         //    Unrealize();
66         //}
67
68         public event EventHandler Deleted;
69         public event EventHandler<EvasKeyEventArgs> KeyUp;
70         public event EventHandler<EvasKeyEventArgs> KeyDown;
71         public event EventHandler Moved
72         {
73             add { _moved.On += value; }
74             remove { _moved.On -= value; }
75         }
76         public event EventHandler Resized
77         {
78             add { _resized.On += value; }
79             remove { _resized.On -= value; }
80         }
81
82         public event EventHandler RenderPost
83         {
84             add { _renderPost.On += value; }
85             remove { _renderPost.On -= value; }
86         }
87
88         public bool IsRealized { get { return Handle != IntPtr.Zero; } }
89
90         public string ClassName
91         {
92             get
93             {
94                 return Interop.Eo.eo_class_name_get(Interop.Eo.eo_class_get(RealHandle));
95             }
96         }
97
98         public double WeightX
99         {
100             get
101             {
102                 return Interop.Evas.GetWeightX(Handle);
103             }
104             set
105             {
106                 Interop.Evas.SetWeightX(Handle, value);
107             }
108         }
109
110         public double WeightY
111         {
112             get
113             {
114                 return Interop.Evas.GetWeightY(Handle);
115             }
116             set
117             {
118                 Interop.Evas.SetWeightY(Handle, value);
119             }
120         }
121
122         public virtual double AlignmentX
123         {
124             get
125             {
126                 return Interop.Evas.GetAlignX(Handle);
127             }
128             set
129             {
130                 Interop.Evas.SetAlignX(Handle, value);
131             }
132         }
133
134         public virtual double AlignmentY
135         {
136             get
137             {
138                 return Interop.Evas.GetAlignY(Handle);
139             }
140             set
141             {
142                 Interop.Evas.SetAlignY(Handle, value);
143             }
144         }
145
146         public int MinimumWidth
147         {
148             get
149             {
150                 int w, h;
151                 Interop.Evas.evas_object_size_hint_min_get(RealHandle, out w, out h);
152                 return w;
153             }
154             set
155             {
156                 int h = MinimumHeight;
157                 Interop.Evas.evas_object_size_hint_min_set(RealHandle, value, h);
158             }
159         }
160
161         public int MinimumHeight
162         {
163             get
164             {
165                 int w, h;
166                 Interop.Evas.evas_object_size_hint_min_get(RealHandle, out w, out h);
167                 return h;
168             }
169             set
170             {
171                 int w = MinimumWidth;
172                 Interop.Evas.evas_object_size_hint_min_set(RealHandle, w, value);
173             }
174         }
175
176         public bool IsVisible
177         {
178             get
179             {
180                 return Interop.Evas.evas_object_visible_get(Handle);
181             }
182         }
183
184         public Rect Geometry
185         {
186             get
187             {
188                 int x, y, w, h;
189                 Interop.Evas.evas_object_geometry_get(Handle, out x, out y, out w, out h);
190                 Rect rect = new Rect(x, y, w, h);
191                 return rect;
192             }
193             set
194             {
195                 Interop.Evas.evas_object_geometry_set(Handle, value.X, value.Y, value.Width, value.Height);
196             }
197         }
198
199         public virtual Color Color
200         {
201             get
202             {
203                 int r, g, b, a;
204                 Interop.Evas.evas_object_color_get(RealHandle, out r, out g, out b, out a);
205                 return Color.FromRgba(r, g, b, a);
206             }
207             set
208             {
209                 Interop.Evas.SetPremultipliedColor(RealHandle, value.R, value.G, value.B, value.A);
210             }
211         }
212
213         public bool IsMapEnabled
214         {
215             get
216             {
217                 return Interop.Evas.evas_object_map_enable_get(Handle);
218             }
219             set
220             {
221                 Interop.Evas.evas_object_map_enable_set(Handle, value);
222             }
223         }
224
225         public EvasMap EvasMap
226         {
227             get
228             {
229                 IntPtr evasMap = Interop.Evas.evas_object_map_get(Handle);
230                 return new EvasMap(evasMap);
231             }
232             set
233             {
234                 Interop.Evas.evas_object_map_set(Handle, value.Handle);
235             }
236         }
237
238         public bool RepeatEvents
239         {
240             get
241             {
242                 return Interop.Evas.evas_object_repeat_events_get(RealHandle);
243             }
244             set
245             {
246                 Interop.Evas.evas_object_repeat_events_set(RealHandle, value);
247             }
248         }
249
250         public bool PropagateEvents
251         {
252             get
253             {
254                 return Interop.Evas.evas_object_propagate_events_get(RealHandle);
255             }
256             set
257             {
258                 Interop.Evas.evas_object_propagate_events_set(RealHandle, value);
259             }
260         }
261
262         public bool PassEvents
263         {
264             get
265             {
266                 return Interop.Evas.evas_object_pass_events_get(RealHandle);
267             }
268             set
269             {
270                 Interop.Evas.evas_object_pass_events_set(RealHandle, value);
271             }
272         }
273
274         public void SetClip(EvasObject clip)
275         {
276             Interop.Evas.evas_object_clip_set(Handle, clip);
277         }
278
279         public void SetAlignment(double x, double y)
280         {
281             Interop.Evas.evas_object_size_hint_align_set(Handle, x, y);
282         }
283
284         public void SetWeight(double x, double y)
285         {
286             Interop.Evas.evas_object_size_hint_weight_set(Handle, x, y);
287         }
288
289         public void Show()
290         {
291             Interop.Evas.evas_object_show(Handle);
292         }
293
294         public void Hide()
295         {
296             Interop.Evas.evas_object_hide(Handle);
297         }
298
299         public void Resize(int w, int h)
300         {
301             Interop.Evas.evas_object_resize(Handle, w, h);
302         }
303
304         public void Move(int x, int y)
305         {
306             Interop.Evas.evas_object_move(Handle, x, y);
307         }
308
309         public void Lower()
310         {
311             Interop.Evas.evas_object_lower(Handle);
312         }
313
314         public static implicit operator IntPtr(EvasObject obj)
315         {
316             if (obj == null)
317                 return IntPtr.Zero;
318             return obj.Handle;
319         }
320
321         public bool KeyGrab(string keyname, bool exclusive)
322         {
323             return Interop.Evas.evas_object_key_grab(Handle, keyname, 0, 0, exclusive);
324         }
325
326         public void KeyUngrab(string keyname)
327         {
328             Interop.Evas.evas_object_key_ungrab(Handle, keyname, 0, 0);
329         }
330
331         public void MarkChanged()
332         {
333             Interop.Evas.evas_object_smart_changed(RealHandle);
334         }
335
336         protected virtual void OnInvalidate()
337         {
338         }
339
340         protected virtual void OnInstantiated()
341         {
342         }
343
344         protected virtual void OnRealized()
345         {
346         }
347
348         protected virtual void OnUnrealize()
349         {
350         }
351
352         protected abstract IntPtr CreateHandle(EvasObject parent);
353
354         public void Realize(EvasObject parent)
355         {
356             if(!IsRealized)
357             {
358                 Parent = parent;
359                 Handle = CreateHandle(parent);
360                 Debug.Assert(Handle != IntPtr.Zero);
361
362                 (parent as Window)?.AddChild(this);
363
364                 OnRealized();
365                 _deleted = new EvasObjectEvent(this, EvasObjectCallbackType.Del);
366                 _keydown = new EvasObjectEvent<EvasKeyEventArgs>(this, EvasObjectCallbackType.KeyDown, EvasKeyEventArgs.Create);
367                 _keyup = new EvasObjectEvent<EvasKeyEventArgs>(this, EvasObjectCallbackType.KeyUp, EvasKeyEventArgs.Create);
368                 _moved = new EvasObjectEvent(this, EvasObjectCallbackType.Move);
369                 _resized = new EvasObjectEvent(this, EvasObjectCallbackType.Resize);
370                 _renderPost = new EvasObjectEvent(this, Interop.Evas.evas_object_evas_get(Handle), EvasObjectCallbackType.RenderPost);
371
372                 _deleted.On += (s, e) => MakeInvalidate();
373                 _keydown.On += (s, e) => KeyDown?.Invoke(this, e);
374                 _keyup.On += (s, e) => KeyUp?.Invoke(this, e);
375             }
376         }
377
378         public void Unrealize()
379         {
380             if (IsRealized)
381             {
382                 OnUnrealize();
383                 IntPtr toBeDeleted = Handle;
384                 Handle = IntPtr.Zero;
385
386                 DisposeEvent();
387
388                 (Parent as Window)?.RemoveChild(this);
389
390                 Interop.Evas.evas_object_del(toBeDeleted);
391                 Parent = null;
392             }
393         }
394
395         private void MakeInvalidate()
396         {
397             Deleted?.Invoke(this, EventArgs.Empty);
398             OnInvalidate();
399             Handle = IntPtr.Zero;
400
401             MakeInvalidateEvent();
402
403             (Parent as Window)?.RemoveChild(this);
404             Parent = null;
405             _deleted = null;
406         }
407
408         private void DisposeEvent()
409         {
410             foreach (var evt in _eventStore)
411             {
412                 evt.Dispose();
413             }
414             _eventStore.Clear();
415         }
416         private void MakeInvalidateEvent()
417         {
418             foreach (var evt in _eventStore)
419             {
420                 evt.MakeInvalidate();
421             }
422             _eventStore.Clear();
423         }
424
425         internal void AddToEventLifeTracker(IInvalidatable item)
426         {
427             _eventStore.Add(item);
428         }
429
430     }
431 }