From 67f97b455ded8a951e639d538ef7da219fa100e8 Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Mon, 3 Oct 2016 23:35:43 -0700 Subject: [PATCH] Remove ChildView widget (#6195) This widget now lives in Mozart: https://fuchsia.googlesource.com/mozart/+/master/lib/flutter/child_view.dart --- dev/manual_tests/mozart.dart | 254 ------------- packages/flutter/lib/rendering.dart | 1 - .../flutter/lib/src/rendering/child_view.dart | 336 ------------------ .../flutter/lib/src/widgets/child_view.dart | 52 --- packages/flutter/lib/widgets.dart | 1 - 5 files changed, 644 deletions(-) delete mode 100644 dev/manual_tests/mozart.dart delete mode 100644 packages/flutter/lib/src/rendering/child_view.dart delete mode 100644 packages/flutter/lib/src/widgets/child_view.dart diff --git a/dev/manual_tests/mozart.dart b/dev/manual_tests/mozart.dart deleted file mode 100644 index d1e56436cc..0000000000 --- a/dev/manual_tests/mozart.dart +++ /dev/null @@ -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 _kLauncherData = [ - 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 onClose; - - @override - _WindowState createState() => new _WindowState(); -} - -class _WindowState extends State { - 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: [ - 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 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 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 { - List _windows = []; - - 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: [ - 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() - )); -} diff --git a/packages/flutter/lib/rendering.dart b/packages/flutter/lib/rendering.dart index 106881a15d..0aa28812d4 100644 --- a/packages/flutter/lib/rendering.dart +++ b/packages/flutter/lib/rendering.dart @@ -27,7 +27,6 @@ export 'src/rendering/auto_layout.dart'; export 'src/rendering/binding.dart'; export 'src/rendering/block.dart'; export 'src/rendering/box.dart'; -export 'src/rendering/child_view.dart'; export 'src/rendering/custom_layout.dart'; export 'src/rendering/debug.dart'; export 'src/rendering/editable_line.dart'; diff --git a/packages/flutter/lib/src/rendering/child_view.dart b/packages/flutter/lib/src/rendering/child_view.dart deleted file mode 100644 index ef07373af7..0000000000 --- a/packages/flutter/lib/src/rendering/child_view.dart +++ /dev/null @@ -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 _connections = new HashMap(); -} - -/// (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 description) { - super.debugFillDescription(description); - description.add('child: $child'); - description.add('scale: $scale'); - } -} diff --git a/packages/flutter/lib/src/widgets/child_view.dart b/packages/flutter/lib/src/widgets/child_view.dart deleted file mode 100644 index 3fc5624f41..0000000000 --- a/packages/flutter/lib/src/widgets/child_view.dart +++ /dev/null @@ -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; - } -} diff --git a/packages/flutter/lib/widgets.dart b/packages/flutter/lib/widgets.dart index 48a880cbfd..9c498bb8e0 100644 --- a/packages/flutter/lib/widgets.dart +++ b/packages/flutter/lib/widgets.dart @@ -15,7 +15,6 @@ export 'src/widgets/auto_layout.dart'; export 'src/widgets/banner.dart'; export 'src/widgets/basic.dart'; export 'src/widgets/binding.dart'; -export 'src/widgets/child_view.dart'; export 'src/widgets/clamp_overscrolls.dart'; export 'src/widgets/container.dart'; export 'src/widgets/debug.dart';