[NUI] introduce CreateViewStyle that is alternative to GetViewStyle (#1681)
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI.Components / 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 using Tizen.NUI.Binding;
22
23 namespace Tizen.NUI.Components
24 {
25     /// <summary>
26     /// The control component is base class of tv nui components. It's abstract class, so cann't instantiate and can only be inherited.
27     /// </summary>
28     /// <since_tizen> 6 </since_tizen>
29     /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
30     [EditorBrowsable(EditorBrowsableState.Never)]
31     public class Control : VisualView
32     {
33         /// <summary> Control style. </summary>
34         /// <since_tizen> 6 </since_tizen>
35         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
36         [EditorBrowsable(EditorBrowsableState.Never)]
37         protected string style;
38
39         private TapGestureDetector tapGestureDetector = new TapGestureDetector();
40
41         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
42         [EditorBrowsable(EditorBrowsableState.Never)]
43         public ControlStyle Style => ViewStyle as ControlStyle;
44
45         static Control() { }
46
47         /// <summary>
48         /// Construct an empty Control.
49         /// </summary>
50         /// <since_tizen> 6 </since_tizen>
51         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
52         [EditorBrowsable(EditorBrowsableState.Never)]
53         public Control() : base()
54         {
55             var cur_type = this.GetType();
56             ViewStyle viewStyle = null;
57
58             do
59             {
60                 if (cur_type.Equals(typeof(Tizen.NUI.Components.Control))) break;
61                 viewStyle = StyleManager.Instance.GetComponentStyle(cur_type);
62                 cur_type = cur_type.BaseType;
63             }
64             while (viewStyle == null);
65
66             if (viewStyle != null)
67             {
68                 ApplyStyle(viewStyle);
69             }
70
71             Initialize(null);
72         }
73
74         /// <summary>
75         /// Construct with style.
76         /// </summary>
77         /// <param name="style">Create control with style.</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(ControlStyle style) : base(style)
82         {
83             Initialize(null);
84         }
85
86         /// <summary>
87         /// Construct with styleSheet
88         /// </summary>
89         /// <param name="styleSheet">StyleSheet to be applied</param>
90         /// <since_tizen> 6 </since_tizen>
91         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
92         [EditorBrowsable(EditorBrowsableState.Never)]
93         public Control(string styleSheet) : base()
94         {
95             ViewStyle viewStyle = StyleManager.Instance.GetViewStyle(styleSheet);
96             if (viewStyle == null)
97             {
98                 throw new InvalidOperationException($"There is no style {styleSheet}");
99             }
100
101             ApplyStyle(viewStyle);
102             this.style = styleSheet;
103
104             Initialize(style);
105         }
106
107         internal void ApplyAttributes(View view, ViewStyle viewStyle)
108         {
109             view.CopyFrom(viewStyle);
110         }
111
112         /// <summary>
113         /// Whether focusable when touch
114         /// </summary>
115         /// <since_tizen> 6 </since_tizen>
116         internal bool StateFocusableOnTouchMode { get; set; }
117
118         internal bool IsFocused { get; set; } = false;
119
120         /// <summary>
121         /// Dispose Control and all children on it.
122         /// </summary>
123         /// <param name="type">Dispose type.</param>
124         /// <since_tizen> 6 </since_tizen>
125         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
126         [EditorBrowsable(EditorBrowsableState.Never)]
127         protected override void Dispose(DisposeTypes type)
128         {
129             if (disposed)
130             {
131                 return;
132             }
133
134             if (type == DisposeTypes.Explicit)
135             {
136                 StyleManager.Instance.ThemeChangedEvent -= OnThemeChangedEvent;
137                 tapGestureDetector.Detected -= OnTapGestureDetected;
138                 tapGestureDetector.Detach(this);
139             }
140
141             base.Dispose(type);
142         }
143
144         /// <summary>
145         /// Called after a key event is received by the view that has had its focus set.
146         /// </summary>
147         /// <param name="key">The key event.</param>
148         /// <returns>True if the key event should be consumed.</returns>
149         /// <since_tizen> 6 </since_tizen>
150         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
151         [EditorBrowsable(EditorBrowsableState.Never)]
152         public override bool OnKey(Key key)
153         {
154             return false;
155         }
156
157         /// <summary>
158         /// Called after the size negotiation has been finished for this control.<br />
159         /// The control is expected to assign this given size to itself or its children.<br />
160         /// 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 />
161         /// As this function is called from inside the size negotiation algorithm, you cannot call RequestRelayout (the call would just be ignored).<br />
162         /// </summary>
163         /// <param name="size">The allocated size.</param>
164         /// <param name="container">The control should add views to this container that it is not able to allocate a size for.</param>
165         /// <since_tizen> 6 </since_tizen>
166         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
167         [EditorBrowsable(EditorBrowsableState.Never)]
168         public override void OnRelayout(Vector2 size, RelayoutContainer container)
169         {
170             base.OnRelayout(size, container);
171             OnUpdate();
172         }
173
174         /// <summary>
175         /// 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.
176         /// </summary>
177         /// <since_tizen> 6 </since_tizen>
178         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
179         [EditorBrowsable(EditorBrowsableState.Never)]
180         public override void OnFocusGained()
181         {
182             IsFocused = true;
183         }
184
185         /// <summary>
186         /// 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.
187         /// </summary>
188         /// <since_tizen> 6 </since_tizen>
189         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
190         [EditorBrowsable(EditorBrowsableState.Never)]
191         public override void OnFocusLost()
192         {
193             IsFocused = false;
194         }
195
196         /// <summary>
197         /// Tap gesture callback.
198         /// </summary>
199         /// <param name="source">The sender</param>
200         /// <param name="e">The tap gesture event data</param>
201         /// <since_tizen> 6 </since_tizen>
202         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
203         [EditorBrowsable(EditorBrowsableState.Never)]
204         protected virtual void OnTapGestureDetected(object source, TapGestureDetector.DetectedEventArgs e) { }
205
206         /// <summary>
207         /// Called after a touch event is received by the owning view.<br />
208         /// CustomViewBehaviour.REQUIRES_TOUCH_EVENTS must be enabled during construction. See CustomView(ViewWrapperImpl.CustomViewBehaviour behaviour).<br />
209         /// </summary>
210         /// <param name="touch">The touch event.</param>
211         /// <returns>True if the event should be consumed.</returns>
212         /// <since_tizen> 6 </since_tizen>
213         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
214         [EditorBrowsable(EditorBrowsableState.Never)]
215         public override bool OnTouch(Touch touch)
216         {
217             // Handle Normal and Pressed states
218             PointStateType state = touch.GetState(0);
219             switch(state)
220             {
221                 case PointStateType.Down:
222                     ControlState = ControlStates.Pressed;
223                     break;
224                 case PointStateType.Interrupted:
225                 case PointStateType.Up:
226                     if (ControlState == ControlStates.Pressed)
227                     {
228                         ControlState = ControlStates.Normal;
229                     }
230                     break;
231                 default:
232                     break;
233             }
234             return false;
235         }
236
237         /// <summary>
238         /// Update by style.
239         /// </summary>
240         /// <since_tizen> 6 </since_tizen>
241         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
242         [EditorBrowsable(EditorBrowsableState.Never)]
243         protected virtual void OnUpdate()
244         {
245         }
246
247         /// <summary>
248         /// Theme change callback when theme is changed, this callback will be trigger.
249         /// </summary>
250         /// <param name="sender">The sender</param>
251         /// <param name="e">The event data</param>
252         /// <since_tizen> 6 </since_tizen>
253         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
254         [EditorBrowsable(EditorBrowsableState.Never)]
255         protected virtual void OnThemeChangedEvent(object sender, StyleManager.ThemeChangeEventArgs e) { }
256
257         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
258         [EditorBrowsable(EditorBrowsableState.Never)]
259         protected virtual void RegisterDetectionOfSubstyleChanges() { }
260
261         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
262         [EditorBrowsable(EditorBrowsableState.Never)]
263         protected override ViewStyle CreateViewStyle()
264         {
265             return new ControlStyle();
266         }
267
268         private void Initialize(string style)
269         {
270             ControlState = ControlStates.Normal;
271
272             RegisterDetectionOfSubstyleChanges();
273
274             LeaveRequired = true;
275
276             StateFocusableOnTouchMode = false;
277
278             tapGestureDetector.Attach(this);
279             tapGestureDetector.Detected += OnTapGestureDetected;
280
281             StyleManager.Instance.ThemeChangedEvent += OnThemeChangedEvent;
282         }
283     }
284 }