[NUI] make Theme not be loaded in tv profile
[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<FocusChangingEventArgs> focusChangingEventHandler;
40         private PreFocusChangeEventCallback focusChangingCallback;
41
42         private EventHandler<FocusChangedEventArgs> focusChangedEventHandler;
43         private FocusChangedEventCallback focusChangedEventCallback;
44
45         private EventHandler<FocusGroupChangedEventArgs> focusGroupChangedEventHandler;
46         private FocusGroupChangedEventCallback focusGroupChangedEventCallback;
47
48         private EventHandler<FocusedViewActivatedEventArgs> focusedViewEnterKeyEventHandler;
49         private FocusedViewEnterKeyEventCallback focusedViewEnterKeyEventCallback;
50
51         private EventHandler<FocusedViewActivatedEventArgs> focusedViewEnterKeyEventHandler2;
52         private FocusedViewEnterKeyEventCallback2 focusedViewEnterKeyEventCallback2;
53
54         internal FocusManager(global::System.IntPtr cPtr, bool cMemoryOwn) : base(cPtr, cMemoryOwn)
55         {
56         }
57
58         internal FocusManager() : this(Interop.FocusManager.NewFocusManager(), true)
59         {
60             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
61         }
62
63         [UnmanagedFunctionPointer(CallingConvention.StdCall)]
64         internal delegate IntPtr PreFocusChangeEventCallback(IntPtr current, IntPtr proposed, View.FocusDirection direction);
65
66         [UnmanagedFunctionPointer(CallingConvention.StdCall)]
67         internal delegate void FocusChangedEventCallback(IntPtr current, IntPtr next);
68
69         [UnmanagedFunctionPointer(CallingConvention.StdCall)]
70         private delegate void FocusGroupChangedEventCallback(IntPtr current, bool forwardDirection);
71
72         [UnmanagedFunctionPointer(CallingConvention.StdCall)]
73         private delegate void FocusedViewEnterKeyEventCallback(IntPtr view);
74
75         [UnmanagedFunctionPointer(CallingConvention.StdCall)]
76         private delegate void FocusedViewEnterKeyEventCallback2(IntPtr view);
77
78         private View internalFocusIndicator = null;
79         private View nullFocusIndicator = null;
80
81         /// <summary>
82         /// PreFocusChange will be triggered before the focus is going to be changed.<br />
83         /// The FocusManager makes the best guess for which view to focus towards the given direction, but applications might want to change that.<br />
84         /// By connecting with this event, they can check the proposed view to focus and return a different view if they wish.<br />
85         /// This event is only triggered when the navigation key is pressed and KeyboardFocusManager tries to move the focus automatically.<br />
86         /// It won't be emitted for focus movement by calling the SetCurrentFocusView directly.<br />
87         /// </summary>
88         /// <since_tizen> 3 </since_tizen>
89         [Obsolete("Please do not use! This will be deprecated in API10. Please use FocusChanging instead!")]
90         // this will be deprecated, so suppress warning would be OK.
91         [System.Diagnostics.CodeAnalysis.SuppressMessage("Naming", "CA1710:Identifiers should have correct suffix", Justification = "<Pending>")]
92         public event EventHandlerWithReturnType<object, PreFocusChangeEventArgs, View> PreFocusChange
93         {
94             add
95             {
96                 if (preFocusChangeEventHandler == null)
97                 {
98                     preFocusChangeCallback = OnPreFocusChange;
99                     using PreFocusChangeSignal signal = PreFocusChangeSignal();
100                     signal?.Connect(preFocusChangeCallback);
101                 }
102                 preFocusChangeEventHandler += value;
103             }
104             remove
105             {
106                 preFocusChangeEventHandler -= value;
107                 using PreFocusChangeSignal signal = PreFocusChangeSignal();
108                 if (preFocusChangeEventHandler == null && signal?.Empty() == false)
109                 {
110                     signal?.Disconnect(preFocusChangeCallback);
111                 }
112             }
113         }
114
115         /// <summary>
116         /// FocusChanging will be triggered before the focus is going to be changed.<br />
117         /// The FocusManager makes the best guess for which view to focus towards the given direction, but applications might want to change that.<br />
118         /// By connecting with this event, they can check the proposed view to focus and assign a different view if they wish.<br />
119         /// This event is only triggered when the navigation key is pressed and FocusManager tries to move the focus automatically.<br />
120         /// It won't be emitted for focus movement by calling the SetCurrentFocusView directly.<br />
121         /// </summary>
122         /// <remarks>
123         /// By setting FocusChangingEventArgs.Proposed with the view to be focused, the focus will be moved to the assigned view.
124         /// </remarks>
125         /// <since_tizen> 10 </since_tizen>
126         public event EventHandler<FocusChangingEventArgs> FocusChanging
127         {
128             add
129             {
130                 if (focusChangingEventHandler == null)
131                 {
132                     focusChangingCallback = OnFocusChanging;
133                     //this is same as old PreFocusChangeSignal, so the body will be same. (only name is changed, behavior is same)
134                     using PreFocusChangeSignal signal = PreFocusChangeSignal();
135                     signal?.Connect(focusChangingCallback);
136                 }
137                 focusChangingEventHandler += value;
138             }
139             remove
140             {
141                 focusChangingEventHandler -= value;
142                 //this is same as old PreFocusChangeSignal, so the body will be same. (only name is changed, behavior is same)
143                 using PreFocusChangeSignal signal = PreFocusChangeSignal();
144                 if (focusChangingEventHandler == null && signal?.Empty() == false)
145                 {
146                     signal?.Disconnect(focusChangingCallback);
147                 }
148             }
149         }
150
151         /// <summary>
152         /// The FocusChanged will be triggered after the current focused view has been changed.
153         /// </summary>
154         /// <since_tizen> 3 </since_tizen>
155         public event EventHandler<FocusChangedEventArgs> FocusChanged
156         {
157             add
158             {
159                 if (focusChangedEventCallback == null)
160                 {
161                     focusChangedEventCallback = OnFocusChanged;
162                     using FocusChangedSignal signal = FocusChangedSignal();
163                     signal?.Connect(focusChangedEventCallback);
164                 }
165                 focusChangedEventHandler += value;
166             }
167             remove
168             {
169                 focusChangedEventHandler -= value;
170
171                 using FocusChangedSignal signal = FocusChangedSignal();
172                 if (focusChangedEventCallback == null && signal?.Empty() == false)
173                 {
174                     signal?.Disconnect(focusChangedEventCallback);
175                 }
176             }
177         }
178
179         /// <summary>
180         /// The FocusGroupChanged will be triggered when the focus group has been changed.<br />
181         /// 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 />
182         /// If not, the application has to set the new focus.<br />
183         /// </summary>
184         /// <since_tizen> 3 </since_tizen>
185         public event EventHandler<FocusGroupChangedEventArgs> FocusGroupChanged
186         {
187             add
188             {
189                 if (focusGroupChangedEventCallback == null)
190                 {
191                     focusGroupChangedEventCallback = OnFocusGroupChanged;
192                     using FocusGroupChangedSignal signal = FocusGroupChangedSignal();
193                     signal?.Connect(focusGroupChangedEventCallback);
194                 }
195                 focusGroupChangedEventHandler += value;
196             }
197             remove
198             {
199                 focusGroupChangedEventHandler -= value;
200
201                 using FocusGroupChangedSignal signal = FocusGroupChangedSignal();
202                 if (focusGroupChangedEventCallback == null && signal?.Empty() == false)
203                 {
204                     signal?.Disconnect(focusGroupChangedEventCallback);
205                 }
206             }
207         }
208
209         /// <summary>
210         /// The FocusedViewActivated will be triggered when the current focused view has the enter key pressed on it.
211         /// </summary>
212         /// <since_tizen> 3 </since_tizen>
213         public event EventHandler<FocusedViewActivatedEventArgs> FocusedViewActivated
214         {
215             add
216             {
217                 if (focusedViewEnterKeyEventCallback == null)
218                 {
219                     focusedViewEnterKeyEventCallback = OnFocusedViewEnterKey;
220                     using ViewSignal signal = FocusedViewEnterKeySignal();
221                     signal?.Connect(focusedViewEnterKeyEventCallback);
222                 }
223                 focusedViewEnterKeyEventHandler += value;
224             }
225             remove
226             {
227                 focusedViewEnterKeyEventHandler -= value;
228
229                 using ViewSignal signal = FocusedViewEnterKeySignal();
230                 if (focusedViewEnterKeyEventCallback != null && signal?.Empty() == false)
231                 {
232                     signal?.Disconnect(focusedViewEnterKeyEventCallback);
233                 }
234             }
235         }
236
237         /// <summary>
238         /// [Obsolete("Do not use this, that will be deprecated.")]
239         /// </summary>
240         /// <since_tizen> 3 </since_tizen>
241         /// Do not use this, that will be deprecated.
242         /// Instead Use FocusedViewActivated.
243         [Obsolete("Do not use this, that will be deprecated. Use FocusManager.FocusedViewActivated instead. " +
244             "Like: " +
245             "FocusManager.Instance.FocusedViewActivated = OnFocusedViewActivated; " +
246             "private void OnFocusedViewActivated(object source, FocusManager.FocusedViewActivatedEventArgs args) {...}")]
247         [EditorBrowsable(EditorBrowsableState.Never)]
248         public event EventHandler<FocusedViewActivatedEventArgs> FocusedViewEnterKeyPressed
249         {
250             add
251             {
252                 if (focusedViewEnterKeyEventCallback2 == null)
253                 {
254                     focusedViewEnterKeyEventCallback2 = OnFocusedViewEnterKey2;
255                     using ViewSignal signal = FocusedViewEnterKeySignal();
256                     signal?.Connect(focusedViewEnterKeyEventCallback2);
257                 }
258                 focusedViewEnterKeyEventHandler2 += value;
259             }
260             remove
261             {
262                 focusedViewEnterKeyEventHandler2 -= value;
263
264                 using ViewSignal signal = FocusedViewEnterKeySignal();
265                 if (focusedViewEnterKeyEventCallback2 != null && signal?.Empty() == false)
266                 {
267                     signal?.Disconnect(focusedViewEnterKeyEventCallback2);
268                 }
269             }
270         }
271
272         /// <summary>
273         /// ICustomFocusAlgorithm is used to provide the custom keyboard focus algorithm for retrieving the next focusable view.<br />
274         /// The application can implement the interface and override the keyboard focus behavior.<br />
275         /// If the focus is changing within a layout container, then the layout container is queried first to provide the next focusable view.<br />
276         /// If this does not provide a valid view, then the Keyboard FocusManager will check focusable properties to determine the next focusable actor.<br />
277         /// If focusable properties are not set, then the keyboard FocusManager calls the GetNextFocusableView() method of this interface.<br />
278         /// </summary>
279         /// <since_tizen> 3 </since_tizen>
280         public interface ICustomFocusAlgorithm
281         {
282             /// <summary>
283             /// Get the next focus actor.
284             /// </summary>
285             /// <param name="current">The current focus view.</param>
286             /// <param name="proposed">The proposed focus view</param>
287             /// <param name="direction">The focus move direction</param>
288             /// <returns>The next focus actor.</returns>
289             /// <since_tizen> 3 </since_tizen>
290             View GetNextFocusableView(View current, View proposed, View.FocusDirection direction);
291         }
292
293
294         /// <summary>
295         /// Gets or sets the status of whether the focus movement should be looped within the same focus group.<br />
296         /// The focus movement is not looped by default.<br />
297         /// </summary>
298         /// <since_tizen> 3 </since_tizen>
299         public bool FocusGroupLoop
300         {
301             set
302             {
303                 SetFocusGroupLoop(value);
304             }
305             get
306             {
307                 return GetFocusGroupLoop();
308             }
309         }
310
311         /// <summary>
312         /// Gets or sets the focus indicator view.<br />
313         /// This will replace the default focus indicator view in the FocusManager and will be added to the focused view as a highlight.<br />
314         /// </summary>
315         /// <since_tizen> 3 </since_tizen>
316         public View FocusIndicator
317         {
318             set
319             {
320                 internalFocusIndicator = value;
321                 if (internalFocusIndicator == null)
322                 {
323                     if (nullFocusIndicator == null)
324                     {
325                         nullFocusIndicator = new View();
326                     }
327                     SetFocusIndicatorView(nullFocusIndicator);
328                 }
329                 else
330                 {
331                     SetFocusIndicatorView(internalFocusIndicator);
332                 }
333             }
334             get
335             {
336                 return internalFocusIndicator;
337             }
338         }
339
340         /// <summary>
341         /// Gets the singleton of the FocusManager object.
342         /// </summary>
343         /// <since_tizen> 3 </since_tizen>
344         public static FocusManager Instance
345         {
346             get
347             {
348                 return instance;
349             }
350         }
351
352         /// <summary>
353         /// Moves the keyboard focus to the given view.<br />
354         /// Only one view can be focused at the same time.<br />
355         /// The view must be in the stage already and keyboard focusable.<br />
356         /// </summary>
357         /// <param name="view">The view to be focused.</param>
358         /// <returns>Whether the focus is successful or not.</returns>
359         /// <since_tizen> 3 </since_tizen>
360         public bool SetCurrentFocusView(View view)
361         {
362             if (view == null)
363             {
364                 throw new ArgumentNullException(nameof(view), "the target view should not be null");
365             }
366
367             bool ret = Interop.FocusManager.SetCurrentFocusActor(SwigCPtr, View.getCPtr(view));
368             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
369             return ret;
370         }
371
372         /// <summary>
373         /// Gets the current focused view.
374         /// </summary>
375         /// <returns>A handle to the current focused view or an empty handle if no view is focused.</returns>
376         /// <since_tizen> 3 </since_tizen>
377         public View GetCurrentFocusView()
378         {
379             //to fix memory leak issue, match the handle count with native side.
380             IntPtr cPtr = Interop.FocusManager.GetCurrentFocusActor(SwigCPtr);
381             View ret = this.GetInstanceSafely<View>(cPtr);
382             return ret;
383         }
384
385         /// <summary>
386         /// Moves the focus to the next focusable view in the focus chain in the given direction (according to the focus traversal order).
387         /// </summary>
388         /// <param name="direction">The direction of the focus movement.</param>
389         /// <returns>True if the movement was successful.</returns>
390         /// <since_tizen> 3 </since_tizen>
391         public bool MoveFocus(View.FocusDirection direction)
392         {
393             bool ret = Interop.FocusManager.MoveFocus(SwigCPtr, (int)direction);
394             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
395             return ret;
396         }
397
398         /// <summary>
399         /// Clears the focus from the current focused view if any, so that no view is focused in the focus chain.<br />
400         /// It will emit the FocusChanged event without the current focused view.<br />
401         /// </summary>
402         /// <since_tizen> 3 </since_tizen>
403         public void ClearFocus()
404         {
405             Interop.FocusManager.ClearFocus(SwigCPtr);
406             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
407         }
408
409         /// <summary>
410         /// Move the focus to previous focused view.
411         /// </summary>
412         /// <since_tizen> 3 </since_tizen>
413         public void MoveFocusBackward()
414         {
415             Interop.FocusManager.MoveFocusBackward(SwigCPtr);
416             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
417         }
418
419         /// <summary>
420         /// 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 />
421         /// Layout controls set themselves as focus groups by default.<br />
422         /// </summary>
423         /// <param name="view">The view to be set as a focus group.</param>
424         /// <param name="isFocusGroup">Whether to set the view as a focus group or not.</param>
425         /// <since_tizen> 3 </since_tizen>
426         public void SetAsFocusGroup(View view, bool isFocusGroup)
427         {
428             Interop.FocusManager.SetAsFocusGroup(SwigCPtr, View.getCPtr(view), isFocusGroup);
429             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
430         }
431
432         /// <summary>
433         /// Checks whether the view is set as a focus group or not.
434         /// </summary>
435         /// <param name="view">The view to be checked.</param>
436         /// <returns>Whether the view is set as a focus group.</returns>
437         /// <since_tizen> 3 </since_tizen>
438         public bool IsFocusGroup(View view)
439         {
440             bool ret = Interop.FocusManager.IsFocusGroup(SwigCPtr, View.getCPtr(view));
441             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
442             return ret;
443         }
444
445         /// <summary>
446         /// Returns the closest ancestor of the given view that is a focus group.
447         /// </summary>
448         /// <param name="view">The view to be checked for its focus group.</param>
449         /// <returns>The focus group the given view belongs to or an empty handle if the given view.</returns>
450         /// <since_tizen> 3 </since_tizen>
451         public View GetFocusGroup(View view)
452         {
453             //to fix memory leak issue, match the handle count with native side.
454             IntPtr cPtr = Interop.FocusManager.GetFocusGroup(SwigCPtr, View.getCPtr(view));
455             View ret = this.GetInstanceSafely<View>(cPtr);
456             return ret;
457         }
458
459         /// <summary>
460         /// Provides the implementation of a custom focus algorithm interface to allow the application to define the focus logic.<br />
461         /// </summary>
462         /// <param name="arg0">The user's implementation of ICustomFocusAlgorithm.</param>
463         /// <since_tizen> 3 </since_tizen>
464         public void SetCustomAlgorithm(ICustomFocusAlgorithm arg0)
465         {
466             if (arg0 != null)
467             {
468                 customAlgorithmInterfaceWrapper = new CustomAlgorithmInterfaceWrapper();
469                 customAlgorithmInterfaceWrapper.SetFocusAlgorithm(arg0);
470
471                 Interop.NDalic.SetCustomAlgorithm(SwigCPtr, CustomAlgorithmInterface.getCPtr(customAlgorithmInterfaceWrapper));
472                 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
473             }
474             else
475             {
476                 Interop.NDalic.SetCustomAlgorithm(SwigCPtr, new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero));
477                 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
478             }
479         }
480
481         /// <summary>
482         /// Sets to use the automatic focus moveing algorithm. <br />
483         /// It moves the focus to the view closest to the keyboard movement direction.
484         /// </summary>
485         /// <param name="enable">Whether using default focus algorithm or not</param>
486         [EditorBrowsable(EditorBrowsableState.Never)]
487         public void EnableDefaultAlgorithm(bool enable)
488         {
489             Interop.FocusManager.EnableDefaultAlgorithm(SwigCPtr, enable);
490             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
491         }
492
493         /// <summary>
494         ///  Checks default focus moveing algorithm is enabled or not
495         /// </summary>
496         /// <returns>Whether default focus algorithm is enabled</returns>
497         [EditorBrowsable(EditorBrowsableState.Never)]
498         public bool IsDefaultAlgorithmEnabled()
499         {
500             bool ret = Interop.FocusManager.IsDefaultAlgorithmEnabled(SwigCPtr);
501             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
502             return ret;
503         }
504
505         /// <summary>
506         /// Get the nearest focusable view.
507         /// </summary>
508         /// <param name="rootView">The view group in which to find the next focusable view.</param>
509         /// <param name="focusedView">The current focused view.</param>
510         /// <param name="direction">The direction.</param>
511         /// <returns>The nearest focusable view, or an empty handle if none exists.</returns>
512         [EditorBrowsable(EditorBrowsableState.Never)]
513         public View GetNearestFocusableActor(View rootView, View focusedView, View.FocusDirection direction)
514         {
515             //to fix memory leak issue, match the handle count with native side.
516             IntPtr cPtr = Interop.FocusManager.GetNearestFocusableActor(View.getCPtr(rootView), View.getCPtr(focusedView), (int)direction);
517             View ret = this.GetInstanceSafely<View>(cPtr);
518             return ret;
519         }
520
521         /// <summary>
522         /// Sets the root view to start moving focus when DefaultAlgorithm is enabled.
523         /// This will only look for focusable Views within that View tree when looking for the next focus.
524         /// </summary>
525         /// <param name="rootView">The root view in which to find the next focusable view.</param>
526         [EditorBrowsable(EditorBrowsableState.Never)]
527         public void SetFocusFinderRootView(View rootView)
528         {
529             Interop.FocusManager.SetFocusFinderRootView(SwigCPtr, View.getCPtr(rootView));
530             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
531         }
532
533         /// <summary>
534         /// Reset the root view that starts moving focus when DefaultAlgorithm is enabled.
535         /// When reset, the window becomes root.
536         /// </summary>
537         [EditorBrowsable(EditorBrowsableState.Never)]
538         public void ResetFocusFinderRootView()
539         {
540             Interop.FocusManager.ResetFocusFinderRootView(SwigCPtr);
541             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
542         }
543
544         /// <summary>
545         /// Get a default focus indicator
546         /// </summary>
547         /// <remarks>
548         /// The type actually <see cref="Tizen.NUI.BaseComponents.ImageView"/> of blue border squred png image, so it would be difficult to modify itself.
549         /// To change focus indicator, creating new indicator and assigning it to FocusIndicator are recommended.
550         /// For example,
551         /// <code>
552         /// FocusManager.Instance.FocusIndicator = new View()
553         /// {
554         ///     PositionUsesPivotPoint = true,
555         ///     PivotPoint = new Position(0, 0, 0),
556         ///     WidthResizePolicy = ResizePolicyType.FillToParent,
557         ///     HeightResizePolicy = ResizePolicyType.FillToParent,
558         ///     BorderlineColor = Color.Orange,
559         ///     BorderlineWidth = 4.0f,
560         ///     BorderlineOffset = -1f,
561         ///     BackgroundColor = new Color(0.2f, 0.2f, 0.2f, 0.2f),
562         /// };
563         /// </code>
564         /// </remarks>
565         /// <returns>instance of default focus indicator</returns>
566         [EditorBrowsable(EditorBrowsableState.Never)]
567         public View GetDefaultFocusIndicator()
568         {
569             ImageView ret = new ImageView(FrameworkInformation.ResourcePath + "keyboard_focus.9.png")
570             {
571                 Name = "DefaultFocusIndicatorCreatedByNUI",
572                 PositionUsesAnchorPoint = true,
573                 ParentOrigin = ParentOrigin.Center,
574                 PivotPoint = ParentOrigin.Center,
575                 Position2D = new Position2D(0, 0),
576             };
577             ret.SetResizePolicy(ResizePolicyType.FillToParent, DimensionType.AllDimensions);
578             return ret;
579         }
580
581         internal static FocusManager Get()
582         {
583             FocusManager ret = new FocusManager(Interop.FocusManager.Get(), true);
584             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
585
586 #if !PROFILE_TV
587             //tv profile never use default focus indicator, so this is not needed!
588             ret.FocusIndicator = ret.GetDefaultFocusIndicator();
589 #endif
590             return ret;
591         }
592
593         internal void SetFocusGroupLoop(bool enabled)
594         {
595             Interop.FocusManager.SetFocusGroupLoop(SwigCPtr, enabled);
596             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
597         }
598
599         internal bool GetFocusGroupLoop()
600         {
601             bool ret = Interop.FocusManager.GetFocusGroupLoop(SwigCPtr);
602             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
603             return ret;
604         }
605
606         internal void SetFocusIndicatorView(View indicator)
607         {
608             Interop.FocusManager.SetFocusIndicatorActor(SwigCPtr, View.getCPtr(indicator));
609             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
610         }
611
612         internal View GetFocusIndicatorView()
613         {
614             //to fix memory leak issue, match the handle count with native side.
615             IntPtr cPtr = Interop.FocusManager.GetFocusIndicatorActor(SwigCPtr);
616             return this.GetInstanceSafely<View>(cPtr);
617         }
618
619         internal PreFocusChangeSignal PreFocusChangeSignal()
620         {
621             PreFocusChangeSignal ret = new PreFocusChangeSignal(Interop.FocusManager.PreFocusChangeSignal(SwigCPtr), false);
622             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
623             return ret;
624         }
625
626         internal FocusChangedSignal FocusChangedSignal()
627         {
628             FocusChangedSignal ret = new FocusChangedSignal(Interop.FocusManager.FocusChangedSignal(SwigCPtr), false);
629             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
630             return ret;
631         }
632
633         internal FocusGroupChangedSignal FocusGroupChangedSignal()
634         {
635             FocusGroupChangedSignal ret = new FocusGroupChangedSignal(Interop.FocusManager.FocusGroupChangedSignal(SwigCPtr), false);
636             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
637             return ret;
638         }
639
640         internal ViewSignal FocusedViewEnterKeySignal()
641         {
642             ViewSignal ret = new ViewSignal(Interop.FocusManager.FocusedActorEnterKeySignal(SwigCPtr), false);
643             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
644             return ret;
645         }
646
647         private IntPtr OnPreFocusChange(IntPtr current, IntPtr proposed, View.FocusDirection direction)
648         {
649             View view = null;
650             PreFocusChangeEventArgs e = new PreFocusChangeEventArgs();
651
652             if (current != global::System.IntPtr.Zero)
653             {
654                 e.CurrentView = Registry.GetManagedBaseHandleFromNativePtr(current) as View;
655             }
656             if (proposed != global::System.IntPtr.Zero)
657             {
658                 e.ProposedView = Registry.GetManagedBaseHandleFromNativePtr(proposed) as View;
659             }
660             e.Direction = direction;
661
662             if (preFocusChangeEventHandler != null)
663             {
664                 view = preFocusChangeEventHandler(this, e);
665             }
666
667             if (view != null)
668             {
669                 return view.GetPtrfromView();
670             }
671             else
672             {
673                 if (e.ProposedView != null) return proposed;
674                 else return current;
675             }
676         }
677
678         private IntPtr OnFocusChanging(IntPtr current, IntPtr proposed, View.FocusDirection direction)
679         {
680             View originallyProposed = null;
681             FocusChangingEventArgs e = new FocusChangingEventArgs();
682
683             if (current != global::System.IntPtr.Zero)
684             {
685                 e.Current = Registry.GetManagedBaseHandleFromNativePtr(current) as View;
686             }
687             if (proposed != global::System.IntPtr.Zero)
688             {
689                 originallyProposed = e.Proposed = Registry.GetManagedBaseHandleFromNativePtr(proposed) as View;
690             }
691             e.Direction = direction;
692
693             focusChangingEventHandler?.Invoke(this, e);
694
695             if (originallyProposed != e.Proposed)
696             {
697                 //when user has changed Proposed
698                 return e.Proposed.GetPtrfromView();
699             }
700             else
701             {
702                 if (originallyProposed != null)
703                 {
704                     return proposed;
705                 }
706                 else
707                 {
708                     return current;
709                 }
710             }
711         }
712
713         private void OnFocusChanged(IntPtr current, IntPtr next)
714         {
715             if (focusChangedEventHandler != null)
716             {
717                 FocusChangedEventArgs e = new FocusChangedEventArgs();
718
719                 e.Previous = e.CurrentView = Registry.GetManagedBaseHandleFromNativePtr(current) as View;
720                 e.Current = e.NextView = Registry.GetManagedBaseHandleFromNativePtr(next) as View;
721                 focusChangedEventHandler(this, e);
722             }
723         }
724
725         private void OnFocusGroupChanged(IntPtr current, bool forwardDirection)
726         {
727             if (focusGroupChangedEventHandler != null)
728             {
729                 FocusGroupChangedEventArgs e = new FocusGroupChangedEventArgs();
730
731                 e.CurrentView = Registry.GetManagedBaseHandleFromNativePtr(current) as View;
732                 e.ForwardDirection = forwardDirection;
733                 focusGroupChangedEventHandler(this, e);
734             }
735         }
736
737         private void OnFocusedViewEnterKey(IntPtr view)
738         {
739             if (focusedViewEnterKeyEventHandler != null)
740             {
741                 FocusedViewActivatedEventArgs e = new FocusedViewActivatedEventArgs();
742                 e.View = Registry.GetManagedBaseHandleFromNativePtr(view) as View;
743                 focusedViewEnterKeyEventHandler(this, e);
744             }
745         }
746
747         /// <summary>
748         /// Do not use this, that will be deprecated.
749         /// </summary>
750         /// Do not use this, that will be deprecated.
751         /// Instead Use OnFocusedViewEnterKey.
752         [Obsolete("Do not use this, that will be deprecated. Use FocusManager.OnFocusedViewEnterKey instead.")]
753         [EditorBrowsable(EditorBrowsableState.Never)]
754         private void OnFocusedViewEnterKey2(IntPtr view)
755         {
756             if (focusedViewEnterKeyEventHandler != null)
757             {
758                 FocusedViewActivatedEventArgs e = new FocusedViewActivatedEventArgs();
759                 e.View = Registry.GetManagedBaseHandleFromNativePtr(view) as View;
760                 focusedViewEnterKeyEventHandler(this, e);
761             }
762         }
763
764         ///<summary>
765         /// Event arguments that passed via the PreFocusChange signal.
766         /// </summary>
767         /// <since_tizen> 3 </since_tizen>
768         [Obsolete("Please do not use! This will be deprecated in API10. Please use FocusChangingEventArgs instead!")]
769         [System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1034:Nested types should not be visible", Justification = "<Pending>")]
770         // this will be deprecated, so suppress warning would be OK.
771         public class PreFocusChangeEventArgs : EventArgs
772         {
773             private View current;
774             private View proposed;
775             private View.FocusDirection direction;
776
777             /// <summary>
778             /// The current focus view.
779             /// </summary>
780             /// <since_tizen> 3 </since_tizen>
781             public View CurrentView
782             {
783                 get
784                 {
785                     return current;
786                 }
787                 set
788                 {
789                     current = value;
790                 }
791             }
792
793             /// <summary>
794             /// The  proposed view.
795             /// </summary>
796             /// <since_tizen> 3 </since_tizen>
797             public View ProposedView
798             {
799                 get
800                 {
801                     return proposed;
802                 }
803                 set
804                 {
805                     proposed = value;
806                 }
807             }
808
809             /// <summary>
810             /// The focus move direction.
811             /// </summary>
812             /// <since_tizen> 3 </since_tizen>
813             public View.FocusDirection Direction
814             {
815                 get
816                 {
817                     return direction;
818                 }
819                 set
820                 {
821                     direction = value;
822                 }
823             }
824         }
825
826         ///<summary>
827         /// Event arguments that passed via the FocusChanged signal.
828         /// </summary>
829         /// <since_tizen> 3 </since_tizen>
830         public class FocusChangedEventArgs : EventArgs
831         {
832             private View currentView;
833             private View nextView;
834             private View previous;
835             private View current;
836
837             /// <summary>
838             /// The current focus view.
839             /// </summary>
840             /// <since_tizen> 3 </since_tizen>
841             [Obsolete("Please do not use! This will be deprecated! Please use Previous instead!")]
842             public View CurrentView
843             {
844                 get
845                 {
846                     return currentView;
847                 }
848                 set
849                 {
850                     currentView = value;
851                 }
852             }
853             /// <summary>
854             /// The next focus view.
855             /// </summary>
856             /// <since_tizen> 3 </since_tizen>
857             [Obsolete("Please do not use! This will be deprecated! Please use Current instead!")]
858             public View NextView
859             {
860                 get
861                 {
862                     return nextView;
863                 }
864                 set
865                 {
866                     nextView = value;
867                 }
868             }
869             /// <summary>
870             /// The previously focused view.
871             /// </summary>
872             /// <since_tizen> 10 </since_tizen>
873             public View Previous
874             {
875                 get
876                 {
877                     return previous;
878                 }
879                 set
880                 {
881                     previous = value;
882                 }
883             }
884             /// <summary>
885             /// The current focused view after focus changed.
886             /// </summary>
887             /// <since_tizen> 10 </since_tizen>
888             public View Current
889             {
890                 get
891                 {
892                     return current;
893                 }
894                 set
895                 {
896                     current = value;
897                 }
898             }
899         }
900
901         ///<summary>
902         /// Event arguments that passed via the FocusGroupChanged signal.
903         /// </summary>
904         /// <since_tizen> 3 </since_tizen>
905         public class FocusGroupChangedEventArgs : EventArgs
906         {
907             private View current;
908             private bool forwardDirection;
909
910             /// <summary>
911             /// The current focus view.
912             /// </summary>
913             /// <since_tizen> 3 </since_tizen>
914             public View CurrentView
915             {
916                 get
917                 {
918                     return current;
919                 }
920                 set
921                 {
922                     current = value;
923                 }
924             }
925
926             /// <summary>
927             /// The forward direction.
928             /// </summary>
929             /// <since_tizen> 3 </since_tizen>
930             public bool ForwardDirection
931             {
932                 get
933                 {
934                     return forwardDirection;
935                 }
936                 set
937                 {
938                     forwardDirection = value;
939                 }
940             }
941         }
942
943         ///<summary>
944         /// Event arguments that passed via the FocusedViewEnterKey signal.
945         /// </summary>
946         /// <since_tizen> 3 </since_tizen>
947         public class FocusedViewActivatedEventArgs : EventArgs
948         {
949             private View view;
950
951             /// <summary>
952             /// View.
953             /// </summary>
954             /// <since_tizen> 3 </since_tizen>
955             public View View
956             {
957                 get
958                 {
959                     return view;
960                 }
961                 set
962                 {
963                     view = value;
964                 }
965             }
966         }
967
968         /// <summary>
969         /// Do not use this, that will be deprecated.
970         /// </summary>
971         /// <since_tizen> 3 </since_tizen>
972         /// Do not use this, that will be deprecated.
973         /// Instead Use FocusedViewActivatedEventArgs.
974         [Obsolete("Do not use this, that will be deprecated. Use FocusedViewActivatedEventArgs instead. " +
975             "Like: " +
976             "FocusManager.Instance.FocusedViewActivated = OnFocusedViewActivated; " +
977             "private void OnFocusedViewActivated(object source, FocusManager.FocusedViewActivatedEventArgs arg)" +
978             "{...}")]
979         [EditorBrowsable(EditorBrowsableState.Never)]
980         [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible")]
981         public class FocusedViewEnterKeyEventArgs : EventArgs
982         {
983             private View view;
984
985             /// <summary>
986             /// View.
987             /// </summary>
988             /// <since_tizen> 3 </since_tizen>
989             public View View
990             {
991                 get
992                 {
993                     return view;
994                 }
995                 set
996                 {
997                     view = value;
998                 }
999             }
1000         }
1001
1002         private class CustomAlgorithmInterfaceWrapper : CustomAlgorithmInterface
1003         {
1004             private FocusManager.ICustomFocusAlgorithm customFocusAlgorithm;
1005
1006             public CustomAlgorithmInterfaceWrapper()
1007             {
1008             }
1009
1010             public void SetFocusAlgorithm(FocusManager.ICustomFocusAlgorithm customFocusAlgorithm)
1011             {
1012                 this.customFocusAlgorithm = customFocusAlgorithm;
1013             }
1014
1015             public override View GetNextFocusableView(View current, View proposed, View.FocusDirection direction, string deviceName)
1016             {
1017                 if (customFocusAlgorithm == null)
1018                 {
1019                     Tizen.Log.Error("NUI", $"[ERROR] User defined ICustomFocusAlgorithm interface class becomes unreachable. Null will be proposed for next focusing!");
1020                     return null;
1021                 }
1022                 if (customFocusAlgorithm is ICustomAwareDeviceFocusAlgorithm deviceAwared)
1023                 {
1024                     return deviceAwared.GetNextFocusableView(current, proposed, direction, deviceName);
1025                 }
1026                 else
1027                 {
1028                     return customFocusAlgorithm.GetNextFocusableView(current, proposed, direction);
1029                 }
1030             }
1031         }
1032     }
1033 }