/* * 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.StdCall)] internal delegate IntPtr PreFocusChangeEventCallback(IntPtr current, IntPtr proposed, View.FocusDirection direction); [UnmanagedFunctionPointer(CallingConvention.StdCall)] internal delegate void FocusChangedEventCallback(IntPtr current, IntPtr next); [UnmanagedFunctionPointer(CallingConvention.StdCall)] private delegate void FocusGroupChangedEventCallback(IntPtr current, bool forwardDirection); [UnmanagedFunctionPointer(CallingConvention.StdCall)] private delegate void FocusedViewEnterKeyEventCallback(IntPtr view); [UnmanagedFunctionPointer(CallingConvention.StdCall)] 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); } } } } }