Commit fb4dbf45 authored by Adam Barth's avatar Adam Barth

Improve TextSpan

Now we just have one TextSpan class that handles both simple strings, trees of
children, and styling both. This approach simplifies the interface for most
clients.

This patch also removes StyledText, which was weakly typed and tricky to use
correctly. The replacement is RichText, which is strongly typed and uses
TextSpan.
parent 755a180a
...@@ -14,24 +14,24 @@ void main() { ...@@ -14,24 +14,24 @@ void main() {
void addAlignmentRow(FlexAlignItems alignItems) { void addAlignmentRow(FlexAlignItems alignItems) {
TextStyle style = const TextStyle(color: const Color(0xFF000000)); TextStyle style = const TextStyle(color: const Color(0xFF000000));
RenderParagraph paragraph = new RenderParagraph(new StyledTextSpan(style, <TextSpan>[new PlainTextSpan('$alignItems')])); RenderParagraph paragraph = new RenderParagraph(new TextSpan(style: style, text: '$alignItems'));
table.add(new RenderPadding(child: paragraph, padding: new EdgeDims.only(top: 20.0))); table.add(new RenderPadding(child: paragraph, padding: new EdgeDims.only(top: 20.0)));
RenderFlex row = new RenderFlex(alignItems: alignItems, textBaseline: TextBaseline.alphabetic); RenderFlex row = new RenderFlex(alignItems: alignItems, textBaseline: TextBaseline.alphabetic);
style = new TextStyle(fontSize: 15.0, color: const Color(0xFF000000)); style = new TextStyle(fontSize: 15.0, color: const Color(0xFF000000));
row.add(new RenderDecoratedBox( row.add(new RenderDecoratedBox(
decoration: new BoxDecoration(backgroundColor: const Color(0x7FFFCCCC)), decoration: new BoxDecoration(backgroundColor: const Color(0x7FFFCCCC)),
child: new RenderParagraph(new StyledTextSpan(style, <TextSpan>[new PlainTextSpan('foo foo foo')])) child: new RenderParagraph(new TextSpan(style: style, text: 'foo foo foo'))
)); ));
style = new TextStyle(fontSize: 10.0, color: const Color(0xFF000000)); style = new TextStyle(fontSize: 10.0, color: const Color(0xFF000000));
row.add(new RenderDecoratedBox( row.add(new RenderDecoratedBox(
decoration: new BoxDecoration(backgroundColor: const Color(0x7FCCFFCC)), decoration: new BoxDecoration(backgroundColor: const Color(0x7FCCFFCC)),
child: new RenderParagraph(new StyledTextSpan(style, <TextSpan>[new PlainTextSpan('foo foo foo')])) child: new RenderParagraph(new TextSpan(style: style, text: 'foo foo foo'))
)); ));
RenderFlex subrow = new RenderFlex(alignItems: alignItems, textBaseline: TextBaseline.alphabetic); RenderFlex subrow = new RenderFlex(alignItems: alignItems, textBaseline: TextBaseline.alphabetic);
style = new TextStyle(fontSize: 25.0, color: const Color(0xFF000000)); style = new TextStyle(fontSize: 25.0, color: const Color(0xFF000000));
subrow.add(new RenderDecoratedBox( subrow.add(new RenderDecoratedBox(
decoration: new BoxDecoration(backgroundColor: const Color(0x7FCCCCFF)), decoration: new BoxDecoration(backgroundColor: const Color(0x7FCCCCFF)),
child: new RenderParagraph(new StyledTextSpan(style, <TextSpan>[new PlainTextSpan('foo foo foo foo')])) child: new RenderParagraph(new TextSpan(style: style, text: 'foo foo foo foo'))
)); ));
subrow.add(new RenderSolidColorBox(const Color(0x7FCCFFFF), desiredSize: new Size(30.0, 40.0))); subrow.add(new RenderSolidColorBox(const Color(0x7FCCFFFF), desiredSize: new Size(30.0, 40.0)));
row.add(subrow); row.add(subrow);
...@@ -48,7 +48,7 @@ void main() { ...@@ -48,7 +48,7 @@ void main() {
void addJustificationRow(FlexJustifyContent justify) { void addJustificationRow(FlexJustifyContent justify) {
const TextStyle style = const TextStyle(color: const Color(0xFF000000)); const TextStyle style = const TextStyle(color: const Color(0xFF000000));
RenderParagraph paragraph = new RenderParagraph(new StyledTextSpan(style, <TextSpan>[new PlainTextSpan('$justify')])); RenderParagraph paragraph = new RenderParagraph(new TextSpan(style: style, text: '$justify'));
table.add(new RenderPadding(child: paragraph, padding: new EdgeDims.only(top: 20.0))); table.add(new RenderPadding(child: paragraph, padding: new EdgeDims.only(top: 20.0)));
RenderFlex row = new RenderFlex(direction: FlexDirection.horizontal); RenderFlex row = new RenderFlex(direction: FlexDirection.horizontal);
row.add(new RenderSolidColorBox(const Color(0xFFFFCCCC), desiredSize: new Size(80.0, 60.0))); row.add(new RenderSolidColorBox(const Color(0xFFFFCCCC), desiredSize: new Size(80.0, 60.0)));
......
...@@ -16,7 +16,7 @@ void main() { ...@@ -16,7 +16,7 @@ void main() {
alignment: const FractionalOffset(0.5, 0.5), alignment: const FractionalOffset(0.5, 0.5),
// We use a RenderParagraph to display the text 'Hello, world.' without // We use a RenderParagraph to display the text 'Hello, world.' without
// any explicit styling. // any explicit styling.
child: new RenderParagraph(new PlainTextSpan('Hello, world.')) child: new RenderParagraph(new TextSpan(text: 'Hello, world.'))
) )
); );
} }
...@@ -97,9 +97,9 @@ class RenderDots extends RenderBox { ...@@ -97,9 +97,9 @@ class RenderDots extends RenderBox {
void main() { void main() {
// Create some styled text to tell the user to interact with the app. // Create some styled text to tell the user to interact with the app.
RenderParagraph paragraph = new RenderParagraph( RenderParagraph paragraph = new RenderParagraph(
new StyledTextSpan( new TextSpan(
new TextStyle(color: Colors.black87), style: new TextStyle(color: Colors.black87),
<TextSpan>[ new PlainTextSpan("Touch me!") ] text: "Touch me!"
) )
); );
// A stack is a render object that layers its children on top of each other. // A stack is a render object that layers its children on top of each other.
......
...@@ -34,9 +34,24 @@ final TextStyle _kUnderline = const TextStyle( ...@@ -34,9 +34,24 @@ final TextStyle _kUnderline = const TextStyle(
Widget toStyledText(String name, String text) { Widget toStyledText(String name, String text) {
TextStyle lineStyle = (name == "Dave") ? _kDaveStyle : _kHalStyle; TextStyle lineStyle = (name == "Dave") ? _kDaveStyle : _kHalStyle;
return new StyledText( return new RichText(
key: new Key(text), key: new Key(text),
elements: [lineStyle, [_kBold, [_kUnderline, name], ":"], text] text: new TextSpan(
style: lineStyle,
children: <TextSpan>[
new TextSpan(
style: _kBold,
children: <TextSpan>[
new TextSpan(
style: _kUnderline,
text: name
),
new TextSpan(text: ':')
]
),
new TextSpan(text: text)
]
)
); );
} }
......
...@@ -240,9 +240,7 @@ List<TextPainter> _initPainters(List<String> labels) { ...@@ -240,9 +240,7 @@ List<TextPainter> _initPainters(List<String> labels) {
for (int i = 0; i < painters.length; ++i) { for (int i = 0; i < painters.length; ++i) {
String label = labels[i]; String label = labels[i];
TextPainter painter = new TextPainter( TextPainter painter = new TextPainter(
new StyledTextSpan(style, [ new TextSpan(style: style, text: label)
new PlainTextSpan(label)
])
); );
painter painter
..maxWidth = double.INFINITY ..maxWidth = double.INFINITY
......
...@@ -9,92 +9,86 @@ import 'text_editing.dart'; ...@@ -9,92 +9,86 @@ import 'text_editing.dart';
import 'text_style.dart'; import 'text_style.dart';
/// An immutable span of text. /// An immutable span of text.
abstract class TextSpan { class TextSpan {
// This class must be immutable, because we won't notice when it changes. const TextSpan({
const TextSpan(); this.style,
void build(ui.ParagraphBuilder builder); this.text,
ui.ParagraphStyle get paragraphStyle => null; this.children
String toPlainText(); // for semantics });
String toString([String prefix = '']); // for debugging
} /// The style to apply to the text and the children.
final TextStyle style;
/// An immutable span of unstyled text.
class PlainTextSpan extends TextSpan {
const PlainTextSpan(this.text);
/// The text contained in the span. /// The text contained in the span.
///
/// If both text and children are non-null, the text will preceed the
/// children.
final String text; final String text;
void build(ui.ParagraphBuilder builder) { /// Additional spans to include as children.
assert(text != null); ///
builder.addText(text); /// If both text and children are non-null, the text will preceed the
} /// children.
bool operator ==(dynamic other) {
if (other is! PlainTextSpan)
return false;
final PlainTextSpan typedOther = other;
return text == typedOther.text;
}
int get hashCode => text.hashCode;
String toPlainText() => text;
String toString([String prefix = '']) => '$prefix$runtimeType: "$text"';
}
/// An immutable text span that applies a style to a list of children.
class StyledTextSpan extends TextSpan {
const StyledTextSpan(this.style, this.children);
/// The style to apply to the children.
final TextStyle style;
/// The children to which the style is applied.
final List<TextSpan> children; final List<TextSpan> children;
void build(ui.ParagraphBuilder builder) { void build(ui.ParagraphBuilder builder) {
assert(style != null); final bool hasStyle = style != null;
assert(children != null); if (hasStyle)
builder.pushStyle(style.textStyle); builder.pushStyle(style.textStyle);
for (TextSpan child in children) { if (text != null)
assert(child != null); builder.addText(text);
child.build(builder); if (children != null) {
for (TextSpan child in children) {
assert(child != null);
child.build(builder);
}
}
if (hasStyle)
builder.pop();
}
void writePlainText(StringBuffer result) {
if (text != null)
result.write(text);
if (children != null) {
for (TextSpan child in children)
child.writePlainText(result);
} }
builder.pop();
} }
ui.ParagraphStyle get paragraphStyle => style.paragraphStyle; String toString([String prefix = '']) {
StringBuffer buffer = new StringBuffer();
buffer.writeln('$prefix$runtimeType:');
String indent = '$prefix ';
buffer.writeln(style.toString(indent));
if (text != null)
buffer.writeln('$indent"$text"');
for (TextSpan child in children)
buffer.writeln(child.toString(indent));
return buffer.toString();
}
bool operator ==(dynamic other) { bool operator ==(dynamic other) {
if (identical(this, other)) if (identical(this, other))
return true; return true;
if (other is! StyledTextSpan) if (other is! TextSpan)
return false; return false;
final StyledTextSpan typedOther = other; final TextSpan typedOther = other;
if (style != typedOther.style || if (typedOther.text != text)
children.length != typedOther.children.length)
return false; return false;
for (int i = 0; i < children.length; ++i) { if (typedOther.style != style)
if (children[i] != typedOther.children[i]) return false;
return false; if ((typedOther.children == null) != (children == null))
return false;
if (children != null) {
for (int i = 0; i < children.length; ++i) {
if (typedOther.children[i] != children[i])
return false;
}
} }
return true; return true;
} }
int get hashCode => hashValues(style, text, hashList(children));
int get hashCode => hashValues(style, hashList(children));
String toPlainText() => children.map((TextSpan child) => child.toPlainText()).join();
String toString([String prefix = '']) {
List<String> result = <String>[];
result.add('$prefix$runtimeType:');
var indent = '$prefix ';
result.add('${style.toString(indent)}');
for (TextSpan child in children)
result.add(child.toString(indent));
return result.join('\n');
}
} }
/// An object that paints a [TextSpan] into a canvas. /// An object that paints a [TextSpan] into a canvas.
...@@ -115,7 +109,7 @@ class TextPainter { ...@@ -115,7 +109,7 @@ class TextPainter {
_text = value; _text = value;
ui.ParagraphBuilder builder = new ui.ParagraphBuilder(); ui.ParagraphBuilder builder = new ui.ParagraphBuilder();
_text.build(builder); _text.build(builder);
_paragraph = builder.build(_text.paragraphStyle ?? new ui.ParagraphStyle()); _paragraph = builder.build(_text.style?.paragraphStyle ?? new ui.ParagraphStyle());
_needsLayout = true; _needsLayout = true;
} }
......
...@@ -19,7 +19,7 @@ final String _kZeroWidthSpace = new String.fromCharCode(0x200B); ...@@ -19,7 +19,7 @@ final String _kZeroWidthSpace = new String.fromCharCode(0x200B);
/// A single line of editable text. /// A single line of editable text.
class RenderEditableLine extends RenderBox { class RenderEditableLine extends RenderBox {
RenderEditableLine({ RenderEditableLine({
StyledTextSpan text, TextSpan text,
Color cursorColor, Color cursorColor,
bool showCursor: false, bool showCursor: false,
Color selectionColor, Color selectionColor,
...@@ -49,12 +49,12 @@ class RenderEditableLine extends RenderBox { ...@@ -49,12 +49,12 @@ class RenderEditableLine extends RenderBox {
ValueChanged<TextSelection> onSelectionChanged; ValueChanged<TextSelection> onSelectionChanged;
/// The text to display /// The text to display
StyledTextSpan get text => _textPainter.text; TextSpan get text => _textPainter.text;
final TextPainter _textPainter; final TextPainter _textPainter;
void set text(StyledTextSpan value) { void set text(TextSpan value) {
if (_textPainter.text == value) if (_textPainter.text == value)
return; return;
StyledTextSpan oldStyledText = _textPainter.text; TextSpan oldStyledText = _textPainter.text;
if (oldStyledText.style != value.style) if (oldStyledText.style != value.style)
_layoutTemplate = null; _layoutTemplate = null;
_textPainter.text = value; _textPainter.text = value;
......
...@@ -100,7 +100,9 @@ class RenderParagraph extends RenderBox { ...@@ -100,7 +100,9 @@ class RenderParagraph extends RenderBox {
Iterable<SemanticAnnotator> getSemanticAnnotators() sync* { Iterable<SemanticAnnotator> getSemanticAnnotators() sync* {
yield (SemanticsNode node) { yield (SemanticsNode node) {
node.label = text.toPlainText(); StringBuffer buffer = new StringBuffer();
text.writePlainText(buffer);
node.label = buffer.toString();
}; };
} }
......
...@@ -1405,12 +1405,12 @@ class Flexible extends ParentDataWidget<Flex> { ...@@ -1405,12 +1405,12 @@ class Flexible extends ParentDataWidget<Flex> {
} }
} }
/// A raw paragraph of text. /// A paragraph of rich text.
/// ///
/// This class is rarely used directly. Instead, consider using [Text], which /// This class is rarely used directly. Instead, consider using [Text], which
/// integrates with [DefaultTextStyle]. /// integrates with [DefaultTextStyle].
class RawText extends LeafRenderObjectWidget { class RichText extends LeafRenderObjectWidget {
RawText({ Key key, this.text }) : super(key: key) { RichText({ Key key, this.text }) : super(key: key) {
assert(text != null); assert(text != null);
} }
...@@ -1418,45 +1418,11 @@ class RawText extends LeafRenderObjectWidget { ...@@ -1418,45 +1418,11 @@ class RawText extends LeafRenderObjectWidget {
RenderParagraph createRenderObject() => new RenderParagraph(text); RenderParagraph createRenderObject() => new RenderParagraph(text);
void updateRenderObject(RenderParagraph renderObject, RawText oldWidget) { void updateRenderObject(RenderParagraph renderObject, RichText oldWidget) {
renderObject.text = text; renderObject.text = text;
} }
} }
/// A convience widget for paragraphs of text with heterogeneous style.
///
/// The elements parameter is a recursive list of lists that matches the
/// following grammar:
///
/// `elements ::= "string" | [<text-style> <elements>*]``
///
/// Where "string" is text to display and text-style is an instance of
/// TextStyle. The text-style applies to all of the elements that follow.
class StyledText extends StatelessComponent {
StyledText({ this.elements, Key key }) : super(key: key) {
assert(_toSpan(elements) != null);
}
/// The recursive list of lists that describes the text and style to paint.
final dynamic elements;
TextSpan _toSpan(dynamic element) {
if (element is String)
return new PlainTextSpan(element);
if (element is Iterable) {
dynamic first = element.first;
if (first is! TextStyle)
throw new ArgumentError("First element of Iterable is a ${first.runtimeType} not a TextStyle");
return new StyledTextSpan(first, element.skip(1).map(_toSpan).toList());
}
throw new ArgumentError("Element is ${element.runtimeType} not a String or an Iterable");
}
Widget build(BuildContext context) {
return new RawText(text: _toSpan(elements));
}
}
/// The text style to apply to descendant [Text] widgets without explicit style. /// The text style to apply to descendant [Text] widgets without explicit style.
class DefaultTextStyle extends InheritedWidget { class DefaultTextStyle extends InheritedWidget {
DefaultTextStyle({ DefaultTextStyle({
...@@ -1504,17 +1470,20 @@ class Text extends StatelessComponent { ...@@ -1504,17 +1470,20 @@ class Text extends StatelessComponent {
/// replace the closest enclosing [DefaultTextStyle]. /// replace the closest enclosing [DefaultTextStyle].
final TextStyle style; final TextStyle style;
TextStyle _getEffectiveStyle(BuildContext context) {
if (style == null || style.inherit)
return DefaultTextStyle.of(context)?.merge(style) ?? style;
else
return style;
}
Widget build(BuildContext context) { Widget build(BuildContext context) {
TextSpan text = new PlainTextSpan(data); return new RichText(
TextStyle combinedStyle; text: new TextSpan(
if (style == null || style.inherit) { style: _getEffectiveStyle(context),
combinedStyle = DefaultTextStyle.of(context)?.merge(style) ?? style; text: data
} else { )
combinedStyle = style; );
}
if (combinedStyle != null)
text = new StyledTextSpan(combinedStyle, <TextSpan>[text]);
return new RawText(text: text);
} }
void debugFillDescription(List<String> description) { void debugFillDescription(List<String> description) {
......
...@@ -25,7 +25,7 @@ class _CheckedModeBannerPainter extends CustomPainter { ...@@ -25,7 +25,7 @@ class _CheckedModeBannerPainter extends CustomPainter {
); );
static final TextPainter textPainter = new TextPainter() static final TextPainter textPainter = new TextPainter()
..text = new StyledTextSpan(kTextStyles, <TextSpan>[new PlainTextSpan('SLOW MODE')]) ..text = new TextSpan(style: kTextStyles, text: 'SLOW MODE')
..maxWidth = kOffset * 2.0 ..maxWidth = kOffset * 2.0
..maxHeight = kHeight ..maxHeight = kHeight
..layout(); ..layout();
......
...@@ -112,7 +112,7 @@ class InputValue { ...@@ -112,7 +112,7 @@ class InputValue {
return typedOther.text == text return typedOther.text == text
&& typedOther.selection == selection && typedOther.selection == selection
&& typedOther.composing == composing; && typedOther.composing == composing;
} }
int get hashCode => hashValues( int get hashCode => hashValues(
text.hashCode, text.hashCode,
...@@ -126,7 +126,7 @@ class InputValue { ...@@ -126,7 +126,7 @@ class InputValue {
TextRange composing TextRange composing
}) { }) {
return new InputValue ( return new InputValue (
text: text ?? this.text, text: text ?? this.text,
selection: selection ?? this.selection, selection: selection ?? this.selection,
composing: composing ?? this.composing composing: composing ?? this.composing
); );
...@@ -394,24 +394,27 @@ class _EditableLineWidget extends LeafRenderObjectWidget { ...@@ -394,24 +394,27 @@ class _EditableLineWidget extends LeafRenderObjectWidget {
..paintOffset = paintOffset; ..paintOffset = paintOffset;
} }
StyledTextSpan get _styledTextSpan { TextSpan get _styledTextSpan {
if (!hideText && value.composing.isValid) { if (!hideText && value.composing.isValid) {
TextStyle composingStyle = style.merge( TextStyle composingStyle = style.merge(
const TextStyle(decoration: TextDecoration.underline) const TextStyle(decoration: TextDecoration.underline)
); );
return new StyledTextSpan(style, <TextSpan>[ return new TextSpan(
new PlainTextSpan(value.composing.textBefore(value.text)), style: style,
new StyledTextSpan(composingStyle, <TextSpan>[ children: <TextSpan>[
new PlainTextSpan(value.composing.textInside(value.text)) new TextSpan(text: value.composing.textBefore(value.text)),
]), new TextSpan(
new PlainTextSpan(value.composing.textAfter(value.text)) style: composingStyle,
text: value.composing.textInside(value.text)
),
new TextSpan(text: value.composing.textAfter(value.text))
]); ]);
} }
String text = value.text; String text = value.text;
if (hideText) if (hideText)
text = new String.fromCharCodes(new List<int>.filled(text.length, 0x2022)); text = new String.fromCharCodes(new List<int>.filled(text.length, 0x2022));
return new StyledTextSpan(style, <TextSpan>[ new PlainTextSpan(text) ]); return new TextSpan(style: style, text: text);
} }
} }
...@@ -172,7 +172,7 @@ class _SemanticsDebuggerEntry { ...@@ -172,7 +172,7 @@ class _SemanticsDebuggerEntry {
message = message.trim(); message = message.trim();
if (message != '') { if (message != '') {
textPainter ??= new TextPainter(); textPainter ??= new TextPainter();
textPainter.text = new StyledTextSpan(textStyles, <TextSpan>[new PlainTextSpan(message)]); textPainter.text = new TextSpan(style: textStyles, text: message);
textPainter.maxWidth = rect.width; textPainter.maxWidth = rect.width;
textPainter.maxHeight = rect.height; textPainter.maxHeight = rect.height;
textPainter.layout(); textPainter.layout();
......
...@@ -15,11 +15,9 @@ class TestBlockPainter extends Painter { ...@@ -15,11 +15,9 @@ class TestBlockPainter extends Painter {
void main() { void main() {
test('block intrinsics', () { test('block intrinsics', () {
RenderParagraph paragraph = new RenderParagraph( RenderParagraph paragraph = new RenderParagraph(
new StyledTextSpan( new TextSpan(
new TextStyle( style: new TextStyle(height: 1.0),
height: 1.0 text: 'Hello World'
),
<TextSpan>[new PlainTextSpan('Hello World')]
) )
); );
const BoxConstraints unconstrained = const BoxConstraints(); const BoxConstraints unconstrained = const BoxConstraints();
......
...@@ -15,7 +15,7 @@ void main() { ...@@ -15,7 +15,7 @@ void main() {
root = new RenderPositionedBox( root = new RenderPositionedBox(
child: new RenderCustomPaint( child: new RenderCustomPaint(
child: child = text = new RenderParagraph(new PlainTextSpan('Hello World')), child: child = text = new RenderParagraph(new TextSpan(text: 'Hello World')),
painter: new TestCallbackPainter( painter: new TestCallbackPainter(
onPaint: () { onPaint: () {
baseline1 = child.getDistanceToBaseline(TextBaseline.alphabetic); baseline1 = child.getDistanceToBaseline(TextBaseline.alphabetic);
...@@ -29,7 +29,7 @@ void main() { ...@@ -29,7 +29,7 @@ void main() {
root = new RenderPositionedBox( root = new RenderPositionedBox(
child: new RenderCustomPaint( child: new RenderCustomPaint(
child: child = new RenderOverflowBox( child: child = new RenderOverflowBox(
child: text = new RenderParagraph(new PlainTextSpan('Hello World')), child: text = new RenderParagraph(new TextSpan(text: 'Hello World')),
maxHeight: height1 / 2.0, maxHeight: height1 / 2.0,
alignment: const FractionalOffset(0.0, 0.0) alignment: const FractionalOffset(0.0, 0.0)
), ),
......
...@@ -35,9 +35,7 @@ class Label extends Node { ...@@ -35,9 +35,7 @@ class Label extends Node {
void paint(Canvas canvas) { void paint(Canvas canvas) {
if (_painter == null) { if (_painter == null) {
PlainTextSpan textSpan = new PlainTextSpan(_text); _painter = new TextPainter(new TextSpan(style: _textStyle, text: _text));
StyledTextSpan styledTextSpan = new StyledTextSpan(_textStyle, <TextSpan>[textSpan]);
_painter = new TextPainter(styledTextSpan);
_painter.maxWidth = double.INFINITY; _painter.maxWidth = double.INFINITY;
_painter.minWidth = 0.0; _painter.minWidth = 0.0;
......
...@@ -166,9 +166,9 @@ class ChartPainter { ...@@ -166,9 +166,9 @@ class ChartPainter {
..value = _roundToPlaces(data.startY + stepSize * i, data.roundToPlaces); ..value = _roundToPlaces(data.startY + stepSize * i, data.roundToPlaces);
if (gridline.value < data.startY || gridline.value > data.endY) if (gridline.value < data.startY || gridline.value > data.endY)
continue; // TODO(jackson): Align things so this doesn't ever happen continue; // TODO(jackson): Align things so this doesn't ever happen
TextSpan text = new StyledTextSpan( TextSpan text = new TextSpan(
_textTheme.body1, style: _textTheme.body1,
[new PlainTextSpan("${gridline.value}")] text: '${gridline.value}'
); );
gridline.labelPainter = new TextPainter(text) gridline.labelPainter = new TextPainter(text)
..maxWidth = _rect.width ..maxWidth = _rect.width
...@@ -213,9 +213,9 @@ class ChartPainter { ...@@ -213,9 +213,9 @@ class ChartPainter {
..start = _convertPointToRectSpace(new Point(data.startX, data.indicatorLine), markerRect) ..start = _convertPointToRectSpace(new Point(data.startX, data.indicatorLine), markerRect)
..end = _convertPointToRectSpace(new Point(data.endX, data.indicatorLine), markerRect); ..end = _convertPointToRectSpace(new Point(data.endX, data.indicatorLine), markerRect);
if (data.indicatorText != null) { if (data.indicatorText != null) {
TextSpan text = new StyledTextSpan( TextSpan text = new TextSpan(
_textTheme.body1, style: _textTheme.body1,
<TextSpan>[new PlainTextSpan("${data.indicatorText}")] text: '${data.indicatorText}'
); );
_indicator.labelPainter = new TextPainter(text) _indicator.labelPainter = new TextPainter(text)
..maxWidth = markerRect.width ..maxWidth = markerRect.width
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment