Commit 13f3a9be authored by Hixie's avatar Hixie

Give type arguments to routes.

These end up not actually being used, currently, because we don't have
generic methods, which you'd need for showDialog() and friends, and we
don't have any way to parameterise a class type at runtime, which you'd
need for MaterialApp routes, but it's a step in the right direction.
parent dc23af9f
......@@ -115,8 +115,8 @@ class Dialog extends StatelessComponent {
}
}
class _DialogRoute extends ModalRoute {
_DialogRoute({ Completer completer, this.child }) : super(completer: completer);
class _DialogRoute<T> extends ModalRoute<T> {
_DialogRoute({ Completer<T> completer, this.child }) : super(completer: completer);
final Widget child;
......
......@@ -36,7 +36,7 @@ class _MaterialPageTransition extends TransitionWithChild {
}
}
class MaterialPageRoute extends ModalRoute {
class MaterialPageRoute<T> extends ModalRoute<T> {
MaterialPageRoute({
this.builder,
NamedRouteSettings settings: const NamedRouteSettings()
......
......@@ -5,10 +5,10 @@
import 'framework.dart';
import 'overlay.dart';
abstract class Route {
abstract class Route<T> {
List<OverlayEntry> get overlayEntries;
void didPush(OverlayState overlay, OverlayEntry insertionPoint) { }
void didPop(dynamic result) { }
void didPop(T result) { }
/// The given route has been pushed onto the navigator after this route.
/// Return true if the route before this one should be notified also. The
......@@ -140,6 +140,9 @@ class NavigatorState extends State<Navigator> {
/// Do not use this for ModalRoutes, or indeed anything other than
/// StateRoutes. Doing so would cause very odd results, e.g. ModalRoutes would
/// get confused about who is current.
///
/// The type of the result argument, if provided, must match the type argument
/// of the class of the given route. (In practice, this is usually "dynamic".)
void remove(Route route, [dynamic result]) {
assert(_modal.contains(route));
assert(route.overlayEntries.isEmpty);
......@@ -155,6 +158,10 @@ class NavigatorState extends State<Navigator> {
/// Removes the current route, notifying the observer (if any), and the
/// previous routes (using [Route.didPopNext]).
///
/// The type of the result argument, if provided, must match the type argument
/// of the class of the current route. (In practice, this is usually
/// "dynamic".)
void pop([dynamic result]) {
setState(() {
// We use setState to guarantee that we'll rebuild, since the routes can't
......
......@@ -23,6 +23,7 @@ class StateRoute extends Route {
List<OverlayEntry> get overlayEntries => const <OverlayEntry>[];
void didPop(dynamic result) {
assert(result == null);
if (onPop != null)
onPop();
}
......@@ -31,7 +32,7 @@ class StateRoute extends Route {
bool didPopNext(Route nextRoute) => true;
}
abstract class OverlayRoute extends Route {
abstract class OverlayRoute<T> extends Route<T> {
List<WidgetBuilder> get builders => const <WidgetBuilder>[];
List<OverlayEntry> get overlayEntries => _overlayEntries;
......@@ -46,7 +47,7 @@ abstract class OverlayRoute extends Route {
}
// Subclasses shouldn't call this if they want to delay the finished() call.
void didPop(dynamic result) {
void didPop(T result) {
finished();
}
......@@ -64,11 +65,15 @@ abstract class OverlayRoute extends Route {
}
}
// TODO(abarth): Should we add a type for the result?
abstract class TransitionRoute extends OverlayRoute {
TransitionRoute({ this.completer });
abstract class TransitionRoute<T> extends OverlayRoute<T> {
TransitionRoute({
Completer<T> popCompleter,
Completer<T> transitionCompleter
}) : _popCompleter = popCompleter,
_transitionCompleter = transitionCompleter;
final Completer completer;
final Completer<T> _popCompleter;
final Completer<T> _transitionCompleter;
Duration get transitionDuration;
bool get opaque;
......@@ -82,7 +87,7 @@ abstract class TransitionRoute extends OverlayRoute {
return new Performance(duration: duration, debugLabel: debugLabel);
}
dynamic _result;
T _result;
void _handleStatusChanged(PerformanceStatus status) {
switch (status) {
......@@ -97,7 +102,6 @@ abstract class TransitionRoute extends OverlayRoute {
break;
case PerformanceStatus.dismissed:
super.finished(); // clear the overlays
completer?.complete(_result);
break;
}
}
......@@ -109,9 +113,15 @@ abstract class TransitionRoute extends OverlayRoute {
super.didPush(overlay, insertionPoint);
}
void didPop(dynamic result) {
void didPop(T result) {
_result = result;
_performance.reverse();
_popCompleter?.complete(_result);
}
void finished() {
super.finished();
_transitionCompleter?.complete(_result);
}
String get debugLabel => '$runtimeType';
......@@ -202,11 +212,11 @@ class ModalPosition {
final double left;
}
abstract class ModalRoute extends TransitionRoute {
abstract class ModalRoute<T> extends TransitionRoute<T> {
ModalRoute({
Completer completer,
Completer<T> completer,
this.settings: const NamedRouteSettings()
}) : super(completer: completer);
}) : super(popCompleter: completer);
// The API for general users of this class
......@@ -263,7 +273,7 @@ abstract class ModalRoute extends TransitionRoute {
super.didPush(overlay, insertionPoint);
}
void didPop(dynamic result) {
void didPop(T result) {
assert(_isCurrent);
_isCurrent = false;
super.didPop(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