/*
* Copyright(c) 2019 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using Tizen.NUI.BaseComponents;
using Tizen.NUI.Binding;
using System.Windows.Input;
namespace Tizen.NUI.Components
{
///
/// The control component is base class of tv nui components. It's abstract class, so cann't instantiate and can only be inherited.
///
/// 6
/// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
[EditorBrowsable(EditorBrowsableState.Never)]
public class Control : VisualView
{
/// Internal used.
[EditorBrowsable(EditorBrowsableState.Never)]
public static readonly BindableProperty CommandProperty = BindableProperty.Create("Command", typeof(ICommand), typeof(Control), null, propertyChanged: (bo, o, n) => ((Control)bo).OnCommandChanged());
/// Internal used.
[EditorBrowsable(EditorBrowsableState.Never)]
public static readonly BindableProperty CommandParameterProperty = BindableProperty.Create("CommandParameter", typeof(object), typeof(Button), null,
propertyChanged: (bindable, oldvalue, newvalue) => ((Button)bindable).CommandCanExecuteChanged(bindable, EventArgs.Empty));
/// Control style.
/// 6
/// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
[EditorBrowsable(EditorBrowsableState.Never)]
protected string StyleName { get; set; }
private TapGestureDetector tapGestureDetector = new TapGestureDetector();
/// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
[EditorBrowsable(EditorBrowsableState.Never)]
public ControlStyle Style => ViewStyle as ControlStyle;
static Control() { }
///
/// Construct an empty Control.
///
/// 6
/// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
[EditorBrowsable(EditorBrowsableState.Never)]
public Control() : base()
{
var cur_type = this.GetType();
ViewStyle viewStyle = null;
do
{
if (cur_type.Equals(typeof(Tizen.NUI.Components.Control))) break;
viewStyle = StyleManager.Instance.GetComponentStyle(cur_type);
cur_type = cur_type.BaseType;
}
while (viewStyle == null);
if (viewStyle != null)
{
ApplyStyle(viewStyle);
}
Initialize(null);
}
///
/// Construct with style.
///
/// Create control with style.
/// 6
/// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
[EditorBrowsable(EditorBrowsableState.Never)]
public Control(ControlStyle style) : base(style)
{
Initialize(null);
}
///
/// Construct with styleSheet
///
/// StyleSheet to be applied
/// 6
/// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
[EditorBrowsable(EditorBrowsableState.Never)]
public Control(string styleSheet) : base()
{
ViewStyle viewStyle = StyleManager.Instance.GetViewStyle(styleSheet);
if (viewStyle == null)
{
throw new InvalidOperationException($"There is no style {styleSheet}");
}
ApplyStyle(viewStyle);
this.StyleName = styleSheet;
Initialize(StyleName);
}
/// Internal used.
[EditorBrowsable(EditorBrowsableState.Never)]
public ICommand Command
{
get { return (ICommand)GetValue(CommandProperty); }
set { SetValue(CommandProperty, value); }
}
/// Internal used.
[EditorBrowsable(EditorBrowsableState.Never)]
public object CommandParameter
{
get { return GetValue(CommandParameterProperty); }
set { SetValue(CommandParameterProperty, value); }
}
///
/// Whether focusable when touch
///
/// 6
internal bool StateFocusableOnTouchMode { get; set; }
internal bool IsFocused { get; set; } = false;
internal void CommandCanExecuteChanged(object sender, EventArgs eventArgs)
{
ICommand cmd = Command;
if (cmd != null)
cmd.CanExecute(CommandParameter);
}
internal void OnCommandChanged()
{
if (Command != null)
{
Command.CanExecuteChanged += CommandCanExecuteChanged;
CommandCanExecuteChanged(this, EventArgs.Empty);
}
}
///
/// Dispose Control and all children on it.
///
/// Dispose type.
/// 6
/// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
[EditorBrowsable(EditorBrowsableState.Never)]
protected override void Dispose(DisposeTypes type)
{
if (disposed)
{
return;
}
if (type == DisposeTypes.Explicit)
{
StyleManager.Instance.ThemeChangedEvent -= OnThemeChangedEvent;
tapGestureDetector.Detected -= OnTapGestureDetected;
tapGestureDetector.Detach(this);
}
base.Dispose(type);
}
///
/// Called after a key event is received by the view that has had its focus set.
///
/// The key event.
/// True if the key event should be consumed.
/// 6
/// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
[EditorBrowsable(EditorBrowsableState.Never)]
public override bool OnKey(Key key)
{
return false;
}
///
/// Called after the size negotiation has been finished for this control.
/// The control is expected to assign this given size to itself or its children.
/// 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.
/// As this function is called from inside the size negotiation algorithm, you cannot call RequestRelayout (the call would just be ignored).
///
/// The allocated size.
/// The control should add views to this container that it is not able to allocate a size for.
/// 6
/// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
[EditorBrowsable(EditorBrowsableState.Never)]
public override void OnRelayout(Vector2 size, RelayoutContainer container)
{
base.OnRelayout(size, container);
OnUpdate();
}
///
/// 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.
///
/// 6
/// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
[EditorBrowsable(EditorBrowsableState.Never)]
public override void OnFocusGained()
{
IsFocused = true;
}
///
/// 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.
///
/// 6
/// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
[EditorBrowsable(EditorBrowsableState.Never)]
public override void OnFocusLost()
{
IsFocused = false;
}
///
/// Tap gesture callback.
///
/// The sender
/// The tap gesture event data
/// 6
/// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
[EditorBrowsable(EditorBrowsableState.Never)]
protected virtual void OnTapGestureDetected(object source, TapGestureDetector.DetectedEventArgs e) { }
///
/// Called after a touch event is received by the owning view.
/// CustomViewBehaviour.REQUIRES_TOUCH_EVENTS must be enabled during construction. See CustomView(ViewWrapperImpl.CustomViewBehaviour behaviour).
///
/// The touch event.
/// True if the event should be consumed.
/// 6
/// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
[EditorBrowsable(EditorBrowsableState.Never)]
public override bool OnTouch(Touch touch)
{
// Handle Normal and Pressed states
PointStateType state = touch.GetState(0);
switch(state)
{
case PointStateType.Down:
ControlState = ControlStates.Pressed;
break;
case PointStateType.Interrupted:
case PointStateType.Up:
if (ControlState == ControlStates.Pressed)
{
ControlState = ControlStates.Normal;
}
break;
default:
break;
}
return false;
}
///
/// Update by style.
///
/// 6
/// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
[EditorBrowsable(EditorBrowsableState.Never)]
protected virtual void OnUpdate()
{
}
///
/// Theme change callback when theme is changed, this callback will be trigger.
///
/// The sender
/// The event data
/// 6
/// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
[EditorBrowsable(EditorBrowsableState.Never)]
protected virtual void OnThemeChangedEvent(object sender, StyleManager.ThemeChangeEventArgs e) { }
/// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
[EditorBrowsable(EditorBrowsableState.Never)]
protected virtual void RegisterDetectionOfSubstyleChanges() { }
/// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
[EditorBrowsable(EditorBrowsableState.Never)]
protected override ViewStyle CreateViewStyle()
{
return new ControlStyle();
}
private void Initialize(string style)
{
ControlState = ControlStates.Normal;
RegisterDetectionOfSubstyleChanges();
LeaveRequired = true;
StateFocusableOnTouchMode = false;
tapGestureDetector.Attach(this);
tapGestureDetector.Detected += OnTapGestureDetected;
StyleManager.Instance.ThemeChangedEvent += OnThemeChangedEvent;
}
}
}