Commit 0e11b0e6 authored by Ian Hickson's avatar Ian Hickson

Make the widgets binding reusable. (#3479)

Previously the widgets layer only provided a concrete binding, which
makes it awkward to extend it compared to other bindings. This moves
widgets to the same style as the other layers.

In a subsequent patch I'll use this to make the tests layer saner.
parent cf56caa7
...@@ -89,7 +89,7 @@ void rotate(Duration timeStamp) { ...@@ -89,7 +89,7 @@ void rotate(Duration timeStamp) {
} }
void main() { void main() {
WidgetFlutterBinding.ensureInitialized(); Widgeteer binding = WidgetFlutterBinding.ensureInitialized();
RenderProxyBox proxy = new RenderProxyBox(); RenderProxyBox proxy = new RenderProxyBox();
attachWidgetTreeToRenderTree(proxy); attachWidgetTreeToRenderTree(proxy);
...@@ -101,6 +101,6 @@ void main() { ...@@ -101,6 +101,6 @@ void main() {
transformBox = new RenderTransform(child: flexRoot, transform: new Matrix4.identity()); transformBox = new RenderTransform(child: flexRoot, transform: new Matrix4.identity());
RenderPadding root = new RenderPadding(padding: new EdgeInsets.all(80.0), child: transformBox); RenderPadding root = new RenderPadding(padding: new EdgeInsets.all(80.0), child: transformBox);
WidgetFlutterBinding.instance.renderView.child = root; binding.renderView.child = root;
WidgetFlutterBinding.instance.addPersistentFrameCallback(rotate); binding.addPersistentFrameCallback(rotate);
} }
...@@ -27,14 +27,14 @@ void main() { ...@@ -27,14 +27,14 @@ void main() {
appState = tester.stateOf(find.byType(stocks.StocksApp)); appState = tester.stateOf(find.byType(stocks.StocksApp));
}); });
WidgetFlutterBinding binding = WidgetFlutterBinding.instance; BuildOwner buildOwner = Widgeteer.instance.buildOwner;
Stopwatch watch = new Stopwatch() Stopwatch watch = new Stopwatch()
..start(); ..start();
for (int i = 0; i < _kNumberOfIterations || _kRunForever; ++i) { for (int i = 0; i < _kNumberOfIterations || _kRunForever; ++i) {
appState.setState(_doNothing); appState.setState(_doNothing);
binding.buildOwner.buildDirtyElements(); buildOwner.buildDirtyElements();
} }
watch.stop(); watch.stop();
......
...@@ -24,14 +24,14 @@ void main() { ...@@ -24,14 +24,14 @@ void main() {
ViewConfiguration big = const ViewConfiguration(size: const Size(360.0, 640.0)); ViewConfiguration big = const ViewConfiguration(size: const Size(360.0, 640.0));
ViewConfiguration small = const ViewConfiguration(size: const Size(355.0, 635.0)); ViewConfiguration small = const ViewConfiguration(size: const Size(355.0, 635.0));
RenderView renderView = WidgetFlutterBinding.instance.renderView; RenderView renderView = Widgeteer.instance.renderView;
Stopwatch watch = new Stopwatch() Stopwatch watch = new Stopwatch()
..start(); ..start();
for (int i = 0; i < _kNumberOfIterations || _kRunForever; ++i) { for (int i = 0; i < _kNumberOfIterations || _kRunForever; ++i) {
renderView.configuration = (i % 2 == 0) ? big : small; renderView.configuration = (i % 2 == 0) ? big : small;
WidgetFlutterBinding.instance.pipelineOwner.flushLayout(); Renderer.instance.pipelineOwner.flushLayout();
} }
watch.stop(); watch.stop();
......
...@@ -20,9 +20,7 @@ import 'semantics.dart'; ...@@ -20,9 +20,7 @@ import 'semantics.dart';
export 'package:flutter/gestures.dart' show HitTestResult; export 'package:flutter/gestures.dart' show HitTestResult;
/// The glue between the render tree and the Flutter engine. /// The glue between the render tree and the Flutter engine.
abstract class Renderer extends Object with Scheduler, Services abstract class Renderer implements Scheduler, Services, HitTestable {
implements HitTestable {
@override @override
void initInstances() { void initInstances() {
super.initInstances(); super.initInstances();
...@@ -73,6 +71,12 @@ abstract class Renderer extends Object with Scheduler, Services ...@@ -73,6 +71,12 @@ abstract class Renderer extends Object with Scheduler, Services
}); });
} }
/// Creates a [RenderView] object to be the root of the
/// [RenderObject] rendering tree, and initializes it so that it
/// will be rendered when the engine is next ready to display a
/// frame.
///
/// Called automatically when the binding is created.
void initRenderView() { void initRenderView() {
if (renderView == null) { if (renderView == null) {
renderView = new RenderView(); renderView = new RenderView();
...@@ -88,6 +92,8 @@ abstract class Renderer extends Object with Scheduler, Services ...@@ -88,6 +92,8 @@ abstract class Renderer extends Object with Scheduler, Services
/// The render tree that's attached to the output surface. /// The render tree that's attached to the output surface.
RenderView get renderView => _renderView; RenderView get renderView => _renderView;
RenderView _renderView; RenderView _renderView;
/// Sets the given [RenderView] object (which must not be null), and its tree, to
/// be the new render tree to display. The previous tree, if any, is detached.
void set renderView(RenderView value) { void set renderView(RenderView value) {
assert(value != null); assert(value != null);
if (_renderView == value) if (_renderView == value)
...@@ -98,11 +104,17 @@ abstract class Renderer extends Object with Scheduler, Services ...@@ -98,11 +104,17 @@ abstract class Renderer extends Object with Scheduler, Services
_renderView.attach(pipelineOwner); _renderView.attach(pipelineOwner);
} }
/// Invoked when the system metrics change.
///
/// See [ui.window.onMetricsChanged].
void handleMetricsChanged() { void handleMetricsChanged() {
assert(renderView != null); assert(renderView != null);
renderView.configuration = new ViewConfiguration(size: ui.window.size); renderView.configuration = new ViewConfiguration(size: ui.window.size);
} }
/// Prepares the rendering library to handle semantics requests from the engine.
///
/// Called automatically when the binding is created.
void initSemantics() { void initSemantics() {
SemanticsNode.onSemanticsEnabled = renderView.scheduleInitialSemantics; SemanticsNode.onSemanticsEnabled = renderView.scheduleInitialSemantics;
shell.provideService(mojom.SemanticsServer.serviceName, (core.MojoMessagePipeEndpoint endpoint) { shell.provideService(mojom.SemanticsServer.serviceName, (core.MojoMessagePipeEndpoint endpoint) {
...@@ -116,6 +128,8 @@ abstract class Renderer extends Object with Scheduler, Services ...@@ -116,6 +128,8 @@ abstract class Renderer extends Object with Scheduler, Services
} }
/// Pump the rendering pipeline to generate a frame. /// Pump the rendering pipeline to generate a frame.
///
/// Called automatically by the engine when it is time to lay out and paint a frame.
void beginFrame() { void beginFrame() {
assert(renderView != null); assert(renderView != null);
pipelineOwner.flushLayout(); pipelineOwner.flushLayout();
......
...@@ -98,7 +98,7 @@ class WidgetsApp extends StatefulWidget { ...@@ -98,7 +98,7 @@ class WidgetsApp extends StatefulWidget {
WidgetsAppState<WidgetsApp> createState() => new WidgetsAppState<WidgetsApp>(); WidgetsAppState<WidgetsApp> createState() => new WidgetsAppState<WidgetsApp>();
} }
class WidgetsAppState<T extends WidgetsApp> extends State<T> implements BindingObserver { class WidgetsAppState<T extends WidgetsApp> extends State<T> implements WidgetsBindingObserver {
GlobalObjectKey _navigator; GlobalObjectKey _navigator;
...@@ -109,12 +109,12 @@ class WidgetsAppState<T extends WidgetsApp> extends State<T> implements BindingO ...@@ -109,12 +109,12 @@ class WidgetsAppState<T extends WidgetsApp> extends State<T> implements BindingO
super.initState(); super.initState();
_navigator = new GlobalObjectKey(this); _navigator = new GlobalObjectKey(this);
didChangeLocale(ui.window.locale); didChangeLocale(ui.window.locale);
WidgetFlutterBinding.instance.addObserver(this); Widgeteer.instance.addObserver(this);
} }
@override @override
void dispose() { void dispose() {
WidgetFlutterBinding.instance.removeObserver(this); Widgeteer.instance.removeObserver(this);
super.dispose(); super.dispose();
} }
......
...@@ -15,44 +15,58 @@ import 'framework.dart'; ...@@ -15,44 +15,58 @@ import 'framework.dart';
export 'dart:ui' show AppLifecycleState, Locale; export 'dart:ui' show AppLifecycleState, Locale;
class BindingObserver { /// Interface for classes that register with the Widgets layer binding.
///
/// See [Widgeteer.addObserver] and [Widgeteer.removeObserver].
abstract class WidgetsBindingObserver {
/// Called when the system tells the app to pop the current route.
/// For example, on Android, this is called when the user presses
/// the back button.
///
/// Observers are notified in registration order until one returns
/// true. If none return true, the application quits.
///
/// Observers are expected to return true if they were able to
/// handle the notification, for example by closing an active dialog
/// box, and false otherwise. The [WidgetsApp] widget uses this
/// mechanism to notify the [Navigator] widget that it should pop
/// its current route if possible.
bool didPopRoute() => false; bool didPopRoute() => false;
/// Called when the application's dimensions change. For example,
/// when a phone is rotated.
void didChangeMetrics() { } void didChangeMetrics() { }
/// Called when the system tells the app that the user's locale has
/// changed. For example, if the user changes the system language
/// settings.
void didChangeLocale(Locale locale) { } void didChangeLocale(Locale locale) { }
/// Called when the system puts the app in the background or returns
/// the app to the foreground.
void didChangeAppLifecycleState(AppLifecycleState state) { } void didChangeAppLifecycleState(AppLifecycleState state) { }
} }
/// A concrete binding for applications based on the Widgets framework. /// The glue between the widgets layer and the Flutter engine.
/// This is the glue that binds the framework to the Flutter engine. abstract class Widgeteer implements Gesturer, Renderer {
class WidgetFlutterBinding extends BindingBase with Scheduler, Gesturer, Services, Renderer {
WidgetFlutterBinding() {
buildOwner.onBuildScheduled = ensureVisualUpdate;
}
/// Creates and initializes the WidgetFlutterBinding. This constructor is
/// idempotent; calling it a second time will just return the
/// previously-created instance.
static WidgetFlutterBinding ensureInitialized() {
if (_instance == null)
new WidgetFlutterBinding();
return _instance;
}
final BuildOwner _buildOwner = new BuildOwner();
/// The [BuildOwner] in charge of executing the build pipeline for the
/// widget tree rooted at this binding.
BuildOwner get buildOwner => _buildOwner;
@override @override
void initInstances() { void initInstances() {
super.initInstances(); super.initInstances();
_instance = this; _instance = this;
buildOwner.onBuildScheduled = ensureVisualUpdate;
ui.window.onLocaleChanged = handleLocaleChanged; ui.window.onLocaleChanged = handleLocaleChanged;
ui.window.onPopRoute = handlePopRoute; ui.window.onPopRoute = handlePopRoute;
ui.window.onAppLifecycleStateChanged = handleAppLifecycleStateChanged; ui.window.onAppLifecycleStateChanged = handleAppLifecycleStateChanged;
} }
/// The current [Widgeteer], if one has been created.
///
/// If you need the binding to be constructed before calling [runApp],
/// you can ensure a Widget binding has been constructed by calling the
/// `WidgetFlutterBinding.ensureInitialized()` function.
static Widgeteer get instance => _instance;
static Widgeteer _instance;
@override @override
void initServiceExtensions() { void initServiceExtensions() {
super.initServiceExtensions(); super.initServiceExtensions();
...@@ -69,48 +83,91 @@ class WidgetFlutterBinding extends BindingBase with Scheduler, Gesturer, Service ...@@ -69,48 +83,91 @@ class WidgetFlutterBinding extends BindingBase with Scheduler, Gesturer, Service
); );
} }
/// The one static instance of this class. /// The [BuildOwner] in charge of executing the build pipeline for the
/// /// widget tree rooted at this binding.
/// Only valid after the WidgetFlutterBinding constructor) has been called. BuildOwner get buildOwner => _buildOwner;
/// Only one binding class can be instantiated per process. If another final BuildOwner _buildOwner = new BuildOwner();
/// BindingBase implementation has been instantiated before this one (e.g.
/// bindings from other frameworks based on the Flutter "rendering" library),
/// then WidgetFlutterBinding.instance will not be valid (and will throw in
/// checked mode).
static WidgetFlutterBinding get instance => _instance;
static WidgetFlutterBinding _instance;
final List<BindingObserver> _observers = new List<BindingObserver>();
void addObserver(BindingObserver observer) => _observers.add(observer); final List<WidgetsBindingObserver> _observers = <WidgetsBindingObserver>[];
bool removeObserver(BindingObserver observer) => _observers.remove(observer);
/// Registers the given object as a binding observer. Binding
/// observers are notified when various application events occur,
/// for example when the system locale changes. Generally, one
/// widget in the widget tree registers itself as a binding
/// observer, and converts the system state into inherited widgets.
///
/// For example, the [WidgetsApp] widget registers as a binding
/// observer and passes the screen size to a [MediaQuery] widget
/// each time it is built, which enables other widgets to use the
/// [MediaQuery.of] static method and (implicitly) the
/// [InheritedWidget] mechanism to be notified whenever the screen
/// size changes (e.g. whenever the screen rotates).
void addObserver(WidgetsBindingObserver observer) => _observers.add(observer);
/// Unregisters the given observer. This should be used sparingly as
/// it is relatively expensive (O(N) in the number of registered
/// observers).
bool removeObserver(WidgetsBindingObserver observer) => _observers.remove(observer);
/// Invoked when the system metrics change.
///
/// Notifies all the observers using
/// [WidgetsBindingObserver.didChangeMetrics].
///
/// See [ui.window.onMetricsChanged].
@override @override
void handleMetricsChanged() { void handleMetricsChanged() {
super.handleMetricsChanged(); super.handleMetricsChanged();
for (BindingObserver observer in _observers) for (WidgetsBindingObserver observer in _observers)
observer.didChangeMetrics(); observer.didChangeMetrics();
} }
/// Invoked when the system locale changes.
///
/// Calls [dispatchLocaleChanged] to notify the binding observers.
///
/// See [ui.window.onLocaleChanged].
void handleLocaleChanged() { void handleLocaleChanged() {
dispatchLocaleChanged(ui.window.locale); dispatchLocaleChanged(ui.window.locale);
} }
/// Notify all the observers that the locale has changed (using
/// [WidgetsBindingObserver.didChangeLocale]), giving them the
/// `locale` argument.
void dispatchLocaleChanged(Locale locale) { void dispatchLocaleChanged(Locale locale) {
for (BindingObserver observer in _observers) for (WidgetsBindingObserver observer in _observers)
observer.didChangeLocale(locale); observer.didChangeLocale(locale);
} }
/// Invoked when the system pops the current route.
///
/// This first notifies the binding observers (using
/// [WidgetsBindingObserver.didPopRoute]), in registration order,
/// until one returns true, meaning that it was able to handle the
/// request (e.g. by closing a dialog box). If none return true,
/// then the application is shut down.
///
/// [WidgetsApp] uses this in conjunction with a [Navigator] to
/// cause the back button to close dialog boxes, return from modal
/// pages, and so forth.
///
/// See [ui.window.onPopRoute].
void handlePopRoute() { void handlePopRoute() {
for (BindingObserver observer in _observers) { for (WidgetsBindingObserver observer in _observers) {
if (observer.didPopRoute()) if (observer.didPopRoute())
return; return;
} }
activity.finishCurrentActivity(); activity.finishCurrentActivity();
} }
/// Invoked when the application lifecycle state changes.
///
/// Notifies all the observers using
/// [WidgetsBindingObserver.didChangeAppLifecycleState].
///
/// See [ui.window.onAppLifecycleStateChanged].
void handleAppLifecycleStateChanged(AppLifecycleState state) { void handleAppLifecycleStateChanged(AppLifecycleState state) {
for (BindingObserver observer in _observers) for (WidgetsBindingObserver observer in _observers)
observer.didChangeAppLifecycleState(state); observer.didChangeAppLifecycleState(state);
} }
...@@ -123,6 +180,8 @@ class WidgetFlutterBinding extends BindingBase with Scheduler, Gesturer, Service ...@@ -123,6 +180,8 @@ class WidgetFlutterBinding extends BindingBase with Scheduler, Gesturer, Service
/// The [Element] that is at the root of the hierarchy (and which wraps the /// The [Element] that is at the root of the hierarchy (and which wraps the
/// [RenderView] object at the root of the rendering hierarchy). /// [RenderView] object at the root of the rendering hierarchy).
///
/// This is initialized the first time [runApp] is called.
Element get renderViewElement => _renderViewElement; Element get renderViewElement => _renderViewElement;
Element _renderViewElement; Element _renderViewElement;
void _runApp(Widget app) { void _runApp(Widget app) {
...@@ -142,18 +201,20 @@ class WidgetFlutterBinding extends BindingBase with Scheduler, Gesturer, Service ...@@ -142,18 +201,20 @@ class WidgetFlutterBinding extends BindingBase with Scheduler, Gesturer, Service
} }
/// Inflate the given widget and attach it to the screen. /// Inflate the given widget and attach it to the screen.
///
/// Initializes the binding using [WidgetFlutterBinding] if necessary.
void runApp(Widget app) { void runApp(Widget app) {
WidgetFlutterBinding.ensureInitialized()._runApp(app); WidgetFlutterBinding.ensureInitialized()._runApp(app);
} }
/// Print a string representation of the currently running app. /// Print a string representation of the currently running app.
void debugDumpApp() { void debugDumpApp() {
assert(WidgetFlutterBinding.instance != null); assert(Widgeteer.instance != null);
assert(WidgetFlutterBinding.instance.renderViewElement != null); assert(Widgeteer.instance.renderViewElement != null);
String mode = 'RELEASE MODE'; String mode = 'RELEASE MODE';
assert(() { mode = 'CHECKED MODE'; return true; }); assert(() { mode = 'CHECKED MODE'; return true; });
debugPrint('${WidgetFlutterBinding.instance.runtimeType} - $mode'); debugPrint('${Widgeteer.instance.runtimeType} - $mode');
debugPrint(WidgetFlutterBinding.instance.renderViewElement.toStringDeep()); debugPrint(Widgeteer.instance.renderViewElement.toStringDeep());
} }
/// This class provides a bridge from a RenderObject to an Element tree. The /// This class provides a bridge from a RenderObject to an Element tree. The
...@@ -259,3 +320,19 @@ class RenderObjectToWidgetElement<T extends RenderObject> extends RootRenderObje ...@@ -259,3 +320,19 @@ class RenderObjectToWidgetElement<T extends RenderObject> extends RootRenderObje
renderObject.child = null; renderObject.child = null;
} }
} }
/// A concrete binding for applications based on the Widgets framework.
/// This is the glue that binds the framework to the Flutter engine.
class WidgetFlutterBinding extends BindingBase with Scheduler, Gesturer, Services, Renderer, Widgeteer {
/// Creates and initializes the WidgetFlutterBinding. This function
/// is idempotent; calling it a second time will just return the
/// previously-created instance.
///
/// You only need to call this method if you need the binding to be
/// initialized before calling [runApp].
static WidgetFlutterBinding ensureInitialized() {
if (Widgeteer.instance == null)
new WidgetFlutterBinding();
return Widgeteer.instance;
}
}
...@@ -417,7 +417,7 @@ class _DragAvatar<T> extends Drag { ...@@ -417,7 +417,7 @@ class _DragAvatar<T> extends Drag {
_lastOffset = globalPosition - dragStartPoint; _lastOffset = globalPosition - dragStartPoint;
_entry.markNeedsBuild(); _entry.markNeedsBuild();
HitTestResult result = new HitTestResult(); HitTestResult result = new HitTestResult();
WidgetFlutterBinding.instance.hitTest(result, globalPosition + feedbackOffset); Widgeteer.instance.hitTest(result, globalPosition + feedbackOffset);
List<_DragTargetState<T>> targets = _getDragTargets(result.path).toList(); List<_DragTargetState<T>> targets = _getDragTargets(result.path).toList();
......
...@@ -21,7 +21,7 @@ const String _extensionMethodName = 'driver'; ...@@ -21,7 +21,7 @@ const String _extensionMethodName = 'driver';
const String _extensionMethod = 'ext.flutter.$_extensionMethodName'; const String _extensionMethod = 'ext.flutter.$_extensionMethodName';
const Duration _kDefaultTimeout = const Duration(seconds: 5); const Duration _kDefaultTimeout = const Duration(seconds: 5);
class _DriverBinding extends WidgetFlutterBinding { class _DriverBinding extends WidgetFlutterBinding { // TODO(ianh): refactor so we're not extending a concrete binding
@override @override
void initServiceExtensions() { void initServiceExtensions() {
super.initServiceExtensions(); super.initServiceExtensions();
...@@ -41,9 +41,9 @@ class _DriverBinding extends WidgetFlutterBinding { ...@@ -41,9 +41,9 @@ class _DriverBinding extends WidgetFlutterBinding {
/// Call this function prior to running your application, e.g. before you call /// Call this function prior to running your application, e.g. before you call
/// `runApp`. /// `runApp`.
void enableFlutterDriverExtension() { void enableFlutterDriverExtension() {
assert(WidgetFlutterBinding.instance == null); assert(Widgeteer.instance == null);
new _DriverBinding(); new _DriverBinding();
assert(WidgetFlutterBinding.instance is _DriverBinding); assert(Widgeteer.instance is _DriverBinding);
} }
/// Handles a command and returns a result. /// Handles a command and returns a result.
......
...@@ -100,9 +100,9 @@ void main() { ...@@ -100,9 +100,9 @@ void main() {
tester.pumpWidget(new Markdown(data: "Data1")); tester.pumpWidget(new Markdown(data: "Data1"));
_expectTextStrings(tester.widgets, <String>["Data1"]); _expectTextStrings(tester.widgets, <String>["Data1"]);
String stateBefore = WidgetFlutterBinding.instance.renderViewElement.toStringDeep(); String stateBefore = Widgeteer.instance.renderViewElement.toStringDeep();
tester.pumpWidget(new Markdown(data: "Data1")); tester.pumpWidget(new Markdown(data: "Data1"));
String stateAfter = WidgetFlutterBinding.instance.renderViewElement.toStringDeep(); String stateAfter = Widgeteer.instance.renderViewElement.toStringDeep();
expect(stateBefore, equals(stateAfter)); expect(stateBefore, equals(stateAfter));
tester.pumpWidget(new Markdown(data: "Data2")); tester.pumpWidget(new Markdown(data: "Data2"));
...@@ -119,9 +119,9 @@ void main() { ...@@ -119,9 +119,9 @@ void main() {
tester.pumpWidget(new Markdown(data: "Test", markdownStyle: style1)); tester.pumpWidget(new Markdown(data: "Test", markdownStyle: style1));
String stateBefore = WidgetFlutterBinding.instance.renderViewElement.toStringDeep(); String stateBefore = Widgeteer.instance.renderViewElement.toStringDeep();
tester.pumpWidget(new Markdown(data: "Test", markdownStyle: style2)); tester.pumpWidget(new Markdown(data: "Test", markdownStyle: style2));
String stateAfter = WidgetFlutterBinding.instance.renderViewElement.toStringDeep(); String stateAfter = Widgeteer.instance.renderViewElement.toStringDeep();
expect(stateBefore, isNot(stateAfter)); expect(stateBefore, isNot(stateAfter));
}); });
}); });
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
/// Testing library for flutter, built on top of `package:test`. /// Testing library for flutter, built on top of `package:test`.
library flutter_test; library flutter_test;
export 'src/element_tree_tester.dart'; export 'src/binding.dart';
export 'src/instrumentation.dart'; export 'src/instrumentation.dart';
export 'src/service_mocker.dart'; export 'src/service_mocker.dart';
export 'src/test_pointer.dart'; export 'src/test_pointer.dart';
......
...@@ -23,18 +23,18 @@ enum EnginePhase { ...@@ -23,18 +23,18 @@ enum EnginePhase {
sendSemanticsTree sendSemanticsTree
} }
class _SteppedWidgetFlutterBinding extends WidgetFlutterBinding { class _SteppedWidgetFlutterBinding extends WidgetFlutterBinding { // TODO(ianh): refactor so we're not extending a concrete binding
_SteppedWidgetFlutterBinding._(this.async); _SteppedWidgetFlutterBinding(this.async);
final FakeAsync async; final FakeAsync async;
/// Creates and initializes the binding. This constructor is /// Creates and initializes the binding. This constructor is
/// idempotent; calling it a second time will just return the /// idempotent; calling it a second time will just return the
/// previously-created instance. /// previously-created instance.
static WidgetFlutterBinding ensureInitialized(FakeAsync async) { static Widgeteer ensureInitialized(FakeAsync async) {
if (WidgetFlutterBinding.instance == null) if (Widgeteer.instance == null)
new _SteppedWidgetFlutterBinding._(async); new _SteppedWidgetFlutterBinding(async);
return WidgetFlutterBinding.instance; return Widgeteer.instance;
} }
EnginePhase phase = EnginePhase.sendSemanticsTree; EnginePhase phase = EnginePhase.sendSemanticsTree;
......
...@@ -17,10 +17,10 @@ typedef Point SizeToPointFunction(Size size); ...@@ -17,10 +17,10 @@ typedef Point SizeToPointFunction(Size size);
/// This class provides hooks for accessing the rendering tree and dispatching /// This class provides hooks for accessing the rendering tree and dispatching
/// fake tap/drag/etc. events. /// fake tap/drag/etc. events.
class Instrumentation { class Instrumentation {
Instrumentation({ WidgetFlutterBinding binding }) Instrumentation({ Widgeteer binding })
: this.binding = binding ?? WidgetFlutterBinding.ensureInitialized(); : this.binding = binding ?? WidgetFlutterBinding.ensureInitialized();
final WidgetFlutterBinding binding; final Widgeteer binding;
/// Returns a list of all the [Layer] objects in the rendering. /// Returns a list of all the [Layer] objects in the rendering.
List<Layer> get layers => _layers(binding.renderView.layer); List<Layer> get layers => _layers(binding.renderView.layer);
......
...@@ -7,7 +7,7 @@ import 'package:flutter/widgets.dart'; ...@@ -7,7 +7,7 @@ import 'package:flutter/widgets.dart';
import 'package:quiver/testing/async.dart'; import 'package:quiver/testing/async.dart';
import 'package:test/test.dart'; import 'package:test/test.dart';
import 'element_tree_tester.dart'; import 'binding.dart';
import 'test_pointer.dart'; import 'test_pointer.dart';
/// Runs the [callback] inside the Flutter test environment. /// Runs the [callback] inside the Flutter test environment.
...@@ -57,7 +57,7 @@ class WidgetTester { ...@@ -57,7 +57,7 @@ class WidgetTester {
/// Exposes the [Element] tree created from widgets. /// Exposes the [Element] tree created from widgets.
final ElementTreeTester elementTreeTester; final ElementTreeTester elementTreeTester;
WidgetFlutterBinding get binding => elementTreeTester.binding; Widgeteer get binding => elementTreeTester.binding;
/// Renders the UI from the given [widget]. /// Renders the UI from the given [widget].
/// ///
......
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