Greg Spencer a1e49be25b
Remove 'must be non-null' and 'must not be null' comments from material. (#134991)
## Description

This removes all of the comments that are of the form "so-and-so (must not be null|can ?not be null|must be non-null)" from the cases where those values are defines as non-nullable values.

This PR removes them from the material library.

This was done by hand, since it really didn't lend itself to scripting, so it needs to be more than just spot-checked, I think. I was careful to leave any comment that referred to parameters that were nullable, but I may have missed some.

In addition to being no longer relevant after null safety has been made the default, these comments were largely fragile, in that it was easy for them to get out of date, and not be accurate anymore anyhow.

This did create a number of constructor comments which basically say "Creates a [Foo].", but I don't really know how to avoid that in a large scale change, since there's not much you can really say in a lot of cases.  I think we might consider some leniency for constructors to the "Comment must be meaningful" style guidance (which we de facto have already, since there are a bunch of these).

## Related PRs
- https://github.com/flutter/flutter/pull/134984
- https://github.com/flutter/flutter/pull/134992
- https://github.com/flutter/flutter/pull/134993
- https://github.com/flutter/flutter/pull/134994

## Tests
 - Documentation only change.
2023-09-20 04:20:49 +00:00

246 lines
8.2 KiB
Dart

// 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 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'material_localizations.dart';
import 'theme_data.dart';
import 'typography.dart';
export 'theme_data.dart' show Brightness, ThemeData;
/// The duration over which theme changes animate by default.
const Duration kThemeAnimationDuration = Duration(milliseconds: 200);
/// Applies a theme to descendant widgets.
///
/// A theme describes the colors and typographic choices of an application.
///
/// {@youtube 560 315 https://www.youtube.com/watch?v=oTvQDJOBXmM}
///
/// Descendant widgets obtain the current theme's [ThemeData] object using
/// [Theme.of]. When a widget uses [Theme.of], it is automatically rebuilt if
/// the theme later changes, so that the changes can be applied.
///
/// The [Theme] widget implies an [IconTheme] widget, set to the value of the
/// [ThemeData.iconTheme] of the [data] for the [Theme].
///
/// See also:
///
/// * [ThemeData], which describes the actual configuration of a theme.
/// * [AnimatedTheme], which animates the [ThemeData] when it changes rather
/// than changing the theme all at once.
/// * [MaterialApp], which includes an [AnimatedTheme] widget configured via
/// the [MaterialApp.theme] argument.
class Theme extends StatelessWidget {
/// Applies the given theme [data] to [child].
const Theme({
super.key,
required this.data,
required this.child,
});
/// Specifies the color and typography values for descendant widgets.
final ThemeData data;
/// The widget below this widget in the tree.
///
/// {@macro flutter.widgets.ProxyWidget.child}
final Widget child;
static final ThemeData _kFallbackTheme = ThemeData.fallback();
/// The data from the closest [Theme] instance that encloses the given
/// context.
///
/// If the given context is enclosed in a [Localizations] widget providing
/// [MaterialLocalizations], the returned data is localized according to the
/// nearest available [MaterialLocalizations].
///
/// Defaults to [ThemeData.fallback] if there is no [Theme] in the given
/// build context.
///
/// Typical usage is as follows:
///
/// ```dart
/// @override
/// Widget build(BuildContext context) {
/// return Text(
/// 'Example',
/// style: Theme.of(context).textTheme.titleLarge,
/// );
/// }
/// ```
///
/// When the [Theme] is actually created in the same `build` function
/// (possibly indirectly, e.g. as part of a [MaterialApp]), the `context`
/// argument to the `build` function can't be used to find the [Theme] (since
/// it's "above" the widget being returned). In such cases, the following
/// technique with a [Builder] can be used to provide a new scope with a
/// [BuildContext] that is "under" the [Theme]:
///
/// ```dart
/// @override
/// Widget build(BuildContext context) {
/// return MaterialApp(
/// theme: ThemeData.light(),
/// home: Builder(
/// // Create an inner BuildContext so that we can refer to
/// // the Theme with Theme.of().
/// builder: (BuildContext context) {
/// return Center(
/// child: Text(
/// 'Example',
/// style: Theme.of(context).textTheme.titleLarge,
/// ),
/// );
/// },
/// ),
/// );
/// }
/// ```
static ThemeData of(BuildContext context) {
final _InheritedTheme? inheritedTheme = context.dependOnInheritedWidgetOfExactType<_InheritedTheme>();
final MaterialLocalizations? localizations = Localizations.of<MaterialLocalizations>(context, MaterialLocalizations);
final ScriptCategory category = localizations?.scriptCategory ?? ScriptCategory.englishLike;
final ThemeData theme = inheritedTheme?.theme.data ?? _kFallbackTheme;
return ThemeData.localize(theme, theme.typography.geometryThemeFor(category));
}
// The inherited themes in widgets library can not infer their values from
// Theme in material library. Wraps the child with these inherited themes to
// overrides their values directly.
Widget _wrapsWidgetThemes(BuildContext context, Widget child) {
final DefaultSelectionStyle selectionStyle = DefaultSelectionStyle.of(context);
return IconTheme(
data: data.iconTheme,
child: DefaultSelectionStyle(
selectionColor: data.textSelectionTheme.selectionColor ?? selectionStyle.selectionColor,
cursorColor: data.textSelectionTheme.cursorColor ?? selectionStyle.cursorColor,
child: child,
),
);
}
@override
Widget build(BuildContext context) {
return _InheritedTheme(
theme: this,
child: CupertinoTheme(
// We're using a MaterialBasedCupertinoThemeData here instead of a
// CupertinoThemeData because it defers some properties to the Material
// ThemeData.
data: MaterialBasedCupertinoThemeData(
materialTheme: data,
),
child: _wrapsWidgetThemes(context, child),
),
);
}
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties.add(DiagnosticsProperty<ThemeData>('data', data, showName: false));
}
}
class _InheritedTheme extends InheritedTheme {
const _InheritedTheme({
required this.theme,
required super.child,
});
final Theme theme;
@override
Widget wrap(BuildContext context, Widget child) {
return Theme(data: theme.data, child: child);
}
@override
bool updateShouldNotify(_InheritedTheme old) => theme.data != old.theme.data;
}
/// An interpolation between two [ThemeData]s.
///
/// This class specializes the interpolation of [Tween<ThemeData>] to call the
/// [ThemeData.lerp] method.
///
/// See [Tween] for a discussion on how to use interpolation objects.
class ThemeDataTween extends Tween<ThemeData> {
/// Creates a [ThemeData] tween.
///
/// The [begin] and [end] properties must be non-null before the tween is
/// first used, but the arguments can be null if the values are going to be
/// filled in later.
ThemeDataTween({ super.begin, super.end });
@override
ThemeData lerp(double t) => ThemeData.lerp(begin!, end!, t);
}
/// Animated version of [Theme] which automatically transitions the colors,
/// etc, over a given duration whenever the given theme changes.
///
/// Here's an illustration of what using this widget looks like, using a [curve]
/// of [Curves.elasticInOut].
/// {@animation 250 266 https://flutter.github.io/assets-for-api-docs/assets/widgets/animated_theme.mp4}
///
/// See also:
///
/// * [Theme], which [AnimatedTheme] uses to actually apply the interpolated
/// theme.
/// * [ThemeData], which describes the actual configuration of a theme.
/// * [MaterialApp], which includes an [AnimatedTheme] widget configured via
/// the [MaterialApp.theme] argument.
class AnimatedTheme extends ImplicitlyAnimatedWidget {
/// Creates an animated theme.
///
/// By default, the theme transition uses a linear curve.
const AnimatedTheme({
super.key,
required this.data,
super.curve,
super.duration = kThemeAnimationDuration,
super.onEnd,
required this.child,
});
/// Specifies the color and typography values for descendant widgets.
final ThemeData data;
/// The widget below this widget in the tree.
///
/// {@macro flutter.widgets.ProxyWidget.child}
final Widget child;
@override
AnimatedWidgetBaseState<AnimatedTheme> createState() => _AnimatedThemeState();
}
class _AnimatedThemeState extends AnimatedWidgetBaseState<AnimatedTheme> {
ThemeDataTween? _data;
@override
void forEachTween(TweenVisitor<dynamic> visitor) {
_data = visitor(_data, widget.data, (dynamic value) => ThemeDataTween(begin: value as ThemeData))! as ThemeDataTween;
}
@override
Widget build(BuildContext context) {
return Theme(
data: _data!.evaluate(animation),
child: widget.child,
);
}
@override
void debugFillProperties(DiagnosticPropertiesBuilder description) {
super.debugFillProperties(description);
description.add(DiagnosticsProperty<ThemeDataTween>('data', _data, showName: false, defaultValue: null));
}
}