import 'package:collection/collection.dart'; import 'package:flutter/widgets.dart'; import 'lottie_drawable.dart'; import 'lottie_property.dart'; import 'model/key_path.dart'; import 'value/lottie_frame_info.dart'; import 'value/lottie_relative_double_value_callback.dart'; import 'value/lottie_relative_integer_value_callback.dart'; import 'value/lottie_relative_point_value_callback.dart'; import 'value/lottie_value_callback.dart'; class ValueDelegate { final List keyPath; final T property; final T? value; final T Function(LottieFrameInfo)? callback; ValueDelegate._(this.keyPath, this.property, this.value, this.callback) : assert(value == null || callback == null, "Value and callback can't be both specified."); static ValueDelegate _offset( List keyPath, Offset property, Offset? value, Offset Function(LottieFrameInfo)? callback, Offset? relative) { if (relative != null) { assert(callback == null); callback = relativeOffsetValueCallback(relative); } return ValueDelegate._(keyPath, property, value, callback); } static ValueDelegate _double( List keyPath, double property, double? value, double Function(LottieFrameInfo)? callback, double? relative) { if (relative != null) { assert(callback == null); callback = relativeDoubleValueCallback(relative); } return ValueDelegate._(keyPath, property, value, callback); } static ValueDelegate _int(List keyPath, int property, int? value, int Function(LottieFrameInfo)? callback, int? relative) { if (relative != null) { assert(callback == null); callback = relativeIntegerValueCallback(relative); } return ValueDelegate._(keyPath, property, value, callback); } static ValueDelegate color(List keyPath, {Color? value, Color Function(LottieFrameInfo)? callback}) => ValueDelegate._(keyPath, LottieProperty.color, value, callback); static ValueDelegate strokeColor(List keyPath, {Color? value, Color Function(LottieFrameInfo)? callback}) => ValueDelegate._(keyPath, LottieProperty.strokeColor, value, callback); /// Opacity value are 0-100 to match after effects static ValueDelegate transformOpacity(List keyPath, {int? value, int Function(LottieFrameInfo)? callback, int? relative}) => _int(keyPath, LottieProperty.transformOpacity, value, callback, relative); /// Opacity value are 0-100 to match after effects static ValueDelegate opacity(List keyPath, {int? value, int Function(LottieFrameInfo)? callback, int? relative}) => _int(keyPath, LottieProperty.opacity, value, callback, relative); static ValueDelegate transformAnchorPoint( List keyPath, { Offset? value, Offset Function(LottieFrameInfo)? callback, Offset? relative, }) { return _offset(keyPath, LottieProperty.transformAnchorPoint, value, callback, relative); } static ValueDelegate transformPosition( List keyPath, { Offset? value, Offset Function(LottieFrameInfo)? callback, Offset? relative, }) => _offset( keyPath, LottieProperty.transformPosition, value, callback, relative); static ValueDelegate ellipseSize( List keyPath, { Offset? value, Offset Function(LottieFrameInfo)? callback, Offset? relative, }) => _offset(keyPath, LottieProperty.ellipseSize, value, callback, relative); static ValueDelegate rectangleSize( List keyPath, { Offset? value, Offset Function(LottieFrameInfo)? callback, Offset? relative, }) => _offset(keyPath, LottieProperty.rectangleSize, value, callback, relative); static ValueDelegate cornerRadius(List keyPath, {double? value, double Function(LottieFrameInfo)? callback, double? relative}) => _double(keyPath, LottieProperty.cornerRadius, value, callback, relative); static ValueDelegate position( List keyPath, { Offset? value, Offset Function(LottieFrameInfo)? callback, Offset? relative, }) => _offset(keyPath, LottieProperty.position, value, callback, relative); static ValueDelegate transformScale( List keyPath, { Offset? value, Offset Function(LottieFrameInfo)? callback, Offset? relative, }) => _offset( keyPath, LottieProperty.transformScale, value, callback, relative); /// In degrees static ValueDelegate transformRotation(List keyPath, {double? value, double Function(LottieFrameInfo)? callback, double? relative}) => _double( keyPath, LottieProperty.transformRotation, value, callback, relative); static ValueDelegate transformSkew(List keyPath, {double? value, double Function(LottieFrameInfo)? callback, double? relative}) => _double(keyPath, LottieProperty.transformSkew, value, callback, relative); static ValueDelegate transformSkewAngle(List keyPath, {double? value, double Function(LottieFrameInfo)? callback, double? relative}) => _double(keyPath, LottieProperty.transformSkewAngle, value, callback, relative); static ValueDelegate strokeWidth(List keyPath, {double? value, double Function(LottieFrameInfo)? callback, double? relative}) => _double(keyPath, LottieProperty.strokeWidth, value, callback, relative); static ValueDelegate textTracking(List keyPath, {double? value, double Function(LottieFrameInfo)? callback, double? relative}) => _double(keyPath, LottieProperty.textTracking, value, callback, relative); static ValueDelegate repeaterCopies(List keyPath, {double? value, double Function(LottieFrameInfo)? callback, double? relative}) => _double( keyPath, LottieProperty.repeaterCopies, value, callback, relative); static ValueDelegate repeaterOffset(List keyPath, {double? value, double Function(LottieFrameInfo)? callback, double? relative}) => _double( keyPath, LottieProperty.repeaterOffset, value, callback, relative); static ValueDelegate polystarPoints(List keyPath, {double? value, double Function(LottieFrameInfo)? callback, double? relative}) => _double( keyPath, LottieProperty.polystarPoints, value, callback, relative); /// In degrees static ValueDelegate polystarRotation(List keyPath, {double? value, double Function(LottieFrameInfo)? callback, double? relative}) => _double( keyPath, LottieProperty.polystarRotation, value, callback, relative); static ValueDelegate polystarInnerRadius(List keyPath, {double? value, double Function(LottieFrameInfo)? callback, double? relative}) => _double(keyPath, LottieProperty.polystarInnerRadius, value, callback, relative); static ValueDelegate polystarOuterRadius(List keyPath, {double? value, double Function(LottieFrameInfo)? callback, double? relative}) => _double(keyPath, LottieProperty.polystarOuterRadius, value, callback, relative); static ValueDelegate polystarInnerRoundedness(List keyPath, {double? value, double Function(LottieFrameInfo)? callback, double? relative}) => _double(keyPath, LottieProperty.polystarInnerRoundedness, value, callback, relative); static ValueDelegate polystarOuterRoundedness(List keyPath, {double? value, double Function(LottieFrameInfo)? callback, double? relative}) => _double(keyPath, LottieProperty.polystarOuterRoundedness, value, callback, relative); /// Opacity value are 0-100 to match after effects static ValueDelegate transformStartOpacity(List keyPath, {double? value, double Function(LottieFrameInfo)? callback, double? relative}) => _double(keyPath, LottieProperty.transformStartOpacity, value, callback, relative); /// Opacity value are 0-100 to match after effects static ValueDelegate transformEndOpacity(List keyPath, {double? value, double Function(LottieFrameInfo)? callback, double? relative}) => _double(keyPath, LottieProperty.transformEndOpacity, value, callback, relative); /// The time value in seconds static ValueDelegate timeRemap(List keyPath, {double? value, double Function(LottieFrameInfo)? callback, double? relative}) => _double(keyPath, LottieProperty.timeRemap, value, callback, relative); static ValueDelegate textSize(List keyPath, {double? value, double Function(LottieFrameInfo)? callback, double? relative}) => _double(keyPath, LottieProperty.textSize, value, callback, relative); static ValueDelegate colorFilter(List keyPath, {ColorFilter? value, ColorFilter Function(LottieFrameInfo)? callback}) => ValueDelegate._(keyPath, LottieProperty.colorFilter, value, callback); static ValueDelegate> gradientColor(List keyPath, {List? value, List Function(LottieFrameInfo>)? callback}) => ValueDelegate._(keyPath, LottieProperty.gradientColor, value, callback); ResolvedValueDelegate? _resolved; ResolvedValueDelegate? _resolve(List resolvedPaths) { _resolved = ResolvedValueDelegate(this, resolvedPaths); return _resolved; } bool isSameProperty(ValueDelegate other) { if (identical(this, other)) return true; return other is ValueDelegate && const ListEquality().equals(other.keyPath, keyPath) && other.property == property; } } ResolvedValueDelegate internalResolved(ValueDelegate valueDelegate) { return valueDelegate._resolved!; } ResolvedValueDelegate? internalResolve( ValueDelegate delegate, List resolvedPaths) { return delegate._resolve(resolvedPaths); } class ResolvedValueDelegate { final ValueDelegate valueDelegate; final List keyPaths; final LottieValueCallback valueCallback; ResolvedValueDelegate(this.valueDelegate, this.keyPaths) : valueCallback = LottieValueCallback(valueDelegate.value) ..callback = valueDelegate.callback; T get property => valueDelegate.property; void updateDelegate(ValueDelegate delegate) { valueCallback ..setValue(delegate.value) ..callback = delegate.callback; } void clear() { valueCallback ..setValue(null) ..callback = null; } /// Add a property callback for the specified {@link KeyPath}. This {@link KeyPath} can resolve /// to multiple contents. In that case, the callbacks's value will apply to all of them. ///

/// Internally, this will check if the {@link KeyPath} has already been resolved with /// {@link #resolveKeyPath(KeyPath)} and will resolve it if it hasn't. void addValueCallback(LottieDrawable drawable) { for (var keyPath in keyPaths) { keyPath.resolvedElement!.addValueCallback(property, valueCallback); } if (keyPaths.isNotEmpty) { drawable.invalidateSelf(); if (property == LottieProperty.timeRemap) { // Time remapping values are read in setProgress. In order for the new value // to apply, we have to re-set the progress with the current progress so that the // time remapping can be reapplied. drawable.setProgress(drawable.progress); } } } }