您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
1953 行
82 KiB
1953 行
82 KiB
using uiwidgets;
|
|
using Unity.UIWidgets.animation;
|
|
using Unity.UIWidgets.foundation;
|
|
using Unity.UIWidgets.painting;
|
|
using Unity.UIWidgets.rendering;
|
|
using Unity.UIWidgets.ui;
|
|
using Unity.UIWidgets.widgets;
|
|
using UnityEngine;
|
|
using Canvas = Unity.UIWidgets.ui.Canvas;
|
|
using Color = Unity.UIWidgets.ui.Color;
|
|
using Rect = Unity.UIWidgets.ui.Rect;
|
|
using TextStyle = Unity.UIWidgets.painting.TextStyle;
|
|
|
|
namespace Unity.UIWidgets.material {
|
|
public class SliderTheme : InheritedTheme {
|
|
public SliderTheme(
|
|
Key key = null,
|
|
SliderThemeData data = null,
|
|
Widget child = null)
|
|
: base(key: key, child: child) {
|
|
D.assert(child != null);
|
|
D.assert(data != null);
|
|
this.data = data;
|
|
}
|
|
|
|
public readonly SliderThemeData data;
|
|
|
|
public static SliderThemeData of(BuildContext context) {
|
|
SliderTheme inheritedTheme = context.dependOnInheritedWidgetOfExactType<SliderTheme>();
|
|
return inheritedTheme != null ? inheritedTheme.data : Theme.of(context).sliderTheme;
|
|
}
|
|
|
|
public override Widget wrap(BuildContext context, Widget child) {
|
|
SliderTheme ancestorTheme = context.findAncestorWidgetOfExactType<SliderTheme>();
|
|
return ReferenceEquals(this, ancestorTheme) ? child : new SliderTheme(data: data, child: child);
|
|
}
|
|
|
|
public override bool updateShouldNotify(InheritedWidget oldWidget) {
|
|
SliderTheme _oldWidget = (SliderTheme) oldWidget;
|
|
return data != _oldWidget.data;
|
|
}
|
|
}
|
|
|
|
|
|
public enum ShowValueIndicator {
|
|
onlyForDiscrete,
|
|
onlyForContinuous,
|
|
always,
|
|
never
|
|
}
|
|
|
|
public enum Thumb {
|
|
start,
|
|
end
|
|
}
|
|
|
|
public class SliderThemeData : Diagnosticable {
|
|
public SliderThemeData(
|
|
float? trackHeight = null,
|
|
Color activeTrackColor = null,
|
|
Color inactiveTrackColor = null,
|
|
Color disabledActiveTrackColor = null,
|
|
Color disabledInactiveTrackColor = null,
|
|
Color activeTickMarkColor = null,
|
|
Color inactiveTickMarkColor = null,
|
|
Color disabledActiveTickMarkColor = null,
|
|
Color disabledInactiveTickMarkColor = null,
|
|
Color thumbColor = null,
|
|
Color overlappingShapeStrokeColor = null,
|
|
Color disabledThumbColor = null,
|
|
Color overlayColor = null,
|
|
Color valueIndicatorColor = null,
|
|
SliderComponentShape overlayShape = null,
|
|
SliderTickMarkShape tickMarkShape = null,
|
|
SliderComponentShape thumbShape = null,
|
|
SliderTrackShape trackShape = null,
|
|
SliderComponentShape valueIndicatorShape = null,
|
|
RangeSliderTickMarkShape rangeTickMarkShape = null,
|
|
RangeSliderThumbShape rangeThumbShape = null,
|
|
RangeSliderTrackShape rangeTrackShape = null,
|
|
RangeSliderValueIndicatorShape rangeValueIndicatorShape = null,
|
|
ShowValueIndicator? showValueIndicator = null,
|
|
TextStyle valueIndicatorTextStyle = null,
|
|
float? minThumbSeparation = null,
|
|
RangeThumbSelector thumbSelector = null
|
|
) {
|
|
this.trackHeight = trackHeight;
|
|
this.activeTrackColor = activeTrackColor;
|
|
this.inactiveTrackColor = inactiveTrackColor;
|
|
this.disabledActiveTrackColor = disabledActiveTrackColor;
|
|
this.disabledInactiveTrackColor = disabledInactiveTrackColor;
|
|
this.activeTickMarkColor = activeTickMarkColor;
|
|
this.inactiveTickMarkColor = inactiveTickMarkColor;
|
|
this.disabledActiveTickMarkColor = disabledActiveTickMarkColor;
|
|
this.disabledInactiveTickMarkColor = disabledInactiveTickMarkColor;
|
|
this.thumbColor = thumbColor;
|
|
this.overlappingShapeStrokeColor = overlappingShapeStrokeColor;
|
|
this.disabledThumbColor = disabledThumbColor;
|
|
this.overlayColor = overlayColor;
|
|
this.valueIndicatorColor = valueIndicatorColor;
|
|
this.overlayShape = overlayShape;
|
|
this.tickMarkShape = tickMarkShape;
|
|
this.thumbShape = thumbShape;
|
|
this.trackShape = trackShape;
|
|
this.valueIndicatorShape = valueIndicatorShape;
|
|
this.rangeTickMarkShape = rangeTickMarkShape;
|
|
this.rangeThumbShape = rangeThumbShape;
|
|
this.rangeTrackShape = rangeTrackShape;
|
|
this.rangeValueIndicatorShape = rangeValueIndicatorShape;
|
|
this.showValueIndicator = showValueIndicator;
|
|
this.valueIndicatorTextStyle = valueIndicatorTextStyle;
|
|
this.minThumbSeparation = minThumbSeparation;
|
|
this.thumbSelector = thumbSelector;
|
|
}
|
|
|
|
public static SliderThemeData fromPrimaryColors(
|
|
Color primaryColor = null,
|
|
Color primaryColorDark = null,
|
|
Color primaryColorLight = null,
|
|
TextStyle valueIndicatorTextStyle = null) {
|
|
D.assert(primaryColor != null);
|
|
D.assert(primaryColorDark != null);
|
|
D.assert(primaryColorLight != null);
|
|
D.assert(valueIndicatorTextStyle != null);
|
|
|
|
const int activeTrackAlpha = 0xff;
|
|
const int inactiveTrackAlpha = 0x3d; // 24% opacity
|
|
const int disabledActiveTrackAlpha = 0x52; // 32% opacity
|
|
const int disabledInactiveTrackAlpha = 0x1f; // 12% opacity
|
|
const int activeTickMarkAlpha = 0x8a; // 54% opacity
|
|
const int inactiveTickMarkAlpha = 0x8a; // 54% opacity
|
|
const int disabledActiveTickMarkAlpha = 0x1f; // 12% opacity
|
|
const int disabledInactiveTickMarkAlpha = 0x1f; // 12% opacity
|
|
const int thumbAlpha = 0xff;
|
|
const int disabledThumbAlpha = 0x52; // 32% opacity
|
|
const int overlayAlpha = 0x1f; // 12% opacity
|
|
const int valueIndicatorAlpha = 0xff;
|
|
|
|
return new SliderThemeData(
|
|
trackHeight: 2.0f,
|
|
activeTrackColor: primaryColor.withAlpha(activeTrackAlpha),
|
|
inactiveTrackColor: primaryColor.withAlpha(inactiveTrackAlpha),
|
|
disabledActiveTrackColor: primaryColorDark.withAlpha(disabledActiveTrackAlpha),
|
|
disabledInactiveTrackColor: primaryColorDark.withAlpha(disabledInactiveTrackAlpha),
|
|
activeTickMarkColor: primaryColorLight.withAlpha(activeTickMarkAlpha),
|
|
inactiveTickMarkColor: primaryColor.withAlpha(inactiveTickMarkAlpha),
|
|
disabledActiveTickMarkColor: primaryColorLight.withAlpha(disabledActiveTickMarkAlpha),
|
|
disabledInactiveTickMarkColor: primaryColorDark.withAlpha(disabledInactiveTickMarkAlpha),
|
|
thumbColor: primaryColor.withAlpha(thumbAlpha),
|
|
overlappingShapeStrokeColor: Colors.white,
|
|
disabledThumbColor: primaryColorDark.withAlpha(disabledThumbAlpha),
|
|
overlayColor: primaryColor.withAlpha(overlayAlpha),
|
|
valueIndicatorColor: primaryColor.withAlpha(valueIndicatorAlpha),
|
|
overlayShape: new RoundSliderOverlayShape(),
|
|
tickMarkShape: new RoundSliderTickMarkShape(),
|
|
thumbShape: new RoundSliderThumbShape(),
|
|
trackShape: new RoundedRectSliderTrackShape(),
|
|
valueIndicatorShape: new PaddleSliderValueIndicatorShape(),
|
|
rangeTickMarkShape: new RoundRangeSliderTickMarkShape(),
|
|
rangeThumbShape: new RoundRangeSliderThumbShape(),
|
|
rangeTrackShape: new RoundedRectRangeSliderTrackShape(),
|
|
rangeValueIndicatorShape: new PaddleRangeSliderValueIndicatorShape(),
|
|
valueIndicatorTextStyle: valueIndicatorTextStyle,
|
|
showValueIndicator: ShowValueIndicator.onlyForDiscrete
|
|
);
|
|
}
|
|
|
|
public readonly float? trackHeight;
|
|
|
|
public readonly Color activeTrackColor;
|
|
|
|
public readonly Color inactiveTrackColor;
|
|
|
|
public readonly Color disabledActiveTrackColor;
|
|
|
|
public readonly Color disabledInactiveTrackColor;
|
|
|
|
public readonly Color activeTickMarkColor;
|
|
|
|
public readonly Color inactiveTickMarkColor;
|
|
|
|
public readonly Color disabledActiveTickMarkColor;
|
|
|
|
public readonly Color disabledInactiveTickMarkColor;
|
|
|
|
public readonly Color thumbColor;
|
|
|
|
public readonly Color overlappingShapeStrokeColor;
|
|
|
|
public readonly Color disabledThumbColor;
|
|
|
|
public readonly Color overlayColor;
|
|
|
|
public readonly Color valueIndicatorColor;
|
|
|
|
public readonly SliderTickMarkShape tickMarkShape;
|
|
|
|
public readonly SliderComponentShape overlayShape;
|
|
|
|
public readonly SliderComponentShape thumbShape;
|
|
|
|
public readonly SliderTrackShape trackShape;
|
|
|
|
public readonly SliderComponentShape valueIndicatorShape;
|
|
|
|
public readonly RangeSliderTickMarkShape rangeTickMarkShape;
|
|
|
|
public readonly RangeSliderThumbShape rangeThumbShape;
|
|
|
|
public readonly RangeSliderTrackShape rangeTrackShape;
|
|
|
|
public readonly RangeSliderValueIndicatorShape rangeValueIndicatorShape;
|
|
|
|
public readonly ShowValueIndicator? showValueIndicator;
|
|
|
|
public readonly TextStyle valueIndicatorTextStyle;
|
|
|
|
public readonly float? minThumbSeparation;
|
|
|
|
public readonly RangeThumbSelector thumbSelector;
|
|
|
|
public SliderThemeData copyWith(
|
|
float? trackHeight = null,
|
|
Color activeTrackColor = null,
|
|
Color inactiveTrackColor = null,
|
|
Color disabledActiveTrackColor = null,
|
|
Color disabledInactiveTrackColor = null,
|
|
Color activeTickMarkColor = null,
|
|
Color inactiveTickMarkColor = null,
|
|
Color disabledActiveTickMarkColor = null,
|
|
Color disabledInactiveTickMarkColor = null,
|
|
Color thumbColor = null,
|
|
Color overlappingShapeStrokeColor = null,
|
|
Color disabledThumbColor = null,
|
|
Color overlayColor = null,
|
|
Color valueIndicatorColor = null,
|
|
SliderComponentShape overlayShape = null,
|
|
SliderTickMarkShape tickMarkShape = null,
|
|
SliderComponentShape thumbShape = null,
|
|
SliderTrackShape trackShape = null,
|
|
SliderComponentShape valueIndicatorShape = null,
|
|
RangeSliderTickMarkShape rangeTickMarkShape = null,
|
|
RangeSliderThumbShape rangeThumbShape = null,
|
|
RangeSliderTrackShape rangeTrackShape = null,
|
|
RangeSliderValueIndicatorShape rangeValueIndicatorShape = null,
|
|
ShowValueIndicator? showValueIndicator = null,
|
|
TextStyle valueIndicatorTextStyle = null,
|
|
float? minThumbSeparation = null,
|
|
RangeThumbSelector thumbSelector = null
|
|
) {
|
|
return new SliderThemeData(
|
|
trackHeight: trackHeight ?? this.trackHeight,
|
|
activeTrackColor: activeTrackColor ?? this.activeTrackColor,
|
|
inactiveTrackColor: inactiveTrackColor ?? this.inactiveTrackColor,
|
|
disabledActiveTrackColor: disabledActiveTrackColor ?? this.disabledActiveTrackColor,
|
|
disabledInactiveTrackColor: disabledInactiveTrackColor ?? this.disabledInactiveTrackColor,
|
|
activeTickMarkColor: activeTickMarkColor ?? this.activeTickMarkColor,
|
|
inactiveTickMarkColor: inactiveTickMarkColor ?? this.inactiveTickMarkColor,
|
|
disabledActiveTickMarkColor: disabledActiveTickMarkColor ?? this.disabledActiveTickMarkColor,
|
|
disabledInactiveTickMarkColor: disabledInactiveTickMarkColor ?? this.disabledInactiveTickMarkColor,
|
|
thumbColor: thumbColor ?? this.thumbColor,
|
|
overlappingShapeStrokeColor: overlappingShapeStrokeColor ?? this.overlappingShapeStrokeColor,
|
|
disabledThumbColor: disabledThumbColor ?? this.disabledThumbColor,
|
|
overlayColor: overlayColor ?? this.overlayColor,
|
|
valueIndicatorColor: valueIndicatorColor ?? this.valueIndicatorColor,
|
|
overlayShape: overlayShape ?? this.overlayShape,
|
|
tickMarkShape: tickMarkShape ?? this.tickMarkShape,
|
|
thumbShape: thumbShape ?? this.thumbShape,
|
|
trackShape: trackShape ?? this.trackShape,
|
|
valueIndicatorShape: valueIndicatorShape ?? this.valueIndicatorShape,
|
|
rangeTickMarkShape: rangeTickMarkShape ?? this.rangeTickMarkShape,
|
|
rangeThumbShape: rangeThumbShape ?? this.rangeThumbShape,
|
|
rangeTrackShape: rangeTrackShape ?? this.rangeTrackShape,
|
|
rangeValueIndicatorShape: rangeValueIndicatorShape ?? this.rangeValueIndicatorShape,
|
|
showValueIndicator: showValueIndicator ?? this.showValueIndicator,
|
|
valueIndicatorTextStyle: valueIndicatorTextStyle ?? this.valueIndicatorTextStyle,
|
|
minThumbSeparation: minThumbSeparation ?? this.minThumbSeparation,
|
|
thumbSelector: thumbSelector ?? this.thumbSelector
|
|
);
|
|
}
|
|
|
|
public static SliderThemeData lerp(SliderThemeData a, SliderThemeData b, float t) {
|
|
D.assert(a != null);
|
|
D.assert(b != null);
|
|
return new SliderThemeData(
|
|
trackHeight: MathUtils.lerpNullableFloat(a.trackHeight, b.trackHeight, t),
|
|
activeTrackColor: Color.lerp(a.activeTrackColor, b.activeTrackColor, t),
|
|
inactiveTrackColor: Color.lerp(a.inactiveTrackColor, b.inactiveTrackColor, t),
|
|
disabledActiveTrackColor: Color.lerp(a.disabledActiveTrackColor, b.disabledActiveTrackColor, t),
|
|
disabledInactiveTrackColor: Color.lerp(a.disabledInactiveTrackColor, b.disabledInactiveTrackColor, t),
|
|
activeTickMarkColor: Color.lerp(a.activeTickMarkColor, b.activeTickMarkColor, t),
|
|
inactiveTickMarkColor: Color.lerp(a.inactiveTickMarkColor, b.inactiveTickMarkColor, t),
|
|
disabledActiveTickMarkColor: Color.lerp(a.disabledActiveTickMarkColor, b.disabledActiveTickMarkColor,
|
|
t),
|
|
disabledInactiveTickMarkColor: Color.lerp(a.disabledInactiveTickMarkColor,
|
|
b.disabledInactiveTickMarkColor, t),
|
|
thumbColor: Color.lerp(a.thumbColor, b.thumbColor, t),
|
|
overlappingShapeStrokeColor: Color.lerp(a.overlappingShapeStrokeColor, b.overlappingShapeStrokeColor, t),
|
|
disabledThumbColor: Color.lerp(a.disabledThumbColor, b.disabledThumbColor, t),
|
|
overlayColor: Color.lerp(a.overlayColor, b.overlayColor, t),
|
|
valueIndicatorColor: Color.lerp(a.valueIndicatorColor, b.valueIndicatorColor, t),
|
|
overlayShape: t < 0.5 ? a.overlayShape : b.overlayShape,
|
|
tickMarkShape: t < 0.5 ? a.tickMarkShape : b.tickMarkShape,
|
|
thumbShape: t < 0.5 ? a.thumbShape : b.thumbShape,
|
|
trackShape: t < 0.5 ? a.trackShape : b.trackShape,
|
|
valueIndicatorShape: t < 0.5 ? a.valueIndicatorShape : b.valueIndicatorShape,
|
|
rangeTickMarkShape: t < 0.5 ? a.rangeTickMarkShape : b.rangeTickMarkShape,
|
|
rangeThumbShape: t < 0.5 ? a.rangeThumbShape : b.rangeThumbShape,
|
|
rangeTrackShape: t < 0.5 ? a.rangeTrackShape : b.rangeTrackShape,
|
|
rangeValueIndicatorShape: t < 0.5 ? a.rangeValueIndicatorShape : b.rangeValueIndicatorShape,
|
|
showValueIndicator: t < 0.5 ? a.showValueIndicator : b.showValueIndicator,
|
|
valueIndicatorTextStyle: TextStyle.lerp(a.valueIndicatorTextStyle, b.valueIndicatorTextStyle, t),
|
|
minThumbSeparation: MathUtils.lerpNullableFloat(a.minThumbSeparation, b.minThumbSeparation, t),
|
|
thumbSelector: t < 0.5 ? a.thumbSelector : b.thumbSelector
|
|
);
|
|
}
|
|
|
|
public bool Equals(SliderThemeData other) {
|
|
if (ReferenceEquals(null, other)) {
|
|
return false;
|
|
}
|
|
|
|
if (ReferenceEquals(this, other)) {
|
|
return true;
|
|
}
|
|
|
|
return Equals(other.trackHeight, trackHeight)
|
|
&& other.activeTrackColor == activeTrackColor
|
|
&& other.inactiveTrackColor == inactiveTrackColor
|
|
&& other.disabledActiveTrackColor == disabledActiveTrackColor
|
|
&& other.disabledInactiveTrackColor == disabledInactiveTrackColor
|
|
&& other.activeTickMarkColor == activeTickMarkColor
|
|
&& other.inactiveTickMarkColor == inactiveTickMarkColor
|
|
&& other.disabledActiveTickMarkColor == disabledActiveTickMarkColor
|
|
&& other.disabledInactiveTickMarkColor == disabledInactiveTickMarkColor
|
|
&& other.thumbColor == thumbColor
|
|
&& other.overlappingShapeStrokeColor == overlappingShapeStrokeColor
|
|
&& other.disabledThumbColor == disabledThumbColor
|
|
&& other.overlayColor == overlayColor
|
|
&& other.valueIndicatorColor == valueIndicatorColor
|
|
&& other.overlayShape == overlayShape
|
|
&& other.tickMarkShape == tickMarkShape
|
|
&& other.thumbShape == thumbShape
|
|
&& other.trackShape == trackShape
|
|
&& other.valueIndicatorShape == valueIndicatorShape
|
|
&& other.rangeTickMarkShape == rangeTickMarkShape
|
|
&& other.rangeThumbShape == rangeThumbShape
|
|
&& other.rangeTrackShape == rangeTrackShape
|
|
&& other.rangeValueIndicatorShape == rangeValueIndicatorShape
|
|
&& other.showValueIndicator == showValueIndicator
|
|
&& other.valueIndicatorTextStyle == valueIndicatorTextStyle
|
|
&& Equals(other.minThumbSeparation, minThumbSeparation)
|
|
&& other.thumbSelector == thumbSelector;
|
|
}
|
|
|
|
public override bool Equals(object obj) {
|
|
if (ReferenceEquals(null, obj)) {
|
|
return false;
|
|
}
|
|
|
|
if (ReferenceEquals(this, obj)) {
|
|
return true;
|
|
}
|
|
|
|
if (obj.GetType() != GetType()) {
|
|
return false;
|
|
}
|
|
|
|
return Equals((SliderThemeData) obj);
|
|
}
|
|
|
|
public static bool operator ==(SliderThemeData left, SliderThemeData right) {
|
|
return Equals(left, right);
|
|
}
|
|
|
|
public static bool operator !=(SliderThemeData left, SliderThemeData right) {
|
|
return !Equals(left, right);
|
|
}
|
|
|
|
int? _cachedHashCode = null;
|
|
|
|
public override int GetHashCode() {
|
|
if (_cachedHashCode != null) {
|
|
return _cachedHashCode.Value;
|
|
}
|
|
|
|
unchecked {
|
|
var hashCode = trackHeight?.GetHashCode() ?? 0;
|
|
hashCode = (hashCode * 397) ^ activeTrackColor?.GetHashCode() ?? 0;
|
|
hashCode = (hashCode * 397) ^ inactiveTrackColor?.GetHashCode() ?? 0;
|
|
hashCode = (hashCode * 397) ^ disabledActiveTrackColor?.GetHashCode() ?? 0;
|
|
hashCode = (hashCode * 397) ^ disabledInactiveTrackColor?.GetHashCode() ?? 0;
|
|
hashCode = (hashCode * 397) ^ activeTickMarkColor?.GetHashCode() ?? 0;
|
|
hashCode = (hashCode * 397) ^ inactiveTickMarkColor?.GetHashCode() ?? 0;
|
|
hashCode = (hashCode * 397) ^ disabledActiveTickMarkColor?.GetHashCode() ?? 0;
|
|
hashCode = (hashCode * 397) ^ disabledInactiveTickMarkColor?.GetHashCode() ?? 0;
|
|
hashCode = (hashCode * 397) ^ thumbColor?.GetHashCode() ?? 0;
|
|
hashCode = (hashCode * 397) ^ overlappingShapeStrokeColor?.GetHashCode() ?? 0;
|
|
hashCode = (hashCode * 397) ^ disabledThumbColor?.GetHashCode() ?? 0;
|
|
hashCode = (hashCode * 397) ^ overlayColor?.GetHashCode() ?? 0;
|
|
hashCode = (hashCode * 397) ^ valueIndicatorColor?.GetHashCode() ?? 0;
|
|
hashCode = (hashCode * 397) ^ overlayShape?.GetHashCode() ?? 0;
|
|
hashCode = (hashCode * 397) ^ tickMarkShape?.GetHashCode() ?? 0;
|
|
hashCode = (hashCode * 397) ^ thumbShape?.GetHashCode() ?? 0;
|
|
hashCode = (hashCode * 397) ^ trackShape?.GetHashCode() ?? 0;
|
|
hashCode = (hashCode * 397) ^ rangeTickMarkShape?.GetHashCode() ?? 0;
|
|
hashCode = (hashCode * 397) ^ rangeThumbShape?.GetHashCode() ?? 0;
|
|
hashCode = (hashCode * 397) ^ rangeTrackShape?.GetHashCode() ?? 0;
|
|
hashCode = (hashCode * 397) ^ rangeValueIndicatorShape?.GetHashCode() ?? 0;
|
|
hashCode = (hashCode * 397) ^ valueIndicatorShape?.GetHashCode() ?? 0;
|
|
hashCode = (hashCode * 397) ^ showValueIndicator?.GetHashCode() ?? 0;
|
|
hashCode = (hashCode * 397) ^ valueIndicatorTextStyle?.GetHashCode() ?? 0;
|
|
hashCode = (hashCode * 397) ^ minThumbSeparation?.GetHashCode() ?? 0;
|
|
hashCode = (hashCode * 397) ^ thumbSelector?.GetHashCode() ?? 0;
|
|
|
|
_cachedHashCode = hashCode;
|
|
return hashCode;
|
|
}
|
|
}
|
|
|
|
public override void debugFillProperties(DiagnosticPropertiesBuilder properties) {
|
|
base.debugFillProperties(properties);
|
|
ThemeData defaultTheme = ThemeData.fallback();
|
|
SliderThemeData defaultData = fromPrimaryColors(
|
|
primaryColor: defaultTheme.primaryColor,
|
|
primaryColorDark: defaultTheme.primaryColorDark,
|
|
primaryColorLight: defaultTheme.primaryColorLight,
|
|
valueIndicatorTextStyle: defaultTheme.accentTextTheme.body2
|
|
);
|
|
properties.add(new DiagnosticsProperty<Color>("activeTrackColor", activeTrackColor,
|
|
defaultValue: defaultData.activeTrackColor));
|
|
properties.add(new DiagnosticsProperty<Color>("activeTrackColor", activeTrackColor,
|
|
defaultValue: defaultData.activeTrackColor));
|
|
properties.add(new DiagnosticsProperty<Color>("inactiveTrackColor", inactiveTrackColor,
|
|
defaultValue: defaultData.inactiveTrackColor));
|
|
properties.add(new DiagnosticsProperty<Color>("disabledActiveTrackColor", disabledActiveTrackColor,
|
|
defaultValue: defaultData.disabledActiveTrackColor, level: DiagnosticLevel.debug));
|
|
properties.add(new DiagnosticsProperty<Color>("disabledInactiveTrackColor", disabledInactiveTrackColor,
|
|
defaultValue: defaultData.disabledInactiveTrackColor, level: DiagnosticLevel.debug));
|
|
properties.add(new DiagnosticsProperty<Color>("activeTickMarkColor", activeTickMarkColor,
|
|
defaultValue: defaultData.activeTickMarkColor, level: DiagnosticLevel.debug));
|
|
properties.add(new DiagnosticsProperty<Color>("inactiveTickMarkColor", inactiveTickMarkColor,
|
|
defaultValue: defaultData.inactiveTickMarkColor, level: DiagnosticLevel.debug));
|
|
properties.add(new DiagnosticsProperty<Color>("disabledActiveTickMarkColor",
|
|
disabledActiveTickMarkColor, defaultValue: defaultData.disabledActiveTickMarkColor,
|
|
level: DiagnosticLevel.debug));
|
|
properties.add(new DiagnosticsProperty<Color>("disabledInactiveTickMarkColor",
|
|
disabledInactiveTickMarkColor, defaultValue: defaultData.disabledInactiveTickMarkColor,
|
|
level: DiagnosticLevel.debug));
|
|
properties.add(new DiagnosticsProperty<Color>("thumbColor", thumbColor,
|
|
defaultValue: defaultData.thumbColor));
|
|
properties.add(new ColorProperty("overlappingShapeStrokeColor", overlappingShapeStrokeColor, defaultValue: defaultData.overlappingShapeStrokeColor));
|
|
|
|
properties.add(new DiagnosticsProperty<Color>("disabledThumbColor", disabledThumbColor,
|
|
defaultValue: defaultData.disabledThumbColor, level: DiagnosticLevel.debug));
|
|
properties.add(new DiagnosticsProperty<Color>("overlayColor", overlayColor,
|
|
defaultValue: defaultData.overlayColor, level: DiagnosticLevel.debug));
|
|
properties.add(new DiagnosticsProperty<Color>("valueIndicatorColor", valueIndicatorColor,
|
|
defaultValue: defaultData.valueIndicatorColor));
|
|
properties.add(new DiagnosticsProperty<SliderComponentShape>("overlayShape", overlayShape,
|
|
defaultValue: defaultData.overlayShape, level: DiagnosticLevel.debug));
|
|
properties.add(new DiagnosticsProperty<SliderTickMarkShape>("tickMarkShape", tickMarkShape,
|
|
defaultValue: defaultData.tickMarkShape, level: DiagnosticLevel.debug));
|
|
properties.add(new DiagnosticsProperty<SliderComponentShape>("thumbShape", thumbShape,
|
|
defaultValue: defaultData.thumbShape, level: DiagnosticLevel.debug));
|
|
properties.add(new DiagnosticsProperty<SliderTrackShape>("trackShape", trackShape,
|
|
defaultValue: defaultData.trackShape, level: DiagnosticLevel.debug));
|
|
properties.add(new DiagnosticsProperty<SliderComponentShape>("valueIndicatorShape",
|
|
valueIndicatorShape, defaultValue: defaultData.valueIndicatorShape, level: DiagnosticLevel.debug));
|
|
properties.add(new DiagnosticsProperty<RangeSliderTickMarkShape>("rangeTickMarkShape", rangeTickMarkShape, defaultValue: defaultData.rangeTickMarkShape));
|
|
properties.add(new DiagnosticsProperty<RangeSliderThumbShape>("rangeThumbShape", rangeThumbShape, defaultValue: defaultData.rangeThumbShape));
|
|
properties.add(new DiagnosticsProperty<RangeSliderTrackShape>("rangeTrackShape", rangeTrackShape, defaultValue: defaultData.rangeTrackShape));
|
|
properties.add(new DiagnosticsProperty<RangeSliderValueIndicatorShape>("rangeValueIndicatorShape", rangeValueIndicatorShape, defaultValue: defaultData.rangeValueIndicatorShape));
|
|
properties.add(new EnumProperty<ShowValueIndicator>("showValueIndicator", showValueIndicator.Value,
|
|
defaultValue: defaultData.showValueIndicator));
|
|
properties.add(new DiagnosticsProperty<TextStyle>("valueIndicatorTextStyle", valueIndicatorTextStyle,
|
|
defaultValue: defaultData.valueIndicatorTextStyle));
|
|
properties.add(new FloatProperty("minThumbSeparation", minThumbSeparation, defaultValue: defaultData.minThumbSeparation));
|
|
properties.add(new DiagnosticsProperty<RangeThumbSelector>("thumbSelector", thumbSelector, defaultValue: defaultData.thumbSelector));
|
|
}
|
|
}
|
|
|
|
public abstract class SliderComponentShape {
|
|
public SliderComponentShape() {
|
|
}
|
|
|
|
public abstract Size getPreferredSize(
|
|
bool isEnabled,
|
|
bool isDiscrete,
|
|
TextPainter textPainter = null);
|
|
|
|
public abstract void paint(
|
|
PaintingContext context,
|
|
Offset center,
|
|
Animation<float> activationAnimation = null,
|
|
Animation<float> enableAnimation = null,
|
|
bool isDiscrete = false,
|
|
TextPainter labelPainter = null,
|
|
RenderBox parentBox = null,
|
|
SliderThemeData sliderTheme = null,
|
|
TextDirection? textDirection = null,
|
|
float? value = null);
|
|
|
|
public static readonly SliderComponentShape noThumb = new _EmptySliderComponentShape();
|
|
|
|
public static readonly SliderComponentShape noOverlay = new _EmptySliderComponentShape();
|
|
}
|
|
|
|
public abstract class SliderTickMarkShape {
|
|
public SliderTickMarkShape() {
|
|
}
|
|
|
|
public abstract Size getPreferredSize(
|
|
SliderThemeData sliderTheme = null,
|
|
bool isEnabled = false);
|
|
|
|
public abstract void paint(
|
|
PaintingContext context,
|
|
Offset offset,
|
|
RenderBox parentBox = null,
|
|
SliderThemeData sliderTheme = null,
|
|
Animation<float> enableAnimation = null,
|
|
Offset thumbCenter = null,
|
|
bool isEnabled = false,
|
|
TextDirection? textDirection = null);
|
|
|
|
public static readonly SliderTickMarkShape noTickMark = new _EmptySliderTickMarkShape();
|
|
}
|
|
|
|
public abstract class SliderTrackShape {
|
|
public SliderTrackShape() {
|
|
}
|
|
|
|
public abstract Rect getPreferredRect(
|
|
RenderBox parentBox = null,
|
|
Offset offset = null,
|
|
SliderThemeData sliderTheme = null,
|
|
bool isEnabled = false,
|
|
bool isDiscrete = false);
|
|
|
|
public abstract void paint(
|
|
PaintingContext context,
|
|
Offset offset,
|
|
RenderBox parentBox = null,
|
|
SliderThemeData sliderTheme = null,
|
|
Animation<float> enableAnimation = null,
|
|
Offset thumbCenter = null,
|
|
bool isEnabled = false,
|
|
bool isDiscrete = false,
|
|
TextDirection? textDirection = null
|
|
);
|
|
}
|
|
|
|
public abstract class RangeSliderThumbShape {
|
|
public RangeSliderThumbShape() {
|
|
}
|
|
|
|
public abstract Size getPreferredSize(bool isEnabled, bool isDiscrete);
|
|
|
|
public abstract void paint(
|
|
PaintingContext context,
|
|
Offset center,
|
|
Animation<float> activationAnimation = null,
|
|
Animation<float> enableAnimation = null,
|
|
bool isDiscrete = false,
|
|
bool isEnabled = false,
|
|
bool? isOnTop = null,
|
|
TextDirection? textDirection = null,
|
|
SliderThemeData sliderTheme = null,
|
|
Thumb? thumb = null
|
|
);
|
|
}
|
|
|
|
public abstract class RangeSliderValueIndicatorShape {
|
|
public RangeSliderValueIndicatorShape() {
|
|
}
|
|
|
|
public abstract Size getPreferredSize(bool isEnabled, bool isDiscrete, TextPainter labelPainter = null);
|
|
|
|
public virtual float getHorizontalShift(
|
|
RenderBox parentBox = null,
|
|
Offset center = null,
|
|
TextPainter labelPainter = null,
|
|
Animation<float> activationAnimation = null
|
|
) {
|
|
return 0;
|
|
}
|
|
|
|
public abstract void paint(
|
|
PaintingContext context,
|
|
Offset center,
|
|
Animation<float> activationAnimation = null,
|
|
Animation<float> enableAnimation = null,
|
|
bool isDiscrete = false,
|
|
bool? isOnTop = null,
|
|
TextPainter labelPainter = null,
|
|
RenderBox parentBox = null,
|
|
SliderThemeData sliderTheme = null,
|
|
TextDirection? textDirection = null,
|
|
float? value = null,
|
|
Thumb? thumb = null
|
|
);
|
|
}
|
|
|
|
public abstract class RangeSliderTickMarkShape {
|
|
public RangeSliderTickMarkShape() {
|
|
}
|
|
|
|
public abstract Size getPreferredSize(
|
|
SliderThemeData sliderTheme = null,
|
|
bool isEnabled = false
|
|
);
|
|
|
|
public abstract void paint(
|
|
PaintingContext context,
|
|
Offset center,
|
|
RenderBox parentBox = null,
|
|
SliderThemeData sliderTheme = null,
|
|
Animation<float> enableAnimation = null,
|
|
Offset startThumbCenter = null,
|
|
Offset endThumbCenter = null,
|
|
bool isEnabled = false,
|
|
TextDirection? textDirection = null
|
|
);
|
|
}
|
|
|
|
public abstract class RangeSliderTrackShape {
|
|
public RangeSliderTrackShape() {
|
|
}
|
|
|
|
public abstract Rect getPreferredRect(
|
|
RenderBox parentBox = null,
|
|
Offset offset = null,
|
|
SliderThemeData sliderTheme = null,
|
|
bool isEnabled = false,
|
|
bool isDiscrete = false
|
|
);
|
|
|
|
public abstract void paint(
|
|
PaintingContext context,
|
|
Offset offset,
|
|
RenderBox parentBox = null,
|
|
SliderThemeData sliderTheme = null,
|
|
Animation<float> enableAnimation = null,
|
|
Offset startThumbCenter = null,
|
|
Offset endThumbCenter = null,
|
|
bool isEnabled = false,
|
|
bool isDiscrete = false,
|
|
TextDirection? textDirection = null
|
|
);
|
|
}
|
|
|
|
public class RectangularSliderTrackShape : SliderTrackShape {
|
|
public RectangularSliderTrackShape(
|
|
float disabledThumbGapWidth = 2.0f) {
|
|
this.disabledThumbGapWidth = disabledThumbGapWidth;
|
|
}
|
|
|
|
public readonly float disabledThumbGapWidth;
|
|
|
|
|
|
public override Rect getPreferredRect(
|
|
RenderBox parentBox = null,
|
|
Offset offset = null,
|
|
SliderThemeData sliderTheme = null,
|
|
bool isEnabled = false,
|
|
bool isDiscrete = false) {
|
|
offset = offset ?? Offset.zero;
|
|
|
|
D.assert(parentBox != null);
|
|
D.assert(sliderTheme != null);
|
|
float thumbWidth = sliderTheme.thumbShape.getPreferredSize(isEnabled, isDiscrete).width;
|
|
float overlayWidth = sliderTheme.overlayShape.getPreferredSize(isEnabled, isDiscrete).width;
|
|
float trackHeight = sliderTheme.trackHeight.Value;
|
|
D.assert(overlayWidth >= 0);
|
|
D.assert(trackHeight >= 0);
|
|
D.assert(parentBox.size.width >= overlayWidth);
|
|
D.assert(parentBox.size.height >= trackHeight);
|
|
|
|
float trackLeft = offset.dx + overlayWidth / 2;
|
|
float trackTop = offset.dy + (parentBox.size.height - trackHeight) / 2;
|
|
float trackWidth = parentBox.size.width - Mathf.Max(thumbWidth, overlayWidth);
|
|
return Rect.fromLTWH(trackLeft, trackTop, trackWidth, trackHeight);
|
|
}
|
|
|
|
public override void paint(
|
|
PaintingContext context,
|
|
Offset offset,
|
|
RenderBox parentBox = null,
|
|
SliderThemeData sliderTheme = null,
|
|
Animation<float> enableAnimation = null,
|
|
Offset thumbCenter = null,
|
|
bool isEnabled = false,
|
|
bool isDiscrete = false,
|
|
TextDirection? textDirection = null) {
|
|
D.assert(context != null);
|
|
D.assert(offset != null);
|
|
D.assert(parentBox != null);
|
|
D.assert(sliderTheme != null);
|
|
D.assert(sliderTheme.disabledActiveTrackColor != null);
|
|
D.assert(sliderTheme.disabledInactiveTrackColor != null);
|
|
D.assert(sliderTheme.activeTrackColor != null);
|
|
D.assert(sliderTheme.inactiveTrackColor != null);
|
|
D.assert(sliderTheme.thumbShape != null);
|
|
D.assert(enableAnimation != null);
|
|
D.assert(textDirection != null);
|
|
D.assert(thumbCenter != null);
|
|
|
|
if (sliderTheme.trackHeight == 0) {
|
|
return;
|
|
}
|
|
|
|
ColorTween activeTrackColorTween = new ColorTween(begin: sliderTheme.disabledActiveTrackColor,
|
|
end: sliderTheme.activeTrackColor);
|
|
ColorTween inactiveTrackColorTween = new ColorTween(begin: sliderTheme.disabledInactiveTrackColor,
|
|
end: sliderTheme.inactiveTrackColor);
|
|
Paint activePaint = new Paint {color = activeTrackColorTween.evaluate(enableAnimation)};
|
|
Paint inactivePaint = new Paint {color = inactiveTrackColorTween.evaluate(enableAnimation)};
|
|
Paint leftTrackPaint = null;
|
|
Paint rightTrackPaint = null;
|
|
switch (textDirection) {
|
|
case TextDirection.ltr:
|
|
leftTrackPaint = activePaint;
|
|
rightTrackPaint = inactivePaint;
|
|
break;
|
|
case TextDirection.rtl:
|
|
leftTrackPaint = inactivePaint;
|
|
rightTrackPaint = activePaint;
|
|
break;
|
|
}
|
|
|
|
Rect trackRect = getPreferredRect(
|
|
parentBox: parentBox,
|
|
offset: offset,
|
|
sliderTheme: sliderTheme,
|
|
isEnabled: isEnabled,
|
|
isDiscrete: isDiscrete
|
|
);
|
|
|
|
Size thumbSize = sliderTheme.thumbShape.getPreferredSize(isEnabled, isDiscrete);
|
|
Rect leftTrackSegment = Rect.fromLTRB(trackRect.left + trackRect.height / 2, trackRect.top,
|
|
thumbCenter.dx - thumbSize.width / 2, trackRect.bottom);
|
|
if (!leftTrackSegment.isEmpty) {
|
|
context.canvas.drawRect(leftTrackSegment, leftTrackPaint);
|
|
}
|
|
|
|
Rect rightTrackSegment = Rect.fromLTRB(thumbCenter.dx + thumbSize.width / 2, trackRect.top, trackRect.right,
|
|
trackRect.bottom);
|
|
if (!rightTrackSegment.isEmpty) {
|
|
context.canvas.drawRect(rightTrackSegment, rightTrackPaint);
|
|
}
|
|
}
|
|
}
|
|
|
|
public class RoundedRectSliderTrackShape : SliderTrackShape {
|
|
public RoundedRectSliderTrackShape() {
|
|
}
|
|
|
|
public override Rect getPreferredRect(
|
|
RenderBox parentBox = null,
|
|
Offset offset = null,
|
|
SliderThemeData sliderTheme = null,
|
|
bool isEnabled = false,
|
|
bool isDiscrete = false) {
|
|
offset = offset ?? Offset.zero;
|
|
|
|
D.assert(parentBox != null);
|
|
D.assert(sliderTheme != null);
|
|
float thumbWidth = sliderTheme.thumbShape.getPreferredSize(isEnabled, isDiscrete).width;
|
|
float overlayWidth = sliderTheme.overlayShape.getPreferredSize(isEnabled, isDiscrete).width;
|
|
float trackHeight = sliderTheme.trackHeight.Value;
|
|
D.assert(overlayWidth >= 0);
|
|
D.assert(trackHeight >= 0);
|
|
D.assert(parentBox.size.width >= overlayWidth);
|
|
D.assert(parentBox.size.height >= trackHeight);
|
|
|
|
float trackLeft = offset.dx + overlayWidth / 2;
|
|
float trackTop = offset.dy + (parentBox.size.height - trackHeight) / 2;
|
|
float trackWidth = parentBox.size.width - Mathf.Max(thumbWidth, overlayWidth);
|
|
return Rect.fromLTWH(trackLeft, trackTop, trackWidth, trackHeight);
|
|
}
|
|
|
|
public override void paint(
|
|
PaintingContext context,
|
|
Offset offset,
|
|
RenderBox parentBox = null,
|
|
SliderThemeData sliderTheme = null,
|
|
Animation<float> enableAnimation = null,
|
|
Offset thumbCenter = null,
|
|
bool isEnabled = false,
|
|
bool isDiscrete = false,
|
|
TextDirection? textDirection = null) {
|
|
D.assert(context != null);
|
|
D.assert(offset != null);
|
|
D.assert(parentBox != null);
|
|
D.assert(sliderTheme != null);
|
|
D.assert(sliderTheme.disabledActiveTrackColor != null);
|
|
D.assert(sliderTheme.disabledInactiveTrackColor != null);
|
|
D.assert(sliderTheme.activeTrackColor != null);
|
|
D.assert(sliderTheme.inactiveTrackColor != null);
|
|
D.assert(sliderTheme.thumbShape != null);
|
|
D.assert(enableAnimation != null);
|
|
D.assert(textDirection != null);
|
|
D.assert(thumbCenter != null);
|
|
|
|
if (sliderTheme.trackHeight <= 0) {
|
|
return;
|
|
}
|
|
|
|
ColorTween activeTrackColorTween = new ColorTween(begin: sliderTheme.disabledActiveTrackColor,
|
|
end: sliderTheme.activeTrackColor);
|
|
ColorTween inactiveTrackColorTween = new ColorTween(begin: sliderTheme.disabledInactiveTrackColor,
|
|
end: sliderTheme.inactiveTrackColor);
|
|
Paint activePaint = new Paint {color = activeTrackColorTween.evaluate(enableAnimation)};
|
|
Paint inactivePaint = new Paint {color = inactiveTrackColorTween.evaluate(enableAnimation)};
|
|
Paint leftTrackPaint = null;
|
|
Paint rightTrackPaint = null;
|
|
switch (textDirection) {
|
|
case TextDirection.ltr:
|
|
leftTrackPaint = activePaint;
|
|
rightTrackPaint = inactivePaint;
|
|
break;
|
|
case TextDirection.rtl:
|
|
leftTrackPaint = inactivePaint;
|
|
rightTrackPaint = activePaint;
|
|
break;
|
|
}
|
|
|
|
Rect trackRect = getPreferredRect(
|
|
parentBox: parentBox,
|
|
offset: offset,
|
|
sliderTheme: sliderTheme,
|
|
isEnabled: isEnabled,
|
|
isDiscrete: isDiscrete
|
|
);
|
|
|
|
Rect leftTrackArcRect = Rect.fromLTWH(trackRect.left, trackRect.top, trackRect.height, trackRect.height);
|
|
if (!leftTrackArcRect.isEmpty) {
|
|
context.canvas.drawArc(leftTrackArcRect, Mathf.PI / 2, Mathf.PI, false, leftTrackPaint);
|
|
}
|
|
|
|
Rect rightTrackArcRect = Rect.fromLTWH(trackRect.right - trackRect.height / 2, trackRect.top,
|
|
trackRect.height, trackRect.height);
|
|
if (!rightTrackArcRect.isEmpty) {
|
|
context.canvas.drawArc(rightTrackArcRect, -Mathf.PI / 2, Mathf.PI, false, rightTrackPaint);
|
|
}
|
|
|
|
Size thumbSize = sliderTheme.thumbShape.getPreferredSize(isEnabled, isDiscrete);
|
|
Rect leftTrackSegment = Rect.fromLTRB(trackRect.left + trackRect.height / 2, trackRect.top,
|
|
thumbCenter.dx - thumbSize.width / 2, trackRect.bottom);
|
|
if (!leftTrackSegment.isEmpty) {
|
|
context.canvas.drawRect(leftTrackSegment, leftTrackPaint);
|
|
}
|
|
|
|
Rect rightTrackSegment = Rect.fromLTRB(thumbCenter.dx + thumbSize.width / 2, trackRect.top, trackRect.right,
|
|
trackRect.bottom);
|
|
if (!rightTrackSegment.isEmpty) {
|
|
context.canvas.drawRect(rightTrackSegment, rightTrackPaint);
|
|
}
|
|
}
|
|
}
|
|
|
|
public class RectangularRangeSliderTrackShape : RangeSliderTrackShape {
|
|
public RectangularRangeSliderTrackShape() {
|
|
}
|
|
|
|
public override Rect getPreferredRect(
|
|
RenderBox parentBox = null,
|
|
Offset offset = null,
|
|
SliderThemeData sliderTheme = null,
|
|
bool isEnabled = false,
|
|
bool isDiscrete = false
|
|
) {
|
|
offset = offset ?? Offset.zero;
|
|
|
|
D.assert(parentBox != null);
|
|
D.assert(offset != null);
|
|
D.assert(sliderTheme != null);
|
|
D.assert(sliderTheme.overlayShape != null);
|
|
|
|
|
|
float overlayWidth = sliderTheme.overlayShape.getPreferredSize(isEnabled, isDiscrete).width;
|
|
float trackHeight = sliderTheme.trackHeight.Value;
|
|
|
|
D.assert(overlayWidth >= 0);
|
|
D.assert(trackHeight >= 0);
|
|
D.assert(parentBox.size.width >= overlayWidth);
|
|
D.assert(parentBox.size.height >= trackHeight);
|
|
|
|
float trackLeft = offset.dx + overlayWidth / 2;
|
|
float trackTop = offset.dy + (parentBox.size.height - trackHeight) / 2;
|
|
float trackWidth = parentBox.size.width - overlayWidth;
|
|
return Rect.fromLTWH(trackLeft, trackTop, trackWidth, trackHeight);
|
|
}
|
|
|
|
public override void paint(
|
|
PaintingContext context,
|
|
Offset offset,
|
|
RenderBox parentBox = null,
|
|
SliderThemeData sliderTheme = null,
|
|
Animation<float> enableAnimation = null,
|
|
Offset startThumbCenter = null,
|
|
Offset endThumbCenter = null,
|
|
bool isEnabled = false,
|
|
bool isDiscrete = false,
|
|
TextDirection? textDirection = null
|
|
) {
|
|
D.assert(context != null);
|
|
D.assert(offset != null);
|
|
D.assert(parentBox != null);
|
|
D.assert(sliderTheme != null);
|
|
D.assert(sliderTheme.disabledActiveTrackColor != null);
|
|
D.assert(sliderTheme.disabledInactiveTrackColor != null);
|
|
D.assert(sliderTheme.activeTrackColor != null);
|
|
D.assert(sliderTheme.inactiveTrackColor != null);
|
|
D.assert(sliderTheme.rangeThumbShape != null);
|
|
D.assert(enableAnimation != null);
|
|
D.assert(startThumbCenter != null);
|
|
D.assert(endThumbCenter != null);
|
|
D.assert(textDirection != null);
|
|
|
|
ColorTween activeTrackColorTween = new ColorTween(begin: sliderTheme.disabledActiveTrackColor,
|
|
end: sliderTheme.activeTrackColor);
|
|
ColorTween inactiveTrackColorTween = new ColorTween(begin: sliderTheme.disabledInactiveTrackColor,
|
|
end: sliderTheme.inactiveTrackColor);
|
|
Paint activePaint = new Paint {color = activeTrackColorTween.evaluate(enableAnimation)};
|
|
Paint inactivePaint = new Paint {color = inactiveTrackColorTween.evaluate(enableAnimation)};
|
|
|
|
Offset leftThumbOffset = null;
|
|
Offset rightThumbOffset = null;
|
|
switch (textDirection) {
|
|
case TextDirection.ltr:
|
|
leftThumbOffset = startThumbCenter;
|
|
rightThumbOffset = endThumbCenter;
|
|
break;
|
|
case TextDirection.rtl:
|
|
leftThumbOffset = endThumbCenter;
|
|
rightThumbOffset = startThumbCenter;
|
|
break;
|
|
}
|
|
|
|
Size thumbSize = sliderTheme.rangeThumbShape.getPreferredSize(isEnabled, isDiscrete);
|
|
float thumbRadius = thumbSize.width / 2;
|
|
|
|
Rect trackRect = getPreferredRect(
|
|
parentBox: parentBox,
|
|
offset: offset,
|
|
sliderTheme: sliderTheme,
|
|
isEnabled: isEnabled,
|
|
isDiscrete: isDiscrete
|
|
);
|
|
Rect leftTrackSegment = Rect.fromLTRB(trackRect.left, trackRect.top, leftThumbOffset.dx - thumbRadius,
|
|
trackRect.bottom);
|
|
if (!leftTrackSegment.isEmpty) {
|
|
context.canvas.drawRect(leftTrackSegment, inactivePaint);
|
|
}
|
|
|
|
Rect middleTrackSegment = Rect.fromLTRB(leftThumbOffset.dx + thumbRadius, trackRect.top,
|
|
rightThumbOffset.dx - thumbRadius, trackRect.bottom);
|
|
if (!middleTrackSegment.isEmpty) {
|
|
context.canvas.drawRect(middleTrackSegment, activePaint);
|
|
}
|
|
|
|
Rect rightTrackSegment = Rect.fromLTRB(rightThumbOffset.dx + thumbRadius, trackRect.top, trackRect.right,
|
|
trackRect.bottom);
|
|
if (!rightTrackSegment.isEmpty) {
|
|
context.canvas.drawRect(rightTrackSegment, inactivePaint);
|
|
}
|
|
}
|
|
}
|
|
|
|
public class RoundedRectRangeSliderTrackShape : RangeSliderTrackShape {
|
|
public override Rect getPreferredRect(
|
|
RenderBox parentBox = null,
|
|
Offset offset = null,
|
|
SliderThemeData sliderTheme = null,
|
|
bool isEnabled = false,
|
|
bool isDiscrete = false
|
|
) {
|
|
offset = offset ?? Offset.zero;
|
|
|
|
D.assert(parentBox != null);
|
|
D.assert(offset != null);
|
|
D.assert(sliderTheme != null);
|
|
D.assert(sliderTheme.overlayShape != null);
|
|
D.assert(sliderTheme.trackHeight != null);
|
|
|
|
float overlayWidth = sliderTheme.overlayShape.getPreferredSize(isEnabled, isDiscrete).width;
|
|
float trackHeight = sliderTheme.trackHeight.Value;
|
|
|
|
D.assert(overlayWidth >= 0);
|
|
D.assert(trackHeight >= 0);
|
|
D.assert(parentBox.size.width >= overlayWidth);
|
|
D.assert(parentBox.size.height >= trackHeight);
|
|
|
|
float trackLeft = offset.dx + overlayWidth / 2;
|
|
float trackTop = offset.dy + (parentBox.size.height - trackHeight) / 2;
|
|
float trackWidth = parentBox.size.width - overlayWidth;
|
|
return Rect.fromLTWH(trackLeft, trackTop, trackWidth, trackHeight);
|
|
}
|
|
|
|
public override void paint(
|
|
PaintingContext context,
|
|
Offset offset,
|
|
RenderBox parentBox = null,
|
|
SliderThemeData sliderTheme = null,
|
|
Animation<float> enableAnimation = null,
|
|
Offset startThumbCenter = null,
|
|
Offset endThumbCenter = null,
|
|
bool isEnabled = false,
|
|
bool isDiscrete = false,
|
|
TextDirection? textDirection = null
|
|
) {
|
|
D.assert(context != null);
|
|
D.assert(offset != null);
|
|
D.assert(parentBox != null);
|
|
D.assert(sliderTheme != null);
|
|
D.assert(sliderTheme.disabledActiveTrackColor != null);
|
|
D.assert(sliderTheme.disabledInactiveTrackColor != null);
|
|
D.assert(sliderTheme.activeTrackColor != null);
|
|
D.assert(sliderTheme.inactiveTrackColor != null);
|
|
D.assert(sliderTheme.rangeThumbShape != null);
|
|
D.assert(enableAnimation != null);
|
|
D.assert(startThumbCenter != null);
|
|
D.assert(endThumbCenter != null);
|
|
D.assert(textDirection != null);
|
|
|
|
ColorTween activeTrackColorTween = new ColorTween(begin: sliderTheme.disabledActiveTrackColor,
|
|
end: sliderTheme.activeTrackColor);
|
|
ColorTween inactiveTrackColorTween = new ColorTween(begin: sliderTheme.disabledInactiveTrackColor,
|
|
end: sliderTheme.inactiveTrackColor);
|
|
Paint activePaint = new Paint {color = activeTrackColorTween.evaluate(enableAnimation)};
|
|
Paint inactivePaint = new Paint {color = inactiveTrackColorTween.evaluate(enableAnimation)};
|
|
|
|
Offset leftThumbOffset = null;
|
|
Offset rightThumbOffset = null;
|
|
switch (textDirection) {
|
|
case TextDirection.ltr:
|
|
leftThumbOffset = startThumbCenter;
|
|
rightThumbOffset = endThumbCenter;
|
|
break;
|
|
case TextDirection.rtl:
|
|
leftThumbOffset = endThumbCenter;
|
|
rightThumbOffset = startThumbCenter;
|
|
break;
|
|
}
|
|
|
|
Size thumbSize = sliderTheme.rangeThumbShape.getPreferredSize(isEnabled, isDiscrete);
|
|
float thumbRadius = thumbSize.width / 2;
|
|
D.assert(thumbRadius > 0);
|
|
|
|
Rect trackRect = getPreferredRect(
|
|
parentBox: parentBox,
|
|
offset: offset,
|
|
sliderTheme: sliderTheme,
|
|
isEnabled: isEnabled,
|
|
isDiscrete: isDiscrete
|
|
);
|
|
|
|
float trackRadius = trackRect.height / 2;
|
|
|
|
Rect leftTrackArcRect = Rect.fromLTWH(trackRect.left, trackRect.top, trackRect.height, trackRect.height);
|
|
if (!leftTrackArcRect.isEmpty) {
|
|
context.canvas.drawArc(leftTrackArcRect, Mathf.PI / 2, Mathf.PI, false, inactivePaint);
|
|
}
|
|
|
|
Rect leftTrackSegment = Rect.fromLTRB(trackRect.left + trackRadius, trackRect.top,
|
|
leftThumbOffset.dx - thumbRadius, trackRect.bottom);
|
|
if (!leftTrackSegment.isEmpty) {
|
|
context.canvas.drawRect(leftTrackSegment, inactivePaint);
|
|
}
|
|
|
|
Rect middleTrackSegment = Rect.fromLTRB(leftThumbOffset.dx + thumbRadius, trackRect.top,
|
|
rightThumbOffset.dx - thumbRadius, trackRect.bottom);
|
|
if (!middleTrackSegment.isEmpty) {
|
|
context.canvas.drawRect(middleTrackSegment, activePaint);
|
|
}
|
|
|
|
Rect rightTrackSegment = Rect.fromLTRB(rightThumbOffset.dx + thumbRadius, trackRect.top,
|
|
trackRect.right - trackRadius, trackRect.bottom);
|
|
if (!rightTrackSegment.isEmpty) {
|
|
context.canvas.drawRect(rightTrackSegment, inactivePaint);
|
|
}
|
|
|
|
Rect rightTrackArcRect = Rect.fromLTWH(trackRect.right - trackRect.height, trackRect.top, trackRect.height,
|
|
trackRect.height);
|
|
if (!rightTrackArcRect.isEmpty) {
|
|
context.canvas.drawArc(rightTrackArcRect, -Mathf.PI / 2, Mathf.PI, false, inactivePaint);
|
|
}
|
|
}
|
|
}
|
|
|
|
public class RoundSliderTickMarkShape : SliderTickMarkShape {
|
|
public RoundSliderTickMarkShape(
|
|
float? tickMarkRadius = null) {
|
|
this.tickMarkRadius = tickMarkRadius;
|
|
}
|
|
|
|
public readonly float? tickMarkRadius;
|
|
|
|
|
|
public override Size getPreferredSize(
|
|
SliderThemeData sliderTheme = null,
|
|
bool isEnabled = false
|
|
) {
|
|
D.assert(sliderTheme != null);
|
|
D.assert(sliderTheme.trackHeight != null);
|
|
return Size.fromRadius(tickMarkRadius ?? sliderTheme.trackHeight.Value / 2f);
|
|
}
|
|
|
|
|
|
public override void paint(
|
|
PaintingContext context,
|
|
Offset center,
|
|
RenderBox parentBox = null,
|
|
SliderThemeData sliderTheme = null,
|
|
Animation<float> enableAnimation = null,
|
|
Offset thumbCenter = null,
|
|
bool isEnabled = false,
|
|
TextDirection? textDirection = null
|
|
) {
|
|
D.assert(context != null);
|
|
D.assert(center != null);
|
|
D.assert(parentBox != null);
|
|
D.assert(sliderTheme != null);
|
|
D.assert(sliderTheme.disabledActiveTickMarkColor != null);
|
|
D.assert(sliderTheme.disabledInactiveTickMarkColor != null);
|
|
D.assert(sliderTheme.activeTickMarkColor != null);
|
|
D.assert(sliderTheme.inactiveTickMarkColor != null);
|
|
D.assert(enableAnimation != null);
|
|
D.assert(textDirection != null);
|
|
D.assert(thumbCenter != null);
|
|
|
|
Color begin = null;
|
|
Color end = null;
|
|
switch (textDirection) {
|
|
case TextDirection.ltr:
|
|
bool isTickMarkRightOfThumb = center.dx > thumbCenter.dx;
|
|
begin = isTickMarkRightOfThumb
|
|
? sliderTheme.disabledInactiveTickMarkColor
|
|
: sliderTheme.disabledActiveTickMarkColor;
|
|
end = isTickMarkRightOfThumb ? sliderTheme.inactiveTickMarkColor : sliderTheme.activeTickMarkColor;
|
|
break;
|
|
case TextDirection.rtl:
|
|
bool isTickMarkLeftOfThumb = center.dx < thumbCenter.dx;
|
|
begin = isTickMarkLeftOfThumb
|
|
? sliderTheme.disabledInactiveTickMarkColor
|
|
: sliderTheme.disabledActiveTickMarkColor;
|
|
end = isTickMarkLeftOfThumb ? sliderTheme.inactiveTickMarkColor : sliderTheme.activeTickMarkColor;
|
|
break;
|
|
}
|
|
|
|
Paint paint = new Paint {color = new ColorTween(begin: begin, end: end).evaluate(enableAnimation)};
|
|
|
|
float tickMarkRadius = getPreferredSize(
|
|
isEnabled: isEnabled,
|
|
sliderTheme: sliderTheme
|
|
).width / 2f;
|
|
if (tickMarkRadius > 0) {
|
|
context.canvas.drawCircle(center, tickMarkRadius, paint);
|
|
}
|
|
}
|
|
}
|
|
|
|
class RoundRangeSliderTickMarkShape : RangeSliderTickMarkShape {
|
|
public RoundRangeSliderTickMarkShape(float? tickMarkRadius = null) {
|
|
this.tickMarkRadius = tickMarkRadius;
|
|
}
|
|
|
|
public readonly float? tickMarkRadius;
|
|
|
|
public override Size getPreferredSize(
|
|
SliderThemeData sliderTheme = null,
|
|
bool isEnabled = false
|
|
) {
|
|
D.assert(sliderTheme != null);
|
|
D.assert(sliderTheme.trackHeight != null);
|
|
|
|
return Size.fromRadius(tickMarkRadius ?? sliderTheme.trackHeight.Value / 2f);
|
|
}
|
|
|
|
public override void paint(
|
|
PaintingContext context,
|
|
Offset center,
|
|
RenderBox parentBox = null,
|
|
SliderThemeData sliderTheme = null,
|
|
Animation<float> enableAnimation = null,
|
|
Offset startThumbCenter = null,
|
|
Offset endThumbCenter = null,
|
|
bool isEnabled = false,
|
|
TextDirection? textDirection = null
|
|
) {
|
|
D.assert(context != null);
|
|
D.assert(center != null);
|
|
D.assert(parentBox != null);
|
|
D.assert(sliderTheme != null);
|
|
D.assert(sliderTheme.disabledActiveTickMarkColor != null);
|
|
D.assert(sliderTheme.disabledInactiveTickMarkColor != null);
|
|
D.assert(sliderTheme.activeTickMarkColor != null);
|
|
D.assert(sliderTheme.inactiveTickMarkColor != null);
|
|
D.assert(enableAnimation != null);
|
|
D.assert(startThumbCenter != null);
|
|
D.assert(endThumbCenter != null);
|
|
D.assert(textDirection != null);
|
|
|
|
bool isBetweenThumbs = false;
|
|
switch (textDirection) {
|
|
case TextDirection.ltr:
|
|
isBetweenThumbs = startThumbCenter.dx < center.dx && center.dx < endThumbCenter.dx;
|
|
break;
|
|
case TextDirection.rtl:
|
|
isBetweenThumbs = endThumbCenter.dx < center.dx && center.dx < startThumbCenter.dx;
|
|
break;
|
|
}
|
|
|
|
Color begin = isBetweenThumbs
|
|
? sliderTheme.disabledActiveTickMarkColor
|
|
: sliderTheme.disabledInactiveTickMarkColor;
|
|
Color end = isBetweenThumbs ? sliderTheme.activeTickMarkColor : sliderTheme.inactiveTickMarkColor;
|
|
Paint paint = new Paint {color = new ColorTween(begin: begin, end: end).evaluate(enableAnimation)};
|
|
|
|
float tickMarkRadius = getPreferredSize(
|
|
isEnabled: isEnabled,
|
|
sliderTheme: sliderTheme
|
|
).width / 2;
|
|
if (tickMarkRadius > 0) {
|
|
context.canvas.drawCircle(center, tickMarkRadius, paint);
|
|
}
|
|
}
|
|
}
|
|
|
|
class _EmptySliderTickMarkShape : SliderTickMarkShape {
|
|
public override Size getPreferredSize(
|
|
SliderThemeData sliderTheme = null,
|
|
bool isEnabled = false) {
|
|
return Size.zero;
|
|
}
|
|
|
|
public override void paint(
|
|
PaintingContext context,
|
|
Offset offset,
|
|
RenderBox parentBox = null,
|
|
SliderThemeData sliderTheme = null,
|
|
Animation<float> enableAnimation = null,
|
|
Offset thumbCenter = null,
|
|
bool isEnabled = false,
|
|
TextDirection? textDirection = null) {
|
|
}
|
|
}
|
|
|
|
class _EmptySliderComponentShape : SliderComponentShape {
|
|
public override Size getPreferredSize(
|
|
bool isEnabled = false,
|
|
bool isDiscrete = false,
|
|
TextPainter textPainter = null) {
|
|
return Size.zero;
|
|
}
|
|
|
|
public override void paint(
|
|
PaintingContext context,
|
|
Offset center,
|
|
Animation<float> activationAnimation = null,
|
|
Animation<float> enableAnimation = null,
|
|
bool isDiscrete = false,
|
|
TextPainter labelPainter = null,
|
|
RenderBox parentBox = null,
|
|
SliderThemeData sliderTheme = null,
|
|
TextDirection? textDirection = null,
|
|
float? value = null) {
|
|
}
|
|
}
|
|
|
|
public class RoundSliderThumbShape : SliderComponentShape {
|
|
public RoundSliderThumbShape(
|
|
float enabledThumbRadius = 10.0f,
|
|
float? disabledThumbRadius = null
|
|
) {
|
|
this.enabledThumbRadius = enabledThumbRadius;
|
|
this.disabledThumbRadius = disabledThumbRadius;
|
|
}
|
|
|
|
public readonly float enabledThumbRadius;
|
|
|
|
public readonly float? disabledThumbRadius;
|
|
|
|
float _disabledThumbRadius {
|
|
get { return disabledThumbRadius ?? enabledThumbRadius; }
|
|
}
|
|
|
|
|
|
public override Size getPreferredSize(bool isEnabled, bool isDiscrete, TextPainter textPainter = null) {
|
|
return Size.fromRadius(isEnabled == true ? enabledThumbRadius : _disabledThumbRadius);
|
|
}
|
|
|
|
|
|
public override void paint(
|
|
PaintingContext context,
|
|
Offset center,
|
|
Animation<float> activationAnimation = null,
|
|
Animation<float> enableAnimation = null,
|
|
bool isDiscrete = false,
|
|
TextPainter labelPainter = null,
|
|
RenderBox parentBox = null,
|
|
SliderThemeData sliderTheme = null,
|
|
TextDirection? textDirection = null,
|
|
float? value = null
|
|
) {
|
|
D.assert(context != null);
|
|
D.assert(center != null);
|
|
D.assert(enableAnimation != null);
|
|
D.assert(sliderTheme != null);
|
|
D.assert(sliderTheme.disabledThumbColor != null);
|
|
D.assert(sliderTheme.thumbColor != null);
|
|
|
|
Canvas canvas = context.canvas;
|
|
Tween<float> radiusTween = new FloatTween(
|
|
begin: _disabledThumbRadius,
|
|
end: enabledThumbRadius
|
|
);
|
|
ColorTween colorTween = new ColorTween(
|
|
begin: sliderTheme.disabledThumbColor,
|
|
end: sliderTheme.thumbColor
|
|
);
|
|
canvas.drawCircle(
|
|
center,
|
|
radiusTween.evaluate(enableAnimation),
|
|
new Paint {color = colorTween.evaluate(enableAnimation)}
|
|
);
|
|
}
|
|
}
|
|
|
|
public class RoundRangeSliderThumbShape : RangeSliderThumbShape {
|
|
public RoundRangeSliderThumbShape(
|
|
float enabledThumbRadius = 10.0f,
|
|
float? disabledThumbRadius = null
|
|
) {
|
|
this.enabledThumbRadius = enabledThumbRadius;
|
|
this.disabledThumbRadius = disabledThumbRadius;
|
|
}
|
|
|
|
public readonly float enabledThumbRadius;
|
|
|
|
public readonly float? disabledThumbRadius;
|
|
|
|
float _disabledThumbRadius {
|
|
get { return disabledThumbRadius ?? enabledThumbRadius; }
|
|
}
|
|
|
|
public override Size getPreferredSize(bool isEnabled, bool isDiscrete) {
|
|
return Size.fromRadius(isEnabled == true ? enabledThumbRadius : _disabledThumbRadius);
|
|
}
|
|
|
|
public override void paint(
|
|
PaintingContext context,
|
|
Offset center,
|
|
Animation<float> activationAnimation = null,
|
|
Animation<float> enableAnimation = null,
|
|
bool isDiscrete = false,
|
|
bool isEnabled = false,
|
|
bool? isOnTop = null,
|
|
TextDirection? textDirection = null,
|
|
SliderThemeData sliderTheme = null,
|
|
Thumb? thumb = null
|
|
) {
|
|
D.assert(context != null);
|
|
D.assert(center != null);
|
|
D.assert(activationAnimation != null);
|
|
D.assert(sliderTheme != null);
|
|
D.assert(sliderTheme.showValueIndicator != null);
|
|
D.assert(sliderTheme.overlappingShapeStrokeColor != null);
|
|
D.assert(enableAnimation != null);
|
|
Canvas canvas = context.canvas;
|
|
Tween<float> radiusTween = new FloatTween(
|
|
begin: _disabledThumbRadius,
|
|
end: enabledThumbRadius
|
|
);
|
|
ColorTween colorTween = new ColorTween(
|
|
begin: sliderTheme.disabledThumbColor,
|
|
end: sliderTheme.thumbColor
|
|
);
|
|
float radius = radiusTween.evaluate(enableAnimation);
|
|
|
|
if (isOnTop == true) {
|
|
bool showValueIndicator = false;
|
|
switch (sliderTheme.showValueIndicator) {
|
|
case ShowValueIndicator.onlyForDiscrete:
|
|
showValueIndicator = isDiscrete;
|
|
break;
|
|
case ShowValueIndicator.onlyForContinuous:
|
|
showValueIndicator = !isDiscrete;
|
|
break;
|
|
case ShowValueIndicator.always:
|
|
showValueIndicator = true;
|
|
break;
|
|
case ShowValueIndicator.never:
|
|
showValueIndicator = false;
|
|
break;
|
|
}
|
|
|
|
if (!showValueIndicator || activationAnimation.value == 0) {
|
|
Paint strokePaint = new Paint {
|
|
color = sliderTheme.overlappingShapeStrokeColor,
|
|
strokeWidth = 1.0f,
|
|
style = PaintingStyle.stroke
|
|
};
|
|
canvas.drawCircle(center, radius, strokePaint);
|
|
}
|
|
}
|
|
|
|
canvas.drawCircle(
|
|
center,
|
|
radius,
|
|
new Paint {color = colorTween.evaluate(enableAnimation)}
|
|
);
|
|
}
|
|
}
|
|
|
|
public class RoundSliderOverlayShape : SliderComponentShape {
|
|
public RoundSliderOverlayShape(
|
|
float overlayRadius = 24.0f) {
|
|
this.overlayRadius = overlayRadius;
|
|
}
|
|
|
|
public readonly float overlayRadius;
|
|
|
|
public override Size getPreferredSize(bool isEnabled, bool isDiscrete, TextPainter textPainter = null) {
|
|
return Size.fromRadius(overlayRadius);
|
|
}
|
|
|
|
public override void paint(
|
|
PaintingContext context,
|
|
Offset center,
|
|
Animation<float> activationAnimation = null,
|
|
Animation<float> enableAnimation = null,
|
|
bool isDiscrete = false,
|
|
TextPainter labelPainter = null,
|
|
RenderBox parentBox = null,
|
|
SliderThemeData sliderTheme = null,
|
|
TextDirection? textDirection = null,
|
|
float? value = null
|
|
) {
|
|
Canvas canvas = context.canvas;
|
|
FloatTween radiusTween = new FloatTween(
|
|
begin: 0.0f,
|
|
end: overlayRadius
|
|
);
|
|
|
|
canvas.drawCircle(
|
|
center,
|
|
radiusTween.evaluate(activationAnimation),
|
|
new Paint {color = sliderTheme.overlayColor}
|
|
);
|
|
}
|
|
}
|
|
|
|
public class PaddleSliderValueIndicatorShape : SliderComponentShape {
|
|
public PaddleSliderValueIndicatorShape() {
|
|
}
|
|
|
|
static readonly _PaddleSliderTrackShapePathPainter _pathPainter = new _PaddleSliderTrackShapePathPainter();
|
|
|
|
public override Size getPreferredSize(
|
|
bool isEnabled,
|
|
bool isDiscrete,
|
|
TextPainter labelPainter = null) {
|
|
D.assert(labelPainter != null);
|
|
return _pathPainter.getPreferredSize(isEnabled, isDiscrete, labelPainter);
|
|
}
|
|
|
|
public override void paint(
|
|
PaintingContext context,
|
|
Offset center,
|
|
Animation<float> activationAnimation = null,
|
|
Animation<float> enableAnimation = null,
|
|
bool isDiscrete = false,
|
|
TextPainter labelPainter = null,
|
|
RenderBox parentBox = null,
|
|
SliderThemeData sliderTheme = null,
|
|
TextDirection? textDirection = null,
|
|
float? value = null
|
|
) {
|
|
D.assert(context != null);
|
|
D.assert(center != null);
|
|
D.assert(activationAnimation != null);
|
|
D.assert(enableAnimation != null);
|
|
D.assert(labelPainter != null);
|
|
D.assert(parentBox != null);
|
|
D.assert(sliderTheme != null);
|
|
|
|
ColorTween enableColor = new ColorTween(
|
|
begin: sliderTheme.disabledThumbColor,
|
|
end: sliderTheme.valueIndicatorColor
|
|
);
|
|
|
|
_pathPainter.drawValueIndicator(
|
|
parentBox,
|
|
context.canvas,
|
|
center,
|
|
new Paint {color = enableColor.evaluate(enableAnimation)},
|
|
activationAnimation.value,
|
|
labelPainter,
|
|
null
|
|
);
|
|
}
|
|
}
|
|
|
|
public class PaddleRangeSliderValueIndicatorShape : RangeSliderValueIndicatorShape {
|
|
public PaddleRangeSliderValueIndicatorShape() {
|
|
}
|
|
|
|
static readonly _PaddleSliderTrackShapePathPainter _pathPainter = new _PaddleSliderTrackShapePathPainter();
|
|
|
|
public override Size getPreferredSize(bool isEnabled, bool isDiscrete, TextPainter labelPainter = null) {
|
|
D.assert(labelPainter != null);
|
|
return _pathPainter.getPreferredSize(isEnabled, isDiscrete, labelPainter);
|
|
}
|
|
|
|
public override float getHorizontalShift(
|
|
RenderBox parentBox = null,
|
|
Offset center = null,
|
|
TextPainter labelPainter = null,
|
|
Animation<float> activationAnimation = null
|
|
) {
|
|
return _pathPainter.getHorizontalShift(
|
|
parentBox: parentBox,
|
|
center: center,
|
|
labelPainter: labelPainter,
|
|
scale: activationAnimation.value
|
|
);
|
|
}
|
|
|
|
public override void paint(
|
|
PaintingContext context,
|
|
Offset center,
|
|
Animation<float> activationAnimation = null,
|
|
Animation<float> enableAnimation = null,
|
|
bool isDiscrete = false,
|
|
bool? isOnTop = null,
|
|
TextPainter labelPainter = null,
|
|
RenderBox parentBox = null,
|
|
SliderThemeData sliderTheme = null,
|
|
TextDirection? textDirection = null,
|
|
float? value = null,
|
|
Thumb? thumb = null
|
|
) {
|
|
D.assert(context != null);
|
|
D.assert(center != null);
|
|
D.assert(activationAnimation != null);
|
|
D.assert(enableAnimation != null);
|
|
D.assert(labelPainter != null);
|
|
D.assert(parentBox != null);
|
|
D.assert(sliderTheme != null);
|
|
ColorTween enableColor = new ColorTween(
|
|
begin: sliderTheme.disabledThumbColor,
|
|
end: sliderTheme.valueIndicatorColor
|
|
);
|
|
|
|
_pathPainter.drawValueIndicator(
|
|
parentBox,
|
|
context.canvas,
|
|
center,
|
|
new Paint {color = enableColor.evaluate(enableAnimation)},
|
|
activationAnimation.value,
|
|
labelPainter,
|
|
isOnTop == true ? sliderTheme.overlappingShapeStrokeColor : null
|
|
);
|
|
}
|
|
}
|
|
|
|
class _PaddleSliderTrackShapePathPainter {
|
|
public _PaddleSliderTrackShapePathPainter() {
|
|
}
|
|
|
|
|
|
const float _topLobeRadius = 16.0f;
|
|
const float _labelTextDesignSize = 14.0f;
|
|
const float _bottomLobeRadius = 10.0f;
|
|
const float _labelPadding = 8.0f;
|
|
const float _distanceBetweenTopBottomCenters = 40.0f;
|
|
const float _middleNeckWidth = 2.0f;
|
|
const float _bottomNeckRadius = 4.5f;
|
|
const float _neckTriangleBase = _topNeckRadius + _middleNeckWidth / 2f;
|
|
const float _rightBottomNeckCenterX = _middleNeckWidth / 2f + _bottomNeckRadius;
|
|
const float _rightBottomNeckAngleStart = Mathf.PI;
|
|
static readonly Offset _topLobeCenter = new Offset(0.0f, -_distanceBetweenTopBottomCenters);
|
|
const float _topNeckRadius = 13.0f;
|
|
const float _neckTriangleHypotenuse = _topLobeRadius + _topNeckRadius;
|
|
const float _twoSeventyDegrees = 3.0f * Mathf.PI / 2.0f;
|
|
const float _ninetyDegrees = Mathf.PI / 2.0f;
|
|
const float _thirtyDegrees = Mathf.PI / 6.0f;
|
|
const float _preferredHeight = _distanceBetweenTopBottomCenters + _topLobeRadius + _bottomLobeRadius;
|
|
const bool _debuggingLabelLocation = false;
|
|
|
|
public Size getPreferredSize(
|
|
bool isEnabled,
|
|
bool isDiscrete,
|
|
TextPainter labelPainter
|
|
) {
|
|
D.assert(labelPainter != null);
|
|
float textScaleFactor = labelPainter.height / _labelTextDesignSize;
|
|
return new Size(labelPainter.width + 2 * _labelPadding * textScaleFactor,
|
|
_preferredHeight * textScaleFactor);
|
|
}
|
|
|
|
static void _addArc(Path path, Offset center, float radius, float startAngle, float endAngle) {
|
|
D.assert(center.isFinite);
|
|
Rect arcRect = Rect.fromCircle(center: center, radius: radius);
|
|
path.arcTo(arcRect, startAngle, endAngle - startAngle, false);
|
|
}
|
|
|
|
internal float getHorizontalShift(
|
|
RenderBox parentBox,
|
|
Offset center,
|
|
TextPainter labelPainter,
|
|
float scale
|
|
) {
|
|
float textScaleFactor = labelPainter.height / _labelTextDesignSize;
|
|
float inverseTextScale = textScaleFactor != 0 ? 1.0f / textScaleFactor : 0.0f;
|
|
float labelHalfWidth = labelPainter.width / 2.0f;
|
|
float halfWidthNeeded = Mathf.Max(
|
|
0.0f,
|
|
inverseTextScale * labelHalfWidth - (_topLobeRadius - _labelPadding)
|
|
);
|
|
float shift = _getIdealOffset(parentBox, halfWidthNeeded, textScaleFactor * scale, center);
|
|
return shift * textScaleFactor;
|
|
}
|
|
|
|
float _getIdealOffset(
|
|
RenderBox parentBox,
|
|
float halfWidthNeeded,
|
|
float scale,
|
|
Offset center
|
|
) {
|
|
const float edgeMargin = 4.0f;
|
|
Rect topLobeRect = Rect.fromLTWH(
|
|
-_topLobeRadius - halfWidthNeeded,
|
|
-_topLobeRadius - _distanceBetweenTopBottomCenters,
|
|
2.0f * (_topLobeRadius + halfWidthNeeded),
|
|
2.0f * _topLobeRadius
|
|
);
|
|
|
|
Offset topLeft = (topLobeRect.topLeft * scale) + center;
|
|
Offset bottomRight = (topLobeRect.bottomRight * scale) + center;
|
|
float shift = 0.0f;
|
|
|
|
float startGlobal = parentBox.localToGlobal(Offset.zero).dx;
|
|
if (topLeft.dx < startGlobal + edgeMargin) {
|
|
shift = startGlobal + edgeMargin - topLeft.dx;
|
|
}
|
|
|
|
float endGlobal = parentBox.localToGlobal(new Offset(parentBox.size.width, parentBox.size.height)).dx;
|
|
if (bottomRight.dx > endGlobal - edgeMargin) {
|
|
shift = endGlobal - edgeMargin - bottomRight.dx;
|
|
}
|
|
|
|
shift = scale == 0.0f ? 0.0f : shift / scale;
|
|
if (shift < 0.0f) {
|
|
shift = Mathf.Max(shift, -halfWidthNeeded);
|
|
}
|
|
else {
|
|
shift = Mathf.Min(shift, halfWidthNeeded);
|
|
}
|
|
|
|
return shift;
|
|
}
|
|
|
|
public void drawValueIndicator(
|
|
RenderBox parentBox,
|
|
Canvas canvas,
|
|
Offset center,
|
|
Paint paint,
|
|
float scale,
|
|
TextPainter labelPainter,
|
|
Color strokePaintColor
|
|
) {
|
|
if (scale == 0.0f) {
|
|
return;
|
|
}
|
|
|
|
float textScaleFactor = labelPainter.height / _labelTextDesignSize;
|
|
float overallScale = scale * textScaleFactor;
|
|
float inverseTextScale = textScaleFactor != 0 ? 1.0f / textScaleFactor : 0.0f;
|
|
float labelHalfWidth = labelPainter.width / 2.0f;
|
|
|
|
canvas.save();
|
|
canvas.translate(center.dx, center.dy);
|
|
canvas.scale(overallScale, overallScale);
|
|
|
|
float bottomNeckTriangleHypotenuse = _bottomNeckRadius + _bottomLobeRadius / overallScale;
|
|
float rightBottomNeckCenterY =
|
|
-Mathf.Sqrt(Mathf.Pow(bottomNeckTriangleHypotenuse, 2) - Mathf.Pow(_rightBottomNeckCenterX, 2));
|
|
float rightBottomNeckAngleEnd = Mathf.PI + Mathf.Atan(rightBottomNeckCenterY / _rightBottomNeckCenterX);
|
|
Path path = new Path();
|
|
path.moveTo(_middleNeckWidth / 2, rightBottomNeckCenterY);
|
|
_addArc(
|
|
path,
|
|
new Offset(_rightBottomNeckCenterX, rightBottomNeckCenterY),
|
|
_bottomNeckRadius,
|
|
_rightBottomNeckAngleStart,
|
|
rightBottomNeckAngleEnd
|
|
);
|
|
_addArc(
|
|
path,
|
|
Offset.zero,
|
|
_bottomLobeRadius / overallScale,
|
|
rightBottomNeckAngleEnd - Mathf.PI,
|
|
2 * Mathf.PI - rightBottomNeckAngleEnd
|
|
);
|
|
_addArc(
|
|
path,
|
|
new Offset(-_rightBottomNeckCenterX, rightBottomNeckCenterY),
|
|
_bottomNeckRadius,
|
|
Mathf.PI - rightBottomNeckAngleEnd,
|
|
0
|
|
);
|
|
|
|
float halfWidthNeeded = Mathf.Max(
|
|
0.0f,
|
|
inverseTextScale * labelHalfWidth - (_topLobeRadius - _labelPadding)
|
|
);
|
|
|
|
float shift = _getIdealOffset(parentBox, halfWidthNeeded, overallScale, center);
|
|
float leftWidthNeeded = halfWidthNeeded - shift;
|
|
float rightWidthNeeded = halfWidthNeeded + shift;
|
|
|
|
float leftAmount = Mathf.Max(0.0f, Mathf.Min(1.0f, leftWidthNeeded / _neckTriangleBase));
|
|
float rightAmount = Mathf.Max(0.0f, Mathf.Min(1.0f, rightWidthNeeded / _neckTriangleBase));
|
|
|
|
float leftTheta = (1.0f - leftAmount) * _thirtyDegrees;
|
|
float rightTheta = (1.0f - rightAmount) * _thirtyDegrees;
|
|
|
|
Offset leftTopNeckCenter = new Offset(
|
|
-_neckTriangleBase,
|
|
_topLobeCenter.dy + Mathf.Cos(leftTheta) * _neckTriangleHypotenuse
|
|
);
|
|
|
|
Offset neckRightCenter = new Offset(
|
|
_neckTriangleBase,
|
|
_topLobeCenter.dy + Mathf.Cos(rightTheta) * _neckTriangleHypotenuse
|
|
);
|
|
|
|
float leftNeckArcAngle = _ninetyDegrees - leftTheta;
|
|
float rightNeckArcAngle = Mathf.PI + _ninetyDegrees - rightTheta;
|
|
|
|
float neckStretchBaseline = Mathf.Max(0.0f,
|
|
rightBottomNeckCenterY - Mathf.Max(leftTopNeckCenter.dy, neckRightCenter.dy));
|
|
float t = Mathf.Pow(inverseTextScale, 3.0f);
|
|
float stretch = (neckStretchBaseline * t).clamp(0.0f, 10.0f * neckStretchBaseline);
|
|
Offset neckStretch = new Offset(0.0f, neckStretchBaseline - stretch);
|
|
|
|
D.assert(() => {
|
|
if (!_debuggingLabelLocation) {
|
|
return true;
|
|
}
|
|
|
|
Offset leftCenter = _topLobeCenter - new Offset(leftWidthNeeded, 0.0f) + neckStretch;
|
|
Offset rightCenter = _topLobeCenter + new Offset(rightWidthNeeded, 0.0f) + neckStretch;
|
|
Rect valueRect = Rect.fromLTRB(
|
|
leftCenter.dx - _topLobeRadius,
|
|
leftCenter.dy - _topLobeRadius,
|
|
rightCenter.dx + _topLobeRadius,
|
|
rightCenter.dy + _topLobeRadius
|
|
);
|
|
Paint outlinePaint = new Paint {
|
|
color = new Color(0xffff0000),
|
|
style = PaintingStyle.stroke,
|
|
strokeWidth = 1.0f
|
|
};
|
|
canvas.drawRect(valueRect, outlinePaint);
|
|
return true;
|
|
});
|
|
|
|
_addArc(
|
|
path,
|
|
leftTopNeckCenter + neckStretch,
|
|
_topNeckRadius,
|
|
0.0f,
|
|
-leftNeckArcAngle
|
|
);
|
|
_addArc(
|
|
path,
|
|
_topLobeCenter - new Offset(leftWidthNeeded, 0.0f) + neckStretch,
|
|
_topLobeRadius,
|
|
_ninetyDegrees + leftTheta,
|
|
_twoSeventyDegrees
|
|
);
|
|
_addArc(
|
|
path,
|
|
_topLobeCenter + new Offset(rightWidthNeeded, 0.0f) + neckStretch,
|
|
_topLobeRadius,
|
|
_twoSeventyDegrees,
|
|
_twoSeventyDegrees + Mathf.PI - rightTheta
|
|
);
|
|
_addArc(
|
|
path,
|
|
neckRightCenter + neckStretch,
|
|
_topNeckRadius,
|
|
rightNeckArcAngle,
|
|
Mathf.PI
|
|
);
|
|
|
|
if (strokePaintColor != null) {
|
|
Paint strokePaint = new Paint {
|
|
color = strokePaintColor,
|
|
strokeWidth = 1.0f,
|
|
style = PaintingStyle.stroke
|
|
};
|
|
|
|
canvas.drawPath(path, strokePaint);
|
|
}
|
|
|
|
canvas.drawPath(path, paint);
|
|
|
|
canvas.save();
|
|
canvas.translate(shift, -_distanceBetweenTopBottomCenters + neckStretch.dy);
|
|
canvas.scale(inverseTextScale, inverseTextScale);
|
|
labelPainter.paint(canvas, Offset.zero - new Offset(labelHalfWidth, labelPainter.height / 2.0f));
|
|
canvas.restore();
|
|
canvas.restore();
|
|
}
|
|
}
|
|
|
|
public delegate Thumb? RangeThumbSelector(TextDirection textDirection,
|
|
RangeValues values,
|
|
float tapValue,
|
|
Size thumbSize,
|
|
Size trackSize,
|
|
float dx
|
|
);
|
|
|
|
public class RangeValues {
|
|
public RangeValues(
|
|
float start,
|
|
float end
|
|
) {
|
|
this.start = start;
|
|
this.end = end;
|
|
}
|
|
|
|
public readonly float start;
|
|
|
|
public readonly float end;
|
|
|
|
public bool Equals(RangeValues obj) {
|
|
if (ReferenceEquals(obj, null)) {
|
|
return false;
|
|
}
|
|
|
|
if (ReferenceEquals(this, obj)) {
|
|
return true;
|
|
}
|
|
|
|
return start.Equals(obj.start)
|
|
&& end.Equals(obj.end);
|
|
}
|
|
|
|
public override bool Equals(object obj) {
|
|
if (ReferenceEquals(obj, null)) {
|
|
return false;
|
|
}
|
|
|
|
if (ReferenceEquals(this, obj)) {
|
|
return true;
|
|
}
|
|
|
|
if (obj.GetType() != GetType()) {
|
|
return false;
|
|
}
|
|
|
|
return Equals((RangeValues) obj);
|
|
}
|
|
|
|
public static bool operator ==(RangeValues left, RangeValues right) {
|
|
return Equals(left, right);
|
|
}
|
|
|
|
public static bool operator !=(RangeValues left, RangeValues right) {
|
|
return !Equals(left, right);
|
|
}
|
|
|
|
public override int GetHashCode() {
|
|
unchecked {
|
|
return (start.GetHashCode() * 397) ^ end.GetHashCode();
|
|
}
|
|
}
|
|
|
|
public override string ToString() {
|
|
return $"{GetType()}({start}, {end})";
|
|
}
|
|
}
|
|
|
|
|
|
public class RangeLabels {
|
|
public RangeLabels(
|
|
string start,
|
|
string end
|
|
) {
|
|
this.start = start;
|
|
this.end = end;
|
|
}
|
|
|
|
public readonly string start;
|
|
|
|
public readonly string end;
|
|
|
|
public bool Equals(RangeLabels obj) {
|
|
if (ReferenceEquals(obj, null)) {
|
|
return false;
|
|
}
|
|
|
|
if (ReferenceEquals(this, obj)) {
|
|
return true;
|
|
}
|
|
|
|
return start.Equals(obj.start)
|
|
&& end.Equals(obj.end);
|
|
}
|
|
|
|
public override bool Equals(object obj) {
|
|
if (ReferenceEquals(obj, null)) {
|
|
return false;
|
|
}
|
|
|
|
if (ReferenceEquals(this, obj)) {
|
|
return true;
|
|
}
|
|
|
|
if (obj.GetType() != GetType()) {
|
|
return false;
|
|
}
|
|
|
|
return Equals((RangeLabels) obj);
|
|
}
|
|
|
|
public static bool operator ==(RangeLabels left, RangeLabels right) {
|
|
return Equals(left, right);
|
|
}
|
|
|
|
public static bool operator !=(RangeLabels left, RangeLabels right) {
|
|
return !Equals(left, right);
|
|
}
|
|
|
|
public override int GetHashCode() {
|
|
unchecked {
|
|
return (start.GetHashCode() * 397) ^ end.GetHashCode();
|
|
}
|
|
}
|
|
|
|
public override string ToString() {
|
|
return $"{GetType()}({start}, {end})";
|
|
}
|
|
}
|
|
}
|