Chromium Code Reviews| Index: sky/sdk/lib/widgets/checkbox.dart |
| diff --git a/sky/sdk/lib/widgets/checkbox.dart b/sky/sdk/lib/widgets/checkbox.dart |
| index 9f709c0241edb80fe16e0a4db006af7937e1fd0f..94adaed2abc16dc9aa6eb077d58c0a43327a39b7 100644 |
| --- a/sky/sdk/lib/widgets/checkbox.dart |
| +++ b/sky/sdk/lib/widgets/checkbox.dart |
| @@ -5,9 +5,11 @@ |
| import 'dart:sky' as sky; |
| import 'package:sky/theme2/colors.dart' as colors; |
| +import 'package:sky/theme2/shadows.dart'; |
| import '../framework/animation/animated_value.dart'; |
| import '../framework/animation/curves.dart'; |
| +import '../painting/shadows.dart'; |
| import '../rendering/box.dart'; |
| import 'animated_component.dart'; |
| import 'basic.dart'; |
| @@ -61,75 +63,137 @@ class Checkbox extends AnimatedComponent { |
| onChanged(!checked); |
| } |
| + void _customPaintCallback(sky.Canvas canvas, Size size) { |
| + // Choose a color between grey and the theme color |
| + sky.Paint paint = new sky.Paint()..strokeWidth = 2.0 |
| + ..color = _kUncheckedColor; |
| + |
| + // The rrect contracts slightly during the animation |
| + double inset = 2.0 - (_checkedAnimation.value - _kMidpoint).abs() * 2.0; |
| + sky.Rect rect = new sky.Rect.fromLTRB(inset, inset, _kEdgeSize - inset, _kEdgeSize - inset); |
| + sky.RRect rrect = new sky.RRect()..setRectXY(rect, _kEdgeRadius, _kEdgeRadius); |
| + |
| + // Outline of the empty rrect |
| + paint.setStyle(sky.PaintingStyle.stroke); |
| + canvas.drawRRect(rrect, paint); |
| + |
| + // Radial gradient that changes size |
| + if (_checkedAnimation.value > 0) { |
| + paint.setStyle(sky.PaintingStyle.fill); |
| + paint.setShader( |
| + new sky.Gradient.radial( |
| + new Point(_kEdgeSize / 2.0, _kEdgeSize / 2.0), |
| + _kEdgeSize * (_kMidpoint - _checkedAnimation.value) * 8.0, |
| + [const sky.Color(0x00000000), _kUncheckedColor], |
| + [0.0, 1.0] |
|
Matt Perry
2015/06/15 18:22:10
FYI, [0, 1] is the default, so you can just leave
|
| + ) |
| + ); |
| + canvas.drawRRect(rrect, paint); |
| + } |
| + |
| + if (_checkedAnimation.value > _kMidpoint) { |
| + double t = (_checkedAnimation.value - _kMidpoint) / (1.0 - _kMidpoint); |
| + |
| + // Solid filled rrect |
| + paint.setStyle(sky.PaintingStyle.strokeAndFill); |
| + paint.color = new Color.fromARGB((t * 255).floor(), |
| + _kCheckedColor.red, |
| + _kCheckedColor.green, |
| + _kCheckedColor.blue); |
| + canvas.drawRRect(rrect, 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 mid = new sky.Point(_kEdgeSize * 0.4, _kEdgeSize * 0.7); |
| + sky.Point end = new sky.Point(_kEdgeSize * 0.8, _kEdgeSize * 0.3); |
| + 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); |
| + path.moveTo(drawStart.x, drawStart.y); |
| + path.lineTo(mid.x, mid.y); |
| + path.lineTo(drawEnd.x, drawEnd.y); |
| + canvas.drawPath(path, paint); |
| + } |
| + } |
| + |
| + double get _width => _kEdgeSize + 2.0; |
| + double get _height => _kEdgeSize + 2.0; |
| + EdgeDims get _margin => const EdgeDims.symmetric(horizontal: 5.0); |
| + |
| UINode build() { |
| return new EventListenerNode( |
| new Container( |
| margin: const EdgeDims.symmetric(horizontal: 5.0), |
| - width: _kEdgeSize + 2.0, |
| - height: _kEdgeSize + 2.0, |
| + width: _width, |
| + height: _height, |
| child: new CustomPaint( |
| token: _checkedAnimation.value, |
| - callback: (sky.Canvas canvas, Size size) { |
| - // Choose a color between grey and the theme color |
| - sky.Paint paint = new sky.Paint()..strokeWidth = 2.0 |
| - ..color = _kUncheckedColor; |
| - |
| - // The rrect contracts slightly during the animation |
| - double inset = 2.0 - (_checkedAnimation.value - _kMidpoint).abs() * 2.0; |
| - sky.Rect rect = new sky.Rect.fromLTRB(inset, inset, _kEdgeSize - inset, _kEdgeSize - inset); |
| - sky.RRect rrect = new sky.RRect()..setRectXY(rect, _kEdgeRadius, _kEdgeRadius); |
| - |
| - |
| - // Outline of the empty rrect |
| - paint.setStyle(sky.PaintingStyle.stroke); |
| - canvas.drawRRect(rrect, paint); |
| - |
| - // Radial gradient that changes size |
| - if (_checkedAnimation.value > 0) { |
| - paint.setStyle(sky.PaintingStyle.fill); |
| - paint.setShader( |
| - new sky.Gradient.radial( |
| - new Point(_kEdgeSize / 2.0, _kEdgeSize / 2.0), |
| - _kEdgeSize * (_kMidpoint - _checkedAnimation.value) * 8.0, |
| - [const sky.Color(0x00000000), _kUncheckedColor], |
| - [0.0, 1.0] |
| - ) |
| - ); |
| - canvas.drawRRect(rrect, paint); |
| - } |
| - |
| - if (_checkedAnimation.value > _kMidpoint) { |
| - double t = (_checkedAnimation.value - _kMidpoint) / (1.0 - _kMidpoint); |
| - |
| - // Solid filled rrect |
| - paint.setStyle(sky.PaintingStyle.strokeAndFill); |
| - paint.color = new Color.fromARGB((t * 255).floor(), |
| - _kCheckedColor.red, |
| - _kCheckedColor.green, |
| - _kCheckedColor.blue); |
| - canvas.drawRRect(rrect, 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 mid = new sky.Point(_kEdgeSize * 0.4, _kEdgeSize * 0.7); |
| - sky.Point end = new sky.Point(_kEdgeSize * 0.8, _kEdgeSize * 0.3); |
| - 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); |
| - path.moveTo(drawStart.x, drawStart.y); |
| - path.lineTo(mid.x, mid.y); |
| - path.lineTo(drawEnd.x, drawEnd.y); |
| - canvas.drawPath(path, paint); |
| - } |
| - } |
| + callback: _customPaintCallback |
| ) |
| ), |
| onGestureTap: _handleClick |
| ); |
| } |
| +} |
| +// TODO(jackson): This should change colors with the theme |
| +sky.Color _kSwitchOnColor = colors.Purple[500]; |
| +const sky.Color _kSwitchOffColor = const sky.Color(0xFFFAFAFA); |
| +sky.Color _kTrackOnColor = new sky.Color(_kSwitchOnColor.value & (0x80 << 24)); |
| +const sky.Color _kTrackOffColor = const sky.Color(0x42000000); |
| +const double _kSwitchWidth = 35.0; |
| +const double _kThumbRadius = 10.0; |
| +const double _kSwitchHeight = _kThumbRadius * 2.0; |
| +const double _kTrackHeight = 10.0; |
| +const double _kTrackRadius = _kTrackHeight / 2.0; |
| +const double _kTrackWidth = _kSwitchWidth - (_kThumbRadius - _kTrackRadius) * 2.0; |
| + |
| +class Switch extends Checkbox { |
| + // TODO(jackson): Hit-test the switch so that it can respond to both taps and swipe gestures |
| + |
| + Switch({ |
| + Object key, |
| + bool checked, |
| + ValueChanged onChanged |
| + }) : super(key: key, checked: checked, onChanged: onChanged); |
| + |
| + double get _width => _kSwitchWidth + 2.0; |
| + double get _height => _kSwitchHeight + 2.0; |
| + EdgeDims get _margin => const EdgeDims.symmetric(horizontal: 5.0); |
| + |
| + void _customPaintCallback(sky.Canvas canvas, Size size) { |
|
abarth-chromium
2015/06/15 18:19:12
You probably want to extract a base class from Che
|
| + sky.Color thumbColor = checked ? _kSwitchOnColor : _kSwitchOffColor; |
| + sky.Color trackColor = checked ? _kTrackOnColor : _kTrackOffColor; |
| + |
| + // Draw the track rrect |
| + sky.Paint paint = new sky.Paint()..color = trackColor; |
| + paint.setStyle(sky.PaintingStyle.fill); |
| + sky.Rect rect = new sky.Rect.fromLTRB( |
| + 0.0, |
| + _kSwitchHeight / 2.0 - _kTrackHeight / 2.0, |
| + _kTrackWidth, |
| + _kSwitchHeight / 2.0 + _kTrackHeight / 2.0 |
| + ); |
| + sky.RRect rrect = new sky.RRect()..setRectXY(rect, _kTrackRadius, _kTrackRadius); |
| + canvas.drawRRect(rrect, paint); |
| + |
| + // Draw the raised thumb with a shadow |
| + paint.color = thumbColor; |
| + var builder = new ShadowDrawLooperBuilder(); |
| + for (BoxShadow boxShadow in shadows[1]) |
| + builder.addShadow(boxShadow.offset, boxShadow.color, boxShadow.blur); |
| + paint.setDrawLooper(builder.build()); |
| + |
| + // The thumb contracts slightly during the animation |
| + double inset = 2.0 - (_checkedAnimation.value - _kMidpoint).abs() * 2.0; |
| + Point thumbPos = new Point( |
| + _kTrackRadius + _checkedAnimation.value * (_kTrackWidth - _kTrackRadius * 2), |
| + _kSwitchHeight / 2.0 |
| + ); |
| + canvas.drawCircle(thumbPos.x, thumbPos.y, _kThumbRadius - inset, paint); |
| + } |
| } |