/*
* Copyright(c) 2021 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.Runtime.InteropServices;
using Tizen.NUI.BaseComponents;
using System.ComponentModel;
namespace Tizen.NUI
{
///
/// Provides the functionality of handling keyboard navigation and maintaining the two-dimensional keyboard focus chain.
/// It provides functionality of setting the focus and moving the focus in four directions( i.e., left, right, up, and down).
/// It also draws a highlight for the focused view and sends an event when the focus is changed.
///
/// 3
public class FocusManager : BaseHandle
{
private static readonly FocusManager instance = FocusManager.Get();
private CustomAlgorithmInterfaceWrapper customAlgorithmInterfaceWrapper;
private EventHandlerWithReturnType preFocusChangeEventHandler;
private PreFocusChangeEventCallback preFocusChangeCallback;
private EventHandler focusChangingEventHandler;
private PreFocusChangeEventCallback focusChangingCallback;
private EventHandler focusChangedEventHandler;
private FocusChangedEventCallback focusChangedEventCallback;
private EventHandler focusGroupChangedEventHandler;
private FocusGroupChangedEventCallback focusGroupChangedEventCallback;
private EventHandler focusedViewEnterKeyEventHandler;
private FocusedViewEnterKeyEventCallback focusedViewEnterKeyEventCallback;
private EventHandler focusedViewEnterKeyEventHandler2;
private FocusedViewEnterKeyEventCallback2 focusedViewEnterKeyEventCallback2;
internal FocusManager(global::System.IntPtr cPtr, bool cMemoryOwn) : base(cPtr, cMemoryOwn)
{
}
internal FocusManager() : this(Interop.FocusManager.NewFocusManager(), true)
{
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
}
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate IntPtr PreFocusChangeEventCallback(IntPtr current, IntPtr proposed, View.FocusDirection direction);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate void FocusChangedEventCallback(IntPtr current, IntPtr next);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void FocusGroupChangedEventCallback(IntPtr current, bool forwardDirection);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void FocusedViewEnterKeyEventCallback(IntPtr view);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void FocusedViewEnterKeyEventCallback2(IntPtr view);
private View internalFocusIndicator = null;
private View nullFocusIndicator = null;
///
/// PreFocusChange will be triggered before the focus is going to be changed.
/// The FocusManager makes the best guess for which view to focus towards the given direction, but applications might want to change that.
/// By connecting with this event, they can check the proposed view to focus and return a different view if they wish.
/// This event is only triggered when the navigation key is pressed and KeyboardFocusManager tries to move the focus automatically.
/// It won't be emitted for focus movement by calling the SetCurrentFocusView directly.
///
/// 3
[Obsolete("Please do not use! This will be deprecated in API10. Please use FocusChanging instead!")]
// this will be deprecated, so suppress warning would be OK.
[System.Diagnostics.CodeAnalysis.SuppressMessage("Naming", "CA1710:Identifiers should have correct suffix", Justification = "")]
public event EventHandlerWithReturnType PreFocusChange
{
add
{
if (preFocusChangeEventHandler == null)
{
preFocusChangeCallback = OnPreFocusChange;
using PreFocusChangeSignal signal = PreFocusChangeSignal();
signal?.Connect(preFocusChangeCallback);
}
preFocusChangeEventHandler += value;
}
remove
{
preFocusChangeEventHandler -= value;
using PreFocusChangeSignal signal = PreFocusChangeSignal();
if (preFocusChangeEventHandler == null && signal?.Empty() == false)
{
signal?.Disconnect(preFocusChangeCallback);
}
}
}
///
/// FocusChanging will be triggered before the focus is going to be changed.
/// The FocusManager makes the best guess for which view to focus towards the given direction, but applications might want to change that.
/// By connecting with this event, they can check the proposed view to focus and assign a different view if they wish.
/// This event is only triggered when the navigation key is pressed and FocusManager tries to move the focus automatically.
/// It won't be emitted for focus movement by calling the SetCurrentFocusView directly.
///
///
/// By setting FocusChangingEventArgs.Proposed with the view to be focused, the focus will be moved to the assigned view.
///
/// 10
public event EventHandler FocusChanging
{
add
{
if (focusChangingEventHandler == null)
{
focusChangingCallback = OnFocusChanging;
//this is same as old PreFocusChangeSignal, so the body will be same. (only name is changed, behavior is same)
using PreFocusChangeSignal signal = PreFocusChangeSignal();
signal?.Connect(focusChangingCallback);
}
focusChangingEventHandler += value;
}
remove
{
focusChangingEventHandler -= value;
//this is same as old PreFocusChangeSignal, so the body will be same. (only name is changed, behavior is same)
using PreFocusChangeSignal signal = PreFocusChangeSignal();
if (focusChangingEventHandler == null && signal?.Empty() == false)
{
signal?.Disconnect(focusChangingCallback);
}
}
}
///
/// The FocusChanged will be triggered after the current focused view has been changed.
///
/// 3
public event EventHandler FocusChanged
{
add
{
if (focusChangedEventCallback == null)
{
focusChangedEventCallback = OnFocusChanged;
using FocusChangedSignal signal = FocusChangedSignal();
signal?.Connect(focusChangedEventCallback);
}
focusChangedEventHandler += value;
}
remove
{
focusChangedEventHandler -= value;
using FocusChangedSignal signal = FocusChangedSignal();
if (focusChangedEventCallback == null && signal?.Empty() == false)
{
signal?.Disconnect(focusChangedEventCallback);
}
}
}
///
/// The FocusGroupChanged will be triggered when the focus group has been changed.
/// If the current focus group has a parent layout control, the FocusManager will make the best guess for the next focus group to move the focus to in the given direction (forward or backward).
/// If not, the application has to set the new focus.
///
/// 3
public event EventHandler FocusGroupChanged
{
add
{
if (focusGroupChangedEventCallback == null)
{
focusGroupChangedEventCallback = OnFocusGroupChanged;
using FocusGroupChangedSignal signal = FocusGroupChangedSignal();
signal?.Connect(focusGroupChangedEventCallback);
}
focusGroupChangedEventHandler += value;
}
remove
{
focusGroupChangedEventHandler -= value;
using FocusGroupChangedSignal signal = FocusGroupChangedSignal();
if (focusGroupChangedEventCallback == null && signal?.Empty() == false)
{
signal?.Disconnect(focusGroupChangedEventCallback);
}
}
}
///
/// The FocusedViewActivated will be triggered when the current focused view has the enter key pressed on it.
///
/// 3
public event EventHandler FocusedViewActivated
{
add
{
if (focusedViewEnterKeyEventCallback == null)
{
focusedViewEnterKeyEventCallback = OnFocusedViewEnterKey;
Interop.FocusManager.FocusedActorEnterKeySignalConnect(SwigCPtr, focusedViewEnterKeyEventCallback.ToHandleRef(this));
NDalicPINVOKE.ThrowExceptionIfExists();
}
focusedViewEnterKeyEventHandler += value;
}
remove
{
focusedViewEnterKeyEventHandler -= value;
if (focusedViewEnterKeyEventHandler == null && focusedViewEnterKeyEventCallback != null)
{
Interop.FocusManager.FocusedActorEnterKeySignalDisconnect(SwigCPtr, focusedViewEnterKeyEventCallback.ToHandleRef(this));
NDalicPINVOKE.ThrowExceptionIfExists();
focusedViewEnterKeyEventCallback = null;
}
}
}
///
/// [Obsolete("Do not use this, that will be deprecated.")]
///
/// 3
/// Do not use this, that will be deprecated.
/// Instead Use FocusedViewActivated.
[Obsolete("Do not use this, that will be deprecated. Use FocusManager.FocusedViewActivated instead. " +
"Like: " +
"FocusManager.Instance.FocusedViewActivated = OnFocusedViewActivated; " +
"private void OnFocusedViewActivated(object source, FocusManager.FocusedViewActivatedEventArgs args) {...}")]
[EditorBrowsable(EditorBrowsableState.Never)]
public event EventHandler FocusedViewEnterKeyPressed
{
add
{
if (focusedViewEnterKeyEventCallback2 == null)
{
focusedViewEnterKeyEventCallback2 = OnFocusedViewEnterKey2;
Interop.FocusManager.FocusedActorEnterKeySignalConnect(SwigCPtr, focusedViewEnterKeyEventCallback2.ToHandleRef(this));
NDalicPINVOKE.ThrowExceptionIfExists();
}
focusedViewEnterKeyEventHandler2 += value;
}
remove
{
focusedViewEnterKeyEventHandler2 -= value;
if (focusedViewEnterKeyEventHandler2 == null && focusedViewEnterKeyEventCallback2 != null)
{
Interop.FocusManager.FocusedActorEnterKeySignalDisconnect(SwigCPtr, focusedViewEnterKeyEventCallback2.ToHandleRef(this));
NDalicPINVOKE.ThrowExceptionIfExists();
focusedViewEnterKeyEventCallback2 = null;
}
}
}
///
/// ICustomFocusAlgorithm is used to provide the custom keyboard focus algorithm for retrieving the next focusable view.
/// The application can implement the interface and override the keyboard focus behavior.
/// If the focus is changing within a layout container, then the layout container is queried first to provide the next focusable view.
/// If this does not provide a valid view, then the Keyboard FocusManager will check focusable properties to determine the next focusable actor.
/// If focusable properties are not set, then the keyboard FocusManager calls the GetNextFocusableView() method of this interface.
///
/// 3
public interface ICustomFocusAlgorithm
{
///
/// Get the next focus actor.
///
/// The current focus view.
/// The proposed focus view
/// The focus move direction
/// The next focus actor.
/// 3
View GetNextFocusableView(View current, View proposed, View.FocusDirection direction);
}
///
/// Gets or sets the status of whether the focus movement should be looped within the same focus group.
/// The focus movement is not looped by default.
///
/// 3
public bool FocusGroupLoop
{
set
{
SetFocusGroupLoop(value);
}
get
{
return GetFocusGroupLoop();
}
}
///
/// Gets or sets the focus indicator view.
/// This will replace the default focus indicator view in the FocusManager and will be added to the focused view as a highlight.
///
/// 3
public View FocusIndicator
{
set
{
internalFocusIndicator = value;
if (internalFocusIndicator == null)
{
if (nullFocusIndicator == null)
{
nullFocusIndicator = new View();
}
SetFocusIndicatorView(nullFocusIndicator);
}
else
{
SetFocusIndicatorView(internalFocusIndicator);
}
}
get
{
return internalFocusIndicator;
}
}
///
/// Gets the singleton of the FocusManager object.
///
/// 3
public static FocusManager Instance
{
get
{
return instance;
}
}
///
/// Moves the keyboard focus to the given view.
/// Only one view can be focused at the same time.
/// The view must be in the stage already and keyboard focusable.
///
/// The view to be focused.
/// Whether the focus is successful or not.
/// 3
public bool SetCurrentFocusView(View view)
{
if (view == null)
{
throw new ArgumentNullException(nameof(view), "the target view should not be null");
}
bool ret = Interop.FocusManager.SetCurrentFocusActor(SwigCPtr, View.getCPtr(view));
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
return ret;
}
///
/// Gets the current focused view.
///
/// A handle to the current focused view or an empty handle if no view is focused.
/// 3
public View GetCurrentFocusView()
{
//to fix memory leak issue, match the handle count with native side.
IntPtr cPtr = Interop.FocusManager.GetCurrentFocusActor(SwigCPtr);
View ret = this.GetInstanceSafely(cPtr);
return ret;
}
///
/// Moves the focus to the next focusable view in the focus chain in the given direction (according to the focus traversal order).
///
/// The direction of the focus movement.
/// True if the movement was successful.
/// 3
public bool MoveFocus(View.FocusDirection direction)
{
bool ret = Interop.FocusManager.MoveFocus(SwigCPtr, (int)direction);
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
return ret;
}
///
/// Clears the focus from the current focused view if any, so that no view is focused in the focus chain.
/// It will emit the FocusChanged event without the current focused view.
///
/// 3
public void ClearFocus()
{
Interop.FocusManager.ClearFocus(SwigCPtr);
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
}
///
/// Move the focus to previous focused view.
///
/// 3
public void MoveFocusBackward()
{
Interop.FocusManager.MoveFocusBackward(SwigCPtr);
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
}
///
/// Sets whether the view is a focus group that can limit the scope of the focus movement to its child views in the focus chain.
/// Layout controls set themselves as focus groups by default.
///
/// The view to be set as a focus group.
/// Whether to set the view as a focus group or not.
/// 3
public void SetAsFocusGroup(View view, bool isFocusGroup)
{
Interop.FocusManager.SetAsFocusGroup(SwigCPtr, View.getCPtr(view), isFocusGroup);
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
}
///
/// Checks whether the view is set as a focus group or not.
///
/// The view to be checked.
/// Whether the view is set as a focus group.
/// 3
public bool IsFocusGroup(View view)
{
bool ret = Interop.FocusManager.IsFocusGroup(SwigCPtr, View.getCPtr(view));
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
return ret;
}
///
/// Returns the closest ancestor of the given view that is a focus group.
///
/// The view to be checked for its focus group.
/// The focus group the given view belongs to or an empty handle if the given view.
/// 3
public View GetFocusGroup(View view)
{
//to fix memory leak issue, match the handle count with native side.
IntPtr cPtr = Interop.FocusManager.GetFocusGroup(SwigCPtr, View.getCPtr(view));
View ret = this.GetInstanceSafely(cPtr);
return ret;
}
///
/// Provides the implementation of a custom focus algorithm interface to allow the application to define the focus logic.
///
/// The user's implementation of ICustomFocusAlgorithm.
/// 3
public void SetCustomAlgorithm(ICustomFocusAlgorithm arg0)
{
if (arg0 != null)
{
customAlgorithmInterfaceWrapper = new CustomAlgorithmInterfaceWrapper();
customAlgorithmInterfaceWrapper.SetFocusAlgorithm(arg0);
Interop.NDalic.SetCustomAlgorithm(SwigCPtr, CustomAlgorithmInterface.getCPtr(customAlgorithmInterfaceWrapper));
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
}
else
{
Interop.NDalic.SetCustomAlgorithm(SwigCPtr, new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero));
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
}
}
///
/// Sets to use the automatic focus moveing algorithm.
/// It moves the focus to the view closest to the keyboard movement direction.
///
/// Whether using default focus algorithm or not
[EditorBrowsable(EditorBrowsableState.Never)]
public void EnableDefaultAlgorithm(bool enable)
{
Interop.FocusManager.EnableDefaultAlgorithm(SwigCPtr, enable);
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
}
///
/// Checks default focus moveing algorithm is enabled or not
///
/// Whether default focus algorithm is enabled
[EditorBrowsable(EditorBrowsableState.Never)]
public bool IsDefaultAlgorithmEnabled()
{
bool ret = Interop.FocusManager.IsDefaultAlgorithmEnabled(SwigCPtr);
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
return ret;
}
///
/// Get the nearest focusable view.
///
/// The view group in which to find the next focusable view.
/// The current focused view.
/// The direction.
/// The nearest focusable view, or an empty handle if none exists.
[EditorBrowsable(EditorBrowsableState.Never)]
public View GetNearestFocusableActor(View rootView, View focusedView, View.FocusDirection direction)
{
//to fix memory leak issue, match the handle count with native side.
IntPtr cPtr = Interop.FocusManager.GetNearestFocusableActor(View.getCPtr(rootView), View.getCPtr(focusedView), (int)direction);
View ret = this.GetInstanceSafely(cPtr);
return ret;
}
///
/// Sets the root view to start moving focus when DefaultAlgorithm is enabled.
/// This will only look for focusable Views within that View tree when looking for the next focus.
///
/// The root view in which to find the next focusable view.
[EditorBrowsable(EditorBrowsableState.Never)]
public void SetFocusFinderRootView(View rootView)
{
Interop.FocusManager.SetFocusFinderRootView(SwigCPtr, View.getCPtr(rootView));
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
}
///
/// Reset the root view that starts moving focus when DefaultAlgorithm is enabled.
/// When reset, the window becomes root.
///
[EditorBrowsable(EditorBrowsableState.Never)]
public void ResetFocusFinderRootView()
{
Interop.FocusManager.ResetFocusFinderRootView(SwigCPtr);
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
}
///
/// Decide using focus indicator or not
///
/// Whether using focus indicator or not
[EditorBrowsable(EditorBrowsableState.Never)]
public void EnableFocusIndicator(bool enable)
{
Interop.FocusManager.EnableFocusIndicator(SwigCPtr, enable);
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
}
///
/// Check focus indicator is enabled or not
///
/// Whether focus indicator is enabled
[EditorBrowsable(EditorBrowsableState.Never)]
public bool IsFocusIndicatorEnabled()
{
bool ret = Interop.FocusManager.IsFocusIndicatorEnabled(SwigCPtr);
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
return ret;
}
///
/// Get a default focus indicator
///
///
/// The type actually of blue border squred png image, so it would be difficult to modify itself.
/// To change focus indicator, creating new indicator and assigning it to FocusIndicator are recommended.
/// For example,
///
/// FocusManager.Instance.FocusIndicator = new View()
/// {
/// PositionUsesPivotPoint = true,
/// PivotPoint = new Position(0, 0, 0),
/// WidthResizePolicy = ResizePolicyType.FillToParent,
/// HeightResizePolicy = ResizePolicyType.FillToParent,
/// BorderlineColor = Color.Orange,
/// BorderlineWidth = 4.0f,
/// BorderlineOffset = -1f,
/// BackgroundColor = new Color(0.2f, 0.2f, 0.2f, 0.2f),
/// };
///
///
/// instance of default focus indicator
[EditorBrowsable(EditorBrowsableState.Never)]
public View GetDefaultFocusIndicator()
{
ImageView ret = new ImageView(FrameworkInformation.ResourcePath + "keyboard_focus.9.png")
{
Name = "DefaultFocusIndicatorCreatedByNUI",
PositionUsesAnchorPoint = true,
ParentOrigin = ParentOrigin.Center,
PivotPoint = ParentOrigin.Center,
Position2D = new Position2D(0, 0),
};
ret.SetResizePolicy(ResizePolicyType.FillToParent, DimensionType.AllDimensions);
return ret;
}
internal static FocusManager Get()
{
FocusManager ret = new FocusManager(Interop.FocusManager.Get(), true);
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
#if !PROFILE_TV
//tv profile never use default focus indicator, so this is not needed!
ret.FocusIndicator = ret.GetDefaultFocusIndicator();
#endif
return ret;
}
internal void SetFocusGroupLoop(bool enabled)
{
Interop.FocusManager.SetFocusGroupLoop(SwigCPtr, enabled);
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
}
internal bool GetFocusGroupLoop()
{
bool ret = Interop.FocusManager.GetFocusGroupLoop(SwigCPtr);
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
return ret;
}
internal void SetFocusIndicatorView(View indicator)
{
Interop.FocusManager.SetFocusIndicatorActor(SwigCPtr, View.getCPtr(indicator));
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
}
internal View GetFocusIndicatorView()
{
//to fix memory leak issue, match the handle count with native side.
IntPtr cPtr = Interop.FocusManager.GetFocusIndicatorActor(SwigCPtr);
return this.GetInstanceSafely(cPtr);
}
internal PreFocusChangeSignal PreFocusChangeSignal()
{
PreFocusChangeSignal ret = new PreFocusChangeSignal(Interop.FocusManager.PreFocusChangeSignal(SwigCPtr), false);
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
return ret;
}
internal FocusChangedSignal FocusChangedSignal()
{
FocusChangedSignal ret = new FocusChangedSignal(Interop.FocusManager.FocusChangedSignal(SwigCPtr), false);
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
return ret;
}
internal FocusGroupChangedSignal FocusGroupChangedSignal()
{
FocusGroupChangedSignal ret = new FocusGroupChangedSignal(Interop.FocusManager.FocusGroupChangedSignal(SwigCPtr), false);
if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
return ret;
}
private IntPtr OnPreFocusChange(IntPtr current, IntPtr proposed, View.FocusDirection direction)
{
View view = null;
PreFocusChangeEventArgs e = new PreFocusChangeEventArgs();
if (current != global::System.IntPtr.Zero)
{
e.CurrentView = Registry.GetManagedBaseHandleFromNativePtr(current) as View;
}
if (proposed != global::System.IntPtr.Zero)
{
e.ProposedView = Registry.GetManagedBaseHandleFromNativePtr(proposed) as View;
}
e.Direction = direction;
if (preFocusChangeEventHandler != null)
{
view = preFocusChangeEventHandler(this, e);
}
if (view != null)
{
return view.GetPtrfromView();
}
else
{
if (e.ProposedView != null) return proposed;
else return current;
}
}
private IntPtr OnFocusChanging(IntPtr current, IntPtr proposed, View.FocusDirection direction)
{
View originallyProposed = null;
FocusChangingEventArgs e = new FocusChangingEventArgs();
if (current != global::System.IntPtr.Zero)
{
e.Current = Registry.GetManagedBaseHandleFromNativePtr(current) as View;
}
if (proposed != global::System.IntPtr.Zero)
{
originallyProposed = e.Proposed = Registry.GetManagedBaseHandleFromNativePtr(proposed) as View;
}
e.Direction = direction;
focusChangingEventHandler?.Invoke(this, e);
if (originallyProposed != e.Proposed)
{
//when user has changed Proposed
return e.Proposed.GetPtrfromView();
}
else
{
if (originallyProposed != null)
{
return proposed;
}
else
{
return current;
}
}
}
private void OnFocusChanged(IntPtr current, IntPtr next)
{
if (focusChangedEventHandler != null)
{
FocusChangedEventArgs e = new FocusChangedEventArgs();
e.Previous = e.CurrentView = Registry.GetManagedBaseHandleFromNativePtr(current) as View;
e.Current = e.NextView = Registry.GetManagedBaseHandleFromNativePtr(next) as View;
focusChangedEventHandler(this, e);
}
}
private void OnFocusGroupChanged(IntPtr current, bool forwardDirection)
{
if (focusGroupChangedEventHandler != null)
{
FocusGroupChangedEventArgs e = new FocusGroupChangedEventArgs();
e.CurrentView = Registry.GetManagedBaseHandleFromNativePtr(current) as View;
e.ForwardDirection = forwardDirection;
focusGroupChangedEventHandler(this, e);
}
}
private void OnFocusedViewEnterKey(IntPtr view)
{
if (focusedViewEnterKeyEventHandler != null)
{
FocusedViewActivatedEventArgs e = new FocusedViewActivatedEventArgs();
e.View = Registry.GetManagedBaseHandleFromNativePtr(view) as View;
focusedViewEnterKeyEventHandler(this, e);
}
}
///
/// Do not use this, that will be deprecated.
///
/// Do not use this, that will be deprecated.
/// Instead Use OnFocusedViewEnterKey.
[Obsolete("Do not use this, that will be deprecated. Use FocusManager.OnFocusedViewEnterKey instead.")]
[EditorBrowsable(EditorBrowsableState.Never)]
private void OnFocusedViewEnterKey2(IntPtr view)
{
if (focusedViewEnterKeyEventHandler != null)
{
FocusedViewActivatedEventArgs e = new FocusedViewActivatedEventArgs();
e.View = Registry.GetManagedBaseHandleFromNativePtr(view) as View;
focusedViewEnterKeyEventHandler(this, e);
}
}
///
/// Event arguments that passed via the PreFocusChange signal.
///
/// 3
[Obsolete("Please do not use! This will be deprecated in API10. Please use FocusChangingEventArgs instead!")]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1034:Nested types should not be visible", Justification = "")]
// this will be deprecated, so suppress warning would be OK.
public class PreFocusChangeEventArgs : EventArgs
{
private View current;
private View proposed;
private View.FocusDirection direction;
///
/// The current focus view.
///
/// 3
public View CurrentView
{
get
{
return current;
}
set
{
current = value;
}
}
///
/// The proposed view.
///
/// 3
public View ProposedView
{
get
{
return proposed;
}
set
{
proposed = value;
}
}
///
/// The focus move direction.
///
/// 3
public View.FocusDirection Direction
{
get
{
return direction;
}
set
{
direction = value;
}
}
}
///
/// Event arguments that passed via the FocusChanged signal.
///
/// 3
public class FocusChangedEventArgs : EventArgs
{
private View currentView;
private View nextView;
private View previous;
private View current;
///
/// The current focus view.
///
/// 3
[Obsolete("Please do not use! This will be deprecated! Please use Previous instead!")]
public View CurrentView
{
get
{
return currentView;
}
set
{
currentView = value;
}
}
///
/// The next focus view.
///
/// 3
[Obsolete("Please do not use! This will be deprecated! Please use Current instead!")]
public View NextView
{
get
{
return nextView;
}
set
{
nextView = value;
}
}
///
/// The previously focused view.
///
/// 10
public View Previous
{
get
{
return previous;
}
set
{
previous = value;
}
}
///
/// The current focused view after focus changed.
///
/// 10
public View Current
{
get
{
return current;
}
set
{
current = value;
}
}
}
///
/// Event arguments that passed via the FocusGroupChanged signal.
///
/// 3
public class FocusGroupChangedEventArgs : EventArgs
{
private View current;
private bool forwardDirection;
///
/// The current focus view.
///
/// 3
public View CurrentView
{
get
{
return current;
}
set
{
current = value;
}
}
///
/// The forward direction.
///
/// 3
public bool ForwardDirection
{
get
{
return forwardDirection;
}
set
{
forwardDirection = value;
}
}
}
///
/// Event arguments that passed via the FocusedViewEnterKey signal.
///
/// 3
public class FocusedViewActivatedEventArgs : EventArgs
{
private View view;
///
/// View.
///
/// 3
public View View
{
get
{
return view;
}
set
{
view = value;
}
}
}
///
/// Do not use this, that will be deprecated.
///
/// 3
/// Do not use this, that will be deprecated.
/// Instead Use FocusedViewActivatedEventArgs.
[Obsolete("Do not use this, that will be deprecated. Use FocusedViewActivatedEventArgs instead. " +
"Like: " +
"FocusManager.Instance.FocusedViewActivated = OnFocusedViewActivated; " +
"private void OnFocusedViewActivated(object source, FocusManager.FocusedViewActivatedEventArgs arg)" +
"{...}")]
[EditorBrowsable(EditorBrowsableState.Never)]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible")]
public class FocusedViewEnterKeyEventArgs : EventArgs
{
private View view;
///
/// View.
///
/// 3
public View View
{
get
{
return view;
}
set
{
view = value;
}
}
}
private class CustomAlgorithmInterfaceWrapper : CustomAlgorithmInterface
{
private FocusManager.ICustomFocusAlgorithm customFocusAlgorithm;
public CustomAlgorithmInterfaceWrapper()
{
}
public void SetFocusAlgorithm(FocusManager.ICustomFocusAlgorithm customFocusAlgorithm)
{
this.customFocusAlgorithm = customFocusAlgorithm;
}
public override View GetNextFocusableView(View current, View proposed, View.FocusDirection direction, string deviceName)
{
if (customFocusAlgorithm == null)
{
Tizen.Log.Error("NUI", $"[ERROR] User defined ICustomFocusAlgorithm interface class becomes unreachable. Null will be proposed for next focusing!");
return null;
}
if (customFocusAlgorithm is ICustomAwareDeviceFocusAlgorithm deviceAwared)
{
return deviceAwared.GetNextFocusableView(current, proposed, direction, deviceName);
}
else
{
return customFocusAlgorithm.GetNextFocusableView(current, proposed, direction);
}
}
}
}
}