提交 61b71a6f 编写于 作者: H Hans Muller

Styling for text fragments

This is a completion of Eric's WIP patch:
https://codereview.chromium.org/1179663005/

Low level support for creating a paragraph that contains
runs of styled text. The styles may be nested.

The Paragraph and RenderParagraph classes have been
replaced by Inline and RenderInline. Styled text is defined
with a tree of InlineText and InlineStyle objects.

R=abarth@chromium.org

Review URL: https://codereview.chromium.org/1177833012.
上级 a7aa9513
......@@ -75,8 +75,12 @@ porchetta bacon kevin meatball meatloaf pig beef ribs chicken. Brisket ribeye
andouille leberkas capicola meatloaf. Chicken pig ball tip pork picanha bresaola
alcatra. Pork pork belly alcatra, flank chuck drumstick biltong doner jowl.
Pancetta meatball tongue tenderloin rump tail jowl boudin.""";
RenderParagraph paragraph = new RenderParagraph(text: meatyString, color: const Color(0xFF009900));
padding = new RenderPadding(padding: const EdgeDims.all(10.0), child: paragraph);
var text = new InlineStyle(
new TextStyle(color: const Color(0xFF009900)),
[new InlineText(meatyString)]);
padding = new RenderPadding(
padding: const EdgeDims.all(10.0),
child: new RenderParagraph(text));
column.add(padding);
// Bottom cell
......
......@@ -20,7 +20,7 @@ void main() {
var table = new RenderFlex(direction: FlexDirection.vertical);
void addRow(FlexJustifyContent justify) {
RenderParagraph paragraph = new RenderParagraph(text: "${justify}");
RenderParagraph paragraph = new RenderParagraph(new InlineText("${justify}"));
table.add(new RenderPadding(child: paragraph, padding: new EdgeDims.only(top: 20.0)));
var row = new RenderFlex(direction: FlexDirection.horizontal);
row.add(new RenderSolidColorBox(const Color(0xFFFFCCCC), desiredSize: new Size(80.0, 60.0)));
......
......@@ -31,9 +31,12 @@ andouille leberkas capicola meatloaf. Chicken pig ball tip pork picanha bresaola
alcatra. Pork pork belly alcatra, flank chuck drumstick biltong doner jowl.
Pancetta meatball tongue tenderloin rump tail jowl boudin.""";
var text = new InlineStyle(
new TextStyle(color: const Color(0xFF009900)),
[new InlineText(meatyString)]);
child = new RenderDecoratedBox(
decoration: new BoxDecoration(backgroundColor: const Color(0xFFFFFFFF)),
child: new RenderParagraph(text: meatyString, color: const Color(0xFF009900))
child: new RenderParagraph(text)
);
flexRoot.add(child);
child.parentData.flex = 1;
......
......@@ -80,13 +80,14 @@ class RenderTouchDemo extends RenderBox {
AppView app;
void main() {
var para = new RenderParagraph(text: "Touch me!");
var paragraph = new RenderParagraph(new InlineText("Touch me!"));
var stack = new RenderStack(children: [
new RenderTouchDemo(),
para,
paragraph,
]);
// Make the paragraph not fill the whole screen so it doesn't eat events.
para.parentData..top = 40.0
..left = 20.0;
// Prevent the RenderParagraph from filling the whole screen so
// that it doesn't eat events.
paragraph.parentData..top = 40.0
..left = 20.0;
app = new AppView(root: stack);
}
......@@ -93,8 +93,6 @@ class EditableText extends Component {
// // style: _cursorStyle
// ));
return new Paragraph(
text: hack
);
return new Text(hack);
}
}
......@@ -7,11 +7,6 @@ import 'dart:sky' as sky;
import 'box.dart';
import 'object.dart';
class RenderInline extends RenderObject {
RenderInline(this.data);
String data;
}
enum FontWeight {
light, // 300
regular, // 400
......@@ -69,6 +64,29 @@ class TextStyle {
return value;
}
void _applyToCSSStyle(sky.CSSStyleDeclaration cssStyle) {
if (color != null) {
cssStyle['color'] = 'rgba(${color.red}, ${color.green}, ${color.blue}, ${color.alpha / 255.0})';
}
if (fontSize != null) {
cssStyle['font-size'] = "${fontSize}px";
}
if (fontWeight != null) {
cssStyle['font-weight'] = const {
FontWeight.light: '300',
FontWeight.regular: '400',
FontWeight.medium: '500',
}[fontWeight];
}
if (textAlign != null) {
cssStyle['text-align'] = const {
TextAlign.left: 'left',
TextAlign.right: 'right',
TextAlign.center: 'center',
}[textAlign];
}
}
String toString([String prefix = '']) {
List<String> result = [];
if (color != null)
......@@ -76,15 +94,63 @@ class TextStyle {
if (fontSize != null)
result.add('${prefix}fontSize: $fontSize');
if (fontWeight != null)
result.add('${prefix}fontWeight: fontWeight');
result.add('${prefix}fontWeight: $fontWeight');
if (textAlign != null)
result.add('${prefix}textAlign: textAlign');
result.add('${prefix}textAlign: $textAlign');
if (result.isEmpty)
return '${prefix}<no style specified>';
return result.join('\n');
}
}
class InlineBase {
sky.Node _toDOM(sky.Document owner);
String toString([String prefix = '']);
}
class InlineText extends InlineBase {
InlineText(this.text) {
assert(text != null);
}
final String text;
sky.Node _toDOM(sky.Document owner) {
return owner.createText(text);
}
String toString([String prefix = '']) => '${prefix}InlineText: "${text}"';
}
class InlineStyle extends InlineBase {
InlineStyle(this.style, this.children) {
assert(style != null && children != null);
}
final TextStyle style;
final List<InlineBase> children;
sky.Node _toDOM(sky.Document owner) {
sky.Element parent = owner.createElement('t');
style._applyToCSSStyle(parent.style);
for (InlineBase child in children) {
parent.appendChild(child._toDOM(owner));
}
return parent;
}
String toString([String prefix = '']) {
List<String> result = [];
result.add('${prefix}InlineStyle:');
var indent = '${prefix} ';
result.add('${style.toString(indent)}');
for (InlineBase child in children) {
result.add(child.toString(indent));
}
return result.join('\n');
}
}
// Unfortunately, using full precision floating point here causes bad layouts
// because floating point math isn't associative. If we add and subtract
// padding, for example, we'll get different values when we estimate sizes and
......@@ -98,36 +164,24 @@ double _applyFloatingPointHack(double layoutValue) {
class RenderParagraph extends RenderBox {
RenderParagraph({
String text,
Color color,
TextStyle style
}) : _style = style {
RenderParagraph(InlineBase inlineValue) {
_layoutRoot.rootElement = _document.createElement('p');
this.text = text;
inline = inlineValue;
}
final sky.Document _document = new sky.Document();
final sky.LayoutRoot _layoutRoot = new sky.LayoutRoot();
String get text => (_layoutRoot.rootElement.firstChild as sky.Text).data;
void set text (String value) {
_layoutRoot.rootElement.setChild(_document.createText(value));
markNeedsLayout();
}
InlineBase _inline;
BoxConstraints _constraintsForCurrentLayout;
TextStyle _style;
TextStyle get style => _style;
void set style (TextStyle value) {
if (_style != value) {
// TODO(hansmuller): decide if a new layout or paint is needed
markNeedsLayout();
_style = value;
}
String get inline => _inline;
void set inline (InlineBase value) {
_inline = value;
_layoutRoot.rootElement.setChild(_inline._toDOM(_document));
markNeedsLayout();
}
BoxConstraints _constraintsForCurrentLayout;
sky.Element _layout(BoxConstraints constraints) {
_layoutRoot.maxWidth = constraints.maxWidth;
_layoutRoot.minWidth = constraints.minWidth;
......@@ -182,31 +236,6 @@ class RenderParagraph extends RenderBox {
if (_constraintsForCurrentLayout != constraints && constraints != null)
_layout(constraints);
if (style != null) {
var cssStyle = _layoutRoot.rootElement.style;
if (style.color != null) {
Color c = style.color;
cssStyle['color'] =
'rgba(${c.red}, ${c.green}, ${c.blue}, ${c.alpha / 255.0})';
}
if (style.fontSize != null) {
cssStyle['font-size'] = "${style.fontSize}px";
}
if (style.fontWeight != null) {
cssStyle['font-weight'] = const {
FontWeight.light: '300',
FontWeight.regular: '400',
FontWeight.medium: '500',
}[style.fontWeight];
}
if (style.textAlign != null) {
cssStyle['text-align'] = const {
TextAlign.left: 'left',
TextAlign.right: 'right',
TextAlign.center: 'center',
}[style.textAlign];
}
}
_layoutRoot.paint(canvas);
}
......@@ -214,9 +243,7 @@ class RenderParagraph extends RenderBox {
String debugDescribeSettings(String prefix) {
String result = '${super.debugDescribeSettings(prefix)}';
if (style != null)
result += '${prefix}style:\n' + style.toString('$prefix ') + '\n';
result += '${prefix}text: ${text}\n';
result += '${prefix}inline: ${inline}\n';
return result;
}
}
......@@ -345,25 +345,22 @@ class Flexible extends ParentDataNode {
: super(child, new FlexBoxParentData()..flex = flex, key: key);
}
class Paragraph extends RenderObjectWrapper {
Paragraph({ String key, this.text, this.style }) : super(key: key);
class Inline extends RenderObjectWrapper {
Inline({ Object key, this.text }) : super(key: key);
RenderParagraph get root => super.root;
RenderParagraph createNode() => new RenderParagraph(text: text, style: style);
RenderParagraph createNode() => new RenderParagraph(text);
final String text;
final TextStyle style;
final InlineBase text;
void syncRenderObject(Widget old) {
super.syncRenderObject(old);
root.text = text;
root.style = style;
root.inline = text;
}
void insert(RenderObjectWrapper child, dynamic slot) {
assert(false);
// Paragraph does not support having children currently
// Inline does not support having children currently
}
}
......@@ -373,7 +370,11 @@ class Text extends Component {
final String data;
final TextStyle style;
bool get interchangeable => true;
Widget build() => new Paragraph(text: data, style: style);
Widget build() {
InlineBase text = new InlineText(data);
if (style != null) text = new InlineStyle(style, [text]);
return new Inline(text: text);
}
}
class Image extends RenderObjectWrapper {
......
......@@ -31,7 +31,7 @@ PAINT FOR FRAME #2 ----------------------------------------------
2 | | | | | | | TestDisplayList() constructor: 800.0 x 600.0
2 | | | | | | | paintChild RenderImage at Point(8.0, 8.0)
2 | | | | | | | | TestDisplayList() constructor: 800.0 x 600.0
2 | | | | | | paintChild RenderPadding at Point(40.0, 20.0)
2 | | | | | | paintChild RenderPadding at Point(40.0, 16.0)
2 | | | | | | | TestDisplayList() constructor: 800.0 x 600.0
2 | | | | | | | paintChild RenderParagraph at Point(24.0, 0.0)
2 | | | | | | | | TestDisplayList() constructor: 800.0 x 600.0
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册