Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
f226c1ea
Unverified
Commit
f226c1ea
authored
Jul 29, 2021
by
olof-dev
Committed by
GitHub
Jul 29, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added parameters boxHeightStyle, boxWidthStyle to RenderParagraph.getBoxesForSelection (#87183)
parent
6a4d5d88
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
175 additions
and
11 deletions
+175
-11
paragraph.dart
packages/flutter/lib/src/rendering/paragraph.dart
+26
-6
paragraph_test.dart
packages/flutter/test/rendering/paragraph_test.dart
+149
-5
No files found.
packages/flutter/lib/src/rendering/paragraph.dart
View file @
f226c1ea
...
@@ -4,7 +4,7 @@
...
@@ -4,7 +4,7 @@
import
'dart:collection'
;
import
'dart:collection'
;
import
'dart:math'
as
math
;
import
'dart:math'
as
math
;
import
'dart:ui'
as
ui
show
Gradient
,
Shader
,
TextBox
,
PlaceholderAlignment
,
TextHeightBehavior
;
import
'dart:ui'
as
ui
show
Gradient
,
Shader
,
TextBox
,
PlaceholderAlignment
,
TextHeightBehavior
,
BoxHeightStyle
,
BoxWidthStyle
;
import
'package:flutter/foundation.dart'
;
import
'package:flutter/foundation.dart'
;
import
'package:flutter/gestures.dart'
;
import
'package:flutter/gestures.dart'
;
...
@@ -787,15 +787,35 @@ class RenderParagraph extends RenderBox
...
@@ -787,15 +787,35 @@ class RenderParagraph extends RenderBox
/// Returns a list of rects that bound the given selection.
/// Returns a list of rects that bound the given selection.
///
///
/// A given selection might have more than one rect if this text painter
/// The [boxHeightStyle] and [boxWidthStyle] arguments may be used to select
/// contains bidirectional text because logically contiguous text might not be
/// the shape of the [TextBox]es. These properties default to
/// visually contiguous.
/// [ui.BoxHeightStyle.tight] and [ui.BoxWidthStyle.tight] respectively and
/// must not be null.
///
/// A given selection might have more than one rect if the [RenderParagraph]
/// contains multiple [InlineSpan]s or bidirectional text, because logically
/// contiguous text might not be visually contiguous.
///
///
/// Valid only after [layout].
/// Valid only after [layout].
List
<
ui
.
TextBox
>
getBoxesForSelection
(
TextSelection
selection
)
{
///
/// See also:
///
/// * [TextPainter.getBoxesForSelection], the method in TextPainter to get
/// the equivalent boxes.
List
<
ui
.
TextBox
>
getBoxesForSelection
(
TextSelection
selection
,
{
ui
.
BoxHeightStyle
boxHeightStyle
=
ui
.
BoxHeightStyle
.
tight
,
ui
.
BoxWidthStyle
boxWidthStyle
=
ui
.
BoxWidthStyle
.
tight
,
})
{
assert
(!
debugNeedsLayout
);
assert
(!
debugNeedsLayout
);
assert
(
boxHeightStyle
!=
null
);
assert
(
boxWidthStyle
!=
null
);
_layoutTextWithConstraints
(
constraints
);
_layoutTextWithConstraints
(
constraints
);
return
_textPainter
.
getBoxesForSelection
(
selection
);
return
_textPainter
.
getBoxesForSelection
(
selection
,
boxHeightStyle:
boxHeightStyle
,
boxWidthStyle:
boxWidthStyle
,
);
}
}
/// Returns the position within the text for the given pixel offset.
/// Returns the position within the text for the given pixel offset.
...
...
packages/flutter/test/rendering/paragraph_test.dart
View file @
f226c1ea
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// found in the LICENSE file.
import
'dart:ui'
as
ui
show
TextBox
;
import
'dart:ui'
as
ui
show
TextBox
,
BoxHeightStyle
,
BoxWidthStyle
;
import
'package:flutter/gestures.dart'
;
import
'package:flutter/gestures.dart'
;
import
'package:flutter/rendering.dart'
;
import
'package:flutter/rendering.dart'
;
...
@@ -28,11 +28,19 @@ class RenderParagraphWithEmptySelectionBoxList extends RenderParagraph {
...
@@ -28,11 +28,19 @@ class RenderParagraphWithEmptySelectionBoxList extends RenderParagraph {
TextSelection
emptyListSelection
;
TextSelection
emptyListSelection
;
@override
@override
List
<
ui
.
TextBox
>
getBoxesForSelection
(
TextSelection
selection
)
{
List
<
ui
.
TextBox
>
getBoxesForSelection
(
TextSelection
selection
,
{
ui
.
BoxHeightStyle
boxHeightStyle
=
ui
.
BoxHeightStyle
.
tight
,
ui
.
BoxWidthStyle
boxWidthStyle
=
ui
.
BoxWidthStyle
.
tight
,
})
{
if
(
selection
==
emptyListSelection
)
{
if
(
selection
==
emptyListSelection
)
{
return
<
ui
.
TextBox
>[];
return
<
ui
.
TextBox
>[];
}
}
return
super
.
getBoxesForSelection
(
selection
);
return
super
.
getBoxesForSelection
(
selection
,
boxHeightStyle:
boxHeightStyle
,
boxWidthStyle:
boxWidthStyle
,
);
}
}
}
}
...
@@ -48,11 +56,19 @@ class RenderParagraphWithEmptyBoxListForWidgetSpan extends RenderParagraph {
...
@@ -48,11 +56,19 @@ class RenderParagraphWithEmptyBoxListForWidgetSpan extends RenderParagraph {
})
:
super
(
text
,
children:
children
,
textDirection:
textDirection
);
})
:
super
(
text
,
children:
children
,
textDirection:
textDirection
);
@override
@override
List
<
ui
.
TextBox
>
getBoxesForSelection
(
TextSelection
selection
)
{
List
<
ui
.
TextBox
>
getBoxesForSelection
(
TextSelection
selection
,
{
ui
.
BoxHeightStyle
boxHeightStyle
=
ui
.
BoxHeightStyle
.
tight
,
ui
.
BoxWidthStyle
boxWidthStyle
=
ui
.
BoxWidthStyle
.
tight
,
})
{
if
(
text
.
getSpanForPosition
(
selection
.
base
)
is
WidgetSpan
)
{
if
(
text
.
getSpanForPosition
(
selection
.
base
)
is
WidgetSpan
)
{
return
<
ui
.
TextBox
>[];
return
<
ui
.
TextBox
>[];
}
}
return
super
.
getBoxesForSelection
(
selection
);
return
super
.
getBoxesForSelection
(
selection
,
boxHeightStyle:
boxHeightStyle
,
boxWidthStyle:
boxWidthStyle
,
);
}
}
}
}
...
@@ -125,6 +141,93 @@ void main() {
...
@@ -125,6 +141,93 @@ void main() {
expect
(
boxes
.
any
((
ui
.
TextBox
box
)
=>
box
.
right
==
100
&&
box
.
top
==
10
),
isTrue
);
expect
(
boxes
.
any
((
ui
.
TextBox
box
)
=>
box
.
right
==
100
&&
box
.
top
==
10
),
isTrue
);
},
skip:
isBrowser
);
// https://github.com/flutter/flutter/issues/61016
},
skip:
isBrowser
);
// https://github.com/flutter/flutter/issues/61016
test
(
'getBoxesForSelection test with multiple TextSpans and lines'
,
()
{
final
RenderParagraph
paragraph
=
RenderParagraph
(
const
TextSpan
(
text:
'First '
,
style:
TextStyle
(
fontFamily:
'Ahem'
,
fontSize:
10.0
),
children:
<
InlineSpan
>[
TextSpan
(
text:
'smallsecond '
,
style:
TextStyle
(
fontSize:
5.0
)),
TextSpan
(
text:
'third fourth fifth'
),
],
),
textDirection:
TextDirection
.
ltr
,
);
// Do layout with width chosen so that this splits as
// First smallsecond |
// third fourth |
// fifth|
// The corresponding line widths come out to be:
// 1st line: 120px wide: 6 chars * 10px plus 12 chars * 5px.
// 2nd line: 130px wide: 13 chars * 10px.
// 3rd line: 50px wide.
layout
(
paragraph
,
constraints:
const
BoxConstraints
(
maxWidth:
140.0
));
final
List
<
ui
.
TextBox
>
boxes
=
paragraph
.
getBoxesForSelection
(
const
TextSelection
(
baseOffset:
0
,
extentOffset:
36
),
);
expect
(
boxes
.
length
,
equals
(
4
));
// The widths of the boxes should match the calculations above.
// The heights should all be 10, except for the box for 'smallsecond ',
// which should have height 5, and be alphabetic baseline-aligned with
// 'First '. The Ahem font specifies alphabetic baselines at 0.2em above the
// bottom extent, and 0.8em below the top, so the difference in top
// alignment becomes (10px * 0.8 - 5px * 0.8) = 4px.
// 'First ':
expect
(
boxes
[
0
],
const
TextBox
.
fromLTRBD
(
0.0
,
0.0
,
60.0
,
10.0
,
TextDirection
.
ltr
));
// 'smallsecond ' in size 5:
expect
(
boxes
[
1
],
const
TextBox
.
fromLTRBD
(
60.0
,
4.0
,
120.0
,
9.0
,
TextDirection
.
ltr
));
// 'third fourth ':
expect
(
boxes
[
2
],
const
TextBox
.
fromLTRBD
(
0.0
,
10.0
,
130.0
,
20.0
,
TextDirection
.
ltr
));
// 'fifth':
expect
(
boxes
[
3
],
const
TextBox
.
fromLTRBD
(
0.0
,
20.0
,
50.0
,
30.0
,
TextDirection
.
ltr
));
},
skip:
!
isLinux
);
// mac typography values can differ
test
(
'getBoxesForSelection test with boxHeightStyle and boxWidthStyle set to max'
,
()
{
final
RenderParagraph
paragraph
=
RenderParagraph
(
const
TextSpan
(
text:
'First '
,
style:
TextStyle
(
fontFamily:
'Ahem'
,
fontSize:
10.0
),
children:
<
InlineSpan
>[
TextSpan
(
text:
'smallsecond '
,
style:
TextStyle
(
fontSize:
8.0
)),
TextSpan
(
text:
'third fourth fifth'
),
],
),
textDirection:
TextDirection
.
ltr
,
);
// Do layout with width chosen so that this splits as
// First smallsecond |
// third fourth |
// fifth|
// The corresponding line widths come out to be:
// 1st line: 156px wide: 6 chars * 10px plus 12 chars * 8px.
// 2nd line: 130px wide: 13 chars * 10px.
// 3rd line: 50px wide.
layout
(
paragraph
,
constraints:
const
BoxConstraints
(
maxWidth:
160.0
));
final
List
<
ui
.
TextBox
>
boxes
=
paragraph
.
getBoxesForSelection
(
const
TextSelection
(
baseOffset:
0
,
extentOffset:
36
),
boxHeightStyle:
ui
.
BoxHeightStyle
.
max
,
boxWidthStyle:
ui
.
BoxWidthStyle
.
max
,
);
expect
(
boxes
.
length
,
equals
(
5
));
// 'First ':
expect
(
boxes
[
0
],
const
TextBox
.
fromLTRBD
(
0.0
,
0.0
,
60.0
,
10.0
,
TextDirection
.
ltr
));
// 'smallsecond ' in size 8, but on same line as previous box, so height remains 10:
expect
(
boxes
[
1
],
const
TextBox
.
fromLTRBD
(
60.0
,
0.0
,
156.0
,
10.0
,
TextDirection
.
ltr
));
// 'third fourth ':
expect
(
boxes
[
2
],
const
TextBox
.
fromLTRBD
(
0.0
,
10.0
,
130.0
,
20.0
,
TextDirection
.
ltr
));
// extra box added to extend width, as per definition of ui.BoxWidthStyle.max:
expect
(
boxes
[
3
],
const
TextBox
.
fromLTRBD
(
130.0
,
10.0
,
156.0
,
20.0
,
TextDirection
.
ltr
));
// 'fifth':
expect
(
boxes
[
4
],
const
TextBox
.
fromLTRBD
(
0.0
,
20.0
,
50.0
,
30.0
,
TextDirection
.
ltr
));
},
skip:
isBrowser
);
// https://github.com/flutter/flutter/issues/61016
test
(
'getWordBoundary control test'
,
()
{
test
(
'getWordBoundary control test'
,
()
{
final
RenderParagraph
paragraph
=
RenderParagraph
(
final
RenderParagraph
paragraph
=
RenderParagraph
(
const
TextSpan
(
text:
_kText
),
const
TextSpan
(
text:
_kText
),
...
@@ -419,6 +522,47 @@ void main() {
...
@@ -419,6 +522,47 @@ void main() {
expect
(
boxes
[
4
],
const
TextBox
.
fromLTRBD
(
48.0
,
0.0
,
62.0
,
14.0
,
TextDirection
.
ltr
));
expect
(
boxes
[
4
],
const
TextBox
.
fromLTRBD
(
48.0
,
0.0
,
62.0
,
14.0
,
TextDirection
.
ltr
));
},
skip:
isBrowser
);
// https://github.com/flutter/flutter/issues/61020
},
skip:
isBrowser
);
// https://github.com/flutter/flutter/issues/61020
test
(
'getBoxesForSelection with boxHeightStyle for inline widgets'
,
()
{
const
TextSpan
text
=
TextSpan
(
text:
'a'
,
style:
TextStyle
(
fontSize:
10.0
),
children:
<
InlineSpan
>[
WidgetSpan
(
child:
SizedBox
(
width:
21
,
height:
21
)),
WidgetSpan
(
child:
SizedBox
(
width:
21
,
height:
21
)),
TextSpan
(
text:
'a'
),
WidgetSpan
(
child:
SizedBox
(
width:
21
,
height:
21
)),
],
);
// Fake the render boxes that correspond to the WidgetSpans. We use
// RenderParagraph to reduce the dependencies this test has. The dimensions
// of these get used in place of the widths and heights specified in the
// SizedBoxes above: each comes out as (w,h) = (14,14).
final
List
<
RenderBox
>
renderBoxes
=
<
RenderBox
>[
RenderParagraph
(
const
TextSpan
(
text:
'b'
),
textDirection:
TextDirection
.
ltr
),
RenderParagraph
(
const
TextSpan
(
text:
'b'
),
textDirection:
TextDirection
.
ltr
),
RenderParagraph
(
const
TextSpan
(
text:
'b'
),
textDirection:
TextDirection
.
ltr
),
];
final
RenderParagraph
paragraph
=
RenderParagraph
(
text
,
textDirection:
TextDirection
.
ltr
,
children:
renderBoxes
,
);
layout
(
paragraph
,
constraints:
const
BoxConstraints
(
maxWidth:
100.0
));
final
List
<
ui
.
TextBox
>
boxes
=
paragraph
.
getBoxesForSelection
(
const
TextSelection
(
baseOffset:
0
,
extentOffset:
8
),
boxHeightStyle:
ui
.
BoxHeightStyle
.
max
,
);
expect
(
boxes
.
length
,
equals
(
5
));
expect
(
boxes
[
0
],
const
TextBox
.
fromLTRBD
(
0.0
,
0.0
,
10.0
,
14.0
,
TextDirection
.
ltr
));
expect
(
boxes
[
1
],
const
TextBox
.
fromLTRBD
(
10.0
,
0.0
,
24.0
,
14.0
,
TextDirection
.
ltr
));
expect
(
boxes
[
2
],
const
TextBox
.
fromLTRBD
(
24.0
,
0.0
,
38.0
,
14.0
,
TextDirection
.
ltr
));
expect
(
boxes
[
3
],
const
TextBox
.
fromLTRBD
(
38.0
,
0.0
,
48.0
,
14.0
,
TextDirection
.
ltr
));
expect
(
boxes
[
4
],
const
TextBox
.
fromLTRBD
(
48.0
,
0.0
,
62.0
,
14.0
,
TextDirection
.
ltr
));
},
skip:
isBrowser
);
// https://github.com/flutter/flutter/issues/61020
test
(
'can compute IntrinsicHeight for widget span'
,
()
{
test
(
'can compute IntrinsicHeight for widget span'
,
()
{
// Regression test for https://github.com/flutter/flutter/issues/59316
// Regression test for https://github.com/flutter/flutter/issues/59316
const
double
screenWidth
=
100.0
;
const
double
screenWidth
=
100.0
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment