From 4d1301e2356cb13c1c60ecc48ecc41d2df29a8a2 Mon Sep 17 00:00:00 2001 From: Xianbing Teng Date: Fri, 19 Jun 2020 14:07:39 +0800 Subject: [PATCH] [NUI.Components] Improve sam score to 4.21 (#1720) Co-authored-by: Xianbing Teng --- .../Controls/Button.Internal.cs | 394 ++++++++++++ src/Tizen.NUI.Components/Controls/Button.cs | 460 +------------- .../FlexibleView/LinearLayoutManager.Internal.cs | 659 +++++++++++++++++++++ .../Controls/FlexibleView/LinearLayoutManager.cs | 654 +------------------- .../Controls/Slider.Internal.cs | 364 ++---------- src/Tizen.NUI.Components/Controls/Slider.cs | 504 ++++++++++++---- src/Tizen.NUI.Components/Utils/StyleManager.cs | 10 +- 7 files changed, 1516 insertions(+), 1529 deletions(-) create mode 100755 src/Tizen.NUI.Components/Controls/Button.Internal.cs create mode 100755 src/Tizen.NUI.Components/Controls/FlexibleView/LinearLayoutManager.Internal.cs diff --git a/src/Tizen.NUI.Components/Controls/Button.Internal.cs b/src/Tizen.NUI.Components/Controls/Button.Internal.cs new file mode 100755 index 0000000..f1ec591 --- /dev/null +++ b/src/Tizen.NUI.Components/Controls/Button.Internal.cs @@ -0,0 +1,394 @@ +using System; +using System.ComponentModel; +using Tizen.NUI.BaseComponents; +using Tizen.NUI.Components.Extension; + +namespace Tizen.NUI.Components +{ + public partial class Button + { + private ImageView overlayImage; + private TextLabel buttonText; + private ImageView buttonIcon; + + private EventHandler stateChangeHander; + + private bool isSelected = false; + private bool isEnabled = true; + private bool isPressed = false; + + private StringSelector textSelector = new StringSelector(); + private StringSelector translatableTextSelector = new StringSelector(); + private ColorSelector textColorSelector = new ColorSelector(); + private FloatSelector pointSizeSelector = new FloatSelector(); + + private StringSelector iconURLSelector = new StringSelector(); + + /// + /// The last touch information triggering selected state change. + /// + [EditorBrowsable(EditorBrowsableState.Never)] + protected Touch SelectionChangedByTouch { get; set; } + + /// + /// The ButtonExtension instance that is injected by ButtonStyle. + /// + [EditorBrowsable(EditorBrowsableState.Never)] + protected ButtonExtension Extension { get; set; } + + /// + /// Creates Button's text part. + /// + /// The created Button's text part. + [EditorBrowsable(EditorBrowsableState.Never)] + protected virtual TextLabel CreateText() + { + return new TextLabel(); + } + + /// + /// Creates Button's icon part. + /// + /// The created Button's icon part. + [EditorBrowsable(EditorBrowsableState.Never)] + protected virtual ImageView CreateIcon() + { + return new ImageView(); + } + + /// + /// Creates Button's overlay image part. + /// + /// The created Button's overlay image part. + [EditorBrowsable(EditorBrowsableState.Never)] + protected virtual ImageView CreateOverlayImage() + { + return new ImageView(); + } + + /// + /// Called when the Button is Clicked by a user + /// + /// The click information. + [EditorBrowsable(EditorBrowsableState.Never)] + protected virtual void OnClick(ClickEventArgs eventArgs) + { + } + + /// + /// Get Button style. + /// + /// The default button style. + /// 8 + protected override ViewStyle CreateViewStyle() + { + return new ButtonStyle(); + } + + /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API. + [EditorBrowsable(EditorBrowsableState.Never)] + protected override void OnUpdate() + { + base.OnUpdate(); + UpdateUIContent(); + + Extension?.OnRelayout(this); + } + + /// + /// Update Button State. + /// + /// The touch information in case the state has changed by touching. + /// 6 + /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API. + [EditorBrowsable(EditorBrowsableState.Never)] + protected void UpdateState() + { + ControlStates sourceState = ControlState; + ControlStates targetState; + + if (isEnabled) + { + if (isPressed) + { + // Pressed + targetState = ControlStates.Pressed; + } + else + { + // Normal + targetState = ControlStates.Normal; + + // Selected + targetState |= (IsSelected ? ControlStates.Selected : 0); + + // Focused, SelectedFocused + targetState |= (IsFocused ? ControlStates.Focused : 0); + } + } + else + { + // Disabled + targetState = ControlStates.Disabled; + + // DisabledSelected, DisabledFocused + targetState |= (IsSelected ? ControlStates.Selected : (IsFocused ? ControlStates.Focused : 0)); + } + + if (sourceState != targetState) + { + ControlState = targetState; + + OnUpdate(); + + StateChangedEventArgs e = new StateChangedEventArgs + { + PreviousState = sourceState, + CurrentState = targetState + }; + stateChangeHander?.Invoke(this, e); + + Extension?.OnControlStateChanged(this, new ControlStateChangedEventArgs(sourceState, targetState)); + } + } + + /// + /// Measure text, it can be override. + /// + /// 6 + /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API. + [EditorBrowsable(EditorBrowsableState.Never)] + protected virtual void MeasureText() + { + if (Style.IconRelativeOrientation == null || Icon == null || TextLabel == null) + { + return; + } + TextLabel.WidthResizePolicy = ResizePolicyType.Fixed; + TextLabel.HeightResizePolicy = ResizePolicyType.Fixed; + int textPaddingStart = Style.TextPadding.Start; + int textPaddingEnd = Style.TextPadding.End; + int textPaddingTop = Style.TextPadding.Top; + int textPaddingBottom = Style.TextPadding.Bottom; + + int iconPaddingStart = Style.IconPadding.Start; + int iconPaddingEnd = Style.IconPadding.End; + int iconPaddingTop = Style.IconPadding.Top; + int iconPaddingBottom = Style.IconPadding.Bottom; + + if (IconRelativeOrientation == IconOrientation.Top || IconRelativeOrientation == IconOrientation.Bottom) + { + TextLabel.SizeWidth = SizeWidth - textPaddingStart - textPaddingEnd; + TextLabel.SizeHeight = SizeHeight - textPaddingTop - textPaddingBottom - iconPaddingTop - iconPaddingBottom - Icon.SizeHeight; + } + else + { + TextLabel.SizeWidth = SizeWidth - textPaddingStart - textPaddingEnd - iconPaddingStart - iconPaddingEnd - Icon.SizeWidth; + TextLabel.SizeHeight = SizeHeight - textPaddingTop - textPaddingBottom; + } + } + + /// + /// Layout child, it can be override. + /// + /// 6 + /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API. + [EditorBrowsable(EditorBrowsableState.Never)] + protected virtual void LayoutChild() + { + if (Style.IconRelativeOrientation == null || Icon == null || TextLabel == null) + { + return; + } + + var buttonIcon = Icon; + var buttonText = TextLabel; + + int textPaddingStart = Style.TextPadding.Start; + int textPaddingEnd = Style.TextPadding.End; + int textPaddingTop = Style.TextPadding.Top; + int textPaddingBottom = Style.TextPadding.Bottom; + + int iconPaddingStart = Style.IconPadding.Start; + int iconPaddingEnd = Style.IconPadding.End; + int iconPaddingTop = Style.IconPadding.Top; + int iconPaddingBottom = Style.IconPadding.Bottom; + + switch (IconRelativeOrientation) + { + case IconOrientation.Top: + buttonIcon.PositionUsesPivotPoint = true; + buttonIcon.ParentOrigin = NUI.ParentOrigin.TopCenter; + buttonIcon.PivotPoint = NUI.PivotPoint.TopCenter; + buttonIcon.Position2D = new Position2D(0, iconPaddingTop); + + buttonText.PositionUsesPivotPoint = true; + buttonText.ParentOrigin = NUI.ParentOrigin.BottomCenter; + buttonText.PivotPoint = NUI.PivotPoint.BottomCenter; + buttonText.Position2D = new Position2D(0, -textPaddingBottom); + break; + case IconOrientation.Bottom: + buttonIcon.PositionUsesPivotPoint = true; + buttonIcon.ParentOrigin = NUI.ParentOrigin.BottomCenter; + buttonIcon.PivotPoint = NUI.PivotPoint.BottomCenter; + buttonIcon.Position2D = new Position2D(0, -iconPaddingBottom); + + buttonText.PositionUsesPivotPoint = true; + buttonText.ParentOrigin = NUI.ParentOrigin.TopCenter; + buttonText.PivotPoint = NUI.PivotPoint.TopCenter; + buttonText.Position2D = new Position2D(0, textPaddingTop); + break; + case IconOrientation.Left: + if (LayoutDirection == ViewLayoutDirectionType.LTR) + { + buttonIcon.PositionUsesPivotPoint = true; + buttonIcon.ParentOrigin = NUI.ParentOrigin.CenterLeft; + buttonIcon.PivotPoint = NUI.PivotPoint.CenterLeft; + buttonIcon.Position2D = new Position2D(iconPaddingStart, 0); + + buttonText.PositionUsesPivotPoint = true; + buttonText.ParentOrigin = NUI.ParentOrigin.CenterRight; + buttonText.PivotPoint = NUI.PivotPoint.CenterRight; + buttonText.Position2D = new Position2D(-textPaddingEnd, 0); + } + else + { + buttonIcon.PositionUsesPivotPoint = true; + buttonIcon.ParentOrigin = NUI.ParentOrigin.CenterRight; + buttonIcon.PivotPoint = NUI.PivotPoint.CenterRight; + buttonIcon.Position2D = new Position2D(-iconPaddingStart, 0); + + buttonText.PositionUsesPivotPoint = true; + buttonText.ParentOrigin = NUI.ParentOrigin.CenterLeft; + buttonText.PivotPoint = NUI.PivotPoint.CenterLeft; + buttonText.Position2D = new Position2D(textPaddingEnd, 0); + } + + break; + case IconOrientation.Right: + if (LayoutDirection == ViewLayoutDirectionType.RTL) + { + buttonIcon.PositionUsesPivotPoint = true; + buttonIcon.ParentOrigin = NUI.ParentOrigin.CenterLeft; + buttonIcon.PivotPoint = NUI.PivotPoint.CenterLeft; + buttonIcon.Position2D = new Position2D(iconPaddingEnd, 0); + + buttonText.PositionUsesPivotPoint = true; + buttonText.ParentOrigin = NUI.ParentOrigin.CenterRight; + buttonText.PivotPoint = NUI.PivotPoint.CenterRight; + buttonText.Position2D = new Position2D(-textPaddingStart, 0); + } + else + { + buttonIcon.PositionUsesPivotPoint = true; + buttonIcon.ParentOrigin = NUI.ParentOrigin.CenterRight; + buttonIcon.PivotPoint = NUI.PivotPoint.CenterRight; + buttonIcon.Position2D = new Position2D(-iconPaddingEnd, 0); + + buttonText.PositionUsesPivotPoint = true; + buttonText.ParentOrigin = NUI.ParentOrigin.CenterLeft; + buttonText.PivotPoint = NUI.PivotPoint.CenterLeft; + buttonText.Position2D = new Position2D(textPaddingStart, 0); + } + break; + default: + break; + } + if (string.IsNullOrEmpty(buttonText.Text)) + { + buttonIcon.ParentOrigin = NUI.ParentOrigin.Center; + buttonIcon.PivotPoint = NUI.PivotPoint.Center; + } + } + + /// + /// Theme change callback when theme is changed, this callback will be trigger. + /// + /// The sender + /// The event data + /// 8 + protected override void OnThemeChangedEvent(object sender, StyleManager.ThemeChangeEventArgs e) + { + ButtonStyle buttonStyle = StyleManager.Instance.GetViewStyle(StyleName) as ButtonStyle; + if (buttonStyle != null) + { + Style.CopyFrom(buttonStyle); + UpdateUIContent(); + } + } + + /// + /// Dispose Button and all children on it. + /// + /// Dispose type. + /// 6 + protected override void Dispose(DisposeTypes type) + { + if (disposed) + { + return; + } + + if (type == DisposeTypes.Explicit) + { + Extension?.OnDispose(this); + + if (Icon != null) + { + Utility.Dispose(Icon); + } + if (TextLabel != null) + { + Utility.Dispose(TextLabel); + } + if (OverlayImage != null) + { + Utility.Dispose(OverlayImage); + } + } + + base.Dispose(type); + } + + /// + /// It is hijack by using protected, style copy problem when class inherited from Button. + /// + /// 6 + private void Initialize() + { + var style = (ButtonStyle)Style; + EnableControlStatePropagation = true; + UpdateState(); + LayoutDirectionChanged += OnLayoutDirectionChanged; + } + + private void UpdateUIContent() + { + MeasureText(); + LayoutChild(); + + Sensitive = isEnabled; + } + + private void OnLayoutDirectionChanged(object sender, LayoutDirectionChangedEventArgs e) + { + MeasureText(); + LayoutChild(); + } + + private void OnClickInternal(ClickEventArgs eventArgs) + { + Command?.Execute(CommandParameter); + OnClick(eventArgs); + Extension?.OnClick(this, eventArgs); + ClickEvent?.Invoke(this, eventArgs); + } + + private void OnIconRelayout(object sender, EventArgs e) + { + MeasureText(); + LayoutChild(); + } + + } +} diff --git a/src/Tizen.NUI.Components/Controls/Button.cs b/src/Tizen.NUI.Components/Controls/Button.cs index 0cc313e..b8e106a 100755 --- a/src/Tizen.NUI.Components/Controls/Button.cs +++ b/src/Tizen.NUI.Components/Controls/Button.cs @@ -27,7 +27,7 @@ namespace Tizen.NUI.Components /// Button may contain text or an icon. /// /// 6 - public class Button : Control + public partial class Button : Control { /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API. [EditorBrowsable(EditorBrowsableState.Never)] @@ -36,13 +36,17 @@ namespace Tizen.NUI.Components var instance = (Button)bindable; if (newValue != null) { - instance.privateIconRelativeOrientation = (IconOrientation?)newValue; + if (instance.Style != null && instance.Style.IconRelativeOrientation != (IconOrientation?)newValue) + { + instance.Style.IconRelativeOrientation = (IconOrientation?)newValue; + instance.UpdateUIContent(); + } } }, defaultValueCreator: (bindable) => { var instance = (Button)bindable; - return instance.privateIconRelativeOrientation; + return instance.Style?.IconRelativeOrientation; }); /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API. [EditorBrowsable(EditorBrowsableState.Never)] @@ -51,13 +55,14 @@ namespace Tizen.NUI.Components var instance = (Button)bindable; if (newValue != null) { - instance.privateIsEnabled = (bool)newValue; + instance.isEnabled = (bool)newValue; + instance.UpdateState(); } }, defaultValueCreator: (bindable) => { var instance = (Button)bindable; - return instance.privateIsEnabled; + return instance.isEnabled; }); /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API. [EditorBrowsable(EditorBrowsableState.Never)] @@ -66,13 +71,14 @@ namespace Tizen.NUI.Components var instance = (Button)bindable; if (newValue != null) { - instance.privateIsSelected = (bool)newValue; + instance.isSelected = (bool)newValue; + instance.UpdateState(); } }, defaultValueCreator: (bindable) => { var instance = (Button)bindable; - return instance.privateIsSelected; + return instance.isSelected; }); /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API. [EditorBrowsable(EditorBrowsableState.Never)] @@ -81,13 +87,13 @@ namespace Tizen.NUI.Components var instance = (Button)bindable; if (newValue != null) { - instance.privateIsSelectable = (bool)newValue; + instance.Style.IsSelectable = (bool)newValue; } }, defaultValueCreator: (bindable) => { var instance = (Button)bindable; - return instance.privateIsSelectable; + return instance.Style?.IsSelectable ?? false; }); /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API. [EditorBrowsable(EditorBrowsableState.Never)] @@ -122,67 +128,6 @@ namespace Tizen.NUI.Components return instance.Style?.TextPadding; }); - private ImageView overlayImage; - private TextLabel buttonText; - private ImageView buttonIcon; - - private EventHandler stateChangeHander; - - private bool isSelected = false; - private bool isEnabled = true; - private bool isPressed = false; - - /// - /// The last touch information triggering selected state change. - /// - [EditorBrowsable(EditorBrowsableState.Never)] - protected Touch SelectionChangedByTouch { get; set; } - - /// - /// The ButtonExtension instance that is injected by ButtonStyle. - /// - [EditorBrowsable(EditorBrowsableState.Never)] - protected ButtonExtension Extension { get; set; } - - /// - /// Creates Button's text part. - /// - /// The created Button's text part. - [EditorBrowsable(EditorBrowsableState.Never)] - protected virtual TextLabel CreateText() - { - return new TextLabel(); - } - - /// - /// Creates Button's icon part. - /// - /// The created Button's icon part. - [EditorBrowsable(EditorBrowsableState.Never)] - protected virtual ImageView CreateIcon() - { - return new ImageView(); - } - - /// - /// Creates Button's overlay image part. - /// - /// The created Button's overlay image part. - [EditorBrowsable(EditorBrowsableState.Never)] - protected virtual ImageView CreateOverlayImage() - { - return new ImageView(); - } - - /// - /// Called when the Button is Clicked by a user - /// - /// The click information. - [EditorBrowsable(EditorBrowsableState.Never)] - protected virtual void OnClick(ClickEventArgs eventArgs) - { - } - static Button() { } /// @@ -219,6 +164,7 @@ namespace Tizen.NUI.Components /// /// 6 public event EventHandler ClickEvent; + /// /// An event for the button state changed signal which can be used to subscribe or unsubscribe the event handler provided by the user.
///
@@ -234,6 +180,7 @@ namespace Tizen.NUI.Components stateChangeHander -= value; } } + /// /// Icon orientation. /// @@ -387,18 +334,6 @@ namespace Tizen.NUI.Components } } - private bool privateIsSelectable - { - get - { - return Style?.IsSelectable ?? false; - } - set - { - Style.IsSelectable = value; - } - } - /// /// Translate text string in Button. /// @@ -455,6 +390,7 @@ namespace Tizen.NUI.Components } } } + /// /// Text color in Button. /// @@ -473,6 +409,7 @@ namespace Tizen.NUI.Components } } } + /// /// Text horizontal alignment in Button. /// @@ -491,6 +428,7 @@ namespace Tizen.NUI.Components } } } + /// /// Icon image's resource url in Button. /// @@ -510,7 +448,6 @@ namespace Tizen.NUI.Components } } - private StringSelector textSelector = new StringSelector(); /// /// Text string selector in Button. /// @@ -535,7 +472,6 @@ namespace Tizen.NUI.Components } } - private StringSelector translatableTextSelector = new StringSelector(); /// /// Translateable text string selector in Button. /// @@ -560,7 +496,6 @@ namespace Tizen.NUI.Components } } - private ColorSelector textColorSelector = new ColorSelector(); /// /// Text color selector in Button. /// @@ -585,7 +520,6 @@ namespace Tizen.NUI.Components } } - private FloatSelector pointSizeSelector = new FloatSelector(); /// /// Text font size selector in Button. /// @@ -610,7 +544,6 @@ namespace Tizen.NUI.Components } } - private StringSelector iconURLSelector = new StringSelector(); /// /// Icon image's resource url selector in Button. /// @@ -650,19 +583,6 @@ namespace Tizen.NUI.Components SetValue(IsSelectedProperty, value); } } - private bool privateIsSelected - { - get - { - return isSelected; - } - set - { - isSelected = value; - - UpdateState(); - } - } /// /// Flag to decide enable or disable in Button. @@ -679,18 +599,6 @@ namespace Tizen.NUI.Components SetValue(IsEnabledProperty, value); } } - private bool privateIsEnabled - { - get - { - return isEnabled; - } - set - { - isEnabled = value; - UpdateState(); - } - } /// /// Icon relative orientation in Button, work only when show icon and text. @@ -709,21 +617,6 @@ namespace Tizen.NUI.Components SetValue(IconRelativeOrientationProperty, value); } } - private IconOrientation? privateIconRelativeOrientation - { - get - { - return Style?.IconRelativeOrientation; - } - set - { - if (Style != null && Style.IconRelativeOrientation != value) - { - Style.IconRelativeOrientation = value; - UpdateUIContent(); - } - } - } /// /// Icon padding in Button, work only when show icon and text. @@ -746,38 +639,6 @@ namespace Tizen.NUI.Components } /// - /// Dispose Button and all children on it. - /// - /// Dispose type. - /// 6 - protected override void Dispose(DisposeTypes type) - { - if (disposed) - { - return; - } - - if (type == DisposeTypes.Explicit) - { - Extension?.OnDispose(this); - - if (Icon != null) - { - Utility.Dispose(Icon); - } - if (TextLabel != null) - { - Utility.Dispose(TextLabel); - } - if (OverlayImage != null) - { - Utility.Dispose(OverlayImage); - } - } - - base.Dispose(type); - } - /// /// Called after a key event is received by the view that has had its focus set. /// /// The key event. @@ -932,292 +793,13 @@ namespace Tizen.NUI.Components } /// - /// Get Button style. - /// - /// The default button style. - /// 8 - protected override ViewStyle CreateViewStyle() - { - return new ButtonStyle(); - } - - /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API. - [EditorBrowsable(EditorBrowsableState.Never)] - protected override void OnUpdate() - { - base.OnUpdate(); - UpdateUIContent(); - - Extension?.OnRelayout(this); - } - - /// - /// Update Button State. - /// - /// The touch information in case the state has changed by touching. - /// 6 - /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API. - [EditorBrowsable(EditorBrowsableState.Never)] - protected void UpdateState() - { - ControlStates sourceState = ControlState; - ControlStates targetState; - - if (isEnabled) - { - if (isPressed) - { - // Pressed - targetState = ControlStates.Pressed; - } - else - { - // Normal - targetState = ControlStates.Normal; - - // Selected - targetState |= (IsSelected ? ControlStates.Selected : 0); - - // Focused, SelectedFocused - targetState |= (IsFocused ? ControlStates.Focused : 0); - } - } - else - { - // Disabled - targetState = ControlStates.Disabled; - - // DisabledSelected, DisabledFocused - targetState |= (IsSelected ? ControlStates.Selected : (IsFocused ? ControlStates.Focused : 0)); - } - - if (sourceState != targetState) - { - ControlState = targetState; - - OnUpdate(); - - StateChangedEventArgs e = new StateChangedEventArgs - { - PreviousState = sourceState, - CurrentState = targetState - }; - stateChangeHander?.Invoke(this, e); - - Extension?.OnControlStateChanged(this, new ControlStateChangedEventArgs(sourceState, targetState)); - } - } - - /// - /// It is hijack by using protected, style copy problem when class inherited from Button. - /// - /// 6 - private void Initialize() - { - var style = (ButtonStyle)Style; - EnableControlStatePropagation = true; - UpdateState(); - LayoutDirectionChanged += OnLayoutDirectionChanged; - } - - /// - /// Measure text, it can be override. - /// - /// 6 - /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API. - [EditorBrowsable(EditorBrowsableState.Never)] - protected virtual void MeasureText() - { - if (Style.IconRelativeOrientation == null || Icon == null || TextLabel == null) - { - return; - } - TextLabel.WidthResizePolicy = ResizePolicyType.Fixed; - TextLabel.HeightResizePolicy = ResizePolicyType.Fixed; - int textPaddingStart = Style.TextPadding.Start; - int textPaddingEnd = Style.TextPadding.End; - int textPaddingTop = Style.TextPadding.Top; - int textPaddingBottom = Style.TextPadding.Bottom; - - int iconPaddingStart = Style.IconPadding.Start; - int iconPaddingEnd = Style.IconPadding.End; - int iconPaddingTop = Style.IconPadding.Top; - int iconPaddingBottom = Style.IconPadding.Bottom; - - if (IconRelativeOrientation == IconOrientation.Top || IconRelativeOrientation == IconOrientation.Bottom) - { - TextLabel.SizeWidth = SizeWidth - textPaddingStart - textPaddingEnd; - TextLabel.SizeHeight = SizeHeight - textPaddingTop - textPaddingBottom - iconPaddingTop - iconPaddingBottom - Icon.SizeHeight; - } - else - { - TextLabel.SizeWidth = SizeWidth - textPaddingStart - textPaddingEnd - iconPaddingStart - iconPaddingEnd - Icon.SizeWidth; - TextLabel.SizeHeight = SizeHeight - textPaddingTop - textPaddingBottom; - } - } - /// - /// Layout child, it can be override. - /// - /// 6 - /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API. - [EditorBrowsable(EditorBrowsableState.Never)] - protected virtual void LayoutChild() - { - if (Style.IconRelativeOrientation == null || Icon == null || TextLabel == null) - { - return; - } - - var buttonIcon = Icon; - var buttonText = TextLabel; - - int textPaddingStart = Style.TextPadding.Start; - int textPaddingEnd = Style.TextPadding.End; - int textPaddingTop = Style.TextPadding.Top; - int textPaddingBottom = Style.TextPadding.Bottom; - - int iconPaddingStart = Style.IconPadding.Start; - int iconPaddingEnd = Style.IconPadding.End; - int iconPaddingTop = Style.IconPadding.Top; - int iconPaddingBottom = Style.IconPadding.Bottom; - - switch (IconRelativeOrientation) - { - case IconOrientation.Top: - buttonIcon.PositionUsesPivotPoint = true; - buttonIcon.ParentOrigin = NUI.ParentOrigin.TopCenter; - buttonIcon.PivotPoint = NUI.PivotPoint.TopCenter; - buttonIcon.Position2D = new Position2D(0, iconPaddingTop); - - buttonText.PositionUsesPivotPoint = true; - buttonText.ParentOrigin = NUI.ParentOrigin.BottomCenter; - buttonText.PivotPoint = NUI.PivotPoint.BottomCenter; - buttonText.Position2D = new Position2D(0, -textPaddingBottom); - break; - case IconOrientation.Bottom: - buttonIcon.PositionUsesPivotPoint = true; - buttonIcon.ParentOrigin = NUI.ParentOrigin.BottomCenter; - buttonIcon.PivotPoint = NUI.PivotPoint.BottomCenter; - buttonIcon.Position2D = new Position2D(0, -iconPaddingBottom); - - buttonText.PositionUsesPivotPoint = true; - buttonText.ParentOrigin = NUI.ParentOrigin.TopCenter; - buttonText.PivotPoint = NUI.PivotPoint.TopCenter; - buttonText.Position2D = new Position2D(0, textPaddingTop); - break; - case IconOrientation.Left: - if (LayoutDirection == ViewLayoutDirectionType.LTR) - { - buttonIcon.PositionUsesPivotPoint = true; - buttonIcon.ParentOrigin = NUI.ParentOrigin.CenterLeft; - buttonIcon.PivotPoint = NUI.PivotPoint.CenterLeft; - buttonIcon.Position2D = new Position2D(iconPaddingStart, 0); - - buttonText.PositionUsesPivotPoint = true; - buttonText.ParentOrigin = NUI.ParentOrigin.CenterRight; - buttonText.PivotPoint = NUI.PivotPoint.CenterRight; - buttonText.Position2D = new Position2D(-textPaddingEnd, 0); - } - else - { - buttonIcon.PositionUsesPivotPoint = true; - buttonIcon.ParentOrigin = NUI.ParentOrigin.CenterRight; - buttonIcon.PivotPoint = NUI.PivotPoint.CenterRight; - buttonIcon.Position2D = new Position2D(-iconPaddingStart, 0); - - buttonText.PositionUsesPivotPoint = true; - buttonText.ParentOrigin = NUI.ParentOrigin.CenterLeft; - buttonText.PivotPoint = NUI.PivotPoint.CenterLeft; - buttonText.Position2D = new Position2D(textPaddingEnd, 0); - } - - break; - case IconOrientation.Right: - if (LayoutDirection == ViewLayoutDirectionType.RTL) - { - buttonIcon.PositionUsesPivotPoint = true; - buttonIcon.ParentOrigin = NUI.ParentOrigin.CenterLeft; - buttonIcon.PivotPoint = NUI.PivotPoint.CenterLeft; - buttonIcon.Position2D = new Position2D(iconPaddingEnd, 0); - - buttonText.PositionUsesPivotPoint = true; - buttonText.ParentOrigin = NUI.ParentOrigin.CenterRight; - buttonText.PivotPoint = NUI.PivotPoint.CenterRight; - buttonText.Position2D = new Position2D(-textPaddingStart, 0); - } - else - { - buttonIcon.PositionUsesPivotPoint = true; - buttonIcon.ParentOrigin = NUI.ParentOrigin.CenterRight; - buttonIcon.PivotPoint = NUI.PivotPoint.CenterRight; - buttonIcon.Position2D = new Position2D(-iconPaddingEnd, 0); - - buttonText.PositionUsesPivotPoint = true; - buttonText.ParentOrigin = NUI.ParentOrigin.CenterLeft; - buttonText.PivotPoint = NUI.PivotPoint.CenterLeft; - buttonText.Position2D = new Position2D(textPaddingStart, 0); - } - break; - default: - break; - } - if (string.IsNullOrEmpty(buttonText.Text)) - { - buttonIcon.ParentOrigin = NUI.ParentOrigin.Center; - buttonIcon.PivotPoint = NUI.PivotPoint.Center; - } - } - /// - /// Theme change callback when theme is changed, this callback will be trigger. - /// - /// The sender - /// The event data - /// 8 - protected override void OnThemeChangedEvent(object sender, StyleManager.ThemeChangeEventArgs e) - { - ButtonStyle buttonStyle = StyleManager.Instance.GetViewStyle(StyleName) as ButtonStyle; - if (buttonStyle != null) - { - Style.CopyFrom(buttonStyle); - UpdateUIContent(); - } - } - - private void UpdateUIContent() - { - MeasureText(); - LayoutChild(); - - Sensitive = isEnabled; - } - - private void OnLayoutDirectionChanged(object sender, LayoutDirectionChangedEventArgs e) - { - MeasureText(); - LayoutChild(); - } - - private void OnClickInternal(ClickEventArgs eventArgs) - { - Command?.Execute(CommandParameter); - OnClick(eventArgs); - Extension?.OnClick(this, eventArgs); - ClickEvent?.Invoke(this, eventArgs); - } - - private void OnIconRelayout(object sender, EventArgs e) - { - MeasureText(); - LayoutChild(); - } - - /// /// ClickEventArgs is a class to record button click event arguments which will sent to user. /// /// 6 public class ClickEventArgs : EventArgs { } + /// /// StateChangeEventArgs is a class to record button state change event arguments which will sent to user. /// diff --git a/src/Tizen.NUI.Components/Controls/FlexibleView/LinearLayoutManager.Internal.cs b/src/Tizen.NUI.Components/Controls/FlexibleView/LinearLayoutManager.Internal.cs new file mode 100755 index 0000000..dfb5c3c --- /dev/null +++ b/src/Tizen.NUI.Components/Controls/FlexibleView/LinearLayoutManager.Internal.cs @@ -0,0 +1,659 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tizen.NUI.Components +{ + public partial class LinearLayoutManager + { + internal virtual void LayoutChunk(FlexibleView.Recycler recycler, + LayoutState layoutState, LayoutChunkResult result) + { + FlexibleView.ViewHolder holder = layoutState.Next(recycler); + if (holder == null) + { + // if we are laying out views in scrap, this may return null which means there is + // no more items to layout. + result.Finished = true; + return; + } + + if (mShouldReverseLayout == (layoutState.LayoutDirection == LayoutState.LAYOUT_START)) + AddView(holder); + else + AddView(holder, 0); + + result.Consumed = mOrientationHelper.GetViewHolderMeasurement(holder); + + float left, top, width, height; + if (mOrientation == VERTICAL) + { + width = Width - PaddingLeft - PaddingRight; + height = result.Consumed; + left = PaddingLeft; + if (layoutState.LayoutDirection == LayoutState.LAYOUT_END) + { + top = layoutState.Offset; + } + else + { + top = layoutState.Offset - height; + } + LayoutChild(holder, left, top, width, height); + } + else + { + width = result.Consumed; + height = Height - PaddingTop - PaddingBottom; + top = PaddingTop; + if (layoutState.LayoutDirection == LayoutState.LAYOUT_END) + { + left = layoutState.Offset; + } + else + { + left = layoutState.Offset - width; + } + LayoutChild(holder, left, top, width, height); + } + + result.Focusable = true; + } + + internal override FlexibleView.ViewHolder OnFocusSearchFailed(FlexibleView.ViewHolder focused, FlexibleView.LayoutManager.Direction direction, FlexibleView.Recycler recycler) + { + if (ChildCount == 0) + { + return null; + } + int layoutDir = ConvertFocusDirectionToLayoutDirection(direction); + if (layoutDir == LayoutState.INVALID_LAYOUT) + { + return null; + } + int maxScroll = (int)(MAX_SCROLL_FACTOR * mOrientationHelper.GetTotalSpace()); + UpdateLayoutState(layoutDir, maxScroll, false); + mLayoutState.ScrollingOffset = LayoutState.SCROLLING_OFFSET_NaN; + mLayoutState.Recycle = false; + Fill(recycler, mLayoutState, true, true); + + FlexibleView.ViewHolder nextFocus; + if (layoutDir == LayoutState.LAYOUT_START) + { + nextFocus = GetChildAt(0); + } + else + { + nextFocus = GetChildAt(ChildCount - 1); + } + return nextFocus; + } + + private void UpdateAnchorInfoForLayout(FlexibleView.Recycler recycler, AnchorInfo anchorInfo) + { + if (UpdateAnchorFromPendingData(anchorInfo)) + { + return; + } + + if (UpdateAnchorFromChildren(recycler, anchorInfo)) + { + return; + } + + anchorInfo.Position = FocusPosition != NO_POSITION ? FocusPosition : 0; + anchorInfo.Coordinate = anchorInfo.LayoutFromEnd ? mOrientationHelper.GetEndAfterPadding() : mOrientationHelper.GetStartAfterPadding(); + } + + + // If there is a pending scroll position or saved states, updates the anchor info from that + // data and returns true + private bool UpdateAnchorFromPendingData(AnchorInfo anchorInfo) + { + if (mPendingScrollPosition == NO_POSITION) + { + return false; + } + // validate scroll position + if (mPendingScrollPosition < 0 || mPendingScrollPosition >= ItemCount) + { + mPendingScrollPosition = NO_POSITION; + mPendingScrollPositionOffset = INVALID_OFFSET; + return false; + } + + anchorInfo.Position = mPendingScrollPosition; + + if (mPendingScrollPositionOffset == INVALID_OFFSET) + { + anchorInfo.Coordinate = anchorInfo.LayoutFromEnd ? mOrientationHelper.GetEndAfterPadding() : mOrientationHelper.GetStartAfterPadding(); + } + else + { + if (mShouldReverseLayout) + { + anchorInfo.Coordinate = mOrientationHelper.GetEndAfterPadding() + - mPendingScrollPositionOffset; + } + else + { + anchorInfo.Coordinate = mOrientationHelper.GetStartAfterPadding() + + mPendingScrollPositionOffset; + } + } + + return true; + } + + // Finds an anchor child from existing Views. Most of the time, this is the view closest to + // start or end that has a valid position (e.g. not removed). + // If a child has focus, it is given priority. + private bool UpdateAnchorFromChildren(FlexibleView.Recycler recycler, AnchorInfo anchorInfo) + { + if (ChildCount == 0) + { + return false; + } + + FlexibleView.ViewHolder anchorChild = FindFirstVisibleItemView(); + if (anchorChild == null) + { + Log.Error("flexibleview", $"exception occurs when updating anchor information!"); + anchorChild = GetChildAt(0); + } + anchorInfo.Position = anchorChild.LayoutPosition; + anchorInfo.Coordinate = mOrientationHelper.GetViewHolderStart(anchorChild); + + return true; + } + + // Converts a focusDirection to orientation. + // + // @param focusDirection One of {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN}, + // {@link View#FOCUS_LEFT}, {@link View#FOCUS_RIGHT}, + // {@link View#FOCUS_BACKWARD}, {@link View#FOCUS_FORWARD} + // or 0 for not applicable + // @return {@link LayoutState#LAYOUT_START} or {@link LayoutState#LAYOUT_END} if focus direction + // is applicable to current state, {@link LayoutState#INVALID_LAYOUT} otherwise. + private int ConvertFocusDirectionToLayoutDirection(FlexibleView.LayoutManager.Direction focusDirection) + { + switch (focusDirection) + { + case FlexibleView.LayoutManager.Direction.Up: + return mOrientation == VERTICAL ? LayoutState.LAYOUT_START + : LayoutState.INVALID_LAYOUT; + case FlexibleView.LayoutManager.Direction.Down: + return mOrientation == VERTICAL ? LayoutState.LAYOUT_END + : LayoutState.INVALID_LAYOUT; + case FlexibleView.LayoutManager.Direction.Left: + return mOrientation == HORIZONTAL ? LayoutState.LAYOUT_START + : LayoutState.INVALID_LAYOUT; + case FlexibleView.LayoutManager.Direction.Right: + return mOrientation == HORIZONTAL ? LayoutState.LAYOUT_END + : LayoutState.INVALID_LAYOUT; + default: + return LayoutState.INVALID_LAYOUT; + } + + } + + + private float Fill(FlexibleView.Recycler recycler, LayoutState layoutState, bool stopOnFocusable, bool immediate) + { + float start = layoutState.Available; + + if (layoutState.ScrollingOffset != LayoutState.SCROLLING_OFFSET_NaN) + { + // TODO ugly bug fix. should not happen + if (layoutState.Available < 0) + { + layoutState.ScrollingOffset += layoutState.Available; + } + if (immediate == true) + { + RecycleByLayoutState(recycler, layoutState, true); + } + } + float remainingSpace = layoutState.Available + layoutState.Extra; + LayoutChunkResult layoutChunkResult = mLayoutChunkResult; + while ((remainingSpace > 0) && layoutState.HasMore(ItemCount)) + { + layoutChunkResult.ResetInternal(); + LayoutChunk(recycler, layoutState, layoutChunkResult); + if (layoutChunkResult.Finished) + { + break; + } + layoutState.Offset += layoutChunkResult.Consumed * layoutState.LayoutDirection; + + // Consume the available space if: + // layoutChunk did not request to be ignored + // OR we are laying out scrap children + // OR we are not doing pre-layout + if (!layoutChunkResult.IgnoreConsumed) + { + layoutState.Available -= layoutChunkResult.Consumed; + // we keep a separate remaining space because mAvailable is important for recycling + remainingSpace -= layoutChunkResult.Consumed; + } + + if (layoutState.ScrollingOffset != LayoutState.SCROLLING_OFFSET_NaN) + { + layoutState.ScrollingOffset += layoutChunkResult.Consumed; + if (layoutState.Available < 0) + { + layoutState.ScrollingOffset += layoutState.Available; + } + if (immediate == true) + { + RecycleByLayoutState(recycler, layoutState, true); + } + } + if (stopOnFocusable && layoutChunkResult.Focusable) + { + break; + } + } + if (immediate == false) + { + RecycleByLayoutState(recycler, layoutState, false); + } + + return start - layoutState.Available; + } + + private void Cache(FlexibleView.Recycler recycler, LayoutState layoutState, bool immediate, float scrolled = 0) + { + if (layoutState.LayoutDirection == LayoutState.LAYOUT_END) + { + // get the first child in the direction we are going + FlexibleView.ViewHolder child = GetChildClosestToEnd(); + if (child != null) + { + if (child.ItemView.Focusable == false || mOrientationHelper.GetViewHolderEnd(child) + scrolled < mOrientationHelper.GetEnd()) + { + layoutState.Available = MAX_SCROLL_FACTOR * mOrientationHelper.GetTotalSpace(); + layoutState.Extra = 0; + layoutState.ScrollingOffset = LayoutState.SCROLLING_OFFSET_NaN; + layoutState.Recycle = false; + Fill(recycler, layoutState, true, immediate); + } + } + } + else + { + FlexibleView.ViewHolder child = GetChildClosestToStart(); + if (child != null) + { + if (child.ItemView.Focusable == false || mOrientationHelper.GetViewHolderStart(child) + scrolled > 0) + { + layoutState.Available = MAX_SCROLL_FACTOR * mOrientationHelper.GetTotalSpace(); + layoutState.Extra = 0; + layoutState.ScrollingOffset = LayoutState.SCROLLING_OFFSET_NaN; + layoutState.Recycle = false; + Fill(recycler, layoutState, true, immediate); + } + } + } + } + + private void RecycleByLayoutState(FlexibleView.Recycler recycler, LayoutState layoutState, bool immediate) + { + if (!layoutState.Recycle) + { + return; + } + if (layoutState.LayoutDirection == LayoutState.LAYOUT_START) + { + RecycleViewsFromEnd(recycler, layoutState.ScrollingOffset, immediate); + } + else + { + RecycleViewsFromStart(recycler, layoutState.ScrollingOffset, immediate); + } + } + + private void RecycleViewsFromStart(FlexibleView.Recycler recycler, float dt, bool immediate) + { + if (dt < 0) + { + return; + } + // ignore padding, ViewGroup may not clip children. + float limit = dt; + int childCount = ChildCount; + if (mShouldReverseLayout) + { + for (int i = childCount - 1; i >= 0; i--) + { + FlexibleView.ViewHolder child = GetChildAt(i); + if (mOrientationHelper.GetViewHolderEnd(child) > limit) + { + // stop here + RecycleChildren(recycler, childCount - 1, i, immediate); + return; + } + } + } + else + { + for (int i = 0; i < childCount; i++) + { + FlexibleView.ViewHolder child = GetChildAt(i); + if (mOrientationHelper.GetViewHolderEnd(child) > limit) + { + // stop here + RecycleChildren(recycler, 0, i, immediate); + return; + } + } + } + } + + private void RecycleViewsFromEnd(FlexibleView.Recycler recycler, float dt, bool immediate) + { + if (dt < 0) + { + return; + } + int childCount = ChildCount; + float limit = mOrientationHelper.GetEnd() - dt; + if (mShouldReverseLayout) + { + for (int i = 0; i < childCount; i++) + { + FlexibleView.ViewHolder child = GetChildAt(i); + if (mOrientationHelper.GetViewHolderStart(child) < limit) + { + // stop here + RecycleChildren(recycler, 0, i, immediate); + return; + } + } + } + else + { + for (int i = childCount - 1; i >= 0; i--) + { + FlexibleView.ViewHolder child = GetChildAt(i); + if (mOrientationHelper.GetViewHolderStart(child) < limit) + { + // stop here + RecycleChildren(recycler, childCount - 1, i, immediate); + return; + } + } + } + } + + private float ScrollBy(float dy, FlexibleView.Recycler recycler, bool immediate) + { + if (ChildCount == 0 || dy == 0) + { + return 0; + } + mLayoutState.Recycle = true; + int layoutDirection = dy < 0 ? LayoutState.LAYOUT_END : LayoutState.LAYOUT_START; + float absDy = Math.Abs(dy); + + UpdateLayoutState(layoutDirection, absDy, true); + + float consumed = mLayoutState.ScrollingOffset + + Fill(recycler, mLayoutState, false, immediate); + + if (consumed < 0) + { + return 0; + } + + float scrolled = absDy > consumed ? -layoutDirection * consumed : dy; + Cache(recycler, mLayoutState, immediate, scrolled); + + mOrientationHelper.OffsetChildren(scrolled, immediate); + + return scrolled; + } + + private void UpdateLayoutState(int layoutDirection, float requiredSpace, bool canUseExistingSpace) + { + mLayoutState.Extra = 0; + mLayoutState.LayoutDirection = layoutDirection; + float scrollingOffset = 0.0f; + if (layoutDirection == LayoutState.LAYOUT_END) + { + mLayoutState.Extra += mOrientationHelper.GetEndPadding(); + // get the first child in the direction we are going + FlexibleView.ViewHolder child = GetChildClosestToEnd(); + if (child != null) + { + // the direction in which we are traversing children + mLayoutState.ItemDirection = mShouldReverseLayout ? LayoutState.ITEM_DIRECTION_HEAD + : LayoutState.ITEM_DIRECTION_TAIL; + mLayoutState.CurrentPosition = child.LayoutPosition + mLayoutState.ItemDirection; + mLayoutState.Offset = mOrientationHelper.GetViewHolderEnd(child); + // calculate how much we can scroll without adding new children (independent of layout) + scrollingOffset = mOrientationHelper.GetViewHolderEnd(child) + - mOrientationHelper.GetEndAfterPadding(); + } + + } + else + { + mLayoutState.Extra += mOrientationHelper.GetStartAfterPadding(); + FlexibleView.ViewHolder child = GetChildClosestToStart(); + if (child != null) + { + mLayoutState.ItemDirection = mShouldReverseLayout ? LayoutState.ITEM_DIRECTION_TAIL + : LayoutState.ITEM_DIRECTION_HEAD; + mLayoutState.CurrentPosition = child.LayoutPosition + mLayoutState.ItemDirection; + mLayoutState.Offset = mOrientationHelper.GetViewHolderStart(child); + scrollingOffset = -mOrientationHelper.GetViewHolderStart(child) + + mOrientationHelper.GetStartAfterPadding(); + } + } + mLayoutState.Available = requiredSpace; + if (canUseExistingSpace) + { + mLayoutState.Available -= scrollingOffset; + } + mLayoutState.ScrollingOffset = scrollingOffset; + } + + // Convenience method to find the child closes to start. Caller should check it has enough + // children. + // + // @return The child closes to start of the layout from user's perspective. + private FlexibleView.ViewHolder GetChildClosestToStart() + { + return GetChildAt(mShouldReverseLayout ? ChildCount - 1 : 0); + } + + // Convenience method to find the child closes to end. Caller should check it has enough + // children. + // + // @return The child closes to end of the layout from user's perspective. + private FlexibleView.ViewHolder GetChildClosestToEnd() + { + return GetChildAt(mShouldReverseLayout ? 0 : ChildCount - 1); + } + + private void UpdateLayoutStateToFillEnd(int itemPosition, float offset) + { + mLayoutState.Available = mOrientationHelper.GetEndAfterPadding() - offset; + mLayoutState.ItemDirection = mShouldReverseLayout ? LayoutState.ITEM_DIRECTION_HEAD : + LayoutState.ITEM_DIRECTION_TAIL; + mLayoutState.CurrentPosition = itemPosition; + mLayoutState.LayoutDirection = LayoutState.LAYOUT_END; + mLayoutState.Offset = offset; + mLayoutState.ScrollingOffset = LayoutState.SCROLLING_OFFSET_NaN; + mLayoutState.Extra = mOrientationHelper.GetEndPadding(); + + } + + private void UpdateLayoutStateToFillStart(int itemPosition, float offset) + { + mLayoutState.Available = offset - mOrientationHelper.GetStartAfterPadding(); + mLayoutState.CurrentPosition = itemPosition; + mLayoutState.ItemDirection = mShouldReverseLayout ? LayoutState.ITEM_DIRECTION_TAIL : + LayoutState.ITEM_DIRECTION_HEAD; + mLayoutState.LayoutDirection = LayoutState.LAYOUT_START; + mLayoutState.Offset = offset; + mLayoutState.ScrollingOffset = LayoutState.SCROLLING_OFFSET_NaN; + mLayoutState.Extra = mOrientationHelper.GetStartAfterPadding(); + } + + private FlexibleView.ViewHolder FindFirstCompleteVisibleItemView() + { + int childCount = ChildCount; + if (mShouldReverseLayout == false) + { + for (int i = 0; i < childCount; i++) + { + FlexibleView.ViewHolder child = GetChildAt(i); + int start = (int)mOrientationHelper.GetViewHolderStart(child); + if (start > 0 && start < (int)mOrientationHelper.GetEnd()) + { + return child; + } + } + } + else + { + for (int i = childCount - 1; i >= 0; i--) + { + FlexibleView.ViewHolder child = GetChildAt(i); + int start = (int)mOrientationHelper.GetViewHolderStart(child); + if (start > 0 && start < (int)mOrientationHelper.GetEnd()) + { + return child; + } + } + } + return null; + } + + private FlexibleView.ViewHolder FindLastCompleteVisibleItemView() + { + int childCount = ChildCount; + if (mShouldReverseLayout == false) + { + for (int i = childCount - 1; i >= 0; i--) + { + FlexibleView.ViewHolder child = GetChildAt(i); + if ((int)mOrientationHelper.GetViewHolderEnd(child) < (int)mOrientationHelper.GetEnd()) + { + return child; + } + } + } + else + { + for (int i = 0; i < childCount; i++) + { + FlexibleView.ViewHolder child = GetChildAt(i); + if ((int)mOrientationHelper.GetViewHolderEnd(child) < (int)mOrientationHelper.GetEnd()) + { + return child; + } + } + } + return null; + } + + // Helper class that keeps temporary state while {LayoutManager} is filling out the empty space. + internal class LayoutState + { + public const int LAYOUT_START = -1; + + public const int LAYOUT_END = 1; + + public const int INVALID_LAYOUT = -1000; + + public const int ITEM_DIRECTION_HEAD = -1; + + public const int ITEM_DIRECTION_TAIL = 1; + + public const int SCROLLING_OFFSET_NaN = -10000; + + // We may not want to recycle children in some cases (e.g. layout) + public bool Recycle = true; + + // Pixel offset where layout should start + public float Offset; + + // Number of pixels that we should fill, in the layout direction. + public float Available; + + // Current position on the adapter to get the next item. + public int CurrentPosition; + + // Defines the direction in which the data adapter is traversed. + // Should be {@link #ITEM_DIRECTION_HEAD} or {@link #ITEM_DIRECTION_TAIL} + public int ItemDirection; + + // Defines the direction in which the layout is filled. + // Should be {@link #LAYOUT_START} or {@link #LAYOUT_END} + public int LayoutDirection; + + // Used when LayoutState is constructed in a scrolling state. + // It should be set the amount of scrolling we can make without creating a new view. + // Settings this is required for efficient view recycling. + public float ScrollingOffset; + + // Used if you want to pre-layout items that are not yet visible. + // The difference with {@link #mAvailable} is that, when recycling, distance laid out for + // {@link #mExtra} is not considered to avoid recycling visible children. + public float Extra = 0; + + // @return true if there are more items in the data adapter + public bool HasMore(int itemCount) + { + return CurrentPosition >= 0 && CurrentPosition < itemCount; + } + + // Gets the view for the next element that we should layout. + // Also updates current item index to the next item, based on {@link #mItemDirection} + // + // @return The next element that we should layout. + public FlexibleView.ViewHolder Next(FlexibleView.Recycler recycler) + { + FlexibleView.ViewHolder itemView = recycler.GetViewForPosition(CurrentPosition); + CurrentPosition += ItemDirection; + + return itemView; + } + } + + internal class LayoutChunkResult + { + public float Consumed; + public bool Finished; + public bool IgnoreConsumed; + public bool Focusable; + + public void ResetInternal() + { + Consumed = 0; + Finished = false; + IgnoreConsumed = false; + Focusable = false; + } + } + + internal class AnchorInfo + { + public int Position; + public float Coordinate; + public bool LayoutFromEnd; + public bool Valid; + + public void Reset() + { + Position = NO_POSITION; + Coordinate = INVALID_OFFSET; + LayoutFromEnd = false; + Valid = false; + } + } + } +} diff --git a/src/Tizen.NUI.Components/Controls/FlexibleView/LinearLayoutManager.cs b/src/Tizen.NUI.Components/Controls/FlexibleView/LinearLayoutManager.cs index ec01688..e7b1e79 100755 --- a/src/Tizen.NUI.Components/Controls/FlexibleView/LinearLayoutManager.cs +++ b/src/Tizen.NUI.Components/Controls/FlexibleView/LinearLayoutManager.cs @@ -25,7 +25,7 @@ namespace Tizen.NUI.Components /// 6 /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API. [EditorBrowsable(EditorBrowsableState.Never)] - public class LinearLayoutManager : FlexibleView.LayoutManager + public partial class LinearLayoutManager : FlexibleView.LayoutManager { /// /// Constant value: 0. @@ -522,657 +522,5 @@ namespace Tizen.NUI.Components } return null; } - - internal virtual void LayoutChunk(FlexibleView.Recycler recycler, - LayoutState layoutState, LayoutChunkResult result) - { - FlexibleView.ViewHolder holder = layoutState.Next(recycler); - if (holder == null) - { - // if we are laying out views in scrap, this may return null which means there is - // no more items to layout. - result.Finished = true; - return; - } - - if (mShouldReverseLayout == (layoutState.LayoutDirection == LayoutState.LAYOUT_START)) - AddView(holder); - else - AddView(holder, 0); - - result.Consumed = mOrientationHelper.GetViewHolderMeasurement(holder); - - float left, top, width, height; - if (mOrientation == VERTICAL) - { - width = Width - PaddingLeft - PaddingRight; - height = result.Consumed; - left = PaddingLeft; - if (layoutState.LayoutDirection == LayoutState.LAYOUT_END) - { - top = layoutState.Offset; - } - else - { - top = layoutState.Offset - height; - } - LayoutChild(holder, left, top, width, height); - } - else - { - width = result.Consumed; - height = Height - PaddingTop - PaddingBottom; - top = PaddingTop; - if (layoutState.LayoutDirection == LayoutState.LAYOUT_END) - { - left = layoutState.Offset; - } - else - { - left = layoutState.Offset - width; - } - LayoutChild(holder, left, top, width, height); - } - - result.Focusable = true; - } - - internal override FlexibleView.ViewHolder OnFocusSearchFailed(FlexibleView.ViewHolder focused, FlexibleView.LayoutManager.Direction direction, FlexibleView.Recycler recycler) - { - if (ChildCount == 0) - { - return null; - } - int layoutDir = ConvertFocusDirectionToLayoutDirection(direction); - if (layoutDir == LayoutState.INVALID_LAYOUT) - { - return null; - } - int maxScroll = (int)(MAX_SCROLL_FACTOR * mOrientationHelper.GetTotalSpace()); - UpdateLayoutState(layoutDir, maxScroll, false); - mLayoutState.ScrollingOffset = LayoutState.SCROLLING_OFFSET_NaN; - mLayoutState.Recycle = false; - Fill(recycler, mLayoutState, true, true); - - FlexibleView.ViewHolder nextFocus; - if (layoutDir == LayoutState.LAYOUT_START) - { - nextFocus = GetChildAt(0); - } - else - { - nextFocus = GetChildAt(ChildCount - 1); - } - return nextFocus; - } - - - private void UpdateAnchorInfoForLayout(FlexibleView.Recycler recycler, AnchorInfo anchorInfo) - { - if (UpdateAnchorFromPendingData(anchorInfo)) - { - return; - } - - if (UpdateAnchorFromChildren(recycler, anchorInfo)) - { - return; - } - - anchorInfo.Position = FocusPosition != NO_POSITION ? FocusPosition : 0; - anchorInfo.Coordinate = anchorInfo.LayoutFromEnd ? mOrientationHelper.GetEndAfterPadding() : mOrientationHelper.GetStartAfterPadding(); - } - - - // If there is a pending scroll position or saved states, updates the anchor info from that - // data and returns true - private bool UpdateAnchorFromPendingData(AnchorInfo anchorInfo) - { - if (mPendingScrollPosition == NO_POSITION) - { - return false; - } - // validate scroll position - if (mPendingScrollPosition < 0 || mPendingScrollPosition >= ItemCount) - { - mPendingScrollPosition = NO_POSITION; - mPendingScrollPositionOffset = INVALID_OFFSET; - return false; - } - - anchorInfo.Position = mPendingScrollPosition; - - if (mPendingScrollPositionOffset == INVALID_OFFSET) - { - anchorInfo.Coordinate = anchorInfo.LayoutFromEnd ? mOrientationHelper.GetEndAfterPadding() : mOrientationHelper.GetStartAfterPadding(); - } - else - { - if (mShouldReverseLayout) - { - anchorInfo.Coordinate = mOrientationHelper.GetEndAfterPadding() - - mPendingScrollPositionOffset; - } - else - { - anchorInfo.Coordinate = mOrientationHelper.GetStartAfterPadding() - + mPendingScrollPositionOffset; - } - } - - return true; - } - - // Finds an anchor child from existing Views. Most of the time, this is the view closest to - // start or end that has a valid position (e.g. not removed). - // If a child has focus, it is given priority. - private bool UpdateAnchorFromChildren(FlexibleView.Recycler recycler, AnchorInfo anchorInfo) - { - if (ChildCount == 0) - { - return false; - } - - FlexibleView.ViewHolder anchorChild = FindFirstVisibleItemView(); - if (anchorChild == null) - { - Log.Error("flexibleview", $"exception occurs when updating anchor information!"); - anchorChild = GetChildAt(0); - } - anchorInfo.Position = anchorChild.LayoutPosition; - anchorInfo.Coordinate = mOrientationHelper.GetViewHolderStart(anchorChild); - - return true; - } - - // Converts a focusDirection to orientation. - // - // @param focusDirection One of {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN}, - // {@link View#FOCUS_LEFT}, {@link View#FOCUS_RIGHT}, - // {@link View#FOCUS_BACKWARD}, {@link View#FOCUS_FORWARD} - // or 0 for not applicable - // @return {@link LayoutState#LAYOUT_START} or {@link LayoutState#LAYOUT_END} if focus direction - // is applicable to current state, {@link LayoutState#INVALID_LAYOUT} otherwise. - private int ConvertFocusDirectionToLayoutDirection(FlexibleView.LayoutManager.Direction focusDirection) - { - switch (focusDirection) - { - case FlexibleView.LayoutManager.Direction.Up: - return mOrientation == VERTICAL ? LayoutState.LAYOUT_START - : LayoutState.INVALID_LAYOUT; - case FlexibleView.LayoutManager.Direction.Down: - return mOrientation == VERTICAL ? LayoutState.LAYOUT_END - : LayoutState.INVALID_LAYOUT; - case FlexibleView.LayoutManager.Direction.Left: - return mOrientation == HORIZONTAL ? LayoutState.LAYOUT_START - : LayoutState.INVALID_LAYOUT; - case FlexibleView.LayoutManager.Direction.Right: - return mOrientation == HORIZONTAL ? LayoutState.LAYOUT_END - : LayoutState.INVALID_LAYOUT; - default: - return LayoutState.INVALID_LAYOUT; - } - - } - - - private float Fill(FlexibleView.Recycler recycler, LayoutState layoutState, bool stopOnFocusable, bool immediate) - { - float start = layoutState.Available; - - if (layoutState.ScrollingOffset != LayoutState.SCROLLING_OFFSET_NaN) - { - // TODO ugly bug fix. should not happen - if (layoutState.Available < 0) - { - layoutState.ScrollingOffset += layoutState.Available; - } - if (immediate == true) - { - RecycleByLayoutState(recycler, layoutState, true); - } - } - float remainingSpace = layoutState.Available + layoutState.Extra; - LayoutChunkResult layoutChunkResult = mLayoutChunkResult; - while ((remainingSpace > 0) && layoutState.HasMore(ItemCount)) - { - layoutChunkResult.ResetInternal(); - LayoutChunk(recycler, layoutState, layoutChunkResult); - if (layoutChunkResult.Finished) - { - break; - } - layoutState.Offset += layoutChunkResult.Consumed * layoutState.LayoutDirection; - - // Consume the available space if: - // layoutChunk did not request to be ignored - // OR we are laying out scrap children - // OR we are not doing pre-layout - if (!layoutChunkResult.IgnoreConsumed) - { - layoutState.Available -= layoutChunkResult.Consumed; - // we keep a separate remaining space because mAvailable is important for recycling - remainingSpace -= layoutChunkResult.Consumed; - } - - if (layoutState.ScrollingOffset != LayoutState.SCROLLING_OFFSET_NaN) - { - layoutState.ScrollingOffset += layoutChunkResult.Consumed; - if (layoutState.Available < 0) - { - layoutState.ScrollingOffset += layoutState.Available; - } - if (immediate == true) - { - RecycleByLayoutState(recycler, layoutState, true); - } - } - if (stopOnFocusable && layoutChunkResult.Focusable) - { - break; - } - } - if (immediate == false) - { - RecycleByLayoutState(recycler, layoutState, false); - } - - return start - layoutState.Available; - } - - private void Cache(FlexibleView.Recycler recycler, LayoutState layoutState, bool immediate, float scrolled = 0) - { - if (layoutState.LayoutDirection == LayoutState.LAYOUT_END) - { - // get the first child in the direction we are going - FlexibleView.ViewHolder child = GetChildClosestToEnd(); - if (child != null) - { - if (child.ItemView.Focusable == false || mOrientationHelper.GetViewHolderEnd(child) + scrolled < mOrientationHelper.GetEnd()) - { - layoutState.Available = MAX_SCROLL_FACTOR * mOrientationHelper.GetTotalSpace(); - layoutState.Extra = 0; - layoutState.ScrollingOffset = LayoutState.SCROLLING_OFFSET_NaN; - layoutState.Recycle = false; - Fill(recycler, layoutState, true, immediate); - } - } - } - else - { - FlexibleView.ViewHolder child = GetChildClosestToStart(); - if (child != null) - { - if (child.ItemView.Focusable == false || mOrientationHelper.GetViewHolderStart(child) + scrolled > 0) - { - layoutState.Available = MAX_SCROLL_FACTOR * mOrientationHelper.GetTotalSpace(); - layoutState.Extra = 0; - layoutState.ScrollingOffset = LayoutState.SCROLLING_OFFSET_NaN; - layoutState.Recycle = false; - Fill(recycler, layoutState, true, immediate); - } - } - } - } - - private void RecycleByLayoutState(FlexibleView.Recycler recycler, LayoutState layoutState, bool immediate) - { - if (!layoutState.Recycle) - { - return; - } - if (layoutState.LayoutDirection == LayoutState.LAYOUT_START) - { - RecycleViewsFromEnd(recycler, layoutState.ScrollingOffset, immediate); - } - else - { - RecycleViewsFromStart(recycler, layoutState.ScrollingOffset, immediate); - } - } - - private void RecycleViewsFromStart(FlexibleView.Recycler recycler, float dt, bool immediate) - { - if (dt < 0) - { - return; - } - // ignore padding, ViewGroup may not clip children. - float limit = dt; - int childCount = ChildCount; - if (mShouldReverseLayout) - { - for (int i = childCount - 1; i >= 0; i--) - { - FlexibleView.ViewHolder child = GetChildAt(i); - if (mOrientationHelper.GetViewHolderEnd(child) > limit) - { - // stop here - RecycleChildren(recycler, childCount - 1, i, immediate); - return; - } - } - } - else - { - for (int i = 0; i < childCount; i++) - { - FlexibleView.ViewHolder child = GetChildAt(i); - if (mOrientationHelper.GetViewHolderEnd(child) > limit) - { - // stop here - RecycleChildren(recycler, 0, i, immediate); - return; - } - } - } - } - - private void RecycleViewsFromEnd(FlexibleView.Recycler recycler, float dt, bool immediate) - { - if (dt < 0) - { - return; - } - int childCount = ChildCount; - float limit = mOrientationHelper.GetEnd() - dt; - if (mShouldReverseLayout) - { - for (int i = 0; i < childCount; i++) - { - FlexibleView.ViewHolder child = GetChildAt(i); - if (mOrientationHelper.GetViewHolderStart(child) < limit) - { - // stop here - RecycleChildren(recycler, 0, i, immediate); - return; - } - } - } - else - { - for (int i = childCount - 1; i >= 0; i--) - { - FlexibleView.ViewHolder child = GetChildAt(i); - if (mOrientationHelper.GetViewHolderStart(child) < limit) - { - // stop here - RecycleChildren(recycler, childCount - 1, i, immediate); - return; - } - } - } - } - - private float ScrollBy(float dy, FlexibleView.Recycler recycler, bool immediate) - { - if (ChildCount == 0 || dy == 0) - { - return 0; - } - mLayoutState.Recycle = true; - int layoutDirection = dy < 0 ? LayoutState.LAYOUT_END : LayoutState.LAYOUT_START; - float absDy = Math.Abs(dy); - - UpdateLayoutState(layoutDirection, absDy, true); - - float consumed = mLayoutState.ScrollingOffset - + Fill(recycler, mLayoutState, false, immediate); - - if (consumed < 0) - { - return 0; - } - - float scrolled = absDy > consumed ? -layoutDirection * consumed : dy; - Cache(recycler, mLayoutState, immediate, scrolled); - - mOrientationHelper.OffsetChildren(scrolled, immediate); - - return scrolled; - } - - private void UpdateLayoutState(int layoutDirection, float requiredSpace, bool canUseExistingSpace) - { - mLayoutState.Extra = 0; - mLayoutState.LayoutDirection = layoutDirection; - float scrollingOffset = 0.0f; - if (layoutDirection == LayoutState.LAYOUT_END) - { - mLayoutState.Extra += mOrientationHelper.GetEndPadding(); - // get the first child in the direction we are going - FlexibleView.ViewHolder child = GetChildClosestToEnd(); - if (child != null) - { - // the direction in which we are traversing children - mLayoutState.ItemDirection = mShouldReverseLayout ? LayoutState.ITEM_DIRECTION_HEAD - : LayoutState.ITEM_DIRECTION_TAIL; - mLayoutState.CurrentPosition = child.LayoutPosition + mLayoutState.ItemDirection; - mLayoutState.Offset = mOrientationHelper.GetViewHolderEnd(child); - // calculate how much we can scroll without adding new children (independent of layout) - scrollingOffset = mOrientationHelper.GetViewHolderEnd(child) - - mOrientationHelper.GetEndAfterPadding(); - } - - } - else - { - mLayoutState.Extra += mOrientationHelper.GetStartAfterPadding(); - FlexibleView.ViewHolder child = GetChildClosestToStart(); - if (child != null) - { - mLayoutState.ItemDirection = mShouldReverseLayout ? LayoutState.ITEM_DIRECTION_TAIL - : LayoutState.ITEM_DIRECTION_HEAD; - mLayoutState.CurrentPosition = child.LayoutPosition + mLayoutState.ItemDirection; - mLayoutState.Offset = mOrientationHelper.GetViewHolderStart(child); - scrollingOffset = -mOrientationHelper.GetViewHolderStart(child) - + mOrientationHelper.GetStartAfterPadding(); - } - } - mLayoutState.Available = requiredSpace; - if (canUseExistingSpace) - { - mLayoutState.Available -= scrollingOffset; - } - mLayoutState.ScrollingOffset = scrollingOffset; - } - - // Convenience method to find the child closes to start. Caller should check it has enough - // children. - // - // @return The child closes to start of the layout from user's perspective. - private FlexibleView.ViewHolder GetChildClosestToStart() - { - return GetChildAt(mShouldReverseLayout ? ChildCount - 1 : 0); - } - - // Convenience method to find the child closes to end. Caller should check it has enough - // children. - // - // @return The child closes to end of the layout from user's perspective. - private FlexibleView.ViewHolder GetChildClosestToEnd() - { - return GetChildAt(mShouldReverseLayout ? 0 : ChildCount - 1); - } - - private void UpdateLayoutStateToFillEnd(int itemPosition, float offset) - { - mLayoutState.Available = mOrientationHelper.GetEndAfterPadding() - offset; - mLayoutState.ItemDirection = mShouldReverseLayout ? LayoutState.ITEM_DIRECTION_HEAD : - LayoutState.ITEM_DIRECTION_TAIL; - mLayoutState.CurrentPosition = itemPosition; - mLayoutState.LayoutDirection = LayoutState.LAYOUT_END; - mLayoutState.Offset = offset; - mLayoutState.ScrollingOffset = LayoutState.SCROLLING_OFFSET_NaN; - mLayoutState.Extra = mOrientationHelper.GetEndPadding(); - - } - - private void UpdateLayoutStateToFillStart(int itemPosition, float offset) - { - mLayoutState.Available = offset - mOrientationHelper.GetStartAfterPadding(); - mLayoutState.CurrentPosition = itemPosition; - mLayoutState.ItemDirection = mShouldReverseLayout ? LayoutState.ITEM_DIRECTION_TAIL : - LayoutState.ITEM_DIRECTION_HEAD; - mLayoutState.LayoutDirection = LayoutState.LAYOUT_START; - mLayoutState.Offset = offset; - mLayoutState.ScrollingOffset = LayoutState.SCROLLING_OFFSET_NaN; - mLayoutState.Extra = mOrientationHelper.GetStartAfterPadding(); - } - - private FlexibleView.ViewHolder FindFirstCompleteVisibleItemView() - { - int childCount = ChildCount; - if (mShouldReverseLayout == false) - { - for (int i = 0; i < childCount; i++) - { - FlexibleView.ViewHolder child = GetChildAt(i); - int start = (int)mOrientationHelper.GetViewHolderStart(child); - if (start > 0 && start < (int)mOrientationHelper.GetEnd()) - { - return child; - } - } - } - else - { - for (int i = childCount - 1; i >= 0; i--) - { - FlexibleView.ViewHolder child = GetChildAt(i); - int start = (int)mOrientationHelper.GetViewHolderStart(child); - if (start > 0 && start < (int)mOrientationHelper.GetEnd()) - { - return child; - } - } - } - return null; - } - - private FlexibleView.ViewHolder FindLastCompleteVisibleItemView() - { - int childCount = ChildCount; - if (mShouldReverseLayout == false) - { - for (int i = childCount - 1; i >= 0; i--) - { - FlexibleView.ViewHolder child = GetChildAt(i); - if ((int)mOrientationHelper.GetViewHolderEnd(child) < (int)mOrientationHelper.GetEnd()) - { - return child; - } - } - } - else - { - for (int i = 0; i < childCount; i++) - { - FlexibleView.ViewHolder child = GetChildAt(i); - if ((int)mOrientationHelper.GetViewHolderEnd(child) < (int)mOrientationHelper.GetEnd()) - { - return child; - } - } - } - return null; - } - - // Helper class that keeps temporary state while {LayoutManager} is filling out the empty space. - internal class LayoutState - { - public const int LAYOUT_START = -1; - - public const int LAYOUT_END = 1; - - public const int INVALID_LAYOUT = -1000; - - public const int ITEM_DIRECTION_HEAD = -1; - - public const int ITEM_DIRECTION_TAIL = 1; - - public const int SCROLLING_OFFSET_NaN = -10000; - - // We may not want to recycle children in some cases (e.g. layout) - public bool Recycle = true; - - // Pixel offset where layout should start - public float Offset; - - // Number of pixels that we should fill, in the layout direction. - public float Available; - - // Current position on the adapter to get the next item. - public int CurrentPosition; - - // Defines the direction in which the data adapter is traversed. - // Should be {@link #ITEM_DIRECTION_HEAD} or {@link #ITEM_DIRECTION_TAIL} - public int ItemDirection; - - // Defines the direction in which the layout is filled. - // Should be {@link #LAYOUT_START} or {@link #LAYOUT_END} - public int LayoutDirection; - - // Used when LayoutState is constructed in a scrolling state. - // It should be set the amount of scrolling we can make without creating a new view. - // Settings this is required for efficient view recycling. - public float ScrollingOffset; - - // Used if you want to pre-layout items that are not yet visible. - // The difference with {@link #mAvailable} is that, when recycling, distance laid out for - // {@link #mExtra} is not considered to avoid recycling visible children. - public float Extra = 0; - - // @return true if there are more items in the data adapter - public bool HasMore(int itemCount) - { - return CurrentPosition >= 0 && CurrentPosition < itemCount; - } - - // Gets the view for the next element that we should layout. - // Also updates current item index to the next item, based on {@link #mItemDirection} - // - // @return The next element that we should layout. - public FlexibleView.ViewHolder Next(FlexibleView.Recycler recycler) - { - FlexibleView.ViewHolder itemView = recycler.GetViewForPosition(CurrentPosition); - CurrentPosition += ItemDirection; - - return itemView; - } - } - - internal class LayoutChunkResult - { - public float Consumed; - public bool Finished; - public bool IgnoreConsumed; - public bool Focusable; - - public void ResetInternal() - { - Consumed = 0; - Finished = false; - IgnoreConsumed = false; - Focusable = false; - } - } - - internal class AnchorInfo - { - public int Position; - public float Coordinate; - public bool LayoutFromEnd; - public bool Valid; - - public void Reset() - { - Position = NO_POSITION; - Coordinate = INVALID_OFFSET; - LayoutFromEnd = false; - Valid = false; - } - - } } } diff --git a/src/Tizen.NUI.Components/Controls/Slider.Internal.cs b/src/Tizen.NUI.Components/Controls/Slider.Internal.cs index 7cbe003..f31bccc 100755 --- a/src/Tizen.NUI.Components/Controls/Slider.Internal.cs +++ b/src/Tizen.NUI.Components/Controls/Slider.Internal.cs @@ -6,95 +6,50 @@ namespace Tizen.NUI.Components { public partial class Slider { - - /// - /// Get Slider style. - /// - /// The default slider style. - /// 8 - protected override ViewStyle CreateViewStyle() - { - return new SliderStyle(); - } - - /// - /// Dispose Slider. - /// - /// Dispose type. - /// 6 - protected override void Dispose(DisposeTypes type) - { - if (disposed) - { - return; - } - - if (type == DisposeTypes.Explicit) - { - if (null != panGestureDetector) - { - if (null != thumbImage) - { - panGestureDetector.Detach(thumbImage); - } - panGestureDetector.Detected -= OnPanGestureDetected; - panGestureDetector.Dispose(); - panGestureDetector = null; - } - - if (null != thumbImage) - { - thumbImage.TouchEvent -= OnTouchEventForThumb; - Utility.Dispose(thumbImage); - } - Utility.Dispose(slidedTrackImage); - if (null != bgTrackImage) - { - bgTrackImage.TouchEvent -= OnTouchEventForBgTrack; - Utility.Dispose(bgTrackImage); - } - Utility.Dispose(lowIndicatorImage); - Utility.Dispose(highIndicatorImage); - Utility.Dispose(lowIndicatorText); - Utility.Dispose(highIndicatorText); - } - - base.Dispose(type); - } - - /// - /// Update Slider by style. - /// - /// 6 - /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API. - [EditorBrowsable(EditorBrowsableState.Never)] - protected override void OnUpdate() - { - RelayoutBaseComponent(); - - UpdateComponentByIndicatorTypeChanged(); - UpdateBgTrackSize(); - UpdateBgTrackPosition(); - UpdateLowIndicatorSize(); - UpdateValue(); - } - - /// - /// Theme change callback when theme is changed, this callback will be trigger. - /// - /// The sender - /// The event data - /// 8 - protected override void OnThemeChangedEvent(object sender, StyleManager.ThemeChangeEventArgs e) - { - SliderStyle sliderStyle = StyleManager.Instance.GetViewStyle(StyleName) as SliderStyle; - if (sliderStyle != null) - { - Style?.CopyFrom(sliderStyle); - RelayoutRequest(); - } - } - + // the background track image object + private ImageView bgTrackImage = null; + // the slided track image object + private ImageView slidedTrackImage = null; + // the thumb image object + private ImageView thumbImage = null; + // the low indicator image object + private ImageView lowIndicatorImage = null; + // the high indicator image object + private ImageView highIndicatorImage = null; + // the low indicator text object + private TextLabel lowIndicatorText = null; + // the high indicator text object + private TextLabel highIndicatorText = null; + // the direction type + private DirectionType direction = DirectionType.Horizontal; + // the indicator type + private IndicatorType indicatorType = IndicatorType.None; + private const float round = 0.5f; + // the minimum value + private float minValue = 0; + // the maximum value + private float maxValue = 100; + // the current value + private float curValue = 0; + // the size of the low indicator + private Size lowIndicatorSize = null; + // the size of the high indicator + private Size highIndicatorSize = null; + // the track thickness value + private uint? trackThickness = null; + // the value of the space between track and indicator object + private Extents _spaceBetweenTrackAndIndicator = null; + + private PanGestureDetector panGestureDetector = null; + private float currentSlidedOffset; + private EventHandler valueChangedHandler; + private EventHandler slidingFinishedHandler; + private EventHandler stateChangedHandler; + + bool isFocused = false; + bool isPressed = false; + + private StringSelector thumbImageURLSelector = new StringSelector(); private void Initialize() { @@ -646,236 +601,5 @@ namespace Tizen.NUI.Components } return size; } - - private void CalculateCurrentValueByGesture(float offset) - { - currentSlidedOffset += offset; - - if (currentSlidedOffset <= 0) - { - curValue = minValue; - } - else if (currentSlidedOffset >= BgTrackLength()) - { - curValue = maxValue; - } - else - { - int bgTrackLength = BgTrackLength(); - if (bgTrackLength != 0) - { - curValue = ((currentSlidedOffset / (float)bgTrackLength) * (float)(maxValue - minValue)) + minValue; - } - } - if (valueChangedHandler != null) - { - ValueChangedArgs args = new ValueChangedArgs(); - args.CurrentValue = curValue; - valueChangedHandler(this, args); - } - } - - private bool OnTouchEventForBgTrack(object source, TouchEventArgs e) - { - PointStateType state = e.Touch.GetState(0); - if (state == PointStateType.Down) - { - Vector2 pos = e.Touch.GetLocalPosition(0); - CalculateCurrentValueByTouch(pos); - UpdateValue(); - if (null != slidingFinishedHandler) - { - SlidingFinishedArgs args = new SlidingFinishedArgs(); - args.CurrentValue = curValue; - slidingFinishedHandler(this, args); - } - } - return false; - } - - private bool OnTouchEventForThumb(object source, TouchEventArgs e) - { - PointStateType state = e.Touch.GetState(0); - if (state == PointStateType.Down) - { - UpdateState(isFocused, true); - } - else if (state == PointStateType.Up) - { - UpdateState(isFocused, false); - } - return true; - } - - private void CalculateCurrentValueByTouch(Vector2 pos) - { - int bgTrackLength = BgTrackLength(); - if (direction == DirectionType.Horizontal) - { - currentSlidedOffset = pos.X; - } - else if (direction == DirectionType.Vertical) - { - currentSlidedOffset = bgTrackLength - pos.Y; - } - if (bgTrackLength != 0) - { - curValue = ((currentSlidedOffset / (float)bgTrackLength) * (maxValue - minValue)) + minValue; - if (null != valueChangedHandler) - { - ValueChangedArgs args = new ValueChangedArgs(); - args.CurrentValue = curValue; - valueChangedHandler(this, args); - } - } - } - - private void UpdateState(bool isFocusedNew, bool isPressedNew) - { - if (isFocused == isFocusedNew && isPressed == isPressedNew) - { - return; - } - if (thumbImage == null || Style == null) - { - return; - } - isFocused = isFocusedNew; - isPressed = isPressedNew; - - if (!isFocused && !isPressed) - { - ControlState = ControlStates.Normal; - if (stateChangedHandler != null) - { - StateChangedArgs args = new StateChangedArgs(); - args.CurrentState = (ControlStates)ControlStates.Normal; - stateChangedHandler(this, args); - } - } - else if (isPressed) - { - ControlState = ControlStates.Pressed; - - if (stateChangedHandler != null) - { - StateChangedArgs args = new StateChangedArgs(); - args.CurrentState = (ControlStates)ControlStates.Pressed; - stateChangedHandler(this, args); - } - } - else if (!isPressed && isFocused) - { - ControlState = ControlStates.Focused; - - if (stateChangedHandler != null) - { - StateChangedArgs args = new StateChangedArgs(); - args.CurrentState = (ControlStates)ControlStates.Focused; - stateChangedHandler(this, args); - } - } - } - - private void UpdateComponentByIndicatorTypeChanged() - { - IndicatorType type = CurrentIndicatorType(); - if (type == IndicatorType.None) - { - if (lowIndicatorImage != null) - { - lowIndicatorImage.Hide(); - } - if (highIndicatorImage != null) - { - highIndicatorImage.Hide(); - } - if (lowIndicatorText != null) - { - lowIndicatorText.Hide(); - } - if (highIndicatorText != null) - { - highIndicatorText.Hide(); - } - } - else if (type == IndicatorType.Image) - { - if (lowIndicatorImage != null) - { - lowIndicatorImage.Show(); - } - if (highIndicatorImage != null) - { - highIndicatorImage.Show(); - } - if (lowIndicatorText != null) - { - lowIndicatorText.Hide(); - } - if (highIndicatorText != null) - { - highIndicatorText.Hide(); - } - } - else if (type == IndicatorType.Text) - { - if (lowIndicatorText != null) - { - lowIndicatorText.Show(); - } - if (highIndicatorText != null) - { - highIndicatorText.Show(); - } - if (lowIndicatorImage != null) - { - lowIndicatorImage.Hide(); - } - if (highIndicatorImage != null) - { - highIndicatorImage.Hide(); - } - } - } - - /// - /// Value Changed event data. - /// - /// 6 - public class ValueChangedArgs : EventArgs - { - /// - /// Curren value - /// - /// 6 - public float CurrentValue; - } - - /// - /// Value Changed event data. - /// - /// 6 - public class SlidingFinishedArgs : EventArgs - { - /// - /// Curren value - /// - /// 6 - public float CurrentValue; - } - - /// - /// State Changed event data. - /// - /// 6 - public class StateChangedArgs : EventArgs - { - /// - /// Curent state - /// - /// 6 - public ControlStates CurrentState; - } } } diff --git a/src/Tizen.NUI.Components/Controls/Slider.cs b/src/Tizen.NUI.Components/Controls/Slider.cs index ea530cf..457c506 100755 --- a/src/Tizen.NUI.Components/Controls/Slider.cs +++ b/src/Tizen.NUI.Components/Controls/Slider.cs @@ -27,66 +27,6 @@ namespace Tizen.NUI.Components /// 6 public partial class Slider : Control { - // the background track image object - private ImageView bgTrackImage = null; - // the slided track image object - private ImageView slidedTrackImage = null; - // the thumb image object - private ImageView thumbImage = null; - // the low indicator image object - private ImageView lowIndicatorImage = null; - // the high indicator image object - private ImageView highIndicatorImage = null; - // the low indicator text object - private TextLabel lowIndicatorText = null; - // the high indicator text object - private TextLabel highIndicatorText = null; - // the direction type - private DirectionType direction = DirectionType.Horizontal; - // the indicator type - private IndicatorType indicatorType = IndicatorType.None; - private const float round = 0.5f; - // the minimum value - private float minValue = 0; - // the maximum value - private float maxValue = 100; - // the current value - private float curValue = 0; - // the size of the low indicator - private Size lowIndicatorSize = null; - // the size of the high indicator - private Size highIndicatorSize = null; - // the track thickness value - private uint? trackThickness = null; - // the value of the space between track and indicator object - private Extents _spaceBetweenTrackAndIndicator = null; - private Extents spaceBetweenTrackAndIndicator - { - get - { - if (null == _spaceBetweenTrackAndIndicator) - { - _spaceBetweenTrackAndIndicator = new Extents((ushort start, ushort end, ushort top, ushort bottom) => - { - Extents extents = new Extents(start, end, top, bottom); - _spaceBetweenTrackAndIndicator.CopyFrom(extents); - }, 0, 0, 0, 0); - } - - return _spaceBetweenTrackAndIndicator; - } - } - - - private PanGestureDetector panGestureDetector = null; - private float currentSlidedOffset; - private EventHandler valueChangedHandler; - private EventHandler slidingFinishedHandler; - private EventHandler stateChangedHandler; - - bool isFocused = false; - bool isPressed = false; - /// 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 IndicatorTypeProperty = BindableProperty.Create("IndicatorType", typeof(IndicatorType), typeof(Slider), IndicatorType.None, propertyChanged: (bindable, oldValue, newValue) => @@ -295,25 +235,6 @@ namespace Tizen.NUI.Components SetValue(IndicatorTypeProperty, value); } } - private IndicatorType privateIndicatorType - { - get - { - return indicatorType; - } - set - { - if (indicatorType == value) - { - return; - } - indicatorType = value; - RelayoutBaseComponent(false); - UpdateBgTrackSize(); - UpdateBgTrackPosition(); - UpdateValue(); - } - } /// /// Gets or sets the minimum value of slider. @@ -401,7 +322,6 @@ namespace Tizen.NUI.Components } } - private StringSelector thumbImageURLSelector = new StringSelector(); /// /// Gets or sets the resource url selector of the thumb image object. /// @@ -479,39 +399,6 @@ namespace Tizen.NUI.Components SetValue(TrackThicknessProperty, value); } } - private uint privateTrackThickness - { - get - { - return trackThickness ?? 0; - } - set - { - trackThickness = value; - if (bgTrackImage != null) - { - if (direction == DirectionType.Horizontal) - { - bgTrackImage.SizeHeight = (float)trackThickness.Value; - } - else if (direction == DirectionType.Vertical) - { - bgTrackImage.SizeWidth = (float)trackThickness.Value; - } - } - if (slidedTrackImage != null) - { - if (direction == DirectionType.Horizontal) - { - slidedTrackImage.SizeHeight = (float)trackThickness.Value; - } - else if (direction == DirectionType.Vertical) - { - slidedTrackImage.SizeWidth = (float)trackThickness.Value; - } - } - } - } /// /// Gets or sets the resource url of the low indicator image object. @@ -640,6 +527,78 @@ namespace Tizen.NUI.Components SetValue(SpaceBetweenTrackAndIndicatorProperty, value); } } + + private Extents spaceBetweenTrackAndIndicator + { + get + { + if (null == _spaceBetweenTrackAndIndicator) + { + _spaceBetweenTrackAndIndicator = new Extents((ushort start, ushort end, ushort top, ushort bottom) => + { + Extents extents = new Extents(start, end, top, bottom); + _spaceBetweenTrackAndIndicator.CopyFrom(extents); + }, 0, 0, 0, 0); + } + + return _spaceBetweenTrackAndIndicator; + } + } + + private IndicatorType privateIndicatorType + { + get + { + return indicatorType; + } + set + { + if (indicatorType == value) + { + return; + } + indicatorType = value; + RelayoutBaseComponent(false); + UpdateBgTrackSize(); + UpdateBgTrackPosition(); + UpdateValue(); + } + } + + private uint privateTrackThickness + { + get + { + return trackThickness ?? 0; + } + set + { + trackThickness = value; + if (bgTrackImage != null) + { + if (direction == DirectionType.Horizontal) + { + bgTrackImage.SizeHeight = (float)trackThickness.Value; + } + else if (direction == DirectionType.Vertical) + { + bgTrackImage.SizeWidth = (float)trackThickness.Value; + } + } + if (slidedTrackImage != null) + { + if (direction == DirectionType.Horizontal) + { + slidedTrackImage.SizeHeight = (float)trackThickness.Value; + } + else if (direction == DirectionType.Vertical) + { + slidedTrackImage.SizeWidth = (float)trackThickness.Value; + } + } + } + } + private uint privateSpaceBetweenTrackAndIndicator { get @@ -733,5 +692,324 @@ namespace Tizen.NUI.Components EnableControlStatePropagation = true; } + + /// + /// Get Slider style. + /// + /// The default slider style. + /// 8 + protected override ViewStyle CreateViewStyle() + { + return new SliderStyle(); + } + + /// + /// Dispose Slider. + /// + /// Dispose type. + /// 6 + protected override void Dispose(DisposeTypes type) + { + if (disposed) + { + return; + } + + if (type == DisposeTypes.Explicit) + { + if (null != panGestureDetector) + { + if (null != thumbImage) + { + panGestureDetector.Detach(thumbImage); + } + panGestureDetector.Detected -= OnPanGestureDetected; + panGestureDetector.Dispose(); + panGestureDetector = null; + } + + if (null != thumbImage) + { + thumbImage.TouchEvent -= OnTouchEventForThumb; + Utility.Dispose(thumbImage); + } + Utility.Dispose(slidedTrackImage); + if (null != bgTrackImage) + { + bgTrackImage.TouchEvent -= OnTouchEventForBgTrack; + Utility.Dispose(bgTrackImage); + } + Utility.Dispose(lowIndicatorImage); + Utility.Dispose(highIndicatorImage); + Utility.Dispose(lowIndicatorText); + Utility.Dispose(highIndicatorText); + } + + base.Dispose(type); + } + + /// + /// Update Slider by style. + /// + /// 6 + /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API. + [EditorBrowsable(EditorBrowsableState.Never)] + protected override void OnUpdate() + { + RelayoutBaseComponent(); + + UpdateComponentByIndicatorTypeChanged(); + UpdateBgTrackSize(); + UpdateBgTrackPosition(); + UpdateLowIndicatorSize(); + UpdateValue(); + } + + /// + /// Theme change callback when theme is changed, this callback will be trigger. + /// + /// The sender + /// The event data + /// 8 + protected override void OnThemeChangedEvent(object sender, StyleManager.ThemeChangeEventArgs e) + { + SliderStyle sliderStyle = StyleManager.Instance.GetViewStyle(StyleName) as SliderStyle; + if (sliderStyle != null) + { + Style?.CopyFrom(sliderStyle); + RelayoutRequest(); + } + } + + private void CalculateCurrentValueByGesture(float offset) + { + currentSlidedOffset += offset; + + if (currentSlidedOffset <= 0) + { + curValue = minValue; + } + else if (currentSlidedOffset >= BgTrackLength()) + { + curValue = maxValue; + } + else + { + int bgTrackLength = BgTrackLength(); + if (bgTrackLength != 0) + { + curValue = ((currentSlidedOffset / (float)bgTrackLength) * (float)(maxValue - minValue)) + minValue; + } + } + if (valueChangedHandler != null) + { + ValueChangedArgs args = new ValueChangedArgs(); + args.CurrentValue = curValue; + valueChangedHandler(this, args); + } + } + + private bool OnTouchEventForBgTrack(object source, TouchEventArgs e) + { + PointStateType state = e.Touch.GetState(0); + if (state == PointStateType.Down) + { + Vector2 pos = e.Touch.GetLocalPosition(0); + CalculateCurrentValueByTouch(pos); + UpdateValue(); + if (null != slidingFinishedHandler) + { + SlidingFinishedArgs args = new SlidingFinishedArgs(); + args.CurrentValue = curValue; + slidingFinishedHandler(this, args); + } + } + return false; + } + + private bool OnTouchEventForThumb(object source, TouchEventArgs e) + { + PointStateType state = e.Touch.GetState(0); + if (state == PointStateType.Down) + { + UpdateState(isFocused, true); + } + else if (state == PointStateType.Up) + { + UpdateState(isFocused, false); + } + return true; + } + + private void CalculateCurrentValueByTouch(Vector2 pos) + { + int bgTrackLength = BgTrackLength(); + if (direction == DirectionType.Horizontal) + { + currentSlidedOffset = pos.X; + } + else if (direction == DirectionType.Vertical) + { + currentSlidedOffset = bgTrackLength - pos.Y; + } + if (bgTrackLength != 0) + { + curValue = ((currentSlidedOffset / (float)bgTrackLength) * (maxValue - minValue)) + minValue; + if (null != valueChangedHandler) + { + ValueChangedArgs args = new ValueChangedArgs(); + args.CurrentValue = curValue; + valueChangedHandler(this, args); + } + } + } + + private void UpdateState(bool isFocusedNew, bool isPressedNew) + { + if (isFocused == isFocusedNew && isPressed == isPressedNew) + { + return; + } + if (thumbImage == null || Style == null) + { + return; + } + isFocused = isFocusedNew; + isPressed = isPressedNew; + + if (!isFocused && !isPressed) + { + ControlState = ControlStates.Normal; + if (stateChangedHandler != null) + { + StateChangedArgs args = new StateChangedArgs(); + args.CurrentState = (ControlStates)ControlStates.Normal; + stateChangedHandler(this, args); + } + } + else if (isPressed) + { + ControlState = ControlStates.Pressed; + + if (stateChangedHandler != null) + { + StateChangedArgs args = new StateChangedArgs(); + args.CurrentState = (ControlStates)ControlStates.Pressed; + stateChangedHandler(this, args); + } + } + else if (!isPressed && isFocused) + { + ControlState = ControlStates.Focused; + + if (stateChangedHandler != null) + { + StateChangedArgs args = new StateChangedArgs(); + args.CurrentState = (ControlStates)ControlStates.Focused; + stateChangedHandler(this, args); + } + } + } + + private void UpdateComponentByIndicatorTypeChanged() + { + IndicatorType type = CurrentIndicatorType(); + if (type == IndicatorType.None) + { + if (lowIndicatorImage != null) + { + lowIndicatorImage.Hide(); + } + if (highIndicatorImage != null) + { + highIndicatorImage.Hide(); + } + if (lowIndicatorText != null) + { + lowIndicatorText.Hide(); + } + if (highIndicatorText != null) + { + highIndicatorText.Hide(); + } + } + else if (type == IndicatorType.Image) + { + if (lowIndicatorImage != null) + { + lowIndicatorImage.Show(); + } + if (highIndicatorImage != null) + { + highIndicatorImage.Show(); + } + if (lowIndicatorText != null) + { + lowIndicatorText.Hide(); + } + if (highIndicatorText != null) + { + highIndicatorText.Hide(); + } + } + else if (type == IndicatorType.Text) + { + if (lowIndicatorText != null) + { + lowIndicatorText.Show(); + } + if (highIndicatorText != null) + { + highIndicatorText.Show(); + } + if (lowIndicatorImage != null) + { + lowIndicatorImage.Hide(); + } + if (highIndicatorImage != null) + { + highIndicatorImage.Hide(); + } + } + } + + /// + /// Value Changed event data. + /// + /// 6 + public class ValueChangedArgs : EventArgs + { + /// + /// Curren value + /// + /// 6 + public float CurrentValue; + } + + /// + /// Value Changed event data. + /// + /// 6 + public class SlidingFinishedArgs : EventArgs + { + /// + /// Curren value + /// + /// 6 + public float CurrentValue; + } + + /// + /// State Changed event data. + /// + /// 6 + public class StateChangedArgs : EventArgs + { + /// + /// Curent state + /// + /// 6 + public ControlStates CurrentState; + } } } diff --git a/src/Tizen.NUI.Components/Utils/StyleManager.cs b/src/Tizen.NUI.Components/Utils/StyleManager.cs index b176283..afc5386 100755 --- a/src/Tizen.NUI.Components/Utils/StyleManager.cs +++ b/src/Tizen.NUI.Components/Utils/StyleManager.cs @@ -240,11 +240,13 @@ namespace Tizen.NUI.Components private void SetInitialThemeByDeviceProfile() { - themeMap.Add(wearableThemeName, WearableTheme.Instance); - themeMap.Add(defaultThemeName, DefaultTheme.Instance); + Theme wearableTheme = WearableTheme.Instance; + Theme defaultTheme = DefaultTheme.Instance; + themeMap.Add(wearableThemeName, wearableTheme); + themeMap.Add(defaultThemeName, defaultTheme); currentThemeName = defaultThemeName; - currentTheme = DefaultTheme.Instance; + currentTheme = defaultTheme; string currentProfile; @@ -262,7 +264,7 @@ namespace Tizen.NUI.Components if (string.Equals(currentProfile, wearableThemeName)) { currentThemeName = wearableThemeName; - currentTheme = WearableTheme.Instance; + currentTheme = wearableTheme; } } -- 2.7.4