OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library trydart.interaction_manager; | 5 library trydart.interaction_manager; |
6 | 6 |
7 import 'dart:html'; | 7 import 'dart:html'; |
8 | 8 |
9 import 'dart:convert' show | 9 import 'dart:convert' show |
10 JSON; | 10 JSON; |
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
209 // editor.scheduleRemoveCodeCompletion(); | 209 // editor.scheduleRemoveCodeCompletion(); |
210 | 210 |
211 // This is a hack to get Safari (iOS) to send mutation events on | 211 // This is a hack to get Safari (iOS) to send mutation events on |
212 // contenteditable. | 212 // contenteditable. |
213 // TODO(ahe): Move to onInput? | 213 // TODO(ahe): Move to onInput? |
214 var newDiv = new DivElement(); | 214 var newDiv = new DivElement(); |
215 hackDiv.replaceWith(newDiv); | 215 hackDiv.replaceWith(newDiv); |
216 hackDiv = newDiv; | 216 hackDiv = newDiv; |
217 } | 217 } |
218 | 218 |
219 // TODO(ahe): This method should be cleaned up. It is too large. | |
220 void onMutation(List<MutationRecord> mutations, MutationObserver observer) { | 219 void onMutation(List<MutationRecord> mutations, MutationObserver observer) { |
221 print('onMutation'); | 220 print('onMutation'); |
222 | 221 |
223 List<Node> highlighting = mainEditorPane.querySelectorAll( | 222 List<Node> highlighting = mainEditorPane.querySelectorAll( |
224 'a.diagnostic>span, .dart-code-completion, .hazed-suggestion'); | 223 'a.diagnostic>span, .dart-code-completion, .hazed-suggestion'); |
225 for (Element element in highlighting) { | 224 for (Element element in highlighting) { |
226 element.remove(); | 225 element.remove(); |
227 } | 226 } |
228 | 227 |
229 Selection selection = window.getSelection(); | 228 Selection selection = window.getSelection(); |
230 Node anchorNode = selection.anchorNode; | 229 TrySelection trySelection = new TrySelection(mainEditorPane, selection); |
231 int anchorOffset = selection.isCollapsed ? selection.anchorOffset : -1; | |
232 | 230 |
233 for (MutationRecord record in mutations) { | 231 for (MutationRecord record in mutations) { |
234 if (record.addedNodes.isEmpty) continue; | 232 normalizeMutationRecord(record, trySelection); |
235 for (Node node in record.addedNodes) { | |
236 if (node.parent == null) continue; | |
237 StringBuffer buffer = new StringBuffer(); | |
238 int selectionOffset = htmlToText(node, buffer, selection); | |
239 Text newNode = new Text('$buffer'); | |
240 node.replaceWith(newNode); | |
241 if (selectionOffset != -1) { | |
242 anchorNode = newNode; | |
243 anchorOffset = selectionOffset; | |
244 } | |
245 } | |
246 } | 233 } |
247 | 234 |
248 String currentText = mainEditorPane.text; | 235 String currentText = mainEditorPane.text; |
249 TrySelection trySelection = | 236 trySelection.updateText(currentText); |
250 new TrySelection(mainEditorPane, selection, currentText); | |
251 | 237 |
252 context.currentCompilationUnit.content = currentText; | 238 context.currentCompilationUnit.content = currentText; |
253 | 239 |
254 editor.seenIdentifiers = new Set<String>.from(mock.identifiers); | 240 editor.seenIdentifiers = new Set<String>.from(mock.identifiers); |
255 | 241 |
256 editor.isMalformedInput = false; | 242 editor.isMalformedInput = false; |
257 int offset = 0; | 243 int offset = 0; |
258 List<Node> nodes = <Node>[]; | 244 List<Node> nodes = <Node>[]; |
259 // + offset + charOffset + globalOffset + (charOffset + charCount) | |
260 // v v v v | |
261 // do identifier_abcdefghijklmnopqrst | |
262 for (Token token = tokenize(currentText); | |
263 token.kind != EOF_TOKEN; | |
264 token = token.next) { | |
265 int charOffset = token.charOffset; | |
266 int charCount = token.charCount; | |
267 | 245 |
268 if (charOffset < offset) continue; // Happens for scanner errors. | 246 tokenizeAndHighlight(currentText, offset, trySelection, nodes); |
269 | |
270 Decoration decoration = editor.getDecoration(token); | |
271 if (decoration == null) continue; | |
272 | |
273 // Add a node for text before current token. | |
274 trySelection.addNodeFromSubstring(offset, charOffset, nodes); | |
275 | |
276 // Add a node for current token. | |
277 trySelection.addNodeFromSubstring( | |
278 charOffset, charOffset + charCount, nodes, decoration); | |
279 | |
280 offset = charOffset + charCount; | |
281 } | |
282 | |
283 // Add a node for anything after the last (decorated) token. | |
284 trySelection.addNodeFromSubstring(offset, currentText.length, nodes); | |
285 | |
286 // Ensure text always ends with a newline. | |
287 if (!currentText.endsWith('\n')) { | |
288 nodes.add(new Text('\n')); | |
289 } | |
290 | 247 |
291 mainEditorPane | 248 mainEditorPane |
292 ..nodes.clear() | 249 ..nodes.clear() |
293 ..nodes.addAll(nodes); | 250 ..nodes.addAll(nodes); |
294 trySelection.adjust(selection); | 251 trySelection.adjust(selection); |
295 | 252 |
296 // Discard highlighting mutations. | 253 // Discard highlighting mutations. |
297 observer.takeRecords(); | 254 observer.takeRecords(); |
298 } | 255 } |
299 | 256 |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
385 void onProjectFileFsEvent(MessageEvent e) { | 342 void onProjectFileFsEvent(MessageEvent e) { |
386 Map map = JSON.decode(e.data); | 343 Map map = JSON.decode(e.data); |
387 List modified = map['modify']; | 344 List modified = map['modify']; |
388 if (modified == null) return; | 345 if (modified == null) return; |
389 for (String name in modified) { | 346 for (String name in modified) { |
390 if (context.lastSaved != null && context.lastSaved.name == name) { | 347 if (context.lastSaved != null && context.lastSaved.name == name) { |
391 context.lastSaved = null; | 348 context.lastSaved = null; |
392 continue; | 349 continue; |
393 } | 350 } |
394 if (context.currentCompilationUnit.name == name) { | 351 if (context.currentCompilationUnit.name == name) { |
395 mainEditorPane.contentEditable = false; | 352 mainEditorPane.contentEditable = 'false'; |
396 statusDiv.text = 'Modified on disk'; | 353 statusDiv.text = 'Modified on disk'; |
397 } | 354 } |
398 } | 355 } |
399 } | 356 } |
400 } | 357 } |
401 | 358 |
402 Future<String> getString(uri) { | 359 Future<String> getString(uri) { |
403 return new Future<String>.sync(() => HttpRequest.getString('$uri')); | 360 return new Future<String>.sync(() => HttpRequest.getString('$uri')); |
404 } | 361 } |
405 | 362 |
(...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
704 event.getModifierState("Fn") || | 661 event.getModifierState("Fn") || |
705 event.getModifierState("Meta") || | 662 event.getModifierState("Meta") || |
706 event.getModifierState("NumLock") || | 663 event.getModifierState("NumLock") || |
707 event.getModifierState("ScrollLock") || | 664 event.getModifierState("ScrollLock") || |
708 event.getModifierState("Scroll") || | 665 event.getModifierState("Scroll") || |
709 event.getModifierState("Win") || | 666 event.getModifierState("Win") || |
710 event.getModifierState("Shift") || | 667 event.getModifierState("Shift") || |
711 event.getModifierState("SymbolLock") || | 668 event.getModifierState("SymbolLock") || |
712 event.getModifierState("OS"); | 669 event.getModifierState("OS"); |
713 } | 670 } |
| 671 |
| 672 void tokenizeAndHighlight(String currentText, |
| 673 int offset, |
| 674 TrySelection trySelection, |
| 675 List<Node> nodes) { |
| 676 // + offset + charOffset + globalOffset + (charOffset + charCount) |
| 677 // v v v v |
| 678 // do identifier_abcdefghijklmnopqrst |
| 679 for (Token token = tokenize(currentText); |
| 680 token.kind != EOF_TOKEN; |
| 681 token = token.next) { |
| 682 int charOffset = token.charOffset; |
| 683 int charCount = token.charCount; |
| 684 |
| 685 if (charOffset < offset) continue; // Happens for scanner errors. |
| 686 |
| 687 Decoration decoration = editor.getDecoration(token); |
| 688 if (decoration == null) continue; |
| 689 |
| 690 // Add a node for text before current token. |
| 691 trySelection.addNodeFromSubstring(offset, charOffset, nodes); |
| 692 |
| 693 // Add a node for current token. |
| 694 trySelection.addNodeFromSubstring( |
| 695 charOffset, charOffset + charCount, nodes, decoration); |
| 696 |
| 697 offset = charOffset + charCount; |
| 698 } |
| 699 |
| 700 // Add a node for anything after the last (decorated) token. |
| 701 trySelection.addNodeFromSubstring(offset, currentText.length, nodes); |
| 702 |
| 703 // Ensure text always ends with a newline. |
| 704 if (!currentText.endsWith('\n')) { |
| 705 nodes.add(new Text('\n')); |
| 706 } |
| 707 } |
| 708 |
| 709 void normalizeMutationRecord(MutationRecord record, TrySelection selection) { |
| 710 if (record.addedNodes.isEmpty) return; |
| 711 for (Node node in record.addedNodes) { |
| 712 if (node.parent == null) continue; |
| 713 StringBuffer buffer = new StringBuffer(); |
| 714 int selectionOffset = htmlToText(node, buffer, selection); |
| 715 Text newNode = new Text('$buffer'); |
| 716 node.replaceWith(newNode); |
| 717 if (selectionOffset != -1) { |
| 718 selection.anchorNode = newNode; |
| 719 selection.anchorOffset = selectionOffset; |
| 720 } |
| 721 } |
| 722 } |
OLD | NEW |