| // 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:sky/widgets/basic.dart'; |
| |
| typedef Widget Builder(Navigator navigator, RouteBase route); |
| |
| abstract class RouteBase { |
| RouteBase({ this.key }); |
| final Object key; |
| Widget build(Navigator navigator, RouteBase route); |
| void popState() { } |
| } |
| |
| class Route extends RouteBase { |
| Route({ String name, this.builder }) : super(key: name); |
| String get name => key; |
| final Builder builder; |
| Widget build(Navigator navigator, RouteBase route) => builder(navigator, route); |
| } |
| |
| class RouteState extends RouteBase { |
| |
| RouteState({ this.callback, this.route, Object key }) : super(key: key); |
| |
| RouteBase route; |
| Function callback; |
| |
| Widget build(Navigator navigator, _) => route.build(navigator, this); |
| |
| void popState() { |
| if (callback != null) |
| callback(this); |
| } |
| } |
| |
| class NavigationState { |
| |
| NavigationState(List<Route> routes) { |
| for (Route route in routes) { |
| if (route.name != null) |
| namedRoutes[route.name] = route; |
| } |
| history.add(routes[0]); |
| } |
| |
| List<RouteBase> history = new List<RouteBase>(); |
| int historyIndex = 0; |
| Map<String, RouteBase> namedRoutes = new Map<String, RouteBase>(); |
| |
| RouteBase get currentRoute => history[historyIndex]; |
| bool hasPrevious() => historyIndex > 0; |
| bool hasNext() => history.length > historyIndex + 1; |
| |
| void pushNamed(String name) { |
| Route route = namedRoutes[name]; |
| assert(route != null); |
| push(route); |
| } |
| |
| void push(RouteBase route) { |
| // Discard future history |
| history.removeRange(historyIndex + 1, history.length); |
| historyIndex = history.length; |
| history.add(route); |
| } |
| |
| void pop() { |
| if (historyIndex > 0) { |
| history[historyIndex].popState(); |
| history.removeLast(); |
| historyIndex--; |
| } |
| } |
| } |
| |
| class Navigator extends StatefulComponent { |
| |
| Navigator(this.state, { String key }) : super(key: key); |
| |
| NavigationState state; |
| |
| void syncFields(Navigator source) { |
| state = source.state; |
| } |
| |
| RouteBase get currentRoute => state.currentRoute; |
| |
| void pushState(Object key, Function callback) { |
| RouteBase route = new RouteState( |
| key: key, |
| callback: callback, |
| route: state.currentRoute |
| ); |
| push(route); |
| } |
| |
| void pushNamed(String name) { |
| setState(() { |
| state.pushNamed(name); |
| }); |
| } |
| |
| void push(RouteBase route) { |
| setState(() { |
| state.push(route); |
| }); |
| } |
| |
| void pop() { |
| setState(() { |
| state.pop(); |
| }); |
| } |
| |
| Widget build() { |
| return state.currentRoute.build(this, state.currentRoute); |
| } |
| } |