1
1
using System . Collections . Generic ;
2
+ using System . Xml . Schema ;
2
3
using Unity . UIWidgets . foundation ;
3
4
using Unity . UIWidgets . gestures ;
4
5
using Unity . UIWidgets . painting ;
@@ -49,6 +50,8 @@ public class RenderEditable : RenderBox {
49
50
TextPainter _textPainter ;
50
51
Color _cursorColor ;
51
52
int ? _maxLines ;
53
+ int ? _minLines ;
54
+ bool _expands ;
52
55
Color _selectionColor ;
53
56
ViewportOffset _offset ;
54
57
ValueNotifier < bool > _showCursor ;
@@ -78,6 +81,8 @@ public RenderEditable(
78
81
Color backgroundCursorColor = null ,
79
82
bool ? hasFocus = null ,
80
83
int ? maxLines = 1 ,
84
+ int ? minLines = null ,
85
+ bool expands = false ,
81
86
StrutStyle strutStyle = null ,
82
87
Color selectionColor = null ,
83
88
TextSelection selection = null ,
@@ -87,21 +92,25 @@ public RenderEditable(
87
92
bool ignorePointer = false ,
88
93
float cursorWidth = 1.0f ,
89
94
Radius cursorRadius = null ,
90
- bool ? enableInteractiveSelection = null ,
91
95
bool paintCursorAboveText = false ,
92
96
Offset cursorOffset = null ,
93
97
float devicePixelRatio = 1.0f ,
98
+ bool ? enableInteractiveSelection = null ,
94
99
EdgeInsets floatingCursorAddedMargin = null ,
95
100
TextSelectionDelegate textSelectionDelegate = null ) {
96
101
floatingCursorAddedMargin = floatingCursorAddedMargin ?? EdgeInsets . fromLTRB ( 4 , 4 , 4 , 5 ) ;
97
102
D . assert ( textSelectionDelegate != null ) ;
103
+ D . assert ( minLines == null || minLines > 0 ) ;
104
+ D . assert ( ( minLines == null ) || maxLines >= minLines , ( ) => "minLines can't be greater than maxLines" ) ;
98
105
this . _textPainter = new TextPainter ( text : text , textAlign : textAlign , textDirection : textDirection ,
99
106
textScaleFactor : textScaleFactor , strutStyle : strutStyle ) ;
100
107
this . _cursorColor = cursorColor ;
101
108
102
109
this . _showCursor = showCursor ?? new ValueNotifier < bool > ( false ) ;
103
110
this . _hasFocus = hasFocus ?? false ;
104
111
this . _maxLines = maxLines ;
112
+ this . _minLines = minLines ;
113
+ this . _expands = expands ;
105
114
this . _selectionColor = selectionColor ;
106
115
this . _selection = selection ;
107
116
this . _obscureText = obscureText ;
@@ -237,6 +246,27 @@ public ValueListenable<bool> selectionEndInViewport {
237
246
238
247
readonly ValueNotifier < bool > _selectionEndInViewport = new ValueNotifier < bool > ( true ) ;
239
248
249
+ void _updateSelectionExtentsVisibility ( Offset effectiveOffset ) {
250
+ Rect visibleRegion = Offset . zero & this . size ;
251
+ Offset startOffset = this . _textPainter . getOffsetForCaret (
252
+ new TextPosition ( offset : this . _selection . start , affinity : this . _selection . affinity ) ,
253
+ Rect . zero
254
+ ) ;
255
+
256
+ float visibleRegionSlop = 0.5f ;
257
+ this . _selectionStartInViewport . value = visibleRegion
258
+ . inflate ( visibleRegionSlop )
259
+ . contains ( startOffset + effectiveOffset ) ;
260
+
261
+ Offset endOffset = this . _textPainter . getOffsetForCaret (
262
+ new TextPosition ( offset : this . _selection . end , affinity : this . _selection . affinity ) ,
263
+ Rect . zero
264
+ ) ;
265
+ this . _selectionEndInViewport . value = visibleRegion
266
+ . inflate ( visibleRegionSlop )
267
+ . contains ( endOffset + effectiveOffset ) ;
268
+ }
269
+
240
270
int _extentOffset = - 1 ;
241
271
242
272
int _baseOffset = - 1 ;
@@ -624,7 +654,7 @@ public ValueNotifier<bool> showCursor {
624
654
}
625
655
}
626
656
627
- bool _hasFocus ;
657
+ bool _hasFocus = false ;
628
658
bool _listenerAttached = false ;
629
659
630
660
public bool hasFocus {
@@ -663,6 +693,31 @@ public int? maxLines {
663
693
}
664
694
}
665
695
696
+ public int ? minLines {
697
+ get { return this . _minLines ; }
698
+ set {
699
+ D . assert ( value == null || value > 0 ) ;
700
+ if ( this . _minLines == value ) {
701
+ return ;
702
+ }
703
+
704
+ this . _minLines = value ;
705
+ this . markNeedsTextLayout ( ) ;
706
+ }
707
+ }
708
+
709
+ public bool expands {
710
+ get { return this . _expands ; }
711
+ set {
712
+ if ( this . expands == value ) {
713
+ return ;
714
+ }
715
+
716
+ this . _expands = value ;
717
+ this . markNeedsTextLayout ( ) ;
718
+ }
719
+ }
720
+
666
721
public Color selectionColor {
667
722
get { return this . _selectionColor ; }
668
723
set {
@@ -985,7 +1040,7 @@ public override void handleEvent(PointerEvent evt, HitTestEntry entry) {
985
1040
}
986
1041
987
1042
public void handleTapDown ( TapDownDetails details ) {
988
- this . _lastTapDownPosition = details . globalPosition - this . _paintOffset ;
1043
+ this . _lastTapDownPosition = details . globalPosition ;
989
1044
if ( ! Application . isMobilePlatform ) {
990
1045
this . selectPosition ( SelectionChangedCause . tap ) ;
991
1046
}
@@ -1089,7 +1144,7 @@ public void selectWordEdge(SelectionChangedCause cause) {
1089
1144
D . assert ( this . _lastTapDownPosition != null ) ;
1090
1145
if ( this . onSelectionChanged != null ) {
1091
1146
TextPosition position =
1092
- this . _textPainter . getPositionForOffset ( this . globalToLocal ( this . _lastTapDownPosition ) ) ;
1147
+ this . _textPainter . getPositionForOffset ( this . globalToLocal ( this . _lastTapDownPosition - this . _paintOffset ) ) ;
1093
1148
TextRange word = this . _textPainter . getWordBoundary ( position ) ;
1094
1149
if ( position . offset - word . start <= 1 ) {
1095
1150
this . onSelectionChanged (
@@ -1188,12 +1243,25 @@ Offset _getPixelPerfectCursorOffset(Rect caretRect) {
1188
1243
1189
1244
void _paintCaret ( Canvas canvas , Offset effectiveOffset , TextPosition textPosition ) {
1190
1245
D . assert ( this . _textLayoutLastWidth == this . constraints . maxWidth ) ;
1191
- var caretOffset = this . _textPainter . getOffsetForCaret ( textPosition , this . _caretPrototype ) ;
1192
1246
var paint = new Paint ( ) { color = this . _floatingCursorOn ? this . backgroundCursorColor : this . _cursorColor } ;
1247
+ var caretOffset = this . _textPainter . getOffsetForCaret ( textPosition , this . _caretPrototype ) + effectiveOffset ;
1193
1248
Rect caretRect = this . _caretPrototype . shift ( caretOffset + effectiveOffset ) ;
1194
1249
if ( this . _cursorOffset != null ) {
1195
1250
caretRect = caretRect . shift ( this . _cursorOffset ) ;
1196
1251
}
1252
+
1253
+ #if ! UNITY_IOS
1254
+ if ( this . _textPainter . getFullHeightForCaret ( textPosition , this . _caretPrototype ) != null ) {
1255
+ caretRect = Rect . fromLTWH (
1256
+ caretRect . left ,
1257
+ caretRect . top - _kCaretHeightOffset ,
1258
+ caretRect . width ,
1259
+ this . _textPainter . getFullHeightForCaret ( textPosition , this . _caretPrototype )
1260
+ ) ;
1261
+ }
1262
+ #endif
1263
+
1264
+ caretRect = caretRect . shift ( this . _getPixelPerfectCursorOffset ( caretRect ) ) ;
1197
1265
1198
1266
if ( this . cursorRadius == null ) {
1199
1267
canvas . drawRect ( caretRect , paint ) ;
@@ -1384,10 +1452,26 @@ void markNeedsSemanticsUpdate() {
1384
1452
}
1385
1453
1386
1454
float _preferredHeight ( float width ) {
1387
- if ( this . maxLines != null ) {
1455
+ bool lockedMax = this . maxLines != null && this . minLines == null ;
1456
+ bool lockedBoth = this . maxLines != null && this . minLines == this . maxLines ;
1457
+ bool singleLine = this . maxLines == 1 ;
1458
+ if ( singleLine || lockedMax || lockedBoth ) {
1388
1459
return this . preferredLineHeight * this . maxLines . Value ;
1389
1460
}
1390
1461
1462
+ bool minLimited = this . minLines != null && this . minLines > 1 ;
1463
+ bool maxLimited = this . maxLines != null ;
1464
+ if ( minLimited || maxLimited ) {
1465
+ this . _layoutText ( width ) ;
1466
+ if ( minLimited && this . _textPainter . height < this . preferredLineHeight * this . minLines . Value ) {
1467
+ return this . preferredLineHeight * this . minLines . Value ;
1468
+ }
1469
+
1470
+ if ( maxLimited && this . _textPainter . height > this . preferredLineHeight * this . maxLines . Value ) {
1471
+ return this . preferredLineHeight * this . maxLines . Value ;
1472
+ }
1473
+ }
1474
+
1391
1475
if ( ! width . isFinite ( ) ) {
1392
1476
var text = this . _textPainter . text . text ;
1393
1477
int lines = 1 ;
@@ -1460,6 +1544,8 @@ public override void debugFillProperties(DiagnosticPropertiesBuilder properties)
1460
1544
properties . add ( new DiagnosticsProperty < Color > ( "cursorColor" , this . cursorColor ) ) ;
1461
1545
properties . add ( new DiagnosticsProperty < ValueNotifier < bool > > ( "showCursor" , this . showCursor ) ) ;
1462
1546
properties . add ( new DiagnosticsProperty < int ? > ( "maxLines" , this . maxLines ) ) ;
1547
+ properties . add ( new DiagnosticsProperty < int ? > ( "minLines" , this . minLines ) ) ;
1548
+ properties . add ( new DiagnosticsProperty < bool > ( "expands" , this . expands ) ) ;
1463
1549
properties . add ( new DiagnosticsProperty < Color > ( "selectionColor" , this . selectionColor ) ) ;
1464
1550
properties . add ( new DiagnosticsProperty < float > ( "textScaleFactor" , this . textScaleFactor ) ) ;
1465
1551
properties . add ( new DiagnosticsProperty < TextSelection > ( "selection" , this . selection ) ) ;
0 commit comments