[NUI] Modify NUI.Components private variable (#2764)
[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
18 using System;
19 using System.ComponentModel;
20 using Tizen.NUI.BaseComponents;
21 using Tizen.NUI.Binding;
22 using System.Windows.Input;
23 using Tizen.System;
24
25 namespace Tizen.NUI.Components
26 {
27     /// <summary>
28     /// The control component is base class of tv nui components. It's abstract class, so can't instantiate and can only be inherited.
29     /// </summary>
30     /// <since_tizen> 6 </since_tizen>
31     /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
32     [EditorBrowsable(EditorBrowsableState.Never)]
33     public class Control : VisualView
34     {
35         /// Internal used.
36         [EditorBrowsable(EditorBrowsableState.Never)]
37         public static readonly BindableProperty CommandProperty = BindableProperty.Create(nameof(Command), typeof(ICommand), typeof(Control), null, propertyChanged: (bo, o, n) => ((Control)bo).OnCommandChanged());
38
39         /// Internal used.
40         [EditorBrowsable(EditorBrowsableState.Never)]
41         public static readonly BindableProperty CommandParameterProperty = BindableProperty.Create(nameof(CommandParameter), typeof(object), typeof(Button), null,
42             propertyChanged: (bindable, oldvalue, newvalue) => ((Button)bindable).CommandCanExecuteChanged(bindable, EventArgs.Empty));
43
44         private bool onThemeChangedEventOverrideChecker;
45
46         private Feedback feedback = null;
47
48         static Control()
49         {
50             ThemeManager.AddPackageTheme(DefaultThemeCreator.Instance);
51         }
52
53         /// <summary>
54         /// This is used to improve theme performance.
55         /// </summary>
56         [EditorBrowsable(EditorBrowsableState.Never)]
57         static public void Preload()
58         {
59             DefaultThemeCreator.Preload();
60         }
61
62         /// <summary>
63         /// Construct an empty Control.
64         /// </summary>
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() : this((ControlStyle)null)
69         {
70         }
71
72         /// <summary>
73         /// Construct with style.
74         /// </summary>
75         /// <param name="style">Create control with style.</param>
76         /// <since_tizen> 6 </since_tizen>
77         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
78         [EditorBrowsable(EditorBrowsableState.Never)]
79         public Control(ControlStyle style) : base(style)
80         {
81         }
82
83         /// <summary>
84         /// Construct with style name
85         /// </summary>
86         /// <param name="styleName">The name of style in the current theme to be applied</param>
87         /// <since_tizen> 6 </since_tizen>
88         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
89         [EditorBrowsable(EditorBrowsableState.Never)]
90         public Control(string styleName) : this(new ControlStyle() /* Apply empty style */)
91         {
92             if (ThemeManager.GetStyle(styleName) == null)
93             {
94                 throw new InvalidOperationException($"There is no style {styleName}");
95             }
96
97             StyleName = styleName;
98         }
99
100         /// <summary>
101         /// Enable/Disable a sound feedback when tap gesture detected.
102         /// </summary>
103         [EditorBrowsable(EditorBrowsableState.Never)]
104         public bool Feedback
105         {
106             get => feedback != null;
107             set
108             {
109                 if (value == (feedback != null))
110                 {
111                     return;
112                 }
113
114                 if (value)
115                 {
116                     feedback = new Feedback();
117                     this.TouchEvent += OnTouchPlayFeedback;
118                 }
119                 else
120                 {
121                     this.TouchEvent -= OnTouchPlayFeedback;
122                     feedback = null;
123                 }
124             }
125         }
126
127         private bool OnTouchPlayFeedback(object source, TouchEventArgs e)
128         {
129             if (Feedback && e?.Touch.GetState(0) == PointStateType.Down)
130             {
131                 if (feedback != null && feedback.IsSupportedPattern(FeedbackType.Sound, "Tap"))
132                 {
133                     feedback.Play(FeedbackType.Sound, "Tap");
134                 }
135             }
136             return false;
137         }
138
139         /// Internal used.
140         [EditorBrowsable(EditorBrowsableState.Never)]
141         public ICommand Command
142         {
143             get { return (ICommand)GetValue(CommandProperty); }
144             set { SetValue(CommandProperty, value); }
145         }
146
147         /// Internal used.
148         [EditorBrowsable(EditorBrowsableState.Never)]
149         public object CommandParameter
150         {
151             get { return GetValue(CommandParameterProperty); }
152             set { SetValue(CommandParameterProperty, value); }
153         }
154
155         /// <summary>
156         /// Whether focusable when touch
157         /// </summary>
158         /// <since_tizen> 6 </since_tizen>
159         internal bool StateFocusableOnTouchMode { get; set; }
160
161         internal bool IsFocused { get; set; } = false;
162
163         internal void CommandCanExecuteChanged(object sender, EventArgs eventArgs)
164         {
165             ICommand cmd = Command;
166             if (cmd != null)
167                 cmd.CanExecute(CommandParameter);
168         }
169
170         internal void OnCommandChanged()
171         {
172             if (Command != null)
173             {
174                 Command.CanExecuteChanged += CommandCanExecuteChanged;
175                 CommandCanExecuteChanged(this, EventArgs.Empty);
176             }
177         }
178
179         /// <summary>
180         /// Dispose Control and all children on it.
181         /// </summary>
182         /// <param name="type">Dispose type.</param>
183         /// <since_tizen> 6 </since_tizen>
184         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
185         [EditorBrowsable(EditorBrowsableState.Never)]
186         protected override void Dispose(DisposeTypes type)
187         {
188             if (disposed)
189             {
190                 return;
191             }
192
193             feedback = null;
194             this.TouchEvent -= OnTouchPlayFeedback;
195
196             if (type == DisposeTypes.Explicit)
197             {
198             }
199
200             base.Dispose(type);
201         }
202
203         /// <inheritdoc/>
204         public override void OnInitialize()
205         {
206             base.OnInitialize();
207
208             LeaveRequired = true;
209             StateFocusableOnTouchMode = false;
210             EnableControlState = true;
211         }
212
213         /// <summary>
214         /// Called after a key event is received by the view that has had its focus set.
215         /// </summary>
216         /// <param name="key">The key event.</param>
217         /// <returns>True if the key event should be consumed.</returns>
218         /// <since_tizen> 6 </since_tizen>
219         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
220         [EditorBrowsable(EditorBrowsableState.Never)]
221         public override bool OnKey(Key key)
222         {
223             return false;
224         }
225
226         /// <summary>
227         /// Called after the size negotiation has been finished for this control.<br />
228         /// The control is expected to assign this given size to itself or its children.<br />
229         /// 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 />
230         /// As this function is called from inside the size negotiation algorithm, you cannot call RequestRelayout (the call would just be ignored).<br />
231         /// </summary>
232         /// <param name="size">The allocated size.</param>
233         /// <param name="container">The control should add views to this container that it is not able to allocate a size for.</param>
234         /// <since_tizen> 6 </since_tizen>
235         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
236         [EditorBrowsable(EditorBrowsableState.Never)]
237         public override void OnRelayout(Vector2 size, RelayoutContainer container)
238         {
239             base.OnRelayout(size, container);
240             OnUpdate();
241         }
242
243         /// <summary>
244         /// 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.
245         /// </summary>
246         /// <since_tizen> 6 </since_tizen>
247         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
248         [EditorBrowsable(EditorBrowsableState.Never)]
249         public override void OnFocusGained()
250         {
251             IsFocused = true;
252         }
253
254         /// <summary>
255         /// 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.
256         /// </summary>
257         /// <since_tizen> 6 </since_tizen>
258         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
259         [EditorBrowsable(EditorBrowsableState.Never)]
260         public override void OnFocusLost()
261         {
262             IsFocused = false;
263         }
264
265         /// <summary>
266         /// Update by style.
267         /// </summary>
268         /// <since_tizen> 6 </since_tizen>
269         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
270         [EditorBrowsable(EditorBrowsableState.Never)]
271         protected virtual void OnUpdate()
272         {
273         }
274
275         /// <summary>
276         /// Theme change callback when theme is changed, this callback will be trigger.
277         /// Note that it is deprecated API.Please use OnThemeChanged instead.
278         /// </summary>
279         /// <param name="sender">The sender</param>
280         /// <param name="e">The event data</param>
281         /// <since_tizen> 6 </since_tizen>
282         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
283         [EditorBrowsable(EditorBrowsableState.Never)]
284         protected virtual void OnThemeChangedEvent(object sender, StyleManager.ThemeChangeEventArgs e)
285         {
286             onThemeChangedEventOverrideChecker = false;
287         }
288
289         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
290         [EditorBrowsable(EditorBrowsableState.Never)]
291         protected override ViewStyle CreateViewStyle()
292         {
293             return new ControlStyle();
294         }
295
296         /// <inheritdoc/>
297         [EditorBrowsable(EditorBrowsableState.Never)]
298         protected override void OnThemeChanged(object sender, ThemeChangedEventArgs e)
299         {
300             // TODO Remove checker after update Tizen.FH.NUI.
301             onThemeChangedEventOverrideChecker = true;
302
303             OnThemeChangedEvent(sender, new StyleManager.ThemeChangeEventArgs { CurrentTheme = e.ThemeId });
304
305             if (onThemeChangedEventOverrideChecker) return;
306
307             // If the OnThemeChangedEvent is not implemented, ApplyStyle()
308             base.OnThemeChanged(sender, e);
309         }
310     }
311 }