Commit 963fb413 authored by Jason Simmons's avatar Jason Simmons

Merge pull request #1245 from jason-simmons/editable_text_initial_blink

Ensure that EditableText always shows a cursor
parents 9b84e6b8 58b421aa
......@@ -156,6 +156,13 @@ class EditableText extends StatefulComponent {
Timer _cursorTimer;
bool _showCursor = false;
/// Whether the blinking cursor is visible (exposed for testing).
bool get test_showCursor => _showCursor;
/// The cursor blink interval (exposed for testing).
Duration get test_cursorBlinkPeriod =>
new Duration(milliseconds: _kCursorBlinkPeriod);
void _cursorTick(Timer timer) {
setState(() {
_showCursor = !_showCursor;
......@@ -184,11 +191,12 @@ class EditableText extends StatefulComponent {
if (!_showCursor)
return;
double cursorHeight = style.fontSize + 2.0 * _kCursorHeightOffset;
Rect cursorRect = new Rect.fromLTWH(
_kCursorGap,
-_kCursorHeightOffset,
(size.height - cursorHeight) / 2.0,
_kCursorWidth,
style.fontSize + 2 * _kCursorHeightOffset
cursorHeight
);
canvas.drawRect(cursorRect, new Paint()..color = cursorColor);
}
......@@ -203,21 +211,22 @@ class EditableText extends StatefulComponent {
else if (!focused && _cursorTimer != null)
_stopCursorTimer();
if (!value.composing.isValid) {
Widget text;
if (value.composing.isValid) {
TextStyle composingStyle = style.merge(const TextStyle(decoration: underline));
text = new StyledText(elements: [
style,
value.textBefore(value.composing),
[composingStyle, value.textInside(value.composing)],
value.textAfter(value.composing)
]);
} else {
// TODO(eseidel): This is the wrong height if empty!
return new Row([new Text(value.text, style: style)]);
text = new Text(value.text, style: style);
}
TextStyle composingStyle = style.merge(const TextStyle(decoration: underline));
StyledText text = new StyledText(elements: [
style,
value.textBefore(value.composing),
[composingStyle, value.textInside(value.composing)],
value.textAfter(value.composing)
]);
Widget cursor = new Container(
height: style.fontSize,
height: style.fontSize * style.height,
width: _kCursorGap + _kCursorWidth,
child: new CustomPaint(callback: _paintCursor, token: _showCursor)
);
......
import 'package:mojo_services/keyboard/keyboard.mojom.dart';
import 'package:quiver/testing/async.dart';
import 'package:sky/rendering.dart';
import 'package:sky/services.dart';
import 'package:sky/widgets.dart';
......@@ -20,12 +21,12 @@ class MockKeyboard implements KeyboardService {
}
void main() {
MockKeyboard mockKeyboard = new MockKeyboard();
serviceMocker.registerMockService(KeyboardServiceName, mockKeyboard);
test('Editable text has consistent width', () {
WidgetTester tester = new WidgetTester();
MockKeyboard mockKeyboard = new MockKeyboard();
serviceMocker.registerMockService(KeyboardServiceName, mockKeyboard);
GlobalKey inputKey = new GlobalKey();
String inputValue;
......@@ -57,4 +58,41 @@ void main() {
// Check that the Input with text has the same size as the empty Input.
expect((input.renderObject as RenderBox).size, equals(emptyInputSize));
});
test('Cursor blinks', () {
WidgetTester tester = new WidgetTester();
GlobalKey inputKey = new GlobalKey();
Widget builder() {
return new Center(
child: new Input(
key: inputKey,
placeholder: 'Placeholder'
)
);
}
new FakeAsync().run((async) {
tester.pumpFrame(builder);
EditableText editableText = tester.findWidget(
(Widget widget) => widget is EditableText);
// Check that the cursor visibility toggles after each blink interval.
void checkCursorToggle() {
bool initialShowCursor = editableText.test_showCursor;
async.elapse(editableText.test_cursorBlinkPeriod);
expect(editableText.test_showCursor, equals(!initialShowCursor));
async.elapse(editableText.test_cursorBlinkPeriod);
expect(editableText.test_showCursor, equals(initialShowCursor));
}
checkCursorToggle();
// Try the test again with a nonempty EditableText.
mockKeyboard.client.setComposingText('X', 1);
checkCursorToggle();
});
});
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment