From 90d47520fd91ab3af362c090a5dd4ec1499be60c Mon Sep 17 00:00:00 2001 From: Mehmet Akin Date: Wed, 7 Oct 2015 01:01:54 +0200 Subject: [PATCH 01/84] Make checkbox widget to fit more closely to material design standard. Make changes to remove animation artefacts. --- .../flutter/lib/src/widgets/checkbox.dart | 28 ++++++++++++------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/packages/flutter/lib/src/widgets/checkbox.dart b/packages/flutter/lib/src/widgets/checkbox.dart index 89cdaee293..2ae53375be 100644 --- a/packages/flutter/lib/src/widgets/checkbox.dart +++ b/packages/flutter/lib/src/widgets/checkbox.dart @@ -15,8 +15,9 @@ export 'package:sky/src/rendering/toggleable.dart' show ValueChanged; const double _kMidpoint = 0.5; const sky.Color _kLightUncheckedColor = const sky.Color(0x8A000000); const sky.Color _kDarkUncheckedColor = const sky.Color(0xB2FFFFFF); -const double _kEdgeSize = 20.0; +const double _kEdgeSize = 18.0; const double _kEdgeRadius = 1.0; +const double _kStrokeWidth = 2.0; /// A material design checkbox /// @@ -127,13 +128,18 @@ class _RenderCheckbox extends RenderToggleable { final PaintingCanvas canvas = context.canvas; // Choose a color between grey and the theme color sky.Paint paint = new sky.Paint() - ..strokeWidth = 2.0 + ..strokeWidth = _kStrokeWidth ..color = uncheckedColor; - // The rrect contracts slightly during the animation + // The rrect contracts slightly during the transition animation from checked states. + // Because we have a stroke size of 2, we should have a minimum 1.0 inset. double inset = 2.0 - (position - _kMidpoint).abs() * 2.0; - sky.Rect rect = new sky.Rect.fromLTWH(offset.dx + inset, offset.dy + inset, - _kEdgeSize - inset, _kEdgeSize - inset); + double rectSize = _kEdgeSize - inset * _kStrokeWidth; + sky.Rect rect = + new sky.Rect.fromLTWH(offset.dx + inset, offset.dy + inset, rectSize, rectSize); + // Create an inner rectangle to cover inside of rectangle. This is needed to avoid + // painting artefacts caused by overlayed paintings. + sky.Rect innerRect = rect.deflate(1.0); sky.RRect rrect = new sky.RRect() ..setRectXY(rect, _kEdgeRadius, _kEdgeRadius); @@ -150,25 +156,27 @@ class _RenderCheckbox extends RenderToggleable { const sky.Color(0x00000000), uncheckedColor ])); - canvas.drawRRect(rrect, paint); + canvas.drawRect(innerRect, paint); } if (position > _kMidpoint) { double t = (position - _kMidpoint) / (1.0 - _kMidpoint); - // Solid filled rrect - paint.setStyle(sky.PaintingStyle.strokeAndFill); + // First draw a rounded rect outline then fill inner rectangle with accent color. paint.color = new Color.fromARGB((t * 255).floor(), _accentColor.red, _accentColor.green, _accentColor.blue); + paint.setStyle(sky.PaintingStyle.stroke); canvas.drawRRect(rrect, paint); + paint.setStyle(sky.PaintingStyle.fill); + canvas.drawRect(innerRect, paint); // White inner check paint.color = const sky.Color(0xFFFFFFFF); paint.setStyle(sky.PaintingStyle.stroke); sky.Path path = new sky.Path(); - sky.Point start = new sky.Point(_kEdgeSize * 0.2, _kEdgeSize * 0.5); + sky.Point start = new sky.Point(_kEdgeSize * 0.15, _kEdgeSize * 0.45); sky.Point mid = new sky.Point(_kEdgeSize * 0.4, _kEdgeSize * 0.7); - sky.Point end = new sky.Point(_kEdgeSize * 0.8, _kEdgeSize * 0.3); + sky.Point end = new sky.Point(_kEdgeSize * 0.85, _kEdgeSize * 0.25); Point lerp(Point p1, Point p2, double t) => new Point(p1.x * (1.0 - t) + p2.x * t, p1.y * (1.0 - t) + p2.y * t); sky.Point drawStart = lerp(start, mid, 1.0 - t); From 30d16e24261465cf4285ab89c6748048745b5589 Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Wed, 7 Oct 2015 09:58:01 -0700 Subject: [PATCH 02/84] Separate Route and PerformanceRoute This patch prepares us to create routes that control their performances more closely. --- .../lib/src/animation/performance.dart | 18 +-- packages/flutter/lib/src/widgets/dialog.dart | 2 +- .../flutter/lib/src/widgets/drag_target.dart | 1 - .../flutter/lib/src/widgets/navigator.dart | 103 ++++++++++-------- .../flutter/lib/src/widgets/popup_menu.dart | 2 +- .../flutter/lib/src/widgets/snack_bar.dart | 2 +- 6 files changed, 69 insertions(+), 59 deletions(-) diff --git a/packages/flutter/lib/src/animation/performance.dart b/packages/flutter/lib/src/animation/performance.dart index 92c77f8b59..3a4125d8fa 100644 --- a/packages/flutter/lib/src/animation/performance.dart +++ b/packages/flutter/lib/src/animation/performance.dart @@ -41,6 +41,15 @@ abstract class PerformanceView { void addStatusListener(PerformanceStatusListener listener); /// Stops calling the listener every time the status of the performance changes void removeStatusListener(PerformanceStatusListener listener); + + /// The current status of this animation + PerformanceStatus get status; + + /// Whether this animation is stopped at the beginning + bool get isDismissed => status == PerformanceStatus.dismissed; + + /// Whether this animation is stopped at the end + bool get isCompleted => status == PerformanceStatus.completed; } /// A timeline that can be reversed and used to update [Animatable]s. @@ -51,7 +60,7 @@ abstract class PerformanceView { /// may also take direct control of the timeline by manipulating [progress], or /// [fling] the timeline causing a physics-based simulation to take over the /// progression. -class Performance implements PerformanceView { +class Performance extends PerformanceView { Performance({ this.duration, double progress }) { _timeline = new SimulationStepper(_tick); if (progress != null) @@ -94,16 +103,9 @@ class Performance implements PerformanceView { return timing != null ? timing.transform(progress, _curveDirection) : progress; } - /// Whether this animation is stopped at the beginning - bool get isDismissed => status == PerformanceStatus.dismissed; - - /// Whether this animation is stopped at the end - bool get isCompleted => status == PerformanceStatus.completed; - /// Whether this animation is currently animating in either the forward or reverse direction bool get isAnimating => _timeline.isAnimating; - /// The current status of this animation PerformanceStatus get status { if (!isAnimating && progress == 1.0) return PerformanceStatus.completed; diff --git a/packages/flutter/lib/src/widgets/dialog.dart b/packages/flutter/lib/src/widgets/dialog.dart index 688f0f9174..88b44ade59 100644 --- a/packages/flutter/lib/src/widgets/dialog.dart +++ b/packages/flutter/lib/src/widgets/dialog.dart @@ -131,7 +131,7 @@ class Dialog extends StatelessComponent { } } -class _DialogRoute extends Route { +class _DialogRoute extends PerformanceRoute { _DialogRoute({ this.completer, this.builder }); final Completer completer; diff --git a/packages/flutter/lib/src/widgets/drag_target.dart b/packages/flutter/lib/src/widgets/drag_target.dart index 5d1533c270..679c2fa1d4 100644 --- a/packages/flutter/lib/src/widgets/drag_target.dart +++ b/packages/flutter/lib/src/widgets/drag_target.dart @@ -256,7 +256,6 @@ class DragRoute extends Route { bool get ephemeral => true; bool get modal => false; bool get opaque => false; - Duration get transitionDuration => const Duration(); Widget build(NavigatorState navigator, PerformanceView nextRoutePerformance) { return new Positioned( diff --git a/packages/flutter/lib/src/widgets/navigator.dart b/packages/flutter/lib/src/widgets/navigator.dart index 112bf87808..909d11bbe7 100644 --- a/packages/flutter/lib/src/widgets/navigator.dart +++ b/packages/flutter/lib/src/widgets/navigator.dart @@ -71,13 +71,6 @@ class NavigatorState extends State { push(new PageRoute(builder)); } - void _insertRoute(Route route) { - _history.insert(_currentPosition, route); - route._onDismissed = _handleRouteDismissed; - route._onRemoveRoute = _handleRemoveRoute; - route.didPush(); - } - void push(Route route) { assert(!_debugCurrentlyHaveRoute(route)); setState(() { @@ -119,13 +112,18 @@ class NavigatorState extends State { return index >= 0 && index <= _currentPosition; } - void _handleRouteDismissed(Route route) { + void _didDismissRoute(Route route) { assert(_history.contains(route)); if (_history.lastIndexOf(route) <= _currentPosition) popRoute(route); } - void _handleRemoveRoute(Route route) { + void _insertRoute(Route route) { + _history.insert(_currentPosition, route); + route.didPush(this); + } + + void _removeRoute(Route route) { assert(_history.contains(route)); setState(() { _history.remove(route); @@ -165,33 +163,7 @@ class NavigatorState extends State { } - abstract class Route { - Route() { - _performance = createPerformance(); - } - - PerformanceView get performance => _performance?.view; - Performance _performance; - _RouteCallback _onDismissed; - _RouteCallback _onRemoveRoute; - - Performance createPerformance() { - Duration duration = transitionDuration; - if (duration > Duration.ZERO) { - return new Performance(duration: duration) - ..addStatusListener((PerformanceStatus status) { - if (status == PerformanceStatus.dismissed) { - if (_onDismissed != null) - _onDismissed(this); - if (_onRemoveRoute != null) - _onRemoveRoute(this); - } - }); - } - return null; - } - /// If hasContent is true, then the route represents some on-screen state. /// /// If hasContent is false, then no performance will be created, and the values of @@ -242,32 +214,69 @@ abstract class Route { /// cover the entire application surface or are in any way semi-transparent. bool get opaque => false; - /// If this is set to a non-zero [Duration], then an [Performance] - /// object, available via the performance field, will be created when the - /// route is first built, using the duration described here. - Duration get transitionDuration => Duration.ZERO; - - bool get isActuallyOpaque => (performance == null || _performance.isCompleted) && opaque; + PerformanceView get performance => null; + bool get isActuallyOpaque => (performance == null || performance.isCompleted) && opaque; Widget build(NavigatorState navigator, PerformanceView nextRoutePerformance); - void didPush() { - _performance?.forward(); + NavigatorState _navigator; + + void didPush(NavigatorState navigator) { + assert(_navigator == null); + _navigator = navigator; + assert(_navigator != null); + performance?.addStatusListener(_handlePerformanceStatusChanged); } void didPop([dynamic result]) { - _performance?.reverse(); - if (performance == null && _onRemoveRoute != null) - _onRemoveRoute(this); + assert(_navigator != null); + if (performance == null) + _navigator._removeRoute(this); + } + + void _handlePerformanceStatusChanged(PerformanceStatus status) { + if (status == PerformanceStatus.dismissed) { + _navigator._didDismissRoute(this); + _navigator._removeRoute(this); + _navigator = null; + } } String toString() => '$runtimeType()'; } +abstract class PerformanceRoute extends Route { + PerformanceView get performance => _performance?.view; + Performance _performance; + + Performance createPerformance() { + Duration duration = transitionDuration; + assert(duration >= Duration.ZERO); + return new Performance(duration: duration); + } + + Duration get transitionDuration; + + bool get isActuallyOpaque => (performance == null || _performance.isCompleted) && opaque; + + Widget build(NavigatorState navigator, PerformanceView nextRoutePerformance); + + void didPush(NavigatorState navigator) { + _performance = createPerformance(); + super.didPush(navigator); + _performance?.forward(); + } + + void didPop([dynamic result]) { + _performance?.reverse(); + super.didPop(result); + } +} + const Duration _kTransitionDuration = const Duration(milliseconds: 150); const Point _kTransitionStartPoint = const Point(0.0, 75.0); -class PageRoute extends Route { +class PageRoute extends PerformanceRoute { PageRoute(this.builder); final RouteBuilder builder; diff --git a/packages/flutter/lib/src/widgets/popup_menu.dart b/packages/flutter/lib/src/widgets/popup_menu.dart index e3cd1059ce..518d921a95 100644 --- a/packages/flutter/lib/src/widgets/popup_menu.dart +++ b/packages/flutter/lib/src/widgets/popup_menu.dart @@ -117,7 +117,7 @@ class MenuPosition { final double left; } -class _MenuRoute extends Route { +class _MenuRoute extends PerformanceRoute { _MenuRoute({ this.completer, this.position, this.builder, this.level }); final Completer completer; diff --git a/packages/flutter/lib/src/widgets/snack_bar.dart b/packages/flutter/lib/src/widgets/snack_bar.dart index 3db720df0f..85454960b4 100644 --- a/packages/flutter/lib/src/widgets/snack_bar.dart +++ b/packages/flutter/lib/src/widgets/snack_bar.dart @@ -97,7 +97,7 @@ class SnackBar extends StatelessComponent { } } -class _SnackBarRoute extends Route { +class _SnackBarRoute extends PerformanceRoute { _SnackBarRoute({ this.content, this.actions }); final Widget content; From 73dce01e87ea4f74626fc7216e9611ad801788d2 Mon Sep 17 00:00:00 2001 From: Chinmay Garde Date: Wed, 7 Oct 2015 11:22:51 -0700 Subject: [PATCH 03/84] Allow updating the rasterizer tracing threshold from Dart --- packages/flutter/lib/src/rendering/layer.dart | 8 ++++++-- packages/flutter/lib/src/rendering/object.dart | 5 +++-- .../lib/src/rendering/statistics_box.dart | 16 ++++++++++++++-- .../lib/src/widgets/statistics_overlay.dart | 11 ++++++++--- 4 files changed, 31 insertions(+), 9 deletions(-) diff --git a/packages/flutter/lib/src/rendering/layer.dart b/packages/flutter/lib/src/rendering/layer.dart index 1e22221d39..efff6c4590 100644 --- a/packages/flutter/lib/src/rendering/layer.dart +++ b/packages/flutter/lib/src/rendering/layer.dart @@ -93,18 +93,22 @@ class StatisticsLayer extends Layer { StatisticsLayer({ Offset offset: Offset.zero, this.paintBounds, - this.optionsMask + this.optionsMask, + this.rasterizerThreshold }) : super(offset: offset); /// The rectangle in this layer's coodinate system that bounds the recording Rect paintBounds; /// A mask specifying the statistics to display - int optionsMask; + final int optionsMask; + + final int rasterizerThreshold; void addToScene(sky.SceneBuilder builder, Offset layerOffset) { assert(optionsMask != null); builder.addStatistics(optionsMask, paintBounds.shift(layerOffset)); + builder.setRasterizerTracingThreshold(rasterizerThreshold); } } diff --git a/packages/flutter/lib/src/rendering/object.dart b/packages/flutter/lib/src/rendering/object.dart index 4ebca858aa..66445d2858 100644 --- a/packages/flutter/lib/src/rendering/object.dart +++ b/packages/flutter/lib/src/rendering/object.dart @@ -132,11 +132,12 @@ class PaintingContext { } } - void paintStatistics(int optionsMask, Offset offset, Size size) { + void paintStatistics(int optionsMask, int rasterizerThreshold, Offset offset, Size size) { StatisticsLayer statsLayer = new StatisticsLayer( offset: offset, paintBounds: new Rect.fromLTWH(0.0, 0.0, size.width, size.height), - optionsMask : optionsMask + optionsMask : optionsMask, + rasterizerThreshold : rasterizerThreshold ); _containerLayer.append(statsLayer); } diff --git a/packages/flutter/lib/src/rendering/statistics_box.dart b/packages/flutter/lib/src/rendering/statistics_box.dart index 98780ea889..e4235c7bbb 100644 --- a/packages/flutter/lib/src/rendering/statistics_box.dart +++ b/packages/flutter/lib/src/rendering/statistics_box.dart @@ -7,7 +7,9 @@ import 'package:sky/src/rendering/object.dart'; class StatisticsBox extends RenderBox { - StatisticsBox({int optionsMask: 0}) : _optionsMask = optionsMask; + StatisticsBox({int optionsMask: 0, int rasterizerThreshold: 0}) + : _optionsMask = optionsMask, + _rasterizerThreshold = rasterizerThreshold; int _optionsMask; int get optionsMask => _optionsMask; @@ -19,6 +21,16 @@ class StatisticsBox extends RenderBox { markNeedsPaint(); } + int _rasterizerThreshold; + int get rasterizerThreshold => _rasterizerThreshold; + void set rasterizerThreshold (int threshold) { + if (threshold == _rasterizerThreshold) { + return; + } + _rasterizerThreshold = threshold; + markNeedsPaint(); + } + bool get sizedByParent => true; double getMinIntrinsicWidth(BoxConstraints constraints) { @@ -42,6 +54,6 @@ class StatisticsBox extends RenderBox { } void paint(PaintingContext context, Offset offset) { - context.paintStatistics(optionsMask, offset, size); + context.paintStatistics(optionsMask, rasterizerThreshold, offset, size); } } diff --git a/packages/flutter/lib/src/widgets/statistics_overlay.dart b/packages/flutter/lib/src/widgets/statistics_overlay.dart index e3d62fc556..fbc3ae33f7 100644 --- a/packages/flutter/lib/src/widgets/statistics_overlay.dart +++ b/packages/flutter/lib/src/widgets/statistics_overlay.dart @@ -40,10 +40,10 @@ class StatisticsOverlay extends LeafRenderObjectWidget { /// Create a statistics overlay that only displays specific statistics. The /// mask is created by shifting 1 by the index of the specific StatisticOption /// to enable. - StatisticsOverlay({ this.optionsMask, Key key }) : super(key: key); + StatisticsOverlay({ this.optionsMask, this.rasterizerThreshold: 0, Key key }) : super(key: key); /// Create a statistics overaly that displays all available statistics - StatisticsOverlay.allEnabled({ Key key }) : super(key: key), optionsMask = ( + StatisticsOverlay.allEnabled({ Key key, this.rasterizerThreshold: 0 }) : super(key: key), optionsMask = ( 1 << StatisticsOption.displayRasterizerStatistics.index | 1 << StatisticsOption.visualizeRasterizerStatistics.index | 1 << StatisticsOption.displayEngineStatistics.index | @@ -51,10 +51,15 @@ class StatisticsOverlay extends LeafRenderObjectWidget { ); final int optionsMask; + final int rasterizerThreshold; - StatisticsBox createRenderObject() => new StatisticsBox(optionsMask: optionsMask); + StatisticsBox createRenderObject() => new StatisticsBox( + optionsMask: optionsMask, + rasterizerThreshold: rasterizerThreshold + ); void updateRenderObject(StatisticsBox renderObject, RenderObjectWidget oldWidget) { renderObject.optionsMask = optionsMask; + renderObject.rasterizerThreshold = rasterizerThreshold; } } From 9f8b53f47a0899e4ffca1d15cf17cf028431591c Mon Sep 17 00:00:00 2001 From: Chinmay Garde Date: Wed, 7 Oct 2015 11:47:30 -0700 Subject: [PATCH 04/84] Document StatisticsOverlay.rasterizerThreshold --- .../lib/src/widgets/statistics_overlay.dart | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/packages/flutter/lib/src/widgets/statistics_overlay.dart b/packages/flutter/lib/src/widgets/statistics_overlay.dart index fbc3ae33f7..f3066413c7 100644 --- a/packages/flutter/lib/src/widgets/statistics_overlay.dart +++ b/packages/flutter/lib/src/widgets/statistics_overlay.dart @@ -51,6 +51,33 @@ class StatisticsOverlay extends LeafRenderObjectWidget { ); final int optionsMask; + + /// The rasterizer threshold is an integer specifying the number of frame + /// intervals that the rasterizer must miss before it decides that the frame + /// is suitable for capturing an SkPicture trace from for further analysis. + /// + /// For example, if you want a trace of all pictures that could not be + /// renderered by the rasterizer within the frame boundary (and hence caused + /// jank), specify 1. Specifying 2 will trace all pictures that took more + /// more than 2 frame intervals to render. Adjust this value to only capture + /// the particularly expensive pictures while skipping the others. Specifying + /// 0 disables all capture. + /// + /// Captured traces are placed on your device in the application documents + /// directory in this form "trace_.skp". These can + /// be viewed in the Skia debugger. + /// + /// Notes: + /// The rasterizer only takes into account the time it took to render + /// the already constructed picture. This include the Skia calls (which is + /// also why an SkPicture trace is generated) but not any of the time spent in + /// dart to construct that picture. To profile that part of your code, use + /// the instrumentation available in observatory. + /// + /// To decide what threshold interval to use, count the number of horizontal + /// lines displayed in the statistics overlay for the rasterizer (not the + /// engine). That should give an idea of how often frames are skipped (and by + /// how many frame intervals). final int rasterizerThreshold; StatisticsBox createRenderObject() => new StatisticsBox( From c363133da35cf5a56c9e2be4bcc9ad38c4a2f129 Mon Sep 17 00:00:00 2001 From: Viktor Lidholt Date: Wed, 7 Oct 2015 13:26:36 -0700 Subject: [PATCH 05/84] Adds support for applying forces and impulses to sprite physics --- .../flutter_sprites/lib/physics_body.dart | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/packages/flutter_sprites/lib/physics_body.dart b/packages/flutter_sprites/lib/physics_body.dart index 0d12febef5..e907b30844 100644 --- a/packages/flutter_sprites/lib/physics_body.dart +++ b/packages/flutter_sprites/lib/physics_body.dart @@ -232,6 +232,58 @@ class PhysicsBody { bool _attached = false; + void applyForce(Offset force, Point worldPoint) { + assert(_body != null); + + Vector2 b2Force = new Vector2( + force.dx / _physicsNode.b2WorldToNodeConversionFactor, + force.dy / _physicsNode.b2WorldToNodeConversionFactor); + + Vector2 b2Point = new Vector2( + worldPoint.x / _physicsNode.b2WorldToNodeConversionFactor, + worldPoint.y / _physicsNode.b2WorldToNodeConversionFactor + ); + + _body.applyForce(b2Force, b2Point); + } + + void applyForceToCenter(Offset force) { + assert(_body != null); + + Vector2 b2Force = new Vector2( + force.dx / _physicsNode.b2WorldToNodeConversionFactor, + force.dy / _physicsNode.b2WorldToNodeConversionFactor); + + _body.applyForceToCenter(b2Force); + } + + void applyTorque(double torque) { + assert(_body != null); + + _body.applyTorque(torque / _physicsNode.b2WorldToNodeConversionFactor); + } + + void applyLinearImpulse(Offset impulse, Point worldPoint, [bool wake = true]) { + assert(_body != null); + + Vector2 b2Impulse = new Vector2( + impulse.dx / _physicsNode.b2WorldToNodeConversionFactor, + impulse.dy / _physicsNode.b2WorldToNodeConversionFactor); + + Vector2 b2Point = new Vector2( + worldPoint.x / _physicsNode.b2WorldToNodeConversionFactor, + worldPoint.y / _physicsNode.b2WorldToNodeConversionFactor + ); + + _body.applyLinearImpulse(b2Impulse, b2Point, wake); + } + + void applyAngularImpulse(double impulse) { + assert(_body != null); + + _body.applyAngularImpulse(impulse / _physicsNode.b2WorldToNodeConversionFactor); + } + void _attach(PhysicsNode physicsNode, Node node) { assert(_attached == false); From 020e749291ab9bf4d6719dec5ea669ffa2ad916c Mon Sep 17 00:00:00 2001 From: Viktor Lidholt Date: Wed, 7 Oct 2015 14:05:11 -0700 Subject: [PATCH 06/84] Fixes typo in sprite physics --- packages/flutter_sprites/lib/physics_body.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/flutter_sprites/lib/physics_body.dart b/packages/flutter_sprites/lib/physics_body.dart index e907b30844..178b1ac48c 100644 --- a/packages/flutter_sprites/lib/physics_body.dart +++ b/packages/flutter_sprites/lib/physics_body.dart @@ -16,7 +16,7 @@ class PhysicsBody { Offset linearVelocity: Offset.zero, double angularVelocity: 0.0, this.linearDampening: 0.0, - double awakeangularDampening: 0.0, + double angularDampening: 0.0, bool allowSleep: true, bool awake: true, bool fixedRotation: false, From d45bf1457c15a6998da09a1a22b19aa3fabfb957 Mon Sep 17 00:00:00 2001 From: Hixie Date: Wed, 7 Oct 2015 08:40:55 -0700 Subject: [PATCH 07/84] HomogeneousViewport support for Theme.of() Previously, RenderObjectElements didn't support being marked dirty. This is fine, except for MixedViewport and HomogeneousViewport, which have builder functions to which they hand themselves as a BuildContext. If those builder functions call, e.g., Theme.of(), then when the theme changes, the Inherited logic tries to tell the RenderObjectElement object that its dependencies changed and that doesn't go down well. This patch fixes this by making RenderObjectElement a BuildableElement, and making MixedViewport and HomogeneousViewport hook into that to rebuild themselves appropriately. Also, this was only found at all because ThemeData didn't implement operator==, so we were aggressively marking the entire tree dirty all the time. That's fixed here too. Also, I changed card_collection.dart to have more features to make this easier to test. This found bugs #1524, #1522, #1528, #1529, #1530, #1531. --- examples/widgets/card_collection.dart | 79 ++++--- .../flutter/lib/src/material/theme_data.dart | 34 +++ .../flutter/lib/src/widgets/framework.dart | 215 +++++++++++------- .../lib/src/widgets/homogeneous_viewport.dart | 6 +- .../lib/src/widgets/mixed_viewport.dart | 46 ++-- .../flutter/lib/src/widgets/navigator.dart | 1 - packages/flutter/lib/src/widgets/radio.dart | 2 +- 7 files changed, 242 insertions(+), 141 deletions(-) diff --git a/examples/widgets/card_collection.dart b/examples/widgets/card_collection.dart index 359b3db226..ce7ac66ee6 100644 --- a/examples/widgets/card_collection.dart +++ b/examples/widgets/card_collection.dart @@ -9,11 +9,13 @@ import 'package:sky/painting.dart'; import 'package:sky/widgets.dart'; class CardModel { - CardModel(this.value, this.height, this.color); + CardModel(this.value, this.height) { + label = "Item $value"; + } int value; double height; - Color color; - String get label => "Item $value"; + int get color => ((value % 9) + 1) * 100; + String label; Key get key => new ObjectKey(this); } @@ -36,6 +38,7 @@ class CardCollectionState extends State { final TextStyle backgroundTextStyle = Typography.white.title.copyWith(textAlign: TextAlign.center); + Map _primaryColor = Colors.deepPurple; List _cardModels; DismissDirection _dismissDirection = DismissDirection.horizontal; bool _snapToCenter = false; @@ -50,19 +53,13 @@ class CardCollectionState extends State { 48.0, 63.0, 82.0, 146.0, 60.0, 55.0, 84.0, 96.0, 50.0, 48.0, 63.0, 82.0, 146.0, 60.0, 55.0, 84.0, 96.0, 50.0 ]; - _cardModels = new List.generate(cardHeights.length, (i) { - Color color = Color.lerp(Colors.red[300], Colors.blue[900], i / cardHeights.length); - return new CardModel(i, cardHeights[i], color); - }); + _cardModels = new List.generate(cardHeights.length, (i) => new CardModel(i, cardHeights[i])); } void _initFixedSizedCardModels() { const int cardCount = 27; const double cardHeight = 100.0; - _cardModels = new List.generate(cardCount, (i) { - Color color = Color.lerp(Colors.red[300], Colors.blue[900], i / cardCount); - return new CardModel(i, cardHeight, color); - }); + _cardModels = new List.generate(cardCount, (i) => new CardModel(i, cardHeight)); } void _initCardModels() { @@ -126,9 +123,14 @@ class CardCollectionState extends State { buildDrawerCheckbox("Fixed size cards", _fixedSizeCards, _toggleFixedSizeCards), buildDrawerCheckbox("Let the sun shine", _sunshine, _toggleSunshine), new DrawerDivider(), - buildDrawerRadioItem(DismissDirection.horizontal, 'action/code'), - buildDrawerRadioItem(DismissDirection.left, 'navigation/arrow_back'), - buildDrawerRadioItem(DismissDirection.right, 'navigation/arrow_forward'), + buildDrawerRadioItem("Deep Purple", Colors.deepPurple, _primaryColor, _selectColor), + buildDrawerRadioItem("Green", Colors.green, _primaryColor, _selectColor), + buildDrawerRadioItem("Amber", Colors.amber, _primaryColor, _selectColor), + buildDrawerRadioItem("Teal", Colors.teal, _primaryColor, _selectColor), + new DrawerDivider(), + buildDrawerRadioItem("Dismiss horizontally", DismissDirection.horizontal, _dismissDirection, _changeDismissDirection, icon: 'action/code'), + buildDrawerRadioItem("Dismiss left", DismissDirection.left, _dismissDirection, _changeDismissDirection, icon: 'navigation/arrow_back'), + buildDrawerRadioItem("Dismiss right", DismissDirection.right, _dismissDirection, _changeDismissDirection, icon: 'navigation/arrow_forward'), ]) ) ); @@ -158,6 +160,12 @@ class CardCollectionState extends State { }); } + void _selectColor(selection) { + setState(() { + _primaryColor = selection; + }); + } + void _changeDismissDirection(DismissDirection newDismissDirection) { setState(() { _dismissDirection = newDismissDirection; @@ -175,16 +183,16 @@ class CardCollectionState extends State { ); } - Widget buildDrawerRadioItem(DismissDirection direction, String icon) { + Widget buildDrawerRadioItem(String label, itemValue, currentValue, RadioValueChanged onChanged, { String icon }) { return new DrawerItem( icon: icon, - onPressed: () { _changeDismissDirection(direction); }, + onPressed: () { onChanged(itemValue); }, child: new Row([ - new Flexible(child: new Text(_dismissDirectionText(direction))), + new Flexible(child: new Text(label)), new Radio( - value: direction, - onChanged: _changeDismissDirection, - groupValue: _dismissDirection + value: itemValue, + groupValue: currentValue, + onChanged: onChanged ) ]) ); @@ -210,11 +218,22 @@ class CardCollectionState extends State { onResized: () { _invalidator([index]); }, onDismissed: () { dismissCard(cardModel); }, child: new Card( - color: cardModel.color, + color: Theme.of(context).primarySwatch[cardModel.color], child: new Container( height: cardModel.height, padding: const EdgeDims.all(8.0), - child: new Center(child: new Text(cardModel.label, style: cardLabelStyle)) + child: new Center( + child: new DefaultTextStyle( + style: cardLabelStyle, + child: new Input( + key: new GlobalObjectKey(cardModel), + initialValue: cardModel.label, + onChanged: (String value) { + cardModel.label = value; + } + ) + ) + ) ) ) ); @@ -341,9 +360,14 @@ class CardCollectionState extends State { body = new Stack([body, indicator]); } - return new Scaffold( - toolBar: buildToolBar(), - body: body + return new Theme( + data: new ThemeData( + primarySwatch: _primaryColor + ), + child: new Scaffold( + toolBar: buildToolBar(), + body: body + ) ); } } @@ -351,11 +375,6 @@ class CardCollectionState extends State { void main() { runApp(new App( title: 'Cards', - theme: new ThemeData( - brightness: ThemeBrightness.light, - primarySwatch: Colors.blue, - accentColor: Colors.redAccent[200] - ), routes: { '/': (RouteArguments args) => new CardCollection(navigator: args.navigator), } diff --git a/packages/flutter/lib/src/material/theme_data.dart b/packages/flutter/lib/src/material/theme_data.dart index 3c3868b39c..4c45b16370 100644 --- a/packages/flutter/lib/src/material/theme_data.dart +++ b/packages/flutter/lib/src/material/theme_data.dart @@ -79,4 +79,38 @@ class ThemeData { Color get accentColor => _accentColor; final ThemeBrightness accentColorBrightness; + + bool operator==(Object other) { + if (other.runtimeType != runtimeType) + return false; + ThemeData otherData = other; + return (otherData.brightness == brightness) && + (otherData.primarySwatch == primarySwatch) && + (otherData.canvasColor == canvasColor) && + (otherData.cardColor == cardColor) && + (otherData.dividerColor == dividerColor) && + (otherData.hintColor == hintColor) && + (otherData.highlightColor == highlightColor) && + (otherData.selectedColor == selectedColor) && + (otherData.hintOpacity == hintOpacity) && + (otherData.text == text) && + (otherData.primaryColorBrightness == primaryColorBrightness) && + (otherData.accentColorBrightness == accentColorBrightness); + } + int get hashCode { + int value = 373; + value = 37 * value + brightness.hashCode; + value = 37 * value + primarySwatch.hashCode; + value = 37 * value + canvasColor.hashCode; + value = 37 * value + cardColor.hashCode; + value = 37 * value + dividerColor.hashCode; + value = 37 * value + hintColor.hashCode; + value = 37 * value + highlightColor.hashCode; + value = 37 * value + selectedColor.hashCode; + value = 37 * value + hintOpacity.hashCode; + value = 37 * value + text.hashCode; + value = 37 * value + primaryColorBrightness.hashCode; + value = 37 * value + accentColorBrightness.hashCode; + return value; + } } diff --git a/packages/flutter/lib/src/widgets/framework.dart b/packages/flutter/lib/src/widgets/framework.dart index f5b64eff8e..f92219de40 100644 --- a/packages/flutter/lib/src/widgets/framework.dart +++ b/packages/flutter/lib/src/widgets/framework.dart @@ -751,8 +751,7 @@ abstract class Element implements BuildContext { assert(() { _debugLifecycleState = _ElementLifecycle.active; return true; }); } - /// Called when an Element is removed from the tree. - /// Currently, an Element removed from the tree never returns. + /// Called when an Element is removed from the tree permanently. void unmount() { assert(_debugLifecycleState == _ElementLifecycle.inactive); assert(widget != null); @@ -824,25 +823,21 @@ class ErrorWidget extends LeafRenderObjectWidget { RenderBox createRenderObject() => new RenderErrorBox(); } -typedef Widget WidgetBuilder(BuildContext context); typedef void BuildScheduler(BuildableElement element); -/// Base class for the instantiation of StatelessComponent and StatefulComponent -/// widgets. +/// Base class for instantiations of widgets that have builders and can be +/// marked dirty. abstract class BuildableElement extends Element { BuildableElement(T widget) : super(widget); - WidgetBuilder _builder; - Element _child; - /// Returns true if the element has been marked as needing rebuilding. bool get dirty => _dirty; bool _dirty = true; - // We to let component authors call setState from initState, didUpdateConfig, - // and build even when state is locked because its convenient and a no-op - // anyway. This flag ensures that this convenience is only allowed on the - // element currently undergoing initState, didUpdateConfig, or build. + // We let component authors call setState from initState, didUpdateConfig, and + // build even when state is locked because its convenient and a no-op anyway. + // This flag ensures that this convenience is only allowed on the element + // currently undergoing initState, didUpdateConfig, or build. bool _debugAllowIgnoredCallsToMarkNeedsBuild = false; bool _debugSetAllowIgnoredCallsToMarkNeedsBuild(bool value) { assert(_debugAllowIgnoredCallsToMarkNeedsBuild == !value); @@ -850,73 +845,12 @@ abstract class BuildableElement extends Element { return true; } - void mount(Element parent, dynamic newSlot) { - super.mount(parent, newSlot); - assert(_child == null); - assert(_active); - rebuild(); - assert(_child != null); - } - - static BuildableElement _debugCurrentBuildTarget; - - /// Reinvokes the build() method of the StatelessComponent object (for - /// stateless components) or the State object (for stateful components) and - /// then updates the widget tree. - /// - /// Called automatically during mount() to generate the first build, by the - /// binding when scheduleBuild() has been called to mark this element dirty, - /// and by update() when the Widget has changed. - void rebuild() { - assert(_debugLifecycleState != _ElementLifecycle.initial); - if (!_active || !_dirty) { - _dirty = false; - return; - } - assert(_debugLifecycleState == _ElementLifecycle.active); - assert(_debugStateLocked); - assert(_debugSetAllowIgnoredCallsToMarkNeedsBuild(true)); - BuildableElement debugPreviousBuildTarget; - assert(() { - debugPreviousBuildTarget = _debugCurrentBuildTarget; - _debugCurrentBuildTarget = this; - return true; - }); - Widget built; - try { - built = _builder(this); - assert(built != null); - } catch (e, stack) { - _debugReportException('building ${_widget}', e, stack); - built = new ErrorWidget(); - } finally { - // We delay marking the element as clean until after calling _builder so - // that attempts to markNeedsBuild() during build() will be ignored. - _dirty = false; - assert(_debugSetAllowIgnoredCallsToMarkNeedsBuild(false)); - } - - try { - _child = updateChild(_child, built, slot); - assert(_child != null); - } catch (e, stack) { - _debugReportException('building ${_widget}', e, stack); - built = new ErrorWidget(); - _child = updateChild(null, built, slot); - } - - assert(() { - assert(_debugCurrentBuildTarget == this); - _debugCurrentBuildTarget = debugPreviousBuildTarget; - return true; - }); - } - static BuildScheduler scheduleBuildFor; static int _debugStateLockLevel = 0; static bool get _debugStateLocked => _debugStateLockLevel > 0; static bool _debugBuilding = false; + static BuildableElement _debugCurrentBuildTarget; /// Establishes a scope in which component build functions can run. /// @@ -989,17 +923,39 @@ abstract class BuildableElement extends Element { scheduleBuildFor(this); } - void visitChildren(ElementVisitor visitor) { - if (_child != null) - visitor(_child); + /// Called by the binding when scheduleBuild() has been called to mark this + /// element dirty, and, in Components, by update() when the Widget has + /// changed. + void rebuild() { + assert(_debugLifecycleState != _ElementLifecycle.initial); + if (!_active || !_dirty) { + _dirty = false; + return; + } + assert(_debugLifecycleState == _ElementLifecycle.active); + assert(_debugStateLocked); + BuildableElement debugPreviousBuildTarget; + assert(() { + debugPreviousBuildTarget = _debugCurrentBuildTarget; + _debugCurrentBuildTarget = this; + return true; + }); + try { + performRebuild(); + } catch (e, stack) { + _debugReportException('rebuilding $this', e, stack); + } finally { + assert(() { + assert(_debugCurrentBuildTarget == this); + _debugCurrentBuildTarget = debugPreviousBuildTarget; + return true; + }); + } + assert(!_dirty); } - bool detachChild(Element child) { - assert(child == _child); - _deactivateChild(_child); - _child = null; - return true; - } + /// Called by rebuild() after the appropriate checks have been made. + void performRebuild(); void dependenciesChanged() { markNeedsBuild(); @@ -1012,8 +968,70 @@ abstract class BuildableElement extends Element { } } +typedef Widget WidgetBuilder(BuildContext context); + +/// Base class for the instantiation of StatelessComponent and StatefulComponent +/// widgets. +abstract class ComponentElement extends BuildableElement { + ComponentElement(T widget) : super(widget); + + WidgetBuilder _builder; + Element _child; + + void mount(Element parent, dynamic newSlot) { + super.mount(parent, newSlot); + assert(_child == null); + assert(_active); + rebuild(); + assert(_child != null); + } + + /// Reinvokes the build() method of the StatelessComponent object (for + /// stateless components) or the State object (for stateful components) and + /// then updates the widget tree. + /// + /// Called automatically during mount() to generate the first build, and by + /// rebuild() when the element needs updating. + void performRebuild() { + assert(_debugSetAllowIgnoredCallsToMarkNeedsBuild(true)); + Widget built; + try { + built = _builder(this); + assert(built != null); + } catch (e, stack) { + _debugReportException('building ${_widget}', e, stack); + built = new ErrorWidget(); + } finally { + // We delay marking the element as clean until after calling _builder so + // that attempts to markNeedsBuild() during build() will be ignored. + _dirty = false; + assert(_debugSetAllowIgnoredCallsToMarkNeedsBuild(false)); + } + try { + _child = updateChild(_child, built, slot); + assert(_child != null); + } catch (e, stack) { + _debugReportException('building ${_widget}', e, stack); + built = new ErrorWidget(); + _child = updateChild(null, built, slot); + } + } + + void visitChildren(ElementVisitor visitor) { + if (_child != null) + visitor(_child); + } + + bool detachChild(Element child) { + assert(child == _child); + _deactivateChild(_child); + _child = null; + return true; + } +} + /// Instantiation of StatelessComponent widgets. -class StatelessComponentElement extends BuildableElement { +class StatelessComponentElement extends ComponentElement { StatelessComponentElement(T widget) : super(widget) { _builder = widget.build; } @@ -1028,7 +1046,7 @@ class StatelessComponentElement extends BuildableE } /// Instantiation of StatefulComponent widgets. -class StatefulComponentElement> extends BuildableElement { +class StatefulComponentElement> extends ComponentElement { StatefulComponentElement(T widget) : _state = widget.createState(), super(widget) { assert(_state._debugTypesAreRight(widget)); // can't use T and U, since normally we don't actually set those @@ -1142,8 +1160,10 @@ class InheritedElement extends StatelessComponentElement { InheritedWidget oldWidget = widget; super.update(newWidget); assert(widget == newWidget); - if (widget.updateShouldNotify(oldWidget)) + if (widget.updateShouldNotify(oldWidget)) { + assert(widget != oldWidget); _notifyDescendants(); + } } void _notifyDescendants() { @@ -1161,7 +1181,7 @@ class InheritedElement extends StatelessComponentElement { } /// Base class for instantiations of RenderObjectWidget subclasses -abstract class RenderObjectElement extends Element { +abstract class RenderObjectElement extends BuildableElement { RenderObjectElement(T widget) : _renderObject = widget.createRenderObject(), super(widget); @@ -1195,6 +1215,7 @@ abstract class RenderObjectElement extends Element ParentDataElement parentDataElement = _findAncestorParentDataElement(); if (parentDataElement != null) updateParentData(parentDataElement.widget); + _dirty = false; } void update(T newWidget) { @@ -1202,6 +1223,26 @@ abstract class RenderObjectElement extends Element super.update(newWidget); assert(widget == newWidget); widget.updateRenderObject(renderObject, oldWidget); + _dirty = false; + } + + void performRebuild() { + reinvokeBuilders(); + _dirty = false; + } + + void reinvokeBuilders() { + // There's no way to mark a normal RenderObjectElement dirty. + // We inherit from BuildableElement so that subclasses can themselves + // implement reinvokeBuilders() if they do provide a way to mark themeselves + // dirty, e.g. if they have a builder callback. (Builder callbacks have a + // 'BuildContext' argument which you can pass to Theme.of() and other + // InheritedWidget APIs which eventually trigger a rebuild.) + print('${runtimeType} failed to implement reinvokeBuilders(), but got marked dirty'); + assert(() { + 'reinvokeBuilders() not implemented'; + return false; + }); } /// Utility function for subclasses that have one or more lists of children. diff --git a/packages/flutter/lib/src/widgets/homogeneous_viewport.dart b/packages/flutter/lib/src/widgets/homogeneous_viewport.dart index 85f8009bc4..18ac69adee 100644 --- a/packages/flutter/lib/src/widgets/homogeneous_viewport.dart +++ b/packages/flutter/lib/src/widgets/homogeneous_viewport.dart @@ -37,8 +37,8 @@ class HomogeneousViewport extends RenderObjectWidget { RenderBlockViewport createRenderObject() => new RenderBlockViewport(); bool isLayoutDifferentThan(HomogeneousViewport oldWidget) { + // changing the builder doesn't imply the layout changed return itemsWrap != oldWidget.itemsWrap || - itemsWrap != oldWidget.itemsWrap || itemExtent != oldWidget.itemExtent || itemCount != oldWidget.itemCount || direction != oldWidget.direction || @@ -89,6 +89,10 @@ class _HomogeneousViewportElement extends RenderObjectElement { if (changes != _ChangeDescription.none || !isValid) { renderObject.markNeedsLayout(); } else { - // we just need to redraw our existing widgets as-is - if (_childrenByKey.length > 0) { - assert(_firstVisibleChildIndex >= 0); - assert(renderObject != null); - final int startIndex = _firstVisibleChildIndex; - int lastIndex = startIndex + _childrenByKey.length - 1; - Element nextSibling = null; - for (int index = lastIndex; index > startIndex; index -= 1) { - final Widget newWidget = _buildWidgetAt(index); - final _ChildKey key = new _ChildKey.fromWidget(newWidget); - final Element oldElement = _childrenByKey[key]; - assert(oldElement != null); - final Element newElement = updateChild(oldElement, newWidget, nextSibling); - assert(newElement != null); - _childrenByKey[key] = newElement; - // Verify that it hasn't changed size. - // If this assertion fires, it means you didn't call "invalidate" - // before changing the size of one of your items. - assert(_debugIsSameSize(newElement, index, _lastLayoutConstraints)); - nextSibling = newElement; - } + reinvokeBuilders(); + } + } + + void reinvokeBuilders() { + // we just need to redraw our existing widgets as-is + if (_childrenByKey.length > 0) { + assert(_firstVisibleChildIndex >= 0); + assert(renderObject != null); + final int startIndex = _firstVisibleChildIndex; + int lastIndex = startIndex + _childrenByKey.length - 1; + Element nextSibling = null; + for (int index = lastIndex; index >= startIndex; index -= 1) { + final Widget newWidget = _buildWidgetAt(index); + final _ChildKey key = new _ChildKey.fromWidget(newWidget); + final Element oldElement = _childrenByKey[key]; + assert(oldElement != null); + final Element newElement = updateChild(oldElement, newWidget, nextSibling); + assert(newElement != null); + _childrenByKey[key] = newElement; + // Verify that it hasn't changed size. + // If this assertion fires, it means you didn't call "invalidate" + // before changing the size of one of your items. + assert(_debugIsSameSize(newElement, index, _lastLayoutConstraints)); + nextSibling = newElement; } } } diff --git a/packages/flutter/lib/src/widgets/navigator.dart b/packages/flutter/lib/src/widgets/navigator.dart index 909d11bbe7..5f879bc034 100644 --- a/packages/flutter/lib/src/widgets/navigator.dart +++ b/packages/flutter/lib/src/widgets/navigator.dart @@ -18,7 +18,6 @@ class RouteArguments { typedef Widget RouteBuilder(RouteArguments args); typedef RouteBuilder RouteGenerator(String name); typedef void StateRouteCallback(StateRoute route); -typedef void _RouteCallback(Route route); class Navigator extends StatefulComponent { Navigator({ diff --git a/packages/flutter/lib/src/widgets/radio.dart b/packages/flutter/lib/src/widgets/radio.dart index 53f487d08b..dfecc4cbbf 100644 --- a/packages/flutter/lib/src/widgets/radio.dart +++ b/packages/flutter/lib/src/widgets/radio.dart @@ -12,7 +12,7 @@ import 'package:sky/src/widgets/theme.dart'; const sky.Color _kLightOffColor = const sky.Color(0x8A000000); const sky.Color _kDarkOffColor = const sky.Color(0xB2FFFFFF); -typedef RadioValueChanged(Object value); +typedef void RadioValueChanged(Object value); class Radio extends StatelessComponent { Radio({ From 68acd2615da53c5d3f2be728a7f9eb54fb99bacc Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Wed, 7 Oct 2015 20:09:45 -0700 Subject: [PATCH 08/84] The Drawer should animate out when popped off the navigator Now with more clear ownership over the Performance. --- packages/flutter/lib/src/widgets/drawer.dart | 134 +++++++++---------- 1 file changed, 64 insertions(+), 70 deletions(-) diff --git a/packages/flutter/lib/src/widgets/drawer.dart b/packages/flutter/lib/src/widgets/drawer.dart index 1d73b9fc84..e294eee6c2 100644 --- a/packages/flutter/lib/src/widgets/drawer.dart +++ b/packages/flutter/lib/src/widgets/drawer.dart @@ -34,120 +34,114 @@ const Duration _kThemeChangeDuration = const Duration(milliseconds: 200); const Point _kOpenPosition = Point.origin; const Point _kClosedPosition = const Point(-_kWidth, 0.0); -class Drawer extends StatefulComponent { - Drawer({ +class _Drawer extends StatelessComponent { + _Drawer({ Key key, this.child, this.level: 3, - this.navigator + this.performance, + this.route }) : super(key: key); final Widget child; final int level; - final NavigatorState navigator; - - DrawerState createState() => new DrawerState(); -} - -class DrawerState extends State { - void initState() { - super.initState(); - _performance = new Performance(duration: _kBaseSettleDuration) - ..addStatusListener((PerformanceStatus status) { - if (status == PerformanceStatus.dismissed) - config.navigator.pop(); - }); - _open(); - } - - Performance _performance; + final PerformanceView performance; + final _DrawerRoute route; Widget build(BuildContext context) { Widget mask = new GestureDetector( - onTap: _close, + onTap: route.close, child: new ColorTransition( - performance: _performance.view, + performance: performance, color: new AnimatedColorValue(Colors.transparent, end: Colors.black54), child: new Container() ) ); Widget content = new SlideTransition( - performance: _performance.view, + performance: performance, position: new AnimatedValue(_kClosedPosition, end: _kOpenPosition), child: new AnimatedContainer( curve: ease, duration: _kThemeChangeDuration, decoration: new BoxDecoration( backgroundColor: Theme.of(context).canvasColor, - boxShadow: shadows[config.level]), + boxShadow: shadows[level]), width: _kWidth, - child: config.child + child: child ) ); - return new GestureDetector( - onHorizontalDragStart: _performance.stop, - onHorizontalDragUpdate: _handleDragUpdate, - onHorizontalDragEnd: _handleDragEnd, - child: new Stack([ - mask, - new Positioned( - top: 0.0, - left: 0.0, - bottom: 0.0, - child: content - ) - ]) - ); - } - - bool get _isMostlyClosed => _performance.progress < 0.5; - - void _handleDragUpdate(double delta) { - _performance.progress += delta / _kWidth; - } - - void _open() { - _performance.fling(velocity: 1.0); - } - - void _close() { - _performance.fling(velocity: -1.0); - } - - void _handleDragEnd(Offset velocity) { - if (velocity.dx.abs() >= _kMinFlingVelocity) { - _performance.fling(velocity: velocity.dx * _kFlingVelocityScale); - } else if (_isMostlyClosed) { - _close(); - } else { - _open(); - } + return new Stack([ + mask, + new Positioned( + top: 0.0, + left: 0.0, + bottom: 0.0, + child: content + ) + ]); } } -class DrawerRoute extends Route { - DrawerRoute({ this.child, this.level }); +class _DrawerRoute extends Route { + _DrawerRoute({ this.child, this.level }); final Widget child; final int level; + PerformanceView get performance => _performance?.view; + Performance _performance = new Performance(duration: _kBaseSettleDuration); + bool get opaque => false; Widget build(NavigatorState navigator, PerformanceView nextRoutePerformance) { return new Focus( key: new GlobalObjectKey(this), autofocus: true, - child: new Drawer( - child: child, - level: level, - navigator: navigator + child: new GestureDetector( + onHorizontalDragStart: () { + _performance?.stop(); + }, + onHorizontalDragUpdate: (double delta) { + _performance?.progress = delta / _kWidth; + }, + onHorizontalDragEnd: _settle, + child: new _Drawer( + child: child, + level: level, + performance: performance + ) ) ); } + + void didPush(NavigatorState navigator) { + super.didPush(navigator); + _performance.forward(); + } + + void didPop([dynamic result]) { + super.didPop(result); + _performance.reverse(); + _performance = null; + } + + void _settle(Offset velocity) { + if (velocity.dx.abs() >= _kMinFlingVelocity) { + _performance?.fling(velocity: velocity.dx * _kFlingVelocityScale); + } else if (_performance?.progress < 0.5) { + close(); + } else { + _performance?.fling(velocity: 1.0); + } + } + + void close() { + _performance?.fling(velocity: -1.0); + } } void showDrawer({ NavigatorState navigator, Widget child, int level: 3 }) { - navigator.push(new DrawerRoute(child: child, level: level)); + navigator.push(new _DrawerRoute(child: child, level: level)); } From d234ed932e356d59e00420974be62b213b48a57b Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Wed, 7 Oct 2015 20:12:39 -0700 Subject: [PATCH 09/84] Re-enable passing tests --- ...aph_builder_test_disabled.dart => paragraph_builder_test.dart} | 0 .../unit/test/engine/{rect_test_disabled.dart => rect_test.dart} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename packages/unit/test/engine/{paragraph_builder_test_disabled.dart => paragraph_builder_test.dart} (100%) rename packages/unit/test/engine/{rect_test_disabled.dart => rect_test.dart} (100%) diff --git a/packages/unit/test/engine/paragraph_builder_test_disabled.dart b/packages/unit/test/engine/paragraph_builder_test.dart similarity index 100% rename from packages/unit/test/engine/paragraph_builder_test_disabled.dart rename to packages/unit/test/engine/paragraph_builder_test.dart diff --git a/packages/unit/test/engine/rect_test_disabled.dart b/packages/unit/test/engine/rect_test.dart similarity index 100% rename from packages/unit/test/engine/rect_test_disabled.dart rename to packages/unit/test/engine/rect_test.dart From 1cea4846bd6ac84d1b162ba0edf04f751737010f Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Thu, 8 Oct 2015 09:45:29 -0700 Subject: [PATCH 10/84] FlatButton highlights but doesn't tap around edge Now we trigger the highlight from the InkWell so that it matches the tap. Fixes #1525 --- .../flutter/lib/src/widgets/drawer_item.dart | 15 ++++++-- .../src/widgets/floating_action_button.dart | 15 ++++++-- .../flutter/lib/src/widgets/ink_well.dart | 38 ++++++++++++++++--- .../lib/src/widgets/material_button.dart | 13 ++++++- 4 files changed, 68 insertions(+), 13 deletions(-) diff --git a/packages/flutter/lib/src/widgets/drawer_item.dart b/packages/flutter/lib/src/widgets/drawer_item.dart index c41ac4a321..3c5ca71dec 100644 --- a/packages/flutter/lib/src/widgets/drawer_item.dart +++ b/packages/flutter/lib/src/widgets/drawer_item.dart @@ -26,7 +26,15 @@ class DrawerItem extends StatefulComponent { _DrawerItemState createState() => new _DrawerItemState(); } -class _DrawerItemState extends ButtonState { +class _DrawerItemState extends State { + bool _highlight = false; + + void _handleHighlightChanged(bool value) { + setState(() { + _highlight = value; + }); + } + TextStyle _getTextStyle(ThemeData themeData) { TextStyle result = themeData.text.body2; if (config.selected) @@ -35,7 +43,7 @@ class _DrawerItemState extends ButtonState { } Color _getBackgroundColor(ThemeData themeData) { - if (highlight) + if (_highlight) return themeData.highlightColor; if (config.selected) return themeData.selectedColor; @@ -48,7 +56,7 @@ class _DrawerItemState extends ButtonState { return new sky.ColorFilter.mode(const Color(0x73000000), sky.TransferMode.dstIn); } - Widget buildContent(BuildContext context) { + Widget build(BuildContext context) { ThemeData themeData = Theme.of(context); List flexChildren = new List(); @@ -80,6 +88,7 @@ class _DrawerItemState extends ButtonState { decoration: new BoxDecoration(backgroundColor: _getBackgroundColor(themeData)), child: new InkWell( onTap: config.onPressed, + onHighlightChanged: _handleHighlightChanged, child: new Row(flexChildren) ) ); diff --git a/packages/flutter/lib/src/widgets/floating_action_button.dart b/packages/flutter/lib/src/widgets/floating_action_button.dart index d2fb663cab..168b5d053b 100644 --- a/packages/flutter/lib/src/widgets/floating_action_button.dart +++ b/packages/flutter/lib/src/widgets/floating_action_button.dart @@ -30,8 +30,16 @@ class FloatingActionButton extends StatefulComponent { _FloatingActionButtonState createState() => new _FloatingActionButtonState(); } -class _FloatingActionButtonState extends ButtonState { - Widget buildContent(BuildContext context) { +class _FloatingActionButtonState extends State { + bool _highlight = false; + + void _handleHighlightChanged(bool value) { + setState(() { + _highlight = value; + }); + } + + Widget build(BuildContext context) { IconThemeColor iconThemeColor = IconThemeColor.white; Color materialColor = config.backgroundColor; if (materialColor == null) { @@ -43,13 +51,14 @@ class _FloatingActionButtonState extends ButtonState { return new Material( color: materialColor, type: MaterialType.circle, - level: highlight ? 3 : 2, + level: _highlight ? 3 : 2, child: new ClipOval( child: new Container( width: _kSize, height: _kSize, child: new InkWell( onTap: config.onPressed, + onHighlightChanged: _handleHighlightChanged, child: new Center( child: new IconTheme( data: new IconThemeData(color: iconThemeColor), diff --git a/packages/flutter/lib/src/widgets/ink_well.dart b/packages/flutter/lib/src/widgets/ink_well.dart index df493434bd..140e2c9ae5 100644 --- a/packages/flutter/lib/src/widgets/ink_well.dart +++ b/packages/flutter/lib/src/widgets/ink_well.dart @@ -98,13 +98,17 @@ class _InkSplash { } } +typedef _HighlightChangedCallback(bool value); + class _RenderInkWell extends RenderProxyBox { _RenderInkWell({ RenderBox child, GestureTapCallback onTap, - GestureLongPressCallback onLongPress + GestureLongPressCallback onLongPress, + _HighlightChangedCallback onHighlightChanged }) : super(child) { this.onTap = onTap; + this.onHighlightChanged = onHighlightChanged; this.onLongPress = onLongPress; } @@ -115,6 +119,13 @@ class _RenderInkWell extends RenderProxyBox { _syncTapRecognizer(); } + _HighlightChangedCallback get onHighlightChanged => _onHighlightChanged; + _HighlightChangedCallback _onHighlightChanged; + void set onHighlightChanged (_HighlightChangedCallback value) { + _onHighlightChanged = value; + _syncTapRecognizer(); + } + GestureTapCallback get onLongPress => _onLongPress; GestureTapCallback _onLongPress; void set onLongPress (GestureTapCallback value) { @@ -148,10 +159,11 @@ class _RenderInkWell extends RenderProxyBox { } void _syncTapRecognizer() { - if (onTap == null) { + if (onTap == null && onHighlightChanged == null) { _disposeTapRecognizer(); } else { _tap ??= new TapGestureRecognizer(router: FlutterBinding.instance.pointerRouter) + ..onTapDown = _handleTapDown ..onTap = _handleTap ..onTapCancel = _handleTapCancel; } @@ -176,13 +188,26 @@ class _RenderInkWell extends RenderProxyBox { _longPress = null; } + void _handleTapDown() { + if (onHighlightChanged != null) + onHighlightChanged(true); + } + void _handleTap() { - _splashes.last?.confirm(); - onTap(); + if (_splashes.isNotEmpty) + _splashes.last.confirm(); + + if (onHighlightChanged != null) + onHighlightChanged(false); + + if (onTap != null) + onTap(); } void _handleTapCancel() { _splashes.last?.cancel(); + if (onHighlightChanged != null) + onHighlightChanged(false); } void _handleLongPress() { @@ -209,16 +234,19 @@ class InkWell extends OneChildRenderObjectWidget { Key key, Widget child, this.onTap, + this.onHighlightChanged, this.onLongPress }) : super(key: key, child: child); final GestureTapCallback onTap; + final _HighlightChangedCallback onHighlightChanged; final GestureLongPressCallback onLongPress; - _RenderInkWell createRenderObject() => new _RenderInkWell(onTap: onTap, onLongPress: onLongPress); + _RenderInkWell createRenderObject() => new _RenderInkWell(onTap: onTap, onHighlightChanged: onHighlightChanged, onLongPress: onLongPress); void updateRenderObject(_RenderInkWell renderObject, InkWell oldWidget) { renderObject.onTap = onTap; + renderObject.onHighlightChanged = onHighlightChanged; renderObject.onLongPress = onLongPress; } } diff --git a/packages/flutter/lib/src/widgets/material_button.dart b/packages/flutter/lib/src/widgets/material_button.dart index 70161208c5..bbd127c655 100644 --- a/packages/flutter/lib/src/widgets/material_button.dart +++ b/packages/flutter/lib/src/widgets/material_button.dart @@ -25,11 +25,19 @@ abstract class MaterialButton extends StatefulComponent { final GestureTapCallback onPressed; } -abstract class MaterialButtonState extends ButtonState { +abstract class MaterialButtonState extends State { + bool highlight = false; + Color getColor(BuildContext context); int get level; - Widget buildContent(BuildContext context) { + void _handleHighlightChanged(bool value) { + setState(() { + highlight = value; + }); + } + + Widget build(BuildContext context) { Widget contents = new Container( padding: new EdgeDims.symmetric(horizontal: 8.0), child: new Center( @@ -47,6 +55,7 @@ abstract class MaterialButtonState extends ButtonState color: getColor(context), child: new InkWell( onTap: config.enabled ? config.onPressed : null, + onHighlightChanged: config.enabled ? _handleHighlightChanged : null, child: contents ) ) From da4f7b988a67420480cf34b0e8ae62655ca77fc8 Mon Sep 17 00:00:00 2001 From: Hans Muller Date: Thu, 8 Oct 2015 09:55:51 -0700 Subject: [PATCH 11/84] BoxConstraints.toString() should show closed intervals --- packages/flutter/lib/src/rendering/box.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/flutter/lib/src/rendering/box.dart b/packages/flutter/lib/src/rendering/box.dart index 4baf5c12e8..5bf22b3437 100644 --- a/packages/flutter/lib/src/rendering/box.dart +++ b/packages/flutter/lib/src/rendering/box.dart @@ -250,7 +250,7 @@ class BoxConstraints extends Constraints { return value; } - String toString() => "BoxConstraints($minWidth<=w<$maxWidth, $minHeight<=h<$maxHeight)"; + String toString() => "BoxConstraints($minWidth<=w<=$maxWidth, $minHeight<=h<=$maxHeight)"; } /// A hit test entry used by [RenderBox] From 56ac0d9cc76f562cff282581866e9b299686cd62 Mon Sep 17 00:00:00 2001 From: Viktor Lidholt Date: Thu, 8 Oct 2015 10:14:47 -0700 Subject: [PATCH 12/84] Adds support for keeping track of contact points in physics --- .../flutter_sprites/lib/physics_node.dart | 82 +++++++++++++++++-- 1 file changed, 76 insertions(+), 6 deletions(-) diff --git a/packages/flutter_sprites/lib/physics_node.dart b/packages/flutter_sprites/lib/physics_node.dart index 12ea4f8531..4510289d93 100644 --- a/packages/flutter_sprites/lib/physics_node.dart +++ b/packages/flutter_sprites/lib/physics_node.dart @@ -183,7 +183,57 @@ class PhysicsNode extends Node { } } } + canvas.restore(); + + // Draw contacts + for (box2d.ContactEdge edge = body.getContactList(); edge != null; edge = edge.next) { + box2d.Contact contact = edge.contact; + Vector2 cA = new Vector2.zero(); + Vector2 cB = new Vector2.zero(); + + box2d.Fixture fixtureA = contact.fixtureA; + box2d.Fixture fixtureB = contact.fixtureB; + + fixtureA.getAABB(contact.getChildIndexA()).getCenterToOut(cA); + fixtureB.getAABB(contact.getChildIndexB()).getCenterToOut(cB); + + Point p1 = new Point( + cA.x * b2WorldToNodeConversionFactor, + cA.y * b2WorldToNodeConversionFactor + ); + + Point p2 = new Point( + cB.x * b2WorldToNodeConversionFactor, + cB.y * b2WorldToNodeConversionFactor + ); + + shapePaint.color = new Color(0x33ffffff); + canvas.drawLine(p1, p2, shapePaint); + + box2d.WorldManifold worldManifold = new box2d.WorldManifold(); + contact.getWorldManifold(worldManifold); + + shapePaint.color = new Color(0xffffffff); + + for (Vector2 pt in worldManifold.points) { + Point pCenter = new Point( + pt.x * b2WorldToNodeConversionFactor, + pt.y * b2WorldToNodeConversionFactor + ); + Offset offset = new Offset( + worldManifold.normal.x * 5.0, + worldManifold.normal.y * 5.0 + ); + + Point p2 = pCenter + offset; + Point p1 = new Point(pCenter.x - offset.dx, pCenter.y - offset.dy); + canvas.drawLine(p1, p2, shapePaint); + canvas.drawCircle(pCenter, 5.0, shapePaint); + } + } + + } } } @@ -195,7 +245,9 @@ class PhysicsContact { this.shapeA, this.shapeB, this.isTouching, - this.isEnabled + this.isEnabled, + this.touchingPoints, + this.touchingNormal ); final Node nodeA; @@ -204,6 +256,8 @@ class PhysicsContact { final PhysicsShape shapeB; final isTouching; bool isEnabled; + final List touchingPoints; + final Offset touchingNormal; } class _ContactCallbackInfo { @@ -264,19 +318,35 @@ class _ContactHandler extends box2d.ContactListener { if (match) { // We have contact and a matched callback, setup contact info + List touchingPoints = null; + Offset touchingNormal = null; + + // Fetch touching points, if any + if (b2Contact.isTouching()) { + box2d.WorldManifold manifold = new box2d.WorldManifold(); + b2Contact.getWorldManifold(manifold); + touchingNormal = new Offset(manifold.normal.x, manifold.normal.y); + touchingPoints = []; + for (Vector2 vec in manifold.points) { + touchingPoints.add(new Point( + vec.x * physicsNode.b2WorldToNodeConversionFactor, + vec.y * physicsNode.b2WorldToNodeConversionFactor + )); + } + } + + // Create the contact PhysicsContact contact = new PhysicsContact( bodyA._node, bodyB._node, fixtureA.userData, fixtureB.userData, b2Contact.isTouching(), - b2Contact.isEnabled() + b2Contact.isEnabled(), + touchingPoints, + touchingNormal ); - if (type == PhysicsContactType.postSolve) { - - } - // Make callback info.callback(type, contact); From 6b1c85a8b0168bfe42680ac1f5205562a79a1001 Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Thu, 8 Oct 2015 10:13:29 -0700 Subject: [PATCH 13/84] SnackBar throws exception on creation It was trying to grab the route's performance before it was created. Now we create the performance eagerly again. --- .../flutter/lib/src/widgets/navigator.dart | 5 ++- packages/unit/test/widget/snack_bar_test.dart | 40 +++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 packages/unit/test/widget/snack_bar_test.dart diff --git a/packages/flutter/lib/src/widgets/navigator.dart b/packages/flutter/lib/src/widgets/navigator.dart index 5f879bc034..13b001b33e 100644 --- a/packages/flutter/lib/src/widgets/navigator.dart +++ b/packages/flutter/lib/src/widgets/navigator.dart @@ -245,6 +245,10 @@ abstract class Route { } abstract class PerformanceRoute extends Route { + PerformanceRoute() { + _performance = createPerformance(); + } + PerformanceView get performance => _performance?.view; Performance _performance; @@ -261,7 +265,6 @@ abstract class PerformanceRoute extends Route { Widget build(NavigatorState navigator, PerformanceView nextRoutePerformance); void didPush(NavigatorState navigator) { - _performance = createPerformance(); super.didPush(navigator); _performance?.forward(); } diff --git a/packages/unit/test/widget/snack_bar_test.dart b/packages/unit/test/widget/snack_bar_test.dart new file mode 100644 index 0000000000..6cb2d6605b --- /dev/null +++ b/packages/unit/test/widget/snack_bar_test.dart @@ -0,0 +1,40 @@ +import 'package:sky/widgets.dart'; +import 'package:test/test.dart'; + +import 'widget_tester.dart'; + +void main() { + test('SnackBar control test', () { + testWidgets((WidgetTester tester) { + String helloSnackBar = 'Hello SnackBar'; + GlobalKey placeholderKey = new GlobalKey(); + Key tapTarget = new Key('tap-target'); + + tester.pumpWidget(new App( + routes: { + '/': (RouteArguments args) { + return new GestureDetector( + onTap: () { + showSnackBar( + navigator: args.navigator, + placeholderKey: placeholderKey, + content: new Text(helloSnackBar) + ); + }, + child: new Center( + key: tapTarget, + child: new Placeholder(key: placeholderKey) + ) + ); + } + } + )); + + tester.tap(tester.findElementByKey(tapTarget)); + + expect(tester.findText(helloSnackBar), isNull); + tester.pump(); + expect(tester.findText(helloSnackBar), isNotNull); + }); + }); +} From 09d26302cb41c94630bff20de34b50ac7d571b7b Mon Sep 17 00:00:00 2001 From: Hans Muller Date: Tue, 6 Oct 2015 16:10:36 -0700 Subject: [PATCH 14/84] IndexedStack Added horizontal and vertical alignment properties to Stack so that the origin of non-positioned children can be specified. Currently all of the non-positioned children just end up with their top-left at 0,0. Now, for example, you can center the children by specifying verticalAlignment: 0.5, horizontalAlignment: 0.5. Added IndexedStack which only paints the stack child specified by the index property. Since it's a Stack, it's as big as the biggest non-positioned child. This component will be essential for building mobile drop down menus. Added a (likely temporary) example that demonstrates IndexedStack. --- examples/widgets/indexed_stack.dart | 71 ++++++++ .../flutter/lib/src/rendering/object.dart | 2 +- packages/flutter/lib/src/rendering/stack.dart | 166 +++++++++++++++--- packages/flutter/lib/src/widgets/basic.dart | 53 +++++- packages/unit/test/widget/stack_test.dart | 91 ++++++++++ 5 files changed, 351 insertions(+), 32 deletions(-) create mode 100644 examples/widgets/indexed_stack.dart diff --git a/examples/widgets/indexed_stack.dart b/examples/widgets/indexed_stack.dart new file mode 100644 index 0000000000..1833412763 --- /dev/null +++ b/examples/widgets/indexed_stack.dart @@ -0,0 +1,71 @@ +// 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/material.dart'; +import 'package:sky/rendering.dart'; +import 'package:sky/widgets.dart'; + +class IndexedStackDemo extends StatefulComponent { + IndexedStackDemo({ this.navigator }); + + final NavigatorState navigator; + + IndexedStackDemoState createState() => new IndexedStackDemoState(); +} + +class IndexedStackDemoState extends State { + int _itemCount = 7; + int _itemIndex = 0; + + void _handleTap() { + setState(() { + _itemIndex = (_itemIndex + 1) % _itemCount; + }); + } + + List _buildMenu(NavigatorState navigator) { + TextStyle style = const TextStyle(fontSize: 18.0, fontWeight: bold); + String pad = ''; + return new List.generate(_itemCount, (int i) { + pad += '-'; + return new PopupMenuItem(value: i, child: new Text('$pad Hello World $i $pad', style: style)); + }); + } + + Widget build(BuildContext context) { + List items = _buildMenu(config.navigator); + IndexedStack indexedStack = new IndexedStack(items, index: _itemIndex, horizontalAlignment: 0.5); + + return new Scaffold( + toolBar: new ToolBar(center: new Text('IndexedStackDemo Demo')), + body: new GestureDetector( + onTap: _handleTap, + child: new Container( + decoration: new BoxDecoration(backgroundColor: Theme.of(context).primarySwatch[50]), + child: new Center( + child: new Container( + child: indexedStack, + padding: const EdgeDims.all(8.0), + decoration: new BoxDecoration(border: new Border.all(color: Theme.of(context).accentColor)) + ) + ) + ) + ) + ); + } +} + +void main() { + runApp(new App( + title: 'IndexedStackDemo', + theme: new ThemeData( + brightness: ThemeBrightness.light, + primarySwatch: Colors.blue, + accentColor: Colors.redAccent[200] + ), + routes: { + '/': (RouteArguments args) => new IndexedStackDemo(navigator: args.navigator), + } + )); +} diff --git a/packages/flutter/lib/src/rendering/object.dart b/packages/flutter/lib/src/rendering/object.dart index 66445d2858..f887c11cb6 100644 --- a/packages/flutter/lib/src/rendering/object.dart +++ b/packages/flutter/lib/src/rendering/object.dart @@ -61,7 +61,7 @@ class PaintingContext { _startRecording(paintBounds); } - /// Construct a painting context for paiting into the given layer with the given bounds + /// Construct a painting context for painting into the given layer with the given bounds PaintingContext.withLayer(ContainerLayer containerLayer, Rect paintBounds) { _containerLayer = containerLayer; _startRecording(paintBounds); diff --git a/packages/flutter/lib/src/rendering/stack.dart b/packages/flutter/lib/src/rendering/stack.dart index 0ea40b060c..41484f2121 100644 --- a/packages/flutter/lib/src/rendering/stack.dart +++ b/packages/flutter/lib/src/rendering/stack.dart @@ -44,32 +44,14 @@ class StackParentData extends BoxParentData with ContainerParentDataMixin '${super.toString()}; top=$top; right=$right; bottom=$bottom, left=$left'; } -/// Implements the stack layout algorithm -/// -/// In a stack layout, the children are positioned on top of each other in the -/// order in which they appear in the child list. First, the non-positioned -/// children (those with null values for top, right, bottom, and left) are -/// layed out and placed in the upper-left corner of the stack. The stack is -/// then sized to enclose all of the non-positioned children. If there are no -/// non-positioned children, the stack becomes as large as possible. -/// -/// Next, the positioned children are laid out. If a child has top and bottom -/// values that are both non-null, the child is given a fixed height determined -/// by deflating the width of the stack by the sum of the top and bottom values. -/// Similarly, if the child has rigth and left values that are both non-null, -/// the child is given a fixed width. Otherwise, the child is given unbounded -/// space in the non-fixed dimensions. -/// -/// Once the child is laid out, the stack positions the child according to the -/// top, right, bottom, and left offsets. For example, if the top value is 10.0, -/// the top edge of the child will be placed 10.0 pixels from the top edge of -/// the stack. If the child extends beyond the bounds of the stack, the stack -/// will clip the child's painting to the bounds of the stack. -class RenderStack extends RenderBox with ContainerRenderObjectMixin, - RenderBoxContainerDefaultsMixin { - RenderStack({ - List children - }) { +abstract class RenderStackBase extends RenderBox + with ContainerRenderObjectMixin, + RenderBoxContainerDefaultsMixin { + RenderStackBase({ + List children, + double horizontalAlignment: 0.0, + double verticalAlignment: 0.0 + }) : _horizontalAlignment = horizontalAlignment, _verticalAlignment = verticalAlignment { addAll(children); } @@ -80,6 +62,24 @@ class RenderStack extends RenderBox with ContainerRenderObjectMixin _horizontalAlignment; + double _horizontalAlignment; + void set horizontalAlignment (double value) { + if (_horizontalAlignment != value) { + _horizontalAlignment = value; + markNeedsLayout(); + } + } + + double get verticalAlignment => _verticalAlignment; + double _verticalAlignment; + void set verticalAlignment (double value) { + if (_verticalAlignment != value) { + _verticalAlignment = value; + markNeedsLayout(); + } + } + double getMinIntrinsicWidth(BoxConstraints constraints) { double width = constraints.minWidth; RenderBox child = firstChild; @@ -186,7 +186,11 @@ class RenderStack extends RenderBox with ContainerRenderObjectMixin children, + double horizontalAlignment: 0.0, + double verticalAlignment: 0.0 + }) : super( + children: children, + horizontalAlignment: horizontalAlignment, + verticalAlignment: verticalAlignment + ); + + void paintStack(PaintingContext context, Offset offset) { + defaultPaint(context, offset); + } +} + +/// Implements the same layout algorithm as RenderStack but only paints the child +/// specified by index. +/// Note: although only one child is displayed, the cost of the layout algorithm is +/// still O(N), like an ordinary stack. +class RenderIndexedStack extends RenderStackBase { + RenderIndexedStack({ + List children, + double horizontalAlignment: 0.0, + double verticalAlignment: 0.0, + int index: 0 + }) : _index = index, super( + children: children, + horizontalAlignment: horizontalAlignment, + verticalAlignment: verticalAlignment + ); + + int get index => _index; + int _index; + void set index (int value) { + if (_index != value) { + _index = value; + markNeedsLayout(); + } + } + + RenderBox _childAtIndex() { + RenderBox child = firstChild; + int i = 0; + while (child != null && i < index) { + assert(child.parentData is StackParentData); + child = child.parentData.nextSibling; + i += 1; + } + assert(i == index); + assert(child != null); + return child; + } + + void hitTestChildren(HitTestResult result, { Point position }) { + if (firstChild == null) + return; + assert(position != null); + RenderBox child = _childAtIndex(); + Point transformed = new Point(position.x - child.parentData.position.x, + position.y - child.parentData.position.y); + child.hitTest(result, position: transformed); + } + + void paintStack(PaintingContext context, Offset offset) { + if (firstChild == null) + return; + RenderBox child = _childAtIndex(); + context.paintChild(child, child.parentData.position + offset); + } +} diff --git a/packages/flutter/lib/src/widgets/basic.dart b/packages/flutter/lib/src/widgets/basic.dart index 7b17690178..ea3a835f99 100644 --- a/packages/flutter/lib/src/widgets/basic.dart +++ b/packages/flutter/lib/src/widgets/basic.dart @@ -513,8 +513,57 @@ class BlockBody extends MultiChildRenderObjectWidget { } class Stack extends MultiChildRenderObjectWidget { - Stack(List children, { Key key }) : super(key: key, children: children); - RenderStack createRenderObject() => new RenderStack(); + Stack(List children, { + Key key, + this.horizontalAlignment: 0.0, + this.verticalAlignment: 0.0 + }) : super(key: key, children: children) { + assert(horizontalAlignment != null); + assert(verticalAlignment != null); + } + + final double horizontalAlignment; + final double verticalAlignment; + + RenderStack createRenderObject() { + return new RenderStack( + horizontalAlignment: horizontalAlignment, + verticalAlignment: verticalAlignment + ); + } + + void updateRenderObject(RenderStack renderObject, Stack oldWidget) { + renderObject.horizontalAlignment = horizontalAlignment; + renderObject.verticalAlignment = verticalAlignment; + } +} + +class IndexedStack extends MultiChildRenderObjectWidget { + IndexedStack(List children, { + Key key, + this.horizontalAlignment: 0.0, + this.verticalAlignment: 0.0, + this.index: 0 + }) : super(key: key, children: children); + + final int index; + final double horizontalAlignment; + final double verticalAlignment; + + RenderIndexedStack createRenderObject() { + return new RenderIndexedStack( + index: index, + verticalAlignment: verticalAlignment, + horizontalAlignment: horizontalAlignment + ); + } + + void updateRenderObject(RenderIndexedStack renderObject, IndexedStack oldWidget) { + super.updateRenderObject(renderObject, oldWidget); + renderObject.index = index; + renderObject.horizontalAlignment = horizontalAlignment; + renderObject.verticalAlignment = verticalAlignment; + } } class Positioned extends ParentDataWidget { diff --git a/packages/unit/test/widget/stack_test.dart b/packages/unit/test/widget/stack_test.dart index 1866bd6436..d7e9ac8afe 100644 --- a/packages/unit/test/widget/stack_test.dart +++ b/packages/unit/test/widget/stack_test.dart @@ -4,6 +4,12 @@ import 'package:test/test.dart'; import 'widget_tester.dart'; void main() { + test('Can construct an empty Stack', () { + testWidgets((WidgetTester tester) { + tester.pumpWidget(new Stack([])); + }); + }); + test('Can change position data', () { testWidgets((WidgetTester tester) { Key key = new Key('container'); @@ -70,4 +76,89 @@ void main() { expect(containerElement.renderObject.parentData.left, isNull); }); }); + + test('Can align non-positioned children', () { + testWidgets((WidgetTester tester) { + Key child0Key = new Key('child0'); + Key child1Key = new Key('child1'); + + tester.pumpWidget( + new Center( + child: new Stack([ + new Container(key: child0Key, width: 20.0, height: 20.0), + new Container(key: child1Key, width: 10.0, height: 10.0) + ], + horizontalAlignment: 0.5, + verticalAlignment: 0.5 + ) + ) + ); + + Element child0 = tester.findElementByKey(child0Key); + expect(child0.renderObject.parentData.position, equals(const Point(0.0, 0.0))); + + Element child1 = tester.findElementByKey(child1Key); + expect(child1.renderObject.parentData.position, equals(const Point(5.0, 5.0))); + }); + }); + + test('Can construct an empty IndexedStack', () { + testWidgets((WidgetTester tester) { + tester.pumpWidget(new IndexedStack([])); + }); + }); + + test('Can construct an IndexedStack', () { + testWidgets((WidgetTester tester) { + int itemCount = 3; + List itemsPainted; + + Widget buildFrame(int index) { + itemsPainted = []; + List items = new List.generate(itemCount, (i) { + return new CustomPaint(child: new Text('$i'), callback: (_0, _1) { itemsPainted.add(i); }); + }); + return new Center(child: new IndexedStack(items, index: index)); + } + + tester.pumpWidget(buildFrame(0)); + expect(tester.findText('0'), isNotNull); + expect(tester.findText('1'), isNotNull); + expect(tester.findText('2'), isNotNull); + expect(itemsPainted, equals([0])); + + tester.pumpWidget(buildFrame(1)); + expect(itemsPainted, equals([1])); + + tester.pumpWidget(buildFrame(2)); + expect(itemsPainted, equals([2])); + }); + }); + + test('Can hit test an IndexedStack', () { + testWidgets((WidgetTester tester) { + Key key = new Key('indexedStack'); + int itemCount = 3; + List itemsTapped; + + Widget buildFrame(int index) { + itemsTapped = []; + List items = new List.generate(itemCount, (i) { + return new GestureDetector(child: new Text('$i'), onTap: () { itemsTapped.add(i); }); + }); + return new Center(child: new IndexedStack(items, key: key, index: index)); + } + + tester.pumpWidget(buildFrame(0)); + expect(itemsTapped, isEmpty); + tester.tap(tester.findElementByKey(key)); + expect(itemsTapped, [0]); + + tester.pumpWidget(buildFrame(2)); + expect(itemsTapped, isEmpty); + tester.tap(tester.findElementByKey(key)); + expect(itemsTapped, [2]); + }); + }); + } From 3308ff002610c1ed9e3b89e9d03781aaff4f90dd Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Thu, 8 Oct 2015 10:22:33 -0700 Subject: [PATCH 15/84] Remove ButtonState Clients should just use a GestureDetector (or an InkWell) instead. --- examples/game/lib/main.dart | 27 ++++++++++--- .../flutter/lib/src/widgets/button_state.dart | 39 ------------------- .../flutter/lib/src/widgets/drawer_item.dart | 1 - .../src/widgets/floating_action_button.dart | 1 - .../lib/src/widgets/material_button.dart | 1 - packages/flutter/lib/widgets.dart | 1 - 6 files changed, 21 insertions(+), 49 deletions(-) delete mode 100644 packages/flutter/lib/src/widgets/button_state.dart diff --git a/examples/game/lib/main.dart b/examples/game/lib/main.dart index 51366d9a40..c8cf7417cb 100644 --- a/examples/game/lib/main.dart +++ b/examples/game/lib/main.dart @@ -151,16 +151,18 @@ class TextureButton extends StatefulComponent { TextureButtonState createState() => new TextureButtonState(); } -class TextureButtonState extends ButtonState { - Widget buildContent(BuildContext context) { - return new Listener( +class TextureButtonState extends State { + bool _highlight = false; + + Widget build(BuildContext context) { + return new GestureDetector( child: new Container( width: config.width, height: config.height, child: new CustomPaint( callback: paintCallback, token: new _TextureButtonToken( - highlight, + _highlight, config.texture, config.textureDown, config.width, @@ -168,9 +170,22 @@ class TextureButtonState extends ButtonState { ) ) ), - onPointerUp: (_) { + onTapDown: () { + setState(() { + _highlight = true; + }); + }, + onTap: () { + setState(() { + _highlight = false; + }); if (config.onPressed != null) config.onPressed(); + }, + onTapCancel: () { + setState(() { + _highlight = false; + }); } ); } @@ -180,7 +195,7 @@ class TextureButtonState extends ButtonState { return; canvas.save(); - if (highlight && config.textureDown != null) { + if (_highlight && config.textureDown != null) { // Draw down state canvas.scale(size.width / config.textureDown.size.width, size.height / config.textureDown.size.height); config.textureDown.drawTexture(canvas, Point.origin, new Paint()); diff --git a/packages/flutter/lib/src/widgets/button_state.dart b/packages/flutter/lib/src/widgets/button_state.dart deleted file mode 100644 index a9c5366cb3..0000000000 --- a/packages/flutter/lib/src/widgets/button_state.dart +++ /dev/null @@ -1,39 +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 'package:sky/src/widgets/basic.dart'; -import 'package:sky/src/widgets/framework.dart'; - -abstract class ButtonState extends State { - bool highlight = false; - - void _handlePointerDown(_) { - setState(() { - highlight = true; - }); - } - - void _handlePointerUp(_) { - setState(() { - highlight = false; - }); - } - - void _handlePointerCancel(_) { - setState(() { - highlight = false; - }); - } - - Widget build(BuildContext context) { - return new Listener( - onPointerDown: _handlePointerDown, - onPointerUp: _handlePointerUp, - onPointerCancel: _handlePointerCancel, - child: buildContent(context) - ); - } - - Widget buildContent(BuildContext context); -} diff --git a/packages/flutter/lib/src/widgets/drawer_item.dart b/packages/flutter/lib/src/widgets/drawer_item.dart index 3c5ca71dec..a963398ce6 100644 --- a/packages/flutter/lib/src/widgets/drawer_item.dart +++ b/packages/flutter/lib/src/widgets/drawer_item.dart @@ -8,7 +8,6 @@ import 'package:sky/gestures.dart'; import 'package:sky/material.dart'; import 'package:sky/painting.dart'; import 'package:sky/src/widgets/basic.dart'; -import 'package:sky/src/widgets/button_state.dart'; import 'package:sky/src/widgets/framework.dart'; import 'package:sky/src/widgets/icon.dart'; import 'package:sky/src/widgets/ink_well.dart'; diff --git a/packages/flutter/lib/src/widgets/floating_action_button.dart b/packages/flutter/lib/src/widgets/floating_action_button.dart index 168b5d053b..8b95422f96 100644 --- a/packages/flutter/lib/src/widgets/floating_action_button.dart +++ b/packages/flutter/lib/src/widgets/floating_action_button.dart @@ -4,7 +4,6 @@ import 'package:sky/gestures.dart'; import 'package:sky/src/widgets/basic.dart'; -import 'package:sky/src/widgets/button_state.dart'; import 'package:sky/src/widgets/framework.dart'; import 'package:sky/src/widgets/icon.dart'; import 'package:sky/src/widgets/ink_well.dart'; diff --git a/packages/flutter/lib/src/widgets/material_button.dart b/packages/flutter/lib/src/widgets/material_button.dart index bbd127c655..4a21d4ebe8 100644 --- a/packages/flutter/lib/src/widgets/material_button.dart +++ b/packages/flutter/lib/src/widgets/material_button.dart @@ -4,7 +4,6 @@ import 'package:sky/gestures.dart'; import 'package:sky/src/widgets/basic.dart'; -import 'package:sky/src/widgets/button_state.dart'; import 'package:sky/src/widgets/framework.dart'; import 'package:sky/src/widgets/ink_well.dart'; import 'package:sky/src/widgets/material.dart'; diff --git a/packages/flutter/lib/widgets.dart b/packages/flutter/lib/widgets.dart index 93eabd8dba..84f308d536 100644 --- a/packages/flutter/lib/widgets.dart +++ b/packages/flutter/lib/widgets.dart @@ -9,7 +9,6 @@ export 'src/widgets/animated_container.dart'; export 'src/widgets/app.dart'; export 'src/widgets/basic.dart'; export 'src/widgets/binding.dart'; -export 'src/widgets/button_state.dart'; export 'src/widgets/card.dart'; export 'src/widgets/checkbox.dart'; export 'src/widgets/date_picker.dart'; From 3cfc9c4d95e581bc42a87fa24091e3c7e62c6219 Mon Sep 17 00:00:00 2001 From: Hans Muller Date: Thu, 8 Oct 2015 10:48:33 -0700 Subject: [PATCH 16/84] Allow Stacks with no children or only poisitioned children --- packages/flutter/lib/src/rendering/stack.dart | 9 +++++---- packages/unit/test/widget/stack_test.dart | 12 ++++++++++++ 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/packages/flutter/lib/src/rendering/stack.dart b/packages/flutter/lib/src/rendering/stack.dart index 41484f2121..b884d2d876 100644 --- a/packages/flutter/lib/src/rendering/stack.dart +++ b/packages/flutter/lib/src/rendering/stack.dart @@ -172,14 +172,15 @@ abstract class RenderStackBase extends RenderBox child = parentData.nextSibling; } - if (hasNonPositionedChildren) + if (hasNonPositionedChildren) { size = new Size(width, height); - else + assert(size.width == constraints.constrainWidth(width)); + assert(size.height == constraints.constrainHeight(height)); + } else { size = constraints.biggest; + } assert(!size.isInfinite); - assert(size.width == constraints.constrainWidth(width)); - assert(size.height == constraints.constrainHeight(height)); child = firstChild; while (child != null) { diff --git a/packages/unit/test/widget/stack_test.dart b/packages/unit/test/widget/stack_test.dart index d7e9ac8afe..b075aaca93 100644 --- a/packages/unit/test/widget/stack_test.dart +++ b/packages/unit/test/widget/stack_test.dart @@ -10,6 +10,12 @@ void main() { }); }); + test('Can construct an empty Centered Stack', () { + testWidgets((WidgetTester tester) { + tester.pumpWidget(new Center(child: new Stack([]))); + }); + }); + test('Can change position data', () { testWidgets((WidgetTester tester) { Key key = new Key('container'); @@ -108,6 +114,12 @@ void main() { }); }); + test('Can construct an empty Centered IndexedStack', () { + testWidgets((WidgetTester tester) { + tester.pumpWidget(new Center(child: new IndexedStack([]))); + }); + }); + test('Can construct an IndexedStack', () { testWidgets((WidgetTester tester) { int itemCount = 3; From 6143492e6e02e3993dd3b318451663b3aad15521 Mon Sep 17 00:00:00 2001 From: Chinmay Garde Date: Thu, 8 Oct 2015 11:50:51 -0700 Subject: [PATCH 17/84] Format trace file names so they are easier to organize --- packages/flutter/lib/src/widgets/statistics_overlay.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/flutter/lib/src/widgets/statistics_overlay.dart b/packages/flutter/lib/src/widgets/statistics_overlay.dart index f3066413c7..6677cfbdd9 100644 --- a/packages/flutter/lib/src/widgets/statistics_overlay.dart +++ b/packages/flutter/lib/src/widgets/statistics_overlay.dart @@ -64,7 +64,7 @@ class StatisticsOverlay extends LeafRenderObjectWidget { /// 0 disables all capture. /// /// Captured traces are placed on your device in the application documents - /// directory in this form "trace_.skp". These can + /// directory in this form "trace_.skp". These can /// be viewed in the Skia debugger. /// /// Notes: From 4254f5fba8639407a4775c65012063d4993b8e7d Mon Sep 17 00:00:00 2001 From: Hixie Date: Thu, 8 Oct 2015 10:51:26 -0700 Subject: [PATCH 18/84] Drawer test. --- packages/flutter/lib/src/widgets/drawer.dart | 136 +++++++++++------- .../flutter/lib/src/widgets/navigator.dart | 5 + packages/unit/test/widget/drawer_test.dart | 70 +++++++++ 3 files changed, 159 insertions(+), 52 deletions(-) create mode 100644 packages/unit/test/widget/drawer_test.dart diff --git a/packages/flutter/lib/src/widgets/drawer.dart b/packages/flutter/lib/src/widgets/drawer.dart index e294eee6c2..2b63b2aebc 100644 --- a/packages/flutter/lib/src/widgets/drawer.dart +++ b/packages/flutter/lib/src/widgets/drawer.dart @@ -35,53 +35,72 @@ const Point _kOpenPosition = Point.origin; const Point _kClosedPosition = const Point(-_kWidth, 0.0); class _Drawer extends StatelessComponent { + _Drawer({ Key key, this.child, this.level: 3, this.performance, + this.interactive, this.route }) : super(key: key); final Widget child; final int level; final PerformanceView performance; + final bool interactive; final _DrawerRoute route; Widget build(BuildContext context) { - Widget mask = new GestureDetector( - onTap: route.close, - child: new ColorTransition( - performance: performance, - color: new AnimatedColorValue(Colors.transparent, end: Colors.black54), - child: new Container() - ) + return new GestureDetector( + onHorizontalDragStart: () { + if (interactive) + route._takeControl(); + }, + onHorizontalDragUpdate: (double delta) { + if (interactive) + route._moveDrawer(delta); + }, + onHorizontalDragEnd: (Offset velocity) { + if (interactive) + route._settle(velocity); + }, + child: new Stack([ + // mask + new GestureDetector( + onTap: () { + if (interactive) + route._close(); + }, + child: new ColorTransition( + performance: performance, + color: new AnimatedColorValue(Colors.transparent, end: Colors.black54), + child: new Container() + ) + ), + // drawer + new Positioned( + top: 0.0, + left: 0.0, + bottom: 0.0, + child: new SlideTransition( + performance: performance, + position: new AnimatedValue(_kClosedPosition, end: _kOpenPosition), + child: new AnimatedContainer( + curve: ease, + duration: _kThemeChangeDuration, + decoration: new BoxDecoration( + backgroundColor: Theme.of(context).canvasColor, + boxShadow: shadows[level]), + width: _kWidth, + child: child + ) + ) + ) + ]) ); - - Widget content = new SlideTransition( - performance: performance, - position: new AnimatedValue(_kClosedPosition, end: _kOpenPosition), - child: new AnimatedContainer( - curve: ease, - duration: _kThemeChangeDuration, - decoration: new BoxDecoration( - backgroundColor: Theme.of(context).canvasColor, - boxShadow: shadows[level]), - width: _kWidth, - child: child - ) - ); - - return new Stack([ - mask, - new Positioned( - top: 0.0, - left: 0.0, - bottom: 0.0, - child: content - ) - ]); } + } class _DrawerRoute extends Route { @@ -95,23 +114,18 @@ class _DrawerRoute extends Route { bool get opaque => false; + bool _interactive = true; + Widget build(NavigatorState navigator, PerformanceView nextRoutePerformance) { return new Focus( key: new GlobalObjectKey(this), autofocus: true, - child: new GestureDetector( - onHorizontalDragStart: () { - _performance?.stop(); - }, - onHorizontalDragUpdate: (double delta) { - _performance?.progress = delta / _kWidth; - }, - onHorizontalDragEnd: _settle, - child: new _Drawer( - child: child, - level: level, - performance: performance - ) + child: new _Drawer( + child: child, + level: level, + performance: performance, + interactive: _interactive, + route: this ) ); } @@ -122,26 +136,44 @@ class _DrawerRoute extends Route { } void didPop([dynamic result]) { + assert(result == null); // because we don't do anything with it, so otherwise it'd be lost super.didPop(result); - _performance.reverse(); - _performance = null; + if (_performance.status != PerformanceStatus.dismissed) + _performance.reverse(); + setState(() { + _interactive = false; + // TODO(ianh): https://github.com/flutter/engine/issues/1539 + }); + } + + void _takeControl() { + assert(_interactive); + _performance.stop(); + } + + void _moveDrawer(double delta) { + assert(_interactive); + _performance.progress += delta / _kWidth; } void _settle(Offset velocity) { + assert(_interactive); if (velocity.dx.abs() >= _kMinFlingVelocity) { - _performance?.fling(velocity: velocity.dx * _kFlingVelocityScale); - } else if (_performance?.progress < 0.5) { - close(); + _performance.fling(velocity: velocity.dx * _kFlingVelocityScale); + } else if (_performance.progress < 0.5) { + _close(); } else { - _performance?.fling(velocity: 1.0); + _performance.fling(velocity: 1.0); } } - void close() { - _performance?.fling(velocity: -1.0); + void _close() { + assert(_interactive); + _performance.fling(velocity: -1.0); } } void showDrawer({ NavigatorState navigator, Widget child, int level: 3 }) { + assert(navigator != null); navigator.push(new _DrawerRoute(child: child, level: level)); } diff --git a/packages/flutter/lib/src/widgets/navigator.dart b/packages/flutter/lib/src/widgets/navigator.dart index 13b001b33e..04e839fe50 100644 --- a/packages/flutter/lib/src/widgets/navigator.dart +++ b/packages/flutter/lib/src/widgets/navigator.dart @@ -220,6 +220,11 @@ abstract class Route { NavigatorState _navigator; + void setState(void fn()) { + assert(_navigator != null); + _navigator.setState(fn); + } + void didPush(NavigatorState navigator) { assert(_navigator == null); _navigator = navigator; diff --git a/packages/unit/test/widget/drawer_test.dart b/packages/unit/test/widget/drawer_test.dart new file mode 100644 index 0000000000..2fb0b24278 --- /dev/null +++ b/packages/unit/test/widget/drawer_test.dart @@ -0,0 +1,70 @@ +import 'package:sky/widgets.dart'; +import 'package:test/test.dart'; + +import 'widget_tester.dart'; + +void main() { + + test('Drawer control test', () { + testWidgets((WidgetTester tester) { + NavigatorState navigator; + tester.pumpWidget( + new App( + routes: { + '/': (RouteArguments args) { + navigator = args.navigator; + new Container(); + } + } + ) + ); + tester.pump(); // no effect + expect(tester.findText('drawer'), isNull); + showDrawer(navigator: navigator, child: new Text('drawer')); + tester.pump(); // drawer should be starting to animate in + expect(tester.findText('drawer'), isNotNull); + tester.pump(new Duration(seconds: 1)); // animation done + expect(tester.findText('drawer'), isNotNull); + navigator.pop(); + tester.pump(); // drawer should be starting to animate away + expect(tester.findText('drawer'), isNotNull); + tester.pump(new Duration(seconds: 1)); // animation done + expect(tester.findText('drawer'), isNull); + }); + }); + + test('Drawer tap test', () { + testWidgets((WidgetTester tester) { + NavigatorState navigator; + tester.pumpWidget(new Container()); // throw away the old App and its Navigator + tester.pumpWidget( + new App( + routes: { + '/': (RouteArguments args) { + navigator = args.navigator; + new Container(); + } + } + ) + ); + tester.pump(); // no effect + expect(tester.findText('drawer'), isNull); + showDrawer(navigator: navigator, child: new Text('drawer')); + tester.pump(); // drawer should be starting to animate in + expect(tester.findText('drawer'), isNotNull); + tester.pump(new Duration(seconds: 1)); // animation done + expect(tester.findText('drawer'), isNotNull); + tester.tap(tester.findText('drawer')); + tester.pump(); // nothing should have happened + expect(tester.findText('drawer'), isNotNull); + tester.pump(new Duration(seconds: 1)); // ditto + expect(tester.findText('drawer'), isNotNull); + tester.tapAt(const Point(750.0, 100.0)); // on the mask + tester.pump(); // drawer should be starting to animate away + expect(tester.findText('drawer'), isNotNull); + tester.pump(new Duration(seconds: 1)); // animation done + expect(tester.findText('drawer'), isNull); + }); + }); + +} From fd8e64c402cefaed35271022ca1840ae9e71542d Mon Sep 17 00:00:00 2001 From: Hans Muller Date: Thu, 8 Oct 2015 12:19:06 -0700 Subject: [PATCH 19/84] Defunct DismissableState should not have live animations --- packages/flutter/lib/src/widgets/dismissable.dart | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/flutter/lib/src/widgets/dismissable.dart b/packages/flutter/lib/src/widgets/dismissable.dart index b47729bdd0..44c9d6ae29 100644 --- a/packages/flutter/lib/src/widgets/dismissable.dart +++ b/packages/flutter/lib/src/widgets/dismissable.dart @@ -64,6 +64,12 @@ class _DismissableState extends State { double _dragExtent = 0.0; bool _dragUnderway = false; + void dispose() { + _fadePerformance?.stop(); + _resizePerformance?.stop(); + super.dispose(); + } + bool get _directionIsYAxis { return config.direction == DismissDirection.vertical || From 8945e0112f846c37453f298d0bbb8db7cb1870e4 Mon Sep 17 00:00:00 2001 From: Hixie Date: Thu, 8 Oct 2015 15:18:23 -0700 Subject: [PATCH 20/84] Changing themes caused crash The root cause was that we crawled the tree to mark anyone who depended on the updated theme dirty _after_ we crawled it to rebuild it. Thus, if anyone was already marked dirty when the process started, then got marked clean by the first (rebuild) walk, then got marked dirty again by the notification, they'd be clean when they got the notification, despite already being in the dirty list, which would cause an assertion. Also IconTheme didn't have an operator==, so it was independently too aggressive about updates. --- .../flutter/lib/src/widgets/framework.dart | 75 +++++++++++-------- packages/flutter/lib/src/widgets/icon.dart | 3 + 2 files changed, 47 insertions(+), 31 deletions(-) diff --git a/packages/flutter/lib/src/widgets/framework.dart b/packages/flutter/lib/src/widgets/framework.dart index f92219de40..dd36a8600b 100644 --- a/packages/flutter/lib/src/widgets/framework.dart +++ b/packages/flutter/lib/src/widgets/framework.dart @@ -7,6 +7,8 @@ import 'dart:collection'; import 'package:sky/rendering.dart'; +// KEYS + /// A Key is an identifier for [Widget]s and [Element]s. A new Widget will only /// be used to reconfigure an existing Element if its Key is the same as its /// original Widget's Key. @@ -171,6 +173,8 @@ class GlobalObjectKey extends GlobalKey { } +// WIDGETS + /// A Widget object describes the configuration for an [Element]. /// Widget subclasses should be immutable with const constructors. /// Widgets form a tree that is then inflated into an Element tree. @@ -193,6 +197,8 @@ abstract class Widget { void debugFillDescription(List description) { } } +// TODO(ianh): move the next four classes to below InheritedWidget + /// RenderObjectWidgets provide the configuration for [RenderObjectElement]s, /// which wrap [RenderObject]s, which provide the actual rendering of the /// application. @@ -382,16 +388,14 @@ abstract class State { } } -abstract class ProxyWidget extends StatelessComponent { - const ProxyWidget({ Key key, Widget this.child }) : super(key: key); +abstract class ProxyComponent extends Widget { + const ProxyComponent({ Key key, this.child }) : super(key: key); final Widget child; - - Widget build(BuildContext context) => child; } -abstract class ParentDataWidget extends ProxyWidget { - ParentDataWidget({ Key key, Widget child }) +abstract class ParentDataWidget extends ProxyComponent { + const ParentDataWidget({ Key key, Widget child }) : super(key: key, child: child); ParentDataElement createElement() => new ParentDataElement(this); @@ -405,7 +409,7 @@ abstract class ParentDataWidget extends ProxyWidget { void applyParentData(RenderObject renderObject); } -abstract class InheritedWidget extends ProxyWidget { +abstract class InheritedWidget extends ProxyComponent { const InheritedWidget({ Key key, Widget child }) : super(key: key, child: child); @@ -414,6 +418,9 @@ abstract class InheritedWidget extends ProxyWidget { bool updateShouldNotify(InheritedWidget oldWidget); } + +// ELEMENTS + bool _canUpdate(Widget oldWidget, Widget newWidget) { return oldWidget.runtimeType == newWidget.runtimeType && oldWidget.key == newWidget.key; @@ -637,6 +644,7 @@ abstract class Element implements BuildContext { assert(_debugLifecycleState == _ElementLifecycle.active); assert(widget != null); assert(newWidget != null); + assert(newWidget != widget); assert(depth != null); assert(_active); assert(_canUpdate(widget, newWidget)); @@ -970,8 +978,8 @@ abstract class BuildableElement extends Element { typedef Widget WidgetBuilder(BuildContext context); -/// Base class for the instantiation of StatelessComponent and StatefulComponent -/// widgets. +/// Base class for the instantiation of StatelessComponent, StatefulComponent, +/// and ProxyComponent widgets. abstract class ComponentElement extends BuildableElement { ComponentElement(T widget) : super(widget); @@ -1114,7 +1122,26 @@ class StatefulComponentElement> } } -class ParentDataElement extends StatelessComponentElement { +abstract class ProxyElement extends ComponentElement { + ProxyElement(T widget) : super(widget) { + _builder = (BuildContext context) => this.widget.child; + } + + void update(T newWidget) { + T oldWidget = widget; + assert(widget != null); + assert(widget != newWidget); + super.update(newWidget); + assert(widget == newWidget); + notifyDescendants(oldWidget); + _dirty = true; + rebuild(); + } + + void notifyDescendants(T oldWidget); +} + +class ParentDataElement extends ProxyElement { ParentDataElement(ParentDataWidget widget) : super(widget); void mount(Element parent, dynamic slot) { @@ -1134,15 +1161,7 @@ class ParentDataElement extends StatelessComponentElement { super.mount(parent, slot); } - void update(ParentDataWidget newWidget) { - ParentDataWidget oldWidget = widget; - super.update(newWidget); - assert(widget == newWidget); - if (widget != oldWidget) - _notifyDescendants(); - } - - void _notifyDescendants() { + void notifyDescendants(ParentDataWidget oldWidget) { void notifyChildren(Element child) { if (child is RenderObjectElement) child.updateParentData(widget); @@ -1153,20 +1172,14 @@ class ParentDataElement extends StatelessComponentElement { } } -class InheritedElement extends StatelessComponentElement { + + +class InheritedElement extends ProxyElement { InheritedElement(InheritedWidget widget) : super(widget); - void update(StatelessComponent newWidget) { - InheritedWidget oldWidget = widget; - super.update(newWidget); - assert(widget == newWidget); - if (widget.updateShouldNotify(oldWidget)) { - assert(widget != oldWidget); - _notifyDescendants(); - } - } - - void _notifyDescendants() { + void notifyDescendants(InheritedWidget oldWidget) { + if (!widget.updateShouldNotify(oldWidget)) + return; final Type ourRuntimeType = widget.runtimeType; void notifyChildren(Element child) { if (child._dependencies != null && diff --git a/packages/flutter/lib/src/widgets/icon.dart b/packages/flutter/lib/src/widgets/icon.dart index 5dcee05232..9b71b138c6 100644 --- a/packages/flutter/lib/src/widgets/icon.dart +++ b/packages/flutter/lib/src/widgets/icon.dart @@ -14,6 +14,9 @@ enum IconThemeColor { white, black } class IconThemeData { const IconThemeData({ this.color }); final IconThemeColor color; + + bool operator==(other) => other.runtimeType == runtimeType && other.color == color; + int get hashCode => color.hashCode; } class IconTheme extends InheritedWidget { From 95a0aceaa105ab6c36785e101b91f01da0a2b3de Mon Sep 17 00:00:00 2001 From: Viktor Lidholt Date: Thu, 8 Oct 2015 16:12:31 -0700 Subject: [PATCH 21/84] Adds basic support for joints in sprite physics --- .../flutter_sprites/lib/physics_body.dart | 9 ++ .../flutter_sprites/lib/physics_joint.dart | 90 +++++++++++++++++++ .../flutter_sprites/lib/physics_node.dart | 7 ++ packages/flutter_sprites/lib/skysprites.dart | 1 + 4 files changed, 107 insertions(+) create mode 100644 packages/flutter_sprites/lib/physics_joint.dart diff --git a/packages/flutter_sprites/lib/physics_body.dart b/packages/flutter_sprites/lib/physics_body.dart index 178b1ac48c..40ee242c0f 100644 --- a/packages/flutter_sprites/lib/physics_body.dart +++ b/packages/flutter_sprites/lib/physics_body.dart @@ -230,6 +230,8 @@ class PhysicsBody { box2d.Body _body; + List _joints = []; + bool _attached = false; void applyForce(Offset force, Point worldPoint) { @@ -338,6 +340,13 @@ class PhysicsBody { _node = node; _attached = true; + + // Attach any joints + for (PhysicsJoint joint in _joints) { + if (joint.bodyA._attached && joint.bodyB._attached) { + joint._attach(physicsNode); + } + } } void _detach() { diff --git a/packages/flutter_sprites/lib/physics_joint.dart b/packages/flutter_sprites/lib/physics_joint.dart new file mode 100644 index 0000000000..cecdd5c581 --- /dev/null +++ b/packages/flutter_sprites/lib/physics_joint.dart @@ -0,0 +1,90 @@ +part of skysprites; + +abstract class PhysicsJoint { + PhysicsJoint(this.bodyA, this.bodyB) { + bodyA._joints.add(this); + bodyB._joints.add(this); + + if (bodyA._attached && bodyB._attached) { + _attach(bodyA._physicsNode); + } + } + + PhysicsBody bodyA; + PhysicsBody bodyB; + + bool _active = true; + box2d.Joint _joint; + + PhysicsNode _physicsNode; + + void _attach(PhysicsNode physicsNode) { + if (_joint == null) { + _physicsNode = physicsNode; + _joint = _createB2Joint(physicsNode); + } + } + + void _detach() { + if (_joint != null && _active) { + _physicsNode.b2World.destroyJoint(_joint); + _joint = null; + } + _active = false; + } + + box2d.Joint _createB2Joint(PhysicsNode physicsNode); +} + +class PhysicsJointRevolute extends PhysicsJoint { + PhysicsJointRevolute( + PhysicsBody bodyA, + PhysicsBody bodyB, + this.anchorWorld, { + double lowerAngle: 0.0, + double upperAngle: 0.0, + bool enableLimit: false + }) : super(bodyA, bodyB) { + this.lowerAngle = lowerAngle; + this.upperAngle = upperAngle; + this.enableLimit = enableLimit; + } + + Point anchorWorld; + double lowerAngle; + double upperAngle; + bool enableLimit; + + box2d.Joint _createB2Joint(PhysicsNode physicsNode) { + // Create Joint Definition + Vector2 vecAnchor = new Vector2( + anchorWorld.x / physicsNode.b2WorldToNodeConversionFactor, + anchorWorld.y / physicsNode.b2WorldToNodeConversionFactor + ); + + box2d.RevoluteJointDef b2Def = new box2d.RevoluteJointDef(); + b2Def.initialize(bodyA._body, bodyB._body, vecAnchor); + b2Def.enableLimit = enableLimit; + b2Def.lowerAngle = lowerAngle; + b2Def.upperAngle = upperAngle; + + // Create joint + return physicsNode.b2World.createJoint(b2Def); + } +} + +class PhysicsJointWeld extends PhysicsJoint { + PhysicsJointWeld( + PhysicsBody bodyA, + PhysicsBody bodyB) : super(bodyA, bodyB); + + box2d.Joint _createB2Joint(PhysicsNode physicsNode) { + box2d.WeldJointDef b2Def = new box2d.WeldJointDef(); + Vector2 middle = new Vector2( + (bodyA._body.position.x + bodyB._body.position.x) / 2.0, + (bodyA._body.position.y + bodyB._body.position.y) / 2.0 + ); + b2Def.initialize(bodyA._body, bodyB._body, middle); + return physicsNode.b2World.createJoint(b2Def); + } +} diff --git a/packages/flutter_sprites/lib/physics_node.dart b/packages/flutter_sprites/lib/physics_node.dart index 4510289d93..69d74829f0 100644 --- a/packages/flutter_sprites/lib/physics_node.dart +++ b/packages/flutter_sprites/lib/physics_node.dart @@ -83,6 +83,13 @@ class PhysicsNode extends Node { void _removeBodiesScheduledForDestruction() { for (box2d.Body b2Body in _bodiesScheduledForDestruction) { + // Destroy any joints before destroying the body + PhysicsBody body = b2Body.userData; + for (PhysicsJoint joint in body._joints) { + joint._detach(); + } + + // Destroy the body b2World.destroyBody(b2Body); } _bodiesScheduledForDestruction.clear(); diff --git a/packages/flutter_sprites/lib/skysprites.dart b/packages/flutter_sprites/lib/skysprites.dart index ad662c65d0..6ffd26de3d 100644 --- a/packages/flutter_sprites/lib/skysprites.dart +++ b/packages/flutter_sprites/lib/skysprites.dart @@ -33,6 +33,7 @@ part 'node3d.dart'; part 'node_with_size.dart'; part 'particle_system.dart'; part 'physics_body.dart'; +part 'physics_joint.dart'; part 'physics_node.dart'; part 'physics_shape.dart'; part 'sound.dart'; From 333c8f5f107c5d72f3ffaab22893ecae4b1d481c Mon Sep 17 00:00:00 2001 From: Viktor Lidholt Date: Thu, 8 Oct 2015 16:13:56 -0700 Subject: [PATCH 22/84] Updates sprite physics test --- examples/game/test_physics.dart | 51 ++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 20 deletions(-) diff --git a/examples/game/test_physics.dart b/examples/game/test_physics.dart index aabb773bd2..137a3257ce 100644 --- a/examples/game/test_physics.dart +++ b/examples/game/test_physics.dart @@ -45,24 +45,11 @@ main() async { } class TestBed extends NodeWithSize { - Sprite _ship; Sprite _obstacle; + PhysicsNode _physicsNode; TestBed() : super(new Size(1024.0, 1024.0)) { - PhysicsNode physicsNode = new PhysicsNode(new Offset(0.0, 100.0)); - - _ship = new Sprite(_spriteSheet["ship.png"]); - _ship.position = new Point(512.0, 512.0); - _ship.size = new Size(64.0, 64.0); - _ship.physicsBody = new PhysicsBody( - new PhysicsShapeGroup([ - new PhysicsShapeCircle(Point.origin, 32.0), - new PhysicsShapePolygon([new Point(0.0, 0.0), new Point(50.0, 0.0), new Point(50.0, 50.0), new Point(0.0, 50.0)]) - ]), - friction: 0.5, - tag: "ship" - ); - physicsNode.addChild(_ship); + _physicsNode = new PhysicsNode(new Offset(0.0, 100.0)); _obstacle = new Sprite(_spriteSheet["ship.png"]); _obstacle.position = new Point(532.0, 800.0); @@ -73,23 +60,47 @@ class TestBed extends NodeWithSize { friction: 0.5, tag: "obstacle" ); - physicsNode.addChild(_obstacle); - physicsNode.addContactCallback(myCallback, "obstacle", "ship", PhysicsContactType.begin); + _physicsNode.addChild(_obstacle); + _physicsNode.addContactCallback(myCallback, "obstacle", "ship", PhysicsContactType.begin); - addChild(physicsNode); + addChild(_physicsNode); userInteractionEnabled = true; } void myCallback(PhysicsContactType type, PhysicsContact contact) { print("CONTACT type: $type"); - contact.nodeB.removeFromParent(); } bool handleEvent(SpriteBoxEvent event) { if (event.type == "pointerdown") { Point pos = convertPointToNodeSpace(event.boxPosition); - _ship.position = pos; + + Sprite shipA; + shipA = new Sprite(_spriteSheet["ship.png"]); + shipA.position = new Point(pos.x - 40.0, pos.y); + shipA.size = new Size(64.0, 64.0); + shipA.physicsBody = new PhysicsBody(new PhysicsShapeCircle(Point.origin, 32.0), + friction: 0.5, + tag: "ship" + ); + _physicsNode.addChild(shipA); + shipA.physicsBody.applyLinearImpulse( + new Offset(randomSignedDouble() * 5.0, randomSignedDouble() * 5.0), + shipA.position + ); + + Sprite shipB; + shipB = new Sprite(_spriteSheet["ship.png"]); + shipB.position = new Point(pos.x + 40.0, pos.y); + shipB.size = new Size(64.0, 64.0); + shipB.physicsBody = new PhysicsBody(new PhysicsShapePolygon([new Point(-25.0, -25.0), new Point(25.0, -25.0), new Point(25.0, 25.0), new Point(-25.0, 25.0)]), + friction: 0.5, + tag: "ship" + ); + _physicsNode.addChild(shipB); + + new PhysicsJointWeld(shipA.physicsBody, shipB.physicsBody); } return true; } From 892d60d538d5d91ce4165379d5f16e14eec5f22c Mon Sep 17 00:00:00 2001 From: Hixie Date: Thu, 1 Oct 2015 09:28:40 -0700 Subject: [PATCH 23/84] Have Flat buttons set their default text styles. Also, have dialog buttons use the accent colour. Also, generally rationalise some of this stuff to match Material better. --- examples/stocks/lib/stock_home.dart | 23 ++++++++ examples/stocks/lib/stock_menu.dart | 13 +++++ packages/flutter/lib/src/material/colors.dart | 16 ++++-- .../flutter/lib/src/material/theme_data.dart | 15 ++++- .../flutter/lib/src/material/typography.dart | 22 ++++---- .../flutter/lib/src/widgets/date_picker.dart | 4 +- packages/flutter/lib/src/widgets/dialog.dart | 10 +++- .../flutter/lib/src/widgets/flat_button.dart | 8 ++- .../flutter/lib/src/widgets/framework.dart | 4 +- .../flutter/lib/src/widgets/material.dart | 6 +- .../lib/src/widgets/material_button.dart | 55 ++++++++++++++++++- .../lib/src/widgets/raised_button.dart | 20 +++++-- 12 files changed, 161 insertions(+), 35 deletions(-) diff --git a/examples/stocks/lib/stock_home.dart b/examples/stocks/lib/stock_home.dart index 106f457a96..5d3bbcf790 100644 --- a/examples/stocks/lib/stock_home.dart +++ b/examples/stocks/lib/stock_home.dart @@ -83,6 +83,29 @@ class StockHomeState extends State { ), new DrawerItem( icon: 'action/account_balance', + onPressed: () { + showDialog(config.navigator, (NavigatorState navigator) { + return new Dialog( + title: new Text('Not Implemented'), + content: new Text('This feature has not yet been implemented.'), + actions: [ + new FlatButton( + child: new Text('USE IT'), + enabled: false, + onPressed: () { + navigator.pop(false); + } + ), + new FlatButton( + child: new Text('OH WELL'), + onPressed: () { + navigator.pop(false); + } + ), + ] + ); + }); + }, child: new Text('Account Balance') ), new DrawerItem( diff --git a/examples/stocks/lib/stock_menu.dart b/examples/stocks/lib/stock_menu.dart index d5c1f95884..c55e646589 100644 --- a/examples/stocks/lib/stock_menu.dart +++ b/examples/stocks/lib/stock_menu.dart @@ -60,6 +60,19 @@ Future showStockMenu(NavigatorState navigator, { bool autorefresh, ValueChanged title: new Text('Not Implemented'), content: new Text('This feature has not yet been implemented.'), actions: [ + new FlatButton( + child: new Row([ + new Icon( + type: 'device/dvr', + size: 18 + ), + new Container( + width: 8.0 + ), + new Text('DUMP APP TO CONSOLE'), + ]), + onPressed: () { debugDumpApp(); } + ), new FlatButton( child: new Text('OH WELL'), onPressed: () { diff --git a/packages/flutter/lib/src/material/colors.dart b/packages/flutter/lib/src/material/colors.dart index b1af32f31e..bde576a1df 100644 --- a/packages/flutter/lib/src/material/colors.dart +++ b/packages/flutter/lib/src/material/colors.dart @@ -9,13 +9,17 @@ import 'dart:sky' show Color; class Colors { Colors._(); - static const white = const Color(0xFFFFFFFF); - static const black = const Color(0xFF000000); static const transparent = const Color(0x00000000); - static const white54 = const Color(0x8AFFFFFF); - static const white87 = const Color(0xDDFFFFFF); - static const black54 = const Color(0x8A000000); + + static const black = const Color(0xFF000000); static const black87 = const Color(0xDD000000); + static const black54 = const Color(0x8A000000); + static const black26 = const Color(0x42000000); // text of disabled flat button in light theme + static const black12 = const Color(0x1F000000); // background of disabled raised buttons in light theme + static const white = const Color(0xFFFFFFFF); + static const white70 = const Color(0xB3FFFFFF); + static const white30 = const Color(0x4DFFFFFF); // text of disabled flat button in dark theme + static const white12 = const Color(0x1FFFFFFF); // background of disabled raised buttons in dark theme static const Map red = const { 50: const Color(0xFFFFEBEE), @@ -355,7 +359,7 @@ class Colors { 100: const Color(0xFFF5F5F5), 200: const Color(0xFFEEEEEE), 300: const Color(0xFFE0E0E0), - 350: const Color(0xFFD6D6D6), // only for raised button while pressed or disabled + 350: const Color(0xFFD6D6D6), // only for raised button while pressed in Light theme 400: const Color(0xFFBDBDBD), 500: const Color(0xFF9E9E9E), 600: const Color(0xFF757575), diff --git a/packages/flutter/lib/src/material/theme_data.dart b/packages/flutter/lib/src/material/theme_data.dart index 4c45b16370..be3092fce6 100644 --- a/packages/flutter/lib/src/material/theme_data.dart +++ b/packages/flutter/lib/src/material/theme_data.dart @@ -59,7 +59,11 @@ class ThemeData { factory ThemeData.dark() => new ThemeData(brightness: ThemeBrightness.dark); factory ThemeData.fallback() => new ThemeData.light(); + /// The brightness of the overall theme of the application. Used by widgets + /// like buttons to determine what color to pick when not using the primary or + /// accent color. final ThemeBrightness brightness; + final Map primarySwatch; final Color canvasColor; final Color cardColor; @@ -70,14 +74,21 @@ class ThemeData { final double hintOpacity; final TextTheme text; - Color _primaryColor; + /// The background colour for major parts of the app (toolbars, tab bars, etc) Color get primaryColor => _primaryColor; + Color _primaryColor; + /// The brightness of the primaryColor. Used to determine the colour of text and + /// icons placed on top of the primary color (e.g. toolbar text). final ThemeBrightness primaryColorBrightness; - Color _accentColor; + /// The foreground color for widgets (knobs, text, etc) Color get accentColor => _accentColor; + Color _accentColor; + /// The brightness of the accentColor. Used to determine the colour of text + /// and icons placed on top of the accent color (e.g. the icons on a floating + /// action button). final ThemeBrightness accentColorBrightness; bool operator==(Object other) { diff --git a/packages/flutter/lib/src/material/typography.dart b/packages/flutter/lib/src/material/typography.dart index 37a2626852..599a273b99 100644 --- a/packages/flutter/lib/src/material/typography.dart +++ b/packages/flutter/lib/src/material/typography.dart @@ -28,17 +28,17 @@ class TextTheme { button = const TextStyle(fontSize: 14.0, fontWeight: FontWeight.w500, color: Colors.black87, textBaseline: TextBaseline.alphabetic); const TextTheme._white() - : display4 = const TextStyle(fontSize: 112.0, fontWeight: FontWeight.w100, color: Colors.white54, textBaseline: TextBaseline.alphabetic), - display3 = const TextStyle(fontSize: 56.0, fontWeight: FontWeight.w400, color: Colors.white54, textBaseline: TextBaseline.alphabetic), - display2 = const TextStyle(fontSize: 45.0, fontWeight: FontWeight.w400, color: Colors.white54, height: 48.0 / 45.0, textBaseline: TextBaseline.alphabetic), - display1 = const TextStyle(fontSize: 34.0, fontWeight: FontWeight.w400, color: Colors.white54, height: 40.0 / 34.0, textBaseline: TextBaseline.alphabetic), - headline = const TextStyle(fontSize: 24.0, fontWeight: FontWeight.w400, color: Colors.white87, height: 32.0 / 24.0, textBaseline: TextBaseline.alphabetic), - title = const TextStyle(fontSize: 20.0, fontWeight: FontWeight.w500, color: Colors.white87, height: 28.0 / 20.0, textBaseline: TextBaseline.alphabetic), - subhead = const TextStyle(fontSize: 16.0, fontWeight: FontWeight.w400, color: Colors.white87, height: 24.0 / 16.0, textBaseline: TextBaseline.alphabetic), - body2 = const TextStyle(fontSize: 14.0, fontWeight: FontWeight.w500, color: Colors.white87, height: 24.0 / 14.0, textBaseline: TextBaseline.alphabetic), - body1 = const TextStyle(fontSize: 14.0, fontWeight: FontWeight.w400, color: Colors.white87, height: 20.0 / 14.0, textBaseline: TextBaseline.alphabetic), - caption = const TextStyle(fontSize: 12.0, fontWeight: FontWeight.w400, color: Colors.white54, textBaseline: TextBaseline.alphabetic), - button = const TextStyle(fontSize: 14.0, fontWeight: FontWeight.w500, color: Colors.white87, textBaseline: TextBaseline.alphabetic); + : display4 = const TextStyle(fontSize: 112.0, fontWeight: FontWeight.w100, color: Colors.white70, textBaseline: TextBaseline.alphabetic), + display3 = const TextStyle(fontSize: 56.0, fontWeight: FontWeight.w400, color: Colors.white70, textBaseline: TextBaseline.alphabetic), + display2 = const TextStyle(fontSize: 45.0, fontWeight: FontWeight.w400, color: Colors.white70, height: 48.0 / 45.0, textBaseline: TextBaseline.alphabetic), + display1 = const TextStyle(fontSize: 34.0, fontWeight: FontWeight.w400, color: Colors.white70, height: 40.0 / 34.0, textBaseline: TextBaseline.alphabetic), + headline = const TextStyle(fontSize: 24.0, fontWeight: FontWeight.w400, color: Colors.white, height: 32.0 / 24.0, textBaseline: TextBaseline.alphabetic), + title = const TextStyle(fontSize: 20.0, fontWeight: FontWeight.w500, color: Colors.white, height: 28.0 / 20.0, textBaseline: TextBaseline.alphabetic), + subhead = const TextStyle(fontSize: 16.0, fontWeight: FontWeight.w400, color: Colors.white, height: 24.0 / 16.0, textBaseline: TextBaseline.alphabetic), + body2 = const TextStyle(fontSize: 14.0, fontWeight: FontWeight.w500, color: Colors.white, height: 24.0 / 14.0, textBaseline: TextBaseline.alphabetic), + body1 = const TextStyle(fontSize: 14.0, fontWeight: FontWeight.w400, color: Colors.white, height: 20.0 / 14.0, textBaseline: TextBaseline.alphabetic), + caption = const TextStyle(fontSize: 12.0, fontWeight: FontWeight.w400, color: Colors.white70, textBaseline: TextBaseline.alphabetic), + button = const TextStyle(fontSize: 14.0, fontWeight: FontWeight.w500, color: Colors.white, textBaseline: TextBaseline.alphabetic); final TextStyle display4; final TextStyle display3; diff --git a/packages/flutter/lib/src/widgets/date_picker.dart b/packages/flutter/lib/src/widgets/date_picker.dart index 56f4ed7fb3..5f428d65e3 100644 --- a/packages/flutter/lib/src/widgets/date_picker.dart +++ b/packages/flutter/lib/src/widgets/date_picker.dart @@ -135,8 +135,8 @@ class _DatePickerHeader extends StatelessComponent { break; case ThemeBrightness.dark: headerTheme = Typography.white; - dayColor = mode == DatePickerMode.day ? Colors.white87 : Colors.white54; - yearColor = mode == DatePickerMode.year ? Colors.white87 : Colors.white54; + dayColor = mode == DatePickerMode.day ? Colors.white : Colors.white70; + yearColor = mode == DatePickerMode.year ? Colors.white : Colors.white70; break; } TextStyle dayStyle = headerTheme.display3.copyWith(color: dayColor, height: 1.0, fontSize: 100.0); diff --git a/packages/flutter/lib/src/widgets/dialog.dart b/packages/flutter/lib/src/widgets/dialog.dart index 88b44ade59..202db68580 100644 --- a/packages/flutter/lib/src/widgets/dialog.dart +++ b/packages/flutter/lib/src/widgets/dialog.dart @@ -12,6 +12,7 @@ import 'package:sky/src/widgets/focus.dart'; import 'package:sky/src/widgets/framework.dart'; import 'package:sky/src/widgets/gesture_detector.dart'; import 'package:sky/src/widgets/material.dart'; +import 'package:sky/src/widgets/material_button.dart'; import 'package:sky/src/widgets/navigator.dart'; import 'package:sky/src/widgets/scrollable.dart'; import 'package:sky/src/widgets/theme.dart'; @@ -95,9 +96,12 @@ class Dialog extends StatelessComponent { } if (actions != null) { - dialogBody.add(new Container( - child: new Row(actions, - justifyContent: FlexJustifyContent.end + dialogBody.add(new ButtonTheme( + color: ButtonColor.accent, + child: new Container( + child: new Row(actions, + justifyContent: FlexJustifyContent.end + ) ) )); } diff --git a/packages/flutter/lib/src/widgets/flat_button.dart b/packages/flutter/lib/src/widgets/flat_button.dart index 164b087f59..238879bfba 100644 --- a/packages/flutter/lib/src/widgets/flat_button.dart +++ b/packages/flutter/lib/src/widgets/flat_button.dart @@ -24,6 +24,9 @@ class FlatButton extends MaterialButton { } class _FlatButtonState extends MaterialButtonState { + + int get level => 0; + Color getColor(BuildContext context) { if (!config.enabled || !highlight) return null; @@ -35,5 +38,8 @@ class _FlatButtonState extends MaterialButtonState { } } - int get level => 0; + ThemeBrightness getColorBrightness(BuildContext context) { + return Theme.of(context).brightness; + } + } diff --git a/packages/flutter/lib/src/widgets/framework.dart b/packages/flutter/lib/src/widgets/framework.dart index dd36a8600b..e1fc342b19 100644 --- a/packages/flutter/lib/src/widgets/framework.dart +++ b/packages/flutter/lib/src/widgets/framework.dart @@ -192,7 +192,7 @@ abstract class Widget { if (data.isEmpty) return '$name'; return '$name(${data.join("; ")})'; - } + } void debugFillDescription(List description) { } } @@ -798,7 +798,7 @@ abstract class Element implements BuildContext { String toString() { final List data = []; debugFillDescription(data); - final String name = widget != null ? '$widget' : '[$runtimeType]'; + final String name = widget != null ? '${widget.runtimeType}' : '[$runtimeType]'; return '$name(${data.join("; ")})'; } diff --git a/packages/flutter/lib/src/widgets/material.dart b/packages/flutter/lib/src/widgets/material.dart index 138994cfd7..4f42d63abd 100644 --- a/packages/flutter/lib/src/widgets/material.dart +++ b/packages/flutter/lib/src/widgets/material.dart @@ -25,7 +25,8 @@ class Material extends StatelessComponent { this.child, this.type: MaterialType.card, this.level: 0, - this.color + this.color, + this.textStyle }) : super(key: key) { assert(level != null); } @@ -34,6 +35,7 @@ class Material extends StatelessComponent { final MaterialType type; final int level; final Color color; + final TextStyle textStyle; Color _getBackgroundColor(BuildContext context) { if (color != null) @@ -52,7 +54,7 @@ class Material extends StatelessComponent { Widget contents = child; if (child != null) { contents = new DefaultTextStyle( - style: Theme.of(context).text.body1, + style: textStyle ?? Theme.of(context).text.body1, child: contents ); if (_kEdges[type] != null) { diff --git a/packages/flutter/lib/src/widgets/material_button.dart b/packages/flutter/lib/src/widgets/material_button.dart index 4a21d4ebe8..cd01b0df43 100644 --- a/packages/flutter/lib/src/widgets/material_button.dart +++ b/packages/flutter/lib/src/widgets/material_button.dart @@ -3,17 +3,42 @@ // found in the LICENSE file. import 'package:sky/gestures.dart'; +import 'package:sky/material.dart'; import 'package:sky/src/widgets/basic.dart'; import 'package:sky/src/widgets/framework.dart'; import 'package:sky/src/widgets/ink_well.dart'; import 'package:sky/src/widgets/material.dart'; +import 'package:sky/src/widgets/theme.dart'; +enum ButtonColor { normal, accent } + +class ButtonTheme extends InheritedWidget { + ButtonTheme({ + Key key, + this.color, + Widget child + }) : super(key: key, child: child) { + assert(child != null); + } + + final ButtonColor color; + + static ButtonColor of(BuildContext context) { + ButtonTheme result = context.inheritedWidgetOfType(ButtonTheme); + return result?.color ?? ButtonColor.normal; + } + + bool updateShouldNotify(ButtonTheme old) => color != old.color; +} + +/// Base class for buttons in the Material theme. /// Rather than using this class directly, please use FlatButton or RaisedButton. abstract class MaterialButton extends StatefulComponent { MaterialButton({ Key key, this.child, this.enabled: true, + this.textColor, this.onPressed }) : super(key: key) { assert(enabled != null); @@ -21,15 +46,40 @@ abstract class MaterialButton extends StatefulComponent { final Widget child; final bool enabled; + final ButtonColor textColor; final GestureTapCallback onPressed; } abstract class MaterialButtonState extends State { bool highlight = false; - Color getColor(BuildContext context); int get level; + Color getColor(BuildContext context); + ThemeBrightness getColorBrightness(BuildContext context); + + Color getTextColor(BuildContext context) { + if (config.enabled) { + switch (config.textColor ?? ButtonTheme.of(context)) { + case ButtonColor.accent: + return Theme.of(context).accentColor; + case ButtonColor.normal: + switch (getColorBrightness(context)) { + case ThemeBrightness.light: + return Colors.black87; + case ThemeBrightness.dark: + return Colors.white; + } + } + } + switch (getColorBrightness(context)) { + case ThemeBrightness.light: + return Colors.black26; + case ThemeBrightness.dark: + return Colors.white30; + } + } + void _handleHighlightChanged(bool value) { setState(() { highlight = value; @@ -41,7 +91,7 @@ abstract class MaterialButtonState extends State { padding: new EdgeDims.symmetric(horizontal: 8.0), child: new Center( shrinkWrap: ShrinkWrap.width, - child: config.child // TODO(ianh): figure out a way to compell the child to have gray text when disabled... + child: config.child ) ); return new Container( @@ -52,6 +102,7 @@ abstract class MaterialButtonState extends State { type: MaterialType.button, level: level, color: getColor(context), + textStyle: Theme.of(context).text.button.copyWith(color: getTextColor(context)), child: new InkWell( onTap: config.enabled ? config.onPressed : null, onHighlightChanged: config.enabled ? _handleHighlightChanged : null, diff --git a/packages/flutter/lib/src/widgets/raised_button.dart b/packages/flutter/lib/src/widgets/raised_button.dart index 6d5e5487c2..b6db80487a 100644 --- a/packages/flutter/lib/src/widgets/raised_button.dart +++ b/packages/flutter/lib/src/widgets/raised_button.dart @@ -26,6 +26,9 @@ class RaisedButton extends MaterialButton { } class _RaisedButtonState extends MaterialButtonState { + + int get level => config.enabled ? (highlight ? 2 : 1) : 0; + Color getColor(BuildContext context) { if (config.enabled) { switch (Theme.of(context).brightness) { @@ -36,16 +39,25 @@ class _RaisedButtonState extends MaterialButtonState { return Colors.grey[300]; break; case ThemeBrightness.dark: + Map swatch = Theme.of(context).primarySwatch ?? Colors.blue; if (highlight) - return Theme.of(context).primarySwatch[700]; + return swatch[700]; else - return Theme.of(context).primarySwatch[600]; + return swatch[600]; break; } } else { - return Colors.grey[350]; + switch (Theme.of(context).brightness) { + case ThemeBrightness.light: + return Colors.black12; + case ThemeBrightness.dark: + return Colors.white12; + } } } - int get level => config.enabled ? (highlight ? 2 : 1) : 0; + ThemeBrightness getColorBrightness(BuildContext context) { + return Theme.of(context).brightness; + } + } From 423db5c22c4ca40e6c8fb355b28092f6cf5fb425 Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Fri, 9 Oct 2015 09:37:23 -0700 Subject: [PATCH 24/84] Rev pub package --- packages/flutter/pubspec.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/flutter/pubspec.yaml b/packages/flutter/pubspec.yaml index 20565dfdd8..b918da6e15 100644 --- a/packages/flutter/pubspec.yaml +++ b/packages/flutter/pubspec.yaml @@ -1,5 +1,5 @@ name: sky -version: 0.0.53 +version: 0.0.54 author: Flutter Authors description: A framework for writing Flutter applications homepage: http://flutter.io @@ -9,8 +9,8 @@ dependencies: mojo_services: '>=0.1.0 <0.2.0' mojo: '>=0.1.0 <0.2.0' newton: ^0.1.4 - sky_engine: ^0.0.31 - sky_services: ^0.0.31 + sky_engine: ^0.0.32 + sky_services: ^0.0.32 sky_tools: ^0.0.15 vector_math: ^1.4.3 intl: ^0.12.4+2 From 37bda251962c3c7ddf6fc545f17f5a775420581a Mon Sep 17 00:00:00 2001 From: Hixie Date: Fri, 9 Oct 2015 09:56:40 -0700 Subject: [PATCH 25/84] Relative paths in internal flutter libraries Now that you import a top-level file for each layer of the Flutter framework, within the framework we can use relative paths without being worried about the copy/pasta problem we used to have. --- packages/flutter/lib/rendering.dart | 42 +++++++++---------- .../lib/src/animation/animated_value.dart | 2 +- .../lib/src/animation/performance.dart | 6 +-- .../lib/src/animation/simulation_stepper.dart | 6 +-- .../flutter/lib/src/animation/ticker.dart | 2 +- packages/flutter/lib/src/gestures/drag.dart | 6 +-- .../flutter/lib/src/gestures/long_press.dart | 8 ++-- .../flutter/lib/src/gestures/recognizer.dart | 8 ++-- packages/flutter/lib/src/gestures/scale.dart | 6 +-- .../flutter/lib/src/gestures/show_press.dart | 6 +-- packages/flutter/lib/src/gestures/tap.dart | 4 +- .../flutter/lib/src/painting/box_painter.dart | 3 +- .../lib/src/painting/text_painter.dart | 4 +- .../lib/src/rendering/auto_layout.dart | 5 ++- .../flutter/lib/src/rendering/binding.dart | 9 ++-- packages/flutter/lib/src/rendering/block.dart | 5 ++- packages/flutter/lib/src/rendering/box.dart | 5 ++- .../lib/src/rendering/editable_paragraph.dart | 9 ++-- packages/flutter/lib/src/rendering/error.dart | 6 +-- packages/flutter/lib/src/rendering/flex.dart | 4 +- packages/flutter/lib/src/rendering/grid.dart | 4 +- packages/flutter/lib/src/rendering/image.dart | 5 ++- .../flutter/lib/src/rendering/object.dart | 11 ++--- .../flutter/lib/src/rendering/paragraph.dart | 7 ++-- .../flutter/lib/src/rendering/proxy_box.dart | 8 ++-- .../lib/src/rendering/shifted_box.dart | 5 ++- packages/flutter/lib/src/rendering/stack.dart | 4 +- .../lib/src/rendering/statistics_box.dart | 4 +- .../flutter/lib/src/rendering/toggleable.dart | 9 ++-- packages/flutter/lib/src/rendering/view.dart | 7 ++-- .../flutter/lib/src/rendering/viewport.dart | 5 ++- .../flutter/lib/src/services/activity.dart | 3 +- .../lib/src/services/asset_bundle.dart | 11 ++--- packages/flutter/lib/src/services/fetch.dart | 3 +- .../flutter/lib/src/services/image_cache.dart | 7 ++-- .../flutter/lib/src/services/keyboard.dart | 3 +- packages/flutter/lib/src/services/shell.dart | 3 +- 37 files changed, 132 insertions(+), 113 deletions(-) diff --git a/packages/flutter/lib/rendering.dart b/packages/flutter/lib/rendering.dart index 5e6821616a..d37ea3cdb6 100644 --- a/packages/flutter/lib/rendering.dart +++ b/packages/flutter/lib/rendering.dart @@ -5,26 +5,26 @@ /// The Flutter rendering tree. library rendering; -export 'package:sky/src/rendering/auto_layout.dart'; -export 'package:sky/src/rendering/block.dart'; -export 'package:sky/src/rendering/box.dart'; -export 'package:sky/src/rendering/debug.dart'; -export 'package:sky/src/rendering/editable_paragraph.dart'; -export 'package:sky/src/rendering/error.dart'; -export 'package:sky/src/rendering/flex.dart'; -export 'package:sky/src/rendering/grid.dart'; -export 'package:sky/src/rendering/hit_test.dart'; -export 'package:sky/src/rendering/image.dart'; -export 'package:sky/src/rendering/layer.dart'; -export 'package:sky/src/rendering/node.dart'; -export 'package:sky/src/rendering/object.dart'; -export 'package:sky/src/rendering/paragraph.dart'; -export 'package:sky/src/rendering/proxy_box.dart'; -export 'package:sky/src/rendering/shifted_box.dart'; -export 'package:sky/src/rendering/binding.dart'; -export 'package:sky/src/rendering/stack.dart'; -export 'package:sky/src/rendering/toggleable.dart'; -export 'package:sky/src/rendering/view.dart'; -export 'package:sky/src/rendering/viewport.dart'; +export 'src/rendering/auto_layout.dart'; +export 'src/rendering/block.dart'; +export 'src/rendering/box.dart'; +export 'src/rendering/debug.dart'; +export 'src/rendering/editable_paragraph.dart'; +export 'src/rendering/error.dart'; +export 'src/rendering/flex.dart'; +export 'src/rendering/grid.dart'; +export 'src/rendering/hit_test.dart'; +export 'src/rendering/image.dart'; +export 'src/rendering/layer.dart'; +export 'src/rendering/node.dart'; +export 'src/rendering/object.dart'; +export 'src/rendering/paragraph.dart'; +export 'src/rendering/proxy_box.dart'; +export 'src/rendering/shifted_box.dart'; +export 'src/rendering/binding.dart'; +export 'src/rendering/stack.dart'; +export 'src/rendering/toggleable.dart'; +export 'src/rendering/view.dart'; +export 'src/rendering/viewport.dart'; export 'package:vector_math/vector_math_64.dart' show Matrix4; diff --git a/packages/flutter/lib/src/animation/animated_value.dart b/packages/flutter/lib/src/animation/animated_value.dart index 9b4a8daa1b..c237d39e64 100644 --- a/packages/flutter/lib/src/animation/animated_value.dart +++ b/packages/flutter/lib/src/animation/animated_value.dart @@ -4,7 +4,7 @@ import 'dart:sky' show Color, Rect; -import 'package:sky/src/animation/curves.dart'; +import 'curves.dart'; /// The direction in which an animation is running enum AnimationDirection { diff --git a/packages/flutter/lib/src/animation/performance.dart b/packages/flutter/lib/src/animation/performance.dart index 3a4125d8fa..0b8a020f17 100644 --- a/packages/flutter/lib/src/animation/performance.dart +++ b/packages/flutter/lib/src/animation/performance.dart @@ -4,9 +4,9 @@ import 'dart:async'; -import 'package:sky/src/animation/animated_value.dart'; -import 'package:sky/src/animation/forces.dart'; -import 'package:sky/src/animation/simulation_stepper.dart'; +import 'animated_value.dart'; +import 'forces.dart'; +import 'simulation_stepper.dart'; /// The status of an animation enum PerformanceStatus { diff --git a/packages/flutter/lib/src/animation/simulation_stepper.dart b/packages/flutter/lib/src/animation/simulation_stepper.dart index dee9cb0c73..843be0a062 100644 --- a/packages/flutter/lib/src/animation/simulation_stepper.dart +++ b/packages/flutter/lib/src/animation/simulation_stepper.dart @@ -5,9 +5,9 @@ import 'dart:async'; import 'package:newton/newton.dart'; -import 'package:sky/src/animation/animated_value.dart'; -import 'package:sky/src/animation/curves.dart'; -import 'package:sky/src/animation/ticker.dart'; +import 'animated_value.dart'; +import 'curves.dart'; +import 'ticker.dart'; /// A simulation that varies from [begin] to [end] over [duration] using [curve] /// diff --git a/packages/flutter/lib/src/animation/ticker.dart b/packages/flutter/lib/src/animation/ticker.dart index 6c0dd32eb0..d609a38144 100644 --- a/packages/flutter/lib/src/animation/ticker.dart +++ b/packages/flutter/lib/src/animation/ticker.dart @@ -4,7 +4,7 @@ import 'dart:async'; -import 'package:sky/src/animation/scheduler.dart'; +import 'scheduler.dart'; typedef TickerCallback(Duration elapsed); diff --git a/packages/flutter/lib/src/gestures/drag.dart b/packages/flutter/lib/src/gestures/drag.dart index 66a7ec6cf0..b93631c918 100644 --- a/packages/flutter/lib/src/gestures/drag.dart +++ b/packages/flutter/lib/src/gestures/drag.dart @@ -4,9 +4,9 @@ import 'dart:sky' as sky; -import 'package:sky/src/gestures/arena.dart'; -import 'package:sky/src/gestures/recognizer.dart'; -import 'package:sky/src/gestures/constants.dart'; +import 'arena.dart'; +import 'recognizer.dart'; +import 'constants.dart'; enum DragState { ready, diff --git a/packages/flutter/lib/src/gestures/long_press.dart b/packages/flutter/lib/src/gestures/long_press.dart index ec1945dea6..6e1114ead7 100644 --- a/packages/flutter/lib/src/gestures/long_press.dart +++ b/packages/flutter/lib/src/gestures/long_press.dart @@ -4,10 +4,10 @@ import 'dart:sky' as sky; -import 'package:sky/src/gestures/arena.dart'; -import 'package:sky/src/gestures/constants.dart'; -import 'package:sky/src/gestures/pointer_router.dart'; -import 'package:sky/src/gestures/recognizer.dart'; +import 'arena.dart'; +import 'constants.dart'; +import 'pointer_router.dart'; +import 'recognizer.dart'; typedef void GestureLongPressCallback(); diff --git a/packages/flutter/lib/src/gestures/recognizer.dart b/packages/flutter/lib/src/gestures/recognizer.dart index bdc081a16a..c36e4b162c 100644 --- a/packages/flutter/lib/src/gestures/recognizer.dart +++ b/packages/flutter/lib/src/gestures/recognizer.dart @@ -5,11 +5,11 @@ import 'dart:async'; import 'dart:sky' as sky; -import 'package:sky/src/gestures/arena.dart'; -import 'package:sky/src/gestures/constants.dart'; -import 'package:sky/src/gestures/pointer_router.dart'; +import 'arena.dart'; +import 'constants.dart'; +import 'pointer_router.dart'; -export 'package:sky/src/gestures/pointer_router.dart' show PointerRouter; +export 'pointer_router.dart' show PointerRouter; abstract class GestureRecognizer extends GestureArenaMember { GestureRecognizer({ PointerRouter router }) : _router = router { diff --git a/packages/flutter/lib/src/gestures/scale.dart b/packages/flutter/lib/src/gestures/scale.dart index 299322b3f7..6f318b688c 100644 --- a/packages/flutter/lib/src/gestures/scale.dart +++ b/packages/flutter/lib/src/gestures/scale.dart @@ -4,9 +4,9 @@ import 'dart:sky' as sky; -import 'package:sky/src/gestures/arena.dart'; -import 'package:sky/src/gestures/recognizer.dart'; -import 'package:sky/src/gestures/constants.dart'; +import 'arena.dart'; +import 'recognizer.dart'; +import 'constants.dart'; enum ScaleState { ready, diff --git a/packages/flutter/lib/src/gestures/show_press.dart b/packages/flutter/lib/src/gestures/show_press.dart index 299b6ae540..85f4ede078 100644 --- a/packages/flutter/lib/src/gestures/show_press.dart +++ b/packages/flutter/lib/src/gestures/show_press.dart @@ -4,9 +4,9 @@ import 'dart:sky' as sky; -import 'package:sky/src/gestures/arena.dart'; -import 'package:sky/src/gestures/constants.dart'; -import 'package:sky/src/gestures/recognizer.dart'; +import 'arena.dart'; +import 'constants.dart'; +import 'recognizer.dart'; typedef void GestureShowPressCallback(); diff --git a/packages/flutter/lib/src/gestures/tap.dart b/packages/flutter/lib/src/gestures/tap.dart index 092874c3da..65bb5bcf0f 100644 --- a/packages/flutter/lib/src/gestures/tap.dart +++ b/packages/flutter/lib/src/gestures/tap.dart @@ -4,8 +4,8 @@ import 'dart:sky' as sky; -import 'package:sky/src/gestures/arena.dart'; -import 'package:sky/src/gestures/recognizer.dart'; +import 'arena.dart'; +import 'recognizer.dart'; typedef void GestureTapCallback(); diff --git a/packages/flutter/lib/src/painting/box_painter.dart b/packages/flutter/lib/src/painting/box_painter.dart index 4fad437902..3e0d98fe5f 100644 --- a/packages/flutter/lib/src/painting/box_painter.dart +++ b/packages/flutter/lib/src/painting/box_painter.dart @@ -7,7 +7,8 @@ import 'dart:sky' as sky; import 'dart:sky' show Point, Offset, Size, Rect, Color, Paint, Path; import 'package:sky/services.dart'; -import 'package:sky/src/painting/shadows.dart'; + +import 'shadows.dart'; /// An immutable set of offsets in each of the four cardinal directions /// diff --git a/packages/flutter/lib/src/painting/text_painter.dart b/packages/flutter/lib/src/painting/text_painter.dart index bb4709e8ef..c51184d86e 100644 --- a/packages/flutter/lib/src/painting/text_painter.dart +++ b/packages/flutter/lib/src/painting/text_painter.dart @@ -4,9 +4,9 @@ import 'dart:sky' as sky; -import 'package:sky/src/painting/text_style.dart'; +import 'text_style.dart'; -export 'package:sky/src/painting/text_style.dart'; +export 'text_style.dart'; /// An immutable span of text abstract class TextSpan { diff --git a/packages/flutter/lib/src/rendering/auto_layout.dart b/packages/flutter/lib/src/rendering/auto_layout.dart index 150f7f4f7e..f394f558a3 100644 --- a/packages/flutter/lib/src/rendering/auto_layout.dart +++ b/packages/flutter/lib/src/rendering/auto_layout.dart @@ -3,8 +3,9 @@ // found in the LICENSE file. import 'package:cassowary/cassowary.dart' as al; -import 'package:sky/src/rendering/box.dart'; -import 'package:sky/src/rendering/object.dart'; + +import 'box.dart'; +import 'object.dart'; /// Hosts the edge parameters and vends useful methods to construct expressions /// for constraints. Also sets up and manages implicit constraints and edit diff --git a/packages/flutter/lib/src/rendering/binding.dart b/packages/flutter/lib/src/rendering/binding.dart index bf9e31ad12..2771cfd4b2 100644 --- a/packages/flutter/lib/src/rendering/binding.dart +++ b/packages/flutter/lib/src/rendering/binding.dart @@ -6,10 +6,11 @@ import 'dart:sky' as sky; import 'package:sky/animation.dart'; import 'package:sky/gestures.dart'; -import 'package:sky/src/rendering/box.dart'; -import 'package:sky/src/rendering/hit_test.dart'; -import 'package:sky/src/rendering/object.dart'; -import 'package:sky/src/rendering/view.dart'; + +import 'box.dart'; +import 'hit_test.dart'; +import 'object.dart'; +import 'view.dart'; int _hammingWeight(int value) { if (value == 0) diff --git a/packages/flutter/lib/src/rendering/block.dart b/packages/flutter/lib/src/rendering/block.dart index 395be74aa1..1d3ba27751 100644 --- a/packages/flutter/lib/src/rendering/block.dart +++ b/packages/flutter/lib/src/rendering/block.dart @@ -4,10 +4,11 @@ import 'dart:math' as math; -import 'package:sky/src/rendering/box.dart'; -import 'package:sky/src/rendering/object.dart'; import 'package:vector_math/vector_math_64.dart'; +import 'box.dart'; +import 'object.dart'; + /// Parent data for use with [RenderBlockBase] class BlockParentData extends BoxParentData with ContainerParentDataMixin { } diff --git a/packages/flutter/lib/src/rendering/box.dart b/packages/flutter/lib/src/rendering/box.dart index 5bf22b3437..33a5b4ae23 100644 --- a/packages/flutter/lib/src/rendering/box.dart +++ b/packages/flutter/lib/src/rendering/box.dart @@ -6,10 +6,11 @@ import 'dart:math' as math; import 'dart:sky' as sky; import 'package:sky/painting.dart'; -import 'package:sky/src/rendering/debug.dart'; -import 'package:sky/src/rendering/object.dart'; import 'package:vector_math/vector_math_64.dart'; +import 'debug.dart'; +import 'object.dart'; + export 'package:sky/painting.dart' show TextBaseline; // This class should only be used in debug builds diff --git a/packages/flutter/lib/src/rendering/editable_paragraph.dart b/packages/flutter/lib/src/rendering/editable_paragraph.dart index f25dcdfdcb..95b0886772 100644 --- a/packages/flutter/lib/src/rendering/editable_paragraph.dart +++ b/packages/flutter/lib/src/rendering/editable_paragraph.dart @@ -3,10 +3,11 @@ // found in the LICENSE file. import 'package:sky/painting.dart'; -import 'package:sky/src/rendering/box.dart'; -import 'package:sky/src/rendering/object.dart'; -import 'package:sky/src/rendering/paragraph.dart'; -import 'package:sky/src/rendering/proxy_box.dart' show SizeChangedCallback; + +import 'box.dart'; +import 'object.dart'; +import 'paragraph.dart'; +import 'proxy_box.dart' show SizeChangedCallback; const _kCursorGap = 1.0; // pixels const _kCursorHeightOffset = 2.0; // pixels diff --git a/packages/flutter/lib/src/rendering/error.dart b/packages/flutter/lib/src/rendering/error.dart index 7bd1abe988..01a72d040e 100644 --- a/packages/flutter/lib/src/rendering/error.dart +++ b/packages/flutter/lib/src/rendering/error.dart @@ -2,9 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:sky/src/rendering/box.dart'; -import 'package:sky/src/rendering/debug.dart'; -import 'package:sky/src/rendering/object.dart'; +import 'box.dart'; +import 'debug.dart'; +import 'object.dart'; const double _kMaxWidth = 100000.0; const double _kMaxHeight = 100000.0; diff --git a/packages/flutter/lib/src/rendering/flex.dart b/packages/flutter/lib/src/rendering/flex.dart index e6a8d6d711..611841c39e 100644 --- a/packages/flutter/lib/src/rendering/flex.dart +++ b/packages/flutter/lib/src/rendering/flex.dart @@ -4,8 +4,8 @@ import 'dart:math' as math; -import 'package:sky/src/rendering/box.dart'; -import 'package:sky/src/rendering/object.dart'; +import 'box.dart'; +import 'object.dart'; /// Parent data for use with [RenderFlex] class FlexParentData extends BoxParentData with ContainerParentDataMixin { diff --git a/packages/flutter/lib/src/rendering/grid.dart b/packages/flutter/lib/src/rendering/grid.dart index b07eca7a3d..fe7cc07747 100644 --- a/packages/flutter/lib/src/rendering/grid.dart +++ b/packages/flutter/lib/src/rendering/grid.dart @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:sky/src/rendering/box.dart'; -import 'package:sky/src/rendering/object.dart'; +import 'box.dart'; +import 'object.dart'; class _GridMetrics { // Grid is width-in, height-out. We fill the max width and adjust height diff --git a/packages/flutter/lib/src/rendering/image.dart b/packages/flutter/lib/src/rendering/image.dart index 9b96467877..656b5f28fd 100644 --- a/packages/flutter/lib/src/rendering/image.dart +++ b/packages/flutter/lib/src/rendering/image.dart @@ -5,8 +5,9 @@ import 'dart:sky' as sky; import 'package:sky/painting.dart'; -import 'package:sky/src/rendering/object.dart'; -import 'package:sky/src/rendering/box.dart'; + +import 'box.dart'; +import 'object.dart'; /// An image in the render tree /// diff --git a/packages/flutter/lib/src/rendering/object.dart b/packages/flutter/lib/src/rendering/object.dart index f887c11cb6..4bedb368f7 100644 --- a/packages/flutter/lib/src/rendering/object.dart +++ b/packages/flutter/lib/src/rendering/object.dart @@ -7,14 +7,15 @@ import 'dart:sky' as sky; import 'dart:sky' show Point, Offset, Size, Rect, Color, Paint, Path; import 'package:sky/animation.dart'; -import 'package:sky/src/rendering/debug.dart'; -import 'package:sky/src/rendering/hit_test.dart'; -import 'package:sky/src/rendering/layer.dart'; -import 'package:sky/src/rendering/node.dart'; import 'package:vector_math/vector_math_64.dart'; +import 'debug.dart'; +import 'hit_test.dart'; +import 'layer.dart'; +import 'node.dart'; + export 'dart:sky' show Point, Offset, Size, Rect, Color, Paint, Path; -export 'package:sky/src/rendering/hit_test.dart' show HitTestTarget, HitTestEntry, HitTestResult; +export 'hit_test.dart' show HitTestTarget, HitTestEntry, HitTestResult; typedef sky.Shader ShaderCallback(Rect bounds); diff --git a/packages/flutter/lib/src/rendering/paragraph.dart b/packages/flutter/lib/src/rendering/paragraph.dart index 1bc509154b..2abd06904e 100644 --- a/packages/flutter/lib/src/rendering/paragraph.dart +++ b/packages/flutter/lib/src/rendering/paragraph.dart @@ -2,9 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:sky/src/painting/text_painter.dart'; -import 'package:sky/src/rendering/box.dart'; -import 'package:sky/src/rendering/object.dart'; +import 'package:sky/painting.dart'; + +import 'box.dart'; +import 'object.dart'; export 'package:sky/src/painting/text_painter.dart'; diff --git a/packages/flutter/lib/src/rendering/proxy_box.dart b/packages/flutter/lib/src/rendering/proxy_box.dart index 1f9a7e3353..9c22ef6ef5 100644 --- a/packages/flutter/lib/src/rendering/proxy_box.dart +++ b/packages/flutter/lib/src/rendering/proxy_box.dart @@ -4,12 +4,12 @@ import 'dart:sky' as sky; -import 'package:sky/src/painting/box_painter.dart'; -import 'package:sky/src/painting/text_style.dart'; -import 'package:sky/src/rendering/object.dart'; -import 'package:sky/src/rendering/box.dart'; +import 'package:sky/painting.dart'; import 'package:vector_math/vector_math_64.dart'; +import 'box.dart'; +import 'object.dart'; + export 'package:sky/src/painting/box_painter.dart'; /// A base class for render objects that resemble their children diff --git a/packages/flutter/lib/src/rendering/shifted_box.dart b/packages/flutter/lib/src/rendering/shifted_box.dart index 26458e8baa..e15675342e 100644 --- a/packages/flutter/lib/src/rendering/shifted_box.dart +++ b/packages/flutter/lib/src/rendering/shifted_box.dart @@ -3,8 +3,9 @@ // found in the LICENSE file. import 'package:sky/painting.dart'; -import 'package:sky/src/rendering/object.dart'; -import 'package:sky/src/rendering/box.dart'; + +import 'box.dart'; +import 'object.dart'; abstract class RenderShiftedBox extends RenderBox with RenderObjectWithChildMixin { diff --git a/packages/flutter/lib/src/rendering/stack.dart b/packages/flutter/lib/src/rendering/stack.dart index b884d2d876..7d075f88b9 100644 --- a/packages/flutter/lib/src/rendering/stack.dart +++ b/packages/flutter/lib/src/rendering/stack.dart @@ -4,8 +4,8 @@ import 'dart:math' as math; -import 'package:sky/src/rendering/box.dart'; -import 'package:sky/src/rendering/object.dart'; +import 'box.dart'; +import 'object.dart'; /// Parent data for use with [RenderStack] class StackParentData extends BoxParentData with ContainerParentDataMixin { diff --git a/packages/flutter/lib/src/rendering/statistics_box.dart b/packages/flutter/lib/src/rendering/statistics_box.dart index e4235c7bbb..dd7bbb0445 100644 --- a/packages/flutter/lib/src/rendering/statistics_box.dart +++ b/packages/flutter/lib/src/rendering/statistics_box.dart @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:sky/src/rendering/box.dart'; -import 'package:sky/src/rendering/object.dart'; +import 'box.dart'; +import 'object.dart'; class StatisticsBox extends RenderBox { diff --git a/packages/flutter/lib/src/rendering/toggleable.dart b/packages/flutter/lib/src/rendering/toggleable.dart index bd98d27cdb..71b83b15f0 100644 --- a/packages/flutter/lib/src/rendering/toggleable.dart +++ b/packages/flutter/lib/src/rendering/toggleable.dart @@ -6,10 +6,11 @@ import 'dart:sky' as sky; import 'package:sky/animation.dart'; import 'package:sky/gestures.dart'; -import 'package:sky/src/rendering/binding.dart'; -import 'package:sky/src/rendering/box.dart'; -import 'package:sky/src/rendering/object.dart'; -import 'package:sky/src/rendering/proxy_box.dart'; + +import 'binding.dart'; +import 'box.dart'; +import 'object.dart'; +import 'proxy_box.dart'; typedef void ValueChanged(bool value); diff --git a/packages/flutter/lib/src/rendering/view.dart b/packages/flutter/lib/src/rendering/view.dart index 74ad261a9f..bc1a5116b0 100644 --- a/packages/flutter/lib/src/rendering/view.dart +++ b/packages/flutter/lib/src/rendering/view.dart @@ -5,11 +5,12 @@ import 'dart:sky' as sky; import 'package:sky/animation.dart'; -import 'package:sky/src/rendering/layer.dart'; -import 'package:sky/src/rendering/object.dart'; -import 'package:sky/src/rendering/box.dart'; import 'package:vector_math/vector_math_64.dart'; +import 'box.dart'; +import 'layer.dart'; +import 'object.dart'; + /// The layout constraints for the root render object class ViewConstraints { const ViewConstraints({ diff --git a/packages/flutter/lib/src/rendering/viewport.dart b/packages/flutter/lib/src/rendering/viewport.dart index 9814e3ebe1..7c0dece986 100644 --- a/packages/flutter/lib/src/rendering/viewport.dart +++ b/packages/flutter/lib/src/rendering/viewport.dart @@ -4,10 +4,11 @@ import 'dart:sky' as sky; -import 'package:sky/src/rendering/object.dart'; -import 'package:sky/src/rendering/box.dart'; import 'package:vector_math/vector_math_64.dart'; +import 'box.dart'; +import 'object.dart'; + /// The direction in which to scroll enum ScrollDirection { /// Scroll left and right diff --git a/packages/flutter/lib/src/services/activity.dart b/packages/flutter/lib/src/services/activity.dart index f8b73ee7a0..c5374b8b40 100644 --- a/packages/flutter/lib/src/services/activity.dart +++ b/packages/flutter/lib/src/services/activity.dart @@ -5,9 +5,10 @@ import 'dart:sky'; import 'dart:async'; -import 'package:sky/src/services/shell.dart'; import 'package:sky_services/activity/activity.mojom.dart'; +import 'shell.dart'; + export 'package:sky_services/activity/activity.mojom.dart'; /// Dart wrapper around Activity mojo service available in Sky on Android. diff --git a/packages/flutter/lib/src/services/asset_bundle.dart b/packages/flutter/lib/src/services/asset_bundle.dart index 0ecfa008bb..8294128776 100644 --- a/packages/flutter/lib/src/services/asset_bundle.dart +++ b/packages/flutter/lib/src/services/asset_bundle.dart @@ -9,11 +9,12 @@ import 'dart:typed_data'; import 'package:mojo/core.dart' as core; import 'package:mojo_services/mojo/asset_bundle/asset_bundle.mojom.dart'; -import 'package:sky/src/services/fetch.dart'; -import 'package:sky/src/services/image_cache.dart'; -import 'package:sky/src/services/image_decoder.dart'; -import 'package:sky/src/services/image_resource.dart'; -import 'package:sky/src/services/shell.dart'; + +import 'fetch.dart'; +import 'image_cache.dart'; +import 'image_decoder.dart'; +import 'image_resource.dart'; +import 'shell.dart'; abstract class AssetBundle { void close(); diff --git a/packages/flutter/lib/src/services/fetch.dart b/packages/flutter/lib/src/services/fetch.dart index c6ce40c643..da2ae34517 100644 --- a/packages/flutter/lib/src/services/fetch.dart +++ b/packages/flutter/lib/src/services/fetch.dart @@ -10,7 +10,8 @@ import 'package:mojo/mojo/url_request.mojom.dart'; import 'package:mojo/mojo/url_response.mojom.dart'; import 'package:mojo_services/mojo/network_service.mojom.dart'; import 'package:mojo_services/mojo/url_loader.mojom.dart'; -import 'package:sky/src/services/shell.dart'; + +import 'shell.dart'; export 'package:mojo/mojo/url_response.mojom.dart' show UrlResponse; diff --git a/packages/flutter/lib/src/services/image_cache.dart b/packages/flutter/lib/src/services/image_cache.dart index 81b3d3f730..52788a854b 100644 --- a/packages/flutter/lib/src/services/image_cache.dart +++ b/packages/flutter/lib/src/services/image_cache.dart @@ -7,9 +7,10 @@ import 'dart:collection'; import 'dart:sky' as sky; import 'package:mojo/mojo/url_response.mojom.dart'; -import 'package:sky/src/services/fetch.dart'; -import 'package:sky/src/services/image_decoder.dart'; -import 'package:sky/src/services/image_resource.dart'; + +import 'fetch.dart'; +import 'image_decoder.dart'; +import 'image_resource.dart'; Future _fetchImage(String url) async { UrlResponse response = await fetchUrl(url); diff --git a/packages/flutter/lib/src/services/keyboard.dart b/packages/flutter/lib/src/services/keyboard.dart index d5bcd97014..81cd017b32 100644 --- a/packages/flutter/lib/src/services/keyboard.dart +++ b/packages/flutter/lib/src/services/keyboard.dart @@ -3,7 +3,8 @@ // found in the LICENSE file. import 'package:mojo_services/keyboard/keyboard.mojom.dart'; -import 'package:sky/src/services/shell.dart'; + +import 'shell.dart'; export 'package:mojo_services/keyboard/keyboard.mojom.dart'; diff --git a/packages/flutter/lib/src/services/shell.dart b/packages/flutter/lib/src/services/shell.dart index 3f3f4112df..679f3c3e40 100644 --- a/packages/flutter/lib/src/services/shell.dart +++ b/packages/flutter/lib/src/services/shell.dart @@ -7,7 +7,8 @@ import 'dart:sky.internals' as internals; import 'package:mojo/application.dart'; import 'package:mojo/core.dart' as core; import 'package:mojo/mojo/service_provider.mojom.dart'; -import 'package:sky/src/services/embedder.dart'; + +import 'embedder.dart'; ApplicationConnection _initConnection() { int rawHandle = internals.takeServicesProvidedByEmbedder(); From cc809491baae03ac9fc6278d7017fc54c7d044b5 Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Fri, 9 Oct 2015 10:03:40 -0700 Subject: [PATCH 26/84] Split material design widgets out of widgets.dart These are now part of material.dart. --- examples/address_book/lib/main.dart | 1 - examples/demo_launcher/lib/main.dart | 1 - examples/fitness/lib/main.dart | 1 - examples/game/lib/main.dart | 1 - examples/mine_digger/lib/main.dart | 1 - examples/stocks/lib/main.dart | 1 - examples/widgets/big_switch.dart | 1 - examples/widgets/card_collection.dart | 1 - examples/widgets/container.dart | 2 +- examples/widgets/date_picker.dart | 1 - examples/widgets/drag_and_drop.dart | 1 - examples/widgets/ensure_visible.dart | 1 - examples/widgets/indexed_stack.dart | 1 - examples/widgets/navigation.dart | 1 - examples/widgets/overlay_geometry.dart | 1 - examples/widgets/pageable_list.dart | 1 - examples/widgets/piano.dart | 1 - examples/widgets/progress_indicator.dart | 1 - examples/widgets/scale.dart | 1 - examples/widgets/sector.dart | 2 +- examples/widgets/spinning_mixed.dart | 2 +- examples/widgets/styled_text.dart | 1 - examples/widgets/tabs.dart | 1 - packages/flutter/lib/material.dart | 39 +++++++++++++++++-- .../lib/src/{widgets => material}/app.dart | 10 ++--- .../lib/src/{widgets => material}/card.dart | 6 +-- .../src/{widgets => material}/checkbox.dart | 11 +++--- .../{widgets => material}/date_picker.dart | 10 ++--- .../lib/src/{widgets => material}/dialog.dart | 15 +++---- .../lib/src/{widgets => material}/drawer.dart | 11 ++---- .../{widgets => material}/drawer_divider.dart | 6 +-- .../{widgets => material}/drawer_header.dart | 6 +-- .../{widgets => material}/drawer_item.dart | 10 ++--- .../{widgets => material}/flat_button.dart | 8 ++-- .../floating_action_button.dart | 12 +++--- .../lib/src/{widgets => material}/icon.dart | 6 +-- .../{widgets => material}/icon_button.dart | 7 ++-- .../src/{widgets => material}/ink_well.dart | 3 +- .../lib/src/{widgets => material}/input.dart | 9 ++--- .../src/{widgets => material}/material.dart | 7 ++-- .../material_button.dart | 10 ++--- .../src/{widgets => material}/popup_menu.dart | 14 +++---- .../popup_menu_item.dart | 6 +-- .../progress_indicator.dart | 7 ++-- .../lib/src/{widgets => material}/radio.dart | 7 ++-- .../{widgets => material}/raised_button.dart | 8 ++-- .../src/{widgets => material}/scaffold.dart | 3 +- .../src/{widgets => material}/snack_bar.dart | 12 ++---- .../lib/src/{widgets => material}/switch.dart | 6 +-- .../lib/src/{widgets => material}/tabs.dart | 17 ++++---- .../lib/src/{widgets => material}/theme.dart | 7 ++-- .../lib/src/{widgets => material}/title.dart | 5 ++- .../src/{widgets => material}/tool_bar.dart | 9 ++--- .../lib/src/widgets/animated_container.dart | 5 ++- packages/flutter/lib/src/widgets/basic.dart | 3 +- packages/flutter/lib/src/widgets/binding.dart | 3 +- .../flutter/lib/src/widgets/dismissable.dart | 9 +++-- .../flutter/lib/src/widgets/drag_target.dart | 9 +++-- .../lib/src/widgets/editable_text.dart | 5 ++- packages/flutter/lib/src/widgets/focus.dart | 2 +- .../lib/src/widgets/gesture_detector.dart | 7 ++-- packages/flutter/lib/src/widgets/mimic.dart | 5 ++- .../lib/src/widgets/mixed_viewport.dart | 5 ++- .../flutter/lib/src/widgets/navigator.dart | 9 +++-- .../flutter/lib/src/widgets/placeholder.dart | 4 +- .../flutter/lib/src/widgets/scrollable.dart | 11 +++--- .../lib/src/widgets/statistics_overlay.dart | 3 +- .../flutter/lib/src/widgets/transitions.dart | 5 ++- .../lib/src/widgets/unique_component.dart | 2 +- packages/flutter/lib/widgets.dart | 29 -------------- .../unit/test/widget/date_picker_test.dart | 2 +- packages/unit/test/widget/drawer_test.dart | 1 + packages/unit/test/widget/input_test.dart | 2 +- .../test/widget/progress_indicator_test.dart | 2 +- packages/unit/test/widget/snack_bar_test.dart | 2 +- 75 files changed, 201 insertions(+), 237 deletions(-) rename packages/flutter/lib/src/{widgets => material}/app.dart (89%) rename packages/flutter/lib/src/{widgets => material}/card.dart (83%) rename packages/flutter/lib/src/{widgets => material}/checkbox.dart (95%) rename packages/flutter/lib/src/{widgets => material}/date_picker.dart (97%) rename packages/flutter/lib/src/{widgets => material}/dialog.dart (90%) rename packages/flutter/lib/src/{widgets => material}/drawer.dart (92%) rename packages/flutter/lib/src/{widgets => material}/drawer_divider.dart (81%) rename packages/flutter/lib/src/{widgets => material}/drawer_header.dart (89%) rename packages/flutter/lib/src/{widgets => material}/drawer_item.dart (91%) rename packages/flutter/lib/src/{widgets => material}/flat_button.dart (84%) rename packages/flutter/lib/src/{widgets => material}/floating_action_button.dart (87%) rename packages/flutter/lib/src/{widgets => material}/icon.dart (95%) rename packages/flutter/lib/src/{widgets => material}/icon_button.dart (81%) rename packages/flutter/lib/src/{widgets => material}/ink_well.dart (98%) rename packages/flutter/lib/src/{widgets => material}/input.dart (94%) rename packages/flutter/lib/src/{widgets => material}/material.dart (91%) rename packages/flutter/lib/src/{widgets => material}/material_button.dart (92%) rename packages/flutter/lib/src/{widgets => material}/popup_menu.dart (92%) rename packages/flutter/lib/src/{widgets => material}/popup_menu_item.dart (84%) rename packages/flutter/lib/src/{widgets => material}/progress_indicator.dart (96%) rename packages/flutter/lib/src/{widgets => material}/radio.dart (90%) rename packages/flutter/lib/src/{widgets => material}/raised_button.dart (89%) rename packages/flutter/lib/src/{widgets => material}/scaffold.dart (96%) rename packages/flutter/lib/src/{widgets => material}/snack_bar.dart (89%) rename packages/flutter/lib/src/{widgets => material}/switch.dart (97%) rename packages/flutter/lib/src/{widgets => material}/tabs.dart (97%) rename packages/flutter/lib/src/{widgets => material}/theme.dart (81%) rename packages/flutter/lib/src/{widgets => material}/title.dart (82%) rename packages/flutter/lib/src/{widgets => material}/tool_bar.dart (90%) diff --git a/examples/address_book/lib/main.dart b/examples/address_book/lib/main.dart index 0c66e80f3e..fb10eccbcc 100644 --- a/examples/address_book/lib/main.dart +++ b/examples/address_book/lib/main.dart @@ -3,7 +3,6 @@ // found in the LICENSE file. import 'package:sky/material.dart'; -import 'package:sky/widgets.dart'; class Field extends StatelessComponent { Field({ diff --git a/examples/demo_launcher/lib/main.dart b/examples/demo_launcher/lib/main.dart index 5f466f4002..dd4bf62a3c 100644 --- a/examples/demo_launcher/lib/main.dart +++ b/examples/demo_launcher/lib/main.dart @@ -5,7 +5,6 @@ import 'package:sky/material.dart'; import 'package:sky/painting.dart'; import 'package:sky/services.dart'; -import 'package:sky/widgets.dart'; AssetBundle _initBundle() { if (rootBundle != null) diff --git a/examples/fitness/lib/main.dart b/examples/fitness/lib/main.dart index ecc10820b5..c747be646d 100644 --- a/examples/fitness/lib/main.dart +++ b/examples/fitness/lib/main.dart @@ -7,7 +7,6 @@ library fitness; import 'package:playfair/playfair.dart' as playfair; import 'package:sky/material.dart'; import 'package:sky/painting.dart'; -import 'package:sky/widgets.dart'; import 'user_data.dart'; import 'date_utils.dart'; diff --git a/examples/game/lib/main.dart b/examples/game/lib/main.dart index c8cf7417cb..9150ab95fc 100644 --- a/examples/game/lib/main.dart +++ b/examples/game/lib/main.dart @@ -8,7 +8,6 @@ import 'package:sky/material.dart'; import 'package:sky/painting.dart'; import 'package:sky/rendering.dart'; import 'package:sky/services.dart'; -import 'package:sky/widgets.dart'; import 'package:skysprites/skysprites.dart'; import 'game_demo.dart'; diff --git a/examples/mine_digger/lib/main.dart b/examples/mine_digger/lib/main.dart index 112d5a3b80..095b010f09 100644 --- a/examples/mine_digger/lib/main.dart +++ b/examples/mine_digger/lib/main.dart @@ -8,7 +8,6 @@ import 'package:sky/material.dart'; import 'package:sky/painting.dart'; import 'package:sky/rendering.dart'; import 'package:sky/services.dart'; -import 'package:sky/widgets.dart'; // Classic minesweeper-inspired game. The mouse controls are standard // except for left + right combo which is not implemented. For touch, diff --git a/examples/stocks/lib/main.dart b/examples/stocks/lib/main.dart index 61c8d62a4e..1a4679006e 100644 --- a/examples/stocks/lib/main.dart +++ b/examples/stocks/lib/main.dart @@ -11,7 +11,6 @@ import 'dart:sky' as sky; import 'package:sky/gestures.dart'; import 'package:sky/material.dart'; import 'package:sky/painting.dart'; -import 'package:sky/widgets.dart'; import 'stock_data.dart'; diff --git a/examples/widgets/big_switch.dart b/examples/widgets/big_switch.dart index 991ab70b5f..cd812fac33 100644 --- a/examples/widgets/big_switch.dart +++ b/examples/widgets/big_switch.dart @@ -3,7 +3,6 @@ // found in the LICENSE file. import 'package:sky/material.dart'; -import 'package:sky/widgets.dart'; class BigSwitch extends StatefulComponent { BigSwitch({ this.scale }); diff --git a/examples/widgets/card_collection.dart b/examples/widgets/card_collection.dart index ce7ac66ee6..7896c6809a 100644 --- a/examples/widgets/card_collection.dart +++ b/examples/widgets/card_collection.dart @@ -6,7 +6,6 @@ import 'dart:sky' as sky; import 'package:sky/material.dart'; import 'package:sky/painting.dart'; -import 'package:sky/widgets.dart'; class CardModel { CardModel(this.value, this.height) { diff --git a/examples/widgets/container.dart b/examples/widgets/container.dart index fbcd0e16ce..5a4b929753 100644 --- a/examples/widgets/container.dart +++ b/examples/widgets/container.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:sky/widgets.dart'; +import 'package:sky/material.dart'; class ContainerApp extends StatelessComponent { Widget build(BuildContext context) { diff --git a/examples/widgets/date_picker.dart b/examples/widgets/date_picker.dart index 48d8e30313..845af140f6 100644 --- a/examples/widgets/date_picker.dart +++ b/examples/widgets/date_picker.dart @@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:sky/widgets.dart'; import 'package:sky/material.dart'; void main() => runApp(new DatePickerDemo()); diff --git a/examples/widgets/drag_and_drop.dart b/examples/widgets/drag_and_drop.dart index 8a7829dc79..a7c5ff63d7 100644 --- a/examples/widgets/drag_and_drop.dart +++ b/examples/widgets/drag_and_drop.dart @@ -5,7 +5,6 @@ import 'package:sky/material.dart'; import 'package:sky/painting.dart'; import 'package:sky/rendering.dart'; -import 'package:sky/widgets.dart'; class DragData { DragData(this.text); diff --git a/examples/widgets/ensure_visible.dart b/examples/widgets/ensure_visible.dart index ddd1891953..d59e0d6cea 100644 --- a/examples/widgets/ensure_visible.dart +++ b/examples/widgets/ensure_visible.dart @@ -3,7 +3,6 @@ // found in the LICENSE file. import 'package:sky/material.dart'; -import 'package:sky/widgets.dart'; class CardModel { CardModel(this.value, this.height, this.color); diff --git a/examples/widgets/indexed_stack.dart b/examples/widgets/indexed_stack.dart index 1833412763..e7a5e4952b 100644 --- a/examples/widgets/indexed_stack.dart +++ b/examples/widgets/indexed_stack.dart @@ -4,7 +4,6 @@ import 'package:sky/material.dart'; import 'package:sky/rendering.dart'; -import 'package:sky/widgets.dart'; class IndexedStackDemo extends StatefulComponent { IndexedStackDemo({ this.navigator }); diff --git a/examples/widgets/navigation.dart b/examples/widgets/navigation.dart index 7ade991408..1e76049291 100644 --- a/examples/widgets/navigation.dart +++ b/examples/widgets/navigation.dart @@ -3,7 +3,6 @@ // found in the LICENSE file. import 'package:sky/material.dart'; -import 'package:sky/widgets.dart'; final Map routes = { '/': (RouteArguments args) => new Container( diff --git a/examples/widgets/overlay_geometry.dart b/examples/widgets/overlay_geometry.dart index cdbc56d253..34be772d52 100644 --- a/examples/widgets/overlay_geometry.dart +++ b/examples/widgets/overlay_geometry.dart @@ -6,7 +6,6 @@ import 'dart:sky' as sky; import 'package:sky/material.dart'; import 'package:sky/rendering.dart'; -import 'package:sky/widgets.dart'; class CardModel { CardModel(this.value, this.height, this.color); diff --git a/examples/widgets/pageable_list.dart b/examples/widgets/pageable_list.dart index 4ad845dc22..f51083e801 100644 --- a/examples/widgets/pageable_list.dart +++ b/examples/widgets/pageable_list.dart @@ -4,7 +4,6 @@ import 'package:sky/material.dart'; import 'package:sky/painting.dart'; -import 'package:sky/widgets.dart'; class CardModel { CardModel(this.value, this.size, this.color); diff --git a/examples/widgets/piano.dart b/examples/widgets/piano.dart index 98a942c258..14845b0e2a 100644 --- a/examples/widgets/piano.dart +++ b/examples/widgets/piano.dart @@ -7,7 +7,6 @@ import 'package:sky_services/media/media.mojom.dart'; import 'package:sky/material.dart'; import 'package:sky/rendering.dart'; import 'package:sky/services.dart'; -import 'package:sky/widgets.dart'; // All of these sounds are marked as public domain at soundbible. const String chimes = "http://soundbible.com/grab.php?id=2030&type=wav"; diff --git a/examples/widgets/progress_indicator.dart b/examples/widgets/progress_indicator.dart index a83de62df1..511f2484df 100644 --- a/examples/widgets/progress_indicator.dart +++ b/examples/widgets/progress_indicator.dart @@ -4,7 +4,6 @@ import 'package:sky/animation.dart'; import 'package:sky/material.dart'; -import 'package:sky/widgets.dart'; class ProgressIndicatorApp extends StatefulComponent { ProgressIndicatorAppState createState() => new ProgressIndicatorAppState(); diff --git a/examples/widgets/scale.dart b/examples/widgets/scale.dart index 626547010d..ecd4c8d41f 100644 --- a/examples/widgets/scale.dart +++ b/examples/widgets/scale.dart @@ -4,7 +4,6 @@ import 'package:sky/material.dart'; import 'package:sky/rendering.dart'; -import 'package:sky/widgets.dart'; class ScaleApp extends StatefulComponent { ScaleAppState createState() => new ScaleAppState(); diff --git a/examples/widgets/sector.dart b/examples/widgets/sector.dart index d32d39944a..c87d87c1a2 100644 --- a/examples/widgets/sector.dart +++ b/examples/widgets/sector.dart @@ -4,8 +4,8 @@ import 'dart:math' as math; +import 'package:sky/material.dart'; import 'package:sky/rendering.dart'; -import 'package:sky/widgets.dart'; import '../rendering/sector_layout.dart'; diff --git a/examples/widgets/spinning_mixed.dart b/examples/widgets/spinning_mixed.dart index f44b0e0acd..eefb71fc26 100644 --- a/examples/widgets/spinning_mixed.dart +++ b/examples/widgets/spinning_mixed.dart @@ -5,8 +5,8 @@ import 'dart:sky' as sky; import 'package:sky/animation.dart'; +import 'package:sky/material.dart'; import 'package:sky/rendering.dart'; -import 'package:sky/widgets.dart'; import '../rendering/solid_color_box.dart'; diff --git a/examples/widgets/styled_text.dart b/examples/widgets/styled_text.dart index a21da29b11..1764acd227 100644 --- a/examples/widgets/styled_text.dart +++ b/examples/widgets/styled_text.dart @@ -4,7 +4,6 @@ import 'package:sky/material.dart'; import 'package:sky/rendering.dart'; -import 'package:sky/widgets.dart'; class StyledTextApp extends StatefulComponent { StyledTextAppState createState() => new StyledTextAppState(); diff --git a/examples/widgets/tabs.dart b/examples/widgets/tabs.dart index 540b3327f9..cec0e7aa53 100644 --- a/examples/widgets/tabs.dart +++ b/examples/widgets/tabs.dart @@ -4,7 +4,6 @@ import 'package:sky/material.dart'; import 'package:sky/painting.dart'; -import 'package:sky/widgets.dart'; class TabbedNavigatorApp extends StatefulComponent { TabbedNavigatorAppState createState() => new TabbedNavigatorAppState(); diff --git a/packages/flutter/lib/material.dart b/packages/flutter/lib/material.dart index 0d69716374..69cabb7288 100644 --- a/packages/flutter/lib/material.dart +++ b/packages/flutter/lib/material.dart @@ -7,9 +7,40 @@ /// See https://www.google.com/design/spec/material-design/introduction.html library material; +export 'src/material/app.dart'; +export 'src/material/card.dart'; +export 'src/material/checkbox.dart'; export 'src/material/colors.dart'; -export 'src/material/edges.dart'; -export 'src/material/shadows.dart'; -export 'src/material/theme_data.dart'; -export 'src/material/typography.dart'; export 'src/material/constants.dart'; +export 'src/material/date_picker.dart'; +export 'src/material/dialog.dart'; +export 'src/material/drawer.dart'; +export 'src/material/drawer_divider.dart'; +export 'src/material/drawer_header.dart'; +export 'src/material/drawer_item.dart'; +export 'src/material/edges.dart'; +export 'src/material/flat_button.dart'; +export 'src/material/floating_action_button.dart'; +export 'src/material/icon_button.dart'; +export 'src/material/icon.dart'; +export 'src/material/ink_well.dart'; +export 'src/material/input.dart'; +export 'src/material/material_button.dart'; +export 'src/material/material.dart'; +export 'src/material/popup_menu.dart'; +export 'src/material/popup_menu_item.dart'; +export 'src/material/progress_indicator.dart'; +export 'src/material/radio.dart'; +export 'src/material/raised_button.dart'; +export 'src/material/scaffold.dart'; +export 'src/material/shadows.dart'; +export 'src/material/snack_bar.dart'; +export 'src/material/switch.dart'; +export 'src/material/tabs.dart'; +export 'src/material/theme.dart'; +export 'src/material/theme_data.dart'; +export 'src/material/title.dart'; +export 'src/material/tool_bar.dart'; +export 'src/material/typography.dart'; + +export 'widgets.dart'; diff --git a/packages/flutter/lib/src/widgets/app.dart b/packages/flutter/lib/src/material/app.dart similarity index 89% rename from packages/flutter/lib/src/widgets/app.dart rename to packages/flutter/lib/src/material/app.dart index c38da71607..e73eab17bd 100644 --- a/packages/flutter/lib/src/widgets/app.dart +++ b/packages/flutter/lib/src/material/app.dart @@ -7,12 +7,10 @@ import 'dart:sky' as sky; import 'package:sky/material.dart'; import 'package:sky/painting.dart'; import 'package:sky/services.dart'; -import 'package:sky/src/widgets/basic.dart'; -import 'package:sky/src/widgets/binding.dart'; -import 'package:sky/src/widgets/framework.dart'; -import 'package:sky/src/widgets/navigator.dart'; -import 'package:sky/src/widgets/theme.dart'; -import 'package:sky/src/widgets/title.dart'; +import 'package:sky/widgets.dart'; + +import 'theme.dart'; +import 'title.dart'; const TextStyle _errorTextStyle = const TextStyle( color: const Color(0xD0FF0000), diff --git a/packages/flutter/lib/src/widgets/card.dart b/packages/flutter/lib/src/material/card.dart similarity index 83% rename from packages/flutter/lib/src/widgets/card.dart rename to packages/flutter/lib/src/material/card.dart index c9e0435805..caf2a647d4 100644 --- a/packages/flutter/lib/src/widgets/card.dart +++ b/packages/flutter/lib/src/material/card.dart @@ -2,9 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:sky/src/widgets/basic.dart'; -import 'package:sky/src/widgets/framework.dart'; -import 'package:sky/src/widgets/material.dart'; +import 'package:sky/widgets.dart'; + +import 'material.dart'; const EdgeDims _kCardMargins = const EdgeDims.all(4.0); diff --git a/packages/flutter/lib/src/widgets/checkbox.dart b/packages/flutter/lib/src/material/checkbox.dart similarity index 95% rename from packages/flutter/lib/src/widgets/checkbox.dart rename to packages/flutter/lib/src/material/checkbox.dart index 2ae53375be..17c57a2750 100644 --- a/packages/flutter/lib/src/widgets/checkbox.dart +++ b/packages/flutter/lib/src/material/checkbox.dart @@ -4,13 +4,12 @@ import 'dart:sky' as sky; -import 'package:sky/src/widgets/basic.dart'; -import 'package:sky/src/widgets/framework.dart'; -import 'package:sky/src/widgets/theme.dart'; -import 'package:sky/src/rendering/object.dart'; -import 'package:sky/src/rendering/toggleable.dart'; +import 'package:sky/rendering.dart'; +import 'package:sky/widgets.dart'; -export 'package:sky/src/rendering/toggleable.dart' show ValueChanged; +import 'theme.dart'; + +export 'package:sky/rendering.dart' show ValueChanged; const double _kMidpoint = 0.5; const sky.Color _kLightUncheckedColor = const sky.Color(0x8A000000); diff --git a/packages/flutter/lib/src/widgets/date_picker.dart b/packages/flutter/lib/src/material/date_picker.dart similarity index 97% rename from packages/flutter/lib/src/widgets/date_picker.dart rename to packages/flutter/lib/src/material/date_picker.dart index 5f428d65e3..8df5a45e5e 100644 --- a/packages/flutter/lib/src/widgets/date_picker.dart +++ b/packages/flutter/lib/src/material/date_picker.dart @@ -9,12 +9,10 @@ import 'package:intl/intl.dart'; import 'package:sky/material.dart'; import 'package:sky/painting.dart'; import 'package:sky/services.dart'; -import 'package:sky/src/widgets/basic.dart'; -import 'package:sky/src/widgets/framework.dart'; -import 'package:sky/src/widgets/gesture_detector.dart'; -import 'package:sky/src/widgets/ink_well.dart'; -import 'package:sky/src/widgets/scrollable.dart'; -import 'package:sky/src/widgets/theme.dart'; +import 'package:sky/widgets.dart'; + +import 'ink_well.dart'; +import 'theme.dart'; typedef void DatePickerValueChanged(DateTime dateTime); diff --git a/packages/flutter/lib/src/widgets/dialog.dart b/packages/flutter/lib/src/material/dialog.dart similarity index 90% rename from packages/flutter/lib/src/widgets/dialog.dart rename to packages/flutter/lib/src/material/dialog.dart index 202db68580..534ec6e5be 100644 --- a/packages/flutter/lib/src/widgets/dialog.dart +++ b/packages/flutter/lib/src/material/dialog.dart @@ -7,16 +7,11 @@ import 'dart:async'; import 'package:sky/animation.dart'; import 'package:sky/gestures.dart'; import 'package:sky/material.dart'; -import 'package:sky/src/widgets/basic.dart'; -import 'package:sky/src/widgets/focus.dart'; -import 'package:sky/src/widgets/framework.dart'; -import 'package:sky/src/widgets/gesture_detector.dart'; -import 'package:sky/src/widgets/material.dart'; -import 'package:sky/src/widgets/material_button.dart'; -import 'package:sky/src/widgets/navigator.dart'; -import 'package:sky/src/widgets/scrollable.dart'; -import 'package:sky/src/widgets/theme.dart'; -import 'package:sky/src/widgets/transitions.dart'; +import 'package:sky/widgets.dart'; + +import 'material.dart'; +import 'material_button.dart'; +import 'theme.dart'; typedef Widget DialogBuilder(NavigatorState navigator); diff --git a/packages/flutter/lib/src/widgets/drawer.dart b/packages/flutter/lib/src/material/drawer.dart similarity index 92% rename from packages/flutter/lib/src/widgets/drawer.dart rename to packages/flutter/lib/src/material/drawer.dart index 2b63b2aebc..fed362e566 100644 --- a/packages/flutter/lib/src/widgets/drawer.dart +++ b/packages/flutter/lib/src/material/drawer.dart @@ -4,14 +4,9 @@ import 'package:sky/animation.dart'; import 'package:sky/material.dart'; -import 'package:sky/src/widgets/animated_container.dart'; -import 'package:sky/src/widgets/framework.dart'; -import 'package:sky/src/widgets/basic.dart'; -import 'package:sky/src/widgets/gesture_detector.dart'; -import 'package:sky/src/widgets/navigator.dart'; -import 'package:sky/src/widgets/theme.dart'; -import 'package:sky/src/widgets/transitions.dart'; -import 'package:sky/src/widgets/focus.dart'; +import 'package:sky/widgets.dart'; + +import 'theme.dart'; // TODO(eseidel): Draw width should vary based on device size: // http://www.google.com/design/spec/layout/structure.html#structure-side-nav diff --git a/packages/flutter/lib/src/widgets/drawer_divider.dart b/packages/flutter/lib/src/material/drawer_divider.dart similarity index 81% rename from packages/flutter/lib/src/widgets/drawer_divider.dart rename to packages/flutter/lib/src/material/drawer_divider.dart index 7841726153..a9f1088270 100644 --- a/packages/flutter/lib/src/widgets/drawer_divider.dart +++ b/packages/flutter/lib/src/material/drawer_divider.dart @@ -2,9 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:sky/src/widgets/basic.dart'; -import 'package:sky/src/widgets/framework.dart'; -import 'package:sky/src/widgets/theme.dart'; +import 'package:sky/widgets.dart'; + +import 'theme.dart'; class DrawerDivider extends StatelessComponent { const DrawerDivider({ Key key }) : super(key: key); diff --git a/packages/flutter/lib/src/widgets/drawer_header.dart b/packages/flutter/lib/src/material/drawer_header.dart similarity index 89% rename from packages/flutter/lib/src/widgets/drawer_header.dart rename to packages/flutter/lib/src/material/drawer_header.dart index be71d34d41..45ae13728e 100644 --- a/packages/flutter/lib/src/widgets/drawer_header.dart +++ b/packages/flutter/lib/src/material/drawer_header.dart @@ -3,9 +3,9 @@ // found in the LICENSE file. import 'package:sky/material.dart'; -import 'package:sky/src/widgets/basic.dart'; -import 'package:sky/src/widgets/framework.dart'; -import 'package:sky/src/widgets/theme.dart'; +import 'package:sky/widgets.dart'; + +import 'theme.dart'; // TODO(jackson): This class should usually render the user's // preferred banner image rather than a solid background diff --git a/packages/flutter/lib/src/widgets/drawer_item.dart b/packages/flutter/lib/src/material/drawer_item.dart similarity index 91% rename from packages/flutter/lib/src/widgets/drawer_item.dart rename to packages/flutter/lib/src/material/drawer_item.dart index a963398ce6..bf5fd3035e 100644 --- a/packages/flutter/lib/src/widgets/drawer_item.dart +++ b/packages/flutter/lib/src/material/drawer_item.dart @@ -7,11 +7,11 @@ import 'dart:sky' as sky; import 'package:sky/gestures.dart'; import 'package:sky/material.dart'; import 'package:sky/painting.dart'; -import 'package:sky/src/widgets/basic.dart'; -import 'package:sky/src/widgets/framework.dart'; -import 'package:sky/src/widgets/icon.dart'; -import 'package:sky/src/widgets/ink_well.dart'; -import 'package:sky/src/widgets/theme.dart'; +import 'package:sky/widgets.dart'; + +import 'icon.dart'; +import 'ink_well.dart'; +import 'theme.dart'; class DrawerItem extends StatefulComponent { const DrawerItem({ Key key, this.icon, this.child, this.onPressed, this.selected: false }) diff --git a/packages/flutter/lib/src/widgets/flat_button.dart b/packages/flutter/lib/src/material/flat_button.dart similarity index 84% rename from packages/flutter/lib/src/widgets/flat_button.dart rename to packages/flutter/lib/src/material/flat_button.dart index 238879bfba..b87e7d1b3c 100644 --- a/packages/flutter/lib/src/widgets/flat_button.dart +++ b/packages/flutter/lib/src/material/flat_button.dart @@ -4,10 +4,10 @@ import 'package:sky/gestures.dart'; import 'package:sky/material.dart'; -import 'package:sky/src/widgets/basic.dart'; -import 'package:sky/src/widgets/framework.dart'; -import 'package:sky/src/widgets/material_button.dart'; -import 'package:sky/src/widgets/theme.dart'; +import 'package:sky/widgets.dart'; + +import 'material_button.dart'; +import 'theme.dart'; class FlatButton extends MaterialButton { FlatButton({ diff --git a/packages/flutter/lib/src/widgets/floating_action_button.dart b/packages/flutter/lib/src/material/floating_action_button.dart similarity index 87% rename from packages/flutter/lib/src/widgets/floating_action_button.dart rename to packages/flutter/lib/src/material/floating_action_button.dart index 8b95422f96..368e3c5ad7 100644 --- a/packages/flutter/lib/src/widgets/floating_action_button.dart +++ b/packages/flutter/lib/src/material/floating_action_button.dart @@ -3,12 +3,12 @@ // found in the LICENSE file. import 'package:sky/gestures.dart'; -import 'package:sky/src/widgets/basic.dart'; -import 'package:sky/src/widgets/framework.dart'; -import 'package:sky/src/widgets/icon.dart'; -import 'package:sky/src/widgets/ink_well.dart'; -import 'package:sky/src/widgets/material.dart'; -import 'package:sky/src/widgets/theme.dart'; +import 'package:sky/widgets.dart'; + +import 'icon.dart'; +import 'ink_well.dart'; +import 'material.dart'; +import 'theme.dart'; // TODO(eseidel): This needs to change based on device size? // http://www.google.com/design/spec/layout/metrics-keylines.html#metrics-keylines-keylines-spacing diff --git a/packages/flutter/lib/src/widgets/icon.dart b/packages/flutter/lib/src/material/icon.dart similarity index 95% rename from packages/flutter/lib/src/widgets/icon.dart rename to packages/flutter/lib/src/material/icon.dart index 9b71b138c6..6d0d119410 100644 --- a/packages/flutter/lib/src/widgets/icon.dart +++ b/packages/flutter/lib/src/material/icon.dart @@ -5,9 +5,9 @@ import 'dart:sky' as sky; import 'package:sky/services.dart'; -import 'package:sky/src/widgets/basic.dart'; -import 'package:sky/src/widgets/theme.dart'; -import 'package:sky/src/widgets/framework.dart'; +import 'package:sky/widgets.dart'; + +import 'theme.dart'; enum IconThemeColor { white, black } diff --git a/packages/flutter/lib/src/widgets/icon_button.dart b/packages/flutter/lib/src/material/icon_button.dart similarity index 81% rename from packages/flutter/lib/src/widgets/icon_button.dart rename to packages/flutter/lib/src/material/icon_button.dart index 662ee5fb52..a2b826d342 100644 --- a/packages/flutter/lib/src/widgets/icon_button.dart +++ b/packages/flutter/lib/src/material/icon_button.dart @@ -5,10 +5,9 @@ import 'dart:sky' as sky; import 'package:sky/gestures.dart'; -import 'package:sky/src/widgets/basic.dart'; -import 'package:sky/src/widgets/icon.dart'; -import 'package:sky/src/widgets/framework.dart'; -import 'package:sky/src/widgets/gesture_detector.dart'; +import 'package:sky/widgets.dart'; + +import 'icon.dart'; class IconButton extends StatelessComponent { const IconButton({ Key key, this.icon, this.onPressed, this.color }) : super(key: key); diff --git a/packages/flutter/lib/src/widgets/ink_well.dart b/packages/flutter/lib/src/material/ink_well.dart similarity index 98% rename from packages/flutter/lib/src/widgets/ink_well.dart rename to packages/flutter/lib/src/material/ink_well.dart index 140e2c9ae5..f77563509c 100644 --- a/packages/flutter/lib/src/widgets/ink_well.dart +++ b/packages/flutter/lib/src/material/ink_well.dart @@ -9,8 +9,7 @@ import 'dart:sky' as sky; import 'package:sky/animation.dart'; import 'package:sky/gestures.dart'; import 'package:sky/rendering.dart'; -import 'package:sky/src/widgets/basic.dart'; -import 'package:sky/src/widgets/framework.dart'; +import 'package:sky/widgets.dart'; const int _kSplashInitialOpacity = 0x30; const double _kSplashCanceledVelocity = 0.7; diff --git a/packages/flutter/lib/src/widgets/input.dart b/packages/flutter/lib/src/material/input.dart similarity index 94% rename from packages/flutter/lib/src/widgets/input.dart rename to packages/flutter/lib/src/material/input.dart index d3a1373073..0b2ad3cb17 100644 --- a/packages/flutter/lib/src/widgets/input.dart +++ b/packages/flutter/lib/src/material/input.dart @@ -6,12 +6,9 @@ import 'package:sky/animation.dart'; import 'package:sky/services.dart'; import 'package:sky/painting.dart'; import 'package:sky/rendering.dart'; -import 'package:sky/src/widgets/basic.dart'; -import 'package:sky/src/widgets/editable_text.dart'; -import 'package:sky/src/widgets/focus.dart'; -import 'package:sky/src/widgets/framework.dart'; -import 'package:sky/src/widgets/scrollable.dart'; -import 'package:sky/src/widgets/theme.dart'; +import 'package:sky/widgets.dart'; + +import 'theme.dart'; export 'package:sky/services.dart' show KeyboardType; diff --git a/packages/flutter/lib/src/widgets/material.dart b/packages/flutter/lib/src/material/material.dart similarity index 91% rename from packages/flutter/lib/src/widgets/material.dart rename to packages/flutter/lib/src/material/material.dart index 4f42d63abd..375a436d51 100644 --- a/packages/flutter/lib/src/widgets/material.dart +++ b/packages/flutter/lib/src/material/material.dart @@ -5,10 +5,9 @@ import 'package:sky/animation.dart'; import 'package:sky/painting.dart'; import 'package:sky/material.dart'; -import 'package:sky/src/widgets/animated_container.dart'; -import 'package:sky/src/widgets/basic.dart'; -import 'package:sky/src/widgets/framework.dart'; -import 'package:sky/src/widgets/theme.dart'; +import 'package:sky/widgets.dart'; + +import 'theme.dart'; enum MaterialType { canvas, card, circle, button } diff --git a/packages/flutter/lib/src/widgets/material_button.dart b/packages/flutter/lib/src/material/material_button.dart similarity index 92% rename from packages/flutter/lib/src/widgets/material_button.dart rename to packages/flutter/lib/src/material/material_button.dart index cd01b0df43..4db52a39b3 100644 --- a/packages/flutter/lib/src/widgets/material_button.dart +++ b/packages/flutter/lib/src/material/material_button.dart @@ -4,11 +4,11 @@ import 'package:sky/gestures.dart'; import 'package:sky/material.dart'; -import 'package:sky/src/widgets/basic.dart'; -import 'package:sky/src/widgets/framework.dart'; -import 'package:sky/src/widgets/ink_well.dart'; -import 'package:sky/src/widgets/material.dart'; -import 'package:sky/src/widgets/theme.dart'; +import 'package:sky/widgets.dart'; + +import 'ink_well.dart'; +import 'material.dart'; +import 'theme.dart'; enum ButtonColor { normal, accent } diff --git a/packages/flutter/lib/src/widgets/popup_menu.dart b/packages/flutter/lib/src/material/popup_menu.dart similarity index 92% rename from packages/flutter/lib/src/widgets/popup_menu.dart rename to packages/flutter/lib/src/material/popup_menu.dart index 518d921a95..6b1922bdac 100644 --- a/packages/flutter/lib/src/widgets/popup_menu.dart +++ b/packages/flutter/lib/src/material/popup_menu.dart @@ -8,15 +8,11 @@ import 'dart:sky' as sky; import 'package:sky/animation.dart'; import 'package:sky/material.dart'; import 'package:sky/painting.dart'; -import 'package:sky/src/widgets/basic.dart'; -import 'package:sky/src/widgets/focus.dart'; -import 'package:sky/src/widgets/framework.dart'; -import 'package:sky/src/widgets/ink_well.dart'; -import 'package:sky/src/widgets/navigator.dart'; -import 'package:sky/src/widgets/popup_menu_item.dart'; -import 'package:sky/src/widgets/scrollable.dart'; -import 'package:sky/src/widgets/theme.dart'; -import 'package:sky/src/widgets/transitions.dart'; +import 'package:sky/widgets.dart'; + +import 'ink_well.dart'; +import 'popup_menu_item.dart'; +import 'theme.dart'; const Duration _kMenuDuration = const Duration(milliseconds: 300); const double _kMenuCloseIntervalEnd = 2.0 / 3.0; diff --git a/packages/flutter/lib/src/widgets/popup_menu_item.dart b/packages/flutter/lib/src/material/popup_menu_item.dart similarity index 84% rename from packages/flutter/lib/src/widgets/popup_menu_item.dart rename to packages/flutter/lib/src/material/popup_menu_item.dart index d52d8e26ab..d09bda2be1 100644 --- a/packages/flutter/lib/src/widgets/popup_menu_item.dart +++ b/packages/flutter/lib/src/material/popup_menu_item.dart @@ -2,9 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:sky/src/widgets/basic.dart'; -import 'package:sky/src/widgets/framework.dart'; -import 'package:sky/src/widgets/theme.dart'; +import 'package:sky/widgets.dart'; + +import 'theme.dart'; const double _kMenuItemHeight = 48.0; const double _kBaselineOffsetFromBottom = 20.0; diff --git a/packages/flutter/lib/src/widgets/progress_indicator.dart b/packages/flutter/lib/src/material/progress_indicator.dart similarity index 96% rename from packages/flutter/lib/src/widgets/progress_indicator.dart rename to packages/flutter/lib/src/material/progress_indicator.dart index 92cdeda620..398b6040ef 100644 --- a/packages/flutter/lib/src/widgets/progress_indicator.dart +++ b/packages/flutter/lib/src/material/progress_indicator.dart @@ -6,10 +6,9 @@ import 'dart:math' as math; import 'dart:sky' as sky; import 'package:sky/animation.dart'; -import 'package:sky/src/widgets/basic.dart'; -import 'package:sky/src/widgets/theme.dart'; -import 'package:sky/src/widgets/framework.dart'; -import 'package:sky/src/widgets/transitions.dart'; +import 'package:sky/widgets.dart'; + +import 'theme.dart'; const double _kLinearProgressIndicatorHeight = 6.0; const double _kMinCircularProgressIndicatorSize = 15.0; diff --git a/packages/flutter/lib/src/widgets/radio.dart b/packages/flutter/lib/src/material/radio.dart similarity index 90% rename from packages/flutter/lib/src/widgets/radio.dart rename to packages/flutter/lib/src/material/radio.dart index dfecc4cbbf..30ae00732c 100644 --- a/packages/flutter/lib/src/widgets/radio.dart +++ b/packages/flutter/lib/src/material/radio.dart @@ -4,10 +4,9 @@ import 'dart:sky' as sky; -import 'package:sky/src/widgets/basic.dart'; -import 'package:sky/src/widgets/framework.dart'; -import 'package:sky/src/widgets/gesture_detector.dart'; -import 'package:sky/src/widgets/theme.dart'; +import 'package:sky/widgets.dart'; + +import 'theme.dart'; const sky.Color _kLightOffColor = const sky.Color(0x8A000000); const sky.Color _kDarkOffColor = const sky.Color(0xB2FFFFFF); diff --git a/packages/flutter/lib/src/widgets/raised_button.dart b/packages/flutter/lib/src/material/raised_button.dart similarity index 89% rename from packages/flutter/lib/src/widgets/raised_button.dart rename to packages/flutter/lib/src/material/raised_button.dart index b6db80487a..3484f6c8a7 100644 --- a/packages/flutter/lib/src/widgets/raised_button.dart +++ b/packages/flutter/lib/src/material/raised_button.dart @@ -4,10 +4,10 @@ import 'package:sky/gestures.dart'; import 'package:sky/material.dart'; -import 'package:sky/src/widgets/basic.dart'; -import 'package:sky/src/widgets/framework.dart'; -import 'package:sky/src/widgets/material_button.dart'; -import 'package:sky/src/widgets/theme.dart'; +import 'package:sky/widgets.dart'; + +import 'material_button.dart'; +import 'theme.dart'; class RaisedButton extends MaterialButton { RaisedButton({ diff --git a/packages/flutter/lib/src/widgets/scaffold.dart b/packages/flutter/lib/src/material/scaffold.dart similarity index 96% rename from packages/flutter/lib/src/widgets/scaffold.dart rename to packages/flutter/lib/src/material/scaffold.dart index bd02c3c4ca..fb65a23884 100644 --- a/packages/flutter/lib/src/widgets/scaffold.dart +++ b/packages/flutter/lib/src/material/scaffold.dart @@ -6,8 +6,7 @@ import 'dart:sky' as sky; import 'package:sky/material.dart'; import 'package:sky/rendering.dart'; -import 'package:sky/src/widgets/basic.dart'; -import 'package:sky/src/widgets/framework.dart'; +import 'package:sky/widgets.dart'; class Scaffold extends StatelessComponent { Scaffold({ diff --git a/packages/flutter/lib/src/widgets/snack_bar.dart b/packages/flutter/lib/src/material/snack_bar.dart similarity index 89% rename from packages/flutter/lib/src/widgets/snack_bar.dart rename to packages/flutter/lib/src/material/snack_bar.dart index 85454960b4..bc66cceb01 100644 --- a/packages/flutter/lib/src/widgets/snack_bar.dart +++ b/packages/flutter/lib/src/material/snack_bar.dart @@ -6,14 +6,10 @@ import 'package:sky/animation.dart'; import 'package:sky/gestures.dart'; import 'package:sky/material.dart'; import 'package:sky/painting.dart'; -import 'package:sky/src/widgets/basic.dart'; -import 'package:sky/src/widgets/framework.dart'; -import 'package:sky/src/widgets/gesture_detector.dart'; -import 'package:sky/src/widgets/material.dart'; -import 'package:sky/src/widgets/navigator.dart'; -import 'package:sky/src/widgets/placeholder.dart'; -import 'package:sky/src/widgets/theme.dart'; -import 'package:sky/src/widgets/transitions.dart'; +import 'package:sky/widgets.dart'; + +import 'material.dart'; +import 'theme.dart'; const double _kSideMargins = 24.0; const double _kVerticalPadding = 14.0; diff --git a/packages/flutter/lib/src/widgets/switch.dart b/packages/flutter/lib/src/material/switch.dart similarity index 97% rename from packages/flutter/lib/src/widgets/switch.dart rename to packages/flutter/lib/src/material/switch.dart index 5452545529..959d940a7a 100644 --- a/packages/flutter/lib/src/widgets/switch.dart +++ b/packages/flutter/lib/src/material/switch.dart @@ -8,9 +8,9 @@ import 'dart:sky' as sky; import 'package:sky/material.dart'; import 'package:sky/painting.dart'; import 'package:sky/rendering.dart'; -import 'package:sky/src/widgets/basic.dart'; -import 'package:sky/src/widgets/theme.dart'; -import 'package:sky/src/widgets/framework.dart'; +import 'package:sky/widgets.dart'; + +import 'theme.dart'; export 'package:sky/rendering.dart' show ValueChanged; diff --git a/packages/flutter/lib/src/widgets/tabs.dart b/packages/flutter/lib/src/material/tabs.dart similarity index 97% rename from packages/flutter/lib/src/widgets/tabs.dart rename to packages/flutter/lib/src/material/tabs.dart index 89367d9977..d6df9b9972 100644 --- a/packages/flutter/lib/src/widgets/tabs.dart +++ b/packages/flutter/lib/src/material/tabs.dart @@ -8,17 +8,16 @@ import 'dart:sky' as sky; import 'package:newton/newton.dart'; import 'package:sky/animation.dart'; import 'package:sky/gestures.dart'; -import 'package:sky/material.dart'; import 'package:sky/painting.dart'; import 'package:sky/rendering.dart'; -import 'package:sky/src/widgets/animated_container.dart'; -import 'package:sky/src/widgets/basic.dart'; -import 'package:sky/src/widgets/framework.dart'; -import 'package:sky/src/widgets/icon.dart'; -import 'package:sky/src/widgets/ink_well.dart'; -import 'package:sky/src/widgets/scrollable.dart'; -import 'package:sky/src/widgets/theme.dart'; -import 'package:sky/src/widgets/transitions.dart'; +import 'package:sky/widgets.dart'; + +import 'colors.dart'; +import 'constants.dart'; +import 'icon.dart'; +import 'ink_well.dart'; +import 'theme.dart'; +import 'typography.dart'; typedef void TabSelectedIndexChanged(int selectedIndex); typedef void TabLayoutChanged(Size size, List widths); diff --git a/packages/flutter/lib/src/widgets/theme.dart b/packages/flutter/lib/src/material/theme.dart similarity index 81% rename from packages/flutter/lib/src/widgets/theme.dart rename to packages/flutter/lib/src/material/theme.dart index c06978b2d7..e46a79ffc4 100644 --- a/packages/flutter/lib/src/widgets/theme.dart +++ b/packages/flutter/lib/src/material/theme.dart @@ -2,10 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:sky/material.dart'; -import 'package:sky/src/widgets/framework.dart'; +import 'package:sky/widgets.dart'; -export 'package:sky/material.dart' show ThemeData, ThemeBrightness; +import 'theme_data.dart'; + +export 'theme_data.dart' show ThemeData, ThemeBrightness; class Theme extends InheritedWidget { Theme({ diff --git a/packages/flutter/lib/src/widgets/title.dart b/packages/flutter/lib/src/material/title.dart similarity index 82% rename from packages/flutter/lib/src/widgets/title.dart rename to packages/flutter/lib/src/material/title.dart index f9f9ae5c4f..bcba1421c4 100644 --- a/packages/flutter/lib/src/widgets/title.dart +++ b/packages/flutter/lib/src/material/title.dart @@ -3,8 +3,9 @@ // found in the LICENSE file. import 'package:sky/services.dart'; -import 'package:sky/src/widgets/theme.dart'; -import 'package:sky/src/widgets/framework.dart'; +import 'package:sky/widgets.dart'; + +import 'theme.dart'; class Title extends StatelessComponent { Title({ this.title, this.child }); diff --git a/packages/flutter/lib/src/widgets/tool_bar.dart b/packages/flutter/lib/src/material/tool_bar.dart similarity index 90% rename from packages/flutter/lib/src/widgets/tool_bar.dart rename to packages/flutter/lib/src/material/tool_bar.dart index b92c938efe..16fc3398a8 100644 --- a/packages/flutter/lib/src/widgets/tool_bar.dart +++ b/packages/flutter/lib/src/material/tool_bar.dart @@ -4,11 +4,10 @@ import 'package:sky/material.dart'; import 'package:sky/painting.dart'; -import 'package:sky/src/widgets/animated_container.dart'; -import 'package:sky/src/widgets/basic.dart'; -import 'package:sky/src/widgets/framework.dart'; -import 'package:sky/src/widgets/icon.dart'; -import 'package:sky/src/widgets/theme.dart'; +import 'package:sky/widgets.dart'; + +import 'icon.dart'; +import 'theme.dart'; class ToolBar extends StatelessComponent { ToolBar({ diff --git a/packages/flutter/lib/src/widgets/animated_container.dart b/packages/flutter/lib/src/widgets/animated_container.dart index 12f65ad1ea..5734cfb8cc 100644 --- a/packages/flutter/lib/src/widgets/animated_container.dart +++ b/packages/flutter/lib/src/widgets/animated_container.dart @@ -3,8 +3,9 @@ // found in the LICENSE file. import 'package:sky/animation.dart'; -import 'package:sky/src/widgets/basic.dart'; -import 'package:sky/src/widgets/framework.dart'; + +import 'basic.dart'; +import 'framework.dart'; import 'package:vector_math/vector_math_64.dart'; diff --git a/packages/flutter/lib/src/widgets/basic.dart b/packages/flutter/lib/src/widgets/basic.dart index ea3a835f99..340fa56e6f 100644 --- a/packages/flutter/lib/src/widgets/basic.dart +++ b/packages/flutter/lib/src/widgets/basic.dart @@ -6,7 +6,8 @@ import 'dart:sky' as sky; import 'package:sky/rendering.dart'; import 'package:sky/services.dart'; -import 'package:sky/src/widgets/framework.dart'; + +import 'framework.dart'; export 'package:sky/rendering.dart' show BackgroundImage, diff --git a/packages/flutter/lib/src/widgets/binding.dart b/packages/flutter/lib/src/widgets/binding.dart index 2699254b6a..d6b6393a2f 100644 --- a/packages/flutter/lib/src/widgets/binding.dart +++ b/packages/flutter/lib/src/widgets/binding.dart @@ -4,7 +4,8 @@ import 'package:sky/animation.dart'; import 'package:sky/rendering.dart'; -import 'package:sky/src/widgets/framework.dart'; + +import 'framework.dart'; class WidgetFlutterBinding extends FlutterBinding { diff --git a/packages/flutter/lib/src/widgets/dismissable.dart b/packages/flutter/lib/src/widgets/dismissable.dart index 44c9d6ae29..a4d43114c9 100644 --- a/packages/flutter/lib/src/widgets/dismissable.dart +++ b/packages/flutter/lib/src/widgets/dismissable.dart @@ -5,10 +5,11 @@ import 'dart:sky' as sky; import 'package:sky/animation.dart'; -import 'package:sky/src/widgets/basic.dart'; -import 'package:sky/src/widgets/transitions.dart'; -import 'package:sky/src/widgets/framework.dart'; -import 'package:sky/src/widgets/gesture_detector.dart'; + +import 'basic.dart'; +import 'transitions.dart'; +import 'framework.dart'; +import 'gesture_detector.dart'; const Duration _kCardDismissFadeout = const Duration(milliseconds: 200); const Duration _kCardDismissResize = const Duration(milliseconds: 300); diff --git a/packages/flutter/lib/src/widgets/drag_target.dart b/packages/flutter/lib/src/widgets/drag_target.dart index 679c2fa1d4..ddd98ba0c0 100644 --- a/packages/flutter/lib/src/widgets/drag_target.dart +++ b/packages/flutter/lib/src/widgets/drag_target.dart @@ -7,10 +7,11 @@ import 'dart:sky' as sky; import 'package:sky/animation.dart'; import 'package:sky/rendering.dart'; -import 'package:sky/src/widgets/basic.dart'; -import 'package:sky/src/widgets/binding.dart'; -import 'package:sky/src/widgets/framework.dart'; -import 'package:sky/src/widgets/navigator.dart'; + +import 'basic.dart'; +import 'binding.dart'; +import 'framework.dart'; +import 'navigator.dart'; typedef bool DragTargetWillAccept(T data); typedef void DragTargetAccept(T data); diff --git a/packages/flutter/lib/src/widgets/editable_text.dart b/packages/flutter/lib/src/widgets/editable_text.dart index fee3793f93..0990eded4f 100644 --- a/packages/flutter/lib/src/widgets/editable_text.dart +++ b/packages/flutter/lib/src/widgets/editable_text.dart @@ -7,8 +7,9 @@ import 'dart:async'; import 'package:mojo_services/keyboard/keyboard.mojom.dart'; import 'package:sky/painting.dart'; import 'package:sky/rendering.dart'; -import 'package:sky/src/widgets/basic.dart'; -import 'package:sky/src/widgets/framework.dart'; + +import 'basic.dart'; +import 'framework.dart'; const _kCursorBlinkPeriod = 500; // milliseconds diff --git a/packages/flutter/lib/src/widgets/focus.dart b/packages/flutter/lib/src/widgets/focus.dart index 098fcf954e..5f2f129d3d 100644 --- a/packages/flutter/lib/src/widgets/focus.dart +++ b/packages/flutter/lib/src/widgets/focus.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:sky/src/widgets/framework.dart'; +import 'framework.dart'; typedef void FocusChanged(GlobalKey key); diff --git a/packages/flutter/lib/src/widgets/gesture_detector.dart b/packages/flutter/lib/src/widgets/gesture_detector.dart index c2d1454c13..6738389db4 100644 --- a/packages/flutter/lib/src/widgets/gesture_detector.dart +++ b/packages/flutter/lib/src/widgets/gesture_detector.dart @@ -5,9 +5,10 @@ import 'dart:sky' as sky; import 'package:sky/gestures.dart'; -import 'package:sky/src/widgets/basic.dart'; -import 'package:sky/src/widgets/framework.dart'; -import 'package:sky/src/rendering/binding.dart'; +import 'package:sky/rendering.dart'; + +import 'basic.dart'; +import 'framework.dart'; class GestureDetector extends StatefulComponent { const GestureDetector({ diff --git a/packages/flutter/lib/src/widgets/mimic.dart b/packages/flutter/lib/src/widgets/mimic.dart index 961db37986..69006782ca 100644 --- a/packages/flutter/lib/src/widgets/mimic.dart +++ b/packages/flutter/lib/src/widgets/mimic.dart @@ -3,8 +3,9 @@ // found in the LICENSE file. import 'package:sky/rendering.dart'; -import 'package:sky/src/widgets/basic.dart'; -import 'package:sky/src/widgets/framework.dart'; + +import 'basic.dart'; +import 'framework.dart'; class MimicableKey { MimicableKey._(this._state); diff --git a/packages/flutter/lib/src/widgets/mixed_viewport.dart b/packages/flutter/lib/src/widgets/mixed_viewport.dart index bf03507751..3941ec81b9 100644 --- a/packages/flutter/lib/src/widgets/mixed_viewport.dart +++ b/packages/flutter/lib/src/widgets/mixed_viewport.dart @@ -3,8 +3,9 @@ // found in the LICENSE file. import 'package:sky/rendering.dart'; -import 'package:sky/src/widgets/framework.dart'; -import 'package:sky/src/widgets/basic.dart'; + +import 'framework.dart'; +import 'basic.dart'; typedef Widget IndexedBuilder(BuildContext context, int index); // return null if index is greater than index of last entry typedef void ExtentsUpdateCallback(double newExtents); diff --git a/packages/flutter/lib/src/widgets/navigator.dart b/packages/flutter/lib/src/widgets/navigator.dart index 04e839fe50..97c9e63255 100644 --- a/packages/flutter/lib/src/widgets/navigator.dart +++ b/packages/flutter/lib/src/widgets/navigator.dart @@ -3,10 +3,11 @@ // found in the LICENSE file. import 'package:sky/animation.dart'; -import 'package:sky/src/widgets/basic.dart'; -import 'package:sky/src/widgets/focus.dart'; -import 'package:sky/src/widgets/framework.dart'; -import 'package:sky/src/widgets/transitions.dart'; + +import 'basic.dart'; +import 'focus.dart'; +import 'framework.dart'; +import 'transitions.dart'; class RouteArguments { const RouteArguments({ this.navigator, this.previousPerformance, this.nextPerformance }); diff --git a/packages/flutter/lib/src/widgets/placeholder.dart b/packages/flutter/lib/src/widgets/placeholder.dart index 69c79184f7..79da8dcdb4 100644 --- a/packages/flutter/lib/src/widgets/placeholder.dart +++ b/packages/flutter/lib/src/widgets/placeholder.dart @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:sky/src/widgets/basic.dart'; -import 'package:sky/src/widgets/framework.dart'; +import 'basic.dart'; +import 'framework.dart'; class Placeholder extends StatefulComponent { Placeholder({ Key key }) : super(key: key); diff --git a/packages/flutter/lib/src/widgets/scrollable.dart b/packages/flutter/lib/src/widgets/scrollable.dart index bf4a08605d..36b1502155 100644 --- a/packages/flutter/lib/src/widgets/scrollable.dart +++ b/packages/flutter/lib/src/widgets/scrollable.dart @@ -10,11 +10,12 @@ import 'package:newton/newton.dart'; import 'package:sky/animation.dart'; import 'package:sky/gestures.dart'; import 'package:sky/rendering.dart'; -import 'package:sky/src/widgets/basic.dart'; -import 'package:sky/src/widgets/framework.dart'; -import 'package:sky/src/widgets/gesture_detector.dart'; -import 'package:sky/src/widgets/homogeneous_viewport.dart'; -import 'package:sky/src/widgets/mixed_viewport.dart'; + +import 'basic.dart'; +import 'framework.dart'; +import 'gesture_detector.dart'; +import 'homogeneous_viewport.dart'; +import 'mixed_viewport.dart'; // The gesture velocity properties are pixels/second, config min,max limits are pixels/ms const double _kMillisecondsPerSecond = 1000.0; diff --git a/packages/flutter/lib/src/widgets/statistics_overlay.dart b/packages/flutter/lib/src/widgets/statistics_overlay.dart index 6677cfbdd9..a4c5eb62a2 100644 --- a/packages/flutter/lib/src/widgets/statistics_overlay.dart +++ b/packages/flutter/lib/src/widgets/statistics_overlay.dart @@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:sky/src/widgets/framework.dart'; +import 'framework.dart'; + import 'package:sky/src/rendering/statistics_box.dart'; /// The options that control whether the statistics overlay displays certain diff --git a/packages/flutter/lib/src/widgets/transitions.dart b/packages/flutter/lib/src/widgets/transitions.dart index 5f3d52bf01..71e9a985ac 100644 --- a/packages/flutter/lib/src/widgets/transitions.dart +++ b/packages/flutter/lib/src/widgets/transitions.dart @@ -3,10 +3,11 @@ // found in the LICENSE file. import 'package:sky/animation.dart'; -import 'package:sky/src/widgets/basic.dart'; -import 'package:sky/src/widgets/framework.dart'; import 'package:vector_math/vector_math_64.dart'; +import 'basic.dart'; +import 'framework.dart'; + export 'package:sky/animation.dart' show AnimationDirection; abstract class TransitionComponent extends StatefulComponent { diff --git a/packages/flutter/lib/src/widgets/unique_component.dart b/packages/flutter/lib/src/widgets/unique_component.dart index 065ee3b033..73b2cc32dd 100644 --- a/packages/flutter/lib/src/widgets/unique_component.dart +++ b/packages/flutter/lib/src/widgets/unique_component.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:sky/widgets.dart'; +import 'framework.dart'; abstract class UniqueComponent extends StatefulComponent { UniqueComponent({ GlobalKey key }) : super(key: key) { diff --git a/packages/flutter/lib/widgets.dart b/packages/flutter/lib/widgets.dart index 84f308d536..2ecb32b564 100644 --- a/packages/flutter/lib/widgets.dart +++ b/packages/flutter/lib/widgets.dart @@ -6,50 +6,21 @@ library widgets; export 'src/widgets/animated_container.dart'; -export 'src/widgets/app.dart'; export 'src/widgets/basic.dart'; export 'src/widgets/binding.dart'; -export 'src/widgets/card.dart'; -export 'src/widgets/checkbox.dart'; -export 'src/widgets/date_picker.dart'; -export 'src/widgets/dialog.dart'; export 'src/widgets/dismissable.dart'; export 'src/widgets/drag_target.dart'; -export 'src/widgets/drawer.dart'; -export 'src/widgets/drawer_divider.dart'; -export 'src/widgets/drawer_header.dart'; -export 'src/widgets/drawer_item.dart'; export 'src/widgets/editable_text.dart'; -export 'src/widgets/flat_button.dart'; -export 'src/widgets/floating_action_button.dart'; export 'src/widgets/focus.dart'; export 'src/widgets/framework.dart'; export 'src/widgets/gesture_detector.dart'; export 'src/widgets/homogeneous_viewport.dart'; -export 'src/widgets/icon.dart'; -export 'src/widgets/icon_button.dart'; -export 'src/widgets/ink_well.dart'; -export 'src/widgets/input.dart'; -export 'src/widgets/material.dart'; -export 'src/widgets/material_button.dart'; export 'src/widgets/mimic.dart'; export 'src/widgets/mixed_viewport.dart'; export 'src/widgets/navigator.dart'; export 'src/widgets/placeholder.dart'; -export 'src/widgets/popup_menu.dart'; -export 'src/widgets/popup_menu_item.dart'; -export 'src/widgets/progress_indicator.dart'; -export 'src/widgets/radio.dart'; -export 'src/widgets/raised_button.dart'; -export 'src/widgets/scaffold.dart'; export 'src/widgets/scrollable.dart'; export 'src/widgets/statistics_overlay.dart'; -export 'src/widgets/snack_bar.dart'; -export 'src/widgets/switch.dart'; -export 'src/widgets/tabs.dart'; -export 'src/widgets/theme.dart'; -export 'src/widgets/title.dart'; -export 'src/widgets/tool_bar.dart'; export 'src/widgets/transitions.dart'; export 'src/widgets/unique_component.dart'; diff --git a/packages/unit/test/widget/date_picker_test.dart b/packages/unit/test/widget/date_picker_test.dart index e3892137f8..975cbe3f42 100644 --- a/packages/unit/test/widget/date_picker_test.dart +++ b/packages/unit/test/widget/date_picker_test.dart @@ -1,4 +1,4 @@ -import 'package:sky/widgets.dart'; +import 'package:sky/material.dart'; import 'package:test/test.dart'; import 'widget_tester.dart'; diff --git a/packages/unit/test/widget/drawer_test.dart b/packages/unit/test/widget/drawer_test.dart index 2fb0b24278..36389c8b3b 100644 --- a/packages/unit/test/widget/drawer_test.dart +++ b/packages/unit/test/widget/drawer_test.dart @@ -1,3 +1,4 @@ +import 'package:sky/material.dart'; import 'package:sky/widgets.dart'; import 'package:test/test.dart'; diff --git a/packages/unit/test/widget/input_test.dart b/packages/unit/test/widget/input_test.dart index 01670d5ec0..e2bfbad04f 100644 --- a/packages/unit/test/widget/input_test.dart +++ b/packages/unit/test/widget/input_test.dart @@ -1,7 +1,7 @@ import 'package:mojo_services/keyboard/keyboard.mojom.dart'; import 'package:sky/rendering.dart'; import 'package:sky/services.dart'; -import 'package:sky/widgets.dart'; +import 'package:sky/material.dart'; import 'package:test/test.dart'; import 'widget_tester.dart'; diff --git a/packages/unit/test/widget/progress_indicator_test.dart b/packages/unit/test/widget/progress_indicator_test.dart index 83389335de..849818b3de 100644 --- a/packages/unit/test/widget/progress_indicator_test.dart +++ b/packages/unit/test/widget/progress_indicator_test.dart @@ -1,6 +1,6 @@ import 'package:sky/rendering.dart'; -import 'package:sky/widgets.dart'; +import 'package:sky/material.dart'; import 'package:test/test.dart'; import 'widget_tester.dart'; diff --git a/packages/unit/test/widget/snack_bar_test.dart b/packages/unit/test/widget/snack_bar_test.dart index 6cb2d6605b..eb056b390f 100644 --- a/packages/unit/test/widget/snack_bar_test.dart +++ b/packages/unit/test/widget/snack_bar_test.dart @@ -1,4 +1,4 @@ -import 'package:sky/widgets.dart'; +import 'package:sky/material.dart'; import 'package:test/test.dart'; import 'widget_tester.dart'; From db3b9e805292ea6778bb2c51c0b9b9464ebe2ebd Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Fri, 9 Oct 2015 10:19:35 -0700 Subject: [PATCH 27/84] Rename App to MaterialApp MaterialApp assumes that you're using material design. Also move radial reaction and fix imports for stats box. --- examples/address_book/lib/main.dart | 2 +- examples/demo_launcher/lib/main.dart | 2 +- examples/fitness/lib/main.dart | 2 +- examples/game/example_effect_line.dart | 2 +- examples/game/lib/main.dart | 2 +- examples/game/test_bed.dart | 2 +- examples/game/test_drawatlas.dart | 2 +- examples/game/test_performance.dart | 2 +- examples/game/test_physics.dart | 2 +- examples/stocks/lib/main.dart | 2 +- examples/widgets/card_collection.dart | 2 +- examples/widgets/drag_and_drop.dart | 2 +- examples/widgets/ensure_visible.dart | 2 +- examples/widgets/indexed_stack.dart | 2 +- examples/widgets/navigation.dart | 2 +- examples/widgets/overlay_geometry.dart | 2 +- examples/widgets/pageable_list.dart | 2 +- examples/widgets/sector.dart | 2 +- packages/flutter/lib/material.dart | 9 +++++---- packages/flutter/lib/painting.dart | 1 - packages/flutter/lib/rendering.dart | 1 + .../src/material/{app.dart => material_app.dart} | 16 +++++----------- .../{painting => material}/radial_reaction.dart | 0 packages/flutter/lib/src/material/switch.dart | 3 ++- .../lib/src/widgets/statistics_overlay.dart | 4 ++-- packages/unit/test/widget/drawer_test.dart | 4 ++-- packages/unit/test/widget/snack_bar_test.dart | 2 +- 27 files changed, 36 insertions(+), 40 deletions(-) rename packages/flutter/lib/src/material/{app.dart => material_app.dart} (79%) rename packages/flutter/lib/src/{painting => material}/radial_reaction.dart (100%) diff --git a/examples/address_book/lib/main.dart b/examples/address_book/lib/main.dart index fb10eccbcc..dee2b76148 100644 --- a/examples/address_book/lib/main.dart +++ b/examples/address_book/lib/main.dart @@ -94,7 +94,7 @@ final ThemeData theme = new ThemeData( ); void main() { - runApp(new App( + runApp(new MaterialApp( title: 'Address Book', theme: theme, routes: { diff --git a/examples/demo_launcher/lib/main.dart b/examples/demo_launcher/lib/main.dart index dd4bf62a3c..a95c24ee5c 100644 --- a/examples/demo_launcher/lib/main.dart +++ b/examples/demo_launcher/lib/main.dart @@ -201,7 +201,7 @@ class DemoHome extends StatelessComponent { } void main() { - runApp(new App( + runApp(new MaterialApp( title: 'Flutter Demos', theme: _theme, routes: { diff --git a/examples/fitness/lib/main.dart b/examples/fitness/lib/main.dart index c747be646d..453648ba5f 100644 --- a/examples/fitness/lib/main.dart +++ b/examples/fitness/lib/main.dart @@ -125,7 +125,7 @@ class FitnessAppState extends State { } Widget build(BuildContext) { - return new App( + return new MaterialApp( theme: new ThemeData( brightness: ThemeBrightness.light, primarySwatch: Colors.indigo, diff --git a/examples/game/example_effect_line.dart b/examples/game/example_effect_line.dart index 05323d00d9..6d05848942 100644 --- a/examples/game/example_effect_line.dart +++ b/examples/game/example_effect_line.dart @@ -53,7 +53,7 @@ class TestAppState extends State { ]; Widget build(BuildContext context) { - return new App( + return new MaterialApp( title: 'EffectLine Demo', theme: _theme, routes: { diff --git a/examples/game/lib/main.dart b/examples/game/lib/main.dart index 9150ab95fc..098f3ebfbf 100644 --- a/examples/game/lib/main.dart +++ b/examples/game/lib/main.dart @@ -81,7 +81,7 @@ class GameDemoState extends State { int _lastScore = 0; Widget build(BuildContext context) { - return new App( + return new MaterialApp( title: 'Asteroids', theme: _theme, routes: { diff --git a/examples/game/test_bed.dart b/examples/game/test_bed.dart index 653a566c0e..b2dc7fbc6e 100644 --- a/examples/game/test_bed.dart +++ b/examples/game/test_bed.dart @@ -32,7 +32,7 @@ main() async { runApp(_app); } -class TestBedApp extends App { +class TestBedApp extends MaterialApp { Widget build() { ThemeData theme = new ThemeData( diff --git a/examples/game/test_drawatlas.dart b/examples/game/test_drawatlas.dart index dba1748a25..edf568e5ae 100644 --- a/examples/game/test_drawatlas.dart +++ b/examples/game/test_drawatlas.dart @@ -32,7 +32,7 @@ main() async { String json = await _bundle.loadString('assets/sprites.json'); _spriteSheet = new SpriteSheet(_images['assets/sprites.png'], json); - runApp(new App( + runApp(new MaterialApp( title: 'Test drawAtlas', theme: _theme, routes: { diff --git a/examples/game/test_performance.dart b/examples/game/test_performance.dart index 5ceab235d4..44d363c12f 100644 --- a/examples/game/test_performance.dart +++ b/examples/game/test_performance.dart @@ -33,7 +33,7 @@ main() async { String json = await _bundle.loadString('assets/sprites.json'); _spriteSheet = new SpriteSheet(_images['assets/sprites.png'], json); - runApp(new App( + runApp(new MaterialApp( title: 'Test Sprite Performance', theme: _theme, routes: { diff --git a/examples/game/test_physics.dart b/examples/game/test_physics.dart index 137a3257ce..4c2ecc10b6 100644 --- a/examples/game/test_physics.dart +++ b/examples/game/test_physics.dart @@ -27,7 +27,7 @@ main() async { String json = await _bundle.loadString('assets/sprites.json'); _spriteSheet = new SpriteSheet(_images['assets/sprites.png'], json); - runApp(new App( + runApp(new MaterialApp( title: 'Test Physics', theme: new ThemeData( brightness: ThemeBrightness.light, diff --git a/examples/stocks/lib/main.dart b/examples/stocks/lib/main.dart index 1a4679006e..f791c55e0c 100644 --- a/examples/stocks/lib/main.dart +++ b/examples/stocks/lib/main.dart @@ -87,7 +87,7 @@ class StocksAppState extends State { } Widget build(BuildContext context) { - return new App( + return new MaterialApp( title: 'Stocks', theme: theme, routes: { diff --git a/examples/widgets/card_collection.dart b/examples/widgets/card_collection.dart index 7896c6809a..0293a73d70 100644 --- a/examples/widgets/card_collection.dart +++ b/examples/widgets/card_collection.dart @@ -372,7 +372,7 @@ class CardCollectionState extends State { } void main() { - runApp(new App( + runApp(new MaterialApp( title: 'Cards', routes: { '/': (RouteArguments args) => new CardCollection(navigator: args.navigator), diff --git a/examples/widgets/drag_and_drop.dart b/examples/widgets/drag_and_drop.dart index a7c5ff63d7..7de9a6b348 100644 --- a/examples/widgets/drag_and_drop.dart +++ b/examples/widgets/drag_and_drop.dart @@ -129,7 +129,7 @@ class DragAndDropAppState extends State { } void main() { - runApp(new App( + runApp(new MaterialApp( title: 'Drag and Drop Flutter Demo', routes: { '/': (RouteArguments args) => new DragAndDropApp(navigator: args.navigator) diff --git a/examples/widgets/ensure_visible.dart b/examples/widgets/ensure_visible.dart index d59e0d6cea..fe570fdfda 100644 --- a/examples/widgets/ensure_visible.dart +++ b/examples/widgets/ensure_visible.dart @@ -13,7 +13,7 @@ class CardModel { Key get key => new ObjectKey(this); } -class EnsureVisibleApp extends App { +class EnsureVisibleApp extends MaterialApp { static const TextStyle cardLabelStyle = const TextStyle(color: Colors.white, fontSize: 18.0, fontWeight: bold); diff --git a/examples/widgets/indexed_stack.dart b/examples/widgets/indexed_stack.dart index e7a5e4952b..5f23624d98 100644 --- a/examples/widgets/indexed_stack.dart +++ b/examples/widgets/indexed_stack.dart @@ -56,7 +56,7 @@ class IndexedStackDemoState extends State { } void main() { - runApp(new App( + runApp(new MaterialApp( title: 'IndexedStackDemo', theme: new ThemeData( brightness: ThemeBrightness.light, diff --git a/examples/widgets/navigation.dart b/examples/widgets/navigation.dart index 1e76049291..9624c20588 100644 --- a/examples/widgets/navigation.dart +++ b/examples/widgets/navigation.dart @@ -57,7 +57,7 @@ final ThemeData theme = new ThemeData( ); void main() { - runApp(new App( + runApp(new MaterialApp( title: 'Navigation Example', theme: theme, routes: routes diff --git a/examples/widgets/overlay_geometry.dart b/examples/widgets/overlay_geometry.dart index 34be772d52..bc55cafbbe 100644 --- a/examples/widgets/overlay_geometry.dart +++ b/examples/widgets/overlay_geometry.dart @@ -156,7 +156,7 @@ class OverlayGeometryAppState extends State { } void main() { - runApp(new App( + runApp(new MaterialApp( theme: new ThemeData( brightness: ThemeBrightness.light, primarySwatch: Colors.blue, diff --git a/examples/widgets/pageable_list.dart b/examples/widgets/pageable_list.dart index f51083e801..05d216d06f 100644 --- a/examples/widgets/pageable_list.dart +++ b/examples/widgets/pageable_list.dart @@ -156,7 +156,7 @@ class PageableListAppState extends State { } void main() { - runApp(new App( + runApp(new MaterialApp( title: 'PageableList', theme: new ThemeData( brightness: ThemeBrightness.light, diff --git a/examples/widgets/sector.dart b/examples/widgets/sector.dart index c87d87c1a2..d6253c228f 100644 --- a/examples/widgets/sector.dart +++ b/examples/widgets/sector.dart @@ -16,7 +16,7 @@ RenderBox initCircle() { ); } -class SectorApp extends App { +class SectorApp extends MaterialApp { RenderBoxToRenderSectorAdapter sectors = initCircle(); math.Random rand = new math.Random(1); diff --git a/packages/flutter/lib/material.dart b/packages/flutter/lib/material.dart index 69cabb7288..e2e50c720c 100644 --- a/packages/flutter/lib/material.dart +++ b/packages/flutter/lib/material.dart @@ -7,7 +7,6 @@ /// See https://www.google.com/design/spec/material-design/introduction.html library material; -export 'src/material/app.dart'; export 'src/material/card.dart'; export 'src/material/checkbox.dart'; export 'src/material/colors.dart'; @@ -25,10 +24,11 @@ export 'src/material/icon_button.dart'; export 'src/material/icon.dart'; export 'src/material/ink_well.dart'; export 'src/material/input.dart'; -export 'src/material/material_button.dart'; export 'src/material/material.dart'; -export 'src/material/popup_menu.dart'; +export 'src/material/material_app.dart'; +export 'src/material/material_button.dart'; export 'src/material/popup_menu_item.dart'; +export 'src/material/popup_menu.dart'; export 'src/material/progress_indicator.dart'; export 'src/material/radio.dart'; export 'src/material/raised_button.dart'; @@ -37,10 +37,11 @@ export 'src/material/shadows.dart'; export 'src/material/snack_bar.dart'; export 'src/material/switch.dart'; export 'src/material/tabs.dart'; -export 'src/material/theme.dart'; export 'src/material/theme_data.dart'; +export 'src/material/theme.dart'; export 'src/material/title.dart'; export 'src/material/tool_bar.dart'; export 'src/material/typography.dart'; +export 'src/material/radial_reaction.dart'; export 'widgets.dart'; diff --git a/packages/flutter/lib/painting.dart b/packages/flutter/lib/painting.dart index a8f20519f7..e23302cef3 100644 --- a/packages/flutter/lib/painting.dart +++ b/packages/flutter/lib/painting.dart @@ -13,7 +13,6 @@ library painting; export 'src/painting/box_painter.dart'; -export 'src/painting/radial_reaction.dart'; export 'src/painting/shadows.dart'; export 'src/painting/text_painter.dart'; export 'src/painting/text_style.dart'; diff --git a/packages/flutter/lib/rendering.dart b/packages/flutter/lib/rendering.dart index d37ea3cdb6..4a9564b7b4 100644 --- a/packages/flutter/lib/rendering.dart +++ b/packages/flutter/lib/rendering.dart @@ -23,6 +23,7 @@ export 'src/rendering/proxy_box.dart'; export 'src/rendering/shifted_box.dart'; export 'src/rendering/binding.dart'; export 'src/rendering/stack.dart'; +export 'src/rendering/statistics_box.dart'; export 'src/rendering/toggleable.dart'; export 'src/rendering/view.dart'; export 'src/rendering/viewport.dart'; diff --git a/packages/flutter/lib/src/material/app.dart b/packages/flutter/lib/src/material/material_app.dart similarity index 79% rename from packages/flutter/lib/src/material/app.dart rename to packages/flutter/lib/src/material/material_app.dart index e73eab17bd..8076d94f1d 100644 --- a/packages/flutter/lib/src/material/app.dart +++ b/packages/flutter/lib/src/material/material_app.dart @@ -23,21 +23,15 @@ const TextStyle _errorTextStyle = const TextStyle( decorationStyle: TextDecorationStyle.double ); -class App extends StatefulComponent { - App({ +class MaterialApp extends StatefulComponent { + MaterialApp({ Key key, this.title, this.theme, this.routes, this.onGenerateRoute }) : super(key: key) { - assert(() { - 'The "routes" argument to App() is required.'; - 'This might be a sign that you have not upgraded to our new Widgets framework.'; - 'For more details see: https://groups.google.com/forum/#!topic/flutter-dev/hcX3OvLws9c'; - '...or look at our examples: https://github.com/flutter/engine/tree/master/examples'; - return routes != null; - }); + assert(routes != null); } final String title; @@ -45,10 +39,10 @@ class App extends StatefulComponent { final Map routes; final RouteGenerator onGenerateRoute; - _AppState createState() => new _AppState(); + _MaterialAppState createState() => new _MaterialAppState(); } -class _AppState extends State { +class _MaterialAppState extends State { GlobalObjectKey _navigator; diff --git a/packages/flutter/lib/src/painting/radial_reaction.dart b/packages/flutter/lib/src/material/radial_reaction.dart similarity index 100% rename from packages/flutter/lib/src/painting/radial_reaction.dart rename to packages/flutter/lib/src/material/radial_reaction.dart diff --git a/packages/flutter/lib/src/material/switch.dart b/packages/flutter/lib/src/material/switch.dart index 959d940a7a..c221028e10 100644 --- a/packages/flutter/lib/src/material/switch.dart +++ b/packages/flutter/lib/src/material/switch.dart @@ -5,11 +5,12 @@ import 'dart:async'; import 'dart:sky' as sky; -import 'package:sky/material.dart'; import 'package:sky/painting.dart'; import 'package:sky/rendering.dart'; import 'package:sky/widgets.dart'; +import 'radial_reaction.dart'; +import 'shadows.dart'; import 'theme.dart'; export 'package:sky/rendering.dart' show ValueChanged; diff --git a/packages/flutter/lib/src/widgets/statistics_overlay.dart b/packages/flutter/lib/src/widgets/statistics_overlay.dart index a4c5eb62a2..80fa77915e 100644 --- a/packages/flutter/lib/src/widgets/statistics_overlay.dart +++ b/packages/flutter/lib/src/widgets/statistics_overlay.dart @@ -2,9 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'framework.dart'; +import 'package:sky/rendering.dart'; -import 'package:sky/src/rendering/statistics_box.dart'; +import 'framework.dart'; /// The options that control whether the statistics overlay displays certain /// aspects of the compositor diff --git a/packages/unit/test/widget/drawer_test.dart b/packages/unit/test/widget/drawer_test.dart index 36389c8b3b..2e976af086 100644 --- a/packages/unit/test/widget/drawer_test.dart +++ b/packages/unit/test/widget/drawer_test.dart @@ -10,7 +10,7 @@ void main() { testWidgets((WidgetTester tester) { NavigatorState navigator; tester.pumpWidget( - new App( + new MaterialApp( routes: { '/': (RouteArguments args) { navigator = args.navigator; @@ -39,7 +39,7 @@ void main() { NavigatorState navigator; tester.pumpWidget(new Container()); // throw away the old App and its Navigator tester.pumpWidget( - new App( + new MaterialApp( routes: { '/': (RouteArguments args) { navigator = args.navigator; diff --git a/packages/unit/test/widget/snack_bar_test.dart b/packages/unit/test/widget/snack_bar_test.dart index eb056b390f..4ddfd84382 100644 --- a/packages/unit/test/widget/snack_bar_test.dart +++ b/packages/unit/test/widget/snack_bar_test.dart @@ -10,7 +10,7 @@ void main() { GlobalKey placeholderKey = new GlobalKey(); Key tapTarget = new Key('tap-target'); - tester.pumpWidget(new App( + tester.pumpWidget(new MaterialApp( routes: { '/': (RouteArguments args) { return new GestureDetector( From 3053e876d0f8bd724cee08af6f8b81ec4ad4ff37 Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Fri, 9 Oct 2015 10:38:02 -0700 Subject: [PATCH 28/84] Remove circular imports of the material.dart library --- packages/flutter/lib/src/material/date_picker.dart | 3 ++- packages/flutter/lib/src/material/dialog.dart | 4 ++-- packages/flutter/lib/src/material/drawer.dart | 3 ++- packages/flutter/lib/src/material/drawer_header.dart | 2 +- packages/flutter/lib/src/material/drawer_item.dart | 2 +- packages/flutter/lib/src/material/flat_button.dart | 2 +- packages/flutter/lib/src/material/material.dart | 3 ++- packages/flutter/lib/src/material/material_app.dart | 1 - packages/flutter/lib/src/material/material_button.dart | 2 +- packages/flutter/lib/src/material/popup_menu.dart | 2 +- packages/flutter/lib/src/material/raised_button.dart | 2 +- packages/flutter/lib/src/material/scaffold.dart | 3 ++- packages/flutter/lib/src/material/snack_bar.dart | 3 ++- packages/flutter/lib/src/material/tool_bar.dart | 4 +++- 14 files changed, 21 insertions(+), 15 deletions(-) diff --git a/packages/flutter/lib/src/material/date_picker.dart b/packages/flutter/lib/src/material/date_picker.dart index 8df5a45e5e..6e09578e48 100644 --- a/packages/flutter/lib/src/material/date_picker.dart +++ b/packages/flutter/lib/src/material/date_picker.dart @@ -6,13 +6,14 @@ import 'dart:async'; import 'package:intl/date_symbols.dart'; import 'package:intl/intl.dart'; -import 'package:sky/material.dart'; import 'package:sky/painting.dart'; import 'package:sky/services.dart'; import 'package:sky/widgets.dart'; +import 'colors.dart'; import 'ink_well.dart'; import 'theme.dart'; +import 'typography.dart'; typedef void DatePickerValueChanged(DateTime dateTime); diff --git a/packages/flutter/lib/src/material/dialog.dart b/packages/flutter/lib/src/material/dialog.dart index 534ec6e5be..a3064fe5b2 100644 --- a/packages/flutter/lib/src/material/dialog.dart +++ b/packages/flutter/lib/src/material/dialog.dart @@ -6,11 +6,11 @@ import 'dart:async'; import 'package:sky/animation.dart'; import 'package:sky/gestures.dart'; -import 'package:sky/material.dart'; import 'package:sky/widgets.dart'; -import 'material.dart'; +import 'colors.dart'; import 'material_button.dart'; +import 'material.dart'; import 'theme.dart'; typedef Widget DialogBuilder(NavigatorState navigator); diff --git a/packages/flutter/lib/src/material/drawer.dart b/packages/flutter/lib/src/material/drawer.dart index fed362e566..12ebda6b09 100644 --- a/packages/flutter/lib/src/material/drawer.dart +++ b/packages/flutter/lib/src/material/drawer.dart @@ -3,9 +3,10 @@ // found in the LICENSE file. import 'package:sky/animation.dart'; -import 'package:sky/material.dart'; import 'package:sky/widgets.dart'; +import 'colors.dart'; +import 'shadows.dart'; import 'theme.dart'; // TODO(eseidel): Draw width should vary based on device size: diff --git a/packages/flutter/lib/src/material/drawer_header.dart b/packages/flutter/lib/src/material/drawer_header.dart index 45ae13728e..e95f1b039d 100644 --- a/packages/flutter/lib/src/material/drawer_header.dart +++ b/packages/flutter/lib/src/material/drawer_header.dart @@ -2,9 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:sky/material.dart'; import 'package:sky/widgets.dart'; +import 'constants.dart'; import 'theme.dart'; // TODO(jackson): This class should usually render the user's diff --git a/packages/flutter/lib/src/material/drawer_item.dart b/packages/flutter/lib/src/material/drawer_item.dart index bf5fd3035e..ac11f1900b 100644 --- a/packages/flutter/lib/src/material/drawer_item.dart +++ b/packages/flutter/lib/src/material/drawer_item.dart @@ -5,10 +5,10 @@ import 'dart:sky' as sky; import 'package:sky/gestures.dart'; -import 'package:sky/material.dart'; import 'package:sky/painting.dart'; import 'package:sky/widgets.dart'; +import 'colors.dart'; import 'icon.dart'; import 'ink_well.dart'; import 'theme.dart'; diff --git a/packages/flutter/lib/src/material/flat_button.dart b/packages/flutter/lib/src/material/flat_button.dart index b87e7d1b3c..0737afa760 100644 --- a/packages/flutter/lib/src/material/flat_button.dart +++ b/packages/flutter/lib/src/material/flat_button.dart @@ -3,9 +3,9 @@ // found in the LICENSE file. import 'package:sky/gestures.dart'; -import 'package:sky/material.dart'; import 'package:sky/widgets.dart'; +import 'colors.dart'; import 'material_button.dart'; import 'theme.dart'; diff --git a/packages/flutter/lib/src/material/material.dart b/packages/flutter/lib/src/material/material.dart index 375a436d51..614dd0d2a3 100644 --- a/packages/flutter/lib/src/material/material.dart +++ b/packages/flutter/lib/src/material/material.dart @@ -4,9 +4,10 @@ import 'package:sky/animation.dart'; import 'package:sky/painting.dart'; -import 'package:sky/material.dart'; import 'package:sky/widgets.dart'; +import 'constants.dart'; +import 'shadows.dart'; import 'theme.dart'; enum MaterialType { canvas, card, circle, button } diff --git a/packages/flutter/lib/src/material/material_app.dart b/packages/flutter/lib/src/material/material_app.dart index 8076d94f1d..704d06c23e 100644 --- a/packages/flutter/lib/src/material/material_app.dart +++ b/packages/flutter/lib/src/material/material_app.dart @@ -4,7 +4,6 @@ import 'dart:sky' as sky; -import 'package:sky/material.dart'; import 'package:sky/painting.dart'; import 'package:sky/services.dart'; import 'package:sky/widgets.dart'; diff --git a/packages/flutter/lib/src/material/material_button.dart b/packages/flutter/lib/src/material/material_button.dart index 4db52a39b3..23f28e9353 100644 --- a/packages/flutter/lib/src/material/material_button.dart +++ b/packages/flutter/lib/src/material/material_button.dart @@ -3,9 +3,9 @@ // found in the LICENSE file. import 'package:sky/gestures.dart'; -import 'package:sky/material.dart'; import 'package:sky/widgets.dart'; +import 'colors.dart'; import 'ink_well.dart'; import 'material.dart'; import 'theme.dart'; diff --git a/packages/flutter/lib/src/material/popup_menu.dart b/packages/flutter/lib/src/material/popup_menu.dart index 6b1922bdac..373ef046ee 100644 --- a/packages/flutter/lib/src/material/popup_menu.dart +++ b/packages/flutter/lib/src/material/popup_menu.dart @@ -6,12 +6,12 @@ import 'dart:async'; import 'dart:sky' as sky; import 'package:sky/animation.dart'; -import 'package:sky/material.dart'; import 'package:sky/painting.dart'; import 'package:sky/widgets.dart'; import 'ink_well.dart'; import 'popup_menu_item.dart'; +import 'shadows.dart'; import 'theme.dart'; const Duration _kMenuDuration = const Duration(milliseconds: 300); diff --git a/packages/flutter/lib/src/material/raised_button.dart b/packages/flutter/lib/src/material/raised_button.dart index 3484f6c8a7..a41b8624ac 100644 --- a/packages/flutter/lib/src/material/raised_button.dart +++ b/packages/flutter/lib/src/material/raised_button.dart @@ -3,9 +3,9 @@ // found in the LICENSE file. import 'package:sky/gestures.dart'; -import 'package:sky/material.dart'; import 'package:sky/widgets.dart'; +import 'colors.dart'; import 'material_button.dart'; import 'theme.dart'; diff --git a/packages/flutter/lib/src/material/scaffold.dart b/packages/flutter/lib/src/material/scaffold.dart index fb65a23884..76fbb5e84d 100644 --- a/packages/flutter/lib/src/material/scaffold.dart +++ b/packages/flutter/lib/src/material/scaffold.dart @@ -4,10 +4,11 @@ import 'dart:sky' as sky; -import 'package:sky/material.dart'; import 'package:sky/rendering.dart'; import 'package:sky/widgets.dart'; +import 'constants.dart'; + class Scaffold extends StatelessComponent { Scaffold({ Key key, diff --git a/packages/flutter/lib/src/material/snack_bar.dart b/packages/flutter/lib/src/material/snack_bar.dart index bc66cceb01..7c663fecd2 100644 --- a/packages/flutter/lib/src/material/snack_bar.dart +++ b/packages/flutter/lib/src/material/snack_bar.dart @@ -4,12 +4,13 @@ import 'package:sky/animation.dart'; import 'package:sky/gestures.dart'; -import 'package:sky/material.dart'; import 'package:sky/painting.dart'; import 'package:sky/widgets.dart'; +import 'constants.dart'; import 'material.dart'; import 'theme.dart'; +import 'typography.dart'; const double _kSideMargins = 24.0; const double _kVerticalPadding = 14.0; diff --git a/packages/flutter/lib/src/material/tool_bar.dart b/packages/flutter/lib/src/material/tool_bar.dart index 16fc3398a8..6be4c60d65 100644 --- a/packages/flutter/lib/src/material/tool_bar.dart +++ b/packages/flutter/lib/src/material/tool_bar.dart @@ -2,12 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:sky/material.dart'; import 'package:sky/painting.dart'; import 'package:sky/widgets.dart'; +import 'constants.dart'; import 'icon.dart'; +import 'shadows.dart'; import 'theme.dart'; +import 'typography.dart'; class ToolBar extends StatelessComponent { ToolBar({ From b07ff55044dad6b854c71ad487388f657a71d697 Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Fri, 9 Oct 2015 11:20:26 -0700 Subject: [PATCH 29/84] Add a flag to TextPainter to use ParagraphBuilder This patch makes it easier to experiment with work on ParagraphBuilder. --- .../lib/src/painting/text_painter.dart | 139 +++++++++++++++++- .../flutter/lib/src/painting/text_style.dart | 3 + 2 files changed, 141 insertions(+), 1 deletion(-) diff --git a/packages/flutter/lib/src/painting/text_painter.dart b/packages/flutter/lib/src/painting/text_painter.dart index c51184d86e..81bb8c5c57 100644 --- a/packages/flutter/lib/src/painting/text_painter.dart +++ b/packages/flutter/lib/src/painting/text_painter.dart @@ -16,6 +16,9 @@ abstract class TextSpan { void _applyStyleToContainer(sky.Element container) { } + + void build(sky.ParagraphBuilder builder); + sky.ParagraphStyle get paragraphStyle => null; } /// An immutable span of unstyled text @@ -31,6 +34,10 @@ class PlainTextSpan extends TextSpan { return owner.createText(text); } + void build(sky.ParagraphBuilder builder) { + builder.addText(text); + } + bool operator ==(other) => other is PlainTextSpan && text == other.text; int get hashCode => text.hashCode; @@ -59,6 +66,15 @@ class StyledTextSpan extends TextSpan { return parent; } + void build(sky.ParagraphBuilder builder) { + builder.pushStyle(style.textStyle); + for (TextSpan child in children) + child.build(builder); + builder.pop(); + } + + sky.ParagraphStyle get paragraphStyle => style.paragraphStyle; + void _applyStyleToContainer(sky.Element container) { style.applyToContainerCSSStyle(container.style); } @@ -97,14 +113,24 @@ class StyledTextSpan extends TextSpan { } } +const bool _kEnableNewTextPainter = false; + /// An object that paints a [TextSpan] into a canvas class TextPainter { - TextPainter(TextSpan text) { + factory TextPainter(TextSpan text) { + if (_kEnableNewTextPainter) + return new _NewTextPainter(text); + return new TextPainter._(text); + } + + TextPainter._(TextSpan text) { _layoutRoot.rootElement = _document.createElement('p'); assert(text != null); this.text = text; } + sky.Paragraph _paragraph; + final sky.Document _document = new sky.Document(); final sky.LayoutRoot _layoutRoot = new sky.LayoutRoot(); bool _needsLayout = true; @@ -214,3 +240,114 @@ class TextPainter { canvas.translate(-offset.dx, -offset.dy); } } + +class _NewTextPainter implements TextPainter { + _NewTextPainter(TextSpan text) { + this.text = text; + } + + sky.Paragraph _paragraph; + bool _needsLayout = true; + + TextSpan _text; + /// The (potentially styled) text to paint + TextSpan get text => _text; + void set text(TextSpan value) { + if (_text == value) + return; + _text = value; + sky.ParagraphBuilder builder = new sky.ParagraphBuilder(); + _text.build(builder); + _paragraph = builder.build(_text.paragraphStyle); + _needsLayout = true; + } + + /// The minimum width at which to layout the text + double get minWidth => _paragraph.minWidth; + void set minWidth(value) { + if (_paragraph.minWidth == value) + return; + _paragraph.minWidth = value; + _needsLayout = true; + } + + /// The maximum width at which to layout the text + double get maxWidth => _paragraph.maxWidth; + void set maxWidth(value) { + if (_paragraph.maxWidth == value) + return; + _paragraph.maxWidth = value; + _needsLayout = true; + } + + /// The minimum height at which to layout the text + double get minHeight => _paragraph.minHeight; + void set minHeight(value) { + if (_paragraph.minHeight == value) + return; + _paragraph.minHeight = value; + _needsLayout = true; + } + + /// The maximum height at which to layout the text + double get maxHeight => _paragraph.maxHeight; + void set maxHeight(value) { + if (_paragraph.maxHeight == value) + return; + _paragraph.maxHeight = value; + } + + // Unfortunately, using full precision floating point here causes bad layouts + // because floating point math isn't associative. If we add and subtract + // padding, for example, we'll get different values when we estimate sizes and + // when we actually compute layout because the operations will end up associated + // differently. To work around this problem for now, we round fractional pixel + // values up to the nearest whole pixel value. The right long-term fix is to do + // layout using fixed precision arithmetic. + double _applyFloatingPointHack(double layoutValue) { + return layoutValue.ceilToDouble(); + } + + /// The width at which decreasing the width of the text would prevent it from painting itself completely within its bounds + double get minContentWidth { + assert(!_needsLayout); + return _applyFloatingPointHack(_paragraph.minIntrinsicWidth); + } + + /// The width at which increasing the width of the text no longer decreases the height + double get maxContentWidth { + assert(!_needsLayout); + return _applyFloatingPointHack(_paragraph.maxIntrinsicWidth); + } + + /// The height required to paint the text completely within its bounds + double get height { + assert(!_needsLayout); + return _applyFloatingPointHack(_paragraph.height); + } + + /// The distance from the top of the text to the first baseline of the given type + double computeDistanceToActualBaseline(TextBaseline baseline) { + assert(!_needsLayout); + switch (baseline) { + case TextBaseline.alphabetic: + return _paragraph.alphabeticBaseline; + case TextBaseline.ideographic: + return _paragraph.ideographicBaseline; + } + } + + /// Compute the visual position of the glyphs for painting the text + void layout() { + if (!_needsLayout) + return; + _paragraph.layout(); + _needsLayout = false; + } + + /// Paint the text onto the given canvas at the given offset + void paint(sky.Canvas canvas, sky.Offset offset) { + assert(!_needsLayout && "Please call layout() before paint() to position the text before painting it." is String); + _paragraph.paint(canvas, offset); + } +} diff --git a/packages/flutter/lib/src/painting/text_style.dart b/packages/flutter/lib/src/painting/text_style.dart index 617778c213..502c95cf76 100644 --- a/packages/flutter/lib/src/painting/text_style.dart +++ b/packages/flutter/lib/src/painting/text_style.dart @@ -152,6 +152,9 @@ class TextStyle { return toCSS[decorationStyle]; } + sky.TextStyle get textStyle => null; + sky.ParagraphStyle get paragraphStyle => null; + /// Program this text style into the engine /// /// Note: This function will likely be removed when we refactor the interface From dfc7f00a888e7a1d360f0438cf28fd5e7de0528d Mon Sep 17 00:00:00 2001 From: Hixie Date: Fri, 9 Oct 2015 09:23:06 -0700 Subject: [PATCH 30/84] Remove workarounds that avoided 'super' in mixins Dart supports this properly now. --- packages/flutter/lib/src/rendering/box.dart | 3 +- packages/flutter/lib/src/rendering/node.dart | 20 ++----- .../flutter/lib/src/rendering/object.dart | 59 +++++++++++-------- 3 files changed, 40 insertions(+), 42 deletions(-) diff --git a/packages/flutter/lib/src/rendering/box.dart b/packages/flutter/lib/src/rendering/box.dart index 33a5b4ae23..57a79c5eab 100644 --- a/packages/flutter/lib/src/rendering/box.dart +++ b/packages/flutter/lib/src/rendering/box.dart @@ -631,7 +631,8 @@ abstract class RenderBox extends RenderObject { String debugDescribeSettings(String prefix) => '${super.debugDescribeSettings(prefix)}${prefix}size: ${size}\n'; } -/// A mixin that provides useful default behaviors for boxes with children managed by the [ContainerRenderObjectMixin] mixin +/// A mixin that provides useful default behaviors for boxes with children +/// managed by the [ContainerRenderObjectMixin] mixin. /// /// By convention, this class doesn't override any members of the superclass. /// Instead, it provides helpful functions that subclasses can call as diff --git a/packages/flutter/lib/src/rendering/node.dart b/packages/flutter/lib/src/rendering/node.dart index e4902add2b..fb989de505 100644 --- a/packages/flutter/lib/src/rendering/node.dart +++ b/packages/flutter/lib/src/rendering/node.dart @@ -68,32 +68,20 @@ class AbstractNode { /// Mark this node as attached. /// - /// Typically called only from overrides of [attachChildren] and to mark the - /// root of a tree attached. + /// Typically called only from the parent's attach(), and to mark the root of + /// a tree attached. void attach() { _attached = true; - attachChildren(); } - /// Override this function in subclasses with child to call attach() for each - /// child. Do not call directly. - attachChildren() { } - /// Mark this node as detached. /// - /// Typically called only from overrides for [detachChildren] and to mark the - /// root of a tree detached. + /// Typically called only from the parent's detach(), and to mark the root of + /// a tree detached. void detach() { _attached = false; - detachChildren(); } - /// Override this function in subclasses with child to call detach() for each - /// child. Do not call directly. - detachChildren() { } - - // TODO(ianh): remove attachChildren()/detachChildren() workaround once mixins can use super. - AbstractNode _parent; /// The parent of this node in the tree. AbstractNode get parent => _parent; diff --git a/packages/flutter/lib/src/rendering/object.dart b/packages/flutter/lib/src/rendering/object.dart index 4bedb368f7..451a35e594 100644 --- a/packages/flutter/lib/src/rendering/object.dart +++ b/packages/flutter/lib/src/rendering/object.dart @@ -25,15 +25,15 @@ typedef sky.Shader ShaderCallback(Rect bounds); /// input parameters to the parent's layout algorithm or their position relative /// to other children. class ParentData { - void detach() { - detachSiblings(); - } - void detachSiblings() { } // workaround for lack of inter-class mixins in Dart + /// Called when the RenderObject is removed from the tree. + void detach() { } - /// Override this function in subclasses to merge in data from other instance into this instance + /// Override this function in subclasses to merge in data from other instance + /// into this instance. void merge(ParentData other) { assert(other.runtimeType == this.runtimeType); } + String toString() => ''; } @@ -1158,11 +1158,13 @@ abstract class RenderObjectWithChildMixin implem if (_child != null) adoptChild(_child); } - void attachChildren() { + void attach() { + super.attach(); if (_child != null) _child.attach(); } - void detachChildren() { + void detach() { + super.detach(); if (_child != null) _child.detach(); } @@ -1178,14 +1180,15 @@ abstract class RenderObjectWithChildMixin implem } /// Parent data to support a doubly-linked list of children -abstract class ContainerParentDataMixin { +abstract class ContainerParentDataMixin implements ParentData { /// The previous sibling in the parent's child list ChildType previousSibling; /// The next sibling in the parent's child list ChildType nextSibling; /// Clear the sibling pointers. - void detachSiblings() { + void detach() { + super.detach(); if (previousSibling != null) { assert(previousSibling.parentData is ContainerParentDataMixin); assert(previousSibling != this); @@ -1362,6 +1365,27 @@ abstract class ContainerRenderObjectMixin Date: Fri, 9 Oct 2015 13:22:12 -0700 Subject: [PATCH 31/84] Adds debug drawing for weld joints in sprite physics --- .../flutter_sprites/lib/physics_node.dart | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/packages/flutter_sprites/lib/physics_node.dart b/packages/flutter_sprites/lib/physics_node.dart index 69d74829f0..57811e75cf 100644 --- a/packages/flutter_sprites/lib/physics_node.dart +++ b/packages/flutter_sprites/lib/physics_node.dart @@ -240,7 +240,56 @@ class PhysicsNode extends Node { } } + // Draw joints + shapePaint.color = new Color(0xff0000ff); + for (box2d.JointEdge edge = body.getJointList(); edge != null; edge = edge.next) { + box2d.Joint joint = edge.joint; + + // Make sure we only draw each joint once + if (joint.getBodyB() == body) + continue; + + // Get anchor A + Vector2 anchorA = new Vector2.zero(); + joint.getAnchorA(anchorA); + + Point ptAnchorA = new Point( + anchorA.x * b2WorldToNodeConversionFactor, + anchorA.y * b2WorldToNodeConversionFactor + ); + + // Get anchor B + Vector2 anchorB = new Vector2.zero(); + joint.getAnchorB(anchorB); + + Point ptAnchorB = new Point( + anchorB.x * b2WorldToNodeConversionFactor, + anchorB.y * b2WorldToNodeConversionFactor + ); + + // Get body A position + Point ptBodyA = new Point( + joint.getBodyA().position.x * b2WorldToNodeConversionFactor, + joint.getBodyA().position.y * b2WorldToNodeConversionFactor + ); + + Point ptBodyB = new Point( + joint.getBodyB().position.x * b2WorldToNodeConversionFactor, + joint.getBodyB().position.y * b2WorldToNodeConversionFactor + ); + + // Draw the joint depending on type + box2d.JointType type = joint.getType(); + + if (type == box2d.JointType.WELD) { + // Draw weld joint + canvas.drawCircle(ptAnchorA, 5.0, shapePaint); + + canvas.drawLine(ptBodyA, ptAnchorA, shapePaint); + canvas.drawLine(ptAnchorB, ptBodyB, shapePaint); + } + } } } } From 8915cf0b8946c8995518b5eb50a5f9a6a43a0df3 Mon Sep 17 00:00:00 2001 From: Hixie Date: Fri, 9 Oct 2015 14:03:54 -0700 Subject: [PATCH 32/84] Avoid painting previous routes redundantly ...once the animation is done. --- packages/flutter/lib/src/widgets/navigator.dart | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/packages/flutter/lib/src/widgets/navigator.dart b/packages/flutter/lib/src/widgets/navigator.dart index 97c9e63255..c6345a1a02 100644 --- a/packages/flutter/lib/src/widgets/navigator.dart +++ b/packages/flutter/lib/src/widgets/navigator.dart @@ -112,6 +112,16 @@ class NavigatorState extends State { return index >= 0 && index <= _currentPosition; } + void _didCompleteRoute(Route route) { + assert(_history.contains(route)); + if (route.isActuallyOpaque) { + setState(() { + // we need to rebuild because our build function depends on + // whether the route is opaque or not. + }); + } + } + void _didDismissRoute(Route route) { assert(_history.contains(route)); if (_history.lastIndexOf(route) <= _currentPosition) @@ -240,7 +250,9 @@ abstract class Route { } void _handlePerformanceStatusChanged(PerformanceStatus status) { - if (status == PerformanceStatus.dismissed) { + if (status == PerformanceStatus.completed) { + _navigator._didCompleteRoute(this); + } else if (status == PerformanceStatus.dismissed) { _navigator._didDismissRoute(this); _navigator._removeRoute(this); _navigator = null; @@ -266,8 +278,6 @@ abstract class PerformanceRoute extends Route { Duration get transitionDuration; - bool get isActuallyOpaque => (performance == null || _performance.isCompleted) && opaque; - Widget build(NavigatorState navigator, PerformanceView nextRoutePerformance); void didPush(NavigatorState navigator) { From ee7c72f4daa6d1e2b2f1bb0bfe365096d913fb60 Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Fri, 9 Oct 2015 14:04:54 -0700 Subject: [PATCH 33/84] Make it fast to draw color icons Instead of using a ColorFilter, plumb the information down to Icon and thereby to Image. --- .../flutter/lib/src/material/icon_button.dart | 29 +++++++++++-------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/packages/flutter/lib/src/material/icon_button.dart b/packages/flutter/lib/src/material/icon_button.dart index a2b826d342..1103a3547a 100644 --- a/packages/flutter/lib/src/material/icon_button.dart +++ b/packages/flutter/lib/src/material/icon_button.dart @@ -10,26 +10,31 @@ import 'package:sky/widgets.dart'; import 'icon.dart'; class IconButton extends StatelessComponent { - const IconButton({ Key key, this.icon, this.onPressed, this.color }) : super(key: key); + const IconButton({ + Key key, + this.icon, + this.color, + this.colorFilter, + this.onPressed + }) : super(key: key); final String icon; - final Color color; + final IconThemeColor color; + final sky.ColorFilter colorFilter; final GestureTapCallback onPressed; Widget build(BuildContext context) { - Widget child = new Icon(type: icon, size: 24); - if (color != null) { - child = new ColorFilter( - color: color, - transferMode: sky.TransferMode.srcATop, - child: child - ); - } return new GestureDetector( onTap: onPressed, child: new Padding( - child: child, - padding: const EdgeDims.all(8.0)) + padding: const EdgeDims.all(8.0), + child: new Icon( + type: icon, + size: 24, + color: color, + colorFilter: colorFilter + ) + ) ); } } From 6e37b51c0ecca5b8a593f78592a33bc3d0cac11b Mon Sep 17 00:00:00 2001 From: Collin Jackson Date: Fri, 9 Oct 2015 14:54:03 -0700 Subject: [PATCH 34/84] Painting images should not anti-alias (improves performance) --- packages/flutter/lib/src/painting/box_painter.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/flutter/lib/src/painting/box_painter.dart b/packages/flutter/lib/src/painting/box_painter.dart index 3e0d98fe5f..9c3974aea9 100644 --- a/packages/flutter/lib/src/painting/box_painter.dart +++ b/packages/flutter/lib/src/painting/box_painter.dart @@ -456,7 +456,7 @@ void paintImage({ break; } // TODO(abarth): Implement |repeat|. - Paint paint = new Paint(); + Paint paint = new Paint()..isAntiAlias = false; if (colorFilter != null) paint.colorFilter = colorFilter; double dx = (bounds.width - destinationSize.width) * positionX; From 32f18cfecb8b8070c0357a70971ab61034f50d8f Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Fri, 9 Oct 2015 14:55:33 -0700 Subject: [PATCH 35/84] Rev pub package --- packages/flutter/pubspec.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/flutter/pubspec.yaml b/packages/flutter/pubspec.yaml index b918da6e15..bcf8676157 100644 --- a/packages/flutter/pubspec.yaml +++ b/packages/flutter/pubspec.yaml @@ -1,15 +1,15 @@ name: sky -version: 0.0.54 +version: 0.0.55 author: Flutter Authors description: A framework for writing Flutter applications homepage: http://flutter.io dependencies: cassowary: ^0.1.7 material_design_icons: ^0.0.3 - mojo_services: '>=0.1.0 <0.2.0' - mojo: '>=0.1.0 <0.2.0' + mojo_services: '>=0.2.0 <0.3.0' + mojo: '>=0.2.0 <0.3.0' newton: ^0.1.4 - sky_engine: ^0.0.32 + sky_engine: ^0.0.33 sky_services: ^0.0.32 sky_tools: ^0.0.15 vector_math: ^1.4.3 From 28d769f3ecb8fe612a1f22dc79e1b13d848b50ff Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Fri, 9 Oct 2015 18:56:16 -0700 Subject: [PATCH 36/84] Fix updater pubspec --- packages/updater/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/updater/pubspec.yaml b/packages/updater/pubspec.yaml index 28de3eed1b..ffff047257 100644 --- a/packages/updater/pubspec.yaml +++ b/packages/updater/pubspec.yaml @@ -4,7 +4,7 @@ author: Flutter Authors description: The autoupdater for flutter homepage: http://flutter.io dependencies: - mojo: '>=0.1.0 <0.2.0' + mojo: '>=0.2.0 <0.3.0' sky: any sky_services: any path: any From 5b37f8750d4ffd1fc29cb9a6e75ed04c75200925 Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Fri, 9 Oct 2015 19:27:13 -0700 Subject: [PATCH 37/84] Rename dart:sky to dart:ui --- examples/BUILD.gn | 2 +- examples/demo_launcher/BUILD.gn | 2 +- examples/game/lib/game_demo.dart | 2 +- examples/game/test_bed.dart | 2 +- examples/game/test_drawatlas.dart | 2 +- examples/game/test_performance.dart | 2 +- examples/game/test_physics.dart | 2 +- examples/mine_digger/lib/main.dart | 2 +- examples/raw/baseline.dart | 2 +- examples/raw/hello_world.dart | 2 +- examples/raw/mutating-dom.dart | 2 +- examples/raw/painting.dart | 2 +- examples/raw/shadow.dart | 2 +- examples/raw/spinning_arabic.dart | 2 +- examples/raw/spinning_image.dart | 2 +- examples/raw/spinning_square.dart | 2 +- examples/rendering/baseline.dart | 2 +- examples/rendering/borders.dart | 2 +- examples/rendering/flex.dart | 2 +- examples/rendering/interactive_flex.dart | 2 +- examples/rendering/sector_layout.dart | 2 +- examples/rendering/shadowed_box.dart | 2 +- examples/rendering/simple_autolayout.dart | 2 +- examples/rendering/solid_color_box.dart | 2 +- examples/rendering/spinning_flex.dart | 2 +- examples/rendering/touch_demo.dart | 2 +- examples/rendering/transform.dart | 2 +- examples/stocks/lib/main.dart | 2 +- examples/widgets/card_collection.dart | 2 +- examples/widgets/overlay_geometry.dart | 2 +- examples/widgets/spinning_mixed.dart | 2 +- packages/flutter/lib/src/animation/animated_value.dart | 2 +- packages/flutter/lib/src/animation/scheduler.dart | 2 +- packages/flutter/lib/src/animation/scroll_behavior.dart | 2 +- packages/flutter/lib/src/gestures/drag.dart | 2 +- packages/flutter/lib/src/gestures/long_press.dart | 2 +- packages/flutter/lib/src/gestures/pointer_router.dart | 2 +- packages/flutter/lib/src/gestures/recognizer.dart | 2 +- packages/flutter/lib/src/gestures/scale.dart | 2 +- packages/flutter/lib/src/gestures/show_press.dart | 2 +- packages/flutter/lib/src/gestures/tap.dart | 2 +- packages/flutter/lib/src/material/checkbox.dart | 2 +- packages/flutter/lib/src/material/colors.dart | 2 +- packages/flutter/lib/src/material/drawer_item.dart | 2 +- packages/flutter/lib/src/material/icon.dart | 2 +- packages/flutter/lib/src/material/icon_button.dart | 2 +- packages/flutter/lib/src/material/ink_well.dart | 2 +- packages/flutter/lib/src/material/material_app.dart | 2 +- packages/flutter/lib/src/material/popup_menu.dart | 2 +- packages/flutter/lib/src/material/progress_indicator.dart | 2 +- packages/flutter/lib/src/material/radial_reaction.dart | 4 ++-- packages/flutter/lib/src/material/radio.dart | 2 +- packages/flutter/lib/src/material/scaffold.dart | 2 +- packages/flutter/lib/src/material/shadows.dart | 2 +- packages/flutter/lib/src/material/switch.dart | 2 +- packages/flutter/lib/src/material/tabs.dart | 2 +- packages/flutter/lib/src/material/theme_data.dart | 2 +- packages/flutter/lib/src/material/typography.dart | 2 +- packages/flutter/lib/src/painting/box_painter.dart | 4 ++-- packages/flutter/lib/src/painting/shadows.dart | 2 +- packages/flutter/lib/src/painting/text_painter.dart | 2 +- packages/flutter/lib/src/painting/text_style.dart | 6 +++--- packages/flutter/lib/src/rendering/binding.dart | 2 +- packages/flutter/lib/src/rendering/box.dart | 2 +- packages/flutter/lib/src/rendering/debug.dart | 2 +- packages/flutter/lib/src/rendering/hit_test.dart | 2 +- packages/flutter/lib/src/rendering/image.dart | 2 +- packages/flutter/lib/src/rendering/layer.dart | 4 ++-- packages/flutter/lib/src/rendering/object.dart | 6 +++--- packages/flutter/lib/src/rendering/proxy_box.dart | 2 +- packages/flutter/lib/src/rendering/toggleable.dart | 2 +- packages/flutter/lib/src/rendering/view.dart | 2 +- packages/flutter/lib/src/rendering/viewport.dart | 2 +- packages/flutter/lib/src/services/activity.dart | 2 +- packages/flutter/lib/src/services/asset_bundle.dart | 4 ++-- packages/flutter/lib/src/services/embedder.dart | 2 +- packages/flutter/lib/src/services/image_cache.dart | 2 +- packages/flutter/lib/src/services/image_decoder.dart | 2 +- packages/flutter/lib/src/services/image_resource.dart | 2 +- packages/flutter/lib/src/services/shell.dart | 2 +- packages/flutter/lib/src/widgets/basic.dart | 2 +- packages/flutter/lib/src/widgets/dismissable.dart | 2 +- packages/flutter/lib/src/widgets/drag_target.dart | 2 +- packages/flutter/lib/src/widgets/gesture_detector.dart | 2 +- packages/flutter/lib/src/widgets/scrollable.dart | 2 +- packages/flutter_sprites/lib/skysprites.dart | 2 +- packages/unit/test/engine/append_child_test.dart | 2 +- packages/unit/test/engine/canvas_test.dart | 4 ++-- packages/unit/test/engine/color_test.dart | 2 +- .../unit/test/engine/document_child_mutations_test.dart | 2 +- packages/unit/test/engine/dom_utils.dart | 2 +- packages/unit/test/engine/get_child_elements_test.dart | 2 +- packages/unit/test/engine/inline_style_test.dart | 2 +- packages/unit/test/engine/insert_before_test.dart | 2 +- packages/unit/test/engine/mock_events.dart | 4 ++-- packages/unit/test/engine/owner_scope_test.dart | 2 +- packages/unit/test/engine/paragraph_builder_test.dart | 2 +- packages/unit/test/engine/rect_test.dart | 2 +- packages/unit/test/engine/replace_child_test.dart | 2 +- packages/unit/test/engine/text_test.dart | 2 +- packages/unit/test/gestures/pointer_router_test.dart | 2 +- packages/unit/test/gestures/scale_test.dart | 2 +- packages/unit/test/gestures/scroll_test.dart | 2 +- packages/unit/test/rendering/image_test.dart | 2 +- packages/unit/test/widget/shader_mask_test.dart | 2 +- packages/unit/test/widget/widget_tester.dart | 2 +- 106 files changed, 116 insertions(+), 116 deletions(-) diff --git a/examples/BUILD.gn b/examples/BUILD.gn index 5ead42c2f1..f8061ae382 100644 --- a/examples/BUILD.gn +++ b/examples/BUILD.gn @@ -7,7 +7,7 @@ group("examples") { deps = [ "//examples/demo_launcher", - "//examples/fitness", + #"//examples/fitness", "//examples/game", "//examples/mine_digger", "//examples/rendering", diff --git a/examples/demo_launcher/BUILD.gn b/examples/demo_launcher/BUILD.gn index a5cd5dae67..a934fb9932 100644 --- a/examples/demo_launcher/BUILD.gn +++ b/examples/demo_launcher/BUILD.gn @@ -12,7 +12,7 @@ sky_app("demo_launcher") { apk_name = "SkyDemo" bundles = [ - "//examples/fitness", + #"//examples/fitness", "//examples/game", "//examples/mine_digger", "//examples/rendering:interactive_flex", diff --git a/examples/game/lib/game_demo.dart b/examples/game/lib/game_demo.dart index 541edd2769..652067bd44 100644 --- a/examples/game/lib/game_demo.dart +++ b/examples/game/lib/game_demo.dart @@ -2,7 +2,7 @@ library game; import 'dart:async'; import 'dart:math' as math; -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'package:sky/rendering.dart'; import 'package:skysprites/skysprites.dart'; diff --git a/examples/game/test_bed.dart b/examples/game/test_bed.dart index b2dc7fbc6e..5588ae8d07 100644 --- a/examples/game/test_bed.dart +++ b/examples/game/test_bed.dart @@ -1,4 +1,4 @@ -import 'dart:sky'; +import 'dart:ui'; import 'package:sky/material.dart'; import 'package:sky/rendering.dart'; diff --git a/examples/game/test_drawatlas.dart b/examples/game/test_drawatlas.dart index edf568e5ae..82422dd8a7 100644 --- a/examples/game/test_drawatlas.dart +++ b/examples/game/test_drawatlas.dart @@ -1,4 +1,4 @@ -import 'dart:sky'; +import 'dart:ui'; import 'package:sky/material.dart'; import 'package:sky/rendering.dart'; diff --git a/examples/game/test_performance.dart b/examples/game/test_performance.dart index 44d363c12f..4bd4255987 100644 --- a/examples/game/test_performance.dart +++ b/examples/game/test_performance.dart @@ -1,4 +1,4 @@ -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'dart:math' as math; import 'package:sky/material.dart'; diff --git a/examples/game/test_physics.dart b/examples/game/test_physics.dart index 4c2ecc10b6..4e8986e6dc 100644 --- a/examples/game/test_physics.dart +++ b/examples/game/test_physics.dart @@ -1,4 +1,4 @@ -import 'dart:sky'; +import 'dart:ui'; import 'package:sky/material.dart'; import 'package:sky/rendering.dart'; diff --git a/examples/mine_digger/lib/main.dart b/examples/mine_digger/lib/main.dart index 095b010f09..23cc79ff30 100644 --- a/examples/mine_digger/lib/main.dart +++ b/examples/mine_digger/lib/main.dart @@ -1,7 +1,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'dart:math'; import 'package:sky/material.dart'; diff --git a/examples/raw/baseline.dart b/examples/raw/baseline.dart index d0f083b55d..ef6d84c2a2 100644 --- a/examples/raw/baseline.dart +++ b/examples/raw/baseline.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'dart:typed_data'; void drawText(sky.Canvas canvas, String lh) { diff --git a/examples/raw/hello_world.dart b/examples/raw/hello_world.dart index a63ad0e137..66b56630af 100644 --- a/examples/raw/hello_world.dart +++ b/examples/raw/hello_world.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'dart:typed_data'; sky.Color color; diff --git a/examples/raw/mutating-dom.dart b/examples/raw/mutating-dom.dart index 208fa53719..0178584733 100644 --- a/examples/raw/mutating-dom.dart +++ b/examples/raw/mutating-dom.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'dart:math' as math; -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'dart:typed_data'; const kMaxIterations = 100; diff --git a/examples/raw/painting.dart b/examples/raw/painting.dart index b24f0f73cc..41273a0b8b 100644 --- a/examples/raw/painting.dart +++ b/examples/raw/painting.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'dart:math' as math; import 'dart:typed_data'; diff --git a/examples/raw/shadow.dart b/examples/raw/shadow.dart index bb440f575f..453cbb5262 100644 --- a/examples/raw/shadow.dart +++ b/examples/raw/shadow.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'dart:typed_data'; sky.Picture paint(sky.Rect paintBounds) { diff --git a/examples/raw/spinning_arabic.dart b/examples/raw/spinning_arabic.dart index 1d2389e5b7..09d1e0f203 100644 --- a/examples/raw/spinning_arabic.dart +++ b/examples/raw/spinning_arabic.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'dart:math' as math; -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'dart:typed_data'; double timeBase = null; diff --git a/examples/raw/spinning_image.dart b/examples/raw/spinning_image.dart index 03b4fd12a3..76e9c81155 100644 --- a/examples/raw/spinning_image.dart +++ b/examples/raw/spinning_image.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'dart:math' as math; -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'dart:typed_data'; import 'package:sky/services.dart'; diff --git a/examples/raw/spinning_square.dart b/examples/raw/spinning_square.dart index 3b036e6021..1cb85c884c 100644 --- a/examples/raw/spinning_square.dart +++ b/examples/raw/spinning_square.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'dart:math' as math; -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'dart:typed_data'; double timeBase = null; diff --git a/examples/rendering/baseline.dart b/examples/rendering/baseline.dart index 9237c9106d..3488e23df8 100644 --- a/examples/rendering/baseline.dart +++ b/examples/rendering/baseline.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'package:sky/rendering.dart'; diff --git a/examples/rendering/borders.dart b/examples/rendering/borders.dart index 1f5777a852..8a9df8d41f 100644 --- a/examples/rendering/borders.dart +++ b/examples/rendering/borders.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'package:sky/rendering.dart'; diff --git a/examples/rendering/flex.dart b/examples/rendering/flex.dart index f0ca8dafd3..a8b3a8b4cb 100644 --- a/examples/rendering/flex.dart +++ b/examples/rendering/flex.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'package:sky/rendering.dart'; import 'solid_color_box.dart'; diff --git a/examples/rendering/interactive_flex.dart b/examples/rendering/interactive_flex.dart index cfebd7cc6f..aee0074544 100644 --- a/examples/rendering/interactive_flex.dart +++ b/examples/rendering/interactive_flex.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'dart:math' as math; import 'package:sky/services.dart'; diff --git a/examples/rendering/sector_layout.dart b/examples/rendering/sector_layout.dart index d57cb2a1bc..1bafaeb52f 100644 --- a/examples/rendering/sector_layout.dart +++ b/examples/rendering/sector_layout.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'dart:math' as math; -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'package:sky/rendering.dart'; diff --git a/examples/rendering/shadowed_box.dart b/examples/rendering/shadowed_box.dart index b48c532121..65f70d73c1 100644 --- a/examples/rendering/shadowed_box.dart +++ b/examples/rendering/shadowed_box.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:sky'; +import 'dart:ui'; import 'package:sky/rendering.dart'; import 'package:sky/material.dart'; diff --git a/examples/rendering/simple_autolayout.dart b/examples/rendering/simple_autolayout.dart index c8b65b94bf..a62dba873f 100644 --- a/examples/rendering/simple_autolayout.dart +++ b/examples/rendering/simple_autolayout.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:sky'; +import 'dart:ui'; import 'package:cassowary/cassowary.dart' as al; import 'package:sky/rendering.dart'; diff --git a/examples/rendering/solid_color_box.dart b/examples/rendering/solid_color_box.dart index 36b772e360..136cd6eeb8 100644 --- a/examples/rendering/solid_color_box.dart +++ b/examples/rendering/solid_color_box.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'package:sky/rendering.dart'; diff --git a/examples/rendering/spinning_flex.dart b/examples/rendering/spinning_flex.dart index 1e72aac95a..6c1455f35b 100644 --- a/examples/rendering/spinning_flex.dart +++ b/examples/rendering/spinning_flex.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'package:sky/animation.dart'; import 'package:sky/rendering.dart'; diff --git a/examples/rendering/touch_demo.dart b/examples/rendering/touch_demo.dart index f00a781cc4..56c1d64aca 100644 --- a/examples/rendering/touch_demo.dart +++ b/examples/rendering/touch_demo.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'package:sky/material.dart'; import 'package:sky/rendering.dart'; diff --git a/examples/rendering/transform.dart b/examples/rendering/transform.dart index 4e675327d3..9b5d3a041d 100644 --- a/examples/rendering/transform.dart +++ b/examples/rendering/transform.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'package:sky/rendering.dart'; diff --git a/examples/stocks/lib/main.dart b/examples/stocks/lib/main.dart index f791c55e0c..1ba3fdd664 100644 --- a/examples/stocks/lib/main.dart +++ b/examples/stocks/lib/main.dart @@ -6,7 +6,7 @@ library stocks; import 'dart:async'; import 'dart:math' as math; -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'package:sky/gestures.dart'; import 'package:sky/material.dart'; diff --git a/examples/widgets/card_collection.dart b/examples/widgets/card_collection.dart index 0293a73d70..e2f45aee5f 100644 --- a/examples/widgets/card_collection.dart +++ b/examples/widgets/card_collection.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'package:sky/material.dart'; import 'package:sky/painting.dart'; diff --git a/examples/widgets/overlay_geometry.dart b/examples/widgets/overlay_geometry.dart index bc55cafbbe..9b28ca113f 100644 --- a/examples/widgets/overlay_geometry.dart +++ b/examples/widgets/overlay_geometry.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'package:sky/material.dart'; import 'package:sky/rendering.dart'; diff --git a/examples/widgets/spinning_mixed.dart b/examples/widgets/spinning_mixed.dart index eefb71fc26..cfde0b373a 100644 --- a/examples/widgets/spinning_mixed.dart +++ b/examples/widgets/spinning_mixed.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'package:sky/animation.dart'; import 'package:sky/material.dart'; diff --git a/packages/flutter/lib/src/animation/animated_value.dart b/packages/flutter/lib/src/animation/animated_value.dart index c237d39e64..47097d0f12 100644 --- a/packages/flutter/lib/src/animation/animated_value.dart +++ b/packages/flutter/lib/src/animation/animated_value.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:sky' show Color, Rect; +import 'dart:ui' show Color, Rect; import 'curves.dart'; diff --git a/packages/flutter/lib/src/animation/scheduler.dart b/packages/flutter/lib/src/animation/scheduler.dart index bfa585e0f3..5b8b4b9aaa 100644 --- a/packages/flutter/lib/src/animation/scheduler.dart +++ b/packages/flutter/lib/src/animation/scheduler.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'dart:collection'; -import 'dart:sky' as sky; +import 'dart:ui' as sky; /// Slows down animations by this factor to help in development. double timeDilation = 1.0; diff --git a/packages/flutter/lib/src/animation/scroll_behavior.dart b/packages/flutter/lib/src/animation/scroll_behavior.dart index 986caa04a8..b5be81572c 100644 --- a/packages/flutter/lib/src/animation/scroll_behavior.dart +++ b/packages/flutter/lib/src/animation/scroll_behavior.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'dart:math' as math; -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'package:newton/newton.dart'; diff --git a/packages/flutter/lib/src/gestures/drag.dart b/packages/flutter/lib/src/gestures/drag.dart index b93631c918..b130441ffd 100644 --- a/packages/flutter/lib/src/gestures/drag.dart +++ b/packages/flutter/lib/src/gestures/drag.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'arena.dart'; import 'recognizer.dart'; diff --git a/packages/flutter/lib/src/gestures/long_press.dart b/packages/flutter/lib/src/gestures/long_press.dart index 6e1114ead7..4ffd348223 100644 --- a/packages/flutter/lib/src/gestures/long_press.dart +++ b/packages/flutter/lib/src/gestures/long_press.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'arena.dart'; import 'constants.dart'; diff --git a/packages/flutter/lib/src/gestures/pointer_router.dart b/packages/flutter/lib/src/gestures/pointer_router.dart index 5de518b1e4..6918b3dc80 100644 --- a/packages/flutter/lib/src/gestures/pointer_router.dart +++ b/packages/flutter/lib/src/gestures/pointer_router.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:sky' as sky; +import 'dart:ui' as sky; /// A callback that receives a [sky.PointerEvent] typedef void PointerRoute(sky.PointerEvent event); diff --git a/packages/flutter/lib/src/gestures/recognizer.dart b/packages/flutter/lib/src/gestures/recognizer.dart index c36e4b162c..7c73f1988d 100644 --- a/packages/flutter/lib/src/gestures/recognizer.dart +++ b/packages/flutter/lib/src/gestures/recognizer.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'dart:async'; -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'arena.dart'; import 'constants.dart'; diff --git a/packages/flutter/lib/src/gestures/scale.dart b/packages/flutter/lib/src/gestures/scale.dart index 6f318b688c..dd0dfa094a 100644 --- a/packages/flutter/lib/src/gestures/scale.dart +++ b/packages/flutter/lib/src/gestures/scale.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'arena.dart'; import 'recognizer.dart'; diff --git a/packages/flutter/lib/src/gestures/show_press.dart b/packages/flutter/lib/src/gestures/show_press.dart index 85f4ede078..754aaa2ea1 100644 --- a/packages/flutter/lib/src/gestures/show_press.dart +++ b/packages/flutter/lib/src/gestures/show_press.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'arena.dart'; import 'constants.dart'; diff --git a/packages/flutter/lib/src/gestures/tap.dart b/packages/flutter/lib/src/gestures/tap.dart index 65bb5bcf0f..0c32edadbd 100644 --- a/packages/flutter/lib/src/gestures/tap.dart +++ b/packages/flutter/lib/src/gestures/tap.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'arena.dart'; import 'recognizer.dart'; diff --git a/packages/flutter/lib/src/material/checkbox.dart b/packages/flutter/lib/src/material/checkbox.dart index 17c57a2750..d02619e50e 100644 --- a/packages/flutter/lib/src/material/checkbox.dart +++ b/packages/flutter/lib/src/material/checkbox.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'package:sky/rendering.dart'; import 'package:sky/widgets.dart'; diff --git a/packages/flutter/lib/src/material/colors.dart b/packages/flutter/lib/src/material/colors.dart index bde576a1df..7df8de2529 100644 --- a/packages/flutter/lib/src/material/colors.dart +++ b/packages/flutter/lib/src/material/colors.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:sky' show Color; +import 'dart:ui' show Color; /// [Color] constants which represent Material design's /// [color palette](http://www.google.com/design/spec/style/color.html). diff --git a/packages/flutter/lib/src/material/drawer_item.dart b/packages/flutter/lib/src/material/drawer_item.dart index ac11f1900b..9a89515c65 100644 --- a/packages/flutter/lib/src/material/drawer_item.dart +++ b/packages/flutter/lib/src/material/drawer_item.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'package:sky/gestures.dart'; import 'package:sky/painting.dart'; diff --git a/packages/flutter/lib/src/material/icon.dart b/packages/flutter/lib/src/material/icon.dart index 6d0d119410..32facf2a25 100644 --- a/packages/flutter/lib/src/material/icon.dart +++ b/packages/flutter/lib/src/material/icon.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'package:sky/services.dart'; import 'package:sky/widgets.dart'; diff --git a/packages/flutter/lib/src/material/icon_button.dart b/packages/flutter/lib/src/material/icon_button.dart index 1103a3547a..dc355e9474 100644 --- a/packages/flutter/lib/src/material/icon_button.dart +++ b/packages/flutter/lib/src/material/icon_button.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'package:sky/gestures.dart'; import 'package:sky/widgets.dart'; diff --git a/packages/flutter/lib/src/material/ink_well.dart b/packages/flutter/lib/src/material/ink_well.dart index f77563509c..5140bbf1a0 100644 --- a/packages/flutter/lib/src/material/ink_well.dart +++ b/packages/flutter/lib/src/material/ink_well.dart @@ -4,7 +4,7 @@ import 'dart:async'; import 'dart:math' as math; -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'package:sky/animation.dart'; import 'package:sky/gestures.dart'; diff --git a/packages/flutter/lib/src/material/material_app.dart b/packages/flutter/lib/src/material/material_app.dart index 704d06c23e..f326b9ff04 100644 --- a/packages/flutter/lib/src/material/material_app.dart +++ b/packages/flutter/lib/src/material/material_app.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'package:sky/painting.dart'; import 'package:sky/services.dart'; diff --git a/packages/flutter/lib/src/material/popup_menu.dart b/packages/flutter/lib/src/material/popup_menu.dart index 373ef046ee..eee0b9fe25 100644 --- a/packages/flutter/lib/src/material/popup_menu.dart +++ b/packages/flutter/lib/src/material/popup_menu.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'dart:async'; -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'package:sky/animation.dart'; import 'package:sky/painting.dart'; diff --git a/packages/flutter/lib/src/material/progress_indicator.dart b/packages/flutter/lib/src/material/progress_indicator.dart index 398b6040ef..cf640a48f5 100644 --- a/packages/flutter/lib/src/material/progress_indicator.dart +++ b/packages/flutter/lib/src/material/progress_indicator.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'dart:math' as math; -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'package:sky/animation.dart'; import 'package:sky/widgets.dart'; diff --git a/packages/flutter/lib/src/material/radial_reaction.dart b/packages/flutter/lib/src/material/radial_reaction.dart index c2822cb9da..a3d68db5ee 100644 --- a/packages/flutter/lib/src/material/radial_reaction.dart +++ b/packages/flutter/lib/src/material/radial_reaction.dart @@ -3,8 +3,8 @@ // found in the LICENSE file. import 'dart:async'; -import 'dart:sky' as sky; -import 'dart:sky' show Point, Offset, Color, Paint; +import 'dart:ui' as sky; +import 'dart:ui' show Point, Offset, Color, Paint; import 'package:sky/animation.dart'; diff --git a/packages/flutter/lib/src/material/radio.dart b/packages/flutter/lib/src/material/radio.dart index 30ae00732c..fc54cc8893 100644 --- a/packages/flutter/lib/src/material/radio.dart +++ b/packages/flutter/lib/src/material/radio.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'package:sky/widgets.dart'; diff --git a/packages/flutter/lib/src/material/scaffold.dart b/packages/flutter/lib/src/material/scaffold.dart index 76fbb5e84d..3d4fbd85d4 100644 --- a/packages/flutter/lib/src/material/scaffold.dart +++ b/packages/flutter/lib/src/material/scaffold.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'package:sky/rendering.dart'; import 'package:sky/widgets.dart'; diff --git a/packages/flutter/lib/src/material/shadows.dart b/packages/flutter/lib/src/material/shadows.dart index dac0f3ed0e..17280dd092 100644 --- a/packages/flutter/lib/src/material/shadows.dart +++ b/packages/flutter/lib/src/material/shadows.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:sky' show Color, Offset; +import 'dart:ui' show Color, Offset; import 'package:sky/painting.dart'; diff --git a/packages/flutter/lib/src/material/switch.dart b/packages/flutter/lib/src/material/switch.dart index c221028e10..ab9573078b 100644 --- a/packages/flutter/lib/src/material/switch.dart +++ b/packages/flutter/lib/src/material/switch.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'dart:async'; -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'package:sky/painting.dart'; import 'package:sky/rendering.dart'; diff --git a/packages/flutter/lib/src/material/tabs.dart b/packages/flutter/lib/src/material/tabs.dart index d6df9b9972..8ef3ae424b 100644 --- a/packages/flutter/lib/src/material/tabs.dart +++ b/packages/flutter/lib/src/material/tabs.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'dart:math' as math; -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'package:newton/newton.dart'; import 'package:sky/animation.dart'; diff --git a/packages/flutter/lib/src/material/theme_data.dart b/packages/flutter/lib/src/material/theme_data.dart index be3092fce6..bee746dd97 100644 --- a/packages/flutter/lib/src/material/theme_data.dart +++ b/packages/flutter/lib/src/material/theme_data.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:sky'; +import 'dart:ui'; import 'package:sky/src/material/typography.dart'; import 'package:sky/src/material/colors.dart'; diff --git a/packages/flutter/lib/src/material/typography.dart b/packages/flutter/lib/src/material/typography.dart index 599a273b99..28ad98ffb2 100644 --- a/packages/flutter/lib/src/material/typography.dart +++ b/packages/flutter/lib/src/material/typography.dart @@ -4,7 +4,7 @@ // See http://www.google.com/design/spec/style/typography.html -import 'dart:sky' show Color; +import 'dart:ui' show Color; import 'package:sky/painting.dart'; import 'package:sky/src/material/colors.dart'; diff --git a/packages/flutter/lib/src/painting/box_painter.dart b/packages/flutter/lib/src/painting/box_painter.dart index 9c3974aea9..4eb16eb1f4 100644 --- a/packages/flutter/lib/src/painting/box_painter.dart +++ b/packages/flutter/lib/src/painting/box_painter.dart @@ -3,8 +3,8 @@ // found in the LICENSE file. import 'dart:math' as math; -import 'dart:sky' as sky; -import 'dart:sky' show Point, Offset, Size, Rect, Color, Paint, Path; +import 'dart:ui' as sky; +import 'dart:ui' show Point, Offset, Size, Rect, Color, Paint, Path; import 'package:sky/services.dart'; diff --git a/packages/flutter/lib/src/painting/shadows.dart b/packages/flutter/lib/src/painting/shadows.dart index dd49e21bc6..b50341c9a7 100644 --- a/packages/flutter/lib/src/painting/shadows.dart +++ b/packages/flutter/lib/src/painting/shadows.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:sky' as sky; +import 'dart:ui' as sky; /// A helper class to build a [sky.DrawLooper] for drawing shadows class ShadowDrawLooperBuilder { diff --git a/packages/flutter/lib/src/painting/text_painter.dart b/packages/flutter/lib/src/painting/text_painter.dart index 81bb8c5c57..cf9ac739d2 100644 --- a/packages/flutter/lib/src/painting/text_painter.dart +++ b/packages/flutter/lib/src/painting/text_painter.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'text_style.dart'; diff --git a/packages/flutter/lib/src/painting/text_style.dart b/packages/flutter/lib/src/painting/text_style.dart index 502c95cf76..74097aca0c 100644 --- a/packages/flutter/lib/src/painting/text_style.dart +++ b/packages/flutter/lib/src/painting/text_style.dart @@ -2,10 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:sky' as sky; -import 'dart:sky' show Point, Offset, Size, Rect, Color, Paint, Path, FontWeight, FontStyle, TextAlign, TextBaseline, TextDecoration, TextDecorationStyle; +import 'dart:ui' as sky; +import 'dart:ui' show Point, Offset, Size, Rect, Color, Paint, Path, FontWeight, FontStyle, TextAlign, TextBaseline, TextDecoration, TextDecorationStyle; -export 'dart:sky' show FontWeight, FontStyle, TextAlign, TextBaseline, TextDecoration, TextDecorationStyle; +export 'dart:ui' show FontWeight, FontStyle, TextAlign, TextBaseline, TextDecoration, TextDecorationStyle; /// A normal font weight const normal = FontWeight.w400; diff --git a/packages/flutter/lib/src/rendering/binding.dart b/packages/flutter/lib/src/rendering/binding.dart index 2771cfd4b2..8c1f9ab59e 100644 --- a/packages/flutter/lib/src/rendering/binding.dart +++ b/packages/flutter/lib/src/rendering/binding.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'package:sky/animation.dart'; import 'package:sky/gestures.dart'; diff --git a/packages/flutter/lib/src/rendering/box.dart b/packages/flutter/lib/src/rendering/box.dart index 57a79c5eab..96c107c261 100644 --- a/packages/flutter/lib/src/rendering/box.dart +++ b/packages/flutter/lib/src/rendering/box.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'dart:math' as math; -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'package:sky/painting.dart'; import 'package:vector_math/vector_math_64.dart'; diff --git a/packages/flutter/lib/src/rendering/debug.dart b/packages/flutter/lib/src/rendering/debug.dart index dbfa3f6b01..0e1e05090a 100644 --- a/packages/flutter/lib/src/rendering/debug.dart +++ b/packages/flutter/lib/src/rendering/debug.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:sky' as sky; +import 'dart:ui' as sky; /// Causes each RenderBox to paint a box around its bounds. bool debugPaintSizeEnabled = false; diff --git a/packages/flutter/lib/src/rendering/hit_test.dart b/packages/flutter/lib/src/rendering/hit_test.dart index 3df2852abf..a54feb16eb 100644 --- a/packages/flutter/lib/src/rendering/hit_test.dart +++ b/packages/flutter/lib/src/rendering/hit_test.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:sky' as sky; +import 'dart:ui' as sky; /// An object that can handle events. abstract class HitTestTarget { diff --git a/packages/flutter/lib/src/rendering/image.dart b/packages/flutter/lib/src/rendering/image.dart index 656b5f28fd..c8022e1db3 100644 --- a/packages/flutter/lib/src/rendering/image.dart +++ b/packages/flutter/lib/src/rendering/image.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'package:sky/painting.dart'; diff --git a/packages/flutter/lib/src/rendering/layer.dart b/packages/flutter/lib/src/rendering/layer.dart index efff6c4590..9afdad8798 100644 --- a/packages/flutter/lib/src/rendering/layer.dart +++ b/packages/flutter/lib/src/rendering/layer.dart @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:sky' as sky; -import 'dart:sky' show Point, Offset, Size, Rect, Color, Paint, Path; +import 'dart:ui' as sky; +import 'dart:ui' show Point, Offset, Size, Rect, Color, Paint, Path; import 'package:vector_math/vector_math_64.dart'; diff --git a/packages/flutter/lib/src/rendering/object.dart b/packages/flutter/lib/src/rendering/object.dart index 451a35e594..f78673f2f1 100644 --- a/packages/flutter/lib/src/rendering/object.dart +++ b/packages/flutter/lib/src/rendering/object.dart @@ -3,8 +3,8 @@ // found in the LICENSE file. import 'dart:math' as math; -import 'dart:sky' as sky; -import 'dart:sky' show Point, Offset, Size, Rect, Color, Paint, Path; +import 'dart:ui' as sky; +import 'dart:ui' show Point, Offset, Size, Rect, Color, Paint, Path; import 'package:sky/animation.dart'; import 'package:vector_math/vector_math_64.dart'; @@ -14,7 +14,7 @@ import 'hit_test.dart'; import 'layer.dart'; import 'node.dart'; -export 'dart:sky' show Point, Offset, Size, Rect, Color, Paint, Path; +export 'dart:ui' show Point, Offset, Size, Rect, Color, Paint, Path; export 'hit_test.dart' show HitTestTarget, HitTestEntry, HitTestResult; typedef sky.Shader ShaderCallback(Rect bounds); diff --git a/packages/flutter/lib/src/rendering/proxy_box.dart b/packages/flutter/lib/src/rendering/proxy_box.dart index 9c22ef6ef5..3ae758a924 100644 --- a/packages/flutter/lib/src/rendering/proxy_box.dart +++ b/packages/flutter/lib/src/rendering/proxy_box.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'package:sky/painting.dart'; import 'package:vector_math/vector_math_64.dart'; diff --git a/packages/flutter/lib/src/rendering/toggleable.dart b/packages/flutter/lib/src/rendering/toggleable.dart index 71b83b15f0..f1b1b9b6f7 100644 --- a/packages/flutter/lib/src/rendering/toggleable.dart +++ b/packages/flutter/lib/src/rendering/toggleable.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'package:sky/animation.dart'; import 'package:sky/gestures.dart'; diff --git a/packages/flutter/lib/src/rendering/view.dart b/packages/flutter/lib/src/rendering/view.dart index bc1a5116b0..6289200eed 100644 --- a/packages/flutter/lib/src/rendering/view.dart +++ b/packages/flutter/lib/src/rendering/view.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'package:sky/animation.dart'; import 'package:vector_math/vector_math_64.dart'; diff --git a/packages/flutter/lib/src/rendering/viewport.dart b/packages/flutter/lib/src/rendering/viewport.dart index 7c0dece986..c27d4e148d 100644 --- a/packages/flutter/lib/src/rendering/viewport.dart +++ b/packages/flutter/lib/src/rendering/viewport.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'package:vector_math/vector_math_64.dart'; diff --git a/packages/flutter/lib/src/services/activity.dart b/packages/flutter/lib/src/services/activity.dart index c5374b8b40..0079a1573f 100644 --- a/packages/flutter/lib/src/services/activity.dart +++ b/packages/flutter/lib/src/services/activity.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:sky'; +import 'dart:ui'; import 'dart:async'; import 'package:sky_services/activity/activity.mojom.dart'; diff --git a/packages/flutter/lib/src/services/asset_bundle.dart b/packages/flutter/lib/src/services/asset_bundle.dart index 8294128776..9adb47a64b 100644 --- a/packages/flutter/lib/src/services/asset_bundle.dart +++ b/packages/flutter/lib/src/services/asset_bundle.dart @@ -3,8 +3,8 @@ // found in the LICENSE file. import 'dart:async'; -import 'dart:sky' as sky; -import 'dart:sky.internals' as internals; +import 'dart:ui' as sky; +import 'dart:ui_internals' as internals; import 'dart:typed_data'; import 'package:mojo/core.dart' as core; diff --git a/packages/flutter/lib/src/services/embedder.dart b/packages/flutter/lib/src/services/embedder.dart index 1d61267c5e..f2e21214cc 100644 --- a/packages/flutter/lib/src/services/embedder.dart +++ b/packages/flutter/lib/src/services/embedder.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:sky.internals' as internals; +import 'dart:ui_internals' as internals; import 'package:mojo/application.dart'; import 'package:mojo/bindings.dart' as bindings; diff --git a/packages/flutter/lib/src/services/image_cache.dart b/packages/flutter/lib/src/services/image_cache.dart index 52788a854b..19c823caf0 100644 --- a/packages/flutter/lib/src/services/image_cache.dart +++ b/packages/flutter/lib/src/services/image_cache.dart @@ -4,7 +4,7 @@ import 'dart:async'; import 'dart:collection'; -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'package:mojo/mojo/url_response.mojom.dart'; diff --git a/packages/flutter/lib/src/services/image_decoder.dart b/packages/flutter/lib/src/services/image_decoder.dart index 375c31398e..2ce69a65ca 100644 --- a/packages/flutter/lib/src/services/image_decoder.dart +++ b/packages/flutter/lib/src/services/image_decoder.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'dart:async'; -import 'dart:sky' show Image, ImageDecoder, ImageDecoderCallback; +import 'dart:ui' show Image, ImageDecoder, ImageDecoderCallback; import 'dart:typed_data'; import 'package:mojo/core.dart' show MojoDataPipeConsumer; diff --git a/packages/flutter/lib/src/services/image_resource.dart b/packages/flutter/lib/src/services/image_resource.dart index d8e6fc50ce..2f887d6a76 100644 --- a/packages/flutter/lib/src/services/image_resource.dart +++ b/packages/flutter/lib/src/services/image_resource.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'dart:async'; -import 'dart:sky' as sky; +import 'dart:ui' as sky; /// A callback for when the image is available. typedef void ImageListener(sky.Image image); diff --git a/packages/flutter/lib/src/services/shell.dart b/packages/flutter/lib/src/services/shell.dart index 679f3c3e40..e2bbffad21 100644 --- a/packages/flutter/lib/src/services/shell.dart +++ b/packages/flutter/lib/src/services/shell.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:sky.internals' as internals; +import 'dart:ui_internals' as internals; import 'package:mojo/application.dart'; import 'package:mojo/core.dart' as core; diff --git a/packages/flutter/lib/src/widgets/basic.dart b/packages/flutter/lib/src/widgets/basic.dart index 340fa56e6f..99bf338173 100644 --- a/packages/flutter/lib/src/widgets/basic.dart +++ b/packages/flutter/lib/src/widgets/basic.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'package:sky/rendering.dart'; import 'package:sky/services.dart'; diff --git a/packages/flutter/lib/src/widgets/dismissable.dart b/packages/flutter/lib/src/widgets/dismissable.dart index a4d43114c9..8114b58d07 100644 --- a/packages/flutter/lib/src/widgets/dismissable.dart +++ b/packages/flutter/lib/src/widgets/dismissable.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'package:sky/animation.dart'; diff --git a/packages/flutter/lib/src/widgets/drag_target.dart b/packages/flutter/lib/src/widgets/drag_target.dart index ddd98ba0c0..672dfbbca7 100644 --- a/packages/flutter/lib/src/widgets/drag_target.dart +++ b/packages/flutter/lib/src/widgets/drag_target.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'dart:collection'; -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'package:sky/animation.dart'; import 'package:sky/rendering.dart'; diff --git a/packages/flutter/lib/src/widgets/gesture_detector.dart b/packages/flutter/lib/src/widgets/gesture_detector.dart index 6738389db4..22b9b7e347 100644 --- a/packages/flutter/lib/src/widgets/gesture_detector.dart +++ b/packages/flutter/lib/src/widgets/gesture_detector.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'package:sky/gestures.dart'; import 'package:sky/rendering.dart'; diff --git a/packages/flutter/lib/src/widgets/scrollable.dart b/packages/flutter/lib/src/widgets/scrollable.dart index 36b1502155..6fe36e3394 100644 --- a/packages/flutter/lib/src/widgets/scrollable.dart +++ b/packages/flutter/lib/src/widgets/scrollable.dart @@ -4,7 +4,7 @@ import 'dart:async'; import 'dart:math' as math; -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'package:newton/newton.dart'; import 'package:sky/animation.dart'; diff --git a/packages/flutter_sprites/lib/skysprites.dart b/packages/flutter_sprites/lib/skysprites.dart index 6ffd26de3d..6669d8071c 100644 --- a/packages/flutter_sprites/lib/skysprites.dart +++ b/packages/flutter_sprites/lib/skysprites.dart @@ -8,7 +8,7 @@ import 'dart:async'; import 'dart:convert'; import 'dart:math' as math; import 'dart:typed_data'; -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'package:box2d/box2d.dart' as box2d; import 'package:mojo/core.dart'; diff --git a/packages/unit/test/engine/append_child_test.dart b/packages/unit/test/engine/append_child_test.dart index fd80f5f9b9..f055661275 100644 --- a/packages/unit/test/engine/append_child_test.dart +++ b/packages/unit/test/engine/append_child_test.dart @@ -1,4 +1,4 @@ -import 'dart:sky'; +import 'dart:ui'; import 'package:test/test.dart'; diff --git a/packages/unit/test/engine/canvas_test.dart b/packages/unit/test/engine/canvas_test.dart index 27a26bc0e8..31daaba371 100644 --- a/packages/unit/test/engine/canvas_test.dart +++ b/packages/unit/test/engine/canvas_test.dart @@ -1,5 +1,5 @@ -import 'dart:sky' as sky; -import 'dart:sky' show Rect, Color, Paint; +import 'dart:ui' as sky; +import 'dart:ui' show Rect, Color, Paint; import 'package:test/test.dart'; import 'package:vector_math/vector_math_64.dart'; diff --git a/packages/unit/test/engine/color_test.dart b/packages/unit/test/engine/color_test.dart index 53a74072a0..2a5c33fd10 100644 --- a/packages/unit/test/engine/color_test.dart +++ b/packages/unit/test/engine/color_test.dart @@ -1,4 +1,4 @@ -import 'dart:sky'; +import 'dart:ui'; import 'package:test/test.dart'; diff --git a/packages/unit/test/engine/document_child_mutations_test.dart b/packages/unit/test/engine/document_child_mutations_test.dart index 40e039ab37..fd83ce64c0 100644 --- a/packages/unit/test/engine/document_child_mutations_test.dart +++ b/packages/unit/test/engine/document_child_mutations_test.dart @@ -1,4 +1,4 @@ -import 'dart:sky'; +import 'dart:ui'; import 'package:test/test.dart'; diff --git a/packages/unit/test/engine/dom_utils.dart b/packages/unit/test/engine/dom_utils.dart index ceb96907db..f45299e2a8 100644 --- a/packages/unit/test/engine/dom_utils.dart +++ b/packages/unit/test/engine/dom_utils.dart @@ -1,4 +1,4 @@ -import 'dart:sky'; +import 'dart:ui'; int childNodeCount(parent) { int count = 0; diff --git a/packages/unit/test/engine/get_child_elements_test.dart b/packages/unit/test/engine/get_child_elements_test.dart index 0161c56980..cd81ebba82 100644 --- a/packages/unit/test/engine/get_child_elements_test.dart +++ b/packages/unit/test/engine/get_child_elements_test.dart @@ -1,4 +1,4 @@ -import 'dart:sky'; +import 'dart:ui'; import 'package:test/test.dart'; diff --git a/packages/unit/test/engine/inline_style_test.dart b/packages/unit/test/engine/inline_style_test.dart index 148ffca8db..d8d0d6ec62 100644 --- a/packages/unit/test/engine/inline_style_test.dart +++ b/packages/unit/test/engine/inline_style_test.dart @@ -1,4 +1,4 @@ -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'package:test/test.dart'; diff --git a/packages/unit/test/engine/insert_before_test.dart b/packages/unit/test/engine/insert_before_test.dart index 2e6a5fa1e2..4af3b4bbb3 100644 --- a/packages/unit/test/engine/insert_before_test.dart +++ b/packages/unit/test/engine/insert_before_test.dart @@ -1,4 +1,4 @@ -import 'dart:sky'; +import 'dart:ui'; import 'package:test/test.dart'; diff --git a/packages/unit/test/engine/mock_events.dart b/packages/unit/test/engine/mock_events.dart index 184fa8f0e8..7604b0f9af 100644 --- a/packages/unit/test/engine/mock_events.dart +++ b/packages/unit/test/engine/mock_events.dart @@ -1,6 +1,6 @@ -import 'dart:sky' as sky; +import 'dart:ui' as sky; -export 'dart:sky' show Point; +export 'dart:ui' show Point; class TestPointerEvent extends sky.PointerEvent { TestPointerEvent({ diff --git a/packages/unit/test/engine/owner_scope_test.dart b/packages/unit/test/engine/owner_scope_test.dart index 6f3d69e650..4b29b17c5f 100644 --- a/packages/unit/test/engine/owner_scope_test.dart +++ b/packages/unit/test/engine/owner_scope_test.dart @@ -1,4 +1,4 @@ -import 'dart:sky'; +import 'dart:ui'; import 'package:test/test.dart'; diff --git a/packages/unit/test/engine/paragraph_builder_test.dart b/packages/unit/test/engine/paragraph_builder_test.dart index 2f24391ce3..7d88d40787 100644 --- a/packages/unit/test/engine/paragraph_builder_test.dart +++ b/packages/unit/test/engine/paragraph_builder_test.dart @@ -1,4 +1,4 @@ -import 'dart:sky'; +import 'dart:ui'; import 'package:test/test.dart'; diff --git a/packages/unit/test/engine/rect_test.dart b/packages/unit/test/engine/rect_test.dart index 14d7303568..6f9ec1adb3 100644 --- a/packages/unit/test/engine/rect_test.dart +++ b/packages/unit/test/engine/rect_test.dart @@ -1,4 +1,4 @@ -import 'dart:sky'; +import 'dart:ui'; import 'package:test/test.dart'; diff --git a/packages/unit/test/engine/replace_child_test.dart b/packages/unit/test/engine/replace_child_test.dart index d275693c3b..ba40e156e0 100644 --- a/packages/unit/test/engine/replace_child_test.dart +++ b/packages/unit/test/engine/replace_child_test.dart @@ -1,4 +1,4 @@ -import 'dart:sky'; +import 'dart:ui'; import 'package:test/test.dart'; diff --git a/packages/unit/test/engine/text_test.dart b/packages/unit/test/engine/text_test.dart index acec02a66c..dcd92dfadc 100644 --- a/packages/unit/test/engine/text_test.dart +++ b/packages/unit/test/engine/text_test.dart @@ -1,4 +1,4 @@ -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'package:test/test.dart'; diff --git a/packages/unit/test/gestures/pointer_router_test.dart b/packages/unit/test/gestures/pointer_router_test.dart index 8cedf5d2dc..e9a67f3f3c 100644 --- a/packages/unit/test/gestures/pointer_router_test.dart +++ b/packages/unit/test/gestures/pointer_router_test.dart @@ -1,4 +1,4 @@ -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'package:sky/gestures.dart'; import 'package:test/test.dart'; diff --git a/packages/unit/test/gestures/scale_test.dart b/packages/unit/test/gestures/scale_test.dart index 6d593a72e6..6e5d59e94d 100644 --- a/packages/unit/test/gestures/scale_test.dart +++ b/packages/unit/test/gestures/scale_test.dart @@ -1,4 +1,4 @@ -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'package:sky/gestures.dart'; import 'package:test/test.dart'; diff --git a/packages/unit/test/gestures/scroll_test.dart b/packages/unit/test/gestures/scroll_test.dart index bee66db54b..e0ded8ffce 100644 --- a/packages/unit/test/gestures/scroll_test.dart +++ b/packages/unit/test/gestures/scroll_test.dart @@ -1,4 +1,4 @@ -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'package:sky/gestures.dart'; import 'package:test/test.dart'; diff --git a/packages/unit/test/rendering/image_test.dart b/packages/unit/test/rendering/image_test.dart index 7e2785f49c..be0e6f7be9 100644 --- a/packages/unit/test/rendering/image_test.dart +++ b/packages/unit/test/rendering/image_test.dart @@ -1,4 +1,4 @@ -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'package:sky/rendering.dart'; import 'package:test/test.dart'; diff --git a/packages/unit/test/widget/shader_mask_test.dart b/packages/unit/test/widget/shader_mask_test.dart index c92122c663..9fc0bae9e2 100644 --- a/packages/unit/test/widget/shader_mask_test.dart +++ b/packages/unit/test/widget/shader_mask_test.dart @@ -1,4 +1,4 @@ -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'package:sky/painting.dart'; import 'package:sky/widgets.dart'; diff --git a/packages/unit/test/widget/widget_tester.dart b/packages/unit/test/widget/widget_tester.dart index cf8f127ee1..95964f3e98 100644 --- a/packages/unit/test/widget/widget_tester.dart +++ b/packages/unit/test/widget/widget_tester.dart @@ -1,4 +1,4 @@ -import 'dart:sky' as sky; +import 'dart:ui' as sky; import 'package:sky/animation.dart'; import 'package:sky/rendering.dart'; From 65eba90843b52658fc36fcbd9920d1cfb7dcc7b7 Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Fri, 9 Oct 2015 20:44:52 -0700 Subject: [PATCH 38/84] Rename package:sky to package:flutter --- examples/address_book/lib/main.dart | 2 +- examples/address_book/pubspec.yaml | 4 ++-- examples/demo_launcher/lib/main.dart | 6 +++--- examples/demo_launcher/pubspec.yaml | 4 ++-- examples/fitness/lib/main.dart | 4 ++-- examples/fitness/lib/user_data.dart | 2 +- examples/fitness/pubspec.yaml | 4 ++-- examples/game/example_effect_line.dart | 8 ++++---- examples/game/lib/game_demo.dart | 2 +- examples/game/lib/main.dart | 8 ++++---- examples/game/pubspec.yaml | 4 ++-- examples/game/test_bed.dart | 8 ++++---- examples/game/test_drawatlas.dart | 8 ++++---- examples/game/test_performance.dart | 8 ++++---- examples/game/test_physics.dart | 8 ++++---- examples/hello_world/lib/main.dart | 2 +- examples/hello_world/pubspec.yaml | 4 ++-- examples/mine_digger/lib/main.dart | 8 ++++---- examples/mine_digger/pubspec.yaml | 4 ++-- examples/raw/pubspec.yaml | 4 ++-- examples/raw/spinning_image.dart | 2 +- examples/rendering/align_items.dart | 2 +- examples/rendering/baseline.dart | 2 +- examples/rendering/borders.dart | 2 +- examples/rendering/flex.dart | 2 +- examples/rendering/interactive_flex.dart | 4 ++-- examples/rendering/justify_content.dart | 2 +- examples/rendering/pubspec.yaml | 4 ++-- examples/rendering/render_grid.dart | 4 ++-- examples/rendering/render_paragraph.dart | 2 +- examples/rendering/sector_layout.dart | 2 +- examples/rendering/shadowed_box.dart | 4 ++-- examples/rendering/simple_autolayout.dart | 2 +- examples/rendering/solid_color_box.dart | 2 +- examples/rendering/spinning_flex.dart | 4 ++-- examples/rendering/touch_demo.dart | 4 ++-- examples/rendering/transform.dart | 2 +- examples/stocks/lib/main.dart | 6 +++--- examples/stocks/lib/stock_data.dart | 2 +- examples/stocks/pubspec.yaml | 4 ++-- examples/widgets/big_switch.dart | 2 +- examples/widgets/card_collection.dart | 4 ++-- examples/widgets/container.dart | 2 +- examples/widgets/date_picker.dart | 2 +- examples/widgets/drag_and_drop.dart | 6 +++--- examples/widgets/ensure_visible.dart | 2 +- examples/widgets/horizontal_scrolling.dart | 2 +- examples/widgets/indexed_stack.dart | 4 ++-- examples/widgets/navigation.dart | 2 +- examples/widgets/overlay_geometry.dart | 4 ++-- examples/widgets/pageable_list.dart | 4 ++-- examples/widgets/piano.dart | 6 +++--- examples/widgets/progress_indicator.dart | 4 ++-- examples/widgets/pubspec.yaml | 4 ++-- examples/widgets/scale.dart | 4 ++-- examples/widgets/sector.dart | 4 ++-- examples/widgets/spinning_mixed.dart | 6 +++--- examples/widgets/styled_text.dart | 4 ++-- examples/widgets/tabs.dart | 4 ++-- packages/flutter/lib/src/material/card.dart | 2 +- packages/flutter/lib/src/material/checkbox.dart | 6 +++--- packages/flutter/lib/src/material/date_picker.dart | 6 +++--- packages/flutter/lib/src/material/dialog.dart | 6 +++--- packages/flutter/lib/src/material/drawer.dart | 4 ++-- .../flutter/lib/src/material/drawer_divider.dart | 2 +- packages/flutter/lib/src/material/drawer_header.dart | 2 +- packages/flutter/lib/src/material/drawer_item.dart | 6 +++--- packages/flutter/lib/src/material/flat_button.dart | 4 ++-- .../lib/src/material/floating_action_button.dart | 4 ++-- packages/flutter/lib/src/material/icon.dart | 4 ++-- packages/flutter/lib/src/material/icon_button.dart | 4 ++-- packages/flutter/lib/src/material/ink_well.dart | 8 ++++---- packages/flutter/lib/src/material/input.dart | 12 ++++++------ packages/flutter/lib/src/material/material.dart | 6 +++--- packages/flutter/lib/src/material/material_app.dart | 6 +++--- .../flutter/lib/src/material/material_button.dart | 4 ++-- packages/flutter/lib/src/material/popup_menu.dart | 6 +++--- .../flutter/lib/src/material/popup_menu_item.dart | 2 +- .../flutter/lib/src/material/progress_indicator.dart | 4 ++-- .../flutter/lib/src/material/radial_reaction.dart | 2 +- packages/flutter/lib/src/material/radio.dart | 2 +- packages/flutter/lib/src/material/raised_button.dart | 4 ++-- packages/flutter/lib/src/material/scaffold.dart | 4 ++-- packages/flutter/lib/src/material/shadows.dart | 2 +- packages/flutter/lib/src/material/snack_bar.dart | 8 ++++---- packages/flutter/lib/src/material/switch.dart | 8 ++++---- packages/flutter/lib/src/material/tabs.dart | 10 +++++----- packages/flutter/lib/src/material/theme.dart | 2 +- packages/flutter/lib/src/material/theme_data.dart | 4 ++-- packages/flutter/lib/src/material/title.dart | 4 ++-- packages/flutter/lib/src/material/tool_bar.dart | 4 ++-- packages/flutter/lib/src/material/typography.dart | 4 ++-- packages/flutter/lib/src/painting/box_painter.dart | 2 +- packages/flutter/lib/src/rendering/binding.dart | 4 ++-- packages/flutter/lib/src/rendering/box.dart | 4 ++-- .../lib/src/rendering/editable_paragraph.dart | 2 +- packages/flutter/lib/src/rendering/image.dart | 2 +- packages/flutter/lib/src/rendering/object.dart | 2 +- packages/flutter/lib/src/rendering/paragraph.dart | 4 ++-- packages/flutter/lib/src/rendering/proxy_box.dart | 4 ++-- packages/flutter/lib/src/rendering/shifted_box.dart | 2 +- packages/flutter/lib/src/rendering/toggleable.dart | 4 ++-- packages/flutter/lib/src/rendering/view.dart | 2 +- .../flutter/lib/src/widgets/animated_container.dart | 2 +- packages/flutter/lib/src/widgets/basic.dart | 6 +++--- packages/flutter/lib/src/widgets/binding.dart | 4 ++-- packages/flutter/lib/src/widgets/dismissable.dart | 2 +- packages/flutter/lib/src/widgets/drag_target.dart | 4 ++-- packages/flutter/lib/src/widgets/editable_text.dart | 4 ++-- packages/flutter/lib/src/widgets/framework.dart | 2 +- .../flutter/lib/src/widgets/gesture_detector.dart | 4 ++-- .../lib/src/widgets/homogeneous_viewport.dart | 6 +++--- packages/flutter/lib/src/widgets/mimic.dart | 2 +- packages/flutter/lib/src/widgets/mixed_viewport.dart | 2 +- packages/flutter/lib/src/widgets/navigator.dart | 2 +- packages/flutter/lib/src/widgets/scrollable.dart | 6 +++--- .../flutter/lib/src/widgets/statistics_overlay.dart | 2 +- packages/flutter/lib/src/widgets/transitions.dart | 4 ++-- packages/flutter/pubspec.yaml | 2 +- packages/flutter_sprites/lib/skysprites.dart | 10 +++++----- packages/flutter_sprites/pubspec.yaml | 4 ++-- packages/unit/pubspec.yaml | 4 ++-- packages/unit/test/animation/scheduler_test.dart | 2 +- packages/unit/test/gestures/arena_test.dart | 2 +- packages/unit/test/gestures/long_press_test.dart | 2 +- packages/unit/test/gestures/pointer_router_test.dart | 2 +- packages/unit/test/gestures/scale_test.dart | 2 +- packages/unit/test/gestures/scroll_test.dart | 2 +- packages/unit/test/gestures/show_press_test.dart | 2 +- packages/unit/test/gestures/tap_test.dart | 2 +- packages/unit/test/painting/edge_dims_test.dart | 2 +- packages/unit/test/rendering/box_test.dart | 4 ++-- packages/unit/test/rendering/flex_test.dart | 2 +- packages/unit/test/rendering/grid_test.dart | 2 +- packages/unit/test/rendering/image_test.dart | 2 +- .../unit/test/rendering/intrinsic_width_test.dart | 2 +- .../unit/test/rendering/positioned_box_test.dart | 2 +- packages/unit/test/rendering/rendering_tester.dart | 2 +- packages/unit/test/rendering/size_test.dart | 2 +- packages/unit/test/rendering/stack_test.dart | 2 +- packages/unit/test/rendering/viewport_test.dart | 2 +- packages/unit/test/services/mock_services.dart | 2 +- packages/unit/test/widget/align_test.dart | 2 +- .../unit/test/widget/animated_container_test.dart | 4 ++-- packages/unit/test/widget/block_test.dart | 2 +- packages/unit/test/widget/box_decoration_test.dart | 4 ++-- packages/unit/test/widget/build_scope_test.dart | 2 +- packages/unit/test/widget/center_test.dart | 2 +- packages/unit/test/widget/coordinates_test.dart | 4 ++-- packages/unit/test/widget/date_picker_test.dart | 2 +- packages/unit/test/widget/dismissable_test.dart | 4 ++-- packages/unit/test/widget/draggable_test.dart | 2 +- packages/unit/test/widget/drawer_test.dart | 4 ++-- packages/unit/test/widget/duplicate_key_test.dart | 2 +- packages/unit/test/widget/flex_test.dart | 2 +- packages/unit/test/widget/focus_test.dart | 2 +- .../test/widget/fractionally_sized_box_test.dart | 4 ++-- packages/unit/test/widget/gesture_detector_test.dart | 2 +- .../unit/test/widget/homogeneous_viewport_test.dart | 2 +- packages/unit/test/widget/input_test.dart | 6 +++--- packages/unit/test/widget/listener_test.dart | 2 +- packages/unit/test/widget/mixed_viewport_test.dart | 2 +- packages/unit/test/widget/multichild_test.dart | 4 ++-- packages/unit/test/widget/navigator_test.dart | 2 +- packages/unit/test/widget/pageable_list_test.dart | 2 +- packages/unit/test/widget/parent_data_test.dart | 4 ++-- .../unit/test/widget/progress_indicator_test.dart | 4 ++-- .../unit/test/widget/render_object_widget_test.dart | 4 ++-- packages/unit/test/widget/reparent_state_test.dart | 2 +- .../widget/scrollable_list_hit_testing_test.dart | 4 ++-- .../test/widget/scrollable_list_horizontal_test.dart | 4 ++-- .../test/widget/scrollable_list_vertical_test.dart | 2 +- packages/unit/test/widget/set_state_3_test.dart | 2 +- packages/unit/test/widget/set_state_test.dart | 2 +- packages/unit/test/widget/shader_mask_test.dart | 4 ++-- packages/unit/test/widget/size_observer_test.dart | 4 ++-- packages/unit/test/widget/snack_bar_test.dart | 2 +- packages/unit/test/widget/snap_scrolling_test.dart | 2 +- packages/unit/test/widget/stack_test.dart | 2 +- .../unit/test/widget/stateful_component_test.dart | 4 ++-- .../unit/test/widget/stateful_components_test.dart | 2 +- packages/unit/test/widget/syncing_test.dart | 2 +- packages/unit/test/widget/test_widgets.dart | 2 +- packages/unit/test/widget/transform_test.dart | 2 +- packages/unit/test/widget/widget_tester.dart | 6 +++--- packages/updater/lib/main.dart | 2 +- packages/updater/pubspec.yaml | 4 ++-- 187 files changed, 331 insertions(+), 331 deletions(-) diff --git a/examples/address_book/lib/main.dart b/examples/address_book/lib/main.dart index dee2b76148..964c39f2cf 100644 --- a/examples/address_book/lib/main.dart +++ b/examples/address_book/lib/main.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:sky/material.dart'; +import 'package:flutter/material.dart'; class Field extends StatelessComponent { Field({ diff --git a/examples/address_book/pubspec.yaml b/examples/address_book/pubspec.yaml index ec6fdab599..435112907b 100644 --- a/examples/address_book/pubspec.yaml +++ b/examples/address_book/pubspec.yaml @@ -1,9 +1,9 @@ name: address_book dependencies: - sky: any + flutter: any sky_tools: any dependency_overrides: material_design_icons: path: ../../sky/packages/material_design_icons - sky: + flutter: path: ../../sky/packages/sky diff --git a/examples/demo_launcher/lib/main.dart b/examples/demo_launcher/lib/main.dart index a95c24ee5c..4d3be4e082 100644 --- a/examples/demo_launcher/lib/main.dart +++ b/examples/demo_launcher/lib/main.dart @@ -2,9 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:sky/material.dart'; -import 'package:sky/painting.dart'; -import 'package:sky/services.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/painting.dart'; +import 'package:flutter/services.dart'; AssetBundle _initBundle() { if (rootBundle != null) diff --git a/examples/demo_launcher/pubspec.yaml b/examples/demo_launcher/pubspec.yaml index 358724f84f..637552c175 100644 --- a/examples/demo_launcher/pubspec.yaml +++ b/examples/demo_launcher/pubspec.yaml @@ -1,9 +1,9 @@ name: demo_launcher dependencies: - sky: any + flutter: any sky_tools: any dependency_overrides: material_design_icons: path: ../../sky/packages/material_design_icons - sky: + flutter: path: ../../sky/packages/sky diff --git a/examples/fitness/lib/main.dart b/examples/fitness/lib/main.dart index 453648ba5f..a354c70313 100644 --- a/examples/fitness/lib/main.dart +++ b/examples/fitness/lib/main.dart @@ -5,8 +5,8 @@ library fitness; import 'package:playfair/playfair.dart' as playfair; -import 'package:sky/material.dart'; -import 'package:sky/painting.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/painting.dart'; import 'user_data.dart'; import 'date_utils.dart'; diff --git a/examples/fitness/lib/user_data.dart b/examples/fitness/lib/user_data.dart index 50c065ac4e..ef6eabb153 100644 --- a/examples/fitness/lib/user_data.dart +++ b/examples/fitness/lib/user_data.dart @@ -9,7 +9,7 @@ import 'dart:async'; import 'package:path/path.dart' as path; import 'main.dart'; -import 'package:sky/services.dart'; +import 'package:flutter/services.dart'; String cachedDataFilePath = null; diff --git a/examples/fitness/pubspec.yaml b/examples/fitness/pubspec.yaml index f680cb0e0e..2b8abd4804 100644 --- a/examples/fitness/pubspec.yaml +++ b/examples/fitness/pubspec.yaml @@ -1,11 +1,11 @@ name: fitness dependencies: - sky: any + flutter: any sky_tools: any playfair: ^0.0.9 path: ^1.3.6 dependency_overrides: material_design_icons: path: ../../sky/packages/material_design_icons - sky: + flutter: path: ../../sky/packages/sky diff --git a/examples/game/example_effect_line.dart b/examples/game/example_effect_line.dart index 6d05848942..d6a92af06f 100644 --- a/examples/game/example_effect_line.dart +++ b/examples/game/example_effect_line.dart @@ -1,7 +1,7 @@ -import 'package:sky/material.dart'; -import 'package:sky/rendering.dart'; -import 'package:sky/services.dart'; -import 'package:sky/widgets.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter/widgets.dart'; import 'package:skysprites/skysprites.dart'; AssetBundle _initBundle() { diff --git a/examples/game/lib/game_demo.dart b/examples/game/lib/game_demo.dart index 652067bd44..95862c7941 100644 --- a/examples/game/lib/game_demo.dart +++ b/examples/game/lib/game_demo.dart @@ -4,7 +4,7 @@ import 'dart:async'; import 'dart:math' as math; import 'dart:ui' as sky; -import 'package:sky/rendering.dart'; +import 'package:flutter/rendering.dart'; import 'package:skysprites/skysprites.dart'; import 'package:vector_math/vector_math_64.dart'; diff --git a/examples/game/lib/main.dart b/examples/game/lib/main.dart index 098f3ebfbf..54be5e7c7e 100644 --- a/examples/game/lib/main.dart +++ b/examples/game/lib/main.dart @@ -4,10 +4,10 @@ import 'dart:async'; -import 'package:sky/material.dart'; -import 'package:sky/painting.dart'; -import 'package:sky/rendering.dart'; -import 'package:sky/services.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/painting.dart'; +import 'package:flutter/rendering.dart'; +import 'package:flutter/services.dart'; import 'package:skysprites/skysprites.dart'; import 'game_demo.dart'; diff --git a/examples/game/pubspec.yaml b/examples/game/pubspec.yaml index 8f12e91948..c7d1356b6d 100644 --- a/examples/game/pubspec.yaml +++ b/examples/game/pubspec.yaml @@ -1,13 +1,13 @@ name: asteroids dependencies: - sky: any + flutter: any sky_tools: any skysprites: any box2d: any dependency_overrides: material_design_icons: path: ../../sky/packages/material_design_icons - sky: + flutter: path: ../../sky/packages/sky skysprites: path: ../../skysprites diff --git a/examples/game/test_bed.dart b/examples/game/test_bed.dart index 5588ae8d07..f63a8c6ca7 100644 --- a/examples/game/test_bed.dart +++ b/examples/game/test_bed.dart @@ -1,9 +1,9 @@ import 'dart:ui'; -import 'package:sky/material.dart'; -import 'package:sky/rendering.dart'; -import 'package:sky/services.dart'; -import 'package:sky/widgets.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter/widgets.dart'; import 'package:skysprites/skysprites.dart'; AssetBundle _initBundle() { diff --git a/examples/game/test_drawatlas.dart b/examples/game/test_drawatlas.dart index 82422dd8a7..f49e36dc2c 100644 --- a/examples/game/test_drawatlas.dart +++ b/examples/game/test_drawatlas.dart @@ -1,9 +1,9 @@ import 'dart:ui'; -import 'package:sky/material.dart'; -import 'package:sky/rendering.dart'; -import 'package:sky/services.dart'; -import 'package:sky/widgets.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter/widgets.dart'; import 'package:skysprites/skysprites.dart'; AssetBundle _initBundle() { diff --git a/examples/game/test_performance.dart b/examples/game/test_performance.dart index 4bd4255987..2d57022976 100644 --- a/examples/game/test_performance.dart +++ b/examples/game/test_performance.dart @@ -1,10 +1,10 @@ import 'dart:ui' as sky; import 'dart:math' as math; -import 'package:sky/material.dart'; -import 'package:sky/rendering.dart'; -import 'package:sky/services.dart'; -import 'package:sky/widgets.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter/widgets.dart'; import 'package:skysprites/skysprites.dart'; AssetBundle _initBundle() { diff --git a/examples/game/test_physics.dart b/examples/game/test_physics.dart index 4e8986e6dc..a3915a40a8 100644 --- a/examples/game/test_physics.dart +++ b/examples/game/test_physics.dart @@ -1,9 +1,9 @@ import 'dart:ui'; -import 'package:sky/material.dart'; -import 'package:sky/rendering.dart'; -import 'package:sky/services.dart'; -import 'package:sky/widgets.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter/widgets.dart'; import 'package:skysprites/skysprites.dart'; AssetBundle _initBundle() { diff --git a/examples/hello_world/lib/main.dart b/examples/hello_world/lib/main.dart index c3a23d1f76..fc37338118 100644 --- a/examples/hello_world/lib/main.dart +++ b/examples/hello_world/lib/main.dart @@ -2,6 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:sky/widgets.dart'; +import 'package:flutter/widgets.dart'; void main() => runApp(new Center(child: new Text('Hello, world!'))); diff --git a/examples/hello_world/pubspec.yaml b/examples/hello_world/pubspec.yaml index 723d63b3d5..6593305cb2 100644 --- a/examples/hello_world/pubspec.yaml +++ b/examples/hello_world/pubspec.yaml @@ -1,9 +1,9 @@ name: hello_world dependencies: - sky: any + flutter: any sky_tools: any dependency_overrides: material_design_icons: path: ../../sky/packages/material_design_icons - sky: + flutter: path: ../../sky/packages/sky diff --git a/examples/mine_digger/lib/main.dart b/examples/mine_digger/lib/main.dart index 23cc79ff30..b17c6a9340 100644 --- a/examples/mine_digger/lib/main.dart +++ b/examples/mine_digger/lib/main.dart @@ -4,10 +4,10 @@ import 'dart:ui' as sky; import 'dart:math'; -import 'package:sky/material.dart'; -import 'package:sky/painting.dart'; -import 'package:sky/rendering.dart'; -import 'package:sky/services.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/painting.dart'; +import 'package:flutter/rendering.dart'; +import 'package:flutter/services.dart'; // Classic minesweeper-inspired game. The mouse controls are standard // except for left + right combo which is not implemented. For touch, diff --git a/examples/mine_digger/pubspec.yaml b/examples/mine_digger/pubspec.yaml index d941b44e6f..739bf26ddd 100644 --- a/examples/mine_digger/pubspec.yaml +++ b/examples/mine_digger/pubspec.yaml @@ -1,9 +1,9 @@ name: mine_digger dependencies: - sky: any + flutter: any sky_tools: any dependency_overrides: material_design_icons: path: ../../sky/packages/material_design_icons - sky: + flutter: path: ../../sky/packages/sky diff --git a/examples/raw/pubspec.yaml b/examples/raw/pubspec.yaml index 1650deddd2..e4ac176448 100644 --- a/examples/raw/pubspec.yaml +++ b/examples/raw/pubspec.yaml @@ -1,9 +1,9 @@ name: raw dependencies: - sky: any + flutter: any sky_tools: any dependency_overrides: material_design_icons: path: ../../sky/packages/material_design_icons - sky: + flutter: path: ../../sky/packages/sky diff --git a/examples/raw/spinning_image.dart b/examples/raw/spinning_image.dart index 76e9c81155..b9fe9b450b 100644 --- a/examples/raw/spinning_image.dart +++ b/examples/raw/spinning_image.dart @@ -6,7 +6,7 @@ import 'dart:math' as math; import 'dart:ui' as sky; import 'dart:typed_data'; -import 'package:sky/services.dart'; +import 'package:flutter/services.dart'; double timeBase = null; diff --git a/examples/rendering/align_items.dart b/examples/rendering/align_items.dart index 8cf517a2bc..50b87f4b3e 100644 --- a/examples/rendering/align_items.dart +++ b/examples/rendering/align_items.dart @@ -2,7 +2,7 @@ // 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:flutter/rendering.dart'; import 'solid_color_box.dart'; diff --git a/examples/rendering/baseline.dart b/examples/rendering/baseline.dart index 3488e23df8..a3838e7ecf 100644 --- a/examples/rendering/baseline.dart +++ b/examples/rendering/baseline.dart @@ -4,7 +4,7 @@ import 'dart:ui' as sky; -import 'package:sky/rendering.dart'; +import 'package:flutter/rendering.dart'; RenderBox getBox(double lh) { RenderParagraph paragraph = new RenderParagraph( diff --git a/examples/rendering/borders.dart b/examples/rendering/borders.dart index 8a9df8d41f..52b642e949 100644 --- a/examples/rendering/borders.dart +++ b/examples/rendering/borders.dart @@ -4,7 +4,7 @@ import 'dart:ui' as sky; -import 'package:sky/rendering.dart'; +import 'package:flutter/rendering.dart'; void main() { var root = new RenderFlex( diff --git a/examples/rendering/flex.dart b/examples/rendering/flex.dart index a8b3a8b4cb..2abaf26719 100644 --- a/examples/rendering/flex.dart +++ b/examples/rendering/flex.dart @@ -4,7 +4,7 @@ import 'dart:ui' as sky; -import 'package:sky/rendering.dart'; +import 'package:flutter/rendering.dart'; import 'solid_color_box.dart'; RenderBox buildFlexExample() { diff --git a/examples/rendering/interactive_flex.dart b/examples/rendering/interactive_flex.dart index aee0074544..79134675ca 100644 --- a/examples/rendering/interactive_flex.dart +++ b/examples/rendering/interactive_flex.dart @@ -5,8 +5,8 @@ import 'dart:ui' as sky; import 'dart:math' as math; -import 'package:sky/services.dart'; -import 'package:sky/rendering.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter/rendering.dart'; import 'solid_color_box.dart'; diff --git a/examples/rendering/justify_content.dart b/examples/rendering/justify_content.dart index 908bd4268c..ffa6f48f53 100644 --- a/examples/rendering/justify_content.dart +++ b/examples/rendering/justify_content.dart @@ -2,7 +2,7 @@ // 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:flutter/rendering.dart'; import 'solid_color_box.dart'; diff --git a/examples/rendering/pubspec.yaml b/examples/rendering/pubspec.yaml index 630a77e2fb..72895ac050 100644 --- a/examples/rendering/pubspec.yaml +++ b/examples/rendering/pubspec.yaml @@ -1,9 +1,9 @@ name: rendering dependencies: - sky: any + flutter: any sky_tools: any dependency_overrides: material_design_icons: path: ../../sky/packages/material_design_icons - sky: + flutter: path: ../../sky/packages/sky diff --git a/examples/rendering/render_grid.dart b/examples/rendering/render_grid.dart index a2e31cf0c8..111fe172df 100644 --- a/examples/rendering/render_grid.dart +++ b/examples/rendering/render_grid.dart @@ -4,8 +4,8 @@ import 'dart:math' as math; -import 'package:sky/material.dart'; -import 'package:sky/rendering.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart'; import 'solid_color_box.dart'; diff --git a/examples/rendering/render_paragraph.dart b/examples/rendering/render_paragraph.dart index e4ab3b4b77..83a9bb0413 100644 --- a/examples/rendering/render_paragraph.dart +++ b/examples/rendering/render_paragraph.dart @@ -2,7 +2,7 @@ // 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:flutter/rendering.dart'; import 'solid_color_box.dart'; diff --git a/examples/rendering/sector_layout.dart b/examples/rendering/sector_layout.dart index 1bafaeb52f..9e4a9889a4 100644 --- a/examples/rendering/sector_layout.dart +++ b/examples/rendering/sector_layout.dart @@ -5,7 +5,7 @@ import 'dart:math' as math; import 'dart:ui' as sky; -import 'package:sky/rendering.dart'; +import 'package:flutter/rendering.dart'; const double kTwoPi = 2 * math.PI; diff --git a/examples/rendering/shadowed_box.dart b/examples/rendering/shadowed_box.dart index 65f70d73c1..130b13765c 100644 --- a/examples/rendering/shadowed_box.dart +++ b/examples/rendering/shadowed_box.dart @@ -4,8 +4,8 @@ import 'dart:ui'; -import 'package:sky/rendering.dart'; -import 'package:sky/material.dart'; +import 'package:flutter/rendering.dart'; +import 'package:flutter/material.dart'; void main() { var coloredBox = new RenderDecoratedBox( diff --git a/examples/rendering/simple_autolayout.dart b/examples/rendering/simple_autolayout.dart index a62dba873f..086e2354aa 100644 --- a/examples/rendering/simple_autolayout.dart +++ b/examples/rendering/simple_autolayout.dart @@ -5,7 +5,7 @@ import 'dart:ui'; import 'package:cassowary/cassowary.dart' as al; -import 'package:sky/rendering.dart'; +import 'package:flutter/rendering.dart'; void main() { RenderDecoratedBox c1 = new RenderDecoratedBox( diff --git a/examples/rendering/solid_color_box.dart b/examples/rendering/solid_color_box.dart index 136cd6eeb8..689631796a 100644 --- a/examples/rendering/solid_color_box.dart +++ b/examples/rendering/solid_color_box.dart @@ -4,7 +4,7 @@ import 'dart:ui' as sky; -import 'package:sky/rendering.dart'; +import 'package:flutter/rendering.dart'; class RenderSolidColorBox extends RenderDecoratedBox { final Size desiredSize; diff --git a/examples/rendering/spinning_flex.dart b/examples/rendering/spinning_flex.dart index 6c1455f35b..ea9ba7651c 100644 --- a/examples/rendering/spinning_flex.dart +++ b/examples/rendering/spinning_flex.dart @@ -4,8 +4,8 @@ import 'dart:ui' as sky; -import 'package:sky/animation.dart'; -import 'package:sky/rendering.dart'; +import 'package:flutter/animation.dart'; +import 'package:flutter/rendering.dart'; import 'solid_color_box.dart'; diff --git a/examples/rendering/touch_demo.dart b/examples/rendering/touch_demo.dart index 56c1d64aca..9a6ec80481 100644 --- a/examples/rendering/touch_demo.dart +++ b/examples/rendering/touch_demo.dart @@ -4,8 +4,8 @@ import 'dart:ui' as sky; -import 'package:sky/material.dart'; -import 'package:sky/rendering.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart'; // Material design colors. :p List kColors = [ diff --git a/examples/rendering/transform.dart b/examples/rendering/transform.dart index 9b5d3a041d..d34758fd3e 100644 --- a/examples/rendering/transform.dart +++ b/examples/rendering/transform.dart @@ -4,7 +4,7 @@ import 'dart:ui' as sky; -import 'package:sky/rendering.dart'; +import 'package:flutter/rendering.dart'; void main() { RenderDecoratedBox green = new RenderDecoratedBox( diff --git a/examples/stocks/lib/main.dart b/examples/stocks/lib/main.dart index 1ba3fdd664..35c7baf6c5 100644 --- a/examples/stocks/lib/main.dart +++ b/examples/stocks/lib/main.dart @@ -8,9 +8,9 @@ import 'dart:async'; import 'dart:math' as math; import 'dart:ui' as sky; -import 'package:sky/gestures.dart'; -import 'package:sky/material.dart'; -import 'package:sky/painting.dart'; +import 'package:flutter/gestures.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/painting.dart'; import 'stock_data.dart'; diff --git a/examples/stocks/lib/stock_data.dart b/examples/stocks/lib/stock_data.dart index 7326970ad9..ed7c726501 100644 --- a/examples/stocks/lib/stock_data.dart +++ b/examples/stocks/lib/stock_data.dart @@ -10,7 +10,7 @@ import 'dart:convert'; import 'dart:math' as math; -import 'package:sky/services.dart'; +import 'package:flutter/services.dart'; final math.Random _rng = new math.Random(); diff --git a/examples/stocks/pubspec.yaml b/examples/stocks/pubspec.yaml index a169d925c0..23b2d38b84 100644 --- a/examples/stocks/pubspec.yaml +++ b/examples/stocks/pubspec.yaml @@ -1,9 +1,9 @@ name: stocks dependencies: - sky: any + flutter: any sky_tools: any dependency_overrides: material_design_icons: path: ../../sky/packages/material_design_icons - sky: + flutter: path: ../../sky/packages/sky diff --git a/examples/widgets/big_switch.dart b/examples/widgets/big_switch.dart index cd812fac33..46a9165a25 100644 --- a/examples/widgets/big_switch.dart +++ b/examples/widgets/big_switch.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:sky/material.dart'; +import 'package:flutter/material.dart'; class BigSwitch extends StatefulComponent { BigSwitch({ this.scale }); diff --git a/examples/widgets/card_collection.dart b/examples/widgets/card_collection.dart index e2f45aee5f..6cbb9889c1 100644 --- a/examples/widgets/card_collection.dart +++ b/examples/widgets/card_collection.dart @@ -4,8 +4,8 @@ import 'dart:ui' as sky; -import 'package:sky/material.dart'; -import 'package:sky/painting.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/painting.dart'; class CardModel { CardModel(this.value, this.height) { diff --git a/examples/widgets/container.dart b/examples/widgets/container.dart index 5a4b929753..9416f7be7b 100644 --- a/examples/widgets/container.dart +++ b/examples/widgets/container.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:sky/material.dart'; +import 'package:flutter/material.dart'; class ContainerApp extends StatelessComponent { Widget build(BuildContext context) { diff --git a/examples/widgets/date_picker.dart b/examples/widgets/date_picker.dart index 845af140f6..8d871dee0d 100644 --- a/examples/widgets/date_picker.dart +++ b/examples/widgets/date_picker.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:sky/material.dart'; +import 'package:flutter/material.dart'; void main() => runApp(new DatePickerDemo()); diff --git a/examples/widgets/drag_and_drop.dart b/examples/widgets/drag_and_drop.dart index 7de9a6b348..63f4d736ad 100644 --- a/examples/widgets/drag_and_drop.dart +++ b/examples/widgets/drag_and_drop.dart @@ -2,9 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:sky/material.dart'; -import 'package:sky/painting.dart'; -import 'package:sky/rendering.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/painting.dart'; +import 'package:flutter/rendering.dart'; class DragData { DragData(this.text); diff --git a/examples/widgets/ensure_visible.dart b/examples/widgets/ensure_visible.dart index fe570fdfda..e4707f72e1 100644 --- a/examples/widgets/ensure_visible.dart +++ b/examples/widgets/ensure_visible.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:sky/material.dart'; +import 'package:flutter/material.dart'; class CardModel { CardModel(this.value, this.height, this.color); diff --git a/examples/widgets/horizontal_scrolling.dart b/examples/widgets/horizontal_scrolling.dart index 52fae2a1d0..f3b26a50ed 100644 --- a/examples/widgets/horizontal_scrolling.dart +++ b/examples/widgets/horizontal_scrolling.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:sky/widgets.dart'; +import 'package:flutter/widgets.dart'; class Circle extends StatelessComponent { Circle({ this.margin: EdgeDims.zero }); diff --git a/examples/widgets/indexed_stack.dart b/examples/widgets/indexed_stack.dart index 5f23624d98..4c0ce83122 100644 --- a/examples/widgets/indexed_stack.dart +++ b/examples/widgets/indexed_stack.dart @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:sky/material.dart'; -import 'package:sky/rendering.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart'; class IndexedStackDemo extends StatefulComponent { IndexedStackDemo({ this.navigator }); diff --git a/examples/widgets/navigation.dart b/examples/widgets/navigation.dart index 9624c20588..73224f4a62 100644 --- a/examples/widgets/navigation.dart +++ b/examples/widgets/navigation.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:sky/material.dart'; +import 'package:flutter/material.dart'; final Map routes = { '/': (RouteArguments args) => new Container( diff --git a/examples/widgets/overlay_geometry.dart b/examples/widgets/overlay_geometry.dart index 9b28ca113f..872a2533f6 100644 --- a/examples/widgets/overlay_geometry.dart +++ b/examples/widgets/overlay_geometry.dart @@ -4,8 +4,8 @@ import 'dart:ui' as sky; -import 'package:sky/material.dart'; -import 'package:sky/rendering.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart'; class CardModel { CardModel(this.value, this.height, this.color); diff --git a/examples/widgets/pageable_list.dart b/examples/widgets/pageable_list.dart index 05d216d06f..8dc8c36d1d 100644 --- a/examples/widgets/pageable_list.dart +++ b/examples/widgets/pageable_list.dart @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:sky/material.dart'; -import 'package:sky/painting.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/painting.dart'; class CardModel { CardModel(this.value, this.size, this.color); diff --git a/examples/widgets/piano.dart b/examples/widgets/piano.dart index 14845b0e2a..63bf0a40e5 100644 --- a/examples/widgets/piano.dart +++ b/examples/widgets/piano.dart @@ -4,9 +4,9 @@ import 'package:mojo/mojo/url_response.mojom.dart'; import 'package:sky_services/media/media.mojom.dart'; -import 'package:sky/material.dart'; -import 'package:sky/rendering.dart'; -import 'package:sky/services.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart'; +import 'package:flutter/services.dart'; // All of these sounds are marked as public domain at soundbible. const String chimes = "http://soundbible.com/grab.php?id=2030&type=wav"; diff --git a/examples/widgets/progress_indicator.dart b/examples/widgets/progress_indicator.dart index 511f2484df..fdf2338008 100644 --- a/examples/widgets/progress_indicator.dart +++ b/examples/widgets/progress_indicator.dart @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:sky/animation.dart'; -import 'package:sky/material.dart'; +import 'package:flutter/animation.dart'; +import 'package:flutter/material.dart'; class ProgressIndicatorApp extends StatefulComponent { ProgressIndicatorAppState createState() => new ProgressIndicatorAppState(); diff --git a/examples/widgets/pubspec.yaml b/examples/widgets/pubspec.yaml index af25190f71..e4c55adc07 100644 --- a/examples/widgets/pubspec.yaml +++ b/examples/widgets/pubspec.yaml @@ -1,9 +1,9 @@ name: widgets dependencies: - sky: any + flutter: any sky_tools: any dependency_overrides: material_design_icons: path: ../../sky/packages/material_design_icons - sky: + flutter: path: ../../sky/packages/sky diff --git a/examples/widgets/scale.dart b/examples/widgets/scale.dart index ecd4c8d41f..47824c82fa 100644 --- a/examples/widgets/scale.dart +++ b/examples/widgets/scale.dart @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:sky/material.dart'; -import 'package:sky/rendering.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart'; class ScaleApp extends StatefulComponent { ScaleAppState createState() => new ScaleAppState(); diff --git a/examples/widgets/sector.dart b/examples/widgets/sector.dart index d6253c228f..624ba1541b 100644 --- a/examples/widgets/sector.dart +++ b/examples/widgets/sector.dart @@ -4,8 +4,8 @@ import 'dart:math' as math; -import 'package:sky/material.dart'; -import 'package:sky/rendering.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart'; import '../rendering/sector_layout.dart'; diff --git a/examples/widgets/spinning_mixed.dart b/examples/widgets/spinning_mixed.dart index cfde0b373a..b59c6e3c74 100644 --- a/examples/widgets/spinning_mixed.dart +++ b/examples/widgets/spinning_mixed.dart @@ -4,9 +4,9 @@ import 'dart:ui' as sky; -import 'package:sky/animation.dart'; -import 'package:sky/material.dart'; -import 'package:sky/rendering.dart'; +import 'package:flutter/animation.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart'; import '../rendering/solid_color_box.dart'; diff --git a/examples/widgets/styled_text.dart b/examples/widgets/styled_text.dart index 1764acd227..2603b3c464 100644 --- a/examples/widgets/styled_text.dart +++ b/examples/widgets/styled_text.dart @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:sky/material.dart'; -import 'package:sky/rendering.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart'; class StyledTextApp extends StatefulComponent { StyledTextAppState createState() => new StyledTextAppState(); diff --git a/examples/widgets/tabs.dart b/examples/widgets/tabs.dart index cec0e7aa53..5a84f93234 100644 --- a/examples/widgets/tabs.dart +++ b/examples/widgets/tabs.dart @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:sky/material.dart'; -import 'package:sky/painting.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/painting.dart'; class TabbedNavigatorApp extends StatefulComponent { TabbedNavigatorAppState createState() => new TabbedNavigatorAppState(); diff --git a/packages/flutter/lib/src/material/card.dart b/packages/flutter/lib/src/material/card.dart index caf2a647d4..4090b3f2a2 100644 --- a/packages/flutter/lib/src/material/card.dart +++ b/packages/flutter/lib/src/material/card.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:sky/widgets.dart'; +import 'package:flutter/widgets.dart'; import 'material.dart'; diff --git a/packages/flutter/lib/src/material/checkbox.dart b/packages/flutter/lib/src/material/checkbox.dart index d02619e50e..1c42cf32ef 100644 --- a/packages/flutter/lib/src/material/checkbox.dart +++ b/packages/flutter/lib/src/material/checkbox.dart @@ -4,12 +4,12 @@ import 'dart:ui' as sky; -import 'package:sky/rendering.dart'; -import 'package:sky/widgets.dart'; +import 'package:flutter/rendering.dart'; +import 'package:flutter/widgets.dart'; import 'theme.dart'; -export 'package:sky/rendering.dart' show ValueChanged; +export 'package:flutter/rendering.dart' show ValueChanged; const double _kMidpoint = 0.5; const sky.Color _kLightUncheckedColor = const sky.Color(0x8A000000); diff --git a/packages/flutter/lib/src/material/date_picker.dart b/packages/flutter/lib/src/material/date_picker.dart index 6e09578e48..12b9227c67 100644 --- a/packages/flutter/lib/src/material/date_picker.dart +++ b/packages/flutter/lib/src/material/date_picker.dart @@ -6,9 +6,9 @@ import 'dart:async'; import 'package:intl/date_symbols.dart'; import 'package:intl/intl.dart'; -import 'package:sky/painting.dart'; -import 'package:sky/services.dart'; -import 'package:sky/widgets.dart'; +import 'package:flutter/painting.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter/widgets.dart'; import 'colors.dart'; import 'ink_well.dart'; diff --git a/packages/flutter/lib/src/material/dialog.dart b/packages/flutter/lib/src/material/dialog.dart index a3064fe5b2..596ceb61f6 100644 --- a/packages/flutter/lib/src/material/dialog.dart +++ b/packages/flutter/lib/src/material/dialog.dart @@ -4,9 +4,9 @@ import 'dart:async'; -import 'package:sky/animation.dart'; -import 'package:sky/gestures.dart'; -import 'package:sky/widgets.dart'; +import 'package:flutter/animation.dart'; +import 'package:flutter/gestures.dart'; +import 'package:flutter/widgets.dart'; import 'colors.dart'; import 'material_button.dart'; diff --git a/packages/flutter/lib/src/material/drawer.dart b/packages/flutter/lib/src/material/drawer.dart index 12ebda6b09..8e6dc024f4 100644 --- a/packages/flutter/lib/src/material/drawer.dart +++ b/packages/flutter/lib/src/material/drawer.dart @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:sky/animation.dart'; -import 'package:sky/widgets.dart'; +import 'package:flutter/animation.dart'; +import 'package:flutter/widgets.dart'; import 'colors.dart'; import 'shadows.dart'; diff --git a/packages/flutter/lib/src/material/drawer_divider.dart b/packages/flutter/lib/src/material/drawer_divider.dart index a9f1088270..4816892121 100644 --- a/packages/flutter/lib/src/material/drawer_divider.dart +++ b/packages/flutter/lib/src/material/drawer_divider.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:sky/widgets.dart'; +import 'package:flutter/widgets.dart'; import 'theme.dart'; diff --git a/packages/flutter/lib/src/material/drawer_header.dart b/packages/flutter/lib/src/material/drawer_header.dart index e95f1b039d..8078c0179b 100644 --- a/packages/flutter/lib/src/material/drawer_header.dart +++ b/packages/flutter/lib/src/material/drawer_header.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:sky/widgets.dart'; +import 'package:flutter/widgets.dart'; import 'constants.dart'; import 'theme.dart'; diff --git a/packages/flutter/lib/src/material/drawer_item.dart b/packages/flutter/lib/src/material/drawer_item.dart index 9a89515c65..c5659c5910 100644 --- a/packages/flutter/lib/src/material/drawer_item.dart +++ b/packages/flutter/lib/src/material/drawer_item.dart @@ -4,9 +4,9 @@ import 'dart:ui' as sky; -import 'package:sky/gestures.dart'; -import 'package:sky/painting.dart'; -import 'package:sky/widgets.dart'; +import 'package:flutter/gestures.dart'; +import 'package:flutter/painting.dart'; +import 'package:flutter/widgets.dart'; import 'colors.dart'; import 'icon.dart'; diff --git a/packages/flutter/lib/src/material/flat_button.dart b/packages/flutter/lib/src/material/flat_button.dart index 0737afa760..5def34464a 100644 --- a/packages/flutter/lib/src/material/flat_button.dart +++ b/packages/flutter/lib/src/material/flat_button.dart @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:sky/gestures.dart'; -import 'package:sky/widgets.dart'; +import 'package:flutter/gestures.dart'; +import 'package:flutter/widgets.dart'; import 'colors.dart'; import 'material_button.dart'; diff --git a/packages/flutter/lib/src/material/floating_action_button.dart b/packages/flutter/lib/src/material/floating_action_button.dart index 368e3c5ad7..e9b6d83c88 100644 --- a/packages/flutter/lib/src/material/floating_action_button.dart +++ b/packages/flutter/lib/src/material/floating_action_button.dart @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:sky/gestures.dart'; -import 'package:sky/widgets.dart'; +import 'package:flutter/gestures.dart'; +import 'package:flutter/widgets.dart'; import 'icon.dart'; import 'ink_well.dart'; diff --git a/packages/flutter/lib/src/material/icon.dart b/packages/flutter/lib/src/material/icon.dart index 32facf2a25..d991cd43d4 100644 --- a/packages/flutter/lib/src/material/icon.dart +++ b/packages/flutter/lib/src/material/icon.dart @@ -4,8 +4,8 @@ import 'dart:ui' as sky; -import 'package:sky/services.dart'; -import 'package:sky/widgets.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter/widgets.dart'; import 'theme.dart'; diff --git a/packages/flutter/lib/src/material/icon_button.dart b/packages/flutter/lib/src/material/icon_button.dart index dc355e9474..292bc823e5 100644 --- a/packages/flutter/lib/src/material/icon_button.dart +++ b/packages/flutter/lib/src/material/icon_button.dart @@ -4,8 +4,8 @@ import 'dart:ui' as sky; -import 'package:sky/gestures.dart'; -import 'package:sky/widgets.dart'; +import 'package:flutter/gestures.dart'; +import 'package:flutter/widgets.dart'; import 'icon.dart'; diff --git a/packages/flutter/lib/src/material/ink_well.dart b/packages/flutter/lib/src/material/ink_well.dart index 5140bbf1a0..9bb4feddbc 100644 --- a/packages/flutter/lib/src/material/ink_well.dart +++ b/packages/flutter/lib/src/material/ink_well.dart @@ -6,10 +6,10 @@ import 'dart:async'; import 'dart:math' as math; import 'dart:ui' as sky; -import 'package:sky/animation.dart'; -import 'package:sky/gestures.dart'; -import 'package:sky/rendering.dart'; -import 'package:sky/widgets.dart'; +import 'package:flutter/animation.dart'; +import 'package:flutter/gestures.dart'; +import 'package:flutter/rendering.dart'; +import 'package:flutter/widgets.dart'; const int _kSplashInitialOpacity = 0x30; const double _kSplashCanceledVelocity = 0.7; diff --git a/packages/flutter/lib/src/material/input.dart b/packages/flutter/lib/src/material/input.dart index 0b2ad3cb17..608601d4d4 100644 --- a/packages/flutter/lib/src/material/input.dart +++ b/packages/flutter/lib/src/material/input.dart @@ -2,15 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:sky/animation.dart'; -import 'package:sky/services.dart'; -import 'package:sky/painting.dart'; -import 'package:sky/rendering.dart'; -import 'package:sky/widgets.dart'; +import 'package:flutter/animation.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter/painting.dart'; +import 'package:flutter/rendering.dart'; +import 'package:flutter/widgets.dart'; import 'theme.dart'; -export 'package:sky/services.dart' show KeyboardType; +export 'package:flutter/services.dart' show KeyboardType; typedef void StringValueChanged(String value); diff --git a/packages/flutter/lib/src/material/material.dart b/packages/flutter/lib/src/material/material.dart index 614dd0d2a3..03080432d2 100644 --- a/packages/flutter/lib/src/material/material.dart +++ b/packages/flutter/lib/src/material/material.dart @@ -2,9 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:sky/animation.dart'; -import 'package:sky/painting.dart'; -import 'package:sky/widgets.dart'; +import 'package:flutter/animation.dart'; +import 'package:flutter/painting.dart'; +import 'package:flutter/widgets.dart'; import 'constants.dart'; import 'shadows.dart'; diff --git a/packages/flutter/lib/src/material/material_app.dart b/packages/flutter/lib/src/material/material_app.dart index f326b9ff04..afa81b9a28 100644 --- a/packages/flutter/lib/src/material/material_app.dart +++ b/packages/flutter/lib/src/material/material_app.dart @@ -4,9 +4,9 @@ import 'dart:ui' as sky; -import 'package:sky/painting.dart'; -import 'package:sky/services.dart'; -import 'package:sky/widgets.dart'; +import 'package:flutter/painting.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter/widgets.dart'; import 'theme.dart'; import 'title.dart'; diff --git a/packages/flutter/lib/src/material/material_button.dart b/packages/flutter/lib/src/material/material_button.dart index 23f28e9353..0a343e9edc 100644 --- a/packages/flutter/lib/src/material/material_button.dart +++ b/packages/flutter/lib/src/material/material_button.dart @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:sky/gestures.dart'; -import 'package:sky/widgets.dart'; +import 'package:flutter/gestures.dart'; +import 'package:flutter/widgets.dart'; import 'colors.dart'; import 'ink_well.dart'; diff --git a/packages/flutter/lib/src/material/popup_menu.dart b/packages/flutter/lib/src/material/popup_menu.dart index eee0b9fe25..750d01dcce 100644 --- a/packages/flutter/lib/src/material/popup_menu.dart +++ b/packages/flutter/lib/src/material/popup_menu.dart @@ -5,9 +5,9 @@ import 'dart:async'; import 'dart:ui' as sky; -import 'package:sky/animation.dart'; -import 'package:sky/painting.dart'; -import 'package:sky/widgets.dart'; +import 'package:flutter/animation.dart'; +import 'package:flutter/painting.dart'; +import 'package:flutter/widgets.dart'; import 'ink_well.dart'; import 'popup_menu_item.dart'; diff --git a/packages/flutter/lib/src/material/popup_menu_item.dart b/packages/flutter/lib/src/material/popup_menu_item.dart index d09bda2be1..f785eb838f 100644 --- a/packages/flutter/lib/src/material/popup_menu_item.dart +++ b/packages/flutter/lib/src/material/popup_menu_item.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:sky/widgets.dart'; +import 'package:flutter/widgets.dart'; import 'theme.dart'; diff --git a/packages/flutter/lib/src/material/progress_indicator.dart b/packages/flutter/lib/src/material/progress_indicator.dart index cf640a48f5..c7d0e8c39f 100644 --- a/packages/flutter/lib/src/material/progress_indicator.dart +++ b/packages/flutter/lib/src/material/progress_indicator.dart @@ -5,8 +5,8 @@ import 'dart:math' as math; import 'dart:ui' as sky; -import 'package:sky/animation.dart'; -import 'package:sky/widgets.dart'; +import 'package:flutter/animation.dart'; +import 'package:flutter/widgets.dart'; import 'theme.dart'; diff --git a/packages/flutter/lib/src/material/radial_reaction.dart b/packages/flutter/lib/src/material/radial_reaction.dart index a3d68db5ee..409cd647c1 100644 --- a/packages/flutter/lib/src/material/radial_reaction.dart +++ b/packages/flutter/lib/src/material/radial_reaction.dart @@ -6,7 +6,7 @@ import 'dart:async'; import 'dart:ui' as sky; import 'dart:ui' show Point, Offset, Color, Paint; -import 'package:sky/animation.dart'; +import 'package:flutter/animation.dart'; const Duration _kShowDuration = const Duration(milliseconds: 300); const Duration _kHideDuration = const Duration(milliseconds: 200); diff --git a/packages/flutter/lib/src/material/radio.dart b/packages/flutter/lib/src/material/radio.dart index fc54cc8893..e44f809897 100644 --- a/packages/flutter/lib/src/material/radio.dart +++ b/packages/flutter/lib/src/material/radio.dart @@ -4,7 +4,7 @@ import 'dart:ui' as sky; -import 'package:sky/widgets.dart'; +import 'package:flutter/widgets.dart'; import 'theme.dart'; diff --git a/packages/flutter/lib/src/material/raised_button.dart b/packages/flutter/lib/src/material/raised_button.dart index a41b8624ac..2f1d9f7ce4 100644 --- a/packages/flutter/lib/src/material/raised_button.dart +++ b/packages/flutter/lib/src/material/raised_button.dart @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:sky/gestures.dart'; -import 'package:sky/widgets.dart'; +import 'package:flutter/gestures.dart'; +import 'package:flutter/widgets.dart'; import 'colors.dart'; import 'material_button.dart'; diff --git a/packages/flutter/lib/src/material/scaffold.dart b/packages/flutter/lib/src/material/scaffold.dart index 3d4fbd85d4..55a7af32b1 100644 --- a/packages/flutter/lib/src/material/scaffold.dart +++ b/packages/flutter/lib/src/material/scaffold.dart @@ -4,8 +4,8 @@ import 'dart:ui' as sky; -import 'package:sky/rendering.dart'; -import 'package:sky/widgets.dart'; +import 'package:flutter/rendering.dart'; +import 'package:flutter/widgets.dart'; import 'constants.dart'; diff --git a/packages/flutter/lib/src/material/shadows.dart b/packages/flutter/lib/src/material/shadows.dart index 17280dd092..f9e998eef4 100644 --- a/packages/flutter/lib/src/material/shadows.dart +++ b/packages/flutter/lib/src/material/shadows.dart @@ -4,7 +4,7 @@ import 'dart:ui' show Color, Offset; -import 'package:sky/painting.dart'; +import 'package:flutter/painting.dart'; const Map> shadows = const { 1: const [ diff --git a/packages/flutter/lib/src/material/snack_bar.dart b/packages/flutter/lib/src/material/snack_bar.dart index 7c663fecd2..7aa793e229 100644 --- a/packages/flutter/lib/src/material/snack_bar.dart +++ b/packages/flutter/lib/src/material/snack_bar.dart @@ -2,10 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:sky/animation.dart'; -import 'package:sky/gestures.dart'; -import 'package:sky/painting.dart'; -import 'package:sky/widgets.dart'; +import 'package:flutter/animation.dart'; +import 'package:flutter/gestures.dart'; +import 'package:flutter/painting.dart'; +import 'package:flutter/widgets.dart'; import 'constants.dart'; import 'material.dart'; diff --git a/packages/flutter/lib/src/material/switch.dart b/packages/flutter/lib/src/material/switch.dart index ab9573078b..5bf2194541 100644 --- a/packages/flutter/lib/src/material/switch.dart +++ b/packages/flutter/lib/src/material/switch.dart @@ -5,15 +5,15 @@ import 'dart:async'; import 'dart:ui' as sky; -import 'package:sky/painting.dart'; -import 'package:sky/rendering.dart'; -import 'package:sky/widgets.dart'; +import 'package:flutter/painting.dart'; +import 'package:flutter/rendering.dart'; +import 'package:flutter/widgets.dart'; import 'radial_reaction.dart'; import 'shadows.dart'; import 'theme.dart'; -export 'package:sky/rendering.dart' show ValueChanged; +export 'package:flutter/rendering.dart' show ValueChanged; const sky.Color _kThumbOffColor = const sky.Color(0xFFFAFAFA); const sky.Color _kTrackOffColor = const sky.Color(0x42000000); diff --git a/packages/flutter/lib/src/material/tabs.dart b/packages/flutter/lib/src/material/tabs.dart index 8ef3ae424b..543aebddbd 100644 --- a/packages/flutter/lib/src/material/tabs.dart +++ b/packages/flutter/lib/src/material/tabs.dart @@ -6,11 +6,11 @@ import 'dart:math' as math; import 'dart:ui' as sky; import 'package:newton/newton.dart'; -import 'package:sky/animation.dart'; -import 'package:sky/gestures.dart'; -import 'package:sky/painting.dart'; -import 'package:sky/rendering.dart'; -import 'package:sky/widgets.dart'; +import 'package:flutter/animation.dart'; +import 'package:flutter/gestures.dart'; +import 'package:flutter/painting.dart'; +import 'package:flutter/rendering.dart'; +import 'package:flutter/widgets.dart'; import 'colors.dart'; import 'constants.dart'; diff --git a/packages/flutter/lib/src/material/theme.dart b/packages/flutter/lib/src/material/theme.dart index e46a79ffc4..aeff56fb43 100644 --- a/packages/flutter/lib/src/material/theme.dart +++ b/packages/flutter/lib/src/material/theme.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:sky/widgets.dart'; +import 'package:flutter/widgets.dart'; import 'theme_data.dart'; diff --git a/packages/flutter/lib/src/material/theme_data.dart b/packages/flutter/lib/src/material/theme_data.dart index bee746dd97..f5a8e1fabd 100644 --- a/packages/flutter/lib/src/material/theme_data.dart +++ b/packages/flutter/lib/src/material/theme_data.dart @@ -4,8 +4,8 @@ import 'dart:ui'; -import 'package:sky/src/material/typography.dart'; -import 'package:sky/src/material/colors.dart'; +import 'package:flutter/src/material/typography.dart'; +import 'package:flutter/src/material/colors.dart'; enum ThemeBrightness { dark, light } diff --git a/packages/flutter/lib/src/material/title.dart b/packages/flutter/lib/src/material/title.dart index bcba1421c4..deca5d18b8 100644 --- a/packages/flutter/lib/src/material/title.dart +++ b/packages/flutter/lib/src/material/title.dart @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:sky/services.dart'; -import 'package:sky/widgets.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter/widgets.dart'; import 'theme.dart'; diff --git a/packages/flutter/lib/src/material/tool_bar.dart b/packages/flutter/lib/src/material/tool_bar.dart index 6be4c60d65..5629b1d5fb 100644 --- a/packages/flutter/lib/src/material/tool_bar.dart +++ b/packages/flutter/lib/src/material/tool_bar.dart @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:sky/painting.dart'; -import 'package:sky/widgets.dart'; +import 'package:flutter/painting.dart'; +import 'package:flutter/widgets.dart'; import 'constants.dart'; import 'icon.dart'; diff --git a/packages/flutter/lib/src/material/typography.dart b/packages/flutter/lib/src/material/typography.dart index 28ad98ffb2..396b0acd1f 100644 --- a/packages/flutter/lib/src/material/typography.dart +++ b/packages/flutter/lib/src/material/typography.dart @@ -6,8 +6,8 @@ import 'dart:ui' show Color; -import 'package:sky/painting.dart'; -import 'package:sky/src/material/colors.dart'; +import 'package:flutter/painting.dart'; +import 'package:flutter/src/material/colors.dart'; // TODO(eseidel): Font weights are supposed to be language relative! // TODO(jackson): Baseline should be language relative! diff --git a/packages/flutter/lib/src/painting/box_painter.dart b/packages/flutter/lib/src/painting/box_painter.dart index 4eb16eb1f4..110aa4421e 100644 --- a/packages/flutter/lib/src/painting/box_painter.dart +++ b/packages/flutter/lib/src/painting/box_painter.dart @@ -6,7 +6,7 @@ import 'dart:math' as math; import 'dart:ui' as sky; import 'dart:ui' show Point, Offset, Size, Rect, Color, Paint, Path; -import 'package:sky/services.dart'; +import 'package:flutter/services.dart'; import 'shadows.dart'; diff --git a/packages/flutter/lib/src/rendering/binding.dart b/packages/flutter/lib/src/rendering/binding.dart index 8c1f9ab59e..d2a6526bf3 100644 --- a/packages/flutter/lib/src/rendering/binding.dart +++ b/packages/flutter/lib/src/rendering/binding.dart @@ -4,8 +4,8 @@ import 'dart:ui' as sky; -import 'package:sky/animation.dart'; -import 'package:sky/gestures.dart'; +import 'package:flutter/animation.dart'; +import 'package:flutter/gestures.dart'; import 'box.dart'; import 'hit_test.dart'; diff --git a/packages/flutter/lib/src/rendering/box.dart b/packages/flutter/lib/src/rendering/box.dart index 96c107c261..3a3c52d7e1 100644 --- a/packages/flutter/lib/src/rendering/box.dart +++ b/packages/flutter/lib/src/rendering/box.dart @@ -5,13 +5,13 @@ import 'dart:math' as math; import 'dart:ui' as sky; -import 'package:sky/painting.dart'; +import 'package:flutter/painting.dart'; import 'package:vector_math/vector_math_64.dart'; import 'debug.dart'; import 'object.dart'; -export 'package:sky/painting.dart' show TextBaseline; +export 'package:flutter/painting.dart' show TextBaseline; // This class should only be used in debug builds class _DebugSize extends Size { diff --git a/packages/flutter/lib/src/rendering/editable_paragraph.dart b/packages/flutter/lib/src/rendering/editable_paragraph.dart index 95b0886772..31c18372ad 100644 --- a/packages/flutter/lib/src/rendering/editable_paragraph.dart +++ b/packages/flutter/lib/src/rendering/editable_paragraph.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:sky/painting.dart'; +import 'package:flutter/painting.dart'; import 'box.dart'; import 'object.dart'; diff --git a/packages/flutter/lib/src/rendering/image.dart b/packages/flutter/lib/src/rendering/image.dart index c8022e1db3..eda9618663 100644 --- a/packages/flutter/lib/src/rendering/image.dart +++ b/packages/flutter/lib/src/rendering/image.dart @@ -4,7 +4,7 @@ import 'dart:ui' as sky; -import 'package:sky/painting.dart'; +import 'package:flutter/painting.dart'; import 'box.dart'; import 'object.dart'; diff --git a/packages/flutter/lib/src/rendering/object.dart b/packages/flutter/lib/src/rendering/object.dart index f78673f2f1..a08076585e 100644 --- a/packages/flutter/lib/src/rendering/object.dart +++ b/packages/flutter/lib/src/rendering/object.dart @@ -6,7 +6,7 @@ import 'dart:math' as math; import 'dart:ui' as sky; import 'dart:ui' show Point, Offset, Size, Rect, Color, Paint, Path; -import 'package:sky/animation.dart'; +import 'package:flutter/animation.dart'; import 'package:vector_math/vector_math_64.dart'; import 'debug.dart'; diff --git a/packages/flutter/lib/src/rendering/paragraph.dart b/packages/flutter/lib/src/rendering/paragraph.dart index 2abd06904e..67bbfc0baa 100644 --- a/packages/flutter/lib/src/rendering/paragraph.dart +++ b/packages/flutter/lib/src/rendering/paragraph.dart @@ -2,12 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:sky/painting.dart'; +import 'package:flutter/painting.dart'; import 'box.dart'; import 'object.dart'; -export 'package:sky/src/painting/text_painter.dart'; +export 'package:flutter/src/painting/text_painter.dart'; /// A render object that displays a paragraph of text class RenderParagraph extends RenderBox { diff --git a/packages/flutter/lib/src/rendering/proxy_box.dart b/packages/flutter/lib/src/rendering/proxy_box.dart index 3ae758a924..24dc33bf9a 100644 --- a/packages/flutter/lib/src/rendering/proxy_box.dart +++ b/packages/flutter/lib/src/rendering/proxy_box.dart @@ -4,13 +4,13 @@ import 'dart:ui' as sky; -import 'package:sky/painting.dart'; +import 'package:flutter/painting.dart'; import 'package:vector_math/vector_math_64.dart'; import 'box.dart'; import 'object.dart'; -export 'package:sky/src/painting/box_painter.dart'; +export 'package:flutter/src/painting/box_painter.dart'; /// A base class for render objects that resemble their children /// diff --git a/packages/flutter/lib/src/rendering/shifted_box.dart b/packages/flutter/lib/src/rendering/shifted_box.dart index e15675342e..6cab77827b 100644 --- a/packages/flutter/lib/src/rendering/shifted_box.dart +++ b/packages/flutter/lib/src/rendering/shifted_box.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:sky/painting.dart'; +import 'package:flutter/painting.dart'; import 'box.dart'; import 'object.dart'; diff --git a/packages/flutter/lib/src/rendering/toggleable.dart b/packages/flutter/lib/src/rendering/toggleable.dart index f1b1b9b6f7..f5df71db1e 100644 --- a/packages/flutter/lib/src/rendering/toggleable.dart +++ b/packages/flutter/lib/src/rendering/toggleable.dart @@ -4,8 +4,8 @@ import 'dart:ui' as sky; -import 'package:sky/animation.dart'; -import 'package:sky/gestures.dart'; +import 'package:flutter/animation.dart'; +import 'package:flutter/gestures.dart'; import 'binding.dart'; import 'box.dart'; diff --git a/packages/flutter/lib/src/rendering/view.dart b/packages/flutter/lib/src/rendering/view.dart index 6289200eed..9e8a07bfd1 100644 --- a/packages/flutter/lib/src/rendering/view.dart +++ b/packages/flutter/lib/src/rendering/view.dart @@ -4,7 +4,7 @@ import 'dart:ui' as sky; -import 'package:sky/animation.dart'; +import 'package:flutter/animation.dart'; import 'package:vector_math/vector_math_64.dart'; import 'box.dart'; diff --git a/packages/flutter/lib/src/widgets/animated_container.dart b/packages/flutter/lib/src/widgets/animated_container.dart index 5734cfb8cc..307fdd431f 100644 --- a/packages/flutter/lib/src/widgets/animated_container.dart +++ b/packages/flutter/lib/src/widgets/animated_container.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:sky/animation.dart'; +import 'package:flutter/animation.dart'; import 'basic.dart'; import 'framework.dart'; diff --git a/packages/flutter/lib/src/widgets/basic.dart b/packages/flutter/lib/src/widgets/basic.dart index 99bf338173..afde446e3e 100644 --- a/packages/flutter/lib/src/widgets/basic.dart +++ b/packages/flutter/lib/src/widgets/basic.dart @@ -4,12 +4,12 @@ import 'dart:ui' as sky; -import 'package:sky/rendering.dart'; -import 'package:sky/services.dart'; +import 'package:flutter/rendering.dart'; +import 'package:flutter/services.dart'; import 'framework.dart'; -export 'package:sky/rendering.dart' show +export 'package:flutter/rendering.dart' show BackgroundImage, BlockDirection, Border, diff --git a/packages/flutter/lib/src/widgets/binding.dart b/packages/flutter/lib/src/widgets/binding.dart index d6b6393a2f..c73678c52e 100644 --- a/packages/flutter/lib/src/widgets/binding.dart +++ b/packages/flutter/lib/src/widgets/binding.dart @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:sky/animation.dart'; -import 'package:sky/rendering.dart'; +import 'package:flutter/animation.dart'; +import 'package:flutter/rendering.dart'; import 'framework.dart'; diff --git a/packages/flutter/lib/src/widgets/dismissable.dart b/packages/flutter/lib/src/widgets/dismissable.dart index 8114b58d07..6659d61ec1 100644 --- a/packages/flutter/lib/src/widgets/dismissable.dart +++ b/packages/flutter/lib/src/widgets/dismissable.dart @@ -4,7 +4,7 @@ import 'dart:ui' as sky; -import 'package:sky/animation.dart'; +import 'package:flutter/animation.dart'; import 'basic.dart'; import 'transitions.dart'; diff --git a/packages/flutter/lib/src/widgets/drag_target.dart b/packages/flutter/lib/src/widgets/drag_target.dart index 672dfbbca7..8ea0cb8e37 100644 --- a/packages/flutter/lib/src/widgets/drag_target.dart +++ b/packages/flutter/lib/src/widgets/drag_target.dart @@ -5,8 +5,8 @@ import 'dart:collection'; import 'dart:ui' as sky; -import 'package:sky/animation.dart'; -import 'package:sky/rendering.dart'; +import 'package:flutter/animation.dart'; +import 'package:flutter/rendering.dart'; import 'basic.dart'; import 'binding.dart'; diff --git a/packages/flutter/lib/src/widgets/editable_text.dart b/packages/flutter/lib/src/widgets/editable_text.dart index 0990eded4f..c2dc68b9f3 100644 --- a/packages/flutter/lib/src/widgets/editable_text.dart +++ b/packages/flutter/lib/src/widgets/editable_text.dart @@ -5,8 +5,8 @@ import 'dart:async'; import 'package:mojo_services/keyboard/keyboard.mojom.dart'; -import 'package:sky/painting.dart'; -import 'package:sky/rendering.dart'; +import 'package:flutter/painting.dart'; +import 'package:flutter/rendering.dart'; import 'basic.dart'; import 'framework.dart'; diff --git a/packages/flutter/lib/src/widgets/framework.dart b/packages/flutter/lib/src/widgets/framework.dart index e1fc342b19..6df59d33c6 100644 --- a/packages/flutter/lib/src/widgets/framework.dart +++ b/packages/flutter/lib/src/widgets/framework.dart @@ -5,7 +5,7 @@ import 'dart:async'; import 'dart:collection'; -import 'package:sky/rendering.dart'; +import 'package:flutter/rendering.dart'; // KEYS diff --git a/packages/flutter/lib/src/widgets/gesture_detector.dart b/packages/flutter/lib/src/widgets/gesture_detector.dart index 22b9b7e347..288ae05763 100644 --- a/packages/flutter/lib/src/widgets/gesture_detector.dart +++ b/packages/flutter/lib/src/widgets/gesture_detector.dart @@ -4,8 +4,8 @@ import 'dart:ui' as sky; -import 'package:sky/gestures.dart'; -import 'package:sky/rendering.dart'; +import 'package:flutter/gestures.dart'; +import 'package:flutter/rendering.dart'; import 'basic.dart'; import 'framework.dart'; diff --git a/packages/flutter/lib/src/widgets/homogeneous_viewport.dart b/packages/flutter/lib/src/widgets/homogeneous_viewport.dart index 18ac69adee..54f33506a2 100644 --- a/packages/flutter/lib/src/widgets/homogeneous_viewport.dart +++ b/packages/flutter/lib/src/widgets/homogeneous_viewport.dart @@ -4,9 +4,9 @@ import 'dart:math' as math; -import 'package:sky/rendering.dart'; -import 'package:sky/src/widgets/framework.dart'; -import 'package:sky/src/widgets/basic.dart'; +import 'package:flutter/rendering.dart'; +import 'package:flutter/src/widgets/framework.dart'; +import 'package:flutter/src/widgets/basic.dart'; typedef List ListBuilder(BuildContext context, int startIndex, int count); diff --git a/packages/flutter/lib/src/widgets/mimic.dart b/packages/flutter/lib/src/widgets/mimic.dart index 69006782ca..6170daa36e 100644 --- a/packages/flutter/lib/src/widgets/mimic.dart +++ b/packages/flutter/lib/src/widgets/mimic.dart @@ -2,7 +2,7 @@ // 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:flutter/rendering.dart'; import 'basic.dart'; import 'framework.dart'; diff --git a/packages/flutter/lib/src/widgets/mixed_viewport.dart b/packages/flutter/lib/src/widgets/mixed_viewport.dart index 3941ec81b9..83a2bf6c3b 100644 --- a/packages/flutter/lib/src/widgets/mixed_viewport.dart +++ b/packages/flutter/lib/src/widgets/mixed_viewport.dart @@ -2,7 +2,7 @@ // 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:flutter/rendering.dart'; import 'framework.dart'; import 'basic.dart'; diff --git a/packages/flutter/lib/src/widgets/navigator.dart b/packages/flutter/lib/src/widgets/navigator.dart index c6345a1a02..c326efd747 100644 --- a/packages/flutter/lib/src/widgets/navigator.dart +++ b/packages/flutter/lib/src/widgets/navigator.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:sky/animation.dart'; +import 'package:flutter/animation.dart'; import 'basic.dart'; import 'focus.dart'; diff --git a/packages/flutter/lib/src/widgets/scrollable.dart b/packages/flutter/lib/src/widgets/scrollable.dart index 6fe36e3394..0ae33f9a7e 100644 --- a/packages/flutter/lib/src/widgets/scrollable.dart +++ b/packages/flutter/lib/src/widgets/scrollable.dart @@ -7,9 +7,9 @@ import 'dart:math' as math; import 'dart:ui' as sky; import 'package:newton/newton.dart'; -import 'package:sky/animation.dart'; -import 'package:sky/gestures.dart'; -import 'package:sky/rendering.dart'; +import 'package:flutter/animation.dart'; +import 'package:flutter/gestures.dart'; +import 'package:flutter/rendering.dart'; import 'basic.dart'; import 'framework.dart'; diff --git a/packages/flutter/lib/src/widgets/statistics_overlay.dart b/packages/flutter/lib/src/widgets/statistics_overlay.dart index 80fa77915e..6784fa9c6b 100644 --- a/packages/flutter/lib/src/widgets/statistics_overlay.dart +++ b/packages/flutter/lib/src/widgets/statistics_overlay.dart @@ -2,7 +2,7 @@ // 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:flutter/rendering.dart'; import 'framework.dart'; diff --git a/packages/flutter/lib/src/widgets/transitions.dart b/packages/flutter/lib/src/widgets/transitions.dart index 71e9a985ac..3749e8d987 100644 --- a/packages/flutter/lib/src/widgets/transitions.dart +++ b/packages/flutter/lib/src/widgets/transitions.dart @@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:sky/animation.dart'; +import 'package:flutter/animation.dart'; import 'package:vector_math/vector_math_64.dart'; import 'basic.dart'; import 'framework.dart'; -export 'package:sky/animation.dart' show AnimationDirection; +export 'package:flutter/animation.dart' show AnimationDirection; abstract class TransitionComponent extends StatefulComponent { TransitionComponent({ diff --git a/packages/flutter/pubspec.yaml b/packages/flutter/pubspec.yaml index bcf8676157..b3c9933bae 100644 --- a/packages/flutter/pubspec.yaml +++ b/packages/flutter/pubspec.yaml @@ -1,4 +1,4 @@ -name: sky +name: flutter version: 0.0.55 author: Flutter Authors description: A framework for writing Flutter applications diff --git a/packages/flutter_sprites/lib/skysprites.dart b/packages/flutter_sprites/lib/skysprites.dart index 6669d8071c..62b2669e7a 100644 --- a/packages/flutter_sprites/lib/skysprites.dart +++ b/packages/flutter_sprites/lib/skysprites.dart @@ -13,11 +13,11 @@ import 'dart:ui' as sky; import 'package:box2d/box2d.dart' as box2d; import 'package:mojo/core.dart'; import 'package:sky_services/media/media.mojom.dart'; -import 'package:sky/animation.dart'; -import 'package:sky/painting.dart'; -import 'package:sky/rendering.dart'; -import 'package:sky/services.dart'; -import 'package:sky/widgets.dart'; +import 'package:flutter/animation.dart'; +import 'package:flutter/painting.dart'; +import 'package:flutter/rendering.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter/widgets.dart'; import 'package:vector_math/vector_math_64.dart'; part 'action.dart'; diff --git a/packages/flutter_sprites/pubspec.yaml b/packages/flutter_sprites/pubspec.yaml index b2fbf54410..6ae19a67fb 100644 --- a/packages/flutter_sprites/pubspec.yaml +++ b/packages/flutter_sprites/pubspec.yaml @@ -4,9 +4,9 @@ version: 0.0.1 author: Flutter Authors homepage: http://flutter.io dependencies: - sky: ">=0.0.36 < 0.1.0" + flutter: ">=0.0.36 < 0.1.0" sky_tools: ">=0.0.10 < 0.1.0" box2d: any dependency_overrides: - sky: + flutter: path: ../sky/packages/sky diff --git a/packages/unit/pubspec.yaml b/packages/unit/pubspec.yaml index d91cb48ef2..51606f08b6 100644 --- a/packages/unit/pubspec.yaml +++ b/packages/unit/pubspec.yaml @@ -1,11 +1,11 @@ name: sky_unit_tests dependencies: - sky: any + flutter: any sky_tools: any test: any quiver: any dependency_overrides: material_design_icons: path: ../packages/material_design_icons - sky: + flutter: path: ../packages/sky diff --git a/packages/unit/test/animation/scheduler_test.dart b/packages/unit/test/animation/scheduler_test.dart index 62f9379c3d..89abadbcb0 100644 --- a/packages/unit/test/animation/scheduler_test.dart +++ b/packages/unit/test/animation/scheduler_test.dart @@ -1,4 +1,4 @@ -import 'package:sky/animation.dart'; +import 'package:flutter/animation.dart'; import 'package:test/test.dart'; void main() { diff --git a/packages/unit/test/gestures/arena_test.dart b/packages/unit/test/gestures/arena_test.dart index f9b8c84777..ccc861b50a 100644 --- a/packages/unit/test/gestures/arena_test.dart +++ b/packages/unit/test/gestures/arena_test.dart @@ -1,4 +1,4 @@ -import 'package:sky/gestures.dart'; +import 'package:flutter/gestures.dart'; import 'package:test/test.dart'; typedef void GestureArenaCallback(Object key); diff --git a/packages/unit/test/gestures/long_press_test.dart b/packages/unit/test/gestures/long_press_test.dart index 85995d1c58..8fb8022dcc 100644 --- a/packages/unit/test/gestures/long_press_test.dart +++ b/packages/unit/test/gestures/long_press_test.dart @@ -1,5 +1,5 @@ import 'package:quiver/testing/async.dart'; -import 'package:sky/gestures.dart'; +import 'package:flutter/gestures.dart'; import 'package:test/test.dart'; import '../engine/mock_events.dart'; diff --git a/packages/unit/test/gestures/pointer_router_test.dart b/packages/unit/test/gestures/pointer_router_test.dart index e9a67f3f3c..6c15896856 100644 --- a/packages/unit/test/gestures/pointer_router_test.dart +++ b/packages/unit/test/gestures/pointer_router_test.dart @@ -1,6 +1,6 @@ import 'dart:ui' as sky; -import 'package:sky/gestures.dart'; +import 'package:flutter/gestures.dart'; import 'package:test/test.dart'; import '../engine/mock_events.dart'; diff --git a/packages/unit/test/gestures/scale_test.dart b/packages/unit/test/gestures/scale_test.dart index 6e5d59e94d..be19bada54 100644 --- a/packages/unit/test/gestures/scale_test.dart +++ b/packages/unit/test/gestures/scale_test.dart @@ -1,6 +1,6 @@ import 'dart:ui' as sky; -import 'package:sky/gestures.dart'; +import 'package:flutter/gestures.dart'; import 'package:test/test.dart'; import '../engine/mock_events.dart'; diff --git a/packages/unit/test/gestures/scroll_test.dart b/packages/unit/test/gestures/scroll_test.dart index e0ded8ffce..e29adafc76 100644 --- a/packages/unit/test/gestures/scroll_test.dart +++ b/packages/unit/test/gestures/scroll_test.dart @@ -1,6 +1,6 @@ import 'dart:ui' as sky; -import 'package:sky/gestures.dart'; +import 'package:flutter/gestures.dart'; import 'package:test/test.dart'; import '../engine/mock_events.dart'; diff --git a/packages/unit/test/gestures/show_press_test.dart b/packages/unit/test/gestures/show_press_test.dart index b9e1fb35ee..6a2005d3a8 100644 --- a/packages/unit/test/gestures/show_press_test.dart +++ b/packages/unit/test/gestures/show_press_test.dart @@ -1,5 +1,5 @@ import 'package:quiver/testing/async.dart'; -import 'package:sky/gestures.dart'; +import 'package:flutter/gestures.dart'; import 'package:test/test.dart'; import '../engine/mock_events.dart'; diff --git a/packages/unit/test/gestures/tap_test.dart b/packages/unit/test/gestures/tap_test.dart index 058e18bd1b..c41860ca11 100644 --- a/packages/unit/test/gestures/tap_test.dart +++ b/packages/unit/test/gestures/tap_test.dart @@ -1,4 +1,4 @@ -import 'package:sky/gestures.dart'; +import 'package:flutter/gestures.dart'; import 'package:test/test.dart'; import '../engine/mock_events.dart'; diff --git a/packages/unit/test/painting/edge_dims_test.dart b/packages/unit/test/painting/edge_dims_test.dart index bfcb4583f3..5dbc3b87f2 100644 --- a/packages/unit/test/painting/edge_dims_test.dart +++ b/packages/unit/test/painting/edge_dims_test.dart @@ -1,4 +1,4 @@ -import 'package:sky/painting.dart'; +import 'package:flutter/painting.dart'; import 'package:test/test.dart'; diff --git a/packages/unit/test/rendering/box_test.dart b/packages/unit/test/rendering/box_test.dart index e0df0fd56a..878237fbb1 100644 --- a/packages/unit/test/rendering/box_test.dart +++ b/packages/unit/test/rendering/box_test.dart @@ -1,5 +1,5 @@ -import 'package:sky/material.dart'; -import 'package:sky/rendering.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart'; import 'package:test/test.dart'; import 'rendering_tester.dart'; diff --git a/packages/unit/test/rendering/flex_test.dart b/packages/unit/test/rendering/flex_test.dart index a27ef65b53..4ce08a1233 100644 --- a/packages/unit/test/rendering/flex_test.dart +++ b/packages/unit/test/rendering/flex_test.dart @@ -1,4 +1,4 @@ -import 'package:sky/rendering.dart'; +import 'package:flutter/rendering.dart'; import 'package:test/test.dart'; import 'rendering_tester.dart'; diff --git a/packages/unit/test/rendering/grid_test.dart b/packages/unit/test/rendering/grid_test.dart index 2a517ea0b3..60852a2e8a 100644 --- a/packages/unit/test/rendering/grid_test.dart +++ b/packages/unit/test/rendering/grid_test.dart @@ -1,4 +1,4 @@ -import 'package:sky/rendering.dart'; +import 'package:flutter/rendering.dart'; import 'package:test/test.dart'; import 'rendering_tester.dart'; diff --git a/packages/unit/test/rendering/image_test.dart b/packages/unit/test/rendering/image_test.dart index be0e6f7be9..2ee22468b6 100644 --- a/packages/unit/test/rendering/image_test.dart +++ b/packages/unit/test/rendering/image_test.dart @@ -1,6 +1,6 @@ import 'dart:ui' as sky; -import 'package:sky/rendering.dart'; +import 'package:flutter/rendering.dart'; import 'package:test/test.dart'; import 'rendering_tester.dart'; diff --git a/packages/unit/test/rendering/intrinsic_width_test.dart b/packages/unit/test/rendering/intrinsic_width_test.dart index e7b636f032..de28dbab9a 100644 --- a/packages/unit/test/rendering/intrinsic_width_test.dart +++ b/packages/unit/test/rendering/intrinsic_width_test.dart @@ -1,4 +1,4 @@ -import 'package:sky/rendering.dart'; +import 'package:flutter/rendering.dart'; import 'package:test/test.dart'; import 'rendering_tester.dart'; diff --git a/packages/unit/test/rendering/positioned_box_test.dart b/packages/unit/test/rendering/positioned_box_test.dart index 90e81e50d0..aaa783efc1 100644 --- a/packages/unit/test/rendering/positioned_box_test.dart +++ b/packages/unit/test/rendering/positioned_box_test.dart @@ -1,4 +1,4 @@ -import 'package:sky/rendering.dart'; +import 'package:flutter/rendering.dart'; import 'package:test/test.dart'; import 'rendering_tester.dart'; diff --git a/packages/unit/test/rendering/rendering_tester.dart b/packages/unit/test/rendering/rendering_tester.dart index f4fa015ff6..10e596d555 100644 --- a/packages/unit/test/rendering/rendering_tester.dart +++ b/packages/unit/test/rendering/rendering_tester.dart @@ -1,4 +1,4 @@ -import 'package:sky/rendering.dart'; +import 'package:flutter/rendering.dart'; const Size _kTestViewSize = const Size(800.0, 600.0); diff --git a/packages/unit/test/rendering/size_test.dart b/packages/unit/test/rendering/size_test.dart index 76e84bcda2..8d7672713a 100644 --- a/packages/unit/test/rendering/size_test.dart +++ b/packages/unit/test/rendering/size_test.dart @@ -1,4 +1,4 @@ -import 'package:sky/rendering.dart'; +import 'package:flutter/rendering.dart'; import 'package:test/test.dart'; import 'rendering_tester.dart'; diff --git a/packages/unit/test/rendering/stack_test.dart b/packages/unit/test/rendering/stack_test.dart index 1fbdf481a2..8a2fb726d6 100644 --- a/packages/unit/test/rendering/stack_test.dart +++ b/packages/unit/test/rendering/stack_test.dart @@ -1,4 +1,4 @@ -import 'package:sky/rendering.dart'; +import 'package:flutter/rendering.dart'; import 'package:test/test.dart'; import 'rendering_tester.dart'; diff --git a/packages/unit/test/rendering/viewport_test.dart b/packages/unit/test/rendering/viewport_test.dart index 0596bd655c..dae2c93acd 100644 --- a/packages/unit/test/rendering/viewport_test.dart +++ b/packages/unit/test/rendering/viewport_test.dart @@ -1,4 +1,4 @@ -import 'package:sky/rendering.dart'; +import 'package:flutter/rendering.dart'; import 'package:test/test.dart'; import 'rendering_tester.dart'; diff --git a/packages/unit/test/services/mock_services.dart b/packages/unit/test/services/mock_services.dart index 7ba79e184d..06242c5958 100644 --- a/packages/unit/test/services/mock_services.dart +++ b/packages/unit/test/services/mock_services.dart @@ -1,4 +1,4 @@ -import 'package:sky/src/services/shell.dart' as shell; +import 'package:flutter/src/services/shell.dart' as shell; // Tests can use ServiceMocker to register replacement implementations // of Mojo services. diff --git a/packages/unit/test/widget/align_test.dart b/packages/unit/test/widget/align_test.dart index 40f617b837..48343cba4d 100644 --- a/packages/unit/test/widget/align_test.dart +++ b/packages/unit/test/widget/align_test.dart @@ -1,4 +1,4 @@ -import 'package:sky/widgets.dart'; +import 'package:flutter/widgets.dart'; import 'package:test/test.dart'; import 'widget_tester.dart'; diff --git a/packages/unit/test/widget/animated_container_test.dart b/packages/unit/test/widget/animated_container_test.dart index b98cee45e9..c54beb01ea 100644 --- a/packages/unit/test/widget/animated_container_test.dart +++ b/packages/unit/test/widget/animated_container_test.dart @@ -1,5 +1,5 @@ -import 'package:sky/rendering.dart'; -import 'package:sky/widgets.dart'; +import 'package:flutter/rendering.dart'; +import 'package:flutter/widgets.dart'; import 'package:test/test.dart'; import 'widget_tester.dart'; diff --git a/packages/unit/test/widget/block_test.dart b/packages/unit/test/widget/block_test.dart index 1f3c9eb3ed..141313ea2b 100644 --- a/packages/unit/test/widget/block_test.dart +++ b/packages/unit/test/widget/block_test.dart @@ -1,4 +1,4 @@ -import 'package:sky/widgets.dart'; +import 'package:flutter/widgets.dart'; import 'package:test/test.dart'; import '../engine/mock_events.dart'; diff --git a/packages/unit/test/widget/box_decoration_test.dart b/packages/unit/test/widget/box_decoration_test.dart index 5c16243064..57bdcd460c 100644 --- a/packages/unit/test/widget/box_decoration_test.dart +++ b/packages/unit/test/widget/box_decoration_test.dart @@ -1,5 +1,5 @@ -import 'package:sky/material.dart'; -import 'package:sky/widgets.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; import 'package:test/test.dart'; import 'widget_tester.dart'; diff --git a/packages/unit/test/widget/build_scope_test.dart b/packages/unit/test/widget/build_scope_test.dart index d54c4f534b..477d4612c5 100644 --- a/packages/unit/test/widget/build_scope_test.dart +++ b/packages/unit/test/widget/build_scope_test.dart @@ -1,4 +1,4 @@ -import 'package:sky/widgets.dart'; +import 'package:flutter/widgets.dart'; import 'package:test/test.dart'; import 'widget_tester.dart'; diff --git a/packages/unit/test/widget/center_test.dart b/packages/unit/test/widget/center_test.dart index a8d74b806d..340e08de9f 100644 --- a/packages/unit/test/widget/center_test.dart +++ b/packages/unit/test/widget/center_test.dart @@ -1,4 +1,4 @@ -import 'package:sky/widgets.dart'; +import 'package:flutter/widgets.dart'; import 'package:test/test.dart'; import 'widget_tester.dart'; diff --git a/packages/unit/test/widget/coordinates_test.dart b/packages/unit/test/widget/coordinates_test.dart index 460d2e45a6..e6ee66bb9f 100644 --- a/packages/unit/test/widget/coordinates_test.dart +++ b/packages/unit/test/widget/coordinates_test.dart @@ -1,5 +1,5 @@ -import 'package:sky/rendering.dart'; -import 'package:sky/widgets.dart'; +import 'package:flutter/rendering.dart'; +import 'package:flutter/widgets.dart'; import 'package:test/test.dart'; import 'widget_tester.dart'; diff --git a/packages/unit/test/widget/date_picker_test.dart b/packages/unit/test/widget/date_picker_test.dart index 975cbe3f42..d0c00eee67 100644 --- a/packages/unit/test/widget/date_picker_test.dart +++ b/packages/unit/test/widget/date_picker_test.dart @@ -1,4 +1,4 @@ -import 'package:sky/material.dart'; +import 'package:flutter/material.dart'; import 'package:test/test.dart'; import 'widget_tester.dart'; diff --git a/packages/unit/test/widget/dismissable_test.dart b/packages/unit/test/widget/dismissable_test.dart index bb4086e65f..b9a7b5f3cc 100644 --- a/packages/unit/test/widget/dismissable_test.dart +++ b/packages/unit/test/widget/dismissable_test.dart @@ -1,5 +1,5 @@ -import 'package:sky/rendering.dart'; -import 'package:sky/widgets.dart'; +import 'package:flutter/rendering.dart'; +import 'package:flutter/widgets.dart'; import 'package:test/test.dart'; import '../engine/mock_events.dart'; diff --git a/packages/unit/test/widget/draggable_test.dart b/packages/unit/test/widget/draggable_test.dart index 8e8b224d2a..fc7ad01093 100644 --- a/packages/unit/test/widget/draggable_test.dart +++ b/packages/unit/test/widget/draggable_test.dart @@ -1,4 +1,4 @@ -import 'package:sky/widgets.dart'; +import 'package:flutter/widgets.dart'; import 'package:test/test.dart'; import '../engine/mock_events.dart'; diff --git a/packages/unit/test/widget/drawer_test.dart b/packages/unit/test/widget/drawer_test.dart index 2e976af086..9cbea0686e 100644 --- a/packages/unit/test/widget/drawer_test.dart +++ b/packages/unit/test/widget/drawer_test.dart @@ -1,5 +1,5 @@ -import 'package:sky/material.dart'; -import 'package:sky/widgets.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; import 'package:test/test.dart'; import 'widget_tester.dart'; diff --git a/packages/unit/test/widget/duplicate_key_test.dart b/packages/unit/test/widget/duplicate_key_test.dart index 39ce16ed82..ff9f59d167 100644 --- a/packages/unit/test/widget/duplicate_key_test.dart +++ b/packages/unit/test/widget/duplicate_key_test.dart @@ -1,4 +1,4 @@ -import 'package:sky/widgets.dart'; +import 'package:flutter/widgets.dart'; import 'package:test/test.dart'; import 'widget_tester.dart'; diff --git a/packages/unit/test/widget/flex_test.dart b/packages/unit/test/widget/flex_test.dart index 2b6044ce57..a1e58afcc4 100644 --- a/packages/unit/test/widget/flex_test.dart +++ b/packages/unit/test/widget/flex_test.dart @@ -1,4 +1,4 @@ -import 'package:sky/widgets.dart'; +import 'package:flutter/widgets.dart'; import 'package:test/test.dart'; import 'widget_tester.dart'; diff --git a/packages/unit/test/widget/focus_test.dart b/packages/unit/test/widget/focus_test.dart index 8806e6e30b..b4c0427732 100644 --- a/packages/unit/test/widget/focus_test.dart +++ b/packages/unit/test/widget/focus_test.dart @@ -1,4 +1,4 @@ -import 'package:sky/widgets.dart'; +import 'package:flutter/widgets.dart'; import 'package:test/test.dart'; import 'widget_tester.dart'; diff --git a/packages/unit/test/widget/fractionally_sized_box_test.dart b/packages/unit/test/widget/fractionally_sized_box_test.dart index 6ab3d21d5d..537c7bb704 100644 --- a/packages/unit/test/widget/fractionally_sized_box_test.dart +++ b/packages/unit/test/widget/fractionally_sized_box_test.dart @@ -1,5 +1,5 @@ -import 'package:sky/rendering.dart'; -import 'package:sky/widgets.dart'; +import 'package:flutter/rendering.dart'; +import 'package:flutter/widgets.dart'; import 'package:test/test.dart'; import 'widget_tester.dart'; diff --git a/packages/unit/test/widget/gesture_detector_test.dart b/packages/unit/test/widget/gesture_detector_test.dart index 206b8e866f..56cd9b337e 100644 --- a/packages/unit/test/widget/gesture_detector_test.dart +++ b/packages/unit/test/widget/gesture_detector_test.dart @@ -1,4 +1,4 @@ -import 'package:sky/widgets.dart'; +import 'package:flutter/widgets.dart'; import 'package:test/test.dart'; import '../engine/mock_events.dart'; diff --git a/packages/unit/test/widget/homogeneous_viewport_test.dart b/packages/unit/test/widget/homogeneous_viewport_test.dart index 3b42818216..87131c23ac 100644 --- a/packages/unit/test/widget/homogeneous_viewport_test.dart +++ b/packages/unit/test/widget/homogeneous_viewport_test.dart @@ -1,4 +1,4 @@ -import 'package:sky/widgets.dart'; +import 'package:flutter/widgets.dart'; import 'package:test/test.dart'; import 'widget_tester.dart'; diff --git a/packages/unit/test/widget/input_test.dart b/packages/unit/test/widget/input_test.dart index e2bfbad04f..42a12123eb 100644 --- a/packages/unit/test/widget/input_test.dart +++ b/packages/unit/test/widget/input_test.dart @@ -1,7 +1,7 @@ import 'package:mojo_services/keyboard/keyboard.mojom.dart'; -import 'package:sky/rendering.dart'; -import 'package:sky/services.dart'; -import 'package:sky/material.dart'; +import 'package:flutter/rendering.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter/material.dart'; import 'package:test/test.dart'; import 'widget_tester.dart'; diff --git a/packages/unit/test/widget/listener_test.dart b/packages/unit/test/widget/listener_test.dart index bdd7a8002a..804494b73c 100644 --- a/packages/unit/test/widget/listener_test.dart +++ b/packages/unit/test/widget/listener_test.dart @@ -1,4 +1,4 @@ -import 'package:sky/widgets.dart'; +import 'package:flutter/widgets.dart'; import 'package:test/test.dart'; import 'widget_tester.dart'; diff --git a/packages/unit/test/widget/mixed_viewport_test.dart b/packages/unit/test/widget/mixed_viewport_test.dart index b72562e830..59037ef753 100644 --- a/packages/unit/test/widget/mixed_viewport_test.dart +++ b/packages/unit/test/widget/mixed_viewport_test.dart @@ -1,4 +1,4 @@ -import 'package:sky/widgets.dart'; +import 'package:flutter/widgets.dart'; import 'package:test/test.dart'; import 'widget_tester.dart'; diff --git a/packages/unit/test/widget/multichild_test.dart b/packages/unit/test/widget/multichild_test.dart index 0a87970e1b..6db41dc6b3 100644 --- a/packages/unit/test/widget/multichild_test.dart +++ b/packages/unit/test/widget/multichild_test.dart @@ -1,5 +1,5 @@ -import 'package:sky/rendering.dart'; -import 'package:sky/widgets.dart'; +import 'package:flutter/rendering.dart'; +import 'package:flutter/widgets.dart'; import 'package:test/test.dart'; import 'test_widgets.dart'; diff --git a/packages/unit/test/widget/navigator_test.dart b/packages/unit/test/widget/navigator_test.dart index a9bfcd5e63..5dfb8f0e68 100644 --- a/packages/unit/test/widget/navigator_test.dart +++ b/packages/unit/test/widget/navigator_test.dart @@ -1,4 +1,4 @@ -import 'package:sky/widgets.dart'; +import 'package:flutter/widgets.dart'; import 'package:test/test.dart'; import 'widget_tester.dart'; diff --git a/packages/unit/test/widget/pageable_list_test.dart b/packages/unit/test/widget/pageable_list_test.dart index e282e69ef6..fe406532b1 100644 --- a/packages/unit/test/widget/pageable_list_test.dart +++ b/packages/unit/test/widget/pageable_list_test.dart @@ -1,4 +1,4 @@ -import 'package:sky/widgets.dart'; +import 'package:flutter/widgets.dart'; import 'package:test/test.dart'; import 'widget_tester.dart'; diff --git a/packages/unit/test/widget/parent_data_test.dart b/packages/unit/test/widget/parent_data_test.dart index f489218596..2d692d0956 100644 --- a/packages/unit/test/widget/parent_data_test.dart +++ b/packages/unit/test/widget/parent_data_test.dart @@ -1,5 +1,5 @@ -import 'package:sky/rendering.dart'; -import 'package:sky/widgets.dart'; +import 'package:flutter/rendering.dart'; +import 'package:flutter/widgets.dart'; import 'package:test/test.dart'; import 'test_widgets.dart'; diff --git a/packages/unit/test/widget/progress_indicator_test.dart b/packages/unit/test/widget/progress_indicator_test.dart index 849818b3de..de3541b24d 100644 --- a/packages/unit/test/widget/progress_indicator_test.dart +++ b/packages/unit/test/widget/progress_indicator_test.dart @@ -1,6 +1,6 @@ -import 'package:sky/rendering.dart'; -import 'package:sky/material.dart'; +import 'package:flutter/rendering.dart'; +import 'package:flutter/material.dart'; import 'package:test/test.dart'; import 'widget_tester.dart'; diff --git a/packages/unit/test/widget/render_object_widget_test.dart b/packages/unit/test/widget/render_object_widget_test.dart index 57335b57d8..76088a6998 100644 --- a/packages/unit/test/widget/render_object_widget_test.dart +++ b/packages/unit/test/widget/render_object_widget_test.dart @@ -1,5 +1,5 @@ -import 'package:sky/rendering.dart'; -import 'package:sky/widgets.dart'; +import 'package:flutter/rendering.dart'; +import 'package:flutter/widgets.dart'; import 'package:test/test.dart'; import 'widget_tester.dart'; diff --git a/packages/unit/test/widget/reparent_state_test.dart b/packages/unit/test/widget/reparent_state_test.dart index ec771415e7..804837f8f8 100644 --- a/packages/unit/test/widget/reparent_state_test.dart +++ b/packages/unit/test/widget/reparent_state_test.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:sky/widgets.dart'; +import 'package:flutter/widgets.dart'; import 'package:test/test.dart'; import 'widget_tester.dart'; diff --git a/packages/unit/test/widget/scrollable_list_hit_testing_test.dart b/packages/unit/test/widget/scrollable_list_hit_testing_test.dart index 32073bea3b..2a392d584f 100644 --- a/packages/unit/test/widget/scrollable_list_hit_testing_test.dart +++ b/packages/unit/test/widget/scrollable_list_hit_testing_test.dart @@ -1,5 +1,5 @@ -import 'package:sky/rendering.dart'; -import 'package:sky/widgets.dart'; +import 'package:flutter/rendering.dart'; +import 'package:flutter/widgets.dart'; import 'package:test/test.dart'; import 'widget_tester.dart'; diff --git a/packages/unit/test/widget/scrollable_list_horizontal_test.dart b/packages/unit/test/widget/scrollable_list_horizontal_test.dart index 506bf58bb2..94cdd51986 100644 --- a/packages/unit/test/widget/scrollable_list_horizontal_test.dart +++ b/packages/unit/test/widget/scrollable_list_horizontal_test.dart @@ -1,5 +1,5 @@ -import 'package:sky/rendering.dart'; -import 'package:sky/widgets.dart'; +import 'package:flutter/rendering.dart'; +import 'package:flutter/widgets.dart'; import 'package:test/test.dart'; import 'widget_tester.dart'; diff --git a/packages/unit/test/widget/scrollable_list_vertical_test.dart b/packages/unit/test/widget/scrollable_list_vertical_test.dart index 8effa15684..3998cef58a 100644 --- a/packages/unit/test/widget/scrollable_list_vertical_test.dart +++ b/packages/unit/test/widget/scrollable_list_vertical_test.dart @@ -1,4 +1,4 @@ -import 'package:sky/widgets.dart'; +import 'package:flutter/widgets.dart'; import 'package:test/test.dart'; import 'widget_tester.dart'; diff --git a/packages/unit/test/widget/set_state_3_test.dart b/packages/unit/test/widget/set_state_3_test.dart index b78ab070eb..cfc2e3fc93 100644 --- a/packages/unit/test/widget/set_state_3_test.dart +++ b/packages/unit/test/widget/set_state_3_test.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:sky/widgets.dart'; +import 'package:flutter/widgets.dart'; import 'package:test/test.dart'; import 'widget_tester.dart'; diff --git a/packages/unit/test/widget/set_state_test.dart b/packages/unit/test/widget/set_state_test.dart index adb9239b0e..f396a0778c 100644 --- a/packages/unit/test/widget/set_state_test.dart +++ b/packages/unit/test/widget/set_state_test.dart @@ -1,4 +1,4 @@ -import 'package:sky/widgets.dart'; +import 'package:flutter/widgets.dart'; import 'package:test/test.dart'; import '../engine/mock_events.dart'; diff --git a/packages/unit/test/widget/shader_mask_test.dart b/packages/unit/test/widget/shader_mask_test.dart index 9fc0bae9e2..379ff9b572 100644 --- a/packages/unit/test/widget/shader_mask_test.dart +++ b/packages/unit/test/widget/shader_mask_test.dart @@ -1,7 +1,7 @@ import 'dart:ui' as sky; -import 'package:sky/painting.dart'; -import 'package:sky/widgets.dart'; +import 'package:flutter/painting.dart'; +import 'package:flutter/widgets.dart'; import 'package:test/test.dart'; import 'widget_tester.dart'; diff --git a/packages/unit/test/widget/size_observer_test.dart b/packages/unit/test/widget/size_observer_test.dart index 6b9b1cadbc..95f9e44eeb 100644 --- a/packages/unit/test/widget/size_observer_test.dart +++ b/packages/unit/test/widget/size_observer_test.dart @@ -1,6 +1,6 @@ -import 'package:sky/rendering.dart'; -import 'package:sky/widgets.dart'; +import 'package:flutter/rendering.dart'; +import 'package:flutter/widgets.dart'; import 'package:test/test.dart'; import 'widget_tester.dart'; diff --git a/packages/unit/test/widget/snack_bar_test.dart b/packages/unit/test/widget/snack_bar_test.dart index 4ddfd84382..1c3fb697fe 100644 --- a/packages/unit/test/widget/snack_bar_test.dart +++ b/packages/unit/test/widget/snack_bar_test.dart @@ -1,4 +1,4 @@ -import 'package:sky/material.dart'; +import 'package:flutter/material.dart'; import 'package:test/test.dart'; import 'widget_tester.dart'; diff --git a/packages/unit/test/widget/snap_scrolling_test.dart b/packages/unit/test/widget/snap_scrolling_test.dart index c5c0bb6607..9a193b4259 100644 --- a/packages/unit/test/widget/snap_scrolling_test.dart +++ b/packages/unit/test/widget/snap_scrolling_test.dart @@ -4,7 +4,7 @@ import 'dart:async'; -import 'package:sky/widgets.dart'; +import 'package:flutter/widgets.dart'; import 'package:test/test.dart'; import 'widget_tester.dart'; diff --git a/packages/unit/test/widget/stack_test.dart b/packages/unit/test/widget/stack_test.dart index b075aaca93..6bf00668b1 100644 --- a/packages/unit/test/widget/stack_test.dart +++ b/packages/unit/test/widget/stack_test.dart @@ -1,4 +1,4 @@ -import 'package:sky/widgets.dart'; +import 'package:flutter/widgets.dart'; import 'package:test/test.dart'; import 'widget_tester.dart'; diff --git a/packages/unit/test/widget/stateful_component_test.dart b/packages/unit/test/widget/stateful_component_test.dart index 694e6613eb..7e7f620a90 100644 --- a/packages/unit/test/widget/stateful_component_test.dart +++ b/packages/unit/test/widget/stateful_component_test.dart @@ -1,5 +1,5 @@ -import 'package:sky/rendering.dart'; -import 'package:sky/widgets.dart'; +import 'package:flutter/rendering.dart'; +import 'package:flutter/widgets.dart'; import 'package:test/test.dart'; import 'widget_tester.dart'; diff --git a/packages/unit/test/widget/stateful_components_test.dart b/packages/unit/test/widget/stateful_components_test.dart index e52e4fd6ad..828611e4c1 100644 --- a/packages/unit/test/widget/stateful_components_test.dart +++ b/packages/unit/test/widget/stateful_components_test.dart @@ -1,4 +1,4 @@ -import 'package:sky/widgets.dart'; +import 'package:flutter/widgets.dart'; import 'package:test/test.dart'; import 'widget_tester.dart'; diff --git a/packages/unit/test/widget/syncing_test.dart b/packages/unit/test/widget/syncing_test.dart index c8849b6cf8..bf6bf8ecb9 100644 --- a/packages/unit/test/widget/syncing_test.dart +++ b/packages/unit/test/widget/syncing_test.dart @@ -1,4 +1,4 @@ -import 'package:sky/widgets.dart'; +import 'package:flutter/widgets.dart'; import 'package:test/test.dart'; import 'widget_tester.dart'; diff --git a/packages/unit/test/widget/test_widgets.dart b/packages/unit/test/widget/test_widgets.dart index 62c2dd0135..f132925cac 100644 --- a/packages/unit/test/widget/test_widgets.dart +++ b/packages/unit/test/widget/test_widgets.dart @@ -1,4 +1,4 @@ -import 'package:sky/widgets.dart'; +import 'package:flutter/widgets.dart'; import 'package:test/test.dart'; import 'widget_tester.dart'; diff --git a/packages/unit/test/widget/transform_test.dart b/packages/unit/test/widget/transform_test.dart index 1fff18fe1c..d9c2a47bb5 100644 --- a/packages/unit/test/widget/transform_test.dart +++ b/packages/unit/test/widget/transform_test.dart @@ -1,4 +1,4 @@ -import 'package:sky/widgets.dart'; +import 'package:flutter/widgets.dart'; import 'package:test/test.dart'; import 'widget_tester.dart'; diff --git a/packages/unit/test/widget/widget_tester.dart b/packages/unit/test/widget/widget_tester.dart index 95964f3e98..284afb000b 100644 --- a/packages/unit/test/widget/widget_tester.dart +++ b/packages/unit/test/widget/widget_tester.dart @@ -1,8 +1,8 @@ import 'dart:ui' as sky; -import 'package:sky/animation.dart'; -import 'package:sky/rendering.dart'; -import 'package:sky/widgets.dart'; +import 'package:flutter/animation.dart'; +import 'package:flutter/rendering.dart'; +import 'package:flutter/widgets.dart'; import 'package:quiver/testing/async.dart'; import 'package:quiver/time.dart'; diff --git a/packages/updater/lib/main.dart b/packages/updater/lib/main.dart index ea168da299..5d0b0a6fcd 100644 --- a/packages/updater/lib/main.dart +++ b/packages/updater/lib/main.dart @@ -6,7 +6,7 @@ import 'dart:async'; import 'dart:io'; import 'package:mojo/core.dart'; -import 'package:sky/services.dart'; +import 'package:flutter/services.dart'; import 'package:sky_services/updater/update_service.mojom.dart'; import 'package:path/path.dart' as path; import 'package:yaml/yaml.dart' as yaml; diff --git a/packages/updater/pubspec.yaml b/packages/updater/pubspec.yaml index ffff047257..df78548785 100644 --- a/packages/updater/pubspec.yaml +++ b/packages/updater/pubspec.yaml @@ -5,12 +5,12 @@ description: The autoupdater for flutter homepage: http://flutter.io dependencies: mojo: '>=0.2.0 <0.3.0' - sky: any + flutter: any sky_services: any path: any yaml: any dependency_overrides: - sky: + flutter: path: ../sky environment: sdk: '>=1.12.0 <2.0.0' From ecce1eb389453491c073b8575ef4e0c43ad5652a Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Fri, 9 Oct 2015 20:55:54 -0700 Subject: [PATCH 39/84] Import dart:ui as ui (instead of as sky) --- examples/game/lib/explosions.dart | 6 +- examples/game/lib/game_demo.dart | 2 +- examples/game/lib/game_demo_node.dart | 2 +- examples/game/lib/game_objects.dart | 6 +- examples/game/lib/power_bar.dart | 2 +- examples/game/lib/repeated_image.dart | 2 +- examples/game/lib/star_field.dart | 12 +- examples/game/test_performance.dart | 18 +-- examples/mine_digger/lib/main.dart | 6 +- examples/raw/baseline.dart | 60 +++++----- examples/raw/hello_world.dart | 52 ++++----- examples/raw/mutating-dom.dart | 66 +++++------ examples/raw/painting.dart | 110 +++++++++--------- examples/raw/shadow.dart | 56 ++++----- examples/raw/spinning_arabic.dart | 42 +++---- examples/raw/spinning_image.dart | 46 ++++---- examples/raw/spinning_square.dart | 34 +++--- examples/rendering/baseline.dart | 4 +- examples/rendering/borders.dart | 20 ++-- examples/rendering/flex.dart | 18 +-- examples/rendering/interactive_flex.dart | 10 +- examples/rendering/sector_layout.dart | 4 +- examples/rendering/solid_color_box.dart | 4 +- examples/rendering/spinning_flex.dart | 10 +- examples/rendering/touch_demo.dart | 8 +- examples/rendering/transform.dart | 6 +- examples/stocks/lib/main.dart | 2 +- examples/stocks/lib/stock_arrow.dart | 6 +- examples/stocks/lib/stock_menu.dart | 4 +- examples/widgets/card_collection.dart | 4 +- examples/widgets/overlay_geometry.dart | 10 +- examples/widgets/spinning_mixed.dart | 8 +- .../flutter/lib/src/animation/scheduler.dart | 6 +- .../lib/src/animation/scroll_behavior.dart | 8 +- packages/flutter/lib/src/gestures/drag.dart | 36 +++--- .../flutter/lib/src/gestures/long_press.dart | 4 +- .../lib/src/gestures/pointer_router.dart | 14 +-- .../flutter/lib/src/gestures/recognizer.dart | 24 ++-- packages/flutter/lib/src/gestures/scale.dart | 22 ++-- .../flutter/lib/src/gestures/show_press.dart | 4 +- packages/flutter/lib/src/gestures/tap.dart | 4 +- .../flutter/lib/src/material/checkbox.dart | 44 +++---- .../flutter/lib/src/material/drawer_item.dart | 8 +- packages/flutter/lib/src/material/icon.dart | 4 +- .../flutter/lib/src/material/icon_button.dart | 4 +- .../flutter/lib/src/material/ink_well.dart | 6 +- .../lib/src/material/material_app.dart | 4 +- .../flutter/lib/src/material/popup_menu.dart | 4 +- .../lib/src/material/progress_indicator.dart | 18 +-- .../lib/src/material/radial_reaction.dart | 4 +- packages/flutter/lib/src/material/radio.dart | 12 +- .../flutter/lib/src/material/scaffold.dart | 4 +- packages/flutter/lib/src/material/switch.dart | 24 ++-- packages/flutter/lib/src/material/tabs.dart | 4 +- .../flutter/lib/src/painting/box_painter.dart | 72 ++++++------ .../flutter/lib/src/painting/shadows.dart | 22 ++-- .../lib/src/painting/text_painter.dart | 40 +++---- .../flutter/lib/src/painting/text_style.dart | 10 +- .../flutter/lib/src/rendering/binding.dart | 24 ++-- packages/flutter/lib/src/rendering/box.dart | 14 +-- packages/flutter/lib/src/rendering/debug.dart | 12 +- .../flutter/lib/src/rendering/hit_test.dart | 4 +- packages/flutter/lib/src/rendering/image.dart | 18 +-- packages/flutter/lib/src/rendering/layer.dart | 30 ++--- .../flutter/lib/src/rendering/object.dart | 38 +++--- .../flutter/lib/src/rendering/proxy_box.dart | 24 ++-- .../flutter/lib/src/rendering/toggleable.dart | 4 +- packages/flutter/lib/src/rendering/view.dart | 14 +-- .../flutter/lib/src/rendering/viewport.dart | 4 +- .../lib/src/services/asset_bundle.dart | 4 +- .../flutter/lib/src/services/image_cache.dart | 4 +- .../lib/src/services/image_resource.dart | 20 ++-- packages/flutter/lib/src/widgets/basic.dart | 22 ++-- .../flutter/lib/src/widgets/dismissable.dart | 6 +- .../flutter/lib/src/widgets/drag_target.dart | 10 +- .../lib/src/widgets/gesture_detector.dart | 4 +- .../flutter/lib/src/widgets/scrollable.dart | 6 +- packages/flutter_sprites/lib/effect_line.dart | 4 +- packages/flutter_sprites/lib/image_map.dart | 12 +- packages/flutter_sprites/lib/layer.dart | 2 +- .../flutter_sprites/lib/particle_system.dart | 12 +- .../flutter_sprites/lib/physics_node.dart | 2 +- packages/flutter_sprites/lib/skysprites.dart | 2 +- packages/flutter_sprites/lib/sprite.dart | 8 +- packages/flutter_sprites/lib/sprite_box.dart | 4 +- packages/flutter_sprites/lib/spritesheet.dart | 4 +- packages/flutter_sprites/lib/texture.dart | 4 +- .../flutter_sprites/lib/textured_line.dart | 8 +- .../flutter_sprites/lib/virtual_joystick.dart | 2 +- packages/unit/test/engine/canvas_test.dart | 6 +- .../unit/test/engine/inline_style_test.dart | 10 +- packages/unit/test/engine/mock_events.dart | 16 +-- packages/unit/test/engine/text_test.dart | 4 +- .../test/gestures/pointer_router_test.dart | 4 +- packages/unit/test/gestures/scale_test.dart | 28 ++--- packages/unit/test/gestures/scroll_test.dart | 14 +-- packages/unit/test/rendering/image_test.dart | 8 +- .../unit/test/widget/shader_mask_test.dart | 4 +- packages/unit/test/widget/widget_tester.dart | 6 +- packages/updater/lib/main.dart | 2 +- 100 files changed, 737 insertions(+), 737 deletions(-) diff --git a/examples/game/lib/explosions.dart b/examples/game/lib/explosions.dart index 73c5bec878..3abdcf5336 100644 --- a/examples/game/lib/explosions.dart +++ b/examples/game/lib/explosions.dart @@ -49,7 +49,7 @@ class ExplosionBig extends Explosion { // Add ring Sprite sprtRing = new Sprite(sheet["explosion_ring.png"]); - sprtRing.transferMode = sky.TransferMode.plus; + sprtRing.transferMode = ui.TransferMode.plus; addChild(sprtRing); Action scale = new ActionTween( (a) => sprtRing.scale = a, 0.2, 1.0, 0.75); @@ -63,7 +63,7 @@ class ExplosionBig extends Explosion { Sprite sprtFlare = new Sprite(sheet["explosion_flare.png"]); sprtFlare.pivot = new Point(0.3, 1.0); sprtFlare.scaleX = 0.3; - sprtFlare.transferMode = sky.TransferMode.plus; + sprtFlare.transferMode = ui.TransferMode.plus; sprtFlare.rotation = randomDouble() * 360.0; addChild(sprtFlare); @@ -86,7 +86,7 @@ class ExplosionMini extends Explosion { Sprite star = new Sprite(sheet["star_0.png"]); star.scale = 0.5; star.colorOverlay = new Color(0xff95f4fb); - star.transferMode = sky.TransferMode.plus; + star.transferMode = ui.TransferMode.plus; addChild(star); double rotationStart = randomDouble() * 90.0; diff --git a/examples/game/lib/game_demo.dart b/examples/game/lib/game_demo.dart index 95862c7941..ceb7b22c2a 100644 --- a/examples/game/lib/game_demo.dart +++ b/examples/game/lib/game_demo.dart @@ -2,7 +2,7 @@ library game; import 'dart:async'; import 'dart:math' as math; -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'package:flutter/rendering.dart'; import 'package:skysprites/skysprites.dart'; diff --git a/examples/game/lib/game_demo_node.dart b/examples/game/lib/game_demo_node.dart index 8ad670c152..c597e9a9ac 100644 --- a/examples/game/lib/game_demo_node.dart +++ b/examples/game/lib/game_demo_node.dart @@ -26,7 +26,7 @@ class GameDemoNode extends NodeWithSize { addChild(_starField); // Add nebula - _nebula = new RepeatedImage(_images["assets/nebula.png"], sky.TransferMode.plus); + _nebula = new RepeatedImage(_images["assets/nebula.png"], ui.TransferMode.plus); addChild(_nebula); // Setup game screen, it will always be anchored to the bottom of the screen diff --git a/examples/game/lib/game_objects.dart b/examples/game/lib/game_objects.dart index 356eb5a170..e10510c2da 100644 --- a/examples/game/lib/game_objects.dart +++ b/examples/game/lib/game_objects.dart @@ -16,7 +16,7 @@ abstract class GameObject extends Node { Paint _paintDebug = new Paint() ..color=new Color(0xffff0000) ..strokeWidth = 1.0 - ..setStyle(sky.PaintingStyle.stroke); + ..setStyle(ui.PaintingStyle.stroke); bool collidingWith(GameObject obj) { return (GameMath.distanceBetweenPoints(position, obj.position) @@ -111,7 +111,7 @@ class Ship extends GameObject { _sprtShield = new Sprite(f.sheet["shield.png"]); _sprtShield.scale = 0.35; - _sprtShield.transferMode = sky.TransferMode.plus; + _sprtShield.transferMode = ui.TransferMode.plus; addChild(_sprtShield); radius = 20.0; @@ -188,7 +188,7 @@ class Laser extends GameObject { Sprite sprt = new Sprite(f.sheet["explosion_particle.png"]); sprt.scale = 0.5; sprt.colorOverlay = laserColor; - sprt.transferMode = sky.TransferMode.plus; + sprt.transferMode = ui.TransferMode.plus; addChild(sprt); sprites.add(sprt); } diff --git a/examples/game/lib/power_bar.dart b/examples/game/lib/power_bar.dart index 53a4106261..dc435d6d2b 100644 --- a/examples/game/lib/power_bar.dart +++ b/examples/game/lib/power_bar.dart @@ -10,7 +10,7 @@ class PowerBar extends NodeWithSize { Paint _paintOutline = new Paint() ..color = new Color(0xffffffff) ..strokeWidth = 1.0 - ..setStyle(sky.PaintingStyle.stroke); + ..setStyle(ui.PaintingStyle.stroke); void paint(PaintingCanvas canvas) { applyTransformForPivot(canvas); diff --git a/examples/game/lib/repeated_image.dart b/examples/game/lib/repeated_image.dart index 23010129f7..5602b0dc02 100644 --- a/examples/game/lib/repeated_image.dart +++ b/examples/game/lib/repeated_image.dart @@ -4,7 +4,7 @@ class RepeatedImage extends Node { Sprite _sprt0; Sprite _sprt1; - RepeatedImage(sky.Image image, [sky.TransferMode mode = null]) { + RepeatedImage(ui.Image image, [ui.TransferMode mode = null]) { _sprt0 = new Sprite.fromImage(image); _sprt0.size = new Size(1024.0, 1024.0); _sprt0.pivot = Point.origin; diff --git a/examples/game/lib/star_field.dart b/examples/game/lib/star_field.dart index 25a138f615..8d8f886a30 100644 --- a/examples/game/lib/star_field.dart +++ b/examples/game/lib/star_field.dart @@ -1,7 +1,7 @@ part of game; class StarField extends NodeWithSize { - sky.Image _image; + ui.Image _image; SpriteSheet _spriteSheet; int _numStars; bool _autoScroll; @@ -15,9 +15,9 @@ class StarField extends NodeWithSize { Size _paddedSize = Size.zero; Paint _paint = new Paint() - ..filterQuality = sky.FilterQuality.low + ..filterQuality = ui.FilterQuality.low ..isAntiAlias = false - ..transferMode = sky.TransferMode.plus; + ..transferMode = ui.TransferMode.plus; StarField(this._spriteSheet, this._numStars, [this._autoScroll = false]) : super(Size.zero) { _image = _spriteSheet.image; @@ -48,9 +48,9 @@ class StarField extends NodeWithSize { void paint(PaintingCanvas canvas) { // Create a transform for each star - List transforms = []; + List transforms = []; for (int i = 0; i < _numStars; i++) { - sky.RSTransform transform = new sky.RSTransform( + ui.RSTransform transform = new ui.RSTransform( _starScales[i], 0.0, _starPositions[i].x - _padding, @@ -60,7 +60,7 @@ class StarField extends NodeWithSize { } // Draw the stars - canvas.drawAtlas(_image, transforms, _rects, _colors, sky.TransferMode.modulate, null, _paint); + canvas.drawAtlas(_image, transforms, _rects, _colors, ui.TransferMode.modulate, null, _paint); } void move(double dx, double dy) { diff --git a/examples/game/test_performance.dart b/examples/game/test_performance.dart index 2d57022976..3e90fee3d0 100644 --- a/examples/game/test_performance.dart +++ b/examples/game/test_performance.dart @@ -1,4 +1,4 @@ -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'dart:math' as math; import 'package:flutter/material.dart'; @@ -202,7 +202,7 @@ class TestPerformanceAtlas extends PerformanceTest { double rotation = 0.0; List rects = []; Paint cachedPaint = new Paint() - ..filterQuality = sky.FilterQuality.low + ..filterQuality = ui.FilterQuality.low ..isAntiAlias = false; TestPerformanceAtlas() { @@ -216,7 +216,7 @@ class TestPerformanceAtlas extends PerformanceTest { void paint(PaintingCanvas canvas) { // Setup transforms - List transforms = []; + List transforms = []; for (int x = 0; x < grid; x++) { for (int y = 0; y < grid; y++) { @@ -238,12 +238,12 @@ class TestPerformanceAtlas extends PerformanceTest { rotation += 1.0; } - sky.RSTransform createTransform(double x, double y, double ax, double ay, double rot, double scale) { + ui.RSTransform createTransform(double x, double y, double ax, double ay, double rot, double scale) { double scos = math.cos(convertDegrees2Radians(rot)) * scale; double ssin = math.sin(convertDegrees2Radians(rot)) * scale; double tx = x + -scos * ax + ssin * ay; double ty = y + -ssin * ax - scos * ay; - return new sky.RSTransform(scos, ssin, tx, ty); + return new ui.RSTransform(scos, ssin, tx, ty); } } @@ -255,7 +255,7 @@ class TestPerformanceAtlas2 extends PerformanceTest { double rotation = 0.0; List rects = []; Paint cachedPaint = new Paint() - ..filterQuality = sky.FilterQuality.low + ..filterQuality = ui.FilterQuality.low ..isAntiAlias = false; TestPerformanceAtlas2() { @@ -269,7 +269,7 @@ class TestPerformanceAtlas2 extends PerformanceTest { void paint(PaintingCanvas canvas) { // Setup transforms - List transforms = []; + List transforms = []; for (int x = 12; x < grid - 12; x++) { for (int y = 0; y < grid; y++) { @@ -291,11 +291,11 @@ class TestPerformanceAtlas2 extends PerformanceTest { rotation += 1.0; } - sky.RSTransform createTransform(double x, double y, double ax, double ay, double rot, double scale) { + ui.RSTransform createTransform(double x, double y, double ax, double ay, double rot, double scale) { double scos = math.cos(convertDegrees2Radians(rot)) * scale; double ssin = math.sin(convertDegrees2Radians(rot)) * scale; double tx = x + -scos * ax + ssin * ay; double ty = y + -ssin * ax - scos * ay; - return new sky.RSTransform(scos, ssin, tx, ty); + return new ui.RSTransform(scos, ssin, tx, ty); } } diff --git a/examples/mine_digger/lib/main.dart b/examples/mine_digger/lib/main.dart index b17c6a9340..1fe6f7e0cc 100644 --- a/examples/mine_digger/lib/main.dart +++ b/examples/mine_digger/lib/main.dart @@ -1,7 +1,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'dart:math'; import 'package:flutter/material.dart'; @@ -85,7 +85,7 @@ class MineDiggerState extends State { } PointerEventListener _pointerDownHandlerFor(int posX, int posY) { - return (sky.PointerEvent event) { + return (ui.PointerEvent event) { if (event.buttons == 1) { probe(posX, posY); } else if (event.buttons == 2) { @@ -190,7 +190,7 @@ class MineDiggerState extends State { ); } - void handleToolbarPointerDown(sky.PointerEvent event) { + void handleToolbarPointerDown(ui.PointerEvent event) { setState(() { resetGame(); }); diff --git a/examples/raw/baseline.dart b/examples/raw/baseline.dart index ef6d84c2a2..234803ab70 100644 --- a/examples/raw/baseline.dart +++ b/examples/raw/baseline.dart @@ -2,20 +2,20 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'dart:typed_data'; -void drawText(sky.Canvas canvas, String lh) { - sky.Paint paint = new sky.Paint(); +void drawText(ui.Canvas canvas, String lh) { + ui.Paint paint = new ui.Paint(); // offset down canvas.translate(0.0, 100.0); // set up the text - sky.Document document = new sky.Document(); - sky.Text arabic = document.createText("مرحبا"); - sky.Text english = document.createText(" Hello"); - sky.Element block = document.createElement('div'); + ui.Document document = new ui.Document(); + ui.Text arabic = document.createText("مرحبا"); + ui.Text english = document.createText(" Hello"); + ui.Element block = document.createElement('div'); block.style['display'] = 'paragraph'; block.style['font-family'] = 'monospace'; block.style['font-size'] = '50px'; @@ -23,21 +23,21 @@ void drawText(sky.Canvas canvas, String lh) { block.style['color'] = '#0000A0'; block.appendChild(arabic); block.appendChild(english); - sky.LayoutRoot layoutRoot = new sky.LayoutRoot(); + ui.LayoutRoot layoutRoot = new ui.LayoutRoot(); layoutRoot.rootElement = block; - layoutRoot.maxWidth = sky.view.width - 20.0; // you need to set a width for this to paint + layoutRoot.maxWidth = ui.view.width - 20.0; // you need to set a width for this to paint layoutRoot.layout(); // draw a line at the text's baseline - sky.Path path = new sky.Path(); + ui.Path path = new ui.Path(); path.moveTo(0.0, 0.0); path.lineTo(block.maxContentWidth, 0.0); path.moveTo(0.0, block.alphabeticBaseline); path.lineTo(block.maxContentWidth, block.alphabeticBaseline); path.moveTo(0.0, block.height); path.lineTo(block.maxContentWidth, block.height); - paint.color = const sky.Color(0xFFFF9000); - paint.setStyle(sky.PaintingStyle.stroke); + paint.color = const ui.Color(0xFFFF9000); + paint.setStyle(ui.PaintingStyle.stroke); paint.strokeWidth = 3.0; canvas.drawPath(path, paint); @@ -45,14 +45,14 @@ void drawText(sky.Canvas canvas, String lh) { layoutRoot.paint(canvas); } -sky.Picture paint(sky.Rect paintBounds) { - sky.PictureRecorder recorder = new sky.PictureRecorder(); - sky.Canvas canvas = new sky.Canvas(recorder, paintBounds); +ui.Picture paint(ui.Rect paintBounds) { + ui.PictureRecorder recorder = new ui.PictureRecorder(); + ui.Canvas canvas = new ui.Canvas(recorder, paintBounds); - sky.Paint paint = new sky.Paint(); - paint.color = const sky.Color(0xFFFFFFFF); - paint.setStyle(sky.PaintingStyle.fill); - canvas.drawRect(new sky.Rect.fromLTRB(0.0, 0.0, sky.view.width, sky.view.height), paint); + ui.Paint paint = new ui.Paint(); + paint.color = const ui.Color(0xFFFFFFFF); + paint.setStyle(ui.PaintingStyle.fill); + canvas.drawRect(new ui.Rect.fromLTRB(0.0, 0.0, ui.view.width, ui.view.height), paint); canvas.translate(10.0, 0.0); drawText(canvas, '1.0'); @@ -61,29 +61,29 @@ sky.Picture paint(sky.Rect paintBounds) { return recorder.endRecording(); } -sky.Scene composite(sky.Picture picture, sky.Rect paintBounds) { - final double devicePixelRatio = sky.view.devicePixelRatio; - sky.Rect sceneBounds = new sky.Rect.fromLTWH(0.0, 0.0, sky.view.width * devicePixelRatio, sky.view.height * devicePixelRatio); +ui.Scene composite(ui.Picture picture, ui.Rect paintBounds) { + final double devicePixelRatio = ui.view.devicePixelRatio; + ui.Rect sceneBounds = new ui.Rect.fromLTWH(0.0, 0.0, ui.view.width * devicePixelRatio, ui.view.height * devicePixelRatio); Float64List deviceTransform = new Float64List(16) ..[0] = devicePixelRatio ..[5] = devicePixelRatio ..[10] = 1.0 ..[15] = 1.0; - sky.SceneBuilder sceneBuilder = new sky.SceneBuilder(sceneBounds) + ui.SceneBuilder sceneBuilder = new ui.SceneBuilder(sceneBounds) ..pushTransform(deviceTransform) - ..addPicture(sky.Offset.zero, picture, paintBounds) + ..addPicture(ui.Offset.zero, picture, paintBounds) ..pop(); return sceneBuilder.build(); } void beginFrame(double timeStamp) { - sky.Rect paintBounds = new sky.Rect.fromLTWH(0.0, 0.0, sky.view.width, sky.view.height); - sky.Picture picture = paint(paintBounds); - sky.Scene scene = composite(picture, paintBounds); - sky.view.scene = scene; + ui.Rect paintBounds = new ui.Rect.fromLTWH(0.0, 0.0, ui.view.width, ui.view.height); + ui.Picture picture = paint(paintBounds); + ui.Scene scene = composite(picture, paintBounds); + ui.view.scene = scene; } void main() { - sky.view.setFrameCallback(beginFrame); - sky.view.scheduleFrame(); + ui.view.setFrameCallback(beginFrame); + ui.view.scheduleFrame(); } diff --git a/examples/raw/hello_world.dart b/examples/raw/hello_world.dart index 66b56630af..7275b03fb0 100644 --- a/examples/raw/hello_world.dart +++ b/examples/raw/hello_world.dart @@ -2,56 +2,56 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'dart:typed_data'; -sky.Color color; +ui.Color color; -sky.Picture paint(sky.Rect paintBounds) { - sky.PictureRecorder recorder = new sky.PictureRecorder(); - sky.Canvas canvas = new sky.Canvas(recorder, paintBounds); - sky.Size size = paintBounds.size; +ui.Picture paint(ui.Rect paintBounds) { + ui.PictureRecorder recorder = new ui.PictureRecorder(); + ui.Canvas canvas = new ui.Canvas(recorder, paintBounds); + ui.Size size = paintBounds.size; double radius = size.shortestSide * 0.45; - sky.Paint paint = new sky.Paint() + ui.Paint paint = new ui.Paint() ..color = color; - canvas.drawCircle(size.center(sky.Point.origin), radius, paint); + canvas.drawCircle(size.center(ui.Point.origin), radius, paint); return recorder.endRecording(); } -sky.Scene composite(sky.Picture picture, sky.Rect paintBounds) { - final double devicePixelRatio = sky.view.devicePixelRatio; - sky.Rect sceneBounds = new sky.Rect.fromLTWH(0.0, 0.0, sky.view.width * devicePixelRatio, sky.view.height * devicePixelRatio); +ui.Scene composite(ui.Picture picture, ui.Rect paintBounds) { + final double devicePixelRatio = ui.view.devicePixelRatio; + ui.Rect sceneBounds = new ui.Rect.fromLTWH(0.0, 0.0, ui.view.width * devicePixelRatio, ui.view.height * devicePixelRatio); Float64List deviceTransform = new Float64List(16) ..[0] = devicePixelRatio ..[5] = devicePixelRatio ..[10] = 1.0 ..[15] = 1.0; - sky.SceneBuilder sceneBuilder = new sky.SceneBuilder(sceneBounds) + ui.SceneBuilder sceneBuilder = new ui.SceneBuilder(sceneBounds) ..pushTransform(deviceTransform) - ..addPicture(sky.Offset.zero, picture, paintBounds) + ..addPicture(ui.Offset.zero, picture, paintBounds) ..pop(); return sceneBuilder.build(); } void beginFrame(double timeStamp) { - sky.Rect paintBounds = new sky.Rect.fromLTWH(0.0, 0.0, sky.view.width, sky.view.height); - sky.Picture picture = paint(paintBounds); - sky.Scene scene = composite(picture, paintBounds); - sky.view.scene = scene; + ui.Rect paintBounds = new ui.Rect.fromLTWH(0.0, 0.0, ui.view.width, ui.view.height); + ui.Picture picture = paint(paintBounds); + ui.Scene scene = composite(picture, paintBounds); + ui.view.scene = scene; } -bool handleEvent(sky.Event event) { +bool handleEvent(ui.Event event) { if (event.type == 'pointerdown') { - color = new sky.Color.fromARGB(255, 0, 0, 255); - sky.view.scheduleFrame(); + color = new ui.Color.fromARGB(255, 0, 0, 255); + ui.view.scheduleFrame(); return true; } if (event.type == 'pointerup') { - color = new sky.Color.fromARGB(255, 0, 255, 0); - sky.view.scheduleFrame(); + color = new ui.Color.fromARGB(255, 0, 255, 0); + ui.view.scheduleFrame(); return true; } @@ -65,8 +65,8 @@ bool handleEvent(sky.Event event) { void main() { print('Hello, world'); - color = new sky.Color.fromARGB(255, 0, 255, 0); - sky.view.setFrameCallback(beginFrame); - sky.view.setEventCallback(handleEvent); - sky.view.scheduleFrame(); + color = new ui.Color.fromARGB(255, 0, 255, 0); + ui.view.setFrameCallback(beginFrame); + ui.view.setEventCallback(handleEvent); + ui.view.scheduleFrame(); } diff --git a/examples/raw/mutating-dom.dart b/examples/raw/mutating-dom.dart index 0178584733..8ce1586d07 100644 --- a/examples/raw/mutating-dom.dart +++ b/examples/raw/mutating-dom.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'dart:math' as math; -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'dart:typed_data'; const kMaxIterations = 100; @@ -14,9 +14,9 @@ void report(String s) { // print("$s\n"); } -sky.LayoutRoot layoutRoot = new sky.LayoutRoot(); -sky.Document document = new sky.Document(); -sky.Element root; +ui.LayoutRoot layoutRoot = new ui.LayoutRoot(); +ui.Document document = new ui.Document(); +ui.Element root; math.Random random = new math.Random(); bool pickThis(double odds) { @@ -29,19 +29,19 @@ String generateCharacter(int min, int max) { return result; } -String colorToCSSString(sky.Color color) { +String colorToCSSString(ui.Color color) { return 'rgba(${color.red}, ${color.green}, ${color.blue}, ${color.alpha / 255.0})'; } -void mutate(sky.Canvas canvas) { +void mutate(ui.Canvas canvas) { // mutate the DOM randomly int iterationsLeft = kMaxIterations; - sky.Node node = root; - sky.Node other = null; + ui.Node node = root; + ui.Node other = null; while (node != null && iterationsLeft > 0) { iterationsLeft -= 1; - if (node is sky.Element && pickThis(0.4)) { - node = (node as sky.Element).firstChild; + if (node is ui.Element && pickThis(0.4)) { + node = (node as ui.Element).firstChild; } else if (node.nextSibling != null && pickThis(0.5)) { node = node.nextSibling; } else if (other == null && node != root && pickThis(0.1)) { @@ -57,7 +57,7 @@ void mutate(sky.Canvas canvas) { } else if (node != root && pickThis(0.001)) { report("remove()"); node.remove(); - } else if (node is sky.Element) { + } else if (node is ui.Element) { if (pickThis(0.1)) { report("appending a new text node (ASCII)"); node.appendChild(document.createText(generateCharacter(0x20, 0x7F))); @@ -80,7 +80,7 @@ void mutate(sky.Canvas canvas) { break; } else if (pickThis(0.1)) { report("styling: color"); - node.style['color'] = colorToCSSString(new sky.Color(random.nextInt(0xFFFFFFFF) | 0xC0808080)); + node.style['color'] = colorToCSSString(new ui.Color(random.nextInt(0xFFFFFFFF) | 0xC0808080)); break; } else if (pickThis(0.1)) { report("styling: font-size"); @@ -148,12 +148,12 @@ void mutate(sky.Canvas canvas) { break; } else if (pickThis(0.1)) { report("styling: text-decoration-color"); - node.style['text-decoration-color'] = colorToCSSString(new sky.Color(random.nextInt(0xFFFFFFFF))); + node.style['text-decoration-color'] = colorToCSSString(new ui.Color(random.nextInt(0xFFFFFFFF))); break; } } else { - assert(node is sky.Text); - final sky.Text text = node; + assert(node is ui.Text); + final ui.Text text = node; if (pickThis(0.1)) { report("appending a new text node (ASCII)"); text.appendData(generateCharacter(0x20, 0x7F)); @@ -182,8 +182,8 @@ void mutate(sky.Canvas canvas) { node = root; int count = 1; while (node != null) { - if (node is sky.Element && node.firstChild != null) { - node = (node as sky.Element).firstChild; + if (node is ui.Element && node.firstChild != null) { + node = (node as ui.Element).firstChild; count += 1; } else { while (node != null && node.nextSibling == null) @@ -202,40 +202,40 @@ void mutate(sky.Canvas canvas) { // draw the result report("recording..."); - layoutRoot.maxWidth = sky.view.width; + layoutRoot.maxWidth = ui.view.width; layoutRoot.layout(); layoutRoot.paint(canvas); report("painting..."); } -sky.Picture paint(sky.Rect paintBounds) { - sky.PictureRecorder recorder = new sky.PictureRecorder(); - sky.Canvas canvas = new sky.Canvas(recorder, paintBounds); +ui.Picture paint(ui.Rect paintBounds) { + ui.PictureRecorder recorder = new ui.PictureRecorder(); + ui.Canvas canvas = new ui.Canvas(recorder, paintBounds); mutate(canvas); return recorder.endRecording(); } -sky.Scene composite(sky.Picture picture, sky.Rect paintBounds) { - final double devicePixelRatio = sky.view.devicePixelRatio; - sky.Rect sceneBounds = new sky.Rect.fromLTWH(0.0, 0.0, sky.view.width * devicePixelRatio, sky.view.height * devicePixelRatio); +ui.Scene composite(ui.Picture picture, ui.Rect paintBounds) { + final double devicePixelRatio = ui.view.devicePixelRatio; + ui.Rect sceneBounds = new ui.Rect.fromLTWH(0.0, 0.0, ui.view.width * devicePixelRatio, ui.view.height * devicePixelRatio); Float64List deviceTransform = new Float64List(16) ..[0] = devicePixelRatio ..[5] = devicePixelRatio ..[10] = 1.0 ..[15] = 1.0; - sky.SceneBuilder sceneBuilder = new sky.SceneBuilder(sceneBounds) + ui.SceneBuilder sceneBuilder = new ui.SceneBuilder(sceneBounds) ..pushTransform(deviceTransform) - ..addPicture(sky.Offset.zero, picture, paintBounds) + ..addPicture(ui.Offset.zero, picture, paintBounds) ..pop(); return sceneBuilder.build(); } void beginFrame(double timeStamp) { - sky.Rect paintBounds = new sky.Rect.fromLTWH(0.0, 0.0, sky.view.width, sky.view.height); - sky.Picture picture = paint(paintBounds); - sky.Scene scene = composite(picture, paintBounds); - sky.view.scene = scene; - sky.view.scheduleFrame(); + ui.Rect paintBounds = new ui.Rect.fromLTWH(0.0, 0.0, ui.view.width, ui.view.height); + ui.Picture picture = paint(paintBounds); + ui.Scene scene = composite(picture, paintBounds); + ui.view.scene = scene; + ui.view.scheduleFrame(); } void main() { @@ -243,6 +243,6 @@ void main() { root.style['display'] = 'paragraph'; root.style['color'] = '#FFFFFF'; layoutRoot.rootElement = root; - sky.view.setFrameCallback(beginFrame); - sky.view.scheduleFrame(); + ui.view.setFrameCallback(beginFrame); + ui.view.scheduleFrame(); } diff --git a/examples/raw/painting.dart b/examples/raw/painting.dart index 41273a0b8b..d02e9583f4 100644 --- a/examples/raw/painting.dart +++ b/examples/raw/painting.dart @@ -2,34 +2,34 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'dart:math' as math; import 'dart:typed_data'; -sky.Picture paint(sky.Rect paintBounds) { - sky.PictureRecorder recorder = new sky.PictureRecorder(); - sky.Canvas canvas = new sky.Canvas(recorder, paintBounds); - sky.Size size = paintBounds.size; +ui.Picture paint(ui.Rect paintBounds) { + ui.PictureRecorder recorder = new ui.PictureRecorder(); + ui.Canvas canvas = new ui.Canvas(recorder, paintBounds); + ui.Size size = paintBounds.size; - sky.Paint paint = new sky.Paint(); - sky.Point mid = size.center(sky.Point.origin); + ui.Paint paint = new ui.Paint(); + ui.Point mid = size.center(ui.Point.origin); double radius = size.shortestSide / 2.0; - canvas.drawPaint(new sky.Paint()..color = const sky.Color(0xFFFFFFFF)); + canvas.drawPaint(new ui.Paint()..color = const ui.Color(0xFFFFFFFF)); canvas.save(); - canvas.translate(-mid.x/2.0, sky.view.height*2.0); + canvas.translate(-mid.x/2.0, ui.view.height*2.0); canvas.clipRect( - new sky.Rect.fromLTRB(0.0, -sky.view.height, sky.view.width, radius)); + new ui.Rect.fromLTRB(0.0, -ui.view.height, ui.view.width, radius)); canvas.translate(mid.x, mid.y); - paint.color = const sky.Color.fromARGB(128, 255, 0, 255); + paint.color = const ui.Color.fromARGB(128, 255, 0, 255); canvas.rotate(math.PI/4.0); - sky.Gradient yellowBlue = new sky.Gradient.linear( - [new sky.Point(-radius, -radius), new sky.Point(0.0, 0.0)], - [const sky.Color(0xFFFFFF00), const sky.Color(0xFF0000FF)]); - canvas.drawRect(new sky.Rect.fromLTRB(-radius, -radius, radius, radius), - new sky.Paint()..setShader(yellowBlue)); + ui.Gradient yellowBlue = new ui.Gradient.linear( + [new ui.Point(-radius, -radius), new ui.Point(0.0, 0.0)], + [const ui.Color(0xFFFFFF00), const ui.Color(0xFF0000FF)]); + canvas.drawRect(new ui.Rect.fromLTRB(-radius, -radius, radius, radius), + new ui.Paint()..setShader(yellowBlue)); // Scale x and y by 0.5. var scaleMatrix = new Float64List.fromList([ @@ -39,70 +39,70 @@ sky.Picture paint(sky.Rect paintBounds) { 0.0, 0.0, 0.0, 1.0, ]); canvas.concat(scaleMatrix); - paint.color = const sky.Color.fromARGB(128, 0, 255, 0); - canvas.drawCircle(sky.Point.origin, radius, paint); + paint.color = const ui.Color.fromARGB(128, 0, 255, 0); + canvas.drawCircle(ui.Point.origin, radius, paint); canvas.restore(); canvas.translate(0.0, 50.0); - var builder = new sky.LayerDrawLooperBuilder() + var builder = new ui.LayerDrawLooperBuilder() ..addLayerOnTop( - new sky.DrawLooperLayerInfo() - ..setOffset(const sky.Offset(150.0, 0.0)) - ..setColorMode(sky.TransferMode.src) - ..setPaintBits(sky.PaintBits.all), - new sky.Paint() - ..color = const sky.Color.fromARGB(128, 255, 255, 0) - ..colorFilter = new sky.ColorFilter.mode( - const sky.Color.fromARGB(128, 0, 0, 255), sky.TransferMode.srcIn) - ..maskFilter = new sky.MaskFilter.blur( - sky.BlurStyle.normal, 3.0, highQuality: true)) + new ui.DrawLooperLayerInfo() + ..setOffset(const ui.Offset(150.0, 0.0)) + ..setColorMode(ui.TransferMode.src) + ..setPaintBits(ui.PaintBits.all), + new ui.Paint() + ..color = const ui.Color.fromARGB(128, 255, 255, 0) + ..colorFilter = new ui.ColorFilter.mode( + const ui.Color.fromARGB(128, 0, 0, 255), ui.TransferMode.srcIn) + ..maskFilter = new ui.MaskFilter.blur( + ui.BlurStyle.normal, 3.0, highQuality: true)) ..addLayerOnTop( - new sky.DrawLooperLayerInfo() - ..setOffset(const sky.Offset(75.0, 75.0)) - ..setColorMode(sky.TransferMode.src) - ..setPaintBits(sky.PaintBits.shader), - new sky.Paint() - ..shader = new sky.Gradient.radial( - new sky.Point(0.0, 0.0), radius/3.0, - [const sky.Color(0xFFFFFF00), const sky.Color(0xFFFF0000)], - null, sky.TileMode.mirror) - // Since we're don't set sky.PaintBits.maskFilter, this has no effect. - ..maskFilter = new sky.MaskFilter.blur( - sky.BlurStyle.normal, 50.0, highQuality: true)) + new ui.DrawLooperLayerInfo() + ..setOffset(const ui.Offset(75.0, 75.0)) + ..setColorMode(ui.TransferMode.src) + ..setPaintBits(ui.PaintBits.shader), + new ui.Paint() + ..shader = new ui.Gradient.radial( + new ui.Point(0.0, 0.0), radius/3.0, + [const ui.Color(0xFFFFFF00), const ui.Color(0xFFFF0000)], + null, ui.TileMode.mirror) + // Since we're don't set ui.PaintBits.maskFilter, this has no effect. + ..maskFilter = new ui.MaskFilter.blur( + ui.BlurStyle.normal, 50.0, highQuality: true)) ..addLayerOnTop( - new sky.DrawLooperLayerInfo()..setOffset(const sky.Offset(225.0, 75.0)), + new ui.DrawLooperLayerInfo()..setOffset(const ui.Offset(225.0, 75.0)), // Since this layer uses a DST color mode, this has no effect. - new sky.Paint()..color = const sky.Color.fromARGB(128, 255, 0, 0)); + new ui.Paint()..color = const ui.Color.fromARGB(128, 255, 0, 0)); paint.drawLooper = builder.build(); - canvas.drawCircle(sky.Point.origin, radius, paint); + canvas.drawCircle(ui.Point.origin, radius, paint); return recorder.endRecording(); } -sky.Scene composite(sky.Picture picture, sky.Rect paintBounds) { - final double devicePixelRatio = sky.view.devicePixelRatio; - sky.Rect sceneBounds = new sky.Rect.fromLTWH(0.0, 0.0, sky.view.width * devicePixelRatio, sky.view.height * devicePixelRatio); +ui.Scene composite(ui.Picture picture, ui.Rect paintBounds) { + final double devicePixelRatio = ui.view.devicePixelRatio; + ui.Rect sceneBounds = new ui.Rect.fromLTWH(0.0, 0.0, ui.view.width * devicePixelRatio, ui.view.height * devicePixelRatio); Float32List deviceTransform = new Float32List(16) ..[0] = devicePixelRatio ..[5] = devicePixelRatio ..[10] = 1.0 ..[15] = 1.0; - sky.SceneBuilder sceneBuilder = new sky.SceneBuilder(sceneBounds) + ui.SceneBuilder sceneBuilder = new ui.SceneBuilder(sceneBounds) ..pushTransform(deviceTransform) - ..addPicture(sky.Offset.zero, picture, paintBounds) + ..addPicture(ui.Offset.zero, picture, paintBounds) ..pop(); return sceneBuilder.build(); } void beginFrame(double timeStamp) { - sky.Rect paintBounds = new sky.Rect.fromLTWH(0.0, 0.0, sky.view.width, sky.view.height); - sky.Picture picture = paint(paintBounds); - sky.Scene scene = composite(picture, paintBounds); - sky.view.scene = scene; + ui.Rect paintBounds = new ui.Rect.fromLTWH(0.0, 0.0, ui.view.width, ui.view.height); + ui.Picture picture = paint(paintBounds); + ui.Scene scene = composite(picture, paintBounds); + ui.view.scene = scene; } void main() { - sky.view.setFrameCallback(beginFrame); - sky.view.scheduleFrame(); + ui.view.setFrameCallback(beginFrame); + ui.view.scheduleFrame(); } diff --git a/examples/raw/shadow.dart b/examples/raw/shadow.dart index 453cbb5262..eedeb0a096 100644 --- a/examples/raw/shadow.dart +++ b/examples/raw/shadow.dart @@ -2,63 +2,63 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'dart:typed_data'; -sky.Picture paint(sky.Rect paintBounds) { - sky.PictureRecorder recorder = new sky.PictureRecorder(); - sky.Canvas canvas = new sky.Canvas(recorder, paintBounds); +ui.Picture paint(ui.Rect paintBounds) { + ui.PictureRecorder recorder = new ui.PictureRecorder(); + ui.Canvas canvas = new ui.Canvas(recorder, paintBounds); double size = 100.0; canvas.translate(size + 10.0, size + 10.0); - sky.Paint paint = new sky.Paint(); - paint.color = const sky.Color.fromARGB(255, 0, 255, 0); - var builder = new sky.LayerDrawLooperBuilder() + ui.Paint paint = new ui.Paint(); + paint.color = const ui.Color.fromARGB(255, 0, 255, 0); + var builder = new ui.LayerDrawLooperBuilder() // Shadow layer. ..addLayerOnTop( - new sky.DrawLooperLayerInfo() - ..setPaintBits(sky.PaintBits.all) - ..setOffset(const sky.Offset(5.0, 5.0)) - ..setColorMode(sky.TransferMode.src), - new sky.Paint() - ..color = const sky.Color.fromARGB(128, 55, 55, 55) - ..maskFilter = new sky.MaskFilter.blur(sky.BlurStyle.normal, 5.0) + new ui.DrawLooperLayerInfo() + ..setPaintBits(ui.PaintBits.all) + ..setOffset(const ui.Offset(5.0, 5.0)) + ..setColorMode(ui.TransferMode.src), + new ui.Paint() + ..color = const ui.Color.fromARGB(128, 55, 55, 55) + ..maskFilter = new ui.MaskFilter.blur(ui.BlurStyle.normal, 5.0) ) // Main layer. - ..addLayerOnTop(new sky.DrawLooperLayerInfo(), new sky.Paint()); + ..addLayerOnTop(new ui.DrawLooperLayerInfo(), new ui.Paint()); paint.drawLooper = builder.build(); canvas.drawPaint( - new sky.Paint()..color = const sky.Color.fromARGB(255, 255, 255, 255)); - canvas.drawRect(new sky.Rect.fromLTRB(-size, -size, size, size), paint); + new ui.Paint()..color = const ui.Color.fromARGB(255, 255, 255, 255)); + canvas.drawRect(new ui.Rect.fromLTRB(-size, -size, size, size), paint); return recorder.endRecording(); } -sky.Scene composite(sky.Picture picture, sky.Rect paintBounds) { - final double devicePixelRatio = sky.view.devicePixelRatio; - sky.Rect sceneBounds = new sky.Rect.fromLTWH(0.0, 0.0, sky.view.width * devicePixelRatio, sky.view.height * devicePixelRatio); +ui.Scene composite(ui.Picture picture, ui.Rect paintBounds) { + final double devicePixelRatio = ui.view.devicePixelRatio; + ui.Rect sceneBounds = new ui.Rect.fromLTWH(0.0, 0.0, ui.view.width * devicePixelRatio, ui.view.height * devicePixelRatio); Float64List deviceTransform = new Float64List(16) ..[0] = devicePixelRatio ..[5] = devicePixelRatio ..[10] = 1.0 ..[15] = 1.0; - sky.SceneBuilder sceneBuilder = new sky.SceneBuilder(sceneBounds) + ui.SceneBuilder sceneBuilder = new ui.SceneBuilder(sceneBounds) ..pushTransform(deviceTransform) - ..addPicture(sky.Offset.zero, picture, paintBounds) + ..addPicture(ui.Offset.zero, picture, paintBounds) ..pop(); return sceneBuilder.build(); } void beginFrame(double timeStamp) { - sky.Rect paintBounds = new sky.Rect.fromLTWH(0.0, 0.0, sky.view.width, sky.view.height); - sky.Picture picture = paint(paintBounds); - sky.Scene scene = composite(picture, paintBounds); - sky.view.scene = scene; + ui.Rect paintBounds = new ui.Rect.fromLTWH(0.0, 0.0, ui.view.width, ui.view.height); + ui.Picture picture = paint(paintBounds); + ui.Scene scene = composite(picture, paintBounds); + ui.view.scene = scene; } void main() { - sky.view.setFrameCallback(beginFrame); - sky.view.scheduleFrame(); + ui.view.setFrameCallback(beginFrame); + ui.view.scheduleFrame(); } diff --git a/examples/raw/spinning_arabic.dart b/examples/raw/spinning_arabic.dart index 09d1e0f203..1e722fcd9c 100644 --- a/examples/raw/spinning_arabic.dart +++ b/examples/raw/spinning_arabic.dart @@ -3,20 +3,20 @@ // found in the LICENSE file. import 'dart:math' as math; -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'dart:typed_data'; double timeBase = null; -sky.LayoutRoot layoutRoot = new sky.LayoutRoot(); +ui.LayoutRoot layoutRoot = new ui.LayoutRoot(); -sky.Picture paint(sky.Rect paintBounds, double delta) { - sky.PictureRecorder recorder = new sky.PictureRecorder(); - sky.Canvas canvas = new sky.Canvas(recorder, paintBounds); +ui.Picture paint(ui.Rect paintBounds, double delta) { + ui.PictureRecorder recorder = new ui.PictureRecorder(); + ui.Canvas canvas = new ui.Canvas(recorder, paintBounds); - canvas.translate(sky.view.width / 2.0, sky.view.height / 2.0); + canvas.translate(ui.view.width / 2.0, ui.view.height / 2.0); canvas.rotate(math.PI * delta / 1800); - canvas.drawRect(new sky.Rect.fromLTRB(-100.0, -100.0, 100.0, 100.0), - new sky.Paint()..color = const sky.Color.fromARGB(255, 0, 255, 0)); + canvas.drawRect(new ui.Rect.fromLTRB(-100.0, -100.0, 100.0, 100.0), + new ui.Paint()..color = const ui.Color.fromARGB(255, 0, 255, 0)); double sin = math.sin(delta / 200); layoutRoot.maxWidth = 150.0 + (50 * sin); @@ -28,17 +28,17 @@ sky.Picture paint(sky.Rect paintBounds, double delta) { return recorder.endRecording(); } -sky.Scene composite(sky.Picture picture, sky.Rect paintBounds) { - final double devicePixelRatio = sky.view.devicePixelRatio; - sky.Rect sceneBounds = new sky.Rect.fromLTWH(0.0, 0.0, sky.view.width * devicePixelRatio, sky.view.height * devicePixelRatio); +ui.Scene composite(ui.Picture picture, ui.Rect paintBounds) { + final double devicePixelRatio = ui.view.devicePixelRatio; + ui.Rect sceneBounds = new ui.Rect.fromLTWH(0.0, 0.0, ui.view.width * devicePixelRatio, ui.view.height * devicePixelRatio); Float64List deviceTransform = new Float64List(16) ..[0] = devicePixelRatio ..[5] = devicePixelRatio ..[10] = 1.0 ..[15] = 1.0; - sky.SceneBuilder sceneBuilder = new sky.SceneBuilder(sceneBounds) + ui.SceneBuilder sceneBuilder = new ui.SceneBuilder(sceneBounds) ..pushTransform(deviceTransform) - ..addPicture(sky.Offset.zero, picture, paintBounds) + ..addPicture(ui.Offset.zero, picture, paintBounds) ..pop(); return sceneBuilder.build(); } @@ -47,15 +47,15 @@ void beginFrame(double timeStamp) { if (timeBase == null) timeBase = timeStamp; double delta = timeStamp - timeBase; - sky.Rect paintBounds = new sky.Rect.fromLTWH(0.0, 0.0, sky.view.width, sky.view.height); - sky.Picture picture = paint(paintBounds, delta); - sky.Scene scene = composite(picture, paintBounds); - sky.view.scene = scene; - sky.view.scheduleFrame(); + ui.Rect paintBounds = new ui.Rect.fromLTWH(0.0, 0.0, ui.view.width, ui.view.height); + ui.Picture picture = paint(paintBounds, delta); + ui.Scene scene = composite(picture, paintBounds); + ui.view.scene = scene; + ui.view.scheduleFrame(); } void main() { - var document = new sky.Document(); + var document = new ui.Document(); var arabic = document.createText("هذا هو قليلا طويلة من النص الذي يجب التفاف ."); var more = document.createText(" و أكثر قليلا لجعله أطول. "); var block = document.createElement('p'); @@ -68,6 +68,6 @@ void main() { layoutRoot.rootElement = block; - sky.view.setFrameCallback(beginFrame); - sky.view.scheduleFrame(); + ui.view.setFrameCallback(beginFrame); + ui.view.scheduleFrame(); } diff --git a/examples/raw/spinning_image.dart b/examples/raw/spinning_image.dart index b9fe9b450b..cd2973bdc5 100644 --- a/examples/raw/spinning_image.dart +++ b/examples/raw/spinning_image.dart @@ -3,29 +3,29 @@ // found in the LICENSE file. import 'dart:math' as math; -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'dart:typed_data'; import 'package:flutter/services.dart'; double timeBase = null; -sky.Image image = null; +ui.Image image = null; String url1 = "https://raw.githubusercontent.com/dart-lang/logos/master/logos_and_wordmarks/dart-logo.png"; String url2 = "http://i2.kym-cdn.com/photos/images/facebook/000/581/296/c09.jpg"; -sky.Picture paint(sky.Rect paintBounds, double delta) { - sky.PictureRecorder recorder = new sky.PictureRecorder(); - sky.Canvas canvas = new sky.Canvas(recorder, paintBounds); +ui.Picture paint(ui.Rect paintBounds, double delta) { + ui.PictureRecorder recorder = new ui.PictureRecorder(); + ui.Canvas canvas = new ui.Canvas(recorder, paintBounds); canvas.translate(paintBounds.width / 2.0, paintBounds.height / 2.0); canvas.rotate(math.PI * delta / 1800); canvas.scale(0.2, 0.2); - sky.Paint paint = new sky.Paint()..color = const sky.Color.fromARGB(255, 0, 255, 0); + ui.Paint paint = new ui.Paint()..color = const ui.Color.fromARGB(255, 0, 255, 0); // Draw image if (image != null) - canvas.drawImage(image, new sky.Point(-image.width / 2.0, -image.height / 2.0), paint); + canvas.drawImage(image, new ui.Point(-image.width / 2.0, -image.height / 2.0), paint); // Draw cut out of image canvas.rotate(math.PI * delta / 1800); @@ -33,25 +33,25 @@ sky.Picture paint(sky.Rect paintBounds, double delta) { var w = image.width.toDouble(); var h = image.width.toDouble(); canvas.drawImageRect(image, - new sky.Rect.fromLTRB(w * 0.25, h * 0.25, w * 0.75, h * 0.75), - new sky.Rect.fromLTRB(-w / 4.0, -h / 4.0, w / 4.0, h / 4.0), + new ui.Rect.fromLTRB(w * 0.25, h * 0.25, w * 0.75, h * 0.75), + new ui.Rect.fromLTRB(-w / 4.0, -h / 4.0, w / 4.0, h / 4.0), paint); } return recorder.endRecording(); } -sky.Scene composite(sky.Picture picture, sky.Rect paintBounds) { - final double devicePixelRatio = sky.view.devicePixelRatio; - sky.Rect sceneBounds = new sky.Rect.fromLTWH(0.0, 0.0, sky.view.width * devicePixelRatio, sky.view.height * devicePixelRatio); +ui.Scene composite(ui.Picture picture, ui.Rect paintBounds) { + final double devicePixelRatio = ui.view.devicePixelRatio; + ui.Rect sceneBounds = new ui.Rect.fromLTWH(0.0, 0.0, ui.view.width * devicePixelRatio, ui.view.height * devicePixelRatio); Float64List deviceTransform = new Float64List(16) ..[0] = devicePixelRatio ..[5] = devicePixelRatio ..[10] = 1.0 ..[15] = 1.0; - sky.SceneBuilder sceneBuilder = new sky.SceneBuilder(sceneBounds) + ui.SceneBuilder sceneBuilder = new ui.SceneBuilder(sceneBounds) ..pushTransform(deviceTransform) - ..addPicture(sky.Offset.zero, picture, paintBounds) + ..addPicture(ui.Offset.zero, picture, paintBounds) ..pop(); return sceneBuilder.build(); } @@ -60,11 +60,11 @@ void beginFrame(double timeStamp) { if (timeBase == null) timeBase = timeStamp; double delta = timeStamp - timeBase; - sky.Rect paintBounds = new sky.Rect.fromLTWH(0.0, 0.0, sky.view.width, sky.view.height); - sky.Picture picture = paint(paintBounds, delta); - sky.Scene scene = composite(picture, paintBounds); - sky.view.scene = scene; - sky.view.scheduleFrame(); + ui.Rect paintBounds = new ui.Rect.fromLTWH(0.0, 0.0, ui.view.width, ui.view.height); + ui.Picture picture = paint(paintBounds, delta); + ui.Scene scene = composite(picture, paintBounds); + ui.view.scene = scene; + ui.view.scheduleFrame(); } @@ -72,13 +72,13 @@ void handleImageLoad(result) { if (result != image) { print("${result.width}x${result.width} image loaded!"); image = result; - sky.view.scheduleFrame(); + ui.view.scheduleFrame(); } else { print("Existing image was loaded again"); } } -bool handleEvent(sky.Event event) { +bool handleEvent(ui.Event event) { if (event.type == "pointerdown") { return true; } @@ -93,6 +93,6 @@ bool handleEvent(sky.Event event) { void main() { imageCache.load(url1).first.then(handleImageLoad); - sky.view.setEventCallback(handleEvent); - sky.view.setFrameCallback(beginFrame); + ui.view.setEventCallback(handleEvent); + ui.view.setFrameCallback(beginFrame); } diff --git a/examples/raw/spinning_square.dart b/examples/raw/spinning_square.dart index 1cb85c884c..8a98bbd839 100644 --- a/examples/raw/spinning_square.dart +++ b/examples/raw/spinning_square.dart @@ -3,46 +3,46 @@ // found in the LICENSE file. import 'dart:math' as math; -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'dart:typed_data'; double timeBase = null; void beginFrame(double timeStamp) { - sky.tracing.begin('beginFrame'); + ui.tracing.begin('beginFrame'); if (timeBase == null) timeBase = timeStamp; double delta = timeStamp - timeBase; // paint - sky.Rect paintBounds = new sky.Rect.fromLTWH(0.0, 0.0, sky.view.width, sky.view.height); - sky.PictureRecorder recorder = new sky.PictureRecorder(); - sky.Canvas canvas = new sky.Canvas(recorder, paintBounds); + ui.Rect paintBounds = new ui.Rect.fromLTWH(0.0, 0.0, ui.view.width, ui.view.height); + ui.PictureRecorder recorder = new ui.PictureRecorder(); + ui.Canvas canvas = new ui.Canvas(recorder, paintBounds); canvas.translate(paintBounds.width / 2.0, paintBounds.height / 2.0); canvas.rotate(math.PI * delta / 1800); - canvas.drawRect(new sky.Rect.fromLTRB(-100.0, -100.0, 100.0, 100.0), - new sky.Paint()..color = const sky.Color.fromARGB(255, 0, 255, 0)); - sky.Picture picture = recorder.endRecording(); + canvas.drawRect(new ui.Rect.fromLTRB(-100.0, -100.0, 100.0, 100.0), + new ui.Paint()..color = const ui.Color.fromARGB(255, 0, 255, 0)); + ui.Picture picture = recorder.endRecording(); // composite - final double devicePixelRatio = sky.view.devicePixelRatio; - sky.Rect sceneBounds = new sky.Rect.fromLTWH(0.0, 0.0, sky.view.width * devicePixelRatio, sky.view.height * devicePixelRatio); + final double devicePixelRatio = ui.view.devicePixelRatio; + ui.Rect sceneBounds = new ui.Rect.fromLTWH(0.0, 0.0, ui.view.width * devicePixelRatio, ui.view.height * devicePixelRatio); Float64List deviceTransform = new Float64List(16) ..[0] = devicePixelRatio ..[5] = devicePixelRatio ..[10] = 1.0 ..[15] = 1.0; - sky.SceneBuilder sceneBuilder = new sky.SceneBuilder(sceneBounds) + ui.SceneBuilder sceneBuilder = new ui.SceneBuilder(sceneBounds) ..pushTransform(deviceTransform) - ..addPicture(sky.Offset.zero, picture, paintBounds) + ..addPicture(ui.Offset.zero, picture, paintBounds) ..pop(); - sky.view.scene = sceneBuilder.build(); + ui.view.scene = sceneBuilder.build(); - sky.tracing.end('beginFrame'); - sky.view.scheduleFrame(); + ui.tracing.end('beginFrame'); + ui.view.scheduleFrame(); } void main() { - sky.view.setFrameCallback(beginFrame); - sky.view.scheduleFrame(); + ui.view.setFrameCallback(beginFrame); + ui.view.scheduleFrame(); } diff --git a/examples/rendering/baseline.dart b/examples/rendering/baseline.dart index a3838e7ecf..11da5f1a20 100644 --- a/examples/rendering/baseline.dart +++ b/examples/rendering/baseline.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'package:flutter/rendering.dart'; @@ -50,7 +50,7 @@ RenderBox getBox(double lh) { path.lineTo(w, h); Paint paint = new Paint(); paint.color = const Color(0xFFFF9000); - paint.setStyle(sky.PaintingStyle.stroke); + paint.setStyle(ui.PaintingStyle.stroke); paint.strokeWidth = 3.0; canvas.drawPath(path, paint); } diff --git a/examples/rendering/borders.dart b/examples/rendering/borders.dart index 52b642e949..452970d912 100644 --- a/examples/rendering/borders.dart +++ b/examples/rendering/borders.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'package:flutter/rendering.dart'; @@ -15,7 +15,7 @@ void main() { additionalConstraints: new BoxConstraints.tightFor(height: 100.0), child: new RenderDecoratedBox( decoration: new BoxDecoration( - backgroundColor: new sky.Color(0xFFFFFF00) + backgroundColor: new ui.Color(0xFFFFFF00) ) ) ) @@ -27,12 +27,12 @@ void main() { child: new RenderDecoratedBox( decoration: new BoxDecoration( border: new Border( - top: new BorderSide(color: new sky.Color(0xFFF00000), width: 5.0), - right: new BorderSide(color: new sky.Color(0xFFFF9000), width: 10.0), - bottom: new BorderSide(color: new sky.Color(0xFFFFF000), width: 15.0), - left: new BorderSide(color: new sky.Color(0xFF00FF00), width: 20.0) + top: new BorderSide(color: new ui.Color(0xFFF00000), width: 5.0), + right: new BorderSide(color: new ui.Color(0xFFFF9000), width: 10.0), + bottom: new BorderSide(color: new ui.Color(0xFFFFF000), width: 15.0), + left: new BorderSide(color: new ui.Color(0xFF00FF00), width: 20.0) ), - backgroundColor: new sky.Color(0xFFDDDDDD) + backgroundColor: new ui.Color(0xFFDDDDDD) ) ) ) @@ -43,7 +43,7 @@ void main() { additionalConstraints: new BoxConstraints.tightFor(height: 100.0), child: new RenderDecoratedBox( decoration: new BoxDecoration( - backgroundColor: new sky.Color(0xFFFFFF00) + backgroundColor: new ui.Color(0xFFFFFF00) ) ) ) @@ -54,7 +54,7 @@ void main() { additionalConstraints: new BoxConstraints.tightFor(height: 100.0), child: new RenderDecoratedBox( decoration: new BoxDecoration( - backgroundColor: new sky.Color(0xFFFFFF00) + backgroundColor: new ui.Color(0xFFFFFF00) ) ) ) @@ -65,7 +65,7 @@ void main() { additionalConstraints: new BoxConstraints.tightFor(height: 100.0), child: new RenderDecoratedBox( decoration: new BoxDecoration( - backgroundColor: new sky.Color(0xFFFFFF00) + backgroundColor: new ui.Color(0xFFFFFF00) ) ) ) diff --git a/examples/rendering/flex.dart b/examples/rendering/flex.dart index 2abaf26719..164220c4df 100644 --- a/examples/rendering/flex.dart +++ b/examples/rendering/flex.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'package:flutter/rendering.dart'; import 'solid_color_box.dart'; @@ -11,24 +11,24 @@ RenderBox buildFlexExample() { RenderFlex flexRoot = new RenderFlex(direction: FlexDirection.vertical); RenderDecoratedBox root = new RenderDecoratedBox( - decoration: new BoxDecoration(backgroundColor: const sky.Color(0xFF000000)), + decoration: new BoxDecoration(backgroundColor: const ui.Color(0xFF000000)), child: flexRoot ); - void addFlexChildSolidColor(RenderFlex parent, sky.Color backgroundColor, { int flex: 0 }) { + void addFlexChildSolidColor(RenderFlex parent, ui.Color backgroundColor, { int flex: 0 }) { RenderSolidColorBox child = new RenderSolidColorBox(backgroundColor); parent.add(child); child.parentData.flex = flex; } // Yellow bar at top - addFlexChildSolidColor(flexRoot, const sky.Color(0xFFFFFF00), flex: 1); + addFlexChildSolidColor(flexRoot, const ui.Color(0xFFFFFF00), flex: 1); // Turquoise box - flexRoot.add(new RenderSolidColorBox(const sky.Color(0x7700FFFF), desiredSize: new sky.Size(100.0, 100.0))); + flexRoot.add(new RenderSolidColorBox(const ui.Color(0x7700FFFF), desiredSize: new ui.Size(100.0, 100.0))); var renderDecoratedBlock = new RenderDecoratedBox( - decoration: new BoxDecoration(backgroundColor: const sky.Color(0xFFFFFFFF)) + decoration: new BoxDecoration(backgroundColor: const ui.Color(0xFFFFFFFF)) ); flexRoot.add(new RenderPadding(padding: const EdgeDims.all(10.0), child: renderDecoratedBlock)); @@ -36,11 +36,11 @@ RenderBox buildFlexExample() { var row = new RenderFlex(direction: FlexDirection.horizontal); // Purple and blue cells - addFlexChildSolidColor(row, const sky.Color(0x77FF00FF), flex: 1); - addFlexChildSolidColor(row, const sky.Color(0xFF0000FF), flex: 2); + addFlexChildSolidColor(row, const ui.Color(0x77FF00FF), flex: 1); + addFlexChildSolidColor(row, const ui.Color(0xFF0000FF), flex: 2); var decoratedRow = new RenderDecoratedBox( - decoration: new BoxDecoration(backgroundColor: const sky.Color(0xFF333333)), + decoration: new BoxDecoration(backgroundColor: const ui.Color(0xFF333333)), child: row ); diff --git a/examples/rendering/interactive_flex.dart b/examples/rendering/interactive_flex.dart index 79134675ca..ce50fd9204 100644 --- a/examples/rendering/interactive_flex.dart +++ b/examples/rendering/interactive_flex.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'dart:math' as math; import 'package:flutter/services.dart'; @@ -19,7 +19,7 @@ class Touch { class RenderImageGrow extends RenderImage { final Size _startingSize; - RenderImageGrow(sky.Image image, Size size) + RenderImageGrow(ui.Image image, Size size) : _startingSize = size, super(image: image, width: size.width, height: size.height); double _growth = 0.0; @@ -35,7 +35,7 @@ RenderImageGrow image; Map touches = new Map(); void handleEvent(event) { - if (event is sky.PointerEvent) { + if (event is ui.PointerEvent) { if (event.type == 'pointermove') image.growth = math.max(0.0, image.growth + event.x - touches[event.pointer].x); touches[event.pointer] = new Touch(event.x, event.y); @@ -59,7 +59,7 @@ void main() { // Resizeable image image = new RenderImageGrow(null, new Size(100.0, null)); - imageCache.load("https://www.dartlang.org/logos/dart-logo.png").first.then((sky.Image dartLogo) { + imageCache.load("https://www.dartlang.org/logos/dart-logo.png").first.then((ui.Image dartLogo) { image.image = dartLogo; }); @@ -99,5 +99,5 @@ Pancetta meatball tongue tenderloin rump tail jowl boudin."""; updateTaskDescription('Interactive Flex', topColor); new FlutterBinding(root: root); - sky.view.setEventCallback(handleEvent); + ui.view.setEventCallback(handleEvent); } diff --git a/examples/rendering/sector_layout.dart b/examples/rendering/sector_layout.dart index 9e4a9889a4..912127ad0a 100644 --- a/examples/rendering/sector_layout.dart +++ b/examples/rendering/sector_layout.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'dart:math' as math; -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'package:flutter/rendering.dart'; @@ -528,7 +528,7 @@ class RenderSolidColor extends RenderDecoratedSector { deltaTheta = constraints.constrainDeltaTheta(desiredDeltaTheta); } - void handleEvent(sky.Event event, HitTestEntry entry) { + void handleEvent(ui.Event event, HitTestEntry entry) { if (event.type == 'pointerdown') decoration = new BoxDecoration(backgroundColor: const Color(0xFFFF0000)); else if (event.type == 'pointerup') diff --git a/examples/rendering/solid_color_box.dart b/examples/rendering/solid_color_box.dart index 689631796a..acd6a6300f 100644 --- a/examples/rendering/solid_color_box.dart +++ b/examples/rendering/solid_color_box.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'package:flutter/rendering.dart'; @@ -42,7 +42,7 @@ class RenderSolidColorBox extends RenderDecoratedBox { size = constraints.constrain(desiredSize); } - void handleEvent(sky.Event event, BoxHitTestEntry entry) { + void handleEvent(ui.Event event, BoxHitTestEntry entry) { if (event.type == 'pointerdown') decoration = new BoxDecoration(backgroundColor: const Color(0xFFFF0000)); else if (event.type == 'pointerup') diff --git a/examples/rendering/spinning_flex.dart b/examples/rendering/spinning_flex.dart index ea9ba7651c..c6d21ce168 100644 --- a/examples/rendering/spinning_flex.dart +++ b/examples/rendering/spinning_flex.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'package:flutter/animation.dart'; import 'package:flutter/rendering.dart'; @@ -15,15 +15,15 @@ RenderTransform transformBox; void main() { RenderFlex flexRoot = new RenderFlex(direction: FlexDirection.vertical); - void addFlexChildSolidColor(RenderFlex parent, sky.Color backgroundColor, { int flex: 0 }) { + void addFlexChildSolidColor(RenderFlex parent, ui.Color backgroundColor, { int flex: 0 }) { RenderSolidColorBox child = new RenderSolidColorBox(backgroundColor); parent.add(child); child.parentData.flex = flex; } - addFlexChildSolidColor(flexRoot, const sky.Color(0xFFFF00FF), flex: 1); - addFlexChildSolidColor(flexRoot, const sky.Color(0xFFFFFF00), flex: 2); - addFlexChildSolidColor(flexRoot, const sky.Color(0xFF00FFFF), flex: 1); + addFlexChildSolidColor(flexRoot, const ui.Color(0xFFFF00FF), flex: 1); + addFlexChildSolidColor(flexRoot, const ui.Color(0xFFFFFF00), flex: 2); + addFlexChildSolidColor(flexRoot, const ui.Color(0xFF00FFFF), flex: 1); transformBox = new RenderTransform(child: flexRoot, transform: new Matrix4.identity()); diff --git a/examples/rendering/touch_demo.dart b/examples/rendering/touch_demo.dart index 9a6ec80481..5c22785110 100644 --- a/examples/rendering/touch_demo.dart +++ b/examples/rendering/touch_demo.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; @@ -24,7 +24,7 @@ class Dot { Dot({ Color color }) : _paint = new Paint()..color = color; - void update(sky.PointerEvent event) { + void update(ui.PointerEvent event) { position = new Point(event.x, event.y); radius = 5 + (95 * event.pressure); } @@ -39,8 +39,8 @@ class RenderTouchDemo extends RenderBox { RenderTouchDemo(); - void handleEvent(sky.Event event, BoxHitTestEntry entry) { - if (event is sky.PointerEvent) { + void handleEvent(ui.Event event, BoxHitTestEntry entry) { + if (event is ui.PointerEvent) { switch (event.type) { case 'pointerdown': Color color = kColors[event.pointer.remainder(kColors.length)]; diff --git a/examples/rendering/transform.dart b/examples/rendering/transform.dart index d34758fd3e..664b0325bf 100644 --- a/examples/rendering/transform.dart +++ b/examples/rendering/transform.dart @@ -2,16 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'package:flutter/rendering.dart'; void main() { RenderDecoratedBox green = new RenderDecoratedBox( - decoration: new BoxDecoration(backgroundColor: const sky.Color(0xFF00FF00)) + decoration: new BoxDecoration(backgroundColor: const ui.Color(0xFF00FF00)) ); RenderConstrainedBox box = new RenderConstrainedBox( - additionalConstraints: new BoxConstraints.tight(const sky.Size(200.0, 200.0)), + additionalConstraints: new BoxConstraints.tight(const ui.Size(200.0, 200.0)), child: green ); diff --git a/examples/stocks/lib/main.dart b/examples/stocks/lib/main.dart index 35c7baf6c5..314a3b57a5 100644 --- a/examples/stocks/lib/main.dart +++ b/examples/stocks/lib/main.dart @@ -6,7 +6,7 @@ library stocks; import 'dart:async'; import 'dart:math' as math; -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; diff --git a/examples/stocks/lib/stock_arrow.dart b/examples/stocks/lib/stock_arrow.dart index a1f56b56df..f745c242bb 100644 --- a/examples/stocks/lib/stock_arrow.dart +++ b/examples/stocks/lib/stock_arrow.dart @@ -25,7 +25,7 @@ class StockArrow extends StatelessComponent { // TODO(jackson): This should change colors with the theme Color color = _colorForPercentChange(percentChange); const double kSize = 40.0; - var arrow = new CustomPaint(callback: (sky.Canvas canvas, Size size) { + var arrow = new CustomPaint(callback: (ui.Canvas canvas, Size size) { Paint paint = new Paint()..color = color; paint.strokeWidth = 1.0; const double padding = 2.0; @@ -49,11 +49,11 @@ class StockArrow extends StatelessComponent { path.lineTo(centerX + w, arrowY + h); path.lineTo(centerX - w, arrowY + h); path.close(); - paint.setStyle(sky.PaintingStyle.fill); + paint.setStyle(ui.PaintingStyle.fill); canvas.drawPath(path, paint); // Draw a circle that circumscribes the arrow. - paint.setStyle(sky.PaintingStyle.stroke); + paint.setStyle(ui.PaintingStyle.stroke); canvas.drawCircle(new Point(centerX, centerY), r, paint); }); diff --git a/examples/stocks/lib/stock_menu.dart b/examples/stocks/lib/stock_menu.dart index c55e646589..1a1ca9af4e 100644 --- a/examples/stocks/lib/stock_menu.dart +++ b/examples/stocks/lib/stock_menu.dart @@ -12,8 +12,8 @@ Future showStockMenu(NavigatorState navigator, { bool autorefresh, ValueChanged switch (await showMenu( navigator: navigator, position: new MenuPosition( - right: sky.view.paddingRight + _kMenuMargin, - top: sky.view.paddingTop + _kMenuMargin + right: ui.view.paddingRight + _kMenuMargin, + top: ui.view.paddingTop + _kMenuMargin ), builder: (NavigatorState navigator) { return [ diff --git a/examples/widgets/card_collection.dart b/examples/widgets/card_collection.dart index 6cbb9889c1..fd2d17a047 100644 --- a/examples/widgets/card_collection.dart +++ b/examples/widgets/card_collection.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'package:flutter/material.dart'; import 'package:flutter/painting.dart'; @@ -299,7 +299,7 @@ class CardCollectionState extends State { }); } - sky.Shader _createShader(Rect bounds) { + ui.Shader _createShader(Rect bounds) { return new LinearGradient( begin: Point.origin, end: new Point(0.0, bounds.height), diff --git a/examples/widgets/overlay_geometry.dart b/examples/widgets/overlay_geometry.dart index 872a2533f6..ffde8ff1fd 100644 --- a/examples/widgets/overlay_geometry.dart +++ b/examples/widgets/overlay_geometry.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; @@ -31,14 +31,14 @@ class Marker extends StatelessComponent { final double size; final MarkerType type; - void paintMarker(sky.Canvas canvas, _) { + void paintMarker(ui.Canvas canvas, _) { Paint paint = new Paint()..color = const Color(0x8000FF00); - paint.setStyle(sky.PaintingStyle.fill); + paint.setStyle(ui.PaintingStyle.fill); double r = size / 2.0; canvas.drawCircle(new Point(r, r), r, paint); paint.color = const Color(0xFFFFFFFF); - paint.setStyle(sky.PaintingStyle.stroke); + paint.setStyle(ui.PaintingStyle.stroke); paint.strokeWidth = 1.0; if (type == MarkerType.topLeft) { canvas.drawLine(new Point(r, r), new Point(r + r - 1.0, r), paint); @@ -103,7 +103,7 @@ class OverlayGeometryAppState extends State { }); } - void handlePointerDown(GlobalKey target, sky.PointerEvent event) { + void handlePointerDown(GlobalKey target, ui.PointerEvent event) { setState(() { markers[MarkerType.touch] = new Point(event.x, event.y); final RenderBox box = target.currentContext.findRenderObject(); diff --git a/examples/widgets/spinning_mixed.dart b/examples/widgets/spinning_mixed.dart index b59c6e3c74..3246c4c753 100644 --- a/examples/widgets/spinning_mixed.dart +++ b/examples/widgets/spinning_mixed.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'package:flutter/animation.dart'; import 'package:flutter/material.dart'; @@ -11,7 +11,7 @@ import 'package:flutter/rendering.dart'; import '../rendering/solid_color_box.dart'; // Solid colour, RenderObject version -void addFlexChildSolidColor(RenderFlex parent, sky.Color backgroundColor, { int flex: 0 }) { +void addFlexChildSolidColor(RenderFlex parent, ui.Color backgroundColor, { int flex: 0 }) { RenderSolidColorBox child = new RenderSolidColorBox(backgroundColor); parent.add(child); child.parentData.flex = flex; @@ -81,9 +81,9 @@ void main() { new RenderBoxToWidgetAdapter(proxy, builder); // adds itself to proxy RenderFlex flexRoot = new RenderFlex(direction: FlexDirection.vertical); - addFlexChildSolidColor(flexRoot, const sky.Color(0xFFFF00FF), flex: 1); + addFlexChildSolidColor(flexRoot, const ui.Color(0xFFFF00FF), flex: 1); flexRoot.add(proxy); - addFlexChildSolidColor(flexRoot, const sky.Color(0xFF0000FF), flex: 1); + addFlexChildSolidColor(flexRoot, const ui.Color(0xFF0000FF), flex: 1); transformBox = new RenderTransform(child: flexRoot, transform: new Matrix4.identity()); RenderPadding root = new RenderPadding(padding: new EdgeDims.all(80.0), child: transformBox); diff --git a/packages/flutter/lib/src/animation/scheduler.dart b/packages/flutter/lib/src/animation/scheduler.dart index 5b8b4b9aaa..064762ded6 100644 --- a/packages/flutter/lib/src/animation/scheduler.dart +++ b/packages/flutter/lib/src/animation/scheduler.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'dart:collection'; -import 'dart:ui' as sky; +import 'dart:ui' as ui; /// Slows down animations by this factor to help in development. double timeDilation = 1.0; @@ -20,7 +20,7 @@ typedef void SchedulerCallback(Duration timeStamp); class Scheduler { /// Requires clients to use the [scheduler] singleton Scheduler._() { - sky.view.setFrameCallback(beginFrame); + ui.view.setFrameCallback(beginFrame); } bool _haveScheduledVisualUpdate = false; @@ -88,7 +88,7 @@ class Scheduler { void ensureVisualUpdate() { if (_haveScheduledVisualUpdate) return; - sky.view.scheduleFrame(); + ui.view.scheduleFrame(); _haveScheduledVisualUpdate = true; } } diff --git a/packages/flutter/lib/src/animation/scroll_behavior.dart b/packages/flutter/lib/src/animation/scroll_behavior.dart index b5be81572c..23656e6c06 100644 --- a/packages/flutter/lib/src/animation/scroll_behavior.dart +++ b/packages/flutter/lib/src/animation/scroll_behavior.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'dart:math' as math; -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'package:newton/newton.dart'; @@ -109,11 +109,11 @@ Simulation _createFlingScrollSimulation(double position, double velocity, double // scrolling less than one logical pixel per frame. We're essentially // normalizing by the devicePixelRatio so that the threshold has the // same effect independent of the device's pixel density. - double endVelocity = 15.0 * sky.view.devicePixelRatio; + double endVelocity = 15.0 * ui.view.devicePixelRatio; // Similar to endVelocity. Stop scrolling when we're this close to // destiniation scroll offset. - double endDistance = 0.5 * sky.view.devicePixelRatio; + double endDistance = 0.5 * ui.view.devicePixelRatio; SpringDescription spring = new SpringDescription.withDampingRatio(mass: 1.0, springConstant: 170.0, ratio: 1.1); ScrollSimulation simulation = @@ -124,7 +124,7 @@ Simulation _createFlingScrollSimulation(double position, double velocity, double Simulation _createSnapScrollSimulation(double startOffset, double endOffset, double velocity) { double startVelocity = velocity * _kSecondsPerMillisecond; - double endVelocity = 15.0 * sky.view.devicePixelRatio * velocity.sign; + double endVelocity = 15.0 * ui.view.devicePixelRatio * velocity.sign; return new FrictionSimulation.through(startOffset, endOffset, startVelocity, endVelocity); } diff --git a/packages/flutter/lib/src/gestures/drag.dart b/packages/flutter/lib/src/gestures/drag.dart index b130441ffd..473b410c0c 100644 --- a/packages/flutter/lib/src/gestures/drag.dart +++ b/packages/flutter/lib/src/gestures/drag.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'arena.dart'; import 'recognizer.dart'; @@ -16,17 +16,17 @@ enum DragState { typedef void GestureDragStartCallback(); typedef void GestureDragUpdateCallback(double delta); -typedef void GestureDragEndCallback(sky.Offset velocity); +typedef void GestureDragEndCallback(ui.Offset velocity); typedef void GesturePanStartCallback(); -typedef void GesturePanUpdateCallback(sky.Offset delta); -typedef void GesturePanEndCallback(sky.Offset velocity); +typedef void GesturePanUpdateCallback(ui.Offset delta); +typedef void GesturePanEndCallback(ui.Offset velocity); typedef void _GesturePolymorphicUpdateCallback(T delta); -int _eventTime(sky.PointerEvent event) => (event.timeStamp * 1000.0).toInt(); // microseconds +int _eventTime(ui.PointerEvent event) => (event.timeStamp * 1000.0).toInt(); // microseconds -bool _isFlingGesture(sky.GestureVelocity velocity) { +bool _isFlingGesture(ui.GestureVelocity velocity) { double velocitySquared = velocity.x * velocity.x + velocity.y * velocity.y; return velocity.isValid && velocitySquared > kMinFlingVelocity * kMinFlingVelocity && @@ -45,12 +45,12 @@ abstract class _DragGestureRecognizer extends GestureRecogniz T _pendingDragDelta; T get _initialPendingDragDelta; - T _getDragDelta(sky.PointerEvent event); + T _getDragDelta(ui.PointerEvent event); bool get _hasSufficientPendingDragDeltaToAccept; - final sky.VelocityTracker _velocityTracker = new sky.VelocityTracker(); + final ui.VelocityTracker _velocityTracker = new ui.VelocityTracker(); - void addPointer(sky.PointerEvent event) { + void addPointer(ui.PointerEvent event) { startTrackingPointer(event.pointer); if (_state == DragState.ready) { _state = DragState.possible; @@ -58,7 +58,7 @@ abstract class _DragGestureRecognizer extends GestureRecogniz } } - void handleEvent(sky.PointerEvent event) { + void handleEvent(ui.PointerEvent event) { assert(_state != DragState.ready); if (event.type == 'pointermove') { _velocityTracker.addPosition(_eventTime(event), event.pointer, event.x, event.y); @@ -96,10 +96,10 @@ abstract class _DragGestureRecognizer extends GestureRecogniz bool wasAccepted = (_state == DragState.accepted); _state = DragState.ready; if (wasAccepted && onEnd != null) { - sky.GestureVelocity gestureVelocity = _velocityTracker.getVelocity(pointer); - sky.Offset velocity = sky.Offset.zero; + ui.GestureVelocity gestureVelocity = _velocityTracker.getVelocity(pointer); + ui.Offset velocity = ui.Offset.zero; if (_isFlingGesture(gestureVelocity)) - velocity = new sky.Offset(gestureVelocity.x, gestureVelocity.y); + velocity = new ui.Offset(gestureVelocity.x, gestureVelocity.y); onEnd(velocity); } _velocityTracker.reset(); @@ -120,7 +120,7 @@ class VerticalDragGestureRecognizer extends _DragGestureRecognizer { }) : super(router: router, onStart: onStart, onUpdate: onUpdate, onEnd: onEnd); double get _initialPendingDragDelta => 0.0; - double _getDragDelta(sky.PointerEvent event) => event.dy; + double _getDragDelta(ui.PointerEvent event) => event.dy; bool get _hasSufficientPendingDragDeltaToAccept => _pendingDragDelta.abs() > kTouchSlop; } @@ -133,11 +133,11 @@ class HorizontalDragGestureRecognizer extends _DragGestureRecognizer { }) : super(router: router, onStart: onStart, onUpdate: onUpdate, onEnd: onEnd); double get _initialPendingDragDelta => 0.0; - double _getDragDelta(sky.PointerEvent event) => event.dx; + double _getDragDelta(ui.PointerEvent event) => event.dx; bool get _hasSufficientPendingDragDeltaToAccept => _pendingDragDelta.abs() > kTouchSlop; } -class PanGestureRecognizer extends _DragGestureRecognizer { +class PanGestureRecognizer extends _DragGestureRecognizer { PanGestureRecognizer({ PointerRouter router, GesturePanStartCallback onStart, @@ -145,8 +145,8 @@ class PanGestureRecognizer extends _DragGestureRecognizer { GesturePanEndCallback onEnd }) : super(router: router, onStart: onStart, onUpdate: onUpdate, onEnd: onEnd); - sky.Offset get _initialPendingDragDelta => sky.Offset.zero; - sky.Offset _getDragDelta(sky.PointerEvent event) => new sky.Offset(event.dx, event.dy); + ui.Offset get _initialPendingDragDelta => ui.Offset.zero; + ui.Offset _getDragDelta(ui.PointerEvent event) => new ui.Offset(event.dx, event.dy); bool get _hasSufficientPendingDragDeltaToAccept { return _pendingDragDelta.distance > kPanSlop; } diff --git a/packages/flutter/lib/src/gestures/long_press.dart b/packages/flutter/lib/src/gestures/long_press.dart index 4ffd348223..4dd278601b 100644 --- a/packages/flutter/lib/src/gestures/long_press.dart +++ b/packages/flutter/lib/src/gestures/long_press.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'arena.dart'; import 'constants.dart'; @@ -22,7 +22,7 @@ class LongPressGestureRecognizer extends PrimaryPointerGestureRecognizer { onLongPress(); } - void handlePrimaryPointer(sky.PointerEvent event) { + void handlePrimaryPointer(ui.PointerEvent event) { if (event.type == 'pointerup') resolve(GestureDisposition.rejected); } diff --git a/packages/flutter/lib/src/gestures/pointer_router.dart b/packages/flutter/lib/src/gestures/pointer_router.dart index 6918b3dc80..d774bb1b5e 100644 --- a/packages/flutter/lib/src/gestures/pointer_router.dart +++ b/packages/flutter/lib/src/gestures/pointer_router.dart @@ -2,18 +2,18 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ui' as sky; +import 'dart:ui' as ui; -/// A callback that receives a [sky.PointerEvent] -typedef void PointerRoute(sky.PointerEvent event); +/// A callback that receives a [ui.PointerEvent] +typedef void PointerRoute(ui.PointerEvent event); -/// A routing table for [sky.PointerEvent] events. +/// A routing table for [ui.PointerEvent] events. class PointerRouter { final Map> _routeMap = new Map>(); /// Adds a route to the routing table /// - /// Whenever this object routes a [sky.PointerEvent] corresponding to + /// Whenever this object routes a [ui.PointerEvent] corresponding to /// pointer, call route. void addRoute(int pointer, PointerRoute route) { List routes = _routeMap.putIfAbsent(pointer, () => new List()); @@ -23,7 +23,7 @@ class PointerRouter { /// Removes a route from the routing table /// - /// No longer call route when routing a [sky.PointerEvent] corresponding to + /// No longer call route when routing a [ui.PointerEvent] corresponding to /// pointer. Requires that this route was previously added to the router. void removeRoute(int pointer, PointerRoute route) { assert(_routeMap.containsKey(pointer)); @@ -37,7 +37,7 @@ class PointerRouter { /// Call the routes registed for this pointer event. /// /// Calls the routes in the order in which they were added to the route. - void route(sky.PointerEvent event) { + void route(ui.PointerEvent event) { List routes = _routeMap[event.pointer]; if (routes == null) return; diff --git a/packages/flutter/lib/src/gestures/recognizer.dart b/packages/flutter/lib/src/gestures/recognizer.dart index 7c73f1988d..a2fca88a5f 100644 --- a/packages/flutter/lib/src/gestures/recognizer.dart +++ b/packages/flutter/lib/src/gestures/recognizer.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'dart:async'; -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'arena.dart'; import 'constants.dart'; @@ -22,9 +22,9 @@ abstract class GestureRecognizer extends GestureArenaMember { final Set _trackedPointers = new Set(); /// The primary entry point for users of this class. - void addPointer(sky.PointerEvent event); + void addPointer(ui.PointerEvent event); - void handleEvent(sky.PointerEvent event); + void handleEvent(ui.PointerEvent event); void acceptGesture(int pointer) { } void rejectGesture(int pointer) { } void didStopTrackingLastPointer(int pointer); @@ -58,7 +58,7 @@ abstract class GestureRecognizer extends GestureArenaMember { didStopTrackingLastPointer(pointer); } - void stopTrackingIfPointerNoLongerDown(sky.PointerEvent event) { + void stopTrackingIfPointerNoLongerDown(ui.PointerEvent event) { if (event.type == 'pointerup' || event.type == 'pointercancel') stopTrackingPointer(event.pointer); } @@ -71,8 +71,8 @@ enum GestureRecognizerState { defunct } -sky.Point _getPoint(sky.PointerEvent event) { - return new sky.Point(event.x, event.y); +ui.Point _getPoint(ui.PointerEvent event) { + return new ui.Point(event.x, event.y); } abstract class PrimaryPointerGestureRecognizer extends GestureRecognizer { @@ -83,10 +83,10 @@ abstract class PrimaryPointerGestureRecognizer extends GestureRecognizer { GestureRecognizerState state = GestureRecognizerState.ready; int primaryPointer; - sky.Point initialPosition; + ui.Point initialPosition; Timer _timer; - void addPointer(sky.PointerEvent event) { + void addPointer(ui.PointerEvent event) { startTrackingPointer(event.pointer); if (state == GestureRecognizerState.ready) { state = GestureRecognizerState.possible; @@ -97,7 +97,7 @@ abstract class PrimaryPointerGestureRecognizer extends GestureRecognizer { } } - void handleEvent(sky.PointerEvent event) { + void handleEvent(ui.PointerEvent event) { assert(state != GestureRecognizerState.ready); if (state == GestureRecognizerState.possible && event.pointer == primaryPointer) { // TODO(abarth): Maybe factor the slop handling out into a separate class? @@ -110,7 +110,7 @@ abstract class PrimaryPointerGestureRecognizer extends GestureRecognizer { } /// Override to provide behavior for the primary pointer when the gesture is still possible. - void handlePrimaryPointer(sky.PointerEvent event); + void handlePrimaryPointer(ui.PointerEvent event); /// Override to be notified with [deadline] is exceeded. /// @@ -143,8 +143,8 @@ abstract class PrimaryPointerGestureRecognizer extends GestureRecognizer { } } - double _getDistance(sky.PointerEvent event) { - sky.Offset offset = _getPoint(event) - initialPosition; + double _getDistance(ui.PointerEvent event) { + ui.Offset offset = _getPoint(event) - initialPosition; return offset.distance; } diff --git a/packages/flutter/lib/src/gestures/scale.dart b/packages/flutter/lib/src/gestures/scale.dart index dd0dfa094a..8898f6ec78 100644 --- a/packages/flutter/lib/src/gestures/scale.dart +++ b/packages/flutter/lib/src/gestures/scale.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'arena.dart'; import 'recognizer.dart'; @@ -15,8 +15,8 @@ enum ScaleState { started } -typedef void GestureScaleStartCallback(sky.Point focalPoint); -typedef void GestureScaleUpdateCallback(double scale, sky.Point focalPoint); +typedef void GestureScaleStartCallback(ui.Point focalPoint); +typedef void GestureScaleUpdateCallback(double scale, ui.Point focalPoint); typedef void GestureScaleEndCallback(); class ScaleGestureRecognizer extends GestureRecognizer { @@ -31,21 +31,21 @@ class ScaleGestureRecognizer extends GestureRecognizer { double _initialSpan; double _currentSpan; - Map _pointerLocations; + Map _pointerLocations; double get _scaleFactor => _initialSpan > 0.0 ? _currentSpan / _initialSpan : 1.0; - void addPointer(sky.PointerEvent event) { + void addPointer(ui.PointerEvent event) { startTrackingPointer(event.pointer); if (_state == ScaleState.ready) { _state = ScaleState.possible; _initialSpan = 0.0; _currentSpan = 0.0; - _pointerLocations = new Map(); + _pointerLocations = new Map(); } } - void handleEvent(sky.PointerEvent event) { + void handleEvent(ui.PointerEvent event) { assert(_state != ScaleState.ready); bool configChanged = false; switch(event.type) { @@ -55,10 +55,10 @@ class ScaleGestureRecognizer extends GestureRecognizer { break; case 'pointerdown': configChanged = true; - _pointerLocations[event.pointer] = new sky.Point(event.x, event.y); + _pointerLocations[event.pointer] = new ui.Point(event.x, event.y); break; case 'pointermove': - _pointerLocations[event.pointer] = new sky.Point(event.x, event.y); + _pointerLocations[event.pointer] = new ui.Point(event.x, event.y); break; } @@ -71,10 +71,10 @@ class ScaleGestureRecognizer extends GestureRecognizer { int count = _pointerLocations.keys.length; // Compute the focal point - sky.Point focalPoint = sky.Point.origin; + ui.Point focalPoint = ui.Point.origin; for (int pointer in _pointerLocations.keys) focalPoint += _pointerLocations[pointer].toOffset(); - focalPoint = new sky.Point(focalPoint.x / count, focalPoint.y / count); + focalPoint = new ui.Point(focalPoint.x / count, focalPoint.y / count); // Span is the average deviation from focal point double totalDeviation = 0.0; diff --git a/packages/flutter/lib/src/gestures/show_press.dart b/packages/flutter/lib/src/gestures/show_press.dart index 754aaa2ea1..d3602c2f69 100644 --- a/packages/flutter/lib/src/gestures/show_press.dart +++ b/packages/flutter/lib/src/gestures/show_press.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'arena.dart'; import 'constants.dart'; @@ -23,7 +23,7 @@ class ShowPressGestureRecognizer extends PrimaryPointerGestureRecognizer { onShowPress(); } - void handlePrimaryPointer(sky.PointerEvent event) { + void handlePrimaryPointer(ui.PointerEvent event) { if (event.type == 'pointerup') resolve(GestureDisposition.rejected); } diff --git a/packages/flutter/lib/src/gestures/tap.dart b/packages/flutter/lib/src/gestures/tap.dart index 0c32edadbd..5d028a842b 100644 --- a/packages/flutter/lib/src/gestures/tap.dart +++ b/packages/flutter/lib/src/gestures/tap.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'arena.dart'; import 'recognizer.dart'; @@ -17,7 +17,7 @@ class TapGestureRecognizer extends PrimaryPointerGestureRecognizer { GestureTapCallback onTapDown; GestureTapCallback onTapCancel; - void handlePrimaryPointer(sky.PointerEvent event) { + void handlePrimaryPointer(ui.PointerEvent event) { if (event.type == 'pointerdown') { if (onTapDown != null) onTapDown(); diff --git a/packages/flutter/lib/src/material/checkbox.dart b/packages/flutter/lib/src/material/checkbox.dart index 1c42cf32ef..df7ee5ce57 100644 --- a/packages/flutter/lib/src/material/checkbox.dart +++ b/packages/flutter/lib/src/material/checkbox.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'package:flutter/rendering.dart'; import 'package:flutter/widgets.dart'; @@ -12,8 +12,8 @@ import 'theme.dart'; export 'package:flutter/rendering.dart' show ValueChanged; const double _kMidpoint = 0.5; -const sky.Color _kLightUncheckedColor = const sky.Color(0x8A000000); -const sky.Color _kDarkUncheckedColor = const sky.Color(0xB2FFFFFF); +const ui.Color _kLightUncheckedColor = const ui.Color(0x8A000000); +const ui.Color _kDarkUncheckedColor = const ui.Color(0xB2FFFFFF); const double _kEdgeSize = 18.0; const double _kEdgeRadius = 1.0; const double _kStrokeWidth = 2.0; @@ -126,7 +126,7 @@ class _RenderCheckbox extends RenderToggleable { void paint(PaintingContext context, Offset offset) { final PaintingCanvas canvas = context.canvas; // Choose a color between grey and the theme color - sky.Paint paint = new sky.Paint() + ui.Paint paint = new ui.Paint() ..strokeWidth = _kStrokeWidth ..color = uncheckedColor; @@ -134,25 +134,25 @@ class _RenderCheckbox extends RenderToggleable { // Because we have a stroke size of 2, we should have a minimum 1.0 inset. double inset = 2.0 - (position - _kMidpoint).abs() * 2.0; double rectSize = _kEdgeSize - inset * _kStrokeWidth; - sky.Rect rect = - new sky.Rect.fromLTWH(offset.dx + inset, offset.dy + inset, rectSize, rectSize); + ui.Rect rect = + new ui.Rect.fromLTWH(offset.dx + inset, offset.dy + inset, rectSize, rectSize); // Create an inner rectangle to cover inside of rectangle. This is needed to avoid // painting artefacts caused by overlayed paintings. - sky.Rect innerRect = rect.deflate(1.0); - sky.RRect rrect = new sky.RRect() + ui.Rect innerRect = rect.deflate(1.0); + ui.RRect rrect = new ui.RRect() ..setRectXY(rect, _kEdgeRadius, _kEdgeRadius); // Outline of the empty rrect - paint.setStyle(sky.PaintingStyle.stroke); + paint.setStyle(ui.PaintingStyle.stroke); canvas.drawRRect(rrect, paint); // Radial gradient that changes size if (position > 0) { - paint.setStyle(sky.PaintingStyle.fill); - paint.setShader(new sky.Gradient.radial( + paint.setStyle(ui.PaintingStyle.fill); + paint.setShader(new ui.Gradient.radial( new Point(_kEdgeSize / 2.0, _kEdgeSize / 2.0), _kEdgeSize * (_kMidpoint - position) * 8.0, [ - const sky.Color(0x00000000), + const ui.Color(0x00000000), uncheckedColor ])); canvas.drawRect(innerRect, paint); @@ -164,22 +164,22 @@ class _RenderCheckbox extends RenderToggleable { // First draw a rounded rect outline then fill inner rectangle with accent color. paint.color = new Color.fromARGB((t * 255).floor(), _accentColor.red, _accentColor.green, _accentColor.blue); - paint.setStyle(sky.PaintingStyle.stroke); + paint.setStyle(ui.PaintingStyle.stroke); canvas.drawRRect(rrect, paint); - paint.setStyle(sky.PaintingStyle.fill); + paint.setStyle(ui.PaintingStyle.fill); canvas.drawRect(innerRect, paint); // White inner check - paint.color = const sky.Color(0xFFFFFFFF); - paint.setStyle(sky.PaintingStyle.stroke); - sky.Path path = new sky.Path(); - sky.Point start = new sky.Point(_kEdgeSize * 0.15, _kEdgeSize * 0.45); - sky.Point mid = new sky.Point(_kEdgeSize * 0.4, _kEdgeSize * 0.7); - sky.Point end = new sky.Point(_kEdgeSize * 0.85, _kEdgeSize * 0.25); + paint.color = const ui.Color(0xFFFFFFFF); + paint.setStyle(ui.PaintingStyle.stroke); + ui.Path path = new ui.Path(); + ui.Point start = new ui.Point(_kEdgeSize * 0.15, _kEdgeSize * 0.45); + ui.Point mid = new ui.Point(_kEdgeSize * 0.4, _kEdgeSize * 0.7); + ui.Point end = new ui.Point(_kEdgeSize * 0.85, _kEdgeSize * 0.25); Point lerp(Point p1, Point p2, double t) => new Point(p1.x * (1.0 - t) + p2.x * t, p1.y * (1.0 - t) + p2.y * t); - sky.Point drawStart = lerp(start, mid, 1.0 - t); - sky.Point drawEnd = lerp(mid, end, t); + ui.Point drawStart = lerp(start, mid, 1.0 - t); + ui.Point drawEnd = lerp(mid, end, t); path.moveTo(offset.dx + drawStart.x, offset.dy + drawStart.y); path.lineTo(offset.dx + mid.x, offset.dy + mid.y); path.lineTo(offset.dx + drawEnd.x, offset.dy + drawEnd.y); diff --git a/packages/flutter/lib/src/material/drawer_item.dart b/packages/flutter/lib/src/material/drawer_item.dart index c5659c5910..6723b15f1e 100644 --- a/packages/flutter/lib/src/material/drawer_item.dart +++ b/packages/flutter/lib/src/material/drawer_item.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'package:flutter/gestures.dart'; import 'package:flutter/painting.dart'; @@ -49,10 +49,10 @@ class _DrawerItemState extends State { return Colors.transparent; } - sky.ColorFilter _getColorFilter(ThemeData themeData) { + ui.ColorFilter _getColorFilter(ThemeData themeData) { if (config.selected) - return new sky.ColorFilter.mode(themeData.primaryColor, sky.TransferMode.srcATop); - return new sky.ColorFilter.mode(const Color(0x73000000), sky.TransferMode.dstIn); + return new ui.ColorFilter.mode(themeData.primaryColor, ui.TransferMode.srcATop); + return new ui.ColorFilter.mode(const Color(0x73000000), ui.TransferMode.dstIn); } Widget build(BuildContext context) { diff --git a/packages/flutter/lib/src/material/icon.dart b/packages/flutter/lib/src/material/icon.dart index d991cd43d4..223dc78de5 100644 --- a/packages/flutter/lib/src/material/icon.dart +++ b/packages/flutter/lib/src/material/icon.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; @@ -62,7 +62,7 @@ class Icon extends StatelessComponent { final int size; final String type; final IconThemeColor color; - final sky.ColorFilter colorFilter; + final ui.ColorFilter colorFilter; String _getColorSuffix(BuildContext context) { IconThemeColor iconThemeColor = color; diff --git a/packages/flutter/lib/src/material/icon_button.dart b/packages/flutter/lib/src/material/icon_button.dart index 292bc823e5..7e8abf6334 100644 --- a/packages/flutter/lib/src/material/icon_button.dart +++ b/packages/flutter/lib/src/material/icon_button.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'package:flutter/gestures.dart'; import 'package:flutter/widgets.dart'; @@ -20,7 +20,7 @@ class IconButton extends StatelessComponent { final String icon; final IconThemeColor color; - final sky.ColorFilter colorFilter; + final ui.ColorFilter colorFilter; final GestureTapCallback onPressed; Widget build(BuildContext context) { diff --git a/packages/flutter/lib/src/material/ink_well.dart b/packages/flutter/lib/src/material/ink_well.dart index 9bb4feddbc..4780f7579d 100644 --- a/packages/flutter/lib/src/material/ink_well.dart +++ b/packages/flutter/lib/src/material/ink_well.dart @@ -4,7 +4,7 @@ import 'dart:async'; import 'dart:math' as math; -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'package:flutter/animation.dart'; import 'package:flutter/gestures.dart'; @@ -91,7 +91,7 @@ class _InkSplash { void paint(PaintingCanvas canvas) { int opacity = (_kSplashInitialOpacity * (1.1 - (_radius.value / _targetRadius))).floor(); - sky.Paint paint = new sky.Paint()..color = new sky.Color(opacity << 24); + ui.Paint paint = new ui.Paint()..color = new ui.Color(opacity << 24); double radius = _pinnedRadius == null ? _radius.value : _pinnedRadius; canvas.drawCircle(position, radius, paint); } @@ -137,7 +137,7 @@ class _RenderInkWell extends RenderProxyBox { TapGestureRecognizer _tap; LongPressGestureRecognizer _longPress; - void handleEvent(sky.Event event, BoxHitTestEntry entry) { + void handleEvent(ui.Event event, BoxHitTestEntry entry) { if (event.type == 'pointerdown' && (_tap != null || _longPress != null)) { _tap?.addPointer(event); _longPress?.addPointer(event); diff --git a/packages/flutter/lib/src/material/material_app.dart b/packages/flutter/lib/src/material/material_app.dart index afa81b9a28..06fa88f3cf 100644 --- a/packages/flutter/lib/src/material/material_app.dart +++ b/packages/flutter/lib/src/material/material_app.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'package:flutter/painting.dart'; import 'package:flutter/services.dart'; @@ -56,7 +56,7 @@ class _MaterialAppState extends State { super.dispose(); } - void _backHandler(sky.Event event) { + void _backHandler(ui.Event event) { assert(mounted); if (event.type == 'back') { NavigatorState navigator = _navigator.currentState; diff --git a/packages/flutter/lib/src/material/popup_menu.dart b/packages/flutter/lib/src/material/popup_menu.dart index 750d01dcce..65bf342b09 100644 --- a/packages/flutter/lib/src/material/popup_menu.dart +++ b/packages/flutter/lib/src/material/popup_menu.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'dart:async'; -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'package:flutter/animation.dart'; import 'package:flutter/painting.dart'; @@ -75,7 +75,7 @@ class PopupMenu extends StatelessComponent { variables: [width, height], builder: (BuildContext context) { return new CustomPaint( - callback: (sky.Canvas canvas, Size size) { + callback: (ui.Canvas canvas, Size size) { double widthValue = width.value * size.width; double heightValue = height.value * size.height; painter.paint(canvas, new Rect.fromLTWH(size.width - widthValue, 0.0, widthValue, heightValue)); diff --git a/packages/flutter/lib/src/material/progress_indicator.dart b/packages/flutter/lib/src/material/progress_indicator.dart index c7d0e8c39f..46d31717a2 100644 --- a/packages/flutter/lib/src/material/progress_indicator.dart +++ b/packages/flutter/lib/src/material/progress_indicator.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'dart:math' as math; -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'package:flutter/animation.dart'; import 'package:flutter/widgets.dart'; @@ -76,10 +76,10 @@ class LinearProgressIndicator extends ProgressIndicator { double bufferValue }) : super(key: key, value: value, bufferValue: bufferValue); - void _paint(BuildContext context, double performanceValue, sky.Canvas canvas, Size size) { + void _paint(BuildContext context, double performanceValue, ui.Canvas canvas, Size size) { Paint paint = new Paint() ..color = _getBackgroundColor(context) - ..setStyle(sky.PaintingStyle.fill); + ..setStyle(ui.PaintingStyle.fill); canvas.drawRect(Point.origin & size, paint); paint.color = _getValueColor(context); @@ -103,7 +103,7 @@ class LinearProgressIndicator extends ProgressIndicator { ), child: new CustomPaint( token: _getCustomPaintToken(performanceValue), - callback: (sky.Canvas canvas, Size size) { + callback: (ui.Canvas canvas, Size size) { _paint(context, performanceValue, canvas, size); } ) @@ -124,15 +124,15 @@ class CircularProgressIndicator extends ProgressIndicator { double bufferValue }) : super(key: key, value: value, bufferValue: bufferValue); - void _paint(BuildContext context, double performanceValue, sky.Canvas canvas, Size size) { + void _paint(BuildContext context, double performanceValue, ui.Canvas canvas, Size size) { Paint paint = new Paint() ..color = _getValueColor(context) ..strokeWidth = _kCircularProgressIndicatorStrokeWidth - ..setStyle(sky.PaintingStyle.stroke); + ..setStyle(ui.PaintingStyle.stroke); if (value != null) { double angle = value.clamp(0.0, 1.0) * _kSweep; - sky.Path path = new sky.Path() + ui.Path path = new ui.Path() ..arcTo(Point.origin & size, _kStartAngle, angle, false); canvas.drawPath(path, paint); } else { @@ -140,7 +140,7 @@ class CircularProgressIndicator extends ProgressIndicator { double endAngle = startAngle + _kTwoPI * 0.75; double arcAngle = startAngle.clamp(0.0, _kTwoPI); double arcSweep = endAngle.clamp(0.0, _kTwoPI) - arcAngle; - sky.Path path = new sky.Path() + ui.Path path = new ui.Path() ..arcTo(Point.origin & size, _kStartAngle + arcAngle, arcSweep, false); canvas.drawPath(path, paint); } @@ -154,7 +154,7 @@ class CircularProgressIndicator extends ProgressIndicator { ), child: new CustomPaint( token: _getCustomPaintToken(performanceValue), - callback: (sky.Canvas canvas, Size size) { + callback: (ui.Canvas canvas, Size size) { _paint(context, performanceValue, canvas, size); } ) diff --git a/packages/flutter/lib/src/material/radial_reaction.dart b/packages/flutter/lib/src/material/radial_reaction.dart index 409cd647c1..35538fa79f 100644 --- a/packages/flutter/lib/src/material/radial_reaction.dart +++ b/packages/flutter/lib/src/material/radial_reaction.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'dart:async'; -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'dart:ui' show Point, Offset, Color, Paint; import 'package:flutter/animation.dart'; @@ -82,7 +82,7 @@ class RadialReaction { final Paint _innerPaint = new Paint(); /// Paint the reaction onto the given canvas at the given offset - void paint(sky.Canvas canvas, Offset offset) { + void paint(ui.Canvas canvas, Offset offset) { _outerPaint.color = _kOuterColor.withAlpha(_roundOpacity(_outerOpacity.value * _fade.value)); canvas.drawCircle(center + offset, radius, _outerPaint); diff --git a/packages/flutter/lib/src/material/radio.dart b/packages/flutter/lib/src/material/radio.dart index e44f809897..e2e65d80d3 100644 --- a/packages/flutter/lib/src/material/radio.dart +++ b/packages/flutter/lib/src/material/radio.dart @@ -2,14 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'package:flutter/widgets.dart'; import 'theme.dart'; -const sky.Color _kLightOffColor = const sky.Color(0x8A000000); -const sky.Color _kDarkOffColor = const sky.Color(0xB2FFFFFF); +const ui.Color _kLightOffColor = const ui.Color(0x8A000000); +const ui.Color _kDarkOffColor = const ui.Color(0xB2FFFFFF); typedef void RadioValueChanged(Object value); @@ -45,18 +45,18 @@ class Radio extends StatelessComponent { width: kDiameter, height: kDiameter, child: new CustomPaint( - callback: (sky.Canvas canvas, Size size) { + callback: (ui.Canvas canvas, Size size) { Paint paint = new Paint()..color = _getColor(context); // Draw the outer circle - paint.setStyle(sky.PaintingStyle.stroke); + paint.setStyle(ui.PaintingStyle.stroke); paint.strokeWidth = 2.0; canvas.drawCircle(const Point(kOuterRadius, kOuterRadius), kOuterRadius, paint); // Draw the inner circle if (value == groupValue) { - paint.setStyle(sky.PaintingStyle.fill); + paint.setStyle(ui.PaintingStyle.fill); canvas.drawCircle(const Point(kOuterRadius, kOuterRadius), kInnerRadius, paint); } } diff --git a/packages/flutter/lib/src/material/scaffold.dart b/packages/flutter/lib/src/material/scaffold.dart index 55a7af32b1..a33e754c35 100644 --- a/packages/flutter/lib/src/material/scaffold.dart +++ b/packages/flutter/lib/src/material/scaffold.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'package:flutter/rendering.dart'; import 'package:flutter/widgets.dart'; @@ -28,7 +28,7 @@ class Scaffold extends StatelessComponent { Widget build(BuildContext context) { double toolBarHeight = 0.0; if (toolBar != null) - toolBarHeight = kToolBarHeight + sky.view.paddingTop; + toolBarHeight = kToolBarHeight + ui.view.paddingTop; double statusBarHeight = 0.0; if (statusBar != null) diff --git a/packages/flutter/lib/src/material/switch.dart b/packages/flutter/lib/src/material/switch.dart index 5bf2194541..9b6573dd04 100644 --- a/packages/flutter/lib/src/material/switch.dart +++ b/packages/flutter/lib/src/material/switch.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'dart:async'; -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'package:flutter/painting.dart'; import 'package:flutter/rendering.dart'; @@ -15,8 +15,8 @@ import 'theme.dart'; export 'package:flutter/rendering.dart' show ValueChanged; -const sky.Color _kThumbOffColor = const sky.Color(0xFFFAFAFA); -const sky.Color _kTrackOffColor = const sky.Color(0x42000000); +const ui.Color _kThumbOffColor = const ui.Color(0xFFFAFAFA); +const ui.Color _kTrackOffColor = const ui.Color(0x42000000); const double _kSwitchWidth = 35.0; const double _kThumbRadius = 10.0; const double _kSwitchHeight = _kThumbRadius * 2.0; @@ -82,8 +82,8 @@ class _RenderSwitch extends RenderToggleable { RadialReaction _radialReaction; - void handleEvent(sky.Event event, BoxHitTestEntry entry) { - if (event is sky.PointerEvent) { + void handleEvent(ui.Event event, BoxHitTestEntry entry) { + if (event is ui.PointerEvent) { if (event.type == 'pointerdown') _showRadialReaction(entry.localPosition); else if (event.type == 'pointerup') @@ -112,21 +112,21 @@ class _RenderSwitch extends RenderToggleable { void paint(PaintingContext context, Offset offset) { final PaintingCanvas canvas = context.canvas; - sky.Color thumbColor = _kThumbOffColor; - sky.Color trackColor = _kTrackOffColor; + ui.Color thumbColor = _kThumbOffColor; + ui.Color trackColor = _kTrackOffColor; if (value) { thumbColor = _thumbColor; - trackColor = new sky.Color(_thumbColor.value & 0x80FFFFFF); + trackColor = new ui.Color(_thumbColor.value & 0x80FFFFFF); } // Draw the track rrect - sky.Paint paint = new sky.Paint() + ui.Paint paint = new ui.Paint() ..color = trackColor - ..style = sky.PaintingStyle.fill; - sky.Rect rect = new sky.Rect.fromLTWH(offset.dx, + ..style = ui.PaintingStyle.fill; + ui.Rect rect = new ui.Rect.fromLTWH(offset.dx, offset.dy + _kSwitchHeight / 2.0 - _kTrackHeight / 2.0, _kTrackWidth, _kTrackHeight); - sky.RRect rrect = new sky.RRect() + ui.RRect rrect = new ui.RRect() ..setRectXY(rect, _kTrackRadius, _kTrackRadius); canvas.drawRRect(rrect, paint); diff --git a/packages/flutter/lib/src/material/tabs.dart b/packages/flutter/lib/src/material/tabs.dart index 543aebddbd..982efcf7ea 100644 --- a/packages/flutter/lib/src/material/tabs.dart +++ b/packages/flutter/lib/src/material/tabs.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'dart:math' as math; -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'package:newton/newton.dart'; import 'package:flutter/animation.dart'; @@ -312,7 +312,7 @@ class Tab extends StatelessComponent { Widget _buildLabelIcon() { assert(label.icon != null); Color iconColor = selected ? selectedColor : color; - sky.ColorFilter filter = new sky.ColorFilter.mode(iconColor, sky.TransferMode.srcATop); + ui.ColorFilter filter = new ui.ColorFilter.mode(iconColor, ui.TransferMode.srcATop); return new Icon(type: label.icon, size: _kTabIconSize, colorFilter: filter); } diff --git a/packages/flutter/lib/src/painting/box_painter.dart b/packages/flutter/lib/src/painting/box_painter.dart index 110aa4421e..959394f266 100644 --- a/packages/flutter/lib/src/painting/box_painter.dart +++ b/packages/flutter/lib/src/painting/box_painter.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'dart:math' as math; -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'dart:ui' show Point, Offset, Size, Rect, Color, Paint, Path; import 'package:flutter/services.dart'; @@ -121,10 +121,10 @@ class EdgeDims { if (b == null) return a * (1.0 - t); return new EdgeDims.TRBL( - sky.lerpDouble(a.top, b.top, t), - sky.lerpDouble(a.right, b.right, t), - sky.lerpDouble(a.bottom, b.bottom, t), - sky.lerpDouble(a.left, b.left, t) + ui.lerpDouble(a.top, b.top, t), + ui.lerpDouble(a.right, b.right, t), + ui.lerpDouble(a.bottom, b.bottom, t), + ui.lerpDouble(a.left, b.left, t) ); } @@ -257,7 +257,7 @@ class BoxShadow { return new BoxShadow( color: Color.lerp(a.color, b.color, t), offset: Offset.lerp(a.offset, b.offset, t), - blur: sky.lerpDouble(a.blur, b.blur, t) + blur: ui.lerpDouble(a.blur, b.blur, t) ); } @@ -287,7 +287,7 @@ class BoxShadow { /// A 2D gradient abstract class Gradient { - sky.Shader createShader(); + ui.Shader createShader(); } /// A 2D linear gradient @@ -297,7 +297,7 @@ class LinearGradient extends Gradient { this.end, this.colors, this.stops, - this.tileMode: sky.TileMode.clamp + this.tileMode: ui.TileMode.clamp }) { assert(colors.length == stops.length); } @@ -319,10 +319,10 @@ class LinearGradient extends Gradient { final List stops; /// How this gradient should tile the plane - final sky.TileMode tileMode; + final ui.TileMode tileMode; - sky.Shader createShader() { - return new sky.Gradient.linear([begin, end], this.colors, + ui.Shader createShader() { + return new ui.Gradient.linear([begin, end], this.colors, this.stops, this.tileMode); } @@ -338,7 +338,7 @@ class RadialGradient extends Gradient { this.radius, this.colors, this.stops, - this.tileMode: sky.TileMode.clamp + this.tileMode: ui.TileMode.clamp }); /// The center of the gradient @@ -361,10 +361,10 @@ class RadialGradient extends Gradient { final List stops; /// How this gradient should tile the plane - final sky.TileMode tileMode; + final ui.TileMode tileMode; - sky.Shader createShader() { - return new sky.Gradient.radial(center, radius, colors, stops, tileMode); + ui.Shader createShader() { + return new ui.Gradient.radial(center, radius, colors, stops, tileMode); } String toString() { @@ -409,10 +409,10 @@ enum ImageRepeat { /// Paint an image into the given rectangle in the canvas void paintImage({ - sky.Canvas canvas, + ui.Canvas canvas, Rect rect, - sky.Image image, - sky.ColorFilter colorFilter, + ui.Image image, + ui.ColorFilter colorFilter, fit: ImageFit.scaleDown, repeat: ImageRepeat.noRepeat, double positionX: 0.5, @@ -476,7 +476,7 @@ class BackgroundImage { final ImageRepeat repeat; /// A color filter to apply to the background image before painting it - final sky.ColorFilter colorFilter; + final ui.ColorFilter colorFilter; BackgroundImage({ ImageResource image, @@ -485,9 +485,9 @@ class BackgroundImage { this.colorFilter }) : _imageResource = image; - sky.Image _image; + ui.Image _image; /// The image to be painted into the background - sky.Image get image => _image; + ui.Image get image => _image; ImageResource _imageResource; @@ -513,7 +513,7 @@ class BackgroundImage { _imageResource.removeListener(_handleImageChanged); } - void _handleImageChanged(sky.Image resolvedImage) { + void _handleImageChanged(ui.Image resolvedImage) { if (resolvedImage == null) return; _image = resolvedImage; @@ -582,7 +582,7 @@ class BoxDecoration { backgroundColor: Color.lerp(null, backgroundColor, factor), backgroundImage: backgroundImage, border: border, - borderRadius: sky.lerpDouble(null, borderRadius, factor), + borderRadius: ui.lerpDouble(null, borderRadius, factor), boxShadow: BoxShadow.lerpList(null, boxShadow, factor), gradient: gradient, shape: shape @@ -604,7 +604,7 @@ class BoxDecoration { backgroundColor: Color.lerp(a.backgroundColor, b.backgroundColor, t), backgroundImage: b.backgroundImage, border: b.border, - borderRadius: sky.lerpDouble(a.borderRadius, b.borderRadius, t), + borderRadius: ui.lerpDouble(a.borderRadius, b.borderRadius, t), boxShadow: BoxShadow.lerpList(a.boxShadow, b.boxShadow, t), gradient: b.gradient, shape: b.shape @@ -697,11 +697,11 @@ class BoxPainter { double shortestSide = rect.shortestSide; // In principle, we should use shortestSide / 2.0, but we don't want to // run into floating point rounding errors. Instead, we just use - // shortestSide and let sky.Canvas do any remaining clamping. + // shortestSide and let ui.Canvas do any remaining clamping. return _decoration.borderRadius > shortestSide ? shortestSide : _decoration.borderRadius; } - void _paintBackgroundColor(sky.Canvas canvas, Rect rect) { + void _paintBackgroundColor(ui.Canvas canvas, Rect rect) { if (_decoration.backgroundColor != null || _decoration.boxShadow != null || _decoration.gradient != null) { @@ -717,18 +717,18 @@ class BoxPainter { canvas.drawRect(rect, _backgroundPaint); } else { double radius = _getEffectiveBorderRadius(rect); - canvas.drawRRect(new sky.RRect()..setRectXY(rect, radius, radius), _backgroundPaint); + canvas.drawRRect(new ui.RRect()..setRectXY(rect, radius, radius), _backgroundPaint); } break; } } } - void _paintBackgroundImage(sky.Canvas canvas, Rect rect) { + void _paintBackgroundImage(ui.Canvas canvas, Rect rect) { final BackgroundImage backgroundImage = _decoration.backgroundImage; if (backgroundImage == null) return; - sky.Image image = backgroundImage.image; + ui.Image image = backgroundImage.image; if (image == null) return; paintImage( @@ -741,7 +741,7 @@ class BoxPainter { ); } - void _paintBorder(sky.Canvas canvas, Rect rect) { + void _paintBorder(ui.Canvas canvas, Rect rect) { if (_decoration.border == null) return; @@ -804,19 +804,19 @@ class BoxPainter { canvas.drawPath(path, paint); } - void _paintBorderWithRadius(sky.Canvas canvas, Rect rect) { + void _paintBorderWithRadius(ui.Canvas canvas, Rect rect) { assert(_hasUniformBorder); assert(_decoration.shape == Shape.rectangle); Color color = _decoration.border.top.color; double width = _decoration.border.top.width; double radius = _getEffectiveBorderRadius(rect); - sky.RRect outer = new sky.RRect()..setRectXY(rect, radius, radius); - sky.RRect inner = new sky.RRect()..setRectXY(rect.deflate(width), radius - width, radius - width); + ui.RRect outer = new ui.RRect()..setRectXY(rect, radius, radius); + ui.RRect inner = new ui.RRect()..setRectXY(rect.deflate(width), radius - width, radius - width); canvas.drawDRRect(outer, inner, new Paint()..color = color); } - void _paintBorderWithCircle(sky.Canvas canvas, Rect rect) { + void _paintBorderWithCircle(ui.Canvas canvas, Rect rect) { assert(_hasUniformBorder); assert(_decoration.shape == Shape.circle); assert(_decoration.borderRadius == null); @@ -827,14 +827,14 @@ class BoxPainter { Paint paint = new Paint() ..color = _decoration.border.top.color ..strokeWidth = width - ..setStyle(sky.PaintingStyle.stroke); + ..setStyle(ui.PaintingStyle.stroke); Point center = rect.center; double radius = (rect.shortestSide - width) / 2.0; canvas.drawCircle(center, radius, paint); } /// Paint the box decoration into the given location on the given canvas - void paint(sky.Canvas canvas, Rect rect) { + void paint(ui.Canvas canvas, Rect rect) { _paintBackgroundColor(canvas, rect); _paintBackgroundImage(canvas, rect); _paintBorder(canvas, rect); diff --git a/packages/flutter/lib/src/painting/shadows.dart b/packages/flutter/lib/src/painting/shadows.dart index b50341c9a7..d0ad34638e 100644 --- a/packages/flutter/lib/src/painting/shadows.dart +++ b/packages/flutter/lib/src/painting/shadows.dart @@ -2,27 +2,27 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ui' as sky; +import 'dart:ui' as ui; -/// A helper class to build a [sky.DrawLooper] for drawing shadows +/// A helper class to build a [ui.DrawLooper] for drawing shadows class ShadowDrawLooperBuilder { - var builder_ = new sky.LayerDrawLooperBuilder(); + var builder_ = new ui.LayerDrawLooperBuilder(); /// Add a shadow with the given parameters - void addShadow(sky.Offset offset, sky.Color color, double blur) { + void addShadow(ui.Offset offset, ui.Color color, double blur) { builder_.addLayerOnTop( - new sky.DrawLooperLayerInfo() - ..setPaintBits(sky.PaintBits.all) + new ui.DrawLooperLayerInfo() + ..setPaintBits(ui.PaintBits.all) ..setOffset(offset) - ..setColorMode(sky.TransferMode.src), - new sky.Paint() + ..setColorMode(ui.TransferMode.src), + new ui.Paint() ..color = color - ..maskFilter = new sky.MaskFilter.blur(sky.BlurStyle.normal, blur)); + ..maskFilter = new ui.MaskFilter.blur(ui.BlurStyle.normal, blur)); } /// Returns the draw looper built for the added shadows - sky.DrawLooper build() { - builder_.addLayerOnTop(new sky.DrawLooperLayerInfo(), new sky.Paint()); + ui.DrawLooper build() { + builder_.addLayerOnTop(new ui.DrawLooperLayerInfo(), new ui.Paint()); return builder_.build(); } } diff --git a/packages/flutter/lib/src/painting/text_painter.dart b/packages/flutter/lib/src/painting/text_painter.dart index cf9ac739d2..733a42b8b8 100644 --- a/packages/flutter/lib/src/painting/text_painter.dart +++ b/packages/flutter/lib/src/painting/text_painter.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'text_style.dart'; @@ -11,14 +11,14 @@ export 'text_style.dart'; /// An immutable span of text abstract class TextSpan { // This class must be immutable, because we won't notice when it changes - sky.Node _toDOM(sky.Document owner); + ui.Node _toDOM(ui.Document owner); String toString([String prefix = '']); - void _applyStyleToContainer(sky.Element container) { + void _applyStyleToContainer(ui.Element container) { } - void build(sky.ParagraphBuilder builder); - sky.ParagraphStyle get paragraphStyle => null; + void build(ui.ParagraphBuilder builder); + ui.ParagraphStyle get paragraphStyle => null; } /// An immutable span of unstyled text @@ -30,11 +30,11 @@ class PlainTextSpan extends TextSpan { /// The text contained in the span final String text; - sky.Node _toDOM(sky.Document owner) { + ui.Node _toDOM(ui.Document owner) { return owner.createText(text); } - void build(sky.ParagraphBuilder builder) { + void build(ui.ParagraphBuilder builder) { builder.addText(text); } @@ -57,8 +57,8 @@ class StyledTextSpan extends TextSpan { /// The children to which the style is applied final List children; - sky.Node _toDOM(sky.Document owner) { - sky.Element parent = owner.createElement('t'); + ui.Node _toDOM(ui.Document owner) { + ui.Element parent = owner.createElement('t'); style.applyToCSSStyle(parent.style); for (TextSpan child in children) { parent.appendChild(child._toDOM(owner)); @@ -66,16 +66,16 @@ class StyledTextSpan extends TextSpan { return parent; } - void build(sky.ParagraphBuilder builder) { + void build(ui.ParagraphBuilder builder) { builder.pushStyle(style.textStyle); for (TextSpan child in children) child.build(builder); builder.pop(); } - sky.ParagraphStyle get paragraphStyle => style.paragraphStyle; + ui.ParagraphStyle get paragraphStyle => style.paragraphStyle; - void _applyStyleToContainer(sky.Element container) { + void _applyStyleToContainer(ui.Element container) { style.applyToContainerCSSStyle(container.style); } @@ -129,10 +129,10 @@ class TextPainter { this.text = text; } - sky.Paragraph _paragraph; + ui.Paragraph _paragraph; - final sky.Document _document = new sky.Document(); - final sky.LayoutRoot _layoutRoot = new sky.LayoutRoot(); + final ui.Document _document = new ui.Document(); + final ui.LayoutRoot _layoutRoot = new ui.LayoutRoot(); bool _needsLayout = true; TextSpan _text; @@ -215,7 +215,7 @@ class TextPainter { /// The distance from the top of the text to the first baseline of the given type double computeDistanceToActualBaseline(TextBaseline baseline) { assert(!_needsLayout); - sky.Element root = _layoutRoot.rootElement; + ui.Element root = _layoutRoot.rootElement; switch (baseline) { case TextBaseline.alphabetic: return root.alphabeticBaseline; case TextBaseline.ideographic: return root.ideographicBaseline; @@ -231,7 +231,7 @@ class TextPainter { } /// Paint the text onto the given canvas at the given offset - void paint(sky.Canvas canvas, sky.Offset offset) { + void paint(ui.Canvas canvas, ui.Offset offset) { assert(!_needsLayout && "Please call layout() before paint() to position the text before painting it." is String); // TODO(ianh): Make LayoutRoot support a paint offset so we don't // need to translate for each span of text. @@ -246,7 +246,7 @@ class _NewTextPainter implements TextPainter { this.text = text; } - sky.Paragraph _paragraph; + ui.Paragraph _paragraph; bool _needsLayout = true; TextSpan _text; @@ -256,7 +256,7 @@ class _NewTextPainter implements TextPainter { if (_text == value) return; _text = value; - sky.ParagraphBuilder builder = new sky.ParagraphBuilder(); + ui.ParagraphBuilder builder = new ui.ParagraphBuilder(); _text.build(builder); _paragraph = builder.build(_text.paragraphStyle); _needsLayout = true; @@ -346,7 +346,7 @@ class _NewTextPainter implements TextPainter { } /// Paint the text onto the given canvas at the given offset - void paint(sky.Canvas canvas, sky.Offset offset) { + void paint(ui.Canvas canvas, ui.Offset offset) { assert(!_needsLayout && "Please call layout() before paint() to position the text before painting it." is String); _paragraph.paint(canvas, offset); } diff --git a/packages/flutter/lib/src/painting/text_style.dart b/packages/flutter/lib/src/painting/text_style.dart index 74097aca0c..43ffa44967 100644 --- a/packages/flutter/lib/src/painting/text_style.dart +++ b/packages/flutter/lib/src/painting/text_style.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'dart:ui' show Point, Offset, Size, Rect, Color, Paint, Path, FontWeight, FontStyle, TextAlign, TextBaseline, TextDecoration, TextDecorationStyle; export 'dart:ui' show FontWeight, FontStyle, TextAlign, TextBaseline, TextDecoration, TextDecorationStyle; @@ -152,14 +152,14 @@ class TextStyle { return toCSS[decorationStyle]; } - sky.TextStyle get textStyle => null; - sky.ParagraphStyle get paragraphStyle => null; + ui.TextStyle get textStyle => null; + ui.ParagraphStyle get paragraphStyle => null; /// Program this text style into the engine /// /// Note: This function will likely be removed when we refactor the interface /// between the framework and the engine - void applyToCSSStyle(sky.CSSStyleDeclaration cssStyle) { + void applyToCSSStyle(ui.CSSStyleDeclaration cssStyle) { if (color != null) { cssStyle['color'] = _colorToCSSString(color); } @@ -201,7 +201,7 @@ class TextStyle { /// /// Note: This function will likely be removed when we refactor the interface /// between the framework and the engine - void applyToContainerCSSStyle(sky.CSSStyleDeclaration cssStyle) { + void applyToContainerCSSStyle(ui.CSSStyleDeclaration cssStyle) { if (textAlign != null) { cssStyle['text-align'] = const { TextAlign.left: 'left', diff --git a/packages/flutter/lib/src/rendering/binding.dart b/packages/flutter/lib/src/rendering/binding.dart index d2a6526bf3..7de8a4ebe7 100644 --- a/packages/flutter/lib/src/rendering/binding.dart +++ b/packages/flutter/lib/src/rendering/binding.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'package:flutter/animation.dart'; import 'package:flutter/gestures.dart'; @@ -29,7 +29,7 @@ class _PointerState { Point lastPosition; } -typedef void EventListener(sky.Event event); +typedef void EventListener(ui.Event event); /// A hit test entry used by [FlutterBinding] class BindingHitTestEntry extends HitTestEntry { @@ -46,9 +46,9 @@ class FlutterBinding extends HitTestTarget { assert(_instance == null); _instance = this; - sky.view.setEventCallback(_handleEvent); + ui.view.setEventCallback(_handleEvent); - sky.view.setMetricsChangedCallback(_handleMetricsChanged); + ui.view.setMetricsChangedCallback(_handleMetricsChanged); if (renderViewOverride == null) { _renderView = new RenderView(child: root); _renderView.attach(); @@ -72,7 +72,7 @@ class FlutterBinding extends HitTestTarget { RenderView _renderView; ViewConstraints _createConstraints() { - return new ViewConstraints(size: new Size(sky.view.width, sky.view.height)); + return new ViewConstraints(size: new Size(ui.view.width, ui.view.height)); } void _handleMetricsChanged() { _renderView.rootConstraints = _createConstraints(); @@ -94,8 +94,8 @@ class FlutterBinding extends HitTestTarget { /// Stops calling listener for every event that isn't localized to a given view coordinate bool removeEventListener(EventListener listener) => _eventListeners.remove(listener); - void _handleEvent(sky.Event event) { - if (event is sky.PointerEvent) { + void _handleEvent(ui.Event event) { + if (event is ui.PointerEvent) { _handlePointerEvent(event); } else { for (EventListener listener in _eventListeners) @@ -111,7 +111,7 @@ class FlutterBinding extends HitTestTarget { /// to hit-test them on each movement. Map _stateForPointer = new Map(); - void _handlePointerEvent(sky.PointerEvent event) { + void _handlePointerEvent(ui.PointerEvent event) { Point position = new Point(event.x, event.y); _PointerState state = _stateForPointer[event.pointer]; @@ -155,15 +155,15 @@ class FlutterBinding extends HitTestTarget { } /// Dispatch the given event to the path of the given hit test result - void dispatchEvent(sky.Event event, HitTestResult result) { + void dispatchEvent(ui.Event event, HitTestResult result) { assert(result != null); for (HitTestEntry entry in result.path) entry.target.handleEvent(event, entry); } - void handleEvent(sky.Event e, BindingHitTestEntry entry) { - if (e is sky.PointerEvent) { - sky.PointerEvent event = e; + void handleEvent(ui.Event e, BindingHitTestEntry entry) { + if (e is ui.PointerEvent) { + ui.PointerEvent event = e; pointerRouter.route(event); if (event.type == 'pointerdown') GestureArena.instance.close(event.pointer); diff --git a/packages/flutter/lib/src/rendering/box.dart b/packages/flutter/lib/src/rendering/box.dart index 3a3c52d7e1..288610e548 100644 --- a/packages/flutter/lib/src/rendering/box.dart +++ b/packages/flutter/lib/src/rendering/box.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'dart:math' as math; -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'package:flutter/painting.dart'; import 'package:vector_math/vector_math_64.dart'; @@ -226,10 +226,10 @@ class BoxConstraints extends Constraints { if (b == null) return a * (1.0 - t); return new BoxConstraints( - minWidth: sky.lerpDouble(a.minWidth, b.minWidth, t), - maxWidth: sky.lerpDouble(a.maxWidth, b.maxWidth, t), - minHeight: sky.lerpDouble(a.minHeight, b.minHeight, t), - maxHeight: sky.lerpDouble(a.maxHeight, b.maxHeight, t) + minWidth: ui.lerpDouble(a.minWidth, b.minWidth, t), + maxWidth: ui.lerpDouble(a.maxWidth, b.maxWidth, t), + minHeight: ui.lerpDouble(a.minHeight, b.minHeight, t), + maxHeight: ui.lerpDouble(a.maxHeight, b.maxHeight, t) ); } @@ -598,14 +598,14 @@ abstract class RenderBox extends RenderObject { } void debugPaintSize(PaintingContext context, Offset offset) { Paint paint = new Paint(); - paint.setStyle(sky.PaintingStyle.stroke); + paint.setStyle(ui.PaintingStyle.stroke); paint.strokeWidth = 1.0; paint.color = debugPaintSizeColor; context.canvas.drawRect(offset & size, paint); } void debugPaintBaselines(PaintingContext context, Offset offset) { Paint paint = new Paint(); - paint.setStyle(sky.PaintingStyle.stroke); + paint.setStyle(ui.PaintingStyle.stroke); paint.strokeWidth = 0.25; Path path; // ideographic baseline diff --git a/packages/flutter/lib/src/rendering/debug.dart b/packages/flutter/lib/src/rendering/debug.dart index 0e1e05090a..cf2df69323 100644 --- a/packages/flutter/lib/src/rendering/debug.dart +++ b/packages/flutter/lib/src/rendering/debug.dart @@ -2,31 +2,31 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ui' as sky; +import 'dart:ui' as ui; /// Causes each RenderBox to paint a box around its bounds. bool debugPaintSizeEnabled = false; /// The color to use when painting RenderObject bounds. -sky.Color debugPaintSizeColor = const sky.Color(0xFF00FFFF); +ui.Color debugPaintSizeColor = const ui.Color(0xFF00FFFF); /// Causes each RenderBox to paint a line at each of its baselines. bool debugPaintBaselinesEnabled = false; /// The color to use when painting alphabetic baselines. -sky.Color debugPaintAlphabeticBaselineColor = const sky.Color(0xFF00FF00); +ui.Color debugPaintAlphabeticBaselineColor = const ui.Color(0xFF00FF00); /// The color ot use when painting ideographic baselines. -sky.Color debugPaintIdeographicBaselineColor = const sky.Color(0xFFFFD000); +ui.Color debugPaintIdeographicBaselineColor = const ui.Color(0xFFFFD000); /// Causes each Layer to paint a box around its bounds. bool debugPaintLayerBordersEnabled = false; /// The color to use when painting Layer borders. -sky.Color debugPaintLayerBordersColor = const sky.Color(0xFFFF9800); +ui.Color debugPaintLayerBordersColor = const ui.Color(0xFFFF9800); /// Causes RenderObjects to paint warnings when painting outside their bounds. bool debugPaintBoundsEnabled = false; /// The color to use when painting RenderError boxes in checked mode. -sky.Color debugErrorBoxColor = const sky.Color(0xFFFF0000); +ui.Color debugErrorBoxColor = const ui.Color(0xFFFF0000); diff --git a/packages/flutter/lib/src/rendering/hit_test.dart b/packages/flutter/lib/src/rendering/hit_test.dart index a54feb16eb..6103624010 100644 --- a/packages/flutter/lib/src/rendering/hit_test.dart +++ b/packages/flutter/lib/src/rendering/hit_test.dart @@ -2,12 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ui' as sky; +import 'dart:ui' as ui; /// An object that can handle events. abstract class HitTestTarget { /// Override this function to receive events. - void handleEvent(sky.Event event, HitTestEntry entry); + void handleEvent(ui.Event event, HitTestEntry entry); } /// Data collected during a hit test about a specific [HitTestTarget]. diff --git a/packages/flutter/lib/src/rendering/image.dart b/packages/flutter/lib/src/rendering/image.dart index eda9618663..e5e7356a83 100644 --- a/packages/flutter/lib/src/rendering/image.dart +++ b/packages/flutter/lib/src/rendering/image.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'package:flutter/painting.dart'; @@ -15,10 +15,10 @@ import 'object.dart'; /// constraints and preserves the image's intrinisc aspect ratio. class RenderImage extends RenderBox { RenderImage({ - sky.Image image, + ui.Image image, double width, double height, - sky.ColorFilter colorFilter, + ui.ColorFilter colorFilter, fit: ImageFit.scaleDown, repeat: ImageRepeat.noRepeat }) : _image = image, @@ -28,10 +28,10 @@ class RenderImage extends RenderBox { _fit = fit, _repeat = repeat; - sky.Image _image; + ui.Image _image; /// The image to display - sky.Image get image => _image; - void set image (sky.Image value) { + ui.Image get image => _image; + void set image (ui.Image value) { if (value == _image) return; _image = value; @@ -60,10 +60,10 @@ class RenderImage extends RenderBox { markNeedsLayout(); } - sky.ColorFilter _colorFilter; + ui.ColorFilter _colorFilter; /// If non-null, apply this color filter to the image before painint. - sky.ColorFilter get colorFilter => _colorFilter; - void set colorFilter (sky.ColorFilter value) { + ui.ColorFilter get colorFilter => _colorFilter; + void set colorFilter (ui.ColorFilter value) { if (value == _colorFilter) return; _colorFilter = value; diff --git a/packages/flutter/lib/src/rendering/layer.dart b/packages/flutter/lib/src/rendering/layer.dart index 9afdad8798..0434fd8332 100644 --- a/packages/flutter/lib/src/rendering/layer.dart +++ b/packages/flutter/lib/src/rendering/layer.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'dart:ui' show Point, Offset, Size, Rect, Color, Paint, Path; import 'package:vector_math/vector_math_64.dart'; @@ -62,7 +62,7 @@ abstract class Layer { /// /// The layerOffset is the accumulated offset of this layer's parent from the /// origin of the builder's coordinate system. - void addToScene(sky.SceneBuilder builder, Offset layerOffset); + void addToScene(ui.SceneBuilder builder, Offset layerOffset); } /// A composited layer containing a [Picture] @@ -79,9 +79,9 @@ class PictureLayer extends Layer { /// The picture recorded for this layer /// /// The picture's coodinate system matches this layer's coodinate system - sky.Picture picture; + ui.Picture picture; - void addToScene(sky.SceneBuilder builder, Offset layerOffset) { + void addToScene(ui.SceneBuilder builder, Offset layerOffset) { builder.addPicture(offset + layerOffset, picture, paintBounds); } @@ -105,7 +105,7 @@ class StatisticsLayer extends Layer { final int rasterizerThreshold; - void addToScene(sky.SceneBuilder builder, Offset layerOffset) { + void addToScene(ui.SceneBuilder builder, Offset layerOffset) { assert(optionsMask != null); builder.addStatistics(optionsMask, paintBounds.shift(layerOffset)); builder.setRasterizerTracingThreshold(rasterizerThreshold); @@ -194,12 +194,12 @@ class ContainerLayer extends Layer { _lastChild = null; } - void addToScene(sky.SceneBuilder builder, Offset layerOffset) { + void addToScene(ui.SceneBuilder builder, Offset layerOffset) { addChildrenToScene(builder, offset + layerOffset); } /// Uploads all of this layer's children to the engine - void addChildrenToScene(sky.SceneBuilder builder, Offset layerOffset) { + void addChildrenToScene(ui.SceneBuilder builder, Offset layerOffset) { Layer child = _firstChild; while (child != null) { child.addToScene(builder, layerOffset); @@ -218,7 +218,7 @@ class ClipRectLayer extends ContainerLayer { // TODO(abarth): Why is the rectangle in the parent's coordinate system // instead of in the coordinate system of this layer? - void addToScene(sky.SceneBuilder builder, Offset layerOffset) { + void addToScene(ui.SceneBuilder builder, Offset layerOffset) { builder.pushClipRect(clipRect.shift(layerOffset)); addChildrenToScene(builder, offset + layerOffset); builder.pop(); @@ -235,11 +235,11 @@ class ClipRRectLayer extends ContainerLayer { // TODO(abarth): Remove. /// The rounded-rect to clip in the parent's coordinate system - sky.RRect clipRRect; + ui.RRect clipRRect; // TODO(abarth): Why is the rounded-rect in the parent's coordinate system // instead of in the coordinate system of this layer? - void addToScene(sky.SceneBuilder builder, Offset layerOffset) { + void addToScene(ui.SceneBuilder builder, Offset layerOffset) { builder.pushClipRRect(clipRRect.shift(layerOffset), bounds.shift(layerOffset)); addChildrenToScene(builder, offset + layerOffset); builder.pop(); @@ -260,7 +260,7 @@ class ClipPathLayer extends ContainerLayer { // TODO(abarth): Why is the path in the parent's coordinate system instead of // in the coordinate system of this layer? - void addToScene(sky.SceneBuilder builder, Offset layerOffset) { + void addToScene(ui.SceneBuilder builder, Offset layerOffset) { builder.pushClipPath(clipPath.shift(layerOffset), bounds.shift(layerOffset)); addChildrenToScene(builder, offset + layerOffset); builder.pop(); @@ -275,7 +275,7 @@ class TransformLayer extends ContainerLayer { /// The matrix to apply Matrix4 transform; - void addToScene(sky.SceneBuilder builder, Offset layerOffset) { + void addToScene(ui.SceneBuilder builder, Offset layerOffset) { Matrix4 offsetTransform = new Matrix4.identity(); offsetTransform.translate(offset.dx + layerOffset.dx, offset.dy + layerOffset.dy); builder.pushTransform((offsetTransform * transform).storage); @@ -298,7 +298,7 @@ class OpacityLayer extends ContainerLayer { /// transparent and 255 is fully opaque. int alpha; - void addToScene(sky.SceneBuilder builder, Offset layerOffset) { + void addToScene(ui.SceneBuilder builder, Offset layerOffset) { builder.pushOpacity(alpha, bounds?.shift(layerOffset)); addChildrenToScene(builder, offset + layerOffset); builder.pop(); @@ -322,9 +322,9 @@ class ColorFilterLayer extends ContainerLayer { Color color; /// The transfer mode to use to combine [color] with the children's painting - sky.TransferMode transferMode; + ui.TransferMode transferMode; - void addToScene(sky.SceneBuilder builder, Offset layerOffset) { + void addToScene(ui.SceneBuilder builder, Offset layerOffset) { builder.pushColorFilter(color, transferMode, bounds.shift(offset)); addChildrenToScene(builder, offset + layerOffset); builder.pop(); diff --git a/packages/flutter/lib/src/rendering/object.dart b/packages/flutter/lib/src/rendering/object.dart index a08076585e..f3b1e30d98 100644 --- a/packages/flutter/lib/src/rendering/object.dart +++ b/packages/flutter/lib/src/rendering/object.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'dart:math' as math; -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'dart:ui' show Point, Offset, Size, Rect, Color, Paint, Path; import 'package:flutter/animation.dart'; @@ -17,7 +17,7 @@ import 'node.dart'; export 'dart:ui' show Point, Offset, Size, Rect, Color, Paint, Path; export 'hit_test.dart' show HitTestTarget, HitTestEntry, HitTestResult; -typedef sky.Shader ShaderCallback(Rect bounds); +typedef ui.Shader ShaderCallback(Rect bounds); /// Base class for data associated with a [RenderObject] by its parent /// @@ -38,9 +38,9 @@ class ParentData { } /// Obsolete class that will be removed eventually -class PaintingCanvas extends sky.Canvas { - PaintingCanvas(sky.PictureRecorder recorder, Rect bounds) : super(recorder, bounds); - // TODO(ianh): Just use sky.Canvas everywhere instead +class PaintingCanvas extends ui.Canvas { + PaintingCanvas(ui.PictureRecorder recorder, Rect bounds) : super(recorder, bounds); + // TODO(ianh): Just use ui.Canvas everywhere instead } /// A place to paint @@ -76,7 +76,7 @@ class PaintingContext { ContainerLayer get containerLayer => _containerLayer; PictureLayer _currentLayer; - sky.PictureRecorder _recorder; + ui.PictureRecorder _recorder; PaintingCanvas _canvas; /// The canvas on which to paint /// @@ -90,7 +90,7 @@ class PaintingContext { assert(_recorder == null); assert(_canvas == null); _currentLayer = new PictureLayer(paintBounds: paintBounds); - _recorder = new sky.PictureRecorder(); + _recorder = new ui.PictureRecorder(); _canvas = new PaintingCanvas(_recorder, paintBounds); _containerLayer.append(_currentLayer); } @@ -186,7 +186,7 @@ class PaintingContext { /// compositing layer. Otherwise, the clip will be applied by the canvas. /// /// Note: clipRRect is in the parent's coordinate space - void paintChildWithClipRRect(RenderObject child, Point childPosition, Rect bounds, sky.RRect clipRRect) { + void paintChildWithClipRRect(RenderObject child, Point childPosition, Rect bounds, ui.RRect clipRRect) { assert(debugCanPaintChild(child)); final Offset childOffset = childPosition.toOffset(); if (!child.needsCompositing) { @@ -246,7 +246,7 @@ class PaintingContext { static Paint _getPaintForAlpha(int alpha) { return new Paint() ..color = new Color.fromARGB(alpha, 0, 0, 0) - ..setTransferMode(sky.TransferMode.srcOver) + ..setTransferMode(ui.TransferMode.srcOver) ..isAntiAlias = false; } @@ -276,9 +276,9 @@ class PaintingContext { } } - static Paint _getPaintForColorFilter(Color color, sky.TransferMode transferMode) { + static Paint _getPaintForColorFilter(Color color, ui.TransferMode transferMode) { return new Paint() - ..colorFilter = new sky.ColorFilter.mode(color, transferMode) + ..colorFilter = new ui.ColorFilter.mode(color, transferMode) ..isAntiAlias = false; } @@ -294,7 +294,7 @@ class PaintingContext { Point childPosition, Rect bounds, Color color, - sky.TransferMode transferMode) { + ui.TransferMode transferMode) { assert(debugCanPaintChild(child)); final Offset childOffset = childPosition.toOffset(); if (!child.needsCompositing) { @@ -315,7 +315,7 @@ class PaintingContext { static Paint _getPaintForShaderMask(Rect bounds, ShaderCallback shaderCallback, - sky.TransferMode transferMode) { + ui.TransferMode transferMode) { return new Paint() ..transferMode = transferMode ..shader = shaderCallback(bounds); @@ -325,7 +325,7 @@ class PaintingContext { Point childPosition, Rect bounds, ShaderCallback shaderCallback, - sky.TransferMode transferMode) { + ui.TransferMode transferMode) { assert(debugCanPaintChild(child)); final Offset childOffset = childPosition.toOffset(); if (!child.needsCompositing) { @@ -628,7 +628,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { /// /// See [FlutterBinding] for an example of how this function is used. static void flushLayout() { - sky.tracing.begin('RenderObject.flushLayout'); + ui.tracing.begin('RenderObject.flushLayout'); _debugDoingLayout = true; try { // TODO(ianh): assert that we're not allowing previously dirty nodes to redirty themeselves @@ -642,7 +642,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { } } finally { _debugDoingLayout = false; - sky.tracing.end('RenderObject.flushLayout'); + ui.tracing.end('RenderObject.flushLayout'); } } void _layoutWithoutResize() { @@ -949,7 +949,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { /// /// See [FlutterBinding] for an example of how this function is used. static void flushPaint() { - sky.tracing.begin('RenderObject.flushPaint'); + ui.tracing.begin('RenderObject.flushPaint'); _debugDoingPaint = true; try { List dirtyNodes = _nodesNeedingPaint; @@ -963,7 +963,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { assert(_nodesNeedingPaint.length == 0); } finally { _debugDoingPaint = false; - sky.tracing.end('RenderObject.flushPaint'); + ui.tracing.end('RenderObject.flushPaint'); } } @@ -1069,7 +1069,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { // EVENTS /// Override this function to handle events that hit this render object - void handleEvent(sky.Event event, HitTestEntry entry) { + void handleEvent(ui.Event event, HitTestEntry entry) { } diff --git a/packages/flutter/lib/src/rendering/proxy_box.dart b/packages/flutter/lib/src/rendering/proxy_box.dart index 24dc33bf9a..42ae88854c 100644 --- a/packages/flutter/lib/src/rendering/proxy_box.dart +++ b/packages/flutter/lib/src/rendering/proxy_box.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'package:flutter/painting.dart'; import 'package:vector_math/vector_math_64.dart'; @@ -627,7 +627,7 @@ class RenderOpacity extends RenderProxyBox { /// Note: This class is relatively expensive because it requires painting the /// child into an intermediate buffer. class RenderColorFilter extends RenderProxyBox { - RenderColorFilter({ RenderBox child, Color color, sky.TransferMode transferMode }) + RenderColorFilter({ RenderBox child, Color color, ui.TransferMode transferMode }) : _color = color, _transferMode = transferMode, super(child) { } @@ -643,9 +643,9 @@ class RenderColorFilter extends RenderProxyBox { } /// The transfer mode to use when combining the child's painting and the [color] - sky.TransferMode get transferMode => _transferMode; - sky.TransferMode _transferMode; - void set transferMode (sky.TransferMode newTransferMode) { + ui.TransferMode get transferMode => _transferMode; + ui.TransferMode _transferMode; + void set transferMode (ui.TransferMode newTransferMode) { assert(newTransferMode != null); if (_transferMode == newTransferMode) return; @@ -660,7 +660,7 @@ class RenderColorFilter extends RenderProxyBox { } class RenderShaderMask extends RenderProxyBox { - RenderShaderMask({ RenderBox child, ShaderCallback shaderCallback, sky.TransferMode transferMode }) + RenderShaderMask({ RenderBox child, ShaderCallback shaderCallback, ui.TransferMode transferMode }) : _shaderCallback = shaderCallback, _transferMode = transferMode, super(child) { } @@ -674,9 +674,9 @@ class RenderShaderMask extends RenderProxyBox { markNeedsPaint(); } - sky.TransferMode get transferMode => _transferMode; - sky.TransferMode _transferMode; - void set transferMode (sky.TransferMode newTransferMode) { + ui.TransferMode get transferMode => _transferMode; + ui.TransferMode _transferMode; + void set transferMode (ui.TransferMode newTransferMode) { assert(newTransferMode != null); if (_transferMode == newTransferMode) return; @@ -745,7 +745,7 @@ class RenderClipRRect extends RenderProxyBox { void paint(PaintingContext context, Offset offset) { if (child != null) { Rect rect = offset & size; - sky.RRect rrect = new sky.RRect()..setRectXY(rect, xRadius, yRadius); + ui.RRect rrect = new ui.RRect()..setRectXY(rect, xRadius, yRadius); context.paintChildWithClipRRect(child, offset.toPoint(), rect, rrect); } } @@ -1056,7 +1056,7 @@ class RenderCustomPaint extends RenderProxyBox { } } -typedef void PointerEventListener(sky.PointerEvent e); +typedef void PointerEventListener(ui.PointerEvent e); /// Invokes the callbacks in response to pointer events. class RenderPointerListener extends RenderProxyBox { @@ -1073,7 +1073,7 @@ class RenderPointerListener extends RenderProxyBox { PointerEventListener onPointerUp; PointerEventListener onPointerCancel; - void handleEvent(sky.Event event, HitTestEntry entry) { + void handleEvent(ui.Event event, HitTestEntry entry) { if (onPointerDown != null && event.type == 'pointerdown') return onPointerDown(event); if (onPointerMove != null && event.type == 'pointermove') diff --git a/packages/flutter/lib/src/rendering/toggleable.dart b/packages/flutter/lib/src/rendering/toggleable.dart index f5df71db1e..959eba22cd 100644 --- a/packages/flutter/lib/src/rendering/toggleable.dart +++ b/packages/flutter/lib/src/rendering/toggleable.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'package:flutter/animation.dart'; import 'package:flutter/gestures.dart'; @@ -37,7 +37,7 @@ abstract class RenderToggleable extends RenderConstrainedBox { double get position => _performance.value; - void handleEvent(sky.Event event, BoxHitTestEntry entry) { + void handleEvent(ui.Event event, BoxHitTestEntry entry) { if (event.type == 'pointerdown') _tap.addPointer(event); } diff --git a/packages/flutter/lib/src/rendering/view.dart b/packages/flutter/lib/src/rendering/view.dart index 9e8a07bfd1..7b0d3548ef 100644 --- a/packages/flutter/lib/src/rendering/view.dart +++ b/packages/flutter/lib/src/rendering/view.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'package:flutter/animation.dart'; import 'package:vector_math/vector_math_64.dart'; @@ -60,7 +60,7 @@ class RenderView extends RenderObject with RenderObjectWithChildMixin } Matrix4 get _logicalToDeviceTransform { - double devicePixelRatio = sky.view.devicePixelRatio; + double devicePixelRatio = ui.view.devicePixelRatio; return new Matrix4.diagonal3Values(devicePixelRatio, devicePixelRatio, 1.0); } @@ -114,15 +114,15 @@ class RenderView extends RenderObject with RenderObjectWithChildMixin /// /// Actually causes the output of the rendering pipeline to appear on screen. void compositeFrame() { - sky.tracing.begin('RenderView.compositeFrame'); + ui.tracing.begin('RenderView.compositeFrame'); try { (layer as TransformLayer).transform = _logicalToDeviceTransform; - Rect bounds = Point.origin & (size * sky.view.devicePixelRatio); - sky.SceneBuilder builder = new sky.SceneBuilder(bounds); + Rect bounds = Point.origin & (size * ui.view.devicePixelRatio); + ui.SceneBuilder builder = new ui.SceneBuilder(bounds); layer.addToScene(builder, Offset.zero); - sky.view.scene = builder.build(); + ui.view.scene = builder.build(); } finally { - sky.tracing.end('RenderView.compositeFrame'); + ui.tracing.end('RenderView.compositeFrame'); } } diff --git a/packages/flutter/lib/src/rendering/viewport.dart b/packages/flutter/lib/src/rendering/viewport.dart index c27d4e148d..eccce14a54 100644 --- a/packages/flutter/lib/src/rendering/viewport.dart +++ b/packages/flutter/lib/src/rendering/viewport.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'package:vector_math/vector_math_64.dart'; @@ -136,7 +136,7 @@ class RenderViewport extends RenderBox with RenderObjectWithChildMixin _fetchImage(String key) async { + Future _fetchImage(String key) async { return await decodeImageFromDataPipe(await load(key)); } diff --git a/packages/flutter/lib/src/services/image_cache.dart b/packages/flutter/lib/src/services/image_cache.dart index 19c823caf0..f7076c82c8 100644 --- a/packages/flutter/lib/src/services/image_cache.dart +++ b/packages/flutter/lib/src/services/image_cache.dart @@ -4,7 +4,7 @@ import 'dart:async'; import 'dart:collection'; -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'package:mojo/mojo/url_response.mojom.dart'; @@ -12,7 +12,7 @@ import 'fetch.dart'; import 'image_decoder.dart'; import 'image_resource.dart'; -Future _fetchImage(String url) async { +Future _fetchImage(String url) async { UrlResponse response = await fetchUrl(url); if (response.statusCode >= 400) { print("Failed (${response.statusCode}) to load image ${url}"); diff --git a/packages/flutter/lib/src/services/image_resource.dart b/packages/flutter/lib/src/services/image_resource.dart index 2f887d6a76..0ac5e2f1cf 100644 --- a/packages/flutter/lib/src/services/image_resource.dart +++ b/packages/flutter/lib/src/services/image_resource.dart @@ -3,14 +3,14 @@ // found in the LICENSE file. import 'dart:async'; -import 'dart:ui' as sky; +import 'dart:ui' as ui; /// A callback for when the image is available. -typedef void ImageListener(sky.Image image); +typedef void ImageListener(ui.Image image); /// A handle to an image resource /// -/// ImageResource represents a handle to a [sky.Image] object. The underlying +/// ImageResource represents a handle to a [ui.Image] object. The underlying /// image object might change over time, either because the image is animating /// or because the underlying image resource was mutated. class ImageResource { @@ -19,17 +19,17 @@ class ImageResource { } bool _resolved = false; - Future _futureImage; - sky.Image _image; + Future _futureImage; + ui.Image _image; final List _listeners = new List(); - /// The first concrete [sky.Image] object represented by this handle. + /// The first concrete [ui.Image] object represented by this handle. /// /// Instead of receivingly only the first image, most clients will want to /// [addListener] to be notified whenever a a concrete image is available. - Future get first => _futureImage; + Future get first => _futureImage; - /// Adds a listener callback that is called whenever a concrete [sky.Image] + /// Adds a listener callback that is called whenever a concrete [ui.Image] /// object is available. Note: If a concrete image is available currently, /// this object will call the listener synchronously. void addListener(ImageListener listener) { @@ -38,12 +38,12 @@ class ImageResource { listener(_image); } - /// Stop listening for new concrete [sky.Image] objects. + /// Stop listening for new concrete [ui.Image] objects. void removeListener(ImageListener listener) { _listeners.remove(listener); } - void _handleImageLoaded(sky.Image image) { + void _handleImageLoaded(ui.Image image) { _image = image; _resolved = true; _notifyListeners(); diff --git a/packages/flutter/lib/src/widgets/basic.dart b/packages/flutter/lib/src/widgets/basic.dart index afde446e3e..23f3576025 100644 --- a/packages/flutter/lib/src/widgets/basic.dart +++ b/packages/flutter/lib/src/widgets/basic.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'package:flutter/rendering.dart'; import 'package:flutter/services.dart'; @@ -61,7 +61,7 @@ class ColorFilter extends OneChildRenderObjectWidget { } final Color color; - final sky.TransferMode transferMode; + final ui.TransferMode transferMode; RenderColorFilter createRenderObject() => new RenderColorFilter(color: color, transferMode: transferMode); @@ -75,7 +75,7 @@ class ShaderMask extends OneChildRenderObjectWidget { ShaderMask({ Key key, this.shaderCallback, - this.transferMode: sky.TransferMode.modulate, + this.transferMode: ui.TransferMode.modulate, Widget child }) : super(key: key, child: child) { assert(shaderCallback != null); @@ -83,7 +83,7 @@ class ShaderMask extends OneChildRenderObjectWidget { } final ShaderCallback shaderCallback; - final sky.TransferMode transferMode; + final ui.TransferMode transferMode; RenderShaderMask createRenderObject() { return new RenderShaderMask( @@ -813,10 +813,10 @@ class Image extends LeafRenderObjectWidget { this.repeat: ImageRepeat.noRepeat }) : super(key: key); - final sky.Image image; + final ui.Image image; final double width; final double height; - final sky.ColorFilter colorFilter; + final ui.ColorFilter colorFilter; final ImageFit fit; final ImageRepeat repeat; @@ -854,7 +854,7 @@ class ImageListener extends StatefulComponent { final ImageResource image; final double width; final double height; - final sky.ColorFilter colorFilter; + final ui.ColorFilter colorFilter; final ImageFit fit; final ImageRepeat repeat; @@ -867,9 +867,9 @@ class _ImageListenerState extends State { config.image.addListener(_handleImageChanged); } - sky.Image _resolvedImage; + ui.Image _resolvedImage; - void _handleImageChanged(sky.Image resolvedImage) { + void _handleImageChanged(ui.Image resolvedImage) { setState(() { _resolvedImage = resolvedImage; }); @@ -913,7 +913,7 @@ class NetworkImage extends StatelessComponent { final String src; final double width; final double height; - final sky.ColorFilter colorFilter; + final ui.ColorFilter colorFilter; final ImageFit fit; final ImageRepeat repeat; @@ -945,7 +945,7 @@ class AssetImage extends StatelessComponent { final AssetBundle bundle; final double width; final double height; - final sky.ColorFilter colorFilter; + final ui.ColorFilter colorFilter; final ImageFit fit; final ImageRepeat repeat; diff --git a/packages/flutter/lib/src/widgets/dismissable.dart b/packages/flutter/lib/src/widgets/dismissable.dart index 6659d61ec1..69f76a8a98 100644 --- a/packages/flutter/lib/src/widgets/dismissable.dart +++ b/packages/flutter/lib/src/widgets/dismissable.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'package:flutter/animation.dart'; @@ -164,7 +164,7 @@ class _DismissableState extends State { _fadePerformance.progress = _dragExtent.abs() / (_size.width * _kDismissCardThreshold); } - bool _isFlingGesture(sky.Offset velocity) { + bool _isFlingGesture(ui.Offset velocity) { double vx = velocity.dx; double vy = velocity.dy; if (_directionIsYAxis) { @@ -193,7 +193,7 @@ class _DismissableState extends State { return false; } - void _handleDragEnd(sky.Offset velocity) { + void _handleDragEnd(ui.Offset velocity) { if (!_isActive || _fadePerformance.isAnimating) return; diff --git a/packages/flutter/lib/src/widgets/drag_target.dart b/packages/flutter/lib/src/widgets/drag_target.dart index 8ea0cb8e37..e0f9ce5d37 100644 --- a/packages/flutter/lib/src/widgets/drag_target.dart +++ b/packages/flutter/lib/src/widgets/drag_target.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'dart:collection'; -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'package:flutter/animation.dart'; import 'package:flutter/rendering.dart'; @@ -69,7 +69,7 @@ class Draggable extends StatefulComponent { class _DraggableState extends State { DragRoute _route; - void _startDrag(sky.PointerEvent event) { + void _startDrag(ui.PointerEvent event) { if (_route != null) return; // TODO(ianh): once we switch to using gestures, just hand the gesture to the route so it can do everything itself. then we can have multiple drags at the same time. final Point point = new Point(event.x, event.y); @@ -97,7 +97,7 @@ class _DraggableState extends State { config.navigator.push(_route); } - void _updateDrag(sky.PointerEvent event) { + void _updateDrag(ui.PointerEvent event) { if (_route != null) { config.navigator.setState(() { _route.update(new Point(event.x, event.y)); @@ -105,14 +105,14 @@ class _DraggableState extends State { } } - void _cancelDrag(sky.PointerEvent event) { + void _cancelDrag(ui.PointerEvent event) { if (_route != null) { config.navigator.popRoute(_route, DragEndKind.canceled); assert(_route == null); } } - void _drop(sky.PointerEvent event) { + void _drop(ui.PointerEvent event) { if (_route != null) { _route.update(new Point(event.x, event.y)); config.navigator.popRoute(_route, DragEndKind.dropped); diff --git a/packages/flutter/lib/src/widgets/gesture_detector.dart b/packages/flutter/lib/src/widgets/gesture_detector.dart index 288ae05763..534148ae4a 100644 --- a/packages/flutter/lib/src/widgets/gesture_detector.dart +++ b/packages/flutter/lib/src/widgets/gesture_detector.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'package:flutter/gestures.dart'; import 'package:flutter/rendering.dart'; @@ -187,7 +187,7 @@ class _GestureDetectorState extends State { return null; } - void _handlePointerDown(sky.PointerEvent event) { + void _handlePointerDown(ui.PointerEvent event) { if (_tap != null) _tap.addPointer(event); if (_showPress != null) diff --git a/packages/flutter/lib/src/widgets/scrollable.dart b/packages/flutter/lib/src/widgets/scrollable.dart index 0ae33f9a7e..310dd57a40 100644 --- a/packages/flutter/lib/src/widgets/scrollable.dart +++ b/packages/flutter/lib/src/widgets/scrollable.dart @@ -4,7 +4,7 @@ import 'dart:async'; import 'dart:math' as math; -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'package:newton/newton.dart'; import 'package:flutter/animation.dart'; @@ -200,7 +200,7 @@ abstract class ScrollableState extends State { return _startToEndAnimation(); } - double _scrollVelocity(sky.Offset velocity) { + double _scrollVelocity(ui.Offset velocity) { double scrollVelocity = config.scrollDirection == ScrollDirection.horizontal ? -velocity.dx : -velocity.dy; @@ -616,7 +616,7 @@ class PageableListState extends ScrollableListState> { .clamp(scrollBehavior.minScrollOffset, scrollBehavior.maxScrollOffset); } - Future fling(sky.Offset velocity) { + Future fling(ui.Offset velocity) { double scrollVelocity = _scrollVelocity(velocity); double newScrollOffset = _snapScrollOffset(scrollOffset + scrollVelocity.sign * config.itemExtent) .clamp(_snapScrollOffset(scrollOffset - config.itemExtent / 2.0), diff --git a/packages/flutter_sprites/lib/effect_line.dart b/packages/flutter_sprites/lib/effect_line.dart index 211e15d057..91f0bb67fc 100644 --- a/packages/flutter_sprites/lib/effect_line.dart +++ b/packages/flutter_sprites/lib/effect_line.dart @@ -15,7 +15,7 @@ class EffectLine extends Node { EffectLine({ this.texture: null, - this.transferMode: sky.TransferMode.dstOver, + this.transferMode: ui.TransferMode.dstOver, List points, this.widthMode : EffectLineWidthMode.linear, this.minWidth: 10.0, @@ -47,7 +47,7 @@ class EffectLine extends Node { final Texture texture; - final sky.TransferMode transferMode; + final ui.TransferMode transferMode; final EffectLineWidthMode widthMode; final double minWidth; diff --git a/packages/flutter_sprites/lib/image_map.dart b/packages/flutter_sprites/lib/image_map.dart index 3de956c630..6392204ddf 100644 --- a/packages/flutter_sprites/lib/image_map.dart +++ b/packages/flutter_sprites/lib/image_map.dart @@ -8,18 +8,18 @@ class ImageMap { ImageMap(AssetBundle bundle) : _bundle = bundle; final AssetBundle _bundle; - final Map _images = new Map(); + final Map _images = new Map(); - Future> load(List urls) { + Future> load(List urls) { return Future.wait(urls.map(_loadImage)); } - Future _loadImage(String url) async { - sky.Image image = await _bundle.loadImage(url).first; + Future _loadImage(String url) async { + ui.Image image = await _bundle.loadImage(url).first; _images[url] = image; return image; } - sky.Image getImage(String url) => _images[url]; - sky.Image operator [](String url) => _images[url]; + ui.Image getImage(String url) => _images[url]; + ui.Image operator [](String url) => _images[url]; } diff --git a/packages/flutter_sprites/lib/layer.dart b/packages/flutter_sprites/lib/layer.dart index 85f934992f..3d8b08543c 100644 --- a/packages/flutter_sprites/lib/layer.dart +++ b/packages/flutter_sprites/lib/layer.dart @@ -22,7 +22,7 @@ class Layer extends Node with SpritePaint { Layer([Rect this.layerRect = null]); Paint _cachedPaint = new Paint() - ..filterQuality = sky.FilterQuality.low + ..filterQuality = ui.FilterQuality.low ..isAntiAlias = false; void _prePaint(PaintingCanvas canvas, Matrix4 matrix) { diff --git a/packages/flutter_sprites/lib/particle_system.dart b/packages/flutter_sprites/lib/particle_system.dart index fc8bb0bc0a..e7b8d1d458 100644 --- a/packages/flutter_sprites/lib/particle_system.dart +++ b/packages/flutter_sprites/lib/particle_system.dart @@ -144,7 +144,7 @@ class ParticleSystem extends Node { /// The transfer mode used to draw the particle system. Default is /// [TransferMode.plus]. - sky.TransferMode transferMode; + ui.TransferMode transferMode; List<_Particle> _particles; @@ -152,7 +152,7 @@ class ParticleSystem extends Node { int _numEmittedParticles = 0; static Paint _paint = new Paint() - ..filterQuality = sky.FilterQuality.low + ..filterQuality = ui.FilterQuality.low ..isAntiAlias = false; ParticleSystem(this.texture, @@ -184,7 +184,7 @@ class ParticleSystem extends Node { this.redVar: 0, this.greenVar: 0, this.blueVar: 0, - this.transferMode: sky.TransferMode.plus, + this.transferMode: ui.TransferMode.plus, this.numParticlesToEmit: 0, this.autoRemoveOnFinish: true}) { _particles = new List<_Particle>(); @@ -359,7 +359,7 @@ class ParticleSystem extends Node { void paint(PaintingCanvas canvas) { - List transforms = []; + List transforms = []; List rects = []; List colors = []; @@ -388,7 +388,7 @@ class ParticleSystem extends Node { double ay = rect.height / 2; double tx = particle.pos[0] + -scos * ax + ssin * ay; double ty = particle.pos[1] + -ssin * ax - scos * ay; - sky.RSTransform transform = new sky.RSTransform(scos, ssin, tx, ty); + ui.RSTransform transform = new ui.RSTransform(scos, ssin, tx, ty); transforms.add(transform); // Color @@ -411,7 +411,7 @@ class ParticleSystem extends Node { } canvas.drawAtlas(texture.image, transforms, rects, colors, - sky.TransferMode.modulate, null, _paint); + ui.TransferMode.modulate, null, _paint); } } diff --git a/packages/flutter_sprites/lib/physics_node.dart b/packages/flutter_sprites/lib/physics_node.dart index 57811e75cf..659fff346a 100644 --- a/packages/flutter_sprites/lib/physics_node.dart +++ b/packages/flutter_sprites/lib/physics_node.dart @@ -137,7 +137,7 @@ class PhysicsNode extends Node { void paintDebug(PaintingCanvas canvas) { Paint shapePaint = new Paint(); - shapePaint.setStyle(sky.PaintingStyle.stroke); + shapePaint.setStyle(ui.PaintingStyle.stroke); shapePaint.strokeWidth = 1.0; for (box2d.Body body = b2World.bodyList; body != null; body = body.getNext()) { diff --git a/packages/flutter_sprites/lib/skysprites.dart b/packages/flutter_sprites/lib/skysprites.dart index 62b2669e7a..7bdd6274d8 100644 --- a/packages/flutter_sprites/lib/skysprites.dart +++ b/packages/flutter_sprites/lib/skysprites.dart @@ -8,7 +8,7 @@ import 'dart:async'; import 'dart:convert'; import 'dart:math' as math; import 'dart:typed_data'; -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'package:box2d/box2d.dart' as box2d; import 'package:mojo/core.dart'; diff --git a/packages/flutter_sprites/lib/sprite.dart b/packages/flutter_sprites/lib/sprite.dart index ded78e7443..f1d30a63db 100644 --- a/packages/flutter_sprites/lib/sprite.dart +++ b/packages/flutter_sprites/lib/sprite.dart @@ -17,7 +17,7 @@ class Sprite extends NodeWithSize with SpritePaint { bool constrainProportions = false; Paint _cachedPaint = new Paint() - ..filterQuality = sky.FilterQuality.low + ..filterQuality = ui.FilterQuality.low ..isAntiAlias = false; /// Creates a new sprite from the provided [texture]. @@ -35,7 +35,7 @@ class Sprite extends NodeWithSize with SpritePaint { /// Creates a new sprite from the provided [image]. /// /// var mySprite = new Sprite.fromImage(myImage); - Sprite.fromImage(sky.Image image) : super(Size.zero) { + Sprite.fromImage(ui.Image image) : super(Size.zero) { assert(image != null); texture = new Texture(image); @@ -107,13 +107,13 @@ abstract class SpritePaint { /// /// // Add the colors of the sprite with the colors of the background /// mySprite.transferMode = TransferMode.plusMode; - sky.TransferMode transferMode; + ui.TransferMode transferMode; void _updatePaint(Paint paint) { paint.color = new Color.fromARGB((255.0*_opacity).toInt(), 255, 255, 255); if (colorOverlay != null) { - paint.colorFilter = new sky.ColorFilter.mode(colorOverlay, sky.TransferMode.srcATop); + paint.colorFilter = new ui.ColorFilter.mode(colorOverlay, ui.TransferMode.srcATop); } if (transferMode != null) { diff --git a/packages/flutter_sprites/lib/sprite_box.dart b/packages/flutter_sprites/lib/sprite_box.dart index 90f88c3b0e..8c1d06be33 100644 --- a/packages/flutter_sprites/lib/sprite_box.dart +++ b/packages/flutter_sprites/lib/sprite_box.dart @@ -185,11 +185,11 @@ class SpriteBox extends RenderBox { } } - void handleEvent(sky.Event event, _SpriteBoxHitTestEntry entry) { + void handleEvent(ui.Event event, _SpriteBoxHitTestEntry entry) { if (!attached) return; - if (event is sky.PointerEvent) { + if (event is ui.PointerEvent) { if (event.type == 'pointerdown') { // Build list of event targets diff --git a/packages/flutter_sprites/lib/spritesheet.dart b/packages/flutter_sprites/lib/spritesheet.dart index 7ec88fc67c..cbf3b50701 100644 --- a/packages/flutter_sprites/lib/spritesheet.dart +++ b/packages/flutter_sprites/lib/spritesheet.dart @@ -8,7 +8,7 @@ part of skysprites; /// the sprite sheet definition are used to reference the different textures. class SpriteSheet { - sky.Image _image; + ui.Image _image; Map _textures = new Map(); /// Creates a new sprite sheet from an [_image] and a sprite sheet [jsonDefinition]. @@ -65,7 +65,7 @@ class SpriteSheet { /// The image used by the sprite sheet. /// /// var spriteSheetImage = mySpriteSheet.image; - sky.Image get image => _image; + ui.Image get image => _image; /// Returns a texture by its name. /// diff --git a/packages/flutter_sprites/lib/texture.dart b/packages/flutter_sprites/lib/texture.dart index 40f41c6725..f690ae2f28 100644 --- a/packages/flutter_sprites/lib/texture.dart +++ b/packages/flutter_sprites/lib/texture.dart @@ -7,7 +7,7 @@ class Texture { /// The image that this texture is a part of. /// /// var textureImage = myTexture.image; - final sky.Image image; + final ui.Image image; /// The logical size of the texture, before being trimmed by the texture packer. /// @@ -51,7 +51,7 @@ class Texture { /// Creates a new texture from an [Image] object. /// /// var myTexture = new Texture(myImage); - Texture(sky.Image image) : + Texture(ui.Image image) : size = new Size(image.width.toDouble(), image.height.toDouble()), image = image, trimmed = false, diff --git a/packages/flutter_sprites/lib/textured_line.dart b/packages/flutter_sprites/lib/textured_line.dart index bf857d97c0..d35d960b4b 100644 --- a/packages/flutter_sprites/lib/textured_line.dart +++ b/packages/flutter_sprites/lib/textured_line.dart @@ -38,8 +38,8 @@ class TexturedLinePainter { _cachedPaint = new Paint(); } else { Matrix4 matrix = new Matrix4.identity(); - sky.ImageShader shader = new sky.ImageShader(texture.image, - sky.TileMode.repeated, sky.TileMode.repeated, matrix.storage); + ui.ImageShader shader = new ui.ImageShader(texture.image, + ui.TileMode.repeated, ui.TileMode.repeated, matrix.storage); _cachedPaint = new Paint(); _cachedPaint.setShader(shader); @@ -77,7 +77,7 @@ class TexturedLinePainter { bool removeArtifacts = true; - sky.TransferMode transferMode = sky.TransferMode.srcOver; + ui.TransferMode transferMode = ui.TransferMode.srcOver; Paint _cachedPaint = new Paint(); @@ -169,7 +169,7 @@ class TexturedLinePainter { lastMiter = currentMiter; } - canvas.drawVertices(sky.VertexMode.triangles, vertices, textureCoordinates, verticeColors, sky.TransferMode.modulate, indicies, _cachedPaint); + canvas.drawVertices(ui.VertexMode.triangles, vertices, textureCoordinates, verticeColors, ui.TransferMode.modulate, indicies, _cachedPaint); } double _xPosForStop(double stop) { diff --git a/packages/flutter_sprites/lib/virtual_joystick.dart b/packages/flutter_sprites/lib/virtual_joystick.dart index cf03531e27..1977f9f863 100644 --- a/packages/flutter_sprites/lib/virtual_joystick.dart +++ b/packages/flutter_sprites/lib/virtual_joystick.dart @@ -14,7 +14,7 @@ class VirtualJoystick extends NodeWithSize { _paintControl = new Paint() ..color=new Color(0xffffffff) ..strokeWidth = 1.0 - ..setStyle(sky.PaintingStyle.stroke); + ..setStyle(ui.PaintingStyle.stroke); } Point _value = Point.origin; diff --git a/packages/unit/test/engine/canvas_test.dart b/packages/unit/test/engine/canvas_test.dart index 31daaba371..d8fe050690 100644 --- a/packages/unit/test/engine/canvas_test.dart +++ b/packages/unit/test/engine/canvas_test.dart @@ -1,4 +1,4 @@ -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'dart:ui' show Rect, Color, Paint; import 'package:test/test.dart'; @@ -6,8 +6,8 @@ import 'package:vector_math/vector_math_64.dart'; void main() { - sky.PictureRecorder recorder = new sky.PictureRecorder(); - sky.Canvas canvas = new sky.Canvas(recorder, new Rect.fromLTRB(0.0, 0.0, 100.0, 100.0)); + ui.PictureRecorder recorder = new ui.PictureRecorder(); + ui.Canvas canvas = new ui.Canvas(recorder, new Rect.fromLTRB(0.0, 0.0, 100.0, 100.0)); test("matrix access should work", () { // Matrix equality doesn't work! diff --git a/packages/unit/test/engine/inline_style_test.dart b/packages/unit/test/engine/inline_style_test.dart index d8d0d6ec62..54ba7d5edc 100644 --- a/packages/unit/test/engine/inline_style_test.dart +++ b/packages/unit/test/engine/inline_style_test.dart @@ -1,11 +1,11 @@ -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'package:test/test.dart'; void main() { test('should be settable using "style" attribute', () { - sky.LayoutRoot layoutRoot = new sky.LayoutRoot(); - var document = new sky.Document(); + ui.LayoutRoot layoutRoot = new ui.LayoutRoot(); + var document = new ui.Document(); var foo = document.createElement('foo'); layoutRoot.rootElement = foo; @@ -16,8 +16,8 @@ void main() { }); test('should not crash when setting style to null', () { - sky.LayoutRoot layoutRoot = new sky.LayoutRoot(); - var document = new sky.Document(); + ui.LayoutRoot layoutRoot = new ui.LayoutRoot(); + var document = new ui.Document(); var foo = document.createElement('foo'); layoutRoot.rootElement = foo; diff --git a/packages/unit/test/engine/mock_events.dart b/packages/unit/test/engine/mock_events.dart index 7604b0f9af..53ddc9ea8e 100644 --- a/packages/unit/test/engine/mock_events.dart +++ b/packages/unit/test/engine/mock_events.dart @@ -1,8 +1,8 @@ -import 'dart:ui' as sky; +import 'dart:ui' as ui; export 'dart:ui' show Point; -class TestPointerEvent extends sky.PointerEvent { +class TestPointerEvent extends ui.PointerEvent { TestPointerEvent({ this.type, this.pointer, @@ -64,9 +64,9 @@ class TestPointer { int pointer; bool isDown = false; - sky.Point location; + ui.Point location; - sky.PointerEvent down([sky.Point newLocation = sky.Point.origin ]) { + ui.PointerEvent down([ui.Point newLocation = ui.Point.origin ]) { assert(!isDown); isDown = true; location = newLocation; @@ -78,9 +78,9 @@ class TestPointer { ); } - sky.PointerEvent move([sky.Point newLocation = sky.Point.origin ]) { + ui.PointerEvent move([ui.Point newLocation = ui.Point.origin ]) { assert(isDown); - sky.Offset delta = newLocation - location; + ui.Offset delta = newLocation - location; location = newLocation; return new TestPointerEvent( type: 'pointermove', @@ -92,7 +92,7 @@ class TestPointer { ); } - sky.PointerEvent up() { + ui.PointerEvent up() { assert(isDown); isDown = false; return new TestPointerEvent( @@ -103,7 +103,7 @@ class TestPointer { ); } - sky.PointerEvent cancel() { + ui.PointerEvent cancel() { assert(isDown); isDown = false; return new TestPointerEvent( diff --git a/packages/unit/test/engine/text_test.dart b/packages/unit/test/engine/text_test.dart index dcd92dfadc..b336df6411 100644 --- a/packages/unit/test/engine/text_test.dart +++ b/packages/unit/test/engine/text_test.dart @@ -1,10 +1,10 @@ -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'package:test/test.dart'; void main() { test("createText(null) shouldn't crash", () { - var doc = new sky.Document(); + var doc = new ui.Document(); doc.createText(null); }); } diff --git a/packages/unit/test/gestures/pointer_router_test.dart b/packages/unit/test/gestures/pointer_router_test.dart index 6c15896856..65f00838f4 100644 --- a/packages/unit/test/gestures/pointer_router_test.dart +++ b/packages/unit/test/gestures/pointer_router_test.dart @@ -1,4 +1,4 @@ -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'package:flutter/gestures.dart'; import 'package:test/test.dart'; @@ -8,7 +8,7 @@ import '../engine/mock_events.dart'; void main() { test('Should route pointers', () { bool callbackRan = false; - void callback(sky.PointerEvent event) { + void callback(ui.PointerEvent event) { callbackRan = true; } diff --git a/packages/unit/test/gestures/scale_test.dart b/packages/unit/test/gestures/scale_test.dart index be19bada54..9acec2c7a3 100644 --- a/packages/unit/test/gestures/scale_test.dart +++ b/packages/unit/test/gestures/scale_test.dart @@ -1,4 +1,4 @@ -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'package:flutter/gestures.dart'; import 'package:test/test.dart'; @@ -12,14 +12,14 @@ void main() { TapGestureRecognizer tap = new TapGestureRecognizer(router: router); bool didStartScale = false; - sky.Point updatedFocalPoint; - scale.onStart = (sky.Point focalPoint) { + ui.Point updatedFocalPoint; + scale.onStart = (ui.Point focalPoint) { didStartScale = true; updatedFocalPoint = focalPoint; }; double updatedScale; - scale.onUpdate = (double scale, sky.Point focalPoint) { + scale.onUpdate = (double scale, ui.Point focalPoint) { updatedScale = scale; updatedFocalPoint = focalPoint; }; @@ -36,7 +36,7 @@ void main() { TestPointer pointer1 = new TestPointer(1); - sky.PointerEvent down = pointer1.down(new Point(10.0, 10.0)); + ui.PointerEvent down = pointer1.down(new Point(10.0, 10.0)); scale.addPointer(down); tap.addPointer(down); @@ -58,7 +58,7 @@ void main() { router.route(pointer1.move(new Point(20.0, 30.0))); expect(didStartScale, isTrue); didStartScale = false; - expect(updatedFocalPoint, new sky.Point(20.0, 30.0)); + expect(updatedFocalPoint, new ui.Point(20.0, 30.0)); updatedFocalPoint = null; expect(updatedScale, 1.0); updatedScale = null; @@ -67,7 +67,7 @@ void main() { // Two-finger scaling TestPointer pointer2 = new TestPointer(2); - sky.PointerEvent down2 = pointer2.down(new Point(10.0, 20.0)); + ui.PointerEvent down2 = pointer2.down(new Point(10.0, 20.0)); scale.addPointer(down2); tap.addPointer(down2); GestureArena.instance.close(2); @@ -83,7 +83,7 @@ void main() { router.route(pointer2.move(new Point(0.0, 10.0))); expect(didStartScale, isTrue); didStartScale = false; - expect(updatedFocalPoint, new sky.Point(10.0, 20.0)); + expect(updatedFocalPoint, new ui.Point(10.0, 20.0)); updatedFocalPoint = null; expect(updatedScale, 2.0); updatedScale = null; @@ -92,7 +92,7 @@ void main() { // Zoom out router.route(pointer2.move(new Point(15.0, 25.0))); - expect(updatedFocalPoint, new sky.Point(17.5, 27.5)); + expect(updatedFocalPoint, new ui.Point(17.5, 27.5)); updatedFocalPoint = null; expect(updatedScale, 0.5); updatedScale = null; @@ -100,7 +100,7 @@ void main() { // Three-finger scaling TestPointer pointer3 = new TestPointer(3); - sky.PointerEvent down3 = pointer3.down(new Point(25.0, 35.0)); + ui.PointerEvent down3 = pointer3.down(new Point(25.0, 35.0)); scale.addPointer(down3); tap.addPointer(down3); GestureArena.instance.close(3); @@ -116,7 +116,7 @@ void main() { router.route(pointer3.move(new Point(55.0, 65.0))); expect(didStartScale, isTrue); didStartScale = false; - expect(updatedFocalPoint, new sky.Point(30.0, 40.0)); + expect(updatedFocalPoint, new ui.Point(30.0, 40.0)); updatedFocalPoint = null; expect(updatedScale, 5.0); updatedScale = null; @@ -128,7 +128,7 @@ void main() { router.route(pointer2.move(new Point(20.0, 30.0))); router.route(pointer3.move(new Point(15.0, 25.0))); expect(didStartScale, isFalse); - expect(updatedFocalPoint, new sky.Point(20.0, 30.0)); + expect(updatedFocalPoint, new ui.Point(20.0, 30.0)); updatedFocalPoint = null; expect(updatedScale, 1.0); updatedScale = null; @@ -147,7 +147,7 @@ void main() { router.route(pointer3.move(new Point(10.0, 20.0))); expect(didStartScale, isTrue); didStartScale = false; - expect(updatedFocalPoint, new sky.Point(15.0, 25.0)); + expect(updatedFocalPoint, new ui.Point(15.0, 25.0)); updatedFocalPoint = null; expect(updatedScale, 2.0); updatedScale = null; @@ -164,7 +164,7 @@ void main() { router.route(pointer3.move(new Point(0.0, 0.0))); expect(didStartScale, isTrue); didStartScale = false; - expect(updatedFocalPoint, new sky.Point(0.0, 0.0)); + expect(updatedFocalPoint, new ui.Point(0.0, 0.0)); updatedFocalPoint = null; expect(updatedScale, 1.0); updatedScale = null; diff --git a/packages/unit/test/gestures/scroll_test.dart b/packages/unit/test/gestures/scroll_test.dart index e29adafc76..e382ab37e5 100644 --- a/packages/unit/test/gestures/scroll_test.dart +++ b/packages/unit/test/gestures/scroll_test.dart @@ -1,4 +1,4 @@ -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'package:flutter/gestures.dart'; import 'package:test/test.dart'; @@ -16,13 +16,13 @@ void main() { didStartPan = true; }; - sky.Offset updatedScrollDelta; - pan.onUpdate = (sky.Offset offset) { + ui.Offset updatedScrollDelta; + pan.onUpdate = (ui.Offset offset) { updatedScrollDelta = offset; }; bool didEndPan = false; - pan.onEnd = (sky.Offset velocity) { + pan.onEnd = (ui.Offset velocity) { didEndPan = true; }; @@ -32,7 +32,7 @@ void main() { }; TestPointer pointer = new TestPointer(5); - sky.PointerEvent down = pointer.down(new Point(10.0, 10.0)); + ui.PointerEvent down = pointer.down(new Point(10.0, 10.0)); pan.addPointer(down); tap.addPointer(down); GestureArena.instance.close(5); @@ -50,14 +50,14 @@ void main() { router.route(pointer.move(new Point(20.0, 20.0))); expect(didStartPan, isTrue); didStartPan = false; - expect(updatedScrollDelta, new sky.Offset(10.0, 10.0)); + expect(updatedScrollDelta, new ui.Offset(10.0, 10.0)); updatedScrollDelta = null; expect(didEndPan, isFalse); expect(didTap, isFalse); router.route(pointer.move(new Point(20.0, 25.0))); expect(didStartPan, isFalse); - expect(updatedScrollDelta, new sky.Offset(0.0, 5.0)); + expect(updatedScrollDelta, new ui.Offset(0.0, 5.0)); updatedScrollDelta = null; expect(didEndPan, isFalse); expect(didTap, isFalse); diff --git a/packages/unit/test/rendering/image_test.dart b/packages/unit/test/rendering/image_test.dart index 2ee22468b6..b794f84a18 100644 --- a/packages/unit/test/rendering/image_test.dart +++ b/packages/unit/test/rendering/image_test.dart @@ -1,21 +1,21 @@ -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'package:flutter/rendering.dart'; import 'package:test/test.dart'; import 'rendering_tester.dart'; -class SquareImage implements sky.Image { +class SquareImage implements ui.Image { int get width => 10; int get height => 10; } -class WideImage implements sky.Image { +class WideImage implements ui.Image { int get width => 20; int get height => 10; } -class TallImage implements sky.Image { +class TallImage implements ui.Image { int get width => 10; int get height => 20; } diff --git a/packages/unit/test/widget/shader_mask_test.dart b/packages/unit/test/widget/shader_mask_test.dart index 379ff9b572..aa465abaa5 100644 --- a/packages/unit/test/widget/shader_mask_test.dart +++ b/packages/unit/test/widget/shader_mask_test.dart @@ -1,4 +1,4 @@ -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'package:flutter/painting.dart'; import 'package:flutter/widgets.dart'; @@ -6,7 +6,7 @@ import 'package:test/test.dart'; import 'widget_tester.dart'; -sky.Shader createShader(Rect bounds) { +ui.Shader createShader(Rect bounds) { return new LinearGradient( begin: Point.origin, end: new Point(0.0, bounds.height), diff --git a/packages/unit/test/widget/widget_tester.dart b/packages/unit/test/widget/widget_tester.dart index 284afb000b..5d6e57f4bd 100644 --- a/packages/unit/test/widget/widget_tester.dart +++ b/packages/unit/test/widget/widget_tester.dart @@ -1,4 +1,4 @@ -import 'dart:ui' as sky; +import 'dart:ui' as ui; import 'package:flutter/animation.dart'; import 'package:flutter/rendering.dart'; @@ -159,13 +159,13 @@ class WidgetTester { _dispatchEvent(p.up(), result); } - void dispatchEvent(sky.Event event, Point location) { + void dispatchEvent(ui.Event event, Point location) { _dispatchEvent(event, _hitTest(location)); } HitTestResult _hitTest(Point location) => WidgetFlutterBinding.instance.hitTest(location); - void _dispatchEvent(sky.Event event, HitTestResult result) { + void _dispatchEvent(ui.Event event, HitTestResult result) { WidgetFlutterBinding.instance.dispatchEvent(event, result); } diff --git a/packages/updater/lib/main.dart b/packages/updater/lib/main.dart index 5d0b0a6fcd..9a748eb6e1 100644 --- a/packages/updater/lib/main.dart +++ b/packages/updater/lib/main.dart @@ -14,7 +14,7 @@ import 'package:yaml/yaml.dart' as yaml; import 'version.dart'; import 'pipe_to_file.dart'; -const String kManifestFile = 'sky.yaml'; +const String kManifestFile = 'ui.yaml'; const String kBundleFile = 'app.skyx'; UpdateServiceProxy _initUpdateService() { From 4417049f78b71b3d30f3627fa65da25c732cac4d Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Fri, 9 Oct 2015 21:00:58 -0700 Subject: [PATCH 40/84] Update package:flutter pubspec --- packages/flutter/pubspec.yaml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/flutter/pubspec.yaml b/packages/flutter/pubspec.yaml index b3c9933bae..2ab9e9a707 100644 --- a/packages/flutter/pubspec.yaml +++ b/packages/flutter/pubspec.yaml @@ -1,18 +1,18 @@ name: flutter -version: 0.0.55 +version: 0.1.0 author: Flutter Authors description: A framework for writing Flutter applications homepage: http://flutter.io dependencies: - cassowary: ^0.1.7 - material_design_icons: ^0.0.3 + cassowary: '>=0.1.7 <0.2.0' + material_design_icons: '>=0.0.3 <0.1.0' mojo_services: '>=0.2.0 <0.3.0' mojo: '>=0.2.0 <0.3.0' - newton: ^0.1.4 - sky_engine: ^0.0.33 - sky_services: ^0.0.32 - sky_tools: ^0.0.15 - vector_math: ^1.4.3 - intl: ^0.12.4+2 + newton: '>=0.1.4 <0.2.0' + sky_engine: '>=0.0.33 <0.1.0' + sky_services: '>=0.0.33 <0.1.0' + sky_tools: '>=0.0.15 <0.1.0' + vector_math: '>=1.4.3 <2.0.0' + intl: '>=0.12.4+2 <0.13.0' environment: sdk: '>=1.12.0 <2.0.0' From 85d8f8c1b399389e43b7c511535e1a57f6ed0b07 Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Sat, 10 Oct 2015 00:42:26 -0700 Subject: [PATCH 41/84] Add a bin/flutter.dart to the flutter package This command will eventually become the main entrypoint for the Flutter tools. Also, fixup a reference to the "sky" package in sky_tool. --- packages/flutter/bin/flutter.dart | 7 +++++++ packages/flutter/lib/sky_tool | 12 ++++++------ packages/flutter/pubspec.yaml | 3 +++ 3 files changed, 16 insertions(+), 6 deletions(-) create mode 100644 packages/flutter/bin/flutter.dart diff --git a/packages/flutter/bin/flutter.dart b/packages/flutter/bin/flutter.dart new file mode 100644 index 0000000000..99338de253 --- /dev/null +++ b/packages/flutter/bin/flutter.dart @@ -0,0 +1,7 @@ +// 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_tools/executable.dart' as executable; + +main(List args) => executable.main(args); diff --git a/packages/flutter/lib/sky_tool b/packages/flutter/lib/sky_tool index 03049850fd..441f92538e 100755 --- a/packages/flutter/lib/sky_tool +++ b/packages/flutter/lib/sky_tool @@ -1255,15 +1255,15 @@ class SkyShellRunner(object): # Also make sure that args is consistent with machine state for local builds if args.local_build and args.sky_src_path is None: - real_sky_path = os.path.realpath(os.path.join(PACKAGES_DIR, 'sky')) - match = re.match(r'pub.dartlang.org/sky', real_sky_path) + real_flutter_path = os.path.realpath(os.path.join(PACKAGES_DIR, 'flutter')) + match = re.match(r'pub.dartlang.org/flutter', real_flutter_path) if match is not None: args.local_build = False else: sky_src_path = os.path.dirname( os.path.dirname( os.path.dirname( - os.path.dirname(real_sky_path)))) + os.path.dirname(real_flutter_path)))) if sky_src_path == '/' or sky_src_path == '': args.local_build = False else: @@ -1275,9 +1275,9 @@ class SkyShellRunner(object): 'to your pubspec.yaml file and then run pub get again:\n' 'dependency_overrides:\n' ' material_design_icons:\n' - ' path: /path/to/sky_engine/src/sky/packages/material_design_icons\n' - ' sky:\n' - ' path: /path/to/sky_engine/src/sky/packages/sky\n') + ' path: /path/to/flutter/engine/src/sky/packages/material_design_icons\n' + ' flutter:\n' + ' path: /path/to/flutter/engine/src/sky/packages/sky\n') if args.local_build: if not os.path.isdir(args.sky_src_path): logging.warning('The selected sky-src-path (' + args.sky_src_path + ') does not exist.' diff --git a/packages/flutter/pubspec.yaml b/packages/flutter/pubspec.yaml index 2ab9e9a707..e4101d9447 100644 --- a/packages/flutter/pubspec.yaml +++ b/packages/flutter/pubspec.yaml @@ -16,3 +16,6 @@ dependencies: intl: '>=0.12.4+2 <0.13.0' environment: sdk: '>=1.12.0 <2.0.0' + +executables: + flutter: From 760811e62b66a3247d14a564eaa508cc1dc61c18 Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Sat, 10 Oct 2015 00:52:32 -0700 Subject: [PATCH 42/84] Rev pub package --- packages/flutter/pubspec.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/flutter/pubspec.yaml b/packages/flutter/pubspec.yaml index 2ab9e9a707..fa862bb6b7 100644 --- a/packages/flutter/pubspec.yaml +++ b/packages/flutter/pubspec.yaml @@ -1,5 +1,5 @@ name: flutter -version: 0.1.0 +version: 0.0.2 author: Flutter Authors description: A framework for writing Flutter applications homepage: http://flutter.io @@ -9,8 +9,8 @@ dependencies: mojo_services: '>=0.2.0 <0.3.0' mojo: '>=0.2.0 <0.3.0' newton: '>=0.1.4 <0.2.0' - sky_engine: '>=0.0.33 <0.1.0' - sky_services: '>=0.0.33 <0.1.0' + sky_engine: '>=0.0.34 <0.1.0' + sky_services: '>=0.0.34 <0.1.0' sky_tools: '>=0.0.15 <0.1.0' vector_math: '>=1.4.3 <2.0.0' intl: '>=0.12.4+2 <0.13.0' From d1b7f175a58b59e35a971a1b72ba8d8b21c3a16a Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Sun, 11 Oct 2015 12:14:46 -0700 Subject: [PATCH 43/84] Rev pub package --- packages/flutter/pubspec.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/flutter/pubspec.yaml b/packages/flutter/pubspec.yaml index c6f2c3b3a7..a90aa09089 100644 --- a/packages/flutter/pubspec.yaml +++ b/packages/flutter/pubspec.yaml @@ -1,5 +1,5 @@ name: flutter -version: 0.0.2 +version: 0.0.3 author: Flutter Authors description: A framework for writing Flutter applications homepage: http://flutter.io @@ -11,7 +11,7 @@ dependencies: newton: '>=0.1.4 <0.2.0' sky_engine: '>=0.0.34 <0.1.0' sky_services: '>=0.0.34 <0.1.0' - sky_tools: '>=0.0.15 <0.1.0' + sky_tools: '>=0.0.18 <0.1.0' vector_math: '>=1.4.3 <2.0.0' intl: '>=0.12.4+2 <0.13.0' environment: From f9a7ed047d085b5e52e66c61f0e5a1339da1a783 Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Mon, 12 Oct 2015 00:24:24 -0700 Subject: [PATCH 44/84] Reattach fitness to the build We can build Fitness again now that playfair has been updated to account for the package:flutter rename. --- examples/BUILD.gn | 2 +- examples/address_book/pubspec.yaml | 2 +- examples/demo_launcher/BUILD.gn | 2 +- examples/demo_launcher/pubspec.yaml | 2 +- examples/fitness/pubspec.yaml | 6 +++--- examples/game/pubspec.yaml | 2 +- examples/hello_world/pubspec.yaml | 2 +- examples/mine_digger/pubspec.yaml | 2 +- examples/raw/pubspec.yaml | 2 +- examples/rendering/pubspec.yaml | 2 +- examples/stocks/pubspec.yaml | 2 +- examples/widgets/pubspec.yaml | 2 +- packages/flutter_sprites/pubspec.yaml | 4 ++-- packages/unit/pubspec.yaml | 2 +- packages/updater/pubspec.yaml | 2 +- 15 files changed, 18 insertions(+), 18 deletions(-) diff --git a/examples/BUILD.gn b/examples/BUILD.gn index f8061ae382..5ead42c2f1 100644 --- a/examples/BUILD.gn +++ b/examples/BUILD.gn @@ -7,7 +7,7 @@ group("examples") { deps = [ "//examples/demo_launcher", - #"//examples/fitness", + "//examples/fitness", "//examples/game", "//examples/mine_digger", "//examples/rendering", diff --git a/examples/address_book/pubspec.yaml b/examples/address_book/pubspec.yaml index 435112907b..30a73e7546 100644 --- a/examples/address_book/pubspec.yaml +++ b/examples/address_book/pubspec.yaml @@ -1,6 +1,6 @@ name: address_book dependencies: - flutter: any + flutter: ">=0.0.3 <0.1.0" sky_tools: any dependency_overrides: material_design_icons: diff --git a/examples/demo_launcher/BUILD.gn b/examples/demo_launcher/BUILD.gn index a934fb9932..a5cd5dae67 100644 --- a/examples/demo_launcher/BUILD.gn +++ b/examples/demo_launcher/BUILD.gn @@ -12,7 +12,7 @@ sky_app("demo_launcher") { apk_name = "SkyDemo" bundles = [ - #"//examples/fitness", + "//examples/fitness", "//examples/game", "//examples/mine_digger", "//examples/rendering:interactive_flex", diff --git a/examples/demo_launcher/pubspec.yaml b/examples/demo_launcher/pubspec.yaml index 637552c175..de60ccf7ab 100644 --- a/examples/demo_launcher/pubspec.yaml +++ b/examples/demo_launcher/pubspec.yaml @@ -1,6 +1,6 @@ name: demo_launcher dependencies: - flutter: any + flutter: ">=0.0.3 <0.1.0" sky_tools: any dependency_overrides: material_design_icons: diff --git a/examples/fitness/pubspec.yaml b/examples/fitness/pubspec.yaml index 2b8abd4804..c018dd7413 100644 --- a/examples/fitness/pubspec.yaml +++ b/examples/fitness/pubspec.yaml @@ -1,9 +1,9 @@ name: fitness dependencies: - flutter: any - sky_tools: any - playfair: ^0.0.9 + flutter: ">=0.0.3 <0.1.0" + playfair: ^0.0.10 path: ^1.3.6 + sky_tools: any dependency_overrides: material_design_icons: path: ../../sky/packages/material_design_icons diff --git a/examples/game/pubspec.yaml b/examples/game/pubspec.yaml index c7d1356b6d..346cb34c2e 100644 --- a/examples/game/pubspec.yaml +++ b/examples/game/pubspec.yaml @@ -1,6 +1,6 @@ name: asteroids dependencies: - flutter: any + flutter: ">=0.0.3 <0.1.0" sky_tools: any skysprites: any box2d: any diff --git a/examples/hello_world/pubspec.yaml b/examples/hello_world/pubspec.yaml index 6593305cb2..7cdd0bc0d6 100644 --- a/examples/hello_world/pubspec.yaml +++ b/examples/hello_world/pubspec.yaml @@ -1,6 +1,6 @@ name: hello_world dependencies: - flutter: any + flutter: ">=0.0.3 <0.1.0" sky_tools: any dependency_overrides: material_design_icons: diff --git a/examples/mine_digger/pubspec.yaml b/examples/mine_digger/pubspec.yaml index 739bf26ddd..b07705c15a 100644 --- a/examples/mine_digger/pubspec.yaml +++ b/examples/mine_digger/pubspec.yaml @@ -1,6 +1,6 @@ name: mine_digger dependencies: - flutter: any + flutter: ">=0.0.3 <0.1.0" sky_tools: any dependency_overrides: material_design_icons: diff --git a/examples/raw/pubspec.yaml b/examples/raw/pubspec.yaml index e4ac176448..02ca8c18af 100644 --- a/examples/raw/pubspec.yaml +++ b/examples/raw/pubspec.yaml @@ -1,6 +1,6 @@ name: raw dependencies: - flutter: any + flutter: ">=0.0.3 <0.1.0" sky_tools: any dependency_overrides: material_design_icons: diff --git a/examples/rendering/pubspec.yaml b/examples/rendering/pubspec.yaml index 72895ac050..0eb70a38f8 100644 --- a/examples/rendering/pubspec.yaml +++ b/examples/rendering/pubspec.yaml @@ -1,6 +1,6 @@ name: rendering dependencies: - flutter: any + flutter: ">=0.0.3 <0.1.0" sky_tools: any dependency_overrides: material_design_icons: diff --git a/examples/stocks/pubspec.yaml b/examples/stocks/pubspec.yaml index 23b2d38b84..2d1c0549f0 100644 --- a/examples/stocks/pubspec.yaml +++ b/examples/stocks/pubspec.yaml @@ -1,6 +1,6 @@ name: stocks dependencies: - flutter: any + flutter: ">=0.0.3 <0.1.0" sky_tools: any dependency_overrides: material_design_icons: diff --git a/examples/widgets/pubspec.yaml b/examples/widgets/pubspec.yaml index e4c55adc07..1a483612b6 100644 --- a/examples/widgets/pubspec.yaml +++ b/examples/widgets/pubspec.yaml @@ -1,6 +1,6 @@ name: widgets dependencies: - flutter: any + flutter: ">=0.0.3 <0.1.0" sky_tools: any dependency_overrides: material_design_icons: diff --git a/packages/flutter_sprites/pubspec.yaml b/packages/flutter_sprites/pubspec.yaml index 6ae19a67fb..d9ec7d32d4 100644 --- a/packages/flutter_sprites/pubspec.yaml +++ b/packages/flutter_sprites/pubspec.yaml @@ -4,8 +4,8 @@ version: 0.0.1 author: Flutter Authors homepage: http://flutter.io dependencies: - flutter: ">=0.0.36 < 0.1.0" - sky_tools: ">=0.0.10 < 0.1.0" + flutter: ">=0.0.3 <0.1.0" + sky_tools: ">=0.0.18 <0.1.0" box2d: any dependency_overrides: flutter: diff --git a/packages/unit/pubspec.yaml b/packages/unit/pubspec.yaml index 51606f08b6..1e6dbe2ca9 100644 --- a/packages/unit/pubspec.yaml +++ b/packages/unit/pubspec.yaml @@ -1,6 +1,6 @@ name: sky_unit_tests dependencies: - flutter: any + flutter: ">=0.0.3 <0.1.0" sky_tools: any test: any quiver: any diff --git a/packages/updater/pubspec.yaml b/packages/updater/pubspec.yaml index df78548785..198081cc74 100644 --- a/packages/updater/pubspec.yaml +++ b/packages/updater/pubspec.yaml @@ -5,7 +5,7 @@ description: The autoupdater for flutter homepage: http://flutter.io dependencies: mojo: '>=0.2.0 <0.3.0' - flutter: any + flutter: ">=0.0.3 <0.1.0" sky_services: any path: any yaml: any From 09665c0d7fb358b14ea1d7adb59ce1ea13b3a06b Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Mon, 12 Oct 2015 09:36:47 -0700 Subject: [PATCH 45/84] Change the default MaterialType to canvas Canvas is by far the most popular type of material by call site (and makes for a faster default because it doesn't have a RRect clip). --- examples/demo_launcher/lib/main.dart | 1 - examples/fitness/lib/feed.dart | 5 +---- examples/fitness/lib/meal.dart | 1 - examples/fitness/lib/measurement.dart | 1 - examples/fitness/lib/settings.dart | 1 - examples/stocks/lib/stock_list.dart | 1 - examples/stocks/lib/stock_settings.dart | 1 - examples/stocks/lib/stock_symbol_viewer.dart | 1 - examples/widgets/scale.dart | 1 - examples/widgets/sector.dart | 1 - packages/flutter/lib/src/material/dialog.dart | 1 + packages/flutter/lib/src/material/material.dart | 2 +- packages/flutter/lib/src/material/snack_bar.dart | 1 - 13 files changed, 3 insertions(+), 15 deletions(-) diff --git a/examples/demo_launcher/lib/main.dart b/examples/demo_launcher/lib/main.dart index 4d3be4e082..f2ed11c693 100644 --- a/examples/demo_launcher/lib/main.dart +++ b/examples/demo_launcher/lib/main.dart @@ -193,7 +193,6 @@ class DemoHome extends StatelessComponent { return new Scaffold( toolBar: new ToolBar(center: new Text('Sky Demos')), body: new Material( - type: MaterialType.canvas, child: new DemoList() ) ); diff --git a/examples/fitness/lib/feed.dart b/examples/fitness/lib/feed.dart index cf075f0f8a..cbb9922bed 100644 --- a/examples/fitness/lib/feed.dart +++ b/examples/fitness/lib/feed.dart @@ -15,7 +15,6 @@ class FitnessItemList extends StatelessComponent { Widget build(BuildContext context) { return new Material( - type: MaterialType.canvas, child: new ScrollableList( padding: const EdgeDims.all(4.0), items: items, @@ -172,10 +171,9 @@ class FeedFragmentState extends State { Widget buildBody() { TextStyle style = Theme.of(context).text.title; if (config.userData == null) - return new Material(type: MaterialType.canvas); + return new Material(); if (config.userData.items.length == 0) return new Material( - type: MaterialType.canvas, child: new Row( [new Text("No data yet.\nAdd some!", style: style)], justifyContent: FlexJustifyContent.center @@ -189,7 +187,6 @@ class FeedFragmentState extends State { ); case FitnessMode.chart: return new Material( - type: MaterialType.canvas, child: new Container( padding: const EdgeDims.all(20.0), child: buildChart() diff --git a/examples/fitness/lib/meal.dart b/examples/fitness/lib/meal.dart index f7e94f06ab..ea96b91ba6 100644 --- a/examples/fitness/lib/meal.dart +++ b/examples/fitness/lib/meal.dart @@ -86,7 +86,6 @@ class MealFragmentState extends State { Widget buildBody() { Meal meal = new Meal(when: new DateTime.now()); return new Material( - type: MaterialType.canvas, child: new ScrollableViewport( child: new Container( padding: const EdgeDims.all(20.0), diff --git a/examples/fitness/lib/measurement.dart b/examples/fitness/lib/measurement.dart index 5adbca1f69..83b8c88cc0 100644 --- a/examples/fitness/lib/measurement.dart +++ b/examples/fitness/lib/measurement.dart @@ -173,7 +173,6 @@ class MeasurementFragmentState extends State { Measurement measurement = new Measurement(when: _when); // TODO(jackson): Revisit the layout of this pane to be more maintainable return new Material( - type: MaterialType.canvas, child: new Container( padding: const EdgeDims.all(20.0), child: new Column([ diff --git a/examples/fitness/lib/settings.dart b/examples/fitness/lib/settings.dart index 9831818340..5c6035290f 100644 --- a/examples/fitness/lib/settings.dart +++ b/examples/fitness/lib/settings.dart @@ -93,7 +93,6 @@ class SettingsFragmentState extends State { Widget buildSettingsPane(BuildContext context) { return new Material( - type: MaterialType.canvas, child: new ScrollableViewport( child: new Container( padding: const EdgeDims.symmetric(vertical: 20.0), diff --git a/examples/stocks/lib/stock_list.dart b/examples/stocks/lib/stock_list.dart index 54c55c0885..c49078626b 100644 --- a/examples/stocks/lib/stock_list.dart +++ b/examples/stocks/lib/stock_list.dart @@ -13,7 +13,6 @@ class StockList extends StatelessComponent { Widget build(BuildContext context) { return new Material( - type: MaterialType.canvas, child: new ScrollableList( items: stocks, itemExtent: StockRow.kHeight, diff --git a/examples/stocks/lib/stock_settings.dart b/examples/stocks/lib/stock_settings.dart index 3686a737ff..1be3c8266c 100644 --- a/examples/stocks/lib/stock_settings.dart +++ b/examples/stocks/lib/stock_settings.dart @@ -84,7 +84,6 @@ class StockSettingsState extends State { // TODO(ianh): Once we have the gesture API hooked up, fix https://github.com/domokit/mojo/issues/281 // (whereby tapping the widgets below causes both the widget and the menu item to fire their callbacks) return new Material( - type: MaterialType.canvas, child: new ScrollableViewport( child: new Container( padding: const EdgeDims.symmetric(vertical: 20.0), diff --git a/examples/stocks/lib/stock_symbol_viewer.dart b/examples/stocks/lib/stock_symbol_viewer.dart index f2407c0820..3f73b08a19 100644 --- a/examples/stocks/lib/stock_symbol_viewer.dart +++ b/examples/stocks/lib/stock_symbol_viewer.dart @@ -33,7 +33,6 @@ class StockSymbolViewerState extends State { center: new Text('${config.stock.name} (${config.stock.symbol})') ), body: new Material( - type: MaterialType.canvas, child: new Block([ new Container( padding: new EdgeDims.all(20.0), diff --git a/examples/widgets/scale.dart b/examples/widgets/scale.dart index 47824c82fa..03c1b92c13 100644 --- a/examples/widgets/scale.dart +++ b/examples/widgets/scale.dart @@ -61,7 +61,6 @@ class ScaleAppState extends State { toolBar: new ToolBar( center: new Text('Scale Demo')), body: new Material( - type: MaterialType.canvas, child: new GestureDetector( onScaleStart: _handleScaleStart, onScaleUpdate: _handleScaleUpdate, diff --git a/examples/widgets/sector.dart b/examples/widgets/sector.dart index 624ba1541b..0b7812118e 100644 --- a/examples/widgets/sector.dart +++ b/examples/widgets/sector.dart @@ -65,7 +65,6 @@ class SectorApp extends MaterialApp { Widget buildBody() { return new Material( - type: MaterialType.canvas, child: new Column([ new Container( padding: new EdgeDims.symmetric(horizontal: 8.0, vertical: 25.0), diff --git a/packages/flutter/lib/src/material/dialog.dart b/packages/flutter/lib/src/material/dialog.dart index 596ceb61f6..1f60f36f96 100644 --- a/packages/flutter/lib/src/material/dialog.dart +++ b/packages/flutter/lib/src/material/dialog.dart @@ -118,6 +118,7 @@ class Dialog extends StatelessComponent { child: new Material( level: 4, color: _getColor(context), + type: MaterialType.card, child: new IntrinsicWidth( child: new Block(dialogBody) ) diff --git a/packages/flutter/lib/src/material/material.dart b/packages/flutter/lib/src/material/material.dart index 03080432d2..dcfbd2113a 100644 --- a/packages/flutter/lib/src/material/material.dart +++ b/packages/flutter/lib/src/material/material.dart @@ -23,7 +23,7 @@ class Material extends StatelessComponent { Material({ Key key, this.child, - this.type: MaterialType.card, + this.type: MaterialType.canvas, this.level: 0, this.color, this.textStyle diff --git a/packages/flutter/lib/src/material/snack_bar.dart b/packages/flutter/lib/src/material/snack_bar.dart index 7aa793e229..8b631d0ce4 100644 --- a/packages/flutter/lib/src/material/snack_bar.dart +++ b/packages/flutter/lib/src/material/snack_bar.dart @@ -79,7 +79,6 @@ class SnackBar extends StatelessComponent { child: new Material( level: 2, color: _kSnackBackground, - type: MaterialType.canvas, child: new Container( margin: const EdgeDims.symmetric(horizontal: _kSideMargins), child: new DefaultTextStyle( From a1d554a575114f6ce8c793ea026df68a181d0574 Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Mon, 12 Oct 2015 10:09:57 -0700 Subject: [PATCH 46/84] Update arrow in stocks search to use ColorFilter We changed IconButton to require a ColorFilter to filter the color of the icon. --- examples/raw/painting.dart | 2 +- examples/stocks/lib/stock_home.dart | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/raw/painting.dart b/examples/raw/painting.dart index d02e9583f4..e43299f86c 100644 --- a/examples/raw/painting.dart +++ b/examples/raw/painting.dart @@ -83,7 +83,7 @@ ui.Picture paint(ui.Rect paintBounds) { ui.Scene composite(ui.Picture picture, ui.Rect paintBounds) { final double devicePixelRatio = ui.view.devicePixelRatio; ui.Rect sceneBounds = new ui.Rect.fromLTWH(0.0, 0.0, ui.view.width * devicePixelRatio, ui.view.height * devicePixelRatio); - Float32List deviceTransform = new Float32List(16) + Float64List deviceTransform = new Float64List(16) ..[0] = devicePixelRatio ..[5] = devicePixelRatio ..[10] = 1.0 diff --git a/examples/stocks/lib/stock_home.dart b/examples/stocks/lib/stock_home.dart index 5d3bbcf790..b42f035783 100644 --- a/examples/stocks/lib/stock_home.dart +++ b/examples/stocks/lib/stock_home.dart @@ -224,7 +224,7 @@ class StockHomeState extends State { return new ToolBar( left: new IconButton( icon: "navigation/arrow_back", - color: Theme.of(context).accentColor, + colorFilter: new ui.ColorFilter.mode(Theme.of(context).accentColor, ui.TransferMode.srcATop), onPressed: _handleSearchEnd ), center: new Input( From 5f907780ff13c26004e579e8774588cdce6782b6 Mon Sep 17 00:00:00 2001 From: Viktor Lidholt Date: Mon, 12 Oct 2015 13:39:20 -0700 Subject: [PATCH 47/84] Working joints in sprite physics --- .../flutter_sprites/lib/physics_joint.dart | 59 +++++++++++++------ .../flutter_sprites/lib/physics_node.dart | 4 +- 2 files changed, 43 insertions(+), 20 deletions(-) diff --git a/packages/flutter_sprites/lib/physics_joint.dart b/packages/flutter_sprites/lib/physics_joint.dart index cecdd5c581..7eaa5cec30 100644 --- a/packages/flutter_sprites/lib/physics_joint.dart +++ b/packages/flutter_sprites/lib/physics_joint.dart @@ -4,10 +4,6 @@ abstract class PhysicsJoint { PhysicsJoint(this.bodyA, this.bodyB) { bodyA._joints.add(this); bodyB._joints.add(this); - - if (bodyA._attached && bodyB._attached) { - _attach(bodyA._physicsNode); - } } PhysicsBody bodyA; @@ -18,6 +14,12 @@ abstract class PhysicsJoint { PhysicsNode _physicsNode; + void _completeCreation() { + if (bodyA._attached && bodyB._attached) { + _attach(bodyA._physicsNode); + } + } + void _attach(PhysicsNode physicsNode) { if (_joint == null) { _physicsNode = physicsNode; @@ -40,7 +42,7 @@ class PhysicsJointRevolute extends PhysicsJoint { PhysicsJointRevolute( PhysicsBody bodyA, PhysicsBody bodyB, - this.anchorWorld, { + this.worldAnchor, { double lowerAngle: 0.0, double upperAngle: 0.0, bool enableLimit: false @@ -48,9 +50,11 @@ class PhysicsJointRevolute extends PhysicsJoint { this.lowerAngle = lowerAngle; this.upperAngle = upperAngle; this.enableLimit = enableLimit; + + _completeCreation(); } - Point anchorWorld; + Point worldAnchor; double lowerAngle; double upperAngle; bool enableLimit; @@ -58,8 +62,8 @@ class PhysicsJointRevolute extends PhysicsJoint { box2d.Joint _createB2Joint(PhysicsNode physicsNode) { // Create Joint Definition Vector2 vecAnchor = new Vector2( - anchorWorld.x / physicsNode.b2WorldToNodeConversionFactor, - anchorWorld.y / physicsNode.b2WorldToNodeConversionFactor + worldAnchor.x / physicsNode.b2WorldToNodeConversionFactor, + worldAnchor.y / physicsNode.b2WorldToNodeConversionFactor ); box2d.RevoluteJointDef b2Def = new box2d.RevoluteJointDef(); @@ -73,18 +77,37 @@ class PhysicsJointRevolute extends PhysicsJoint { } } +class PhysicsJointPrismatic extends PhysicsJoint { + PhysicsJointPrismatic( + PhysicsBody bodyA, + PhysicsBody bodyB, + this.axis) : super(bodyA, bodyB) { + _completeCreation(); + } + + Offset axis; + + box2d.Joint _createB2Joint(PhysicsNode physicsNode) { + box2d.PrismaticJointDef b2Def = new box2d.PrismaticJointDef(); + b2Def.initialize(bodyA._body, bodyB._body, bodyA._body.position, new Vector2(axis.dx, axis.dy)); + return physicsNode.b2World.createJoint(b2Def); + } +} + class PhysicsJointWeld extends PhysicsJoint { PhysicsJointWeld( PhysicsBody bodyA, - PhysicsBody bodyB) : super(bodyA, bodyB); + PhysicsBody bodyB) : super(bodyA, bodyB) { + _completeCreation(); + } - box2d.Joint _createB2Joint(PhysicsNode physicsNode) { - box2d.WeldJointDef b2Def = new box2d.WeldJointDef(); - Vector2 middle = new Vector2( - (bodyA._body.position.x + bodyB._body.position.x) / 2.0, - (bodyA._body.position.y + bodyB._body.position.y) / 2.0 - ); - b2Def.initialize(bodyA._body, bodyB._body, middle); - return physicsNode.b2World.createJoint(b2Def); - } + box2d.Joint _createB2Joint(PhysicsNode physicsNode) { + box2d.WeldJointDef b2Def = new box2d.WeldJointDef(); + Vector2 middle = new Vector2( + (bodyA._body.position.x + bodyB._body.position.x) / 2.0, + (bodyA._body.position.y + bodyB._body.position.y) / 2.0 + ); + b2Def.initialize(bodyA._body, bodyB._body, middle); + return physicsNode.b2World.createJoint(b2Def); + } } diff --git a/packages/flutter_sprites/lib/physics_node.dart b/packages/flutter_sprites/lib/physics_node.dart index 57811e75cf..9cfe8776c3 100644 --- a/packages/flutter_sprites/lib/physics_node.dart +++ b/packages/flutter_sprites/lib/physics_node.dart @@ -33,7 +33,7 @@ class PhysicsNode extends Node { List _bodiesScheduledForDestruction = []; - double b2WorldToNodeConversionFactor = 500.0; + double b2WorldToNodeConversionFactor = 10.0; Offset get gravity { Vector2 g = b2World.getGravity(); @@ -282,7 +282,7 @@ class PhysicsNode extends Node { // Draw the joint depending on type box2d.JointType type = joint.getType(); - if (type == box2d.JointType.WELD) { + if (type == box2d.JointType.WELD || type == box2d.JointType.REVOLUTE) { // Draw weld joint canvas.drawCircle(ptAnchorA, 5.0, shapePaint); From 4e787993910f21be8af7ca6e0642bcd5628c010d Mon Sep 17 00:00:00 2001 From: Viktor Lidholt Date: Mon, 12 Oct 2015 13:39:47 -0700 Subject: [PATCH 48/84] Updates sprite physics test --- examples/game/test_physics.dart | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/examples/game/test_physics.dart b/examples/game/test_physics.dart index 4c2ecc10b6..78f257455c 100644 --- a/examples/game/test_physics.dart +++ b/examples/game/test_physics.dart @@ -78,29 +78,33 @@ class TestBed extends NodeWithSize { Sprite shipA; shipA = new Sprite(_spriteSheet["ship.png"]); + shipA.opacity = 0.3; shipA.position = new Point(pos.x - 40.0, pos.y); shipA.size = new Size(64.0, 64.0); shipA.physicsBody = new PhysicsBody(new PhysicsShapeCircle(Point.origin, 32.0), friction: 0.5, + restitution: 0.5, tag: "ship" ); _physicsNode.addChild(shipA); shipA.physicsBody.applyLinearImpulse( - new Offset(randomSignedDouble() * 5.0, randomSignedDouble() * 5.0), + new Offset(randomSignedDouble() * 5000.0, randomSignedDouble() * 5000.0), shipA.position ); Sprite shipB; shipB = new Sprite(_spriteSheet["ship.png"]); + shipB.opacity = 0.3; shipB.position = new Point(pos.x + 40.0, pos.y); shipB.size = new Size(64.0, 64.0); shipB.physicsBody = new PhysicsBody(new PhysicsShapePolygon([new Point(-25.0, -25.0), new Point(25.0, -25.0), new Point(25.0, 25.0), new Point(-25.0, 25.0)]), friction: 0.5, + restitution: 0.5, tag: "ship" ); _physicsNode.addChild(shipB); - new PhysicsJointWeld(shipA.physicsBody, shipB.physicsBody); + new PhysicsJointRevolute(shipA.physicsBody, shipB.physicsBody, pos); } return true; } From bb9cf6d78b7147c6e9ac31147b8f0427ad89a22b Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Mon, 12 Oct 2015 13:45:33 -0700 Subject: [PATCH 49/84] Add .old extension to silence analyzer These examples haven't been ported to fn3 yet. Before this patch, they caused a lot of noise in the analyzer output. --- examples/game/test_performance.dart | 2 +- .../widgets/{ensure_visible.dart => ensure_visible.dart.old} | 0 examples/widgets/{sector.dart => sector.dart.old} | 0 .../widgets/{spinning_mixed.dart => spinning_mixed.dart.old} | 0 4 files changed, 1 insertion(+), 1 deletion(-) rename examples/widgets/{ensure_visible.dart => ensure_visible.dart.old} (100%) rename examples/widgets/{sector.dart => sector.dart.old} (100%) rename examples/widgets/{spinning_mixed.dart => spinning_mixed.dart.old} (100%) diff --git a/examples/game/test_performance.dart b/examples/game/test_performance.dart index 3e90fee3d0..3fddd44d86 100644 --- a/examples/game/test_performance.dart +++ b/examples/game/test_performance.dart @@ -37,7 +37,7 @@ main() async { title: 'Test Sprite Performance', theme: _theme, routes: { - '/': (NavigatorState navigator, RouteState route) { + '/': (RouteArguments args) { return new SpriteWidget(new TestPerformance()); } } diff --git a/examples/widgets/ensure_visible.dart b/examples/widgets/ensure_visible.dart.old similarity index 100% rename from examples/widgets/ensure_visible.dart rename to examples/widgets/ensure_visible.dart.old diff --git a/examples/widgets/sector.dart b/examples/widgets/sector.dart.old similarity index 100% rename from examples/widgets/sector.dart rename to examples/widgets/sector.dart.old diff --git a/examples/widgets/spinning_mixed.dart b/examples/widgets/spinning_mixed.dart.old similarity index 100% rename from examples/widgets/spinning_mixed.dart rename to examples/widgets/spinning_mixed.dart.old From 5a7d21675aa238e7799220784542d51ee7e66a48 Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Mon, 12 Oct 2015 14:20:28 -0700 Subject: [PATCH 50/84] Remove demo_launcher This example is outdated. --- examples/BUILD.gn | 3 - examples/demo_launcher/BUILD.gn | 28 --- .../demo_launcher/apk/AndroidManifest.xml | 20 -- examples/demo_launcher/apk/BUILD.gn | 27 --- examples/demo_launcher/apk/README.md | 8 - .../org/domokit/sky/demo/SkyDemoActivity.java | 31 --- .../domokit/sky/demo/SkyDemoApplication.java | 30 --- .../apk/release_notes/0.0.18.txt | 1 - .../apk/release_notes/0.0.19.txt | 7 - .../apk/release_notes/0.0.20.txt | 1 - .../apk/release_notes/0.0.21.txt | 3 - .../apk/release_notes/0.0.22.txt | 2 - .../apk/release_notes/0.0.23.txt | 3 - .../apk/release_notes/0.0.24.txt | 1 - .../apk/res/mipmap-hdpi/ic_launcher.png | Bin 6242 -> 0 bytes .../apk/res/mipmap-mdpi/ic_launcher.png | Bin 3340 -> 0 bytes .../apk/res/mipmap-xhdpi/ic_launcher.png | Bin 9573 -> 0 bytes .../apk/res/mipmap-xxhdpi/ic_launcher.png | Bin 17306 -> 0 bytes .../apk/res/mipmap-xxxhdpi/ic_launcher.png | Bin 26588 -> 0 bytes .../demo_launcher/assets/game_thumbnail.png | Bin 286354 -> 0 bytes .../demo_launcher/assets/sector_thumbnail.png | Bin 24278 -> 0 bytes .../demo_launcher/assets/stocks_thumbnail.png | Bin 57860 -> 0 bytes examples/demo_launcher/lib/main.dart | 210 ------------------ examples/demo_launcher/pubspec.yaml | 9 - examples/demo_launcher/sky.yaml | 4 - examples/rendering/BUILD.gn | 17 -- examples/widgets/BUILD.gn | 27 --- 27 files changed, 432 deletions(-) delete mode 100644 examples/demo_launcher/BUILD.gn delete mode 100644 examples/demo_launcher/apk/AndroidManifest.xml delete mode 100644 examples/demo_launcher/apk/BUILD.gn delete mode 100644 examples/demo_launcher/apk/README.md delete mode 100644 examples/demo_launcher/apk/org/domokit/sky/demo/SkyDemoActivity.java delete mode 100644 examples/demo_launcher/apk/org/domokit/sky/demo/SkyDemoApplication.java delete mode 100644 examples/demo_launcher/apk/release_notes/0.0.18.txt delete mode 100644 examples/demo_launcher/apk/release_notes/0.0.19.txt delete mode 100644 examples/demo_launcher/apk/release_notes/0.0.20.txt delete mode 100644 examples/demo_launcher/apk/release_notes/0.0.21.txt delete mode 100644 examples/demo_launcher/apk/release_notes/0.0.22.txt delete mode 100644 examples/demo_launcher/apk/release_notes/0.0.23.txt delete mode 100644 examples/demo_launcher/apk/release_notes/0.0.24.txt delete mode 100644 examples/demo_launcher/apk/res/mipmap-hdpi/ic_launcher.png delete mode 100644 examples/demo_launcher/apk/res/mipmap-mdpi/ic_launcher.png delete mode 100644 examples/demo_launcher/apk/res/mipmap-xhdpi/ic_launcher.png delete mode 100644 examples/demo_launcher/apk/res/mipmap-xxhdpi/ic_launcher.png delete mode 100644 examples/demo_launcher/apk/res/mipmap-xxxhdpi/ic_launcher.png delete mode 100644 examples/demo_launcher/assets/game_thumbnail.png delete mode 100644 examples/demo_launcher/assets/sector_thumbnail.png delete mode 100644 examples/demo_launcher/assets/stocks_thumbnail.png delete mode 100644 examples/demo_launcher/lib/main.dart delete mode 100644 examples/demo_launcher/pubspec.yaml delete mode 100644 examples/demo_launcher/sky.yaml delete mode 100644 examples/rendering/BUILD.gn delete mode 100644 examples/widgets/BUILD.gn diff --git a/examples/BUILD.gn b/examples/BUILD.gn index 5ead42c2f1..01a2d5f84f 100644 --- a/examples/BUILD.gn +++ b/examples/BUILD.gn @@ -6,12 +6,9 @@ group("examples") { testonly = true deps = [ - "//examples/demo_launcher", "//examples/fitness", "//examples/game", "//examples/mine_digger", - "//examples/rendering", "//examples/stocks", - "//examples/widgets", ] } diff --git a/examples/demo_launcher/BUILD.gn b/examples/demo_launcher/BUILD.gn deleted file mode 100644 index a5cd5dae67..0000000000 --- a/examples/demo_launcher/BUILD.gn +++ /dev/null @@ -1,28 +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("//sky/build/sky_app.gni") - -sky_app("demo_launcher") { - main_dart = "lib/main.dart" - manifest = "sky.yaml" - - if (is_android) { - apk_name = "SkyDemo" - - bundles = [ - "//examples/fitness", - "//examples/game", - "//examples/mine_digger", - "//examples/rendering:interactive_flex", - "//examples/stocks", - "//examples/widgets:cards", - ] - - deps = [ - "//examples/demo_launcher/apk:java", - "//examples/demo_launcher/apk:resources", - ] - } -} diff --git a/examples/demo_launcher/apk/AndroidManifest.xml b/examples/demo_launcher/apk/AndroidManifest.xml deleted file mode 100644 index ec14badc14..0000000000 --- a/examples/demo_launcher/apk/AndroidManifest.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/examples/demo_launcher/apk/BUILD.gn b/examples/demo_launcher/apk/BUILD.gn deleted file mode 100644 index ae2e77e1ba..0000000000 --- a/examples/demo_launcher/apk/BUILD.gn +++ /dev/null @@ -1,27 +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. - -assert(is_android) - -import("//build/config/android/config.gni") -import("//build/config/android/rules.gni") - -android_library("java") { - java_files = [ - "org/domokit/sky/demo/SkyDemoActivity.java", - "org/domokit/sky/demo/SkyDemoApplication.java", - ] - - deps = [ - "//base:base_java", - "//mojo/public/java:bindings", - "//mojo/public/java:system", - "//sky/shell:java", - ] -} - -android_resources("resources") { - resource_dirs = [ "res" ] - android_manifest = "AndroidManifest.xml" -} diff --git a/examples/demo_launcher/apk/README.md b/examples/demo_launcher/apk/README.md deleted file mode 100644 index 6bde0ac995..0000000000 --- a/examples/demo_launcher/apk/README.md +++ /dev/null @@ -1,8 +0,0 @@ -Icon image comes from: -https://openclipart.org/detail/30073/tango%20weather%20few%20clouds -and is public domain. - -Icon resources were generated using: -http://romannurik.github.io/AndroidAssetStudio/icons-launcher.html -which produces art under CC 3.0: -http://creativecommons.org/licenses/by/3.0/ diff --git a/examples/demo_launcher/apk/org/domokit/sky/demo/SkyDemoActivity.java b/examples/demo_launcher/apk/org/domokit/sky/demo/SkyDemoActivity.java deleted file mode 100644 index ad97c69be8..0000000000 --- a/examples/demo_launcher/apk/org/domokit/sky/demo/SkyDemoActivity.java +++ /dev/null @@ -1,31 +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. - -package org.domokit.sky.demo; - -import android.content.Intent; - -import org.domokit.sky.shell.SkyActivity; - -/** - * Main activity for SkyDemo. - */ -public class SkyDemoActivity extends SkyActivity { - @Override - protected void onSkyReady() { - Intent intent = getIntent(); - String action = intent.getAction(); - - if (Intent.ACTION_VIEW.equals(action)) { - String bundleName = intent.getStringExtra("bundleName"); - if (bundleName != null && loadBundleByName(bundleName)) { - return; - } - loadUrl(intent.getDataString()); - return; - } - - super.onSkyReady(); - } -} diff --git a/examples/demo_launcher/apk/org/domokit/sky/demo/SkyDemoApplication.java b/examples/demo_launcher/apk/org/domokit/sky/demo/SkyDemoApplication.java deleted file mode 100644 index 48f8a15622..0000000000 --- a/examples/demo_launcher/apk/org/domokit/sky/demo/SkyDemoApplication.java +++ /dev/null @@ -1,30 +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. - -package org.domokit.sky.demo; - -import android.content.Context; - -import org.domokit.sky.shell.ResourceExtractor; -import org.domokit.sky.shell.SkyApplication; - -/** - * SkyDemo implementation of {@link android.app.Application} - */ -public class SkyDemoApplication extends SkyApplication { - private static final String[] DEMO_RESOURCES = { - "cards.skyx", - "fitness.skyx", - "game.skyx", - "interactive_flex.skyx", - "mine_digger.skyx", - "stocks.skyx", - }; - - @Override - protected void onBeforeResourceExtraction(ResourceExtractor extractor) { - super.onBeforeResourceExtraction(extractor); - extractor.addResources(DEMO_RESOURCES); - } -} diff --git a/examples/demo_launcher/apk/release_notes/0.0.18.txt b/examples/demo_launcher/apk/release_notes/0.0.18.txt deleted file mode 100644 index 023b7f6281..0000000000 --- a/examples/demo_launcher/apk/release_notes/0.0.18.txt +++ /dev/null @@ -1 +0,0 @@ -First version published to production from our service account. \ No newline at end of file diff --git a/examples/demo_launcher/apk/release_notes/0.0.19.txt b/examples/demo_launcher/apk/release_notes/0.0.19.txt deleted file mode 100644 index 8756530cb9..0000000000 --- a/examples/demo_launcher/apk/release_notes/0.0.19.txt +++ /dev/null @@ -1,7 +0,0 @@ -Fixed a common startup crasher on Android systems before 5.0 -Fixed to not draw behind the status bar on before Android 5.0 -First release from new http://github.com/domokit/sky_engine repository. - -I suspect there may still be some crashes we will be fixing -in the coming days as we set up systems to catch these crashes -before they are shipped to users. diff --git a/examples/demo_launcher/apk/release_notes/0.0.20.txt b/examples/demo_launcher/apk/release_notes/0.0.20.txt deleted file mode 100644 index 1deb9ce393..0000000000 --- a/examples/demo_launcher/apk/release_notes/0.0.20.txt +++ /dev/null @@ -1 +0,0 @@ -Fixes crash on Nexus 6 diff --git a/examples/demo_launcher/apk/release_notes/0.0.21.txt b/examples/demo_launcher/apk/release_notes/0.0.21.txt deleted file mode 100644 index d3b495f7b5..0000000000 --- a/examples/demo_launcher/apk/release_notes/0.0.21.txt +++ /dev/null @@ -1,3 +0,0 @@ -Huge speed improvements in Asteroids. -Fixed startup crash on many devices. -Lots of various other widget fixes. diff --git a/examples/demo_launcher/apk/release_notes/0.0.22.txt b/examples/demo_launcher/apk/release_notes/0.0.22.txt deleted file mode 100644 index a85c10a236..0000000000 --- a/examples/demo_launcher/apk/release_notes/0.0.22.txt +++ /dev/null @@ -1,2 +0,0 @@ -- No longer crashes on Android M Developer Preview -- 3x scrolling speed improvement. diff --git a/examples/demo_launcher/apk/release_notes/0.0.23.txt b/examples/demo_launcher/apk/release_notes/0.0.23.txt deleted file mode 100644 index 7e60f6e4c4..0000000000 --- a/examples/demo_launcher/apk/release_notes/0.0.23.txt +++ /dev/null @@ -1,3 +0,0 @@ -Small updates for various demos -Asteroids has sounds, Fitness has charting, etc. -This app is slowly being replaced by publishing individual apps. diff --git a/examples/demo_launcher/apk/release_notes/0.0.24.txt b/examples/demo_launcher/apk/release_notes/0.0.24.txt deleted file mode 100644 index df1f09a2e7..0000000000 --- a/examples/demo_launcher/apk/release_notes/0.0.24.txt +++ /dev/null @@ -1 +0,0 @@ -Minor updates to various demos including game. diff --git a/examples/demo_launcher/apk/res/mipmap-hdpi/ic_launcher.png b/examples/demo_launcher/apk/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index b34d8110b156efe6d987308f78a020edcfe4d2da..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6242 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 M07*qoM6N<$f_5AGVgLXD diff --git a/examples/demo_launcher/apk/res/mipmap-mdpi/ic_launcher.png b/examples/demo_launcher/apk/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index 7c42388c4dfb26db12246d792313598f23210e48..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3340 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 W^YV+Hsp@M00000y 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 FV1i~tN|XQq diff --git a/examples/demo_launcher/apk/res/mipmap-xxxhdpi/ic_launcher.png b/examples/demo_launcher/apk/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index 8c4b3686eaf26f0a0cfa764b924031e9e54fd37b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26588 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 diff --git a/examples/demo_launcher/assets/game_thumbnail.png b/examples/demo_launcher/assets/game_thumbnail.png deleted file mode 100644 index e1cec9dfb8469db1bbc1c60248afc0bf2f488003..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 286354 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±Gec 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

A-K$Lf(p?y8!FXWu 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%0A~I2-<(G&ojkRcq10VzYee>`(nH72>9Myv2gn9 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

Xvo5;`tH>0z{8z~Rkbj!; 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%0A`868z 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 diff --git a/examples/demo_launcher/assets/stocks_thumbnail.png b/examples/demo_launcher/assets/stocks_thumbnail.png deleted file mode 100644 index 327708c1aaa6957afccb262070819587549818c4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 57860 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

@Ng*KW=n**CK> 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 diff --git a/examples/demo_launcher/lib/main.dart b/examples/demo_launcher/lib/main.dart deleted file mode 100644 index f2ed11c693..0000000000 --- a/examples/demo_launcher/lib/main.dart +++ /dev/null @@ -1,210 +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 'package:flutter/material.dart'; -import 'package:flutter/painting.dart'; -import 'package:flutter/services.dart'; - -AssetBundle _initBundle() { - if (rootBundle != null) - return rootBundle; - const String _kAssetBase = '..'; - return new NetworkAssetBundle(Uri.base.resolve(_kAssetBase)); -} - -final AssetBundle _bundle = _initBundle(); - -void launch(String relativeUrl, String bundle) { - // TODO(eseidel): This is a hack to keep non-skyx examples working for now: - Uri productionBase = Uri.parse( - 'https://domokit.github.io/example/demo_launcher/lib/main.dart'); - Uri base = rootBundle == null ? Uri.base : productionBase; - Uri url = base.resolve(relativeUrl); - - ComponentName component = new ComponentName() - ..packageName = 'org.domokit.sky.demo' - ..className = 'org.domokit.sky.demo.SkyDemoActivity'; - Intent intent = new Intent() - ..action = 'android.intent.action.VIEW' - ..component = component - ..flags = MULTIPLE_TASK | NEW_DOCUMENT - ..url = url.toString(); - - if (bundle != null) { - StringExtra extra = new StringExtra() - ..name = 'bundleName' - ..value = bundle; - intent.stringExtras = [extra]; - } - - activity.startActivity(intent); -} - -class FlutterDemo { - FlutterDemo({ - name, - this.href, - this.bundle, - this.description, - this.textTheme, - this.decoration - }) : name = name, key = new Key(name); - final String name; - final Key key; - final String href; - final String bundle; - final String description; - final TextTheme textTheme; - final BoxDecoration decoration; -} - -List demos = [ - new FlutterDemo( - name: 'Stocks', - href: '../../stocks/lib/main.dart', - bundle: 'stocks.skyx', - description: 'Multi-screen app with scrolling list', - textTheme: Typography.black, - decoration: new BoxDecoration( - backgroundImage: new BackgroundImage( - image: _bundle.loadImage('assets/stocks_thumbnail.png'), - fit: ImageFit.cover - ) - ) - ), - new FlutterDemo( - name: 'Asteroids', - href: '../../game/lib/main.dart', - bundle: 'game.skyx', - description: '2D game using sprite sheets', - textTheme: Typography.white, - decoration: new BoxDecoration( - backgroundImage: new BackgroundImage( - image: _bundle.loadImage('assets/game_thumbnail.png'), - fit: ImageFit.cover - ) - ) - ), - new FlutterDemo( - name: 'Fitness', - href: '../../fitness/lib/main.dart', - bundle: 'fitness.skyx', - description: 'Track progress towards healthy goals', - textTheme: Typography.white, - decoration: new BoxDecoration( - backgroundColor: Colors.indigo[500] - ) - ), - new FlutterDemo( - name: 'Swipe Away', - href: '../../widgets/card_collection.dart', - bundle: 'cards.skyx', - description: 'Infinite list of swipeable cards', - textTheme: Typography.white, - decoration: new BoxDecoration( - backgroundColor: Colors.redAccent[200] - ) - ), - new FlutterDemo( - name: 'Interactive Text', - href: '../../rendering/interactive_flex.dart', - bundle: 'interactive_flex.skyx', - description: 'Swipe to reflow the app', - textTheme: Typography.white, - decoration: new BoxDecoration( - backgroundColor: const Color(0xFF0081C6) - ) - ), - // new SkyDemo( - - // 'Touch Demo', '../../rendering/touch_demo.dart', 'Simple example showing handling of touch events at a low level'), - new FlutterDemo( - name: 'Minedigger Game', - href: '../../mine_digger/lib/main.dart', - bundle: 'mine_digger.skyx', - description: 'Clone of the classic Minesweeper game', - textTheme: Typography.white, - decoration: new BoxDecoration( - backgroundColor: Colors.black - ) - ), - - // TODO(jackson): This doesn't seem to be working - // new SkyDemo('Licenses', 'LICENSES.sky'), -]; - -const double kCardHeight = 120.0; -const EdgeDims kListPadding = const EdgeDims.all(4.0); - -class DemoCard extends StatelessComponent { - DemoCard({ Key key, this.demo }) : super(key: key); - - final FlutterDemo demo; - - Widget build(BuildContext context) { - return new Container( - height: kCardHeight, - child: new Card( - child: new Container( - decoration: demo.decoration, - child: new InkWell( - onTap: () => launch(demo.href, demo.bundle), - child: new Container( - margin: const EdgeDims.only(top: 24.0, left: 24.0), - child: new Column([ - new Text(demo.name, style: demo.textTheme.title), - new Flexible( - child: new Text(demo.description, style: demo.textTheme.subhead) - ) - ], - alignItems: FlexAlignItems.start - ) - ) - ) - ) - ) - ); - } -} - -class DemoList extends StatelessComponent { - Widget _buildDemoCard(BuildContext context, FlutterDemo demo) { - return new DemoCard(key: demo.key, demo: demo); - } - - Widget build(BuildContext context) { - return new ScrollableList( - items: demos, - itemExtent: kCardHeight, - itemBuilder: _buildDemoCard, - padding: kListPadding - ); - } -} - -final ThemeData _theme = new ThemeData( - brightness: ThemeBrightness.light, - primarySwatch: Colors.teal -); - -class DemoHome extends StatelessComponent { - Widget build(BuildContext context) { - return new Scaffold( - toolBar: new ToolBar(center: new Text('Sky Demos')), - body: new Material( - child: new DemoList() - ) - ); - } -} - -void main() { - runApp(new MaterialApp( - title: 'Flutter Demos', - theme: _theme, - routes: { - '/': (RouteArguments args) => new DemoHome() - } - )); -} diff --git a/examples/demo_launcher/pubspec.yaml b/examples/demo_launcher/pubspec.yaml deleted file mode 100644 index de60ccf7ab..0000000000 --- a/examples/demo_launcher/pubspec.yaml +++ /dev/null @@ -1,9 +0,0 @@ -name: demo_launcher -dependencies: - flutter: ">=0.0.3 <0.1.0" - sky_tools: any -dependency_overrides: - material_design_icons: - path: ../../sky/packages/material_design_icons - flutter: - path: ../../sky/packages/sky diff --git a/examples/demo_launcher/sky.yaml b/examples/demo_launcher/sky.yaml deleted file mode 100644 index 4e78c11015..0000000000 --- a/examples/demo_launcher/sky.yaml +++ /dev/null @@ -1,4 +0,0 @@ -assets: - - assets/game_thumbnail.png - - assets/sector_thumbnail.png - - assets/stocks_thumbnail.png diff --git a/examples/rendering/BUILD.gn b/examples/rendering/BUILD.gn deleted file mode 100644 index 3cadbad52a..0000000000 --- a/examples/rendering/BUILD.gn +++ /dev/null @@ -1,17 +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("//sky/build/skyx.gni") - -skyx("interactive_flex") { - main_dart = "interactive_flex.dart" -} - -group("rendering") { - testonly = true - - deps = [ - ":interactive_flex", - ] -} diff --git a/examples/widgets/BUILD.gn b/examples/widgets/BUILD.gn deleted file mode 100644 index 2de2c054ff..0000000000 --- a/examples/widgets/BUILD.gn +++ /dev/null @@ -1,27 +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("//sky/build/skyx.gni") - -skyx("sector") { - main_dart = "sector.dart" -} - -skyx("piano") { - main_dart = "piano.dart" -} - -skyx("cards") { - main_dart = "card_collection.dart" -} - -group("widgets") { - testonly = true - - deps = [ - ":cards", - ":piano", - ":sector", - ] -} From 909716956eecb7ffb8b78d4ab05fab46d9f4a8ad Mon Sep 17 00:00:00 2001 From: Viktor Lidholt Date: Mon, 12 Oct 2015 15:28:02 -0700 Subject: [PATCH 51/84] Adds pulley joint to sprite physics and makes joint variables final --- .../flutter_sprites/lib/physics_joint.dart | 69 +++++++++++++++---- 1 file changed, 54 insertions(+), 15 deletions(-) diff --git a/packages/flutter_sprites/lib/physics_joint.dart b/packages/flutter_sprites/lib/physics_joint.dart index 7eaa5cec30..375488d7f0 100644 --- a/packages/flutter_sprites/lib/physics_joint.dart +++ b/packages/flutter_sprites/lib/physics_joint.dart @@ -6,8 +6,8 @@ abstract class PhysicsJoint { bodyB._joints.add(this); } - PhysicsBody bodyA; - PhysicsBody bodyB; + final PhysicsBody bodyA; + final PhysicsBody bodyB; bool _active = true; box2d.Joint _joint; @@ -43,21 +43,17 @@ class PhysicsJointRevolute extends PhysicsJoint { PhysicsBody bodyA, PhysicsBody bodyB, this.worldAnchor, { - double lowerAngle: 0.0, - double upperAngle: 0.0, - bool enableLimit: false + this.lowerAngle: 0.0, + this.upperAngle: 0.0, + this.enableLimit: false }) : super(bodyA, bodyB) { - this.lowerAngle = lowerAngle; - this.upperAngle = upperAngle; - this.enableLimit = enableLimit; - _completeCreation(); } - Point worldAnchor; - double lowerAngle; - double upperAngle; - bool enableLimit; + final Point worldAnchor; + final double lowerAngle; + final double upperAngle; + final bool enableLimit; box2d.Joint _createB2Joint(PhysicsNode physicsNode) { // Create Joint Definition @@ -81,7 +77,8 @@ class PhysicsJointPrismatic extends PhysicsJoint { PhysicsJointPrismatic( PhysicsBody bodyA, PhysicsBody bodyB, - this.axis) : super(bodyA, bodyB) { + this.axis + ) : super(bodyA, bodyB) { _completeCreation(); } @@ -97,7 +94,8 @@ class PhysicsJointPrismatic extends PhysicsJoint { class PhysicsJointWeld extends PhysicsJoint { PhysicsJointWeld( PhysicsBody bodyA, - PhysicsBody bodyB) : super(bodyA, bodyB) { + PhysicsBody bodyB + ) : super(bodyA, bodyB) { _completeCreation(); } @@ -111,3 +109,44 @@ class PhysicsJointWeld extends PhysicsJoint { return physicsNode.b2World.createJoint(b2Def); } } + +class PhysicsJointPulley extends PhysicsJoint { + PhysicsJointPulley( + PhysicsBody bodyA, + PhysicsBody bodyB, + this.groundAnchorA, + this.groundAnchorB, + this.anchorA, + this.anchorB, + this.ratio + ) : super(bodyA, bodyB) { + _completeCreation(); + } + + final Point groundAnchorA; + final Point groundAnchorB; + final Point anchorA; + final Point anchorB; + final double ratio; + + box2d.Joint _createB2Joint(PhysicsNode physicsNode) { + box2d.PulleyJointDef b2Def = new box2d.PulleyJointDef(); + b2Def.initialize( + bodyA._body, + bodyB._body, + _convertPosToVec(groundAnchorA, physicsNode), + _convertPosToVec(groundAnchorB, physicsNode), + _convertPosToVec(anchorA, physicsNode), + _convertPosToVec(anchorB, physicsNode), + ratio + ); + return physicsNode.b2World.createJoint(b2Def); + } +} + +Vector2 _convertPosToVec(Point pt, PhysicsNode physicsNode) { + return new Vector2( + pt.x / physicsNode.b2WorldToNodeConversionFactor, + pt.y / physicsNode.b2WorldToNodeConversionFactor + ); +} From 13ade2c732f2bca23dde03e2a3e797c78735fff9 Mon Sep 17 00:00:00 2001 From: Viktor Lidholt Date: Mon, 12 Oct 2015 15:55:47 -0700 Subject: [PATCH 52/84] Adds check for breaking forces in sprite physics joints --- .../flutter_sprites/lib/physics_joint.dart | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/packages/flutter_sprites/lib/physics_joint.dart b/packages/flutter_sprites/lib/physics_joint.dart index 375488d7f0..1a5020a65e 100644 --- a/packages/flutter_sprites/lib/physics_joint.dart +++ b/packages/flutter_sprites/lib/physics_joint.dart @@ -8,6 +8,7 @@ abstract class PhysicsJoint { final PhysicsBody bodyA; final PhysicsBody bodyB; + final double breakingForce; bool _active = true; box2d.Joint _joint; @@ -36,6 +37,25 @@ abstract class PhysicsJoint { } box2d.Joint _createB2Joint(PhysicsNode physicsNode); + + void destroy() { + _detach(); + } + + void _checkBreakingForce(double dt) { + if (breakingForce == null) return; + + if (_joint != null && _active) { + Vector2 reactionForce = new Vector2.zero(); + _joint.getReactionForce(1.0 / dt, reactionForce); + + if (breakingForce * breakingForce < reactionForce.length2) { + // TODO: Add callback + + destroy(); + } + } + } } class PhysicsJointRevolute extends PhysicsJoint { From 477a54c3758574768a2de0f68cea19f9ec87ae47 Mon Sep 17 00:00:00 2001 From: Collin Jackson Date: Mon, 12 Oct 2015 16:10:46 -0700 Subject: [PATCH 53/84] Allow derived classes of Scrollable to listen for scroll events --- packages/flutter/lib/src/widgets/scrollable.dart | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/flutter/lib/src/widgets/scrollable.dart b/packages/flutter/lib/src/widgets/scrollable.dart index 310dd57a40..71723e6bc3 100644 --- a/packages/flutter/lib/src/widgets/scrollable.dart +++ b/packages/flutter/lib/src/widgets/scrollable.dart @@ -166,8 +166,7 @@ abstract class ScrollableState extends State { setState(() { _scrollOffset = newScrollOffset; }); - if (config.onScroll != null) - config.onScroll(_scrollOffset); + dispatchOnScroll(); } Future scrollTo(double newScrollOffset, { Duration duration, Curve curve: ease }) { @@ -200,6 +199,12 @@ abstract class ScrollableState extends State { return _startToEndAnimation(); } + // Derived classes can override this method and call super.dispatchOnScroll() + void dispatchOnScroll() { + if (config.onScroll != null) + config.onScroll(_scrollOffset); + } + double _scrollVelocity(ui.Offset velocity) { double scrollVelocity = config.scrollDirection == ScrollDirection.horizontal ? -velocity.dx From f2cc43a483784a5106a49cf8fab9dd570d287a1d Mon Sep 17 00:00:00 2001 From: Hixie Date: Fri, 9 Oct 2015 13:54:40 -0700 Subject: [PATCH 54/84] Lots of trivial warning fixes Add type annotations in many places. Fix some identifiers to have more lint-satisfying names. Make all operator==s consistent in style. Reorder some functions for consistency. Make ParentData no longer dynamic, and fix all the code around that. --- examples/stocks/lib/stock_data.dart | 6 +- examples/stocks/lib/stock_home.dart | 24 +-- examples/stocks/lib/stock_menu.dart | 6 +- examples/stocks/lib/stock_row.dart | 14 +- examples/stocks/lib/stock_settings.dart | 10 +- examples/stocks/lib/stock_symbol_viewer.dart | 6 +- .../flutter/lib/src/animation/scheduler.dart | 2 +- .../flutter/lib/src/gestures/recognizer.dart | 2 +- .../flutter/lib/src/material/checkbox.dart | 2 +- packages/flutter/lib/src/material/colors.dart | 70 ++++---- .../flutter/lib/src/material/date_picker.dart | 12 +- packages/flutter/lib/src/material/dialog.dart | 2 +- packages/flutter/lib/src/material/drawer.dart | 2 +- .../lib/src/material/drawer_header.dart | 2 +- packages/flutter/lib/src/material/edges.dart | 2 +- packages/flutter/lib/src/material/icon.dart | 10 +- packages/flutter/lib/src/material/input.dart | 1 + .../flutter/lib/src/material/popup_menu.dart | 8 +- .../lib/src/material/progress_indicator.dart | 2 +- .../lib/src/material/radial_reaction.dart | 2 +- .../flutter/lib/src/material/shadows.dart | 12 +- .../flutter/lib/src/material/snack_bar.dart | 4 +- packages/flutter/lib/src/material/switch.dart | 2 +- packages/flutter/lib/src/material/tabs.dart | 52 +++--- .../flutter/lib/src/material/tool_bar.dart | 2 +- .../flutter/lib/src/painting/box_painter.dart | 31 ++-- .../flutter/lib/src/painting/shadows.dart | 23 +-- .../lib/src/painting/text_painter.dart | 84 ++++++++-- .../flutter/lib/src/painting/text_style.dart | 36 ++-- .../lib/src/rendering/auto_layout.dart | 26 +-- packages/flutter/lib/src/rendering/block.dart | 45 +++-- packages/flutter/lib/src/rendering/box.dart | 63 +++---- packages/flutter/lib/src/rendering/flex.dart | 47 +++--- packages/flutter/lib/src/rendering/grid.dart | 9 +- packages/flutter/lib/src/rendering/image.dart | 2 +- .../flutter/lib/src/rendering/object.dart | 157 +++++++++--------- .../flutter/lib/src/rendering/proxy_box.dart | 18 +- .../lib/src/rendering/shifted_box.dart | 34 ++-- packages/flutter/lib/src/rendering/stack.dart | 87 +++++----- .../flutter/lib/src/rendering/viewport.dart | 4 +- .../lib/src/services/asset_bundle.dart | 2 +- packages/flutter/lib/src/services/fetch.dart | 2 +- .../flutter/lib/src/services/image_cache.dart | 5 +- packages/flutter/lib/src/widgets/basic.dart | 4 +- .../lib/src/widgets/editable_text.dart | 40 +++-- .../flutter/lib/src/widgets/framework.dart | 76 +++++---- .../lib/src/widgets/mixed_viewport.dart | 10 +- .../flutter/lib/src/widgets/scrollable.dart | 4 +- .../lib/src/widgets/statistics_overlay.dart | 14 +- packages/unit/test/widget/input_test.dart | 16 +- 50 files changed, 611 insertions(+), 485 deletions(-) diff --git a/examples/stocks/lib/stock_data.dart b/examples/stocks/lib/stock_data.dart index ed7c726501..53bffc3ba3 100644 --- a/examples/stocks/lib/stock_data.dart +++ b/examples/stocks/lib/stock_data.dart @@ -57,8 +57,8 @@ const _kChunkCount = 30; String _urlToFetch(int chunk) { if (rootBundle == null) - return '../data/stock_data_${chunk}.json'; - return 'https://domokit.github.io/examples/stocks/data/stock_data_${chunk}.json'; + return '../data/stock_data_$chunk.json'; + return 'https://domokit.github.io/examples/stocks/data/stock_data_$chunk.json'; } class StockDataFetcher { @@ -81,9 +81,7 @@ class StockDataFetcher { return; } JsonDecoder decoder = new JsonDecoder(); - callback(new StockData(decoder.convert(json))); - if (_nextChunk < _kChunkCount) _fetchNextChunk(); }); diff --git a/examples/stocks/lib/stock_home.dart b/examples/stocks/lib/stock_home.dart index b42f035783..0d18aec008 100644 --- a/examples/stocks/lib/stock_home.dart +++ b/examples/stocks/lib/stock_home.dart @@ -37,8 +37,10 @@ class StockHomeState extends State { } void _handleSearchEnd() { - assert(config.navigator.currentRoute is StateRoute); - assert((config.navigator.currentRoute as StateRoute).owner == this); // TODO(ianh): remove cast once analyzer is cleverer + assert(() { + final StateRoute currentRoute = config.navigator.currentRoute; + assert(currentRoute.owner == this); + }); config.navigator.pop(); setState(() { _isSearching = false; @@ -74,7 +76,7 @@ class StockHomeState extends State { void _showDrawer() { showDrawer( navigator: config.navigator, - child: new Block([ + child: new Block([ new DrawerHeader(child: new Text('Stocks')), new DrawerItem( icon: 'action/assessment', @@ -88,7 +90,7 @@ class StockHomeState extends State { return new Dialog( title: new Text('Not Implemented'), content: new Text('This feature has not yet been implemented.'), - actions: [ + actions: [ new FlatButton( child: new Text('USE IT'), enabled: false, @@ -117,7 +119,7 @@ class StockHomeState extends State { new DrawerItem( icon: 'action/thumb_up', onPressed: () => _handleStockModeChange(StockMode.optimistic), - child: new Row([ + child: new Row([ new Flexible(child: new Text('Optimistic')), new Radio(value: StockMode.optimistic, groupValue: config.stockMode, onChanged: _handleStockModeChange) ]) @@ -125,7 +127,7 @@ class StockHomeState extends State { new DrawerItem( icon: 'action/thumb_down', onPressed: () => _handleStockModeChange(StockMode.pessimistic), - child: new Row([ + child: new Row([ new Flexible(child: new Text('Pessimistic')), new Radio(value: StockMode.pessimistic, groupValue: config.stockMode, onChanged: _handleStockModeChange) ]) @@ -155,7 +157,7 @@ class StockHomeState extends State { onPressed: _showDrawer ), center: new Text('Stocks'), - right: [ + right: [ new IconButton( icon: "action/search", onPressed: _handleSearchBegin @@ -171,14 +173,14 @@ class StockHomeState extends State { int selectedTabIndex = 0; Iterable _getStockList(Iterable symbols) { - return symbols.map((symbol) => config.stocks[symbol]); + return symbols.map((String symbol) => config.stocks[symbol]); } Iterable _filterBySearchQuery(Iterable stocks) { if (_searchQuery == null) return stocks; RegExp regexp = new RegExp(_searchQuery, caseSensitive: false); - return stocks.where((stock) => stock.symbol.contains(regexp)); + return stocks.where((Stock stock) => stock.symbol.contains(regexp)); } Widget buildStockList(BuildContext context, Iterable stocks) { @@ -211,7 +213,7 @@ class StockHomeState extends State { ) ], selectedIndex: selectedTabIndex, - onChanged: (tabIndex) { + onChanged: (int tabIndex) { setState(() { selectedTabIndex = tabIndex; } ); } ); @@ -245,7 +247,7 @@ class StockHomeState extends State { navigator: config.navigator, placeholderKey: _snackBarPlaceholderKey, content: new Text("Stock purchased!"), - actions: [ + actions: [ new SnackBarAction(label: "UNDO", onPressed: _handleUndo) ] ); diff --git a/examples/stocks/lib/stock_menu.dart b/examples/stocks/lib/stock_menu.dart index 1a1ca9af4e..d6ab8b998f 100644 --- a/examples/stocks/lib/stock_menu.dart +++ b/examples/stocks/lib/stock_menu.dart @@ -19,7 +19,7 @@ Future showStockMenu(NavigatorState navigator, { bool autorefresh, ValueChanged return [ new PopupMenuItem( value: _MenuItems.autorefresh, - child: new Row([ + child: new Row([ new Flexible(child: new Text('Autorefresh')), new Checkbox( value: autorefresh, @@ -59,9 +59,9 @@ Future showStockMenu(NavigatorState navigator, { bool autorefresh, ValueChanged return new Dialog( title: new Text('Not Implemented'), content: new Text('This feature has not yet been implemented.'), - actions: [ + actions: [ new FlatButton( - child: new Row([ + child: new Row([ new Icon( type: 'device/dvr', size: 18 diff --git a/examples/stocks/lib/stock_row.dart b/examples/stocks/lib/stock_row.dart index da95327cf1..3014eb21ff 100644 --- a/examples/stocks/lib/stock_row.dart +++ b/examples/stocks/lib/stock_row.dart @@ -10,9 +10,15 @@ class StockRowPartGlobalKey extends GlobalKey { const StockRowPartGlobalKey(this.stock, this.part) : super.constructor(); final Stock stock; final StockRowPartKind part; - String toString() => '[StockRowPartGlobalKey ${stock.symbol}:${part.toString().split(".")[1]})]'; - bool operator==(other) => other is StockRowPartGlobalKey && identical(other.stock, stock) && identical(other.part, part); + bool operator ==(dynamic other) { + if (other is! StockRowPartGlobalKey) + return false; + final StockRowPartGlobalKey typedOther = other; + return stock == typedOther.stock && + part == typedOther.part; + } int get hashCode => 37 * (37 * (373) + identityHashCode(stock)) + identityHashCode(part); + String toString() => '[StockRowPartGlobalKey ${stock.symbol}:${part.toString().split(".")[1]})]'; } typedef void StockRowActionCallback(Stock stock, GlobalKey row, GlobalKey arrowKey, GlobalKey symbolKey, GlobalKey priceKey); @@ -65,14 +71,14 @@ class StockRow extends StatelessComponent { bottom: new BorderSide(color: Theme.of(context).dividerColor) ) ), - child: new Row([ + child: new Row([ new Container( key: arrowKey, child: new StockArrow(percentChange: stock.percentChange), margin: const EdgeDims.only(right: 5.0) ), new Flexible( - child: new Row([ + child: new Row([ new Flexible( flex: 2, child: new Text( diff --git a/examples/stocks/lib/stock_settings.dart b/examples/stocks/lib/stock_settings.dart index 1be3c8266c..c0404c7268 100644 --- a/examples/stocks/lib/stock_settings.dart +++ b/examples/stocks/lib/stock_settings.dart @@ -42,7 +42,7 @@ class StockSettingsState extends State { onDismiss: () { navigator.pop(false); }, - actions: [ + actions: [ new FlatButton( child: new Text('NO THANKS'), onPressed: () { @@ -87,22 +87,22 @@ class StockSettingsState extends State { child: new ScrollableViewport( child: new Container( padding: const EdgeDims.symmetric(vertical: 20.0), - child: new BlockBody([ + child: new BlockBody([ new DrawerItem( icon: 'action/thumb_up', onPressed: () => _confirmOptimismChange(), - child: new Row([ + child: new Row([ new Flexible(child: new Text('Everything is awesome')), new Checkbox( value: config.optimism == StockMode.optimistic, - onChanged: (_) => _confirmOptimismChange() + onChanged: (bool value) => _confirmOptimismChange() ), ]) ), new DrawerItem( icon: 'action/backup', onPressed: () { _handleBackupChanged(!(config.backup == BackupMode.enabled)); }, - child: new Row([ + child: new Row([ new Flexible(child: new Text('Back up stock list to the cloud')), new Switch( value: config.backup == BackupMode.enabled, diff --git a/examples/stocks/lib/stock_symbol_viewer.dart b/examples/stocks/lib/stock_symbol_viewer.dart index 3f73b08a19..ec0dd6c275 100644 --- a/examples/stocks/lib/stock_symbol_viewer.dart +++ b/examples/stocks/lib/stock_symbol_viewer.dart @@ -33,12 +33,12 @@ class StockSymbolViewerState extends State { center: new Text('${config.stock.name} (${config.stock.symbol})') ), body: new Material( - child: new Block([ + child: new Block([ new Container( padding: new EdgeDims.all(20.0), - child: new Column([ + child: new Column([ new Text('Last Sale', style: headings), - new Text('${lastSale} (${changeInPrice})'), + new Text('$lastSale ($changeInPrice)'), new Container( height: 8.0 ), diff --git a/packages/flutter/lib/src/animation/scheduler.dart b/packages/flutter/lib/src/animation/scheduler.dart index 064762ded6..699ced4830 100644 --- a/packages/flutter/lib/src/animation/scheduler.dart +++ b/packages/flutter/lib/src/animation/scheduler.dart @@ -45,7 +45,7 @@ class Scheduler { Map callbacks = _transientCallbacks; _transientCallbacks = new Map(); - callbacks.forEach((id, callback) { + callbacks.forEach((int id, SchedulerCallback callback) { if (!_removedIds.contains(id)) callback(timeStamp); }); diff --git a/packages/flutter/lib/src/gestures/recognizer.dart b/packages/flutter/lib/src/gestures/recognizer.dart index a2fca88a5f..9adcb3d90a 100644 --- a/packages/flutter/lib/src/gestures/recognizer.dart +++ b/packages/flutter/lib/src/gestures/recognizer.dart @@ -30,7 +30,7 @@ abstract class GestureRecognizer extends GestureArenaMember { void didStopTrackingLastPointer(int pointer); void resolve(GestureDisposition disposition) { - List localEntries = new List.from(_entries); + List localEntries = new List.from(_entries); _entries.clear(); for (GestureArenaEntry entry in localEntries) entry.resolve(disposition); diff --git a/packages/flutter/lib/src/material/checkbox.dart b/packages/flutter/lib/src/material/checkbox.dart index df7ee5ce57..4de7ed9f4e 100644 --- a/packages/flutter/lib/src/material/checkbox.dart +++ b/packages/flutter/lib/src/material/checkbox.dart @@ -151,7 +151,7 @@ class _RenderCheckbox extends RenderToggleable { paint.setStyle(ui.PaintingStyle.fill); paint.setShader(new ui.Gradient.radial( new Point(_kEdgeSize / 2.0, _kEdgeSize / 2.0), - _kEdgeSize * (_kMidpoint - position) * 8.0, [ + _kEdgeSize * (_kMidpoint - position) * 8.0, [ const ui.Color(0x00000000), uncheckedColor ])); diff --git a/packages/flutter/lib/src/material/colors.dart b/packages/flutter/lib/src/material/colors.dart index 7df8de2529..68fa5913e3 100644 --- a/packages/flutter/lib/src/material/colors.dart +++ b/packages/flutter/lib/src/material/colors.dart @@ -21,7 +21,7 @@ class Colors { static const white30 = const Color(0x4DFFFFFF); // text of disabled flat button in dark theme static const white12 = const Color(0x1FFFFFFF); // background of disabled raised buttons in dark theme - static const Map red = const { + static const Map red = const { 50: const Color(0xFFFFEBEE), 100: const Color(0xFFFFCDD2), 200: const Color(0xFFEF9A9A), @@ -34,14 +34,14 @@ class Colors { 900: const Color(0xFFB71C1C), }; - static const Map redAccent = const { + static const Map redAccent = const { 100: const Color(0xFFFF8A80), 200: const Color(0xFFFF5252), 400: const Color(0xFFFF1744), 700: const Color(0xFFD50000), }; - static const Map pink = const { + static const Map pink = const { 50: const Color(0xFFFCE4EC), 100: const Color(0xFFF8BBD0), 200: const Color(0xFFF48FB1), @@ -54,14 +54,14 @@ class Colors { 900: const Color(0xFF880E4F), }; - static const Map pinkAccent = const { + static const Map pinkAccent = const { 100: const Color(0xFFFF80AB), 200: const Color(0xFFFF4081), 400: const Color(0xFFF50057), 700: const Color(0xFFC51162), }; - static const Map purple = const { + static const Map purple = const { 50: const Color(0xFFF3E5F5), 100: const Color(0xFFE1BEE7), 200: const Color(0xFFCE93D8), @@ -74,14 +74,14 @@ class Colors { 900: const Color(0xFF4A148C), }; - static const Map purpleAccent = const { + static const Map purpleAccent = const { 100: const Color(0xFFEA80FC), 200: const Color(0xFFE040FB), 400: const Color(0xFFD500F9), 700: const Color(0xFFAA00FF), }; - static const Map deepPurple = const { + static const Map deepPurple = const { 50: const Color(0xFFEDE7F6), 100: const Color(0xFFD1C4E9), 200: const Color(0xFFB39DDB), @@ -94,14 +94,14 @@ class Colors { 900: const Color(0xFF311B92), }; - static const Map deepPurpleAccent = const { + static const Map deepPurpleAccent = const { 100: const Color(0xFFB388FF), 200: const Color(0xFF7C4DFF), 400: const Color(0xFF651FFF), 700: const Color(0xFF6200EA), }; - static const Map indigo = const { + static const Map indigo = const { 50: const Color(0xFFE8EAF6), 100: const Color(0xFFC5CAE9), 200: const Color(0xFF9FA8DA), @@ -114,14 +114,14 @@ class Colors { 900: const Color(0xFF1A237E), }; - static const Map indigoAccent = const { + static const Map indigoAccent = const { 100: const Color(0xFF8C9EFF), 200: const Color(0xFF536DFE), 400: const Color(0xFF3D5AFE), 700: const Color(0xFF304FFE), }; - static const Map blue = const { + static const Map blue = const { 50: const Color(0xFFE3F2FD), 100: const Color(0xFFBBDEFB), 200: const Color(0xFF90CAF9), @@ -134,14 +134,14 @@ class Colors { 900: const Color(0xFF0D47A1), }; - static const Map blueAccent = const { + static const Map blueAccent = const { 100: const Color(0xFF82B1FF), 200: const Color(0xFF448AFF), 400: const Color(0xFF2979FF), 700: const Color(0xFF2962FF), }; - static const Map lightBlue = const { + static const Map lightBlue = const { 50: const Color(0xFFE1F5FE), 100: const Color(0xFFB3E5FC), 200: const Color(0xFF81D4FA), @@ -154,14 +154,14 @@ class Colors { 900: const Color(0xFF01579B), }; - static const Map lightBlueAccent = const { + static const Map lightBlueAccent = const { 100: const Color(0xFF80D8FF), 200: const Color(0xFF40C4FF), 400: const Color(0xFF00B0FF), 700: const Color(0xFF0091EA), }; - static const Map cyan = const { + static const Map cyan = const { 50: const Color(0xFFE0F7FA), 100: const Color(0xFFB2EBF2), 200: const Color(0xFF80DEEA), @@ -174,14 +174,14 @@ class Colors { 900: const Color(0xFF006064), }; - static const Map cyanAccent = const { + static const Map cyanAccent = const { 100: const Color(0xFF84FFFF), 200: const Color(0xFF18FFFF), 400: const Color(0xFF00E5FF), 700: const Color(0xFF00B8D4), }; - static const Map teal = const { + static const Map teal = const { 50: const Color(0xFFE0F2F1), 100: const Color(0xFFB2DFDB), 200: const Color(0xFF80CBC4), @@ -194,14 +194,14 @@ class Colors { 900: const Color(0xFF004D40), }; - static const Map tealAccent = const { + static const Map tealAccent = const { 100: const Color(0xFFA7FFEB), 200: const Color(0xFF64FFDA), 400: const Color(0xFF1DE9B6), 700: const Color(0xFF00BFA5), }; - static const Map green = const { + static const Map green = const { 50: const Color(0xFFE8F5E9), 100: const Color(0xFFC8E6C9), 200: const Color(0xFFA5D6A7), @@ -214,14 +214,14 @@ class Colors { 900: const Color(0xFF1B5E20), }; - static const Map greenAccent = const { + static const Map greenAccent = const { 100: const Color(0xFFB9F6CA), 200: const Color(0xFF69F0AE), 400: const Color(0xFF00E676), 700: const Color(0xFF00C853), }; - static const Map lightGreen = const { + static const Map lightGreen = const { 50: const Color(0xFFF1F8E9), 100: const Color(0xFFDCEDC8), 200: const Color(0xFFC5E1A5), @@ -234,14 +234,14 @@ class Colors { 900: const Color(0xFF33691E), }; - static const Map lightGreenAccent = const { + static const Map lightGreenAccent = const { 100: const Color(0xFFCCFF90), 200: const Color(0xFFB2FF59), 400: const Color(0xFF76FF03), 700: const Color(0xFF64DD17), }; - static const Map lime = const { + static const Map lime = const { 50: const Color(0xFFF9FBE7), 100: const Color(0xFFF0F4C3), 200: const Color(0xFFE6EE9C), @@ -254,14 +254,14 @@ class Colors { 900: const Color(0xFF827717), }; - static const Map limeAccent = const { + static const Map limeAccent = const { 100: const Color(0xFFF4FF81), 200: const Color(0xFFEEFF41), 400: const Color(0xFFC6FF00), 700: const Color(0xFFAEEA00), }; - static const Map yellow = const { + static const Map yellow = const { 50: const Color(0xFFFFFDE7), 100: const Color(0xFFFFF9C4), 200: const Color(0xFFFFF59D), @@ -274,14 +274,14 @@ class Colors { 900: const Color(0xFFF57F17), }; - static const Map yellowAccent = const { + static const Map yellowAccent = const { 100: const Color(0xFFFFFF8D), 200: const Color(0xFFFFFF00), 400: const Color(0xFFFFEA00), 700: const Color(0xFFFFD600), }; - static const Map amber = const { + static const Map amber = const { 50: const Color(0xFFFFF8E1), 100: const Color(0xFFFFECB3), 200: const Color(0xFFFFE082), @@ -294,14 +294,14 @@ class Colors { 900: const Color(0xFFFF6F00), }; - static const Map amberAccent = const { + static const Map amberAccent = const { 100: const Color(0xFFFFE57F), 200: const Color(0xFFFFD740), 400: const Color(0xFFFFC400), 700: const Color(0xFFFFAB00), }; - static const Map orange = const { + static const Map orange = const { 50: const Color(0xFFFFF3E0), 100: const Color(0xFFFFE0B2), 200: const Color(0xFFFFCC80), @@ -314,14 +314,14 @@ class Colors { 900: const Color(0xFFE65100), }; - static const Map orangeAccent = const { + static const Map orangeAccent = const { 100: const Color(0xFFFFD180), 200: const Color(0xFFFFAB40), 400: const Color(0xFFFF9100), 700: const Color(0xFFFF6D00), }; - static const Map deepOrange = const { + static const Map deepOrange = const { 50: const Color(0xFFFBE9E7), 100: const Color(0xFFFFCCBC), 200: const Color(0xFFFFAB91), @@ -334,14 +334,14 @@ class Colors { 900: const Color(0xFFBF360C), }; - static const Map deepOrangeAccent = const { + static const Map deepOrangeAccent = const { 100: const Color(0xFFFF9E80), 200: const Color(0xFFFF6E40), 400: const Color(0xFFFF3D00), 700: const Color(0xFFDD2C00), }; - static const Map brown = const { + static const Map brown = const { 50: const Color(0xFFEFEBE9), 100: const Color(0xFFD7CCC8), 200: const Color(0xFFBCAAA4), @@ -354,7 +354,7 @@ class Colors { 900: const Color(0xFF3E2723), }; - static const Map grey = const { + static const Map grey = const { 50: const Color(0xFFFAFAFA), 100: const Color(0xFFF5F5F5), 200: const Color(0xFFEEEEEE), @@ -369,7 +369,7 @@ class Colors { 900: const Color(0xFF212121), }; - static const Map blueGrey = const { + static const Map blueGrey = const { 50: const Color(0xFFECEFF1), 100: const Color(0xFFCFD8DC), 200: const Color(0xFFB0BEC5), diff --git a/packages/flutter/lib/src/material/date_picker.dart b/packages/flutter/lib/src/material/date_picker.dart index 12b9227c67..46caf21ff3 100644 --- a/packages/flutter/lib/src/material/date_picker.dart +++ b/packages/flutter/lib/src/material/date_picker.dart @@ -94,7 +94,7 @@ class _DatePickerState extends State { ); break; } - return new Column([ + return new Column([ header, new Container( height: _calendarHeight, @@ -145,7 +145,7 @@ class _DatePickerHeader extends StatelessComponent { return new Container( padding: new EdgeDims.all(10.0), decoration: new BoxDecoration(backgroundColor: theme.primaryColor), - child: new Column([ + child: new Column([ new GestureDetector( onTap: () => _handleChangeMode(DatePickerMode.day), child: new Text(new DateFormat("MMM").format(selectedDate).toUpperCase(), style: monthStyle) @@ -190,11 +190,11 @@ class DayPicker extends StatelessComponent { DateFormat dateFormat = new DateFormat(); DateSymbols symbols = dateFormat.dateSymbols; - List headers = []; + List headers = []; for (String weekDay in symbols.NARROWWEEKDAYS) { headers.add(new Text(weekDay, style: headerStyle)); } - List rows = [ + List rows = [ new Text(new DateFormat("MMMM y").format(displayedMonth), style: monthStyle), new Flex( headers, @@ -208,7 +208,7 @@ class DayPicker extends StatelessComponent { int daysInMonth = new DateTime(year, month + 1).difference(new DateTime(year, month)).inDays; int firstDay = new DateTime(year, month).day; int weeksShown = 6; - List days = [ + List days = [ DateTime.SUNDAY, DateTime.MONDAY, DateTime.TUESDAY, @@ -218,7 +218,7 @@ class DayPicker extends StatelessComponent { DateTime.SATURDAY ]; int daySlots = weeksShown * days.length; - List labels = []; + List labels = []; for (int i = 0; i < daySlots; i++) { // This assumes a start day of SUNDAY, but could be changed. int day = i - firstDay + 1; diff --git a/packages/flutter/lib/src/material/dialog.dart b/packages/flutter/lib/src/material/dialog.dart index 1f60f36f96..9a39a00578 100644 --- a/packages/flutter/lib/src/material/dialog.dart +++ b/packages/flutter/lib/src/material/dialog.dart @@ -101,7 +101,7 @@ class Dialog extends StatelessComponent { )); } - return new Stack([ + return new Stack([ new GestureDetector( onTap: onDismiss, child: new Container( diff --git a/packages/flutter/lib/src/material/drawer.dart b/packages/flutter/lib/src/material/drawer.dart index 8e6dc024f4..d41e0875de 100644 --- a/packages/flutter/lib/src/material/drawer.dart +++ b/packages/flutter/lib/src/material/drawer.dart @@ -61,7 +61,7 @@ class _Drawer extends StatelessComponent { if (interactive) route._settle(velocity); }, - child: new Stack([ + child: new Stack([ // mask new GestureDetector( onTap: () { diff --git a/packages/flutter/lib/src/material/drawer_header.dart b/packages/flutter/lib/src/material/drawer_header.dart index 8078c0179b..650d0f2422 100644 --- a/packages/flutter/lib/src/material/drawer_header.dart +++ b/packages/flutter/lib/src/material/drawer_header.dart @@ -29,7 +29,7 @@ class DrawerHeader extends StatelessComponent { ), padding: const EdgeDims.only(bottom: 7.0), margin: const EdgeDims.only(bottom: 8.0), - child: new Column([ + child: new Column([ new Flexible(child: new Container()), new Container( padding: const EdgeDims.symmetric(horizontal: 16.0), diff --git a/packages/flutter/lib/src/material/edges.dart b/packages/flutter/lib/src/material/edges.dart index fad0e0f09d..c753c423ba 100644 --- a/packages/flutter/lib/src/material/edges.dart +++ b/packages/flutter/lib/src/material/edges.dart @@ -5,7 +5,7 @@ enum MaterialEdge { canvas, card, circle } // This map gives the border radii for each type of material. -const Map edges = const { +const Map edges = const { MaterialEdge.canvas: null, MaterialEdge.card: 2.0, MaterialEdge.circle: null, diff --git a/packages/flutter/lib/src/material/icon.dart b/packages/flutter/lib/src/material/icon.dart index 223dc78de5..8c25d35387 100644 --- a/packages/flutter/lib/src/material/icon.dart +++ b/packages/flutter/lib/src/material/icon.dart @@ -15,7 +15,13 @@ class IconThemeData { const IconThemeData({ this.color }); final IconThemeColor color; - bool operator==(other) => other.runtimeType == runtimeType && other.color == color; + bool operator ==(dynamic other) { + if (other is! IconThemeData) + return false; + final IconThemeData typedOther = other; + return color == typedOther; + } + int get hashCode => color.hashCode; } @@ -96,7 +102,7 @@ class Icon extends StatelessComponent { String colorSuffix = _getColorSuffix(context); return new AssetImage( bundle: _iconBundle, - name: '${category}/${density}/ic_${subtype}_${colorSuffix}_${size}dp.png', + name: '$category/$density/ic_${subtype}_${colorSuffix}_${size}dp.png', width: size.toDouble(), height: size.toDouble(), colorFilter: colorFilter diff --git a/packages/flutter/lib/src/material/input.dart b/packages/flutter/lib/src/material/input.dart index 608601d4d4..1322f68473 100644 --- a/packages/flutter/lib/src/material/input.dart +++ b/packages/flutter/lib/src/material/input.dart @@ -119,6 +119,7 @@ class _InputState extends ScrollableState { ) ), onPointerDown: (_) { + // TODO(ianh): https://github.com/flutter/engine/issues/1530 if (Focus.at(context, config)) { assert(_keyboardHandle.attached); _keyboardHandle.showByRequest(); diff --git a/packages/flutter/lib/src/material/popup_menu.dart b/packages/flutter/lib/src/material/popup_menu.dart index 65bf342b09..10d0c2bab0 100644 --- a/packages/flutter/lib/src/material/popup_menu.dart +++ b/packages/flutter/lib/src/material/popup_menu.dart @@ -49,7 +49,7 @@ class PopupMenu extends StatelessComponent { )); double unit = 1.0 / (items.length + 1.5); // 1.0 for the width and 0.5 for the last item's fade. - List children = []; + List children = []; for (int i = 0; i < items.length; ++i) { double start = (i + 1) * unit; @@ -64,15 +64,15 @@ class PopupMenu extends StatelessComponent { ); } - final width = new AnimatedValue(0.0, end: 1.0, curve: new Interval(0.0, unit)); - final height = new AnimatedValue(0.0, end: 1.0, curve: new Interval(0.0, unit * items.length)); + final AnimatedValue width = new AnimatedValue(0.0, end: 1.0, curve: new Interval(0.0, unit)); + final AnimatedValue height = new AnimatedValue(0.0, end: 1.0, curve: new Interval(0.0, unit * items.length)); return new FadeTransition( performance: performance, opacity: new AnimatedValue(0.0, end: 1.0, curve: new Interval(0.0, 1.0 / 3.0)), child: new BuilderTransition( performance: performance, - variables: [width, height], + variables: >[width, height], builder: (BuildContext context) { return new CustomPaint( callback: (ui.Canvas canvas, Size size) { diff --git a/packages/flutter/lib/src/material/progress_indicator.dart b/packages/flutter/lib/src/material/progress_indicator.dart index 46d31717a2..2c20a0af3e 100644 --- a/packages/flutter/lib/src/material/progress_indicator.dart +++ b/packages/flutter/lib/src/material/progress_indicator.dart @@ -60,7 +60,7 @@ class _ProgressIndicatorState extends State { return config._buildIndicator(context, _performance.value); return new BuilderTransition( - variables: [_performance.variable], + variables: >[_performance.variable], performance: _performance.view, builder: (BuildContext context) { return config._buildIndicator(context, _performance.value); diff --git a/packages/flutter/lib/src/material/radial_reaction.dart b/packages/flutter/lib/src/material/radial_reaction.dart index 35538fa79f..ee4748f909 100644 --- a/packages/flutter/lib/src/material/radial_reaction.dart +++ b/packages/flutter/lib/src/material/radial_reaction.dart @@ -37,7 +37,7 @@ class RadialReaction { _showPerformance.updateVariable(_innerRadius); }); _fade = new ValuePerformance( - variable: new AnimatedValue(1.0, end: 0.0, curve: easeIn), + variable: new AnimatedValue(1.0, end: 0.0, curve: easeIn), duration: _kHideDuration ); } diff --git a/packages/flutter/lib/src/material/shadows.dart b/packages/flutter/lib/src/material/shadows.dart index f9e998eef4..32be8300d2 100644 --- a/packages/flutter/lib/src/material/shadows.dart +++ b/packages/flutter/lib/src/material/shadows.dart @@ -6,8 +6,8 @@ import 'dart:ui' show Color, Offset; import 'package:flutter/painting.dart'; -const Map> shadows = const { - 1: const [ +const Map> shadows = const >{ + 1: const [ const BoxShadow( color: const Color(0x1F000000), offset: const Offset(0.0, 1.0), @@ -17,7 +17,7 @@ const Map> shadows = const { offset: const Offset(0.0, 1.0), blur: 2.0), ], - 2: const [ + 2: const [ const BoxShadow( color: const Color(0x29000000), offset: const Offset(0.0, 3.0), @@ -27,7 +27,7 @@ const Map> shadows = const { offset: const Offset(0.0, 3.0), blur: 6.0), ], - 3: const [ + 3: const [ const BoxShadow( color: const Color(0x30000000), offset: const Offset(0.0, 10.0), @@ -37,7 +37,7 @@ const Map> shadows = const { offset: const Offset(0.0, 6.0), blur: 6.0), ], - 4: const [ + 4: const [ const BoxShadow( color: const Color(0x40000000), offset: const Offset(0.0, 14.0), @@ -47,7 +47,7 @@ const Map> shadows = const { offset: const Offset(0.0, 10.0), blur: 10.0), ], - 5: const [ + 5: const [ const BoxShadow( color: const Color(0x4E000000), offset: const Offset(0.0, 19.0), diff --git a/packages/flutter/lib/src/material/snack_bar.dart b/packages/flutter/lib/src/material/snack_bar.dart index 8b631d0ce4..3441fa7438 100644 --- a/packages/flutter/lib/src/material/snack_bar.dart +++ b/packages/flutter/lib/src/material/snack_bar.dart @@ -24,7 +24,7 @@ class SnackBarAction extends StatelessComponent { final String label; final GestureTapCallback onPressed; - Widget build(BuildContext) { + Widget build(BuildContext context) { return new GestureDetector( onTap: onPressed, child: new Container( @@ -51,7 +51,7 @@ class SnackBar extends StatelessComponent { final PerformanceView performance; Widget build(BuildContext context) { - List children = [ + List children = [ new Flexible( child: new Container( margin: const EdgeDims.symmetric(vertical: _kVerticalPadding), diff --git a/packages/flutter/lib/src/material/switch.dart b/packages/flutter/lib/src/material/switch.dart index 9b6573dd04..c5233fa2a3 100644 --- a/packages/flutter/lib/src/material/switch.dart +++ b/packages/flutter/lib/src/material/switch.dart @@ -70,7 +70,7 @@ class _RenderSwitch extends RenderToggleable { Color thumbColor: _kThumbOffColor, ValueChanged onChanged }) : _thumbColor = thumbColor, - super(value: value, onChanged: onChanged, size: _kSwitchSize) {} + super(value: value, onChanged: onChanged, size: _kSwitchSize); Color _thumbColor; Color get thumbColor => _thumbColor; diff --git a/packages/flutter/lib/src/material/tabs.dart b/packages/flutter/lib/src/material/tabs.dart index 982efcf7ea..695708b531 100644 --- a/packages/flutter/lib/src/material/tabs.dart +++ b/packages/flutter/lib/src/material/tabs.dart @@ -33,8 +33,7 @@ const int _kTabIconSize = 24; const double _kTabBarScrollDrag = 0.025; const Duration _kTabBarScroll = const Duration(milliseconds: 200); -class _TabBarParentData extends BoxParentData with - ContainerParentDataMixin { } +class _TabBarParentData extends ContainerBoxParentDataMixin { } class _RenderTabBar extends RenderBox with ContainerRenderObjectMixin, @@ -100,8 +99,8 @@ class _RenderTabBar extends RenderBox with RenderBox child = firstChild; while (child != null) { maxWidth = math.max(maxWidth, child.getMinIntrinsicWidth(widthConstraints)); - assert(child.parentData is _TabBarParentData); - child = child.parentData.nextSibling; + final _TabBarParentData childParentData = child.parentData; + child = childParentData.nextSibling; } double width = isScrollable ? maxWidth : maxWidth * childCount; return constraints.constrainWidth(width); @@ -115,8 +114,8 @@ class _RenderTabBar extends RenderBox with RenderBox child = firstChild; while (child != null) { maxWidth = math.max(maxWidth, child.getMaxIntrinsicWidth(widthConstraints)); - assert(child.parentData is _TabBarParentData); - child = child.parentData.nextSibling; + final _TabBarParentData childParentData = child.parentData; + child = childParentData.nextSibling; } double width = isScrollable ? maxWidth : maxWidth * childCount; return constraints.constrainWidth(width); @@ -139,10 +138,10 @@ class _RenderTabBar extends RenderBox with RenderBox child = firstChild; while (child != null) { child.layout(tabConstraints); - assert(child.parentData is _TabBarParentData); - child.parentData.position = new Point(x, 0.0); + final _TabBarParentData childParentData = child.parentData; + childParentData.position = new Point(x, 0.0); x += tabWidth; - child = child.parentData.nextSibling; + child = childParentData.nextSibling; } } @@ -157,10 +156,10 @@ class _RenderTabBar extends RenderBox with RenderBox child = firstChild; while (child != null) { child.layout(tabConstraints, parentUsesSize: true); - assert(child.parentData is _TabBarParentData); - child.parentData.position = new Point(x, 0.0); + final _TabBarParentData childParentData = child.parentData; + childParentData.position = new Point(x, 0.0); x += child.size.width; - child = child.parentData.nextSibling; + child = childParentData.nextSibling; } return x; } @@ -180,7 +179,8 @@ class _RenderTabBar extends RenderBox with int childIndex = 0; while (child != null) { widths[childIndex++] = child.size.width; - child = child.parentData.nextSibling; + final _TabBarParentData childParentData = child.parentData; + child = childParentData.nextSibling; } assert(childIndex == widths.length); } @@ -221,24 +221,24 @@ class _RenderTabBar extends RenderBox with return; } - var size = new Size(selectedTab.size.width, _kTabIndicatorHeight); - var point = new Point( - selectedTab.parentData.position.x, + final Size size = new Size(selectedTab.size.width, _kTabIndicatorHeight); + final _TabBarParentData selectedTabParentData = selectedTab.parentData; + final Point point = new Point( + selectedTabParentData.position.x, _tabBarHeight - _kTabIndicatorHeight ); - Rect rect = (point + offset) & size; - canvas.drawRect(rect, new Paint()..color = indicatorColor); + canvas.drawRect((point + offset) & size, new Paint()..color = indicatorColor); } void paint(PaintingContext context, Offset offset) { int index = 0; RenderBox child = firstChild; while (child != null) { - assert(child.parentData is _TabBarParentData); - context.paintChild(child, child.parentData.position + offset); + final _TabBarParentData childParentData = child.parentData; + context.paintChild(child, childParentData.position + offset); if (index++ == selectedIndex) _paintIndicator(context.canvas, child, offset); - child = child.parentData.nextSibling; + child = childParentData.nextSibling; } } } @@ -426,7 +426,7 @@ class _TabBarState extends ScrollableState { assert(tabIndex >= 0 && tabIndex < _tabWidths.length); double tabLeft = 0.0; if (tabIndex > 0) - tabLeft = _tabWidths.take(tabIndex).reduce((sum, width) => sum + width); + tabLeft = _tabWidths.take(tabIndex).reduce((double sum, double width) => sum + width); double tabTop = 0.0; double tabBottom = _tabBarSize.height - _kTabIndicatorHeight; double tabRight = tabLeft + _tabWidths[tabIndex]; @@ -469,7 +469,7 @@ class _TabBarState extends ScrollableState { void _updateScrollBehavior() { scrollBehavior.updateExtents( containerExtent: config.scrollDirection == ScrollDirection.vertical ? _viewportSize.height : _viewportSize.width, - contentExtent: _tabWidths.reduce((sum, width) => sum + width) + contentExtent: _tabWidths.reduce((double sum, double width) => sum + width) ); } @@ -523,7 +523,7 @@ class _TabBarState extends ScrollableState { child: new DefaultTextStyle( style: textStyle, child: new BuilderTransition( - variables: [_indicatorRect], + variables: >[_indicatorRect], performance: _indicatorAnimation.view, builder: (BuildContext context) { return new _TabBarWrapper( @@ -591,9 +591,9 @@ class TabNavigator extends StatelessComponent { Widget build(BuildContext context) { assert(views != null && views.isNotEmpty); assert(selectedIndex >= 0 && selectedIndex < views.length); - return new Column([ + return new Column([ new TabBar( - labels: views.map((view) => view.label), + labels: views.map((TabNavigatorView view) => view.label), onChanged: onChanged, selectedIndex: selectedIndex, isScrollable: isScrollable diff --git a/packages/flutter/lib/src/material/tool_bar.dart b/packages/flutter/lib/src/material/tool_bar.dart index 5629b1d5fb..cdcbe9ccac 100644 --- a/packages/flutter/lib/src/material/tool_bar.dart +++ b/packages/flutter/lib/src/material/tool_bar.dart @@ -70,7 +70,7 @@ class ToolBar extends StatelessComponent { ), child: new DefaultTextStyle( style: sideStyle, - child: new Column([ + child: new Column([ new Container( child: new Row(children), height: kToolBarHeight diff --git a/packages/flutter/lib/src/painting/box_painter.dart b/packages/flutter/lib/src/painting/box_painter.dart index 959394f266..e018615599 100644 --- a/packages/flutter/lib/src/painting/box_painter.dart +++ b/packages/flutter/lib/src/painting/box_painter.dart @@ -101,15 +101,6 @@ class EdgeDims { ); } - bool operator ==(other) { - return identical(this, other) || - (other is EdgeDims && - top == other.top && - right == other.right && - bottom == other.bottom && - left == other.left); - } - /// Linearly interpolate between two EdgeDims /// /// If either is null, this function interpolates from [EdgeDims.zero]. @@ -131,6 +122,18 @@ class EdgeDims { /// An EdgeDims with zero offsets in each direction static const EdgeDims zero = const EdgeDims.TRBL(0.0, 0.0, 0.0, 0.0); + bool operator ==(dynamic other) { + if (identical(this, other)) + return true; + if (other is! EdgeDims) + return false; + final EdgeDims typedOther = other; + return top == typedOther.top && + right == typedOther.right && + bottom == typedOther.bottom && + left == typedOther.left; + } + int get hashCode { int value = 373; value = 37 * value + top.hashCode; @@ -139,6 +142,7 @@ class EdgeDims { value = 37 * value + right.hashCode; return value; } + String toString() => "EdgeDims($top, $right, $bottom, $left)"; } @@ -322,8 +326,7 @@ class LinearGradient extends Gradient { final ui.TileMode tileMode; ui.Shader createShader() { - return new ui.Gradient.linear([begin, end], this.colors, - this.stops, this.tileMode); + return new ui.Gradient.linear([begin, end], this.colors, this.stops, this.tileMode); } String toString() { @@ -612,7 +615,7 @@ class BoxDecoration { } String toString([String prefix = '']) { - List result = []; + List result = []; if (backgroundColor != null) result.add('${prefix}backgroundColor: $backgroundColor'); if (backgroundImage != null) @@ -622,13 +625,13 @@ class BoxDecoration { if (borderRadius != null) result.add('${prefix}borderRadius: $borderRadius'); if (boxShadow != null) - result.add('${prefix}boxShadow: ${boxShadow.map((shadow) => shadow.toString())}'); + result.add('${prefix}boxShadow: ${boxShadow.map((BoxShadow shadow) => shadow.toString())}'); if (gradient != null) result.add('${prefix}gradient: $gradient'); if (shape != Shape.rectangle) result.add('${prefix}shape: $shape'); if (result.isEmpty) - return '${prefix}'; + return '$prefix'; return result.join('\n'); } } diff --git a/packages/flutter/lib/src/painting/shadows.dart b/packages/flutter/lib/src/painting/shadows.dart index d0ad34638e..28cc7be7ac 100644 --- a/packages/flutter/lib/src/painting/shadows.dart +++ b/packages/flutter/lib/src/painting/shadows.dart @@ -6,23 +6,24 @@ import 'dart:ui' as ui; /// A helper class to build a [ui.DrawLooper] for drawing shadows class ShadowDrawLooperBuilder { - var builder_ = new ui.LayerDrawLooperBuilder(); + ui.LayerDrawLooperBuilder _builder = new ui.LayerDrawLooperBuilder(); /// Add a shadow with the given parameters void addShadow(ui.Offset offset, ui.Color color, double blur) { - builder_.addLayerOnTop( - new ui.DrawLooperLayerInfo() - ..setPaintBits(ui.PaintBits.all) - ..setOffset(offset) - ..setColorMode(ui.TransferMode.src), - new ui.Paint() - ..color = color - ..maskFilter = new ui.MaskFilter.blur(ui.BlurStyle.normal, blur)); + _builder.addLayerOnTop( + new ui.DrawLooperLayerInfo() + ..setPaintBits(ui.PaintBits.all) + ..setOffset(offset) + ..setColorMode(ui.TransferMode.src), + new ui.Paint() + ..color = color + ..maskFilter = new ui.MaskFilter.blur(ui.BlurStyle.normal, blur) + ); } /// Returns the draw looper built for the added shadows ui.DrawLooper build() { - builder_.addLayerOnTop(new ui.DrawLooperLayerInfo(), new ui.Paint()); - return builder_.build(); + _builder.addLayerOnTop(new ui.DrawLooperLayerInfo(), new ui.Paint()); + return _builder.build(); } } diff --git a/packages/flutter/lib/src/painting/text_painter.dart b/packages/flutter/lib/src/painting/text_painter.dart index 733a42b8b8..710a11f11d 100644 --- a/packages/flutter/lib/src/painting/text_painter.dart +++ b/packages/flutter/lib/src/painting/text_painter.dart @@ -38,10 +38,16 @@ class PlainTextSpan extends TextSpan { builder.addText(text); } - bool operator ==(other) => other is PlainTextSpan && text == other.text; + bool operator ==(dynamic other) { + if (other is! PlainTextSpan) + return false; + final PlainTextSpan typedOther = other; + return text == typedOther.text; + } + int get hashCode => text.hashCode; - String toString([String prefix = '']) => '${prefix}${runtimeType}: "${text}"'; + String toString([String prefix = '']) => '$prefix$runtimeType: "$text"'; } /// An immutable text span that applies a style to a list of children @@ -79,15 +85,17 @@ class StyledTextSpan extends TextSpan { style.applyToContainerCSSStyle(container.style); } - bool operator ==(other) { + bool operator ==(dynamic other) { if (identical(this, other)) return true; - if (other is! StyledTextSpan - || style != other.style - || children.length != other.children.length) + if (other is! StyledTextSpan) + return false; + final StyledTextSpan typedOther = other; + if (style != typedOther.style || + children.length != typedOther.children.length) return false; for (int i = 0; i < children.length; ++i) { - if (children[i] != other.children[i]) + if (children[i] != typedOther.children[i]) return false; } return true; @@ -102,28 +110,72 @@ class StyledTextSpan extends TextSpan { } String toString([String prefix = '']) { - List result = []; - result.add('${prefix}${runtimeType}:'); - var indent = '${prefix} '; + List result = []; + result.add('$prefix$runtimeType:'); + var indent = '$prefix '; result.add('${style.toString(indent)}'); - for (TextSpan child in children) { + for (TextSpan child in children) result.add(child.toString(indent)); - } return result.join('\n'); } } const bool _kEnableNewTextPainter = false; -/// An object that paints a [TextSpan] into a canvas -class TextPainter { +abstract class TextPainter { + factory TextPainter(TextSpan text) { if (_kEnableNewTextPainter) return new _NewTextPainter(text); - return new TextPainter._(text); + return new _OldTextPainter(text); } - TextPainter._(TextSpan text) { + /// The (potentially styled) text to paint + TextSpan get text; + void set text(TextSpan value); + + /// The minimum width at which to layout the text + double get minWidth; + void set minWidth(double value); + + /// The maximum width at which to layout the text + double get maxWidth; + void set maxWidth(double value); + + /// The minimum height at which to layout the text + double get minHeight; + void set minHeight(double value); + + /// The maximum height at which to layout the text + double get maxHeight; + void set maxHeight(double value); + + /// The width at which decreasing the width of the text would prevent it from + /// painting itself completely within its bounds + double get minContentWidth; + + /// The width at which increasing the width of the text no longer decreases + /// the height + double get maxContentWidth; + + /// The height required to paint the text completely within its bounds + double get height; + + /// The distance from the top of the text to the first baseline of the given + /// type + double computeDistanceToActualBaseline(TextBaseline baseline); + + /// Compute the visual position of the glyphs for painting the text + void layout(); + + /// Paint the text onto the given canvas at the given offset + void paint(ui.Canvas canvas, ui.Offset offset); + +} + +/// An object that paints a [TextSpan] into a canvas +class _OldTextPainter implements TextPainter { + _OldTextPainter(TextSpan text) { _layoutRoot.rootElement = _document.createElement('p'); assert(text != null); this.text = text; diff --git a/packages/flutter/lib/src/painting/text_style.dart b/packages/flutter/lib/src/painting/text_style.dart index 43ffa44967..dc840cef93 100644 --- a/packages/flutter/lib/src/painting/text_style.dart +++ b/packages/flutter/lib/src/painting/text_style.dart @@ -137,7 +137,7 @@ class TextStyle { TextDecoration.overline: 'overline', TextDecoration.lineThrough: 'lineThrough' }; - return decoration.map((d) => toCSS[d]).join(' '); + return decoration.map((TextDecoration d) => toCSS[d]).join(' '); } static String _decorationStyleToCSSString(TextDecorationStyle decorationStyle) { @@ -210,24 +210,26 @@ class TextStyle { }[textAlign]; } if (height != null) { - cssStyle['line-height'] = '${height}'; + cssStyle['line-height'] = '$height'; } } - bool operator ==(other) { + bool operator ==(dynamic other) { if (identical(this, other)) return true; - return other is TextStyle && - color == other.color && - fontFamily == other.fontFamily && - fontSize == other.fontSize && - fontWeight == other.fontWeight && - fontStyle == other.fontStyle && - textAlign == other.textAlign && - textBaseline == other.textBaseline && - decoration == other.decoration && - decorationColor == other.decorationColor && - decorationStyle == other.decorationStyle; + if (other is! TextStyle) + return false; + final TextStyle typedOther = other; + return color == typedOther.color && + fontFamily == typedOther.fontFamily && + fontSize == typedOther.fontSize && + fontWeight == typedOther.fontWeight && + fontStyle == typedOther.fontStyle && + textAlign == typedOther.textAlign && + textBaseline == typedOther.textBaseline && + decoration == typedOther.decoration && + decorationColor == typedOther.decorationColor && + decorationStyle == typedOther.decorationStyle; } int get hashCode { @@ -247,12 +249,12 @@ class TextStyle { } String toString([String prefix = '']) { - List result = []; + List result = []; if (color != null) result.add('${prefix}color: $color'); // TODO(hansmuller): escape the fontFamily string. if (fontFamily != null) - result.add('${prefix}fontFamily: "${fontFamily}"'); + result.add('${prefix}fontFamily: "$fontFamily"'); if (fontSize != null) result.add('${prefix}fontSize: $fontSize'); if (fontWeight != null) @@ -270,7 +272,7 @@ class TextStyle { if (decorationStyle != null) result.add('${prefix}decorationStyle: $decorationStyle'); if (result.isEmpty) - return '${prefix}'; + return '$prefix'; return result.join('\n'); } } diff --git a/packages/flutter/lib/src/rendering/auto_layout.dart b/packages/flutter/lib/src/rendering/auto_layout.dart index f394f558a3..4aca6f7dd0 100644 --- a/packages/flutter/lib/src/rendering/auto_layout.dart +++ b/packages/flutter/lib/src/rendering/auto_layout.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:cassowary/cassowary.dart' as al; +import 'package:cassowary/cassowary.dart' as al; // "auto layout" import 'box.dart'; import 'object.dart'; @@ -40,11 +40,12 @@ abstract class _AutoLayoutParamMixin { } void _setupEditVariablesInSolver(al.Solver solver, double priority) { - solver.addEditVariables([ + solver.addEditVariables([ _leftEdge.variable, _rightEdge.variable, _topEdge.variable, - _bottomEdge.variable], priority); + _bottomEdge.variable + ], priority); } void _applyEditsAtSize(al.Solver solver, Size size) { @@ -90,8 +91,7 @@ abstract class _AutoLayoutParamMixin { } } -class AutoLayoutParentData extends BoxParentData - with ContainerParentDataMixin, _AutoLayoutParamMixin { +class AutoLayoutParentData extends ContainerBoxParentDataMixin with _AutoLayoutParamMixin { AutoLayoutParentData(this._renderBox) { _setupLayoutParameters(this); @@ -103,8 +103,10 @@ class AutoLayoutParentData extends BoxParentData // This is called by the parent's layout function // to lay our box out. assert(_renderBox.parentData == this); - assert(_renderBox.parent is RenderAutoLayout); - assert((_renderBox.parent as RenderAutoLayout).debugDoingThisLayout); // TODO(ianh): Remove cast once the analyzer is cleverer + assert(() { + final RenderAutoLayout parent = _renderBox.parent; + assert(parent.debugDoingThisLayout); + }); BoxConstraints size = new BoxConstraints.tightFor( width: _rightEdge.value - _leftEdge.value, height: _bottomEdge.value - _topEdge.value @@ -114,7 +116,7 @@ class AutoLayoutParentData extends BoxParentData } List _constructImplicitConstraints() { - return [ + return [ _leftEdge >= al.cm(0.0), // The left edge must be positive. _rightEdge >= _leftEdge, // Width must be positive. ]; @@ -174,11 +176,15 @@ class RenderAutoLayout extends RenderBox void adoptChild(RenderObject child) { // Make sure to call super first to setup the parent data super.adoptChild(child); - child.parentData._setupImplicitConstraints(_solver); + final AutoLayoutParentData childParentData = child.parentData; + childParentData._setupImplicitConstraints(_solver); + assert(child.parentData == childParentData); } void dropChild(RenderObject child) { - child.parentData._removeImplicitConstraints(_solver); + final AutoLayoutParentData childParentData = child.parentData; + childParentData._removeImplicitConstraints(_solver); + assert(child.parentData == childParentData); super.dropChild(child); } diff --git a/packages/flutter/lib/src/rendering/block.dart b/packages/flutter/lib/src/rendering/block.dart index 1d3ba27751..18745490dc 100644 --- a/packages/flutter/lib/src/rendering/block.dart +++ b/packages/flutter/lib/src/rendering/block.dart @@ -10,7 +10,7 @@ import 'box.dart'; import 'object.dart'; /// Parent data for use with [RenderBlockBase] -class BlockParentData extends BoxParentData with ContainerParentDataMixin { } +class BlockParentData extends ContainerBoxParentDataMixin { } /// The direction in which the block should lay out enum BlockDirection { @@ -106,10 +106,11 @@ abstract class RenderBlockBase extends RenderBox with ContainerRenderObjectMixin RenderBox child = firstChild; while (child != null) { child.layout(innerConstraints, parentUsesSize: true); - assert(child.parentData is BlockParentData); - child.parentData.position = isVertical ? new Point(0.0, position) : new Point(position, 0.0); + final BlockParentData childParentData = child.parentData; + childParentData.position = isVertical ? new Point(0.0, position) : new Point(position, 0.0); position += isVertical ? child.size.height : child.size.width; - child = child.parentData.nextSibling; + assert(child.parentData == childParentData); + child = childParentData.nextSibling; } size = isVertical ? constraints.constrain(new Size(constraints.maxWidth, _mainAxisExtent)) : @@ -117,7 +118,7 @@ abstract class RenderBlockBase extends RenderBox with ContainerRenderObjectMixin assert(!size.isInfinite); } - String debugDescribeSettings(String prefix) => '${super.debugDescribeSettings(prefix)}${prefix}direction: ${direction}\n'; + String debugDescribeSettings(String prefix) => '${super.debugDescribeSettings(prefix)}${prefix}direction: $direction\n'; } /// A block layout with a concrete set of children @@ -136,8 +137,8 @@ class RenderBlock extends RenderBlockBase { RenderBox child = firstChild; while (child != null) { extent = math.max(extent, childSize(child, innerConstraints)); - assert(child.parentData is BlockParentData); - child = child.parentData.nextSibling; + final BlockParentData childParentData = child.parentData; + child = childParentData.nextSibling; } return extent; } @@ -156,24 +157,28 @@ class RenderBlock extends RenderBlockBase { return childExtent == child.getMaxIntrinsicWidth(innerConstraints); }); extent += childExtent; - assert(child.parentData is BlockParentData); - child = child.parentData.nextSibling; + final BlockParentData childParentData = child.parentData; + child = childParentData.nextSibling; } return math.max(extent, minExtent); } double getMinIntrinsicWidth(BoxConstraints constraints) { if (isVertical) { - return _getIntrinsicCrossAxis(constraints, - (c, innerConstraints) => c.getMinIntrinsicWidth(innerConstraints)); + return _getIntrinsicCrossAxis( + constraints, + (RenderBox child, BoxConstraints innerConstraints) => child.getMinIntrinsicWidth(innerConstraints) + ); } return _getIntrinsicMainAxis(constraints); } double getMaxIntrinsicWidth(BoxConstraints constraints) { if (isVertical) { - return _getIntrinsicCrossAxis(constraints, - (c, innerConstraints) => c.getMaxIntrinsicWidth(innerConstraints)); + return _getIntrinsicCrossAxis( + constraints, + (RenderBox child, BoxConstraints innerConstraints) => child.getMaxIntrinsicWidth(innerConstraints) + ); } return _getIntrinsicMainAxis(constraints); } @@ -181,15 +186,19 @@ class RenderBlock extends RenderBlockBase { double getMinIntrinsicHeight(BoxConstraints constraints) { if (isVertical) return _getIntrinsicMainAxis(constraints); - return _getIntrinsicCrossAxis(constraints, - (c, innerConstraints) => c.getMinIntrinsicWidth(innerConstraints)); + return _getIntrinsicCrossAxis( + constraints, + (RenderBox child, BoxConstraints innerConstraints) => child.getMinIntrinsicWidth(innerConstraints) + ); } double getMaxIntrinsicHeight(BoxConstraints constraints) { if (isVertical) return _getIntrinsicMainAxis(constraints); - return _getIntrinsicCrossAxis(constraints, - (c, innerConstraints) => c.getMaxIntrinsicWidth(innerConstraints)); + return _getIntrinsicCrossAxis( + constraints, + (RenderBox child, BoxConstraints innerConstraints) => child.getMaxIntrinsicWidth(innerConstraints) + ); } double computeDistanceToActualBaseline(TextBaseline baseline) { @@ -391,5 +400,5 @@ class RenderBlockViewport extends RenderBlockBase { defaultHitTestChildren(result, position: position + new Offset(-startOffset, 0.0)); } - String debugDescribeSettings(String prefix) => '${super.debugDescribeSettings(prefix)}${prefix}startOffset: ${startOffset}\n'; + String debugDescribeSettings(String prefix) => '${super.debugDescribeSettings(prefix)}${prefix}startOffset: $startOffset\n'; } diff --git a/packages/flutter/lib/src/rendering/box.dart b/packages/flutter/lib/src/rendering/box.dart index 288610e548..cfc9cd2cd5 100644 --- a/packages/flutter/lib/src/rendering/box.dart +++ b/packages/flutter/lib/src/rendering/box.dart @@ -233,15 +233,18 @@ class BoxConstraints extends Constraints { ); } - bool operator ==(other) { + bool operator ==(dynamic other) { if (identical(this, other)) return true; - return other is BoxConstraints && - minWidth == other.minWidth && - maxWidth == other.maxWidth && - minHeight == other.minHeight && - maxHeight == other.maxHeight; + if (other is! BoxConstraints) + return false; + final BoxConstraints typedOther = other; + return minWidth == typedOther.minWidth && + maxWidth == typedOther.maxWidth && + minHeight == typedOther.minHeight && + maxHeight == typedOther.maxHeight; } + int get hashCode { int value = 373; value = 37 * value + minWidth.hashCode; @@ -274,6 +277,10 @@ class BoxParentData extends ParentData { String toString() => 'position=$position'; } +/// Abstract ParentData subclass for RenderBox subclasses that want the +/// ContainerRenderObjectMixin. +abstract class ContainerBoxParentDataMixin extends BoxParentData with ContainerParentDataMixin { } + /// A render object in a 2D cartesian coordinate system /// /// The size of each box is expressed as a width and a height. Each box has its @@ -349,7 +356,7 @@ abstract class RenderBox extends RenderObject { assert(hasSize); assert(() { if (_size is _DebugSize) { - final _DebugSize _size = this._size; // TODO(ianh): Remove this once the analyzer is cleverer + final _DebugSize _size = this._size; assert(_size._owner == this); if (RenderObject.debugActiveLayout != null) { // we are always allowed to access our own size (for print debugging and asserts if nothing else) @@ -358,7 +365,7 @@ abstract class RenderBox extends RenderObject { assert(debugDoingThisResize || debugDoingThisLayout || (RenderObject.debugActiveLayout == parent && _size._canBeUsedByParent)); } - assert(_size == this._size); // TODO(ianh): Remove this once the analyzer is cleverer + assert(_size == this._size); } return true; }); @@ -406,8 +413,7 @@ abstract class RenderBox extends RenderObject { double getDistanceToBaseline(TextBaseline baseline, { bool onlyReal: false }) { assert(!needsLayout); assert(!_debugDoingBaseline); - final parent = this.parent; // TODO(ianh): Remove this once the analyzer is cleverer - assert(parent is RenderObject); + final RenderObject parent = this.parent; assert(() { if (RenderObject.debugDoingLayout) return (RenderObject.debugActiveLayout == parent) && parent.debugDoingThisLayout; @@ -419,7 +425,7 @@ abstract class RenderBox extends RenderObject { assert(_debugSetDoingBaseline(true)); double result = getDistanceToActualBaseline(baseline); assert(_debugSetDoingBaseline(false)); - assert(parent == this.parent); // TODO(ianh): Remove this once the analyzer is cleverer + assert(parent == this.parent); if (result == null && !onlyReal) return size.height; return result; @@ -475,10 +481,9 @@ abstract class RenderBox extends RenderObject { if (_cachedBaselines != null && _cachedBaselines.isNotEmpty) { // if we have cached data, then someone must have used our data assert(_ancestorUsesBaseline); - final parent = this.parent; // TODO(ianh): Remove this once the analyzer is cleverer - assert(parent is RenderObject); + final RenderObject parent = this.parent; parent.markNeedsLayout(); - assert(parent == this.parent); // TODO(ianh): Remove this once the analyzer is cleverer + assert(parent == this.parent); // Now that they're dirty, we can forget that they used the // baseline. If they use it again, then we'll set the bit // again, and if we get dirty again, we'll notify them again. @@ -628,7 +633,7 @@ abstract class RenderBox extends RenderObject { } } - String debugDescribeSettings(String prefix) => '${super.debugDescribeSettings(prefix)}${prefix}size: ${size}\n'; + String debugDescribeSettings(String prefix) => '${super.debugDescribeSettings(prefix)}${prefix}size: $size\n'; } /// A mixin that provides useful default behaviors for boxes with children @@ -637,7 +642,7 @@ abstract class RenderBox extends RenderObject { /// By convention, this class doesn't override any members of the superclass. /// Instead, it provides helpful functions that subclasses can call as /// appropriate. -abstract class RenderBoxContainerDefaultsMixin> implements ContainerRenderObjectMixin { +abstract class RenderBoxContainerDefaultsMixin> implements ContainerRenderObjectMixin { /// Returns the baseline of the first child with a baseline /// @@ -647,11 +652,11 @@ abstract class RenderBoxContainerDefaultsMixin { +class FlexParentData extends ContainerBoxParentDataMixin { /// The flex factor to use for this child /// /// If null, the child is inflexible and determines its own size. If non-null, @@ -174,8 +174,8 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin c.getMinIntrinsicWidth(innerConstraints) + childSize: (RenderBox child, BoxConstraints innerConstraints) => child.getMinIntrinsicWidth(innerConstraints) ); } @@ -291,7 +291,7 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin c.getMaxIntrinsicWidth(innerConstraints) + childSize: (RenderBox child, BoxConstraints innerConstraints) => child.getMaxIntrinsicWidth(innerConstraints) ); } @@ -299,7 +299,7 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin c.getMinIntrinsicHeight(innerConstraints) + childSize: (RenderBox child, BoxConstraints innerConstraints) => child.getMinIntrinsicHeight(innerConstraints) ); } @@ -307,7 +307,7 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin c.getMaxIntrinsicHeight(innerConstraints)); + childSize: (RenderBox child, BoxConstraints innerConstraints) => child.getMaxIntrinsicHeight(innerConstraints)); } double computeDistanceToActualBaseline(TextBaseline baseline) { @@ -317,8 +317,8 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin 0) { @@ -350,7 +350,7 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin '${super.debugDescribeSettings(prefix)}${prefix}direction: ${_direction}\n${prefix}justifyContent: ${_justifyContent}\n${prefix}alignItems: ${_alignItems}\n${prefix}textBaseline: ${_textBaseline}\n'; + String debugDescribeSettings(String prefix) => '${super.debugDescribeSettings(prefix)}${prefix}direction: $_direction\n${prefix}justifyContent: $_justifyContent\n${prefix}alignItems: $_alignItems\n${prefix}textBaseline: $_textBaseline\n'; } diff --git a/packages/flutter/lib/src/rendering/grid.dart b/packages/flutter/lib/src/rendering/grid.dart index fe7cc07747..05c69cc469 100644 --- a/packages/flutter/lib/src/rendering/grid.dart +++ b/packages/flutter/lib/src/rendering/grid.dart @@ -42,7 +42,7 @@ class _GridMetrics { } /// Parent data for use with [RenderGrid] -class GridParentData extends BoxParentData with ContainerParentDataMixin {} +class GridParentData extends ContainerBoxParentDataMixin {} /// Implements the grid layout algorithm /// @@ -120,14 +120,17 @@ class RenderGrid extends RenderBox with ContainerRenderObjectMixin= metrics.childrenPerRow) { row += 1; column = 0; } - child = child.parentData.nextSibling; + + assert(child.parentData == childParentData); + child = childParentData.nextSibling; } } diff --git a/packages/flutter/lib/src/rendering/image.dart b/packages/flutter/lib/src/rendering/image.dart index e5e7356a83..ce6800c807 100644 --- a/packages/flutter/lib/src/rendering/image.dart +++ b/packages/flutter/lib/src/rendering/image.dart @@ -174,5 +174,5 @@ class RenderImage extends RenderBox { ); } - String debugDescribeSettings(String prefix) => '${super.debugDescribeSettings(prefix)}${prefix}width: ${width}\n${prefix}height: ${height}\n'; + String debugDescribeSettings(String prefix) => '${super.debugDescribeSettings(prefix)}${prefix}width: $width\n${prefix}height: $height\n'; } diff --git a/packages/flutter/lib/src/rendering/object.dart b/packages/flutter/lib/src/rendering/object.dart index f3b1e30d98..7b9c0a1b3d 100644 --- a/packages/flutter/lib/src/rendering/object.dart +++ b/packages/flutter/lib/src/rendering/object.dart @@ -445,7 +445,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { /// used between the parent and child. For example, in box layout, the /// parent data is completely opaque but in sector layout the child is /// permitted to read some fields of the parent data. - dynamic parentData; // TODO(ianh): change the type of this back to ParentData once the analyzer is cleverer + ParentData parentData; /// Override to setup parent data correctly for your children /// @@ -493,13 +493,13 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { dynamic debugExceptionContext = ''; void _debugReportException(String method, dynamic exception, StackTrace stack) { print('-- EXCEPTION --'); - print('The following exception was raised during ${method}():'); + print('The following exception was raised during $method():'); print('$exception'); print('Stack trace:'); print('$stack'); print('The following RenderObject was being processed when the exception was fired:\n${this}'); if (debugExceptionContext != '') - 'That RenderObject had the following exception context:\n${debugExceptionContext}'.split('\n').forEach(print); + 'That RenderObject had the following exception context:\n$debugExceptionContext'.split('\n').forEach(print); if (debugRenderingExceptionHandler != null) debugRenderingExceptionHandler(this, method, exception, stack); } @@ -577,14 +577,13 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { _needsLayout = true; assert(_relayoutSubtreeRoot != null); if (_relayoutSubtreeRoot != this) { - final parent = this.parent; // TODO(ianh): Remove this once the analyzer is cleverer - assert(parent is RenderObject); + final RenderObject parent = this.parent; if (!_doingThisLayoutWithCallback) { parent.markNeedsLayout(); } else { assert(parent._debugDoingThisLayout); } - assert(parent == this.parent); // TODO(ianh): Remove this once the analyzer is cleverer + assert(parent == this.parent); } else { _nodesNeedingLayout.add(this); scheduler.ensureVisualUpdate(); @@ -635,7 +634,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { while(_nodesNeedingLayout.isNotEmpty) { List dirtyNodes = _nodesNeedingLayout; _nodesNeedingLayout = new List(); - dirtyNodes..sort((a, b) => a.depth - b.depth)..forEach((node) { + dirtyNodes..sort((RenderObject a, RenderObject b) => a.depth - b.depth)..forEach((RenderObject node) { if (node._needsLayout && node.attached) node._layoutWithoutResize(); }); @@ -696,13 +695,13 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { /// implemented here) to return early if the child does not need to do any /// work to update its layout information. void layout(Constraints constraints, { bool parentUsesSize: false }) { - final parent = this.parent; // TODO(ianh): Remove this once the analyzer is cleverer + final RenderObject parent = this.parent; RenderObject relayoutSubtreeRoot; if (!parentUsesSize || sizedByParent || constraints.isTight || parent is! RenderObject) relayoutSubtreeRoot = this; else relayoutSubtreeRoot = parent._relayoutSubtreeRoot; - assert(parent == this.parent); // TODO(ianh): Remove this once the analyzer is cleverer + assert(parent == this.parent); if (!needsLayout && constraints == _constraints && relayoutSubtreeRoot == _relayoutSubtreeRoot) return; _constraints = constraints; @@ -745,7 +744,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { }); _needsLayout = false; markNeedsPaint(); - assert(parent == this.parent); // TODO(ianh): Remove this once the analyzer is cleverer + assert(parent == this.parent); } /// Whether the constraints are the only input to the sizing algorithm (in @@ -866,9 +865,10 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { if (_needsCompositingBitsUpdate) return; _needsCompositingBitsUpdate = true; - final AbstractNode parent = this.parent; // TODO(ianh): remove the once the analyzer is cleverer + final AbstractNode parent = this.parent; if (parent is RenderObject) parent._markNeedsCompositingBitsUpdate(); + assert(parent == this.parent); } bool _needsCompositing = false; /// Whether we or one of our descendants has a compositing layer @@ -930,7 +930,9 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { // care of updating the layer we're in and when they do that // we'll get our paint() method called. assert(_layer == null); - (parent as RenderObject).markNeedsPaint(); // TODO(ianh): remove the cast once the analyzer is cleverer + final RenderObject parent = this.parent; + parent.markNeedsPaint(); + assert(parent == this.parent); } else { // If we're the root of the render tree (probably a RenderView), // then we have to paint ourselves, since nobody else can paint @@ -955,7 +957,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { List dirtyNodes = _nodesNeedingPaint; _nodesNeedingPaint = new List(); // Sort the dirty nodes in reverse order (deepest first). - for (RenderObject node in dirtyNodes..sort((a, b) => b.depth - a.depth)) { + for (RenderObject node in dirtyNodes..sort((RenderObject a, RenderObject b) => b.depth - a.depth)) { assert(node._needsPaint); if (node.attached) node._repaint(); @@ -1095,7 +1097,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { /// Returns a human understandable name String toString() { - String header = '${runtimeType}'; + String header = '$runtimeType'; if (_relayoutSubtreeRoot != null && _relayoutSubtreeRoot != this) { int count = 1; RenderObject target = parent; @@ -1127,7 +1129,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { /// Returns a string describing the current node's fields, one field per line, /// with each line prefixed by the prefix argument. Subclasses should override /// this to have their information included in toStringDeep(). - String debugDescribeSettings(String prefix) => '${prefix}parentData: ${parentData}\n${prefix}constraints: ${constraints}\n'; + String debugDescribeSettings(String prefix) => '${prefix}parentData: $parentData\n${prefix}constraints: $constraints\n'; /// Returns a string describing the current node's descendants. Each line of /// the subtree in the output should be indented by the prefix argument. @@ -1190,16 +1192,16 @@ abstract class ContainerParentDataMixin implemen void detach() { super.detach(); if (previousSibling != null) { - assert(previousSibling.parentData is ContainerParentDataMixin); + final ContainerParentDataMixin previousSiblingParentData = previousSibling.parentData; assert(previousSibling != this); - assert(previousSibling.parentData.nextSibling == this); - previousSibling.parentData.nextSibling = nextSibling; + assert(previousSiblingParentData.nextSibling == this); + previousSiblingParentData.nextSibling = nextSibling; } if (nextSibling != null) { - assert(nextSibling.parentData is ContainerParentDataMixin); + final ContainerParentDataMixin nextSiblingParentData = nextSibling.parentData; assert(nextSibling != this); - assert(nextSibling.parentData.previousSibling == this); - nextSibling.parentData.previousSibling = previousSibling; + assert(nextSiblingParentData.previousSibling == this); + nextSiblingParentData.previousSibling = previousSibling; } previousSibling = null; nextSibling = null; @@ -1213,20 +1215,20 @@ abstract class ContainerParentDataMixin implemen abstract class ContainerRenderObjectMixin> implements RenderObject { bool _debugUltimatePreviousSiblingOf(ChildType child, { ChildType equals }) { - assert(child.parentData is ParentDataType); - while (child.parentData.previousSibling != null) { - assert(child.parentData.previousSibling != child); - child = child.parentData.previousSibling; - assert(child.parentData is ParentDataType); + ParentDataType childParentData = child.parentData; + while (childParentData.previousSibling != null) { + assert(childParentData.previousSibling != child); + child = childParentData.previousSibling; + childParentData = child.parentData; } return child == equals; } bool _debugUltimateNextSiblingOf(ChildType child, { ChildType equals }) { - assert(child.parentData is ParentDataType); - while (child.parentData.nextSibling != null) { - assert(child.parentData.nextSibling != child); - child = child.parentData.nextSibling; - assert(child.parentData is ParentDataType); + ParentDataType childParentData = child.parentData; + while (childParentData.nextSibling != null) { + assert(childParentData.nextSibling != child); + child = childParentData.nextSibling; + childParentData = child.parentData; } return child == equals; } @@ -1238,17 +1240,17 @@ abstract class ContainerRenderObjectMixin 0); if (before == null) { // append at the end (_lastChild) - child.parentData.previousSibling = _lastChild; + childParentData.previousSibling = _lastChild; if (_lastChild != null) { - assert(_lastChild.parentData is ParentDataType); - _lastChild.parentData.nextSibling = child; + final ParentDataType _lastChildParentData = _lastChild.parentData; + _lastChildParentData.nextSibling = child; } _lastChild = child; if (_firstChild == null) @@ -1258,24 +1260,24 @@ abstract class ContainerRenderObjectMixin= 0); - if (child.parentData.previousSibling == null) { + if (childParentData.previousSibling == null) { assert(_firstChild == child); - _firstChild = child.parentData.nextSibling; + _firstChild = childParentData.nextSibling; } else { - assert(child.parentData.previousSibling.parentData is ParentDataType); - child.parentData.previousSibling.parentData.nextSibling = child.parentData.nextSibling; + final ParentDataType childPreviousSiblingParentData = childParentData.previousSibling.parentData; + childPreviousSiblingParentData.nextSibling = childParentData.nextSibling; } - if (child.parentData.nextSibling == null) { + if (childParentData.nextSibling == null) { assert(_lastChild == child); - _lastChild = child.parentData.previousSibling; + _lastChild = childParentData.previousSibling; } else { - assert(child.parentData.nextSibling.parentData is ParentDataType); - child.parentData.nextSibling.parentData.previousSibling = child.parentData.previousSibling; + final ParentDataType childNextSiblingParentData = childParentData.nextSibling.parentData; + childNextSiblingParentData.previousSibling = childParentData.previousSibling; } - child.parentData.previousSibling = null; - child.parentData.nextSibling = null; + childParentData.previousSibling = null; + childParentData.nextSibling = null; _childCount -= 1; } @@ -1337,10 +1339,10 @@ abstract class ContainerRenderObjectMixin '${super.debugDescribeSettings(prefix)}${prefix}additionalConstraints: ${additionalConstraints}\n'; + String debugDescribeSettings(String prefix) => '${super.debugDescribeSettings(prefix)}${prefix}additionalConstraints: $additionalConstraints\n'; } /// A render object that, for both width and height, imposes a tight constraint @@ -376,7 +376,7 @@ class RenderAspectRatio extends RenderProxyBox { RenderAspectRatio({ RenderBox child, double aspectRatio - }) : super(child), _aspectRatio = aspectRatio { + }) : _aspectRatio = aspectRatio, super(child) { assert(_aspectRatio != null); } @@ -419,7 +419,7 @@ class RenderAspectRatio extends RenderProxyBox { child.layout(new BoxConstraints.tight(size)); } - String debugDescribeSettings(String prefix) => '${super.debugDescribeSettings(prefix)}${prefix}aspectRatio: ${aspectRatio}\n'; + String debugDescribeSettings(String prefix) => '${super.debugDescribeSettings(prefix)}${prefix}aspectRatio: $aspectRatio\n'; } /// Sizes its child to the child's intrinsic width @@ -514,7 +514,7 @@ class RenderIntrinsicWidth extends RenderProxyBox { } } - String debugDescribeSettings(String prefix) => '${super.debugDescribeSettings(prefix)}${prefix}stepWidth: ${stepWidth}\n${prefix}stepHeight: ${stepHeight}\n'; + String debugDescribeSettings(String prefix) => '${super.debugDescribeSettings(prefix)}${prefix}stepWidth: $stepWidth\n${prefix}stepHeight: $stepHeight\n'; } @@ -628,8 +628,7 @@ class RenderOpacity extends RenderProxyBox { /// child into an intermediate buffer. class RenderColorFilter extends RenderProxyBox { RenderColorFilter({ RenderBox child, Color color, ui.TransferMode transferMode }) - : _color = color, _transferMode = transferMode, super(child) { - } + : _color = color, _transferMode = transferMode, super(child); /// The color to use as input to the color filter Color get color => _color; @@ -661,8 +660,7 @@ class RenderColorFilter extends RenderProxyBox { class RenderShaderMask extends RenderProxyBox { RenderShaderMask({ RenderBox child, ShaderCallback shaderCallback, ui.TransferMode transferMode }) - : _shaderCallback = shaderCallback, _transferMode = transferMode, super(child) { - } + : _shaderCallback = shaderCallback, _transferMode = transferMode, super(child); ShaderCallback get shaderCallback => _shaderCallback; ShaderCallback _shaderCallback; @@ -969,9 +967,9 @@ class RenderTransform extends RenderProxyBox { } String debugDescribeSettings(String prefix) { - List result = _transform.toString().split('\n').map((s) => '$prefix $s\n').toList(); + List result = _transform.toString().split('\n').map((String s) => '$prefix $s\n').toList(); result.removeLast(); - return '${super.debugDescribeSettings(prefix)}${prefix}transform matrix:\n${result.join()}\n${prefix}origin: ${origin}\n'; + return '${super.debugDescribeSettings(prefix)}${prefix}transform matrix:\n${result.join()}\n${prefix}origin: $origin\n'; } } diff --git a/packages/flutter/lib/src/rendering/shifted_box.dart b/packages/flutter/lib/src/rendering/shifted_box.dart index 6cab77827b..89eacfb5ce 100644 --- a/packages/flutter/lib/src/rendering/shifted_box.dart +++ b/packages/flutter/lib/src/rendering/shifted_box.dart @@ -44,9 +44,9 @@ abstract class RenderShiftedBox extends RenderBox with RenderObjectWithChildMixi if (child != null) { assert(!needsLayout); result = child.getDistanceToActualBaseline(baseline); - assert(child.parentData is BoxParentData); + final BoxParentData childParentData = child.parentData; if (result != null) - result += child.parentData.position.y; + result += childParentData.position.y; } else { result = super.computeDistanceToActualBaseline(baseline); } @@ -54,15 +54,17 @@ abstract class RenderShiftedBox extends RenderBox with RenderObjectWithChildMixi } void paint(PaintingContext context, Offset offset) { - if (child != null) - context.paintChild(child, child.parentData.position + offset); + if (child != null) { + final BoxParentData childParentData = child.parentData; + context.paintChild(child, childParentData.position + offset); + } } void hitTestChildren(HitTestResult result, { Point position }) { if (child != null) { - assert(child.parentData is BoxParentData); - child.hitTest(result, position: new Point(position.x - child.parentData.position.x, - position.y - child.parentData.position.y)); + final BoxParentData childParentData = child.parentData; + child.hitTest(result, position: new Point(position.x - childParentData.position.x, + position.y - childParentData.position.y)); } } @@ -125,15 +127,15 @@ class RenderPadding extends RenderShiftedBox { } BoxConstraints innerConstraints = constraints.deflate(padding); child.layout(innerConstraints, parentUsesSize: true); - assert(child.parentData is BoxParentData); - child.parentData.position = new Point(padding.left, padding.top); + final BoxParentData childParentData = child.parentData; + childParentData.position = new Point(padding.left, padding.top); size = constraints.constrain(new Size( padding.left + child.size.width + padding.right, padding.top + child.size.height + padding.bottom )); } - String debugDescribeSettings(String prefix) => '${super.debugDescribeSettings(prefix)}${prefix}padding: ${padding}\n'; + String debugDescribeSettings(String prefix) => '${super.debugDescribeSettings(prefix)}${prefix}padding: $padding\n'; } enum ShrinkWrap { @@ -204,16 +206,16 @@ class RenderPositionedBox extends RenderShiftedBox { child.layout(constraints.loosen(), parentUsesSize: true); size = constraints.constrain(new Size(_shinkWrapWidth ? child.size.width : double.INFINITY, _shinkWrapHeight ? child.size.height : double.INFINITY)); - assert(child.parentData is BoxParentData); Offset delta = size - child.size; - child.parentData.position = (delta.scale(horizontal, vertical)).toPoint(); + final BoxParentData childParentData = child.parentData; + childParentData.position = (delta.scale(horizontal, vertical)).toPoint(); } else { size = constraints.constrain(new Size(_shinkWrapWidth ? 0.0 : double.INFINITY, _shinkWrapHeight ? 0.0 : double.INFINITY)); } } - String debugDescribeSettings(String prefix) => '${super.debugDescribeSettings(prefix)}${prefix}horizontal: ${horizontal}\n${prefix}vertical: ${vertical}\n'; + String debugDescribeSettings(String prefix) => '${super.debugDescribeSettings(prefix)}${prefix}horizontal: $horizontal\n${prefix}vertical: $vertical\n'; } class RenderBaseline extends RenderShiftedBox { @@ -253,13 +255,13 @@ class RenderBaseline extends RenderShiftedBox { if (child != null) { child.layout(constraints.loosen(), parentUsesSize: true); size = constraints.constrain(child.size); - assert(child.parentData is BoxParentData); double delta = baseline - child.getDistanceToBaseline(baselineType); - child.parentData.position = new Point(0.0, delta); + final BoxParentData childParentData = child.parentData; + childParentData.position = new Point(0.0, delta); } else { performResize(); } } - String debugDescribeSettings(String prefix) => '${super.debugDescribeSettings(prefix)}${prefix}baseline: ${baseline}\nbaselineType: ${baselineType}'; + String debugDescribeSettings(String prefix) => '${super.debugDescribeSettings(prefix)}${prefix}baseline: $baseline\nbaselineType: $baselineType'; } diff --git a/packages/flutter/lib/src/rendering/stack.dart b/packages/flutter/lib/src/rendering/stack.dart index 7d075f88b9..2382411e69 100644 --- a/packages/flutter/lib/src/rendering/stack.dart +++ b/packages/flutter/lib/src/rendering/stack.dart @@ -8,7 +8,7 @@ import 'box.dart'; import 'object.dart'; /// Parent data for use with [RenderStack] -class StackParentData extends BoxParentData with ContainerParentDataMixin { +class StackParentData extends ContainerBoxParentDataMixin { /// The offset of the child's top edge from the top of the stack double top; @@ -84,10 +84,11 @@ abstract class RenderStackBase extends RenderBox double width = constraints.minWidth; RenderBox child = firstChild; while (child != null) { - assert(child.parentData is StackParentData); - if (!child.parentData.isPositioned) + final StackParentData childParentData = child.parentData; + if (!childParentData.isPositioned) width = math.max(width, child.getMinIntrinsicWidth(constraints)); - child = child.parentData.nextSibling; + assert(child.parentData == childParentData); + child = childParentData.nextSibling; } assert(width == constraints.constrainWidth(width)); return width; @@ -98,12 +99,13 @@ abstract class RenderStackBase extends RenderBox double width = constraints.minWidth; RenderBox child = firstChild; while (child != null) { - assert(child.parentData is StackParentData); - if (!child.parentData.isPositioned) { + final StackParentData childParentData = child.parentData; + if (!childParentData.isPositioned) { hasNonPositionedChildren = true; width = math.max(width, child.getMaxIntrinsicWidth(constraints)); } - child = child.parentData.nextSibling; + assert(child.parentData == childParentData); + child = childParentData.nextSibling; } if (!hasNonPositionedChildren) return constraints.constrainWidth(); @@ -115,10 +117,11 @@ abstract class RenderStackBase extends RenderBox double height = constraints.minHeight; RenderBox child = firstChild; while (child != null) { - assert(child.parentData is StackParentData); - if (!child.parentData.isPositioned) + final StackParentData childParentData = child.parentData; + if (!childParentData.isPositioned) height = math.max(height, child.getMinIntrinsicHeight(constraints)); - child = child.parentData.nextSibling; + assert(child.parentData == childParentData); + child = childParentData.nextSibling; } assert(height == constraints.constrainHeight(height)); return height; @@ -129,12 +132,13 @@ abstract class RenderStackBase extends RenderBox double height = constraints.minHeight; RenderBox child = firstChild; while (child != null) { - assert(child.parentData is StackParentData); - if (!child.parentData.isPositioned) { + final StackParentData childParentData = child.parentData; + if (!childParentData.isPositioned) { hasNonPositionedChildren = true; height = math.max(height, child.getMaxIntrinsicHeight(constraints)); } - child = child.parentData.nextSibling; + assert(child.parentData == childParentData); + child = childParentData.nextSibling; } if (!hasNonPositionedChildren) return constraints.constrainHeight(); @@ -155,21 +159,20 @@ abstract class RenderStackBase extends RenderBox RenderBox child = firstChild; while (child != null) { - assert(child.parentData is StackParentData); - final StackParentData parentData = child.parentData; + final StackParentData childParentData = child.parentData; - if (!parentData.isPositioned) { + if (!childParentData.isPositioned) { hasNonPositionedChildren = true; child.layout(constraints, parentUsesSize: true); - parentData.position = Point.origin; + childParentData.position = Point.origin; final Size childSize = child.size; width = math.max(width, childSize.width); height = math.max(height, childSize.height); } - child = parentData.nextSibling; + child = childParentData.nextSibling; } if (hasNonPositionedChildren) { @@ -184,46 +187,46 @@ abstract class RenderStackBase extends RenderBox child = firstChild; while (child != null) { - assert(child.parentData is StackParentData); - final StackParentData childData = child.parentData; + final StackParentData childParentData = child.parentData; - if (!childData.isPositioned) { + if (!childParentData.isPositioned) { double x = (size.width - child.size.width) * horizontalAlignment; double y = (size.height - child.size.height) * verticalAlignment; - childData.position = new Point(x, y); + childParentData.position = new Point(x, y); } else { BoxConstraints childConstraints = const BoxConstraints(); - if (childData.left != null && childData.right != null) - childConstraints = childConstraints.tightenWidth(size.width - childData.right - childData.left); + if (childParentData.left != null && childParentData.right != null) + childConstraints = childConstraints.tightenWidth(size.width - childParentData.right - childParentData.left); - if (childData.top != null && childData.bottom != null) - childConstraints = childConstraints.tightenHeight(size.height - childData.bottom - childData.top); + if (childParentData.top != null && childParentData.bottom != null) + childConstraints = childConstraints.tightenHeight(size.height - childParentData.bottom - childParentData.top); child.layout(childConstraints, parentUsesSize: true); double x = 0.0; - if (childData.left != null) - x = childData.left; - else if (childData.right != null) - x = size.width - childData.right - child.size.width; + if (childParentData.left != null) + x = childParentData.left; + else if (childParentData.right != null) + x = size.width - childParentData.right - child.size.width; if (x < 0.0 || x + child.size.width > size.width) _hasVisualOverflow = true; double y = 0.0; - if (childData.top != null) - y = childData.top; - else if (childData.bottom != null) - y = size.height - childData.bottom - child.size.height; + if (childParentData.top != null) + y = childParentData.top; + else if (childParentData.bottom != null) + y = size.height - childParentData.bottom - child.size.height; if (y < 0.0 || y + child.size.height > size.height) _hasVisualOverflow = true; - childData.position = new Point(x, y); + childParentData.position = new Point(x, y); } - child = childData.nextSibling; + assert(child.parentData == childParentData); + child = childParentData.nextSibling; } } @@ -320,8 +323,8 @@ class RenderIndexedStack extends RenderStackBase { RenderBox child = firstChild; int i = 0; while (child != null && i < index) { - assert(child.parentData is StackParentData); - child = child.parentData.nextSibling; + final StackParentData childParentData = child.parentData; + child = childParentData.nextSibling; i += 1; } assert(i == index); @@ -334,8 +337,9 @@ class RenderIndexedStack extends RenderStackBase { return; assert(position != null); RenderBox child = _childAtIndex(); - Point transformed = new Point(position.x - child.parentData.position.x, - position.y - child.parentData.position.y); + final StackParentData childParentData = child.parentData; + Point transformed = new Point(position.x - childParentData.position.x, + position.y - childParentData.position.y); child.hitTest(result, position: transformed); } @@ -343,6 +347,7 @@ class RenderIndexedStack extends RenderStackBase { if (firstChild == null) return; RenderBox child = _childAtIndex(); - context.paintChild(child, child.parentData.position + offset); + final StackParentData childParentData = child.parentData; + context.paintChild(child, childParentData.position + offset); } } diff --git a/packages/flutter/lib/src/rendering/viewport.dart b/packages/flutter/lib/src/rendering/viewport.dart index eccce14a54..be961ea7fb 100644 --- a/packages/flutter/lib/src/rendering/viewport.dart +++ b/packages/flutter/lib/src/rendering/viewport.dart @@ -128,8 +128,8 @@ class RenderViewport extends RenderBox with RenderObjectWithChildMixin fetchUrl(String relativeUrl) async { UrlRequest request = new UrlRequest() ..url = url ..autoFollowRedirects = true; - return fetch(request); + return await fetch(request); } Future fetchBody(String relativeUrl) async { diff --git a/packages/flutter/lib/src/services/image_cache.dart b/packages/flutter/lib/src/services/image_cache.dart index f7076c82c8..8826477eab 100644 --- a/packages/flutter/lib/src/services/image_cache.dart +++ b/packages/flutter/lib/src/services/image_cache.dart @@ -3,7 +3,6 @@ // found in the LICENSE file. import 'dart:async'; -import 'dart:collection'; import 'dart:ui' as ui; import 'package:mojo/mojo/url_response.mojom.dart'; @@ -15,7 +14,7 @@ import 'image_resource.dart'; Future _fetchImage(String url) async { UrlResponse response = await fetchUrl(url); if (response.statusCode >= 400) { - print("Failed (${response.statusCode}) to load image ${url}"); + print("Failed (${response.statusCode}) to load image $url"); return null; } return await decodeImageFromDataPipe(response.body); @@ -24,7 +23,7 @@ Future _fetchImage(String url) async { class _ImageCache { _ImageCache._(); - final HashMap _cache = new Map(); + final Map _cache = new Map(); ImageResource load(String url) { return _cache.putIfAbsent(url, () { diff --git a/packages/flutter/lib/src/widgets/basic.dart b/packages/flutter/lib/src/widgets/basic.dart index 23f3576025..f4f3d1c4c0 100644 --- a/packages/flutter/lib/src/widgets/basic.dart +++ b/packages/flutter/lib/src/widgets/basic.dart @@ -770,7 +770,7 @@ class DefaultTextStyle extends InheritedWidget { } class Text extends StatelessComponent { - Text(this.data, { Key key, TextStyle this.style }) : super(key: key) { + Text(this.data, { Key key, this.style }) : super(key: key) { assert(data != null); } @@ -790,7 +790,7 @@ class Text extends StatelessComponent { combinedStyle = style; } if (combinedStyle != null) - text = new StyledTextSpan(combinedStyle, [text]); + text = new StyledTextSpan(combinedStyle, [text]); return new Paragraph(text: text); } diff --git a/packages/flutter/lib/src/widgets/editable_text.dart b/packages/flutter/lib/src/widgets/editable_text.dart index c2dc68b9f3..8698c69d12 100644 --- a/packages/flutter/lib/src/widgets/editable_text.dart +++ b/packages/flutter/lib/src/widgets/editable_text.dart @@ -11,22 +11,22 @@ import 'package:flutter/rendering.dart'; import 'basic.dart'; import 'framework.dart'; -const _kCursorBlinkPeriod = 500; // milliseconds +const _kCursorBlinkHalfPeriod = 500; // milliseconds typedef void StringUpdated(); class TextRange { + const TextRange({ this.start, this.end }); + const TextRange.collapsed(int position) + : start = position, + end = position; + const TextRange.empty() + : start = -1, + end = -1; + final int start; final int end; - TextRange({this.start, this.end}); - TextRange.collapsed(int position) - : start = position, - end = position; - const TextRange.empty() - : start = -1, - end = -1; - bool get isValid => start >= 0 && end >= 0; bool get isCollapsed => start == end; } @@ -155,12 +155,14 @@ class EditableTextState extends State { Timer _cursorTimer; bool _showCursor = false; - /// Whether the blinking cursor is visible (exposed for testing). - bool get test_showCursor => _showCursor; + /// Whether the blinking cursor is actually visible at this precise moment + /// (it's hidden half the time, since it blinks). + bool get cursorCurrentlyVisible => _showCursor; - /// The cursor blink interval (exposed for testing). - Duration get test_cursorBlinkPeriod => - new Duration(milliseconds: _kCursorBlinkPeriod); + /// The cursor blink interval (the amount of time the cursor is in the "on" + /// state or the "off" state). A complete cursor blink period is twice this + /// value (half on, half off). + Duration get cursorBlinkInterval => new Duration(milliseconds: _kCursorBlinkHalfPeriod); void _cursorTick(Timer timer) { setState(() { @@ -171,7 +173,9 @@ class EditableTextState extends State { void _startCursorTimer() { _showCursor = true; _cursorTimer = new Timer.periodic( - new Duration(milliseconds: _kCursorBlinkPeriod), _cursorTick); + new Duration(milliseconds: _kCursorBlinkHalfPeriod), + _cursorTick + ); } void dispose() { @@ -254,16 +258,16 @@ class _EditableTextWidget extends LeafRenderObjectWidget { const TextStyle(decoration: underline) ); - return new StyledTextSpan(style, [ + return new StyledTextSpan(style, [ new PlainTextSpan(value.textBefore(value.composing)), - new StyledTextSpan(composingStyle, [ + new StyledTextSpan(composingStyle, [ new PlainTextSpan(value.textInside(value.composing)) ]), new PlainTextSpan(value.textAfter(value.composing)) ]); } - return new StyledTextSpan(style, [ + return new StyledTextSpan(style, [ new PlainTextSpan(value.text) ]); } diff --git a/packages/flutter/lib/src/widgets/framework.dart b/packages/flutter/lib/src/widgets/framework.dart index 6df59d33c6..5ff36a3ab8 100644 --- a/packages/flutter/lib/src/widgets/framework.dart +++ b/packages/flutter/lib/src/widgets/framework.dart @@ -30,9 +30,14 @@ abstract class Key { class ValueKey extends Key { const ValueKey(this.value) : super.constructor(); final T value; - String toString() => '[\'${value}\']'; - bool operator==(other) => other is ValueKey && other.value == value; + bool operator ==(dynamic other) { + if (other is! ValueKey) + return false; + final ValueKey typedOther = other; + return value == typedOther.value; + } int get hashCode => value.hashCode; + String toString() => '[\'$value\']'; } /// A kind of [Key] that takes its identity from the object used as its value. @@ -42,9 +47,14 @@ class ValueKey extends Key { class ObjectKey extends Key { const ObjectKey(this.value) : super.constructor(); final Object value; - String toString() => '[${value.runtimeType}(${value.hashCode})]'; - bool operator==(other) => other is ObjectKey && identical(other.value, value); + bool operator ==(dynamic other) { + if (other is! ObjectKey) + return false; + final ObjectKey typedOther = other; + return identical(value, typedOther.value); + } int get hashCode => identityHashCode(value); + String toString() => '[${value.runtimeType}(${value.hashCode})]'; } typedef void GlobalKeyRemoveListener(GlobalKey key); @@ -57,7 +67,7 @@ abstract class GlobalKey extends Key { /// Constructs a LabeledGlobalKey, which is a GlobalKey with a label used for debugging. /// The label is not used for comparing the identity of the key. - factory GlobalKey({ String label }) => new LabeledGlobalKey(label); // the label is purely for debugging purposes and is otherwise ignored + factory GlobalKey({ String label }) => new LabeledGlobalKey(label); // the label is purely for debugging purposes and is otherwise ignored static final Map _registry = new Map(); static final Map _debugDuplicates = new Map(); @@ -154,7 +164,7 @@ abstract class GlobalKey extends Key { /// Each LabeledGlobalKey instance is a unique key. /// The optional label can be used for documentary purposes. It does not affect /// the key's identity. -class LabeledGlobalKey extends GlobalKey { +class LabeledGlobalKey extends GlobalKey { const LabeledGlobalKey(this._label) : super.constructor(); final String _label; String toString() => '[GlobalKey ${_label != null ? _label : hashCode}]'; @@ -167,9 +177,14 @@ class LabeledGlobalKey extends GlobalKey { class GlobalObjectKey extends GlobalKey { const GlobalObjectKey(this.value) : super.constructor(); final Object value; - String toString() => '[GlobalKey ${value.runtimeType}(${value.hashCode})]'; - bool operator==(other) => other is GlobalObjectKey && identical(other.value, value); + bool operator ==(dynamic other) { + if (other is! GlobalObjectKey) + return false; + final GlobalObjectKey typedOther = other; + return identical(value, typedOther.value); + } int get hashCode => identityHashCode(value); + String toString() => '[GlobalKey ${value.runtimeType}(${value.hashCode})]'; } @@ -233,7 +248,7 @@ abstract class LeafRenderObjectWidget extends RenderObjectWidget { /// that have a single child slot. (This superclass only provides the storage /// for that child, it doesn't actually provide the updating logic.) abstract class OneChildRenderObjectWidget extends RenderObjectWidget { - const OneChildRenderObjectWidget({ Key key, Widget this.child }) : super(key: key); + const OneChildRenderObjectWidget({ Key key, this.child }) : super(key: key); final Widget child; @@ -245,7 +260,7 @@ abstract class OneChildRenderObjectWidget extends RenderObjectWidget { /// storage for that child list, it doesn't actually provide the updating /// logic.) abstract class MultiChildRenderObjectWidget extends RenderObjectWidget { - const MultiChildRenderObjectWidget({ Key key, List this.children }) + const MultiChildRenderObjectWidget({ Key key, this.children }) : super(key: key); final List children; @@ -812,7 +827,7 @@ abstract class Element implements BuildContext { } String toStringDeep([String prefixLineOne = '', String prefixOtherLines = '']) { - String result = '${prefixLineOne}$this\n'; + String result = '$prefixLineOne$this\n'; List children = []; visitChildren((Element child) { children.add(child); @@ -1007,7 +1022,7 @@ abstract class ComponentElement extends BuildableElement { built = _builder(this); assert(built != null); } catch (e, stack) { - _debugReportException('building ${_widget}', e, stack); + _debugReportException('building $_widget', e, stack); built = new ErrorWidget(); } finally { // We delay marking the element as clean until after calling _builder so @@ -1019,7 +1034,7 @@ abstract class ComponentElement extends BuildableElement { _child = updateChild(_child, built, slot); assert(_child != null); } catch (e, stack) { - _debugReportException('building ${_widget}', e, stack); + _debugReportException('building $_widget', e, stack); built = new ErrorWidget(); _child = updateChild(null, built, slot); } @@ -1251,7 +1266,7 @@ abstract class RenderObjectElement extends Buildab // dirty, e.g. if they have a builder callback. (Builder callbacks have a // 'BuildContext' argument which you can pass to Theme.of() and other // InheritedWidget APIs which eventually trigger a rebuild.) - print('${runtimeType} failed to implement reinvokeBuilders(), but got marked dirty'); + print('$runtimeType failed to implement reinvokeBuilders(), but got marked dirty'); assert(() { 'reinvokeBuilders() not implemented'; return false; @@ -1297,9 +1312,6 @@ abstract class RenderObjectElement extends Buildab // 6. Sync null with any items in the list of keys that are still // mounted. - final ContainerRenderObjectMixin renderObject = this.renderObject; // TODO(ianh): Remove this once the analyzer is cleverer - assert(renderObject is ContainerRenderObjectMixin); - int childrenTop = 0; int newChildrenBottom = newWidgets.length - 1; int oldChildrenBottom = oldChildren.length - 1; @@ -1401,7 +1413,6 @@ abstract class RenderObjectElement extends Buildab _deactivateChild(oldChild); } - assert(renderObject == this.renderObject); // TODO(ianh): Remove this once the analyzer is cleverer return newChildren; } @@ -1500,11 +1511,10 @@ class OneChildRenderObjectElement extends } void insertChildRenderObject(RenderObject child, dynamic slot) { - final renderObject = this.renderObject; // TODO(ianh): Remove this once the analyzer is cleverer - assert(renderObject is RenderObjectWithChildMixin); + final RenderObjectWithChildMixin renderObject = this.renderObject; assert(slot == null); renderObject.child = child; - assert(renderObject == this.renderObject); // TODO(ianh): Remove this once the analyzer is cleverer + assert(renderObject == this.renderObject); } void moveChildRenderObject(RenderObject child, dynamic slot) { @@ -1512,11 +1522,10 @@ class OneChildRenderObjectElement extends } void removeChildRenderObject(RenderObject child) { - final renderObject = this.renderObject; // TODO(ianh): Remove this once the analyzer is cleverer - assert(renderObject is RenderObjectWithChildMixin); + final RenderObjectWithChildMixin renderObject = this.renderObject; assert(renderObject.child == child); renderObject.child = null; - assert(renderObject == this.renderObject); // TODO(ianh): Remove this once the analyzer is cleverer + assert(renderObject == this.renderObject); } } @@ -1529,27 +1538,24 @@ class MultiChildRenderObjectElement exte List _children; void insertChildRenderObject(RenderObject child, Element slot) { - final renderObject = this.renderObject; // TODO(ianh): Remove this once the analyzer is cleverer - RenderObject nextSibling = slot?.renderObject; - assert(renderObject is ContainerRenderObjectMixin); + final ContainerRenderObjectMixin renderObject = this.renderObject; + final RenderObject nextSibling = slot?.renderObject; renderObject.add(child, before: nextSibling); - assert(renderObject == this.renderObject); // TODO(ianh): Remove this once the analyzer is cleverer + assert(renderObject == this.renderObject); } void moveChildRenderObject(RenderObject child, dynamic slot) { - final renderObject = this.renderObject; // TODO(ianh): Remove this once the analyzer is cleverer - RenderObject nextSibling = slot?.renderObject; - assert(renderObject is ContainerRenderObjectMixin); + final ContainerRenderObjectMixin renderObject = this.renderObject; + final RenderObject nextSibling = slot?.renderObject; renderObject.move(child, before: nextSibling); - assert(renderObject == this.renderObject); // TODO(ianh): Remove this once the analyzer is cleverer + assert(renderObject == this.renderObject); } void removeChildRenderObject(RenderObject child) { - final renderObject = this.renderObject; // TODO(ianh): Remove this once the analyzer is cleverer - assert(renderObject is ContainerRenderObjectMixin); + final ContainerRenderObjectMixin renderObject = this.renderObject; assert(child.parent == renderObject); renderObject.remove(child); - assert(renderObject == this.renderObject); // TODO(ianh): Remove this once the analyzer is cleverer + assert(renderObject == this.renderObject); } bool _debugHasDuplicateIds() { diff --git a/packages/flutter/lib/src/widgets/mixed_viewport.dart b/packages/flutter/lib/src/widgets/mixed_viewport.dart index 83a2bf6c3b..2965054988 100644 --- a/packages/flutter/lib/src/widgets/mixed_viewport.dart +++ b/packages/flutter/lib/src/widgets/mixed_viewport.dart @@ -56,7 +56,13 @@ class _ChildKey { factory _ChildKey.fromWidget(Widget widget) => new _ChildKey(widget.runtimeType, widget.key); final Type type; final Key key; - bool operator ==(other) => other is _ChildKey && other.type == type && other.key == key; + bool operator ==(dynamic other) { + if (other is! _ChildKey) + return false; + final _ChildKey typedOther = other; + return type == typedOther.type && + key == typedOther.key; + } int get hashCode => 373 * 37 * type.hashCode + key.hashCode; String toString() => "_ChildKey(type: $type, key: $key)"; } @@ -327,7 +333,7 @@ class _MixedViewportElement extends RenderObjectElement { double newExtent = _getElementExtent(element, innerConstraints); bool result = _childExtents[index] == newExtent; if (!result) - print("Element $element at index $index was size ${_childExtents[index]} but is now size ${newExtent} yet no invalidate() was received to that effect"); + print("Element $element at index $index was size ${_childExtents[index]} but is now size $newExtent yet no invalidate() was received to that effect"); return result; } diff --git a/packages/flutter/lib/src/widgets/scrollable.dart b/packages/flutter/lib/src/widgets/scrollable.dart index 310dd57a40..35ca49d92f 100644 --- a/packages/flutter/lib/src/widgets/scrollable.dart +++ b/packages/flutter/lib/src/widgets/scrollable.dart @@ -511,7 +511,7 @@ abstract class ScrollableWidgetListState extends List _buildItems(BuildContext context, int start, int count) { List result = buildItems(context, start, count); - assert(result.every((item) => item.key != null)); + assert(result.every((Widget item) => item.key != null)); return result; } @@ -603,7 +603,7 @@ class PageableList extends ScrollableList { final Curve curve; final PageChangedCallback onPageChanged; - PageableListState createState() => new PageableListState(); + PageableListState createState() => new PageableListState(); } class PageableListState extends ScrollableListState> { diff --git a/packages/flutter/lib/src/widgets/statistics_overlay.dart b/packages/flutter/lib/src/widgets/statistics_overlay.dart index 6784fa9c6b..090dbb4cc6 100644 --- a/packages/flutter/lib/src/widgets/statistics_overlay.dart +++ b/packages/flutter/lib/src/widgets/statistics_overlay.dart @@ -44,12 +44,14 @@ class StatisticsOverlay extends LeafRenderObjectWidget { StatisticsOverlay({ this.optionsMask, this.rasterizerThreshold: 0, Key key }) : super(key: key); /// Create a statistics overaly that displays all available statistics - StatisticsOverlay.allEnabled({ Key key, this.rasterizerThreshold: 0 }) : super(key: key), optionsMask = ( - 1 << StatisticsOption.displayRasterizerStatistics.index | - 1 << StatisticsOption.visualizeRasterizerStatistics.index | - 1 << StatisticsOption.displayEngineStatistics.index | - 1 << StatisticsOption.visualizeEngineStatistics.index - ); + StatisticsOverlay.allEnabled({ Key key, this.rasterizerThreshold: 0 }) + : optionsMask = ( + 1 << StatisticsOption.displayRasterizerStatistics.index | + 1 << StatisticsOption.visualizeRasterizerStatistics.index | + 1 << StatisticsOption.displayEngineStatistics.index | + 1 << StatisticsOption.visualizeEngineStatistics.index + ), + super(key: key); final int optionsMask; diff --git a/packages/unit/test/widget/input_test.dart b/packages/unit/test/widget/input_test.dart index 42a12123eb..8b1cef06be 100644 --- a/packages/unit/test/widget/input_test.dart +++ b/packages/unit/test/widget/input_test.dart @@ -77,11 +77,17 @@ void main() { // Check that the cursor visibility toggles after each blink interval. void checkCursorToggle() { - bool initialShowCursor = editableText.test_showCursor; - tester.async.elapse(editableText.test_cursorBlinkPeriod); - expect(editableText.test_showCursor, equals(!initialShowCursor)); - tester.async.elapse(editableText.test_cursorBlinkPeriod); - expect(editableText.test_showCursor, equals(initialShowCursor)); + bool initialShowCursor = editableText.cursorCurrentlyVisible; + tester.async.elapse(editableText.cursorBlinkInterval); + expect(editableText.cursorCurrentlyVisible, equals(!initialShowCursor)); + tester.async.elapse(editableText.cursorBlinkInterval); + expect(editableText.cursorCurrentlyVisible, equals(initialShowCursor)); + tester.async.elapse(editableText.cursorBlinkInterval ~/ 10); + expect(editableText.cursorCurrentlyVisible, equals(initialShowCursor)); + tester.async.elapse(editableText.cursorBlinkInterval); + expect(editableText.cursorCurrentlyVisible, equals(!initialShowCursor)); + tester.async.elapse(editableText.cursorBlinkInterval); + expect(editableText.cursorCurrentlyVisible, equals(initialShowCursor)); } checkCursorToggle(); From 2d2b4a8a58437998f8a0159b5f3dbd3a2db02264 Mon Sep 17 00:00:00 2001 From: Viktor Lidholt Date: Mon, 12 Oct 2015 16:53:24 -0700 Subject: [PATCH 55/84] Save list of sprite physics joints --- packages/flutter_sprites/lib/physics_joint.dart | 2 ++ packages/flutter_sprites/lib/physics_node.dart | 2 ++ 2 files changed, 4 insertions(+) diff --git a/packages/flutter_sprites/lib/physics_joint.dart b/packages/flutter_sprites/lib/physics_joint.dart index 1a5020a65e..2c251a862e 100644 --- a/packages/flutter_sprites/lib/physics_joint.dart +++ b/packages/flutter_sprites/lib/physics_joint.dart @@ -25,6 +25,7 @@ abstract class PhysicsJoint { if (_joint == null) { _physicsNode = physicsNode; _joint = _createB2Joint(physicsNode); + _physicsNode._joints.add(this); } } @@ -32,6 +33,7 @@ abstract class PhysicsJoint { if (_joint != null && _active) { _physicsNode.b2World.destroyJoint(_joint); _joint = null; + _physicsNode._joints.remove(this); } _active = false; } diff --git a/packages/flutter_sprites/lib/physics_node.dart b/packages/flutter_sprites/lib/physics_node.dart index fb76b21781..fbaeb9c008 100644 --- a/packages/flutter_sprites/lib/physics_node.dart +++ b/packages/flutter_sprites/lib/physics_node.dart @@ -31,6 +31,8 @@ class PhysicsNode extends Node { _ContactHandler _contactHandler; + List _joints = []; + List _bodiesScheduledForDestruction = []; double b2WorldToNodeConversionFactor = 10.0; From 3784086322ca94fca45dbfb308ad0b6fe051712f Mon Sep 17 00:00:00 2001 From: Viktor Lidholt Date: Mon, 12 Oct 2015 16:54:58 -0700 Subject: [PATCH 56/84] Break sprite physics joints --- packages/flutter_sprites/lib/physics_node.dart | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/flutter_sprites/lib/physics_node.dart b/packages/flutter_sprites/lib/physics_node.dart index fbaeb9c008..5496662f9b 100644 --- a/packages/flutter_sprites/lib/physics_node.dart +++ b/packages/flutter_sprites/lib/physics_node.dart @@ -79,6 +79,11 @@ class PhysicsNode extends Node { body._node._setRotationFromPhysics(degrees(b2Body.getAngle())); } + // Break joints + for (PhysicsJoint joint in _joints) { + joint._checkBreakingForce(dt); + } + // Remove bodies that were marked for destruction during the simulation _removeBodiesScheduledForDestruction(); } From 6488a13315581748abb9996328d4fc47299a3a02 Mon Sep 17 00:00:00 2001 From: Viktor Lidholt Date: Mon, 12 Oct 2015 16:59:58 -0700 Subject: [PATCH 57/84] Adds breakingForce argument to joints constructors in sprite physics --- .../flutter_sprites/lib/physics_joint.dart | 25 ++++++++++++------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/packages/flutter_sprites/lib/physics_joint.dart b/packages/flutter_sprites/lib/physics_joint.dart index 2c251a862e..50d938b215 100644 --- a/packages/flutter_sprites/lib/physics_joint.dart +++ b/packages/flutter_sprites/lib/physics_joint.dart @@ -1,7 +1,7 @@ part of skysprites; abstract class PhysicsJoint { - PhysicsJoint(this.bodyA, this.bodyB) { + PhysicsJoint(this.bodyA, this.bodyB, this.breakingForce) { bodyA._joints.add(this); bodyB._joints.add(this); } @@ -67,8 +67,9 @@ class PhysicsJointRevolute extends PhysicsJoint { this.worldAnchor, { this.lowerAngle: 0.0, this.upperAngle: 0.0, - this.enableLimit: false - }) : super(bodyA, bodyB) { + this.enableLimit: false, + double breakingForce + }) : super(bodyA, bodyB, breakingForce) { _completeCreation(); } @@ -99,8 +100,10 @@ class PhysicsJointPrismatic extends PhysicsJoint { PhysicsJointPrismatic( PhysicsBody bodyA, PhysicsBody bodyB, - this.axis - ) : super(bodyA, bodyB) { + this.axis, { + double breakingForce + } + ) : super(bodyA, bodyB, breakingForce) { _completeCreation(); } @@ -116,8 +119,10 @@ class PhysicsJointPrismatic extends PhysicsJoint { class PhysicsJointWeld extends PhysicsJoint { PhysicsJointWeld( PhysicsBody bodyA, - PhysicsBody bodyB - ) : super(bodyA, bodyB) { + PhysicsBody bodyB, { + double breakingForce + } + ) : super(bodyA, bodyB, breakingForce) { _completeCreation(); } @@ -140,8 +145,10 @@ class PhysicsJointPulley extends PhysicsJoint { this.groundAnchorB, this.anchorA, this.anchorB, - this.ratio - ) : super(bodyA, bodyB) { + this.ratio, { + double breakingForce + } + ) : super(bodyA, bodyB, breakingForce) { _completeCreation(); } From cb77bd44f66cdf906f5d8a821476ac70fecfb987 Mon Sep 17 00:00:00 2001 From: Hixie Date: Mon, 12 Oct 2015 17:07:27 -0700 Subject: [PATCH 58/84] Remove an infinity in layout code. --- packages/flutter/lib/src/rendering/statistics_box.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/flutter/lib/src/rendering/statistics_box.dart b/packages/flutter/lib/src/rendering/statistics_box.dart index dd7bbb0445..54f78e8f79 100644 --- a/packages/flutter/lib/src/rendering/statistics_box.dart +++ b/packages/flutter/lib/src/rendering/statistics_box.dart @@ -50,7 +50,7 @@ class StatisticsBox extends RenderBox { } void performResize() { - size = constraints.constrain(Size.infinite); + size = constraints.biggest; } void paint(PaintingContext context, Offset offset) { From 7c5092f7b1f404723c8cedff64616acf60dd703c Mon Sep 17 00:00:00 2001 From: Viktor Lidholt Date: Tue, 13 Oct 2015 09:39:53 -0700 Subject: [PATCH 59/84] Adds support for dampening on weld physics joints in sprites --- packages/flutter_sprites/lib/physics_joint.dart | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/packages/flutter_sprites/lib/physics_joint.dart b/packages/flutter_sprites/lib/physics_joint.dart index 50d938b215..8b10a4e258 100644 --- a/packages/flutter_sprites/lib/physics_joint.dart +++ b/packages/flutter_sprites/lib/physics_joint.dart @@ -64,7 +64,7 @@ class PhysicsJointRevolute extends PhysicsJoint { PhysicsJointRevolute( PhysicsBody bodyA, PhysicsBody bodyB, - this.worldAnchor, { + this._worldAnchor, { this.lowerAngle: 0.0, this.upperAngle: 0.0, this.enableLimit: false, @@ -73,7 +73,7 @@ class PhysicsJointRevolute extends PhysicsJoint { _completeCreation(); } - final Point worldAnchor; + final Point _worldAnchor; final double lowerAngle; final double upperAngle; final bool enableLimit; @@ -81,8 +81,8 @@ class PhysicsJointRevolute extends PhysicsJoint { box2d.Joint _createB2Joint(PhysicsNode physicsNode) { // Create Joint Definition Vector2 vecAnchor = new Vector2( - worldAnchor.x / physicsNode.b2WorldToNodeConversionFactor, - worldAnchor.y / physicsNode.b2WorldToNodeConversionFactor + _worldAnchor.x / physicsNode.b2WorldToNodeConversionFactor, + _worldAnchor.y / physicsNode.b2WorldToNodeConversionFactor ); box2d.RevoluteJointDef b2Def = new box2d.RevoluteJointDef(); @@ -120,12 +120,17 @@ class PhysicsJointWeld extends PhysicsJoint { PhysicsJointWeld( PhysicsBody bodyA, PhysicsBody bodyB, { - double breakingForce + double breakingForce, + this.dampening: 0.0, + this.frequency: 0.0 } ) : super(bodyA, bodyB, breakingForce) { _completeCreation(); } + final double dampening; + final double frequency; + box2d.Joint _createB2Joint(PhysicsNode physicsNode) { box2d.WeldJointDef b2Def = new box2d.WeldJointDef(); Vector2 middle = new Vector2( @@ -133,6 +138,8 @@ class PhysicsJointWeld extends PhysicsJoint { (bodyA._body.position.y + bodyB._body.position.y) / 2.0 ); b2Def.initialize(bodyA._body, bodyB._body, middle); + b2Def.dampingRatio = dampening; + b2Def.frequencyHz = frequency; return physicsNode.b2World.createJoint(b2Def); } } From 2feb51d6bc4ebcd3fd4c63acdd113e1a64efbb79 Mon Sep 17 00:00:00 2001 From: Viktor Lidholt Date: Tue, 13 Oct 2015 13:18:30 -0700 Subject: [PATCH 60/84] Adds more joint types to sprite physics --- .../flutter_sprites/lib/physics_joint.dart | 166 +++++++++++++++++- 1 file changed, 163 insertions(+), 3 deletions(-) diff --git a/packages/flutter_sprites/lib/physics_joint.dart b/packages/flutter_sprites/lib/physics_joint.dart index 8b10a4e258..6c92a95546 100644 --- a/packages/flutter_sprites/lib/physics_joint.dart +++ b/packages/flutter_sprites/lib/physics_joint.dart @@ -1,13 +1,19 @@ part of skysprites; abstract class PhysicsJoint { - PhysicsJoint(this.bodyA, this.bodyB, this.breakingForce) { + PhysicsJoint(this._bodyA, this._bodyB, this.breakingForce) { bodyA._joints.add(this); bodyB._joints.add(this); } - final PhysicsBody bodyA; - final PhysicsBody bodyB; + PhysicsBody _bodyA; + + PhysicsBody get bodyA => _bodyA; + + PhysicsBody _bodyB; + + PhysicsBody get bodyB => _bodyB; + final double breakingForce; bool _active = true; @@ -180,6 +186,160 @@ class PhysicsJointPulley extends PhysicsJoint { } } +class PhysicsJointGear extends PhysicsJoint { + PhysicsJointGear( + PhysicsBody bodyA, + PhysicsBody bodyB, { + double breakingForce, + this.ratio: 0.0 + } + ) : super(bodyA, bodyB, breakingForce) { + _completeCreation(); + } + + final double ratio; + + box2d.Joint _createB2Joint(PhysicsNode physicsNode) { + box2d.GearJointDef b2Def = new box2d.GearJointDef(); + b2Def.bodyA = bodyA._body; + b2Def.bodyB = bodyB._body; + b2Def.ratio = ratio; + + return physicsNode.b2World.createJoint(b2Def); + } +} + +class PhysicsJointDistance extends PhysicsJoint { + PhysicsJointDistance( + PhysicsBody bodyA, + PhysicsBody bodyB, + this.anchorA, + this.anchorB, { + double breakingForce, + this.length, + this.dampening: 0.0, + this.frequency: 0.0 + } + ) : super(bodyA, bodyB, breakingForce) { + _completeCreation(); + } + + final Point anchorA; + final Point anchorB; + final double length; + final double dampening; + final double frequency; + + box2d.Joint _createB2Joint(PhysicsNode physicsNode) { + box2d.DistanceJointDef b2Def = new box2d.DistanceJointDef(); + b2Def.initialize( + bodyA._body, + bodyB._body, + _convertPosToVec(anchorA, physicsNode), + _convertPosToVec(anchorB, physicsNode) + ); + b2Def.dampingRatio = dampening; + b2Def.frequencyHz = frequency; + if (length != null) + b2Def.length = length / physicsNode.b2WorldToNodeConversionFactor; + + return physicsNode.b2World.createJoint(b2Def); + } +} + +class PhysicsJointWheel extends PhysicsJoint { + PhysicsJointWheel( + PhysicsBody bodyA, + PhysicsBody bodyB, + this.anchor, + this.axis, { + double breakingForce, + this.dampening: 0.0, + this.frequency: 0.0 + } + ) : super(bodyA, bodyB, breakingForce) { + _completeCreation(); + } + + final Point anchor; + final Offset axis; + final double dampening; + final double frequency; + + box2d.Joint _createB2Joint(PhysicsNode physicsNode) { + box2d.WheelJointDef b2Def = new box2d.WheelJointDef(); + b2Def.initialize( + bodyA._body, + bodyB._body, + _convertPosToVec(anchor, physicsNode), + new Vector2(axis.dx, axis.dy) + ); + b2Def.dampingRatio = dampening; + b2Def.frequencyHz = frequency; + + return physicsNode.b2World.createJoint(b2Def); + } +} + +class PhysicsJointFriction extends PhysicsJoint { + PhysicsJointFriction( + PhysicsBody bodyA, + PhysicsBody bodyB, + this.anchor, { + double breakingForce, + this.maxForce: 0.0, + this.maxTorque: 0.0 + } + ) : super(bodyA, bodyB, breakingForce) { + _completeCreation(); + } + + final Point anchor; + final double maxForce; + final double maxTorque; + + box2d.Joint _createB2Joint(PhysicsNode physicsNode) { + box2d.FrictionJointDef b2Def = new box2d.FrictionJointDef(); + b2Def.initialize( + bodyA._body, + bodyB._body, + _convertPosToVec(anchor, physicsNode) + ); + b2Def.maxForce = maxForce / physicsNode.b2WorldToNodeConversionFactor; + b2Def.maxTorque = maxTorque / physicsNode.b2WorldToNodeConversionFactor; + return physicsNode.b2World.createJoint(b2Def); + } +} + +class PhysicsJointConstantVolume extends PhysicsJoint { + PhysicsJointConstantVolume( + this.bodies, { + double breakingForce, + this.dampening, + this.frequency + } + ) : super(null, null, breakingForce) { + assert(bodies.length > 2); + _bodyA = bodies[0]; + _bodyB = bodies[1]; + _completeCreation(); + } + + final List bodies; + final double dampening; + final double frequency; + + box2d.Joint _createB2Joint(PhysicsNode physicsNode) { + box2d.ConstantVolumeJointDef b2Def = new box2d.ConstantVolumeJointDef(); + for (PhysicsBody body in bodies) { + b2Def.addBody(body._body); + } + b2Def.dampingRatio = dampening; + b2Def.frequencyHz = frequency; + return physicsNode.b2World.createJoint(b2Def); + } +} + Vector2 _convertPosToVec(Point pt, PhysicsNode physicsNode) { return new Vector2( pt.x / physicsNode.b2WorldToNodeConversionFactor, From 998a066a827e94f3fa1da346796b11f3354e0f0d Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Tue, 13 Oct 2015 12:04:38 -0700 Subject: [PATCH 61/84] Add a centerSlice parameter to images This lets you draw nine-patch images. --- examples/widgets/nine_patch.dart | 14 +++ .../flutter/lib/src/painting/box_painter.dart | 119 ++++++++++++------ packages/flutter/lib/src/rendering/image.dart | 51 +++++--- packages/flutter/lib/src/widgets/basic.dart | 37 ++++-- packages/flutter_sprites/lib/label.dart | 2 +- 5 files changed, 153 insertions(+), 70 deletions(-) create mode 100644 examples/widgets/nine_patch.dart diff --git a/examples/widgets/nine_patch.dart b/examples/widgets/nine_patch.dart new file mode 100644 index 0000000000..f0faf2cd60 --- /dev/null +++ b/examples/widgets/nine_patch.dart @@ -0,0 +1,14 @@ +// 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:flutter/painting.dart'; +import 'package:flutter/material.dart'; + +void main() { + runApp(new NetworkImage( + src: "http://38.media.tumblr.com/avatar_497c78dc767d_128.png", + fit: ImageFit.contain, + centerSlice: new Rect.fromLTRB(40.0, 40.0, 88.0, 88.0) + )); +} diff --git a/packages/flutter/lib/src/painting/box_painter.dart b/packages/flutter/lib/src/painting/box_painter.dart index e018615599..117c71823b 100644 --- a/packages/flutter/lib/src/painting/box_painter.dart +++ b/packages/flutter/lib/src/painting/box_painter.dart @@ -10,43 +10,47 @@ import 'package:flutter/services.dart'; import 'shadows.dart'; -/// An immutable set of offsets in each of the four cardinal directions +/// An immutable set of offsets in each of the four cardinal directions. /// /// Typically used for an offset from each of the four sides of a box. For /// example, the padding inside a box can be represented using this class. class EdgeDims { - /// Constructs an EdgeDims from offsets from the top, right, bottom and left + /// Constructs an EdgeDims from offsets from the top, right, bottom and left. const EdgeDims.TRBL(this.top, this.right, this.bottom, this.left); - /// Constructs an EdgeDims where all the offsets are value + /// Constructs an EdgeDims where all the offsets are value. const EdgeDims.all(double value) : top = value, right = value, bottom = value, left = value; - /// Constructs an EdgeDims with only the given values non-zero + /// Constructs an EdgeDims with only the given values non-zero. const EdgeDims.only({ this.top: 0.0, this.right: 0.0, this.bottom: 0.0, this.left: 0.0 }); - /// Constructs an EdgeDims with symmetrical vertical and horizontal offsets + /// Constructs an EdgeDims with symmetrical vertical and horizontal offsets. const EdgeDims.symmetric({ double vertical: 0.0, double horizontal: 0.0 }) : top = vertical, left = horizontal, bottom = vertical, right = horizontal; - /// The offset from the top + /// The offset from the top. final double top; - /// The offset from the right + /// The offset from the right. final double right; - /// The offset from the bottom + /// The offset from the bottom. final double bottom; - /// The offset from the left + /// The offset from the left. final double left; + /// Whether every dimension is non-negative. bool get isNonNegative => top >= 0.0 && right >= 0.0 && bottom >= 0.0 && left >= 0.0; + /// The size that this edge dims would occupy with an empty interior. + Size get collapsedSize => new Size(left + right, top + bottom); + EdgeDims operator-(EdgeDims other) { return new EdgeDims.TRBL( top - other.top, @@ -101,7 +105,7 @@ class EdgeDims { ); } - /// Linearly interpolate between two EdgeDims + /// Linearly interpolate between two EdgeDims. /// /// If either is null, this function interpolates from [EdgeDims.zero]. static EdgeDims lerp(EdgeDims a, EdgeDims b, double t) { @@ -119,7 +123,7 @@ class EdgeDims { ); } - /// An EdgeDims with zero offsets in each direction + /// An EdgeDims with zero offsets in each direction. static const EdgeDims zero = const EdgeDims.TRBL(0.0, 0.0, 0.0, 0.0); bool operator ==(dynamic other) { @@ -416,88 +420,121 @@ void paintImage({ Rect rect, ui.Image image, ui.ColorFilter colorFilter, - fit: ImageFit.scaleDown, + ImageFit fit, repeat: ImageRepeat.noRepeat, + Rect centerSlice, double positionX: 0.5, double positionY: 0.5 }) { - Size bounds = rect.size; - Size imageSize = new Size(image.width.toDouble(), image.height.toDouble()); + Size outputSize = rect.size; + Size inputSize = new Size(image.width.toDouble(), image.height.toDouble()); + Offset sliceBorder; + if (centerSlice != null) { + sliceBorder = new Offset( + centerSlice.left + inputSize.width - centerSlice.right, + centerSlice.top + inputSize.height - centerSlice.bottom + ); + outputSize -= sliceBorder; + inputSize -= sliceBorder; + } Size sourceSize; Size destinationSize; - switch(fit) { + fit ??= centerSlice == null ? ImageFit.scaleDown : ImageFit.fill; + assert(centerSlice == null || (fit != ImageFit.none && fit != ImageFit.cover)); + switch (fit) { case ImageFit.fill: - sourceSize = imageSize; - destinationSize = bounds; + sourceSize = inputSize; + destinationSize = outputSize; break; case ImageFit.contain: - sourceSize = imageSize; - if (bounds.width / bounds.height > sourceSize.width / sourceSize.height) - destinationSize = new Size(sourceSize.width * bounds.height / sourceSize.height, bounds.height); + sourceSize = inputSize; + if (outputSize.width / outputSize.height > sourceSize.width / sourceSize.height) + destinationSize = new Size(sourceSize.width * outputSize.height / sourceSize.height, outputSize.height); else - destinationSize = new Size(bounds.width, sourceSize.height * bounds.width / sourceSize.width); + destinationSize = new Size(outputSize.width, sourceSize.height * outputSize.width / sourceSize.width); break; case ImageFit.cover: - if (bounds.width / bounds.height > imageSize.width / imageSize.height) - sourceSize = new Size(imageSize.width, imageSize.width * bounds.height / bounds.width); + if (outputSize.width / outputSize.height > inputSize.width / inputSize.height) + sourceSize = new Size(inputSize.width, inputSize.width * outputSize.height / outputSize.width); else - sourceSize = new Size(imageSize.height * bounds.width / bounds.height, imageSize.height); - destinationSize = bounds; + sourceSize = new Size(inputSize.height * outputSize.width / outputSize.height, inputSize.height); + destinationSize = outputSize; break; case ImageFit.none: - sourceSize = new Size(math.min(imageSize.width, bounds.width), - math.min(imageSize.height, bounds.height)); + sourceSize = new Size(math.min(inputSize.width, outputSize.width), + math.min(inputSize.height, outputSize.height)); destinationSize = sourceSize; break; case ImageFit.scaleDown: - sourceSize = imageSize; - destinationSize = bounds; + sourceSize = inputSize; + destinationSize = outputSize; if (sourceSize.height > destinationSize.height) destinationSize = new Size(sourceSize.width * destinationSize.height / sourceSize.height, sourceSize.height); if (sourceSize.width > destinationSize.width) destinationSize = new Size(destinationSize.width, sourceSize.height * destinationSize.width / sourceSize.width); break; } + if (centerSlice != null) { + outputSize += sliceBorder; + destinationSize += sliceBorder; + // We don't have the ability to draw a subset of the image at the same time + // as we apply a nine-patch stretch. + assert(sourceSize == inputSize); + } // TODO(abarth): Implement |repeat|. Paint paint = new Paint()..isAntiAlias = false; if (colorFilter != null) paint.colorFilter = colorFilter; - double dx = (bounds.width - destinationSize.width) * positionX; - double dy = (bounds.height - destinationSize.height) * positionY; + double dx = (outputSize.width - destinationSize.width) * positionX; + double dy = (outputSize.height - destinationSize.height) * positionY; Point destinationPosition = rect.topLeft + new Offset(dx, dy); - canvas.drawImageRect(image, Point.origin & sourceSize, destinationPosition & destinationSize, paint); + Rect destinationRect = destinationPosition & destinationSize; + if (centerSlice == null) + canvas.drawImageRect(image, Point.origin & sourceSize, destinationRect, paint); + else + canvas.drawImageNine(image, centerSlice, destinationRect, paint); } typedef void BackgroundImageChangeListener(); -/// A background image for a box +/// A background image for a box. class BackgroundImage { - /// How the background image should be inscribed into the box + /// How the background image should be inscribed into the box. final ImageFit fit; - /// How to paint any portions of the box not covered by the background image + /// How to paint any portions of the box not covered by the background image. final ImageRepeat repeat; - /// A color filter to apply to the background image before painting it + /// The center slice for a nine-patch image. + /// + /// The region of the image inside the center slice will be stretched both + /// horizontally and vertically to fit the image into its destination. The + /// region of the image above and below the center slice will be stretched + /// only horizontally and the region of the image to the left and right of + /// the center slice will be stretched only vertically. + final Rect centerSlice; + + /// A color filter to apply to the background image before painting it. final ui.ColorFilter colorFilter; BackgroundImage({ ImageResource image, - this.fit: ImageFit.scaleDown, + this.fit, this.repeat: ImageRepeat.noRepeat, + this.centerSlice, this.colorFilter }) : _imageResource = image; - ui.Image _image; - /// The image to be painted into the background + /// The image to be painted into the background. ui.Image get image => _image; + ui.Image _image; ImageResource _imageResource; final List _listeners = new List(); - /// Call listener when the background images changes (e.g., arrives from the network) + /// Call listener when the background images changes (e.g., arrives from the network). void addChangeListener(BackgroundImageChangeListener listener) { // We add the listener to the _imageResource first so that the first change // listener doesn't get callback synchronously if the image resource is @@ -507,7 +544,7 @@ class BackgroundImage { _listeners.add(listener); } - /// No longer call listener when the background image changes + /// No longer call listener when the background image changes. void removeChangeListener(BackgroundImageChangeListener listener) { _listeners.remove(listener); // We need to remove ourselves as listeners from the _imageResource so that diff --git a/packages/flutter/lib/src/rendering/image.dart b/packages/flutter/lib/src/rendering/image.dart index ce6800c807..3863cc0f22 100644 --- a/packages/flutter/lib/src/rendering/image.dart +++ b/packages/flutter/lib/src/rendering/image.dart @@ -9,7 +9,7 @@ import 'package:flutter/painting.dart'; import 'box.dart'; import 'object.dart'; -/// An image in the render tree +/// An image in the render tree. /// /// The render image attempts to find a size for itself that fits in the given /// constraints and preserves the image's intrinisc aspect ratio. @@ -19,18 +19,20 @@ class RenderImage extends RenderBox { double width, double height, ui.ColorFilter colorFilter, - fit: ImageFit.scaleDown, - repeat: ImageRepeat.noRepeat + ImageFit fit, + repeat: ImageRepeat.noRepeat, + Rect centerSlice }) : _image = image, _width = width, _height = height, _colorFilter = colorFilter, _fit = fit, - _repeat = repeat; + _repeat = repeat, + _centerSlice = centerSlice; - ui.Image _image; - /// The image to display + /// The image to display. ui.Image get image => _image; + ui.Image _image; void set image (ui.Image value) { if (value == _image) return; @@ -40,9 +42,9 @@ class RenderImage extends RenderBox { markNeedsLayout(); } - double _width; - /// If non-null, requires the image to have this width + /// If non-null, requires the image to have this width. double get width => _width; + double _width; void set width (double value) { if (value == _width) return; @@ -50,9 +52,9 @@ class RenderImage extends RenderBox { markNeedsLayout(); } - double _height; - /// If non-null, requires the image to have this height + /// If non-null, requires the image to have this height. double get height => _height; + double _height; void set height (double value) { if (value == _height) return; @@ -60,9 +62,9 @@ class RenderImage extends RenderBox { markNeedsLayout(); } - ui.ColorFilter _colorFilter; /// If non-null, apply this color filter to the image before painint. ui.ColorFilter get colorFilter => _colorFilter; + ui.ColorFilter _colorFilter; void set colorFilter (ui.ColorFilter value) { if (value == _colorFilter) return; @@ -70,9 +72,9 @@ class RenderImage extends RenderBox { markNeedsPaint(); } - ImageFit _fit; - /// How to inscribe the image into the place allocated during layout + /// How to inscribe the image into the place allocated during layout. ImageFit get fit => _fit; + ImageFit _fit; void set fit (ImageFit value) { if (value == _fit) return; @@ -80,9 +82,9 @@ class RenderImage extends RenderBox { markNeedsPaint(); } - ImageRepeat _repeat; - /// Not yet implemented + /// Not yet implemented. ImageRepeat get repeat => _repeat; + ImageRepeat _repeat; void set repeat (ImageRepeat value) { if (value == _repeat) return; @@ -90,7 +92,23 @@ class RenderImage extends RenderBox { markNeedsPaint(); } - /// Find a size for the render image within the given constraints + /// The center slice for a nine-patch image. + /// + /// The region of the image inside the center slice will be stretched both + /// horizontally and vertically to fit the image into its destination. The + /// region of the image above and below the center slice will be stretched + /// only horizontally and the region of the image to the left and right of + /// the center slice will be stretched only vertically. + Rect get centerSlice => _centerSlice; + Rect _centerSlice; + void set centerSlice (Rect value) { + if (value == _centerSlice) + return; + _centerSlice = value; + markNeedsPaint(); + } + + /// Find a size for the render image within the given constraints. /// /// - The dimensions of the RenderImage must fit within the constraints. /// - The aspect ratio of the RenderImage matches the instrinsic aspect @@ -170,6 +188,7 @@ class RenderImage extends RenderBox { image: _image, colorFilter: _colorFilter, fit: _fit, + centerSlice: _centerSlice, repeat: _repeat ); } diff --git a/packages/flutter/lib/src/widgets/basic.dart b/packages/flutter/lib/src/widgets/basic.dart index f4f3d1c4c0..202980efd0 100644 --- a/packages/flutter/lib/src/widgets/basic.dart +++ b/packages/flutter/lib/src/widgets/basic.dart @@ -809,8 +809,9 @@ class Image extends LeafRenderObjectWidget { this.width, this.height, this.colorFilter, - this.fit: ImageFit.scaleDown, - this.repeat: ImageRepeat.noRepeat + this.fit, + this.repeat: ImageRepeat.noRepeat, + this.centerSlice }) : super(key: key); final ui.Image image; @@ -819,6 +820,7 @@ class Image extends LeafRenderObjectWidget { final ui.ColorFilter colorFilter; final ImageFit fit; final ImageRepeat repeat; + final Rect centerSlice; RenderImage createRenderObject() => new RenderImage( image: image, @@ -826,7 +828,8 @@ class Image extends LeafRenderObjectWidget { height: height, colorFilter: colorFilter, fit: fit, - repeat: repeat); + repeat: repeat, + centerSlice: centerSlice); void updateRenderObject(RenderImage renderObject, Image oldWidget) { renderObject.image = image; @@ -835,6 +838,7 @@ class Image extends LeafRenderObjectWidget { renderObject.colorFilter = colorFilter; renderObject.fit = fit; renderObject.repeat = repeat; + renderObject.centerSlice = centerSlice; } } @@ -845,8 +849,9 @@ class ImageListener extends StatefulComponent { this.width, this.height, this.colorFilter, - this.fit: ImageFit.scaleDown, - this.repeat: ImageRepeat.noRepeat + this.fit, + this.repeat: ImageRepeat.noRepeat, + this.centerSlice }) : super(key: key) { assert(image != null); } @@ -857,6 +862,7 @@ class ImageListener extends StatefulComponent { final ui.ColorFilter colorFilter; final ImageFit fit; final ImageRepeat repeat; + final Rect centerSlice; _ImageListenerState createState() => new _ImageListenerState(); } @@ -894,7 +900,8 @@ class _ImageListenerState extends State { height: config.height, colorFilter: config.colorFilter, fit: config.fit, - repeat: config.repeat + repeat: config.repeat, + centerSlice: config.centerSlice ); } } @@ -906,8 +913,9 @@ class NetworkImage extends StatelessComponent { this.width, this.height, this.colorFilter, - this.fit: ImageFit.scaleDown, - this.repeat: ImageRepeat.noRepeat + this.fit, + this.repeat: ImageRepeat.noRepeat, + this.centerSlice }) : super(key: key); final String src; @@ -916,6 +924,7 @@ class NetworkImage extends StatelessComponent { final ui.ColorFilter colorFilter; final ImageFit fit; final ImageRepeat repeat; + final Rect centerSlice; Widget build(BuildContext context) { return new ImageListener( @@ -924,7 +933,8 @@ class NetworkImage extends StatelessComponent { height: height, colorFilter: colorFilter, fit: fit, - repeat: repeat + repeat: repeat, + centerSlice: centerSlice ); } } @@ -937,8 +947,9 @@ class AssetImage extends StatelessComponent { this.width, this.height, this.colorFilter, - this.fit: ImageFit.scaleDown, - this.repeat: ImageRepeat.noRepeat + this.fit, + this.repeat: ImageRepeat.noRepeat, + this.centerSlice }) : super(key: key); final String name; @@ -948,6 +959,7 @@ class AssetImage extends StatelessComponent { final ui.ColorFilter colorFilter; final ImageFit fit; final ImageRepeat repeat; + final Rect centerSlice; Widget build(BuildContext context) { return new ImageListener( @@ -956,7 +968,8 @@ class AssetImage extends StatelessComponent { height: height, colorFilter: colorFilter, fit: fit, - repeat: repeat + repeat: repeat, + centerSlice: centerSlice ); } } diff --git a/packages/flutter_sprites/lib/label.dart b/packages/flutter_sprites/lib/label.dart index be515e8598..b428c1042c 100644 --- a/packages/flutter_sprites/lib/label.dart +++ b/packages/flutter_sprites/lib/label.dart @@ -1,7 +1,7 @@ part of skysprites; /// Labels are used to display a string of text in a the node tree. To align -/// the label, the textAlign property of teh [TextStyle] can be set. +/// the label, the textAlign property of the [TextStyle] can be set. class Label extends Node { /// Creates a new Label with the provided [_text] and [_textStyle]. Label(this._text, [this._textStyle]) { From 8f65e0cb34a21d95ea12a03cbce0a77f4d3ca312 Mon Sep 17 00:00:00 2001 From: Viktor Lidholt Date: Tue, 13 Oct 2015 13:51:15 -0700 Subject: [PATCH 62/84] Add callback when physics joints break --- .../flutter_sprites/lib/physics_joint.dart | 44 +++++++++++++------ 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/packages/flutter_sprites/lib/physics_joint.dart b/packages/flutter_sprites/lib/physics_joint.dart index 6c92a95546..f71ae5414d 100644 --- a/packages/flutter_sprites/lib/physics_joint.dart +++ b/packages/flutter_sprites/lib/physics_joint.dart @@ -1,7 +1,9 @@ part of skysprites; +typedef void PhysicsJointBreakCallback(PhysicsJoint joint); + abstract class PhysicsJoint { - PhysicsJoint(this._bodyA, this._bodyB, this.breakingForce) { + PhysicsJoint(this._bodyA, this._bodyB, this.breakingForce, this.breakCallback) { bodyA._joints.add(this); bodyB._joints.add(this); } @@ -16,6 +18,8 @@ abstract class PhysicsJoint { final double breakingForce; + final PhysicsJointBreakCallback breakCallback; + bool _active = true; box2d.Joint _joint; @@ -58,9 +62,12 @@ abstract class PhysicsJoint { _joint.getReactionForce(1.0 / dt, reactionForce); if (breakingForce * breakingForce < reactionForce.length2) { - // TODO: Add callback - + // Destroy the joint destroy(); + + // Notify any observer + if (breakCallback != null) + breakCallback(this); } } } @@ -74,8 +81,9 @@ class PhysicsJointRevolute extends PhysicsJoint { this.lowerAngle: 0.0, this.upperAngle: 0.0, this.enableLimit: false, + PhysicsJointBreakCallback breakCallback, double breakingForce - }) : super(bodyA, bodyB, breakingForce) { + }) : super(bodyA, bodyB, breakingForce, breakCallback) { _completeCreation(); } @@ -107,9 +115,10 @@ class PhysicsJointPrismatic extends PhysicsJoint { PhysicsBody bodyA, PhysicsBody bodyB, this.axis, { - double breakingForce + double breakingForce, + PhysicsJointBreakCallback breakCallback } - ) : super(bodyA, bodyB, breakingForce) { + ) : super(bodyA, bodyB, breakingForce, breakCallback) { _completeCreation(); } @@ -127,10 +136,11 @@ class PhysicsJointWeld extends PhysicsJoint { PhysicsBody bodyA, PhysicsBody bodyB, { double breakingForce, + PhysicsJointBreakCallback breakCallback, this.dampening: 0.0, this.frequency: 0.0 } - ) : super(bodyA, bodyB, breakingForce) { + ) : super(bodyA, bodyB, breakingForce, breakCallback) { _completeCreation(); } @@ -159,9 +169,10 @@ class PhysicsJointPulley extends PhysicsJoint { this.anchorA, this.anchorB, this.ratio, { - double breakingForce + double breakingForce, + PhysicsJointBreakCallback breakCallback } - ) : super(bodyA, bodyB, breakingForce) { + ) : super(bodyA, bodyB, breakingForce, breakCallback) { _completeCreation(); } @@ -191,9 +202,10 @@ class PhysicsJointGear extends PhysicsJoint { PhysicsBody bodyA, PhysicsBody bodyB, { double breakingForce, + PhysicsJointBreakCallback breakCallback, this.ratio: 0.0 } - ) : super(bodyA, bodyB, breakingForce) { + ) : super(bodyA, bodyB, breakingForce, breakCallback) { _completeCreation(); } @@ -216,11 +228,12 @@ class PhysicsJointDistance extends PhysicsJoint { this.anchorA, this.anchorB, { double breakingForce, + PhysicsJointBreakCallback breakCallback, this.length, this.dampening: 0.0, this.frequency: 0.0 } - ) : super(bodyA, bodyB, breakingForce) { + ) : super(bodyA, bodyB, breakingForce, breakCallback) { _completeCreation(); } @@ -254,10 +267,11 @@ class PhysicsJointWheel extends PhysicsJoint { this.anchor, this.axis, { double breakingForce, + PhysicsJointBreakCallback breakCallback, this.dampening: 0.0, this.frequency: 0.0 } - ) : super(bodyA, bodyB, breakingForce) { + ) : super(bodyA, bodyB, breakingForce, breakCallback) { _completeCreation(); } @@ -287,10 +301,11 @@ class PhysicsJointFriction extends PhysicsJoint { PhysicsBody bodyB, this.anchor, { double breakingForce, + PhysicsJointBreakCallback breakCallback, this.maxForce: 0.0, this.maxTorque: 0.0 } - ) : super(bodyA, bodyB, breakingForce) { + ) : super(bodyA, bodyB, breakingForce, breakCallback) { _completeCreation(); } @@ -315,10 +330,11 @@ class PhysicsJointConstantVolume extends PhysicsJoint { PhysicsJointConstantVolume( this.bodies, { double breakingForce, + PhysicsJointBreakCallback breakCallback, this.dampening, this.frequency } - ) : super(null, null, breakingForce) { + ) : super(null, null, breakingForce, breakCallback) { assert(bodies.length > 2); _bodyA = bodies[0]; _bodyB = bodies[1]; From 93fa4464ba475f7d5a7c3d95b86cf09fef027518 Mon Sep 17 00:00:00 2001 From: Jim Beveridge Date: Tue, 13 Oct 2015 13:53:05 -0700 Subject: [PATCH 63/84] Show new flutter tool and its use in the widgets dir. --- examples/README.md | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/examples/README.md b/examples/README.md index 7068ad2726..2078c3ab9c 100644 --- a/examples/README.md +++ b/examples/README.md @@ -2,15 +2,22 @@ Flutter Examples ================ This directory contains several examples of using Flutter. Each of these is an -individual Dart application package. If you wish to run them with `sky_tool` -then you will want to run `pub get` inside their directory before running -`./packages/sky/sky_tool start`. +individual Dart application package. -1. *Hello, world.* The [hello world app](hello_world) is a basic app that shows +To run a sample with the `flutter` tool, run `pub get` inside its directory, +then run `flutter start`. (See the +[getting started guide](https://flutter.github.io/getting-started/) to install +the `flutter` tool.) + +Available examples include: + +- *Hello, world.* The [hello world app](hello_world) is a basic app that shows the text "hello, world." -2. *Stocks.* The [stocks app](stocks) is an example of a typical mobile app +- *Stocks.* The [stocks app](stocks) is an example of a typical mobile app built using Flutter. The app shows a list of all the stocks in the NASDAQ. -3. *Widgets.* The [widgets app](widgets) contains a number of Flutter widgets so - you can experiment with them in a simple container. +- *Widgets.* The [widget apps](widgets) demonstrate a number of Flutter widgets + so you can experiment with them in a simple container. There is no main.dart + in this directory because each file is a standalone sample. To run a + particular file, use `flutter start -t filename.dart`. From e3d7cba48241677ebe766463c9728aaddc7fc5c1 Mon Sep 17 00:00:00 2001 From: Viktor Lidholt Date: Tue, 13 Oct 2015 14:15:27 -0700 Subject: [PATCH 64/84] Updates flutter sprites pubspec --- packages/flutter_sprites/pubspec.yaml | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/packages/flutter_sprites/pubspec.yaml b/packages/flutter_sprites/pubspec.yaml index d9ec7d32d4..4e1035b28e 100644 --- a/packages/flutter_sprites/pubspec.yaml +++ b/packages/flutter_sprites/pubspec.yaml @@ -1,12 +1,9 @@ -name: skysprites +name: flutter_sprites description: A sprite toolkit built on top of Flutter -version: 0.0.1 +version: 0.0.2 author: Flutter Authors homepage: http://flutter.io dependencies: flutter: ">=0.0.3 <0.1.0" sky_tools: ">=0.0.18 <0.1.0" - box2d: any -dependency_overrides: - flutter: - path: ../sky/packages/sky + box2d: ">=0.2.0 <0.3.0" From 1cf1cf9c64a37f904a41f4132e5fb7e98d5806ea Mon Sep 17 00:00:00 2001 From: Hixie Date: Fri, 9 Oct 2015 10:15:56 -0700 Subject: [PATCH 65/84] Port first sector demo to fn3 Also, fix warnings in rendering/sector_layout.dart Also, fix hit testing in rendering/sector_layout.dart Also, add WidgetToRenderBoxAdapter Also, make the rendering library debugging tools more resilient to dumping stuff before layout is complete. --- examples/raw/pubspec.yaml | 2 +- examples/rendering/lib/sector_layout.dart | 527 +++++++++++++++++ examples/rendering/pubspec.yaml | 2 +- examples/rendering/sector_layout.dart | 534 +----------------- examples/widgets/pubspec.yaml | 5 +- .../widgets/{sector.dart.old => sector.dart} | 58 +- packages/flutter/lib/src/rendering/box.dart | 2 +- packages/flutter/lib/src/widgets/basic.dart | 16 + 8 files changed, 584 insertions(+), 562 deletions(-) create mode 100644 examples/rendering/lib/sector_layout.dart rename examples/widgets/{sector.dart.old => sector.dart} (76%) diff --git a/examples/raw/pubspec.yaml b/examples/raw/pubspec.yaml index 02ca8c18af..0443125d5f 100644 --- a/examples/raw/pubspec.yaml +++ b/examples/raw/pubspec.yaml @@ -1,4 +1,4 @@ -name: raw +name: sky_raw_examples dependencies: flutter: ">=0.0.3 <0.1.0" sky_tools: any diff --git a/examples/rendering/lib/sector_layout.dart b/examples/rendering/lib/sector_layout.dart new file mode 100644 index 0000000000..8944c5f672 --- /dev/null +++ b/examples/rendering/lib/sector_layout.dart @@ -0,0 +1,527 @@ +// 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 'dart:ui' as ui; + +import 'package:flutter/rendering.dart'; + +const double kTwoPi = 2 * math.PI; + +class SectorConstraints extends Constraints { + const SectorConstraints({ + this.minDeltaRadius: 0.0, + this.maxDeltaRadius: double.INFINITY, + this.minDeltaTheta: 0.0, + this.maxDeltaTheta: kTwoPi + }); + + const SectorConstraints.tight({ double deltaRadius: 0.0, double deltaTheta: 0.0 }) + : minDeltaRadius = deltaRadius, + maxDeltaRadius = deltaRadius, + minDeltaTheta = deltaTheta, + maxDeltaTheta = deltaTheta; + + final double minDeltaRadius; + final double maxDeltaRadius; + final double minDeltaTheta; + final double maxDeltaTheta; + + double constrainDeltaRadius(double deltaRadius) { + return clamp(min: minDeltaRadius, max: maxDeltaRadius, value: deltaRadius); + } + + double constrainDeltaTheta(double deltaTheta) { + return clamp(min: minDeltaTheta, max: maxDeltaTheta, value: deltaTheta); + } + + bool get isTight => minDeltaTheta >= maxDeltaTheta && minDeltaTheta >= maxDeltaTheta; +} + +class SectorDimensions { + const SectorDimensions({ this.deltaRadius: 0.0, this.deltaTheta: 0.0 }); + + factory SectorDimensions.withConstraints( + SectorConstraints constraints, + { double deltaRadius: 0.0, double deltaTheta: 0.0 } + ) { + return new SectorDimensions( + deltaRadius: constraints.constrainDeltaRadius(deltaRadius), + deltaTheta: constraints.constrainDeltaTheta(deltaTheta) + ); + } + + final double deltaRadius; + final double deltaTheta; +} + +class SectorParentData extends ParentData { + double radius = 0.0; + double theta = 0.0; +} + +abstract class RenderSector extends RenderObject { + + void setupParentData(RenderObject child) { + if (child.parentData is! SectorParentData) + child.parentData = new SectorParentData(); + } + + // RenderSectors always use SectorParentData subclasses, as they need to be + // able to read their position information for painting and hit testing. + SectorParentData get parentData => super.parentData; + + SectorDimensions getIntrinsicDimensions(SectorConstraints constraints, double radius) { + return new SectorDimensions.withConstraints(constraints); + } + + SectorConstraints get constraints => super.constraints; + bool debugDoesMeetConstraints() { + assert(constraints != null); + assert(deltaRadius != null); + assert(deltaRadius < double.INFINITY); + assert(deltaTheta != null); + assert(deltaTheta < double.INFINITY); + return constraints.minDeltaRadius <= deltaRadius && + deltaRadius <= math.max(constraints.minDeltaRadius, constraints.maxDeltaRadius) && + constraints.minDeltaTheta <= deltaTheta && + deltaTheta <= math.max(constraints.minDeltaTheta, constraints.maxDeltaTheta); + } + void performResize() { + // default behaviour for subclasses that have sizedByParent = true + deltaRadius = constraints.constrainDeltaRadius(0.0); + deltaTheta = constraints.constrainDeltaTheta(0.0); + } + void performLayout() { + // descendants have to either override performLayout() to set both + // the dimensions and lay out children, or, set sizedByParent to + // true so that performResize()'s logic above does its thing. + assert(sizedByParent); + } + + Rect get paintBounds => new Rect.fromLTWH(0.0, 0.0, 2.0 * deltaRadius, 2.0 * deltaRadius); + + bool hitTest(HitTestResult result, { double radius, double theta }) { + if (radius < parentData.radius || radius >= parentData.radius + deltaRadius || + theta < parentData.theta || theta >= parentData.theta + deltaTheta) + return false; + hitTestChildren(result, radius: radius, theta: theta); + result.add(new HitTestEntry(this)); + return true; + } + void hitTestChildren(HitTestResult result, { double radius, double theta }) { } + + double deltaRadius; + double deltaTheta; +} + +abstract class RenderDecoratedSector extends RenderSector { + + RenderDecoratedSector(BoxDecoration decoration) : _decoration = decoration; + + BoxDecoration _decoration; + BoxDecoration get decoration => _decoration; + void set decoration (BoxDecoration value) { + if (value == _decoration) + return; + _decoration = value; + markNeedsPaint(); + } + + // offset must point to the center of the circle + void paint(PaintingContext context, Offset offset) { + assert(deltaRadius != null); + assert(deltaTheta != null); + assert(parentData is SectorParentData); + + if (_decoration == null) + return; + + if (_decoration.backgroundColor != null) { + final PaintingCanvas canvas = context.canvas; + Paint paint = new Paint()..color = _decoration.backgroundColor; + Path path = new Path(); + double outerRadius = (parentData.radius + deltaRadius); + Rect outerBounds = new Rect.fromLTRB(offset.dx-outerRadius, offset.dy-outerRadius, offset.dx+outerRadius, offset.dy+outerRadius); + path.arcTo(outerBounds, parentData.theta, deltaTheta, true); + double innerRadius = parentData.radius; + Rect innerBounds = new Rect.fromLTRB(offset.dx-innerRadius, offset.dy-innerRadius, offset.dx+innerRadius, offset.dy+innerRadius); + path.arcTo(innerBounds, parentData.theta + deltaTheta, -deltaTheta, false); + path.close(); + canvas.drawPath(path, paint); + } + } + +} + +class SectorChildListParentData extends SectorParentData with ContainerParentDataMixin { } + +class RenderSectorWithChildren extends RenderDecoratedSector with ContainerRenderObjectMixin { + RenderSectorWithChildren(BoxDecoration decoration) : super(decoration); + + void hitTestChildren(HitTestResult result, { double radius, double theta }) { + RenderSector child = lastChild; + while (child != null) { + if (child.hitTest(result, radius: radius, theta: theta)) + return; + final SectorChildListParentData childParentData = child.parentData; + child = childParentData.previousSibling; + } + } + + void visitChildren(RenderObjectVisitor visitor) { + RenderSector child = lastChild; + while (child != null) { + visitor(child); + final SectorChildListParentData childParentData = child.parentData; + child = childParentData.previousSibling; + } + } +} + +class RenderSectorRing extends RenderSectorWithChildren { + // lays out RenderSector children in a ring + + RenderSectorRing({ + BoxDecoration decoration, + double deltaRadius: double.INFINITY, + double padding: 0.0 + }) : _padding = padding, _desiredDeltaRadius = deltaRadius, super(decoration); + + double _desiredDeltaRadius; + double get desiredDeltaRadius => _desiredDeltaRadius; + void set desiredDeltaRadius(double value) { + assert(value != null); + if (_desiredDeltaRadius != value) { + _desiredDeltaRadius = value; + markNeedsLayout(); + } + } + + double _padding; + double get padding => _padding; + void set padding(double value) { + // TODO(ianh): avoid code duplication + assert(value != null); + if (_padding != value) { + _padding = value; + markNeedsLayout(); + } + } + + void setupParentData(RenderObject child) { + // TODO(ianh): avoid code duplication + if (child.parentData is! SectorChildListParentData) + child.parentData = new SectorChildListParentData(); + } + + SectorDimensions getIntrinsicDimensions(SectorConstraints constraints, double radius) { + double outerDeltaRadius = constraints.constrainDeltaRadius(desiredDeltaRadius); + double innerDeltaRadius = outerDeltaRadius - padding * 2.0; + double childRadius = radius + padding; + double paddingTheta = math.atan(padding / (radius + outerDeltaRadius)); + double innerTheta = paddingTheta; // increments with each child + double remainingDeltaTheta = constraints.maxDeltaTheta - (innerTheta + paddingTheta); + RenderSector child = firstChild; + while (child != null) { + SectorConstraints innerConstraints = new SectorConstraints( + maxDeltaRadius: innerDeltaRadius, + maxDeltaTheta: remainingDeltaTheta + ); + SectorDimensions childDimensions = child.getIntrinsicDimensions(innerConstraints, childRadius); + innerTheta += childDimensions.deltaTheta; + remainingDeltaTheta -= childDimensions.deltaTheta; + final SectorChildListParentData childParentData = child.parentData; + child = childParentData.nextSibling; + if (child != null) { + innerTheta += paddingTheta; + remainingDeltaTheta -= paddingTheta; + } + } + return new SectorDimensions.withConstraints(constraints, + deltaRadius: outerDeltaRadius, + deltaTheta: innerTheta); + } + + void performLayout() { + assert(this.parentData is SectorParentData); + deltaRadius = constraints.constrainDeltaRadius(desiredDeltaRadius); + assert(deltaRadius < double.INFINITY); + double innerDeltaRadius = deltaRadius - padding * 2.0; + double childRadius = this.parentData.radius + padding; + double paddingTheta = math.atan(padding / (this.parentData.radius + deltaRadius)); + double innerTheta = paddingTheta; // increments with each child + double remainingDeltaTheta = constraints.maxDeltaTheta - (innerTheta + paddingTheta); + RenderSector child = firstChild; + while (child != null) { + SectorConstraints innerConstraints = new SectorConstraints( + maxDeltaRadius: innerDeltaRadius, + maxDeltaTheta: remainingDeltaTheta + ); + assert(child.parentData is SectorParentData); + child.parentData.theta = innerTheta; + child.parentData.radius = childRadius; + child.layout(innerConstraints, parentUsesSize: true); + innerTheta += child.deltaTheta; + remainingDeltaTheta -= child.deltaTheta; + final SectorChildListParentData childParentData = child.parentData; + child = childParentData.nextSibling; + if (child != null) { + innerTheta += paddingTheta; + remainingDeltaTheta -= paddingTheta; + } + } + deltaTheta = innerTheta; + } + + // offset must point to the center of our circle + // each sector then knows how to paint itself at its location + void paint(PaintingContext context, Offset offset) { + // TODO(ianh): avoid code duplication + super.paint(context, offset); + RenderSector child = firstChild; + while (child != null) { + context.paintChild(child, offset.toPoint()); + final SectorChildListParentData childParentData = child.parentData; + child = childParentData.nextSibling; + } + } + +} + +class RenderSectorSlice extends RenderSectorWithChildren { + // lays out RenderSector children in a stack + + RenderSectorSlice({ + BoxDecoration decoration, + double deltaTheta: kTwoPi, + double padding: 0.0 + }) : _padding = padding, _desiredDeltaTheta = deltaTheta, super(decoration); + + double _desiredDeltaTheta; + double get desiredDeltaTheta => _desiredDeltaTheta; + void set desiredDeltaTheta(double value) { + assert(value != null); + if (_desiredDeltaTheta != value) { + _desiredDeltaTheta = value; + markNeedsLayout(); + } + } + + double _padding; + double get padding => _padding; + void set padding(double value) { + // TODO(ianh): avoid code duplication + assert(value != null); + if (_padding != value) { + _padding = value; + markNeedsLayout(); + } + } + + void setupParentData(RenderObject child) { + // TODO(ianh): avoid code duplication + if (child.parentData is! SectorChildListParentData) + child.parentData = new SectorChildListParentData(); + } + + SectorDimensions getIntrinsicDimensions(SectorConstraints constraints, double radius) { + assert(this.parentData is SectorParentData); + double paddingTheta = math.atan(padding / this.parentData.radius); + double outerDeltaTheta = constraints.constrainDeltaTheta(desiredDeltaTheta); + double innerDeltaTheta = outerDeltaTheta - paddingTheta * 2.0; + double childRadius = this.parentData.radius + padding; + double remainingDeltaRadius = constraints.maxDeltaRadius - (padding * 2.0); + RenderSector child = firstChild; + while (child != null) { + SectorConstraints innerConstraints = new SectorConstraints( + maxDeltaRadius: remainingDeltaRadius, + maxDeltaTheta: innerDeltaTheta + ); + SectorDimensions childDimensions = child.getIntrinsicDimensions(innerConstraints, childRadius); + childRadius += childDimensions.deltaRadius; + remainingDeltaRadius -= childDimensions.deltaRadius; + final SectorChildListParentData childParentData = child.parentData; + child = childParentData.nextSibling; + childRadius += padding; + remainingDeltaRadius -= padding; + } + return new SectorDimensions.withConstraints(constraints, + deltaRadius: childRadius - this.parentData.radius, + deltaTheta: outerDeltaTheta); + } + + void performLayout() { + assert(this.parentData is SectorParentData); + deltaTheta = constraints.constrainDeltaTheta(desiredDeltaTheta); + assert(deltaTheta <= kTwoPi); + double paddingTheta = math.atan(padding / this.parentData.radius); + double innerTheta = this.parentData.theta + paddingTheta; + double innerDeltaTheta = deltaTheta - paddingTheta * 2.0; + double childRadius = this.parentData.radius + padding; + double remainingDeltaRadius = constraints.maxDeltaRadius - (padding * 2.0); + RenderSector child = firstChild; + while (child != null) { + SectorConstraints innerConstraints = new SectorConstraints( + maxDeltaRadius: remainingDeltaRadius, + maxDeltaTheta: innerDeltaTheta + ); + child.parentData.theta = innerTheta; + child.parentData.radius = childRadius; + child.layout(innerConstraints, parentUsesSize: true); + childRadius += child.deltaRadius; + remainingDeltaRadius -= child.deltaRadius; + final SectorChildListParentData childParentData = child.parentData; + child = childParentData.nextSibling; + childRadius += padding; + remainingDeltaRadius -= padding; + } + deltaRadius = childRadius - this.parentData.radius; + } + + // offset must point to the center of our circle + // each sector then knows how to paint itself at its location + void paint(PaintingContext context, Offset offset) { + // TODO(ianh): avoid code duplication + super.paint(context, offset); + RenderSector child = firstChild; + while (child != null) { + assert(child.parentData is SectorChildListParentData); + context.paintChild(child, offset.toPoint()); + final SectorChildListParentData childParentData = child.parentData; + child = childParentData.nextSibling; + } + } + +} + +class RenderBoxToRenderSectorAdapter extends RenderBox with RenderObjectWithChildMixin { + + RenderBoxToRenderSectorAdapter({ double innerRadius: 0.0, RenderSector child }) : + _innerRadius = innerRadius { + this.child = child; + } + + double _innerRadius; + double get innerRadius => _innerRadius; + void set innerRadius(double value) { + _innerRadius = value; + markNeedsLayout(); + } + + void setupParentData(RenderObject child) { + if (child.parentData is! SectorParentData) + child.parentData = new SectorParentData(); + } + + double getMinIntrinsicWidth(BoxConstraints constraints) { + if (child == null) + return super.getMinIntrinsicWidth(constraints); + return getIntrinsicDimensions(constraints).width; + } + + double getMaxIntrinsicWidth(BoxConstraints constraints) { + if (child == null) + return super.getMaxIntrinsicWidth(constraints); + return getIntrinsicDimensions(constraints).width; + } + + double getMinIntrinsicHeight(BoxConstraints constraints) { + if (child == null) + return super.getMinIntrinsicHeight(constraints); + return getIntrinsicDimensions(constraints).height; + } + + double getMaxIntrinsicHeight(BoxConstraints constraints) { + if (child == null) + return super.getMaxIntrinsicHeight(constraints); + return getIntrinsicDimensions(constraints).height; + } + + Size getIntrinsicDimensions(BoxConstraints constraints) { + assert(child is RenderSector); + assert(child.parentData is SectorParentData); + assert(constraints.maxWidth < double.INFINITY || constraints.maxHeight < double.INFINITY); + double maxChildDeltaRadius = math.min(constraints.maxWidth, constraints.maxHeight) / 2.0 - innerRadius; + SectorDimensions childDimensions = child.getIntrinsicDimensions(new SectorConstraints(maxDeltaRadius: maxChildDeltaRadius), innerRadius); + double dimension = (innerRadius + childDimensions.deltaRadius) * 2.0; + return constraints.constrain(new Size(dimension, dimension)); + } + + void performLayout() { + if (child == null) { + size = constraints.constrain(Size.zero); + } else { + assert(child is RenderSector); + assert(constraints.maxWidth < double.INFINITY || constraints.maxHeight < double.INFINITY); + double maxChildDeltaRadius = math.min(constraints.maxWidth, constraints.maxHeight) / 2.0 - innerRadius; + assert(child.parentData is SectorParentData); + child.parentData.radius = innerRadius; + child.parentData.theta = 0.0; + child.layout(new SectorConstraints(maxDeltaRadius: maxChildDeltaRadius), parentUsesSize: true); + double dimension = (innerRadius + child.deltaRadius) * 2.0; + size = constraints.constrain(new Size(dimension, dimension)); + } + } + + void paint(PaintingContext context, Offset offset) { + super.paint(context, offset); + if (child != null) { + Rect bounds = offset & size; + // we move the offset to the center of the circle for the RenderSectors + context.paintChild(child, bounds.center); + } + } + + bool hitTest(HitTestResult result, { Point position }) { + if (child == null) + return false; + double x = position.x; + double y = position.y; + // translate to our origin + x -= size.width/2.0; + y -= size.height/2.0; + // convert to radius/theta + double radius = math.sqrt(x*x+y*y); + double theta = (math.atan2(x, -y) - math.PI/2.0) % kTwoPi; + if (radius < innerRadius) + return false; + if (radius >= innerRadius + child.deltaRadius) + return false; + if (theta > child.deltaTheta) + return false; + child.hitTest(result, radius: radius, theta: theta); + result.add(new BoxHitTestEntry(this, position)); + return true; + } + +} + +class RenderSolidColor extends RenderDecoratedSector { + RenderSolidColor(Color backgroundColor, { + this.desiredDeltaRadius: double.INFINITY, + this.desiredDeltaTheta: kTwoPi + }) : this.backgroundColor = backgroundColor, + super(new BoxDecoration(backgroundColor: backgroundColor)); + + double desiredDeltaRadius; + double desiredDeltaTheta; + final Color backgroundColor; + + SectorDimensions getIntrinsicDimensions(SectorConstraints constraints, double radius) { + return new SectorDimensions.withConstraints(constraints, deltaTheta: desiredDeltaTheta); + } + + void performLayout() { + deltaRadius = constraints.constrainDeltaRadius(desiredDeltaRadius); + deltaTheta = constraints.constrainDeltaTheta(desiredDeltaTheta); + } + + void handleEvent(ui.Event event, HitTestEntry entry) { + if (event.type == 'pointerdown') + decoration = new BoxDecoration(backgroundColor: const Color(0xFFFF0000)); + else if (event.type == 'pointerup') + decoration = new BoxDecoration(backgroundColor: backgroundColor); + } +} diff --git a/examples/rendering/pubspec.yaml b/examples/rendering/pubspec.yaml index 0eb70a38f8..5158fb4835 100644 --- a/examples/rendering/pubspec.yaml +++ b/examples/rendering/pubspec.yaml @@ -1,4 +1,4 @@ -name: rendering +name: flutter_rendering_examples dependencies: flutter: ">=0.0.3 <0.1.0" sky_tools: any diff --git a/examples/rendering/sector_layout.dart b/examples/rendering/sector_layout.dart index 912127ad0a..ac3fc4699e 100644 --- a/examples/rendering/sector_layout.dart +++ b/examples/rendering/sector_layout.dart @@ -2,539 +2,9 @@ // 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 'dart:ui' as ui; - +import 'dart:async'; import 'package:flutter/rendering.dart'; - -const double kTwoPi = 2 * math.PI; - -class SectorConstraints extends Constraints { - const SectorConstraints({ - this.minDeltaRadius: 0.0, - this.maxDeltaRadius: double.INFINITY, - this.minDeltaTheta: 0.0, - this.maxDeltaTheta: kTwoPi - }); - - const SectorConstraints.tight({ double deltaRadius: 0.0, double deltaTheta: 0.0 }) - : minDeltaRadius = deltaRadius, - maxDeltaRadius = deltaRadius, - minDeltaTheta = deltaTheta, - maxDeltaTheta = deltaTheta; - - final double minDeltaRadius; - final double maxDeltaRadius; - final double minDeltaTheta; - final double maxDeltaTheta; - - double constrainDeltaRadius(double deltaRadius) { - return clamp(min: minDeltaRadius, max: maxDeltaRadius, value: deltaRadius); - } - - double constrainDeltaTheta(double deltaTheta) { - return clamp(min: minDeltaTheta, max: maxDeltaTheta, value: deltaTheta); - } - - bool get isTight => minDeltaTheta >= maxDeltaTheta && minDeltaTheta >= maxDeltaTheta; -} - -class SectorDimensions { - const SectorDimensions({ this.deltaRadius: 0.0, this.deltaTheta: 0.0 }); - - factory SectorDimensions.withConstraints( - SectorConstraints constraints, - { double deltaRadius: 0.0, double deltaTheta: 0.0 } - ) { - return new SectorDimensions( - deltaRadius: constraints.constrainDeltaRadius(deltaRadius), - deltaTheta: constraints.constrainDeltaTheta(deltaTheta) - ); - } - - final double deltaRadius; - final double deltaTheta; -} - -class SectorParentData extends ParentData { - double radius = 0.0; - double theta = 0.0; -} - -abstract class RenderSector extends RenderObject { - - void setupParentData(RenderObject child) { - if (child.parentData is! SectorParentData) - child.parentData = new SectorParentData(); - } - - SectorDimensions getIntrinsicDimensions(SectorConstraints constraints, double radius) { - return new SectorDimensions.withConstraints(constraints); - } - - SectorConstraints get constraints => super.constraints; - bool debugDoesMeetConstraints() { - assert(constraints != null); - assert(deltaRadius != null); - assert(deltaRadius < double.INFINITY); - assert(deltaTheta != null); - assert(deltaTheta < double.INFINITY); - return constraints.minDeltaRadius <= deltaRadius && - deltaRadius <= math.max(constraints.minDeltaRadius, constraints.maxDeltaRadius) && - constraints.minDeltaTheta <= deltaTheta && - deltaTheta <= math.max(constraints.minDeltaTheta, constraints.maxDeltaTheta); - } - void performResize() { - // default behaviour for subclasses that have sizedByParent = true - deltaRadius = constraints.constrainDeltaRadius(0.0); - deltaTheta = constraints.constrainDeltaTheta(0.0); - } - void performLayout() { - // descendants have to either override performLayout() to set both - // the dimensions and lay out children, or, set sizedByParent to - // true so that performResize()'s logic above does its thing. - assert(sizedByParent); - } - - Rect get paintBounds => new Rect.fromLTWH(0.0, 0.0, 2.0 * deltaRadius, 2.0 * deltaRadius); - - bool hitTest(HitTestResult result, { double radius, double theta }) { - assert(parentData is SectorParentData); - if (radius < parentData.radius || radius >= parentData.radius + deltaRadius || - theta < parentData.theta || theta >= parentData.theta + deltaTheta) - return false; - hitTestChildren(result, radius: radius, theta: theta); - result.add(new HitTestEntry(this)); - return true; - } - void hitTestChildren(HitTestResult result, { double radius, double theta }) { } - - double deltaRadius; - double deltaTheta; -} - -abstract class RenderDecoratedSector extends RenderSector { - - RenderDecoratedSector(BoxDecoration decoration) : _decoration = decoration; - - BoxDecoration _decoration; - BoxDecoration get decoration => _decoration; - void set decoration (BoxDecoration value) { - if (value == _decoration) - return; - _decoration = value; - markNeedsPaint(); - } - - // offset must point to the center of the circle - void paint(PaintingContext context, Offset offset) { - assert(deltaRadius != null); - assert(deltaTheta != null); - assert(parentData is SectorParentData); - - if (_decoration == null) - return; - - if (_decoration.backgroundColor != null) { - final PaintingCanvas canvas = context.canvas; - Paint paint = new Paint()..color = _decoration.backgroundColor; - Path path = new Path(); - double outerRadius = (parentData.radius + deltaRadius); - Rect outerBounds = new Rect.fromLTRB(offset.dx-outerRadius, offset.dy-outerRadius, offset.dx+outerRadius, offset.dy+outerRadius); - path.arcTo(outerBounds, parentData.theta, deltaTheta, true); - double innerRadius = parentData.radius; - Rect innerBounds = new Rect.fromLTRB(offset.dx-innerRadius, offset.dy-innerRadius, offset.dx+innerRadius, offset.dy+innerRadius); - path.arcTo(innerBounds, parentData.theta + deltaTheta, -deltaTheta, false); - path.close(); - canvas.drawPath(path, paint); - } - } - -} - -class SectorChildListParentData extends SectorParentData with ContainerParentDataMixin { } - -class RenderSectorWithChildren extends RenderDecoratedSector with ContainerRenderObjectMixin { - RenderSectorWithChildren(BoxDecoration decoration) : super(decoration); - - void hitTestChildren(HitTestResult result, { double radius, double theta }) { - RenderSector child = lastChild; - while (child != null) { - assert(child.parentData is SectorChildListParentData); - if (child.hitTest(result, radius: radius, theta: theta)) - return; - child = child.parentData.previousSibling; - } - } - - void visitChildren(RenderObjectVisitor visitor) { - RenderSector child = lastChild; - while (child != null) { - visitor(child); - child = child.parentData.previousSibling; - } - } -} - -class RenderSectorRing extends RenderSectorWithChildren { - // lays out RenderSector children in a ring - - RenderSectorRing({ - BoxDecoration decoration, - double deltaRadius: double.INFINITY, - double padding: 0.0 - }) : super(decoration), _padding = padding, _desiredDeltaRadius = deltaRadius; - - double _desiredDeltaRadius; - double get desiredDeltaRadius => _desiredDeltaRadius; - void set desiredDeltaRadius(double value) { - assert(value != null); - if (_desiredDeltaRadius != value) { - _desiredDeltaRadius = value; - markNeedsLayout(); - } - } - - double _padding; - double get padding => _padding; - void set padding(double value) { - // TODO(ianh): avoid code duplication - assert(value != null); - if (_padding != value) { - _padding = value; - markNeedsLayout(); - } - } - - void setupParentData(RenderObject child) { - // TODO(ianh): avoid code duplication - if (child.parentData is! SectorChildListParentData) - child.parentData = new SectorChildListParentData(); - } - - SectorDimensions getIntrinsicDimensions(SectorConstraints constraints, double radius) { - double outerDeltaRadius = constraints.constrainDeltaRadius(desiredDeltaRadius); - double innerDeltaRadius = outerDeltaRadius - padding * 2.0; - double childRadius = radius + padding; - double paddingTheta = math.atan(padding / (radius + outerDeltaRadius)); - double innerTheta = paddingTheta; // increments with each child - double remainingDeltaTheta = constraints.maxDeltaTheta - (innerTheta + paddingTheta); - RenderSector child = firstChild; - while (child != null) { - SectorConstraints innerConstraints = new SectorConstraints( - maxDeltaRadius: innerDeltaRadius, - maxDeltaTheta: remainingDeltaTheta - ); - SectorDimensions childDimensions = child.getIntrinsicDimensions(innerConstraints, childRadius); - innerTheta += childDimensions.deltaTheta; - remainingDeltaTheta -= childDimensions.deltaTheta; - assert(child.parentData is SectorChildListParentData); - child = child.parentData.nextSibling; - if (child != null) { - innerTheta += paddingTheta; - remainingDeltaTheta -= paddingTheta; - } - } - return new SectorDimensions.withConstraints(constraints, - deltaRadius: outerDeltaRadius, - deltaTheta: innerTheta); - } - - void performLayout() { - assert(this.parentData is SectorParentData); - deltaRadius = constraints.constrainDeltaRadius(desiredDeltaRadius); - assert(deltaRadius < double.INFINITY); - double innerDeltaRadius = deltaRadius - padding * 2.0; - double childRadius = this.parentData.radius + padding; - double paddingTheta = math.atan(padding / (this.parentData.radius + deltaRadius)); - double innerTheta = paddingTheta; // increments with each child - double remainingDeltaTheta = constraints.maxDeltaTheta - (innerTheta + paddingTheta); - RenderSector child = firstChild; - while (child != null) { - SectorConstraints innerConstraints = new SectorConstraints( - maxDeltaRadius: innerDeltaRadius, - maxDeltaTheta: remainingDeltaTheta - ); - assert(child.parentData is SectorParentData); - child.parentData.theta = innerTheta; - child.parentData.radius = childRadius; - child.layout(innerConstraints, parentUsesSize: true); - innerTheta += child.deltaTheta; - remainingDeltaTheta -= child.deltaTheta; - assert(child.parentData is SectorChildListParentData); - child = child.parentData.nextSibling; - if (child != null) { - innerTheta += paddingTheta; - remainingDeltaTheta -= paddingTheta; - } - } - deltaTheta = innerTheta; - } - - // offset must point to the center of our circle - // each sector then knows how to paint itself at its location - void paint(PaintingContext context, Offset offset) { - // TODO(ianh): avoid code duplication - super.paint(context, offset); - RenderSector child = firstChild; - while (child != null) { - assert(child.parentData is SectorChildListParentData); - context.paintChild(child, offset.toPoint()); - child = child.parentData.nextSibling; - } - } - -} - -class RenderSectorSlice extends RenderSectorWithChildren { - // lays out RenderSector children in a stack - - RenderSectorSlice({ - BoxDecoration decoration, - double deltaTheta: kTwoPi, - double padding: 0.0 - }) : super(decoration), _padding = padding, _desiredDeltaTheta = deltaTheta; - - double _desiredDeltaTheta; - double get desiredDeltaTheta => _desiredDeltaTheta; - void set desiredDeltaTheta(double value) { - assert(value != null); - if (_desiredDeltaTheta != value) { - _desiredDeltaTheta = value; - markNeedsLayout(); - } - } - - double _padding; - double get padding => _padding; - void set padding(double value) { - // TODO(ianh): avoid code duplication - assert(value != null); - if (_padding != value) { - _padding = value; - markNeedsLayout(); - } - } - - void setupParentData(RenderObject child) { - // TODO(ianh): avoid code duplication - if (child.parentData is! SectorChildListParentData) - child.parentData = new SectorChildListParentData(); - } - - SectorDimensions getIntrinsicDimensions(SectorConstraints constraints, double radius) { - assert(this.parentData is SectorParentData); - double paddingTheta = math.atan(padding / this.parentData.radius); - double outerDeltaTheta = constraints.constrainDeltaTheta(desiredDeltaTheta); - double innerDeltaTheta = outerDeltaTheta - paddingTheta * 2.0; - double childRadius = this.parentData.radius + padding; - double remainingDeltaRadius = constraints.maxDeltaRadius - (padding * 2.0); - RenderSector child = firstChild; - while (child != null) { - SectorConstraints innerConstraints = new SectorConstraints( - maxDeltaRadius: remainingDeltaRadius, - maxDeltaTheta: innerDeltaTheta - ); - SectorDimensions childDimensions = child.getIntrinsicDimensions(innerConstraints, childRadius); - childRadius += childDimensions.deltaRadius; - remainingDeltaRadius -= childDimensions.deltaRadius; - assert(child.parentData is SectorChildListParentData); - child = child.parentData.nextSibling; - childRadius += padding; - remainingDeltaRadius -= padding; - } - return new SectorDimensions.withConstraints(constraints, - deltaRadius: childRadius - this.parentData.radius, - deltaTheta: outerDeltaTheta); - } - - void performLayout() { - assert(this.parentData is SectorParentData); - deltaTheta = constraints.constrainDeltaTheta(desiredDeltaTheta); - assert(deltaTheta <= kTwoPi); - double paddingTheta = math.atan(padding / this.parentData.radius); - double innerTheta = this.parentData.theta + paddingTheta; - double innerDeltaTheta = deltaTheta - paddingTheta * 2.0; - double childRadius = this.parentData.radius + padding; - double remainingDeltaRadius = constraints.maxDeltaRadius - (padding * 2.0); - RenderSector child = firstChild; - while (child != null) { - SectorConstraints innerConstraints = new SectorConstraints( - maxDeltaRadius: remainingDeltaRadius, - maxDeltaTheta: innerDeltaTheta - ); - child.parentData.theta = innerTheta; - child.parentData.radius = childRadius; - child.layout(innerConstraints, parentUsesSize: true); - childRadius += child.deltaRadius; - remainingDeltaRadius -= child.deltaRadius; - assert(child.parentData is SectorChildListParentData); - child = child.parentData.nextSibling; - childRadius += padding; - remainingDeltaRadius -= padding; - } - deltaRadius = childRadius - this.parentData.radius; - } - - // offset must point to the center of our circle - // each sector then knows how to paint itself at its location - void paint(PaintingContext context, Offset offset) { - // TODO(ianh): avoid code duplication - super.paint(context, offset); - RenderSector child = firstChild; - while (child != null) { - assert(child.parentData is SectorChildListParentData); - context.paintChild(child, offset.toPoint()); - child = child.parentData.nextSibling; - } - } - -} - -class RenderBoxToRenderSectorAdapter extends RenderBox { - - RenderBoxToRenderSectorAdapter({ double innerRadius: 0.0, RenderSector child }) : - _innerRadius = innerRadius { - _child = child; - adoptChild(_child); - } - - double _innerRadius; - double get innerRadius => _innerRadius; - void set innerRadius(double value) { - _innerRadius = value; - markNeedsLayout(); - } - - RenderSector _child; - RenderSector get child => _child; - void set child(RenderSector value) { - if (_child != null) - dropChild(_child); - _child = value; - adoptChild(_child); - markNeedsLayout(); - } - - void setupParentData(RenderObject child) { - if (child.parentData is! SectorParentData) - child.parentData = new SectorParentData(); - } - - void visitChildren(RenderObjectVisitor visitor) { - visitor(_child); - } - - double getMinIntrinsicWidth(BoxConstraints constraints) { - if (child == null) - return super.getMinIntrinsicWidth(constraints); - return getIntrinsicDimensions(constraints).width; - } - - double getMaxIntrinsicWidth(BoxConstraints constraints) { - if (child == null) - return super.getMaxIntrinsicWidth(constraints); - return getIntrinsicDimensions(constraints).width; - } - - double getMinIntrinsicHeight(BoxConstraints constraints) { - if (child == null) - return super.getMinIntrinsicHeight(constraints); - return getIntrinsicDimensions(constraints).height; - } - - double getMaxIntrinsicHeight(BoxConstraints constraints) { - if (child == null) - return super.getMaxIntrinsicHeight(constraints); - return getIntrinsicDimensions(constraints).height; - } - - Size getIntrinsicDimensions(BoxConstraints constraints) { - assert(child is RenderSector); - assert(child.parentData is SectorParentData); - assert(constraints.maxWidth < double.INFINITY || constraints.maxHeight < double.INFINITY); - double maxChildDeltaRadius = math.min(constraints.maxWidth, constraints.maxHeight) / 2.0 - innerRadius; - SectorDimensions childDimensions = child.getIntrinsicDimensions(new SectorConstraints(maxDeltaRadius: maxChildDeltaRadius), innerRadius); - double dimension = (innerRadius + childDimensions.deltaRadius) * 2.0; - return constraints.constrain(new Size(dimension, dimension)); - } - - void performLayout() { - if (child == null) { - size = constraints.constrain(Size.zero); - } else { - assert(child is RenderSector); - assert(constraints.maxWidth < double.INFINITY || constraints.maxHeight < double.INFINITY); - double maxChildDeltaRadius = math.min(constraints.maxWidth, constraints.maxHeight) / 2.0 - innerRadius; - assert(child.parentData is SectorParentData); - child.parentData.radius = innerRadius; - child.parentData.theta = 0.0; - child.layout(new SectorConstraints(maxDeltaRadius: maxChildDeltaRadius), parentUsesSize: true); - double dimension = (innerRadius + child.deltaRadius) * 2.0; - size = constraints.constrain(new Size(dimension, dimension)); - } - } - - void paint(PaintingContext context, Offset offset) { - super.paint(context, offset); - if (child != null) { - Rect bounds = offset & size; - // we move the offset to the center of the circle for the RenderSectors - context.paintChild(child, bounds.center); - } - } - - bool hitTest(HitTestResult result, { Point position }) { - double x = position.x; - double y = position.y; - if (child == null) - return false; - // translate to our origin - x -= size.width/2.0; - y -= size.height/2.0; - // convert to radius/theta - double radius = math.sqrt(x*x+y*y); - double theta = (math.atan2(x, -y) - math.PI/2.0) % kTwoPi; - if (radius < innerRadius) - return false; - if (radius >= innerRadius + child.deltaRadius) - return false; - if (theta > child.deltaTheta) - return false; - child.hitTest(result, radius: radius, theta: theta); - result.add(new BoxHitTestEntry(this, position)); - return true; - } - -} - -class RenderSolidColor extends RenderDecoratedSector { - RenderSolidColor(Color backgroundColor, { - this.desiredDeltaRadius: double.INFINITY, - this.desiredDeltaTheta: kTwoPi - }) : this.backgroundColor = backgroundColor, - super(new BoxDecoration(backgroundColor: backgroundColor)); - - double desiredDeltaRadius; - double desiredDeltaTheta; - final Color backgroundColor; - - SectorDimensions getIntrinsicDimensions(SectorConstraints constraints, double radius) { - return new SectorDimensions.withConstraints(constraints, deltaTheta: desiredDeltaTheta); - } - - void performLayout() { - deltaRadius = constraints.constrainDeltaRadius(desiredDeltaRadius); - deltaTheta = constraints.constrainDeltaTheta(desiredDeltaTheta); - } - - void handleEvent(ui.Event event, HitTestEntry entry) { - if (event.type == 'pointerdown') - decoration = new BoxDecoration(backgroundColor: const Color(0xFFFF0000)); - else if (event.type == 'pointerup') - decoration = new BoxDecoration(backgroundColor: backgroundColor); - } -} +import 'lib/sector_layout.dart'; RenderBox buildSectorExample() { RenderSectorRing rootCircle = new RenderSectorRing(padding: 20.0); diff --git a/examples/widgets/pubspec.yaml b/examples/widgets/pubspec.yaml index 1a483612b6..8cc7e8c150 100644 --- a/examples/widgets/pubspec.yaml +++ b/examples/widgets/pubspec.yaml @@ -1,9 +1,12 @@ -name: widgets +name: sky_widgets_examples dependencies: flutter: ">=0.0.3 <0.1.0" sky_tools: any + flutter_rendering_examples: any dependency_overrides: material_design_icons: path: ../../sky/packages/material_design_icons flutter: path: ../../sky/packages/sky + flutter_rendering_examples: + path: ../rendering diff --git a/examples/widgets/sector.dart.old b/examples/widgets/sector.dart similarity index 76% rename from examples/widgets/sector.dart.old rename to examples/widgets/sector.dart index 0b7812118e..38bf742021 100644 --- a/examples/widgets/sector.dart.old +++ b/examples/widgets/sector.dart @@ -7,7 +7,7 @@ import 'dart:math' as math; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; -import '../rendering/sector_layout.dart'; +import 'package:flutter_rendering_examples/sector_layout.dart'; RenderBox initCircle() { return new RenderBoxToRenderSectorAdapter( @@ -16,10 +16,14 @@ RenderBox initCircle() { ); } -class SectorApp extends MaterialApp { +class SectorApp extends StatefulComponent { + SectorAppState createState() => new SectorAppState(); +} - RenderBoxToRenderSectorAdapter sectors = initCircle(); - math.Random rand = new math.Random(1); +class SectorAppState extends State { + + final RenderBoxToRenderSectorAdapter sectors = initCircle(); + final math.Random rand = new math.Random(1); void addSector() { double deltaTheta; @@ -52,27 +56,27 @@ class SectorApp extends MaterialApp { RenderBoxToRenderSectorAdapter sectorAddIcon = initSector(const Color(0xFF00DD00)); RenderBoxToRenderSectorAdapter sectorRemoveIcon = initSector(const Color(0xFFDD0000)); - bool enabledAdd = true; - bool enabledRemove = false; + bool _enabledAdd = true; + bool _enabledRemove = false; void updateEnabledState() { setState(() { var ring = (sectors.child as RenderSectorRing); SectorDimensions currentSize = ring.getIntrinsicDimensions(const SectorConstraints(), ring.deltaRadius); - enabledAdd = currentSize.deltaTheta < kTwoPi; - enabledRemove = ring.firstChild != null; + _enabledAdd = currentSize.deltaTheta < kTwoPi; + _enabledRemove = ring.firstChild != null; }); } Widget buildBody() { return new Material( - child: new Column([ + child: new Column([ new Container( padding: new EdgeDims.symmetric(horizontal: 8.0, vertical: 25.0), - child: new Row([ + child: new Row([ new RaisedButton( - enabled: enabledAdd, + enabled: _enabledAdd, child: new IntrinsicWidth( - child: new Row([ + child: new Row([ new Container( padding: new EdgeDims.all(4.0), margin: new EdgeDims.only(right: 10.0), @@ -84,9 +88,9 @@ class SectorApp extends MaterialApp { onPressed: addSector ), new RaisedButton( - enabled: enabledRemove, + enabled: _enabledRemove, child: new IntrinsicWidth( - child: new Row([ + child: new Row([ new Container( padding: new EdgeDims.all(4.0), margin: new EdgeDims.only(right: 10.0), @@ -117,18 +121,20 @@ class SectorApp extends MaterialApp { ); } - Widget build() { - return new Theme( - data: new ThemeData.light(), - child: new Title( - title: 'Sector Layout', - child: new Scaffold( - toolBar: new ToolBar( - center: new Text('Sector Layout in a Widget Tree') - ), - body: buildBody() - ) - ) + Widget build(BuildContext context) { + return new MaterialApp( + theme: new ThemeData.light(), + title: 'Sector Layout', + routes: { + '/': (RouteArguments args) { + return new Scaffold( + toolBar: new ToolBar( + center: new Text('Sector Layout in a Widget Tree') + ), + body: buildBody() + ); + } + } ); } } diff --git a/packages/flutter/lib/src/rendering/box.dart b/packages/flutter/lib/src/rendering/box.dart index cfc9cd2cd5..25bb5d8829 100644 --- a/packages/flutter/lib/src/rendering/box.dart +++ b/packages/flutter/lib/src/rendering/box.dart @@ -633,7 +633,7 @@ abstract class RenderBox extends RenderObject { } } - String debugDescribeSettings(String prefix) => '${super.debugDescribeSettings(prefix)}${prefix}size: $size\n'; + String debugDescribeSettings(String prefix) => '${super.debugDescribeSettings(prefix)}${prefix}size: ${ hasSize ? size : "MISSING" }\n'; } /// A mixin that provides useful default behaviors for boxes with children diff --git a/packages/flutter/lib/src/widgets/basic.dart b/packages/flutter/lib/src/widgets/basic.dart index f4f3d1c4c0..346a4181a6 100644 --- a/packages/flutter/lib/src/widgets/basic.dart +++ b/packages/flutter/lib/src/widgets/basic.dart @@ -961,6 +961,22 @@ class AssetImage extends StatelessComponent { } } +class WidgetToRenderBoxAdapter extends LeafRenderObjectWidget { + WidgetToRenderBoxAdapter(RenderBox renderBox) + : renderBox = renderBox, + // WidgetToRenderBoxAdapter objects are keyed to their render box. This + // prevents the widget being used in the widget hierarchy in two different + // places, which would cause the RenderBox to get inserted in multiple + // places in the RenderObject tree. + super(key: new GlobalObjectKey(renderBox)) { + assert(renderBox != null); + } + + final RenderBox renderBox; + + RenderBox createRenderObject() => renderBox; +} + // EVENT HANDLING From 42469d2cb9570b1da6a0ec8ba6b8561fa9e9a421 Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Tue, 13 Oct 2015 14:26:58 -0700 Subject: [PATCH 66/84] Fix game's pubspec.yaml --- examples/game/pubspec.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/game/pubspec.yaml b/examples/game/pubspec.yaml index 346cb34c2e..1787c99852 100644 --- a/examples/game/pubspec.yaml +++ b/examples/game/pubspec.yaml @@ -2,12 +2,12 @@ name: asteroids dependencies: flutter: ">=0.0.3 <0.1.0" sky_tools: any - skysprites: any + flutter_sprites: any box2d: any dependency_overrides: material_design_icons: path: ../../sky/packages/material_design_icons flutter: path: ../../sky/packages/sky - skysprites: + flutter_sprites: path: ../../skysprites From ec205ac5c5fe357f896917baf815446291f96a16 Mon Sep 17 00:00:00 2001 From: Kris Giesing Date: Mon, 12 Oct 2015 16:14:53 -0700 Subject: [PATCH 67/84] Add dart-layer input event abstraction --- examples/mine_digger/lib/main.dart | 6 +- examples/rendering/sector_layout.dart | 4 +- examples/rendering/solid_color_box.dart | 5 +- examples/rendering/touch_demo.dart | 9 +- packages/flutter/lib/gestures.dart | 1 + packages/flutter/lib/src/gestures/drag.dart | 15 +-- packages/flutter/lib/src/gestures/events.dart | 114 ++++++++++++++++++ .../flutter/lib/src/gestures/long_press.dart | 5 +- .../lib/src/gestures/pointer_router.dart | 14 +-- .../flutter/lib/src/gestures/recognizer.dart | 17 +-- packages/flutter/lib/src/gestures/scale.dart | 5 +- .../flutter/lib/src/gestures/show_press.dart | 5 +- packages/flutter/lib/src/gestures/tap.dart | 5 +- .../flutter/lib/src/material/ink_well.dart | 2 +- .../lib/src/material/material_app.dart | 5 +- packages/flutter/lib/src/material/switch.dart | 5 +- .../flutter/lib/src/rendering/binding.dart | 19 +-- .../flutter/lib/src/rendering/hit_test.dart | 4 +- .../flutter/lib/src/rendering/object.dart | 3 +- .../flutter/lib/src/rendering/proxy_box.dart | 5 +- .../flutter/lib/src/rendering/toggleable.dart | 4 +- .../flutter/lib/src/widgets/drag_target.dart | 10 +- .../lib/src/widgets/gesture_detector.dart | 4 +- packages/unit/test/engine/mock_events.dart | 75 ++---------- .../unit/test/gestures/long_press_test.dart | 6 +- .../test/gestures/pointer_router_test.dart | 4 +- packages/unit/test/gestures/scale_test.dart | 24 ++-- packages/unit/test/gestures/scroll_test.dart | 6 +- .../unit/test/gestures/show_press_test.dart | 6 +- packages/unit/test/gestures/tap_test.dart | 6 +- packages/unit/test/widget/widget_tester.dart | 7 +- 31 files changed, 224 insertions(+), 176 deletions(-) create mode 100644 packages/flutter/lib/src/gestures/events.dart diff --git a/examples/mine_digger/lib/main.dart b/examples/mine_digger/lib/main.dart index 1fe6f7e0cc..588fa70779 100644 --- a/examples/mine_digger/lib/main.dart +++ b/examples/mine_digger/lib/main.dart @@ -1,9 +1,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ui' as ui; import 'dart:math'; +import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter/painting.dart'; import 'package:flutter/rendering.dart'; @@ -85,7 +85,7 @@ class MineDiggerState extends State { } PointerEventListener _pointerDownHandlerFor(int posX, int posY) { - return (ui.PointerEvent event) { + return (PointerInputEvent event) { if (event.buttons == 1) { probe(posX, posY); } else if (event.buttons == 2) { @@ -190,7 +190,7 @@ class MineDiggerState extends State { ); } - void handleToolbarPointerDown(ui.PointerEvent event) { + void handleToolbarPointerDown(PointerInputEvent event) { setState(() { resetGame(); }); diff --git a/examples/rendering/sector_layout.dart b/examples/rendering/sector_layout.dart index 912127ad0a..87d42c896b 100644 --- a/examples/rendering/sector_layout.dart +++ b/examples/rendering/sector_layout.dart @@ -3,9 +3,9 @@ // found in the LICENSE file. import 'dart:math' as math; -import 'dart:ui' as ui; import 'package:flutter/rendering.dart'; +import 'package:flutter/gestures.dart'; const double kTwoPi = 2 * math.PI; @@ -528,7 +528,7 @@ class RenderSolidColor extends RenderDecoratedSector { deltaTheta = constraints.constrainDeltaTheta(desiredDeltaTheta); } - void handleEvent(ui.Event event, HitTestEntry entry) { + void handleEvent(InputEvent event, HitTestEntry entry) { if (event.type == 'pointerdown') decoration = new BoxDecoration(backgroundColor: const Color(0xFFFF0000)); else if (event.type == 'pointerup') diff --git a/examples/rendering/solid_color_box.dart b/examples/rendering/solid_color_box.dart index acd6a6300f..31928d821c 100644 --- a/examples/rendering/solid_color_box.dart +++ b/examples/rendering/solid_color_box.dart @@ -2,9 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ui' as ui; - import 'package:flutter/rendering.dart'; +import 'package:flutter/gestures.dart'; class RenderSolidColorBox extends RenderDecoratedBox { final Size desiredSize; @@ -42,7 +41,7 @@ class RenderSolidColorBox extends RenderDecoratedBox { size = constraints.constrain(desiredSize); } - void handleEvent(ui.Event event, BoxHitTestEntry entry) { + void handleEvent(InputEvent event, BoxHitTestEntry entry) { if (event.type == 'pointerdown') decoration = new BoxDecoration(backgroundColor: const Color(0xFFFF0000)); else if (event.type == 'pointerup') diff --git a/examples/rendering/touch_demo.dart b/examples/rendering/touch_demo.dart index 5c22785110..024fd17d84 100644 --- a/examples/rendering/touch_demo.dart +++ b/examples/rendering/touch_demo.dart @@ -2,10 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ui' as ui; - import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; +import 'package:flutter/gestures.dart'; // Material design colors. :p List kColors = [ @@ -24,7 +23,7 @@ class Dot { Dot({ Color color }) : _paint = new Paint()..color = color; - void update(ui.PointerEvent event) { + void update(PointerInputEvent event) { position = new Point(event.x, event.y); radius = 5 + (95 * event.pressure); } @@ -39,8 +38,8 @@ class RenderTouchDemo extends RenderBox { RenderTouchDemo(); - void handleEvent(ui.Event event, BoxHitTestEntry entry) { - if (event is ui.PointerEvent) { + void handleEvent(InputEvent event, BoxHitTestEntry entry) { + if (event is PointerInputEvent) { switch (event.type) { case 'pointerdown': Color color = kColors[event.pointer.remainder(kColors.length)]; diff --git a/packages/flutter/lib/gestures.dart b/packages/flutter/lib/gestures.dart index 138cf554ca..f5432bc455 100644 --- a/packages/flutter/lib/gestures.dart +++ b/packages/flutter/lib/gestures.dart @@ -8,6 +8,7 @@ library gestures; export 'src/gestures/arena.dart'; export 'src/gestures/constants.dart'; export 'src/gestures/drag.dart'; +export 'src/gestures/events.dart'; export 'src/gestures/long_press.dart'; export 'src/gestures/pointer_router.dart'; export 'src/gestures/recognizer.dart'; diff --git a/packages/flutter/lib/src/gestures/drag.dart b/packages/flutter/lib/src/gestures/drag.dart index 473b410c0c..5a183d8263 100644 --- a/packages/flutter/lib/src/gestures/drag.dart +++ b/packages/flutter/lib/src/gestures/drag.dart @@ -7,6 +7,7 @@ import 'dart:ui' as ui; import 'arena.dart'; import 'recognizer.dart'; import 'constants.dart'; +import 'events.dart'; enum DragState { ready, @@ -24,7 +25,7 @@ typedef void GesturePanEndCallback(ui.Offset velocity); typedef void _GesturePolymorphicUpdateCallback(T delta); -int _eventTime(ui.PointerEvent event) => (event.timeStamp * 1000.0).toInt(); // microseconds +int _eventTime(PointerInputEvent event) => (event.timeStamp * 1000.0).toInt(); // microseconds bool _isFlingGesture(ui.GestureVelocity velocity) { double velocitySquared = velocity.x * velocity.x + velocity.y * velocity.y; @@ -45,12 +46,12 @@ abstract class _DragGestureRecognizer extends GestureRecogniz T _pendingDragDelta; T get _initialPendingDragDelta; - T _getDragDelta(ui.PointerEvent event); + T _getDragDelta(PointerInputEvent event); bool get _hasSufficientPendingDragDeltaToAccept; final ui.VelocityTracker _velocityTracker = new ui.VelocityTracker(); - void addPointer(ui.PointerEvent event) { + void addPointer(PointerInputEvent event) { startTrackingPointer(event.pointer); if (_state == DragState.ready) { _state = DragState.possible; @@ -58,7 +59,7 @@ abstract class _DragGestureRecognizer extends GestureRecogniz } } - void handleEvent(ui.PointerEvent event) { + void handleEvent(PointerInputEvent event) { assert(_state != DragState.ready); if (event.type == 'pointermove') { _velocityTracker.addPosition(_eventTime(event), event.pointer, event.x, event.y); @@ -120,7 +121,7 @@ class VerticalDragGestureRecognizer extends _DragGestureRecognizer { }) : super(router: router, onStart: onStart, onUpdate: onUpdate, onEnd: onEnd); double get _initialPendingDragDelta => 0.0; - double _getDragDelta(ui.PointerEvent event) => event.dy; + double _getDragDelta(PointerInputEvent event) => event.dy; bool get _hasSufficientPendingDragDeltaToAccept => _pendingDragDelta.abs() > kTouchSlop; } @@ -133,7 +134,7 @@ class HorizontalDragGestureRecognizer extends _DragGestureRecognizer { }) : super(router: router, onStart: onStart, onUpdate: onUpdate, onEnd: onEnd); double get _initialPendingDragDelta => 0.0; - double _getDragDelta(ui.PointerEvent event) => event.dx; + double _getDragDelta(PointerInputEvent event) => event.dx; bool get _hasSufficientPendingDragDeltaToAccept => _pendingDragDelta.abs() > kTouchSlop; } @@ -146,7 +147,7 @@ class PanGestureRecognizer extends _DragGestureRecognizer { }) : super(router: router, onStart: onStart, onUpdate: onUpdate, onEnd: onEnd); ui.Offset get _initialPendingDragDelta => ui.Offset.zero; - ui.Offset _getDragDelta(ui.PointerEvent event) => new ui.Offset(event.dx, event.dy); + ui.Offset _getDragDelta(PointerInputEvent event) => new ui.Offset(event.dx, event.dy); bool get _hasSufficientPendingDragDeltaToAccept { return _pendingDragDelta.distance > kPanSlop; } diff --git a/packages/flutter/lib/src/gestures/events.dart b/packages/flutter/lib/src/gestures/events.dart new file mode 100644 index 0000000000..664a519b52 --- /dev/null +++ b/packages/flutter/lib/src/gestures/events.dart @@ -0,0 +1,114 @@ +import 'dart:ui' as ui; + +/// Dart-layer version of ui.Event +class InputEvent { + + InputEvent({ this.type }) : timeStamp = 0.0; + + factory InputEvent.fromSkyEvent(ui.Event event) { + if (event is ui.PointerEvent) + return new PointerInputEvent.fromUiEvent(event); + + // Default event + InputEvent result = new InputEvent(); + result.type = event.type; + result.timeStamp = event.timeStamp; + } + + String type; + double timeStamp; +} + +/// Dart-layer version of ui.PointerInputEvent +class PointerInputEvent extends InputEvent { + + // Map actual input pointer value to a unique value + // Since events are serialized we can just use a counter + static Map _pointerMap = new Map(); + static int _pointerCount = 0; + + PointerInputEvent({ + String type, + this.pointer, + this.kind, + this.x, + this.y, + this.dx, + this.dy, + this.buttons, + this.down, + this.primary, + this.obscured, + this.pressure, + this.pressureMin, + this.pressureMax, + this.distance, + this.distanceMin, + this.distanceMax, + this.radiusMajor, + this.radiusMinor, + this.radiusMin, + this.radiusMax, + this.orientation, + this.tilt + }) : super(type: type); + + PointerInputEvent.fromUiEvent(ui.PointerEvent event) { + type = event.type; + timeStamp = event.timeStamp; + + if (type == 'pointerdown') { + pointer = _pointerCount; + _pointerMap[event.pointer] = _pointerCount; + _pointerCount++; + } else { + pointer = _pointerMap[event.pointer]; + } + + kind = event.kind; + x = event.x; + y = event.y; + dx = event.dx; + dy = event.dy; + buttons = event.buttons; + down = event.down; + primary = event.primary; + obscured = event.obscured; + pressure = event.pressure; + pressureMin = event.pressureMin; + pressureMax = event.pressureMax; + distance = event.distance; + distanceMin = event.distanceMin; + distanceMax = event.distanceMax; + radiusMajor = event.radiusMajor; + radiusMinor = event.radiusMinor; + radiusMin = event.radiusMin; + radiusMax = event.radiusMax; + orientation = event.orientation; + tilt = event.tilt; + + } + + int pointer; + String kind; + double x; + double y; + double dx; + double dy; + int buttons; + bool down; + bool primary; + bool obscured; + double pressure; + double pressureMin; + double pressureMax; + double distance; + double distanceMin; + double distanceMax; + double radiusMajor; + double radiusMinor; + double radiusMin; + double radiusMax; + double orientation; + double tilt; +} diff --git a/packages/flutter/lib/src/gestures/long_press.dart b/packages/flutter/lib/src/gestures/long_press.dart index 4dd278601b..2db0483772 100644 --- a/packages/flutter/lib/src/gestures/long_press.dart +++ b/packages/flutter/lib/src/gestures/long_press.dart @@ -2,10 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ui' as ui; - import 'arena.dart'; import 'constants.dart'; +import 'events.dart'; import 'pointer_router.dart'; import 'recognizer.dart'; @@ -22,7 +21,7 @@ class LongPressGestureRecognizer extends PrimaryPointerGestureRecognizer { onLongPress(); } - void handlePrimaryPointer(ui.PointerEvent event) { + void handlePrimaryPointer(PointerInputEvent event) { if (event.type == 'pointerup') resolve(GestureDisposition.rejected); } diff --git a/packages/flutter/lib/src/gestures/pointer_router.dart b/packages/flutter/lib/src/gestures/pointer_router.dart index d774bb1b5e..7af85a24c4 100644 --- a/packages/flutter/lib/src/gestures/pointer_router.dart +++ b/packages/flutter/lib/src/gestures/pointer_router.dart @@ -2,18 +2,18 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ui' as ui; +import 'package:flutter/src/gestures/events.dart'; -/// A callback that receives a [ui.PointerEvent] -typedef void PointerRoute(ui.PointerEvent event); +/// A callback that receives a [PointerInputEvent] +typedef void PointerRoute(PointerInputEvent event); -/// A routing table for [ui.PointerEvent] events. +/// A routing table for [PointerInputEvent] events. class PointerRouter { final Map> _routeMap = new Map>(); /// Adds a route to the routing table /// - /// Whenever this object routes a [ui.PointerEvent] corresponding to + /// Whenever this object routes a [PointerInputEvent] corresponding to /// pointer, call route. void addRoute(int pointer, PointerRoute route) { List routes = _routeMap.putIfAbsent(pointer, () => new List()); @@ -23,7 +23,7 @@ class PointerRouter { /// Removes a route from the routing table /// - /// No longer call route when routing a [ui.PointerEvent] corresponding to + /// No longer call route when routing a [PointerInputEvent] corresponding to /// pointer. Requires that this route was previously added to the router. void removeRoute(int pointer, PointerRoute route) { assert(_routeMap.containsKey(pointer)); @@ -37,7 +37,7 @@ class PointerRouter { /// Call the routes registed for this pointer event. /// /// Calls the routes in the order in which they were added to the route. - void route(ui.PointerEvent event) { + void route(PointerInputEvent event) { List routes = _routeMap[event.pointer]; if (routes == null) return; diff --git a/packages/flutter/lib/src/gestures/recognizer.dart b/packages/flutter/lib/src/gestures/recognizer.dart index 9adcb3d90a..93bc2d85be 100644 --- a/packages/flutter/lib/src/gestures/recognizer.dart +++ b/packages/flutter/lib/src/gestures/recognizer.dart @@ -7,6 +7,7 @@ import 'dart:ui' as ui; import 'arena.dart'; import 'constants.dart'; +import 'events.dart'; import 'pointer_router.dart'; export 'pointer_router.dart' show PointerRouter; @@ -22,9 +23,9 @@ abstract class GestureRecognizer extends GestureArenaMember { final Set _trackedPointers = new Set(); /// The primary entry point for users of this class. - void addPointer(ui.PointerEvent event); + void addPointer(PointerInputEvent event); - void handleEvent(ui.PointerEvent event); + void handleEvent(PointerInputEvent event); void acceptGesture(int pointer) { } void rejectGesture(int pointer) { } void didStopTrackingLastPointer(int pointer); @@ -58,7 +59,7 @@ abstract class GestureRecognizer extends GestureArenaMember { didStopTrackingLastPointer(pointer); } - void stopTrackingIfPointerNoLongerDown(ui.PointerEvent event) { + void stopTrackingIfPointerNoLongerDown(PointerInputEvent event) { if (event.type == 'pointerup' || event.type == 'pointercancel') stopTrackingPointer(event.pointer); } @@ -71,7 +72,7 @@ enum GestureRecognizerState { defunct } -ui.Point _getPoint(ui.PointerEvent event) { +ui.Point _getPoint(PointerInputEvent event) { return new ui.Point(event.x, event.y); } @@ -86,7 +87,7 @@ abstract class PrimaryPointerGestureRecognizer extends GestureRecognizer { ui.Point initialPosition; Timer _timer; - void addPointer(ui.PointerEvent event) { + void addPointer(PointerInputEvent event) { startTrackingPointer(event.pointer); if (state == GestureRecognizerState.ready) { state = GestureRecognizerState.possible; @@ -97,7 +98,7 @@ abstract class PrimaryPointerGestureRecognizer extends GestureRecognizer { } } - void handleEvent(ui.PointerEvent event) { + void handleEvent(PointerInputEvent event) { assert(state != GestureRecognizerState.ready); if (state == GestureRecognizerState.possible && event.pointer == primaryPointer) { // TODO(abarth): Maybe factor the slop handling out into a separate class? @@ -110,7 +111,7 @@ abstract class PrimaryPointerGestureRecognizer extends GestureRecognizer { } /// Override to provide behavior for the primary pointer when the gesture is still possible. - void handlePrimaryPointer(ui.PointerEvent event); + void handlePrimaryPointer(PointerInputEvent event); /// Override to be notified with [deadline] is exceeded. /// @@ -143,7 +144,7 @@ abstract class PrimaryPointerGestureRecognizer extends GestureRecognizer { } } - double _getDistance(ui.PointerEvent event) { + double _getDistance(PointerInputEvent event) { ui.Offset offset = _getPoint(event) - initialPosition; return offset.distance; } diff --git a/packages/flutter/lib/src/gestures/scale.dart b/packages/flutter/lib/src/gestures/scale.dart index 8898f6ec78..7e2f53a159 100644 --- a/packages/flutter/lib/src/gestures/scale.dart +++ b/packages/flutter/lib/src/gestures/scale.dart @@ -7,6 +7,7 @@ import 'dart:ui' as ui; import 'arena.dart'; import 'recognizer.dart'; import 'constants.dart'; +import 'events.dart'; enum ScaleState { ready, @@ -35,7 +36,7 @@ class ScaleGestureRecognizer extends GestureRecognizer { double get _scaleFactor => _initialSpan > 0.0 ? _currentSpan / _initialSpan : 1.0; - void addPointer(ui.PointerEvent event) { + void addPointer(PointerInputEvent event) { startTrackingPointer(event.pointer); if (_state == ScaleState.ready) { _state = ScaleState.possible; @@ -45,7 +46,7 @@ class ScaleGestureRecognizer extends GestureRecognizer { } } - void handleEvent(ui.PointerEvent event) { + void handleEvent(PointerInputEvent event) { assert(_state != ScaleState.ready); bool configChanged = false; switch(event.type) { diff --git a/packages/flutter/lib/src/gestures/show_press.dart b/packages/flutter/lib/src/gestures/show_press.dart index d3602c2f69..18ee1ca595 100644 --- a/packages/flutter/lib/src/gestures/show_press.dart +++ b/packages/flutter/lib/src/gestures/show_press.dart @@ -2,10 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ui' as ui; - import 'arena.dart'; import 'constants.dart'; +import 'events.dart'; import 'recognizer.dart'; typedef void GestureShowPressCallback(); @@ -23,7 +22,7 @@ class ShowPressGestureRecognizer extends PrimaryPointerGestureRecognizer { onShowPress(); } - void handlePrimaryPointer(ui.PointerEvent event) { + void handlePrimaryPointer(PointerInputEvent event) { if (event.type == 'pointerup') resolve(GestureDisposition.rejected); } diff --git a/packages/flutter/lib/src/gestures/tap.dart b/packages/flutter/lib/src/gestures/tap.dart index 5d028a842b..16ee90f081 100644 --- a/packages/flutter/lib/src/gestures/tap.dart +++ b/packages/flutter/lib/src/gestures/tap.dart @@ -2,9 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ui' as ui; - import 'arena.dart'; +import 'events.dart'; import 'recognizer.dart'; typedef void GestureTapCallback(); @@ -17,7 +16,7 @@ class TapGestureRecognizer extends PrimaryPointerGestureRecognizer { GestureTapCallback onTapDown; GestureTapCallback onTapCancel; - void handlePrimaryPointer(ui.PointerEvent event) { + void handlePrimaryPointer(PointerInputEvent event) { if (event.type == 'pointerdown') { if (onTapDown != null) onTapDown(); diff --git a/packages/flutter/lib/src/material/ink_well.dart b/packages/flutter/lib/src/material/ink_well.dart index 4780f7579d..161be19e5e 100644 --- a/packages/flutter/lib/src/material/ink_well.dart +++ b/packages/flutter/lib/src/material/ink_well.dart @@ -137,7 +137,7 @@ class _RenderInkWell extends RenderProxyBox { TapGestureRecognizer _tap; LongPressGestureRecognizer _longPress; - void handleEvent(ui.Event event, BoxHitTestEntry entry) { + void handleEvent(InputEvent event, BoxHitTestEntry entry) { if (event.type == 'pointerdown' && (_tap != null || _longPress != null)) { _tap?.addPointer(event); _longPress?.addPointer(event); diff --git a/packages/flutter/lib/src/material/material_app.dart b/packages/flutter/lib/src/material/material_app.dart index 06fa88f3cf..04b3087bd6 100644 --- a/packages/flutter/lib/src/material/material_app.dart +++ b/packages/flutter/lib/src/material/material_app.dart @@ -2,8 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ui' as ui; - +import 'package:flutter/gestures.dart'; import 'package:flutter/painting.dart'; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; @@ -56,7 +55,7 @@ class _MaterialAppState extends State { super.dispose(); } - void _backHandler(ui.Event event) { + void _backHandler(InputEvent event) { assert(mounted); if (event.type == 'back') { NavigatorState navigator = _navigator.currentState; diff --git a/packages/flutter/lib/src/material/switch.dart b/packages/flutter/lib/src/material/switch.dart index c5233fa2a3..9de1a2c203 100644 --- a/packages/flutter/lib/src/material/switch.dart +++ b/packages/flutter/lib/src/material/switch.dart @@ -6,6 +6,7 @@ import 'dart:async'; import 'dart:ui' as ui; import 'package:flutter/painting.dart'; +import 'package:flutter/gestures.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/widgets.dart'; @@ -82,8 +83,8 @@ class _RenderSwitch extends RenderToggleable { RadialReaction _radialReaction; - void handleEvent(ui.Event event, BoxHitTestEntry entry) { - if (event is ui.PointerEvent) { + void handleEvent(InputEvent event, BoxHitTestEntry entry) { + if (event is PointerInputEvent) { if (event.type == 'pointerdown') _showRadialReaction(entry.localPosition); else if (event.type == 'pointerup') diff --git a/packages/flutter/lib/src/rendering/binding.dart b/packages/flutter/lib/src/rendering/binding.dart index 7de8a4ebe7..f34caaa50a 100644 --- a/packages/flutter/lib/src/rendering/binding.dart +++ b/packages/flutter/lib/src/rendering/binding.dart @@ -29,7 +29,7 @@ class _PointerState { Point lastPosition; } -typedef void EventListener(ui.Event event); +typedef void EventListener(InputEvent event); /// A hit test entry used by [FlutterBinding] class BindingHitTestEntry extends HitTestEntry { @@ -95,11 +95,12 @@ class FlutterBinding extends HitTestTarget { bool removeEventListener(EventListener listener) => _eventListeners.remove(listener); void _handleEvent(ui.Event event) { - if (event is ui.PointerEvent) { - _handlePointerEvent(event); + InputEvent ourEvent = new InputEvent.fromSkyEvent(event); + if (ourEvent is PointerInputEvent) { + _handlePointerInputEvent(ourEvent); } else { for (EventListener listener in _eventListeners) - listener(event); + listener(ourEvent); } } @@ -111,7 +112,7 @@ class FlutterBinding extends HitTestTarget { /// to hit-test them on each movement. Map _stateForPointer = new Map(); - void _handlePointerEvent(ui.PointerEvent event) { + void _handlePointerInputEvent(PointerInputEvent event) { Point position = new Point(event.x, event.y); _PointerState state = _stateForPointer[event.pointer]; @@ -155,15 +156,15 @@ class FlutterBinding extends HitTestTarget { } /// Dispatch the given event to the path of the given hit test result - void dispatchEvent(ui.Event event, HitTestResult result) { + void dispatchEvent(InputEvent event, HitTestResult result) { assert(result != null); for (HitTestEntry entry in result.path) entry.target.handleEvent(event, entry); } - void handleEvent(ui.Event e, BindingHitTestEntry entry) { - if (e is ui.PointerEvent) { - ui.PointerEvent event = e; + void handleEvent(InputEvent e, BindingHitTestEntry entry) { + if (e is PointerInputEvent) { + PointerInputEvent event = e; pointerRouter.route(event); if (event.type == 'pointerdown') GestureArena.instance.close(event.pointer); diff --git a/packages/flutter/lib/src/rendering/hit_test.dart b/packages/flutter/lib/src/rendering/hit_test.dart index 6103624010..12396b1a13 100644 --- a/packages/flutter/lib/src/rendering/hit_test.dart +++ b/packages/flutter/lib/src/rendering/hit_test.dart @@ -2,12 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ui' as ui; +import 'package:flutter/gestures.dart'; /// An object that can handle events. abstract class HitTestTarget { /// Override this function to receive events. - void handleEvent(ui.Event event, HitTestEntry entry); + void handleEvent(InputEvent event, HitTestEntry entry); } /// Data collected during a hit test about a specific [HitTestTarget]. diff --git a/packages/flutter/lib/src/rendering/object.dart b/packages/flutter/lib/src/rendering/object.dart index 7b9c0a1b3d..94b6c3b687 100644 --- a/packages/flutter/lib/src/rendering/object.dart +++ b/packages/flutter/lib/src/rendering/object.dart @@ -7,6 +7,7 @@ import 'dart:ui' as ui; import 'dart:ui' show Point, Offset, Size, Rect, Color, Paint, Path; import 'package:flutter/animation.dart'; +import 'package:flutter/gestures.dart'; import 'package:vector_math/vector_math_64.dart'; import 'debug.dart'; @@ -1071,7 +1072,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { // EVENTS /// Override this function to handle events that hit this render object - void handleEvent(ui.Event event, HitTestEntry entry) { + void handleEvent(InputEvent event, HitTestEntry entry) { } diff --git a/packages/flutter/lib/src/rendering/proxy_box.dart b/packages/flutter/lib/src/rendering/proxy_box.dart index 6bb775f7ce..02619505cc 100644 --- a/packages/flutter/lib/src/rendering/proxy_box.dart +++ b/packages/flutter/lib/src/rendering/proxy_box.dart @@ -5,6 +5,7 @@ import 'dart:ui' as ui; import 'package:flutter/painting.dart'; +import 'package:flutter/gestures.dart'; import 'package:vector_math/vector_math_64.dart'; import 'box.dart'; @@ -1054,7 +1055,7 @@ class RenderCustomPaint extends RenderProxyBox { } } -typedef void PointerEventListener(ui.PointerEvent e); +typedef void PointerEventListener(PointerInputEvent e); /// Invokes the callbacks in response to pointer events. class RenderPointerListener extends RenderProxyBox { @@ -1071,7 +1072,7 @@ class RenderPointerListener extends RenderProxyBox { PointerEventListener onPointerUp; PointerEventListener onPointerCancel; - void handleEvent(ui.Event event, HitTestEntry entry) { + void handleEvent(InputEvent event, HitTestEntry entry) { if (onPointerDown != null && event.type == 'pointerdown') return onPointerDown(event); if (onPointerMove != null && event.type == 'pointermove') diff --git a/packages/flutter/lib/src/rendering/toggleable.dart b/packages/flutter/lib/src/rendering/toggleable.dart index 959eba22cd..f6e7879993 100644 --- a/packages/flutter/lib/src/rendering/toggleable.dart +++ b/packages/flutter/lib/src/rendering/toggleable.dart @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ui' as ui; - import 'package:flutter/animation.dart'; import 'package:flutter/gestures.dart'; @@ -37,7 +35,7 @@ abstract class RenderToggleable extends RenderConstrainedBox { double get position => _performance.value; - void handleEvent(ui.Event event, BoxHitTestEntry entry) { + void handleEvent(InputEvent event, BoxHitTestEntry entry) { if (event.type == 'pointerdown') _tap.addPointer(event); } diff --git a/packages/flutter/lib/src/widgets/drag_target.dart b/packages/flutter/lib/src/widgets/drag_target.dart index e0f9ce5d37..6de530d648 100644 --- a/packages/flutter/lib/src/widgets/drag_target.dart +++ b/packages/flutter/lib/src/widgets/drag_target.dart @@ -3,9 +3,9 @@ // found in the LICENSE file. import 'dart:collection'; -import 'dart:ui' as ui; import 'package:flutter/animation.dart'; +import 'package:flutter/gestures.dart'; import 'package:flutter/rendering.dart'; import 'basic.dart'; @@ -69,7 +69,7 @@ class Draggable extends StatefulComponent { class _DraggableState extends State { DragRoute _route; - void _startDrag(ui.PointerEvent event) { + void _startDrag(PointerInputEvent event) { if (_route != null) return; // TODO(ianh): once we switch to using gestures, just hand the gesture to the route so it can do everything itself. then we can have multiple drags at the same time. final Point point = new Point(event.x, event.y); @@ -97,7 +97,7 @@ class _DraggableState extends State { config.navigator.push(_route); } - void _updateDrag(ui.PointerEvent event) { + void _updateDrag(PointerInputEvent event) { if (_route != null) { config.navigator.setState(() { _route.update(new Point(event.x, event.y)); @@ -105,14 +105,14 @@ class _DraggableState extends State { } } - void _cancelDrag(ui.PointerEvent event) { + void _cancelDrag(PointerInputEvent event) { if (_route != null) { config.navigator.popRoute(_route, DragEndKind.canceled); assert(_route == null); } } - void _drop(ui.PointerEvent event) { + void _drop(PointerInputEvent event) { if (_route != null) { _route.update(new Point(event.x, event.y)); config.navigator.popRoute(_route, DragEndKind.dropped); diff --git a/packages/flutter/lib/src/widgets/gesture_detector.dart b/packages/flutter/lib/src/widgets/gesture_detector.dart index 534148ae4a..5862ee3c43 100644 --- a/packages/flutter/lib/src/widgets/gesture_detector.dart +++ b/packages/flutter/lib/src/widgets/gesture_detector.dart @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ui' as ui; - import 'package:flutter/gestures.dart'; import 'package:flutter/rendering.dart'; @@ -187,7 +185,7 @@ class _GestureDetectorState extends State { return null; } - void _handlePointerDown(ui.PointerEvent event) { + void _handlePointerDown(PointerInputEvent event) { if (_tap != null) _tap.addPointer(event); if (_showPress != null) diff --git a/packages/unit/test/engine/mock_events.dart b/packages/unit/test/engine/mock_events.dart index 53ddc9ea8e..ffb8befab9 100644 --- a/packages/unit/test/engine/mock_events.dart +++ b/packages/unit/test/engine/mock_events.dart @@ -1,64 +1,9 @@ import 'dart:ui' as ui; +import 'package:flutter/gestures.dart'; + export 'dart:ui' show Point; -class TestPointerEvent extends ui.PointerEvent { - TestPointerEvent({ - this.type, - this.pointer, - this.kind, - this.x, - this.y, - this.dx, - this.dy, - this.velocityX, - this.velocityY, - this.buttons, - this.down, - this.primary, - this.obscured, - this.pressure, - this.pressureMin, - this.pressureMax, - this.distance, - this.distanceMin, - this.distanceMax, - this.radiusMajor, - this.radiusMinor, - this.radiusMin, - this.radiusMax, - this.orientation, - this.tilt - }); - - // These are all of the PointerEvent members, but not all of Event. - String type; - int pointer; - String kind; - double x; - double y; - double dx; - double dy; - double velocityX; - double velocityY; - int buttons; - bool down; - bool primary; - bool obscured; - double pressure; - double pressureMin; - double pressureMax; - double distance; - double distanceMin; - double distanceMax; - double radiusMajor; - double radiusMinor; - double radiusMin; - double radiusMax; - double orientation; - double tilt; -} - class TestPointer { TestPointer([ this.pointer = 1 ]); @@ -66,11 +11,11 @@ class TestPointer { bool isDown = false; ui.Point location; - ui.PointerEvent down([ui.Point newLocation = ui.Point.origin ]) { + PointerInputEvent down([ui.Point newLocation = ui.Point.origin ]) { assert(!isDown); isDown = true; location = newLocation; - return new TestPointerEvent( + return new PointerInputEvent( type: 'pointerdown', pointer: pointer, x: location.x, @@ -78,11 +23,11 @@ class TestPointer { ); } - ui.PointerEvent move([ui.Point newLocation = ui.Point.origin ]) { + PointerInputEvent move([ui.Point newLocation = ui.Point.origin ]) { assert(isDown); ui.Offset delta = newLocation - location; location = newLocation; - return new TestPointerEvent( + return new PointerInputEvent( type: 'pointermove', pointer: pointer, x: newLocation.x, @@ -92,10 +37,10 @@ class TestPointer { ); } - ui.PointerEvent up() { + PointerInputEvent up() { assert(isDown); isDown = false; - return new TestPointerEvent( + return new PointerInputEvent( type: 'pointerup', pointer: pointer, x: location.x, @@ -103,10 +48,10 @@ class TestPointer { ); } - ui.PointerEvent cancel() { + PointerInputEvent cancel() { assert(isDown); isDown = false; - return new TestPointerEvent( + return new PointerInputEvent( type: 'pointercancel', pointer: pointer, x: location.x, diff --git a/packages/unit/test/gestures/long_press_test.dart b/packages/unit/test/gestures/long_press_test.dart index 8fb8022dcc..133901f9fc 100644 --- a/packages/unit/test/gestures/long_press_test.dart +++ b/packages/unit/test/gestures/long_press_test.dart @@ -2,16 +2,14 @@ import 'package:quiver/testing/async.dart'; import 'package:flutter/gestures.dart'; import 'package:test/test.dart'; -import '../engine/mock_events.dart'; - -final TestPointerEvent down = new TestPointerEvent( +final PointerInputEvent down = new PointerInputEvent( pointer: 5, type: 'pointerdown', x: 10.0, y: 10.0 ); -final TestPointerEvent up = new TestPointerEvent( +final PointerInputEvent up = new PointerInputEvent( pointer: 5, type: 'pointerup', x: 11.0, diff --git a/packages/unit/test/gestures/pointer_router_test.dart b/packages/unit/test/gestures/pointer_router_test.dart index 65f00838f4..ba3efb9932 100644 --- a/packages/unit/test/gestures/pointer_router_test.dart +++ b/packages/unit/test/gestures/pointer_router_test.dart @@ -1,5 +1,3 @@ -import 'dart:ui' as ui; - import 'package:flutter/gestures.dart'; import 'package:test/test.dart'; @@ -8,7 +6,7 @@ import '../engine/mock_events.dart'; void main() { test('Should route pointers', () { bool callbackRan = false; - void callback(ui.PointerEvent event) { + void callback(PointerInputEvent event) { callbackRan = true; } diff --git a/packages/unit/test/gestures/scale_test.dart b/packages/unit/test/gestures/scale_test.dart index 9acec2c7a3..473d0235ca 100644 --- a/packages/unit/test/gestures/scale_test.dart +++ b/packages/unit/test/gestures/scale_test.dart @@ -36,7 +36,7 @@ void main() { TestPointer pointer1 = new TestPointer(1); - ui.PointerEvent down = pointer1.down(new Point(10.0, 10.0)); + PointerInputEvent down = pointer1.down(new ui.Point(10.0, 10.0)); scale.addPointer(down); tap.addPointer(down); @@ -55,7 +55,7 @@ void main() { expect(didEndScale, isFalse); expect(didTap, isFalse); - router.route(pointer1.move(new Point(20.0, 30.0))); + router.route(pointer1.move(new ui.Point(20.0, 30.0))); expect(didStartScale, isTrue); didStartScale = false; expect(updatedFocalPoint, new ui.Point(20.0, 30.0)); @@ -67,7 +67,7 @@ void main() { // Two-finger scaling TestPointer pointer2 = new TestPointer(2); - ui.PointerEvent down2 = pointer2.down(new Point(10.0, 20.0)); + PointerInputEvent down2 = pointer2.down(new ui.Point(10.0, 20.0)); scale.addPointer(down2); tap.addPointer(down2); GestureArena.instance.close(2); @@ -80,7 +80,7 @@ void main() { expect(didStartScale, isFalse); // Zoom in - router.route(pointer2.move(new Point(0.0, 10.0))); + router.route(pointer2.move(new ui.Point(0.0, 10.0))); expect(didStartScale, isTrue); didStartScale = false; expect(updatedFocalPoint, new ui.Point(10.0, 20.0)); @@ -91,7 +91,7 @@ void main() { expect(didTap, isFalse); // Zoom out - router.route(pointer2.move(new Point(15.0, 25.0))); + router.route(pointer2.move(new ui.Point(15.0, 25.0))); expect(updatedFocalPoint, new ui.Point(17.5, 27.5)); updatedFocalPoint = null; expect(updatedScale, 0.5); @@ -100,7 +100,7 @@ void main() { // Three-finger scaling TestPointer pointer3 = new TestPointer(3); - ui.PointerEvent down3 = pointer3.down(new Point(25.0, 35.0)); + PointerInputEvent down3 = pointer3.down(new ui.Point(25.0, 35.0)); scale.addPointer(down3); tap.addPointer(down3); GestureArena.instance.close(3); @@ -113,7 +113,7 @@ void main() { expect(didStartScale, isFalse); // Zoom in - router.route(pointer3.move(new Point(55.0, 65.0))); + router.route(pointer3.move(new ui.Point(55.0, 65.0))); expect(didStartScale, isTrue); didStartScale = false; expect(updatedFocalPoint, new ui.Point(30.0, 40.0)); @@ -124,9 +124,9 @@ void main() { expect(didTap, isFalse); // Return to original positions but with different fingers - router.route(pointer1.move(new Point(25.0, 35.0))); - router.route(pointer2.move(new Point(20.0, 30.0))); - router.route(pointer3.move(new Point(15.0, 25.0))); + router.route(pointer1.move(new ui.Point(25.0, 35.0))); + router.route(pointer2.move(new ui.Point(20.0, 30.0))); + router.route(pointer3.move(new ui.Point(15.0, 25.0))); expect(didStartScale, isFalse); expect(updatedFocalPoint, new ui.Point(20.0, 30.0)); updatedFocalPoint = null; @@ -144,7 +144,7 @@ void main() { expect(didTap, isFalse); // Continue scaling with two fingers - router.route(pointer3.move(new Point(10.0, 20.0))); + router.route(pointer3.move(new ui.Point(10.0, 20.0))); expect(didStartScale, isTrue); didStartScale = false; expect(updatedFocalPoint, new ui.Point(15.0, 25.0)); @@ -161,7 +161,7 @@ void main() { expect(didTap, isFalse); // Continue panning with one finger - router.route(pointer3.move(new Point(0.0, 0.0))); + router.route(pointer3.move(new ui.Point(0.0, 0.0))); expect(didStartScale, isTrue); didStartScale = false; expect(updatedFocalPoint, new ui.Point(0.0, 0.0)); diff --git a/packages/unit/test/gestures/scroll_test.dart b/packages/unit/test/gestures/scroll_test.dart index e382ab37e5..0fe4f5b04e 100644 --- a/packages/unit/test/gestures/scroll_test.dart +++ b/packages/unit/test/gestures/scroll_test.dart @@ -32,7 +32,7 @@ void main() { }; TestPointer pointer = new TestPointer(5); - ui.PointerEvent down = pointer.down(new Point(10.0, 10.0)); + PointerInputEvent down = pointer.down(new ui.Point(10.0, 10.0)); pan.addPointer(down); tap.addPointer(down); GestureArena.instance.close(5); @@ -47,7 +47,7 @@ void main() { expect(didEndPan, isFalse); expect(didTap, isFalse); - router.route(pointer.move(new Point(20.0, 20.0))); + router.route(pointer.move(new ui.Point(20.0, 20.0))); expect(didStartPan, isTrue); didStartPan = false; expect(updatedScrollDelta, new ui.Offset(10.0, 10.0)); @@ -55,7 +55,7 @@ void main() { expect(didEndPan, isFalse); expect(didTap, isFalse); - router.route(pointer.move(new Point(20.0, 25.0))); + router.route(pointer.move(new ui.Point(20.0, 25.0))); expect(didStartPan, isFalse); expect(updatedScrollDelta, new ui.Offset(0.0, 5.0)); updatedScrollDelta = null; diff --git a/packages/unit/test/gestures/show_press_test.dart b/packages/unit/test/gestures/show_press_test.dart index 6a2005d3a8..d5e5dd5e9f 100644 --- a/packages/unit/test/gestures/show_press_test.dart +++ b/packages/unit/test/gestures/show_press_test.dart @@ -2,16 +2,14 @@ import 'package:quiver/testing/async.dart'; import 'package:flutter/gestures.dart'; import 'package:test/test.dart'; -import '../engine/mock_events.dart'; - -final TestPointerEvent down = new TestPointerEvent( +final PointerInputEvent down = new PointerInputEvent( pointer: 5, type: 'pointerdown', x: 10.0, y: 10.0 ); -final TestPointerEvent up = new TestPointerEvent( +final PointerInputEvent up = new PointerInputEvent( pointer: 5, type: 'pointerup', x: 11.0, diff --git a/packages/unit/test/gestures/tap_test.dart b/packages/unit/test/gestures/tap_test.dart index c41860ca11..a8cf91c9f9 100644 --- a/packages/unit/test/gestures/tap_test.dart +++ b/packages/unit/test/gestures/tap_test.dart @@ -1,8 +1,6 @@ import 'package:flutter/gestures.dart'; import 'package:test/test.dart'; -import '../engine/mock_events.dart'; - void main() { test('Should recognize tap', () { PointerRouter router = new PointerRouter(); @@ -13,7 +11,7 @@ void main() { tapRecognized = true; }; - TestPointerEvent down = new TestPointerEvent( + PointerInputEvent down = new PointerInputEvent( pointer: 5, type: 'pointerdown', x: 10.0, @@ -26,7 +24,7 @@ void main() { router.route(down); expect(tapRecognized, isFalse); - TestPointerEvent up = new TestPointerEvent( + PointerInputEvent up = new PointerInputEvent( pointer: 5, type: 'pointerup', x: 11.0, diff --git a/packages/unit/test/widget/widget_tester.dart b/packages/unit/test/widget/widget_tester.dart index 5d6e57f4bd..dbc599a5e8 100644 --- a/packages/unit/test/widget/widget_tester.dart +++ b/packages/unit/test/widget/widget_tester.dart @@ -1,6 +1,5 @@ -import 'dart:ui' as ui; - import 'package:flutter/animation.dart'; +import 'package:flutter/gestures.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/widgets.dart'; import 'package:quiver/testing/async.dart'; @@ -159,13 +158,13 @@ class WidgetTester { _dispatchEvent(p.up(), result); } - void dispatchEvent(ui.Event event, Point location) { + void dispatchEvent(InputEvent event, Point location) { _dispatchEvent(event, _hitTest(location)); } HitTestResult _hitTest(Point location) => WidgetFlutterBinding.instance.hitTest(location); - void _dispatchEvent(ui.Event event, HitTestResult result) { + void _dispatchEvent(InputEvent event, HitTestResult result) { WidgetFlutterBinding.instance.dispatchEvent(event, result); } From f343b7af07f92bb2316139456a48c3a0553236df Mon Sep 17 00:00:00 2001 From: Jason Simmons Date: Tue, 13 Oct 2015 11:00:54 -0700 Subject: [PATCH 68/84] Update to mojo 1292152bf533de1bfebf5966d6246e149f87add3 --- packages/flutter/lib/src/widgets/editable_text.dart | 2 ++ packages/flutter/pubspec.yaml | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/flutter/lib/src/widgets/editable_text.dart b/packages/flutter/lib/src/widgets/editable_text.dart index 8698c69d12..7e8ca295cd 100644 --- a/packages/flutter/lib/src/widgets/editable_text.dart +++ b/packages/flutter/lib/src/widgets/editable_text.dart @@ -128,6 +128,8 @@ class EditableString implements KeyboardClient { selection = new TextRange(start: start, end: end); onUpdated(); } + + void submit(SubmitAction action) {} } class EditableText extends StatefulComponent { diff --git a/packages/flutter/pubspec.yaml b/packages/flutter/pubspec.yaml index a90aa09089..227716fef9 100644 --- a/packages/flutter/pubspec.yaml +++ b/packages/flutter/pubspec.yaml @@ -6,7 +6,7 @@ homepage: http://flutter.io dependencies: cassowary: '>=0.1.7 <0.2.0' material_design_icons: '>=0.0.3 <0.1.0' - mojo_services: '>=0.2.0 <0.3.0' + mojo_services: '>=0.3.0 <0.4.0' mojo: '>=0.2.0 <0.3.0' newton: '>=0.1.4 <0.2.0' sky_engine: '>=0.0.34 <0.1.0' From 090c37077bb90326ff89efdbed4c0a9597047d2d Mon Sep 17 00:00:00 2001 From: Jason Simmons Date: Tue, 13 Oct 2015 16:07:38 -0700 Subject: [PATCH 69/84] Update imports of skysprites to flutter_sprites --- examples/game/example_effect_line.dart | 2 +- examples/game/lib/game_demo.dart | 2 +- examples/game/lib/main.dart | 2 +- examples/game/test_bed.dart | 2 +- examples/game/test_drawatlas.dart | 2 +- examples/game/test_performance.dart | 2 +- examples/game/test_physics.dart | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/game/example_effect_line.dart b/examples/game/example_effect_line.dart index d6a92af06f..3185eb3610 100644 --- a/examples/game/example_effect_line.dart +++ b/examples/game/example_effect_line.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; -import 'package:skysprites/skysprites.dart'; +import 'package:flutter_sprites/skysprites.dart'; AssetBundle _initBundle() { if (rootBundle != null) diff --git a/examples/game/lib/game_demo.dart b/examples/game/lib/game_demo.dart index ceb7b22c2a..7867b60732 100644 --- a/examples/game/lib/game_demo.dart +++ b/examples/game/lib/game_demo.dart @@ -5,7 +5,7 @@ import 'dart:math' as math; import 'dart:ui' as ui; import 'package:flutter/rendering.dart'; -import 'package:skysprites/skysprites.dart'; +import 'package:flutter_sprites/skysprites.dart'; import 'package:vector_math/vector_math_64.dart'; part 'custom_actions.dart'; diff --git a/examples/game/lib/main.dart b/examples/game/lib/main.dart index 54be5e7c7e..e3f9a5963a 100644 --- a/examples/game/lib/main.dart +++ b/examples/game/lib/main.dart @@ -8,7 +8,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/painting.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/services.dart'; -import 'package:skysprites/skysprites.dart'; +import 'package:flutter_sprites/skysprites.dart'; import 'game_demo.dart'; diff --git a/examples/game/test_bed.dart b/examples/game/test_bed.dart index f63a8c6ca7..c31fe63198 100644 --- a/examples/game/test_bed.dart +++ b/examples/game/test_bed.dart @@ -4,7 +4,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; -import 'package:skysprites/skysprites.dart'; +import 'package:flutter_sprites/skysprites.dart'; AssetBundle _initBundle() { if (rootBundle != null) diff --git a/examples/game/test_drawatlas.dart b/examples/game/test_drawatlas.dart index f49e36dc2c..ff33504984 100644 --- a/examples/game/test_drawatlas.dart +++ b/examples/game/test_drawatlas.dart @@ -4,7 +4,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; -import 'package:skysprites/skysprites.dart'; +import 'package:flutter_sprites/skysprites.dart'; AssetBundle _initBundle() { if (rootBundle != null) diff --git a/examples/game/test_performance.dart b/examples/game/test_performance.dart index 3fddd44d86..5e762c4ec9 100644 --- a/examples/game/test_performance.dart +++ b/examples/game/test_performance.dart @@ -5,7 +5,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; -import 'package:skysprites/skysprites.dart'; +import 'package:flutter_sprites/skysprites.dart'; AssetBundle _initBundle() { if (rootBundle != null) diff --git a/examples/game/test_physics.dart b/examples/game/test_physics.dart index 327b054594..41941770c8 100644 --- a/examples/game/test_physics.dart +++ b/examples/game/test_physics.dart @@ -4,7 +4,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; -import 'package:skysprites/skysprites.dart'; +import 'package:flutter_sprites/skysprites.dart'; AssetBundle _initBundle() { if (rootBundle != null) From a88a85e695f0652b3d73662db8598b868e109bc7 Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Tue, 13 Oct 2015 16:34:01 -0700 Subject: [PATCH 70/84] Rename skysprites to flutter_sprites --- examples/game/example_effect_line.dart | 2 +- examples/game/lib/game_demo.dart | 2 +- examples/game/lib/main.dart | 2 +- examples/game/test_bed.dart | 2 +- examples/game/test_drawatlas.dart | 2 +- examples/game/test_performance.dart | 2 +- examples/game/test_physics.dart | 2 +- packages/flutter_sprites/README.md | 2 +- .../flutter_sprites/lib/flutter_sprites.dart | 48 +++++++++++++++++++ packages/flutter_sprites/lib/skysprites.dart | 48 ------------------- .../flutter_sprites/lib/{ => src}/action.dart | 2 +- .../lib/{ => src}/action_spline.dart | 2 +- .../lib/{ => src}/color_secuence.dart | 2 +- .../lib/{ => src}/constraint.dart | 2 +- .../lib/{ => src}/effect_line.dart | 2 +- .../lib/{ => src}/image_map.dart | 2 +- .../flutter_sprites/lib/{ => src}/label.dart | 2 +- .../flutter_sprites/lib/{ => src}/layer.dart | 2 +- .../flutter_sprites/lib/{ => src}/node.dart | 2 +- .../flutter_sprites/lib/{ => src}/node3d.dart | 2 +- .../lib/{ => src}/node_with_size.dart | 2 +- .../lib/{ => src}/particle_system.dart | 2 +- .../lib/{ => src}/physics_body.dart | 2 +- .../lib/{ => src}/physics_joint.dart | 2 +- .../lib/{ => src}/physics_node.dart | 2 +- .../lib/{ => src}/physics_shape.dart | 2 +- .../flutter_sprites/lib/{ => src}/sound.dart | 2 +- .../lib/{ => src}/sound_manager.dart | 2 +- .../flutter_sprites/lib/{ => src}/sprite.dart | 2 +- .../lib/{ => src}/sprite_box.dart | 2 +- .../lib/{ => src}/sprite_widget.dart | 2 +- .../lib/{ => src}/spritesheet.dart | 2 +- .../lib/{ => src}/texture.dart | 2 +- .../lib/{ => src}/textured_line.dart | 2 +- .../flutter_sprites/lib/{ => src}/util.dart | 2 +- .../lib/{ => src}/virtual_joystick.dart | 2 +- 36 files changed, 82 insertions(+), 82 deletions(-) create mode 100644 packages/flutter_sprites/lib/flutter_sprites.dart delete mode 100644 packages/flutter_sprites/lib/skysprites.dart rename packages/flutter_sprites/lib/{ => src}/action.dart (99%) rename packages/flutter_sprites/lib/{ => src}/action_spline.dart (98%) rename packages/flutter_sprites/lib/{ => src}/color_secuence.dart (99%) rename packages/flutter_sprites/lib/{ => src}/constraint.dart (99%) rename packages/flutter_sprites/lib/{ => src}/effect_line.dart (99%) rename packages/flutter_sprites/lib/{ => src}/image_map.dart (96%) rename packages/flutter_sprites/lib/{ => src}/label.dart (98%) rename packages/flutter_sprites/lib/{ => src}/layer.dart (98%) rename packages/flutter_sprites/lib/{ => src}/node.dart (99%) rename packages/flutter_sprites/lib/{ => src}/node3d.dart (98%) rename packages/flutter_sprites/lib/{ => src}/node_with_size.dart (98%) rename packages/flutter_sprites/lib/{ => src}/particle_system.dart (99%) rename packages/flutter_sprites/lib/{ => src}/physics_body.dart (99%) rename packages/flutter_sprites/lib/{ => src}/physics_joint.dart (99%) rename packages/flutter_sprites/lib/{ => src}/physics_node.dart (99%) rename packages/flutter_sprites/lib/{ => src}/physics_shape.dart (98%) rename packages/flutter_sprites/lib/{ => src}/sound.dart (99%) rename packages/flutter_sprites/lib/{ => src}/sound_manager.dart (99%) rename packages/flutter_sprites/lib/{ => src}/sprite.dart (99%) rename packages/flutter_sprites/lib/{ => src}/sprite_box.dart (99%) rename packages/flutter_sprites/lib/{ => src}/sprite_widget.dart (98%) rename packages/flutter_sprites/lib/{ => src}/spritesheet.dart (98%) rename packages/flutter_sprites/lib/{ => src}/texture.dart (99%) rename packages/flutter_sprites/lib/{ => src}/textured_line.dart (99%) rename packages/flutter_sprites/lib/{ => src}/util.dart (99%) rename packages/flutter_sprites/lib/{ => src}/virtual_joystick.dart (98%) diff --git a/examples/game/example_effect_line.dart b/examples/game/example_effect_line.dart index 3185eb3610..a352103b1a 100644 --- a/examples/game/example_effect_line.dart +++ b/examples/game/example_effect_line.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; -import 'package:flutter_sprites/skysprites.dart'; +import 'package:flutter_sprites/flutter_sprites.dart'; AssetBundle _initBundle() { if (rootBundle != null) diff --git a/examples/game/lib/game_demo.dart b/examples/game/lib/game_demo.dart index 7867b60732..637423d4ea 100644 --- a/examples/game/lib/game_demo.dart +++ b/examples/game/lib/game_demo.dart @@ -5,7 +5,7 @@ import 'dart:math' as math; import 'dart:ui' as ui; import 'package:flutter/rendering.dart'; -import 'package:flutter_sprites/skysprites.dart'; +import 'package:flutter_sprites/flutter_sprites.dart'; import 'package:vector_math/vector_math_64.dart'; part 'custom_actions.dart'; diff --git a/examples/game/lib/main.dart b/examples/game/lib/main.dart index e3f9a5963a..e7497703b7 100644 --- a/examples/game/lib/main.dart +++ b/examples/game/lib/main.dart @@ -8,7 +8,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/painting.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/services.dart'; -import 'package:flutter_sprites/skysprites.dart'; +import 'package:flutter_sprites/flutter_sprites.dart'; import 'game_demo.dart'; diff --git a/examples/game/test_bed.dart b/examples/game/test_bed.dart index c31fe63198..ec1de1f3c4 100644 --- a/examples/game/test_bed.dart +++ b/examples/game/test_bed.dart @@ -4,7 +4,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; -import 'package:flutter_sprites/skysprites.dart'; +import 'package:flutter_sprites/flutter_sprites.dart'; AssetBundle _initBundle() { if (rootBundle != null) diff --git a/examples/game/test_drawatlas.dart b/examples/game/test_drawatlas.dart index ff33504984..f1d854147c 100644 --- a/examples/game/test_drawatlas.dart +++ b/examples/game/test_drawatlas.dart @@ -4,7 +4,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; -import 'package:flutter_sprites/skysprites.dart'; +import 'package:flutter_sprites/flutter_sprites.dart'; AssetBundle _initBundle() { if (rootBundle != null) diff --git a/examples/game/test_performance.dart b/examples/game/test_performance.dart index 5e762c4ec9..fcf25c4efa 100644 --- a/examples/game/test_performance.dart +++ b/examples/game/test_performance.dart @@ -5,7 +5,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; -import 'package:flutter_sprites/skysprites.dart'; +import 'package:flutter_sprites/flutter_sprites.dart'; AssetBundle _initBundle() { if (rootBundle != null) diff --git a/examples/game/test_physics.dart b/examples/game/test_physics.dart index 41941770c8..ecadb2f6f0 100644 --- a/examples/game/test_physics.dart +++ b/examples/game/test_physics.dart @@ -4,7 +4,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; -import 'package:flutter_sprites/skysprites.dart'; +import 'package:flutter_sprites/flutter_sprites.dart'; AssetBundle _initBundle() { if (rootBundle != null) diff --git a/packages/flutter_sprites/README.md b/packages/flutter_sprites/README.md index a3cb2c3c07..a7ebb814a9 100644 --- a/packages/flutter_sprites/README.md +++ b/packages/flutter_sprites/README.md @@ -1,4 +1,4 @@ -# skysprites +# Flutter Sprites A sprite toolkit built on top of Flutter. diff --git a/packages/flutter_sprites/lib/flutter_sprites.dart b/packages/flutter_sprites/lib/flutter_sprites.dart new file mode 100644 index 0000000000..e4e69cb962 --- /dev/null +++ b/packages/flutter_sprites/lib/flutter_sprites.dart @@ -0,0 +1,48 @@ +// 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. + +library flutter_sprites; + +import 'dart:async'; +import 'dart:convert'; +import 'dart:math' as math; +import 'dart:typed_data'; +import 'dart:ui' as ui; + +import 'package:box2d/box2d.dart' as box2d; +import 'package:mojo/core.dart'; +import 'package:sky_services/media/media.mojom.dart'; +import 'package:flutter/animation.dart'; +import 'package:flutter/painting.dart'; +import 'package:flutter/rendering.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter/widgets.dart'; +import 'package:vector_math/vector_math_64.dart'; + +part 'src/action.dart'; +part 'src/action_spline.dart'; +part 'src/color_secuence.dart'; +part 'src/constraint.dart'; +part 'src/effect_line.dart'; +part 'src/image_map.dart'; +part 'src/label.dart'; +part 'src/layer.dart'; +part 'src/node.dart'; +part 'src/node3d.dart'; +part 'src/node_with_size.dart'; +part 'src/particle_system.dart'; +part 'src/physics_body.dart'; +part 'src/physics_joint.dart'; +part 'src/physics_node.dart'; +part 'src/physics_shape.dart'; +part 'src/sound.dart'; +part 'src/sound_manager.dart'; +part 'src/sprite.dart'; +part 'src/spritesheet.dart'; +part 'src/sprite_box.dart'; +part 'src/sprite_widget.dart'; +part 'src/texture.dart'; +part 'src/textured_line.dart'; +part 'src/util.dart'; +part 'src/virtual_joystick.dart'; diff --git a/packages/flutter_sprites/lib/skysprites.dart b/packages/flutter_sprites/lib/skysprites.dart deleted file mode 100644 index 7bdd6274d8..0000000000 --- a/packages/flutter_sprites/lib/skysprites.dart +++ /dev/null @@ -1,48 +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. - -library skysprites; - -import 'dart:async'; -import 'dart:convert'; -import 'dart:math' as math; -import 'dart:typed_data'; -import 'dart:ui' as ui; - -import 'package:box2d/box2d.dart' as box2d; -import 'package:mojo/core.dart'; -import 'package:sky_services/media/media.mojom.dart'; -import 'package:flutter/animation.dart'; -import 'package:flutter/painting.dart'; -import 'package:flutter/rendering.dart'; -import 'package:flutter/services.dart'; -import 'package:flutter/widgets.dart'; -import 'package:vector_math/vector_math_64.dart'; - -part 'action.dart'; -part 'action_spline.dart'; -part 'color_secuence.dart'; -part 'constraint.dart'; -part 'effect_line.dart'; -part 'image_map.dart'; -part 'label.dart'; -part 'layer.dart'; -part 'node.dart'; -part 'node3d.dart'; -part 'node_with_size.dart'; -part 'particle_system.dart'; -part 'physics_body.dart'; -part 'physics_joint.dart'; -part 'physics_node.dart'; -part 'physics_shape.dart'; -part 'sound.dart'; -part 'sound_manager.dart'; -part 'sprite.dart'; -part 'spritesheet.dart'; -part 'sprite_box.dart'; -part 'sprite_widget.dart'; -part 'texture.dart'; -part 'textured_line.dart'; -part 'util.dart'; -part 'virtual_joystick.dart'; diff --git a/packages/flutter_sprites/lib/action.dart b/packages/flutter_sprites/lib/src/action.dart similarity index 99% rename from packages/flutter_sprites/lib/action.dart rename to packages/flutter_sprites/lib/src/action.dart index 01c9486a10..7f867b9073 100644 --- a/packages/flutter_sprites/lib/action.dart +++ b/packages/flutter_sprites/lib/src/action.dart @@ -1,4 +1,4 @@ -part of skysprites; +part of flutter_sprites; typedef void ActionCallback(); diff --git a/packages/flutter_sprites/lib/action_spline.dart b/packages/flutter_sprites/lib/src/action_spline.dart similarity index 98% rename from packages/flutter_sprites/lib/action_spline.dart rename to packages/flutter_sprites/lib/src/action_spline.dart index 1d0e2d105e..c86fb73758 100644 --- a/packages/flutter_sprites/lib/action_spline.dart +++ b/packages/flutter_sprites/lib/src/action_spline.dart @@ -1,4 +1,4 @@ -part of skysprites; +part of flutter_sprites; Point _cardinalSplineAt(Point p0, Point p1, Point p2, Point p3, double tension, double t) { double t2 = t * t; diff --git a/packages/flutter_sprites/lib/color_secuence.dart b/packages/flutter_sprites/lib/src/color_secuence.dart similarity index 99% rename from packages/flutter_sprites/lib/color_secuence.dart rename to packages/flutter_sprites/lib/src/color_secuence.dart index 5bf041b351..a91f63b2a6 100644 --- a/packages/flutter_sprites/lib/color_secuence.dart +++ b/packages/flutter_sprites/lib/src/color_secuence.dart @@ -1,4 +1,4 @@ -part of skysprites; +part of flutter_sprites; /// A sequence of colors representing a gradient or a color transition over /// time. The sequence is represented by a list of [colors] and a list of diff --git a/packages/flutter_sprites/lib/constraint.dart b/packages/flutter_sprites/lib/src/constraint.dart similarity index 99% rename from packages/flutter_sprites/lib/constraint.dart rename to packages/flutter_sprites/lib/src/constraint.dart index 2edb9b0c84..99296cf1d3 100644 --- a/packages/flutter_sprites/lib/constraint.dart +++ b/packages/flutter_sprites/lib/src/constraint.dart @@ -1,4 +1,4 @@ -part of skysprites; +part of flutter_sprites; /// A constraint limits or otherwise controls a [Node]'s properties, such as /// position or rotation. Add a list of constraints by setting the [Node]'s diff --git a/packages/flutter_sprites/lib/effect_line.dart b/packages/flutter_sprites/lib/src/effect_line.dart similarity index 99% rename from packages/flutter_sprites/lib/effect_line.dart rename to packages/flutter_sprites/lib/src/effect_line.dart index 91f0bb67fc..6a48d36030 100644 --- a/packages/flutter_sprites/lib/effect_line.dart +++ b/packages/flutter_sprites/lib/src/effect_line.dart @@ -1,4 +1,4 @@ -part of skysprites; +part of flutter_sprites; enum EffectLineWidthMode { linear, diff --git a/packages/flutter_sprites/lib/image_map.dart b/packages/flutter_sprites/lib/src/image_map.dart similarity index 96% rename from packages/flutter_sprites/lib/image_map.dart rename to packages/flutter_sprites/lib/src/image_map.dart index 6392204ddf..f72fe33941 100644 --- a/packages/flutter_sprites/lib/image_map.dart +++ b/packages/flutter_sprites/lib/src/image_map.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -part of skysprites; +part of flutter_sprites; class ImageMap { ImageMap(AssetBundle bundle) : _bundle = bundle; diff --git a/packages/flutter_sprites/lib/label.dart b/packages/flutter_sprites/lib/src/label.dart similarity index 98% rename from packages/flutter_sprites/lib/label.dart rename to packages/flutter_sprites/lib/src/label.dart index b428c1042c..8f061924c4 100644 --- a/packages/flutter_sprites/lib/label.dart +++ b/packages/flutter_sprites/lib/src/label.dart @@ -1,4 +1,4 @@ -part of skysprites; +part of flutter_sprites; /// Labels are used to display a string of text in a the node tree. To align /// the label, the textAlign property of the [TextStyle] can be set. diff --git a/packages/flutter_sprites/lib/layer.dart b/packages/flutter_sprites/lib/src/layer.dart similarity index 98% rename from packages/flutter_sprites/lib/layer.dart rename to packages/flutter_sprites/lib/src/layer.dart index 3d8b08543c..c1c578fb0a 100644 --- a/packages/flutter_sprites/lib/layer.dart +++ b/packages/flutter_sprites/lib/src/layer.dart @@ -1,4 +1,4 @@ -part of skysprites; +part of flutter_sprites; /// A [Node] that provides an intermediate rendering surface in the sprite /// rendering tree. A [Layer] can be used to change the opacity, color, or to diff --git a/packages/flutter_sprites/lib/node.dart b/packages/flutter_sprites/lib/src/node.dart similarity index 99% rename from packages/flutter_sprites/lib/node.dart rename to packages/flutter_sprites/lib/src/node.dart index 0896b9c123..e3151585a7 100644 --- a/packages/flutter_sprites/lib/node.dart +++ b/packages/flutter_sprites/lib/src/node.dart @@ -1,4 +1,4 @@ -part of skysprites; +part of flutter_sprites; double convertDegrees2Radians(double degrees) => degrees * math.PI/180.8; diff --git a/packages/flutter_sprites/lib/node3d.dart b/packages/flutter_sprites/lib/src/node3d.dart similarity index 98% rename from packages/flutter_sprites/lib/node3d.dart rename to packages/flutter_sprites/lib/src/node3d.dart index c3e26b09a1..40fb629c28 100644 --- a/packages/flutter_sprites/lib/node3d.dart +++ b/packages/flutter_sprites/lib/src/node3d.dart @@ -1,4 +1,4 @@ -part of skysprites; +part of flutter_sprites; /// An node that transforms its children using a 3D perspective projection. This /// node type can be used to create 3D flips and other similar effects. diff --git a/packages/flutter_sprites/lib/node_with_size.dart b/packages/flutter_sprites/lib/src/node_with_size.dart similarity index 98% rename from packages/flutter_sprites/lib/node_with_size.dart rename to packages/flutter_sprites/lib/src/node_with_size.dart index 8c7371b834..3380a44037 100644 --- a/packages/flutter_sprites/lib/node_with_size.dart +++ b/packages/flutter_sprites/lib/src/node_with_size.dart @@ -1,4 +1,4 @@ -part of skysprites; +part of flutter_sprites; /// The super class of any [Node] that has a size. /// diff --git a/packages/flutter_sprites/lib/particle_system.dart b/packages/flutter_sprites/lib/src/particle_system.dart similarity index 99% rename from packages/flutter_sprites/lib/particle_system.dart rename to packages/flutter_sprites/lib/src/particle_system.dart index e7b8d1d458..c3b256dc14 100644 --- a/packages/flutter_sprites/lib/particle_system.dart +++ b/packages/flutter_sprites/lib/src/particle_system.dart @@ -1,4 +1,4 @@ -part of skysprites; +part of flutter_sprites; class _Particle { Vector2 pos; diff --git a/packages/flutter_sprites/lib/physics_body.dart b/packages/flutter_sprites/lib/src/physics_body.dart similarity index 99% rename from packages/flutter_sprites/lib/physics_body.dart rename to packages/flutter_sprites/lib/src/physics_body.dart index 40ee242c0f..0517d7b702 100644 --- a/packages/flutter_sprites/lib/physics_body.dart +++ b/packages/flutter_sprites/lib/src/physics_body.dart @@ -1,4 +1,4 @@ -part of skysprites; +part of flutter_sprites; enum PhysicsBodyType { static, diff --git a/packages/flutter_sprites/lib/physics_joint.dart b/packages/flutter_sprites/lib/src/physics_joint.dart similarity index 99% rename from packages/flutter_sprites/lib/physics_joint.dart rename to packages/flutter_sprites/lib/src/physics_joint.dart index f71ae5414d..262bb227c9 100644 --- a/packages/flutter_sprites/lib/physics_joint.dart +++ b/packages/flutter_sprites/lib/src/physics_joint.dart @@ -1,4 +1,4 @@ -part of skysprites; +part of flutter_sprites; typedef void PhysicsJointBreakCallback(PhysicsJoint joint); diff --git a/packages/flutter_sprites/lib/physics_node.dart b/packages/flutter_sprites/lib/src/physics_node.dart similarity index 99% rename from packages/flutter_sprites/lib/physics_node.dart rename to packages/flutter_sprites/lib/src/physics_node.dart index 5496662f9b..2f0a43acfc 100644 --- a/packages/flutter_sprites/lib/physics_node.dart +++ b/packages/flutter_sprites/lib/src/physics_node.dart @@ -1,4 +1,4 @@ -part of skysprites; +part of flutter_sprites; enum PhysicsContactType { preSolve, diff --git a/packages/flutter_sprites/lib/physics_shape.dart b/packages/flutter_sprites/lib/src/physics_shape.dart similarity index 98% rename from packages/flutter_sprites/lib/physics_shape.dart rename to packages/flutter_sprites/lib/src/physics_shape.dart index 657b85d1ec..4a98d39eec 100644 --- a/packages/flutter_sprites/lib/physics_shape.dart +++ b/packages/flutter_sprites/lib/src/physics_shape.dart @@ -1,4 +1,4 @@ -part of skysprites; +part of flutter_sprites; abstract class PhysicsShape { diff --git a/packages/flutter_sprites/lib/sound.dart b/packages/flutter_sprites/lib/src/sound.dart similarity index 99% rename from packages/flutter_sprites/lib/sound.dart rename to packages/flutter_sprites/lib/src/sound.dart index 902bbb5ee6..378f87c533 100644 --- a/packages/flutter_sprites/lib/sound.dart +++ b/packages/flutter_sprites/lib/src/sound.dart @@ -1,4 +1,4 @@ -part of skysprites; +part of flutter_sprites; // TODO: The sound effects should probably use Android's SoundPool instead of // MediaPlayer as it is more efficient and flexible for playing back sound effects diff --git a/packages/flutter_sprites/lib/sound_manager.dart b/packages/flutter_sprites/lib/src/sound_manager.dart similarity index 99% rename from packages/flutter_sprites/lib/sound_manager.dart rename to packages/flutter_sprites/lib/src/sound_manager.dart index 4c0b328686..01bd5b0cbd 100644 --- a/packages/flutter_sprites/lib/sound_manager.dart +++ b/packages/flutter_sprites/lib/src/sound_manager.dart @@ -1,4 +1,4 @@ -part of skysprites; +part of flutter_sprites; enum SoundFadeMode { crossFade, diff --git a/packages/flutter_sprites/lib/sprite.dart b/packages/flutter_sprites/lib/src/sprite.dart similarity index 99% rename from packages/flutter_sprites/lib/sprite.dart rename to packages/flutter_sprites/lib/src/sprite.dart index f1d30a63db..3a532f42dc 100644 --- a/packages/flutter_sprites/lib/sprite.dart +++ b/packages/flutter_sprites/lib/src/sprite.dart @@ -1,4 +1,4 @@ -part of skysprites; +part of flutter_sprites; /// A Sprite is a [Node] that renders a bitmap image to the screen. class Sprite extends NodeWithSize with SpritePaint { diff --git a/packages/flutter_sprites/lib/sprite_box.dart b/packages/flutter_sprites/lib/src/sprite_box.dart similarity index 99% rename from packages/flutter_sprites/lib/sprite_box.dart rename to packages/flutter_sprites/lib/src/sprite_box.dart index 8c1d06be33..18b2b8b326 100644 --- a/packages/flutter_sprites/lib/sprite_box.dart +++ b/packages/flutter_sprites/lib/src/sprite_box.dart @@ -1,4 +1,4 @@ -part of skysprites; +part of flutter_sprites; /// Options for setting up a [SpriteBox]. /// diff --git a/packages/flutter_sprites/lib/sprite_widget.dart b/packages/flutter_sprites/lib/src/sprite_widget.dart similarity index 98% rename from packages/flutter_sprites/lib/sprite_widget.dart rename to packages/flutter_sprites/lib/src/sprite_widget.dart index a1068f5044..4c71605831 100644 --- a/packages/flutter_sprites/lib/sprite_widget.dart +++ b/packages/flutter_sprites/lib/src/sprite_widget.dart @@ -1,4 +1,4 @@ -part of skysprites; +part of flutter_sprites; /// A widget that uses a [SpriteBox] to render a sprite node tree to the screen. class SpriteWidget extends OneChildRenderObjectWidget { diff --git a/packages/flutter_sprites/lib/spritesheet.dart b/packages/flutter_sprites/lib/src/spritesheet.dart similarity index 98% rename from packages/flutter_sprites/lib/spritesheet.dart rename to packages/flutter_sprites/lib/src/spritesheet.dart index cbf3b50701..3fb116a9e5 100644 --- a/packages/flutter_sprites/lib/spritesheet.dart +++ b/packages/flutter_sprites/lib/src/spritesheet.dart @@ -1,4 +1,4 @@ -part of skysprites; +part of flutter_sprites; /// A sprite sheet packs a number of smaller images into a single large image. /// diff --git a/packages/flutter_sprites/lib/texture.dart b/packages/flutter_sprites/lib/src/texture.dart similarity index 99% rename from packages/flutter_sprites/lib/texture.dart rename to packages/flutter_sprites/lib/src/texture.dart index f690ae2f28..129bb9830e 100644 --- a/packages/flutter_sprites/lib/texture.dart +++ b/packages/flutter_sprites/lib/src/texture.dart @@ -1,4 +1,4 @@ -part of skysprites; +part of flutter_sprites; /// A texture represents a rectangular area of an image and is typically used to draw a sprite to the screen. /// diff --git a/packages/flutter_sprites/lib/textured_line.dart b/packages/flutter_sprites/lib/src/textured_line.dart similarity index 99% rename from packages/flutter_sprites/lib/textured_line.dart rename to packages/flutter_sprites/lib/src/textured_line.dart index d35d960b4b..3bf96404ce 100644 --- a/packages/flutter_sprites/lib/textured_line.dart +++ b/packages/flutter_sprites/lib/src/textured_line.dart @@ -1,4 +1,4 @@ -part of skysprites; +part of flutter_sprites; class TexturedLine extends Node { TexturedLine(List points, List colors, List widths, [Texture texture, List textureStops]) { diff --git a/packages/flutter_sprites/lib/util.dart b/packages/flutter_sprites/lib/src/util.dart similarity index 99% rename from packages/flutter_sprites/lib/util.dart rename to packages/flutter_sprites/lib/src/util.dart index 0cb740cd7e..5dbd940385 100644 --- a/packages/flutter_sprites/lib/util.dart +++ b/packages/flutter_sprites/lib/src/util.dart @@ -1,4 +1,4 @@ -part of skysprites; +part of flutter_sprites; math.Random _random = new math.Random(); diff --git a/packages/flutter_sprites/lib/virtual_joystick.dart b/packages/flutter_sprites/lib/src/virtual_joystick.dart similarity index 98% rename from packages/flutter_sprites/lib/virtual_joystick.dart rename to packages/flutter_sprites/lib/src/virtual_joystick.dart index 1977f9f863..c08495e440 100644 --- a/packages/flutter_sprites/lib/virtual_joystick.dart +++ b/packages/flutter_sprites/lib/src/virtual_joystick.dart @@ -1,4 +1,4 @@ -part of skysprites; +part of flutter_sprites; class VirtualJoystick extends NodeWithSize { VirtualJoystick() : super(new Size(160.0, 160.0)) { From 6529f54c0897c905a7bdae15ede9b47d4bf9a6ba Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Tue, 13 Oct 2015 16:52:01 -0700 Subject: [PATCH 71/84] Rev pub packages --- packages/flutter/pubspec.yaml | 8 ++++---- packages/flutter_sprites/pubspec.yaml | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/flutter/pubspec.yaml b/packages/flutter/pubspec.yaml index a90aa09089..293b5ce561 100644 --- a/packages/flutter/pubspec.yaml +++ b/packages/flutter/pubspec.yaml @@ -1,5 +1,5 @@ name: flutter -version: 0.0.3 +version: 0.0.4 author: Flutter Authors description: A framework for writing Flutter applications homepage: http://flutter.io @@ -9,9 +9,9 @@ dependencies: mojo_services: '>=0.2.0 <0.3.0' mojo: '>=0.2.0 <0.3.0' newton: '>=0.1.4 <0.2.0' - sky_engine: '>=0.0.34 <0.1.0' - sky_services: '>=0.0.34 <0.1.0' - sky_tools: '>=0.0.18 <0.1.0' + sky_engine: '>=0.0.35 <0.1.0' + sky_services: '>=0.0.35 <0.1.0' + sky_tools: '>=0.0.20 <0.1.0' vector_math: '>=1.4.3 <2.0.0' intl: '>=0.12.4+2 <0.13.0' environment: diff --git a/packages/flutter_sprites/pubspec.yaml b/packages/flutter_sprites/pubspec.yaml index 4e1035b28e..a95f819395 100644 --- a/packages/flutter_sprites/pubspec.yaml +++ b/packages/flutter_sprites/pubspec.yaml @@ -4,6 +4,6 @@ version: 0.0.2 author: Flutter Authors homepage: http://flutter.io dependencies: - flutter: ">=0.0.3 <0.1.0" - sky_tools: ">=0.0.18 <0.1.0" + flutter: ">=0.0.4 <0.1.0" + sky_tools: ">=0.0.20 <0.1.0" box2d: ">=0.2.0 <0.3.0" From 9f74a178fd81272693abced6cce0a0fff08bf3c8 Mon Sep 17 00:00:00 2001 From: Kris Giesing Date: Tue, 13 Oct 2015 16:57:40 -0700 Subject: [PATCH 72/84] Address comments --- packages/flutter/lib/src/gestures/events.dart | 136 +++++++++--------- .../lib/src/gestures/pointer_router.dart | 2 +- .../flutter/lib/src/rendering/binding.dart | 2 +- packages/unit/test/gestures/scale_test.dart | 24 ++-- 4 files changed, 83 insertions(+), 81 deletions(-) diff --git a/packages/flutter/lib/src/gestures/events.dart b/packages/flutter/lib/src/gestures/events.dart index 664a519b52..30298389e4 100644 --- a/packages/flutter/lib/src/gestures/events.dart +++ b/packages/flutter/lib/src/gestures/events.dart @@ -1,25 +1,27 @@ import 'dart:ui' as ui; -/// Dart-layer version of ui.Event +/// Base class for input events. class InputEvent { - InputEvent({ this.type }) : timeStamp = 0.0; + const InputEvent({ this.type, this.timeStamp: 0.0 }); - factory InputEvent.fromSkyEvent(ui.Event event) { + factory InputEvent.fromUiEvent(ui.Event event) { if (event is ui.PointerEvent) return new PointerInputEvent.fromUiEvent(event); // Default event - InputEvent result = new InputEvent(); - result.type = event.type; - result.timeStamp = event.timeStamp; + return new InputEvent( + type: event.type, + timeStamp: event.timeStamp + ); } - String type; - double timeStamp; + final String type; + final double timeStamp; + } -/// Dart-layer version of ui.PointerInputEvent +/// Input event class PointerInputEvent extends InputEvent { // Map actual input pointer value to a unique value @@ -27,8 +29,9 @@ class PointerInputEvent extends InputEvent { static Map _pointerMap = new Map(); static int _pointerCount = 0; - PointerInputEvent({ + const PointerInputEvent({ String type, + double timeStamp: 0.0, this.pointer, this.kind, this.x, @@ -51,64 +54,63 @@ class PointerInputEvent extends InputEvent { this.radiusMax, this.orientation, this.tilt - }) : super(type: type); - - PointerInputEvent.fromUiEvent(ui.PointerEvent event) { - type = event.type; - timeStamp = event.timeStamp; - - if (type == 'pointerdown') { - pointer = _pointerCount; - _pointerMap[event.pointer] = _pointerCount; - _pointerCount++; - } else { - pointer = _pointerMap[event.pointer]; - } - - kind = event.kind; - x = event.x; - y = event.y; - dx = event.dx; - dy = event.dy; - buttons = event.buttons; - down = event.down; - primary = event.primary; - obscured = event.obscured; - pressure = event.pressure; - pressureMin = event.pressureMin; - pressureMax = event.pressureMax; - distance = event.distance; - distanceMin = event.distanceMin; - distanceMax = event.distanceMax; - radiusMajor = event.radiusMajor; - radiusMinor = event.radiusMinor; - radiusMin = event.radiusMin; - radiusMax = event.radiusMax; - orientation = event.orientation; - tilt = event.tilt; + }) : super(type: type, timeStamp: timeStamp); + factory PointerInputEvent.fromUiEvent(ui.PointerEvent event) { + PointerInputEvent result = new PointerInputEvent( + type: event.type, + timeStamp: event.timeStamp, + pointer: (event.type == 'pointerDown') ? _pointerCount : _pointerMap[event.pointer], + kind: event.kind, + x: event.x, + y: event.y, + dx: event.dx, + dy: event.dy, + buttons: event.buttons, + down: event.down, + primary: event.primary, + obscured: event.obscured, + pressure: event.pressure, + pressureMin: event.pressureMin, + pressureMax: event.pressureMax, + distance: event.distance, + distanceMin: event.distanceMin, + distanceMax: event.distanceMax, + radiusMajor: event.radiusMajor, + radiusMinor: event.radiusMinor, + radiusMin: event.radiusMin, + radiusMax: event.radiusMax, + orientation: event.orientation, + tilt: event.tilt + ); + if (event.type == 'pointerdown') { + _pointerMap[event.pointer] = _pointerCount; + _pointerCount++; + } + return result; } - int pointer; - String kind; - double x; - double y; - double dx; - double dy; - int buttons; - bool down; - bool primary; - bool obscured; - double pressure; - double pressureMin; - double pressureMax; - double distance; - double distanceMin; - double distanceMax; - double radiusMajor; - double radiusMinor; - double radiusMin; - double radiusMax; - double orientation; - double tilt; + final int pointer; + final String kind; + final double x; + final double y; + final double dx; + final double dy; + final int buttons; + final bool down; + final bool primary; + final bool obscured; + final double pressure; + final double pressureMin; + final double pressureMax; + final double distance; + final double distanceMin; + final double distanceMax; + final double radiusMajor; + final double radiusMinor; + final double radiusMin; + final double radiusMax; + final double orientation; + final double tilt; + } diff --git a/packages/flutter/lib/src/gestures/pointer_router.dart b/packages/flutter/lib/src/gestures/pointer_router.dart index 7af85a24c4..4e8ab17d82 100644 --- a/packages/flutter/lib/src/gestures/pointer_router.dart +++ b/packages/flutter/lib/src/gestures/pointer_router.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:flutter/src/gestures/events.dart'; +import 'events.dart'; /// A callback that receives a [PointerInputEvent] typedef void PointerRoute(PointerInputEvent event); diff --git a/packages/flutter/lib/src/rendering/binding.dart b/packages/flutter/lib/src/rendering/binding.dart index f34caaa50a..99685d3d34 100644 --- a/packages/flutter/lib/src/rendering/binding.dart +++ b/packages/flutter/lib/src/rendering/binding.dart @@ -95,7 +95,7 @@ class FlutterBinding extends HitTestTarget { bool removeEventListener(EventListener listener) => _eventListeners.remove(listener); void _handleEvent(ui.Event event) { - InputEvent ourEvent = new InputEvent.fromSkyEvent(event); + InputEvent ourEvent = new InputEvent.fromUiEvent(event); if (ourEvent is PointerInputEvent) { _handlePointerInputEvent(ourEvent); } else { diff --git a/packages/unit/test/gestures/scale_test.dart b/packages/unit/test/gestures/scale_test.dart index 473d0235ca..149d14be0a 100644 --- a/packages/unit/test/gestures/scale_test.dart +++ b/packages/unit/test/gestures/scale_test.dart @@ -36,7 +36,7 @@ void main() { TestPointer pointer1 = new TestPointer(1); - PointerInputEvent down = pointer1.down(new ui.Point(10.0, 10.0)); + PointerInputEvent down = pointer1.down(new Point(10.0, 10.0)); scale.addPointer(down); tap.addPointer(down); @@ -55,7 +55,7 @@ void main() { expect(didEndScale, isFalse); expect(didTap, isFalse); - router.route(pointer1.move(new ui.Point(20.0, 30.0))); + router.route(pointer1.move(new Point(20.0, 30.0))); expect(didStartScale, isTrue); didStartScale = false; expect(updatedFocalPoint, new ui.Point(20.0, 30.0)); @@ -67,7 +67,7 @@ void main() { // Two-finger scaling TestPointer pointer2 = new TestPointer(2); - PointerInputEvent down2 = pointer2.down(new ui.Point(10.0, 20.0)); + PointerInputEvent down2 = pointer2.down(new Point(10.0, 20.0)); scale.addPointer(down2); tap.addPointer(down2); GestureArena.instance.close(2); @@ -80,7 +80,7 @@ void main() { expect(didStartScale, isFalse); // Zoom in - router.route(pointer2.move(new ui.Point(0.0, 10.0))); + router.route(pointer2.move(new Point(0.0, 10.0))); expect(didStartScale, isTrue); didStartScale = false; expect(updatedFocalPoint, new ui.Point(10.0, 20.0)); @@ -91,7 +91,7 @@ void main() { expect(didTap, isFalse); // Zoom out - router.route(pointer2.move(new ui.Point(15.0, 25.0))); + router.route(pointer2.move(new Point(15.0, 25.0))); expect(updatedFocalPoint, new ui.Point(17.5, 27.5)); updatedFocalPoint = null; expect(updatedScale, 0.5); @@ -100,7 +100,7 @@ void main() { // Three-finger scaling TestPointer pointer3 = new TestPointer(3); - PointerInputEvent down3 = pointer3.down(new ui.Point(25.0, 35.0)); + PointerInputEvent down3 = pointer3.down(new Point(25.0, 35.0)); scale.addPointer(down3); tap.addPointer(down3); GestureArena.instance.close(3); @@ -113,7 +113,7 @@ void main() { expect(didStartScale, isFalse); // Zoom in - router.route(pointer3.move(new ui.Point(55.0, 65.0))); + router.route(pointer3.move(new Point(55.0, 65.0))); expect(didStartScale, isTrue); didStartScale = false; expect(updatedFocalPoint, new ui.Point(30.0, 40.0)); @@ -124,9 +124,9 @@ void main() { expect(didTap, isFalse); // Return to original positions but with different fingers - router.route(pointer1.move(new ui.Point(25.0, 35.0))); - router.route(pointer2.move(new ui.Point(20.0, 30.0))); - router.route(pointer3.move(new ui.Point(15.0, 25.0))); + router.route(pointer1.move(new Point(25.0, 35.0))); + router.route(pointer2.move(new Point(20.0, 30.0))); + router.route(pointer3.move(new Point(15.0, 25.0))); expect(didStartScale, isFalse); expect(updatedFocalPoint, new ui.Point(20.0, 30.0)); updatedFocalPoint = null; @@ -144,7 +144,7 @@ void main() { expect(didTap, isFalse); // Continue scaling with two fingers - router.route(pointer3.move(new ui.Point(10.0, 20.0))); + router.route(pointer3.move(new Point(10.0, 20.0))); expect(didStartScale, isTrue); didStartScale = false; expect(updatedFocalPoint, new ui.Point(15.0, 25.0)); @@ -161,7 +161,7 @@ void main() { expect(didTap, isFalse); // Continue panning with one finger - router.route(pointer3.move(new ui.Point(0.0, 0.0))); + router.route(pointer3.move(new Point(0.0, 0.0))); expect(didStartScale, isTrue); didStartScale = false; expect(updatedFocalPoint, new ui.Point(0.0, 0.0)); From 02843214839c6ba739508d164e732c6662fa7c9e Mon Sep 17 00:00:00 2001 From: Kris Giesing Date: Tue, 13 Oct 2015 17:32:04 -0700 Subject: [PATCH 73/84] Address more comments --- packages/flutter/lib/src/gestures/events.dart | 34 +++++++++++++------ packages/unit/test/gestures/scroll_test.dart | 6 ++-- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/packages/flutter/lib/src/gestures/events.dart b/packages/flutter/lib/src/gestures/events.dart index 30298389e4..031017b1f2 100644 --- a/packages/flutter/lib/src/gestures/events.dart +++ b/packages/flutter/lib/src/gestures/events.dart @@ -1,3 +1,7 @@ +// 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:ui' as ui; /// Base class for input events. @@ -21,14 +25,9 @@ class InputEvent { } -/// Input event +/// Input event representing a touch or button. class PointerInputEvent extends InputEvent { - // Map actual input pointer value to a unique value - // Since events are serialized we can just use a counter - static Map _pointerMap = new Map(); - static int _pointerCount = 0; - const PointerInputEvent({ String type, double timeStamp: 0.0, @@ -60,7 +59,7 @@ class PointerInputEvent extends InputEvent { PointerInputEvent result = new PointerInputEvent( type: event.type, timeStamp: event.timeStamp, - pointer: (event.type == 'pointerDown') ? _pointerCount : _pointerMap[event.pointer], + pointer: _getPointerValue(event.type, event.pointer), kind: event.kind, x: event.x, y: event.y, @@ -83,13 +82,26 @@ class PointerInputEvent extends InputEvent { orientation: event.orientation, tilt: event.tilt ); - if (event.type == 'pointerdown') { - _pointerMap[event.pointer] = _pointerCount; - _pointerCount++; - } return result; } + // Map actual input pointer value to a unique value + // Since events are serialized we can just use a counter + static Map _pointerMap = new Map(); + static int _pointerCount = 0; + + static int _getPointerValue(String eventType, int pointer) { + int result; + if (eventType == 'pointerdown') { + result = pointer; + _pointerMap[pointer] = _pointerCount; + _pointerCount++; + } else { + result = _pointerMap[pointer]; + } + return result; + } + final int pointer; final String kind; final double x; diff --git a/packages/unit/test/gestures/scroll_test.dart b/packages/unit/test/gestures/scroll_test.dart index 0fe4f5b04e..09a6ccd72d 100644 --- a/packages/unit/test/gestures/scroll_test.dart +++ b/packages/unit/test/gestures/scroll_test.dart @@ -32,7 +32,7 @@ void main() { }; TestPointer pointer = new TestPointer(5); - PointerInputEvent down = pointer.down(new ui.Point(10.0, 10.0)); + PointerInputEvent down = pointer.down(new Point(10.0, 10.0)); pan.addPointer(down); tap.addPointer(down); GestureArena.instance.close(5); @@ -47,7 +47,7 @@ void main() { expect(didEndPan, isFalse); expect(didTap, isFalse); - router.route(pointer.move(new ui.Point(20.0, 20.0))); + router.route(pointer.move(new Point(20.0, 20.0))); expect(didStartPan, isTrue); didStartPan = false; expect(updatedScrollDelta, new ui.Offset(10.0, 10.0)); @@ -55,7 +55,7 @@ void main() { expect(didEndPan, isFalse); expect(didTap, isFalse); - router.route(pointer.move(new ui.Point(20.0, 25.0))); + router.route(pointer.move(new Point(20.0, 25.0))); expect(didStartPan, isFalse); expect(updatedScrollDelta, new ui.Offset(0.0, 5.0)); updatedScrollDelta = null; From 921d432092156058f0ed4421acbb730ac896e019 Mon Sep 17 00:00:00 2001 From: Hans Muller Date: Tue, 13 Oct 2015 09:42:39 -0700 Subject: [PATCH 74/84] Added Painter, ScrollingListPainter, MaterialScrollbarPainter Enabled displaying a scrollbar in ScrollingLists. The scrollbar is painted as an "overlay", i.e. it's painted on top of the scrolling list's visible children. Added an abstract Painter base class that encapsulates a paint method and the renderer that it's attached to. RenderBlockViewport and HomogenousViewport now support an overlayPainter property. If specified, RenderBlockViewport attaches itself to the overlayPainter when it's attached to the rendering tree. RenderBlockViewport now calls overlayPainter.paint() after it has painted its children. Added an abstract ScrollingListPainter class that exposes ScrollingList's state which might be needed for painting. Like its scroll direction and scrollOffset. The ScrollingListPainter is notified when a scroll starts and ends. Defined a Material-specific ScrollingListPainter that renders a scrollbar. The scrollbar thumb is faded in/out when the scroll starts/ends. Added onScrollStart and onScrollEnd listeners to Scrollable. --- examples/widgets/scrollbar.dart | 67 ++++++++++ packages/flutter/lib/material.dart | 1 + .../lib/src/material/scrollbar_painter.dart | 82 ++++++++++++ packages/flutter/lib/src/rendering/block.dart | 27 ++++ .../flutter/lib/src/rendering/object.dart | 21 +++ .../lib/src/widgets/homogeneous_viewport.dart | 7 +- .../flutter/lib/src/widgets/scrollable.dart | 120 ++++++++++++++++-- 7 files changed, 315 insertions(+), 10 deletions(-) create mode 100644 examples/widgets/scrollbar.dart create mode 100644 packages/flutter/lib/src/material/scrollbar_painter.dart diff --git a/examples/widgets/scrollbar.dart b/examples/widgets/scrollbar.dart new file mode 100644 index 0000000000..b488467a24 --- /dev/null +++ b/examples/widgets/scrollbar.dart @@ -0,0 +1,67 @@ +// 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:intl/intl.dart'; +import 'package:flutter/material.dart'; + +class ScrollbarApp extends StatefulComponent { + ScrollbarApp({ this.navigator }); + + final NavigatorState navigator; + + ScrollbarAppState createState() => new ScrollbarAppState(); +} + +class ScrollbarAppState extends State { + final int _itemCount = 20; + final double _itemExtent = 50.0; + final ScrollbarPainter _scrollbarPainter = new ScrollbarPainter(); + + Widget _buildMenu(BuildContext context) { + NumberFormat dd = new NumberFormat("00", "en_US"); + return new ScrollableList( + items: new List.generate(_itemCount, (int i) => i), + itemExtent: _itemExtent, + itemBuilder: (BuildContext _, int i) => new Text('Item ${dd.format(i)}', style: Theme.of(context).text.title), + scrollableListPainter: _scrollbarPainter + ); + } + + Widget build(BuildContext context) { + Widget scrollable = new Container( + margin: new EdgeDims.symmetric(horizontal: 6.0), // TODO(hansmuller) 6.0 should be based on _kScrollbarThumbWidth + child: new Center( + shrinkWrap: ShrinkWrap.both, + child: new Container( + width: 80.0, + height: _itemExtent * 5.0, + child: _buildMenu(context) + ) + ) + ); + + return new Scaffold( + toolBar: new ToolBar(center: new Text('Scrollbar Demo')), + body: new Container( + decoration: new BoxDecoration(backgroundColor: Theme.of(context).primarySwatch[50]), + padding: new EdgeDims.all(12.0), + child: new Center(child: new Card(child: scrollable)) + ) + ); + } +} + +void main() { + runApp(new MaterialApp( + title: 'ScrollbarApp', + theme: new ThemeData( + brightness: ThemeBrightness.light, + primarySwatch: Colors.blue, + accentColor: Colors.redAccent[200] + ), + routes: { + '/': (RouteArguments args) => new ScrollbarApp(navigator: args.navigator), + } + )); +} diff --git a/packages/flutter/lib/material.dart b/packages/flutter/lib/material.dart index e2e50c720c..88adadfc68 100644 --- a/packages/flutter/lib/material.dart +++ b/packages/flutter/lib/material.dart @@ -33,6 +33,7 @@ export 'src/material/progress_indicator.dart'; export 'src/material/radio.dart'; export 'src/material/raised_button.dart'; export 'src/material/scaffold.dart'; +export 'src/material/scrollbar_painter.dart'; export 'src/material/shadows.dart'; export 'src/material/snack_bar.dart'; export 'src/material/switch.dart'; diff --git a/packages/flutter/lib/src/material/scrollbar_painter.dart b/packages/flutter/lib/src/material/scrollbar_painter.dart new file mode 100644 index 0000000000..16b2175553 --- /dev/null +++ b/packages/flutter/lib/src/material/scrollbar_painter.dart @@ -0,0 +1,82 @@ +// 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:async'; +import 'dart:ui' as ui; + +import 'package:flutter/animation.dart'; +import 'package:flutter/rendering.dart'; +import 'package:flutter/widgets.dart'; + +const double _kMinScrollbarThumbLength = 18.0; +const double _kScrollbarThumbGirth = 6.0; +const Duration _kScrollbarThumbFadeDuration = const Duration(milliseconds: 300); + +class ScrollbarPainter extends ScrollableListPainter { + + double _opacity = 0.0; + int get _alpha => (_opacity * 0xFF).round(); + + // TODO(hansmuller): thumb color should come from ThemeData. + Color get thumbColor => const Color(0xFF9E9E9E); + + void paintThumb(PaintingContext context, Rect thumbBounds) { + final Paint paint = new Paint()..color = thumbColor.withAlpha(_alpha); + context.canvas.drawRect(thumbBounds, paint); + } + + void paintScrollbar(PaintingContext context, Offset offset) { + final Rect viewportBounds = offset & viewportSize; + Point thumbOrigin; + Size thumbSize; + + if (isVertical) { + double thumbHeight = viewportBounds.height * viewportBounds.height / contentExtent; + thumbHeight = thumbHeight.clamp(_kMinScrollbarThumbLength, viewportBounds.height); + final double maxThumbTop = viewportBounds.height - thumbHeight; + double thumbTop = (scrollOffset / (contentExtent - viewportBounds.height)) * maxThumbTop; + thumbTop = viewportBounds.top + thumbTop.clamp(0.0, maxThumbTop); + thumbOrigin = new Point(viewportBounds.right - _kScrollbarThumbGirth, thumbTop); + thumbSize = new Size(_kScrollbarThumbGirth, thumbHeight); + } else { + double thumbWidth = viewportBounds.width * viewportBounds.width / contentExtent; + thumbWidth = thumbWidth.clamp(_kMinScrollbarThumbLength, viewportBounds.width); + final double maxThumbLeft = viewportBounds.width - thumbWidth; + double thumbLeft = (scrollOffset / (contentExtent - viewportBounds.width)) * maxThumbLeft; + thumbLeft = viewportBounds.left + thumbLeft.clamp(0.0, maxThumbLeft); + thumbOrigin = new Point(thumbLeft, viewportBounds.height - _kScrollbarThumbGirth); + thumbSize = new Size(thumbWidth, _kScrollbarThumbGirth); + } + + paintThumb(context, thumbOrigin & thumbSize); + } + + void paint(PaintingContext context, Offset offset) { + if (_alpha == 0) + return; + paintScrollbar(context, offset); + } + + ValuePerformance _fade; + + Future scrollStarted() { + _fade ??= new ValuePerformance() + ..duration = _kScrollbarThumbFadeDuration + ..variable = new AnimatedValue(0.0, end: 1.0, curve: ease) + ..addListener(() { + _opacity = _fade.value; + renderer?.markNeedsPaint(); + }); + return _fade.forward(); + } + + Future scrollEnded() { + return _fade.reverse(); + } + + void detach() { + super.detach(); + _fade?.stop(); + } +} diff --git a/packages/flutter/lib/src/rendering/block.dart b/packages/flutter/lib/src/rendering/block.dart index 18745490dc..edbc0eae43 100644 --- a/packages/flutter/lib/src/rendering/block.dart +++ b/packages/flutter/lib/src/rendering/block.dart @@ -237,6 +237,7 @@ class RenderBlockViewport extends RenderBlockBase { ExtentCallback totalExtentCallback, ExtentCallback maxCrossAxisDimensionCallback, ExtentCallback minCrossAxisDimensionCallback, + Painter overlayPainter, BlockDirection direction: BlockDirection.vertical, double itemExtent, double minExtent: 0.0, @@ -246,6 +247,7 @@ class RenderBlockViewport extends RenderBlockBase { _totalExtentCallback = totalExtentCallback, _maxCrossAxisExtentCallback = maxCrossAxisDimensionCallback, _minCrossAxisExtentCallback = minCrossAxisDimensionCallback, + _overlayPainter = overlayPainter, _startOffset = startOffset, super(children: children, direction: direction, itemExtent: itemExtent, minExtent: minExtent); @@ -298,6 +300,27 @@ class RenderBlockViewport extends RenderBlockBase { markNeedsLayout(); } + Painter get overlayPainter => _overlayPainter; + Painter _overlayPainter; + void set overlayPainter(Painter value) { + if (_overlayPainter == value) + return; + _overlayPainter?.detach(); + _overlayPainter = value; + _overlayPainter?.attach(this); + markNeedsPaint(); + } + + void attach() { + super.attach(); + _overlayPainter?.attach(this); + } + + void detach() { + super.detach(); + _overlayPainter?.detach(); + } + /// The offset at which to paint the first child /// /// Note: you can modify this property from within [callback], if necessary. @@ -377,11 +400,15 @@ class RenderBlockViewport extends RenderBlockBase { void paint(PaintingContext context, Offset offset) { context.canvas.save(); + context.canvas.clipRect(offset & size); if (isVertical) defaultPaint(context, offset.translate(0.0, startOffset)); else defaultPaint(context, offset.translate(startOffset, 0.0)); + + overlayPainter?.paint(context, offset); + context.canvas.restore(); } diff --git a/packages/flutter/lib/src/rendering/object.dart b/packages/flutter/lib/src/rendering/object.dart index 7b9c0a1b3d..243779648b 100644 --- a/packages/flutter/lib/src/rendering/object.dart +++ b/packages/flutter/lib/src/rendering/object.dart @@ -394,6 +394,27 @@ class PaintingContext { } +/// An encapsulation of a renderer and a paint() method. +/// +/// A renderer may allow its paint() method to be augmented or redefined by +/// providing a Painter. See for example overlayPainter in BlockViewport. +abstract class Painter { + RenderObject get renderObject => _renderObject; + RenderObject _renderObject; + + void attach(RenderObject renderObject) { + assert(_renderObject == null); + _renderObject = renderObject; + } + + void detach() { + assert(_renderObject != null); + _renderObject = null; + } + + void paint(PaintingContext context, Offset offset); +} + /// An abstract set of layout constraints /// /// Concrete layout models (such as box) will create concrete subclasses to diff --git a/packages/flutter/lib/src/widgets/homogeneous_viewport.dart b/packages/flutter/lib/src/widgets/homogeneous_viewport.dart index 54f33506a2..3ee2735afa 100644 --- a/packages/flutter/lib/src/widgets/homogeneous_viewport.dart +++ b/packages/flutter/lib/src/widgets/homogeneous_viewport.dart @@ -18,7 +18,8 @@ class HomogeneousViewport extends RenderObjectWidget { this.itemExtent, // required this.itemCount, // optional, but you cannot shrink-wrap this class or otherwise use its intrinsic dimensions if you don't specify it this.direction: ScrollDirection.vertical, - this.startOffset: 0.0 + this.startOffset: 0.0, + this.overlayPainter }) : super(key: key) { assert(itemExtent != null); } @@ -29,6 +30,7 @@ class HomogeneousViewport extends RenderObjectWidget { final int itemCount; final ScrollDirection direction; final double startOffset; + final Painter overlayPainter; _HomogeneousViewportElement createElement() => new _HomogeneousViewportElement(this); @@ -70,6 +72,7 @@ class _HomogeneousViewportElement extends RenderObjectElement extends State { return _scrollBehavior; } + GestureDragStartCallback _getDragStartHandler(ScrollDirection direction) { + if (config.scrollDirection != direction || !scrollBehavior.isScrollable) + return null; + return _handleDragStart; + } + GestureDragUpdateCallback _getDragUpdateHandler(ScrollDirection direction) { if (config.scrollDirection != direction || !scrollBehavior.isScrollable) return null; @@ -88,8 +98,10 @@ abstract class ScrollableState extends State { Widget build(BuildContext context) { return new GestureDetector( + onVerticalDragStart: _getDragStartHandler(ScrollDirection.vertical), onVerticalDragUpdate: _getDragUpdateHandler(ScrollDirection.vertical), onVerticalDragEnd: _getDragEndHandler(ScrollDirection.vertical), + onHorizontalDragStart: _getDragStartHandler(ScrollDirection.horizontal), onHorizontalDragUpdate: _getDragUpdateHandler(ScrollDirection.horizontal), onHorizontalDragEnd: _getDragEndHandler(ScrollDirection.horizontal), child: new Listener( @@ -199,12 +211,22 @@ abstract class ScrollableState extends State { return _startToEndAnimation(); } + void dispatchOnScrollStart() { + if (config.onScrollStart != null) + config.onScrollStart(_scrollOffset); + } + // Derived classes can override this method and call super.dispatchOnScroll() void dispatchOnScroll() { if (config.onScroll != null) config.onScroll(_scrollOffset); } + void dispatchOnScrollEnd() { + if (config.onScrollEnd != null) + config.onScrollEnd(_scrollOffset); + } + double _scrollVelocity(ui.Offset velocity) { double scrollVelocity = config.scrollDirection == ScrollDirection.horizontal ? -velocity.dx @@ -216,14 +238,20 @@ abstract class ScrollableState extends State { _animation.stop(); } + void _handleDragStart() { + scheduleMicrotask(dispatchOnScrollStart); + } + void _handleDragUpdate(double delta) { // We negate the delta here because a positive scroll offset moves the // the content up (or to the left) rather than down (or the right). scrollBy(-delta); } - void _handleDragEnd(Offset velocity) { - fling(velocity); + Future _handleDragEnd(Offset velocity) { + return fling(velocity).then((_) { + dispatchOnScrollEnd(); + }); } } @@ -379,6 +407,52 @@ class Block extends StatelessComponent { } } +abstract class ScrollableListPainter extends Painter { + void attach(RenderObject renderObject) { + assert(renderObject is RenderBlockViewport); + super.attach(renderObject); + } + + RenderBlockViewport get renderer => renderObject; + + bool get isVertical => renderer.isVertical; + + Size get viewportSize => renderer.size; + + double get contentExtent => _contentExtent; + double _contentExtent = 0.0; + void set contentExtent (double value) { + assert(value != null); + assert(value >= 0.0); + if (_contentExtent == value) + return; + _contentExtent = value; + renderer?.markNeedsPaint(); + } + + double get scrollOffset => _scrollOffset; + double _scrollOffset = 0.0; + void set scrollOffset (double value) { + assert(value != null); + assert(value >= 0.0 && value <= 1.0); + if (_scrollOffset == value) + return; + _scrollOffset = value; + renderer?.markNeedsPaint(); + } + + /// Called when a scroll starts. Subclasses may override this method to + /// initialize some state or to play an animation. The returned Future should + /// complete when the computation triggered by this method has finished. + Future scrollStarted() => new Future.value(); + + + /// Similar to scrollStarted(). Called when a scroll ends. For fling scrolls + /// "ended" means that the scroll animation either stopped of its own accord + /// or was canceled by the user. + Future scrollEnded() => new Future.value(); +} + /// An optimized scrollable widget for a large number of children that are all /// the same size (extent) in the scrollDirection. For example for /// ScrollDirection.vertical itemExtent is the height of each item. Use this @@ -394,7 +468,8 @@ abstract class ScrollableWidgetList extends Scrollable { double snapAlignmentOffset: 0.0, this.itemsWrap: false, this.itemExtent, - this.padding + this.padding, + this.scrollableListPainter }) : super( key: key, initialScrollOffset: initialScrollOffset, @@ -409,6 +484,7 @@ abstract class ScrollableWidgetList extends Scrollable { final bool itemsWrap; final double itemExtent; final EdgeDims padding; + final ScrollableListPainter scrollableListPainter; } abstract class ScrollableWidgetListState extends ScrollableState { @@ -480,18 +556,40 @@ abstract class ScrollableWidgetListState extends return new EdgeDims.only(top: padding.top, bottom: padding.bottom); } - void _updateScrollBehavior() { - // if you don't call this from build(), you must call it from setState(). + double get _contentExtent { double contentExtent = config.itemExtent * itemCount; if (config.padding != null) contentExtent += _leadingPadding + _trailingPadding; + return contentExtent; + } + + void _updateScrollBehavior() { + // if you don't call this from build(), you must call it from setState(). + if (config.scrollableListPainter != null) + config.scrollableListPainter.contentExtent = _contentExtent; scrollTo(scrollBehavior.updateExtents( - contentExtent: contentExtent, + contentExtent: _contentExtent, containerExtent: _containerExtent, scrollOffset: scrollOffset )); } + void dispatchOnScrollStart() { + super.dispatchOnScrollStart(); + config.scrollableListPainter?.scrollStarted(); + } + + void dispatchOnScroll() { + super.dispatchOnScroll(); + if (config.scrollableListPainter != null) + config.scrollableListPainter.scrollOffset = scrollOffset; + } + + void dispatchOnScrollEnd() { + super.dispatchOnScrollEnd(); + config.scrollableListPainter?.scrollEnded(); + } + Widget buildContent(BuildContext context) { if (itemCount != _previousItemCount) { _previousItemCount = itemCount; @@ -508,7 +606,8 @@ abstract class ScrollableWidgetListState extends itemExtent: config.itemExtent, itemCount: itemCount, direction: config.scrollDirection, - startOffset: scrollOffset - _leadingPadding + startOffset: scrollOffset - _leadingPadding, + overlayPainter: config.scrollableListPainter ) ) ); @@ -541,7 +640,8 @@ class ScrollableList extends ScrollableWidgetList { this.itemBuilder, itemsWrap: false, double itemExtent, - EdgeDims padding + EdgeDims padding, + ScrollableListPainter scrollableListPainter }) : super( key: key, initialScrollOffset: initialScrollOffset, @@ -551,7 +651,9 @@ class ScrollableList extends ScrollableWidgetList { snapAlignmentOffset: snapAlignmentOffset, itemsWrap: itemsWrap, itemExtent: itemExtent, - padding: padding); + padding: padding, + scrollableListPainter: scrollableListPainter + ); final List items; final ItemBuilder itemBuilder; From 7946dc3a3485ee1b044e697d41830e67edc1aa79 Mon Sep 17 00:00:00 2001 From: Hixie Date: Fri, 9 Oct 2015 11:08:13 -0700 Subject: [PATCH 75/84] Write down some unwritten rules of Flutter development. --- examples/widgets/README | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 examples/widgets/README diff --git a/examples/widgets/README b/examples/widgets/README new file mode 100644 index 0000000000..54c151f8bb --- /dev/null +++ b/examples/widgets/README @@ -0,0 +1,12 @@ +Small examples of the Flutter widget framework +============================================== + +To run these, open a terminal in this directory and use the following +command: + +```bash +pub global activate flutter +flutter start --checked -t foo.dart +``` + +...where `foo.dart` is the file you want to run. From 1beda0d6bf9c261841bb2df9c35aebb808a541a3 Mon Sep 17 00:00:00 2001 From: Jason Simmons Date: Wed, 14 Oct 2015 12:20:58 -0700 Subject: [PATCH 76/84] Update the package versions of flutter and flutter_sprites --- packages/flutter/pubspec.yaml | 6 +++--- packages/flutter_sprites/pubspec.yaml | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/flutter/pubspec.yaml b/packages/flutter/pubspec.yaml index fbba750a87..4ea141a4e7 100644 --- a/packages/flutter/pubspec.yaml +++ b/packages/flutter/pubspec.yaml @@ -1,5 +1,5 @@ name: flutter -version: 0.0.4 +version: 0.0.5 author: Flutter Authors description: A framework for writing Flutter applications homepage: http://flutter.io @@ -9,8 +9,8 @@ dependencies: mojo_services: '>=0.3.0 <0.4.0' mojo: '>=0.2.0 <0.3.0' newton: '>=0.1.4 <0.2.0' - sky_engine: '>=0.0.35 <0.1.0' - sky_services: '>=0.0.35 <0.1.0' + sky_engine: 0.0.36 + sky_services: 0.0.36 sky_tools: '>=0.0.20 <0.1.0' vector_math: '>=1.4.3 <2.0.0' intl: '>=0.12.4+2 <0.13.0' diff --git a/packages/flutter_sprites/pubspec.yaml b/packages/flutter_sprites/pubspec.yaml index a95f819395..b1afc598c5 100644 --- a/packages/flutter_sprites/pubspec.yaml +++ b/packages/flutter_sprites/pubspec.yaml @@ -1,9 +1,9 @@ name: flutter_sprites description: A sprite toolkit built on top of Flutter -version: 0.0.2 +version: 0.0.3 author: Flutter Authors homepage: http://flutter.io dependencies: - flutter: ">=0.0.4 <0.1.0" + flutter: ">=0.0.5 <0.1.0" sky_tools: ">=0.0.20 <0.1.0" box2d: ">=0.2.0 <0.3.0" From 29f2a0f2270955b34502e471b82c53b81e291736 Mon Sep 17 00:00:00 2001 From: Viktor Lidholt Date: Wed, 14 Oct 2015 12:58:47 -0700 Subject: [PATCH 77/84] Adds missing sprite physics shapes --- .../lib/src/physics_shape.dart | 76 ++++++++++++++++++- 1 file changed, 75 insertions(+), 1 deletion(-) diff --git a/packages/flutter_sprites/lib/src/physics_shape.dart b/packages/flutter_sprites/lib/src/physics_shape.dart index 4a98d39eec..2669aeb2be 100644 --- a/packages/flutter_sprites/lib/src/physics_shape.dart +++ b/packages/flutter_sprites/lib/src/physics_shape.dart @@ -32,7 +32,6 @@ class PhysicsShapeCircle extends PhysicsShape { } class PhysicsShapePolygon extends PhysicsShape { - PhysicsShapePolygon(this.points); final List points; @@ -53,6 +52,81 @@ class PhysicsShapePolygon extends PhysicsShape { } } +class PhysicsShapeBox extends PhysicsShape { + PhysicsShapeBox( + this.width, + this.height, [ + this.center = Point.origin, + this.rotation = 0.0 + ]); + + final double width; + final double height; + final Point center; + final double rotation; + + box2d.Shape _createB2Shape(PhysicsNode node) { + box2d.PolygonShape shape = new box2d.PolygonShape(); + shape.setAsBox( + width / node.b2WorldToNodeConversionFactor, + height / node.b2WorldToNodeConversionFactor, + new Vector2( + center.x / node.b2WorldToNodeConversionFactor, + center.y / node.b2WorldToNodeConversionFactor + ), + radians(rotation) + ); + return shape; + } +} + +class PhysicsShapeChain extends PhysicsShape { + PhysicsShapeChain(this.points, [this.loop=false]); + + final List points; + final bool loop; + + box2d.Shape _createB2Shape(PhysicsNode node) { + List vectors = []; + for (Point point in points) { + Vector2 vec = new Vector2( + point.x / node.b2WorldToNodeConversionFactor, + point.y / node.b2WorldToNodeConversionFactor + ); + vectors.add(vec); + } + + box2d.ChainShape shape = new box2d.ChainShape(); + if (loop) + shape.createLoop(vectors, vectors.length); + else + shape.createChain(vectors, vectors.length); + return shape; + } +} + +class PhysicsShapeEdge extends PhysicsShape { + PhysicsShapeEdge(this.pointA, this.pointB); + + final Point pointA; + final Point pointB; + + box2d.Shape _createB2Shape(PhysicsNode node) { + box2d.EdgeShape shape = new box2d.EdgeShape(); + shape.set( + new Vector2( + pointA.x / node.b2WorldToNodeConversionFactor, + pointA.y / node.b2WorldToNodeConversionFactor + ), + new Vector2( + pointB.x / node.b2WorldToNodeConversionFactor, + pointB.y / node.b2WorldToNodeConversionFactor + ) + ); + return shape; + } +} + class PhysicsShapeGroup extends PhysicsShape { PhysicsShapeGroup(this.shapes); From 52c1fe5105030458851d5cd475dd14f5ab4ee5e2 Mon Sep 17 00:00:00 2001 From: Kris Giesing Date: Wed, 14 Oct 2015 13:09:51 -0700 Subject: [PATCH 78/84] Refactor to move conversion into the binding class --- packages/flutter/lib/src/gestures/events.dart | 62 +-------- .../flutter/lib/src/rendering/binding.dart | 120 ++++++++++++++---- 2 files changed, 100 insertions(+), 82 deletions(-) diff --git a/packages/flutter/lib/src/gestures/events.dart b/packages/flutter/lib/src/gestures/events.dart index 031017b1f2..722b9984a9 100644 --- a/packages/flutter/lib/src/gestures/events.dart +++ b/packages/flutter/lib/src/gestures/events.dart @@ -2,25 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ui' as ui; - /// Base class for input events. class InputEvent { const InputEvent({ this.type, this.timeStamp: 0.0 }); - factory InputEvent.fromUiEvent(ui.Event event) { - if (event is ui.PointerEvent) - return new PointerInputEvent.fromUiEvent(event); - - // Default event - return new InputEvent( - type: event.type, - timeStamp: event.timeStamp - ); - } - final String type; + // TODO: Should timeStamp be a DateTime object instead of double? + // Some client code (e.g. drag.dart) does math on the time stamp. final double timeStamp; } @@ -55,53 +44,6 @@ class PointerInputEvent extends InputEvent { this.tilt }) : super(type: type, timeStamp: timeStamp); - factory PointerInputEvent.fromUiEvent(ui.PointerEvent event) { - PointerInputEvent result = new PointerInputEvent( - type: event.type, - timeStamp: event.timeStamp, - pointer: _getPointerValue(event.type, event.pointer), - kind: event.kind, - x: event.x, - y: event.y, - dx: event.dx, - dy: event.dy, - buttons: event.buttons, - down: event.down, - primary: event.primary, - obscured: event.obscured, - pressure: event.pressure, - pressureMin: event.pressureMin, - pressureMax: event.pressureMax, - distance: event.distance, - distanceMin: event.distanceMin, - distanceMax: event.distanceMax, - radiusMajor: event.radiusMajor, - radiusMinor: event.radiusMinor, - radiusMin: event.radiusMin, - radiusMax: event.radiusMax, - orientation: event.orientation, - tilt: event.tilt - ); - return result; - } - - // Map actual input pointer value to a unique value - // Since events are serialized we can just use a counter - static Map _pointerMap = new Map(); - static int _pointerCount = 0; - - static int _getPointerValue(String eventType, int pointer) { - int result; - if (eventType == 'pointerdown') { - result = pointer; - _pointerMap[pointer] = _pointerCount; - _pointerCount++; - } else { - result = _pointerMap[pointer]; - } - return result; - } - final int pointer; final String kind; final double x; diff --git a/packages/flutter/lib/src/rendering/binding.dart b/packages/flutter/lib/src/rendering/binding.dart index 99685d3d34..3484b40469 100644 --- a/packages/flutter/lib/src/rendering/binding.dart +++ b/packages/flutter/lib/src/rendering/binding.dart @@ -23,12 +23,6 @@ int _hammingWeight(int value) { return weight; } -class _PointerState { - _PointerState({ this.result, this.lastPosition }); - HitTestResult result; - Point lastPosition; -} - typedef void EventListener(InputEvent event); /// A hit test entry used by [FlutterBinding] @@ -39,6 +33,93 @@ class BindingHitTestEntry extends HitTestEntry { final HitTestResult result; } +/// State used in converting ui.Event to InputEvent +class _PointerState { + _PointerState({ this.pointer, this.lastPosition }); + int pointer; + Point lastPosition; +} + +class _UiEventConverter { + static InputEvent convert(ui.Event event) { + if (event is ui.PointerEvent) + return convertPointerEvent(event); + + // Default event + return new InputEvent( + type: event.type, + timeStamp: event.timeStamp + ); + } + + // Map actual input pointer value to a unique value + // Since events are serialized we can just use a counter + static Map _stateForPointer = new Map(); + static int _pointerCount = 0; + + static PointerInputEvent convertPointerEvent(ui.PointerEvent event) { + Point position = new Point(event.x, event.y); + + _PointerState state = _stateForPointer[event.pointer]; + double dx, dy; + switch (event.type) { + case 'pointerdown': + if (state == null) { + state = new _PointerState(lastPosition: position); + _stateForPointer[event.pointer] = state; + } + state.pointer = _pointerCount; + _pointerCount++; + break; + case 'pointermove': + // state == null means the pointer is hovering + if (state != null) { + dx = position.x - state.lastPosition.x; + dy = position.y - state.lastPosition.y; + state.lastPosition = position; + } + break; + case 'pointerup': + case 'pointercancel': + // state == null indicates spurious events + if (state != null) { + // Only remove the pointer state when the last button has been released. + if (_hammingWeight(event.buttons) <= 1) + _stateForPointer.remove(event.pointer); + } + break; + } + + return new PointerInputEvent( + type: event.type, + timeStamp: event.timeStamp, + pointer: state.pointer, + kind: event.kind, + x: event.x, + y: event.y, + dx: dx, + dy: dy, + buttons: event.buttons, + down: event.down, + primary: event.primary, + obscured: event.obscured, + pressure: event.pressure, + pressureMin: event.pressureMin, + pressureMax: event.pressureMax, + distance: event.distance, + distanceMin: event.distanceMin, + distanceMax: event.distanceMax, + radiusMajor: event.radiusMajor, + radiusMinor: event.radiusMinor, + radiusMin: event.radiusMin, + radiusMax: event.radiusMax, + orientation: event.orientation, + tilt: event.tilt + ); + } + +} + /// The glue between the render tree and the Flutter engine class FlutterBinding extends HitTestTarget { @@ -95,7 +176,7 @@ class FlutterBinding extends HitTestTarget { bool removeEventListener(EventListener listener) => _eventListeners.remove(listener); void _handleEvent(ui.Event event) { - InputEvent ourEvent = new InputEvent.fromUiEvent(event); + InputEvent ourEvent = _UiEventConverter.convert(event); if (ourEvent is PointerInputEvent) { _handlePointerInputEvent(ourEvent); } else { @@ -110,41 +191,36 @@ class FlutterBinding extends HitTestTarget { /// State for all pointers which are currently down. /// We do not track the state of hovering pointers because we need /// to hit-test them on each movement. - Map _stateForPointer = new Map(); + Map _resultForPointer = new Map(); void _handlePointerInputEvent(PointerInputEvent event) { - Point position = new Point(event.x, event.y); - - _PointerState state = _stateForPointer[event.pointer]; + HitTestResult result = _resultForPointer[event.pointer]; switch (event.type) { case 'pointerdown': - if (state == null) { - state = new _PointerState(result: hitTest(position), lastPosition: position); - _stateForPointer[event.pointer] = state; + if (result == null) { + result = hitTest(new Point(event.x, event.y)); + _resultForPointer[event.pointer] = result; } break; case 'pointermove': - if (state == null) { + if (result == null) { // The pointer is hovering, ignore it for now since we don't // know what to do with it yet. return; } - event.dx = position.x - state.lastPosition.x; - event.dy = position.y - state.lastPosition.y; - state.lastPosition = position; break; case 'pointerup': case 'pointercancel': - if (state == null) { + if (result == null) { // This seems to be a spurious event. Ignore it. return; } - // Only remove the pointer state when the last button has been released. + // Only remove the hit test result when the last button has been released. if (_hammingWeight(event.buttons) <= 1) - _stateForPointer.remove(event.pointer); + _resultForPointer.remove(event.pointer); break; } - dispatchEvent(event, state.result); + dispatchEvent(event, result); } /// Determine which [HitTestTarget] objects are located at a given position From 98b83e0cf5e17a476d54c93b4d8a9b0bc969c0f2 Mon Sep 17 00:00:00 2001 From: Jason Simmons Date: Wed, 14 Oct 2015 12:56:18 -0700 Subject: [PATCH 79/84] Implement better synchronization between the state of the input widget and the keyboard IME Also add an input widget API for the keyboard submit button --- packages/flutter/lib/src/material/input.dart | 16 ++++++++++++++-- .../flutter/lib/src/services/keyboard.dart | 12 ++++++++++++ .../lib/src/widgets/editable_text.dart | 19 +++++++++++++------ packages/unit/test/widget/input_test.dart | 4 ++++ 4 files changed, 43 insertions(+), 8 deletions(-) diff --git a/packages/flutter/lib/src/material/input.dart b/packages/flutter/lib/src/material/input.dart index 1322f68473..3102411485 100644 --- a/packages/flutter/lib/src/material/input.dart +++ b/packages/flutter/lib/src/material/input.dart @@ -13,6 +13,7 @@ import 'theme.dart'; export 'package:flutter/services.dart' show KeyboardType; typedef void StringValueChanged(String value); +typedef void StringValueSubmitted(String value); // TODO(eseidel): This isn't right, it's 16px on the bottom: // http://www.google.com/design/spec/components/text-fields.html#text-fields-single-line-text-field @@ -24,7 +25,8 @@ class Input extends Scrollable { this.initialValue: '', this.placeholder, this.onChanged, - this.keyboardType: KeyboardType.TEXT + this.keyboardType: KeyboardType.TEXT, + this.onSubmitted }) : super( key: key, initialScrollOffset: 0.0, @@ -35,6 +37,7 @@ class Input extends Scrollable { final KeyboardType keyboardType; final String placeholder; final StringValueChanged onChanged; + final StringValueSubmitted onSubmitted; _InputState createState() => new _InputState(); } @@ -52,7 +55,8 @@ class _InputState extends ScrollableState { _value = config.initialValue; _editableValue = new EditableString( text: _value, - onUpdated: _handleTextUpdated + onUpdated: _handleTextUpdated, + onSubmitted: _handleTextSubmitted ); } @@ -66,12 +70,20 @@ class _InputState extends ScrollableState { } } + void _handleTextSubmitted() { + if (config.onSubmitted != null) + config.onSubmitted(_value); + } + Widget buildContent(BuildContext context) { ThemeData themeData = Theme.of(context); bool focused = Focus.at(context, config); if (focused && !_keyboardHandle.attached) { _keyboardHandle = keyboard.show(_editableValue.stub, config.keyboardType); + _keyboardHandle.setText(_editableValue.text); + _keyboardHandle.setSelection(_editableValue.selection.start, + _editableValue.selection.end); } else if (!focused && _keyboardHandle.attached) { _keyboardHandle.release(); } diff --git a/packages/flutter/lib/src/services/keyboard.dart b/packages/flutter/lib/src/services/keyboard.dart index 81cd017b32..a56df6a021 100644 --- a/packages/flutter/lib/src/services/keyboard.dart +++ b/packages/flutter/lib/src/services/keyboard.dart @@ -77,6 +77,18 @@ class KeyboardHandle { assert(_keyboard._currentHandle != this); } + void setText(String text) { + assert(_attached); + assert(_keyboard._currentHandle == this); + _keyboard.service.setText(text); + } + + void setSelection(int start, int end) { + assert(_attached); + assert(_keyboard._currentHandle == this); + _keyboard.service.setSelection(start, end); + } + } final Keyboard keyboard = new Keyboard(_KeyboardConnection.instance.keyboardService); diff --git a/packages/flutter/lib/src/widgets/editable_text.dart b/packages/flutter/lib/src/widgets/editable_text.dart index 7e8ca295cd..ac6af86e6a 100644 --- a/packages/flutter/lib/src/widgets/editable_text.dart +++ b/packages/flutter/lib/src/widgets/editable_text.dart @@ -14,6 +14,7 @@ import 'framework.dart'; const _kCursorBlinkHalfPeriod = 500; // milliseconds typedef void StringUpdated(); +typedef void StringSubmitted(); class TextRange { const TextRange({ this.start, this.end }); @@ -32,18 +33,22 @@ class TextRange { } class EditableString implements KeyboardClient { + EditableString({this.text: '', this.onUpdated, this.onSubmitted}) { + assert(onUpdated != null); + assert(onSubmitted != null); + stub = new KeyboardClientStub.unbound()..impl = this; + selection = new TextRange(start: text.length, end: text.length); + } + String text; TextRange composing = const TextRange.empty(); - TextRange selection = const TextRange.empty(); + TextRange selection; final StringUpdated onUpdated; + final StringSubmitted onSubmitted; KeyboardClientStub stub; - EditableString({this.text: '', this.onUpdated}) { - stub = new KeyboardClientStub.unbound()..impl = this; - } - String textBefore(TextRange range) { return text.substring(0, range.start); } @@ -129,7 +134,9 @@ class EditableString implements KeyboardClient { onUpdated(); } - void submit(SubmitAction action) {} + void submit(SubmitAction action) { + onSubmitted(); + } } class EditableText extends StatefulComponent { diff --git a/packages/unit/test/widget/input_test.dart b/packages/unit/test/widget/input_test.dart index 8b1cef06be..3aedb0f36d 100644 --- a/packages/unit/test/widget/input_test.dart +++ b/packages/unit/test/widget/input_test.dart @@ -17,6 +17,10 @@ class MockKeyboard implements KeyboardService { void showByRequest() {} void hide() {} + + void setText(String text) {} + + void setSelection(int start, int end) {} } void main() { From 3c95ce621c88848e4192285ab8990933a04f4ce3 Mon Sep 17 00:00:00 2001 From: Hixie Date: Wed, 14 Oct 2015 15:30:21 -0700 Subject: [PATCH 80/84] Transform alignment For those times where you want to spin something around a point relative to the size of your box, but you don't know the size of your box. --- .../flutter/lib/src/rendering/proxy_box.dart | 58 ++++++++++-- packages/flutter/lib/src/widgets/basic.dart | 7 +- packages/unit/test/widget/transform_test.dart | 91 +++++++++++++++++++ 3 files changed, 148 insertions(+), 8 deletions(-) diff --git a/packages/flutter/lib/src/rendering/proxy_box.dart b/packages/flutter/lib/src/rendering/proxy_box.dart index 02619505cc..d68ec6c8a9 100644 --- a/packages/flutter/lib/src/rendering/proxy_box.dart +++ b/packages/flutter/lib/src/rendering/proxy_box.dart @@ -862,15 +862,41 @@ class RenderDecoratedBox extends RenderProxyBox { String debugDescribeSettings(String prefix) => '${super.debugDescribeSettings(prefix)}${prefix}decoration:\n${_painter.decoration.toString(prefix + " ")}\n'; } +/// An offset that's expressed as a fraction of a Size. +/// +/// FractionalOffset(0.0, 0.0) represents the top left of the Size, +/// FractionalOffset(1.0, 1.0) represents the bottom right of the Size. +class FractionalOffset { + const FractionalOffset(this.x, this.y); + final double x; + final double y; + bool operator ==(dynamic other) { + if (other is! FractionalOffset) + return false; + final FractionalOffset typedOther = other; + return x == typedOther.x && + y == typedOther.y; + } + int get hashCode { + int value = 373; + value = 37 * value + x.hashCode; + value = 37 * value + y.hashCode; + return value; + } +} + /// Applies a transformation before painting its child class RenderTransform extends RenderProxyBox { RenderTransform({ Matrix4 transform, Offset origin, + FractionalOffset alignment, RenderBox child }) : super(child) { assert(transform != null); + assert(alignment == null || (alignment.x != null && alignment.y != null)); this.transform = transform; + this.alignment = alignment; this.origin = origin; } @@ -888,6 +914,20 @@ class RenderTransform extends RenderProxyBox { markNeedsPaint(); } + /// The alignment of the origin, relative to the size of the box. + /// + /// This is equivalent to setting an origin based on the size of the box. + /// If it is specificed at the same time as an offset, both are applied. + FractionalOffset get alignment => _alignment; + FractionalOffset _alignment; + void set alignment (FractionalOffset newAlignment) { + assert(newAlignment == null || (newAlignment.x != null && newAlignment.y != null)); + if (_alignment == newAlignment) + return; + _alignment = newAlignment; + markNeedsPaint(); + } + // Note the lack of a getter for transform because Matrix4 is not immutable Matrix4 _transform; @@ -937,13 +977,19 @@ class RenderTransform extends RenderProxyBox { } Matrix4 get _effectiveTransform { - if (_origin == null) + if (_origin == null && _alignment == null) return _transform; - return new Matrix4 - .identity() - .translate(_origin.dx, _origin.dy) - .multiply(_transform) - .translate(-_origin.dx, -_origin.dy); + Matrix4 result = new Matrix4.identity(); + if (_origin != null) + result.translate(_origin.dx, _origin.dy); + if (_alignment != null) + result.translate(_alignment.x * size.width, _alignment.y * size.height); + result.multiply(_transform); + if (_alignment != null) + result.translate(-_alignment.x * size.width, -_alignment.y * size.height); + if (_origin != null) + result.translate(-_origin.dx, -_origin.dy); + return result; } bool hitTest(HitTestResult result, { Point position }) { diff --git a/packages/flutter/lib/src/widgets/basic.dart b/packages/flutter/lib/src/widgets/basic.dart index 147faf5732..1ef3bd88f4 100644 --- a/packages/flutter/lib/src/widgets/basic.dart +++ b/packages/flutter/lib/src/widgets/basic.dart @@ -23,6 +23,7 @@ export 'package:flutter/rendering.dart' show FlexAlignItems, FlexDirection, FlexJustifyContent, + FractionalOffset, Matrix4, Offset, Paint, @@ -171,19 +172,21 @@ class ClipOval extends OneChildRenderObjectWidget { // POSITIONING AND SIZING NODES class Transform extends OneChildRenderObjectWidget { - Transform({ Key key, this.transform, this.origin, Widget child }) + Transform({ Key key, this.transform, this.origin, this.alignment, Widget child }) : super(key: key, child: child) { assert(transform != null); } final Matrix4 transform; final Offset origin; + final FractionalOffset alignment; - RenderTransform createRenderObject() => new RenderTransform(transform: transform, origin: origin); + RenderTransform createRenderObject() => new RenderTransform(transform: transform, origin: origin, alignment: alignment); void updateRenderObject(RenderTransform renderObject, Transform oldWidget) { renderObject.transform = transform; renderObject.origin = origin; + renderObject.alignment = alignment; } } diff --git a/packages/unit/test/widget/transform_test.dart b/packages/unit/test/widget/transform_test.dart index d9c2a47bb5..efa44cdf45 100644 --- a/packages/unit/test/widget/transform_test.dart +++ b/packages/unit/test/widget/transform_test.dart @@ -48,4 +48,95 @@ void main() { expect(didReceiveTap, isTrue); }); }); + + test('Transform alignment', () { + testWidgets((WidgetTester tester) { + bool didReceiveTap = false; + tester.pumpWidget( + new Stack([ + new Positioned( + top: 100.0, + left: 100.0, + child: new Container( + width: 100.0, + height: 100.0, + decoration: new BoxDecoration( + backgroundColor: new Color(0xFF0000FF) + ) + ) + ), + new Positioned( + top: 100.0, + left: 100.0, + child: new Container( + width: 100.0, + height: 100.0, + child: new Transform( + transform: new Matrix4.identity().scale(0.5, 0.5), + alignment: new FractionalOffset(1.0, 0.5), + child: new GestureDetector( + onTap: () { + didReceiveTap = true; + }, + child: new Container() + ) + ) + ) + ) + ]) + ); + + expect(didReceiveTap, isFalse); + tester.tapAt(new Point(110.0, 110.0)); + expect(didReceiveTap, isFalse); + tester.tapAt(new Point(190.0, 150.0)); + expect(didReceiveTap, isTrue); + }); + }); + + test('Transform offset + alignment', () { + testWidgets((WidgetTester tester) { + bool didReceiveTap = false; + tester.pumpWidget( + new Stack([ + new Positioned( + top: 100.0, + left: 100.0, + child: new Container( + width: 100.0, + height: 100.0, + decoration: new BoxDecoration( + backgroundColor: new Color(0xFF0000FF) + ) + ) + ), + new Positioned( + top: 100.0, + left: 100.0, + child: new Container( + width: 100.0, + height: 100.0, + child: new Transform( + transform: new Matrix4.identity().scale(0.5, 0.5), + origin: new Offset(100.0, 0.0), + alignment: new FractionalOffset(0.0, 0.5), + child: new GestureDetector( + onTap: () { + didReceiveTap = true; + }, + child: new Container() + ) + ) + ) + ) + ]) + ); + + expect(didReceiveTap, isFalse); + tester.tapAt(new Point(110.0, 110.0)); + expect(didReceiveTap, isFalse); + tester.tapAt(new Point(190.0, 150.0)); + expect(didReceiveTap, isTrue); + }); + }); } From c912ee23018276239c78f9855d9cde186453b2ee Mon Sep 17 00:00:00 2001 From: Viktor Lidholt Date: Wed, 14 Oct 2015 16:28:51 -0700 Subject: [PATCH 81/84] Fixes touch handling in SpriteBox --- packages/flutter_sprites/lib/flutter_sprites.dart | 1 + packages/flutter_sprites/lib/src/sprite_box.dart | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/flutter_sprites/lib/flutter_sprites.dart b/packages/flutter_sprites/lib/flutter_sprites.dart index e4e69cb962..38e2e46d2d 100644 --- a/packages/flutter_sprites/lib/flutter_sprites.dart +++ b/packages/flutter_sprites/lib/flutter_sprites.dart @@ -14,6 +14,7 @@ import 'package:box2d/box2d.dart' as box2d; import 'package:mojo/core.dart'; import 'package:sky_services/media/media.mojom.dart'; import 'package:flutter/animation.dart'; +import 'package:flutter/gestures.dart'; import 'package:flutter/painting.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/services.dart'; diff --git a/packages/flutter_sprites/lib/src/sprite_box.dart b/packages/flutter_sprites/lib/src/sprite_box.dart index 18b2b8b326..f2bc2f4db5 100644 --- a/packages/flutter_sprites/lib/src/sprite_box.dart +++ b/packages/flutter_sprites/lib/src/sprite_box.dart @@ -185,11 +185,11 @@ class SpriteBox extends RenderBox { } } - void handleEvent(ui.Event event, _SpriteBoxHitTestEntry entry) { + void handleEvent(InputEvent event, _SpriteBoxHitTestEntry entry) { if (!attached) return; - if (event is ui.PointerEvent) { + if (event is PointerInputEvent) { if (event.type == 'pointerdown') { // Build list of event targets From 5fa5971bf7dfed4d3f5eb456bfc803e74dd123b8 Mon Sep 17 00:00:00 2001 From: Viktor Lidholt Date: Wed, 14 Oct 2015 16:30:36 -0700 Subject: [PATCH 82/84] Refactors sprite physics debug drawing --- .../flutter_sprites/lib/flutter_sprites.dart | 1 + .../lib/src/physics_debug.dart | 97 ++++++++++ .../flutter_sprites/lib/src/physics_node.dart | 167 ++---------------- 3 files changed, 110 insertions(+), 155 deletions(-) create mode 100644 packages/flutter_sprites/lib/src/physics_debug.dart diff --git a/packages/flutter_sprites/lib/flutter_sprites.dart b/packages/flutter_sprites/lib/flutter_sprites.dart index 38e2e46d2d..9db7007a29 100644 --- a/packages/flutter_sprites/lib/flutter_sprites.dart +++ b/packages/flutter_sprites/lib/flutter_sprites.dart @@ -34,6 +34,7 @@ part 'src/node3d.dart'; part 'src/node_with_size.dart'; part 'src/particle_system.dart'; part 'src/physics_body.dart'; +part 'src/physics_debug.dart'; part 'src/physics_joint.dart'; part 'src/physics_node.dart'; part 'src/physics_shape.dart'; diff --git a/packages/flutter_sprites/lib/src/physics_debug.dart b/packages/flutter_sprites/lib/src/physics_debug.dart new file mode 100644 index 0000000000..cc3bc0c618 --- /dev/null +++ b/packages/flutter_sprites/lib/src/physics_debug.dart @@ -0,0 +1,97 @@ +part of flutter_sprites; + +class _PhysicsDebugDraw extends box2d.DebugDraw { + _PhysicsDebugDraw( + box2d.ViewportTransform transform, + this.physicsNode + ) : super(transform); + + PhysicsNode physicsNode; + + PaintingCanvas canvas; + + void drawSegment(Vector2 p1, Vector2 p2, box2d.Color3i color) { + Paint paint = new Paint()..color = _toColor(color); + canvas.drawLine(_toPoint(p1), _toPoint(p2), paint); + } + + void drawSolidPolygon( + List vertices, + int vertexCount, + box2d.Color3i color + ) { + Path path = new Path(); + Point pt = _toPoint(vertices[0]); + path.moveTo(pt.x, pt.y); + for (int i = 1; i < vertexCount; i++) { + pt = _toPoint(vertices[i]); + path.lineTo(pt.x, pt.y); + } + + Paint paint = new Paint()..color = _toColor(color); + canvas.drawPath(path, paint); + } + + void drawCircle(Vector2 center, num radius, box2d.Color3i color, [Vector2 axis]) { + print("drawCircle: $center"); + Paint paint = new Paint() + ..color = _toColor(color) + ..setStyle(ui.PaintingStyle.stroke) + ..strokeWidth = 1.0; + + canvas.drawCircle(_toPoint(center), _scale(radius), paint); + } + + void drawSolidCircle(Vector2 center, num radius, Vector2 axis, box2d.Color3i color) { + Paint paint = new Paint() + ..color = _toColor(color); + + canvas.drawCircle(_toPoint(center), _scale(radius), paint); + } + + void drawPoint(Vector2 point, num radiusOnScreen, box2d.Color3i color) { + drawSolidCircle(point, radiusOnScreen, null, color); + } + + void drawParticles( + List centers, + double radius, + List colors, + int count + ) { + // TODO: Implement + } + + void drawParticlesWireframe( + List centers, + double radius, + List colors, + int count + ) { + // TODO: Implement + } + + void drawTransform(box2d.Transform xf, box2d.Color3i color) { + drawCircle(xf.p, 0.1, color); + // TODO: Improve + } + + void drawStringXY(num x, num y, String s, box2d.Color3i color) { + // TODO: Implement + } + + Color _toColor(box2d.Color3i color) { + return new Color.fromARGB(255, color.x, color.y, color.z); + } + + Point _toPoint(Vector2 vec) { + return new Point( + vec.x * physicsNode.b2WorldToNodeConversionFactor, + vec.y * physicsNode.b2WorldToNodeConversionFactor + ); + } + + double _scale(double value) { + return value * physicsNode.b2WorldToNodeConversionFactor; + } +} diff --git a/packages/flutter_sprites/lib/src/physics_node.dart b/packages/flutter_sprites/lib/src/physics_node.dart index 2f0a43acfc..f95bb2df5a 100644 --- a/packages/flutter_sprites/lib/src/physics_node.dart +++ b/packages/flutter_sprites/lib/src/physics_node.dart @@ -25,6 +25,14 @@ class PhysicsNode extends Node { void _init() { _contactHandler = new _ContactHandler(this); b2World.setContactListener(_contactHandler); + + box2d.ViewportTransform transform = new box2d.ViewportTransform( + new Vector2.zero(), + new Vector2.zero(), + 1.0 + ); + _debugDraw = new _PhysicsDebugDraw(transform, this); + b2World.debugDraw = _debugDraw; } box2d.World b2World; @@ -35,6 +43,8 @@ class PhysicsNode extends Node { List _bodiesScheduledForDestruction = []; + _PhysicsDebugDraw _debugDraw; + double b2WorldToNodeConversionFactor = 10.0; Offset get gravity { @@ -143,161 +153,8 @@ class PhysicsNode extends Node { } void paintDebug(PaintingCanvas canvas) { - Paint shapePaint = new Paint(); - shapePaint.setStyle(ui.PaintingStyle.stroke); - shapePaint.strokeWidth = 1.0; - - for (box2d.Body body = b2World.bodyList; body != null; body = body.getNext()) { - canvas.save(); - - Point point = new Point( - body.position.x * b2WorldToNodeConversionFactor, - body.position.y * b2WorldToNodeConversionFactor); - - canvas.translate(point.x, point.y); - canvas.rotate(body.getAngle()); - - if (body.getType() == box2d.BodyType.DYNAMIC) { - if (body.isAwake()) - shapePaint.color = new Color(0xff00ff00); - else - shapePaint.color = new Color(0xff666666); - } - else if (body.getType() == box2d.BodyType.STATIC) - shapePaint.color = new Color(0xffff0000); - else if (body.getType() == box2d.BodyType.KINEMATIC) - shapePaint.color = new Color(0xffff9900); - - for (box2d.Fixture fixture = body.getFixtureList(); fixture != null; fixture = fixture.getNext()) { - box2d.Shape shape = fixture.getShape(); - - if (shape.shapeType == box2d.ShapeType.CIRCLE) { - box2d.CircleShape circle = shape; - Point cp = new Point( - circle.p.x * b2WorldToNodeConversionFactor, - circle.p.y * b2WorldToNodeConversionFactor - ); - double radius = circle.radius * b2WorldToNodeConversionFactor; - canvas.drawCircle(cp, radius, shapePaint); - } else if (shape.shapeType == box2d.ShapeType.POLYGON) { - box2d.PolygonShape poly = shape; - List points = []; - for (int i = 0; i < poly.getVertexCount(); i++) { - Vector2 vertex = poly.getVertex(i); - Point pt = new Point( - vertex.x * b2WorldToNodeConversionFactor, - vertex.y * b2WorldToNodeConversionFactor - ); - points.add(pt); - } - if (points.length >= 2) { - for (int i = 0; i < points.length; i++) { - canvas.drawLine(points[i], points[(i + 1) % points.length], shapePaint); - } - } - } - } - - canvas.restore(); - - // Draw contacts - for (box2d.ContactEdge edge = body.getContactList(); edge != null; edge = edge.next) { - box2d.Contact contact = edge.contact; - Vector2 cA = new Vector2.zero(); - Vector2 cB = new Vector2.zero(); - - box2d.Fixture fixtureA = contact.fixtureA; - box2d.Fixture fixtureB = contact.fixtureB; - - fixtureA.getAABB(contact.getChildIndexA()).getCenterToOut(cA); - fixtureB.getAABB(contact.getChildIndexB()).getCenterToOut(cB); - - Point p1 = new Point( - cA.x * b2WorldToNodeConversionFactor, - cA.y * b2WorldToNodeConversionFactor - ); - - Point p2 = new Point( - cB.x * b2WorldToNodeConversionFactor, - cB.y * b2WorldToNodeConversionFactor - ); - - shapePaint.color = new Color(0x33ffffff); - canvas.drawLine(p1, p2, shapePaint); - - box2d.WorldManifold worldManifold = new box2d.WorldManifold(); - contact.getWorldManifold(worldManifold); - - shapePaint.color = new Color(0xffffffff); - - for (Vector2 pt in worldManifold.points) { - Point pCenter = new Point( - pt.x * b2WorldToNodeConversionFactor, - pt.y * b2WorldToNodeConversionFactor - ); - Offset offset = new Offset( - worldManifold.normal.x * 5.0, - worldManifold.normal.y * 5.0 - ); - - Point p2 = pCenter + offset; - Point p1 = new Point(pCenter.x - offset.dx, pCenter.y - offset.dy); - canvas.drawLine(p1, p2, shapePaint); - canvas.drawCircle(pCenter, 5.0, shapePaint); - } - } - - // Draw joints - shapePaint.color = new Color(0xff0000ff); - - for (box2d.JointEdge edge = body.getJointList(); edge != null; edge = edge.next) { - box2d.Joint joint = edge.joint; - - // Make sure we only draw each joint once - if (joint.getBodyB() == body) - continue; - - // Get anchor A - Vector2 anchorA = new Vector2.zero(); - joint.getAnchorA(anchorA); - - Point ptAnchorA = new Point( - anchorA.x * b2WorldToNodeConversionFactor, - anchorA.y * b2WorldToNodeConversionFactor - ); - - // Get anchor B - Vector2 anchorB = new Vector2.zero(); - joint.getAnchorB(anchorB); - - Point ptAnchorB = new Point( - anchorB.x * b2WorldToNodeConversionFactor, - anchorB.y * b2WorldToNodeConversionFactor - ); - - // Get body A position - Point ptBodyA = new Point( - joint.getBodyA().position.x * b2WorldToNodeConversionFactor, - joint.getBodyA().position.y * b2WorldToNodeConversionFactor - ); - - Point ptBodyB = new Point( - joint.getBodyB().position.x * b2WorldToNodeConversionFactor, - joint.getBodyB().position.y * b2WorldToNodeConversionFactor - ); - - // Draw the joint depending on type - box2d.JointType type = joint.getType(); - - if (type == box2d.JointType.WELD || type == box2d.JointType.REVOLUTE) { - // Draw weld joint - canvas.drawCircle(ptAnchorA, 5.0, shapePaint); - - canvas.drawLine(ptBodyA, ptAnchorA, shapePaint); - canvas.drawLine(ptAnchorB, ptBodyB, shapePaint); - } - } - } + _debugDraw.canvas = canvas; + b2World.drawDebugData(); } } From c17782569d04ffe4852638a51d0be643a3819b40 Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Wed, 14 Oct 2015 16:33:31 -0700 Subject: [PATCH 83/84] Add a ListItem widget --- packages/flutter/lib/material.dart | 1 + .../flutter/lib/src/material/constants.dart | 5 ++ .../flutter/lib/src/material/list_item.dart | 63 +++++++++++++++++++ 3 files changed, 69 insertions(+) create mode 100644 packages/flutter/lib/src/material/list_item.dart diff --git a/packages/flutter/lib/material.dart b/packages/flutter/lib/material.dart index 88adadfc68..51bcfafe62 100644 --- a/packages/flutter/lib/material.dart +++ b/packages/flutter/lib/material.dart @@ -24,6 +24,7 @@ export 'src/material/icon_button.dart'; export 'src/material/icon.dart'; export 'src/material/ink_well.dart'; export 'src/material/input.dart'; +export 'src/material/list_item.dart'; export 'src/material/material.dart'; export 'src/material/material_app.dart'; export 'src/material/material_button.dart'; diff --git a/packages/flutter/lib/src/material/constants.dart b/packages/flutter/lib/src/material/constants.dart index 6ae28e73ce..9b50a30118 100644 --- a/packages/flutter/lib/src/material/constants.dart +++ b/packages/flutter/lib/src/material/constants.dart @@ -16,6 +16,11 @@ const double kStatusBarHeight = 50.0; const double kToolBarHeight = 56.0; const double kSnackBarHeight = 52.0; +// https://www.google.com/design/spec/layout/metrics-keylines.html#metrics-keylines-keylines-spacing +const double kListTitleHeight = 72.0; +const double kListSubtitleHeight = 48.0; +const double kListItemHeight = 72.0; + const double kMaterialDrawerHeight = 140.0; const double kScrollbarSize = 10.0; const Duration kScrollbarFadeDuration = const Duration(milliseconds: 250); diff --git a/packages/flutter/lib/src/material/list_item.dart b/packages/flutter/lib/src/material/list_item.dart new file mode 100644 index 0000000000..84377c65ef --- /dev/null +++ b/packages/flutter/lib/src/material/list_item.dart @@ -0,0 +1,63 @@ +// 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:flutter/gestures.dart'; +import 'package:flutter/painting.dart'; +import 'package:flutter/widgets.dart'; + +import 'ink_well.dart'; +import 'constants.dart'; + +class ListItem extends StatelessComponent { + ListItem({ + Key key, + this.left, + this.center, + this.right, + this.onTap, + this.onLongPress + }) : super(key: key) { + assert(center != null); + } + + final Widget left; + final Widget center; + final Widget right; + final GestureTapCallback onTap; + final GestureLongPressCallback onLongPress; + + Widget build(BuildContext context) { + List children = new List(); + + if (left != null) { + children.add(new Container( + margin: new EdgeDims.only(right: 16.0), + width: 40.0, + child: left + )); + } + + children.add(new Flexible( + child: center + )); + + if (right != null) { + children.add(new Container( + margin: new EdgeDims.only(left: 8.0), + width: 40.0, + child: right + )); + } + + return new Container( + height: kListItemHeight, + padding: const EdgeDims.symmetric(horizontal: 16.0), + child: new InkWell( + onTap: onTap, + onLongPress: onLongPress, + child: new Row(children) + ) + ); + } +} From 0442b642fe3fc7e9e746b793af95389aa47cf8d3 Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Wed, 14 Oct 2015 21:29:35 -0700 Subject: [PATCH 84/84] Fix TextDecoration.lineThrough We had a typo in our CSS translation. --- packages/flutter/lib/src/painting/text_style.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/flutter/lib/src/painting/text_style.dart b/packages/flutter/lib/src/painting/text_style.dart index dc840cef93..9ca3de29a9 100644 --- a/packages/flutter/lib/src/painting/text_style.dart +++ b/packages/flutter/lib/src/painting/text_style.dart @@ -135,7 +135,7 @@ class TextStyle { TextDecoration.none: 'none', TextDecoration.underline: 'underline', TextDecoration.overline: 'overline', - TextDecoration.lineThrough: 'lineThrough' + TextDecoration.lineThrough: 'line-through' }; return decoration.map((TextDecoration d) => toCSS[d]).join(' '); }