Chromium Code Reviews| Index: sky/sdk/lib/widgets/drawer.dart |
| diff --git a/sky/sdk/lib/widgets/drawer.dart b/sky/sdk/lib/widgets/drawer.dart |
| index 37ddbd886d7a5b3780a49372b830df6afdb6e246..15aa0341b5c3db760748d7b58ed6acb22b0eb3f2 100644 |
| --- a/sky/sdk/lib/widgets/drawer.dart |
| +++ b/sky/sdk/lib/widgets/drawer.dart |
| @@ -11,6 +11,7 @@ import 'animated_component.dart'; |
| import 'animation_builder.dart'; |
| import 'basic.dart'; |
| import 'scrollable_viewport.dart'; |
| +import 'navigator.dart'; |
| import 'theme.dart'; |
| // TODO(eseidel): Draw width should vary based on device size: |
| @@ -36,37 +37,111 @@ const Curve _kAnimationCurve = linear; |
| typedef void DrawerStatusChangeHandler (bool showing); |
| -class DrawerController { |
| - DrawerController(this.onStatusChange) { |
| - builder = new AnimationBuilder() |
| +class Drawer extends AnimatedComponent { |
| + Drawer({ |
| + String key, |
| + this.children, |
| + this.showing: false, |
| + this.level: 0, |
| + this.onStatusChange, |
| + this.navigator |
| + }) : super(key: key); |
| + |
| + List<Widget> children; |
| + bool showing; |
| + int level; |
| + DrawerStatusChangeHandler onStatusChange; |
| + Navigator navigator; |
| + |
| + AnimationPerformance _performance; |
| + AnimationBuilder _builder; |
| + |
| + void initState() { |
| + _builder = new AnimationBuilder() |
| ..position = new AnimatedType<Point>( |
| new Point(-_kWidth, 0.0), end: Point.origin, curve: _kAnimationCurve); |
| - performance = builder.createPerformance([builder.position], |
| - duration: _kBaseSettleDuration) |
| + _performance = _builder.createPerformance([_builder.position], |
| + duration: _kBaseSettleDuration) |
| ..addListener(_checkValue); |
| + watchPerformance(_performance); |
| } |
| - final DrawerStatusChangeHandler onStatusChange; |
| - AnimationPerformance performance; |
| - AnimationBuilder builder; |
| + void syncFields(Drawer source) { |
| + const String kDrawerRouteName = "[open drawer]"; |
|
abarth-chromium
2015/07/11 02:00:54
I wonder if the navigation should let you use opaq
jackson
2015/07/14 18:25:50
I agree, I'll do this in a new CL.
|
| + children = source.children; |
| + level = source.level; |
| + navigator = source.navigator; |
| + if (showing != source.showing) { |
| + showing = source.showing; |
| + if (showing) { |
| + if (navigator != null) { |
| + navigator.pushState(kDrawerRouteName, (_) { |
| + onStatusChange(false); |
| + }); |
| + } |
| + _performance.play(); |
| + } else { |
| + if (navigator != null && navigator.currentRoute.name == kDrawerRouteName) |
| + navigator.pop(); |
| + _performance.reverse(); |
| + } |
| + } |
| + super.syncFields(source); |
| + } |
| + |
| + // TODO(mpcomplete): the animation system should handle building, maybe? Or |
| + // at least setting the transform. Figure out how this could work for things |
| + // like fades, slides, rotates, pinch, etc. |
| + Widget build() { |
| + if (isClosed) { |
| + return new Container(width: 0.0, height: 0.0); |
| + } |
|
abarth-chromium
2015/07/11 02:00:54
We should make an |Empty| widget so that this can
jackson
2015/07/14 18:25:49
This isn't needed now that we aren't building when
|
| + |
| + // TODO(mpcomplete): animate as a fade-in. |
| + double scaler = _performance.progress; |
| + Color maskColor = new Color.fromARGB((0x7F * scaler).floor(), 0, 0, 0); |
| + |
| + var mask = new Listener( |
| + child: new Container(decoration: new BoxDecoration(backgroundColor: maskColor)), |
| + onGestureTap: handleMaskTap |
| + ); |
| + |
| + Widget content = _builder.build( |
| + new Container( |
| + decoration: new BoxDecoration( |
| + backgroundColor: Theme.of(this).canvasColor, |
| + boxShadow: shadows[level]), |
| + width: _kWidth, |
| + child: new ScrollableBlock(children) |
| + )); |
| + |
| + return new Listener( |
| + child: new Stack([ mask, content ]), |
| + onPointerDown: handlePointerDown, |
| + onPointerMove: handlePointerMove, |
| + onPointerUp: handlePointerUp, |
| + onPointerCancel: handlePointerCancel, |
| + onGestureFlingStart: handleFlingStart |
| + ); |
| + } |
| - double get xPosition => builder.position.value.x; |
| + double get xPosition => _builder.position.value.x; |
| bool _oldClosedState = true; |
| void _checkValue() { |
| - var newClosedState = isClosed; |
| + bool newClosedState = isClosed; |
| if (onStatusChange != null && _oldClosedState != newClosedState) { |
| onStatusChange(!newClosedState); |
| - _oldClosedState = newClosedState; |
| } |
| + _oldClosedState = newClosedState; |
| } |
| - bool get isClosed => performance.isDismissed; |
| + bool get isClosed => _performance.isDismissed; |
| bool get _isMostlyClosed => xPosition <= -_kWidth/2; |
| - void open() => performance.play(); |
| + void open() => _performance.play(); |
| - void close() => performance.reverse(); |
| + void close() => _performance.reverse(); |
|
abarth-chromium
2015/07/11 02:00:54
We can delete most of these functions. They exist
jackson
2015/07/14 18:25:50
Done.
|
| void _settle() => _isMostlyClosed ? close() : open(); |
| @@ -74,82 +149,27 @@ class DrawerController { |
| // TODO(mpcomplete): Figure out how to generalize these handlers on a |
| // "PannableThingy" interface. |
| - void handlePointerDown(_) => performance.stop(); |
| + void handlePointerDown(_) => _performance.stop(); |
| void handlePointerMove(sky.PointerEvent event) { |
| - if (performance.isAnimating) |
| + if (_performance.isAnimating) |
| return; |
| - performance.progress += event.dx / _kWidth; |
| + _performance.progress += event.dx / _kWidth; |
| } |
| void handlePointerUp(_) { |
| - if (!performance.isAnimating) |
| + if (!_performance.isAnimating) |
| _settle(); |
| } |
| void handlePointerCancel(_) { |
| - if (!performance.isAnimating) |
| + if (!_performance.isAnimating) |
| _settle(); |
| } |
| void handleFlingStart(event) { |
| double velocityX = event.velocityX / 1000; |
| if (velocityX.abs() >= _kMinFlingVelocity) |
| - performance.fling(velocity: velocityX / _kWidth); |
| + _performance.fling(velocity: velocityX / _kWidth); |
| } |
| } |
| - |
| -class Drawer extends AnimatedComponent { |
| - Drawer({ |
| - String key, |
| - this.controller, |
| - this.children, |
| - this.level: 0 |
| - }) : super(key: key) { |
| - watchPerformance(controller.performance); |
| - } |
| - |
| - List<Widget> children; |
| - int level; |
| - DrawerController controller; |
| - |
| - void syncFields(Drawer source) { |
| - children = source.children; |
| - level = source.level; |
| - controller = source.controller; |
| - super.syncFields(source); |
| - } |
| - |
| - // TODO(mpcomplete): the animation system should handle building, maybe? Or |
| - // at least setting the transform. Figure out how this could work for things |
| - // like fades, slides, rotates, pinch, etc. |
| - Widget build() { |
| - // TODO(mpcomplete): animate as a fade-in. |
| - double scaler = controller.performance.progress; |
| - Color maskColor = new Color.fromARGB((0x7F * scaler).floor(), 0, 0, 0); |
| - |
| - var mask = new Listener( |
| - child: new Container(decoration: new BoxDecoration(backgroundColor: maskColor)), |
| - onGestureTap: controller.handleMaskTap |
| - ); |
| - |
| - Widget content = controller.builder.build( |
| - new Container( |
| - decoration: new BoxDecoration( |
| - backgroundColor: Theme.of(this).canvasColor, |
| - boxShadow: shadows[level]), |
| - width: _kWidth, |
| - child: new ScrollableBlock(children) |
| - )); |
| - |
| - return new Listener( |
| - child: new Stack([ mask, content ]), |
| - onPointerDown: controller.handlePointerDown, |
| - onPointerMove: controller.handlePointerMove, |
| - onPointerUp: controller.handlePointerUp, |
| - onPointerCancel: controller.handlePointerCancel, |
| - onGestureFlingStart: controller.handleFlingStart |
| - ); |
| - } |
| - |
| -} |