From: Joogab Yun Date: Fri, 12 Mar 2021 01:50:58 +0000 (+0900) Subject: 1. [NUI] Add TouchArea property. X-Git-Tag: submit/tizen_6.0/20211216.043505~1^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=24eba54fa2b25d88448e66b5b4b4dd1cf58bf80f;p=platform%2Fcore%2Fcsapi%2Ftizenfx.git 1. [NUI] Add TouchArea property. Default touchable area is view's size. TouchArea can reset the view's touchable area. This is usefull when the view is small, but it should have a larger touch area. for example View view = new View(); view.Size = new Size(10, 10); view.TouchEvent += OnTouchEvent; view.TouchArea = new Size2D(200, 200); The view is small, If you want to set the touch area to a larger area, you can use the TouchArea property. 2. [NUI] change type from Size2D to Size at TouchArea api 3. [NUI] Change TouchArea to TouchAreaOffset (#2948) You can expand the touch area. for example) View view = new View(); view.Size = new Size(10, 10); view.TouchEvent += OnTouch; view.TouchAreaOffset = new Offset(-100, 100, 100, -100); // left, right, bottom, top then touch area is 210x210. this is view.width -touchAreaOffset.left + touchAreaOffset.right and view.height + touchAreaOffset.bottom -touchAreaOffset.top 4. [NUI] Change ulong to uint at Interop.Touch.GetMouseButton (#3057) 5. [NUI] Change interruptView to InterceptTouchEvent 6. [NUI] Add NeedGesturePropagation (#3130) This is used when the parent view wants to listen to gesture events. 7. [NUI] Add FocusableInTouch property This is a property that allows you to have focus even when touched. If Focusable is false, FocusableInTouchMode is disabled. If you want to have focus on touch in touch mode, you need to set both settings to true. focusable = true, focusableInTouch = true, 8. [NUI] Add source type to TapGesture. This is similar to MouseButton in TouchEvent. Now, you can see from which input the tap was made. 9. [NUI] Supports moving focus of items in ScrollableBase 10. [NUI] Add EnableDefaultAlgorithm and IsDefaultAlgorithmEnabled 11. [NUI] Add FocusableChildren 12. [NUI] Check if pan gesture need to propagation If it's a nested scroll, calculate whether the gesture should be sent to the parent. --- diff --git a/src/Tizen.NUI.Components/Controls/ScrollableBase.cs b/src/Tizen.NUI.Components/Controls/ScrollableBase.cs index 4b26f154a..cc3e31777 100755 --- a/src/Tizen.NUI.Components/Controls/ScrollableBase.cs +++ b/src/Tizen.NUI.Components/Controls/ScrollableBase.cs @@ -610,7 +610,6 @@ namespace Tizen.NUI.Components private float maxScrollDistance; private float childTargetPosition = 0.0f; private PanGestureDetector mPanGestureDetector; - private View mInterruptTouchingChild; private ScrollbarBase scrollBar; private bool scrolling = false; private float ratioOfScreenWidthToCompleteScroll = 0.5f; @@ -686,13 +685,6 @@ namespace Tizen.NUI.Components propertyNotification.Notified += OnPropertyChanged; base.Add(ContentContainer); - //Interrupt touching when panning is started - mInterruptTouchingChild = new View() - { - Size = new Size(Window.Instance.WindowSize), - BackgroundColor = Color.Transparent, - }; - mInterruptTouchingChild.TouchEvent += OnIterruptTouchingChildTouched; Scrollbar = new Scrollbar(); //Show vertical shadow on the top (or bottom) of the scrollable when panning down (or up). @@ -718,9 +710,11 @@ namespace Tizen.NUI.Components { AccessibilityManager.Instance.SetAccessibilityAttribute(this, AccessibilityManager.AccessibilityAttribute.Trait, "ScrollableBase"); } + + SetKeyboardNavigationSupport(true); } - private bool OnIterruptTouchingChildTouched(object source, View.TouchEventArgs args) + private bool OnInterruptTouchingChildTouched(object source, View.TouchEventArgs args) { if (args.Touch.GetState(0) == PointStateType.Down) { @@ -874,7 +868,7 @@ namespace Tizen.NUI.Components private void OnScrollAnimationEnded() { scrolling = false; - base.Remove(mInterruptTouchingChild); + this.InterceptTouchEvent -= OnInterruptTouchingChildTouched; ScrollEventArgs eventArgs = new ScrollEventArgs(ContentContainer.CurrentPosition); ScrollAnimationEnded?.Invoke(this, eventArgs); @@ -1285,20 +1279,19 @@ namespace Tizen.NUI.Components private void OnPanGestureDetected(object source, PanGestureDetector.DetectedEventArgs e) { - OnPanGesture(e.PanGesture); + e.Handled = OnPanGesture(e.PanGesture); } - private void OnPanGesture(PanGesture panGesture) + private bool OnPanGesture(PanGesture panGesture) { + bool handled = true; if (SnapToPage && scrollAnimation != null && scrollAnimation.State == Animation.States.Playing) { - return; + return handled; } - if (panGesture.State == Gesture.StateType.Started) { readyToNotice = false; - base.Add(mInterruptTouchingChild); AttachShadowView(); Debug.WriteLineIf(LayoutDebugScrollableBase, "Gesture Start"); if (scrolling && !SnapToPage) @@ -1306,6 +1299,21 @@ namespace Tizen.NUI.Components StopScroll(); } totalDisplacementForPan = 0.0f; + + // check if gesture need to propagation + var checkDisplacement = (ScrollingDirection == Direction.Horizontal) ? panGesture.Displacement.X : panGesture.Displacement.Y; + var checkChildCurrentPosition = (ScrollingDirection == Direction.Horizontal) ? ContentContainer.PositionX : ContentContainer.PositionY; + var checkChildTargetPosition = checkChildCurrentPosition + checkDisplacement; + var checkFinalTargetPosition = BoundScrollPosition(checkChildTargetPosition); + handled = !((int)checkFinalTargetPosition == 0 || -(int)checkFinalTargetPosition == (int)maxScrollDistance); + // If you propagate a gesture event, return; + if(!handled) + { + return handled; + } + + //Interrupt touching when panning is started + this.InterceptTouchEvent += OnInterruptTouchingChildTouched; OnScrollDragStarted(); } else if (panGesture.State == Gesture.StateType.Continuing) @@ -1326,6 +1334,7 @@ namespace Tizen.NUI.Components DragVerticalShadow(totalDisplacementForPan, panGesture.Displacement.Y); } Debug.WriteLineIf(LayoutDebugScrollableBase, "OnPanGestureDetected Continue totalDisplacementForPan:" + totalDisplacementForPan); + } else if (panGesture.State == Gesture.StateType.Finished || panGesture.State == Gesture.StateType.Cancelled) { @@ -1366,6 +1375,7 @@ namespace Tizen.NUI.Components readyToNotice = true; OnScrollAnimationStarted(); } + return handled; } internal override bool OnAccessibilityPan(PanGesture gestures) @@ -1568,6 +1578,81 @@ namespace Tizen.NUI.Components } } + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override View GetNextFocusableView(View currentFocusedView, View.FocusDirection direction, bool loopEnabled) + { + View nextFocusedView = null; + + int currentIndex = ContentContainer.Children.IndexOf(currentFocusedView); + + switch (direction) + { + case View.FocusDirection.Left: + case View.FocusDirection.Up: + { + if (currentIndex > 0) + { + nextFocusedView = ContentContainer.Children[--currentIndex]; + } + break; + } + case View.FocusDirection.Right: + case View.FocusDirection.Down: + { + if (currentIndex < ContentContainer.Children.Count - 1) + { + nextFocusedView = ContentContainer.Children[++currentIndex]; + } + break; + } + } + + if (nextFocusedView != null) + { + // Check next focused view is inside of visible area. + // If it is not, move scroll position to make it visible. + Position scrollPosition = ContentContainer.CurrentPosition; + float targetPosition = -(ScrollingDirection == Direction.Horizontal ? scrollPosition.X : scrollPosition.Y); + + float left = nextFocusedView.Position.X; + float right = nextFocusedView.Position.X + nextFocusedView.Size.Width; + float top = nextFocusedView.Position.Y; + float bottom = nextFocusedView.Position.Y + nextFocusedView.Size.Height; + + float visibleRectangleLeft = -scrollPosition.X; + float visibleRectangleRight = -scrollPosition.X + Size.Width; + float visibleRectangleTop = -scrollPosition.Y; + float visibleRectangleBottom = -scrollPosition.Y + Size.Height; + + if (ScrollingDirection == Direction.Horizontal) + { + if (left < visibleRectangleLeft) + { + targetPosition = left; + } + else if (right > visibleRectangleRight) + { + targetPosition = right - Size.Width; + } + } + else + { + if (top < visibleRectangleTop) + { + targetPosition = top; + } + else if (bottom > visibleRectangleBottom) + { + targetPosition = bottom - Size.Height; + } + } + ScrollTo(targetPosition, true); + } + + return nextFocusedView; + } } } // namespace diff --git a/src/Tizen.NUI/src/internal/Interop/Interop.Actor.cs b/src/Tizen.NUI/src/internal/Interop/Interop.Actor.cs index 90dfbfc74..12caa1312 100755 --- a/src/Tizen.NUI/src/internal/Interop/Interop.Actor.cs +++ b/src/Tizen.NUI/src/internal/Interop/Interop.Actor.cs @@ -121,6 +121,9 @@ namespace Tizen.NUI [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_Actor_RemoveRenderer__SWIG_1")] public static extern void Actor_RemoveRenderer__SWIG_1(global::System.Runtime.InteropServices.HandleRef jarg1, uint jarg2); + + [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_Actor_SetNeedGesturePropagation")] + public static extern float SetNeedGesturePropagation(global::System.Runtime.InteropServices.HandleRef jarg1, bool jarg2); } } } diff --git a/src/Tizen.NUI/src/internal/Interop/Interop.ActorInternal.cs b/src/Tizen.NUI/src/internal/Interop/Interop.ActorInternal.cs index c1962bbfe..816b018c4 100755 --- a/src/Tizen.NUI/src/internal/Interop/Interop.ActorInternal.cs +++ b/src/Tizen.NUI/src/internal/Interop/Interop.ActorInternal.cs @@ -182,6 +182,19 @@ namespace Tizen.NUI [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_Actor_IsKeyboardFocusable")] public static extern bool Actor_IsKeyboardFocusable(global::System.Runtime.InteropServices.HandleRef jarg1); + [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_Actor_SetKeyboardFocusableChildren")] + public static extern void SetKeyboardFocusableChildren(global::System.Runtime.InteropServices.HandleRef manager, bool focusable); + + [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_Actor_AreChildrenKeyBoardFocusable")] + [return: global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.U1)] + public static extern bool AreChildrenKeyBoardFocusable(global::System.Runtime.InteropServices.HandleRef manager); + + [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_Actor_SetTouchFocusable")] + public static extern void SetFocusableInTouch(global::System.Runtime.InteropServices.HandleRef jarg1, bool jarg2); + + [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_Actor_IsTouchFocusable")] + public static extern bool IsFocusableInTouch(global::System.Runtime.InteropServices.HandleRef jarg1); + [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_Actor_SetSizeScalePolicy")] public static extern void Actor_SetSizeScalePolicy(global::System.Runtime.InteropServices.HandleRef jarg1, int jarg2); @@ -199,6 +212,12 @@ namespace Tizen.NUI [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_Actor_GetMaximumSize")] public static extern global::System.IntPtr Actor_GetMaximumSize(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_DevelActor_Property_SetTouchAreaOffset")] + public static extern void SetTouchAreaOffset(global::System.Runtime.InteropServices.HandleRef jarg1, int jarg2, int jarg3, int jarg4, int jarg5); + + [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_DevelActor_Property_GetTouchAreaOffset")] + public static extern void GetTouchAreaOffset(global::System.Runtime.InteropServices.HandleRef jarg1, out int jarg2, out int jarg3, out int jarg4, out int jarg5); } } } diff --git a/src/Tizen.NUI/src/internal/Interop/Interop.FocusManager.cs b/src/Tizen.NUI/src/internal/Interop/Interop.FocusManager.cs index 3ab94b091..c35d8208c 100755 --- a/src/Tizen.NUI/src/internal/Interop/Interop.FocusManager.cs +++ b/src/Tizen.NUI/src/internal/Interop/Interop.FocusManager.cs @@ -65,6 +65,13 @@ namespace Tizen.NUI [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_KeyboardFocusManager_FocusedActorEnterKeySignal")] public static extern global::System.IntPtr FocusManager_FocusedActorEnterKeySignal(global::System.Runtime.InteropServices.HandleRef jarg1); + [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_KeyboardFocusManager_EnableDefaultAlgorithm")] + public static extern void EnableDefaultAlgorithm(global::System.Runtime.InteropServices.HandleRef jarg1, bool jarg2); + + [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_KeyboardFocusManager_IsDefaultAlgorithmEnabled")] + [return: global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.U1)] + public static extern bool IsDefaultAlgorithmEnabled(global::System.Runtime.InteropServices.HandleRef jarg1); + [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_KeyboardFocusManager_SWIGUpcast")] public static extern global::System.IntPtr FocusManager_SWIGUpcast(global::System.IntPtr jarg1); } diff --git a/src/Tizen.NUI/src/internal/Interop/Interop.TapGesture.cs b/src/Tizen.NUI/src/internal/Interop/Interop.TapGesture.cs index 62e76d7f6..6cf439ebc 100755 --- a/src/Tizen.NUI/src/internal/Interop/Interop.TapGesture.cs +++ b/src/Tizen.NUI/src/internal/Interop/Interop.TapGesture.cs @@ -49,6 +49,9 @@ namespace Tizen.NUI [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_TapGesture_localPoint_get")] public static extern global::System.IntPtr TapGesture_localPoint_get(global::System.Runtime.InteropServices.HandleRef jarg1); + + [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_TapGesture_sourceType_get")] + public static extern int SourceTypeGet(global::System.Runtime.InteropServices.HandleRef jarg1); } } } \ No newline at end of file diff --git a/src/Tizen.NUI/src/internal/Interop/Interop.Touch.cs b/src/Tizen.NUI/src/internal/Interop/Interop.Touch.cs index c8f9f4506..daeb11912 100755 --- a/src/Tizen.NUI/src/internal/Interop/Interop.Touch.cs +++ b/src/Tizen.NUI/src/internal/Interop/Interop.Touch.cs @@ -15,7 +15,7 @@ namespace Tizen.NUI public static extern global::System.IntPtr new_Touch__SWIG_1(global::System.Runtime.InteropServices.HandleRef jarg1); [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_Touch_GetMouseButton")] - public static extern int Touch_GetMouseButton(global::System.Runtime.InteropServices.HandleRef jarg1, ulong jarg2); + public static extern int Touch_GetMouseButton(global::System.Runtime.InteropServices.HandleRef jarg1, uint jarg2); [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_Touch_Assign")] public static extern global::System.IntPtr Touch_Assign(global::System.Runtime.InteropServices.HandleRef jarg1, global::System.Runtime.InteropServices.HandleRef jarg2); diff --git a/src/Tizen.NUI/src/internal/ViewWrapperImpl.cs b/src/Tizen.NUI/src/internal/ViewWrapperImpl.cs index 3b0f6ff0a..47cbf8d88 100755 --- a/src/Tizen.NUI/src/internal/ViewWrapperImpl.cs +++ b/src/Tizen.NUI/src/internal/ViewWrapperImpl.cs @@ -520,7 +520,7 @@ namespace Tizen.NUI } else { - return currentFocusedActor; + return global::System.IntPtr.Zero; } } diff --git a/src/Tizen.NUI/src/public/BaseComponents/Style/ViewStyle.cs b/src/Tizen.NUI/src/public/BaseComponents/Style/ViewStyle.cs index a1c3f6e94..3f7b28a60 100755 --- a/src/Tizen.NUI/src/public/BaseComponents/Style/ViewStyle.cs +++ b/src/Tizen.NUI/src/public/BaseComponents/Style/ViewStyle.cs @@ -44,6 +44,8 @@ namespace Tizen.NUI.BaseComponents private View upFocusableView; private View downFocusableView; private bool? focusable; + private bool? focusableChildren; + private bool? focusableInTouch; private bool? positionUsesPivotPoint; private int? siblingOrder; private Position parentOrigin; @@ -248,6 +250,29 @@ namespace Tizen.NUI.BaseComponents set => SetValue(FocusableProperty, value); } + /// + /// Whether the children of this view can be focusable by keyboard navigation. If user sets this to false, the children of this view will not be focused. + /// Note : Default value is true. + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public bool? FocusableChildren + { + get => (bool?)GetValue(FocusableChildrenProperty); + set => SetValue(FocusableChildrenProperty, value); + } + + /// + /// Whether this view can focus by touch. + /// If Focusable is false, FocusableInTouch is disabled. + /// If you want to have focus on touch, you need to set both Focusable and FocusableInTouch settings to true. + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public bool? FocusableInTouch + { + get => (bool?)GetValue(FocusableInTouchProperty); + set => SetValue(FocusableInTouchProperty, value); + } + /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API. [EditorBrowsable(EditorBrowsableState.Never)] public Size2D Size2D diff --git a/src/Tizen.NUI/src/public/BaseComponents/Style/ViewStyleBindableProperty.cs b/src/Tizen.NUI/src/public/BaseComponents/Style/ViewStyleBindableProperty.cs index c0e91a36d..76db17955 100755 --- a/src/Tizen.NUI/src/public/BaseComponents/Style/ViewStyleBindableProperty.cs +++ b/src/Tizen.NUI/src/public/BaseComponents/Style/ViewStyleBindableProperty.cs @@ -222,6 +222,22 @@ namespace Tizen.NUI.BaseComponents var viewStyle = (ViewStyle)bindable; return viewStyle.downFocusableView; }); + + /// Bindable property of FocusableChildren. Please do not open it. + [EditorBrowsable(EditorBrowsableState.Never)] + public static readonly BindableProperty FocusableChildrenProperty = BindableProperty.Create(nameof(FocusableChildren), typeof(bool?), typeof(ViewStyle), true, + propertyChanged: (bindable, oldValue, newValue) => ((ViewStyle)bindable).focusableChildren = (bool?)newValue, + defaultValueCreator: (bindable) => ((ViewStyle)bindable).focusableChildren + ); + + + /// Bindable property of FocusableInTouch. Please do not open it. + [EditorBrowsable(EditorBrowsableState.Never)] + public static readonly BindableProperty FocusableInTouchProperty = BindableProperty.Create(nameof(FocusableInTouch), typeof(bool?), typeof(ViewStyle), null, + propertyChanged: (bindable, oldValue, newValue) => ((ViewStyle)bindable).focusableInTouch = (bool?)newValue, + defaultValueCreator: (bindable) => ((ViewStyle)bindable).focusableInTouch + ); + /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API. [EditorBrowsable(EditorBrowsableState.Never)] public static readonly BindableProperty FocusableProperty = BindableProperty.Create(nameof(Focusable), typeof(bool?), typeof(ViewStyle), null, propertyChanged: (bindable, oldValue, newValue) => diff --git a/src/Tizen.NUI/src/public/BaseComponents/View.cs b/src/Tizen.NUI/src/public/BaseComponents/View.cs index e6243cce5..8d19a98ff 100755 --- a/src/Tizen.NUI/src/public/BaseComponents/View.cs +++ b/src/Tizen.NUI/src/public/BaseComponents/View.cs @@ -737,6 +737,43 @@ namespace Tizen.NUI.BaseComponents } } + /// + /// Whether the children of this view can be focusable by keyboard navigation. If user sets this to false, the children of this actor view will not be focused. + /// Note : Default value is true. + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public bool FocusableChildren + { + set + { + SetValue(FocusableChildrenProperty, value); + NotifyPropertyChanged(); + } + get + { + return (bool)GetValue(FocusableChildrenProperty); + } + } + + /// + /// Whether this view can focus by touch. + /// If Focusable is false, FocusableInTouch is disabled. + /// If you want to have focus on touch, you need to set both Focusable and FocusableInTouch settings to true. + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public bool FocusableInTouch + { + set + { + SetValue(FocusableInTouchProperty, value); + NotifyPropertyChanged(); + } + get + { + return (bool)GetValue(FocusableInTouchProperty); + } + } + /// /// Retrieves the position of the view.
/// The coordinates are relative to the view's parent.
diff --git a/src/Tizen.NUI/src/public/BaseComponents/ViewBindableProperty.cs b/src/Tizen.NUI/src/public/BaseComponents/ViewBindableProperty.cs index b2cb0fa3a..908115ee3 100755 --- a/src/Tizen.NUI/src/public/BaseComponents/ViewBindableProperty.cs +++ b/src/Tizen.NUI/src/public/BaseComponents/ViewBindableProperty.cs @@ -604,6 +604,36 @@ namespace Tizen.NUI.BaseComponents return view.IsKeyboardFocusable(); }); + /// + /// FocusableChildrenProperty + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public static readonly BindableProperty FocusableChildrenProperty = BindableProperty.Create(nameof(FocusableChildren), typeof(bool), typeof(View), true, propertyChanged: (bindable, oldValue, newValue) => + { + var view = (View)bindable; + if (newValue != null) { view.SetKeyboardFocusableChildren((bool)newValue); } + }, + defaultValueCreator: (bindable) => + { + var view = (View)bindable; + return view.AreChildrenKeyBoardFocusable(); + }); + + /// + /// FocusableInTouchProperty + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public static readonly BindableProperty FocusableInTouchProperty = BindableProperty.Create(nameof(FocusableInTouch), typeof(bool), typeof(View), false, propertyChanged: (bindable, oldValue, newValue) => + { + var view = (View)bindable; + if (newValue != null) { view.SetFocusableInTouch((bool)newValue); } + }, + defaultValueCreator: (bindable) => + { + var view = (View)bindable; + return view.IsFocusableInTouch(); + }); + /// /// Size2DProperty /// diff --git a/src/Tizen.NUI/src/public/BaseComponents/ViewEvent.cs b/src/Tizen.NUI/src/public/BaseComponents/ViewEvent.cs index 1bcf86e2a..3f491fde6 100755 --- a/src/Tizen.NUI/src/public/BaseComponents/ViewEvent.cs +++ b/src/Tizen.NUI/src/public/BaseComponents/ViewEvent.cs @@ -1278,5 +1278,51 @@ namespace Tizen.NUI.BaseComponents } } + /// + /// TouchArea can expand the view's touchable area.
+ /// If you set the TouchAreaOffset on an view, when you touch the view, the touch area is used rather than the size of the view.
+ /// This is based on the top left x, y coordinates.
+ /// example)
+ /// view.Size = new Size(100, 100);
+ /// view.TouchAreaOffset = new Offset(-10, 20, 30, -40); // left, right, bottom, top
+ /// then touch area is 130x170.
+ /// this is view.width + TouchAreaOffset.right - TouchAreaOffset.left and view.height + TouchAreaOffset.bottom - TouchAreaOffset.top
+ /// +---------------------+
+ /// | ^ |
+ /// | | |
+ /// | | -40 |
+ /// | | |
+ /// | | |
+ /// | +----+----+ |
+ /// | | | |
+ /// | -10| | 20 |
+ /// |<---+ +----->|
+ /// | | | |
+ /// | | | |
+ /// | +----+----+ |
+ /// | | |
+ /// | | 30 |
+ /// | | |
+ /// | v |
+ /// +---------------------+
+ ///
+ [EditorBrowsable(EditorBrowsableState.Never)] + public Offset TouchAreaOffset + { + get + { + Interop.ActorInternal.GetTouchAreaOffset(SwigCPtr, out int left, out int right, out int bottom, out int top); + if (NDalicPINVOKE.SWIGPendingException.Pending) + throw NDalicPINVOKE.SWIGPendingException.Retrieve(); + return new Offset(left, right, bottom, top); + } + set + { + Interop.ActorInternal.SetTouchAreaOffset(SwigCPtr, value.Left, value.Right, value.Bottom, value.Top); + if (NDalicPINVOKE.SWIGPendingException.Pending) + throw NDalicPINVOKE.SWIGPendingException.Retrieve(); + } + } + } } diff --git a/src/Tizen.NUI/src/public/BaseComponents/ViewInternal.cs b/src/Tizen.NUI/src/public/BaseComponents/ViewInternal.cs index 11b06d2f0..ad173f1a6 100755 --- a/src/Tizen.NUI/src/public/BaseComponents/ViewInternal.cs +++ b/src/Tizen.NUI/src/public/BaseComponents/ViewInternal.cs @@ -873,6 +873,36 @@ namespace Tizen.NUI.BaseComponents return ret; } + internal void SetKeyboardFocusableChildren(bool focusable) + { + Interop.ActorInternal.SetKeyboardFocusableChildren(SwigCPtr, focusable); + if (NDalicPINVOKE.SWIGPendingException.Pending) + throw NDalicPINVOKE.SWIGPendingException.Retrieve(); + } + + internal bool AreChildrenKeyBoardFocusable() + { + bool ret = Interop.ActorInternal.AreChildrenKeyBoardFocusable(SwigCPtr); + if (NDalicPINVOKE.SWIGPendingException.Pending) + throw NDalicPINVOKE.SWIGPendingException.Retrieve(); + return ret; + } + + internal void SetFocusableInTouch(bool enabled) + { + Interop.ActorInternal.SetFocusableInTouch(SwigCPtr, enabled); + if (NDalicPINVOKE.SWIGPendingException.Pending) + throw NDalicPINVOKE.SWIGPendingException.Retrieve(); + } + + internal bool IsFocusableInTouch() + { + bool ret = Interop.ActorInternal.IsFocusableInTouch(SwigCPtr); + if (NDalicPINVOKE.SWIGPendingException.Pending) + throw NDalicPINVOKE.SWIGPendingException.Retrieve(); + return ret; + } + internal void SetResizePolicy(ResizePolicyType policy, DimensionType dimension) { Interop.Actor.Actor_SetResizePolicy(swigCPtr, (int)policy, (int)dimension); diff --git a/src/Tizen.NUI/src/public/FocusManager.cs b/src/Tizen.NUI/src/public/FocusManager.cs index 33e146fb7..f9827c114 100755 --- a/src/Tizen.NUI/src/public/FocusManager.cs +++ b/src/Tizen.NUI/src/public/FocusManager.cs @@ -410,6 +410,30 @@ namespace Tizen.NUI } } + /// + /// 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; + } + internal static FocusManager Get() { FocusManager ret = new FocusManager(Interop.FocusManager.FocusManager_Get(), true); diff --git a/src/Tizen.NUI/src/public/LongPressGestureDetector.cs b/src/Tizen.NUI/src/public/LongPressGestureDetector.cs index df9645f92..f76fa072c 100755 --- a/src/Tizen.NUI/src/public/LongPressGestureDetector.cs +++ b/src/Tizen.NUI/src/public/LongPressGestureDetector.cs @@ -241,6 +241,7 @@ namespace Tizen.NUI { private View _view; private LongPressGesture _longPressGesture; + private bool handled = true; /// /// View the attached view. @@ -277,6 +278,22 @@ namespace Tizen.NUI _longPressGesture = value; } } + + /// + /// Gets or sets a value that indicates whether the event handler has completely handled the event or whether the system should continue its own processing. + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public bool Handled + { + get => handled; + set + { + handled = value; + Interop.Actor.SetNeedGesturePropagation(View.getCPtr(_view), !value); + if (NDalicPINVOKE.SWIGPendingException.Pending) + throw NDalicPINVOKE.SWIGPendingException.Retrieve(); + } + } } } } diff --git a/src/Tizen.NUI/src/public/NUIConstants.cs b/src/Tizen.NUI/src/public/NUIConstants.cs index 178d165df..3a02c2cb3 100755 --- a/src/Tizen.NUI/src/public/NUIConstants.cs +++ b/src/Tizen.NUI/src/public/NUIConstants.cs @@ -1806,6 +1806,55 @@ namespace Tizen.NUI NoThirdParty } + + /// + /// Offset has left, right, bottom, top value. + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public struct Offset + { + /// + /// Constructor + /// + /// left offset + /// right offset + /// bottom offset + /// top offset + [EditorBrowsable(EditorBrowsableState.Never)] + public Offset(int left, int right, int bottom, int top) + { + Left = left; + Right = right; + Bottom = bottom; + Top = top; + } + + /// + /// Left + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public int Left {get; set;} + + /// + /// Right + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public int Right {get; set;} + + /// + /// Bottom + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public int Bottom {get; set;} + + /// + /// Top + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public int Top {get; set;} + + } + /// /// TODO This is to get TizenFX resource path. It needs to be fixed to use application framework API in the future. /// Internal use only. Do not open this API. diff --git a/src/Tizen.NUI/src/public/PanGestureDetector.cs b/src/Tizen.NUI/src/public/PanGestureDetector.cs index 9d144f696..d7980bd59 100755 --- a/src/Tizen.NUI/src/public/PanGestureDetector.cs +++ b/src/Tizen.NUI/src/public/PanGestureDetector.cs @@ -554,6 +554,7 @@ namespace Tizen.NUI { private View _view; private PanGesture _panGesture; + private bool handled = true; /// /// The attached view. @@ -590,6 +591,22 @@ namespace Tizen.NUI _panGesture = value; } } + + /// + /// Gets or sets a value that indicates whether the event handler has completely handled the event or whether the system should continue its own processing. + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public bool Handled + { + get => handled; + set + { + handled = value; + Interop.Actor.SetNeedGesturePropagation(View.getCPtr(_view), !value); + if (NDalicPINVOKE.SWIGPendingException.Pending) + throw NDalicPINVOKE.SWIGPendingException.Retrieve(); + } + } } internal class Property diff --git a/src/Tizen.NUI/src/public/PinchGestureDetector.cs b/src/Tizen.NUI/src/public/PinchGestureDetector.cs index b34ee583e..e7a8d388d 100755 --- a/src/Tizen.NUI/src/public/PinchGestureDetector.cs +++ b/src/Tizen.NUI/src/public/PinchGestureDetector.cs @@ -164,6 +164,7 @@ namespace Tizen.NUI { private View _view; private PinchGesture _pinchGesture; + private bool handled = true; /// /// The attached view. @@ -200,6 +201,22 @@ namespace Tizen.NUI _pinchGesture = value; } } + + /// + /// Gets or sets a value that indicates whether the event handler has completely handled the event or whether the system should continue its own processing. + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public bool Handled + { + get => handled; + set + { + handled = value; + Interop.Actor.SetNeedGesturePropagation(View.getCPtr(_view), !value); + if (NDalicPINVOKE.SWIGPendingException.Pending) + throw NDalicPINVOKE.SWIGPendingException.Retrieve(); + } + } } } } diff --git a/src/Tizen.NUI/src/public/RotationGestureDetector.cs b/src/Tizen.NUI/src/public/RotationGestureDetector.cs index 8ca4a4b6a..86b995d1b 100755 --- a/src/Tizen.NUI/src/public/RotationGestureDetector.cs +++ b/src/Tizen.NUI/src/public/RotationGestureDetector.cs @@ -164,6 +164,7 @@ namespace Tizen.NUI { private View _view; private RotationGesture _rotationGesture; + private bool handled = true; /// /// The attached view. @@ -200,6 +201,22 @@ namespace Tizen.NUI _rotationGesture = value; } } + + /// + /// Gets or sets a value that indicates whether the event handler has completely handled the event or whether the system should continue its own processing. + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public bool Handled + { + get => handled; + set + { + handled = value; + Interop.Actor.SetNeedGesturePropagation(View.getCPtr(_view), !value); + if (NDalicPINVOKE.SWIGPendingException.Pending) + throw NDalicPINVOKE.SWIGPendingException.Retrieve(); + } + } } } diff --git a/src/Tizen.NUI/src/public/TapGesture.cs b/src/Tizen.NUI/src/public/TapGesture.cs index 1f2371084..ec454c95a 100755 --- a/src/Tizen.NUI/src/public/TapGesture.cs +++ b/src/Tizen.NUI/src/public/TapGesture.cs @@ -87,6 +87,20 @@ namespace Tizen.NUI } } + /// + /// The gesture source type of touches property (read-only). + /// If you tap with a mouse button, this will tell you which mouse input you tapped. + /// Primary(Left), Secondary(Right). Tertiary(Wheel). + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public GestureSourceType SourceType + { + get + { + return sourceType; + } + } + private uint numberOfTaps { set @@ -149,6 +163,16 @@ namespace Tizen.NUI } } + private GestureSourceType sourceType + { + get + { + GestureSourceType ret = (GestureSourceType)Interop.TapGesture.SourceTypeGet(SwigCPtr); + if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); + return ret; + } + } + internal static global::System.Runtime.InteropServices.HandleRef getCPtr(TapGesture obj) { return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr; @@ -173,4 +197,32 @@ namespace Tizen.NUI Interop.TapGesture.delete_TapGesture(swigCPtr); } } + + /// + /// Gesture source type. + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public enum GestureSourceType + { + /// + /// invalid data. + /// + [EditorBrowsable(EditorBrowsableState.Never)] + Invalid = -1, + /// + /// Primary. + /// + [EditorBrowsable(EditorBrowsableState.Never)] + Primary = 1, + /// + /// Secondary. + /// + [EditorBrowsable(EditorBrowsableState.Never)] + Secondary = 3, + /// + /// Third (tertiary) + /// + [EditorBrowsable(EditorBrowsableState.Never)] + Tertiary = 2, + } } diff --git a/src/Tizen.NUI/src/public/TapGestureDetector.cs b/src/Tizen.NUI/src/public/TapGestureDetector.cs index ae2e45b45..f6a11426d 100755 --- a/src/Tizen.NUI/src/public/TapGestureDetector.cs +++ b/src/Tizen.NUI/src/public/TapGestureDetector.cs @@ -214,6 +214,7 @@ namespace Tizen.NUI if (_detectedEventHandler != null) { + e.Handled = true; //here we send all data to user event handlers _detectedEventHandler(this, e); } @@ -229,6 +230,7 @@ namespace Tizen.NUI { private View _view; private TapGesture _tapGesture; + private bool handled = true; /// /// The attached view. @@ -265,6 +267,22 @@ namespace Tizen.NUI _tapGesture = value; } } + + /// + /// Gets or sets a value that indicates whether the event handler has completely handled the event or whether the system should continue its own processing. + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public bool Handled + { + get => handled; + set + { + handled = value; + Interop.Actor.SetNeedGesturePropagation(View.getCPtr(_view), !value); + if (NDalicPINVOKE.SWIGPendingException.Pending) + throw NDalicPINVOKE.SWIGPendingException.Retrieve(); + } + } } } } diff --git a/test/Tizen.NUI.Samples/Tizen.NUI.Samples/Samples/FocusFinderSample.cs b/test/Tizen.NUI.Samples/Tizen.NUI.Samples/Samples/FocusFinderSample.cs new file mode 100644 index 000000000..813cbf1d2 --- /dev/null +++ b/test/Tizen.NUI.Samples/Tizen.NUI.Samples/Samples/FocusFinderSample.cs @@ -0,0 +1,233 @@ +using Tizen.NUI; +using Tizen.NUI.BaseComponents; +using Tizen.NUI.Components; +using Tizen.NUI.Events; +using System.Collections.Generic; + +namespace Tizen.NUI.Samples +{ + public class FocusFinderSample : IExample + { + + int ItemWidth = 100; + int ItemHeight = 100; + int ItemSpacing = 10; + + public View TargetView = new View(); + TextLabel _textLabel; + + + public void Activate() + { + Window window = NUIApplication.GetDefaultWindow(); + + FocusManager.Instance.EnableDefaultAlgorithm(true); + + var absLayout = new View + { + Layout = new AbsoluteLayout(), + WidthResizePolicy = ResizePolicyType.FillToParent, + HeightResizePolicy = ResizePolicyType.FillToParent, + // FocusableChildren = false, + }; + window.Add(absLayout); + + List buttons = new List(); + + for (int row = 0; row < 5; row++) + { + for (int cols = 0; cols < 5; cols++) + { + var btn = MakeFocusableButton($"{row * 5 + cols}"); + btn.Position = new Position(ItemWidth + cols * (ItemWidth + ItemSpacing), ItemHeight + 300 + row * (ItemHeight + ItemSpacing)); + buttons.Add(btn); + absLayout.Add(btn); + } + } + + var changeLayout = new Button + { + Focusable = true, + FocusableInTouch = true, + Text = "Change Position", + SizeWidth = 300, + SizeHeight = 100, + }; + + changeLayout.Position = new Position(10, 10); + + absLayout.Add(changeLayout); + changeLayout.Clicked += (s, e) => + { + buttons.Reverse(); + + for (int row = 0; row < 5; row++) + { + for (int cols = 0; cols < 5; cols++) + { + + var btn = buttons[row * 5 + cols]; + btn.Position = new Position(ItemWidth + cols * (ItemWidth + ItemSpacing), ItemHeight + 300 + row * (ItemHeight + ItemSpacing)); + } + } + }; + + var hideButton = new Button + { + Focusable = true, + FocusableInTouch = true, + Text = "Hide button", + SizeWidth = 400, + SizeHeight = 100, + }; + + hideButton.Position = new Position(340, 10); + hideButton.Clicked += (s, e) => + { + + for (int i = 0; i < buttons.Count; i++) + { + if (i % 2 == 0) + { + if (buttons[i].Visibility) + { + buttons[i].Hide(); + } + else + { + buttons[i].Show(); + } + } + } + }; + absLayout.Add(hideButton); + + + var overlap = new Button + { + Focusable = true, + FocusableInTouch = true, + Text = "Overlap view", + SizeWidth = 300, + SizeHeight = 100, + }; + overlap.Position = new Position(10, 120); + absLayout.Add(overlap); + + View overlappedView = null; + overlap.Clicked += (s, e) => + { + if (overlappedView != null) + { + overlappedView.Unparent(); + overlappedView.Dispose(); + overlappedView = null; + return; + } + + overlappedView = new View + { + Focusable = true, + FocusableInTouch = true, + Layout = new AbsoluteLayout(), + SizeWidth = 400, + SizeHeight = 400, + BackgroundColor = new Color(1f, 0.5f, 0.5f, 0.5f) + }; + overlappedView.Position = new Position(ItemWidth, ItemHeight + 300); + absLayout.Add(overlappedView); + + var innerButton = MakeFocusableButton("InnerButton"); + innerButton.SizeWidth = 350; + innerButton.SizeHeight = 350; + overlappedView.Add(innerButton); + innerButton.Position = new Position(10, 10); + }; + + _textLabel = new TextLabel + { + Text = "Focused : ", + SizeWidth = 500, + SizeHeight = 200, + }; + _textLabel.Position = new Position(340, 220); + absLayout.Add(_textLabel); + + + + + + + var absLayout2 = new View + { + Layout = new AbsoluteLayout(), + WidthResizePolicy = ResizePolicyType.FillToParent, + HeightResizePolicy = ResizePolicyType.FillToParent, + }; + window.Add(absLayout2); + + var btn1 = MakeFocusableButton("#"); + btn1.Position = new Position(ItemWidth, ItemHeight + 170); + ((Button)btn1).TextColor = Color.Red; + absLayout2.Add(btn1); + + var btn2 = MakeFocusableButton("%"); + btn2.Position = new Position(ItemWidth + 1 * (ItemWidth + ItemSpacing), ItemHeight + 170); + ((Button)btn2).TextColor = Color.Red; + absLayout2.Add(btn2); + + var btn3 = MakeFocusableButton("*"); + btn3.Position = new Position(ItemWidth + 2 * (ItemWidth + ItemSpacing), ItemHeight + 170); + ((Button)btn3).TextColor = Color.Red; + absLayout2.Add(btn3); + + var btn4 = MakeFocusableButton("+"); + btn4.Position = new Position(ItemWidth + 3 * (ItemWidth + ItemSpacing), ItemHeight + 170); + ((Button)btn4).TextColor = Color.Red; + absLayout2.Add(btn4); + + var btn5 = MakeFocusableButton("-"); + btn5.Position = new Position(ItemWidth + 4 * (ItemWidth + ItemSpacing), ItemHeight + 170); + ((Button)btn5).TextColor = Color.Red; + absLayout2.Add(btn5); + + + var focusableChildrenView = new Button + { + Focusable = true, + FocusableInTouch = true, + Text = "FocusableChildren", + SizeWidth = 400, + SizeHeight = 100, + }; + focusableChildrenView.Position = new Position(340, 120); + absLayout.Add(focusableChildrenView); + + focusableChildrenView.Clicked += (s, e) => + { + absLayout2.FocusableChildren = false; + }; + } + + View MakeFocusableButton(string title) + { + var btn = new Button + { + Focusable = true, + FocusableInTouch = true, + Text = title, + SizeWidth = ItemWidth, + SizeHeight = ItemHeight, + }; + + btn.FocusGained += (s, e) => btn.Text = $"[{title}]"; + btn.FocusLost += (s, e) => btn.Text = $"{title}"; + btn.FocusGained += (s, e) => _textLabel.Text = $"Focused : {title}"; + return btn; + } + + public void Deactivate() + { + } + } +} diff --git a/test/Tizen.NUI.Samples/Tizen.NUI.Samples/Samples/TouchGestureSample.cs b/test/Tizen.NUI.Samples/Tizen.NUI.Samples/Samples/TouchGestureSample.cs index e956f00a6..05e257830 100755 --- a/test/Tizen.NUI.Samples/Tizen.NUI.Samples/Samples/TouchGestureSample.cs +++ b/test/Tizen.NUI.Samples/Tizen.NUI.Samples/Samples/TouchGestureSample.cs @@ -9,7 +9,6 @@ namespace Tizen.NUI.Samples public class TouchGestureSample : IExample { private View root; - GestureDetectorManager mGestureDetector; private TextLabel frontView; private TextLabel backView; @@ -33,6 +32,7 @@ namespace Tizen.NUI.Samples BackgroundColor = new Color(1.0f, 0.0f, 0.0f, 1.0f), }; frontView.TouchEvent += OnFrontTouchEvent; + frontView.TouchAreaOffset = new Offset(-10, 20, 30, -40); // left, right, bottom, top backView = new TextLabel @@ -44,7 +44,6 @@ namespace Tizen.NUI.Samples BackgroundColor = new Color(1.0f, 1.0f, 0.0f, 1.0f), }; - mGestureDetector = new GestureDetectorManager(backView, new MyGestureListener()); backView.TouchEvent += OnBackTouchEvent; backView.Add(frontView); @@ -63,37 +62,9 @@ namespace Tizen.NUI.Samples private bool OnBackTouchEvent(object source, View.TouchEventArgs e) { Tizen.Log.Error("NUI", $"OnBackTouchEvent {e.Touch.GetState(0)}\n"); - mGestureDetector.FeedTouchEvent(source, e, this); return false; } - class MyGestureListener : GestureDetectorManager.GestureListener - { - public override void OnTap(object sender, TapGestureDetector.DetectedEventArgs e, object userData) - { - Tizen.Log.Error("NUI", $"OnTap \n"); - if(userData != null) - { - TouchGestureSample sample = (TouchGestureSample) userData; - sample.ChangeText(); - } - } - - public override void OnPan(object sender, PanGestureDetector.DetectedEventArgs e, object userData) - { - Tizen.Log.Error("NUI", $"OnPan \n"); - } - - public override void OnPinch(object sender, PinchGestureDetector.DetectedEventArgs e, object userData) - { - Tizen.Log.Error("NUI", $"OnPinch \n"); - } - - public override void OnLongPress(object sender, LongPressGestureDetector.DetectedEventArgs e, object userData) - { - Tizen.Log.Error("NUI", $"OnLongPress \n"); - } - } public void Deactivate() {