Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions com.unity.uiwidgets/Runtime/painting/text_painter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ public class TextPainter {
TextDirection? _textDirection;
float _textScaleFactor;
Paragraph _layoutTemplate;
Paragraph _layoutCursorTemplate;
Paragraph _paragraph;
bool _needsLayout = true;
int? _maxLines;
Expand Down Expand Up @@ -106,6 +107,7 @@ public float textScaleFactor {
_textScaleFactor = value;
markNeedsLayout();
_layoutTemplate = null;
_layoutCursorTemplate = null;
}
}

Expand All @@ -131,6 +133,7 @@ public InlineSpan text {

if (!Equals(_text == null ? null : _text.style, value == null ? null : value.style)) {
_layoutTemplate = null;
_layoutCursorTemplate = null;
}

_text = value;
Expand All @@ -155,6 +158,7 @@ public TextDirection? textDirection {
_textDirection = value;
markNeedsLayout();
_layoutTemplate = null;
_layoutCursorTemplate = null;
}
}

Expand Down Expand Up @@ -451,6 +455,45 @@ ParagraphStyle _createParagraphStyle(TextDirection defaultTextDirection = TextDi
);
}

ParagraphStyle _createParagraphStyleWithNoStrutStyle(TextDirection defaultTextDirection = TextDirection.ltr) {
D.assert(textDirection != null,
() => "TextPainter.textDirection must be set to a non-null value before using the TextPainter.");
return _text.style?.getParagraphStyle(
textAlign: textAlign,
textDirection: textDirection ?? defaultTextDirection,
textScaleFactor: textScaleFactor,
maxLines: _maxLines,
textHeightBehavior: _textHeightBehavior,
ellipsis: _ellipsis,
locale: _locale
) ?? new ParagraphStyle(
textAlign: textAlign,
textDirection: textDirection ?? defaultTextDirection,
maxLines: maxLines,
textHeightBehavior: _textHeightBehavior,
ellipsis: ellipsis,
locale: locale
);
}

public float preferredCursorHeight {
get {
if (_layoutCursorTemplate == null) {
var builder = new ParagraphBuilder(_createParagraphStyleWithNoStrutStyle(TextDirection.ltr)
); // direction doesn't matter, text is just a space
if (text != null && text.style != null) {
builder.pushStyle(text.style.getTextStyle(textScaleFactor: textScaleFactor));
}

builder.addText(" ");
_layoutCursorTemplate = builder.build();
_layoutCursorTemplate.layout(new ParagraphConstraints(float.PositiveInfinity));
}

return _layoutCursorTemplate.height();
}
}

public float preferredLineHeight {
get {
if (_layoutTemplate == null) {
Expand Down
81 changes: 64 additions & 17 deletions com.unity.uiwidgets/Runtime/rendering/editable.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Unity.UIWidgets.async;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.gestures;
Expand Down Expand Up @@ -385,16 +386,18 @@ void _handleSelectionChange(
TextSelection nextSelection,
SelectionChangedCause cause
) {

bool focusingEmpty = nextSelection.baseOffset == 0
&& nextSelection.extentOffset == 0
&& !hasFocus;
//force to update selection no matter whether the selection really changes
//it should not affect the ui logics except some performance drop
/*bool focusingEmpty = nextSelection.baseOffset == 0
&& nextSelection.extentOffset == 0
&& !hasFocus;
if (nextSelection == selection
&& cause != SelectionChangedCause.keyboard
&& !focusingEmpty) {
Debug.Log("[ZXW2] handle double tap6 <>>>");
return;
}

}*/
onSelectionChanged?.Invoke(nextSelection, this, cause);
}

Expand Down Expand Up @@ -1290,6 +1293,10 @@ public float preferredLineHeight {
get { return _textPainter.preferredLineHeight; }
}

private float preferredCursorHeight {
get { return _textPainter.preferredCursorHeight; }
}

float _preferredHeight(float width) {
bool lockedMax = maxLines != null && minLines == null;
bool lockedBoth = maxLines != null && minLines == maxLines;
Expand Down Expand Up @@ -1454,7 +1461,7 @@ public void selectWordsInRange(Offset from = null, Offset to = null, SelectionCh
? firstWord
: _selectWordAtOffset(
_textPainter.getPositionForOffset(globalToLocal(to - _paintOffset)));

_handleSelectionChange(
new TextSelection(
baseOffset: firstWord.baseOffset,
Expand Down Expand Up @@ -1537,14 +1544,26 @@ Rect _getCaretPrototype {
switch (Application.platform) {
case RuntimePlatform.IPhonePlayer:
return Rect.fromLTWH(0.0f, 0.0f, cursorWidth,
preferredLineHeight + 2.0f);
preferredCursorHeight + 2.0f);
default:
return Rect.fromLTWH(0.0f, EditableUtils._kCaretHeightOffset, cursorWidth,
preferredLineHeight - 2.0f * EditableUtils._kCaretHeightOffset);
return Rect.fromLTWH(0.0f, 0.0f, cursorWidth,
preferredCursorHeight);
}
}
}

Rect _getCaretPrototypeForEmptyLine {
get {
switch (Application.platform) {
case RuntimePlatform.IPhonePlayer:
return Rect.fromLTWH(0.0f, (preferredLineHeight - preferredCursorHeight) / 2, cursorWidth,
preferredCursorHeight + 2.0f);
default:
return Rect.fromLTWH(0.0f, (preferredLineHeight - preferredCursorHeight) / 2, cursorWidth,
preferredCursorHeight);
}
}
}


protected override void performLayout() {
BoxConstraints constraints = this.constraints;
Expand Down Expand Up @@ -1577,13 +1596,37 @@ void _paintCaret(Canvas canvas, Offset effectiveOffset, TextPosition textPositio
_textLayoutLastMinWidth == constraints.minWidth,
() => $"Last width ({_textLayoutLastMinWidth}, {_textLayoutLastMaxWidth}) not the same as max width constraint ({constraints.minWidth}, {constraints.maxWidth}).");
var paint = new Paint() {color = _floatingCursorOn ? backgroundCursorColor : _cursorColor};
var caretOffset = _textPainter.getOffsetForCaret(textPosition, _caretPrototype) + effectiveOffset;
Rect caretRect = _caretPrototype.shift(caretOffset);

//force offset to 0 (at the beginning of the text if the text is currently focused
if (hasFocus && textPosition.offset == -1)
{
textPosition = new TextPosition(0, textPosition.affinity);
}
//if there is no contents in this editable yet, we use the _getCaretPrototypeForEmptyLine API to fetch the proper caret height
var currentCaretPrototype = _caretPrototype;
var content = new StringBuilder();
text.computeToPlainText(content, false, false);

//Debug.Log("[ZXW] text is " + content.ToString());
if (string.IsNullOrEmpty(content.ToString())) {
currentCaretPrototype = _getCaretPrototypeForEmptyLine;
}

//Debug.Log("[ZXW] caret offset is " + currentCaretPrototype.top + " " + _caretPrototype.top + " " + _getCaretPrototypeForEmptyLine.top);


var caretOffset = _textPainter.getOffsetForCaret(textPosition, currentCaretPrototype) + effectiveOffset;

Rect caretRect = currentCaretPrototype.shift(caretOffset);

//Debug.Log("[ZXW] caretRect is " + effectiveOffset.dy + " " + caretOffset.dy + " " + caretRect.top);


if (_cursorOffset != null) {
caretRect = caretRect.shift(_cursorOffset);
//Debug.Log("[ZXW] caretRect shift " + _cursorOffset.dy + " " + caretRect.top);
}

float? caretHeight = _textPainter.getFullHeightForCaret(textPosition, _caretPrototype);
float? caretHeight = _textPainter.getFullHeightForCaret(textPosition, currentCaretPrototype);
if (caretHeight != null) {
switch (Application.platform) {
case RuntimePlatform.IPhonePlayer:
Expand All @@ -1598,16 +1641,20 @@ void _paintCaret(Canvas canvas, Offset effectiveOffset, TextPosition textPositio
default:
caretRect = Rect.fromLTWH(
caretRect.left,
caretRect.top - EditableUtils._kCaretHeightOffset,
caretRect.top,
caretRect.width,
caretHeight.Value
);

//Debug.Log("[ZXW] caretRect final " + caretRect.height + " " + caretRect.top);
break;
}
}

caretRect = caretRect.shift(_getPixelPerfectCursorOffset(caretRect));


//Debug.Log("[ZXW] caretRect pixel perfect " + caretRect.height + " " + caretRect.top);

if (cursorRadius == null) {
canvas.drawRect(caretRect, paint);
}
Expand Down