| // 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/widgets.dart'; |
| |
| import 'colors.dart'; |
| import 'debug.dart'; |
| import 'ink_well.dart'; |
| import 'material.dart'; |
| import 'theme.dart'; |
| |
| enum ButtonColor { normal, accent } |
| |
| class ButtonTheme extends InheritedWidget { |
| ButtonTheme({ |
| Key key, |
| this.color, |
| Widget child |
| }) : super(key: key, child: child) { |
| assert(child != null); |
| } |
| |
| final ButtonColor color; |
| |
| /// The color from the closest instance of this class that encloses the given context. |
| /// |
| /// Defaults to [ButtonColor.normal] if none exists. |
| static ButtonColor of(BuildContext context) { |
| ButtonTheme result = context.inheritFromWidgetOfExactType(ButtonTheme); |
| return result?.color ?? ButtonColor.normal; |
| } |
| |
| bool updateShouldNotify(ButtonTheme old) => color != old.color; |
| } |
| |
| /// Base class for buttons in the Material theme. |
| /// Rather than using this class directly, please use [FlatButton] or [RaisedButton]. |
| /// |
| /// MaterialButtons whose [onPressed] handler is null will be disabled. To have |
| /// an enabled button, make sure to pass a non-null value for onPressed. |
| abstract class MaterialButton extends StatefulComponent { |
| MaterialButton({ |
| Key key, |
| this.child, |
| this.textTheme, |
| this.textColor, |
| this.disabledTextColor, |
| this.onPressed |
| }) : super(key: key); |
| |
| final Widget child; |
| final ButtonColor textTheme; |
| final Color textColor; |
| final Color disabledTextColor; |
| |
| /// The callback that is invoked when the button is tapped or otherwise activated. |
| /// |
| /// If this is set to null, the button will be disabled. |
| final VoidCallback onPressed; |
| |
| /// Whether the button is enabled or disabled. Buttons are disabled by default. To |
| /// enable a button, set its [onPressed] property to a non-null value. |
| bool get enabled => onPressed != null; |
| |
| void debugFillDescription(List<String> description) { |
| super.debugFillDescription(description); |
| if (!enabled) |
| description.add('disabled'); |
| } |
| } |
| |
| abstract class MaterialButtonState<T extends MaterialButton> extends State<T> { |
| bool highlight = false; |
| |
| int get elevation; |
| Color getColor(BuildContext context); |
| ThemeBrightness getColorBrightness(BuildContext context); |
| |
| Color getTextColor(BuildContext context) { |
| if (config.enabled) { |
| if (config.textColor != null) |
| return config.textColor; |
| switch (config.textTheme ?? ButtonTheme.of(context)) { |
| case ButtonColor.accent: |
| return Theme.of(context).accentColor; |
| case ButtonColor.normal: |
| switch (getColorBrightness(context)) { |
| case ThemeBrightness.light: |
| return Colors.black87; |
| case ThemeBrightness.dark: |
| return Colors.white; |
| } |
| } |
| } |
| if (config.disabledTextColor != null) |
| return config.disabledTextColor; |
| switch (getColorBrightness(context)) { |
| case ThemeBrightness.light: |
| return Colors.black26; |
| case ThemeBrightness.dark: |
| return Colors.white30; |
| } |
| } |
| |
| void _handleHighlightChanged(bool value) { |
| setState(() { |
| // mostly just used by the RaisedButton subclass to change the elevation |
| highlight = value; |
| }); |
| } |
| |
| Widget build(BuildContext context) { |
| assert(debugCheckHasMaterial(context)); |
| Widget contents = new InkWell( |
| onTap: config.onPressed, |
| onHighlightChanged: _handleHighlightChanged, |
| child: new Container( |
| padding: new EdgeDims.symmetric(horizontal: 8.0), |
| child: new Center( |
| widthFactor: 1.0, |
| child: config.child |
| ) |
| ) |
| ); |
| TextStyle style = Theme.of(context).text.button.copyWith(color: getTextColor(context)); |
| int elevation = this.elevation; |
| Color color = getColor(context); |
| if (elevation > 0 || color != null) { |
| contents = new Material( |
| type: MaterialType.button, |
| color: getColor(context), |
| elevation: elevation, |
| textStyle: style, |
| child: contents |
| ); |
| } else { |
| contents = new DefaultTextStyle( |
| style: style, |
| child: contents |
| ); |
| } |
| return new Container( |
| height: 36.0, |
| constraints: new BoxConstraints(minWidth: 88.0), |
| padding: const EdgeDims.symmetric(horizontal: 8.0), |
| margin: const EdgeDims.all(8.0), |
| child: contents |
| ); |
| } |
| } |