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