blob: 57603a58716659350a756a1f0943751886c93e74 [file] [log] [blame]
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui' show lerpDouble;
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'theme.dart';
@immutable
/// Defines the visual properties of [ProgressIndicator] widgets.
///
/// Used by [ProgressIndicatorTheme] to control the visual properties of
/// progress indicators in a widget subtree.
///
/// To obtain this configuration, use [ProgressIndicatorTheme.of] to access
/// the closest ancestor [ProgressIndicatorTheme] of the current [BuildContext].
///
/// See also:
///
/// * [ProgressIndicatorTheme], an [InheritedWidget] that propagates the
/// theme down its subtree.
/// * [ThemeData.progressIndicatorTheme], which describes the defaults for
/// any progress indicators as part of the application's [ThemeData].
class ProgressIndicatorThemeData with Diagnosticable {
/// Creates the set of properties used to configure [ProgressIndicator] widgets.
const ProgressIndicatorThemeData({
this.color,
this.linearTrackColor,
this.linearMinHeight,
this.circularTrackColor,
this.refreshBackgroundColor,
});
/// The color of the [ProgressIndicator]'s indicator.
///
/// If null, then it will use [ColorScheme.primary] of the ambient
/// [ThemeData.colorScheme].
///
/// See also:
///
/// * [ProgressIndicator.color], which specifies the indicator color for a
/// specific progress indicator.
/// * [ProgressIndicator.valueColor], which specifies the indicator color
/// a an animated color.
final Color? color;
/// {@macro flutter.material.LinearProgressIndicator.trackColor}
final Color? linearTrackColor;
/// {@macro flutter.material.LinearProgressIndicator.minHeight}
final double? linearMinHeight;
/// {@macro flutter.material.CircularProgressIndicator.trackColor}
final Color? circularTrackColor;
/// {@macro flutter.material.RefreshProgressIndicator.backgroundColor}
final Color? refreshBackgroundColor;
/// Creates a copy of this object but with the given fields replaced with the
/// new values.
ProgressIndicatorThemeData copyWith({
Color? color,
Color? linearTrackColor,
double? linearMinHeight,
Color? circularTrackColor,
Color? refreshBackgroundColor,
}) {
return ProgressIndicatorThemeData(
color: color ?? this.color,
linearTrackColor : linearTrackColor ?? this.linearTrackColor,
linearMinHeight : linearMinHeight ?? this.linearMinHeight,
circularTrackColor : circularTrackColor ?? this.circularTrackColor,
refreshBackgroundColor : refreshBackgroundColor ?? this.refreshBackgroundColor,
);
}
/// Linearly interpolate between two progress indicator themes.
///
/// If both arguments are null, then null is returned.
static ProgressIndicatorThemeData? lerp(ProgressIndicatorThemeData? a, ProgressIndicatorThemeData? b, double t) {
if (a == null && b == null)
return null;
assert(t != null);
return ProgressIndicatorThemeData(
color: Color.lerp(a?.color, b?.color, t),
linearTrackColor : Color.lerp(a?.linearTrackColor, b?.linearTrackColor, t),
linearMinHeight : lerpDouble(a?.linearMinHeight, b?.linearMinHeight, t),
circularTrackColor : Color.lerp(a?.circularTrackColor, b?.circularTrackColor, t),
refreshBackgroundColor : Color.lerp(a?.refreshBackgroundColor, b?.refreshBackgroundColor, t),
);
}
@override
int get hashCode {
return hashValues(
color,
linearTrackColor,
linearMinHeight,
circularTrackColor,
refreshBackgroundColor,
);
}
@override
bool operator==(Object other) {
if (identical(this, other))
return true;
if (other.runtimeType != runtimeType)
return false;
return other is ProgressIndicatorThemeData
&& other.color == color
&& other.linearTrackColor == linearTrackColor
&& other.linearMinHeight == linearMinHeight
&& other.circularTrackColor == circularTrackColor
&& other.refreshBackgroundColor == refreshBackgroundColor;
}
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties.add(ColorProperty('color', color, defaultValue: null));
properties.add(ColorProperty('linearTrackColor', linearTrackColor, defaultValue: null));
properties.add(DoubleProperty('linearMinHeight', linearMinHeight, defaultValue: null));
properties.add(ColorProperty('circularTrackColor', circularTrackColor, defaultValue: null));
properties.add(ColorProperty('refreshBackgroundColor', refreshBackgroundColor, defaultValue: null));
}
}
/// An inherited widget that defines the configuration for
/// [ProgressIndicator]s in this widget's subtree.
///
/// Values specified here are used for [ProgressIndicator] properties that are not
/// given an explicit non-null value.
///
/// {@tool snippet}
///
/// Here is an example of a progress indicator theme that applies a red indicator
/// color.
///
/// ```dart
/// const ProgressIndicatorTheme(
/// data: ProgressIndicatorThemeData(
/// color: Colors.red,
/// ),
/// child: LinearProgressIndicator()
/// )
/// ```
/// {@end-tool}
class ProgressIndicatorTheme extends InheritedTheme {
/// Creates a theme that controls the configurations for [ProgressIndicator]
/// widgets.
const ProgressIndicatorTheme({
Key? key,
required this.data,
required Widget child,
}) : assert(data != null), super(key: key, child: child);
/// The properties for descendant [ProgressIndicator] widgets.
final ProgressIndicatorThemeData data;
/// Returns the [data] from the closest [ProgressIndicatorTheme] ancestor. If
/// there is no ancestor, it returns [ThemeData.progressIndicatorTheme].
///
/// Typical usage is as follows:
///
/// ```dart
/// ProgressIndicatorThemeData theme = ProgressIndicatorTheme.of(context);
/// ```
static ProgressIndicatorThemeData of(BuildContext context) {
final ProgressIndicatorTheme? progressIndicatorTheme = context.dependOnInheritedWidgetOfExactType<ProgressIndicatorTheme>();
return progressIndicatorTheme?.data ?? Theme.of(context).progressIndicatorTheme;
}
@override
Widget wrap(BuildContext context, Widget child) {
return ProgressIndicatorTheme(data: data, child: child);
}
@override
bool updateShouldNotify(ProgressIndicatorTheme oldWidget) => data != oldWidget.data;
}