/*
* Copyright(c) 2022 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 System.ComponentModel;
using Tizen.NUI.Accessibility;
using Tizen.NUI.BaseComponents;
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, IAtspiValue
{
///
/// SpaceBetweenTrackAndIndicatorProperty
///
[EditorBrowsable(EditorBrowsableState.Never)]
public static readonly BindableProperty IndicatorProperty = BindableProperty.Create(nameof(Indicator), 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;
});
///
/// SpaceBetweenTrackAndIndicatorProperty
///
[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;
});
///
/// TrackThicknessProperty
///
[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;
});
///
/// IsValueShownProperty
///
[EditorBrowsable(EditorBrowsableState.Never)]
public static readonly BindableProperty IsValueShownProperty = BindableProperty.Create(nameof(IsValueShown), typeof(bool), typeof(Slider), true, propertyChanged: (bindable, oldValue, newValue) =>
{
var instance = (Slider)bindable;
if (newValue != null)
{
bool newValueShown = (bool)newValue;
if (instance.isValueShown != newValueShown)
{
instance.isValueShown = newValueShown;
}
}
},
defaultValueCreator: (bindable) =>
{
var instance = (Slider)bindable;
return instance.isValueShown;
});
///
/// ValueIndicatorTextProperty
///
[EditorBrowsable(EditorBrowsableState.Never)]
public static readonly BindableProperty ValueIndicatorTextProperty = BindableProperty.Create(nameof(ValueIndicatorText), typeof(string), typeof(Slider), string.Empty, propertyChanged: (bindable, oldValue, newValue) =>
{
var instance = (Slider)bindable;
if (newValue != null)
{
string newText = (string)newValue;
instance.valueIndicatorText.Text = newText;
}
},
defaultValueCreator: (bindable) =>
{
var instance = (Slider)bindable;
return instance.valueIndicatorText.Text;
});
///
/// Bindable property of CurrentValue
///
/// Hidden API, used for NUI XAML data binding
///
///
[EditorBrowsable(EditorBrowsableState.Never)]
public static readonly BindableProperty CurrentValueProperty = BindableProperty.Create(nameof(CurrentValue), typeof(float), typeof(Slider), 0.0f, BindingMode.TwoWay,
propertyChanged: (bindable, oldValue, newValue) =>
{
var instance = (Slider)bindable;
if (newValue != null)
{
float value = (float)newValue;
if (value < instance.minValue)
{
instance.curValue = instance.minValue;
}
else if (value > instance.maxValue)
{
instance.curValue = instance.maxValue;
}
else
{
instance.curValue = value;
}
instance.sliderValueChangedHandler?.Invoke(instance, new SliderValueChangedEventArgs
{
CurrentValue = instance.curValue
});
if (Accessibility.Accessibility.IsEnabled && instance.IsHighlighted)
{
instance.EmitAccessibilityEvent(AccessibilityPropertyChangeEvent.Value);
}
instance.UpdateValue();
}
},
defaultValueCreator: (bindable) =>
{
var instance = (Slider)bindable;
return instance.curValue;
}
);
static Slider() { }
///
/// The constructor of the Slider class.
///
/// 6
public Slider()
{
Focusable = true;
Initialize();
}
///
/// The constructor of the Slider class with specific style.
///
/// The string to initialize the Slider
/// 8
public Slider(string style) : base(style)
{
Focusable = true;
Initialize();
}
///
/// The constructor of the Slider class with specific style.
///
/// The style object to initialize the Slider
/// 8
public Slider(SliderStyle sliderStyle) : base(sliderStyle)
{
Focusable = true;
Initialize();
}
///
/// 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 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 currently applied style.
///
///
/// Modifying contents in style may cause unexpected behaviour.
///
/// 8
public SliderStyle Style => (SliderStyle)(ViewStyle as SliderStyle)?.Clone();
///
/// Gets or sets the direction type of slider.
///
/// 6
public DirectionType Direction
{
get
{
return (DirectionType)GetValue(DirectionProperty);
}
set
{
SetValue(DirectionProperty, value);
NotifyPropertyChanged();
}
}
private DirectionType InternalDirection
{
get
{
return direction;
}
set
{
if (direction == value)
{
return;
}
direction = value;
RelayoutBaseComponent(false);
UpdateBgTrackSize();
UpdateBgTrackPosition();
UpdateWarningTrackSize();
UpdateValue();
}
}
///
/// Gets or sets the indicator type, arrow or sign.
///
/// 6
public IndicatorType Indicator
{
get
{
return (IndicatorType)GetValue(IndicatorProperty);
}
set
{
SetValue(IndicatorProperty, value);
}
}
///
/// Gets or sets the minimum value of slider.
///
/// 6
public float MinValue
{
get
{
return (float)GetValue(MinValueProperty);
}
set
{
SetValue(MinValueProperty, value);
NotifyPropertyChanged();
}
}
private float InternalMinValue
{
get
{
return minValue;
}
set
{
minValue = value;
UpdateValue();
}
}
///
/// Gets or sets the maximum value of slider.
///
/// 6
public float MaxValue
{
get
{
return (float)GetValue(MaxValueProperty);
}
set
{
SetValue(MaxValueProperty, value);
NotifyPropertyChanged();
}
}
private float InternalMaxValue
{
get
{
return maxValue;
}
set
{
maxValue = value;
UpdateValue();
}
}
///
/// Gets or sets the current value of slider.
///
/// 6
public float CurrentValue
{
get
{
return (float)GetValue(CurrentValueProperty);
}
set
{
SetValue(CurrentValueProperty, value);
}
}
///
/// Gets or sets the size of the thumb image object.
///
/// 6
public Size ThumbSize
{
get
{
return GetValue(ThumbSizeProperty) as Size;
}
set
{
SetValue(ThumbSizeProperty, value);
NotifyPropertyChanged();
}
}
private Size InternalThumbSize
{
get
{
return thumbImage?.Size;
}
set
{
if (null != thumbImage)
{
thumbImage.Size = value;
thumbSize = value;
}
}
}
///
/// Gets or sets the resource url of the thumb image object.
///
/// Please use ThumbImageUrl property.
///
/// 6
public string ThumbImageURL
{
get
{
return GetValue(ThumbImageURLProperty) as string;
}
set
{
SetValue(ThumbImageURLProperty, value);
NotifyPropertyChanged();
}
}
private string InternalThumbImageURL
{
get
{
return thumbImage?.ResourceUrl;
}
set
{
if (null != thumbImage)
{
thumbImage.ResourceUrl = value;
thumbImageUrl = value;
}
}
}
///
/// Gets or sets the resource url selector of the thumb image object.
/// Getter returns copied selector value if exist, null otherwise.
///
/// Please use ThumbImageUrl property.
///
/// Thrown when setting null value.
/// 6
public StringSelector ThumbImageURLSelector
{
get
{
return GetValue(ThumbImageURLSelectorProperty) as StringSelector;
}
set
{
SetValue(ThumbImageURLSelectorProperty, value);
NotifyPropertyChanged();
}
}
private StringSelector InternalThumbImageURLSelector
{
get
{
Selector resourceUrlSelector = thumbImage?.ResourceUrlSelector;
if(resourceUrlSelector != null)
{
return new StringSelector(resourceUrlSelector);
}
return null;
}
set
{
if (value == null || thumbImage == null)
{
throw new NullReferenceException("Slider.ThumbImageURLSelector is null");
}
else
{
thumbImage.ResourceUrlSelector = value;
}
}
}
///
/// Gets or sets the Url of the thumb image.
///
/// Thrown when setting null value.
/// 9
public Selector ThumbImageUrl
{
get
{
return GetValue(ThumbImageUrlProperty) as Selector;
}
set
{
SetValue(ThumbImageUrlProperty, value);
NotifyPropertyChanged();
}
}
private Selector InternalThumbImageUrl
{
get
{
if (thumbImage == null)
{
return null;
}
else
{
return thumbImage.ResourceUrlSelector;
}
}
set
{
if (value == null || thumbImage == null)
{
throw new NullReferenceException("Slider.ThumbImageUrl is null");
}
else
{
thumbImage.ResourceUrlSelector = value;
}
}
}
///
/// Gets or sets the color of the thumb image object.
///
/// 8
public Color ThumbColor
{
get
{
return GetValue(ThumbColorProperty) as Color;
}
set
{
SetValue(ThumbColorProperty, value);
NotifyPropertyChanged();
}
}
private Color InternalThumbColor
{
get
{
return thumbColor;
}
set
{
if (null != thumbImage)
{
thumbColor = value;
if (thumbImage.ResourceUrl != null)
{
thumbImage.ResourceUrl = null;
}
using (PropertyMap map = new PropertyMap())
{
// To remove CA2000 warning messages, use `using` statement.
using (PropertyValue type = new PropertyValue((int)Visual.Type.Color))
{
map.Insert((int)Visual.Property.Type, type);
}
using (PropertyValue color = new PropertyValue(thumbColor))
{
map.Insert((int)ColorVisualProperty.MixColor, color);
}
using (PropertyValue radius = new PropertyValue(0.5f))
{
map.Insert((int)Visual.Property.CornerRadius, radius);
}
using (PropertyValue policyType = new PropertyValue((int)VisualTransformPolicyType.Relative))
{
map.Insert((int)Visual.Property.CornerRadiusPolicy, policyType);
}
thumbImage.Image = map;
}
}
}
}
///
/// Gets or sets the color of the background track image object.
///
/// 6
public Color BgTrackColor
{
get
{
return GetValue(BgTrackColorProperty) as Color;
}
set
{
SetValue(BgTrackColorProperty, value);
NotifyPropertyChanged();
}
}
private Color InternalBgTrackColor
{
get
{
return bgTrackImage?.BackgroundColor;
}
set
{
if (null != bgTrackImage)
{
bgTrackImage.BackgroundColor = value;
}
}
}
///
/// Gets or sets the color of the slided track image object.
///
/// 6
public Color SlidedTrackColor
{
get
{
return GetValue(SlidedTrackColorProperty) as Color;
}
set
{
SetValue(SlidedTrackColorProperty, value);
NotifyPropertyChanged();
}
}
private Color InternalSlidedTrackColor
{
get
{
return slidedTrackImage?.BackgroundColor;
}
set
{
if (null != slidedTrackImage)
{
slidedTrackImage.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 warning start value between minimum value and maximum value of slider.
///
/// This will be public opened later after ACR done. Before ACR, need to be hidden as inhouse API.
[EditorBrowsable(EditorBrowsableState.Never)]
public float WarningStartValue
{
get
{
return (float)GetValue(WarningStartValueProperty);
}
set
{
SetValue(WarningStartValueProperty, value);
NotifyPropertyChanged();
}
}
private float InternalWarningStartValue
{
get
{
return warningStartValue;
}
set
{
warningStartValue = value;
UpdateValue();
}
}
///
/// Gets or sets the color of the warning track image object.
///
/// This will be public opened later after ACR done. Before ACR, need to be hidden as inhouse API.
[EditorBrowsable(EditorBrowsableState.Never)]
public Color WarningTrackColor
{
get
{
return GetValue(WarningTrackColorProperty) as Color;
}
set
{
SetValue(WarningTrackColorProperty, value);
NotifyPropertyChanged();
}
}
private Color InternalWarningTrackColor
{
get
{
return warningTrackImage?.BackgroundColor;
}
set
{
if (null != warningTrackImage)
{
warningTrackImage.BackgroundColor = value;
}
}
}
///
/// Gets or sets the color of the warning slided track image object.
///
/// This will be public opened later after ACR done. Before ACR, need to be hidden as inhouse API.
[EditorBrowsable(EditorBrowsableState.Never)]
public Color WarningSlidedTrackColor
{
get
{
return GetValue(WarningSlidedTrackColorProperty) as Color;
}
set
{
SetValue(WarningSlidedTrackColorProperty, value);
NotifyPropertyChanged();
}
}
private Color InternalWarningSlidedTrackColor
{
get
{
return warningSlidedTrackImage?.BackgroundColor;
}
set
{
if (null != warningSlidedTrackImage)
{
warningSlidedTrackImage.BackgroundColor = value;
}
}
}
///
/// Gets or sets the Url of the warning thumb image.
///
/// Thrown when setting null value.
/// This will be public opened later after ACR done. Before ACR, need to be hidden as inhouse API.
[EditorBrowsable(EditorBrowsableState.Never)]
public Selector WarningThumbImageUrl
{
get
{
return GetValue(WarningThumbImageUrlProperty) as Selector;
}
set
{
SetValue(WarningThumbImageUrlProperty, value);
NotifyPropertyChanged();
}
}
private Selector InternalWarningThumbImageUrl
{
get
{
return warningThumbImageUrlSelector;
}
set
{
if (value == null || thumbImage == null)
{
throw new NullReferenceException("Slider.WarningThumbImageUrl is null");
}
else
{
warningThumbImageUrlSelector = value;
}
}
}
///
/// Gets or sets the color of the warning thumb image object.
///
/// This will be public opened later after ACR done. Before ACR, need to be hidden as inhouse API.
[EditorBrowsable(EditorBrowsableState.Never)]
public Color WarningThumbColor
{
get
{
return GetValue(WarningThumbColorProperty) as Color;
}
set
{
SetValue(WarningThumbColorProperty, value);
NotifyPropertyChanged();
}
}
private Color InternalWarningThumbColor
{
get
{
return warningThumbColor;
}
set
{
warningThumbColor = value;
}
}
///
/// Gets or sets the resource url of the low indicator image object.
///
/// 6
public string LowIndicatorImageURL
{
get
{
return GetValue(LowIndicatorImageURLProperty) as string;
}
set
{
SetValue(LowIndicatorImageURLProperty, value);
NotifyPropertyChanged();
}
}
private string InternalLowIndicatorImageURL
{
get
{
return lowIndicatorImage?.ResourceUrl;
}
set
{
if (null == lowIndicatorImage)
{
lowIndicatorImage = new ImageView
{
AccessibilityHidden = true,
};
}
lowIndicatorImage.ResourceUrl = value;
}
}
///
/// Gets or sets the resource url of the high indicator image object.
///
/// 6
public string HighIndicatorImageURL
{
get
{
return GetValue(HighIndicatorImageURLProperty) as string;
}
set
{
SetValue(HighIndicatorImageURLProperty, value);
NotifyPropertyChanged();
}
}
private string InternalHighIndicatorImageURL
{
get
{
return highIndicatorImage?.ResourceUrl;
}
set
{
if (null == highIndicatorImage)
{
highIndicatorImage = new ImageView
{
AccessibilityHidden = true,
};
}
highIndicatorImage.ResourceUrl = value;
}
}
///
/// Gets or sets the text content of the low indicator text object.
///
/// 6
public string LowIndicatorTextContent
{
get
{
return GetValue(LowIndicatorTextContentProperty) as string;
}
set
{
SetValue(LowIndicatorTextContentProperty, value);
NotifyPropertyChanged();
}
}
private string InternalLowIndicatorTextContent
{
get
{
return lowIndicatorText?.Text;
}
set
{
if (null != lowIndicatorText)
{
lowIndicatorText.Text = value;
}
}
}
///
/// Gets or sets the text content of the high indicator text object.
///
/// 6
public string HighIndicatorTextContent
{
get
{
return GetValue(HighIndicatorTextContentProperty) as string;
}
set
{
SetValue(HighIndicatorTextContentProperty, value);
NotifyPropertyChanged();
}
}
private string InternalHighIndicatorTextContent
{
get
{
return highIndicatorText?.Text;
}
set
{
if (null != highIndicatorText)
{
highIndicatorText.Text = value;
}
}
}
///
/// Gets or sets the size of the low indicator object(image or text).
///
/// 6
public Size LowIndicatorSize
{
get
{
return GetValue(LowIndicatorSizeProperty) as Size;
}
set
{
SetValue(LowIndicatorSizeProperty, value);
NotifyPropertyChanged();
}
}
private Size InternalLowIndicatorSize
{
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 GetValue(HighIndicatorSizeProperty) as Size;
}
set
{
SetValue(HighIndicatorSizeProperty, value);
NotifyPropertyChanged();
}
}
private Size InternalHighIndicatorSize
{
get
{
return highIndicatorSize;
}
set
{
highIndicatorSize = value;
UpdateHighIndicatorSize();
UpdateBgTrackSize();
UpdateBgTrackPosition();
UpdateValue();
}
}
///
/// 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);
}
}
///
/// Flag to decide whether the value indicator is shown
///
/// 9
public bool IsValueShown
{
get
{
return (bool)GetValue(IsValueShownProperty);
}
set
{
SetValue(IsValueShownProperty, value);
}
}
///
/// Gets or sets the text of value indicator.
///
/// 9
public string ValueIndicatorText
{
get
{
return (string)GetValue(ValueIndicatorTextProperty);
}
set
{
SetValue(ValueIndicatorTextProperty, value);
}
}
///
/// Gets or sets the size of the value indicator image object.
///
/// 9
public Size ValueIndicatorSize
{
get
{
return GetValue(ValueIndicatorSizeProperty) as Size;
}
set
{
SetValue(ValueIndicatorSizeProperty, value);
NotifyPropertyChanged();
}
}
private Size InternalValueIndicatorSize
{
get
{
return valueIndicatorImage?.Size;
}
set
{
if (null != valueIndicatorImage)
{
valueIndicatorImage.Size = value;
}
}
}
///
/// Gets or sets the resource url of the value indicator image object.
///
/// 9
public string ValueIndicatorUrl
{
get
{
return GetValue(ValueIndicatorUrlProperty) as string;
}
set
{
SetValue(ValueIndicatorUrlProperty, value);
NotifyPropertyChanged();
}
}
private string InternalValueIndicatorUrl
{
get
{
return valueIndicatorImage?.ResourceUrl;
}
set
{
if (null != valueIndicatorImage)
{
valueIndicatorImage.ResourceUrl = value;
}
}
}
///
/// Flag to decide whether the thumb snaps to the nearest discrete value when the user drags the thumb or taps.
///
/// The default value is false.
///
/// 9
public bool IsDiscrete
{
get
{
return (bool)GetValue(IsDiscreteProperty);
}
set
{
SetValue(IsDiscreteProperty, value);
NotifyPropertyChanged();
}
}
private bool InternalIsDiscrete { get; set; } = false;
///
/// Gets or sets the discrete value of slider.
///
///
/// The discrete value is evenly spaced between MinValue and MaxValue.
/// For example, MinValue is 0, MaxValue is 100, and DiscreteValue is 20.
/// Then, the thumb can only go to 0, 20, 40, 60, 80, and 100.
/// The default is 0.
///
/// 9
public float DiscreteValue
{
get
{
return (float)GetValue(DiscreteValueProperty);
}
set
{
SetValue(DiscreteValueProperty, value);
NotifyPropertyChanged();
}
}
private float InternalDiscreteValue
{
get
{
return discreteValue;
}
set
{
discreteValue = value;
UpdateValue();
}
}
private Extents spaceBetweenTrackAndIndicator
{
get
{
if (null == spaceTrackIndicator)
{
spaceTrackIndicator = new Extents((ushort start, ushort end, ushort top, ushort bottom) =>
{
Extents extents = new Extents(start, end, top, bottom);
spaceTrackIndicator.CopyFrom(extents);
}, 0, 0, 0, 0);
}
return spaceTrackIndicator;
}
}
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;
}
}
if (warningTrackImage != null)
{
if (direction == DirectionType.Horizontal)
{
warningTrackImage.SizeHeight = (float)trackThickness.Value;
}
else if (direction == DirectionType.Vertical)
{
warningTrackImage.SizeWidth = (float)trackThickness.Value;
}
}
if (warningSlidedTrackImage != null)
{
if (direction == DirectionType.Horizontal)
{
warningSlidedTrackImage.SizeHeight = (float)trackThickness.Value;
}
else if (direction == DirectionType.Vertical)
{
warningSlidedTrackImage.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();
}
private bool editMode = false;
private View recoverIndicator;
private View editModeIndicator;
///
[EditorBrowsable(EditorBrowsableState.Never)]
public override bool OnKeyboardEnter()
{
if (!IsEnabled)
{
return false;
}
if (editMode)
{
//set editMode false (toggle the mode)
editMode = false;
FocusManager.Instance.FocusIndicator = recoverIndicator;
}
else
{
//set editMode true (toggle the mode)
editMode = true;
if (editModeIndicator == null)
{
editModeIndicator = new View()
{
PositionUsesPivotPoint = true,
PivotPoint = new Position(0, 0, 0),
WidthResizePolicy = ResizePolicyType.FillToParent,
HeightResizePolicy = ResizePolicyType.FillToParent,
BorderlineColor = Color.Red,
BorderlineWidth = 6.0f,
BorderlineOffset = -1f,
BackgroundColor = new Color(0.2f, 0.2f, 0.2f, 0.4f),
AccessibilityHidden = true,
};
}
recoverIndicator = FocusManager.Instance.FocusIndicator;
FocusManager.Instance.FocusIndicator = editModeIndicator;
}
UpdateState(true, isPressed);
return true;
}
///
[EditorBrowsable(EditorBrowsableState.Never)]
public override bool OnKey(Key key)
{
if (!IsEnabled || null == key)
{
return false;
}
if (key.State == Key.StateType.Down)
{
float valueDiff;
if (IsDiscrete)
{
valueDiff = discreteValue;
}
else
{
// TODO : Currently we set the velocity of value as 1% hardly.
// Can we use AccessibilityGetMinimumIncrement?
valueDiff = (maxValue - minValue) * 0.01f;
}
if ((direction == DirectionType.Horizontal && key.KeyPressedName == "Left") ||
(direction == DirectionType.Vertical && key.KeyPressedName == "Down"))
{
if (editMode)
{
if (minValue < curValue)
{
isPressed = true;
CurrentValue -= valueDiff;
}
return true; // Consumed
}
}
else if ((direction == DirectionType.Horizontal && key.KeyPressedName == "Right") ||
(direction == DirectionType.Vertical && key.KeyPressedName == "Up"))
{
if (editMode)
{
if (maxValue > curValue)
{
isPressed = true;
CurrentValue += valueDiff;
}
return true; // Consumed
}
}
}
else if (key.State == Key.StateType.Up)
{
isPressed = false;
}
if (key.KeyPressedName == "Up" || key.KeyPressedName == "Right" || key.KeyPressedName == "Down" || key.KeyPressedName == "Left")
{
if (editMode)
{
return true;
}
}
return false;
}
///
/// 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?.LowIndicatorImage)
{
CreateLowIndicatorImage().ApplyStyle(sliderStyle.LowIndicatorImage);
}
if (null != sliderStyle?.HighIndicatorImage)
{
CreateHighIndicatorImage().ApplyStyle(sliderStyle.HighIndicatorImage);
}
if (null != sliderStyle?.Track)
{
CreateBackgroundTrack().ApplyStyle(sliderStyle.Track);
}
if (null != sliderStyle?.Thumb)
{
CreateThumb().ApplyStyle(sliderStyle.Thumb);
}
if (null != sliderStyle?.ValueIndicatorText)
{
CreateValueIndicatorText().ApplyStyle(sliderStyle.ValueIndicatorText);
}
if (null != sliderStyle?.ValueIndicatorImage)
{
CreateValueIndicatorImage().ApplyStyle(sliderStyle.ValueIndicatorImage);
}
if (null != sliderStyle?.WarningTrack)
{
CreateWarningTrack().ApplyStyle(sliderStyle.WarningTrack);
}
if (null != sliderStyle?.WarningProgress)
{
CreateWarningSlidedTrack().ApplyStyle(sliderStyle.WarningProgress);
}
EnableControlStatePropagation = true;
}
///
/// Gets minimum value for Accessibility.
///
[EditorBrowsable(EditorBrowsableState.Never)]
double IAtspiValue.AccessibilityGetMinimum()
{
return (double)MinValue;
}
///
/// Gets the current value for Accessibility.
///
[EditorBrowsable(EditorBrowsableState.Never)]
double IAtspiValue.AccessibilityGetCurrent()
{
return (double)CurrentValue;
}
///
/// Formatted current value.
///
[EditorBrowsable(EditorBrowsableState.Never)]
string IAtspiValue.AccessibilityGetValueText()
{
return $"{CurrentValue}";
}
///
/// Gets maximum value for Accessibility.
///
[EditorBrowsable(EditorBrowsableState.Never)]
double IAtspiValue.AccessibilityGetMaximum()
{
return (double)MaxValue;
}
///
/// Sets the current value using Accessibility.
///
[EditorBrowsable(EditorBrowsableState.Never)]
bool IAtspiValue.AccessibilitySetCurrent(double value)
{
var current = (float)value;
if (current >= MinValue && current <= MaxValue)
{
CurrentValue = current;
return true;
}
return false;
}
///
/// Gets minimum increment for Accessibility.
///
[EditorBrowsable(EditorBrowsableState.Never)]
double IAtspiValue.AccessibilityGetMinimumIncrement()
{
// FIXME
return (MaxValue - MinValue) / 20.0;
}
///
/// Initialize AT-SPI object.
///
[EditorBrowsable(EditorBrowsableState.Never)]
public override void OnInitialize()
{
base.OnInitialize();
AccessibilityRole = Role.Slider;
}
///
/// Get Slider style.
///
/// The default slider style.
/// 8
protected override ViewStyle CreateViewStyle()
{
return new SliderStyle();
}
///
/// Dispose Slider.
///
/// Dispose type.
/// 6
protected override void Dispose(DisposeTypes type)
{
if (disposed)
{
return;
}
if (type == DisposeTypes.Explicit)
{
if (null != panGestureDetector)
{
panGestureDetector.Detach(this);
panGestureDetector.Detected -= OnPanGestureDetected;
panGestureDetector.Dispose();
panGestureDetector = null;
}
if (null != thumbImage)
{
thumbImage.TouchEvent -= OnTouchEventForThumb;
Utility.Dispose(thumbImage);
}
Utility.Dispose(warningSlidedTrackImage);
Utility.Dispose(warningTrackImage);
Utility.Dispose(slidedTrackImage);
Utility.Dispose(bgTrackImage);
Utility.Dispose(lowIndicatorImage);
Utility.Dispose(highIndicatorImage);
Utility.Dispose(lowIndicatorText);
Utility.Dispose(highIndicatorText);
Utility.Dispose(valueIndicatorImage);
Utility.Dispose(valueIndicatorText);
this.TouchEvent -= OnTouchEventForTrack;
recoverIndicator = null;
if (editModeIndicator != null)
{
editModeIndicator.Dispose();
editModeIndicator = null;
}
}
base.Dispose(type);
}
///
/// Update Slider by style.
///
/// This will be public opened later after ACR done. Before ACR, need to be hidden as inhouse API.
[EditorBrowsable(EditorBrowsableState.Never)]
protected override void OnUpdate()
{
RelayoutBaseComponent();
UpdateComponentByIndicatorTypeChanged();
UpdateBgTrackSize();
UpdateBgTrackPosition();
UpdateWarningTrackSize();
UpdateLowIndicatorSize();
UpdateHighIndicatorSize();
UpdateValue();
}
///
[EditorBrowsable(EditorBrowsableState.Never)]
protected override void OnEnabled(bool enabled)
{
base.OnEnabled(enabled);
UpdateValue();
}
private void CalculateCurrentValueByGesture(float offset)
{
currentSlidedOffset += offset;
float resultValue = this.CurrentValue;
int bgTrackLength = GetBgTrackLength();
if (bgTrackLength != 0)
{
resultValue = ((currentSlidedOffset / (float)bgTrackLength) * (float)(maxValue - minValue)) + minValue;
}
if (IsDiscrete)
{
this.CurrentValue = CalculateDiscreteValue(resultValue);
}
else
{
this.CurrentValue = resultValue;
}
}
private bool OnTouchEventForTrack(object source, TouchEventArgs e)
{
if (!IsEnabled)
{
return false;
}
if (this.FocusableInTouch == false && editMode == false)
{
isFocused = false;
}
PointStateType state = e.Touch.GetState(0);
if (state == PointStateType.Down)
{
if (isValueShown)
{
valueIndicatorImage.Show();
}
UpdateState(isFocused, true);
sliderSlidingStartedHandler?.Invoke(this, new SliderSlidingStartedEventArgs
{
CurrentValue = curValue
});
Vector2 pos = e.Touch.GetLocalPosition(0);
CalculateCurrentValueByTouch(pos);
UpdateValue();
}
else if (state == PointStateType.Up)
{
if (isValueShown)
{
valueIndicatorImage.Hide();
}
UpdateState(isFocused, false);
sliderSlidingFinishedHandler?.Invoke(this, new SliderSlidingFinishedEventArgs
{
CurrentValue = curValue
});
}
return false;
}
private bool OnTouchEventForThumb(object source, TouchEventArgs e)
{
if (this.FocusableInTouch == false && editMode == false)
{
isFocused = false;
}
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 = GetBgTrackLength();
if (direction == DirectionType.Horizontal)
{
currentSlidedOffset = pos.X - GetBgTrackLowIndicatorOffset();
}
else if (direction == DirectionType.Vertical)
{
currentSlidedOffset = this.Size2D.Height - pos.Y - GetBgTrackLowIndicatorOffset();
}
if (bgTrackLength != 0)
{
float resultValue = ((currentSlidedOffset / (float)bgTrackLength) * (maxValue - minValue)) + minValue;
if (IsDiscrete)
{
this.CurrentValue = CalculateDiscreteValue(resultValue);
}
else
{
this.CurrentValue = resultValue;
}
}
}
private float CalculateDiscreteValue(float value)
{
return ((float)Math.Round((value / discreteValue)) * discreteValue);
}
private void UpdateState(bool isFocusedNew, bool isPressedNew)
{
if (isFocused == isFocusedNew && isPressed == isPressedNew)
{
return;
}
if (thumbImage == null || Style == null)
{
return;
}
isFocused = isFocusedNew;
isPressed = isPressedNew;
if (!IsEnabled) // Disabled
{
ControlState = ControlState.Disabled;
}
else if (!isFocused && !isPressed)
{
ControlState = ControlState.Normal;
}
else if (isPressed)
{
ControlState = ControlState.Pressed;
}
else if (!isPressed && isFocused)
{
ControlState = ControlState.Focused;
}
}
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();
}
}
}
}
}