7706b567e951bfe1e12097040c8a51b2df199b7a
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI / src / public / Input / FocusManager.cs
1 /*
2  * Copyright(c) 2021 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17
18 using System;
19 using System.Runtime.InteropServices;
20 using Tizen.NUI.BaseComponents;
21 using System.ComponentModel;
22
23 namespace Tizen.NUI
24 {
25     /// <summary>
26     /// Provides the functionality of handling keyboard navigation and maintaining the two-dimensional keyboard focus chain.<br />
27     /// It provides functionality of setting the focus and moving the focus in four directions( i.e., left, right, up, and down).<br />
28     /// It also draws a highlight for the focused view and sends an event when the focus is changed.<br />
29     /// </summary>
30     /// <since_tizen> 3 </since_tizen>
31     public class FocusManager : BaseHandle
32     {
33         private static readonly FocusManager instance = FocusManager.Get();
34         private CustomAlgorithmInterfaceWrapper customAlgorithmInterfaceWrapper;
35
36         private EventHandlerWithReturnType<object, PreFocusChangeEventArgs, View> preFocusChangeEventHandler;
37         private PreFocusChangeEventCallback preFocusChangeCallback;
38
39         private EventHandler<FocusChangedEventArgs> focusChangedEventHandler;
40         private FocusChangedEventCallback focusChangedEventCallback;
41
42         private EventHandler<FocusGroupChangedEventArgs> focusGroupChangedEventHandler;
43         private FocusGroupChangedEventCallback focusGroupChangedEventCallback;
44
45         private EventHandler<FocusedViewActivatedEventArgs> focusedViewEnterKeyEventHandler;
46         private FocusedViewEnterKeyEventCallback focusedViewEnterKeyEventCallback;
47
48         private EventHandler<FocusedViewActivatedEventArgs> focusedViewEnterKeyEventHandler2;
49         private FocusedViewEnterKeyEventCallback2 focusedViewEnterKeyEventCallback2;
50
51         internal FocusManager(global::System.IntPtr cPtr, bool cMemoryOwn) : base(cPtr, cMemoryOwn)
52         {
53         }
54
55         internal FocusManager() : this(Interop.FocusManager.NewFocusManager(), true)
56         {
57             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
58         }
59
60         [UnmanagedFunctionPointer(CallingConvention.StdCall)]
61         internal delegate IntPtr PreFocusChangeEventCallback(IntPtr current, IntPtr proposed, View.FocusDirection direction);
62
63         [UnmanagedFunctionPointer(CallingConvention.StdCall)]
64         internal delegate void FocusChangedEventCallback(IntPtr current, IntPtr next);
65
66         [UnmanagedFunctionPointer(CallingConvention.StdCall)]
67         private delegate void FocusGroupChangedEventCallback(IntPtr current, bool forwardDirection);
68
69         [UnmanagedFunctionPointer(CallingConvention.StdCall)]
70         private delegate void FocusedViewEnterKeyEventCallback(IntPtr view);
71
72         [UnmanagedFunctionPointer(CallingConvention.StdCall)]
73         private delegate void FocusedViewEnterKeyEventCallback2(IntPtr view);
74
75         private View internalFocusIndicator = null;
76
77         /// <summary>
78         /// PreFocusChange will be triggered before the focus is going to be changed.<br />
79         /// The FocusManager makes the best guess for which view to focus towards the given direction, but applications might want to change that.<br />
80         /// By connecting with this event, they can check the proposed view to focus and return a different view if they wish.<br />
81         /// This event is only triggered when the navigation key is pressed and KeyboardFocusManager tries to move the focus automatically.<br />
82         /// It won't be emitted for focus movement by calling the SetCurrentFocusView directly.<br />
83         /// </summary>
84         /// <since_tizen> 3 </since_tizen>
85         public event EventHandlerWithReturnType<object, PreFocusChangeEventArgs, View> PreFocusChange
86         {
87             add
88             {
89                 if (preFocusChangeEventHandler == null)
90                 {
91                     preFocusChangeCallback = OnPreFocusChange;
92                     PreFocusChangeSignal().Connect(preFocusChangeCallback);
93                 }
94                 preFocusChangeEventHandler += value;
95             }
96             remove
97             {
98                 preFocusChangeEventHandler -= value;
99                 if (preFocusChangeEventHandler == null && PreFocusChangeSignal().Empty() == false)
100                 {
101                     PreFocusChangeSignal().Disconnect(preFocusChangeCallback);
102                 }
103             }
104         }
105
106         /// <summary>
107         /// The FocusGroupChanged will be triggered after the current focused view has been changed.
108         /// </summary>
109         /// <since_tizen> 3 </since_tizen>
110         public event EventHandler<FocusChangedEventArgs> FocusChanged
111         {
112             add
113             {
114                 if (focusChangedEventCallback == null)
115                 {
116                     focusChangedEventCallback = OnFocusChanged;
117                     FocusChangedSignal().Connect(focusChangedEventCallback);
118                 }
119                 focusChangedEventHandler += value;
120             }
121             remove
122             {
123                 focusChangedEventHandler -= value;
124
125                 if (focusChangedEventCallback == null && FocusChangedSignal().Empty() == false)
126                 {
127                     FocusChangedSignal().Disconnect(focusChangedEventCallback);
128                 }
129             }
130         }
131
132         /// <summary>
133         /// The FocusGroupChanged will be triggered when the focus group has been changed.<br />
134         /// 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).<br />
135         /// If not, the application has to set the new focus.<br />
136         /// </summary>
137         /// <since_tizen> 3 </since_tizen>
138         public event EventHandler<FocusGroupChangedEventArgs> FocusGroupChanged
139         {
140             add
141             {
142                 if (focusGroupChangedEventCallback == null)
143                 {
144                     focusGroupChangedEventCallback = OnFocusGroupChanged;
145                     FocusGroupChangedSignal().Connect(focusGroupChangedEventCallback);
146                 }
147                 focusGroupChangedEventHandler += value;
148             }
149             remove
150             {
151                 focusGroupChangedEventHandler -= value;
152
153                 if (focusGroupChangedEventCallback == null && FocusGroupChangedSignal().Empty() == false)
154                 {
155                     FocusGroupChangedSignal().Disconnect(focusGroupChangedEventCallback);
156                 }
157             }
158         }
159
160         /// <summary>
161         /// The FocusedViewActivated will be triggered when the current focused view has the enter key pressed on it.
162         /// </summary>
163         /// <since_tizen> 3 </since_tizen>
164         public event EventHandler<FocusedViewActivatedEventArgs> FocusedViewActivated
165         {
166             add
167             {
168                 if (focusedViewEnterKeyEventCallback == null)
169                 {
170                     focusedViewEnterKeyEventCallback = OnFocusedViewEnterKey;
171                     FocusedViewEnterKeySignal().Connect(focusedViewEnterKeyEventCallback);
172                 }
173                 focusedViewEnterKeyEventHandler += value;
174             }
175             remove
176             {
177                 focusedViewEnterKeyEventHandler -= value;
178
179                 if (focusedViewEnterKeyEventCallback != null && FocusedViewEnterKeySignal().Empty() == false)
180                 {
181                     FocusedViewEnterKeySignal().Disconnect(focusedViewEnterKeyEventCallback);
182                 }
183             }
184         }
185
186         /// <summary>
187         /// [Obsolete("Please do not use! this will be deprecated")]
188         /// </summary>
189         /// <since_tizen> 3 </since_tizen>
190         /// Please do not use! this will be deprecated!
191         /// Instead please use FocusedViewActivated.
192         [Obsolete("Please do not use! This will be deprecated! Please use FocusManager.FocusedViewActivated instead! " +
193             "Like: " +
194             "FocusManager.Instance.FocusedViewActivated = OnFocusedViewActivated; " +
195             "private void OnFocusedViewActivated(object source, FocusManager.FocusedViewActivatedEventArgs args) {...}")]
196         [EditorBrowsable(EditorBrowsableState.Never)]
197         public event EventHandler<FocusedViewActivatedEventArgs> FocusedViewEnterKeyPressed
198         {
199             add
200             {
201                 if (focusedViewEnterKeyEventCallback2 == null)
202                 {
203                     focusedViewEnterKeyEventCallback2 = OnFocusedViewEnterKey2;
204                     FocusedViewEnterKeySignal().Connect(focusedViewEnterKeyEventCallback2);
205                 }
206                 focusedViewEnterKeyEventHandler2 += value;
207             }
208             remove
209             {
210                 focusedViewEnterKeyEventHandler2 -= value;
211
212                 if (focusedViewEnterKeyEventCallback2 != null && FocusedViewEnterKeySignal().Empty() == false)
213                 {
214                     FocusedViewEnterKeySignal().Disconnect(focusedViewEnterKeyEventCallback2);
215                 }
216             }
217         }
218
219         /// <summary>
220         /// ICustomFocusAlgorithm is used to provide the custom keyboard focus algorithm for retrieving the next focusable view.<br />
221         /// The application can implement the interface and override the keyboard focus behavior.<br />
222         /// If the focus is changing within a layout container, then the layout container is queried first to provide the next focusable view.<br />
223         /// If this does not provide a valid view, then the Keyboard FocusManager will check focusable properties to determine the next focusable actor.<br />
224         /// If focusable properties are not set, then the keyboard FocusManager calls the GetNextFocusableView() method of this interface.<br />
225         /// </summary>
226         /// <since_tizen> 3 </since_tizen>
227         public interface ICustomFocusAlgorithm
228         {
229             /// <summary>
230             /// Get the next focus actor.
231             /// </summary>
232             /// <param name="current">The current focus view.</param>
233             /// <param name="proposed">The proposed focus view</param>
234             /// <param name="direction">The focus move direction</param>
235             /// <returns>The next focus actor.</returns>
236             /// <since_tizen> 3 </since_tizen>
237             View GetNextFocusableView(View current, View proposed, View.FocusDirection direction);
238         }
239
240
241         /// <summary>
242         /// Gets or sets the status of whether the focus movement should be looped within the same focus group.<br />
243         /// The focus movement is not looped by default.<br />
244         /// </summary>
245         /// <since_tizen> 3 </since_tizen>
246         public bool FocusGroupLoop
247         {
248             set
249             {
250                 SetFocusGroupLoop(value);
251             }
252             get
253             {
254                 return GetFocusGroupLoop();
255             }
256         }
257
258         /// <summary>
259         /// Gets or sets the focus indicator view.<br />
260         /// This will replace the default focus indicator view in the FocusManager and will be added to the focused view as a highlight.<br />
261         /// </summary>
262         /// <since_tizen> 3 </since_tizen>
263         public View FocusIndicator
264         {
265             set
266             {
267                 SetFocusIndicatorView(value);
268             }
269             get
270             {
271                 return GetFocusIndicatorView();
272             }
273         }
274
275         /// <summary>
276         /// Gets the singleton of the FocusManager object.
277         /// </summary>
278         /// <since_tizen> 3 </since_tizen>
279         public static FocusManager Instance
280         {
281             get
282             {
283                 return instance;
284             }
285         }
286
287         /// <summary>
288         /// Moves the keyboard focus to the given view.<br />
289         /// Only one view can be focused at the same time.<br />
290         /// The view must be in the stage already and keyboard focusable.<br />
291         /// </summary>
292         /// <param name="view">The view to be focused.</param>
293         /// <returns>Whether the focus is successful or not.</returns>
294         /// <since_tizen> 3 </since_tizen>
295         public bool SetCurrentFocusView(View view)
296         {
297             if (view == null)
298             {
299                 throw new ArgumentNullException(nameof(view), "the target view should not be null");
300             }
301
302             bool ret = Interop.FocusManager.SetCurrentFocusActor(SwigCPtr, View.getCPtr(view));
303             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
304             return ret;
305         }
306
307         /// <summary>
308         /// Gets the current focused view.
309         /// </summary>
310         /// <returns>A handle to the current focused view or an empty handle if no view is focused.</returns>
311         /// <since_tizen> 3 </since_tizen>
312         public View GetCurrentFocusView()
313         {
314             //to fix memory leak issue, match the handle count with native side.
315             IntPtr cPtr = Interop.FocusManager.GetCurrentFocusActor(SwigCPtr);
316             View ret = this.GetInstanceSafely<View>(cPtr);
317             return ret;
318         }
319
320         /// <summary>
321         /// Moves the focus to the next focusable view in the focus chain in the given direction (according to the focus traversal order).
322         /// </summary>
323         /// <param name="direction">The direction of the focus movement.</param>
324         /// <returns>True if the movement was successful.</returns>
325         /// <since_tizen> 3 </since_tizen>
326         public bool MoveFocus(View.FocusDirection direction)
327         {
328             bool ret = Interop.FocusManager.MoveFocus(SwigCPtr, (int)direction);
329             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
330             return ret;
331         }
332
333         /// <summary>
334         /// Clears the focus from the current focused view if any, so that no view is focused in the focus chain.<br />
335         /// It will emit the FocusChanged event without the current focused view.<br />
336         /// </summary>
337         /// <since_tizen> 3 </since_tizen>
338         public void ClearFocus()
339         {
340             Interop.FocusManager.ClearFocus(SwigCPtr);
341             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
342         }
343
344         /// <summary>
345         /// Move the focus to previous focused view.
346         /// </summary>
347         /// <since_tizen> 3 </since_tizen>
348         public void MoveFocusBackward()
349         {
350             Interop.FocusManager.MoveFocusBackward(SwigCPtr);
351             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
352         }
353
354         /// <summary>
355         /// 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.<br />
356         /// Layout controls set themselves as focus groups by default.<br />
357         /// </summary>
358         /// <param name="view">The view to be set as a focus group.</param>
359         /// <param name="isFocusGroup">Whether to set the view as a focus group or not.</param>
360         /// <since_tizen> 3 </since_tizen>
361         public void SetAsFocusGroup(View view, bool isFocusGroup)
362         {
363             Interop.FocusManager.SetAsFocusGroup(SwigCPtr, View.getCPtr(view), isFocusGroup);
364             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
365         }
366
367         /// <summary>
368         /// Checks whether the view is set as a focus group or not.
369         /// </summary>
370         /// <param name="view">The view to be checked.</param>
371         /// <returns>Whether the view is set as a focus group.</returns>
372         /// <since_tizen> 3 </since_tizen>
373         public bool IsFocusGroup(View view)
374         {
375             bool ret = Interop.FocusManager.IsFocusGroup(SwigCPtr, View.getCPtr(view));
376             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
377             return ret;
378         }
379
380         /// <summary>
381         /// Returns the closest ancestor of the given view that is a focus group.
382         /// </summary>
383         /// <param name="view">The view to be checked for its focus group.</param>
384         /// <returns>The focus group the given view belongs to or an empty handle if the given view.</returns>
385         /// <since_tizen> 3 </since_tizen>
386         public View GetFocusGroup(View view)
387         {
388             //to fix memory leak issue, match the handle count with native side.
389             IntPtr cPtr = Interop.FocusManager.GetFocusGroup(SwigCPtr, View.getCPtr(view));
390             View ret = this.GetInstanceSafely<View>(cPtr);
391             return ret;
392         }
393
394         /// <summary>
395         /// Provides the implementation of a custom focus algorithm interface to allow the application to define the focus logic.<br />
396         /// </summary>
397         /// <param name="arg0">The user's implementation of ICustomFocusAlgorithm.</param>
398         /// <since_tizen> 3 </since_tizen>
399         public void SetCustomAlgorithm(ICustomFocusAlgorithm arg0)
400         {
401             if (arg0 != null)
402             {
403                 customAlgorithmInterfaceWrapper = new CustomAlgorithmInterfaceWrapper();
404                 customAlgorithmInterfaceWrapper.SetFocusAlgorithm(arg0);
405
406                 Interop.NDalic.SetCustomAlgorithm(SwigCPtr, CustomAlgorithmInterface.getCPtr(customAlgorithmInterfaceWrapper));
407                 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
408             }
409             else
410             {
411                 Interop.NDalic.SetCustomAlgorithm(SwigCPtr, new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero));
412                 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
413             }
414         }
415
416         /// <summary>
417         /// Sets to use the automatic focus moveing algorithm. <br />
418         /// It moves the focus to the view closest to the keyboard movement direction.
419         /// </summary>
420         /// <param name="enable">Whether using default focus algorithm or not</param>
421         [EditorBrowsable(EditorBrowsableState.Never)]
422         public void EnableDefaultAlgorithm(bool enable)
423         {
424             Interop.FocusManager.EnableDefaultAlgorithm(SwigCPtr, enable);
425             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
426         }
427
428         /// <summary>
429         ///  Checks default focus moveing algorithm is enabled or not
430         /// </summary>
431         /// <returns>Whether default focus algorithm is enabled</returns>
432         [EditorBrowsable(EditorBrowsableState.Never)]
433         public bool IsDefaultAlgorithmEnabled()
434         {
435             bool ret = Interop.FocusManager.IsDefaultAlgorithmEnabled(SwigCPtr);
436             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
437             return ret;
438         }
439
440         /// <summary>
441         /// Get the nearest focusable view.
442         /// </summary>
443         /// <param name="rootView">The view group in which to find the next focusable view.</param>
444         /// <param name="focusedView">The current focused view.</param>
445         /// <param name="direction">The direction.</param>
446         /// <returns>The nearest focusable view, or an empty handle if none exists.</returns>
447         [EditorBrowsable(EditorBrowsableState.Never)]
448         public View GetNearestFocusableActor(View rootView, View focusedView, View.FocusDirection direction)
449         {
450             //to fix memory leak issue, match the handle count with native side.
451             IntPtr cPtr = Interop.FocusManager.GetNearestFocusableActor(View.getCPtr(rootView), View.getCPtr(focusedView), (int)direction);
452             View ret = this.GetInstanceSafely<View>(cPtr);
453             return ret;
454         }
455
456         internal static FocusManager Get()
457         {
458             FocusManager ret = new FocusManager(Interop.FocusManager.Get(), true);
459             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
460             return ret;
461         }
462
463         internal void SetFocusGroupLoop(bool enabled)
464         {
465             Interop.FocusManager.SetFocusGroupLoop(SwigCPtr, enabled);
466             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
467         }
468
469         internal bool GetFocusGroupLoop()
470         {
471             bool ret = Interop.FocusManager.GetFocusGroupLoop(SwigCPtr);
472             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
473             return ret;
474         }
475
476         internal void SetFocusIndicatorView(View indicator)
477         {
478             Interop.FocusManager.SetFocusIndicatorActor(SwigCPtr, View.getCPtr(indicator));
479             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
480             internalFocusIndicator = indicator;
481         }
482
483         internal View GetFocusIndicatorView()
484         {
485             //to fix memory leak issue, match the handle count with native side.
486             IntPtr cPtr = Interop.FocusManager.GetFocusIndicatorActor(SwigCPtr);
487             internalFocusIndicator = this.GetInstanceSafely<View>(cPtr);
488             return internalFocusIndicator;
489         }
490
491         internal PreFocusChangeSignal PreFocusChangeSignal()
492         {
493             PreFocusChangeSignal ret = new PreFocusChangeSignal(Interop.FocusManager.PreFocusChangeSignal(SwigCPtr), false);
494             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
495             return ret;
496         }
497
498         internal FocusChangedSignal FocusChangedSignal()
499         {
500             FocusChangedSignal ret = new FocusChangedSignal(Interop.FocusManager.FocusChangedSignal(SwigCPtr), false);
501             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
502             return ret;
503         }
504
505         internal FocusGroupChangedSignal FocusGroupChangedSignal()
506         {
507             FocusGroupChangedSignal ret = new FocusGroupChangedSignal(Interop.FocusManager.FocusGroupChangedSignal(SwigCPtr), false);
508             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
509             return ret;
510         }
511
512         internal ViewSignal FocusedViewEnterKeySignal()
513         {
514             ViewSignal ret = new ViewSignal(Interop.FocusManager.FocusedActorEnterKeySignal(SwigCPtr), false);
515             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
516             return ret;
517         }
518
519         private IntPtr OnPreFocusChange(IntPtr current, IntPtr proposed, View.FocusDirection direction)
520         {
521             View view = null;
522             PreFocusChangeEventArgs e = new PreFocusChangeEventArgs();
523
524             if (current != global::System.IntPtr.Zero)
525             {
526                 e.CurrentView = Registry.GetManagedBaseHandleFromNativePtr(current) as View;
527             }
528             if (proposed != global::System.IntPtr.Zero)
529             {
530                 e.ProposedView = Registry.GetManagedBaseHandleFromNativePtr(proposed) as View;
531             }
532             e.Direction = direction;
533
534             if (preFocusChangeEventHandler != null)
535             {
536                 view = preFocusChangeEventHandler(this, e);
537             }
538
539             if (view != null)
540             {
541                 return view.GetPtrfromView();
542             }
543             else
544             {
545                 if (e.ProposedView != null) return proposed;
546                 else return current;
547             }
548         }
549
550         private void OnFocusChanged(IntPtr current, IntPtr next)
551         {
552             if (focusChangedEventHandler != null)
553             {
554                 FocusChangedEventArgs e = new FocusChangedEventArgs();
555
556                 e.CurrentView = Registry.GetManagedBaseHandleFromNativePtr(current) as View;
557                 e.NextView = Registry.GetManagedBaseHandleFromNativePtr(next) as View;
558                 focusChangedEventHandler(this, e);
559             }
560         }
561
562         private void OnFocusGroupChanged(IntPtr current, bool forwardDirection)
563         {
564             if (focusGroupChangedEventHandler != null)
565             {
566                 FocusGroupChangedEventArgs e = new FocusGroupChangedEventArgs();
567
568                 e.CurrentView = Registry.GetManagedBaseHandleFromNativePtr(current) as View;
569                 e.ForwardDirection = forwardDirection;
570                 focusGroupChangedEventHandler(this, e);
571             }
572         }
573
574         private void OnFocusedViewEnterKey(IntPtr view)
575         {
576             if (focusedViewEnterKeyEventHandler != null)
577             {
578                 FocusedViewActivatedEventArgs e = new FocusedViewActivatedEventArgs();
579                 e.View = Registry.GetManagedBaseHandleFromNativePtr(view) as View;
580                 focusedViewEnterKeyEventHandler(this, e);
581             }
582         }
583
584         /// <summary>
585         /// Please do not use! this will be deprecated!
586         /// </summary>
587         /// Please do not use! this will be deprecated!
588         /// Instead please use OnFocusedViewEnterKey.
589         [Obsolete("Please do not use! This will be deprecated! Please use FocusManager.OnFocusedViewEnterKey instead!")]
590         [EditorBrowsable(EditorBrowsableState.Never)]
591         private void OnFocusedViewEnterKey2(IntPtr view)
592         {
593             if (focusedViewEnterKeyEventHandler != null)
594             {
595                 FocusedViewActivatedEventArgs e = new FocusedViewActivatedEventArgs();
596                 e.View = Registry.GetManagedBaseHandleFromNativePtr(view) as View;
597                 focusedViewEnterKeyEventHandler(this, e);
598             }
599         }
600
601         ///<summary>
602         /// Event arguments that passed via the PreFocusChange signal.
603         /// </summary>
604         /// <since_tizen> 3 </since_tizen>
605         public class PreFocusChangeEventArgs : EventArgs
606         {
607             private View current;
608             private View proposed;
609             private View.FocusDirection direction;
610
611             /// <summary>
612             /// The current focus view.
613             /// </summary>
614             /// <since_tizen> 3 </since_tizen>
615             public View CurrentView
616             {
617                 get
618                 {
619                     return current;
620                 }
621                 set
622                 {
623                     current = value;
624                 }
625             }
626
627             /// <summary>
628             /// The  proposed view.
629             /// </summary>
630             /// <since_tizen> 3 </since_tizen>
631             public View ProposedView
632             {
633                 get
634                 {
635                     return proposed;
636                 }
637                 set
638                 {
639                     proposed = value;
640                 }
641             }
642
643             /// <summary>
644             /// The focus move direction.
645             /// </summary>
646             /// <since_tizen> 3 </since_tizen>
647             public View.FocusDirection Direction
648             {
649                 get
650                 {
651                     return direction;
652                 }
653                 set
654                 {
655                     direction = value;
656                 }
657             }
658         }
659
660         ///<summary>
661         /// Event arguments that passed via the FocusChanged signal.
662         /// </summary>
663         /// <since_tizen> 3 </since_tizen>
664         public class FocusChangedEventArgs : EventArgs
665         {
666             private View current;
667             private View next;
668
669             /// <summary>
670             /// The current focus view.
671             /// </summary>
672             /// <since_tizen> 3 </since_tizen>
673             public View CurrentView
674             {
675                 get
676                 {
677                     return current;
678                 }
679                 set
680                 {
681                     current = value;
682                 }
683             }
684             /// <summary>
685             /// The next focus view.
686             /// </summary>
687             /// <since_tizen> 3 </since_tizen>
688             public View NextView
689             {
690                 get
691                 {
692                     return next;
693                 }
694                 set
695                 {
696                     next = value;
697                 }
698             }
699         }
700
701         ///<summary>
702         /// Event arguments that passed via the FocusGroupChanged signal.
703         /// </summary>
704         /// <since_tizen> 3 </since_tizen>
705         public class FocusGroupChangedEventArgs : EventArgs
706         {
707             private View current;
708             private bool forwardDirection;
709
710             /// <summary>
711             /// The current focus view.
712             /// </summary>
713             /// <since_tizen> 3 </since_tizen>
714             public View CurrentView
715             {
716                 get
717                 {
718                     return current;
719                 }
720                 set
721                 {
722                     current = value;
723                 }
724             }
725
726             /// <summary>
727             /// The forward direction.
728             /// </summary>
729             /// <since_tizen> 3 </since_tizen>
730             public bool ForwardDirection
731             {
732                 get
733                 {
734                     return forwardDirection;
735                 }
736                 set
737                 {
738                     forwardDirection = value;
739                 }
740             }
741         }
742
743         ///<summary>
744         /// Event arguments that passed via the FocusedViewEnterKey signal.
745         /// </summary>
746         /// <since_tizen> 3 </since_tizen>
747         public class FocusedViewActivatedEventArgs : EventArgs
748         {
749             private View view;
750
751             /// <summary>
752             /// View.
753             /// </summary>
754             /// <since_tizen> 3 </since_tizen>
755             public View View
756             {
757                 get
758                 {
759                     return view;
760                 }
761                 set
762                 {
763                     view = value;
764                 }
765             }
766         }
767
768         /// <summary>
769         /// Please do not use! this will be deprecated
770         /// </summary>
771         /// <since_tizen> 3 </since_tizen>
772         /// Please do not use! this will be deprecated.
773         /// Instead please use FocusedViewActivatedEventArgs.
774         [Obsolete("Please do not use! This will be deprecated! Please use FocusedViewActivatedEventArgs instead! " +
775             "Like: " +
776             "FocusManager.Instance.FocusedViewActivated = OnFocusedViewActivated; " +
777             "private void OnFocusedViewActivated(object source, FocusManager.FocusedViewActivatedEventArgs arg)" +
778             "{...}")]
779         [EditorBrowsable(EditorBrowsableState.Never)]
780         [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible")]
781         public class FocusedViewEnterKeyEventArgs : EventArgs
782         {
783             private View view;
784
785             /// <summary>
786             /// View.
787             /// </summary>
788             /// <since_tizen> 3 </since_tizen>
789             public View View
790             {
791                 get
792                 {
793                     return view;
794                 }
795                 set
796                 {
797                     view = value;
798                 }
799             }
800         }
801
802         private class CustomAlgorithmInterfaceWrapper : CustomAlgorithmInterface
803         {
804             private FocusManager.ICustomFocusAlgorithm customFocusAlgorithm;
805
806             public CustomAlgorithmInterfaceWrapper()
807             {
808             }
809
810             public void SetFocusAlgorithm(FocusManager.ICustomFocusAlgorithm customFocusAlgorithm)
811             {
812                 this.customFocusAlgorithm = customFocusAlgorithm;
813             }
814
815             public override View GetNextFocusableView(View current, View proposed, View.FocusDirection direction, string deviceName)
816             {
817                 if (customFocusAlgorithm == null)
818                 {
819                     Tizen.Log.Error("NUI", $"[ERROR] User defined ICustomFocusAlgorithm interface class becomes unreachable. Null will be proposed for next focusing!");
820                     return null;
821                 }
822                 if (customFocusAlgorithm is ICustomAwareDeviceFocusAlgorithm deviceAwared)
823                 {
824                     return deviceAwared.GetNextFocusableView(current, proposed, direction, deviceName);
825                 }
826                 else
827                 {
828                     return customFocusAlgorithm.GetNextFocusableView(current, proposed, direction);
829                 }
830             }
831         }
832     }
833 }