Fixed issue where key event does not occur when focus is lost (#24)
[platform/core/csapi/tizenfx.git] / src / ElmSharp / ElmSharp / Widget.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 ElmSharp.Accessible;
20
21 namespace ElmSharp
22 {
23     /// <summary>
24     /// Enumeration for the focus direction.
25     /// </summary>
26     /// <since_tizen> preview </since_tizen>
27     public enum FocusDirection
28     {
29         /// <summary>
30         /// Previous direction.
31         /// </summary>
32         Previous,
33
34         /// <summary>
35         /// Next direction.
36         /// </summary>
37         Next,
38
39         /// <summary>
40         /// Up direction.
41         /// </summary>
42         Up,
43
44         /// <summary>
45         /// Down direction.
46         /// </summary>
47         Down,
48
49         /// <summary>
50         /// Right direction.
51         /// </summary>
52         Right,
53
54         /// <summary>
55         /// Left direction.
56         /// </summary>
57         Left
58     }
59
60     /// <summary>
61     /// The Widget is an abstract class and the parent of other widgets.
62     /// Inherits from <see cref="EvasObject"/>.
63     /// </summary>
64     /// <since_tizen> preview </since_tizen>
65     public abstract class Widget : AccessibleObject
66     {
67         Dictionary<string, EvasObject> _partContents = new Dictionary<string, EvasObject>();
68
69         SmartEvent _focused;
70         SmartEvent _unfocused;
71
72         internal Color _backgroundColor = Color.Default;
73         internal int _opacity = Color.Default.A;
74
75         /// <summary>
76         /// Creates and initializes a new instance of the Widget class.
77         /// </summary>
78         /// <since_tizen> preview </since_tizen>
79         protected Widget()
80         {
81         }
82
83         /// <summary>
84         /// Creates and initializes a new instance of the Widget class.
85         /// </summary>
86         /// <param name="parent">The parent of the new Widget instance.</param>
87         /// <since_tizen> preview </since_tizen>
88         protected Widget(EvasObject parent) : base(parent)
89         {
90         }
91
92         /// <summary>
93         /// Updates the part contents.
94         /// </summary>
95         /// <param name="content">The content which is put into the part.</param>
96         /// <param name="part">The updated part.</param>
97         /// <since_tizen> preview </since_tizen>
98         protected void UpdatePartContents(EvasObject content, string part = "__default__")
99         {
100             _partContents[part] = content;
101         }
102
103         /// <summary>
104         /// Focused will be triggered when the widget is focused.
105         /// </summary>
106         /// <since_tizen> preview </since_tizen>
107         public event EventHandler Focused;
108
109         /// <summary>
110         /// Unfocused will be triggered when the widget is unfocused.
111         /// </summary>
112         /// <since_tizen> preview </since_tizen>
113         public event EventHandler Unfocused;
114
115         /// <summary>
116         /// Sets or gets the state of the widget, which might be enabled or disabled.
117         /// </summary>
118         /// <since_tizen> preview </since_tizen>
119         public virtual bool IsEnabled
120         {
121             get
122             {
123                 return !Interop.Elementary.elm_object_disabled_get(RealHandle);
124             }
125             set
126             {
127                 Interop.Elementary.elm_object_disabled_set(RealHandle, !value);
128             }
129         }
130
131         /// <summary>
132         /// Sets or gets the style of the widget.
133         /// </summary>
134         /// <since_tizen> preview </since_tizen>
135         public string Style
136         {
137             get
138             {
139                 return Interop.Elementary.elm_object_style_get(RealHandle);
140             }
141             set
142             {
143                 Interop.Elementary.elm_object_style_set(RealHandle, value);
144             }
145         }
146
147         /// <summary>
148         /// Gets whether this widget is focused.
149         /// </summary>
150         /// <since_tizen> preview </since_tizen>
151         public bool IsFocused
152         {
153             get
154             {
155                 return Interop.Elementary.elm_object_focus_get(RealHandle);
156             }
157         }
158
159         /// <summary>
160         /// Gets whether a widget is focusable or not.
161         /// </summary>
162         /// <remarks>Widgets which are meant to be interacted with by input events, are created able to be focused by default.</remarks>
163         /// <since_tizen> preview </since_tizen>
164         public bool IsFocusAllowed
165         {
166             get
167             {
168                 return Interop.Elementary.elm_object_focus_allow_get(RealHandle);
169             }
170         }
171
172         /// <summary>
173         /// Sets or gets the text of the widget.
174         /// </summary>
175         /// <remarks>It could be overridden by special child class.</remarks>
176         /// <since_tizen> preview </since_tizen>
177         public virtual string Text
178         {
179             get
180             {
181                 return Interop.Elementary.elm_object_part_text_get(RealHandle);
182             }
183             set
184             {
185                 Interop.Elementary.elm_object_part_text_set(RealHandle, IntPtr.Zero, value);
186             }
187         }
188
189         /// <summary>
190         /// Sets or gets the background color of the widget.
191         /// </summary>
192         /// <remarks>It could be overridden by special child class.</remarks>
193         /// <since_tizen> preview </since_tizen>
194         public virtual Color BackgroundColor
195         {
196             get
197             {
198                 if (!_backgroundColor.IsDefault)
199                 {
200                     _backgroundColor = GetPartColor("bg");
201                 }
202                 return _backgroundColor;
203             }
204             set
205             {
206                 if (value.IsDefault)
207                 {
208                     Console.WriteLine("Widget instance doesn't support to set BackgroundColor to Color.Default.");
209                 }
210                 else
211                 {
212                     SetPartColor("bg", value);
213                     _backgroundColor = value;
214                 }
215             }
216         }
217
218         /// <summary>
219         /// Sets or gets the opacity of the widget.
220         /// </summary>
221         /// <remarks>It could be overridden by special child class.</remarks>
222         /// <since_tizen> preview </since_tizen>
223         public virtual int Opacity
224         {
225             get
226             {
227                 if (_opacity != Color.Default.A)
228                 {
229                     _opacity = GetPartOpacity("opacity");
230                 }
231                 return _opacity;
232             }
233             set
234             {
235                 SetPartOpacity("opacity", value);
236                 _opacity = value;
237             }
238         }
239
240         /// <summary>
241         /// Sets or gets whether a widget and its children are focusable or not.
242         /// </summary>
243         /// <since_tizen> preview </since_tizen>
244         public bool AllowTreeFocus
245         {
246             get
247             {
248                 return Interop.Elementary.elm_object_tree_focus_allow_get(RealHandle);
249             }
250             set
251             {
252                 Interop.Elementary.elm_object_tree_focus_allow_set(RealHandle, value);
253             }
254         }
255
256         /// <summary>
257         /// Sets or gets the widget's mirrored mode.
258         /// </summary>
259         /// <since_tizen> preview </since_tizen>
260         public bool IsMirroredMode
261         {
262             get
263             {
264                 return Interop.Elementary.elm_object_mirrored_get(RealHandle);
265             }
266             set
267             {
268                 Interop.Elementary.elm_object_mirrored_set(RealHandle, value);
269             }
270         }
271
272         /// <summary>
273         /// Sets or gets the widget's mirrored mode setting.
274         /// When widget is set to automatic mode(true), it follows the system mirrored mode.
275         /// </summary>
276         /// <since_tizen> preview </since_tizen>
277         public bool IsAutoMirroredMode
278         {
279             get
280             {
281                 return Interop.Elementary.elm_object_mirrored_automatic_get(RealHandle);
282             }
283             set
284             {
285                 Interop.Elementary.elm_object_mirrored_automatic_set(RealHandle, value);
286             }
287         }
288
289         /// <summary>
290         /// Sets the widget to be focused or not.
291         /// </summary>
292         /// <param name="isFocus">Whether be focused.</param>
293         /// <since_tizen> preview </since_tizen>
294         public void SetFocus(bool isFocus)
295         {
296             Interop.Elementary.elm_object_focus_set(RealHandle, isFocus);
297
298             // Temporary code due to focus issue (will be removed at Tizen 5.0)
299             if (this is Window)
300             {
301                 if (isFocus && !Interop.Evas.evas_object_focus_get(RealHandle))
302                     Interop.Evas.evas_object_focus_set(RealHandle, true);
303             }
304         }
305
306         /// <summary>
307         /// Sets the ability for a widget to be focused.
308         /// </summary>
309         /// <param name="isAllowFocus">true if the object can be focused, false if not(and on errors).</param>
310         /// <since_tizen> preview </since_tizen>
311         public void AllowFocus(bool isAllowFocus)
312         {
313             Interop.Elementary.elm_object_focus_allow_set(RealHandle, isAllowFocus);
314         }
315
316         /// <summary>
317         /// Gives focus to the next widget in the widget tree.
318         /// </summary>
319         /// <param name="direction">Direction to move the focus.</param>
320         /// <since_tizen> preview </since_tizen>
321         public void FocusNext(FocusDirection direction)
322         {
323             Interop.Elementary.elm_object_focus_next(RealHandle, (int)direction);
324         }
325
326         /// <summary>
327         /// Sets the next widget with specific focus direction.
328         /// </summary>
329         /// <param name="next">Focus next widget.</param>
330         /// <param name="direction">Focus direction.</param>
331         /// <since_tizen> preview </since_tizen>
332         public void SetNextFocusObject(EvasObject next, FocusDirection direction)
333         {
334             Interop.Elementary.elm_object_focus_next_object_set(RealHandle, next.RealHandle, (int)direction);
335         }
336
337         /// <summary>
338         /// Sets content to the particular part of the widget, and the preserve old content will not be unset.
339         /// </summary>
340         /// <param name="part">The name of the particular part.</param>
341         /// <param name="content">The content.</param>
342         /// <seealso cref="SetPartContent(string, EvasObject, bool)"/>
343         /// <since_tizen> preview </since_tizen>
344         public virtual bool SetPartContent(string part, EvasObject content)
345         {
346             return SetPartContent(part, content, false);
347         }
348
349         /// <summary>
350         /// Sets content to the particular part of the widget.
351         /// </summary>
352         /// <param name="part">The name of the particular part.</param>
353         /// <param name="content">The content.</param>
354         /// <param name="preserveOldContent">true, preserve old content will be unset. false, preserve old content will not be unset.</param>
355         /// <seealso cref="SetPartContent(string, EvasObject)"/>
356         /// <since_tizen> preview </since_tizen>
357         public virtual bool SetPartContent(string part, EvasObject content, bool preserveOldContent)
358         {
359             if (preserveOldContent)
360             {
361                 Interop.Elementary.elm_object_part_content_unset(RealHandle, part);
362             }
363             Interop.Elementary.elm_object_part_content_set(RealHandle, part, content);
364             UpdatePartContents(content, part);
365             return true;
366         }
367
368         /// <summary>
369         /// Sets content to the widget, and the preserve old content will not be unset.
370         /// </summary>
371         /// <param name="content">The content.</param>
372         /// <seealso cref="SetContent(EvasObject, bool)"/>
373         /// <since_tizen> preview </since_tizen>
374         public void SetContent(EvasObject content)
375         {
376             SetContent(content, false);
377         }
378
379         /// <summary>
380         /// Sets content to the widget.
381         /// </summary>
382         /// <param name="content">The content.</param>
383         /// <param name="preserveOldContent">true, preserve old content will be unset. false, preserve old content will not be unset.</param>
384         /// <seealso cref="SetContent(EvasObject)"/>
385         /// <since_tizen> preview </since_tizen>
386         public void SetContent(EvasObject content, bool preserveOldContent)
387         {
388             if (preserveOldContent)
389             {
390                 Interop.Elementary.elm_object_content_unset(RealHandle);
391             }
392
393             Interop.Elementary.elm_object_content_set(RealHandle, content);
394             UpdatePartContents(content);
395         }
396
397         /// <summary>
398         /// Sets text to the particular part of the widget.
399         /// </summary>
400         /// <param name="part">The name of the particular part.</param>
401         /// <param name="text">The text.</param>
402         /// <since_tizen> preview </since_tizen>
403         public virtual bool SetPartText(string part, string text)
404         {
405             Interop.Elementary.elm_object_part_text_set(RealHandle, part, text);
406             return true;
407         }
408
409         /// <summary>
410         /// Gets text of a particular part of the widget.
411         /// </summary>
412         /// <param name="part">The name of the particular part.</param>
413         /// <returns>Text of the particular part of the widget.</returns>
414         /// <since_tizen> preview </since_tizen>
415         public virtual string GetPartText(string part)
416         {
417             return Interop.Elementary.elm_object_part_text_get(RealHandle, part);
418         }
419
420         /// <summary>
421         /// Sets color of a particular part of the widget.
422         /// </summary>
423         /// <param name="part">The name of the particular part.</param>
424         /// <param name="color">The color to be set to the widget.</param>
425         /// <remarks>This method is a virtual method, it could be overridden by special child class.</remarks>
426         /// <since_tizen> preview </since_tizen>
427         public virtual void SetPartColor(string part, Color color)
428         {
429             Interop.Elementary.elm_object_color_class_color_set(RealHandle, part, color.R * color.A / 255,
430                                                                               color.G * color.A / 255,
431                                                                               color.B * color.A / 255,
432                                                                               color.A);
433         }
434
435         /// <summary>
436         /// Gets color of the particular part of the widget.
437         /// </summary>
438         /// <param name="part">The name of the particular part.</param>
439         /// <returns>The color of the particular part.</returns>
440         /// <remarks>This method is a virtual method, it could be overridden by special child class.</remarks>
441         /// <since_tizen> preview </since_tizen>
442         public virtual Color GetPartColor(string part)
443         {
444             int r, g, b, a;
445             Interop.Elementary.elm_object_color_class_color_get(RealHandle, part, out r, out g, out b, out a);
446             return new Color((int)(r / (a / 255.0)), (int)(g / (a / 255.0)), (int)(b / (a / 255.0)), a);
447         }
448
449         /// <summary>
450         /// Sets opacity of the particular part of the widget.
451         /// </summary>
452         /// <param name="part">The name of the particular part.</param>
453         /// <param name="opacity">The opacity of the particular part.</param>
454         /// <since_tizen> preview </since_tizen>
455         public void SetPartOpacity(string part, int opacity)
456         {
457             Interop.Elementary.elm_object_color_class_color_set(Handle, part, 255, 255, 255, opacity);
458         }
459
460         /// <summary>
461         /// Gets opacity of the particular part of the widget.
462         /// </summary>
463         /// <param name="part">The name of the particular part.</param>
464         /// <returns>Opacity value of the particular part.</returns>
465         /// <since_tizen> preview </since_tizen>
466         public int GetPartOpacity(string part)
467         {
468             int r, g, b, a;
469             Interop.Elementary.elm_object_color_class_color_get(Handle, part, out r, out g, out b, out a);
470             return a;
471         }
472
473         /// <summary>
474         /// Sends a signal to the edje object of the widget.
475         /// </summary>
476         /// <param name="emission">The signal's name.</param>
477         /// <param name="source">The signal's source.</param>
478         /// <since_tizen> preview </since_tizen>
479         public void SignalEmit(string emission, string source)
480         {
481             Interop.Elementary.elm_object_signal_emit(Handle, emission, source);
482         }
483
484         /// <summary>
485         /// The callback of the Realized event.
486         /// </summary>
487         /// <since_tizen> preview </since_tizen>
488         protected override void OnRealized()
489         {
490             base.OnRealized();
491             _focused = new SmartEvent(this, "focused");
492             _focused.On += (s, e) => Focused?.Invoke(this, EventArgs.Empty);
493
494             _unfocused = new SmartEvent(this, "unfocused");
495             _unfocused.On += (s, e) => Unfocused?.Invoke(this, EventArgs.Empty);
496         }
497
498         internal IntPtr GetPartContent(string part)
499         {
500             return Interop.Elementary.elm_object_part_content_get(RealHandle, part);
501         }
502     }
503 }