flutter_flutter/sdk/lib/framework/editing/editable_string.dart
John McCutchan b017dfd995 Rationalize Dart mojo and sky package structure.
NOTE: This CL appears far larger than it actually is for two reasons:

1) Many files were moved around to use the Dart package directory structure.
2) Many .dart files had to have import paths updated.

- Organize mojo/public/dart so that it uses standard Dart package layout
- Organize mojo/dart/apptest so that it uses a standard Dart package layout
- Organize sky/sdk so that it uses a standard Dart package layout
- Create a mojo/testing package (used by unittests)
- Introduce the 'dart_pkg' gn rule which populates gen/Config/dart-pkg
- All internally vended Dart packages must have a corresponding dart_pkg rule
- It is now possible to use dependency_overrides: in pubspec.yaml to mix internal and external package dependencies (enables analyzer, editor, webstorm usage for internal developers).
- Package root for dart content handler ends with "packages/"
- Imports of mojo package uris no longer need the "public/dart"
- mojo/public/tools/dart_package.py is a clone of mojo/public/tools/gn/zip.py
- Sky tests no longer run 'deploy_sdk' script.

R=eseidel@chromium.org

Review URL: https://codereview.chromium.org/1132063007
2015-05-18 14:41:39 -07:00

123 lines
3.3 KiB
Dart

// 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();
}
}