blob: ddcaa11e98045a46456d2d62a38792b99ba5941d [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 'carousel.dart';
import 'material.dart';
import 'theme.dart';
// Examples can assume:
// late BuildContext context;
/// Defines default property values for descendant [CarouselView] widgets.
///
/// Descendant widgets obtain the current [CarouselViewThemeData] object using
/// [CarouselViewTheme.of]. Instances of [CarouselViewThemeData] can be
/// customized with [CarouselViewThemeData.copyWith].
///
/// Typically a [CarouselViewThemeData] is specified as part of the overall [Theme]
/// with [ThemeData.carouselViewTheme].
///
/// All [CarouselViewThemeData] properties are `null` by default. When null, the [CarouselView]
/// will provide its own defaults.
///
/// See also:
///
/// * [CarouselViewTheme], an [InheritedWidget] that propagates the theme to its descendants.
/// * [ThemeData], which describes the overall theme information for the application.
@immutable
class CarouselViewThemeData with Diagnosticable {
/// Creates a theme that can be used for [ThemeData.carouselViewTheme].
const CarouselViewThemeData({
this.elevation,
this.backgroundColor,
this.overlayColor,
this.shape,
this.padding,
this.itemClipBehavior,
});
/// The amount of space to surround each carousel item with.
///
/// Overrides the default value for [CarouselView.padding].
final EdgeInsets? padding;
/// The background color for each carousel item.
///
/// Overrides the default value for [CarouselView.backgroundColor].
final Color? backgroundColor;
/// The z-coordinate of each carousel item.
///
/// This controls the size of the shadow below the carousel.
///
/// Overrides the default value for [CarouselView.elevation].
final double? elevation;
/// The shape of the carousel item's [Material].
///
/// Overrides the default value for [CarouselView.shape].
final OutlinedBorder? shape;
/// The clip behavior for each carousel item.
///
/// The item content will be clipped (or not) according to this option.
/// Refer to the [Clip] enum for more details on the different clip options.
///
/// Overrides the default value for [CarouselView.itemClipBehavior].
final Clip? itemClipBehavior;
/// The highlight color to indicate the carousel items are in pressed, hovered
/// or focused states.
///
/// Overrides the default value for [CarouselView.overlayColor].
final WidgetStateProperty<Color?>? overlayColor;
/// Creates a copy of this object with the given fields replaced with the
/// new values.
CarouselViewThemeData copyWith({
Color? backgroundColor,
double? elevation,
OutlinedBorder? shape,
WidgetStateProperty<Color?>? overlayColor,
EdgeInsets? padding,
Clip? itemClipBehavior,
}) {
return CarouselViewThemeData(
backgroundColor: backgroundColor ?? this.backgroundColor,
elevation: elevation ?? this.elevation,
shape: shape ?? this.shape,
overlayColor: overlayColor ?? this.overlayColor,
padding: padding ?? this.padding,
itemClipBehavior: itemClipBehavior ?? this.itemClipBehavior,
);
}
/// Linearly interpolate between two carousel themes.
///
/// {@macro dart.ui.shadow.lerp}
static CarouselViewThemeData lerp(CarouselViewThemeData? a, CarouselViewThemeData? b, double t) {
if (identical(a, b) && a != null) {
return a;
}
return CarouselViewThemeData(
backgroundColor: Color.lerp(a?.backgroundColor, b?.backgroundColor, t),
elevation: lerpDouble(a?.elevation, b?.elevation, t),
shape: ShapeBorder.lerp(a?.shape, b?.shape, t) as OutlinedBorder?,
overlayColor: WidgetStateProperty.lerp<Color?>(
a?.overlayColor,
b?.overlayColor,
t,
Color.lerp,
),
padding: EdgeInsets.lerp(a?.padding, b?.padding, t),
itemClipBehavior: t < 0.5 ? a?.itemClipBehavior : b?.itemClipBehavior,
);
}
@override
int get hashCode =>
Object.hash(backgroundColor, elevation, shape, overlayColor, padding, itemClipBehavior);
@override
bool operator ==(Object other) {
if (identical(this, other)) {
return true;
}
if (other.runtimeType != runtimeType) {
return false;
}
return other is CarouselViewThemeData &&
other.backgroundColor == backgroundColor &&
other.elevation == elevation &&
other.shape == shape &&
other.overlayColor == overlayColor &&
other.padding == padding &&
other.itemClipBehavior == itemClipBehavior;
}
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties.add(ColorProperty('backgroundColor', backgroundColor, defaultValue: null));
properties.add(DoubleProperty('elevation', elevation, defaultValue: null));
properties.add(DiagnosticsProperty<OutlinedBorder>('shape', shape, defaultValue: null));
properties.add(
DiagnosticsProperty<WidgetStateProperty<Color?>>(
'overlayColor',
overlayColor,
defaultValue: null,
),
);
properties.add(DiagnosticsProperty<EdgeInsets>('padding', padding, defaultValue: null));
properties.add(EnumProperty<Clip>('itemClipBehavior', itemClipBehavior, defaultValue: null));
}
}
/// Applies a carousel theme to descendant [CarouselView] widgets.
///
/// Descendant widgets obtain the current theme's [CarouselViewThemeData] using
/// [CarouselViewTheme.of]. When a widget uses [CarouselViewTheme.of], it is automatically
/// rebuilt if the theme later changes.
///
/// A carousel theme can be specified as part of the overall Material theme using
/// [ThemeData.carouselViewTheme].
///
/// See also:
///
/// * [CarouselViewThemeData], which describes the actual configuration of a carousel
/// theme.
/// * [Theme], which controls the overall theme inheritance.
class CarouselViewTheme extends InheritedTheme {
/// Creates a carousel theme that configures all descendant [CarouselView] widgets.
const CarouselViewTheme({super.key, required this.data, required super.child});
/// The properties for descendant carousel widgets.
final CarouselViewThemeData data;
/// Returns the configuration [data] from the closest [CarouselViewTheme] ancestor.
///
/// If there is no ancestor, it returns [ThemeData.carouselViewTheme].
///
/// Typical usage is as follows:
///
/// ```dart
/// CarouselViewThemeData theme = CarouselViewTheme.of(context);
/// ```
static CarouselViewThemeData of(BuildContext context) {
final CarouselViewTheme? inheritedTheme = context
.dependOnInheritedWidgetOfExactType<CarouselViewTheme>();
return inheritedTheme?.data ?? Theme.of(context).carouselViewTheme;
}
/// Wraps the given [child] with a [CarouselViewTheme] containing the [data].
@override
Widget wrap(BuildContext context, Widget child) {
return CarouselViewTheme(data: data, child: child);
}
/// Returns true if the [data] fields of the two themes are different.
@override
bool updateShouldNotify(CarouselViewTheme oldWidget) => data != oldWidget.data;
}