diff --git a/examples/raw/shadowed_box.dart b/examples/raw/shadowed_box.dart index ee03459fcfc..161d74a884f 100644 --- a/examples/raw/shadowed_box.dart +++ b/examples/raw/shadowed_box.dart @@ -6,17 +6,23 @@ import 'dart:sky'; import 'package:sky/framework/app.dart'; import 'package:sky/framework/rendering/box.dart'; import 'package:sky/framework/rendering/flex.dart'; +import 'package:sky/framework/theme2/shadows.dart'; AppView app; void main() { var coloredBox = new RenderDecoratedBox( - decoration: new BoxDecoration(backgroundColor: const Color(0xFFFFFF00)) + decoration: new BoxDecoration( + backgroundColor: const Color(0xFFFAFAFA), + boxShadow: Shadow[3]) ); - var shadow = const BoxShadow( - color: const Color(0xFFEEEEEE), offset: const Size(5.0, 5.0), blur: 5.0); - var shadowBox = new RenderShadowedBox(shadow: shadow, child: coloredBox); - var paddedBox = new RenderPadding(padding: const EdgeDims.all(30.0), - child: shadowBox); - app = new AppView(paddedBox); + var paddedBox = new RenderPadding( + padding: const EdgeDims.all(50.0), + child: coloredBox); + app = new AppView(new RenderDecoratedBox( + decoration: const BoxDecoration( + backgroundColor: const Color(0xFFFFFFFF) + ), + child: paddedBox + )); } diff --git a/sdk/lib/framework/components2/popup_menu.dart b/sdk/lib/framework/components2/popup_menu.dart index a398980bf59..184a627891a 100644 --- a/sdk/lib/framework/components2/popup_menu.dart +++ b/sdk/lib/framework/components2/popup_menu.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 'animated_component.dart'; import '../animation/animated_value.dart'; import '../fn2.dart'; import '../theme2/colors.dart'; +import '../theme2/shadows.dart'; +import 'animated_component.dart'; import 'dart:async'; import 'dart:math' as math; import 'material.dart'; @@ -98,16 +99,15 @@ class PopupMenu extends AnimatedComponent { return new PopupMenuItem(key: i++, children: item, opacity: opacity); })); + // border-radius: 2px + // inlineStyle: _inlineStyle(), return new ShrinkWrapWidth( - child: new Material( - content: new Container( - padding: const EdgeDims.all(8.0), - // border-radius: 2px - decoration: new BoxDecoration(backgroundColor: Grey[50]), - // inlineStyle: _inlineStyle(), - child: new BlockContainer(children: children) - ), - level: level + child: new Container( + padding: const EdgeDims.all(8.0), + decoration: new BoxDecoration( + backgroundColor: Grey[50], + boxShadow: Shadow[level]), + child: new BlockContainer(children: children) ) ); } diff --git a/sdk/lib/framework/rendering/box.dart b/sdk/lib/framework/rendering/box.dart index e6810a3355a..3b2ac5ab2b3 100644 --- a/sdk/lib/framework/rendering/box.dart +++ b/sdk/lib/framework/rendering/box.dart @@ -630,15 +630,31 @@ class Border { String toString() => 'Border($top, $right, $bottom, $left)'; } +class BoxShadow { + const BoxShadow({ + this.color, + this.offset, + this.blur + }); + + final Color color; + final Size offset; + final double blur; + + String toString() => 'BoxShadow($color, $offset, $blur)'; +} + // This must be immutable, because we won't notice when it changes class BoxDecoration { const BoxDecoration({ this.backgroundColor, - this.border + this.border, + this.boxShadow }); final Color backgroundColor; final Border border; + final List boxShadow; String toString([String prefix = '']) { List result = []; @@ -646,6 +662,8 @@ class BoxDecoration { result.add('${prefix}backgroundColor: $backgroundColor'); if (border != null) result.add('${prefix}border: $border'); + // if (boxShadow != null) + // result.add('${prefix}boxShadow: $boxShadow'); if (result.isEmpty) return '${prefix}'; return result.join('\n'); @@ -668,17 +686,50 @@ class RenderDecoratedBox extends RenderProxyBox { if (value == _decoration) return; _decoration = value; + _cachedBackgroundPaint = null; markNeedsPaint(); } + Paint _cachedBackgroundPaint; + Paint get _backgroundPaint { + if (_cachedBackgroundPaint == null) { + Paint paint = new Paint(); + + if (_decoration.backgroundColor != null) + paint.color = _decoration.backgroundColor; + + if (_decoration.boxShadow != null) { + var builder = new sky.LayerDrawLooperBuilder(); + for (BoxShadow boxShadow in _decoration.boxShadow) { + builder.addLayerOnTop( + new sky.DrawLooperLayerInfo() + ..setPaintBits(-1) + ..setOffset(boxShadow.offset.toPoint()) + ..setColorMode(sky.TransferMode.srcMode), + (Paint layerPaint) { + layerPaint.color = boxShadow.color; + layerPaint.setMaskFilter( + new sky.MaskFilter.Blur(sky.BlurStyle.normal, + boxShadow.blur, + highQuality: true)); + }); + } + builder.addLayerOnTop(new sky.DrawLooperLayerInfo(), (_) {}); + paint.setDrawLooper(builder.build()); + } + + _cachedBackgroundPaint = paint; + } + + return _cachedBackgroundPaint; + } + void paint(RenderObjectDisplayList canvas) { assert(size.width != null); assert(size.height != null); - if (_decoration.backgroundColor != null) { - Paint paint = new Paint()..color = _decoration.backgroundColor; - canvas.drawRect(new Rect.fromLTRB(0.0, 0.0, size.width, size.height), paint); - } + if (_decoration.backgroundColor != null || _decoration.boxShadow != null) + canvas.drawRect(new Rect.fromLTRB(0.0, 0.0, size.width, size.height), _backgroundPaint); if (_decoration.border != null) { assert(_decoration.border.top != null); @@ -823,63 +874,6 @@ class RenderSizeObserver extends RenderProxyBox { } } -// This must be immutable, because we won't notice when it changes -class BoxShadow { - const BoxShadow({ - this.color, - this.offset, - this.blur - }); - - final Size offset; - final double blur; - final Color color; -} - -class RenderShadowedBox extends RenderProxyBox { - - RenderShadowedBox({ - BoxShadow shadow, - RenderBox child - }) : _shadow = shadow, super(child); - - BoxShadow _shadow; - BoxShadow get shadow => _shadow; - void set shadow (BoxShadow value) { - if (value == _shadow) - return; - _shadow = value; - markNeedsPaint(); - } - - Paint _createShadowPaint(BoxShadow shadow) { - // TODO(eseidel): This should not be hard-coded yellow. - Paint paint = new Paint()..color = const Color.fromARGB(255, 0, 255, 0); - var builder = new sky.LayerDrawLooperBuilder() - // Shadow layer. - ..addLayerOnTop( - new sky.DrawLooperLayerInfo() - ..setPaintBits(-1) - ..setOffset(shadow.offset.toPoint()) - ..setColorMode(sky.TransferMode.srcMode), - (Paint layerPaint) { - layerPaint.color = shadow.color; - layerPaint.setMaskFilter( - new sky.MaskFilter.Blur(sky.BlurStyle.normal, shadow.blur, highQuality: true)); - }) - // Main layer. - ..addLayerOnTop(new sky.DrawLooperLayerInfo(), (_) {}); - paint.setDrawLooper(builder.build()); - return paint; - } - - void paint(RenderObjectDisplayList canvas) { - Paint paint = _createShadowPaint(_shadow); - canvas.drawRect(new Rect.fromLTRB(0.0, 0.0, size.width, size.height), paint); - super.paint(canvas); - } -} - typedef void CustomPaintCallback(sky.Canvas canvas); class RenderCustomPaint extends RenderProxyBox { diff --git a/sdk/lib/framework/theme2/shadows.dart b/sdk/lib/framework/theme2/shadows.dart index 6c0d8ee5f7b..b5e0d23fe01 100644 --- a/sdk/lib/framework/theme2/shadows.dart +++ b/sdk/lib/framework/theme2/shadows.dart @@ -2,10 +2,58 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -const Map Shadow = const { - 1: '0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24)', - 2: '0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23)', - 3: '0 10px 20px rgba(0,0,0,0.19), 0 6px 6px rgba(0,0,0,0.23)', - 4: '0 14px 28px rgba(0,0,0,0.25), 0 10px 10px rgba(0,0,0,0.22)', - 5: '0 19px 38px rgba(0,0,0,0.30), 0 15px 12px rgba(0,0,0,0.22)', +import '../rendering/box.dart'; +import 'dart:sky' show Color, Size; + +const Map> Shadow = const { + 1: const [ + const BoxShadow( + color: const Color(0x1F000000), + offset: const Size(0.0, 1.0), + blur: 3.0), + const BoxShadow( + color: const Color(0x3D000000), + offset: const Size(0.0, 1.0), + blur: 2.0), + ], + 2: const [ + const BoxShadow( + color: const Color(0x29000000), + offset: const Size(0.0, 3.0), + blur: 6.0), + const BoxShadow( + color: const Color(0x3B000000), + offset: const Size(0.0, 3.0), + blur: 6.0), + ], + 3: const [ + const BoxShadow( + color: const Color(0x30000000), + offset: const Size(0.0, 10.0), + blur: 20.0), + const BoxShadow( + color: const Color(0x3B000000), + offset: const Size(0.0, 6.0), + blur: 6.0), + ], + 4: const [ + const BoxShadow( + color: const Color(0x40000000), + offset: const Size(0.0, 14.0), + blur: 28.0), + const BoxShadow( + color: const Color(0x38000000), + offset: const Size(0.0, 10.0), + blur: 10.0), + ], + 5: const [ + const BoxShadow( + color: const Color(0x4E000000), + offset: const Size(0.0, 19.0), + blur: 28.0), + const BoxShadow( + color: const Color(0x38000000), + offset: const Size(0.0, 15.0), + blur: 12.0), + ], };