Merge pull request #2434 from johnmccutchan/service_protocol_discovery
Add ServiceProtocolDiscovery with tests
diff --git a/examples/layers/raw/canvas.dart b/examples/layers/raw/canvas.dart
index 7108aaa..bbf861c 100644
--- a/examples/layers/raw/canvas.dart
+++ b/examples/layers/raw/canvas.dart
@@ -69,18 +69,12 @@
ui.Scene composite(ui.Picture picture, ui.Rect paintBounds) {
final double devicePixelRatio = ui.window.devicePixelRatio;
- ui.Rect sceneBounds = new ui.Rect.fromLTWH(
- 0.0,
- 0.0,
- ui.window.size.width * devicePixelRatio,
- ui.window.size.height * devicePixelRatio
- );
Float64List deviceTransform = new Float64List(16)
..[0] = devicePixelRatio
..[5] = devicePixelRatio
..[10] = 1.0
..[15] = 1.0;
- ui.SceneBuilder sceneBuilder = new ui.SceneBuilder(sceneBounds)
+ ui.SceneBuilder sceneBuilder = new ui.SceneBuilder()
..pushTransform(deviceTransform)
..addPicture(ui.Offset.zero, picture)
..pop();
diff --git a/examples/layers/raw/hello_world.dart b/examples/layers/raw/hello_world.dart
index a9f1f3e..d624c28 100644
--- a/examples/layers/raw/hello_world.dart
+++ b/examples/layers/raw/hello_world.dart
@@ -28,7 +28,7 @@
));
final ui.Picture picture = recorder.endRecording();
- final ui.SceneBuilder sceneBuilder = new ui.SceneBuilder(physicalBounds)
+ final ui.SceneBuilder sceneBuilder = new ui.SceneBuilder()
// TODO(abarth): We should be able to add a picture without pushing a
// container layer first.
..pushClipRect(physicalBounds)
diff --git a/examples/layers/raw/spinning_square.dart b/examples/layers/raw/spinning_square.dart
index c4f464a..24b3e73 100644
--- a/examples/layers/raw/spinning_square.dart
+++ b/examples/layers/raw/spinning_square.dart
@@ -36,18 +36,12 @@
// COMPOSITE
final double devicePixelRatio = ui.window.devicePixelRatio;
- ui.Rect sceneBounds = new ui.Rect.fromLTWH(
- 0.0,
- 0.0,
- ui.window.size.width * devicePixelRatio,
- ui.window.size.height * devicePixelRatio
- );
Float64List deviceTransform = new Float64List(16)
..[0] = devicePixelRatio
..[5] = devicePixelRatio
..[10] = 1.0
..[15] = 1.0;
- ui.SceneBuilder sceneBuilder = new ui.SceneBuilder(sceneBounds)
+ ui.SceneBuilder sceneBuilder = new ui.SceneBuilder()
..pushTransform(deviceTransform)
..addPicture(ui.Offset.zero, picture)
..pop();
diff --git a/examples/layers/raw/text.dart b/examples/layers/raw/text.dart
index 24e90fb..d8e431f 100644
--- a/examples/layers/raw/text.dart
+++ b/examples/layers/raw/text.dart
@@ -28,18 +28,12 @@
ui.Scene composite(ui.Picture picture, ui.Rect paintBounds) {
final double devicePixelRatio = ui.window.devicePixelRatio;
- ui.Rect sceneBounds = new ui.Rect.fromLTWH(
- 0.0,
- 0.0,
- ui.window.size.width * devicePixelRatio,
- ui.window.size.height * devicePixelRatio
- );
Float64List deviceTransform = new Float64List(16)
..[0] = devicePixelRatio
..[5] = devicePixelRatio
..[10] = 1.0
..[15] = 1.0;
- ui.SceneBuilder sceneBuilder = new ui.SceneBuilder(sceneBounds)
+ ui.SceneBuilder sceneBuilder = new ui.SceneBuilder()
..pushTransform(deviceTransform)
..addPicture(ui.Offset.zero, picture)
..pop();
diff --git a/examples/layers/raw/touch_input.dart b/examples/layers/raw/touch_input.dart
index aca8938..b8569bf 100644
--- a/examples/layers/raw/touch_input.dart
+++ b/examples/layers/raw/touch_input.dart
@@ -48,12 +48,6 @@
// pixels, which are then scalled by the device pixel ratio before being drawn
// on the screen.
final double devicePixelRatio = ui.window.devicePixelRatio;
- ui.Rect sceneBounds = new ui.Rect.fromLTWH(
- 0.0,
- 0.0,
- ui.window.size.width * devicePixelRatio,
- ui.window.size.height * devicePixelRatio
- );
// This transform scales the x and y coordinates by the devicePixelRatio.
Float64List deviceTransform = new Float64List(16)
@@ -66,7 +60,7 @@
// transform that scale its children by the device pixel ratio. This transform
// lets us paint in "logical" pixels which are converted to device pixels by
// this scaling operation.
- ui.SceneBuilder sceneBuilder = new ui.SceneBuilder(sceneBounds)
+ ui.SceneBuilder sceneBuilder = new ui.SceneBuilder()
..pushTransform(deviceTransform)
..addPicture(ui.Offset.zero, picture)
..pop();
diff --git a/packages/flutter/lib/src/material/popup_menu.dart b/packages/flutter/lib/src/material/popup_menu.dart
index 2effaf7..c6701d4 100644
--- a/packages/flutter/lib/src/material/popup_menu.dart
+++ b/packages/flutter/lib/src/material/popup_menu.dart
@@ -28,7 +28,7 @@
const double _kMenuWidthStep = 56.0;
const double _kMenuScreenPadding = 8.0;
-abstract class PopupMenuEntry<T> extends StatelessComponent {
+abstract class PopupMenuEntry<T> extends StatefulComponent {
PopupMenuEntry({ Key key }) : super(key: key);
double get height;
@@ -41,7 +41,11 @@
final double height;
- Widget build(BuildContext context) => new Divider(height: height);
+ _PopupMenuDividerState createState() => new _PopupMenuDividerState();
+}
+
+class _PopupMenuDividerState extends State<PopupMenuDivider> {
+ Widget build(BuildContext context) => new Divider(height: config.height);
}
class PopupMenuItem<T> extends PopupMenuEntry<T> {
@@ -58,20 +62,31 @@
double get height => _kMenuItemHeight;
+ _PopupMenuItemState<PopupMenuItem<T>> createState() => new _PopupMenuItemState<PopupMenuItem<T>>();
+}
+
+class _PopupMenuItemState<T extends PopupMenuItem> extends State<T> {
+ // Override this to put something else in the menu entry.
+ Widget buildChild() => config.child;
+
+ void onTap() {
+ Navigator.pop(context, config.value);
+ }
+
Widget build(BuildContext context) {
final ThemeData theme = Theme.of(context);
TextStyle style = theme.text.subhead;
- if (!enabled)
+ if (!config.enabled)
style = style.copyWith(color: theme.disabledColor);
Widget item = new DefaultTextStyle(
style: style,
child: new Baseline(
- baseline: height - _kBaselineOffsetFromBottom,
- child: child
+ baseline: config.height - _kBaselineOffsetFromBottom,
+ child: buildChild()
)
);
- if (!enabled) {
+ if (!config.enabled) {
final bool isDark = theme.brightness == ThemeBrightness.dark;
item = new IconTheme(
data: new IconThemeData(opacity: isDark ? 0.5 : 0.38),
@@ -79,11 +94,14 @@
);
}
- return new MergeSemantics(
- child: new Container(
- height: height,
- padding: const EdgeDims.symmetric(horizontal: _kMenuHorizontalPadding),
- child: item
+ return new InkWell(
+ onTap: config.enabled ? onTap : null,
+ child: new MergeSemantics(
+ child: new Container(
+ height: config.height,
+ padding: const EdgeDims.symmetric(horizontal: _kMenuHorizontalPadding),
+ child: item
+ )
)
);
}
@@ -93,19 +111,52 @@
CheckedPopupMenuItem({
Key key,
T value,
- checked: false,
+ this.checked: false,
bool enabled: true,
Widget child
}) : super(
key: key,
value: value,
enabled: enabled,
- child: new ListItem(
- enabled: enabled,
- left: new Icon(icon: checked ? Icons.done : null),
- primary: child
- )
+ child: child
);
+
+ final bool checked;
+
+ _CheckedPopupMenuItemState<T> createState() => new _CheckedPopupMenuItemState<T>();
+}
+
+class _CheckedPopupMenuItemState<T> extends _PopupMenuItemState<CheckedPopupMenuItem<T>> {
+ static const Duration _kFadeDuration = const Duration(milliseconds: 150);
+ AnimationController _controller;
+ Animation<double> get _opacity => _controller.view;
+
+ void initState() {
+ super.initState();
+ _controller = new AnimationController(duration: _kFadeDuration)
+ ..value = config.checked ? 1.0 : 0.0
+ ..addListener(() => setState(() { /* animation changed */ }));
+ }
+
+ void onTap() {
+ // This fades the checkmark in or out when tapped.
+ if (config.checked)
+ _controller.reverse();
+ else
+ _controller.forward();
+ super.onTap();
+ }
+
+ Widget buildChild() {
+ return new ListItem(
+ enabled: config.enabled,
+ left: new FadeTransition(
+ opacity: _opacity,
+ child: new Icon(icon: _controller.isDismissed ? null : Icons.done)
+ ),
+ primary: config.child
+ );
+ }
}
class _PopupMenu<T> extends StatelessComponent {
@@ -127,7 +178,6 @@
parent: route.animation,
curve: new Interval(start, end)
);
- final bool enabled = route.items[i].enabled;
Widget item = route.items[i];
if (route.initialValue != null && route.initialValue == route.items[i].value) {
item = new Container(
@@ -137,10 +187,7 @@
}
children.add(new FadeTransition(
opacity: opacity,
- child: new InkWell(
- onTap: enabled ? () { Navigator.pop(context, route.items[i].value); } : null,
- child: item
- )
+ child: item
));
}
diff --git a/packages/flutter/lib/src/rendering/view.dart b/packages/flutter/lib/src/rendering/view.dart
index 826caed..9a982ad 100644
--- a/packages/flutter/lib/src/rendering/view.dart
+++ b/packages/flutter/lib/src/rendering/view.dart
@@ -122,8 +122,7 @@
try {
final TransformLayer transformLayer = layer;
transformLayer.transform = _logicalToDeviceTransform;
- Rect bounds = Point.origin & (size * ui.window.devicePixelRatio);
- ui.SceneBuilder builder = new ui.SceneBuilder(bounds);
+ ui.SceneBuilder builder = new ui.SceneBuilder();
transformLayer.addToScene(builder, Offset.zero);
assert(layer == transformLayer);
ui.Scene scene = builder.build();