diff --git a/packages/flutter/lib/src/fn3/framework.dart b/packages/flutter/lib/src/fn3/framework.dart index 99d9d1d74b..7c6df961c9 100644 --- a/packages/flutter/lib/src/fn3/framework.dart +++ b/packages/flutter/lib/src/fn3/framework.dart @@ -298,6 +298,8 @@ abstract class State { /// The context in which this object will be built BuildContext get context => _element; + bool get mounted => _element != null; + /// Called when this object is inserted into the tree. Override this function /// to perform initialization that depends on the location at which this /// object was inserted into the tree or on the widget configuration object. diff --git a/packages/flutter/lib/src/fn3/mimic.dart b/packages/flutter/lib/src/fn3/mimic.dart new file mode 100644 index 0000000000..b331366e1d --- /dev/null +++ b/packages/flutter/lib/src/fn3/mimic.dart @@ -0,0 +1,87 @@ +// 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/rendering.dart'; +import 'package:sky/src/fn3/basic.dart'; +import 'package:sky/src/fn3/framework.dart'; + +class MimicableKey { + MimicableKey._(this._state); + + final MimicableState _state; + + Rect get globalBounds => _state._globalBounds; + + void stopMimic() { + _state._stopMimic(); + } +} + +class Mimic extends StatelessComponent { + Mimic({ Key key, this.original }) : super(key: key); + + final MimicableKey original; + + Widget build(BuildContext context) { + if (original != null && original._state._beingMimicked) + return original._state.config.child; + return new Container(); + } +} + +class Mimicable extends StatefulComponent { + Mimicable({ Key key, this.child }) : super(key: key); + + final Widget child; + + MimicableState createState() => new MimicableState(); +} + +class MimicableState extends State { + Size _size; + bool _beingMimicked = false; + + MimicableKey startMimic() { + assert(!_beingMimicked); + assert(_size != null); + setState(() { + _beingMimicked = true; + }); + return new MimicableKey._(this); + } + + void _stopMimic() { + assert(!_beingMimicked); + if (!mounted) { + _beingMimicked = false; + return; + } + setState(() { + _beingMimicked = false; + }); + } + + Rect get _globalBounds { + RenderBox box = context.findRenderObject(); + return box.localToGlobal(Point.origin) & box.size; + } + + void _handleSizeChanged(Size size) { + setState(() { + _size = size; + }); + } + + Widget build(BuildContext context) { + if (_beingMimicked) { + return new ConstrainedBox( + constraints: new BoxConstraints.tight(_size) + ); + } + return new SizeObserver( + callback: _handleSizeChanged, + child: config.child + ); + } +}