You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
samples/web/charts/flutter/lib/src/text_element.dart

184 lines
4.9 KiB

// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import 'package:flutter_web_ui/ui.dart' show TextAlign, TextDirection;
import 'package:charts_common/common.dart' as common
show
MaxWidthStrategy,
TextElement,
TextDirection,
TextMeasurement,
TextStyle;
import 'package:flutter_web/rendering.dart'
show Color, TextBaseline, TextPainter, TextSpan, TextStyle;
/// Flutter implementation for text measurement and painter.
class TextElement implements common.TextElement {
static const ellipsis = '\u{2026}';
@override
final String text;
final double textScaleFactor;
var _painterReady = false;
common.TextStyle _textStyle;
common.TextDirection _textDirection = common.TextDirection.ltr;
int _maxWidth;
common.MaxWidthStrategy _maxWidthStrategy;
TextPainter _textPainter;
common.TextMeasurement _measurement;
double _opacity;
TextElement(this.text, {common.TextStyle style, this.textScaleFactor})
: _textStyle = style;
@override
common.TextStyle get textStyle => _textStyle;
@override
set textStyle(common.TextStyle value) {
if (_textStyle == value) {
return;
}
_textStyle = value;
_painterReady = false;
}
@override
set textDirection(common.TextDirection direction) {
if (_textDirection == direction) {
return;
}
_textDirection = direction;
_painterReady = false;
}
@override
common.TextDirection get textDirection => _textDirection;
@override
int get maxWidth => _maxWidth;
@override
set maxWidth(int value) {
if (_maxWidth == value) {
return;
}
_maxWidth = value;
_painterReady = false;
}
@override
common.MaxWidthStrategy get maxWidthStrategy => _maxWidthStrategy;
@override
set maxWidthStrategy(common.MaxWidthStrategy maxWidthStrategy) {
if (_maxWidthStrategy == maxWidthStrategy) {
return;
}
_maxWidthStrategy = maxWidthStrategy;
_painterReady = false;
}
@override
set opacity(double opacity) {
if (opacity != _opacity) {
_painterReady = false;
_opacity = opacity;
}
}
@override
common.TextMeasurement get measurement {
if (!_painterReady) {
_refreshPainter();
}
return _measurement;
}
/// The estimated distance between where we asked to draw the text (top, left)
/// and where it visually started (top + verticalFontShift, left).
///
/// 10% of reported font height seems to be about right.
int get verticalFontShift {
if (!_painterReady) {
_refreshPainter();
}
return (_textPainter.height * 0.1).ceil();
}
TextPainter get textPainter {
if (!_painterReady) {
_refreshPainter();
}
return _textPainter;
}
/// Create text painter and measure based on current settings
void _refreshPainter() {
_opacity ??= 1.0;
var color = new Color.fromARGB(
(textStyle.color.a * _opacity).round(),
textStyle.color.r,
textStyle.color.g,
textStyle.color.b,
);
_textPainter = new TextPainter(
text: new TextSpan(
text: text,
style: new TextStyle(
color: color,
fontSize: textStyle.fontSize.toDouble(),
fontFamily: textStyle.fontFamily)))
..textDirection = TextDirection.ltr
// TODO Flip once textAlign works
..textAlign = TextAlign.left
// ..textAlign = _textDirection == common.TextDirection.rtl ?
// TextAlign.right : TextAlign.left
..ellipsis = maxWidthStrategy == common.MaxWidthStrategy.ellipsize
? ellipsis
: null;
if (textScaleFactor != null) {
_textPainter.textScaleFactor = textScaleFactor;
}
_textPainter.layout(maxWidth: maxWidth?.toDouble() ?? double.infinity);
final baseline =
_textPainter.computeDistanceToActualBaseline(TextBaseline.alphabetic);
// Estimating the actual draw height to 70% of measures size.
//
// The font reports a size larger than the drawn size, which makes it
// difficult to shift the text around to get it to visually line up
// vertically with other components.
_measurement = new common.TextMeasurement(
horizontalSliceWidth: _textPainter.width,
verticalSliceWidth: _textPainter.height * 0.70,
baseline: baseline);
_painterReady = true;
}
}