66e2f4300d124aadb1c4dc3cffea813adb2c3e43
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI.CommonUI / Controls / Control.cs
1 /*
2  * Copyright(c) 2019 Samsung Electronics Co., Ltd.
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.ComponentModel;
20 using Tizen.NUI.BaseComponents;
21
22 namespace Tizen.NUI.CommonUI
23 {
24     /// <summary>
25     /// The control component is base class of tv nui components. It's abstract class, so cann't instantiate and can only be inherited.
26     /// </summary>
27     /// <since_tizen> 6 </since_tizen>
28     /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
29     [EditorBrowsable(EditorBrowsableState.Never)]
30     public abstract class Control : VisualView
31     {
32         /// <summary>
33         /// Control style.
34         /// </summary>
35         /// <since_tizen> 6 </since_tizen>
36         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
37         [EditorBrowsable(EditorBrowsableState.Never)]
38         protected string style;
39         /// <summary>
40         /// Control attributes.
41         /// </summary>
42         /// <since_tizen> 6 </since_tizen>
43         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
44         [EditorBrowsable(EditorBrowsableState.Never)]
45         protected Attributes attributes;
46
47         private TapGestureDetector tapGestureDetector = new TapGestureDetector();
48         private bool isFocused = false;
49
50         /// <summary>
51         /// Construct an empty Control.
52         /// </summary>
53         /// <since_tizen> 6 </since_tizen>
54         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
55         [EditorBrowsable(EditorBrowsableState.Never)]
56         public Control() : base()
57         {
58             Initialize(null);
59         }
60
61         /// <summary>
62         /// Construct with attributes
63         /// </summary>
64         /// <param name="attributes">Create attributes customized by user</param>
65         /// <since_tizen> 6 </since_tizen>
66         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
67         [EditorBrowsable(EditorBrowsableState.Never)]
68         public Control(Attributes attributes) : base()
69         {
70             Initialize(null);
71             this.attributes = attributes.Clone();
72         }
73
74         /// <summary>
75         /// Construct with style
76         /// </summary>
77         /// <param name="style">Style to be applied</param>
78         /// <since_tizen> 6 </since_tizen>
79         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
80         [EditorBrowsable(EditorBrowsableState.Never)]
81         public Control(string style) : base()
82         {
83             Initialize(style);
84         }
85
86         /// <summary>
87         /// Get/Set the control state.
88         /// </summary>
89         /// <since_tizen> 6 </since_tizen>
90         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
91         [EditorBrowsable(EditorBrowsableState.Never)]
92         public new ControlStates State
93         {
94             get;
95             set;
96         }
97         /// <summary>
98         /// Whether focusable when touch
99         /// </summary>
100         /// <since_tizen> 6 </since_tizen>
101         internal bool StateFocusableOnTouchMode
102         {
103             get;
104             set;
105         }
106
107         internal bool IsFocused
108         {
109             get
110             {
111                 return isFocused || HasFocus();
112             }
113         }
114         /// <summary>
115         /// Apply attributes for View, Image or TextLabel.
116         /// </summary>
117         /// <param name="view">View which will be applied attrs</param>
118         /// <param name="attrs">Attributes for View, Image or TextLabel</param>
119         /// <since_tizen> 6 </since_tizen>
120         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
121         [EditorBrowsable(EditorBrowsableState.Never)]
122         protected  void ApplyAttributes(View view, ViewAttributes attrs)
123         {
124             if (view == null || attrs == null)
125             {
126                 return;
127             }
128
129             if (attrs.Position2D != null)
130             {
131                 view.Position2D = attrs.Position2D;
132             }
133             if (attrs.Size2D != null)
134             {
135                 view.Size2D = attrs.Size2D;
136             }
137             if (attrs.MinimumSize != null)
138             {
139                 view.MinimumSize = attrs.MinimumSize;
140             }
141             if (attrs.BackgroundColor?.GetValue(State) != null)
142             {
143                 view.BackgroundColor = attrs.BackgroundColor.GetValue(State);
144             }
145             if (attrs.PositionUsesPivotPoint != null)
146             {
147                 view.PositionUsesPivotPoint = attrs.PositionUsesPivotPoint.Value;
148             }
149             if (attrs.ParentOrigin != null)
150             {
151                 view.ParentOrigin = attrs.ParentOrigin;
152             }
153             if (attrs.PivotPoint != null)
154             {
155                 view.PivotPoint = attrs.PivotPoint;
156             }
157             if (attrs.WidthResizePolicy!= null)
158             {
159                 view.WidthResizePolicy = attrs.WidthResizePolicy.Value;
160             }
161             if (attrs.HeightResizePolicy != null)
162             {
163                 view.HeightResizePolicy = attrs.HeightResizePolicy.Value;
164             }
165             if (attrs.SizeModeFactor != null)
166             {
167                 view.SizeModeFactor = attrs.SizeModeFactor;
168             }
169             if (attrs.Opacity?.GetValue(State) != null)
170             {
171                 view.Opacity = attrs.Opacity.GetValue(State).Value;
172             }
173
174             ImageView image = view as ImageView;
175             ImageAttributes imageAttrs = attrs as ImageAttributes;
176             if (image != null && imageAttrs != null)
177             {
178                 if (imageAttrs.ResourceURL?.GetValue(State) != null)
179                 {
180                     image.ResourceUrl = imageAttrs.ResourceURL.GetValue(State);
181                 }
182                 if (imageAttrs.Border?.GetValue(State) != null)
183                 {
184                     image.Border = imageAttrs.Border.GetValue(State);
185                 }
186       
187             }
188
189             TextLabel text = view as TextLabel;
190             TextAttributes textAttrs = attrs as TextAttributes;
191             if (text != null && textAttrs != null)
192             {
193                 if (textAttrs.Text?.GetValue(State) != null )
194                 {
195                     text.Text = textAttrs.Text.GetValue(State);
196                 }
197                 if (textAttrs.TranslatableText?.GetValue(State) != null)
198                 {
199                     text.TranslatableText = textAttrs.TranslatableText.GetValue(State);
200                 }
201                 if (textAttrs.MultiLine != null)
202                 {
203                     text.MultiLine = textAttrs.MultiLine.Value;
204                 }
205                 if (textAttrs.HorizontalAlignment != null)
206                 {
207                     text.HorizontalAlignment = textAttrs.HorizontalAlignment.Value;
208                 }
209                 if (textAttrs.VerticalAlignment != null)
210                 {
211                     text.VerticalAlignment = textAttrs.VerticalAlignment.Value;
212                 }
213                 if (textAttrs.EnableMarkup != null)
214                 {
215                     text.EnableMarkup = textAttrs.EnableMarkup.Value;
216                 }
217                 if (textAttrs.AutoScrollLoopCount != null)
218                 {
219                     text.AutoScrollLoopCount = textAttrs.AutoScrollLoopCount.Value;
220                 }
221                 if (textAttrs.AutoScrollSpeed != null)
222                 {
223                     text.AutoScrollSpeed = textAttrs.AutoScrollSpeed.Value;
224                 }
225                 if (textAttrs.AutoScrollGap != null)
226                 {
227                     text.AutoScrollGap = textAttrs.AutoScrollGap.Value;
228                 }
229                 if (textAttrs.AutoScrollLoopDelay != null)
230                 {
231                     text.AutoScrollLoopDelay = textAttrs.AutoScrollLoopDelay.Value;
232                 }
233                 if (textAttrs.AutoScrollStopMode != null)
234                 {
235                     text.AutoScrollStopMode = textAttrs.AutoScrollStopMode.Value;
236                 }
237                 if (textAttrs.LineSpacing != null)
238                 {
239                     text.LineSpacing = textAttrs.LineSpacing.Value;
240                 }
241                 if (textAttrs.TextColor?.GetValue(State) != null)
242                 {
243                     text.TextColor = textAttrs.TextColor.GetValue(State);
244                 }
245                 if (textAttrs.FontFamily != null)
246                 {
247                     text.FontFamily = textAttrs.FontFamily;
248                 }
249                 if (textAttrs.PointSize?.GetValue(State) != null)
250                 {
251                     text.PointSize = textAttrs.PointSize.GetValue(State).Value;
252                 }
253
254                 int thickness = 0;
255
256                 if (textAttrs.OutstrokeThickness?.GetValue(State) != null)
257                 {
258                     thickness = textAttrs.OutstrokeThickness.GetValue(State).Value;
259                 }
260                 if (textAttrs.OutstrokeColor?.GetValue(State) != null)
261                 {
262                     Color outstrokeColor = textAttrs.OutstrokeColor.GetValue(State);
263                     PropertyMap outlineMap = new PropertyMap();
264                     outlineMap.Add("color", new PropertyValue(new Color(outstrokeColor.R, outstrokeColor.G, outstrokeColor.B, outstrokeColor.A)));
265                     outlineMap.Add("width", new PropertyValue(thickness));
266                     text.Outline = outlineMap;
267                 }
268                 else
269                 {
270                     text.Outline = new PropertyMap();
271                 }
272             }
273
274             TextField textField = view as TextField;
275             TextFieldAttributes textFieldAttrs = attrs as TextFieldAttributes;
276             if (textField != null && textFieldAttrs != null)
277             {
278                 if (textFieldAttrs.Text?.GetValue(State) != null)
279                 {
280                     textField.Text = textFieldAttrs.Text.GetValue(State);
281                 }
282                 if (textFieldAttrs.PlaceholderText?.GetValue(State) != null)
283                 {
284                     textField.PlaceholderText = textFieldAttrs.PlaceholderText.GetValue(State);
285                 }
286                 if (textFieldAttrs.TranslatablePlaceholderText?.GetValue(State) != null)
287                 {
288                     textField.TranslatablePlaceholderText = textFieldAttrs.TranslatablePlaceholderText.GetValue(State);
289                 }
290                 if (textFieldAttrs.HorizontalAlignment != null)
291                 {
292                     textField.HorizontalAlignment = textFieldAttrs.HorizontalAlignment.Value;
293                 }
294                 if (textFieldAttrs.VerticalAlignment != null)
295                 {
296                     textField.VerticalAlignment = textFieldAttrs.VerticalAlignment.Value;
297                 }
298                 if (textFieldAttrs.EnableMarkup != null)
299                 {
300                     textField.EnableMarkup = textFieldAttrs.EnableMarkup.Value;
301                 }
302                 if (textFieldAttrs.TextColor?.GetValue(State) != null)
303                 {
304                     textField.TextColor = textFieldAttrs.TextColor.GetValue(State);
305                 }
306                 if (textFieldAttrs.PlaceholderTextColor?.GetValue(State) != null)
307                 {
308                     textField.PlaceholderTextColor = textFieldAttrs.PlaceholderTextColor.GetValue(State);
309                 }
310                 if (textFieldAttrs.PrimaryCursorColor?.GetValue(State) != null)
311                 {
312                     textField.PrimaryCursorColor = textFieldAttrs.PrimaryCursorColor.GetValue(State);
313                 }
314                 if (textFieldAttrs.SecondaryCursorColor?.GetValue(State) != null)
315                 {
316                     textField.SecondaryCursorColor = textFieldAttrs.SecondaryCursorColor.GetValue(State);
317                 }
318                 if (textFieldAttrs.FontFamily != null)
319                 {
320                     textField.FontFamily = textFieldAttrs.FontFamily;
321                 }
322                 if (textFieldAttrs.PointSize?.GetValue(State) != null)
323                 {
324                     textField.PointSize = textFieldAttrs.PointSize.GetValue(State).Value;
325                 }
326                 if (textFieldAttrs.EnableCursorBlink != null)
327                 {
328                     textField.EnableCursorBlink = textFieldAttrs.EnableCursorBlink.Value;
329                 }
330                 if (textFieldAttrs.EnableSelection != null)
331                 {
332                     textField.EnableSelection = textFieldAttrs.EnableSelection.Value;
333                 }
334                 if (textFieldAttrs.CursorWidth != null)
335                 {
336                     textField.CursorWidth = textFieldAttrs.CursorWidth.Value;
337                 }
338                 if (textFieldAttrs.EnableEllipsis != null)
339                 {
340                     textField.Ellipsis = textFieldAttrs.EnableEllipsis.Value;
341                 }
342             }
343         }
344         /// <summary>
345         /// Dispose Control and all children on it.
346         /// </summary>
347         /// <param name="type">Dispose type.</param>
348         /// <since_tizen> 6 </since_tizen>
349         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
350         [EditorBrowsable(EditorBrowsableState.Never)]
351         protected override void Dispose(DisposeTypes type)
352         {
353             if (disposed)
354             {
355                 return;
356             }
357
358             if (type == DisposeTypes.Explicit)
359             {
360                 StyleManager.Instance.ThemeChangedEvent -= OnThemeChangedEvent;
361                 tapGestureDetector.Detected -= OnTapGestureDetected;
362                 tapGestureDetector.Detach(this);
363             }
364             base.Dispose(type);
365         }
366         /// <summary>
367         /// Get attribues, it is abstract function and must be override.
368         /// </summary>
369         /// <since_tizen> 6 </since_tizen>
370         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
371         [EditorBrowsable(EditorBrowsableState.Never)]
372         protected abstract Attributes GetAttributes();
373         /// <summary>
374         /// Called after a key event is received by the view that has had its focus set.
375         /// </summary>
376         /// <param name="key">The key event.</param>
377         /// <returns>True if the key event should be consumed.</returns>
378         /// <since_tizen> 6 </since_tizen>
379         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
380         [EditorBrowsable(EditorBrowsableState.Never)]
381         public override bool OnKey(Key key)
382         {
383             return false;
384         }
385
386         /// <summary>
387         /// Called after the size negotiation has been finished for this control.<br />
388         /// The control is expected to assign this given size to itself or its children.<br />
389         /// Should be overridden by derived classes if they need to layout views differently after certain operations like add or remove views, resize, or after changing specific properties.<br />
390         /// As this function is called from inside the size negotiation algorithm, you cannot call RequestRelayout (the call would just be ignored).<br />
391         /// </summary>
392         /// <param name="size">The allocated size.</param>
393         /// <param name="container">The control should add views to this container that it is not able to allocate a size for.</param>
394         /// <since_tizen> 6 </since_tizen>
395         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
396         [EditorBrowsable(EditorBrowsableState.Never)]
397         public override void OnRelayout(Vector2 size, RelayoutContainer container)
398         {
399             OnUpdate();
400         }
401
402         /// <summary>
403         /// Called when the control gain key input focus. Should be overridden by derived classes if they need to customize what happens when the focus is gained.
404         /// </summary>
405         /// <since_tizen> 6 </since_tizen>
406         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
407         [EditorBrowsable(EditorBrowsableState.Never)]
408         public override void OnFocusGained()
409         {
410             isFocused = true;
411         }
412
413         /// <summary>
414         /// Called when the control loses key input focus. Should be overridden by derived classes if they need to customize what happens when the focus is lost.
415         /// </summary>
416         /// <since_tizen> 6 </since_tizen>
417         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
418         [EditorBrowsable(EditorBrowsableState.Never)]
419         public override void OnFocusLost()
420         {
421             isFocused = false;
422         }
423
424         /// <summary>
425         /// Tap gesture callback.
426         /// </summary>
427         /// <param name="source">The sender</param>
428         /// <param name="e">The tap gesture event data</param>
429         /// <since_tizen> 6 </since_tizen>
430         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
431         [EditorBrowsable(EditorBrowsableState.Never)]
432         protected virtual void OnTapGestureDetected(object source, TapGestureDetector.DetectedEventArgs e)
433         {
434         }
435         /// <summary>
436         /// Called after a touch event is received by the owning view.<br />
437         /// CustomViewBehaviour.REQUIRES_TOUCH_EVENTS must be enabled during construction. See CustomView(ViewWrapperImpl.CustomViewBehaviour behaviour).<br />
438         /// </summary>
439         /// <param name="touch">The touch event.</param>
440         /// <returns>True if the event should be consumed.</returns>
441         /// <since_tizen> 6 </since_tizen>
442         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
443         [EditorBrowsable(EditorBrowsableState.Never)]
444         public override bool OnTouch(Touch touch)
445         {
446             return false;
447         }
448
449         /// <summary>
450         /// Update by attributes.
451         /// </summary>
452         /// <since_tizen> 6 </since_tizen>
453         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
454         [EditorBrowsable(EditorBrowsableState.Never)]
455         protected virtual void OnUpdate()
456         {
457         }
458         /// <summary>
459         /// Theme change callback when theme is changed, this callback will be trigger.
460         /// </summary>
461         /// <param name="sender">The sender</param>
462         /// <param name="e">The event data</param>
463         /// <since_tizen> 6 </since_tizen>
464         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
465         [EditorBrowsable(EditorBrowsableState.Never)]
466         protected virtual void OnThemeChangedEvent(object sender, StyleManager.ThemeChangeEventArgs e)
467         {
468         }
469
470         private void Initialize(string style)
471         {
472             attributes = (style == null) ? GetAttributes() : GetAttributes(style);
473             State = ControlStates.Normal;
474
475             LeaveRequired = true;
476
477             StateFocusableOnTouchMode = false;
478
479             tapGestureDetector.Attach(this);
480             tapGestureDetector.Detected += OnTapGestureDetected;
481
482             StyleManager.Instance.ThemeChangedEvent += OnThemeChangedEvent;
483         }
484
485         private Attributes GetAttributes(string style)
486         {
487             Attributes attributes = StyleManager.Instance.GetAttributes(style);
488             if(attributes == null)
489             {
490                 throw new InvalidOperationException($"There is no style {style}");
491             }
492             this.style = style;
493             return attributes;
494         }
495
496     }
497 }