Adam Barth 64a645352c Give loose contraints to text inside input widget
The input widget scrolls, so it should give its text loose constraints.  That
way the text ends up being its intrinsic size even if put in a context with
tight constraints.

Fixes #298
2015-11-11 09:37:01 -08:00

124 lines
3.7 KiB
Dart

// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/painting.dart';
import 'box.dart';
import 'object.dart';
export 'package:flutter/painting.dart' show
FontStyle,
FontWeight,
PlainTextSpan,
StyledTextSpan,
TextAlign,
TextBaseline,
TextDecoration,
TextDecorationStyle,
TextSpan,
TextStyle,
normal,
bold,
underline,
overline,
lineThrough;
/// A render object that displays a paragraph of text
class RenderParagraph extends RenderBox {
RenderParagraph(
TextSpan text
) : textPainter = new TextPainter(text) {
assert(text != null);
}
final TextPainter textPainter;
BoxConstraints _constraintsForCurrentLayout; // when null, we don't have a current layout
/// The text to display
TextSpan get text => textPainter.text;
void set text(TextSpan value) {
if (textPainter.text == value)
return;
textPainter.text = value;
_constraintsForCurrentLayout = null;
markNeedsLayout();
}
void layoutText(BoxConstraints constraints) {
assert(constraints != null);
if (_constraintsForCurrentLayout == constraints)
return; // already cached this layout
textPainter.maxWidth = constraints.maxWidth;
textPainter.minWidth = constraints.minWidth;
textPainter.minHeight = constraints.minHeight;
textPainter.maxHeight = constraints.maxHeight;
textPainter.layout();
// By default, we shrinkwrap to the intrinsic width.
double width = constraints.constrainWidth(textPainter.maxIntrinsicWidth);
textPainter.minWidth = width;
textPainter.maxWidth = width;
textPainter.layout();
_constraintsForCurrentLayout = constraints;
}
double getMinIntrinsicWidth(BoxConstraints constraints) {
layoutText(constraints);
return constraints.constrainWidth(textPainter.minIntrinsicWidth);
}
double getMaxIntrinsicWidth(BoxConstraints constraints) {
layoutText(constraints);
return constraints.constrainWidth(textPainter.maxIntrinsicWidth);
}
double _getIntrinsicHeight(BoxConstraints constraints) {
layoutText(constraints);
return constraints.constrainHeight(textPainter.size.height);
}
double getMinIntrinsicHeight(BoxConstraints constraints) {
return _getIntrinsicHeight(constraints);
}
double getMaxIntrinsicHeight(BoxConstraints constraints) {
return _getIntrinsicHeight(constraints);
}
double computeDistanceToActualBaseline(TextBaseline baseline) {
assert(!needsLayout);
layoutText(constraints);
return textPainter.computeDistanceToActualBaseline(baseline);
}
bool hitTestSelf(Point position) => true;
void performLayout() {
layoutText(constraints);
size = constraints.constrain(textPainter.size);
}
void paint(PaintingContext context, Offset offset) {
// Ideally we could compute the min/max intrinsic width/height with a
// non-destructive operation. However, currently, computing these values
// will destroy state inside the painter. If that happens, we need to
// get back the correct state by calling _layout again.
//
// TODO(abarth): Make computing the min/max intrinsic width/height
// a non-destructive operation.
layoutText(constraints);
textPainter.paint(context.canvas, offset);
}
// we should probably expose a way to do precise (inter-glpyh) hit testing
String debugDescribeChildren(String prefix) {
return '$prefix \u2558\u2550\u2566\u2550\u2550 text \u2550\u2550\u2550\n'
'${text.toString("$prefix \u2551 ")}\n'
'$prefix \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n'
'$prefix\n';
}
}