icon_theme_data.dart 6.9 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
  }

  /// 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
79
  /// icon theme is null, 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
    return IconThemeData(
171 172 173 174 175
      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),
176 177
      color: Color.lerp(a?.color, b?.color, t),
      opacity: ui.lerpDouble(a?.opacity, b?.opacity, t),
178
      shadows: Shadow.lerpList(a?.shadows, b?.shadows, t),
179 180 181
    );
  }

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

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

210
  @override
211 212
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
213 214 215 216 217
    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));
218
    properties.add(ColorProperty('color', color, defaultValue: null));
219
    properties.add(DoubleProperty('opacity', opacity, defaultValue: null));
220
    properties.add(IterableProperty<Shadow>('shadows', shadows, defaultValue: null));
221
  }
Adam Barth's avatar
Adam Barth committed
222
}