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