Merge pull request #1471 from abarth/paint_selection
Input should paint selections
This commit is contained in:
@@ -18,6 +18,7 @@ export 'src/painting/colors.dart';
|
||||
export 'src/painting/decoration.dart';
|
||||
export 'src/painting/edge_dims.dart';
|
||||
export 'src/painting/shadows.dart';
|
||||
export 'src/painting/text_editing.dart';
|
||||
export 'src/painting/text_painter.dart';
|
||||
export 'src/painting/text_style.dart';
|
||||
export 'src/painting/transforms.dart';
|
||||
|
||||
@@ -20,6 +20,7 @@ class Input extends StatefulComponent {
|
||||
Input({
|
||||
GlobalKey key,
|
||||
this.initialValue: '',
|
||||
this.initialSelection,
|
||||
this.keyboardType: KeyboardType.text,
|
||||
this.icon,
|
||||
this.labelText,
|
||||
@@ -35,9 +36,12 @@ class Input extends StatefulComponent {
|
||||
assert(key != null);
|
||||
}
|
||||
|
||||
/// Initial editable text for the input field.
|
||||
/// The initial editable text for the input field.
|
||||
final String initialValue;
|
||||
|
||||
/// The initial selection for this input field.
|
||||
final TextSelection initialSelection;
|
||||
|
||||
/// The type of keyboard to use for editing the text.
|
||||
final KeyboardType keyboardType;
|
||||
|
||||
@@ -90,6 +94,7 @@ class _InputState extends State<Input> {
|
||||
_value = config.initialValue;
|
||||
_editableString = new EditableString(
|
||||
text: _value,
|
||||
selection: config.initialSelection,
|
||||
onUpdated: _handleTextUpdated,
|
||||
onSubmitted: _handleTextSubmitted
|
||||
);
|
||||
@@ -215,7 +220,8 @@ class _InputState extends State<Input> {
|
||||
focused: focused,
|
||||
style: textStyle,
|
||||
hideText: config.hideText,
|
||||
cursorColor: cursorColor
|
||||
cursorColor: cursorColor,
|
||||
selectionColor: cursorColor
|
||||
)
|
||||
));
|
||||
|
||||
|
||||
144
packages/flutter/lib/src/painting/text_editing.dart
Normal file
144
packages/flutter/lib/src/painting/text_editing.dart
Normal file
@@ -0,0 +1,144 @@
|
||||
// Copyright 2016 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.
|
||||
|
||||
/// Whether a [TextPosition] is visually upstream or downstream of its offset.
|
||||
///
|
||||
/// For example, when a text position exists at a line break, a single offset has
|
||||
/// two visual positions, one prior to the line break (at the end of the first
|
||||
/// line) and one after the line break (at the start of the second line). A text
|
||||
/// affinity disambiguates between those cases. (Something similar happens with
|
||||
/// between runs of bidirectional text.)
|
||||
enum TextAffinity {
|
||||
/// The position has affinity for the upstream side of the text position.
|
||||
///
|
||||
/// For example, if the offset of the text position is a line break, the
|
||||
/// position represents the end of the first line.
|
||||
upstream,
|
||||
|
||||
/// The position has affinity for the downstream side of the text position.
|
||||
///
|
||||
/// For example, if the offset of the text position is a line break, the
|
||||
/// position represents the start of the second line.
|
||||
downstream
|
||||
}
|
||||
|
||||
/// A visual position in a string of text.
|
||||
class TextPosition {
|
||||
const TextPosition({ this.offset, this.affinity: TextAffinity.downstream });
|
||||
|
||||
/// The index of the character just prior to the position.
|
||||
final int offset;
|
||||
|
||||
/// If the offset has more than one visual location (e.g., occurs at a line
|
||||
/// break), which of the two locations is represented by this position.
|
||||
final TextAffinity affinity;
|
||||
}
|
||||
|
||||
/// A range of characters in a string of text.
|
||||
class TextRange {
|
||||
const TextRange({ this.start, this.end });
|
||||
|
||||
/// A text range that starts and ends at offset.
|
||||
const TextRange.collapsed(int offset)
|
||||
: start = offset,
|
||||
end = offset;
|
||||
|
||||
/// A text range that contains nothing and is not in the text.
|
||||
static const TextRange empty = const TextRange(start: -1, end: -1);
|
||||
|
||||
/// The index of the first character in the range.
|
||||
final int start;
|
||||
|
||||
/// The next index after the characters in this range.
|
||||
final int end;
|
||||
|
||||
/// Whether this range represents a valid position in the text.
|
||||
bool get isValid => start >= 0 && end >= 0;
|
||||
|
||||
/// Whether this range is empty (but still potentially placed inside the text).
|
||||
bool get isCollapsed => start == end;
|
||||
|
||||
/// Whether the start of this range preceeds the end.
|
||||
bool get isNormalized => end >= start;
|
||||
|
||||
/// The text before this range.
|
||||
String textBefore(String text) {
|
||||
assert(isNormalized);
|
||||
return text.substring(0, start);
|
||||
}
|
||||
|
||||
/// The text after this range.
|
||||
String textAfter(String text) {
|
||||
assert(isNormalized);
|
||||
return text.substring(end);
|
||||
}
|
||||
|
||||
/// The text inside this range.
|
||||
String textInside(String text) {
|
||||
assert(isNormalized);
|
||||
return text.substring(start, end);
|
||||
}
|
||||
}
|
||||
|
||||
/// A range of text that represents a selection.
|
||||
class TextSelection extends TextRange {
|
||||
const TextSelection({
|
||||
int baseOffset,
|
||||
int extentOffset,
|
||||
this.affinity: TextAffinity.downstream,
|
||||
this.isDirectional: false
|
||||
}) : baseOffset = baseOffset,
|
||||
extentOffset = extentOffset,
|
||||
super(
|
||||
start: baseOffset < extentOffset ? baseOffset : extentOffset,
|
||||
end: baseOffset < extentOffset ? extentOffset : baseOffset
|
||||
);
|
||||
|
||||
const TextSelection.collapsed({
|
||||
int offset,
|
||||
this.affinity: TextAffinity.downstream,
|
||||
this.isDirectional: false
|
||||
}) : baseOffset = offset, extentOffset = offset, super.collapsed(offset);
|
||||
|
||||
/// The offset at which the selection originates.
|
||||
///
|
||||
/// Might be larger than, smaller than, or equal to extent.
|
||||
final int baseOffset;
|
||||
|
||||
/// The offset at which the selection terminates.
|
||||
///
|
||||
/// When the user uses the arrow keys to adjust the selection, this is the
|
||||
/// value that changes. Similarly, if the current theme paints a caret on one
|
||||
/// side of the selection, this is the location at which to paint the caret.
|
||||
///
|
||||
/// Might be larger than, smaller than, or equal to base.
|
||||
final int extentOffset;
|
||||
|
||||
/// If the the text range is collpased and has more than one visual location
|
||||
/// (e.g., occurs at a line break), which of the two locations to use when
|
||||
/// painting the caret.
|
||||
final TextAffinity affinity;
|
||||
|
||||
/// Whether this selection has disambiguated its base and extent.
|
||||
///
|
||||
/// On some platforms, the base and extent are not disambiguated until the
|
||||
/// first time the user adjusts the selection. At that point, either the start
|
||||
/// or the end of the selection becomes the base and the other one becomes the
|
||||
/// extent and is adjusted.
|
||||
final bool isDirectional;
|
||||
|
||||
/// The position at which the selection originates.
|
||||
///
|
||||
/// Might be larger than, smaller than, or equal to extent.
|
||||
TextPosition get base => new TextPosition(offset: baseOffset, affinity: affinity);
|
||||
|
||||
/// The position at which the selection terminates.
|
||||
///
|
||||
/// When the user uses the arrow keys to adjust the selection, this is the
|
||||
/// value that changes. Similarly, if the current theme paints a caret on one
|
||||
/// side of the selection, this is the location at which to paint the caret.
|
||||
///
|
||||
/// Might be larger than, smaller than, or equal to base.
|
||||
TextPosition get extent => new TextPosition(offset: extentOffset, affinity: affinity);
|
||||
}
|
||||
@@ -5,6 +5,7 @@
|
||||
import 'dart:ui' as ui;
|
||||
|
||||
import 'basic_types.dart';
|
||||
import 'text_editing.dart';
|
||||
import 'text_style.dart';
|
||||
|
||||
/// An immutable span of text.
|
||||
@@ -215,4 +216,53 @@ class TextPainter {
|
||||
assert(!_needsLayout && "Please call layout() before paint() to position the text before painting it." is String);
|
||||
_paragraph.paint(canvas, offset);
|
||||
}
|
||||
|
||||
Offset _getOffsetFromUpstream(int offset, Rect caretPrototype) {
|
||||
List<ui.TextBox> boxes = _paragraph.getBoxesForRange(offset - 1, offset);
|
||||
if (boxes.isEmpty)
|
||||
return null;
|
||||
ui.TextBox box = boxes[0];
|
||||
double caretEnd = box.end;
|
||||
double dx = box.direction == ui.TextDirection.rtl ? caretEnd : caretEnd - caretPrototype.width;
|
||||
return new Offset(dx, 0.0);
|
||||
}
|
||||
|
||||
Offset _getOffsetFromDownstream(int offset, Rect caretPrototype) {
|
||||
List<ui.TextBox> boxes = _paragraph.getBoxesForRange(offset, offset + 1);
|
||||
if (boxes.isEmpty)
|
||||
return null;
|
||||
ui.TextBox box = boxes[0];
|
||||
double caretStart = box.start;
|
||||
double dx = box.direction == ui.TextDirection.rtl ? caretStart - caretPrototype.width : caretStart;
|
||||
return new Offset(dx, 0.0);
|
||||
}
|
||||
|
||||
/// Returns the offset at which to paint the caret.
|
||||
Offset getOffsetForCaret(TextPosition position, Rect caretPrototype) {
|
||||
assert(!_needsLayout);
|
||||
int offset = position.offset;
|
||||
// TODO(abarth): Handle the directionality of the text painter itself.
|
||||
const Offset emptyOffset = Offset.zero;
|
||||
switch (position.affinity) {
|
||||
case TextAffinity.upstream:
|
||||
return _getOffsetFromUpstream(offset, caretPrototype)
|
||||
?? _getOffsetFromDownstream(offset, caretPrototype)
|
||||
?? emptyOffset;
|
||||
case TextAffinity.downstream:
|
||||
return _getOffsetFromDownstream(offset, caretPrototype)
|
||||
?? _getOffsetFromUpstream(offset, caretPrototype)
|
||||
?? emptyOffset;
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a list of rects that bound the given selection.
|
||||
///
|
||||
/// A given selection might have more than one rect if this text painter
|
||||
/// contains bidirectional text because logically contiguous text might not be
|
||||
/// visually contiguous.
|
||||
List<ui.TextBox> getBoxesForSelection(TextSelection selection) {
|
||||
assert(!_needsLayout);
|
||||
return _paragraph.getBoxesForRange(selection.start, selection.end);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -11,9 +11,9 @@ import 'object.dart';
|
||||
import 'paragraph.dart';
|
||||
import 'proxy_box.dart' show SizeChangedCallback;
|
||||
|
||||
const _kCursorGap = 1.0; // pixels
|
||||
const _kCursorHeightOffset = 2.0; // pixels
|
||||
const _kCursorWidth = 1.0; // pixels
|
||||
const _kCaretGap = 1.0; // pixels
|
||||
const _kCaretHeightOffset = 2.0; // pixels
|
||||
const _kCaretWidth = 1.0; // pixels
|
||||
|
||||
final String _kZeroWidthSpace = new String.fromCharCode(0x200B);
|
||||
|
||||
@@ -23,11 +23,14 @@ class RenderEditableLine extends RenderBox {
|
||||
StyledTextSpan text,
|
||||
Color cursorColor,
|
||||
bool showCursor: false,
|
||||
Color selectionColor,
|
||||
TextSelection selection,
|
||||
Offset paintOffset: Offset.zero,
|
||||
this.onContentSizeChanged
|
||||
}) : _textPainter = new TextPainter(text),
|
||||
_cursorColor = cursorColor,
|
||||
_showCursor = showCursor,
|
||||
_selection = selection,
|
||||
_paintOffset = paintOffset {
|
||||
assert(!showCursor || cursorColor != null);
|
||||
// TODO(abarth): These min/max values should be the default for TextPainter.
|
||||
@@ -72,6 +75,27 @@ class RenderEditableLine extends RenderBox {
|
||||
markNeedsPaint();
|
||||
}
|
||||
|
||||
Color get selectionColor => _selectionColor;
|
||||
Color _selectionColor;
|
||||
void set selectionColor(Color value) {
|
||||
if (_selectionColor == value)
|
||||
return;
|
||||
_selectionColor = value;
|
||||
markNeedsPaint();
|
||||
}
|
||||
|
||||
List<ui.TextBox> _selectionRects;
|
||||
|
||||
TextSelection get selection => _selection;
|
||||
TextSelection _selection;
|
||||
void set selection(TextSelection value) {
|
||||
if (_selection == value)
|
||||
return;
|
||||
_selection = value;
|
||||
_selectionRects = null;
|
||||
markNeedsPaint();
|
||||
}
|
||||
|
||||
Offset get paintOffset => _paintOffset;
|
||||
Offset _paintOffset;
|
||||
void set paintOffset(Offset value) {
|
||||
@@ -144,10 +168,14 @@ class RenderEditableLine extends RenderBox {
|
||||
_constraintsForCurrentLayout = constraints;
|
||||
}
|
||||
|
||||
Rect _caretPrototype;
|
||||
|
||||
void performLayout() {
|
||||
size = new Size(constraints.maxWidth, constraints.constrainHeight(_preferredHeight));
|
||||
_caretPrototype = new Rect.fromLTWH(0.0, _kCaretHeightOffset, _kCaretWidth, size.height - 2.0 * _kCaretHeightOffset);
|
||||
_selectionRects = null;
|
||||
_layoutText(new BoxConstraints(minHeight: constraints.minHeight, maxHeight: constraints.maxHeight));
|
||||
Size contentSize = new Size(_textPainter.width + _kCursorGap + _kCursorWidth, _textPainter.height);
|
||||
Size contentSize = new Size(_textPainter.width + _kCaretGap + _kCaretWidth, _textPainter.height);
|
||||
if (_contentSize != contentSize) {
|
||||
_contentSize = contentSize;
|
||||
if (onContentSizeChanged != null)
|
||||
@@ -155,20 +183,41 @@ class RenderEditableLine extends RenderBox {
|
||||
}
|
||||
}
|
||||
|
||||
void _paintContents(PaintingContext context, Offset offset) {
|
||||
_textPainter.paint(context.canvas, offset + _paintOffset);
|
||||
void _paintCaret(Canvas canvas, Offset effectiveOffset) {
|
||||
Offset caretOffset = _textPainter.getOffsetForCaret(_selection.extent, _caretPrototype);
|
||||
Paint paint = new Paint()..color = _cursorColor;
|
||||
canvas.drawRect(_caretPrototype.shift(caretOffset + effectiveOffset), paint);
|
||||
}
|
||||
|
||||
if (_showCursor) {
|
||||
Rect cursorRect = new Rect.fromLTWH(
|
||||
offset.dx + _paintOffset.dx + _contentSize.width - _kCursorWidth,
|
||||
offset.dy + _paintOffset.dy + _kCursorHeightOffset,
|
||||
_kCursorWidth,
|
||||
size.height - 2.0 * _kCursorHeightOffset
|
||||
void _paintSelection(Canvas canvas, Offset effectiveOffset) {
|
||||
assert(_selectionRects != null);
|
||||
Paint paint = new Paint()..color = _selectionColor;
|
||||
for (ui.TextBox box in _selectionRects) {
|
||||
Rect selectionRect = new Rect.fromLTWH(
|
||||
effectiveOffset.dx + box.left,
|
||||
effectiveOffset.dy + _kCaretHeightOffset,
|
||||
box.right - box.left,
|
||||
size.height - 2.0 * _kCaretHeightOffset
|
||||
);
|
||||
context.canvas.drawRect(cursorRect, new Paint()..color = _cursorColor);
|
||||
canvas.drawRect(selectionRect, paint);
|
||||
}
|
||||
}
|
||||
|
||||
void _paintContents(PaintingContext context, Offset offset) {
|
||||
Offset effectiveOffset = offset + _paintOffset;
|
||||
|
||||
if (_selection != null) {
|
||||
if (_selection.isCollapsed && _showCursor && cursorColor != null) {
|
||||
_paintCaret(context.canvas, effectiveOffset);
|
||||
} else if (!_selection.isCollapsed && _selectionColor != null) {
|
||||
_selectionRects ??= _textPainter.getBoxesForSelection(_selection);
|
||||
_paintSelection(context.canvas, effectiveOffset);
|
||||
}
|
||||
}
|
||||
|
||||
_textPainter.paint(context.canvas, effectiveOffset);
|
||||
}
|
||||
|
||||
bool get _hasVisualOverflow => _contentSize.width > size.width;
|
||||
|
||||
void paint(PaintingContext context, Offset offset) {
|
||||
|
||||
@@ -14,57 +14,19 @@ import 'framework.dart';
|
||||
import 'scrollable.dart';
|
||||
import 'scroll_behavior.dart';
|
||||
|
||||
export 'package:flutter/painting.dart' show TextSelection;
|
||||
|
||||
const Duration _kCursorBlinkHalfPeriod = const Duration(milliseconds: 500);
|
||||
|
||||
/// A range of characters in a string of tet.
|
||||
class TextRange {
|
||||
const TextRange({ this.start, this.end });
|
||||
|
||||
/// A text range that starts and ends at position.
|
||||
const TextRange.collapsed(int position)
|
||||
: start = position,
|
||||
end = position;
|
||||
|
||||
/// A text range that contains nothing and is not in the text.
|
||||
static const TextRange empty = const TextRange(start: -1, end: -1);
|
||||
|
||||
/// The index of the first character in the range.
|
||||
final int start;
|
||||
|
||||
/// The next index after the characters in this range.
|
||||
final int end;
|
||||
|
||||
/// Whether this range represents a valid position in the text.
|
||||
bool get isValid => start >= 0 && end >= 0;
|
||||
|
||||
/// Whether this range is empty (but still potentially placed inside the text).
|
||||
bool get isCollapsed => start == end;
|
||||
|
||||
/// The text before this range.
|
||||
String textBefore(String text) {
|
||||
return text.substring(0, start);
|
||||
}
|
||||
|
||||
/// The text after this range.
|
||||
String textAfter(String text) {
|
||||
return text.substring(end);
|
||||
}
|
||||
|
||||
/// The text inside this range.
|
||||
String textInside(String text) {
|
||||
return text.substring(start, end);
|
||||
}
|
||||
}
|
||||
|
||||
class _KeyboardClientImpl implements KeyboardClient {
|
||||
_KeyboardClientImpl({
|
||||
this.text: '',
|
||||
String text: '',
|
||||
TextSelection selection,
|
||||
this.onUpdated,
|
||||
this.onSubmitted
|
||||
}) {
|
||||
}) : text = text, selection = selection ?? new TextSelection.collapsed(offset: text.length) {
|
||||
assert(onUpdated != null);
|
||||
assert(onSubmitted != null);
|
||||
selection = new TextRange(start: text.length, end: text.length);
|
||||
}
|
||||
|
||||
/// The current text being edited.
|
||||
@@ -80,7 +42,7 @@ class _KeyboardClientImpl implements KeyboardClient {
|
||||
TextRange composing = TextRange.empty;
|
||||
|
||||
/// The range of text that is currently selected.
|
||||
TextRange selection = TextRange.empty;
|
||||
TextSelection selection;
|
||||
|
||||
/// A keyboard client stub that can be attached to a keyboard service.
|
||||
KeyboardClientStub createStub() {
|
||||
@@ -125,7 +87,7 @@ class _KeyboardClientImpl implements KeyboardClient {
|
||||
void commitText(String text, int newCursorPosition) {
|
||||
// TODO(abarth): Why is |newCursorPosition| always 1?
|
||||
TextRange committedRange = _replaceOrAppend(composing, text);
|
||||
selection = new TextRange.collapsed(committedRange.end);
|
||||
selection = new TextSelection.collapsed(offset: committedRange.end);
|
||||
composing = TextRange.empty;
|
||||
onUpdated();
|
||||
}
|
||||
@@ -138,9 +100,9 @@ class _KeyboardClientImpl implements KeyboardClient {
|
||||
new TextRange(start: selection.end, end: afterRangeEnd);
|
||||
_delete(afterRange);
|
||||
_delete(beforeRange);
|
||||
selection = new TextRange(
|
||||
start: math.max(selection.start - beforeLength, 0),
|
||||
end: math.max(selection.end - beforeLength, 0)
|
||||
selection = new TextSelection(
|
||||
baseOffset: math.max(selection.start - beforeLength, 0),
|
||||
extentOffset: math.max(selection.end - beforeLength, 0)
|
||||
);
|
||||
onUpdated();
|
||||
}
|
||||
@@ -153,12 +115,12 @@ class _KeyboardClientImpl implements KeyboardClient {
|
||||
void setComposingText(String text, int newCursorPosition) {
|
||||
// TODO(abarth): Why is |newCursorPosition| always 1?
|
||||
composing = _replaceOrAppend(composing, text);
|
||||
selection = new TextRange.collapsed(composing.end);
|
||||
selection = new TextSelection.collapsed(offset: composing.end);
|
||||
onUpdated();
|
||||
}
|
||||
|
||||
void setSelection(int start, int end) {
|
||||
selection = new TextRange(start: start, end: end);
|
||||
selection = new TextSelection(baseOffset: start, extentOffset: end);
|
||||
onUpdated();
|
||||
}
|
||||
|
||||
@@ -175,10 +137,12 @@ class _KeyboardClientImpl implements KeyboardClient {
|
||||
class EditableString {
|
||||
EditableString({
|
||||
String text: '',
|
||||
TextSelection selection,
|
||||
VoidCallback onUpdated,
|
||||
VoidCallback onSubmitted
|
||||
}) : _client = new _KeyboardClientImpl(
|
||||
text: text,
|
||||
selection: selection,
|
||||
onUpdated: onUpdated,
|
||||
onSubmitted: onSubmitted
|
||||
);
|
||||
@@ -192,7 +156,7 @@ class EditableString {
|
||||
TextRange get composing => _client.composing;
|
||||
|
||||
/// The range of text that is currently selected.
|
||||
TextRange get selection => _client.selection;
|
||||
TextSelection get selection => _client.selection;
|
||||
|
||||
/// A keyboard client stub that can be attached to a keyboard service.
|
||||
///
|
||||
@@ -215,7 +179,8 @@ class RawEditableLine extends Scrollable {
|
||||
this.focused: false,
|
||||
this.hideText: false,
|
||||
this.style,
|
||||
this.cursorColor
|
||||
this.cursorColor,
|
||||
this.selectionColor
|
||||
}) : super(
|
||||
key: key,
|
||||
initialScrollOffset: 0.0,
|
||||
@@ -237,6 +202,9 @@ class RawEditableLine extends Scrollable {
|
||||
/// The color to use when painting the cursor.
|
||||
final Color cursorColor;
|
||||
|
||||
/// The color to use when painting the selection.
|
||||
final Color selectionColor;
|
||||
|
||||
RawEditableTextState createState() => new RawEditableTextState();
|
||||
}
|
||||
|
||||
@@ -307,9 +275,9 @@ class RawEditableTextState extends ScrollableState<RawEditableLine> {
|
||||
assert(config.focused != null);
|
||||
assert(config.cursorColor != null);
|
||||
|
||||
if (config.focused && _cursorTimer == null)
|
||||
if (_cursorTimer == null && config.focused && config.value.selection.isCollapsed)
|
||||
_startCursorTimer();
|
||||
else if (!config.focused && _cursorTimer != null)
|
||||
else if (_cursorTimer != null && (!config.focused || !config.value.selection.isCollapsed))
|
||||
_stopCursorTimer();
|
||||
|
||||
return new SizeObserver(
|
||||
@@ -319,6 +287,7 @@ class RawEditableTextState extends ScrollableState<RawEditableLine> {
|
||||
style: config.style,
|
||||
cursorColor: config.cursorColor,
|
||||
showCursor: _showCursor,
|
||||
selectionColor: config.selectionColor,
|
||||
hideText: config.hideText,
|
||||
onContentSizeChanged: _handleContentSizeChanged,
|
||||
paintOffset: new Offset(-scrollOffset, 0.0)
|
||||
@@ -334,6 +303,7 @@ class _EditableLineWidget extends LeafRenderObjectWidget {
|
||||
this.style,
|
||||
this.cursorColor,
|
||||
this.showCursor,
|
||||
this.selectionColor,
|
||||
this.hideText,
|
||||
this.onContentSizeChanged,
|
||||
this.paintOffset
|
||||
@@ -343,6 +313,7 @@ class _EditableLineWidget extends LeafRenderObjectWidget {
|
||||
final TextStyle style;
|
||||
final Color cursorColor;
|
||||
final bool showCursor;
|
||||
final Color selectionColor;
|
||||
final bool hideText;
|
||||
final SizeChangedCallback onContentSizeChanged;
|
||||
final Offset paintOffset;
|
||||
@@ -352,6 +323,8 @@ class _EditableLineWidget extends LeafRenderObjectWidget {
|
||||
text: _styledTextSpan,
|
||||
cursorColor: cursorColor,
|
||||
showCursor: showCursor,
|
||||
selectionColor: selectionColor,
|
||||
selection: value.selection,
|
||||
onContentSizeChanged: onContentSizeChanged,
|
||||
paintOffset: paintOffset
|
||||
);
|
||||
@@ -362,6 +335,8 @@ class _EditableLineWidget extends LeafRenderObjectWidget {
|
||||
renderObject.text = _styledTextSpan;
|
||||
renderObject.cursorColor = cursorColor;
|
||||
renderObject.showCursor = showCursor;
|
||||
renderObject.selectionColor = selectionColor;
|
||||
renderObject.selection = value.selection;
|
||||
renderObject.onContentSizeChanged = onContentSizeChanged;
|
||||
renderObject.paintOffset = paintOffset;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user