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 {
child: new Icon(type: 'image/photo_camera', size: 24),
backgroundColor: Theme.of(this).accentColor,
onPressed: () {
showDialog = true;
navigator.pushState(this, (_) {
showDialog = false;
});
navigator.push(new DialogRoute(builder: (navigator, route) {
return 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();
}
),
]
);
}));
}
);
}
......@@ -104,47 +124,15 @@ class AddressBookApp extends App {
);
}
bool showDialog = false;
Widget buildMain(Navigator navigator) {
List<Widget> layers = [
new Focus(
initialFocus: nameKey,
child: new Scaffold(
toolbar: buildToolBar(navigator),
body: buildBody(navigator),
floatingActionButton: buildFloatingActionButton(navigator)
)
return new Focus(
initialFocus: nameKey,
child: new Scaffold(
toolbar: buildToolBar(navigator),
body: buildBody(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;
......
......@@ -18,8 +18,6 @@ class StockSettings extends StatefulComponent {
BackupMode backup;
SettingsUpdater updater;
bool _showModeDialog = false;
void syncFields(StockSettings source) {
navigator = source.navigator;
optimism = source.optimism;
......@@ -47,10 +45,26 @@ class StockSettings extends StatefulComponent {
_handleOptimismChanged(false);
break;
case StockMode.pessimistic:
_showModeDialog = true;
navigator.pushState(this, (_) {
_showModeDialog = false;
});
navigator.push(new DialogRoute(builder: (navigator, route) {
return 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();
}
),
]
);
}));
break;
}
}
......@@ -104,32 +118,9 @@ class StockSettings extends StatefulComponent {
}
Widget build() {
List<Widget> layers = [
new Scaffold(
toolbar: buildToolBar(),
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);
return new Scaffold(
toolbar: buildToolBar(),
body: buildSettingsPane()
);
}
}
......@@ -46,14 +46,11 @@ class Dialog extends Component {
}
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) {
children.add(new Padding(
dialogBody.add(new Padding(
padding: new EdgeDims(24.0, 24.0, content == null ? 20.0 : 0.0, 24.0),
child: new DefaultTextStyle(
style: Theme.of(this).text.title,
......@@ -63,7 +60,7 @@ class Dialog extends Component {
}
if (content != null) {
children.add(new Padding(
dialogBody.add(new Padding(
padding: const EdgeDims(20.0, 24.0, 24.0, 24.0),
child: new DefaultTextStyle(
style: Theme.of(this).text.subhead,
......@@ -73,11 +70,15 @@ class Dialog extends Component {
}
if (actions != null)
children.add(new Flex(actions, justifyContent: FlexJustifyContent.end));
dialogBody.add(new Flex(actions, justifyContent: FlexJustifyContent.end));
return new Stack([
new Listener(
child: mask,
child: new Container(
decoration: const BoxDecoration(
backgroundColor: const Color(0x7F000000)
)
),
onGestureTap: (_) => onDismiss()
),
new Center(
......@@ -89,12 +90,13 @@ class Dialog extends Component {
level: 4,
color: _color,
child: new ShrinkWrapWidth(
child: new ScrollableBlock(children)
child: new ScrollableBlock(dialogBody)
)
)
)
)
)
]);
}
}
......@@ -9,22 +9,40 @@ import 'package:sky/widgets/animated_component.dart';
import 'package:sky/widgets/basic.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 {
Widget build(Navigator navigator, RouteBase route);
bool get isOpaque;
void popState() { }
}
class Route extends RouteBase {
Route({ this.name, this.builder });
final String name;
final Builder builder;
final RouteBuilder builder;
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 });
Function callback;
......@@ -32,6 +50,7 @@ class RouteState extends RouteBase {
StatefulComponent owner;
Widget build(Navigator navigator, RouteBase route) => null;
bool get isOpaque => false;
void popState() {
if (callback != null)
......@@ -52,7 +71,7 @@ class Transition extends AnimatedComponent {
this.onDismissed,
this.onCompleted,
this.interactive
}) : super(key: key);
}): super(key: key);
Widget content;
TransitionDirection direction;
bool interactive;
......@@ -145,7 +164,7 @@ class Transition extends AnimatedComponent {
class HistoryEntry {
HistoryEntry({ this.route });
final RouteBase route;
bool transitionFinished = false;
bool fullyOpaque = false;
// TODO(jackson): Keep track of the requested transition
}
......@@ -182,7 +201,7 @@ class NavigationState {
if (historyIndex > 0) {
HistoryEntry entry = history[historyIndex];
entry.route.popState();
entry.transitionFinished = false;
entry.fullyOpaque = false;
historyIndex--;
}
}
......@@ -231,7 +250,7 @@ class Navigator extends StatefulComponent {
List<Widget> visibleRoutes = new List<Widget>();
for (int i = 0; i < state.history.length; i++) {
// 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;
HistoryEntry historyEntry = state.history[i];
Widget content = historyEntry.route.build(this, historyEntry.route);
......@@ -253,7 +272,7 @@ class Navigator extends StatefulComponent {
},
onCompleted: () {
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