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.ComponentModel;
20 using Tizen.NUI.BaseComponents;
21 using Tizen.NUI.Binding;
22 using System.Windows.Input;
25 namespace Tizen.NUI.Components
28 /// The control component is base class of tv nui components. It's abstract class, so can't instantiate and can only be inherited.
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
38 [EditorBrowsable(EditorBrowsableState.Never)]
39 public static readonly BindableProperty FeedbackProperty = BindableProperty.Create(nameof(Feedback), typeof(bool), typeof(Control), default(bool), propertyChanged: (bindable, oldValue, newValue) =>
41 var instance = (Control)bindable;
44 instance.InternalFeedback = (bool)newValue;
47 defaultValueCreator: (bindable) =>
49 var instance = (Control)bindable;
50 return instance.InternalFeedback;
54 [EditorBrowsable(EditorBrowsableState.Never)]
55 public static readonly BindableProperty CommandProperty = BindableProperty.Create(nameof(Command), typeof(ICommand), typeof(Control), null, propertyChanged: (bo, o, n) => ((Control)bo).OnCommandChanged());
58 [EditorBrowsable(EditorBrowsableState.Never)]
59 public static readonly BindableProperty CommandParameterProperty = BindableProperty.Create(nameof(CommandParameter), typeof(object), typeof(Button), null,
60 propertyChanged: (bindable, oldvalue, newvalue) => ((Button)bindable).CommandCanExecuteChanged(bindable, EventArgs.Empty));
62 private bool onThemeChangedEventOverrideChecker;
64 private Feedback feedback = null;
68 ThemeManager.AddPackageTheme(DefaultThemeCreator.Instance);
72 /// This is used to improve theme performance.
74 [EditorBrowsable(EditorBrowsableState.Never)]
75 static public new void Preload()
77 DefaultThemeCreator.Preload();
81 /// Construct an empty Control.
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() : this((ControlStyle)null)
91 /// Construct with style.
93 /// <param name="style">Create control with style.</param>
94 /// <since_tizen> 6 </since_tizen>
95 /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
96 [EditorBrowsable(EditorBrowsableState.Never)]
97 public Control(ControlStyle style) : base(style)
102 /// Construct with style name
104 /// <param name="styleName">The name of style in the current theme to be applied</param>
105 /// <since_tizen> 6 </since_tizen>
106 /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
107 [EditorBrowsable(EditorBrowsableState.Never)]
108 public Control(string styleName) : base(ThemeManager.GetInitialStyleWithoutClone(styleName) ?? throw new InvalidOperationException($"There is no style {styleName}"))
110 this.styleName = styleName;
116 /// Enable/Disable a sound feedback when tap gesture detected.
118 [EditorBrowsable(EditorBrowsableState.Never)]
123 return (bool)GetValue(FeedbackProperty);
127 SetValue(FeedbackProperty, value);
128 NotifyPropertyChanged();
131 private bool InternalFeedback
133 get => feedback != null;
136 if (value == (feedback != null))
145 feedback = new Feedback();
146 this.TouchEvent += OnTouchPlayFeedback;
148 catch (NotSupportedException e)
150 Log.Error("NUI", $"[ERROR] No support of Feedback: {e}");
152 catch (InvalidOperationException e)
154 Log.Error("NUI", $"[ERROR] Fail to initialize Feedback: {e}");
159 this.TouchEvent -= OnTouchPlayFeedback;
165 private bool OnTouchPlayFeedback(object source, TouchEventArgs e)
167 if (Feedback && e?.Touch.GetState(0) == PointStateType.Down)
169 if (feedback != null && feedback.IsSupportedPattern(FeedbackType.Sound, "Tap"))
171 feedback.Play(FeedbackType.Sound, "Tap");
178 [EditorBrowsable(EditorBrowsableState.Never)]
179 public ICommand Command
181 get { return (ICommand)GetValue(CommandProperty); }
182 set { SetValue(CommandProperty, value); }
186 [EditorBrowsable(EditorBrowsableState.Never)]
187 public object CommandParameter
189 get { return GetValue(CommandParameterProperty); }
190 set { SetValue(CommandParameterProperty, value); }
194 /// Whether focusable when touch
196 /// <since_tizen> 6 </since_tizen>
197 internal bool StateFocusableOnTouchMode { get; set; }
199 internal bool IsFocused { get; set; } = false;
201 internal void CommandCanExecuteChanged(object sender, EventArgs eventArgs)
203 ICommand cmd = Command;
205 cmd.CanExecute(CommandParameter);
208 internal void OnCommandChanged()
212 Command.CanExecuteChanged += CommandCanExecuteChanged;
213 CommandCanExecuteChanged(this, EventArgs.Empty);
218 /// Dispose Control and all children on it.
220 /// <param name="type">Dispose type.</param>
221 /// <since_tizen> 6 </since_tizen>
222 /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
223 [EditorBrowsable(EditorBrowsableState.Never)]
224 protected override void Dispose(DisposeTypes type)
232 this.TouchEvent -= OnTouchPlayFeedback;
234 if (type == DisposeTypes.Explicit)
242 public override void OnInitialize()
246 LeaveRequired = true;
247 StateFocusableOnTouchMode = false;
248 EnableControlState = true;
252 /// Called after a key event is received by the view that has had its focus set.
254 /// <param name="key">The key event.</param>
255 /// <returns>True if the key event should be consumed.</returns>
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 public override bool OnKey(Key key)
265 /// Called after the size negotiation has been finished for this control.<br />
266 /// The control is expected to assign this given size to itself or its children.<br />
267 /// 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 />
268 /// As this function is called from inside the size negotiation algorithm, you cannot call RequestRelayout (the call would just be ignored).<br />
270 /// <param name="size">The allocated size.</param>
271 /// <param name="container">The control should add views to this container that it is not able to allocate a size for.</param>
272 /// <since_tizen> 6 </since_tizen>
273 /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
274 [EditorBrowsable(EditorBrowsableState.Never)]
275 public override void OnRelayout(Vector2 size, RelayoutContainer container)
277 base.OnRelayout(size, container);
282 /// 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.
284 /// <since_tizen> 6 </since_tizen>
285 /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
286 [EditorBrowsable(EditorBrowsableState.Never)]
287 public override void OnFocusGained()
293 /// 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.
295 /// <since_tizen> 6 </since_tizen>
296 /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
297 [EditorBrowsable(EditorBrowsableState.Never)]
298 public override void OnFocusLost()
306 /// <since_tizen> 6 </since_tizen>
307 /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
308 [EditorBrowsable(EditorBrowsableState.Never)]
309 protected virtual void OnUpdate()
314 /// Theme change callback when theme is changed, this callback will be trigger.
315 /// Note that it is deprecated API.Please use OnThemeChanged instead.
317 /// <param name="sender">The sender</param>
318 /// <param name="e">The event data</param>
319 /// <since_tizen> 6 </since_tizen>
320 /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
321 [EditorBrowsable(EditorBrowsableState.Never)]
322 protected virtual void OnThemeChangedEvent(object sender, StyleManager.ThemeChangeEventArgs e)
324 onThemeChangedEventOverrideChecker = false;
327 /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
328 [EditorBrowsable(EditorBrowsableState.Never)]
329 protected override ViewStyle CreateViewStyle()
331 return new ControlStyle();
335 [EditorBrowsable(EditorBrowsableState.Never)]
336 protected override void OnThemeChanged(object sender, ThemeChangedEventArgs e)
338 // TODO Remove checker after update Tizen.FH.NUI.
339 onThemeChangedEventOverrideChecker = true;
341 OnThemeChangedEvent(sender, new StyleManager.ThemeChangeEventArgs { CurrentTheme = e.ThemeId });
343 if (onThemeChangedEventOverrideChecker) return;
345 // If the OnThemeChangedEvent is not implemented, ApplyStyle()
346 base.OnThemeChanged(sender, e);
350 /// when the derived class of Control is used as container and itself is not Focusable, this can be used when calling SetCurrentFocusView()
351 /// this can return Focusable View inside of itself. this can be utilized when default algorithm is enabled and when the case of setting first key focus in container.
353 /// <returns>Focusable View inside of container</returns>
354 [EditorBrowsable(EditorBrowsableState.Never)]
355 protected internal virtual View PassFocusableViewInsideIfNeeded()