• Greg Spencer's avatar
    Convert Diagnosticable to a mixin (#51495) · 210f4d83
    Greg Spencer authored
    This converts Diagnosticable to be a mixin instead of an abstract class, so that it can be used to add diagnostics to classes which already have a base class.
    
    It leaves in place the DiagnosticableMixin mixin, since there are some plugins that are still using it, and removing it would mean that those plugins wouldn't work with master branch Flutter anymore. DiagnosticableMixin will be removed once this mixin version of Diagnosticable makes its way to the stable branch.
    Unverified
    210f4d83
divider_theme.dart 5.59 KB
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:ui' show lerpDouble;

import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';

import 'theme.dart';

/// Defines the visual properties of [Divider], [VerticalDivider], dividers
/// between [ListTile]s, and dividers between rows in [DataTable]s.
///
/// Descendant widgets obtain the current [DividerThemeData] object using
/// `DividerTheme.of(context)`. Instances of [DividerThemeData]
/// can be customized with [DividerThemeData.copyWith].
///
/// Typically a [DividerThemeData] is specified as part of the overall
/// [Theme] with [ThemeData.dividerTheme].
///
/// All [DividerThemeData] properties are `null` by default. When null,
/// the widgets will provide their own defaults.
///
/// See also:
///
///  * [ThemeData], which describes the overall theme information for the
///    application.
class DividerThemeData with Diagnosticable {

  /// Creates a theme that can be used for [DividerTheme] or
  /// [ThemeData.dividerTheme].
  const DividerThemeData({
    this.color,
    this.space,
    this.thickness,
    this.indent,
    this.endIndent,
  });

  /// The color of [Divider]s and [VerticalDivider]s, also
  /// used between [ListTile]s, between rows in [DataTable]s, and so forth.
  final Color color;

  /// The [Divider]'s width or the [VerticalDivider]'s height.
  ///
  /// This represents the amount of horizontal or vertical space the divider
  /// takes up.
  final double space;

  /// The thickness of the line drawn within the divider.
  final double thickness;

  /// The amount of empty space at the leading edge of [Divider] or top edge of
  /// [VerticalDivider].
  final double indent;

  /// The amount of empty space at the trailing edge of [Divider] or bottom edge
  /// of [VerticalDivider].
  final double endIndent;

  /// Creates a copy of this object with the given fields replaced with the
  /// new values.
  DividerThemeData copyWith({
    Color color,
    double space,
    double thickness,
    double indent,
    double endIndent,
  }) {
    return DividerThemeData(
      color: color ?? this.color,
      space: space ?? this.space,
      thickness: thickness ?? this.thickness,
      indent: indent ?? this.indent,
      endIndent: endIndent ?? this.endIndent,
    );
  }

  /// Linearly interpolate between two Divider themes.
  ///
  /// The argument `t` must not be null.
  ///
  /// {@macro dart.ui.shadow.lerp}
  static DividerThemeData lerp(DividerThemeData a, DividerThemeData b, double t) {
    assert(t != null);
    return DividerThemeData(
      color: Color.lerp(a?.color, b?.color, t),
      space: lerpDouble(a?.space, b?.space, t),
      thickness: lerpDouble(a?.thickness, b?.thickness, t),
      indent: lerpDouble(a?.indent, b?.indent, t),
      endIndent: lerpDouble(a?.endIndent, b?.endIndent, t),
    );
  }

  @override
  int get hashCode {
    return hashValues(
      color,
      space,
      thickness,
      indent,
      endIndent,
    );
  }

  @override
  bool operator ==(Object other) {
    if (identical(this, other))
      return true;
    if (other.runtimeType != runtimeType)
      return false;
    return other is DividerThemeData
        && other.color == color
        && other.space == space
        && other.thickness == thickness
        && other.indent == indent
        && other.endIndent == endIndent;
  }

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(ColorProperty('color', color, defaultValue: null));
    properties.add(DoubleProperty('space', space, defaultValue: null));
    properties.add(DoubleProperty('thickness', thickness, defaultValue: null));
    properties.add(DoubleProperty('indent', indent, defaultValue: null));
    properties.add(DoubleProperty('endIndent', endIndent, defaultValue: null));
  }
}

/// An inherited widget that defines the configuration for
/// [Divider]s, [VerticalDivider]s, dividers between [ListTile]s, and dividers
/// between rows in [DataTable]s in this widget's subtree.
class DividerTheme extends InheritedTheme {
  /// Creates a divider theme that controls the configurations for
  /// [Divider]s, [VerticalDivider]s, dividers between [ListTile]s, and dividers
  /// between rows in [DataTable]s in its widget subtree.
  const DividerTheme({
    Key key,
    @required this.data,
    Widget child,
  }) : assert(data != null),
       super(key: key, child: child);

  /// The properties for descendant [Divider]s, [VerticalDivider]s, dividers
  /// between [ListTile]s, and dividers between rows in [DataTable]s.
  final DividerThemeData data;

  /// The closest instance of this class's [data] value that encloses the given
  /// context.
  ///
  /// If there is no ancestor, it returns [ThemeData.dividerTheme]. Applications
  /// can assume that the returned value will not be null.
  ///
  /// Typical usage is as follows:
  ///
  /// ```dart
  /// DividerThemeData theme = DividerTheme.of(context);
  /// ```
  static DividerThemeData of(BuildContext context) {
    final DividerTheme dividerTheme = context.dependOnInheritedWidgetOfExactType<DividerTheme>();
    return dividerTheme?.data ?? Theme.of(context).dividerTheme;
  }

  @override
  Widget wrap(BuildContext context, Widget child) {
    final DividerTheme ancestorTheme = context.findAncestorWidgetOfExactType<DividerTheme>();
    return identical(this, ancestorTheme) ? child : DividerTheme(data: data, child: child);
  }

  @override
  bool updateShouldNotify(DividerTheme oldWidget) => data != oldWidget.data;
}