Commit b003fc89 authored by Adam Barth's avatar Adam Barth

Merge pull request #1875 from abarth/page_storage

Add PageStorage support to Navigator2
parents fca9b8f3 4877c061
......@@ -8,6 +8,7 @@ import 'basic.dart';
import 'framework.dart';
import 'navigator2.dart';
import 'overlay.dart';
import 'page_storage.dart';
import 'transitions.dart';
// TODO(abarth): Should we add a type for the result?
......@@ -81,8 +82,9 @@ class _PageState extends State<_Page> {
Widget build(BuildContext context) {
if (config.route._offstage) {
return new OffStage(
child: new KeyedSubtree(
child: new PageStorage(
key: _subtreeKey,
bucket: config.route._storageBucket,
child: _invokeBuilder()
)
);
......@@ -93,8 +95,9 @@ class _PageState extends State<_Page> {
child: new FadeTransition(
performance: config.route.performance,
opacity: _opacity,
child: new KeyedSubtree(
child: new PageStorage(
key: _subtreeKey,
bucket: config.route._storageBucket,
child: _invokeBuilder()
)
)
......@@ -132,6 +135,8 @@ class PageRoute extends TransitionRoute {
Duration get transitionDuration => const Duration(milliseconds: 150);
List<Widget> createWidgets() => [ new _Page(key: pageKey, route: this) ];
final PageStorageBucket _storageBucket = new PageStorageBucket();
bool get offstage => _offstage;
bool _offstage = false;
void set offstage (bool value) {
......
// 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 'framework.dart';
class _StorageEntryIdentifier {
Type clientType;
List<Key> keys;
void addKey(Key key) {
assert(key != null);
assert(key is! GlobalKey);
keys ??= <Key>[];
keys.add(key);
}
GlobalKey scopeKey;
bool operator ==(dynamic other) {
if (other is! _StorageEntryIdentifier)
return false;
final _StorageEntryIdentifier typedOther = other;
if (clientType != typedOther.clientType ||
scopeKey != typedOther.scopeKey ||
keys?.length != typedOther.keys?.length)
return false;
if (keys != null) {
for (int index = 0; index < keys.length; index += 1) {
if (keys[index] != typedOther.keys[index])
return false;
}
}
return true;
}
int get hashCode {
int value = 373;
value = 37 * value + clientType.hashCode;
value = 37 * value + scopeKey.hashCode;
if (keys != null) {
for (Key key in keys)
value = 37 * value + key.hashCode;
}
return value;
}
}
class PageStorageBucket {
_StorageEntryIdentifier _computeStorageIdentifier(BuildContext context) {
_StorageEntryIdentifier result = new _StorageEntryIdentifier();
result.clientType = context.widget.runtimeType;
Key lastKey = context.widget.key;
if (lastKey is! GlobalKey) {
context.visitAncestorElements((Element element) {
if (element.widget.key is GlobalKey) {
lastKey = element.widget.key;
return false;
} else if (element.widget.key != null) {
result.addKey(element.widget.key);
}
return true;
});
return result;
}
assert(lastKey is GlobalKey);
result.scopeKey = lastKey;
return result;
}
Map<_StorageEntryIdentifier, dynamic> _storage;
void writeState(BuildContext context, dynamic data) {
_storage ??= <_StorageEntryIdentifier, dynamic>{};
_storage[_computeStorageIdentifier(context)] = data;
}
dynamic readState(BuildContext context) {
return _storage != null ? _storage[_computeStorageIdentifier(context)] : null;
}
}
class PageStorage extends StatelessComponent {
PageStorage({
Key key,
this.child,
this.bucket
}) : super(key: key);
final Widget child;
final PageStorageBucket bucket;
/// Might return null if there is no PageStorage in this context.
static PageStorageBucket of(BuildContext context) {
PageStorageBucket result;
context.visitAncestorElements((Element element) {
Widget widget = element.widget;
if (widget is PageStorage) {
result = widget.bucket;
return false;
}
return true;
});
return result;
}
Widget build(BuildContext context) => child;
}
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