// Copyright 2019 The Chromium 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/rendering.dart'; import 'package:flutter/widgets.dart'; import 'theme.dart'; /// Defines the color and border properties of [ToggleButtons] widgets. /// /// Used by [ToggleButtonsTheme] to control the color and border properties /// of toggle buttons in a widget subtree. /// /// To obtain the current [ToggleButtonsTheme], use [ToggleButtonsTheme.of]. /// /// Values specified here are used for [ToggleButtons] properties that are not /// given an explicit non-null value. /// /// See also: /// /// * [ToggleButtonsTheme], which describes the actual configuration of a /// toggle buttons theme. class ToggleButtonsThemeData extends Diagnosticable { /// Creates the set of color and border properties used to configure /// [ToggleButtons]. const ToggleButtonsThemeData({ this.textStyle, this.constraints, this.color, this.selectedColor, this.disabledColor, this.fillColor, this.focusColor, this.highlightColor, this.hoverColor, this.splashColor, this.borderColor, this.selectedBorderColor, this.disabledBorderColor, this.borderRadius, this.borderWidth, }); /// The default text style for [ToggleButtons.children]. /// /// [TextStyle.color] will be ignored and substituted by [color], /// [selectedColor] or [disabledColor] depending on whether the buttons /// are active, selected, or disabled. final TextStyle textStyle; /// Defines the button's size. /// /// Typically used to constrain the button's minimum size. final BoxConstraints constraints; /// The color for descendant [Text] and [Icon] widgets if the toggle button /// is enabled. final Color color; /// The color for descendant [Text] and [Icon] widgets if the toggle button /// is selected. final Color selectedColor; /// The color for descendant [Text] and [Icon] widgets if the toggle button /// is disabled. final Color disabledColor; /// The fill color for selected toggle buttons. final Color fillColor; /// The color to use for filling the button when the button has input focus. final Color focusColor; /// The highlight color for the toggle button's [InkWell]. final Color highlightColor; /// The splash color for the toggle button's [InkWell]. final Color splashColor; /// The color to use for filling the toggle button when the button has a /// pointer hovering over it. final Color hoverColor; /// The border color to display when the toggle button is enabled. final Color borderColor; /// The border color to display when the toggle button is selected. final Color selectedBorderColor; /// The border color to display when the toggle button is disabled. final Color disabledBorderColor; /// The width of the border surrounding each toggle button. /// /// This applies to both the greater surrounding border, as well as the /// borders dividing each toggle button. /// /// To render a hairline border (one physical pixel), set borderWidth to 0.0. /// See [BorderSide.width] for more details on hairline borders. final double borderWidth; /// The radii of the border's corners. final BorderRadius borderRadius; /// Creates a copy of this object but with the given fields replaced with the /// new values. ToggleButtonsThemeData copyWith({ TextStyle textStyle, BoxConstraints constraints, Color color, Color selectedColor, Color disabledColor, Color fillColor, Color focusColor, Color highlightColor, Color hoverColor, Color splashColor, Color borderColor, Color selectedBorderColor, Color disabledBorderColor, BorderRadius borderRadius, double borderWidth, }) { return ToggleButtonsThemeData( textStyle: textStyle ?? this.textStyle, constraints: constraints ?? this.constraints, color: color ?? this.color, selectedColor: selectedColor ?? this.selectedColor, disabledColor: disabledColor ?? this.disabledColor, fillColor: fillColor ?? this.fillColor, focusColor: focusColor ?? this.focusColor, highlightColor: highlightColor ?? this.highlightColor, hoverColor: hoverColor ?? this.hoverColor, splashColor: splashColor ?? this.splashColor, borderColor: borderColor ?? this.borderColor, selectedBorderColor: selectedBorderColor ?? this.selectedBorderColor, disabledBorderColor: disabledBorderColor ?? this.disabledBorderColor, borderRadius: borderRadius ?? this.borderRadius, borderWidth: borderWidth ?? this.borderWidth, ); } /// Linearly interpolate between two toggle buttons themes. static ToggleButtonsThemeData lerp(ToggleButtonsThemeData a, ToggleButtonsThemeData b, double t) { assert (t != null); if (a == null && b == null) return null; return ToggleButtonsThemeData( textStyle: TextStyle.lerp(a?.textStyle, b?.textStyle, t), constraints: BoxConstraints.lerp(a?.constraints, b?.constraints, t), color: Color.lerp(a?.color, b?.color, t), selectedColor: Color.lerp(a?.selectedColor, b?.selectedColor, t), disabledColor: Color.lerp(a?.disabledColor, b?.disabledColor, t), fillColor: Color.lerp(a?.fillColor, b?.fillColor, t), focusColor: Color.lerp(a?.focusColor, b?.focusColor, t), highlightColor: Color.lerp(a?.highlightColor, b?.highlightColor, t), hoverColor: Color.lerp(a?.hoverColor, b?.hoverColor, t), splashColor: Color.lerp(a?.splashColor, b?.splashColor, t), borderColor: Color.lerp(a?.borderColor, b?.borderColor, t), selectedBorderColor: Color.lerp(a?.selectedBorderColor, b?.selectedBorderColor, t), disabledBorderColor: Color.lerp(a?.disabledBorderColor, b?.disabledBorderColor, t), borderRadius: BorderRadius.lerp(a?.borderRadius, b?.borderRadius, t), borderWidth: lerpDouble(a?.borderWidth, b?.borderWidth, t), ); } @override int get hashCode { return hashValues( textStyle, constraints, color, selectedColor, disabledColor, fillColor, focusColor, highlightColor, hoverColor, splashColor, borderColor, selectedBorderColor, disabledBorderColor, borderRadius, borderWidth, ); } @override bool operator ==(Object other) { if (identical(this, other)) return true; if (other.runtimeType != runtimeType) return false; final ToggleButtonsThemeData typedOther = other; return typedOther.textStyle == textStyle && typedOther.constraints == constraints && typedOther.color == color && typedOther.selectedColor == selectedColor && typedOther.disabledColor == disabledColor && typedOther.fillColor == fillColor && typedOther.focusColor == focusColor && typedOther.highlightColor == highlightColor && typedOther.hoverColor == hoverColor && typedOther.splashColor == splashColor && typedOther.borderColor == borderColor && typedOther.selectedBorderColor == selectedBorderColor && typedOther.disabledBorderColor == disabledBorderColor && typedOther.borderRadius == borderRadius && typedOther.borderWidth == borderWidth; } @override void debugFillProperties(DiagnosticPropertiesBuilder properties) { super.debugFillProperties(properties); textStyle?.debugFillProperties(properties, prefix: 'textStyle.'); properties.add(DiagnosticsProperty<BoxConstraints>('constraints', constraints, defaultValue: null)); properties.add(ColorProperty('color', color, defaultValue: null)); properties.add(ColorProperty('selectedColor', selectedColor, defaultValue: null)); properties.add(ColorProperty('disabledColor', disabledColor, defaultValue: null)); properties.add(ColorProperty('fillColor', fillColor, defaultValue: null)); properties.add(ColorProperty('focusColor', focusColor, defaultValue: null)); properties.add(ColorProperty('highlightColor', highlightColor, defaultValue: null)); properties.add(ColorProperty('hoverColor', hoverColor, defaultValue: null)); properties.add(ColorProperty('splashColor', splashColor, defaultValue: null)); properties.add(ColorProperty('borderColor', borderColor, defaultValue: null)); properties.add(ColorProperty('selectedBorderColor', selectedBorderColor, defaultValue: null)); properties.add(ColorProperty('disabledBorderColor', disabledBorderColor, defaultValue: null)); properties.add(DiagnosticsProperty<BorderRadius>('borderRadius', borderRadius, defaultValue: null)); properties.add(DoubleProperty('borderWidth', borderWidth, defaultValue: null)); } } /// An inherited widget that defines color and border parameters for /// [ToggleButtons] in this widget's subtree. /// /// Values specified here are used for [ToggleButtons] properties that are not /// given an explicit non-null value. class ToggleButtonsTheme extends InheritedTheme { /// Creates a toggle buttons theme that controls the color and border /// parameters for [ToggleButtons]. /// /// The data argument must not be null. const ToggleButtonsTheme({ Key key, @required this.data, Widget child, }) : assert(data != null), super(key: key, child: child); /// Specifies the color and border values for descendant [ToggleButtons] widgets. final ToggleButtonsThemeData data; /// The closest instance of this class that encloses the given context. /// /// If there is no enclosing [ToggleButtonsTheme] widget, then /// [ThemeData.toggleButtonsTheme] is used. /// /// Typical usage is as follows: /// /// ```dart /// ToggleButtonsTheme theme = ToggleButtonsTheme.of(context); /// ``` static ToggleButtonsThemeData of(BuildContext context) { final ToggleButtonsTheme toggleButtonsTheme = context.inheritFromWidgetOfExactType(ToggleButtonsTheme); return toggleButtonsTheme?.data ?? Theme.of(context).toggleButtonsTheme; } @override Widget wrap(BuildContext context, Widget child) { final ToggleButtonsTheme ancestorTheme = context.ancestorWidgetOfExactType(ToggleButtonsTheme); return identical(this, ancestorTheme) ? child : ToggleButtonsTheme(data: data, child: child); } @override bool updateShouldNotify(ToggleButtonsTheme oldWidget) => data != oldWidget.data; }