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
b89935e5
Commit
b89935e5
authored
Jan 31, 2016
by
Adam Barth
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1496 from abarth/move_caret
Adds the ability to move the caret by tapping
parents
4125f386
36099383
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
108 additions
and
68 deletions
+108
-68
input.dart
packages/flutter/lib/src/material/input.dart
+22
-10
text_editing.dart
packages/flutter/lib/src/painting/text_editing.dart
+15
-34
text_painter.dart
packages/flutter/lib/src/painting/text_painter.dart
+5
-0
editable_line.dart
packages/flutter/lib/src/rendering/editable_line.dart
+40
-9
proxy_box.dart
packages/flutter/lib/src/rendering/proxy_box.dart
+2
-5
basic.dart
packages/flutter/lib/src/widgets/basic.dart
+1
-1
editable.dart
packages/flutter/lib/src/widgets/editable.dart
+23
-9
No files found.
packages/flutter/lib/src/material/input.dart
View file @
b89935e5
...
...
@@ -121,6 +121,16 @@ class _InputState extends State<Input> {
}
}
void
_requestKeyboard
()
{
if
(
Focus
.
at
(
context
))
{
assert
(
_isAttachedToKeyboard
);
_keyboardHandle
.
showByRequest
();
}
else
{
Focus
.
moveTo
(
config
.
key
);
// we'll get told to rebuild and we'll take care of the keyboard then
}
}
void
_handleTextUpdated
()
{
if
(
_value
!=
_editableString
.
text
)
{
setState
(()
{
...
...
@@ -137,6 +147,15 @@ class _InputState extends State<Input> {
config
.
onSubmitted
(
_value
);
}
void
_handleSelectionChanged
(
TextSelection
selection
)
{
if
(
_isAttachedToKeyboard
)
{
_keyboardHandle
.
setSelection
(
selection
.
start
,
selection
.
end
);
}
else
{
_editableString
.
setSelection
(
selection
);
_requestKeyboard
();
}
}
Widget
build
(
BuildContext
context
)
{
assert
(
debugCheckHasMaterial
(
context
));
ThemeData
themeData
=
Theme
.
of
(
context
);
...
...
@@ -221,7 +240,8 @@ class _InputState extends State<Input> {
style:
textStyle
,
hideText:
config
.
hideText
,
cursorColor:
cursorColor
,
selectionColor:
cursorColor
selectionColor:
cursorColor
,
onSelectionChanged:
_handleSelectionChanged
)
));
...
...
@@ -258,15 +278,7 @@ class _InputState extends State<Input> {
return
new
GestureDetector
(
behavior:
HitTestBehavior
.
opaque
,
onTap:
()
{
if
(
Focus
.
at
(
context
))
{
assert
(
_isAttachedToKeyboard
);
_keyboardHandle
.
showByRequest
();
}
else
{
Focus
.
moveTo
(
config
.
key
);
// we'll get told to rebuild and we'll take care of the keyboard then
}
},
onTap:
_requestKeyboard
,
child:
new
Padding
(
padding:
const
EdgeDims
.
symmetric
(
horizontal:
16.0
),
child:
child
...
...
packages/flutter/lib/src/painting/text_editing.dart
View file @
b89935e5
...
...
@@ -2,38 +2,9 @@
// 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
}
import
'dart:ui'
show
TextAffinity
,
TextPosition
;
/// 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
;
}
export
'dart:ui'
show
TextAffinity
,
TextPosition
;
/// A range of characters in a string of text.
class
TextRange
{
...
...
@@ -97,9 +68,15 @@ class TextSelection extends TextRange {
const
TextSelection
.
collapsed
({
int
offset
,
this
.
affinity
:
TextAffinity
.
downstream
,
this
.
isDirectional
:
false
})
:
baseOffset
=
offset
,
extentOffset
=
offset
,
super
.
collapsed
(
offset
);
this
.
affinity
:
TextAffinity
.
downstream
})
:
baseOffset
=
offset
,
extentOffset
=
offset
,
isDirectional
=
false
,
super
.
collapsed
(
offset
);
TextSelection
.
fromPosition
(
TextPosition
position
)
:
baseOffset
=
position
.
offset
,
extentOffset
=
position
.
offset
,
affinity
=
position
.
affinity
,
isDirectional
=
false
,
super
.
collapsed
(
position
.
offset
);
/// The offset at which the selection originates.
///
...
...
@@ -141,4 +118,8 @@ class TextSelection extends TextRange {
///
/// Might be larger than, smaller than, or equal to base.
TextPosition
get
extent
=>
new
TextPosition
(
offset:
extentOffset
,
affinity:
affinity
);
String
toString
()
{
return
'
$runtimeType
(baseOffset:
$baseOffset
, extentOffset:
$extentOffset
, affinity:
$affinity
, isDirectional:
$isDirectional
)'
;
}
}
packages/flutter/lib/src/painting/text_painter.dart
View file @
b89935e5
...
...
@@ -265,4 +265,9 @@ class TextPainter {
return
_paragraph
.
getBoxesForRange
(
selection
.
start
,
selection
.
end
);
}
TextPosition
getPositionForOffset
(
Offset
offset
)
{
assert
(!
_needsLayout
);
return
_paragraph
.
getPositionForOffset
(
offset
);
}
}
packages/flutter/lib/src/rendering/editable_line.dart
View file @
b89935e5
...
...
@@ -4,12 +4,12 @@
import
'dart:ui'
as
ui
;
import
'package:flutter/gestures.dart'
;
import
'package:flutter/painting.dart'
;
import
'box.dart'
;
import
'object.dart'
;
import
'paragraph.dart'
;
import
'proxy_box.dart'
show
SizeChangedCallback
;
const
_kCaretGap
=
1.0
;
// pixels
const
_kCaretHeightOffset
=
2.0
;
// pixels
...
...
@@ -26,22 +26,28 @@ class RenderEditableLine extends RenderBox {
Color
selectionColor
,
TextSelection
selection
,
Offset
paintOffset:
Offset
.
zero
,
this
.
onSelectionChanged
,
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.
_textPainter
..
minWidth
=
0.0
..
maxWidth
=
double
.
INFINITY
..
minHeight
=
0.0
..
maxHeight
=
double
.
INFINITY
;
assert
(!
showCursor
||
cursorColor
!=
null
);
// TODO(abarth): These min/max values should be the default for TextPainter.
_textPainter
..
minWidth
=
0.0
..
maxWidth
=
double
.
INFINITY
..
minHeight
=
0.0
..
maxHeight
=
double
.
INFINITY
;
_tap
=
new
TapGestureRecognizer
(
router:
Gesturer
.
instance
.
pointerRouter
,
gestureArena:
Gesturer
.
instance
.
gestureArena
)
..
onTapDown
=
_handleTapDown
..
onTap
=
_handleTap
..
onTapCancel
=
_handleTapCancel
;
}
SizeChangedCallback
onContentSizeChanged
;
ValueChanged
<
Size
>
onContentSizeChanged
;
ValueChanged
<
TextSelection
>
onSelectionChanged
;
/// The text to display
StyledTextSpan
get
text
=>
_textPainter
.
text
;
...
...
@@ -147,6 +153,31 @@ class RenderEditableLine extends RenderBox {
bool
hitTestSelf
(
Point
position
)
=>
true
;
TapGestureRecognizer
_tap
;
void
handleEvent
(
PointerEvent
event
,
BoxHitTestEntry
entry
)
{
if
(
event
is
PointerDownEvent
&&
onSelectionChanged
!=
null
)
_tap
.
addPointer
(
event
);
}
Point
_lastTapDownPosition
;
void
_handleTapDown
(
Point
globalPosition
)
{
_lastTapDownPosition
=
globalPosition
;
}
void
_handleTap
()
{
assert
(
_lastTapDownPosition
!=
null
);
final
Point
global
=
_lastTapDownPosition
;
_lastTapDownPosition
=
null
;
if
(
onSelectionChanged
!=
null
)
{
TextPosition
position
=
_textPainter
.
getPositionForOffset
(
globalToLocal
(
global
).
toOffset
());
onSelectionChanged
(
new
TextSelection
.
fromPosition
(
position
));
}
}
void
_handleTapCancel
()
{
_lastTapDownPosition
=
null
;
}
BoxConstraints
_constraintsForCurrentLayout
;
// when null, we don't have a current layout
// TODO(abarth): This logic should live in TextPainter and be shared with RenderParagraph.
...
...
packages/flutter/lib/src/rendering/proxy_box.dart
View file @
b89935e5
...
...
@@ -1115,9 +1115,6 @@ class RenderFractionalTranslation extends RenderProxyBox {
}
}
/// Called when a size changes.
typedef
void
SizeChangedCallback
(
Size
newSize
);
/// Calls [onSizeChanged] whenever the child's layout size changes
///
/// Because size observer calls its callback during layout, you cannot modify
...
...
@@ -1131,7 +1128,7 @@ class RenderSizeObserver extends RenderProxyBox {
}
/// The callback to call whenever the child's layout size changes
SizeChangedCallback
onSizeChanged
;
ValueChanged
<
Size
>
onSizeChanged
;
void
performLayout
()
{
Size
oldSize
=
hasSize
?
size
:
null
;
...
...
@@ -1540,7 +1537,7 @@ class RenderSemanticAnnotations extends RenderProxyBox {
/// If 'container' is true, this RenderObject will introduce a new
/// node in the semantics tree. Otherwise, the semantics will be
/// merged with the semantics of any ancestors.
///
///
/// The 'container' flag is implicitly set to true on the immediate
/// semantics-providing descendants of a node where multiple
/// children have semantics or have descendants providing semantics.
...
...
packages/flutter/lib/src/widgets/basic.dart
View file @
b89935e5
...
...
@@ -819,7 +819,7 @@ class SizeObserver extends OneChildRenderObjectWidget {
}
/// The callback to call whenever the child's layout size changes
final
SizeChangedCallback
onSizeChanged
;
final
ValueChanged
<
Size
>
onSizeChanged
;
RenderSizeObserver
createRenderObject
()
=>
new
RenderSizeObserver
(
onSizeChanged:
onSizeChanged
);
...
...
packages/flutter/lib/src/widgets/editable.dart
View file @
b89935e5
...
...
@@ -158,6 +158,10 @@ class EditableString {
/// The range of text that is currently selected.
TextSelection
get
selection
=>
_client
.
selection
;
void
setSelection
(
TextSelection
selection
)
{
_client
.
selection
=
selection
;
}
/// A keyboard client stub that can be attached to a keyboard service.
///
/// See [Keyboard].
...
...
@@ -180,7 +184,8 @@ class RawEditableLine extends Scrollable {
this
.
hideText
:
false
,
this
.
style
,
this
.
cursorColor
,
this
.
selectionColor
this
.
selectionColor
,
this
.
onSelectionChanged
})
:
super
(
key:
key
,
initialScrollOffset:
0.0
,
...
...
@@ -205,6 +210,9 @@ class RawEditableLine extends Scrollable {
/// The color to use when painting the selection.
final
Color
selectionColor
;
/// Called when the user requests a change to the selection.
final
ValueChanged
<
TextSelection
>
onSelectionChanged
;
RawEditableTextState
createState
()
=>
new
RawEditableTextState
();
}
...
...
@@ -290,6 +298,7 @@ class RawEditableTextState extends ScrollableState<RawEditableLine> {
selectionColor:
config
.
selectionColor
,
hideText:
config
.
hideText
,
onContentSizeChanged:
_handleContentSizeChanged
,
onSelectionChanged:
config
.
onSelectionChanged
,
paintOffset:
new
Offset
(-
scrollOffset
,
0.0
)
)
);
...
...
@@ -306,6 +315,7 @@ class _EditableLineWidget extends LeafRenderObjectWidget {
this
.
selectionColor
,
this
.
hideText
,
this
.
onContentSizeChanged
,
this
.
onSelectionChanged
,
this
.
paintOffset
})
:
super
(
key:
key
);
...
...
@@ -315,7 +325,8 @@ class _EditableLineWidget extends LeafRenderObjectWidget {
final
bool
showCursor
;
final
Color
selectionColor
;
final
bool
hideText
;
final
SizeChangedCallback
onContentSizeChanged
;
final
ValueChanged
<
Size
>
onContentSizeChanged
;
final
ValueChanged
<
TextSelection
>
onSelectionChanged
;
final
Offset
paintOffset
;
RenderEditableLine
createRenderObject
()
{
...
...
@@ -326,19 +337,22 @@ class _EditableLineWidget extends LeafRenderObjectWidget {
selectionColor:
selectionColor
,
selection:
value
.
selection
,
onContentSizeChanged:
onContentSizeChanged
,
onSelectionChanged:
onSelectionChanged
,
paintOffset:
paintOffset
);
}
void
updateRenderObject
(
RenderEditableLine
renderObject
,
_EditableLineWidget
oldWidget
)
{
renderObject
.
text
=
_styledTextSpan
;
renderObject
.
cursorColor
=
cursorColor
;
renderObject
.
showCursor
=
showCursor
;
renderObject
.
selectionColor
=
selectionColor
;
renderObject
.
selection
=
value
.
selection
;
renderObject
.
onContentSizeChanged
=
onContentSizeChanged
;
renderObject
.
paintOffset
=
paintOffset
;
renderObject
..
text
=
_styledTextSpan
..
cursorColor
=
cursorColor
..
showCursor
=
showCursor
..
selectionColor
=
selectionColor
..
selection
=
value
.
selection
..
onContentSizeChanged
=
onContentSizeChanged
..
onSelectionChanged
=
onSelectionChanged
..
paintOffset
=
paintOffset
;
}
StyledTextSpan
get
_styledTextSpan
{
...
...
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