Unverified Commit 198a51ac authored by Hans Muller's avatar Hans Muller Committed by GitHub

Migrate the Material Date pickers to M3 Reprise (#119033)

parent 38843814
......@@ -27,6 +27,7 @@ import 'package:gen_defaults/button_template.dart';
import 'package:gen_defaults/card_template.dart';
import 'package:gen_defaults/checkbox_template.dart';
import 'package:gen_defaults/color_scheme_template.dart';
import 'package:gen_defaults/date_picker_template.dart';
import 'package:gen_defaults/dialog_template.dart';
import 'package:gen_defaults/divider_template.dart';
import 'package:gen_defaults/drawer_template.dart';
......@@ -147,6 +148,7 @@ Future<void> main(List<String> args) async {
CardTemplate('Card', '$materialLib/card.dart', tokens).updateFile();
CheckboxTemplate('Checkbox', '$materialLib/checkbox.dart', tokens).updateFile();
ColorSchemeTemplate('ColorScheme', '$materialLib/theme_data.dart', tokens).updateFile();
DatePickerTemplate('DatePicker', '$materialLib/date_picker_theme.dart', tokens).updateFile();
DialogFullscreenTemplate('DialogFullscreen', '$materialLib/dialog.dart', tokens).updateFile();
DialogTemplate('Dialog', '$materialLib/dialog.dart', tokens).updateFile();
DividerTemplate('Divider', '$materialLib/divider.dart', tokens).updateFile();
......
// 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 'template.dart';
class DatePickerTemplate extends TokenTemplate {
const DatePickerTemplate(super.blockName, super.fileName, super.tokens, {
super.colorSchemePrefix = '_colors.',
super.textThemePrefix = '_textTheme.'
});
String _layerOpacity(String layerToken) {
if (tokens.containsKey(layerToken)) {
final String? layerValue = tokens[layerToken] as String?;
if (tokens.containsKey(layerValue)) {
final String? opacityValue = opacity(layerValue!);
if (opacityValue != null) {
return '.withOpacity($opacityValue)';
}
}
}
return '';
}
String _stateColor(String componentToken, String? type, String state) {
final String baseColor = color(
type != null
? '$componentToken.$type.$state.state-layer.color'
: '$componentToken.$state.state-layer.color',
''
);
if (baseColor.isEmpty) {
return 'null';
}
final String opacity = _layerOpacity('$componentToken.$state.state-layer.opacity');
return '$baseColor$opacity';
}
@override
String generate() => '''
class _${blockName}DefaultsM3 extends DatePickerThemeData {
_${blockName}DefaultsM3(this.context)
: super(
elevation: ${elevation("md.comp.date-picker.modal.container")},
shape: ${shape("md.comp.date-picker.modal.container")},
rangePickerElevation: ${elevation("md.comp.date-picker.modal.range-selection.container")},
rangePickerShape: ${shape("md.comp.date-picker.modal.range-selection.container")},
);
final BuildContext context;
late final ThemeData _theme = Theme.of(context);
late final ColorScheme _colors = _theme.colorScheme;
late final TextTheme _textTheme = _theme.textTheme;
@override
Color? get backgroundColor => ${componentColor("md.comp.date-picker.modal.container")};
@override
Color? get shadowColor => ${colorOrTransparent("md.comp.date-picker.modal.container.shadow-color")};
@override
Color? get surfaceTintColor => ${colorOrTransparent("md.comp.date-picker.modal.container.surface-tint-layer.color")};
@override
Color? get headerBackgroundColor => ${colorOrTransparent("md.comp.date-picker.modal.header.container.color")};
@override
Color? get headerForegroundColor => ${colorOrTransparent("md.comp.date-picker.modal.header.headline.color")};
@override
TextStyle? get headerHeadlineStyle => ${textStyle("md.comp.date-picker.modal.header.headline")};
@override
TextStyle? get headerHelpStyle => ${textStyle("md.comp.date-picker.modal.header.supporting-text")};
@override
TextStyle? get weekdayStyle => ${textStyle("md.comp.date-picker.modal.weekdays.label-text")}?.apply(
color: ${componentColor("md.comp.date-picker.modal.weekdays.label-text")},
);
@override
TextStyle? get dayStyle => ${textStyle("md.comp.date-picker.modal.date.label-text")};
@override
MaterialStateProperty<Color?>? get dayForegroundColor =>
MaterialStateProperty.resolveWith((Set<MaterialState> states) {
if (states.contains(MaterialState.selected)) {
return ${componentColor('md.comp.date-picker.modal.date.selected.label-text')};
} else if (states.contains(MaterialState.disabled)) {
return ${componentColor('md.comp.date-picker.modal.date.unselected.label-text')}.withOpacity(0.38);
}
return ${componentColor('md.comp.date-picker.modal.date.unselected.label-text')};
});
@override
MaterialStateProperty<Color?>? get dayBackgroundColor =>
MaterialStateProperty.resolveWith((Set<MaterialState> states) {
if (states.contains(MaterialState.selected)) {
return ${componentColor('md.comp.date-picker.modal.date.selected.container')};
}
return ${componentColor('md.comp.date-picker.modal.date.unselected.container')};
});
@override
MaterialStateProperty<Color?>? get dayOverlayColor =>
MaterialStateProperty.resolveWith((Set<MaterialState> states) {
if (states.contains(MaterialState.selected)) {
if (states.contains(MaterialState.hovered)) {
return ${_stateColor('md.comp.date-picker.modal.date', 'selected', 'hover')};
}
if (states.contains(MaterialState.focused)) {
return ${_stateColor('md.comp.date-picker.modal.date', 'selected', 'focus')};
}
if (states.contains(MaterialState.pressed)) {
return ${_stateColor('md.comp.date-picker.modal.date', 'selected', 'pressed')};
}
} else {
if (states.contains(MaterialState.hovered)) {
return ${_stateColor('md.comp.date-picker.modal.date', 'unselected', 'hover')};
}
if (states.contains(MaterialState.focused)) {
return ${_stateColor('md.comp.date-picker.modal.date', 'unselected', 'focus')};
}
if (states.contains(MaterialState.pressed)) {
return ${_stateColor('md.comp.date-picker.modal.date', 'unselected', 'pressed')};
}
}
return null;
});
@override
MaterialStateProperty<Color?>? get todayForegroundColor =>
MaterialStateProperty.resolveWith((Set<MaterialState> states) {
if (states.contains(MaterialState.selected)) {
return ${componentColor('md.comp.date-picker.modal.date.selected.label-text')};
} else if (states.contains(MaterialState.disabled)) {
return ${componentColor('md.comp.date-picker.modal.date.today.label-text')}.withOpacity(0.38);
}
return ${componentColor('md.comp.date-picker.modal.date.today.label-text')};
});
@override
MaterialStateProperty<Color?>? get todayBackgroundColor => dayBackgroundColor;
@override
BorderSide? get todayBorder => ${border('md.comp.date-picker.modal.date.today.container.outline')};
@override
TextStyle? get yearStyle => ${textStyle("md.comp.date-picker.modal.year-selection.year.label-text")};
@override
MaterialStateProperty<Color?>? get yearForegroundColor =>
MaterialStateProperty.resolveWith((Set<MaterialState> states) {
if (states.contains(MaterialState.selected)) {
return ${componentColor('md.comp.date-picker.modal.year-selection.year.selected.label-text')};
} else if (states.contains(MaterialState.disabled)) {
return ${componentColor('md.comp.date-picker.modal.year-selection.year.unselected.label-text')}.withOpacity(0.38);
}
return ${componentColor('md.comp.date-picker.modal.year-selection.year.unselected.label-text')};
});
@override
MaterialStateProperty<Color?>? get yearBackgroundColor =>
MaterialStateProperty.resolveWith((Set<MaterialState> states) {
if (states.contains(MaterialState.selected)) {
return ${componentColor('md.comp.date-picker.modal.year-selection.year.selected.container')};
}
return ${componentColor('md.comp.date-picker.modal.year-selection.year.unselected.container')};
});
@override
MaterialStateProperty<Color?>? get yearOverlayColor =>
MaterialStateProperty.resolveWith((Set<MaterialState> states) {
if (states.contains(MaterialState.selected)) {
if (states.contains(MaterialState.hovered)) {
return ${_stateColor('md.comp.date-picker.modal.year-selection.year', 'selected', 'hover')};
}
if (states.contains(MaterialState.focused)) {
return ${_stateColor('md.comp.date-picker.modal.year-selection.year', 'selected', 'focus')};
}
if (states.contains(MaterialState.pressed)) {
return ${_stateColor('md.comp.date-picker.modal.year-selection.year', 'selected', 'pressed')};
}
} else {
if (states.contains(MaterialState.hovered)) {
return ${_stateColor('md.comp.date-picker.modal.year-selection.year', 'unselected', 'hover')};
}
if (states.contains(MaterialState.focused)) {
return ${_stateColor('md.comp.date-picker.modal.year-selection.year', 'unselected', 'focus')};
}
if (states.contains(MaterialState.pressed)) {
return ${_stateColor('md.comp.date-picker.modal.year-selection.year', 'unselected', 'pressed')};
}
}
return null;
});
@override
Color? get rangePickerShadowColor => ${colorOrTransparent("md.comp.date-picker.modal.range-selection.container.shadow-color")};
@override
Color? get rangePickerSurfaceTintColor => ${colorOrTransparent("md.comp.date-picker.modal.range-selection.container.surface-tint-layer.color")};
@override
Color? get rangeSelectionBackgroundColor => ${colorOrTransparent("md.comp.date-picker.modal.range-selection.active-indicator.container.color")};
@override
MaterialStateProperty<Color?>? get rangeSelectionOverlayColor =>
MaterialStateProperty.resolveWith((Set<MaterialState> states) {
if (states.contains(MaterialState.hovered)) {
return ${_stateColor('md.comp.date-picker.modal.range-selection.date.in-range.', null, 'hover')};
}
if (states.contains(MaterialState.focused)) {
return ${_stateColor('md.comp.date-picker.modal.range-selection.date.in-range.', null, 'focus')};
}
if (states.contains(MaterialState.pressed)) {
return ${_stateColor('md.comp.date-picker.modal.range-selection.date.in-range.', null, 'pressed')};
}
return null;
});
@override
Color? get rangePickerHeaderBackgroundColor => ${colorOrTransparent("md.comp.date-picker.modal.header.container.color")};
@override
Color? get rangePickerHeaderForegroundColor => ${colorOrTransparent("md.comp.date-picker.modal.header.headline.color")};
@override
TextStyle? get rangePickerHeaderHeadlineStyle => ${textStyle("md.comp.date-picker.modal.range-selection.header.headline")};
@override
TextStyle? get rangePickerHeaderHelpStyle => ${textStyle("md.comp.date-picker.modal.range-selection.month.subhead")};
}
''';
}
......@@ -65,6 +65,7 @@ export 'src/material/data_table_source.dart';
export 'src/material/data_table_theme.dart';
export 'src/material/date.dart';
export 'src/material/date_picker.dart';
export 'src/material/date_picker_theme.dart';
export 'src/material/debug.dart';
export 'src/material/desktop_text_selection.dart';
export 'src/material/desktop_text_selection_toolbar.dart';
......
This diff is collapsed.
......@@ -234,11 +234,16 @@ class _InputDatePickerFormFieldState extends State<InputDatePickerFormField> {
@override
Widget build(BuildContext context) {
final ThemeData theme = Theme.of(context);
final bool useMaterial3 = theme.useMaterial3;
final MaterialLocalizations localizations = MaterialLocalizations.of(context);
final InputDecorationTheme inputTheme = Theme.of(context).inputDecorationTheme;
final InputDecorationTheme inputTheme = theme.inputDecorationTheme;
final InputBorder inputBorder = inputTheme.border
?? (useMaterial3 ? const OutlineInputBorder() : const UnderlineInputBorder());
return TextFormField(
decoration: InputDecoration(
border: inputTheme.border ?? const UnderlineInputBorder(),
border: inputBorder,
filled: inputTheme.filled,
hintText: widget.fieldHintText ?? localizations.dateHelpText,
labelText: widget.fieldLabelText ?? localizations.dateInputLabel,
......
......@@ -254,6 +254,7 @@ class Material extends StatefulWidget {
/// The color to paint the shadow below the material.
///
/// {@template flutter.material.material.shadowColor}
/// If null and [ThemeData.useMaterial3] is true then [ThemeData]'s
/// [ColorScheme.shadow] will be used. If [ThemeData.useMaterial3] is false
/// then [ThemeData.shadowColor] will be used.
......@@ -266,11 +267,13 @@ class Material extends StatefulWidget {
/// property if it is null.
/// * [ThemeData.applyElevationOverlayColor], which turns elevation overlay
/// on or off for dark themes.
/// {@endtemplate}
final Color? shadowColor;
/// The color of the surface tint overlay applied to the material color
/// to indicate elevation.
///
/// {@template flutter.material.material.surfaceTintColor}
/// Material Design 3 introduced a new way for some components to indicate
/// their elevation by using a surface tint color overlay on top of the
/// base material [color]. This overlay is painted with an opacity that is
......@@ -291,6 +294,7 @@ class Material extends StatefulWidget {
/// tint.
/// * https://m3.material.io/styles/color/the-color-system/color-roles
/// which specifies how the overlay is applied.
/// {@endtemplate}
final Color? surfaceTintColor;
/// The typographical style to use for text within this material.
......@@ -298,11 +302,13 @@ class Material extends StatefulWidget {
/// Defines the material's shape as well its shadow.
///
/// {@template flutter.material.material.shape}
/// If shape is non null, the [borderRadius] is ignored and the material's
/// clip boundary and shadow are defined by the shape.
///
/// A shadow is only displayed if the [elevation] is greater than
/// zero.
/// {@endtemplate}
final ShapeBorder? shape;
/// Whether to paint the [shape] border in front of the [child].
......
......@@ -22,6 +22,7 @@ import 'color_scheme.dart';
import 'colors.dart';
import 'constants.dart';
import 'data_table_theme.dart';
import 'date_picker_theme.dart';
import 'dialog_theme.dart';
import 'divider_theme.dart';
import 'drawer_theme.dart';
......@@ -348,6 +349,7 @@ class ThemeData with Diagnosticable {
CheckboxThemeData? checkboxTheme,
ChipThemeData? chipTheme,
DataTableThemeData? dataTableTheme,
DatePickerThemeData? datePickerTheme,
DialogTheme? dialogTheme,
DividerThemeData? dividerTheme,
DrawerThemeData? drawerTheme,
......@@ -600,6 +602,7 @@ class ThemeData with Diagnosticable {
checkboxTheme ??= const CheckboxThemeData();
chipTheme ??= const ChipThemeData();
dataTableTheme ??= const DataTableThemeData();
datePickerTheme ??= const DatePickerThemeData();
dialogTheme ??= const DialogTheme();
dividerTheme ??= const DividerThemeData();
drawerTheme ??= const DrawerThemeData();
......@@ -697,6 +700,7 @@ class ThemeData with Diagnosticable {
checkboxTheme: checkboxTheme,
chipTheme: chipTheme,
dataTableTheme: dataTableTheme,
datePickerTheme: datePickerTheme,
dialogTheme: dialogTheme,
dividerTheme: dividerTheme,
drawerTheme: drawerTheme,
......@@ -810,6 +814,7 @@ class ThemeData with Diagnosticable {
required this.checkboxTheme,
required this.chipTheme,
required this.dataTableTheme,
required this.datePickerTheme,
required this.dialogTheme,
required this.dividerTheme,
required this.drawerTheme,
......@@ -1238,6 +1243,7 @@ class ThemeData with Diagnosticable {
/// - [ActionChip] (used for Assist and Suggestion chips),
/// - [FilterChip], [ChoiceChip] (used for single selection filter chips),
/// - [InputChip]
/// * Date pickers: [showDatePicker], [showDateRangePicker], [DatePickerDialog], [DateRangePickerDialog], [InputDatePickerFormField]
/// * Dialogs: [Dialog], [AlertDialog]
/// * Divider: [Divider]
/// * Lists: [ListTile]
......@@ -1252,6 +1258,7 @@ class ThemeData with Diagnosticable {
/// * Switch: [Switch]
/// * Tabs: [TabBar]
/// * TextFields: [TextField] together with its [InputDecoration]
/// * Time pickers: [showTimePicker], [TimePickerDialog]
/// * Top app bar: [AppBar]
///
/// In addition, this flag enables features introduced in Android 12.
......@@ -1473,6 +1480,10 @@ class ThemeData with Diagnosticable {
/// widgets.
final DataTableThemeData dataTableTheme;
/// A theme for customizing the appearance and layout of [DatePickerDialog]
/// widgets.
final DatePickerThemeData datePickerTheme;
/// A theme for customizing the shape of a dialog.
final DialogTheme dialogTheme;
......@@ -1811,6 +1822,7 @@ class ThemeData with Diagnosticable {
CheckboxThemeData? checkboxTheme,
ChipThemeData? chipTheme,
DataTableThemeData? dataTableTheme,
DatePickerThemeData? datePickerTheme,
DialogTheme? dialogTheme,
DividerThemeData? dividerTheme,
DrawerThemeData? drawerTheme,
......@@ -1971,6 +1983,7 @@ class ThemeData with Diagnosticable {
checkboxTheme: checkboxTheme ?? this.checkboxTheme,
chipTheme: chipTheme ?? this.chipTheme,
dataTableTheme: dataTableTheme ?? this.dataTableTheme,
datePickerTheme: datePickerTheme ?? this.datePickerTheme,
dialogTheme: dialogTheme ?? this.dialogTheme,
dividerTheme: dividerTheme ?? this.dividerTheme,
drawerTheme: drawerTheme ?? this.drawerTheme,
......@@ -2165,6 +2178,7 @@ class ThemeData with Diagnosticable {
checkboxTheme: CheckboxThemeData.lerp(a.checkboxTheme, b.checkboxTheme, t),
chipTheme: ChipThemeData.lerp(a.chipTheme, b.chipTheme, t)!,
dataTableTheme: DataTableThemeData.lerp(a.dataTableTheme, b.dataTableTheme, t),
datePickerTheme: DatePickerThemeData.lerp(a.datePickerTheme, b.datePickerTheme, t),
dialogTheme: DialogTheme.lerp(a.dialogTheme, b.dialogTheme, t),
dividerTheme: DividerThemeData.lerp(a.dividerTheme, b.dividerTheme, t),
drawerTheme: DrawerThemeData.lerp(a.drawerTheme, b.drawerTheme, t)!,
......@@ -2273,6 +2287,7 @@ class ThemeData with Diagnosticable {
other.checkboxTheme == checkboxTheme &&
other.chipTheme == chipTheme &&
other.dataTableTheme == dataTableTheme &&
other.datePickerTheme == datePickerTheme &&
other.dialogTheme == dialogTheme &&
other.dividerTheme == dividerTheme &&
other.drawerTheme == drawerTheme &&
......@@ -2378,6 +2393,7 @@ class ThemeData with Diagnosticable {
checkboxTheme,
chipTheme,
dataTableTheme,
datePickerTheme,
dialogTheme,
dividerTheme,
drawerTheme,
......@@ -2485,6 +2501,7 @@ class ThemeData with Diagnosticable {
properties.add(DiagnosticsProperty<CheckboxThemeData>('checkboxTheme', checkboxTheme, defaultValue: defaultData.checkboxTheme, level: DiagnosticLevel.debug));
properties.add(DiagnosticsProperty<ChipThemeData>('chipTheme', chipTheme, level: DiagnosticLevel.debug));
properties.add(DiagnosticsProperty<DataTableThemeData>('dataTableTheme', dataTableTheme, defaultValue: defaultData.dataTableTheme, level: DiagnosticLevel.debug));
properties.add(DiagnosticsProperty<DatePickerThemeData>('datePickerTheme', datePickerTheme, defaultValue: defaultData.datePickerTheme, level: DiagnosticLevel.debug));
properties.add(DiagnosticsProperty<DialogTheme>('dialogTheme', dialogTheme, defaultValue: defaultData.dialogTheme, level: DiagnosticLevel.debug));
properties.add(DiagnosticsProperty<DividerThemeData>('dividerTheme', dividerTheme, defaultValue: defaultData.dividerTheme, level: DiagnosticLevel.debug));
properties.add(DiagnosticsProperty<DrawerThemeData>('drawerTheme', drawerTheme, defaultValue: defaultData.drawerTheme, level: DiagnosticLevel.debug));
......
This diff is collapsed.
......@@ -781,6 +781,7 @@ void main() {
checkboxTheme: const CheckboxThemeData(),
chipTheme: chipTheme,
dataTableTheme: const DataTableThemeData(),
datePickerTheme: const DatePickerThemeData(),
dialogTheme: const DialogTheme(backgroundColor: Colors.black),
dividerTheme: const DividerThemeData(color: Colors.black),
drawerTheme: const DrawerThemeData(),
......@@ -901,6 +902,7 @@ void main() {
checkboxTheme: const CheckboxThemeData(),
chipTheme: otherChipTheme,
dataTableTheme: const DataTableThemeData(),
datePickerTheme: const DatePickerThemeData(backgroundColor: Colors.amber),
dialogTheme: const DialogTheme(backgroundColor: Colors.white),
dividerTheme: const DividerThemeData(color: Colors.white),
drawerTheme: const DrawerThemeData(),
......@@ -1008,6 +1010,7 @@ void main() {
chipTheme: otherTheme.chipTheme,
dataTableTheme: otherTheme.dataTableTheme,
dialogTheme: otherTheme.dialogTheme,
datePickerTheme: otherTheme.datePickerTheme,
dividerTheme: otherTheme.dividerTheme,
drawerTheme: otherTheme.drawerTheme,
elevatedButtonTheme: otherTheme.elevatedButtonTheme,
......@@ -1110,6 +1113,7 @@ void main() {
expect(themeDataCopy.checkboxTheme, equals(otherTheme.checkboxTheme));
expect(themeDataCopy.chipTheme, equals(otherTheme.chipTheme));
expect(themeDataCopy.dataTableTheme, equals(otherTheme.dataTableTheme));
expect(themeDataCopy.datePickerTheme, equals(otherTheme.datePickerTheme));
expect(themeDataCopy.dialogTheme, equals(otherTheme.dialogTheme));
expect(themeDataCopy.dividerTheme, equals(otherTheme.dividerTheme));
expect(themeDataCopy.drawerTheme, equals(otherTheme.drawerTheme));
......@@ -1248,6 +1252,7 @@ void main() {
'checkboxTheme',
'chipTheme',
'dataTableTheme',
'datePickerTheme',
'dialogTheme',
'dividerTheme',
'drawerTheme',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment