Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1951)

Unified Diff: dart/site/try/src/interaction_manager.dart

Issue 265063002: Better handling of large files. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge
Patch Set: Merged with r35799 Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « dart/site/try/line_numbers.css ('k') | dart/site/try/src/selection.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: dart/site/try/src/interaction_manager.dart
diff --git a/dart/site/try/src/interaction_manager.dart b/dart/site/try/src/interaction_manager.dart
index 5b309a96cbcbe2fff1d870ac2d033120d9539b94..4d4dd24d06b7b0a7e121b040d4895eae4d6983b6 100644
--- a/dart/site/try/src/interaction_manager.dart
+++ b/dart/site/try/src/interaction_manager.dart
@@ -92,6 +92,8 @@ abstract class InteractionManager {
void onInput(Event event);
+ // TODO(ahe): Rename to onKeyDown (as it is called in response to keydown
+ // event).
void onKeyUp(KeyboardEvent event);
void onMutation(List<MutationRecord> mutations, MutationObserver observer);
@@ -228,13 +230,28 @@ class InitialState extends InteractionState {
void onUnmodifiedKeyUp(KeyboardEvent event) {
switch (event.keyCode) {
case KeyCode.ENTER: {
- event.preventDefault();
Selection selection = window.getSelection();
- if (isCollapsed(selection) && selection.anchorNode is Text) {
- Text text = selection.anchorNode;
- int offset = selection.anchorOffset;
- text.insertData(offset, '\n');
- selection.collapse(text, offset + 1);
+ if (isCollapsed(selection)) {
+ event.preventDefault();
+ Node node = selection.anchorNode;
+ if (node is Text) {
+ Text text = node;
+ int offset = selection.anchorOffset;
+ // If at end-of-file, insert an extra newline. The the extra
+ // newline ensures that the next line isn't empty. At least Chrome
+ // behaves as if "\n" is just a single line. "\nc" (where c is any
+ // character) is two lines, according to Chrome.
+ String newline = isAtEndOfFile(text, offset) ? '\n\n' : '\n';
+ text.insertData(offset, newline);
+ selection.collapse(text, offset + 1);
+ } else if (node is Element) {
+ node.appendText('\n\n');
+ selection.collapse(node.firstChild, 1);
+ } else {
+ window.console
+ ..error('Unexpected node')
+ ..dir(node);
+ }
}
break;
}
@@ -262,8 +279,46 @@ class InitialState extends InteractionState {
Selection selection = window.getSelection();
TrySelection trySelection = new TrySelection(mainEditorPane, selection);
+ Set<Node> normalizedNodes = new Set<Node>();
for (MutationRecord record in mutations) {
- normalizeMutationRecord(record, trySelection);
+ normalizeMutationRecord(record, trySelection, normalizedNodes);
+ }
+
+ if (normalizedNodes.length == 1) {
+ Node node = normalizedNodes.single;
+ if (node is Element && node.classes.contains('lineNumber')) {
+ print('Single line change: ${node.outerHtml}');
+
+ String currentText = node.text;
+
+ trySelection = new TrySelection(node, selection);
+ trySelection.updateText(currentText);
+
+ editor.isMalformedInput = false;
+ int offset = 0;
+ List<Node> nodes = <Node>[];
+
+ String state = '';
+ Element previousLine = node.previousElementSibling;
+ if (previousLine != null) {
+ state = previousLine.getAttribute('dart-state');
+ }
+ for (String line in splitLines(currentText)) {
+ List<Node> lineNodes = <Node>[];
+ state = tokenizeAndHighlight(
+ line, state, offset, trySelection, lineNodes);
+ offset += line.length;
+ nodes.add(makeLine(lineNodes, state));
+ }
+
+ node.parent.insertAllBefore(nodes, node);
+ node.remove();
+ trySelection.adjust(selection);
+
+ // Discard highlighting mutations.
+ observer.takeRecords();
+ return;
+ }
}
String currentText = mainEditorPane.text;
@@ -278,14 +333,12 @@ class InitialState extends InteractionState {
List<Node> nodes = <Node>[];
String state = '';
- for (String line in currentText.split(new RegExp('^', multiLine: true))) {
+ for (String line in splitLines(currentText)) {
List<Node> lineNodes = <Node>[];
state =
tokenizeAndHighlight(line, state, offset, trySelection, lineNodes);
offset += line.length;
- nodes.add(new SpanElement()
- ..nodes.addAll(lineNodes)
- ..classes.add('lineNumber'));
+ nodes.add(makeLine(lineNodes, state));
}
mainEditorPane
@@ -785,17 +838,60 @@ bool isUnterminatedMultiLineToken(UnterminatedToken token) {
token.start == 'r"""';
}
-void normalizeMutationRecord(MutationRecord record, TrySelection selection) {
- if (record.addedNodes.isEmpty) return;
+void normalizeMutationRecord(MutationRecord record,
+ TrySelection selection,
+ Set<Node> normalizedNodes) {
for (Node node in record.addedNodes) {
if (node.parent == null) continue;
StringBuffer buffer = new StringBuffer();
int selectionOffset = htmlToText(node, buffer, selection);
Text newNode = new Text('$buffer');
node.replaceWith(newNode);
+ normalizedNodes.add(findLine(newNode));
if (selectionOffset != -1) {
selection.anchorNode = newNode;
selection.anchorOffset = selectionOffset;
}
}
+ if (!record.removedNodes.isEmpty) {
+ normalizedNodes.add(findLine(record.target));
+ }
+ if (record.type == "characterData") {
+ normalizedNodes.add(findLine(record.target));
+ }
+}
+
+// Finds the line of [node] (a parent node with CSS class 'lineNumber').
+// If no such parent exists, return mainEditorPane if it is a parent.
+// Otherwise return [node].
+Node findLine(Node node) {
+ for (Node n = node; n != null; n = n.parent) {
+ if (n is Element && n.classes.contains('lineNumber')) return n;
+ if (n == mainEditorPane) return n;
+ }
+ return node;
+}
+
+Element makeLine(List<Node> lineNodes, String state) {
+ // Using a div element here (anything with display=block) generally messes up
+ // editing and navigation. We would like to use a block element here so
+ // error messages show as expected. But no such luck. Fortunately, there
+ // are strong indications that the current solution for displaying errors
+ // isn't good enough anyways.
+ return new SpanElement()
+ ..setAttribute('dart-state', state)
+ ..nodes.addAll(lineNodes)
+ ..classes.add('lineNumber');
+}
+
+bool isAtEndOfFile(Text text, int offset) {
+ Node line = findLine(text);
+ return
+ line.nextNode == null &&
+ text.parent.nextNode == null &&
+ offset == text.length;
+}
+
+List<String> splitLines(String text) {
+ return text.split(new RegExp('^', multiLine: true));
}
« no previous file with comments | « dart/site/try/line_numbers.css ('k') | dart/site/try/src/selection.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698