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
b89d81a9
Commit
b89d81a9
authored
Feb 02, 2016
by
Adam Barth
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1522 from abarth/editing_mojom
Update to new editing.mojom
parents
6f1d4df3
fade0dc0
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
75 additions
and
157 deletions
+75
-157
input.dart
packages/flutter/lib/src/material/input.dart
+10
-7
keyboard.dart
packages/flutter/lib/src/services/keyboard.dart
+16
-25
editable.dart
packages/flutter/lib/src/widgets/editable.dart
+30
-77
input_test.dart
packages/flutter/test/widget/input_test.dart
+19
-48
No files found.
packages/flutter/lib/src/material/input.dart
View file @
b89d81a9
...
...
@@ -6,6 +6,7 @@ import 'package:flutter/animation.dart';
import
'package:flutter/rendering.dart'
;
import
'package:flutter/services.dart'
;
import
'package:flutter/widgets.dart'
;
import
'package:sky_services/editing/editing.mojom.dart'
as
mojom
;
import
'colors.dart'
;
import
'debug.dart'
;
...
...
@@ -13,7 +14,7 @@ import 'icon.dart';
import
'theme.dart'
;
export
'package:flutter/rendering.dart'
show
ValueChanged
;
export
'package:
flutter/services
.dart'
show
KeyboardType
;
export
'package:
sky_services/editing/editing.mojom
.dart'
show
KeyboardType
;
/// A material design text input field.
class
Input
extends
StatefulComponent
{
...
...
@@ -110,10 +111,11 @@ class _InputState extends State<Input> {
void
_attachOrDetachKeyboard
(
bool
focused
)
{
if
(
focused
&&
!
_isAttachedToKeyboard
)
{
_keyboardHandle
=
keyboard
.
show
(
_editableString
.
createStub
(),
config
.
keyboardType
);
_keyboardHandle
.
setText
(
_editableString
.
text
);
_keyboardHandle
.
setSelection
(
_editableString
.
selection
.
start
,
_editableString
.
selection
.
end
);
_keyboardHandle
=
keyboard
.
attach
(
_editableString
.
createStub
(),
new
mojom
.
KeyboardConfiguration
()
..
type
=
config
.
keyboardType
);
_keyboardHandle
.
setEditingState
(
_editableString
.
editingState
);
_keyboardHandle
.
show
();
}
else
if
(!
focused
&&
_isAttachedToKeyboard
)
{
_keyboardHandle
.
release
();
_keyboardHandle
=
null
;
...
...
@@ -124,7 +126,7 @@ class _InputState extends State<Input> {
void
_requestKeyboard
()
{
if
(
Focus
.
at
(
context
))
{
assert
(
_isAttachedToKeyboard
);
_keyboardHandle
.
show
ByRequest
();
_keyboardHandle
.
show
();
}
else
{
Focus
.
moveTo
(
config
.
key
);
// we'll get told to rebuild and we'll take care of the keyboard then
...
...
@@ -149,7 +151,8 @@ class _InputState extends State<Input> {
void
_handleSelectionChanged
(
TextSelection
selection
)
{
if
(
_isAttachedToKeyboard
)
{
_keyboardHandle
.
setSelection
(
selection
.
start
,
selection
.
end
);
_editableString
.
setSelection
(
selection
);
_keyboardHandle
.
setEditingState
(
_editableString
.
editingState
);
}
else
{
_editableString
.
setSelection
(
selection
);
_requestKeyboard
();
...
...
packages/flutter/lib/src/services/keyboard.dart
View file @
b89d81a9
...
...
@@ -4,11 +4,11 @@
import
'dart:async'
;
import
'package:
mojo_services/keyboard/keyboard.mojom.dart'
;
import
'package:
sky_services/editing/editing.mojom.dart'
as
mojom
;
import
'binding.dart'
;
export
'package:
mojo_services/keyboard/keyboard.mojom.dart'
;
export
'package:
sky_services/editing/editing.mojom.dart'
show
KeyboardType
;
/// An interface to the system's keyboard.
///
...
...
@@ -19,22 +19,24 @@ class Keyboard {
// The service is exposed in case you need direct access.
// However, as a general rule, you should be able to do
// most of what you need using only this class.
final
KeyboardService
service
;
final
mojom
.
Keyboard
service
;
KeyboardHandle
_currentHandle
;
bool
_hidePending
=
false
;
KeyboardHandle
show
(
KeyboardClientStub
stub
,
KeyboardType
keyboardType
)
{
KeyboardHandle
attach
(
mojom
.
KeyboardClientStub
stub
,
mojom
.
KeyboardConfiguration
configuration
)
{
assert
(
stub
!=
null
);
_currentHandle
?.
release
();
assert
(
_currentHandle
==
null
);
_currentHandle
=
new
KeyboardHandle
.
_show
(
this
,
stub
,
keyboardType
);
_currentHandle
=
new
KeyboardHandle
.
_
(
this
);
service
.
setClient
(
stub
,
configuration
);
return
_currentHandle
;
}
void
_scheduleHide
()
{
if
(
_hidePending
)
return
;
if
(
_hidePending
)
return
;
_hidePending
=
true
;
// Schedule a deferred task that hides the keyboard. If someone else shows
...
...
@@ -50,21 +52,17 @@ class Keyboard {
}
class
KeyboardHandle
{
KeyboardHandle
.
_show
(
Keyboard
keyboard
,
KeyboardClientStub
stub
,
KeyboardType
keyboardType
)
:
_keyboard
=
keyboard
{
_keyboard
.
service
.
show
(
stub
,
keyboardType
);
_attached
=
true
;
}
KeyboardHandle
.
_
(
Keyboard
keyboard
)
:
_keyboard
=
keyboard
,
_attached
=
true
;
final
Keyboard
_keyboard
;
bool
_attached
;
bool
get
attached
=>
_attached
;
void
show
ByRequest
()
{
void
show
()
{
assert
(
_attached
);
assert
(
_keyboard
.
_currentHandle
==
this
);
_keyboard
.
service
.
show
ByRequest
();
_keyboard
.
service
.
show
();
}
void
release
()
{
...
...
@@ -77,25 +75,18 @@ class KeyboardHandle {
assert
(
_keyboard
.
_currentHandle
!=
this
);
}
void
set
Text
(
String
text
)
{
void
set
EditingState
(
mojom
.
EditingState
state
)
{
assert
(
_attached
);
assert
(
_keyboard
.
_currentHandle
==
this
);
_keyboard
.
service
.
set
Text
(
text
);
_keyboard
.
service
.
set
EditingState
(
state
);
}
void
setSelection
(
int
start
,
int
end
)
{
assert
(
_attached
);
assert
(
_keyboard
.
_currentHandle
==
this
);
_keyboard
.
service
.
setSelection
(
start
,
end
);
}
}
KeyboardService
Proxy
_initKeyboardProxy
(
)
{
KeyboardServiceProxy
proxy
=
new
KeyboardService
Proxy
.
unbound
();
mojom
.
Keyboard
Proxy
_initKeyboardProxy
(
)
{
mojom
.
KeyboardProxy
proxy
=
new
mojom
.
Keyboard
Proxy
.
unbound
();
shell
.
connectToService
(
null
,
proxy
);
return
proxy
;
}
final
KeyboardService
Proxy
_keyboardProxy
=
_initKeyboardProxy
();
final
mojom
.
Keyboard
Proxy
_keyboardProxy
=
_initKeyboardProxy
();
final
Keyboard
keyboard
=
new
Keyboard
(
_keyboardProxy
.
ptr
);
packages/flutter/lib/src/widgets/editable.dart
View file @
b89d81a9
...
...
@@ -3,9 +3,8 @@
// found in the LICENSE file.
import
'dart:async'
;
import
'dart:math'
as
math
;
import
'package:
mojo_services/keyboard/keyboard.mojom.dart'
;
import
'package:
sky_services/editing/editing.mojom.dart'
as
mojom
;
import
'package:flutter/painting.dart'
;
import
'package:flutter/rendering.dart'
;
...
...
@@ -18,7 +17,16 @@ export 'package:flutter/painting.dart' show TextSelection;
const
Duration
_kCursorBlinkHalfPeriod
=
const
Duration
(
milliseconds:
500
);
class
_KeyboardClientImpl
implements
KeyboardClient
{
TextSelection
_getTextSelectionFromEditingState
(
mojom
.
EditingState
state
)
{
return
new
TextSelection
(
baseOffset:
state
.
selectionBase
,
extentOffset:
state
.
selectionExtent
,
affinity:
TextAffinity
.
values
[
state
.
selectionAffinity
.
mojoEnumValue
],
isDirectional:
state
.
selectionIsDirectional
);
}
class
_KeyboardClientImpl
implements
mojom
.
KeyboardClient
{
_KeyboardClientImpl
({
String
text:
''
,
TextSelection
selection
,
...
...
@@ -45,86 +53,29 @@ class _KeyboardClientImpl implements KeyboardClient {
TextSelection
selection
;
/// A keyboard client stub that can be attached to a keyboard service.
KeyboardClientStub
createStub
()
{
return
new
KeyboardClientStub
.
unbound
()..
impl
=
this
;
}
void
_delete
(
TextRange
range
)
{
if
(
range
.
isCollapsed
||
!
range
.
isValid
)
return
;
text
=
range
.
textBefore
(
text
)
+
range
.
textAfter
(
text
);
}
TextRange
_append
(
String
newText
)
{
int
start
=
text
.
length
;
text
+=
newText
;
return
new
TextRange
(
start:
start
,
end:
start
+
newText
.
length
);
}
TextRange
_replace
(
TextRange
range
,
String
newText
)
{
assert
(
range
.
isValid
);
String
before
=
range
.
textBefore
(
text
);
String
after
=
range
.
textAfter
(
text
);
text
=
before
+
newText
+
after
;
return
new
TextRange
(
start:
before
.
length
,
end:
before
.
length
+
newText
.
length
);
}
TextRange
_replaceOrAppend
(
TextRange
range
,
String
newText
)
{
if
(!
range
.
isValid
)
return
_append
(
newText
);
return
_replace
(
range
,
newText
);
}
void
commitCompletion
(
CompletionData
completion
)
{
// TODO(abarth): Not implemented.
mojom
.
KeyboardClientStub
createStub
()
{
return
new
mojom
.
KeyboardClientStub
.
unbound
()..
impl
=
this
;
}
void
commitCorrection
(
CorrectionData
correction
)
{
// TODO(abarth): Not implemented.
mojom
.
EditingState
get
editingState
{
return
new
mojom
.
EditingState
()
..
text
=
text
..
selectionBase
=
selection
.
baseOffset
..
selectionExtent
=
selection
.
extentOffset
..
selectionAffinity
=
mojom
.
TextAffinity
.
values
[
selection
.
affinity
.
index
]
..
selectionIsDirectional
=
selection
.
isDirectional
..
composingBase
=
composing
.
start
..
composingExtent
=
composing
.
end
;
}
void
commitText
(
String
text
,
int
newCursorPosition
)
{
// TODO(abarth): Why is |newCursorPosition| always 1?
TextRange
committedRange
=
_replaceOrAppend
(
composing
,
text
);
selection
=
new
TextSelection
.
collapsed
(
offset:
committedRange
.
end
);
composing
=
TextRange
.
empty
;
onUpdated
();
}
void
deleteSurroundingText
(
int
beforeLength
,
int
afterLength
)
{
TextRange
beforeRange
=
new
TextRange
(
start:
selection
.
start
-
beforeLength
,
end:
selection
.
start
);
int
afterRangeEnd
=
math
.
min
(
selection
.
end
+
afterLength
,
text
.
length
);
TextRange
afterRange
=
new
TextRange
(
start:
selection
.
end
,
end:
afterRangeEnd
);
_delete
(
afterRange
);
_delete
(
beforeRange
);
selection
=
new
TextSelection
(
baseOffset:
math
.
max
(
selection
.
start
-
beforeLength
,
0
),
extentOffset:
math
.
max
(
selection
.
end
-
beforeLength
,
0
)
);
onUpdated
();
}
void
setComposingRegion
(
int
start
,
int
end
)
{
composing
=
new
TextRange
(
start:
start
,
end:
end
);
void
updateEditingState
(
mojom
.
EditingState
state
)
{
text
=
state
.
text
;
selection
=
_getTextSelectionFromEditingState
(
state
);
composing
=
new
TextRange
(
start:
state
.
composingBase
,
end:
state
.
composingExtent
);
onUpdated
();
}
void
setComposingText
(
String
text
,
int
newCursorPosition
)
{
// TODO(abarth): Why is |newCursorPosition| always 1?
composing
=
_replaceOrAppend
(
composing
,
text
);
selection
=
new
TextSelection
.
collapsed
(
offset:
composing
.
end
);
onUpdated
();
}
void
setSelection
(
int
start
,
int
end
)
{
selection
=
new
TextSelection
(
baseOffset:
start
,
extentOffset:
end
);
onUpdated
();
}
void
submit
(
SubmitAction
action
)
{
void
submit
(
mojom
.
SubmitAction
action
)
{
composing
=
TextRange
.
empty
;
onSubmitted
();
}
...
...
@@ -162,10 +113,12 @@ class EditableString {
_client
.
selection
=
selection
;
}
mojom
.
EditingState
get
editingState
=>
_client
.
editingState
;
/// A keyboard client stub that can be attached to a keyboard service.
///
/// See [Keyboard].
KeyboardClientStub
createStub
()
=>
_client
.
createStub
();
mojom
.
KeyboardClientStub
createStub
()
=>
_client
.
createStub
();
void
didDetachKeyboard
()
{
_client
.
composing
=
TextRange
.
empty
;
...
...
packages/flutter/test/widget/input_test.dart
View file @
b89d81a9
...
...
@@ -5,32 +5,29 @@
import
'package:flutter_test/flutter_test.dart'
;
import
'package:flutter/material.dart'
;
import
'package:flutter/rendering.dart'
;
import
'package:flutter/services.dart'
;
import
'package:mojo_services/keyboard/keyboard.mojom.dart'
;
import
'package:sky_services/editing/editing.mojom.dart'
as
mojom
;
import
'package:test/test.dart'
;
import
'../services/mock_services.dart'
;
class
MockKeyboard
implements
KeyboardService
{
KeyboardClient
client
;
class
MockKeyboard
implements
mojom
.
Keyboard
{
mojom
.
KeyboardClient
client
;
void
s
how
(
KeyboardClientStub
client
,
KeyboardType
type
)
{
void
s
etClient
(
mojom
.
KeyboardClientStub
client
,
mojom
.
KeyboardConfiguration
configuraiton
)
{
this
.
client
=
client
.
impl
;
}
void
show
ByRequest
()
{}
void
show
()
{}
void
hide
()
{}
void
setText
(
String
text
)
{}
void
setSelection
(
int
start
,
int
end
)
{}
void
setEditingState
(
mojom
.
EditingState
state
)
{}
}
void
main
(
)
{
WidgetFlutterBinding
.
ensureInitialized
();
// for serviceMocker
MockKeyboard
mockKeyboard
=
new
MockKeyboard
();
serviceMocker
.
registerMockService
(
KeyboardService
.
serviceName
,
mockKeyboard
);
serviceMocker
.
registerMockService
(
mojom
.
Keyboard
.
serviceName
,
mockKeyboard
);
test
(
'Editable text has consistent size'
,
()
{
testWidgets
((
WidgetTester
tester
)
{
...
...
@@ -57,7 +54,10 @@ void main() {
void
enterText
(
String
testValue
)
{
// Simulate entry of text through the keyboard.
expect
(
mockKeyboard
.
client
,
isNotNull
);
mockKeyboard
.
client
.
setComposingText
(
testValue
,
testValue
.
length
);
mockKeyboard
.
client
.
updateEditingState
(
new
mojom
.
EditingState
()
..
text
=
testValue
..
composingBase
=
0
..
composingExtent
=
testValue
.
length
);
// Check that the onChanged event handler fired.
expect
(
inputValue
,
equals
(
testValue
));
...
...
@@ -110,46 +110,14 @@ void main() {
checkCursorToggle
();
// Try the test again with a nonempty EditableText.
mockKeyboard
.
client
.
setComposingText
(
'X'
,
1
);
mockKeyboard
.
client
.
updateEditingState
(
new
mojom
.
EditingState
()
..
text
=
'X'
..
selectionBase
=
1
..
selectionExtent
=
1
);
checkCursorToggle
();
});
});
test
(
'Selection remains valid'
,
()
{
testWidgets
((
WidgetTester
tester
)
{
GlobalKey
inputKey
=
new
GlobalKey
();
Widget
builder
()
{
return
new
Center
(
child:
new
Material
(
child:
new
Input
(
key:
inputKey
,
hintText:
'Placeholder'
)
)
);
}
tester
.
pumpWidget
(
builder
());
const
String
testValue
=
'ABC'
;
mockKeyboard
.
client
.
commitText
(
testValue
,
testValue
.
length
);
dynamic
input
=
inputKey
.
currentState
;
// Delete characters and verify that the selection follows the length
// of the text.
for
(
int
i
=
0
;
i
<
testValue
.
length
;
i
++)
{
mockKeyboard
.
client
.
deleteSurroundingText
(
1
,
0
);
expect
(
input
.
editableValue
.
selection
.
start
,
equals
(
testValue
.
length
-
i
-
1
));
}
// Delete a characters when the text is empty. The selection should
// remain at zero.
mockKeyboard
.
client
.
deleteSurroundingText
(
1
,
0
);
expect
(
input
.
editableValue
.
selection
.
start
,
equals
(
0
));
});
});
test
(
'hideText control test'
,
()
{
testWidgets
((
WidgetTester
tester
)
{
GlobalKey
inputKey
=
new
GlobalKey
();
...
...
@@ -169,7 +137,10 @@ void main() {
tester
.
pumpWidget
(
builder
());
const
String
testValue
=
'ABC'
;
mockKeyboard
.
client
.
commitText
(
testValue
,
testValue
.
length
);
mockKeyboard
.
client
.
updateEditingState
(
new
mojom
.
EditingState
()
..
text
=
testValue
..
selectionBase
=
testValue
.
length
..
selectionExtent
=
testValue
.
length
);
tester
.
pump
();
});
...
...
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