blob: f8a7bbcafd480ec2cea8d91ad67c1bc4c56b20b7 [file] [log] [blame]
// 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';
abstract class GlobalKeyWatcher extends StatefulComponent {
GlobalKeyWatcher({
Key key,
this.watchedKey
});
GlobalKey watchedKey;
void syncConstructorArguments(GlobalKeyWatcher source) {
if (source != source.watchedKey) {
_removeListeners();
watchedKey = source.watchedKey;
_addListeners();
}
}
void didMount() {
super.didMount();
_addListeners();
}
void didUnmount() {
super.didUnmount();
_removeListeners();
}
void didSyncWatchedKey(GlobalKey key, Widget widget) {
assert(key == watchedKey);
}
void didRemoveWatchedKey(GlobalKey key) {
assert(key == watchedKey);
}
void _addListeners() {
GlobalKey.registerSyncListener(watchedKey, didSyncWatchedKey);
GlobalKey.registerRemoveListener(watchedKey, didRemoveWatchedKey);
}
void _removeListeners() {
GlobalKey.unregisterSyncListener(watchedKey, didSyncWatchedKey);
GlobalKey.unregisterRemoveListener(watchedKey, didRemoveWatchedKey);
}
}
typedef MimicReadyCallback();
class Mimic extends GlobalKeyWatcher {
Mimic({
Key key,
GlobalKey original,
this.onMimicReady
}) : super(key: key, watchedKey: original);
MimicReadyCallback onMimicReady;
void syncConstructorArguments(Mimic source) {
onMimicReady = source.onMimicReady;
super.syncConstructorArguments(source);
}
Mimicable _mimicable;
void didMount() {
super.didMount();
if (_mimicable == null)
_setMimicable(GlobalKey.getWidget(watchedKey));
}
void didUnmount() {
super.didUnmount();
if (_mimicable != null) {
_mimicable.stopMimic();
_mimicable = null;
}
}
void didSyncWatchedKey(GlobalKey key, Widget widget) {
super.didSyncWatchedKey(key, widget);
_setMimicable(widget);
}
void didRemoveWatchedKey(GlobalKey key) {
super.didRemoveWatchedKey(key);
_setMimicable(null);
}
void _setMimicable(widget) {
if (_mimicable == null && widget != null)
widget.startMimic();
setState(() {
_mimicable = widget;
});
if (onMimicReady != null && _mimicable != null && _mimicable._didBuildPlaceholder)
onMimicReady();
}
Widget build() {
if (_mimicable == null || !_mimicable._didBuildPlaceholder)
return new Container();
return _mimicable.child;
}
}
class Mimicable extends StatefulComponent {
Mimicable({ GlobalKey key, this.child }) : super(key: key);
Widget child;
Size _size;
Size get size => _size;
void syncConstructorArguments(Mimicable source) {
child = source.child;
}
bool _didBuildPlaceholder = false;
Rect get globalBounds {
if (_size == null)
return null;
return localToGlobal(Point.origin) & _size;
}
bool _mimicRequested = false;
void startMimic() {
assert(!_mimicRequested);
setState(() {
_mimicRequested = true;
});
}
void stopMimic() {
assert(_mimicRequested);
setState(() {
_mimicRequested = false;
});
}
void _handleSizeChanged(Size size) {
setState(() {
_size = size;
});
}
Widget build() {
_didBuildPlaceholder = _mimicRequested && _size != null;
if (_didBuildPlaceholder) {
return new ConstrainedBox(
constraints: new BoxConstraints.tight(_size)
);
}
return new SizeObserver(
callback: _handleSizeChanged,
child: child
);
}
}