| // 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 'input_decorator.dart'; |
| import 'menu_style.dart'; |
| import 'theme.dart'; |
| |
| // Examples can assume: |
| // late BuildContext context; |
| |
| /// Overrides the default values of visual properties for descendant [DropdownMenu] widgets. |
| /// |
| /// Descendant widgets obtain the current [DropdownMenuThemeData] object with |
| /// [DropdownMenuTheme.of]. Instances of [DropdownMenuTheme] can |
| /// be customized with [DropdownMenuThemeData.copyWith]. |
| /// |
| /// Typically a [DropdownMenuTheme] is specified as part of the overall [Theme] with |
| /// [ThemeData.dropdownMenuTheme]. |
| /// |
| /// All [DropdownMenuThemeData] properties are null by default. When null, the [DropdownMenu] |
| /// computes its own default values, typically based on the overall |
| /// theme's [ThemeData.colorScheme], [ThemeData.textTheme], and [ThemeData.iconTheme]. |
| @immutable |
| class DropdownMenuThemeData with Diagnosticable { |
| /// Creates a [DropdownMenuThemeData] that can be used to override default properties |
| /// in a [DropdownMenuTheme] widget. |
| const DropdownMenuThemeData({ |
| this.textStyle, |
| this.inputDecorationTheme, |
| this.menuStyle, |
| }); |
| |
| /// Overrides the default value for [DropdownMenu.textStyle]. |
| final TextStyle? textStyle; |
| |
| /// The input decoration theme for the [TextField]s in a [DropdownMenu]. |
| /// |
| /// If this is null, the [DropdownMenu] provides its own defaults. |
| final InputDecorationTheme? inputDecorationTheme; |
| |
| /// Overrides the menu's default style in a [DropdownMenu]. |
| /// |
| /// Any values not set in the [MenuStyle] will use the menu default for that |
| /// property. |
| final MenuStyle? menuStyle; |
| |
| /// Creates a copy of this object with the given fields replaced with the |
| /// new values. |
| DropdownMenuThemeData copyWith({ |
| TextStyle? textStyle, |
| InputDecorationTheme? inputDecorationTheme, |
| MenuStyle? menuStyle, |
| }) { |
| return DropdownMenuThemeData( |
| textStyle: textStyle ?? this.textStyle, |
| inputDecorationTheme: inputDecorationTheme ?? this.inputDecorationTheme, |
| menuStyle: menuStyle ?? this.menuStyle, |
| ); |
| } |
| |
| /// Linearly interpolates between two dropdown menu themes. |
| static DropdownMenuThemeData lerp(DropdownMenuThemeData? a, DropdownMenuThemeData? b, double t) { |
| if (identical(a, b) && a != null) { |
| return a; |
| } |
| return DropdownMenuThemeData( |
| textStyle: TextStyle.lerp(a?.textStyle, b?.textStyle, t), |
| inputDecorationTheme: t < 0.5 ? a?.inputDecorationTheme : b?.inputDecorationTheme, |
| menuStyle: MenuStyle.lerp(a?.menuStyle, b?.menuStyle, t), |
| ); |
| } |
| |
| @override |
| int get hashCode => Object.hash( |
| textStyle, |
| inputDecorationTheme, |
| menuStyle, |
| ); |
| |
| @override |
| bool operator ==(Object other) { |
| if (identical(this, other)) { |
| return true; |
| } |
| if (other.runtimeType != runtimeType) { |
| return false; |
| } |
| return other is DropdownMenuThemeData |
| && other.textStyle == textStyle |
| && other.inputDecorationTheme == inputDecorationTheme |
| && other.menuStyle == menuStyle; |
| } |
| |
| @override |
| void debugFillProperties(DiagnosticPropertiesBuilder properties) { |
| super.debugFillProperties(properties); |
| properties.add(DiagnosticsProperty<TextStyle>('textStyle', textStyle, defaultValue: null)); |
| properties.add(DiagnosticsProperty<InputDecorationTheme>('inputDecorationTheme', inputDecorationTheme, defaultValue: null)); |
| properties.add(DiagnosticsProperty<MenuStyle>('menuStyle', menuStyle, defaultValue: null)); |
| } |
| } |
| |
| /// An inherited widget that defines the visual properties for [DropdownMenu]s in this widget's subtree. |
| /// |
| /// Values specified here are used for [DropdownMenu] properties that are not |
| /// given an explicit non-null value. |
| class DropdownMenuTheme extends InheritedTheme { |
| /// Creates a [DropdownMenuTheme] that controls visual parameters for |
| /// descendant [DropdownMenu]s. |
| const DropdownMenuTheme({ |
| super.key, |
| required this.data, |
| required super.child, |
| }); |
| |
| /// Specifies the visual properties used by descendant [DropdownMenu] |
| /// widgets. |
| final DropdownMenuThemeData data; |
| |
| /// The closest instance of this class that encloses the given context. |
| /// |
| /// If there is no enclosing [DropdownMenuTheme] widget, then |
| /// [ThemeData.dropdownMenuTheme] is used. |
| /// |
| /// Typical usage is as follows: |
| /// |
| /// ```dart |
| /// DropdownMenuThemeData theme = DropdownMenuTheme.of(context); |
| /// ``` |
| /// |
| /// See also: |
| /// |
| /// * [maybeOf], which returns null if it doesn't find a |
| /// [DropdownMenuTheme] ancestor. |
| static DropdownMenuThemeData of(BuildContext context) { |
| return maybeOf(context) ?? Theme.of(context).dropdownMenuTheme; |
| } |
| |
| /// The data from the closest instance of this class that encloses the given |
| /// context, if any. |
| /// |
| /// Use this function if you want to allow situations where no |
| /// [DropdownMenuTheme] is in scope. Prefer using [DropdownMenuTheme.of] |
| /// in situations where a [DropdownMenuThemeData] is expected to be |
| /// non-null. |
| /// |
| /// If there is no [DropdownMenuTheme] in scope, then this function will |
| /// return null. |
| /// |
| /// Typical usage is as follows: |
| /// |
| /// ```dart |
| /// DropdownMenuThemeData? theme = DropdownMenuTheme.maybeOf(context); |
| /// if (theme == null) { |
| /// // Do something else instead. |
| /// } |
| /// ``` |
| /// |
| /// See also: |
| /// |
| /// * [of], which will return [ThemeData.dropdownMenuTheme] if it doesn't |
| /// find a [DropdownMenuTheme] ancestor, instead of returning null. |
| static DropdownMenuThemeData? maybeOf(BuildContext context) { |
| return context.dependOnInheritedWidgetOfExactType<DropdownMenuTheme>()?.data; |
| } |
| |
| @override |
| Widget wrap(BuildContext context, Widget child) { |
| return DropdownMenuTheme(data: data, child: child); |
| } |
| |
| @override |
| bool updateShouldNotify(DropdownMenuTheme oldWidget) => data != oldWidget.data; |
| } |