Commit 0c6e3416 authored by Hixie's avatar Hixie

Canceling a dropdown menu selects null value

Previously we didn't distinguish between canceling the menu (which
popped the route with no return value, i.e. null) and explicitly
selecting an item whose value is null (pop with value null). Both fired
onChange(null).

Now we box the return value so we can distinguish the two cases.

I would have preferred to just disallow "null" as a value but it turns
out people like being able to use "null" as a value for much the same
reason we do, and it seems best for us to pay the complexity cost of
boxing than having everyone else do it. :-)
parent 09ab8050
......@@ -95,7 +95,10 @@ class _DropDownMenu<T> extends StatusTransitionComponent {
padding: _kMenuHorizontalPadding,
child: route.items[itemIndex]
),
onTap: () => Navigator.pop(context, route.items[itemIndex].value)
onTap: () => Navigator.pop(
context,
new _DropDownRouteResult<T>(route.items[itemIndex].value)
)
)
));
}
......@@ -143,9 +146,24 @@ class _DropDownMenu<T> extends StatusTransitionComponent {
}
}
class _DropDownRoute<T> extends PopupRoute<T> {
// We box the return value so that the return value can be null. Otherwise,
// canceling the route (which returns null) would get confused with actually
// returning a real null value.
class _DropDownRouteResult<T> {
const _DropDownRouteResult(this.result);
final T result;
bool operator ==(dynamic other) {
if (other is! _DropDownRouteResult)
return false;
final _DropDownRouteResult<T> typedOther = other;
return result == typedOther.result;
}
int get hashCode => result.hashCode;
}
class _DropDownRoute<T> extends PopupRoute<_DropDownRouteResult<T>> {
_DropDownRoute({
Completer<T> completer,
Completer<_DropDownRouteResult<T>> completer,
this.items,
this.selectedIndex,
this.rect,
......@@ -246,7 +264,7 @@ class _DropDownButtonState<T> extends State<DropDownButton<T>> {
void _handleTap() {
final RenderBox renderBox = indexedStackKey.currentContext.findRenderObject();
final Rect rect = renderBox.localToGlobal(Point.origin) & renderBox.size;
final Completer completer = new Completer<T>();
final Completer completer = new Completer<_DropDownRouteResult<T>>();
Navigator.push(context, new _DropDownRoute<T>(
completer: completer,
items: config.items,
......@@ -254,11 +272,11 @@ class _DropDownButtonState<T> extends State<DropDownButton<T>> {
rect: _kMenuHorizontalPadding.inflateRect(rect),
elevation: config.elevation
));
completer.future.then((T newValue) {
if (!mounted)
completer.future.then((_DropDownRouteResult<T> newValue) {
if (!mounted || newValue == null)
return;
if (config.onChanged != null)
config.onChanged(newValue);
config.onChanged(newValue.result);
});
}
......
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