1 | // Copyright 2014 The Flutter Authors. All rights reserved. |
2 | // Use of this source code is governed by a BSD-style license that can be |
3 | // found in the LICENSE file. |
4 | |
5 | /// @docImport 'elevated_button.dart'; |
6 | library; |
7 | |
8 | import 'package:flutter/foundation.dart'; |
9 | import 'package:flutter/widgets.dart'; |
10 | |
11 | import 'button_style.dart'; |
12 | import 'theme.dart'; |
13 | |
14 | // Examples can assume: |
15 | // late BuildContext context; |
16 | |
17 | /// A [ButtonStyle] that overrides the default appearance of |
18 | /// [ElevatedButton]s when it's used with [ElevatedButtonTheme] or with the |
19 | /// overall [Theme]'s [ThemeData.elevatedButtonTheme]. |
20 | /// |
21 | /// The [style]'s properties override [ElevatedButton]'s default style, |
22 | /// i.e. the [ButtonStyle] returned by [ElevatedButton.defaultStyleOf]. Only |
23 | /// the style's non-null property values or resolved non-null |
24 | /// [WidgetStateProperty] values are used. |
25 | /// |
26 | /// See also: |
27 | /// |
28 | /// * [ElevatedButtonTheme], the theme which is configured with this class. |
29 | /// * [ElevatedButton.defaultStyleOf], which returns the default [ButtonStyle] |
30 | /// for text buttons. |
31 | /// * [ElevatedButton.styleFrom], which converts simple values into a |
32 | /// [ButtonStyle] that's consistent with [ElevatedButton]'s defaults. |
33 | /// * [WidgetStateProperty.resolve], "resolve" a material state property |
34 | /// to a simple value based on a set of [WidgetState]s. |
35 | /// * [ThemeData.elevatedButtonTheme], which can be used to override the default |
36 | /// [ButtonStyle] for [ElevatedButton]s below the overall [Theme]. |
37 | @immutable |
38 | class ElevatedButtonThemeData with Diagnosticable { |
39 | /// Creates an [ElevatedButtonThemeData]. |
40 | /// |
41 | /// The [style] may be null. |
42 | const ElevatedButtonThemeData({this.style}); |
43 | |
44 | /// Overrides for [ElevatedButton]'s default style. |
45 | /// |
46 | /// Non-null properties or non-null resolved [WidgetStateProperty] |
47 | /// values override the [ButtonStyle] returned by |
48 | /// [ElevatedButton.defaultStyleOf]. |
49 | /// |
50 | /// If [style] is null, then this theme doesn't override anything. |
51 | final ButtonStyle? style; |
52 | |
53 | /// Linearly interpolate between two elevated button themes. |
54 | static ElevatedButtonThemeData? lerp( |
55 | ElevatedButtonThemeData? a, |
56 | ElevatedButtonThemeData? b, |
57 | double t, |
58 | ) { |
59 | if (identical(a, b)) { |
60 | return a; |
61 | } |
62 | return ElevatedButtonThemeData(style: ButtonStyle.lerp(a?.style, b?.style, t)); |
63 | } |
64 | |
65 | @override |
66 | int get hashCode => style.hashCode; |
67 | |
68 | @override |
69 | bool operator ==(Object other) { |
70 | if (identical(this, other)) { |
71 | return true; |
72 | } |
73 | if (other.runtimeType != runtimeType) { |
74 | return false; |
75 | } |
76 | return other is ElevatedButtonThemeData && other.style == style; |
77 | } |
78 | |
79 | @override |
80 | void debugFillProperties(DiagnosticPropertiesBuilder properties) { |
81 | super.debugFillProperties(properties); |
82 | properties.add(DiagnosticsProperty<ButtonStyle>('style' , style, defaultValue: null)); |
83 | } |
84 | } |
85 | |
86 | /// Overrides the default [ButtonStyle] of its [ElevatedButton] descendants. |
87 | /// |
88 | /// See also: |
89 | /// |
90 | /// * [ElevatedButtonThemeData], which is used to configure this theme. |
91 | /// * [ElevatedButton.defaultStyleOf], which returns the default [ButtonStyle] |
92 | /// for elevated buttons. |
93 | /// * [ElevatedButton.styleFrom], which converts simple values into a |
94 | /// [ButtonStyle] that's consistent with [ElevatedButton]'s defaults. |
95 | /// * [ThemeData.elevatedButtonTheme], which can be used to override the default |
96 | /// [ButtonStyle] for [ElevatedButton]s below the overall [Theme]. |
97 | class ElevatedButtonTheme extends InheritedTheme { |
98 | /// Create a [ElevatedButtonTheme]. |
99 | const ElevatedButtonTheme({super.key, required this.data, required super.child}); |
100 | |
101 | /// The configuration of this theme. |
102 | final ElevatedButtonThemeData data; |
103 | |
104 | /// The closest instance of this class that encloses the given context. |
105 | /// |
106 | /// If there is no enclosing [ElevatedButtonTheme] widget, then |
107 | /// [ThemeData.elevatedButtonTheme] is used. |
108 | /// |
109 | /// Typical usage is as follows: |
110 | /// |
111 | /// ```dart |
112 | /// ElevatedButtonThemeData theme = ElevatedButtonTheme.of(context); |
113 | /// ``` |
114 | static ElevatedButtonThemeData of(BuildContext context) { |
115 | final ElevatedButtonTheme? buttonTheme = |
116 | context.dependOnInheritedWidgetOfExactType<ElevatedButtonTheme>(); |
117 | return buttonTheme?.data ?? Theme.of(context).elevatedButtonTheme; |
118 | } |
119 | |
120 | @override |
121 | Widget wrap(BuildContext context, Widget child) { |
122 | return ElevatedButtonTheme(data: data, child: child); |
123 | } |
124 | |
125 | @override |
126 | bool updateShouldNotify(ElevatedButtonTheme oldWidget) => data != oldWidget.data; |
127 | } |
128 | |