[go: nahoru, domu]

Skip to content

Commit

Permalink
Hide EditableString implementation details
Browse files Browse the repository at this point in the history
Previously, EditableString had many public members because it needed to
implement the KeyboardClient interface. However, that's confusing
because these methods cannot be called directly.

Now EditableString holds a private implementation of the KeyboardClient,
which hides the implementation details.

Fixes flutter#208
Fixes flutter#209
  • Loading branch information
abarth committed Jan 26, 2016
1 parent 7737117 commit f0ea0ea
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 37 deletions.
2 changes: 1 addition & 1 deletion packages/flutter/lib/src/material/input.dart
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ class _InputState extends State<Input> {
_editableString.selection.end);
} else if (!focused && _keyboardHandle.attached) {
_keyboardHandle.release();
_editableString.composing = TextRange.empty;
_editableString.didDetachKeyboard();
}
}

Expand Down
4 changes: 3 additions & 1 deletion packages/flutter/lib/src/services/keyboard.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@ class _KeyboardConnection {
static final _KeyboardConnection instance = new _KeyboardConnection();
}

/// An interface to the system's keyboard.
///
/// Most clients will want to use the [keyboard] singleton instance.
class Keyboard {

Keyboard(this.service);

// The service is exposed in case you need direct access.
Expand Down
105 changes: 70 additions & 35 deletions packages/flutter/lib/src/widgets/editable.dart
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,7 @@ class TextRange {
end = position;

/// A text range that contains nothing and is not in the text.
const TextRange._empty()
: start = -1,
end = -1;

static const TextRange empty = const TextRange._empty();
static const TextRange empty = const TextRange(start: -1, end: -1);

/// The index of the first character in the range.
final int start;
Expand All @@ -43,11 +39,29 @@ class TextRange {

/// Whether this range is empty (but still potentially placed inside the text).
bool get isCollapsed => start == end;

/// The text before this range.
String textBefore(String text) {
return text.substring(0, start);
}

/// The text after this range.
String textAfter(String text) {
return text.substring(end);
}

/// The text inside this range.
String textInside(String text) {
return text.substring(start, end);
}
}

/// A string that can be manipulated by a keyboard.
class EditableString implements KeyboardClient {
EditableString({this.text: '', this.onUpdated, this.onSubmitted}) {
class _KeyboardClientImpl implements KeyboardClient {
_KeyboardClientImpl({
this.text: '',
this.onUpdated,
this.onSubmitted
}) {
assert(onUpdated != null);
assert(onSubmitted != null);
stub = new KeyboardClientStub.unbound()..impl = this;
Expand All @@ -57,39 +71,24 @@ class EditableString implements KeyboardClient {
/// The current text being edited.
String text;

// The range of text that is still being composed.
TextRange composing = TextRange.empty;

/// The range of text that is currently selected.
TextRange selection;

/// Called whenever the text changes.
final VoidCallback onUpdated;

/// Called whenever the user indicates they are done editing the string.
final VoidCallback onSubmitted;

/// A keyboard client stub that can be attached to a keyboard service.
KeyboardClientStub stub;

/// The text before the given range.
String textBefore(TextRange range) {
return text.substring(0, range.start);
}
// The range of text that is still being composed.
TextRange composing = TextRange.empty;

/// The text after the given range.
String textAfter(TextRange range) {
return text.substring(range.end);
}
/// The range of text that is currently selected.
TextRange selection = TextRange.empty;

/// The text inside the given range.
String textInside(TextRange range) {
return text.substring(range.start, range.end);
}
/// A keyboard client stub that can be attached to a keyboard service.
KeyboardClientStub stub;

void _delete(TextRange range) {
if (range.isCollapsed || !range.isValid) return;
text = textBefore(range) + textAfter(range);
text = range.textBefore(text) + range.textAfter(text);
}

TextRange _append(String newText) {
Expand All @@ -101,8 +100,8 @@ class EditableString implements KeyboardClient {
TextRange _replace(TextRange range, String newText) {
assert(range.isValid);

String before = textBefore(range);
String after = textAfter(range);
String before = range.textBefore(text);
String after = range.textAfter(text);

text = before + newText + after;
return new TextRange(
Expand Down Expand Up @@ -168,6 +167,42 @@ class EditableString implements KeyboardClient {
}
}

/// A string that can be manipulated by a keyboard.
///
/// Can be displayed with [RawEditableLine]. For a more featureful input widget,
/// consider using [Input].
class EditableString {
EditableString({
String text: '',
VoidCallback onUpdated,
VoidCallback onSubmitted
}) : _client = new _KeyboardClientImpl(
text: text,
onUpdated: onUpdated,
onSubmitted: onSubmitted
);

final _KeyboardClientImpl _client;

/// The current text being edited.
String get text => _client.text;

// The range of text that is still being composed.
TextRange get composing => _client.composing;

/// The range of text that is currently selected.
TextRange get selection => _client.selection;

/// A keyboard client stub that can be attached to a keyboard service.
///
/// See [Keyboard].
KeyboardClientStub get stub => _client.stub;

void didDetachKeyboard() {
_client.composing = TextRange.empty;
}
}

/// A basic single-line input control.
///
/// This control is not intended to be used directly. Instead, consider using
Expand Down Expand Up @@ -337,11 +372,11 @@ class _EditableLineWidget extends LeafRenderObjectWidget {
);

return new StyledTextSpan(style, <TextSpan>[
new PlainTextSpan(value.textBefore(value.composing)),
new PlainTextSpan(value.composing.textBefore(value.text)),
new StyledTextSpan(composingStyle, <TextSpan>[
new PlainTextSpan(value.textInside(value.composing))
new PlainTextSpan(value.composing.textInside(value.text))
]),
new PlainTextSpan(value.textAfter(value.composing))
new PlainTextSpan(value.composing.textAfter(value.text))
]);
}

Expand Down

1 comment on commit f0ea0ea

@jason-simmons
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Please sign in to comment.