--- /dev/null
+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<StateChangedEventArgs> 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();
+
+ /// <summary>
+ /// The last touch information triggering selected state change.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ protected Touch SelectionChangedByTouch { get; set; }
+
+ /// <summary>
+ /// The ButtonExtension instance that is injected by ButtonStyle.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ protected ButtonExtension Extension { get; set; }
+
+ /// <summary>
+ /// Creates Button's text part.
+ /// </summary>
+ /// <return>The created Button's text part.</return>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ protected virtual TextLabel CreateText()
+ {
+ return new TextLabel();
+ }
+
+ /// <summary>
+ /// Creates Button's icon part.
+ /// </summary>
+ /// <return>The created Button's icon part.</return>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ protected virtual ImageView CreateIcon()
+ {
+ return new ImageView();
+ }
+
+ /// <summary>
+ /// Creates Button's overlay image part.
+ /// </summary>
+ /// <return>The created Button's overlay image part.</return>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ protected virtual ImageView CreateOverlayImage()
+ {
+ return new ImageView();
+ }
+
+ /// <summary>
+ /// Called when the Button is Clicked by a user
+ /// </summary>
+ /// <param name="eventArgs">The click information.</param>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ protected virtual void OnClick(ClickEventArgs eventArgs)
+ {
+ }
+
+ /// <summary>
+ /// Get Button style.
+ /// </summary>
+ /// <returns>The default button style.</returns>
+ /// <since_tizen> 8 </since_tizen>
+ 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);
+ }
+
+ /// <summary>
+ /// Update Button State.
+ /// </summary>
+ /// <param name="touchInfo">The touch information in case the state has changed by touching.</param>
+ /// <since_tizen> 6 </since_tizen>
+ /// 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));
+ }
+ }
+
+ /// <summary>
+ /// Measure text, it can be override.
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ /// 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;
+ }
+ }
+
+ /// <summary>
+ /// Layout child, it can be override.
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ /// 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;
+ }
+ }
+
+ /// <summary>
+ /// Theme change callback when theme is changed, this callback will be trigger.
+ /// </summary>
+ /// <param name="sender">The sender</param>
+ /// <param name="e">The event data</param>
+ /// <since_tizen> 8 </since_tizen>
+ protected override void OnThemeChangedEvent(object sender, StyleManager.ThemeChangeEventArgs e)
+ {
+ ButtonStyle buttonStyle = StyleManager.Instance.GetViewStyle(StyleName) as ButtonStyle;
+ if (buttonStyle != null)
+ {
+ Style.CopyFrom(buttonStyle);
+ UpdateUIContent();
+ }
+ }
+
+ /// <summary>
+ /// Dispose Button and all children on it.
+ /// </summary>
+ /// <param name="type">Dispose type.</param>
+ /// <since_tizen> 6 </since_tizen>
+ 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);
+ }
+
+ /// <summary>
+ /// It is hijack by using protected, style copy problem when class inherited from Button.
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ 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();
+ }
+
+ }
+}
/// Button may contain text or an icon.
/// </summary>
/// <since_tizen> 6 </since_tizen>
- 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)]
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)]
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)]
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)]
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)]
return instance.Style?.TextPadding;
});
- private ImageView overlayImage;
- private TextLabel buttonText;
- private ImageView buttonIcon;
-
- private EventHandler<StateChangedEventArgs> stateChangeHander;
-
- private bool isSelected = false;
- private bool isEnabled = true;
- private bool isPressed = false;
-
- /// <summary>
- /// The last touch information triggering selected state change.
- /// </summary>
- [EditorBrowsable(EditorBrowsableState.Never)]
- protected Touch SelectionChangedByTouch { get; set; }
-
- /// <summary>
- /// The ButtonExtension instance that is injected by ButtonStyle.
- /// </summary>
- [EditorBrowsable(EditorBrowsableState.Never)]
- protected ButtonExtension Extension { get; set; }
-
- /// <summary>
- /// Creates Button's text part.
- /// </summary>
- /// <return>The created Button's text part.</return>
- [EditorBrowsable(EditorBrowsableState.Never)]
- protected virtual TextLabel CreateText()
- {
- return new TextLabel();
- }
-
- /// <summary>
- /// Creates Button's icon part.
- /// </summary>
- /// <return>The created Button's icon part.</return>
- [EditorBrowsable(EditorBrowsableState.Never)]
- protected virtual ImageView CreateIcon()
- {
- return new ImageView();
- }
-
- /// <summary>
- /// Creates Button's overlay image part.
- /// </summary>
- /// <return>The created Button's overlay image part.</return>
- [EditorBrowsable(EditorBrowsableState.Never)]
- protected virtual ImageView CreateOverlayImage()
- {
- return new ImageView();
- }
-
- /// <summary>
- /// Called when the Button is Clicked by a user
- /// </summary>
- /// <param name="eventArgs">The click information.</param>
- [EditorBrowsable(EditorBrowsableState.Never)]
- protected virtual void OnClick(ClickEventArgs eventArgs)
- {
- }
-
static Button() { }
/// <summary>
/// </summary>
/// <since_tizen> 6 </since_tizen>
public event EventHandler<ClickEventArgs> ClickEvent;
+
/// <summary>
/// An event for the button state changed signal which can be used to subscribe or unsubscribe the event handler provided by the user.<br />
/// </summary>
stateChangeHander -= value;
}
}
+
/// <summary>
/// Icon orientation.
/// </summary>
}
}
- private bool privateIsSelectable
- {
- get
- {
- return Style?.IsSelectable ?? false;
- }
- set
- {
- Style.IsSelectable = value;
- }
- }
-
/// <summary>
/// Translate text string in Button.
/// </summary>
}
}
}
+
/// <summary>
/// Text color in Button.
/// </summary>
}
}
}
+
/// <summary>
/// Text horizontal alignment in Button.
/// </summary>
}
}
}
+
/// <summary>
/// Icon image's resource url in Button.
/// </summary>
}
}
- private StringSelector textSelector = new StringSelector();
/// <summary>
/// Text string selector in Button.
/// </summary>
}
}
- private StringSelector translatableTextSelector = new StringSelector();
/// <summary>
/// Translateable text string selector in Button.
/// </summary>
}
}
- private ColorSelector textColorSelector = new ColorSelector();
/// <summary>
/// Text color selector in Button.
/// </summary>
}
}
- private FloatSelector pointSizeSelector = new FloatSelector();
/// <summary>
/// Text font size selector in Button.
/// </summary>
}
}
- private StringSelector iconURLSelector = new StringSelector();
/// <summary>
/// Icon image's resource url selector in Button.
/// </summary>
SetValue(IsSelectedProperty, value);
}
}
- private bool privateIsSelected
- {
- get
- {
- return isSelected;
- }
- set
- {
- isSelected = value;
-
- UpdateState();
- }
- }
/// <summary>
/// Flag to decide enable or disable in Button.
SetValue(IsEnabledProperty, value);
}
}
- private bool privateIsEnabled
- {
- get
- {
- return isEnabled;
- }
- set
- {
- isEnabled = value;
- UpdateState();
- }
- }
/// <summary>
/// Icon relative orientation in Button, work only when show icon and text.
SetValue(IconRelativeOrientationProperty, value);
}
}
- private IconOrientation? privateIconRelativeOrientation
- {
- get
- {
- return Style?.IconRelativeOrientation;
- }
- set
- {
- if (Style != null && Style.IconRelativeOrientation != value)
- {
- Style.IconRelativeOrientation = value;
- UpdateUIContent();
- }
- }
- }
/// <summary>
/// Icon padding in Button, work only when show icon and text.
}
/// <summary>
- /// Dispose Button and all children on it.
- /// </summary>
- /// <param name="type">Dispose type.</param>
- /// <since_tizen> 6 </since_tizen>
- 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);
- }
- /// <summary>
/// Called after a key event is received by the view that has had its focus set.
/// </summary>
/// <param name="key">The key event.</param>
}
/// <summary>
- /// Get Button style.
- /// </summary>
- /// <returns>The default button style.</returns>
- /// <since_tizen> 8 </since_tizen>
- 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);
- }
-
- /// <summary>
- /// Update Button State.
- /// </summary>
- /// <param name="touchInfo">The touch information in case the state has changed by touching.</param>
- /// <since_tizen> 6 </since_tizen>
- /// 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));
- }
- }
-
- /// <summary>
- /// It is hijack by using protected, style copy problem when class inherited from Button.
- /// </summary>
- /// <since_tizen> 6 </since_tizen>
- private void Initialize()
- {
- var style = (ButtonStyle)Style;
- EnableControlStatePropagation = true;
- UpdateState();
- LayoutDirectionChanged += OnLayoutDirectionChanged;
- }
-
- /// <summary>
- /// Measure text, it can be override.
- /// </summary>
- /// <since_tizen> 6 </since_tizen>
- /// 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;
- }
- }
- /// <summary>
- /// Layout child, it can be override.
- /// </summary>
- /// <since_tizen> 6 </since_tizen>
- /// 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;
- }
- }
- /// <summary>
- /// Theme change callback when theme is changed, this callback will be trigger.
- /// </summary>
- /// <param name="sender">The sender</param>
- /// <param name="e">The event data</param>
- /// <since_tizen> 8 </since_tizen>
- 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();
- }
-
- /// <summary>
/// ClickEventArgs is a class to record button click event arguments which will sent to user.
/// </summary>
/// <since_tizen> 6 </since_tizen>
public class ClickEventArgs : EventArgs
{
}
+
/// <summary>
/// StateChangeEventArgs is a class to record button state change event arguments which will sent to user.
/// </summary>
--- /dev/null
+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;
+ }
+ }
+ }
+}
/// <since_tizen> 6 </since_tizen>
/// 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
{
/// <summary>
/// Constant value: 0.
}
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;
- }
-
- }
}
}
{
public partial class Slider
{
-
- /// <summary>
- /// Get Slider style.
- /// </summary>
- /// <returns>The default slider style.</returns>
- /// <since_tizen> 8 </since_tizen>
- protected override ViewStyle CreateViewStyle()
- {
- return new SliderStyle();
- }
-
- /// <summary>
- /// Dispose Slider.
- /// </summary>
- /// <param name="type">Dispose type.</param>
- /// <since_tizen> 6 </since_tizen>
- 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);
- }
-
- /// <summary>
- /// Update Slider by style.
- /// </summary>
- /// <since_tizen> 6 </since_tizen>
- /// 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();
- }
-
- /// <summary>
- /// Theme change callback when theme is changed, this callback will be trigger.
- /// </summary>
- /// <param name="sender">The sender</param>
- /// <param name="e">The event data</param>
- /// <since_tizen> 8 </since_tizen>
- 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<ValueChangedArgs> valueChangedHandler;
+ private EventHandler<SlidingFinishedArgs> slidingFinishedHandler;
+ private EventHandler<StateChangedArgs> stateChangedHandler;
+
+ bool isFocused = false;
+ bool isPressed = false;
+
+ private StringSelector thumbImageURLSelector = new StringSelector();
private void Initialize()
{
}
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();
- }
- }
- }
-
- /// <summary>
- /// Value Changed event data.
- /// </summary>
- /// <since_tizen> 6 </since_tizen>
- public class ValueChangedArgs : EventArgs
- {
- /// <summary>
- /// Curren value
- /// </summary>
- /// <since_tizen> 6 </since_tizen>
- public float CurrentValue;
- }
-
- /// <summary>
- /// Value Changed event data.
- /// </summary>
- /// <since_tizen> 6 </since_tizen>
- public class SlidingFinishedArgs : EventArgs
- {
- /// <summary>
- /// Curren value
- /// </summary>
- /// <since_tizen> 6 </since_tizen>
- public float CurrentValue;
- }
-
- /// <summary>
- /// State Changed event data.
- /// </summary>
- /// <since_tizen> 6 </since_tizen>
- public class StateChangedArgs : EventArgs
- {
- /// <summary>
- /// Curent state
- /// </summary>
- /// <since_tizen> 6 </since_tizen>
- public ControlStates CurrentState;
- }
}
}
/// <since_tizen> 6 </since_tizen>
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<ValueChangedArgs> valueChangedHandler;
- private EventHandler<SlidingFinishedArgs> slidingFinishedHandler;
- private EventHandler<StateChangedArgs> 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) =>
SetValue(IndicatorTypeProperty, value);
}
}
- private IndicatorType privateIndicatorType
- {
- get
- {
- return indicatorType;
- }
- set
- {
- if (indicatorType == value)
- {
- return;
- }
- indicatorType = value;
- RelayoutBaseComponent(false);
- UpdateBgTrackSize();
- UpdateBgTrackPosition();
- UpdateValue();
- }
- }
/// <summary>
/// Gets or sets the minimum value of slider.
}
}
- private StringSelector thumbImageURLSelector = new StringSelector();
/// <summary>
/// Gets or sets the resource url selector of the thumb image object.
/// </summary>
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;
- }
- }
- }
- }
/// <summary>
/// Gets or sets the resource url of the low indicator image object.
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
EnableControlStatePropagation = true;
}
+
+ /// <summary>
+ /// Get Slider style.
+ /// </summary>
+ /// <returns>The default slider style.</returns>
+ /// <since_tizen> 8 </since_tizen>
+ protected override ViewStyle CreateViewStyle()
+ {
+ return new SliderStyle();
+ }
+
+ /// <summary>
+ /// Dispose Slider.
+ /// </summary>
+ /// <param name="type">Dispose type.</param>
+ /// <since_tizen> 6 </since_tizen>
+ 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);
+ }
+
+ /// <summary>
+ /// Update Slider by style.
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ /// 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();
+ }
+
+ /// <summary>
+ /// Theme change callback when theme is changed, this callback will be trigger.
+ /// </summary>
+ /// <param name="sender">The sender</param>
+ /// <param name="e">The event data</param>
+ /// <since_tizen> 8 </since_tizen>
+ 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();
+ }
+ }
+ }
+
+ /// <summary>
+ /// Value Changed event data.
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ public class ValueChangedArgs : EventArgs
+ {
+ /// <summary>
+ /// Curren value
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ public float CurrentValue;
+ }
+
+ /// <summary>
+ /// Value Changed event data.
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ public class SlidingFinishedArgs : EventArgs
+ {
+ /// <summary>
+ /// Curren value
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ public float CurrentValue;
+ }
+
+ /// <summary>
+ /// State Changed event data.
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ public class StateChangedArgs : EventArgs
+ {
+ /// <summary>
+ /// Curent state
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ public ControlStates CurrentState;
+ }
}
}
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;
if (string.Equals(currentProfile, wearableThemeName))
{
currentThemeName = wearableThemeName;
- currentTheme = WearableTheme.Instance;
+ currentTheme = wearableTheme;
}
}