2 * Copyright(c) 2019 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 using System.Diagnostics;
20 using System.ComponentModel;
21 using Tizen.NUI.BaseComponents;
22 using Tizen.NUI.Binding;
23 using System.Windows.Input;
26 namespace Tizen.NUI.Components
29 /// The control component is base class of tv nui components. It's abstract class, so cann't instantiate and can only be inherited.
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
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());
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));
45 private bool onThemeChangedEventOverrideChecker;
47 private Feedback feedback = null;
49 private TapGestureDetector tapGestureDetector = null;
51 /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
52 [EditorBrowsable(EditorBrowsableState.Never)]
53 public ControlStyle Style => (ControlStyle)ViewStyle.Clone();
58 /// Construct an empty Control.
60 /// <since_tizen> 6 </since_tizen>
61 /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
62 [EditorBrowsable(EditorBrowsableState.Never)]
63 public Control() : this((ControlStyle)null)
68 /// Construct with style.
70 /// <param name="style">Create control with style.</param>
71 /// <since_tizen> 6 </since_tizen>
72 /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
73 [EditorBrowsable(EditorBrowsableState.Never)]
74 public Control(ControlStyle style) : base(style)
80 /// Construct with style name
82 /// <param name="styleName">The name of style in the current theme to be applied</param>
83 /// <since_tizen> 6 </since_tizen>
84 /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
85 [EditorBrowsable(EditorBrowsableState.Never)]
86 public Control(string styleName) : this(ThemeManager.GetStyle(styleName) as ControlStyle)
88 if (ThemeManager.GetStyle(styleName) == null)
90 throw new InvalidOperationException($"There is no style {styleName}");
93 this.styleName = styleName;
94 ThemeChangeSensitive = true;
98 /// Enable/Disable a sound feedback when tap gesture detected.
100 [EditorBrowsable(EditorBrowsableState.Never)]
103 get => feedback != null;
106 if (value == (feedback != null))
113 Debug.Assert(feedback == null && tapGestureDetector == null);
115 tapGestureDetector = new TapGestureDetector();
116 tapGestureDetector.Attach(this);
117 tapGestureDetector.Detected += OnTapGestureDetected;
118 feedback = new Feedback();
122 Debug.Assert(feedback != null && tapGestureDetector != null);
127 tapGestureDetector.Detected -= OnTapGestureDetected;
128 tapGestureDetector.Detach(this);
129 tapGestureDetector = null;
135 [EditorBrowsable(EditorBrowsableState.Never)]
136 public ICommand Command
138 get { return (ICommand)GetValue(CommandProperty); }
139 set { SetValue(CommandProperty, value); }
143 [EditorBrowsable(EditorBrowsableState.Never)]
144 public object CommandParameter
146 get { return GetValue(CommandParameterProperty); }
147 set { SetValue(CommandParameterProperty, value); }
151 /// Whether focusable when touch
153 /// <since_tizen> 6 </since_tizen>
154 internal bool StateFocusableOnTouchMode { get; set; }
156 internal bool IsFocused { get; set; } = false;
158 internal void CommandCanExecuteChanged(object sender, EventArgs eventArgs)
160 ICommand cmd = Command;
162 cmd.CanExecute(CommandParameter);
165 internal void OnCommandChanged()
169 Command.CanExecuteChanged += CommandCanExecuteChanged;
170 CommandCanExecuteChanged(this, EventArgs.Empty);
175 /// Dispose Control and all children on it.
177 /// <param name="type">Dispose type.</param>
178 /// <since_tizen> 6 </since_tizen>
179 /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
180 [EditorBrowsable(EditorBrowsableState.Never)]
181 protected override void Dispose(DisposeTypes type)
188 if (type == DisposeTypes.Explicit)
190 Feedback = false; // Release feedback resources.
197 /// Called after a key event is received by the view that has had its focus set.
199 /// <param name="key">The key event.</param>
200 /// <returns>True if the key event should be consumed.</returns>
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 public override bool OnKey(Key key)
210 /// Called after the size negotiation has been finished for this control.<br />
211 /// The control is expected to assign this given size to itself or its children.<br />
212 /// 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 />
213 /// As this function is called from inside the size negotiation algorithm, you cannot call RequestRelayout (the call would just be ignored).<br />
215 /// <param name="size">The allocated size.</param>
216 /// <param name="container">The control should add views to this container that it is not able to allocate a size for.</param>
217 /// <since_tizen> 6 </since_tizen>
218 /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
219 [EditorBrowsable(EditorBrowsableState.Never)]
220 public override void OnRelayout(Vector2 size, RelayoutContainer container)
222 base.OnRelayout(size, container);
227 /// 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.
229 /// <since_tizen> 6 </since_tizen>
230 /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
231 [EditorBrowsable(EditorBrowsableState.Never)]
232 public override void OnFocusGained()
238 /// 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.
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 public override void OnFocusLost()
249 /// Tap gesture callback.
251 /// <param name="source">The sender</param>
252 /// <param name="e">The tap gesture event data</param>
253 /// <since_tizen> 6 </since_tizen>
254 /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
255 [EditorBrowsable(EditorBrowsableState.Never)]
256 protected virtual void OnTapGestureDetected(object source, TapGestureDetector.DetectedEventArgs e)
258 if (Feedback && e?.TapGesture?.State == Gesture.StateType.Started)
260 if (feedback != null && feedback.IsSupportedPattern(FeedbackType.Sound, "Tap"))
262 feedback.Play(FeedbackType.Sound, "Tap");
270 /// <since_tizen> 6 </since_tizen>
271 /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
272 [EditorBrowsable(EditorBrowsableState.Never)]
273 protected virtual void OnUpdate()
278 /// Theme change callback when theme is changed, this callback will be trigger.
279 /// Note that it is deprecated API.Please use OnThemeChanged instead.
281 /// <param name="sender">The sender</param>
282 /// <param name="e">The event data</param>
283 /// <since_tizen> 6 </since_tizen>
284 /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
285 [EditorBrowsable(EditorBrowsableState.Never)]
286 protected virtual void OnThemeChangedEvent(object sender, StyleManager.ThemeChangeEventArgs e)
288 onThemeChangedEventOverrideChecker = false;
291 /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
292 [EditorBrowsable(EditorBrowsableState.Never)]
293 protected override ViewStyle CreateViewStyle()
295 return new ControlStyle();
299 [EditorBrowsable(EditorBrowsableState.Never)]
300 protected override void OnThemeChanged(object sender, ThemeChangedEventArgs e)
302 // TODO Remove checker after update Tizen.FH.NUI.
303 onThemeChangedEventOverrideChecker = true;
305 OnThemeChangedEvent(sender, new StyleManager.ThemeChangeEventArgs { CurrentTheme = e.ThemeId });
307 if (onThemeChangedEventOverrideChecker) return;
309 // If the OnThemeChangedEvent is not implemented, ApplyStyle()
310 base.OnThemeChanged(sender, e);
313 private void Initialize()
315 LeaveRequired = true;
317 StateFocusableOnTouchMode = false;
319 EnableControlState = true;