2018-02-05 12:59:45 -08:00

255 lines
8.5 KiB
Dart

// Copyright 2015 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 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'theme.dart';
/// Used with [ButtonTheme] and [ButtonThemeData] to define a button's base
/// colors, and the defaults for the button's minimum size, internal padding,
/// and shape.
///
/// See also:
///
/// * [RaisedButton], which styles itself based on the ambient [ButtonTheme].
/// * [FlatButton], which styles itself based on the ambient [ButtonTheme].
enum ButtonTextTheme {
/// Button text is black or white depending on [ThemeData.brightness].
normal,
/// Button text is [ThemeData.accentColor].
accent,
/// Button text is based on [ThemeData.primaryColor].
primary,
}
/// Used with [ButtonThemeData] to configure the color and geometry of buttons.
///
/// A button theme can be specified as part of the overall Material theme
/// using [ThemeData.buttomTheme]. The Material theme's button theme data
/// can be overridden with [ButtonTheme].
///
/// The actual appearance of buttons depends on the button theme, the
/// button's enabled state, its elevation (if any) and the overall Material
/// theme.
///
/// See also:
///
/// * [FlatButton] and [RaisedButton], which are styled based on the
/// ambient button theme.
/// * [ThemeData.textTheme], `button` is the default text style for button labels.
/// * [ThemeData.buttonColor], the fill color for [RaisedButton]s unless the
/// button theme's text theme is [ButtonTextTheme.primary].
/// * [ThemeData.primaryColor], the fill or text color if a button theme's text
/// theme is [ButtonTextTheme.primary].
/// * [ThemeData.accentColor], the text color for buttons when button theme's
/// text theme is [ButtonTextTheme.accent].
/// * [ThemeData.disabled], the default text color for disabled buttons.
/// * [ThemeData.brightness], used to select contrasting text and fill colors.
/// * [ThemeData.highlightColor], a button [InkWell]'s default highlight color.
/// * [ThemeData.splashColor], a button [InkWell]'s default splash color.
/// * [RawMaterialButton], which can be used to configure a button that doesn't
/// depend on any inherited themes.
class ButtonTheme extends InheritedWidget {
/// Creates a button theme.
///
/// The [textTheme], [minWidth], and [height] arguments must not be null.
ButtonTheme({
Key key,
ButtonTextTheme textTheme: ButtonTextTheme.normal,
double minWidth: 88.0,
double height: 36.0,
EdgeInsetsGeometry padding,
ShapeBorder shape,
Widget child,
}) : assert(textTheme != null),
assert(minWidth != null && minWidth >= 0.0),
assert(height != null && height >= 0.0),
data = new ButtonThemeData(
textTheme: textTheme,
minWidth: minWidth,
height: height,
padding: padding,
shape: shape,
),
super(key: key, child: child);
/// Creates a button theme that is appropriate for button bars, as used in
/// dialog footers and in the headers of data tables.
///
/// This theme is denser, with a smaller [minWidth] and [padding], than the
/// default theme. Also, this theme uses [ButtonTextTheme.accent] rather than
/// [ButtonTextTheme.normal].
///
/// For best effect, the label of the button at the edge of the container
/// should have text that ends up wider than 64.0 pixels. This ensures that
/// the alignment of the text matches the alignment of the edge of the
/// container.
///
/// For example, buttons at the bottom of [Dialog] or [Card] widgets use this
/// button theme.
ButtonTheme.bar({
Key key,
ButtonTextTheme textTheme: ButtonTextTheme.accent,
double minWidth: 64.0,
double height: 36.0,
EdgeInsetsGeometry padding: const EdgeInsets.symmetric(horizontal: 8.0),
ShapeBorder shape,
Widget child,
}) : assert(textTheme != null),
assert(minWidth != null && minWidth >= 0.0),
assert(height != null && height >= 0.0),
data = new ButtonThemeData(
textTheme: textTheme,
minWidth: minWidth,
height: height,
padding: padding,
shape: shape,
),
super(key: key, child: child);
/// Specifies the color and geometry of buttons.
final ButtonThemeData data;
/// The closest instance of this class that encloses the given context.
///
/// Typical usage is as follows:
///
/// ```dart
/// ButtonThemeData theme = ButtonTheme.of(context);
/// ```
static ButtonThemeData of(BuildContext context) {
final ButtonTheme result = context.inheritFromWidgetOfExactType(ButtonTheme);
return result?.data ?? Theme.of(context).buttonTheme;
}
@override
bool updateShouldNotify(ButtonTheme oldTheme) => data != oldTheme.data;
}
/// Used with [ButtonTheme] to configure the color and geometry of buttons.
///
/// A button theme can be specified as part of the overall Material theme
/// using [ThemeData.buttomTheme]. The Material theme's button theme data
/// can be overridden with [ButtonTheme].
class ButtonThemeData {
/// Create a button theme object that can be used with [ButtonTheme]
/// or [ThemeData].
///
/// The [textTheme], [minWidth], and [height] parameters must not be null.
const ButtonThemeData({
this.textTheme: ButtonTextTheme.normal,
this.minWidth: 88.0,
this.height: 36.0,
EdgeInsetsGeometry padding,
ShapeBorder shape,
}) : assert(textTheme != null),
assert(minWidth != null && minWidth >= 0.0),
assert(height != null && height >= 0.0),
_padding = padding,
_shape = shape;
/// The minimum width for buttons.
///
/// The actual horizontal space allocated for a button's child is
/// at least this value less the theme's horizontal [padding].
///
/// Defaults to 88.0 logical pixels.
final double minWidth;
/// The minimum height for buttons.
///
/// Defaults to 36.0 logical pixels.
final double height;
/// Defines a button's base colors, and the defaults for the button's minimum
/// size, internal padding, and shape.
final ButtonTextTheme textTheme;
/// Simply a convenience that returns [minWidth] and [height] as a
/// [BoxConstraints] object:
/// ```dart
/// return new BoxConstraints(
/// minWidth: minWidth,
/// minHeight: height,
/// );
/// ```
BoxConstraints get constraints {
return new BoxConstraints(
minWidth: minWidth,
minHeight: height,
);
}
/// Padding for a button's child (typically the button's label).
///
/// Defaults to 24.0 on the left and right if [textTheme] is
/// [ButtonTextTheme.primary], 16.0 on the left and right otherwise.
EdgeInsetsGeometry get padding {
if (_padding != null)
return _padding;
switch (textTheme) {
case ButtonTextTheme.normal:
case ButtonTextTheme.accent:
return const EdgeInsets.symmetric(horizontal: 16.0);
case ButtonTextTheme.primary:
return const EdgeInsets.symmetric(horizontal: 24.0);
}
return EdgeInsets.zero;
}
final EdgeInsetsGeometry _padding;
/// The shape of a button's material.
///
/// The button's highlight and splash are clipped to this shape. If the
/// button has an elevation, then its drop shadow is defined by this
/// shape as well.
///
/// Defaults to a rounded rectangle with circular corner radii of 4.0 if
/// [textTheme] is [ButtonTextTheme.primary], a rounded rectangle with
/// circular corner radii of 2.0 otherwise.
ShapeBorder get shape {
if (_shape != null)
return _shape;
switch (textTheme) {
case ButtonTextTheme.normal:
case ButtonTextTheme.accent:
return const RoundedRectangleBorder(
borderRadius: const BorderRadius.all(const Radius.circular(2.0)),
);
case ButtonTextTheme.primary:
return const RoundedRectangleBorder(
borderRadius: const BorderRadius.all(const Radius.circular(4.0)),
);
}
return const RoundedRectangleBorder();
}
final ShapeBorder _shape;
@override
bool operator ==(dynamic other) {
if (other.runtimeType != runtimeType)
return false;
final ButtonThemeData typedOther = other;
return textTheme == typedOther.textTheme
&& minWidth == typedOther.minWidth
&& height == typedOther.height
&& padding == typedOther.padding
&& shape == typedOther.shape;
}
@override
int get hashCode {
return hashValues(
textTheme,
minWidth,
height,
padding,
shape,
);
}
}