Commit 6e2d6549 authored by Hans Muller's avatar Hans Muller

Merge pull request #2311 from HansMuller/menu_divider

Added PopupMenuDivider, Divider

Added a Divider class and replaced uses of DrawerDivider with it.

Popup menus are now lists of PopupMenuEntry items. PopupMenuItem and PopupMenuDivider are PopupMenuEntry subclasses.

PopupMenuDivider builds a Divider.
parents 52a24840 d8eaac42
......@@ -111,7 +111,7 @@ class MenuDemoState extends State<MenuDemo> {
primary: new Text('An item with a sectioned menu'),
right: new PopupMenuButton<String>(
onSelected: showMenuSelection,
items: <PopupMenuItem>[
items: <PopupMenuEntry<String>>[
new PopupMenuItem(
value: 'Preview',
child: new ListItem(
......@@ -128,12 +128,12 @@ class MenuDemoState extends State<MenuDemo> {
),
new PopupMenuItem(
value: 'Get Link',
hasDivider: true,
child: new ListItem(
left: new Icon(icon: 'content/link'),
primary: new Text('Get Link')
)
),
new PopupMenuDivider(),
new PopupMenuItem(
value: 'Remove',
child: new ListItem(
......
......@@ -56,7 +56,7 @@ class GalleryDrawer extends StatelessComponent {
]
)
),
new DrawerDivider(),
new Divider(),
new DrawerItem(
icon: 'action/hourglass_empty',
selected: timeDilation != 1.0,
......
......@@ -169,7 +169,7 @@ class StockHomeState extends State<StockHome> {
},
child: new Text('Dump App to Console')
),
new DrawerDivider(),
new Divider(),
new DrawerItem(
icon: 'action/thumb_up',
onPressed: () => _handleStockModeChange(StockMode.optimistic),
......@@ -190,7 +190,7 @@ class StockHomeState extends State<StockHome> {
]
)
),
new DrawerDivider(),
new Divider(),
new DrawerItem(
icon: 'action/settings',
onPressed: _handleShowSettings,
......
......@@ -128,20 +128,20 @@ class CardCollectionState extends State<CardCollection> {
buildDrawerCheckbox("Fixed size cards", _fixedSizeCards, _toggleFixedSizeCards),
buildDrawerCheckbox("Let the sun shine", _sunshine, _toggleSunshine),
buildDrawerCheckbox("Vary font sizes", _varyFontSizes, _toggleVaryFontSizes, enabled: !_editable),
new DrawerDivider(),
new Divider(),
buildDrawerColorRadioItem("Deep Purple", Colors.deepPurple, _primaryColor, _selectColor),
buildDrawerColorRadioItem("Green", Colors.green, _primaryColor, _selectColor),
buildDrawerColorRadioItem("Amber", Colors.amber, _primaryColor, _selectColor),
buildDrawerColorRadioItem("Teal", Colors.teal, _primaryColor, _selectColor),
new DrawerDivider(),
new Divider(),
buildDrawerDirectionRadioItem("Dismiss horizontally", DismissDirection.horizontal, _dismissDirection, _changeDismissDirection, icon: 'action/code'),
buildDrawerDirectionRadioItem("Dismiss left", DismissDirection.left, _dismissDirection, _changeDismissDirection, icon: 'navigation/arrow_back'),
buildDrawerDirectionRadioItem("Dismiss right", DismissDirection.right, _dismissDirection, _changeDismissDirection, icon: 'navigation/arrow_forward'),
new DrawerDivider(),
new Divider(),
buildFontRadioItem("Left-align text", new TextStyle(textAlign: TextAlign.left), _textStyle, _changeTextStyle, icon: 'editor/format_align_left', enabled: !_editable),
buildFontRadioItem("Center-align text", new TextStyle(textAlign: TextAlign.center), _textStyle, _changeTextStyle, icon: 'editor/format_align_center', enabled: !_editable),
buildFontRadioItem("Right-align text", new TextStyle(textAlign: TextAlign.right), _textStyle, _changeTextStyle, icon: 'editor/format_align_right', enabled: !_editable),
new DrawerDivider(),
new Divider(),
new DrawerItem(
icon: 'device/dvr',
onPressed: () { debugDumpApp(); debugDumpRenderTree(); },
......
......@@ -20,9 +20,9 @@ export 'src/material/date_picker.dart';
export 'src/material/date_picker_dialog.dart';
export 'src/material/dialog.dart';
export 'src/material/drawer.dart';
export 'src/material/drawer_divider.dart';
export 'src/material/drawer_header.dart';
export 'src/material/drawer_item.dart';
export 'src/material/divider.dart';
export 'src/material/dropdown.dart';
export 'src/material/flat_button.dart';
export 'src/material/flexible_space_bar.dart';
......
......@@ -6,20 +6,29 @@ import 'package:flutter/widgets.dart';
import 'theme.dart';
class DrawerDivider extends StatelessComponent {
const DrawerDivider({ Key key }) : super(key: key);
class Divider extends StatelessComponent {
Divider({ Key key, this.height: 16.0, this.indent: 0.0, this.color }) : super(key: key) {
assert(height >= 1.0);
}
final double height;
final double indent;
final Color color;
Widget build(BuildContext context) {
final double bottom = (height ~/ 2.0).toDouble();
return new Container(
height: 0.0,
margin: new EdgeDims.only(
top: height - bottom - 1.0,
left: indent,
bottom: bottom
),
decoration: new BoxDecoration(
border: new Border(
bottom: new BorderSide(
color: Theme.of(context).dividerColor
)
bottom: new BorderSide(color: color ?? Theme.of(context).dividerColor)
)
),
margin: const EdgeDims.symmetric(vertical: 8.0)
)
);
}
}
......@@ -6,6 +6,7 @@ import 'dart:async';
import 'package:flutter/widgets.dart';
import 'divider.dart';
import 'icon.dart';
import 'icon_button.dart';
import 'icon_theme.dart';
......@@ -26,20 +27,36 @@ const double _kMenuVerticalPadding = 8.0;
const double _kMenuWidthStep = 56.0;
const double _kMenuScreenPadding = 8.0;
class PopupMenuItem<T> extends StatelessComponent {
abstract class PopupMenuEntry<T> extends StatelessComponent {
PopupMenuEntry({ Key key }) : super(key: key);
double get height;
T get value => null;
bool get enabled => true;
}
class PopupMenuDivider extends PopupMenuEntry<dynamic> {
PopupMenuDivider({ Key key, this.height: 16.0 }) : super(key: key);
final double height;
Widget build(BuildContext context) => new Divider(height: height);
}
class PopupMenuItem<T> extends PopupMenuEntry<T> {
PopupMenuItem({
Key key,
this.value,
this.enabled: true,
this.hasDivider: false,
this.child
}) : super(key: key);
final T value;
final bool enabled;
final bool hasDivider;
final Widget child;
double get height => _kMenuItemHeight;
Widget build(BuildContext context) {
final ThemeData theme = Theme.of(context);
TextStyle style = theme.text.subhead;
......@@ -49,7 +66,7 @@ class PopupMenuItem<T> extends StatelessComponent {
Widget item = new DefaultTextStyle(
style: style,
child: new Baseline(
baseline: _kMenuItemHeight - _kBaselineOffsetFromBottom,
baseline: height - _kBaselineOffsetFromBottom,
child: child
)
);
......@@ -63,11 +80,8 @@ class PopupMenuItem<T> extends StatelessComponent {
return new MergeSemantics(
child: new Container(
height: _kMenuItemHeight,
height: height,
padding: const EdgeDims.symmetric(horizontal: _kMenuHorizontalPadding),
decoration: !hasDivider ? null : new BoxDecoration(
border: new Border(bottom: new BorderSide(color: theme.dividerColor))
),
child: item
)
);
......@@ -172,10 +186,10 @@ class _PopupMenu<T> extends StatelessComponent {
}
class _PopupMenuRouteLayout extends OneChildLayoutDelegate {
_PopupMenuRouteLayout(this.position, this.selectedIndex);
_PopupMenuRouteLayout(this.position, this.selectedItemOffset);
final ModalPosition position;
final int selectedIndex;
final double selectedItemOffset;
BoxConstraints getConstraintsForChild(BoxConstraints constraints) {
return new BoxConstraints(
......@@ -195,8 +209,8 @@ class _PopupMenuRouteLayout extends OneChildLayoutDelegate {
double y = position?.top
?? (position?.bottom != null ? size.height - (position.bottom - childSize.height) : _kMenuScreenPadding);
if (selectedIndex != -1)
y -= (_kMenuItemHeight * selectedIndex) + _kMenuVerticalPadding + _kMenuItemHeight / 2.0;
if (selectedItemOffset != null)
y -= selectedItemOffset + _kMenuVerticalPadding + _kMenuItemHeight / 2.0;
if (x < _kMenuScreenPadding)
x = _kMenuScreenPadding;
......@@ -224,7 +238,7 @@ class _PopupMenuRoute<T> extends PopupRoute<T> {
}) : super(completer: completer);
final ModalPosition position;
final List<PopupMenuItem<T>> items;
final List<PopupMenuEntry<T>> items;
final dynamic initialValue;
final int elevation;
......@@ -242,19 +256,20 @@ class _PopupMenuRoute<T> extends PopupRoute<T> {
Color get barrierColor => null;
Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> forwardAnimation) {
int selectedIndex = -1;
double selectedItemOffset = null;
if (initialValue != null) {
for (int i = 0; i < items.length; i++)
if (initialValue == items[i].value) {
selectedIndex = i;
selectedItemOffset = 0.0;
for (int i = 0; i < items.length; i++) {
if (initialValue == items[i].value)
break;
}
selectedItemOffset += items[i].height;
}
}
final Size screenSize = MediaQuery.of(context).size;
return new ConstrainedBox(
constraints: new BoxConstraints(maxWidth: screenSize.width, maxHeight: screenSize.height),
child: new CustomOneChildLayout(
delegate: new _PopupMenuRouteLayout(position, selectedIndex),
delegate: new _PopupMenuRouteLayout(position, selectedItemOffset),
child: new _PopupMenu(route: this)
)
);
......@@ -269,7 +284,7 @@ class _PopupMenuRoute<T> extends PopupRoute<T> {
Future/*<T>*/ showMenu/*<T>*/({
BuildContext context,
ModalPosition position,
List<PopupMenuItem/*<T>*/> items,
List<PopupMenuEntry/*<T>*/> items,
dynamic/*=T*/ initialValue,
int elevation: 8
}) {
......@@ -305,7 +320,7 @@ class PopupMenuButton<T> extends StatefulComponent {
this.child
}) : super(key: key);
final List<PopupMenuItem<T>> items;
final List<PopupMenuEntry<T>> items;
final T initialValue;
final PopupMenuItemSelected<T> onSelected;
final String tooltip;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment