mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Apparently I didn't so much _move_ the files as _delete_ the files. Let's re-add them.
TBR=abarth Review URL: https://codereview.chromium.org/1177223007.
This commit is contained in:
parent
82019129c1
commit
69685d5478
122
sdk/lib/editing/editable_string.dart
Normal file
122
sdk/lib/editing/editable_string.dart
Normal file
@ -0,0 +1,122 @@
|
||||
// Copyright 2015 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:mojom/keyboard/keyboard.mojom.dart';
|
||||
|
||||
typedef void StringUpdated();
|
||||
|
||||
class TextRange {
|
||||
final int start;
|
||||
final int end;
|
||||
|
||||
TextRange({this.start, this.end});
|
||||
TextRange.collapsed(int position)
|
||||
: start = position,
|
||||
end = position;
|
||||
const TextRange.empty()
|
||||
: start = -1,
|
||||
end = -1;
|
||||
|
||||
bool get isValid => start >= 0 && end >= 0;
|
||||
bool get isCollapsed => start == end;
|
||||
}
|
||||
|
||||
class EditableString implements KeyboardClient {
|
||||
String text;
|
||||
TextRange composing = const TextRange.empty();
|
||||
TextRange selection = const TextRange.empty();
|
||||
|
||||
final StringUpdated onUpdated;
|
||||
|
||||
KeyboardClientStub stub;
|
||||
|
||||
EditableString({this.text: '', this.onUpdated}) {
|
||||
stub = new KeyboardClientStub.unbound()..impl = this;
|
||||
}
|
||||
|
||||
String textBefore(TextRange range) {
|
||||
return text.substring(0, range.start);
|
||||
}
|
||||
|
||||
String textAfter(TextRange range) {
|
||||
return text.substring(range.end);
|
||||
}
|
||||
|
||||
String textInside(TextRange range) {
|
||||
return text.substring(range.start, range.end);
|
||||
}
|
||||
|
||||
void _delete(TextRange range) {
|
||||
if (range.isCollapsed || !range.isValid) return;
|
||||
text = textBefore(range) + textAfter(range);
|
||||
}
|
||||
|
||||
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 = textBefore(range);
|
||||
String after = textAfter(range);
|
||||
|
||||
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.
|
||||
}
|
||||
|
||||
void commitCorrection(CorrectionData correction) {
|
||||
// TODO(abarth): Not implemented.
|
||||
}
|
||||
|
||||
void commitText(String text, int newCursorPosition) {
|
||||
// TODO(abarth): Why is |newCursorPosition| always 1?
|
||||
TextRange committedRange = _replaceOrAppend(composing, text);
|
||||
selection = new TextRange.collapsed(committedRange.end);
|
||||
composing = const TextRange.empty();
|
||||
onUpdated();
|
||||
}
|
||||
|
||||
void deleteSurroundingText(int beforeLength, int afterLength) {
|
||||
TextRange beforeRange = new TextRange(
|
||||
start: selection.start - beforeLength, end: selection.start);
|
||||
TextRange afterRange =
|
||||
new TextRange(start: selection.end, end: selection.end + afterLength);
|
||||
_delete(afterRange);
|
||||
_delete(beforeRange);
|
||||
selection = new TextRange(
|
||||
start: selection.start - beforeLength,
|
||||
end: selection.end - beforeLength);
|
||||
onUpdated();
|
||||
}
|
||||
|
||||
void setComposingRegion(int start, int end) {
|
||||
composing = new TextRange(start: start, end: end);
|
||||
onUpdated();
|
||||
}
|
||||
|
||||
void setComposingText(String text, int newCursorPosition) {
|
||||
// TODO(abarth): Why is |newCursorPosition| always 1?
|
||||
composing = _replaceOrAppend(composing, text);
|
||||
selection = new TextRange.collapsed(composing.end);
|
||||
onUpdated();
|
||||
}
|
||||
|
||||
void setSelection(int start, int end) {
|
||||
selection = new TextRange(start: start, end: end);
|
||||
onUpdated();
|
||||
}
|
||||
}
|
||||
98
sdk/lib/editing/editable_text.dart
Normal file
98
sdk/lib/editing/editable_text.dart
Normal file
@ -0,0 +1,98 @@
|
||||
// Copyright 2015 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import '../widgets/basic.dart';
|
||||
import 'editable_string.dart';
|
||||
|
||||
class EditableText extends Component {
|
||||
|
||||
EditableText({String key, this.value, this.focused})
|
||||
: super(key: key, stateful: true);
|
||||
|
||||
// static final Style _cursorStyle = new Style('''
|
||||
// width: 2px;
|
||||
// height: 1.2em;
|
||||
// vertical-align: top;
|
||||
// background-color: ${Blue[500]};'''
|
||||
// );
|
||||
|
||||
// static final Style _composingStyle = new Style('''
|
||||
// text-decoration: underline;'''
|
||||
// );
|
||||
|
||||
EditableString value;
|
||||
bool focused;
|
||||
|
||||
void syncFields(EditableText source) {
|
||||
value = source.value;
|
||||
focused = source.focused;
|
||||
}
|
||||
|
||||
Timer _cursorTimer;
|
||||
bool _showCursor = false;
|
||||
|
||||
void _cursorTick(Timer timer) {
|
||||
setState(() {
|
||||
_showCursor = !_showCursor;
|
||||
});
|
||||
}
|
||||
|
||||
void _startCursorTimer() {
|
||||
_showCursor = true;
|
||||
_cursorTimer = new Timer.periodic(
|
||||
new Duration(milliseconds: 500), _cursorTick);
|
||||
}
|
||||
|
||||
void didUnmount() {
|
||||
if (_cursorTimer != null)
|
||||
_stopCursorTimer();
|
||||
super.didUnmount();
|
||||
}
|
||||
|
||||
void _stopCursorTimer() {
|
||||
_cursorTimer.cancel();
|
||||
_cursorTimer = null;
|
||||
_showCursor = false;
|
||||
}
|
||||
|
||||
Widget build() {
|
||||
if (focused && _cursorTimer == null)
|
||||
_startCursorTimer();
|
||||
else if (!focused && _cursorTimer != null)
|
||||
_stopCursorTimer();
|
||||
|
||||
//List<Widget> children = new List<Widget>();
|
||||
String hack = "";
|
||||
|
||||
if (!value.composing.isValid) {
|
||||
// children.add(new TextFragment(value.text));
|
||||
hack += value.text;
|
||||
} else {
|
||||
hack += value.textBefore(value.composing);
|
||||
hack += value.textInside(value.composing);
|
||||
hack += value.textAfter(value.composing);
|
||||
// if (!composing.isEmpty) {
|
||||
// children.add(new TextFragment(
|
||||
// composing,
|
||||
// key: 'composing',
|
||||
// style: _composingStyle
|
||||
// ));
|
||||
// }
|
||||
|
||||
// String afterComposing = value.textAfter(value.composing);
|
||||
// if (!afterComposing.isEmpty)
|
||||
// children.add(new TextFragment(afterComposing));
|
||||
}
|
||||
|
||||
// if (_showCursor)
|
||||
// children.add(new Container(
|
||||
// key: 'cursor',
|
||||
// // style: _cursorStyle
|
||||
// ));
|
||||
|
||||
return new Text(hack);
|
||||
}
|
||||
}
|
||||
101
sdk/lib/editing/input.dart
Normal file
101
sdk/lib/editing/input.dart
Normal file
@ -0,0 +1,101 @@
|
||||
// Copyright 2015 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import '../widgets/basic.dart';
|
||||
import 'editable_string.dart';
|
||||
import 'editable_text.dart';
|
||||
import 'keyboard.dart';
|
||||
|
||||
typedef void ValueChanged(value);
|
||||
|
||||
class Input extends Component {
|
||||
|
||||
Input({String key,
|
||||
this.placeholder,
|
||||
this.onChanged,
|
||||
this.focused})
|
||||
: super(key: key, stateful: true) {
|
||||
_editableValue = new EditableString(
|
||||
text: _value,
|
||||
onUpdated: _handleTextUpdated
|
||||
);
|
||||
}
|
||||
|
||||
// static final Style _style = new Style('''
|
||||
// transform: translateX(0);
|
||||
// margin: 8px;
|
||||
// padding: 8px;
|
||||
// border-bottom: 1px solid ${Grey[200]};
|
||||
// align-self: center;
|
||||
// height: 1.2em;
|
||||
// white-space: pre;
|
||||
// overflow: hidden;'''
|
||||
// );
|
||||
|
||||
// static final Style _placeholderStyle = new Style('''
|
||||
// top: 8px;
|
||||
// left: 8px;
|
||||
// position: absolute;
|
||||
// ${typography.black.caption};'''
|
||||
// );
|
||||
|
||||
// static final String _focusedInlineStyle = '''
|
||||
// padding: 7px;
|
||||
// border-bottom: 2px solid ${Blue[500]};''';
|
||||
|
||||
String placeholder;
|
||||
ValueChanged onChanged;
|
||||
bool focused = false;
|
||||
|
||||
void syncFields(Input source) {
|
||||
placeholder = source.placeholder;
|
||||
onChanged = source.onChanged;
|
||||
focused = source.focused;
|
||||
}
|
||||
|
||||
String _value = '';
|
||||
bool _isAttachedToKeyboard = false;
|
||||
EditableString _editableValue;
|
||||
|
||||
void _handleTextUpdated() {
|
||||
scheduleBuild();
|
||||
if (_value != _editableValue.text) {
|
||||
_value = _editableValue.text;
|
||||
if (onChanged != null)
|
||||
onChanged(_value);
|
||||
}
|
||||
}
|
||||
|
||||
Widget build() {
|
||||
if (focused && !_isAttachedToKeyboard) {
|
||||
keyboard.show(_editableValue.stub);
|
||||
_isAttachedToKeyboard = true;
|
||||
}
|
||||
|
||||
List<Widget> children = [];
|
||||
|
||||
if (placeholder != null && _value.isEmpty) {
|
||||
children.add(new Container(
|
||||
// style: _placeholderStyle,
|
||||
child: new Text(placeholder)
|
||||
));
|
||||
}
|
||||
|
||||
children.add(new EditableText(value: _editableValue, focused: focused));
|
||||
|
||||
return new Listener(
|
||||
// style: _style,
|
||||
// inlineStyle: focused ? _focusedInlineStyle : null,
|
||||
child: new Stack(children),
|
||||
onPointerDown: (_) => keyboard.showByRequest()
|
||||
);
|
||||
}
|
||||
|
||||
void didUnmount() {
|
||||
if (_isAttachedToKeyboard)
|
||||
keyboard.hide();
|
||||
super.didUnmount();
|
||||
}
|
||||
|
||||
}
|
||||
21
sdk/lib/editing/keyboard.dart
Normal file
21
sdk/lib/editing/keyboard.dart
Normal file
@ -0,0 +1,21 @@
|
||||
// Copyright 2015 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:mojom/keyboard/keyboard.mojom.dart';
|
||||
|
||||
import '../framework/shell.dart' as shell;
|
||||
|
||||
class _KeyboardConnection {
|
||||
KeyboardServiceProxy proxy;
|
||||
|
||||
_KeyboardConnection() {
|
||||
proxy = new KeyboardServiceProxy.unbound();
|
||||
shell.requestService("mojo:keyboard", proxy);
|
||||
}
|
||||
|
||||
KeyboardService get keyboard => proxy.ptr;
|
||||
}
|
||||
|
||||
final _KeyboardConnection _connection = new _KeyboardConnection();
|
||||
final KeyboardService keyboard = _connection.keyboard;
|
||||
Loading…
x
Reference in New Issue
Block a user