Commit 051655fa authored by Ian Hickson's avatar Ian Hickson

Merge pull request #278 from Hixie/nav-dialogs

Use the navigator to stack dialogs.
parents db63850e ac6342ab
...@@ -68,10 +68,30 @@ class AddressBookApp extends App { ...@@ -68,10 +68,30 @@ class AddressBookApp extends App {
child: new Icon(type: 'image/photo_camera', size: 24), child: new Icon(type: 'image/photo_camera', size: 24),
backgroundColor: Theme.of(this).accentColor, backgroundColor: Theme.of(this).accentColor,
onPressed: () { onPressed: () {
showDialog = true; navigator.push(new DialogRoute(builder: (navigator, route) {
navigator.pushState(this, (_) { return new Dialog(
showDialog = false; title: new Text("Describe your picture"),
}); content: new ScrollableBlock([
new Field(inputKey: fillKey, icon: "editor/format_color_fill", placeholder: "Color"),
new Field(inputKey: emoticonKey, icon: "editor/insert_emoticon", placeholder: "Emotion"),
]),
onDismiss: navigator.pop,
actions: [
new FlatButton(
child: new Text('DISCARD'),
onPressed: () {
navigator.pop();
}
),
new FlatButton(
child: new Text('SAVE'),
onPressed: () {
navigator.pop();
}
),
]
);
}));
} }
); );
} }
...@@ -104,47 +124,15 @@ class AddressBookApp extends App { ...@@ -104,47 +124,15 @@ class AddressBookApp extends App {
); );
} }
bool showDialog = false;
Widget buildMain(Navigator navigator) { Widget buildMain(Navigator navigator) {
List<Widget> layers = [ return new Focus(
new Focus( initialFocus: nameKey,
initialFocus: nameKey, child: new Scaffold(
child: new Scaffold( toolbar: buildToolBar(navigator),
toolbar: buildToolBar(navigator), body: buildBody(navigator),
body: buildBody(navigator), floatingActionButton: buildFloatingActionButton(navigator)
floatingActionButton: buildFloatingActionButton(navigator)
)
) )
]; );
if (showDialog) {
layers.add(new Focus(
initialFocus: fillKey,
child: new Dialog(
title: new Text("Describe your picture"),
content: new ScrollableBlock([
new Field(inputKey: fillKey, icon: "editor/format_color_fill", placeholder: "Color"),
new Field(inputKey: emoticonKey, icon: "editor/insert_emoticon", placeholder: "Emotion"),
]),
onDismiss: navigator.pop,
actions: [
new FlatButton(
child: new Text('DISCARD'),
onPressed: () {
navigator.pop();
}
),
new FlatButton(
child: new Text('SAVE'),
onPressed: () {
navigator.pop();
}
),
]
)
));
}
return new Stack(layers);
} }
NavigationState _navigationState; NavigationState _navigationState;
......
...@@ -18,8 +18,6 @@ class StockSettings extends StatefulComponent { ...@@ -18,8 +18,6 @@ class StockSettings extends StatefulComponent {
BackupMode backup; BackupMode backup;
SettingsUpdater updater; SettingsUpdater updater;
bool _showModeDialog = false;
void syncFields(StockSettings source) { void syncFields(StockSettings source) {
navigator = source.navigator; navigator = source.navigator;
optimism = source.optimism; optimism = source.optimism;
...@@ -47,10 +45,26 @@ class StockSettings extends StatefulComponent { ...@@ -47,10 +45,26 @@ class StockSettings extends StatefulComponent {
_handleOptimismChanged(false); _handleOptimismChanged(false);
break; break;
case StockMode.pessimistic: case StockMode.pessimistic:
_showModeDialog = true; navigator.push(new DialogRoute(builder: (navigator, route) {
navigator.pushState(this, (_) { return new Dialog(
_showModeDialog = false; title: new Text("Change mode?"),
}); content: new Text("Optimistic mode means everything is awesome. Are you sure you can handle that?"),
onDismiss: navigator.pop,
actions: [
new FlatButton(
child: new Text('NO THANKS'),
onPressed: navigator.pop
),
new FlatButton(
child: new Text('AGREE'),
onPressed: () {
_handleOptimismChanged(true);
navigator.pop();
}
),
]
);
}));
break; break;
} }
} }
...@@ -104,32 +118,9 @@ class StockSettings extends StatefulComponent { ...@@ -104,32 +118,9 @@ class StockSettings extends StatefulComponent {
} }
Widget build() { Widget build() {
List<Widget> layers = [ return new Scaffold(
new Scaffold( toolbar: buildToolBar(),
toolbar: buildToolBar(), body: buildSettingsPane()
body: buildSettingsPane() );
)
];
if (_showModeDialog) {
layers.add(new Dialog(
title: new Text("Change mode?"),
content: new Text("Optimistic mode means everything is awesome. Are you sure you can handle that?"),
onDismiss: navigator.pop,
actions: [
new FlatButton(
child: new Text('NO THANKS'),
onPressed: navigator.pop
),
new FlatButton(
child: new Text('AGREE'),
onPressed: () {
_handleOptimismChanged(true);
navigator.pop();
}
),
]
));
}
return new Stack(layers);
} }
} }
...@@ -46,14 +46,11 @@ class Dialog extends Component { ...@@ -46,14 +46,11 @@ class Dialog extends Component {
} }
Widget build() { Widget build() {
Container mask = new Container(
decoration: const BoxDecoration(
backgroundColor: const Color(0x7F000000)));
List<Widget> children = new List<Widget>(); List<Widget> dialogBody = new List<Widget>();
if (title != null) { if (title != null) {
children.add(new Padding( dialogBody.add(new Padding(
padding: new EdgeDims(24.0, 24.0, content == null ? 20.0 : 0.0, 24.0), padding: new EdgeDims(24.0, 24.0, content == null ? 20.0 : 0.0, 24.0),
child: new DefaultTextStyle( child: new DefaultTextStyle(
style: Theme.of(this).text.title, style: Theme.of(this).text.title,
...@@ -63,7 +60,7 @@ class Dialog extends Component { ...@@ -63,7 +60,7 @@ class Dialog extends Component {
} }
if (content != null) { if (content != null) {
children.add(new Padding( dialogBody.add(new Padding(
padding: const EdgeDims(20.0, 24.0, 24.0, 24.0), padding: const EdgeDims(20.0, 24.0, 24.0, 24.0),
child: new DefaultTextStyle( child: new DefaultTextStyle(
style: Theme.of(this).text.subhead, style: Theme.of(this).text.subhead,
...@@ -73,11 +70,15 @@ class Dialog extends Component { ...@@ -73,11 +70,15 @@ class Dialog extends Component {
} }
if (actions != null) if (actions != null)
children.add(new Flex(actions, justifyContent: FlexJustifyContent.end)); dialogBody.add(new Flex(actions, justifyContent: FlexJustifyContent.end));
return new Stack([ return new Stack([
new Listener( new Listener(
child: mask, child: new Container(
decoration: const BoxDecoration(
backgroundColor: const Color(0x7F000000)
)
),
onGestureTap: (_) => onDismiss() onGestureTap: (_) => onDismiss()
), ),
new Center( new Center(
...@@ -89,12 +90,13 @@ class Dialog extends Component { ...@@ -89,12 +90,13 @@ class Dialog extends Component {
level: 4, level: 4,
color: _color, color: _color,
child: new ShrinkWrapWidth( child: new ShrinkWrapWidth(
child: new ScrollableBlock(children) child: new ScrollableBlock(dialogBody)
) )
) )
) )
) )
) )
]); ]);
} }
} }
...@@ -9,22 +9,40 @@ import 'package:sky/widgets/animated_component.dart'; ...@@ -9,22 +9,40 @@ import 'package:sky/widgets/animated_component.dart';
import 'package:sky/widgets/basic.dart'; import 'package:sky/widgets/basic.dart';
import 'package:vector_math/vector_math.dart'; import 'package:vector_math/vector_math.dart';
typedef Widget Builder(Navigator navigator, RouteBase route); typedef Widget RouteBuilder(Navigator navigator, RouteBase route);
abstract class RouteBase { abstract class RouteBase {
Widget build(Navigator navigator, RouteBase route); Widget build(Navigator navigator, RouteBase route);
bool get isOpaque;
void popState() { } void popState() { }
} }
class Route extends RouteBase { class Route extends RouteBase {
Route({ this.name, this.builder }); Route({ this.name, this.builder });
final String name; final String name;
final Builder builder; final RouteBuilder builder;
Widget build(Navigator navigator, RouteBase route) => builder(navigator, route); Widget build(Navigator navigator, RouteBase route) => builder(navigator, route);
bool get isOpaque => true;
} }
class RouteState extends RouteBase { class DialogRoute extends RouteBase {
DialogRoute({ this.builder, this.callback });
final RouteBuilder builder;
Function callback;
Widget build(Navigator navigator, RouteBase route) => builder(navigator, route);
bool get isOpaque => false;
void popState() {
if (callback != null)
callback(this);
}
}
class RouteState extends RouteBase {
RouteState({ this.callback, this.route, this.owner }); RouteState({ this.callback, this.route, this.owner });
Function callback; Function callback;
...@@ -32,6 +50,7 @@ class RouteState extends RouteBase { ...@@ -32,6 +50,7 @@ class RouteState extends RouteBase {
StatefulComponent owner; StatefulComponent owner;
Widget build(Navigator navigator, RouteBase route) => null; Widget build(Navigator navigator, RouteBase route) => null;
bool get isOpaque => false;
void popState() { void popState() {
if (callback != null) if (callback != null)
...@@ -52,7 +71,7 @@ class Transition extends AnimatedComponent { ...@@ -52,7 +71,7 @@ class Transition extends AnimatedComponent {
this.onDismissed, this.onDismissed,
this.onCompleted, this.onCompleted,
this.interactive this.interactive
}) : super(key: key); }): super(key: key);
Widget content; Widget content;
TransitionDirection direction; TransitionDirection direction;
bool interactive; bool interactive;
...@@ -145,7 +164,7 @@ class Transition extends AnimatedComponent { ...@@ -145,7 +164,7 @@ class Transition extends AnimatedComponent {
class HistoryEntry { class HistoryEntry {
HistoryEntry({ this.route }); HistoryEntry({ this.route });
final RouteBase route; final RouteBase route;
bool transitionFinished = false; bool fullyOpaque = false;
// TODO(jackson): Keep track of the requested transition // TODO(jackson): Keep track of the requested transition
} }
...@@ -182,7 +201,7 @@ class NavigationState { ...@@ -182,7 +201,7 @@ class NavigationState {
if (historyIndex > 0) { if (historyIndex > 0) {
HistoryEntry entry = history[historyIndex]; HistoryEntry entry = history[historyIndex];
entry.route.popState(); entry.route.popState();
entry.transitionFinished = false; entry.fullyOpaque = false;
historyIndex--; historyIndex--;
} }
} }
...@@ -231,7 +250,7 @@ class Navigator extends StatefulComponent { ...@@ -231,7 +250,7 @@ class Navigator extends StatefulComponent {
List<Widget> visibleRoutes = new List<Widget>(); List<Widget> visibleRoutes = new List<Widget>();
for (int i = 0; i < state.history.length; i++) { for (int i = 0; i < state.history.length; i++) {
// Avoid building routes that are not visible // Avoid building routes that are not visible
if (i + 1 < state.history.length && state.history[i + 1].transitionFinished) if (i + 1 < state.history.length && state.history[i + 1].fullyOpaque)
continue; continue;
HistoryEntry historyEntry = state.history[i]; HistoryEntry historyEntry = state.history[i];
Widget content = historyEntry.route.build(this, historyEntry.route); Widget content = historyEntry.route.build(this, historyEntry.route);
...@@ -253,7 +272,7 @@ class Navigator extends StatefulComponent { ...@@ -253,7 +272,7 @@ class Navigator extends StatefulComponent {
}, },
onCompleted: () { onCompleted: () {
setState(() { setState(() {
historyEntry.transitionFinished = true; historyEntry.fullyOpaque = historyEntry.route.isOpaque;
}); });
} }
); );
......
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