Unverified Commit 3ce88d38 authored by Qun Cheng's avatar Qun Cheng Committed by GitHub

Replace menu defaults with tokens (#113963)

parent af34b104
......@@ -31,6 +31,7 @@ import 'package:gen_defaults/filter_chip_template.dart';
import 'package:gen_defaults/icon_button_template.dart';
import 'package:gen_defaults/input_chip_template.dart';
import 'package:gen_defaults/input_decorator_template.dart';
import 'package:gen_defaults/menu_template.dart';
import 'package:gen_defaults/navigation_bar_template.dart';
import 'package:gen_defaults/navigation_rail_template.dart';
import 'package:gen_defaults/popup_menu_template.dart';
......@@ -135,6 +136,7 @@ Future<void> main(List<String> args) async {
IconButtonTemplate('IconButton', '$materialLib/icon_button.dart', tokens).updateFile();
InputChipTemplate('InputChip', '$materialLib/input_chip.dart', tokens).updateFile();
InputDecoratorTemplate('InputDecorator', '$materialLib/input_decorator.dart', tokens).updateFile();
MenuTemplate('Menu', '$materialLib/menu_anchor.dart', tokens).updateFile();
NavigationBarTemplate('NavigationBar', '$materialLib/navigation_bar.dart', tokens).updateFile();
NavigationRailTemplate('NavigationRail', '$materialLib/navigation_rail.dart', tokens).updateFile();
PopupMenuTemplate('PopupMenu', '$materialLib/popup_menu.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 MenuTemplate extends TokenTemplate {
const MenuTemplate(super.blockName, super.fileName, super.tokens, {
super.colorSchemePrefix = '_colors.',
});
@override
String generate() => '''
class _MenuBarDefaultsM3 extends MenuStyle {
_MenuBarDefaultsM3(this.context)
: super(
elevation: const MaterialStatePropertyAll<double?>(${elevation('md.comp.menu.container')}),
shape: const MaterialStatePropertyAll<OutlinedBorder>(_defaultMenuBorder),
alignment: AlignmentDirectional.bottomStart,
);
static const RoundedRectangleBorder _defaultMenuBorder =
${shape('md.comp.menu.container', '')};
final BuildContext context;
late final ColorScheme _colors = Theme.of(context).colorScheme;
@override
MaterialStateProperty<Color?> get backgroundColor {
return MaterialStatePropertyAll<Color?>(${componentColor('md.comp.menu.container')});
}
@override
MaterialStateProperty<Color?>? get shadowColor {
return MaterialStatePropertyAll<Color?>(${color('md.comp.menu.container.shadow-color')});
}
@override
MaterialStateProperty<Color?>? get surfaceTintColor {
return MaterialStatePropertyAll<Color?>(${componentColor('md.comp.menu.container.surface-tint-layer')});
}
@override
MaterialStateProperty<EdgeInsetsGeometry?>? get padding {
return MaterialStatePropertyAll<EdgeInsetsGeometry>(
EdgeInsetsDirectional.symmetric(
horizontal: math.max(
_kTopLevelMenuHorizontalMinPadding,
2 + Theme.of(context).visualDensity.baseSizeAdjustment.dx,
),
),
);
}
}
class _MenuButtonDefaultsM3 extends ButtonStyle {
_MenuButtonDefaultsM3(this.context)
: super(
animationDuration: kThemeChangeDuration,
enableFeedback: true,
alignment: AlignmentDirectional.centerStart,
);
final BuildContext context;
late final ColorScheme _colors = Theme.of(context).colorScheme;
@override
MaterialStateProperty<Color?>? get backgroundColor {
return ButtonStyleButton.allOrNull<Color>(Colors.transparent);
}
// No default shadow color
// No default surface tint color
@override
MaterialStateProperty<double>? get elevation {
return ButtonStyleButton.allOrNull<double>(0.0);
}
@override
MaterialStateProperty<Color?>? get foregroundColor {
return MaterialStateProperty.resolveWith((Set<MaterialState> states) {
if (states.contains(MaterialState.disabled)) {
return ${componentColor('md.comp.menu.list-item.disabled.label-text')};
}
if (states.contains(MaterialState.pressed)) {
return ${componentColor('md.comp.menu.list-item.pressed.label-text')};
}
if (states.contains(MaterialState.hovered)) {
return ${componentColor('md.comp.menu.list-item.hover.label-text')};
}
if (states.contains(MaterialState.focused)) {
return ${componentColor('md.comp.menu.list-item.focus.label-text')};
}
return ${componentColor('md.comp.menu.list-item.label-text')};
});
}
@override
MaterialStateProperty<Color?>? get iconColor {
return MaterialStateProperty.resolveWith((Set<MaterialState> states) {
if (states.contains(MaterialState.disabled)) {
return ${componentColor('md.comp.menu.list-item.with-leading-icon.disabled.leading-icon')};
}
if (states.contains(MaterialState.pressed)) {
return ${componentColor('md.comp.menu.list-item.with-leading-icon.pressed.icon')};
}
if (states.contains(MaterialState.hovered)) {
return ${componentColor('md.comp.menu.list-item.with-leading-icon.hover.icon')};
}
if (states.contains(MaterialState.focused)) {
return ${componentColor('md.comp.menu.list-item.with-leading-icon.focus.icon')};
}
return ${componentColor('md.comp.menu.list-item.with-leading-icon.leading-icon')};
});
}
// No default fixedSize
@override
MaterialStateProperty<Size>? get maximumSize {
return ButtonStyleButton.allOrNull<Size>(Size.infinite);
}
@override
MaterialStateProperty<Size>? get minimumSize {
return ButtonStyleButton.allOrNull<Size>(const Size(64.0, ${tokens['md.comp.menu.list-item.container.height']}));
}
@override
MaterialStateProperty<MouseCursor?>? get mouseCursor {
return MaterialStateProperty.resolveWith(
(Set<MaterialState> states) {
if (states.contains(MaterialState.disabled)) {
return SystemMouseCursors.basic;
}
return SystemMouseCursors.click;
},
);
}
@override
MaterialStateProperty<Color?>? get overlayColor {
return MaterialStateProperty.resolveWith(
(Set<MaterialState> states) {
if (states.contains(MaterialState.pressed)) {
return ${componentColor('md.comp.menu.list-item.pressed.state-layer')};
}
if (states.contains(MaterialState.hovered)) {
return ${componentColor('md.comp.menu.list-item.hover.state-layer')};
}
if (states.contains(MaterialState.focused)) {
return ${componentColor('md.comp.menu.list-item.focus.state-layer')};
}
return Colors.transparent;
},
);
}
@override
MaterialStateProperty<EdgeInsetsGeometry>? get padding {
return ButtonStyleButton.allOrNull<EdgeInsetsGeometry>(_scaledPadding(context));
}
// No default side
@override
MaterialStateProperty<OutlinedBorder>? get shape {
return ButtonStyleButton.allOrNull<OutlinedBorder>(const RoundedRectangleBorder());
}
@override
InteractiveInkFeatureFactory? get splashFactory => Theme.of(context).splashFactory;
@override
MaterialTapTargetSize? get tapTargetSize => Theme.of(context).materialTapTargetSize;
@override
MaterialStateProperty<TextStyle?> get textStyle {
return MaterialStatePropertyAll<TextStyle?>(${textStyle('md.comp.menu.list-item.label-text')});
}
@override
VisualDensity? get visualDensity => Theme.of(context).visualDensity;
// The horizontal padding number comes from the spec.
EdgeInsetsGeometry _scaledPadding(BuildContext context) {
return ButtonStyleButton.scaledPadding(
const EdgeInsets.symmetric(horizontal: 12),
const EdgeInsets.symmetric(horizontal: 8),
const EdgeInsets.symmetric(horizontal: 4),
MediaQuery.maybeOf(context)?.textScaleFactor ?? 1,
);
}
}
class _MenuDefaultsM3 extends MenuStyle {
_MenuDefaultsM3(this.context)
: super(
elevation: const MaterialStatePropertyAll<double?>(${elevation('md.comp.menu.container')}),
shape: const MaterialStatePropertyAll<OutlinedBorder>(_defaultMenuBorder),
alignment: AlignmentDirectional.topEnd,
);
static const RoundedRectangleBorder _defaultMenuBorder =
${shape('md.comp.menu.container', '')};
final BuildContext context;
late final ColorScheme _colors = Theme.of(context).colorScheme;
@override
MaterialStateProperty<Color?> get backgroundColor {
return MaterialStatePropertyAll<Color?>(${componentColor('md.comp.menu.container')});
}
@override
MaterialStateProperty<Color?>? get surfaceTintColor {
return MaterialStatePropertyAll<Color?>(${componentColor('md.comp.menu.container.surface-tint-layer')});
}
@override
MaterialStateProperty<Color?>? get shadowColor {
return MaterialStatePropertyAll<Color?>(${color('md.comp.menu.container.shadow-color')});
}
@override
MaterialStateProperty<EdgeInsetsGeometry?>? get padding {
return MaterialStatePropertyAll<EdgeInsetsGeometry>(
EdgeInsetsDirectional.symmetric(
vertical: math.max(
_kMenuVerticalMinPadding,
2 + Theme.of(context).visualDensity.baseSizeAdjustment.dy,
),
),
);
}
}
''';
}
......@@ -21,14 +21,14 @@ void main() {
await tester.sendKeyDownEvent(LogicalKeyboardKey.controlRight);
await tester.tapAt(const Offset(100, 200));
await tester.pump();
expect(tester.getRect(findMenu()), equals(const Rect.fromLTRB(100.0, 200.0, 404.0, 352.0)));
expect(tester.getRect(findMenu()), equals(const Rect.fromLTRB(100.0, 200.0, 388.0, 360.0)));
// Make sure tapping in a different place causes the menu to move.
await tester.tapAt(const Offset(200, 100));
await tester.pump();
await tester.sendKeyUpEvent(LogicalKeyboardKey.controlRight);
expect(tester.getRect(findMenu()), equals(const Rect.fromLTRB(200.0, 100.0, 504.0, 252.0)));
expect(tester.getRect(findMenu()), equals(const Rect.fromLTRB(200.0, 100.0, 488.0, 260.0)));
expect(find.text(example.MenuEntry.about.label), findsOneWidget);
expect(find.text(example.MenuEntry.showMessage.label), findsOneWidget);
......
......@@ -151,6 +151,7 @@ class ButtonStyle with Diagnosticable {
this.minimumSize,
this.fixedSize,
this.maximumSize,
this.iconColor,
this.iconSize,
this.side,
this.shape,
......@@ -230,6 +231,11 @@ class ButtonStyle with Diagnosticable {
/// This value must be greater than or equal to [minimumSize].
final MaterialStateProperty<Size?>? maximumSize;
/// The icon's color inside of the button.
///
/// If this is null, the icon color will be [foregroundColor].
final MaterialStateProperty<Color?>? iconColor;
/// The icon's size inside of the button.
final MaterialStateProperty<double?>? iconSize;
......@@ -323,6 +329,7 @@ class ButtonStyle with Diagnosticable {
MaterialStateProperty<Size?>? minimumSize,
MaterialStateProperty<Size?>? fixedSize,
MaterialStateProperty<Size?>? maximumSize,
MaterialStateProperty<Color?>? iconColor,
MaterialStateProperty<double?>? iconSize,
MaterialStateProperty<BorderSide?>? side,
MaterialStateProperty<OutlinedBorder?>? shape,
......@@ -346,6 +353,7 @@ class ButtonStyle with Diagnosticable {
minimumSize: minimumSize ?? this.minimumSize,
fixedSize: fixedSize ?? this.fixedSize,
maximumSize: maximumSize ?? this.maximumSize,
iconColor: iconColor ?? this.iconColor,
iconSize: iconSize ?? this.iconSize,
side: side ?? this.side,
shape: shape ?? this.shape,
......@@ -380,6 +388,7 @@ class ButtonStyle with Diagnosticable {
minimumSize: minimumSize ?? style.minimumSize,
fixedSize: fixedSize ?? style.fixedSize,
maximumSize: maximumSize ?? style.maximumSize,
iconColor: iconColor ?? style.iconColor,
iconSize: iconSize ?? style.iconSize,
side: side ?? style.side,
shape: shape ?? style.shape,
......@@ -407,6 +416,7 @@ class ButtonStyle with Diagnosticable {
minimumSize,
fixedSize,
maximumSize,
iconColor,
iconSize,
side,
shape,
......@@ -441,6 +451,7 @@ class ButtonStyle with Diagnosticable {
&& other.minimumSize == minimumSize
&& other.fixedSize == fixedSize
&& other.maximumSize == maximumSize
&& other.iconColor == iconColor
&& other.iconSize == iconSize
&& other.side == side
&& other.shape == shape
......@@ -467,6 +478,7 @@ class ButtonStyle with Diagnosticable {
properties.add(DiagnosticsProperty<MaterialStateProperty<Size?>>('minimumSize', minimumSize, defaultValue: null));
properties.add(DiagnosticsProperty<MaterialStateProperty<Size?>>('fixedSize', fixedSize, defaultValue: null));
properties.add(DiagnosticsProperty<MaterialStateProperty<Size?>>('maximumSize', maximumSize, defaultValue: null));
properties.add(DiagnosticsProperty<MaterialStateProperty<Color?>>('iconColor', iconColor, defaultValue: null));
properties.add(DiagnosticsProperty<MaterialStateProperty<double?>>('iconSize', iconSize, defaultValue: null));
properties.add(DiagnosticsProperty<MaterialStateProperty<BorderSide?>>('side', side, defaultValue: null));
properties.add(DiagnosticsProperty<MaterialStateProperty<OutlinedBorder?>>('shape', shape, defaultValue: null));
......@@ -496,6 +508,7 @@ class ButtonStyle with Diagnosticable {
minimumSize: MaterialStateProperty.lerp<Size?>(a?.minimumSize, b?.minimumSize, t, Size.lerp),
fixedSize: MaterialStateProperty.lerp<Size?>(a?.fixedSize, b?.fixedSize, t, Size.lerp),
maximumSize: MaterialStateProperty.lerp<Size?>(a?.maximumSize, b?.maximumSize, t, Size.lerp),
iconColor: MaterialStateProperty.lerp<Color?>(a?.iconColor, b?.iconColor, t, Color.lerp),
iconSize: MaterialStateProperty.lerp<double?>(a?.iconSize, b?.iconSize, t, lerpDouble),
side: _lerpSides(a?.side, b?.side, t),
shape: MaterialStateProperty.lerp<OutlinedBorder?>(a?.shape, b?.shape, t, OutlinedBorder.lerp),
......
......@@ -287,6 +287,7 @@ class _ButtonStyleState extends State<ButtonStyleButton> with TickerProviderStat
final Size? resolvedMinimumSize = resolve<Size?>((ButtonStyle? style) => style?.minimumSize);
final Size? resolvedFixedSize = resolve<Size?>((ButtonStyle? style) => style?.fixedSize);
final Size? resolvedMaximumSize = resolve<Size?>((ButtonStyle? style) => style?.maximumSize);
final Color? resolvedIconColor = resolve<Color?>((ButtonStyle? style) => style?.iconColor);
final double? resolvedIconSize = resolve<double?>((ButtonStyle? style) => style?.iconSize);
final BorderSide? resolvedSide = resolve<BorderSide?>((ButtonStyle? style) => style?.side);
final OutlinedBorder? resolvedShape = resolve<OutlinedBorder?>((ButtonStyle? style) => style?.shape);
......@@ -400,7 +401,7 @@ class _ButtonStyleState extends State<ButtonStyleButton> with TickerProviderStat
customBorder: resolvedShape.copyWith(side: resolvedSide),
statesController: statesController,
child: IconTheme.merge(
data: IconThemeData(color: resolvedForegroundColor, size: resolvedIconSize),
data: IconThemeData(color: resolvedIconColor ?? resolvedForegroundColor, size: resolvedIconSize),
child: Padding(
padding: padding,
child: Align(
......
......@@ -153,6 +153,8 @@ class TextButton extends ButtonStyleButton {
Color? disabledBackgroundColor,
Color? shadowColor,
Color? surfaceTintColor,
Color? iconColor,
Color? disabledIconColor,
double? elevation,
TextStyle? textStyle,
EdgeInsetsGeometry? padding,
......@@ -193,6 +195,11 @@ class TextButton extends ButtonStyleButton {
final MaterialStateProperty<Color?>? overlayColor = (foreground == null)
? null
: _TextButtonDefaultOverlay(foreground);
final MaterialStateProperty<Color?>? iconColorProp = (iconColor == null && disabledIconColor == null)
? null
: disabledIconColor == null
? ButtonStyleButton.allOrNull<Color?>(iconColor)
: _TextButtonDefaultIconColor(iconColor, disabledIconColor);
final MaterialStateProperty<MouseCursor>? mouseCursor = (enabledMouseCursor == null && disabledMouseCursor == null)
? null
: _TextButtonDefaultMouseCursor(enabledMouseCursor!, disabledMouseCursor!);
......@@ -204,6 +211,7 @@ class TextButton extends ButtonStyleButton {
overlayColor: overlayColor,
shadowColor: ButtonStyleButton.allOrNull<Color>(shadowColor),
surfaceTintColor: ButtonStyleButton.allOrNull<Color>(surfaceTintColor),
iconColor: iconColorProp,
elevation: ButtonStyleButton.allOrNull<double>(elevation),
padding: ButtonStyleButton.allOrNull<EdgeInsetsGeometry>(padding),
minimumSize: ButtonStyleButton.allOrNull<Size>(minimumSize),
......@@ -422,6 +430,27 @@ class _TextButtonDefaultOverlay extends MaterialStateProperty<Color?> {
}
}
@immutable
class _TextButtonDefaultIconColor extends MaterialStateProperty<Color?> {
_TextButtonDefaultIconColor(this.iconColor, this.disabledIconColor);
final Color? iconColor;
final Color? disabledIconColor;
@override
Color? resolve(Set<MaterialState> states) {
if (states.contains(MaterialState.disabled)) {
return disabledIconColor;
}
return iconColor;
}
@override
String toString() {
return '{disabled: $disabledIconColor, color: $iconColor}';
}
}
@immutable
class _TextButtonDefaultMouseCursor extends MaterialStateProperty<MouseCursor> with Diagnosticable {
_TextButtonDefaultMouseCursor(this.enabledCursor, this.disabledCursor);
......
......@@ -27,6 +27,7 @@ void main() {
expect(style.minimumSize, null);
expect(style.fixedSize, null);
expect(style.maximumSize, null);
expect(style.iconColor, null);
expect(style.iconSize, null);
expect(style.side, null);
expect(style.shape, null);
......@@ -63,6 +64,7 @@ void main() {
minimumSize: MaterialStatePropertyAll<Size>(Size(1.0, 2.0)),
side: MaterialStatePropertyAll<BorderSide>(BorderSide(width: 4.0, color: Color(0xfffffff6))),
maximumSize: MaterialStatePropertyAll<Size>(Size(100.0, 200.0)),
iconColor: MaterialStatePropertyAll<Color>(Color(0xfffffff6)),
iconSize: MaterialStatePropertyAll<double>(48.1),
shape: MaterialStatePropertyAll<OutlinedBorder>(StadiumBorder()),
mouseCursor: MaterialStatePropertyAll<MouseCursor>(SystemMouseCursors.forbidden),
......@@ -87,6 +89,7 @@ void main() {
'padding: MaterialStatePropertyAll(EdgeInsets.all(1.0))',
'minimumSize: MaterialStatePropertyAll(Size(1.0, 2.0))',
'maximumSize: MaterialStatePropertyAll(Size(100.0, 200.0))',
'iconColor: MaterialStatePropertyAll(Color(0xfffffff6))',
'iconSize: MaterialStatePropertyAll(48.1)',
'side: MaterialStatePropertyAll(BorderSide(color: Color(0xfffffff6), width: 4.0))',
'shape: MaterialStatePropertyAll(StadiumBorder(BorderSide(width: 0.0, style: none)))',
......@@ -109,6 +112,7 @@ void main() {
const MaterialStateProperty<Size> minimumSize = MaterialStatePropertyAll<Size>(Size(1, 2));
const MaterialStateProperty<Size> fixedSize = MaterialStatePropertyAll<Size>(Size(3, 4));
const MaterialStateProperty<Size> maximumSize = MaterialStatePropertyAll<Size>(Size(5, 6));
const MaterialStateProperty<Color> iconColor = MaterialStatePropertyAll<Color>(Color(0xfffffff6));
const MaterialStateProperty<double> iconSize = MaterialStatePropertyAll<double>(48.0);
const MaterialStateProperty<BorderSide> side = MaterialStatePropertyAll<BorderSide>(BorderSide());
const MaterialStateProperty<OutlinedBorder> shape = MaterialStatePropertyAll<OutlinedBorder>(StadiumBorder());
......@@ -130,6 +134,7 @@ void main() {
minimumSize: minimumSize,
fixedSize: fixedSize,
maximumSize: maximumSize,
iconColor: iconColor,
iconSize: iconSize,
side: side,
shape: shape,
......@@ -154,6 +159,7 @@ void main() {
minimumSize: minimumSize,
fixedSize: fixedSize,
maximumSize: maximumSize,
iconColor: iconColor,
iconSize: iconSize,
side: side,
shape: shape,
......
......@@ -87,13 +87,13 @@ void main() {
// Open a test menu.
await tester.tap(find.text(TestMenu.mainMenu1.label));
await tester.pump();
expect(tester.getRect(findMenuBarPanel().first), equals(const Rect.fromLTRB(240.0, 0.0, 560.0, 68.0)));
expect(tester.getRect(findMenuBarPanel().first), equals(const Rect.fromLTRB(228.0, 0.0, 572.0, 68.0)));
final Material menuBarMaterial = getMenuBarPanelMaterial(tester);
expect(menuBarMaterial.elevation, equals(15));
expect(menuBarMaterial.color, equals(Colors.red));
final Material subMenuMaterial = getSubmenuPanelMaterial(tester);
expect(tester.getRect(findSubmenuPanel()), equals(const Rect.fromLTRB(350.0, 58.0, 580.0, 210.0)));
expect(tester.getRect(findSubmenuPanel()), equals(const Rect.fromLTRB(346.0, 58.0, 560.0, 218.0)));
expect(subMenuMaterial.elevation, equals(20));
expect(subMenuMaterial.color, equals(Colors.green));
});
......@@ -160,19 +160,19 @@ void main() {
await tester.tap(find.text(TestMenu.mainMenu1.label));
await tester.pump();
expect(tester.getRect(findMenuBarPanel().first), equals(const Rect.fromLTRB(238.0, 0.0, 562.0, 72.0)));
expect(tester.getRect(findMenuBarPanel().first), equals(const Rect.fromLTRB(226.0, 0.0, 574.0, 72.0)));
final Material menuBarMaterial = getMenuBarPanelMaterial(tester);
expect(menuBarMaterial.elevation, equals(10.0));
expect(menuBarMaterial.color, equals(Colors.blue));
final Material subMenuMaterial = getSubmenuPanelMaterial(tester);
expect(tester.getRect(findSubmenuPanel()), equals(const Rect.fromLTRB(336.0, 60.0, 594.0, 232.0)));
expect(tester.getRect(findSubmenuPanel()), equals(const Rect.fromLTRB(332.0, 60.0, 574.0, 232.0)));
expect(subMenuMaterial.elevation, equals(18));
expect(subMenuMaterial.color, equals(Colors.cyan));
expect(subMenuMaterial.shape, equals(const BeveledRectangleBorder()));
final Finder menuItem = findSubMenuItem();
expect(tester.getRect(menuItem.first), equals(const Rect.fromLTRB(350.0, 74.0, 580.0, 122.0)));
expect(tester.getRect(menuItem.first), equals(const Rect.fromLTRB(346.0, 74.0, 560.0, 122.0)));
final Material menuItemMaterial = tester.widget<Material>(
find.ancestor(of: find.text(TestMenu.subMenu10.label), matching: find.byType(Material)).first);
expect(menuItemMaterial.color, equals(Colors.amber));
......
......@@ -261,20 +261,20 @@ void main() {
);
await tester.pump();
expect(tester.getRect(find.byType(MenuBar)), equals(const Rect.fromLTRB(240.0, 0.0, 560.0, 48.0)));
expect(tester.getRect(find.byType(MenuBar)), equals(const Rect.fromLTRB(228.0, 0.0, 572.0, 48.0)));
// Open and make sure things are the right size.
await tester.tap(find.text(TestMenu.mainMenu1.label));
await tester.pump();
expect(tester.getRect(find.byType(MenuBar)), equals(const Rect.fromLTRB(240.0, 0.0, 560.0, 48.0)));
expect(tester.getRect(find.byType(MenuBar)), equals(const Rect.fromLTRB(228.0, 0.0, 572.0, 48.0)));
expect(
tester.getRect(find.text(TestMenu.subMenu10.label)),
equals(const Rect.fromLTRB(366.0, 64.0, 520.0, 78.0)),
equals(const Rect.fromLTRB(366.0, 68.0, 520.0, 82.0)),
);
expect(
tester.getRect(find.ancestor(of: find.text(TestMenu.subMenu10.label), matching: find.byType(Material)).at(1)),
equals(const Rect.fromLTRB(350.0, 48.0, 602.0, 178.0)),
equals(const Rect.fromLTRB(346.0, 48.0, 579.0, 186.0)),
);
});
});
......
......@@ -87,13 +87,13 @@ void main() {
// Open a test menu.
await tester.tap(find.text(TestMenu.mainMenu1.label));
await tester.pump();
expect(tester.getRect(findMenuBarPanel().first), equals(const Rect.fromLTRB(246.0, 0.0, 554.0, 48.0)));
expect(tester.getRect(findMenuBarPanel().first), equals(const Rect.fromLTRB(234.0, 0.0, 566.0, 48.0)));
final Material menuBarMaterial = getMenuBarPanelMaterial(tester);
expect(menuBarMaterial.elevation, equals(20));
expect(menuBarMaterial.color, equals(Colors.green));
final Material subMenuMaterial = getSubmenuPanelMaterial(tester);
expect(tester.getRect(findSubmenuPanel()), equals(const Rect.fromLTRB(340.0, 48.0, 590.0, 212.0)));
expect(tester.getRect(findSubmenuPanel()), equals(const Rect.fromLTRB(336.0, 48.0, 570.0, 212.0)));
expect(subMenuMaterial.elevation, equals(15));
expect(subMenuMaterial.color, equals(Colors.red));
});
......@@ -160,19 +160,19 @@ void main() {
await tester.tap(find.text(TestMenu.mainMenu1.label));
await tester.pump();
expect(tester.getRect(findMenuBarPanel().first), equals(const Rect.fromLTRB(238.0, 0.0, 562.0, 72.0)));
expect(tester.getRect(findMenuBarPanel().first), equals(const Rect.fromLTRB(226.0, 0.0, 574.0, 72.0)));
final Material menuBarMaterial = getMenuBarPanelMaterial(tester);
expect(menuBarMaterial.elevation, equals(10.0));
expect(menuBarMaterial.color, equals(Colors.blue));
final Material subMenuMaterial = getSubmenuPanelMaterial(tester);
expect(tester.getRect(findSubmenuPanel()), equals(const Rect.fromLTRB(336.0, 60.0, 594.0, 232.0)));
expect(tester.getRect(findSubmenuPanel()), equals(const Rect.fromLTRB(332.0, 60.0, 574.0, 232.0)));
expect(subMenuMaterial.elevation, equals(18));
expect(subMenuMaterial.color, equals(Colors.cyan));
expect(subMenuMaterial.shape, equals(const BeveledRectangleBorder()));
final Finder menuItem = findSubMenuItem();
expect(tester.getRect(menuItem.first), equals(const Rect.fromLTRB(350.0, 74.0, 580.0, 122.0)));
expect(tester.getRect(menuItem.first), equals(const Rect.fromLTRB(346.0, 74.0, 560.0, 122.0)));
final Material menuItemMaterial = tester.widget<Material>(
find.ancestor(of: find.text(TestMenu.subMenu10.label), matching: find.byType(Material)).first);
expect(menuItemMaterial.color, equals(Colors.amber));
......
......@@ -1685,6 +1685,62 @@ void main() {
expect(controller.value, <MaterialState>{MaterialState.disabled});
expect(count, 1);
});
testWidgets('icon color can be different from the text color', (WidgetTester tester) async {
final Key iconButtonKey = UniqueKey();
const ColorScheme colorScheme = ColorScheme.light();
final ThemeData theme = ThemeData.from(colorScheme: colorScheme);
await tester.pumpWidget(
MaterialApp(
theme: theme,
home: Center(
child: TextButton.icon(
key: iconButtonKey,
style: TextButton.styleFrom(iconColor: Colors.red),
icon: const Icon(Icons.add),
onPressed: () {},
label: const Text('button'),
),
),
),
);
Finder buttonMaterial = find.descendant(
of: find.byKey(iconButtonKey),
matching: find.byType(Material),
);
Material material = tester.widget<Material>(buttonMaterial);
expect(material.textStyle!.color, colorScheme.primary);
Color? iconColor() => _iconStyle(tester, Icons.add)?.color;
expect(iconColor(), equals(Colors.red));
// disabled button
await tester.pumpWidget(
MaterialApp(
theme: theme,
home: Center(
child: TextButton.icon(
key: iconButtonKey,
style: TextButton.styleFrom(iconColor: Colors.red, disabledIconColor: Colors.blue),
icon: const Icon(Icons.add),
onPressed: null,
label: const Text('button'),
),
),
),
);
buttonMaterial = find.descendant(
of: find.byKey(iconButtonKey),
matching: find.byType(Material),
);
material = tester.widget<Material>(buttonMaterial);
expect(material.textStyle!.color, colorScheme.onSurface.withOpacity(0.38));
expect(iconColor(), equals(Colors.blue));
});
}
TextStyle? _iconStyle(WidgetTester tester, IconData icon) {
......
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