Remove ChildView widget (#6195)
This widget now lives in Mozart: https://fuchsia.googlesource.com/mozart/+/master/lib/flutter/child_view.dart
This commit is contained in:
parent
8071a82d51
commit
67f97b455d
@ -1,254 +0,0 @@
|
|||||||
// 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 'dart:math' as math;
|
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
class LauncherData {
|
|
||||||
const LauncherData({ this.url, this.title });
|
|
||||||
final String url;
|
|
||||||
final String title;
|
|
||||||
}
|
|
||||||
|
|
||||||
final List<LauncherData> _kLauncherData = <LauncherData>[
|
|
||||||
const LauncherData(
|
|
||||||
url: 'mojo:noodles_view',
|
|
||||||
title: 'Noodles'
|
|
||||||
),
|
|
||||||
const LauncherData(
|
|
||||||
url: 'mojo:shapes_view',
|
|
||||||
title: 'Shapes'
|
|
||||||
),
|
|
||||||
new LauncherData(
|
|
||||||
url: Uri.base.resolve('../../../examples/stocks/build/app.flx').toString(),
|
|
||||||
title: 'Stocks'
|
|
||||||
),
|
|
||||||
];
|
|
||||||
|
|
||||||
const Size _kInitialWindowSize = const Size(200.0, 200.0);
|
|
||||||
const double _kWindowPadding = 10.0;
|
|
||||||
|
|
||||||
enum WindowSide {
|
|
||||||
topCenter,
|
|
||||||
topRight,
|
|
||||||
bottomRight,
|
|
||||||
}
|
|
||||||
|
|
||||||
class WindowDecoration extends StatelessWidget {
|
|
||||||
WindowDecoration({
|
|
||||||
Key key,
|
|
||||||
this.side,
|
|
||||||
this.color,
|
|
||||||
this.onTap,
|
|
||||||
this.onPanUpdate
|
|
||||||
}) : super(key: key);
|
|
||||||
|
|
||||||
final WindowSide side;
|
|
||||||
final Color color;
|
|
||||||
final GestureTapCallback onTap;
|
|
||||||
final GestureDragUpdateCallback onPanUpdate;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
double top, right, bottom, left, width, height;
|
|
||||||
|
|
||||||
height = _kWindowPadding * 2.0;
|
|
||||||
|
|
||||||
if (side == WindowSide.topCenter || side == WindowSide.topRight)
|
|
||||||
top = 0.0;
|
|
||||||
|
|
||||||
if (side == WindowSide.topRight || side == WindowSide.bottomRight) {
|
|
||||||
right = 0.0;
|
|
||||||
width = _kWindowPadding * 2.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (side == WindowSide.topCenter) {
|
|
||||||
left = _kWindowPadding;
|
|
||||||
right = _kWindowPadding;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (side == WindowSide.bottomRight)
|
|
||||||
bottom = 0.0;
|
|
||||||
|
|
||||||
return new Positioned(
|
|
||||||
top: top,
|
|
||||||
right: right,
|
|
||||||
bottom: bottom,
|
|
||||||
left: left,
|
|
||||||
width: width,
|
|
||||||
height: height,
|
|
||||||
child: new GestureDetector(
|
|
||||||
onTap: onTap,
|
|
||||||
onPanUpdate: onPanUpdate,
|
|
||||||
child: new Container(
|
|
||||||
decoration: new BoxDecoration(
|
|
||||||
backgroundColor: color
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Window extends StatefulWidget {
|
|
||||||
Window({ Key key, this.child, this.onClose }) : super(key: key);
|
|
||||||
|
|
||||||
final ChildViewConnection child;
|
|
||||||
final ValueChanged<ChildViewConnection> onClose;
|
|
||||||
|
|
||||||
@override
|
|
||||||
_WindowState createState() => new _WindowState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _WindowState extends State<Window> {
|
|
||||||
Offset _offset = Offset.zero;
|
|
||||||
Size _size = _kInitialWindowSize;
|
|
||||||
|
|
||||||
void _handleResizerDrag(DragUpdateDetails details) {
|
|
||||||
setState(() {
|
|
||||||
_size = new Size(
|
|
||||||
math.max(0.0, _size.width + details.delta.dx),
|
|
||||||
math.max(0.0, _size.height + details.delta.dy)
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void _handleRepositionDrag(DragUpdateDetails details) {
|
|
||||||
setState(() {
|
|
||||||
_offset += details.delta;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void _handleClose() {
|
|
||||||
config.onClose(config.child);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return new Positioned(
|
|
||||||
left: _offset.dx,
|
|
||||||
top: _offset.dy,
|
|
||||||
width: _size.width + _kWindowPadding * 2.0,
|
|
||||||
height: _size.height + _kWindowPadding * 2.0,
|
|
||||||
child: new Stack(
|
|
||||||
children: <Widget>[
|
|
||||||
new WindowDecoration(
|
|
||||||
side: WindowSide.topCenter,
|
|
||||||
onPanUpdate: _handleRepositionDrag,
|
|
||||||
color: Colors.green[200]
|
|
||||||
),
|
|
||||||
new WindowDecoration(
|
|
||||||
side: WindowSide.topRight,
|
|
||||||
onTap: _handleClose,
|
|
||||||
color: Colors.red[200]
|
|
||||||
),
|
|
||||||
new WindowDecoration(
|
|
||||||
side: WindowSide.bottomRight,
|
|
||||||
onPanUpdate: _handleResizerDrag,
|
|
||||||
color: Colors.blue[200]
|
|
||||||
),
|
|
||||||
new Container(
|
|
||||||
padding: const EdgeInsets.all(_kWindowPadding),
|
|
||||||
child: new Material(
|
|
||||||
elevation: 8,
|
|
||||||
child: new ChildView(child: config.child)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
]
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class LauncherItem extends StatelessWidget {
|
|
||||||
LauncherItem({
|
|
||||||
Key key,
|
|
||||||
this.url,
|
|
||||||
this.child,
|
|
||||||
this.onLaunch
|
|
||||||
}) : super(key: key);
|
|
||||||
|
|
||||||
final String url;
|
|
||||||
final Widget child;
|
|
||||||
final ValueChanged<ChildViewConnection> onLaunch;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return new RaisedButton(
|
|
||||||
onPressed: () { onLaunch(new ChildViewConnection(url: url)); },
|
|
||||||
child: child
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Launcher extends StatelessWidget {
|
|
||||||
Launcher({ Key key, this.items }) : super(key: key);
|
|
||||||
|
|
||||||
final List<Widget> items;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return new ButtonBar(
|
|
||||||
alignment: MainAxisAlignment.center,
|
|
||||||
children: items
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class WindowManager extends StatefulWidget {
|
|
||||||
@override
|
|
||||||
_WindowManagerState createState() => new _WindowManagerState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _WindowManagerState extends State<WindowManager> {
|
|
||||||
List<ChildViewConnection> _windows = <ChildViewConnection>[];
|
|
||||||
|
|
||||||
void _handleLaunch(ChildViewConnection child) {
|
|
||||||
setState(() {
|
|
||||||
_windows.add(child);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void _handleClose(ChildViewConnection child) {
|
|
||||||
setState(() {
|
|
||||||
_windows.remove(child);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return new Material(
|
|
||||||
child: new Stack(
|
|
||||||
children: <Widget>[
|
|
||||||
new Positioned(
|
|
||||||
left: 0.0,
|
|
||||||
right: 0.0,
|
|
||||||
bottom: 0.0,
|
|
||||||
child: new Launcher(items: _kLauncherData.map((LauncherData data) {
|
|
||||||
return new LauncherItem(
|
|
||||||
url: data.url,
|
|
||||||
onLaunch: _handleLaunch,
|
|
||||||
child: new Text(data.title)
|
|
||||||
);
|
|
||||||
}).toList())
|
|
||||||
)
|
|
||||||
]..addAll(_windows.map((ChildViewConnection child) {
|
|
||||||
return new Window(
|
|
||||||
key: new ObjectKey(child),
|
|
||||||
onClose: _handleClose,
|
|
||||||
child: child
|
|
||||||
);
|
|
||||||
}))
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
runApp(new MaterialApp(
|
|
||||||
title: 'Mozart',
|
|
||||||
home: new WindowManager()
|
|
||||||
));
|
|
||||||
}
|
|
@ -27,7 +27,6 @@ export 'src/rendering/auto_layout.dart';
|
|||||||
export 'src/rendering/binding.dart';
|
export 'src/rendering/binding.dart';
|
||||||
export 'src/rendering/block.dart';
|
export 'src/rendering/block.dart';
|
||||||
export 'src/rendering/box.dart';
|
export 'src/rendering/box.dart';
|
||||||
export 'src/rendering/child_view.dart';
|
|
||||||
export 'src/rendering/custom_layout.dart';
|
export 'src/rendering/custom_layout.dart';
|
||||||
export 'src/rendering/debug.dart';
|
export 'src/rendering/debug.dart';
|
||||||
export 'src/rendering/editable_line.dart';
|
export 'src/rendering/editable_line.dart';
|
||||||
|
@ -1,336 +0,0 @@
|
|||||||
// Copyright 2016 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 'dart:async';
|
|
||||||
import 'dart:collection';
|
|
||||||
import 'dart:ui' as ui;
|
|
||||||
|
|
||||||
import 'package:flutter/services.dart';
|
|
||||||
import 'package:flutter_services/mojo/gfx/composition/scene_token.dart' as mojom;
|
|
||||||
import 'package:flutter_services/mojo/ui/view_containers.dart' as mojom;
|
|
||||||
import 'package:flutter_services/mojo/ui/view_provider.dart' as mojom;
|
|
||||||
import 'package:flutter_services/mojo/ui/view_properties.dart' as mojom;
|
|
||||||
import 'package:flutter_services/mojo/ui/view_token.dart' as mojom;
|
|
||||||
import 'package:flutter_services/mojo/ui/views.dart' as mojom;
|
|
||||||
import 'package:flutter_services/mojo/geometry.dart' as mojom;
|
|
||||||
import 'package:mojo/application.dart';
|
|
||||||
import 'package:mojo/core.dart' as core;
|
|
||||||
import 'package:mojo/mojo/service_provider.mojom.dart' as mojom;
|
|
||||||
|
|
||||||
import 'box.dart';
|
|
||||||
import 'object.dart';
|
|
||||||
import 'layer.dart';
|
|
||||||
|
|
||||||
mojom.ViewProxy _initViewProxy() {
|
|
||||||
int viewHandle = ui.MojoServices.takeView();
|
|
||||||
if (viewHandle == core.MojoHandle.INVALID)
|
|
||||||
return null;
|
|
||||||
return new mojom.ViewProxy.fromHandle(new core.MojoHandle(viewHandle));
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(abarth): The view host is a unique resource. We should structure how we
|
|
||||||
// take the handle from the engine so that multiple libraries can interact with
|
|
||||||
// the view host safely. Unfortunately, the view host has a global namespace of
|
|
||||||
// view keys, which means any scheme for sharing the view host also needs to
|
|
||||||
// provide a mechanism for coordinating about view keys.
|
|
||||||
final mojom.ViewProxy _viewProxy = _initViewProxy();
|
|
||||||
final mojom.View _view = _viewProxy;
|
|
||||||
|
|
||||||
mojom.ViewContainer _initViewContainer() {
|
|
||||||
if (_view == null)
|
|
||||||
return null;
|
|
||||||
mojom.ViewContainerProxy viewContainerProxy = new mojom.ViewContainerProxy.unbound();
|
|
||||||
_view.getContainer(viewContainerProxy);
|
|
||||||
viewContainerProxy.setListener(new mojom.ViewContainerListenerStub.unbound()..impl = _ViewContainerListenerImpl.instance);
|
|
||||||
return viewContainerProxy;
|
|
||||||
}
|
|
||||||
|
|
||||||
final mojom.ViewContainer _viewContainer = _initViewContainer();
|
|
||||||
|
|
||||||
typedef dynamic _ResponseFactory();
|
|
||||||
|
|
||||||
class _ViewContainerListenerImpl extends mojom.ViewContainerListener {
|
|
||||||
static final _ViewContainerListenerImpl instance = new _ViewContainerListenerImpl();
|
|
||||||
|
|
||||||
@override
|
|
||||||
dynamic onChildAttached(int childKey, mojom.ViewInfo childViewInfo, [_ResponseFactory responseFactory = null]) {
|
|
||||||
ChildViewConnection connection = _connections[childKey];
|
|
||||||
connection?._onAttachedToContainer(childViewInfo);
|
|
||||||
return responseFactory();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
dynamic onChildUnavailable(int childKey, [_ResponseFactory responseFactory = null]) {
|
|
||||||
ChildViewConnection connection = _connections[childKey];
|
|
||||||
connection?._onUnavailable();
|
|
||||||
return responseFactory();
|
|
||||||
}
|
|
||||||
|
|
||||||
final Map<int, ChildViewConnection> _connections = new HashMap<int, ChildViewConnection>();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// (mojo-only) A connection with a child view.
|
|
||||||
///
|
|
||||||
/// Used with the [ChildView] widget to display a child view.
|
|
||||||
class ChildViewConnection {
|
|
||||||
/// Establishes a connection to the app at the given URL.
|
|
||||||
ChildViewConnection({ String url }) {
|
|
||||||
mojom.ViewProviderProxy viewProvider = shell.connectToApplicationService(
|
|
||||||
url, mojom.ViewProvider.connectToService
|
|
||||||
);
|
|
||||||
mojom.ServiceProviderProxy incomingServices = new mojom.ServiceProviderProxy.unbound();
|
|
||||||
_viewOwner = new mojom.ViewOwnerProxy.unbound();
|
|
||||||
viewProvider.createView(_viewOwner, incomingServices);
|
|
||||||
viewProvider.close();
|
|
||||||
_connection = new ApplicationConnection(null, incomingServices);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Wraps an already-established connection to a child app.
|
|
||||||
ChildViewConnection.fromViewOwner({
|
|
||||||
mojom.ViewOwnerProxy viewOwner,
|
|
||||||
ApplicationConnection connection
|
|
||||||
}) : _connection = connection, _viewOwner = viewOwner;
|
|
||||||
|
|
||||||
/// The underlying application connection to the child app.
|
|
||||||
///
|
|
||||||
/// Useful for requesting services from the child app and for providing
|
|
||||||
/// services to the child app.
|
|
||||||
ApplicationConnection get connection => _connection;
|
|
||||||
ApplicationConnection _connection;
|
|
||||||
|
|
||||||
mojom.ViewOwnerProxy _viewOwner;
|
|
||||||
|
|
||||||
static int _nextViewKey = 1;
|
|
||||||
int _viewKey;
|
|
||||||
|
|
||||||
int _sceneVersion = 1;
|
|
||||||
mojom.ViewProperties _currentViewProperties;
|
|
||||||
|
|
||||||
VoidCallback _onViewInfoAvailable;
|
|
||||||
mojom.ViewInfo _viewInfo;
|
|
||||||
|
|
||||||
void _onAttachedToContainer(mojom.ViewInfo viewInfo) {
|
|
||||||
assert(_viewInfo == null);
|
|
||||||
_viewInfo = viewInfo;
|
|
||||||
if (_onViewInfoAvailable != null)
|
|
||||||
_onViewInfoAvailable();
|
|
||||||
}
|
|
||||||
|
|
||||||
void _onUnavailable() {
|
|
||||||
_viewInfo = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
void _addChildToViewHost() {
|
|
||||||
assert(_attached);
|
|
||||||
assert(_viewOwner != null);
|
|
||||||
assert(_viewKey == null);
|
|
||||||
assert(_viewInfo == null);
|
|
||||||
_viewKey = _nextViewKey++;
|
|
||||||
_viewContainer?.addChild(_viewKey, _viewOwner);
|
|
||||||
_viewOwner = null;
|
|
||||||
assert(!_ViewContainerListenerImpl.instance._connections.containsKey(_viewKey));
|
|
||||||
_ViewContainerListenerImpl.instance._connections[_viewKey] = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void _removeChildFromViewHost() {
|
|
||||||
assert(!_attached);
|
|
||||||
assert(_viewOwner == null);
|
|
||||||
assert(_viewKey != null);
|
|
||||||
assert(_ViewContainerListenerImpl.instance._connections[_viewKey] == this);
|
|
||||||
_ViewContainerListenerImpl.instance._connections.remove(_viewKey);
|
|
||||||
_viewOwner = new mojom.ViewOwnerProxy.unbound();
|
|
||||||
_viewContainer?.removeChild(_viewKey, _viewOwner);
|
|
||||||
_viewKey = null;
|
|
||||||
_viewInfo = null;
|
|
||||||
_currentViewProperties = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The number of render objects attached to this view. In between frames, we
|
|
||||||
// might have more than one connected if we get added to a new render object
|
|
||||||
// before we get removed from the old render object. By the time we get around
|
|
||||||
// to computing our layout, we must be back to just having one render object.
|
|
||||||
int _attachments = 0;
|
|
||||||
bool get _attached => _attachments > 0;
|
|
||||||
|
|
||||||
void _attach() {
|
|
||||||
assert(_attachments >= 0);
|
|
||||||
++_attachments;
|
|
||||||
if (_viewKey == null)
|
|
||||||
_addChildToViewHost();
|
|
||||||
}
|
|
||||||
|
|
||||||
void _detach() {
|
|
||||||
assert(_attached);
|
|
||||||
--_attachments;
|
|
||||||
scheduleMicrotask(_removeChildFromViewHostIfNeeded);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _removeChildFromViewHostIfNeeded() {
|
|
||||||
assert(_attachments >= 0);
|
|
||||||
if (_attachments == 0)
|
|
||||||
_removeChildFromViewHost();
|
|
||||||
}
|
|
||||||
|
|
||||||
mojom.ViewProperties _createViewProperties(int physicalWidth,
|
|
||||||
int physicalHeight,
|
|
||||||
double devicePixelRatio) {
|
|
||||||
if (_currentViewProperties != null &&
|
|
||||||
_currentViewProperties.displayMetrics.devicePixelRatio == devicePixelRatio &&
|
|
||||||
_currentViewProperties.viewLayout.size.width == physicalWidth &&
|
|
||||||
_currentViewProperties.viewLayout.size.height == physicalHeight)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
mojom.DisplayMetrics displayMetrics = new mojom.DisplayMetrics()
|
|
||||||
..devicePixelRatio = devicePixelRatio;
|
|
||||||
mojom.Size size = new mojom.Size()
|
|
||||||
..width = physicalWidth
|
|
||||||
..height = physicalHeight;
|
|
||||||
mojom.ViewLayout viewLayout = new mojom.ViewLayout()
|
|
||||||
..size = size;
|
|
||||||
_currentViewProperties = new mojom.ViewProperties()
|
|
||||||
..displayMetrics = displayMetrics
|
|
||||||
..viewLayout = viewLayout;
|
|
||||||
return _currentViewProperties;
|
|
||||||
}
|
|
||||||
|
|
||||||
void _setChildProperties(int physicalWidth, int physicalHeight, double devicePixelRatio) {
|
|
||||||
assert(_attached);
|
|
||||||
assert(_attachments == 1);
|
|
||||||
assert(_viewKey != null);
|
|
||||||
if (_view == null)
|
|
||||||
return;
|
|
||||||
mojom.ViewProperties viewProperties = _createViewProperties(physicalWidth, physicalHeight, devicePixelRatio);
|
|
||||||
if (viewProperties == null)
|
|
||||||
return;
|
|
||||||
_viewContainer.setChildProperties(_viewKey, _sceneVersion++, viewProperties);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// (mojo-only) A view of a child application.
|
|
||||||
class RenderChildView extends RenderBox {
|
|
||||||
/// Creates a child view render object.
|
|
||||||
///
|
|
||||||
/// The [scale] argument must not be null.
|
|
||||||
RenderChildView({
|
|
||||||
ChildViewConnection child,
|
|
||||||
double scale
|
|
||||||
}) : _scale = scale {
|
|
||||||
assert(scale != null);
|
|
||||||
this.child = child;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The child to display.
|
|
||||||
ChildViewConnection get child => _child;
|
|
||||||
ChildViewConnection _child;
|
|
||||||
set child (ChildViewConnection value) {
|
|
||||||
if (value == _child)
|
|
||||||
return;
|
|
||||||
if (attached && _child != null) {
|
|
||||||
_child._detach();
|
|
||||||
assert(_child._onViewInfoAvailable != null);
|
|
||||||
_child._onViewInfoAvailable = null;
|
|
||||||
}
|
|
||||||
_child = value;
|
|
||||||
if (attached && _child != null) {
|
|
||||||
_child._attach();
|
|
||||||
assert(_child._onViewInfoAvailable == null);
|
|
||||||
_child._onViewInfoAvailable = markNeedsPaint;
|
|
||||||
}
|
|
||||||
if (_child == null) {
|
|
||||||
markNeedsPaint();
|
|
||||||
} else {
|
|
||||||
markNeedsLayout();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The device pixel ratio to provide the child.
|
|
||||||
double get scale => _scale;
|
|
||||||
double _scale;
|
|
||||||
set scale (double value) {
|
|
||||||
assert(value != null);
|
|
||||||
if (value == _scale)
|
|
||||||
return;
|
|
||||||
_scale = value;
|
|
||||||
if (_child != null)
|
|
||||||
markNeedsLayout();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void attach(PipelineOwner owner) {
|
|
||||||
super.attach(owner);
|
|
||||||
if (_child != null) {
|
|
||||||
_child._attach();
|
|
||||||
assert(_child._onViewInfoAvailable == null);
|
|
||||||
_child._onViewInfoAvailable = markNeedsPaint;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void detach() {
|
|
||||||
if (_child != null) {
|
|
||||||
_child._detach();
|
|
||||||
assert(_child._onViewInfoAvailable != null);
|
|
||||||
_child._onViewInfoAvailable = null;
|
|
||||||
}
|
|
||||||
super.detach();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
bool get alwaysNeedsCompositing => true;
|
|
||||||
|
|
||||||
TextPainter _debugErrorMessage;
|
|
||||||
|
|
||||||
int _physicalWidth;
|
|
||||||
int _physicalHeight;
|
|
||||||
|
|
||||||
@override
|
|
||||||
void performLayout() {
|
|
||||||
size = constraints.biggest;
|
|
||||||
if (_child != null) {
|
|
||||||
_physicalWidth = (size.width * scale).round();
|
|
||||||
_physicalHeight = (size.height * scale).round();
|
|
||||||
_child._setChildProperties(_physicalWidth, _physicalHeight, scale);
|
|
||||||
assert(() {
|
|
||||||
if (_view == null) {
|
|
||||||
_debugErrorMessage ??= new TextPainter(
|
|
||||||
text: new TextSpan(text: 'Child views are supported only when running in Mojo shell.')
|
|
||||||
);
|
|
||||||
_debugErrorMessage.layout(minWidth: size.width, maxWidth: size.width);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
bool hitTestSelf(Point position) => true;
|
|
||||||
|
|
||||||
@override
|
|
||||||
void paint(PaintingContext context, Offset offset) {
|
|
||||||
assert(needsCompositing);
|
|
||||||
if (_child?._viewInfo != null) {
|
|
||||||
context.addLayer(new ChildSceneLayer(
|
|
||||||
offset: offset,
|
|
||||||
devicePixelRatio: scale,
|
|
||||||
physicalWidth: _physicalWidth,
|
|
||||||
physicalHeight: _physicalHeight,
|
|
||||||
sceneToken: _child._viewInfo.sceneToken.value
|
|
||||||
));
|
|
||||||
}
|
|
||||||
assert(() {
|
|
||||||
if (_view == null) {
|
|
||||||
context.canvas.drawRect(offset & size, new Paint()..color = const Color(0xFF0000FF));
|
|
||||||
_debugErrorMessage.paint(context.canvas, offset);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void debugFillDescription(List<String> description) {
|
|
||||||
super.debugFillDescription(description);
|
|
||||||
description.add('child: $child');
|
|
||||||
description.add('scale: $scale');
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,52 +0,0 @@
|
|||||||
// Copyright 2016 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:flutter/rendering.dart';
|
|
||||||
|
|
||||||
import 'framework.dart';
|
|
||||||
import 'media_query.dart';
|
|
||||||
|
|
||||||
export 'package:flutter/rendering.dart' show ChildViewConnection;
|
|
||||||
|
|
||||||
/// (mojo-only) A widget that is replaced by content from another process.
|
|
||||||
///
|
|
||||||
/// Requires a [MediaQuery] ancestor to provide appropriate media information to
|
|
||||||
/// the child.
|
|
||||||
class ChildView extends StatelessWidget {
|
|
||||||
/// Creates a widget that is replaced by content from another process.
|
|
||||||
ChildView({ Key key, this.child }) : super(key: key);
|
|
||||||
|
|
||||||
/// A connection to the child whose content will replace this widget.
|
|
||||||
final ChildViewConnection child;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return new _ChildViewWidget(
|
|
||||||
child: child,
|
|
||||||
scale: MediaQuery.of(context).devicePixelRatio
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class _ChildViewWidget extends LeafRenderObjectWidget {
|
|
||||||
_ChildViewWidget({
|
|
||||||
ChildViewConnection child,
|
|
||||||
this.scale
|
|
||||||
}) : child = child, super(key: new GlobalObjectKey(child)) {
|
|
||||||
assert(scale != null);
|
|
||||||
}
|
|
||||||
|
|
||||||
final ChildViewConnection child;
|
|
||||||
final double scale;
|
|
||||||
|
|
||||||
@override
|
|
||||||
RenderChildView createRenderObject(BuildContext context) => new RenderChildView(child: child, scale: scale);
|
|
||||||
|
|
||||||
@override
|
|
||||||
void updateRenderObject(BuildContext context, RenderChildView renderObject) {
|
|
||||||
renderObject
|
|
||||||
..child = child
|
|
||||||
..scale = scale;
|
|
||||||
}
|
|
||||||
}
|
|
@ -15,7 +15,6 @@ export 'src/widgets/auto_layout.dart';
|
|||||||
export 'src/widgets/banner.dart';
|
export 'src/widgets/banner.dart';
|
||||||
export 'src/widgets/basic.dart';
|
export 'src/widgets/basic.dart';
|
||||||
export 'src/widgets/binding.dart';
|
export 'src/widgets/binding.dart';
|
||||||
export 'src/widgets/child_view.dart';
|
|
||||||
export 'src/widgets/clamp_overscrolls.dart';
|
export 'src/widgets/clamp_overscrolls.dart';
|
||||||
export 'src/widgets/container.dart';
|
export 'src/widgets/container.dart';
|
||||||
export 'src/widgets/debug.dart';
|
export 'src/widgets/debug.dart';
|
||||||
|
Loading…
x
Reference in New Issue
Block a user