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 'package:flutter/material.dart';
6///
7/// @docImport 'icon.dart';
8/// @docImport 'image_icon.dart';
9library;
10
11import 'package:flutter/foundation.dart';
12
13import 'basic.dart';
14import 'framework.dart';
15import 'icon_theme_data.dart';
16import 'inherited_theme.dart';
17
18// Examples can assume:
19// late BuildContext context;
20
21/// Controls the default properties of icons in a widget subtree.
22///
23/// The icon theme is honored by [Icon] and [ImageIcon] widgets.
24class IconTheme extends InheritedTheme {
25 /// Creates an icon theme that controls properties of descendant widgets.
26 const IconTheme({super.key, required this.data, required super.child});
27
28 /// Creates an icon theme that controls the properties of
29 /// descendant widgets, and merges in the current icon theme, if any.
30 static Widget merge({Key? key, required IconThemeData data, required Widget child}) {
31 return Builder(
32 builder: (BuildContext context) {
33 return IconTheme(
34 key: key,
35 data: _getInheritedIconThemeData(context).merge(data),
36 child: child,
37 );
38 },
39 );
40 }
41
42 /// The set of properties to use for icons in this subtree.
43 final IconThemeData data;
44
45 /// The data from the closest instance of this class that encloses the given
46 /// context, if any.
47 ///
48 /// If there is no ambient icon theme, defaults to [IconThemeData.fallback].
49 /// The returned [IconThemeData] is concrete (all values are non-null; see
50 /// [IconThemeData.isConcrete]). Any properties on the ambient icon theme that
51 /// are null get defaulted to the values specified on
52 /// [IconThemeData.fallback].
53 ///
54 /// The [Theme] widget from the `material` library introduces an [IconTheme]
55 /// widget set to the [ThemeData.iconTheme], so in a Material Design
56 /// application, this will typically default to the icon theme from the
57 /// ambient [Theme].
58 ///
59 /// Typical usage is as follows:
60 ///
61 /// ```dart
62 /// IconThemeData theme = IconTheme.of(context);
63 /// ```
64 static IconThemeData of(BuildContext context) {
65 final IconThemeData iconThemeData = _getInheritedIconThemeData(context).resolve(context);
66 return iconThemeData.isConcrete
67 ? iconThemeData
68 : iconThemeData.copyWith(
69 size: iconThemeData.size ?? const IconThemeData.fallback().size,
70 fill: iconThemeData.fill ?? const IconThemeData.fallback().fill,
71 weight: iconThemeData.weight ?? const IconThemeData.fallback().weight,
72 grade: iconThemeData.grade ?? const IconThemeData.fallback().grade,
73 opticalSize: iconThemeData.opticalSize ?? const IconThemeData.fallback().opticalSize,
74 color: iconThemeData.color ?? const IconThemeData.fallback().color,
75 opacity: iconThemeData.opacity ?? const IconThemeData.fallback().opacity,
76 shadows: iconThemeData.shadows ?? const IconThemeData.fallback().shadows,
77 applyTextScaling:
78 iconThemeData.applyTextScaling ?? const IconThemeData.fallback().applyTextScaling,
79 );
80 }
81
82 static IconThemeData _getInheritedIconThemeData(BuildContext context) {
83 final IconTheme? iconTheme = context.dependOnInheritedWidgetOfExactType<IconTheme>();
84 return iconTheme?.data ?? const IconThemeData.fallback();
85 }
86
87 @override
88 bool updateShouldNotify(IconTheme oldWidget) => data != oldWidget.data;
89
90 @override
91 Widget wrap(BuildContext context, Widget child) {
92 return IconTheme(data: data, child: child);
93 }
94
95 @override
96 void debugFillProperties(DiagnosticPropertiesBuilder properties) {
97 super.debugFillProperties(properties);
98 data.debugFillProperties(properties);
99 }
100}
101