icon_theme_data.dart 6.93 KB
Newer Older
Ian Hickson's avatar
Ian Hickson committed
1
// Copyright 2014 The Flutter Authors. All rights reserved.
Adam Barth's avatar
Adam Barth committed
2 3 4
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5
import 'dart:ui' as ui show lerpDouble;
Adam Barth's avatar
Adam Barth committed
6

7
import 'package:flutter/foundation.dart';
8
import 'package:flutter/painting.dart';
9

10 11
import 'framework.dart' show BuildContext;

12
/// Defines the size, font variations, color, opacity, and shadows of icons.
13
///
14
/// Used by [IconTheme] to control those properties in a widget subtree.
Ian Hickson's avatar
Ian Hickson committed
15 16
///
/// To obtain the current icon theme, use [IconTheme.of]. To convert an icon
17 18
/// theme to a version with all the fields filled in, use
/// [IconThemeData.fallback].
19
@immutable
20
class IconThemeData with Diagnosticable {
21 22
  /// Creates an icon theme data.
  ///
23 24
  /// The opacity applies to both explicit and default icon colors. The value
  /// is clamped between 0.0 and 1.0.
25 26 27 28 29 30 31 32 33 34 35 36 37
  const IconThemeData({
    this.size,
    this.fill,
    this.weight,
    this.grade,
    this.opticalSize,
    this.color,
    double? opacity,
    this.shadows,
  }) : _opacity = opacity,
       assert(fill == null || (0.0 <= fill && fill <= 1.0)),
       assert(weight == null || (0.0 < weight)),
       assert(opticalSize == null || (0.0 < opticalSize));
Ian Hickson's avatar
Ian Hickson committed
38

39
  /// Creates an icon theme with some reasonable default values.
40
  ///
41 42
  /// The [size] is 24.0, [fill] is 0.0, [weight] is 400.0, [grade] is 0.0,
  /// opticalSize is 48.0, [color] is black, and [opacity] is 1.0.
43
  const IconThemeData.fallback()
44 45 46 47 48 49
      : size = 24.0,
        fill = 0.0,
        weight = 400.0,
        grade = 0.0,
        opticalSize = 48.0,
        color = const Color(0xFF000000),
50 51
        _opacity = 1.0,
        shadows = null;
52

Ian Hickson's avatar
Ian Hickson committed
53 54
  /// Creates a copy of this icon theme but with the given fields replaced with
  /// the new values.
55 56 57 58 59 60 61 62 63 64
  IconThemeData copyWith({
    double? size,
    double? fill,
    double? weight,
    double? grade,
    double? opticalSize,
    Color? color,
    double? opacity,
    List<Shadow>? shadows,
  }) {
65
    return IconThemeData(
66 67 68 69 70
      size: size ?? this.size,
      fill: fill ?? this.fill,
      weight: weight ?? this.weight,
      grade: grade ?? this.grade,
      opticalSize: opticalSize ?? this.opticalSize,
71 72
      color: color ?? this.color,
      opacity: opacity ?? this.opacity,
73
      shadows: shadows ?? this.shadows,
74
    );
Ian Hickson's avatar
Ian Hickson committed
75 76 77 78 79
  }

  /// Returns a new icon theme that matches this icon theme but with some values
  /// replaced by the non-null parameters of the given icon theme. If the given
  /// icon theme is null, simply returns this icon theme.
80
  IconThemeData merge(IconThemeData? other) {
81
    if (other == null) {
Ian Hickson's avatar
Ian Hickson committed
82
      return this;
83
    }
84
    return copyWith(
85 86 87 88 89
      size: other.size,
      fill: other.fill,
      weight: other.weight,
      grade: other.grade,
      opticalSize: other.opticalSize,
90 91
      color: other.color,
      opacity: other.opacity,
92
      shadows: other.shadows,
93
    );
Ian Hickson's avatar
Ian Hickson committed
94 95
  }

96 97 98 99 100 101 102 103 104 105 106 107 108 109
  /// Called by [IconTheme.of] to convert this instance to an [IconThemeData]
  /// that fits the given [BuildContext].
  ///
  /// This method gives the ambient [IconThemeData] a chance to update itself,
  /// after it's been retrieved by [IconTheme.of], and before being returned as
  /// the final result. For instance, [CupertinoIconThemeData] overrides this method
  /// to resolve [color], in case [color] is a [CupertinoDynamicColor] and needs
  /// to be resolved against the given [BuildContext] before it can be used as a
  /// regular [Color].
  ///
  /// The default implementation returns this [IconThemeData] as-is.
  ///
  /// See also:
  ///
110
  ///  * [CupertinoIconThemeData.resolve] an implementation that resolves
111
  ///    the color of [CupertinoIconThemeData] before returning.
112 113
  IconThemeData resolve(BuildContext context) => this;

114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
  /// Whether all the properties (except shadows) of this object are non-null.
  bool get isConcrete => size != null
    && fill != null
    && weight != null
    && grade != null
    && opticalSize != null
    && color != null
    && opacity != null;

  /// The default for [Icon.size].
  ///
  /// Falls back to 24.0.
  final double? size;

  /// The default for [Icon.fill].
  ///
  /// Falls back to 0.0.
  final double? fill;

  /// The default for [Icon.weight].
  ///
  /// Falls back to 400.0.
  final double? weight;

  /// The default for [Icon.grade].
  ///
  /// Falls back to 0.0.
  final double? grade;

  /// The default for [Icon.opticalSize].
  ///
  /// Falls back to 48.0.
  final double? opticalSize;
147

148 149 150 151 152 153 154
  /// The default for [Icon.color].
  ///
  /// In material apps, if there is a [Theme] without any [IconTheme]s
  /// specified, icon colors default to white if [ThemeData.brightness] is dark
  /// and black if [ThemeData.brightness] is light.
  ///
  /// Otherwise, falls back to black.
155
  final Color? color;
Adam Barth's avatar
Adam Barth committed
156 157

  /// An opacity to apply to both explicit and default icon colors.
158 159
  ///
  /// Falls back to 1.0.
160
  double? get opacity => _opacity == null ? null : clampDouble(_opacity!, 0.0, 1.0);
161
  final double? _opacity;
Adam Barth's avatar
Adam Barth committed
162

163
  /// The default for [Icon.shadows].
164 165
  final List<Shadow>? shadows;

166
  /// Linearly interpolate between two icon theme data objects.
167
  ///
168
  /// {@macro dart.ui.shadow.lerp}
169
  static IconThemeData lerp(IconThemeData? a, IconThemeData? b, double t) {
170
    assert(t != null);
171
    return IconThemeData(
172 173 174 175 176
      size: ui.lerpDouble(a?.size, b?.size, t),
      fill: ui.lerpDouble(a?.fill, b?.fill, t),
      weight: ui.lerpDouble(a?.weight, b?.weight, t),
      grade: ui.lerpDouble(a?.grade, b?.grade, t),
      opticalSize: ui.lerpDouble(a?.opticalSize, b?.opticalSize, t),
177 178
      color: Color.lerp(a?.color, b?.color, t),
      opacity: ui.lerpDouble(a?.opacity, b?.opacity, t),
179
      shadows: Shadow.lerpList(a?.shadows, b?.shadows, t),
180 181 182
    );
  }

183
  @override
184
  bool operator ==(Object other) {
185
    if (other.runtimeType != runtimeType) {
Adam Barth's avatar
Adam Barth committed
186
      return false;
187
    }
188
    return other is IconThemeData
189 190 191 192 193
        && other.size == size
        && other.fill == fill
        && other.weight == weight
        && other.grade == grade
        && other.opticalSize == opticalSize
194 195
        && other.color == color
        && other.opacity == opacity
196
        && listEquals(other.shadows, shadows);
Adam Barth's avatar
Adam Barth committed
197 198
  }

199
  @override
200
  int get hashCode => Object.hash(
201 202 203 204 205
    size,
    fill,
    weight,
    grade,
    opticalSize,
206 207 208 209
    color,
    opacity,
    shadows == null ? null : Object.hashAll(shadows!),
  );
Adam Barth's avatar
Adam Barth committed
210

211
  @override
212 213
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
214 215 216 217 218
    properties.add(DoubleProperty('size', size, defaultValue: null));
    properties.add(DoubleProperty('fill', fill, defaultValue: null));
    properties.add(DoubleProperty('weight', weight, defaultValue: null));
    properties.add(DoubleProperty('grade', grade, defaultValue: null));
    properties.add(DoubleProperty('opticalSize', opticalSize, defaultValue: null));
219
    properties.add(ColorProperty('color', color, defaultValue: null));
220
    properties.add(DoubleProperty('opacity', opacity, defaultValue: null));
221
    properties.add(IterableProperty<Shadow>('shadows', shadows, defaultValue: null));
222
  }
Adam Barth's avatar
Adam Barth committed
223
}