/*
* Copyright(c) 2019 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System;
using Tizen.NUI.BaseComponents;
using System.ComponentModel;
using Tizen.NUI.Binding;
namespace Tizen.NUI.Components
{
///
/// Slider value changed event data.
///
/// 8
public class SliderValueChangedEventArgs : EventArgs
{
///
/// Current Slider value
///
/// 8
public float CurrentValue { get; set; }
}
///
/// Slider sliding started event data.
///
/// 8
public class SliderSlidingStartedEventArgs : EventArgs
{
///
/// Current Slider value
///
/// 8
public float CurrentValue { get; set; }
}
///
/// Slider sliding finished event data.
///
/// 8
public class SliderSlidingFinishedEventArgs : EventArgs
{
///
/// Current Slider value
///
/// 8
public float CurrentValue { get; set; }
}
///
/// A slider lets users select a value from a continuous or discrete range of values by moving the slider thumb.
///
/// 6
public partial class Slider : 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)]
public static readonly BindableProperty IndicatorTypeProperty = BindableProperty.Create("IndicatorType", typeof(IndicatorType), typeof(Slider), IndicatorType.None, propertyChanged: (bindable, oldValue, newValue) =>
{
var instance = (Slider)bindable;
if (newValue != null)
{
instance.privateIndicatorType = (IndicatorType)newValue;
}
},
defaultValueCreator: (bindable) =>
{
var instance = (Slider)bindable;
return instance.privateIndicatorType;
});
/// 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 SpaceBetweenTrackAndIndicatorProperty = BindableProperty.Create(nameof(SpaceBetweenTrackAndIndicator), typeof(uint), typeof(Slider), (uint)0, propertyChanged: (bindable, oldValue, newValue) =>
{
var instance = (Slider)bindable;
if (newValue != null)
{
instance.privateSpaceBetweenTrackAndIndicator = (uint)newValue;
}
},
defaultValueCreator: (bindable) =>
{
var instance = (Slider)bindable;
return instance.privateSpaceBetweenTrackAndIndicator;
});
/// 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 TrackThicknessProperty = BindableProperty.Create(nameof(TrackThickness), typeof(uint), typeof(Slider), (uint)0, propertyChanged: (bindable, oldValue, newValue) =>
{
var instance = (Slider)bindable;
if (newValue != null)
{
instance.privateTrackThickness = (uint)newValue;
}
},
defaultValueCreator: (bindable) =>
{
var instance = (Slider)bindable;
return instance.privateTrackThickness;
});
static Slider() { }
///
/// The constructor of the Slider class.
///
/// 6
public Slider()
{
Initialize();
}
///
/// The constructor of the Slider class with specific style.
///
/// The string to initialize the Slider
/// 8
public Slider(string style) : base(style)
{
Initialize();
}
///
/// The constructor of the Slider class with specific style.
///
/// The style object to initialize the Slider
/// 8
public Slider(SliderStyle sliderStyle) : base(sliderStyle)
{
Initialize();
}
///
/// The value changed event handler.
///
/// 6
[Obsolete("Deprecated in API8; Will be removed in API10. Please use ValueChanged event instead.")]
public event EventHandler ValueChangedEvent
{
add
{
valueChangedHandler += value;
}
remove
{
valueChangedHandler -= value;
}
}
///
/// The sliding finished event handler.
///
/// 6
[Obsolete("Deprecated in API8; Will be removed in API10. Please use SlidingFinished event instead.")]
public event EventHandler SlidingFinishedEvent
{
add
{
slidingFinishedHandler += value;
}
remove
{
slidingFinishedHandler -= value;
}
}
///
/// The value changed event handler.
///
/// 8
public event EventHandler ValueChanged
{
add
{
sliderValueChangedHandler += value;
}
remove
{
sliderValueChangedHandler -= value;
}
}
///
/// The sliding started event handler.
///
/// 8
public event EventHandler SlidingStarted
{
add
{
sliderSlidingStartedHandler += value;
}
remove
{
sliderSlidingStartedHandler -= value;
}
}
///
/// The sliding finished event handler.
///
/// 8
public event EventHandler SlidingFinished
{
add
{
sliderSlidingFinishedHandler += value;
}
remove
{
sliderSlidingFinishedHandler -= value;
}
}
///
/// The state changed event handler.
///
/// 6
[Obsolete("Deprecated in API8; Will be removed in API10. Please use View.ControlStateChangedEvent")]
public event EventHandler StateChangedEvent
{
add
{
stateChangedHandler += value;
}
remove
{
stateChangedHandler -= value;
}
}
///
/// The direction type of slider.
///
/// 6
public enum DirectionType
{
///
/// The Horizontal type.
///
/// 6
Horizontal,
///
/// The Vertical type.
///
/// 6
Vertical
}
///
/// The indicator type of slider.
///
/// 6
public enum IndicatorType
{
/// Only contains slider bar.
/// 6
None,
/// Contains slider bar, IndicatorImage.
/// 6
Image,
/// Contains slider bar, IndicatorText.
/// 6
Text
}
///
/// Return a copied Style instance of Slider
///
///
/// It returns copied Style instance and changing it does not effect to the Slider.
/// Style setting is possible by using constructor or the function of ApplyStyle(ViewStyle viewStyle)
///
/// 8
public new SliderStyle Style
{
get
{
var result = new SliderStyle(sliderStyle);
result.CopyPropertiesFromView(this);
result.Track.CopyPropertiesFromView(bgTrackImage);
result.Progress.CopyPropertiesFromView(slidedTrackImage);
result.Thumb.CopyPropertiesFromView(thumbImage);
result.LowIndicatorImage.CopyPropertiesFromView(lowIndicatorImage);
result.HighIndicatorImage.CopyPropertiesFromView(highIndicatorImage);
result.LowIndicator.CopyPropertiesFromView(lowIndicatorText);
result.HighIndicator.CopyPropertiesFromView(highIndicatorText);
return result;
}
}
///
/// Return a copied Style instance of Slider
///
private SliderStyle sliderStyle => ViewStyle as SliderStyle;
///
/// Gets or sets the direction type of slider.
///
/// 6
public DirectionType Direction
{
get
{
return direction;
}
set
{
if (direction == value)
{
return;
}
direction = value;
RelayoutBaseComponent(false);
UpdateBgTrackSize();
UpdateBgTrackPosition();
UpdateValue();
}
}
///
/// Gets or sets the indicator type, arrow or sign.
///
/// 6
public IndicatorType Indicator
{
get
{
return (IndicatorType)GetValue(IndicatorTypeProperty);
}
set
{
SetValue(IndicatorTypeProperty, value);
}
}
///
/// Gets or sets the minimum value of slider.
///
/// 6
public float MinValue
{
get
{
return minValue;
}
set
{
minValue = value;
UpdateValue();
}
}
///
/// Gets or sets the maximum value of slider.
///
/// 6
public float MaxValue
{
get
{
return maxValue;
}
set
{
maxValue = value;
UpdateValue();
}
}
///
/// Gets or sets the current value of slider.
///
/// 6
public float CurrentValue
{
get
{
return curValue;
}
set
{
curValue = value;
UpdateValue();
}
}
///
/// Gets or sets the size of the thumb image object.
///
/// 6
public Size ThumbSize
{
get
{
return thumbImage?.Size;
}
set
{
if (null != thumbImage)
{
thumbImage.Size = value;
sliderStyle.Thumb.Size = value;
}
}
}
///
/// Gets or sets the resource url of the thumb image object.
///
/// 6
public string ThumbImageURL
{
get
{
return thumbImage?.ResourceUrl;
}
set
{
if (null != thumbImage)
{
thumbImage.ResourceUrl = value;
sliderStyle.Thumb.ResourceUrl = value;
}
}
}
///
/// Gets or sets the resource url selector of the thumb image object.
/// Getter returns copied selector value if exist, null otherwise.
///
/// Thrown when setting null value.
/// 6
public StringSelector ThumbImageURLSelector
{
get => thumbImage == null ? null : new StringSelector((Selector)thumbImage.GetValue(ImageView.ResourceUrlSelectorProperty));
set
{
if (value == null || thumbImage == null)
{
throw new NullReferenceException("Slider.ThumbImageURLSelector is null");
}
else
{
thumbImage.SetValue(ImageView.ResourceUrlSelectorProperty, value);
}
}
}
///
/// Gets or sets the color of the thumb image object.
///
/// 8
public Color ThumbColor
{
get
{
return thumbImage?.Color;
}
set
{
if (null != thumbImage)
{
thumbImage.Color = value;
sliderStyle.Thumb.Color = value;
}
}
}
///
/// Gets or sets the color of the background track image object.
///
/// 6
public Color BgTrackColor
{
get
{
return bgTrackImage?.BackgroundColor;
}
set
{
if (null != bgTrackImage)
{
bgTrackImage.BackgroundColor = value;
sliderStyle.Track.BackgroundColor = value;
}
}
}
///
/// Gets or sets the color of the slided track image object.
///
/// 6
public Color SlidedTrackColor
{
get
{
return slidedTrackImage?.BackgroundColor;
}
set
{
if (null != slidedTrackImage)
{
slidedTrackImage.BackgroundColor = value;
sliderStyle.Progress.BackgroundColor = value;
}
}
}
///
/// Gets or sets the thickness value of the track.
///
/// 6
public uint TrackThickness
{
get
{
return (uint)GetValue(TrackThicknessProperty);
}
set
{
SetValue(TrackThicknessProperty, value);
}
}
///
/// Gets or sets the resource url of the low indicator image object.
///
/// 6
public string LowIndicatorImageURL
{
get
{
return lowIndicatorImage?.ResourceUrl;
}
set
{
if (null == lowIndicatorImage) lowIndicatorImage = new ImageView();
lowIndicatorImage.ResourceUrl = value;
sliderStyle.LowIndicatorImage.ResourceUrl = value;
}
}
///
/// Gets or sets the resource url of the high indicator image object.
///
/// 6
public string HighIndicatorImageURL
{
get
{
return highIndicatorImage?.ResourceUrl;
}
set
{
if (null == highIndicatorImage) highIndicatorImage = new ImageView();
highIndicatorImage.ResourceUrl = value;
sliderStyle.HighIndicatorImage.ResourceUrl = value;
}
}
///
/// Gets or sets the text content of the low indicator text object.
///
/// 6
public string LowIndicatorTextContent
{
get
{
return lowIndicatorText?.Text;
}
set
{
if (null != lowIndicatorText)
{
lowIndicatorText.Text = value;
sliderStyle.LowIndicator.Text = value;
}
}
}
///
/// Gets or sets the text content of the high indicator text object.
///
/// 6
public string HighIndicatorTextContent
{
get
{
return highIndicatorText?.Text;
}
set
{
if (null != highIndicatorText)
{
highIndicatorText.Text = value;
sliderStyle.HighIndicator.Text = value;
}
}
}
///
/// Gets or sets the size of the low indicator object(image or text).
///
/// 6
public Size LowIndicatorSize
{
get
{
return lowIndicatorSize;
}
set
{
lowIndicatorSize = value;
UpdateLowIndicatorSize();
UpdateBgTrackSize();
UpdateBgTrackPosition();
UpdateValue();
}
}
///
/// Gets or sets the size of the high indicator object(image or text).
///
/// 6
public Size HighIndicatorSize
{
get
{
return highIndicatorText?.Size;
}
set
{
if (null != highIndicatorText)
{
highIndicatorText.Size = value;
sliderStyle.HighIndicator.Size = value;
}
}
}
///
/// Gets or sets the value of the space between track and indicator.
///
/// 6
public uint SpaceBetweenTrackAndIndicator
{
get
{
return (uint)GetValue(SpaceBetweenTrackAndIndicatorProperty);
}
set
{
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
{
return privateTrackPadding.Start;
}
set
{
ushort val = (ushort)value;
privateTrackPadding = new Extents(val, val, val, val);
}
}
private Extents privateTrackPadding
{
get
{
return spaceBetweenTrackAndIndicator;
}
set
{
spaceBetweenTrackAndIndicator.CopyFrom(value);
UpdateComponentByIndicatorTypeChanged();
UpdateBgTrackSize();
UpdateBgTrackPosition();
UpdateValue();
}
}
///
/// Focus gained callback.
///
/// 8
public override void OnFocusGained()
{
//State = ControlStates.Focused;
UpdateState(true, isPressed);
base.OnFocusGained();
}
///
/// Focus Lost callback.
///
/// 8
public override void OnFocusLost()
{
//State = ControlStates.Normal;
UpdateState(false, isPressed);
base.OnFocusLost();
}
///
/// Apply style to scrollbar.
///
/// The style to apply.
/// 8
public override void ApplyStyle(ViewStyle viewStyle)
{
base.ApplyStyle(viewStyle);
SliderStyle sliderStyle = viewStyle as SliderStyle;
if (null != sliderStyle?.Progress)
{
CreateSlidedTrack().ApplyStyle(sliderStyle.Progress);
}
if (null != sliderStyle?.LowIndicator)
{
CreateLowIndicatorText().ApplyStyle(sliderStyle.LowIndicator);
}
if (null != sliderStyle?.HighIndicator)
{
CreateHighIndicatorText().ApplyStyle(sliderStyle.HighIndicator);
}
if (null != sliderStyle?.Track)
{
CreateBackgroundTrack().ApplyStyle(sliderStyle.Track);
}
if (null != sliderStyle?.Thumb)
{
CreateThumb().ApplyStyle(sliderStyle.Thumb);
}
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();
}
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);
}
if (sliderValueChangedHandler != null)
{
SliderValueChangedEventArgs args = new SliderValueChangedEventArgs();
args.CurrentValue = curValue;
sliderValueChangedHandler(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);
}
if (null != sliderSlidingFinishedHandler)
{
SliderSlidingFinishedEventArgs args = new SliderSlidingFinishedEventArgs();
args.CurrentValue = curValue;
sliderSlidingFinishedHandler(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);
}
if (null != sliderValueChangedHandler)
{
SliderValueChangedEventArgs args = new SliderValueChangedEventArgs();
args.CurrentValue = curValue;
sliderValueChangedHandler(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 = ControlState.Normal;
if (stateChangedHandler != null)
{
StateChangedArgs args = new StateChangedArgs();
args.CurrentState = (ControlStates)ControlStates.Normal;
stateChangedHandler(this, args);
}
}
else if (isPressed)
{
ControlState = ControlState.Pressed;
if (stateChangedHandler != null)
{
StateChangedArgs args = new StateChangedArgs();
args.CurrentState = (ControlStates)ControlStates.Pressed;
stateChangedHandler(this, args);
}
}
else if (!isPressed && isFocused)
{
ControlState = ControlState.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
[Obsolete("Deprecated in API8; Will be removed in API10. Please use SliderValueChangedEventArgs instead.")]
[global::System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible")]
public class ValueChangedArgs : EventArgs
{
///
/// Curren value
///
/// 6
/// It will be removed in API10
[global::System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1051:Do not declare visible instance fields")]
[Obsolete("Deprecated in API8; Will be removed in API10. Please use SliderValueChangedEventArgs.CurrentValue instead.")]
public float CurrentValue;
}
///
/// Value Changed event data.
///
/// 6
[Obsolete("Deprecated in API8; Will be removed in API10. Please use SliderSlidingFinishedEventArgs instead.")]
[global::System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible")]
public class SlidingFinishedArgs : EventArgs
{
///
/// Curren value
///
/// 6
/// It will be removed in API10
[global::System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1051:Do not declare visible instance fields")]
[Obsolete("Deprecated in API8; Will be removed in API10. Please use SliderSlidingFinishedEventArgs.CurrentValue instead.")]
public float CurrentValue;
}
///
/// State Changed event data.
///
/// 6
[Obsolete("Deprecated in API8; Will be removed in API10. Please use View.ControlStateChangedEventArgs")]
[global::System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible")]
public class StateChangedArgs : EventArgs
{
///
/// Curent state
///
/// 6
/// It will be removed in API10
[global::System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1051:Do not declare visible instance fields")]
[Obsolete("Deprecated in API8; Will be removed in API10")]
public ControlStates CurrentState;
}
}
}