From e525943d81f2e10db9c2bb80b1b4e2f050c9752a Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Sun, 30 Aug 2015 22:25:27 -0700 Subject: [PATCH] Add dartdoc for the painting code --- .../flutter/lib/painting/box_painter.dart | 304 ++++++++++++++---- .../flutter/lib/painting/radial_reaction.dart | 18 +- packages/flutter/lib/painting/shadows.dart | 5 +- .../flutter/lib/painting/text_painter.dart | 21 +- packages/flutter/lib/painting/text_style.dart | 145 ++++++++- packages/flutter/lib/widgets/README.md | 3 +- .../lib/widgets/animated_container.dart | 2 +- 7 files changed, 412 insertions(+), 86 deletions(-) diff --git a/packages/flutter/lib/painting/box_painter.dart b/packages/flutter/lib/painting/box_painter.dart index bf0fe70464..c085218cb6 100644 --- a/packages/flutter/lib/painting/box_painter.dart +++ b/packages/flutter/lib/painting/box_painter.dart @@ -10,22 +10,40 @@ import 'package:sky/base/image_resource.dart'; import 'package:sky/base/lerp.dart'; import 'package:sky/painting/shadows.dart'; +/// 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 { - // used for e.g. padding + // TODO(abarth): Remove this constructor or rename it to EdgeDims.fromTRBL. + /// Constructs an EdgeDims from offsets from the top, right, bottom and left const EdgeDims(this.top, this.right, this.bottom, this.left); + + /// 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 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 const EdgeDims.symmetric({ double vertical: 0.0, double horizontal: 0.0 }) : top = vertical, left = horizontal, bottom = vertical, right = horizontal; + /// The offset from the top final double top; + + /// The offset from the right final double right; + + /// The offset from the bottom final double bottom; + + /// The offset from the left final double left; bool operator ==(other) { @@ -52,6 +70,7 @@ class EdgeDims { left - other.left); } + /// An EdgeDims with zero offsets in each direction static const EdgeDims zero = const EdgeDims(0.0, 0.0, 0.0, 0.0); int get hashCode { @@ -65,14 +84,20 @@ class EdgeDims { String toString() => "EdgeDims($top, $right, $bottom, $left)"; } +/// A side of a border of a box class BorderSide { const BorderSide({ this.color: const Color(0xFF000000), this.width: 1.0 }); + + /// The color of this side of the border final Color color; + + /// The width of this side of the border final double width; + /// A black border side of zero width static const none = const BorderSide(width: 0.0); int get hashCode { @@ -84,6 +109,7 @@ class BorderSide { String toString() => 'BorderSide($color, $width)'; } +/// A border of a box, comprised of four sides class Border { const Border({ this.top: BorderSide.none, @@ -92,6 +118,7 @@ class Border { this.left: BorderSide.none }); + /// A uniform border with all sides the same color and width factory Border.all({ Color color: const Color(0xFF000000), double width: 1.0 @@ -100,11 +127,19 @@ class Border { return new Border(top: side, right: side, bottom: side, left: side); } + /// The top side of this border final BorderSide top; + + /// The right side of this border final BorderSide right; + + /// The bottom side of this border final BorderSide bottom; + + /// The left side of this border final BorderSide left; + /// The widths of the sides of this border represented as an EdgeDims EdgeDims get dimensions { return new EdgeDims(top.width, right.width, bottom.width, left.width); } @@ -120,6 +155,10 @@ class Border { String toString() => 'Border($top, $right, $bottom, $left)'; } +/// A shadow cast by a box +/// +/// Note: BoxShadow can cast non-rectangular shadows if the box is +/// non-rectangular (e.g., has a border radius or a circular shape). class BoxShadow { const BoxShadow({ this.color, @@ -127,10 +166,16 @@ class BoxShadow { this.blur }); + /// The color of the shadow final Color color; + + /// The displacement of the shadow from the box final Offset offset; + + /// The standard deviation of the Gaussian to convolve with the box's shape final double blur; + /// Returns a new box shadow with its offset and blur scaled by the given factor BoxShadow scale(double factor) { return new BoxShadow( color: color, @@ -139,97 +184,172 @@ class BoxShadow { ); } + /// Linearly interpolate between two box shadows + /// + /// If either box shadow is null, this function linearly interpolates from a + /// a box shadow that matches the other box shadow in color but has a zero + /// offset and a zero blur. + static BoxShadow lerp(BoxShadow a, BoxShadow b, double t) { + if (a == null && b == null) + return null; + if (a == null) + return b.scale(t); + if (b == null) + return a.scale(1.0 - t); + return new BoxShadow( + color: lerpColor(a.color, b.color, t), + offset: lerpOffset(a.offset, b.offset, t), + blur: lerpNum(a.blur, b.blur, t) + ); + } + + /// Linearly interpolate between two lists of box shadows + /// + /// If the lists differ in length, excess items are lerped with null. + static List lerpList(List a, List b, double t) { + if (a == null && b == null) + return null; + if (a == null) + a = new List(); + if (b == null) + b = new List(); + List result = new List(); + int commonLength = math.min(a.length, b.length); + for (int i = 0; i < commonLength; ++i) + result.add(BoxShadow.lerp(a[i], b[i], t)); + for (int i = commonLength; i < a.length; ++i) + result.add(a[i].scale(1.0 - t)); + for (int i = commonLength; i < b.length; ++i) + result.add(b[i].scale(t)); + return result; + } + String toString() => 'BoxShadow($color, $offset, $blur)'; } -BoxShadow lerpBoxShadow(BoxShadow a, BoxShadow b, double t) { - if (a == null && b == null) - return null; - if (a == null) - return b.scale(t); - if (b == null) - return a.scale(1.0 - t); - return new BoxShadow( - color: lerpColor(a.color, b.color, t), - offset: lerpOffset(a.offset, b.offset, t), - blur: lerpNum(a.blur, b.blur, t) - ); -} - -List lerpListBoxShadow(List a, List b, double t) { - if (a == null && b == null) - return null; - if (a == null) - a = new List(); - if (b == null) - b = new List(); - List result = new List(); - int commonLength = math.min(a.length, b.length); - for (int i = 0; i < commonLength; ++i) - result.add(lerpBoxShadow(a[i], b[i], t)); - for (int i = commonLength; i < a.length; ++i) - result.add(a[i].scale(1.0 - t)); - for (int i = commonLength; i < b.length; ++i) - result.add(b[i].scale(t)); - return result; -} - +/// A 2D gradient abstract class Gradient { sky.Shader createShader(); } +/// A 2D linear gradient class LinearGradient extends Gradient { LinearGradient({ - this.endPoints, + this.begin, + this.end, this.colors, - this.colorStops, + this.stops, this.tileMode: sky.TileMode.clamp - }); + }) { + assert(colors.length == stops.length); + } - final List endPoints; + /// The point at which stop 0.0 of the gradient is placed + final Point begin; + + /// The point at which stop 1.0 of the gradient is placed + final Point end; + + /// The colors the gradient should obtain at each of the stops + /// + /// Note: This list must have the same length as [stops]. final List colors; - final List colorStops; + + /// A list of values from 0.0 to 1.0 that denote fractions of the vector from start to end + /// + /// Note: This list must have the same length as [colors]. + final List stops; + + /// How this gradient should tile the plane final sky.TileMode tileMode; sky.Shader createShader() { - return new sky.Gradient.linear(this.endPoints, this.colors, - this.colorStops, this.tileMode); + return new sky.Gradient.linear([begin, end], this.colors, + this.stops, this.tileMode); } String toString() { - return 'LinearGradient($endPoints, $colors, $colorStops, $tileMode)'; + return 'LinearGradient($begin, $end, $colors, $stops, $tileMode)'; } } +/// A 2D radial gradient class RadialGradient extends Gradient { RadialGradient({ this.center, this.radius, this.colors, - this.colorStops, + this.stops, this.tileMode: sky.TileMode.clamp }); + /// The center of the gradient final Point center; + + /// The radius at which stop 1.0 is placed final double radius; + + /// The colors the gradient should obtain at each of the stops + /// + /// Note: This list must have the same length as [stops]. final List colors; - final List colorStops; + + /// A list of values from 0.0 to 1.0 that denote concentric rings + /// + /// The rings are centered at [center] and have a radius equal to the value of + /// the stop times [radius]. + /// + /// Note: This list must have the same length as [colors]. + final List stops; + + /// How this gradient should tile the plane final sky.TileMode tileMode; sky.Shader createShader() { - return new sky.Gradient.radial(this.center, this.radius, this.colors, - this.colorStops, this.tileMode); + return new sky.Gradient.radial(center, radius, colors, stops, tileMode); } String toString() { - return 'RadialGradient($center, $radius, $colors, $colorStops, $tileMode)'; + return 'RadialGradient($center, $radius, $colors, $stops, $tileMode)'; } } -enum ImageFit { fill, contain, cover, none, scaleDown } +/// How an image should be inscribed into a box +enum ImageFit { + /// Fill the box by distorting the image's aspect ratio + fill, -enum ImageRepeat { repeat, repeatX, repeatY, noRepeat } + /// As large as possible while still containing the image entirely within the box + contain, + /// As small as possible while still covering the entire box + cover, + + /// Center the image within the box and discard any portions of the image that + /// lie outside the box + none, + + /// Center the image within the box and, if necessary, scale the image down to + /// ensure that the image fits within the box + scaleDown +} + +/// How to paint any portions of a box not covered by an image +enum ImageRepeat { + /// Repeat the image in both the x and y directions until the box is filled + repeat, + + /// Repeat the image in the x direction until the box is filled horizontally + repeatX, + + /// Repeat the image in the y direction until the box is filled vertically + repeatY, + + /// Leave uncovered poritions of the box transparent + noRepeat +} + +/// Paint an image into the given rectangle in the canvas void paintImage({ sky.Canvas canvas, Rect rect, @@ -289,9 +409,15 @@ void paintImage({ typedef void BackgroundImageChangeListener(); +/// A background image for a box class BackgroundImage { + /// 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 final ImageRepeat repeat; + + /// A color filter to apply to the background image before painting it final sky.ColorFilter colorFilter; BackgroundImage({ @@ -302,6 +428,7 @@ class BackgroundImage { }) : _imageResource = image; sky.Image _image; + /// The image to be painted into the background sky.Image get image => _image; ImageResource _imageResource; @@ -309,6 +436,7 @@ class BackgroundImage { final List _listeners = new List(); + /// 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 @@ -318,6 +446,7 @@ class BackgroundImage { _listeners.add(listener); } + /// 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 @@ -340,9 +469,17 @@ class BackgroundImage { String toString() => 'BackgroundImage($fit, $repeat)'; } -enum Shape { rectangle, circle } +// TODO(abarth): Rename to BoxShape? +/// A 2D geometrical shape +enum Shape { + /// An axis-aligned, 2D rectangle + rectangle, -// This must be immutable, because we won't notice when it changes + /// A 2D locus of points equidistant from a single point + circle +} + +/// An immutable description of how to paint a box class BoxDecoration { const BoxDecoration({ this.backgroundColor, // null = don't draw background color @@ -354,14 +491,33 @@ class BoxDecoration { this.shape: Shape.rectangle }); + /// The color to fill in the background of the box + /// + /// The color is filled into the shape of the box (e.g., either a rectangle, + /// potentially with a border radius, or a circle). final Color backgroundColor; + + /// An image to paint above the background color final BackgroundImage backgroundImage; - final double borderRadius; + + /// A border to draw above the background final Border border; + + /// If non-null, the corners of this box are rounded by this radius + /// + /// Applies only to boxes with rectangular shapes. + final double borderRadius; + + /// A list of shadows cast by this box behind the background final List boxShadow; + + /// A graident to use when filling the background final Gradient gradient; + + /// The shape to fill the background color into and to cast as a shadow final Shape shape; + /// Returns a new box decoration that is scalled by the given factor BoxDecoration scale(double factor) { // TODO(abarth): Scale ALL the things. return new BoxDecoration( @@ -369,12 +525,34 @@ class BoxDecoration { backgroundImage: backgroundImage, border: border, borderRadius: lerpNum(null, borderRadius, factor), - boxShadow: lerpListBoxShadow(null, boxShadow, factor), + boxShadow: BoxShadow.lerpList(null, boxShadow, factor), gradient: gradient, shape: shape ); } + /// Linearly interpolate between two box decorations + /// + /// Interpolates each parameter of the box decoration separately. + static BoxDecoration lerp(BoxDecoration a, BoxDecoration b, double t) { + if (a == null && b == null) + return null; + if (a == null) + return b.scale(t); + if (b == null) + return a.scale(1.0 - t); + // TODO(abarth): lerp ALL the fields. + return new BoxDecoration( + backgroundColor: lerpColor(a.backgroundColor, b.backgroundColor, t), + backgroundImage: b.backgroundImage, + border: b.border, + borderRadius: lerpNum(a.borderRadius, b.borderRadius, t), + boxShadow: BoxShadow.lerpList(a.boxShadow, b.boxShadow, t), + gradient: b.gradient, + shape: b.shape + ); + } + String toString([String prefix = '']) { List result = []; if (backgroundColor != null) @@ -397,31 +575,14 @@ class BoxDecoration { } } -BoxDecoration lerpBoxDecoration(BoxDecoration a, BoxDecoration b, double t) { - if (a == null && b == null) - return null; - if (a == null) - return b.scale(t); - if (b == null) - return a.scale(1.0 - t); - // TODO(abarth): lerp ALL the fields. - return new BoxDecoration( - backgroundColor: lerpColor(a.backgroundColor, b.backgroundColor, t), - backgroundImage: b.backgroundImage, - border: b.border, - borderRadius: lerpNum(a.borderRadius, b.borderRadius, t), - boxShadow: lerpListBoxShadow(a.boxShadow, b.boxShadow, t), - gradient: b.gradient, - shape: b.shape - ); -} - +/// An object that paints a [BoxDecoration] into a canvas class BoxPainter { BoxPainter(BoxDecoration decoration) : _decoration = decoration { assert(decoration != null); } BoxDecoration _decoration; + /// The box decoration to paint BoxDecoration get decoration => _decoration; void set decoration (BoxDecoration value) { assert(value != null); @@ -611,6 +772,7 @@ class BoxPainter { canvas.drawCircle(center, radius, paint); } + /// Paint the box decoration into the given location on the given canvas void paint(sky.Canvas canvas, Rect rect) { _paintBackgroundColor(canvas, rect); _paintBackgroundImage(canvas, rect); diff --git a/packages/flutter/lib/painting/radial_reaction.dart b/packages/flutter/lib/painting/radial_reaction.dart index 4df1e609c0..69663d00b1 100644 --- a/packages/flutter/lib/painting/radial_reaction.dart +++ b/packages/flutter/lib/painting/radial_reaction.dart @@ -20,6 +20,9 @@ int _roundOpacity(double opacity) { return (255 * opacity).round(); } +/// A material design radial ink reaction +/// +/// See [https://www.google.com/design/spec/animation/responsive-interaction.html#responsive-interaction-radial-action] class RadialReaction { RadialReaction({ this.center, @@ -41,7 +44,10 @@ class RadialReaction { ..duration =_kHideDuration; } + /// The center of the circle in which the reaction occurs final Point center; + + /// The radius of the circle in which the reaction occurs final double radius; AnimationPerformance _showPerformance; @@ -54,15 +60,22 @@ class RadialReaction { AnimationPerformance _hidePerformance; AnimatedValue _fade; - void show() { - _showComplete = _showPerformance.forward(); + /// Show the reaction + /// + /// Returns a future that resolves when the reaction is completely revealed. + Future show() { + return _showComplete = _showPerformance.forward(); } + /// Hide the reaction + /// + /// Returns a future that resolves when the reaction is completely hidden. Future hide() async { await _showComplete; await _hidePerformance.forward(); } + /// Call listener whenever the visual appearance of the reaction changes void addListener(Function listener) { _showPerformance.addListener(listener); _hidePerformance.addListener(listener); @@ -71,6 +84,7 @@ class RadialReaction { final Paint _outerPaint = new Paint(); final Paint _innerPaint = new Paint(); + /// Paint the reaction onto the given canvas at the given offset void paint(sky.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/painting/shadows.dart b/packages/flutter/lib/painting/shadows.dart index 5cbcacfb9b..c2c95e029f 100644 --- a/packages/flutter/lib/painting/shadows.dart +++ b/packages/flutter/lib/painting/shadows.dart @@ -4,11 +4,11 @@ import 'dart:sky' as sky; -/// Helper class to build a Paint DrawLooper that adds shadows to the Paint's -/// operation. +/// A helper class to build a [sky.DrawLooper] for drawing shadows class ShadowDrawLooperBuilder { var builder_ = new sky.LayerDrawLooperBuilder(); + /// Add a shadow with the given parameters void addShadow(sky.Offset offset, sky.Color color, double blur) { builder_.addLayerOnTop( new sky.DrawLooperLayerInfo() @@ -20,6 +20,7 @@ class ShadowDrawLooperBuilder { ..setMaskFilter(new sky.MaskFilter.blur(sky.BlurStyle.normal, blur))); } + /// Returns the draw looper built for the added shadows sky.DrawLooper build() { builder_.addLayerOnTop(new sky.DrawLooperLayerInfo(), new sky.Paint()); return builder_.build(); diff --git a/packages/flutter/lib/painting/text_painter.dart b/packages/flutter/lib/painting/text_painter.dart index 70bd9b9f6e..bdc51ab418 100644 --- a/packages/flutter/lib/painting/text_painter.dart +++ b/packages/flutter/lib/painting/text_painter.dart @@ -8,8 +8,9 @@ import 'package:sky/painting/text_style.dart'; export 'package:sky/painting/text_style.dart'; -// This must be immutable, because we won't notice when it changes +/// 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); String toString([String prefix = '']); @@ -17,11 +18,13 @@ abstract class TextSpan { } } +/// An immutable span of unstyled text class PlainTextSpan extends TextSpan { PlainTextSpan(this.text) { assert(text != null); } + /// The text contained in the span final String text; sky.Node _toDOM(sky.Document owner) { @@ -34,13 +37,17 @@ class PlainTextSpan extends TextSpan { String toString([String prefix = '']) => '${prefix}${runtimeType}: "${text}"'; } +/// An immutable text span that applies a style to a list of children class StyledTextSpan extends TextSpan { StyledTextSpan(this.style, this.children) { assert(style != null); assert(children != null); } + /// The style to apply to the children final TextStyle style; + + /// The children to which the style is applied final List children; sky.Node _toDOM(sky.Document owner) { @@ -90,6 +97,7 @@ class StyledTextSpan extends TextSpan { } } +/// An object that paints a [TextSpan] into a canvas class TextPainter { TextPainter(TextSpan text) { _layoutRoot.rootElement = _document.createElement('p'); @@ -102,6 +110,7 @@ class TextPainter { bool _needsLayout = true; TextSpan _text; + /// The (potentially styled) text to paint TextSpan get text => _text; void set text(TextSpan value) { if (_text == value) @@ -113,6 +122,7 @@ class TextPainter { _needsLayout = true; } + /// The minimum width at which to layout the text double get minWidth => _layoutRoot.minWidth; void set minWidth(value) { if (_layoutRoot.minWidth == value) @@ -121,6 +131,7 @@ class TextPainter { _needsLayout = true; } + /// The maximum width at which to layout the text double get maxWidth => _layoutRoot.maxWidth; void set maxWidth(value) { if (_layoutRoot.maxWidth == value) @@ -129,6 +140,7 @@ class TextPainter { _needsLayout = true; } + /// The minimum height at which to layout the text double get minHeight => _layoutRoot.minHeight; void set minHeight(value) { if (_layoutRoot.minHeight == value) @@ -137,6 +149,7 @@ class TextPainter { _needsLayout = true; } + /// The maximum height at which to layout the text double get maxHeight => _layoutRoot.maxHeight; void set maxHeight(value) { if (_layoutRoot.maxHeight == value) @@ -144,21 +157,25 @@ class TextPainter { _layoutRoot.maxHeight = value; } + /// 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 _layoutRoot.rootElement.minContentWidth; } + /// The width at which increasing the width of the text no longer decreases the height double get maxContentWidth { assert(!_needsLayout); return _layoutRoot.rootElement.maxContentWidth; } + /// The height required to paint the text completely within its bounds double get height { assert(!_needsLayout); return _layoutRoot.rootElement.height; } + /// 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; @@ -168,6 +185,7 @@ class TextPainter { } } + /// Compute the visual position of the glyphs for painting the text void layout() { if (!_needsLayout) return; @@ -175,6 +193,7 @@ class TextPainter { _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); // TODO(ianh): Make LayoutRoot support a paint offset so we don't diff --git a/packages/flutter/lib/painting/text_style.dart b/packages/flutter/lib/painting/text_style.dart index d0bca270f5..15bd6a517b 100644 --- a/packages/flutter/lib/painting/text_style.dart +++ b/packages/flutter/lib/painting/text_style.dart @@ -4,23 +4,118 @@ import 'dart:sky'; -enum FontWeight { w100, w200, w300, w400, w500, w600, w700, w800, w900 } +/// The thickness of the glyphs used to draw the text +enum FontWeight { + /// Thin, the least thick + w100, + + /// Extra-light + w200, + + /// Light + w300, + + /// Normal / regular / plain + w400, + + /// Medium + w500, + + /// Semi-bold + w600, + + /// Bold + w700, + + /// Extra-bold + w800, + + /// Black, the most thick + w900 +} + +/// A normal font weight const normal = FontWeight.w400; + +/// A bold font weight const bold = FontWeight.w700; -enum FontStyle { normal, italic, oblique } +/// Whether to slant the glyphs in the font +enum FontStyle { + /// Use the upright glyphs + normal, -enum TextAlign { left, right, center } + /// Use glyphs designed for slanting + italic, -enum TextBaseline { alphabetic, ideographic } + /// Use the upright glyphs but slant them during painting + oblique // TODO(abarth): Remove. We don't really support this value. +} -enum TextDecoration { none, underline, overline, lineThrough } +/// Whether to align text horizontally +enum TextAlign { + /// Align the text on the left edge of the container + left, + + /// Align the text on the right edge of the container + right, + + /// Align the text in the center of the container + center +} + +/// A horizontal line used for aligning text +enum TextBaseline { + // The horizontal line used to align the bottom of glyphs for alphabetic characters + alphabetic, + + // The horizontal line used to align ideographic characters + ideographic +} + +/// A linear decoration to draw near the text +enum TextDecoration { + /// Do not draw a decoration + none, + + /// Draw a line underneath each line of text + underline, + + /// Draw a line above each line of text + overline, + + /// Draw a line through each line of text + lineThrough +} + +/// Draw a line underneath each line of text const underline = const [TextDecoration.underline]; + +/// Draw a line above each line of text const overline = const [TextDecoration.overline]; + +/// Draw a line through each line of text const lineThrough = const [TextDecoration.lineThrough]; -enum TextDecorationStyle { solid, double, dotted, dashed, wavy } +/// The style in which to draw a text decoration +enum TextDecorationStyle { + /// Draw a solid line + solid, + /// Draw two lines + double, + + /// Draw a dotted line + dotted, + + /// Draw a dashed line + dashed, + + /// Draw a sinusoidal line + wavy +} + +/// An immutable style in which paint text class TextStyle { const TextStyle({ this.color, @@ -36,18 +131,42 @@ class TextStyle { this.decorationStyle }); + /// The color to use when painting the text final Color color; + + /// The name of the font to use when painting the text final String fontFamily; - final double fontSize; // in pixels + + /// The size of gyphs (in logical pixels) to use when painting the text + final double fontSize; + + /// The font weight to use when painting the text final FontWeight fontWeight; + + /// The font style to use when painting the text final FontStyle fontStyle; + + /// How the text should be aligned (applies only to the outermost + /// StyledTextSpan, which establishes the container for the text) final TextAlign textAlign; + + /// The baseline to use for aligning the text final TextBaseline textBaseline; - final double height; // multiple of fontSize + + /// The distance between the text baselines, as a multiple of the font size + final double height; + + /// A list of decorations to paint near the text final List decoration; // TODO(ianh): Switch this to a Set<> once Dart supports constant Sets + + /// The color in which to paint the text decorations final Color decorationColor; + + /// The style in which to paint the text decorations final TextDecorationStyle decorationStyle; + /// Returns a new text style that matches this text style but with the given + /// values replaced TextStyle copyWith({ Color color, String fontFamily, @@ -76,6 +195,8 @@ class TextStyle { ); } + /// Returns a new text style that matches this text style but with some values + /// replaced by the non-null parameters of the given text style TextStyle merge(TextStyle other) { return copyWith( color: other.color, @@ -124,6 +245,10 @@ class TextStyle { return toCSS[decorationStyle]; } + /// 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(CSSStyleDeclaration cssStyle) { if (color != null) { cssStyle['color'] = _colorToCSSString(color); @@ -163,6 +288,10 @@ class TextStyle { } } + /// Program the container aspects of 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 applyToContainerCSSStyle(CSSStyleDeclaration cssStyle) { if (textAlign != null) { cssStyle['text-align'] = const { diff --git a/packages/flutter/lib/widgets/README.md b/packages/flutter/lib/widgets/README.md index e622fbd41f..3deaa763df 100644 --- a/packages/flutter/lib/widgets/README.md +++ b/packages/flutter/lib/widgets/README.md @@ -131,7 +131,8 @@ import 'package:sky/widgets.dart'; final BoxDecoration _decoration = new BoxDecoration( borderRadius: 5.0, gradient: new LinearGradient( - endPoints: [ Point.origin, const Point(0.0, 36.0) ], + start: Point.origin, + end: const Point(0.0, 36.0), colors: [ const Color(0xFFEEEEEE), const Color(0xFFCCCCCC) ] ) ); diff --git a/packages/flutter/lib/widgets/animated_container.dart b/packages/flutter/lib/widgets/animated_container.dart index 190765e759..4e53bebe8b 100644 --- a/packages/flutter/lib/widgets/animated_container.dart +++ b/packages/flutter/lib/widgets/animated_container.dart @@ -25,7 +25,7 @@ class AnimatedBoxDecorationValue extends AnimatedValue { AnimatedBoxDecorationValue(BoxDecoration begin, { BoxDecoration end, Curve curve: linear }) : super(begin, end: end, curve: curve); - BoxDecoration lerp(double t) => lerpBoxDecoration(begin, end, t); + BoxDecoration lerp(double t) => BoxDecoration.lerp(begin, end, t); } class AnimatedEdgeDimsValue extends AnimatedValue {