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

Side by Side Diff: dart/site/try/src/interaction_manager.dart

Issue 261413002: Use ShadowRoot to hide non-user content (for example, diagnostics). (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge
Patch Set: Address Kasper's comments. 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « dart/site/try/src/html_to_text.dart ('k') | dart/site/try/src/shadow_root.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
57 import 'selection.dart' show 57 import 'selection.dart' show
58 TrySelection, 58 TrySelection,
59 isCollapsed; 59 isCollapsed;
60 60
61 import 'editor.dart' as editor; 61 import 'editor.dart' as editor;
62 62
63 import 'mock.dart' as mock; 63 import 'mock.dart' as mock;
64 64
65 import 'settings.dart' as settings; 65 import 'settings.dart' as settings;
66 66
67 import 'shadow_root.dart' show
68 getShadowRoot,
69 removeShadowRootPolyfill,
70 setShadowRoot;
71
67 const String TRY_DART_NEW_DEFECT = 72 const String TRY_DART_NEW_DEFECT =
68 'https://code.google.com/p/dart/issues/entry' 73 'https://code.google.com/p/dart/issues/entry'
69 '?template=Try+Dart+Internal+Error'; 74 '?template=Try+Dart+Internal+Error';
70 75
71 /** 76 /**
72 * UI interaction manager for the entire application. 77 * UI interaction manager for the entire application.
73 */ 78 */
74 abstract class InteractionManager { 79 abstract class InteractionManager {
75 // Design note: All UI interactions go through one instance of this 80 // Design note: All UI interactions go through one instance of this
76 // class. This is by design. 81 // class. This is by design.
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
250 } else { 255 } else {
251 window.console 256 window.console
252 ..error('Unexpected node') 257 ..error('Unexpected node')
253 ..dir(node); 258 ..dir(node);
254 } 259 }
255 } 260 }
256 break; 261 break;
257 } 262 }
258 } 263 }
259 264
260 // editor.scheduleRemoveCodeCompletion();
261
262 // This is a hack to get Safari (iOS) to send mutation events on 265 // This is a hack to get Safari (iOS) to send mutation events on
263 // contenteditable. 266 // contenteditable.
264 // TODO(ahe): Move to onInput? 267 // TODO(ahe): Move to onInput?
265 var newDiv = new DivElement(); 268 var newDiv = new DivElement();
266 hackDiv.replaceWith(newDiv); 269 hackDiv.replaceWith(newDiv);
267 hackDiv = newDiv; 270 hackDiv = newDiv;
268 } 271 }
269 272
270 void onMutation(List<MutationRecord> mutations, MutationObserver observer) { 273 void onMutation(List<MutationRecord> mutations, MutationObserver observer) {
271 print('onMutation'); 274 print('onMutation');
272 275
273 List<Node> highlighting = mainEditorPane.querySelectorAll( 276 removeCodeCompletion();
274 'a.diagnostic>span, .dart-code-completion, .hazed-suggestion');
275 for (Element element in highlighting) {
276 element.remove();
277 }
278 277
279 Selection selection = window.getSelection(); 278 Selection selection = window.getSelection();
280 TrySelection trySelection = new TrySelection(mainEditorPane, selection); 279 TrySelection trySelection = new TrySelection(mainEditorPane, selection);
281 280
282 Set<Node> normalizedNodes = new Set<Node>(); 281 Set<Node> normalizedNodes = new Set<Node>();
283 for (MutationRecord record in mutations) { 282 for (MutationRecord record in mutations) {
284 normalizeMutationRecord(record, trySelection, normalizedNodes); 283 normalizeMutationRecord(record, trySelection, normalizedNodes);
285 } 284 }
286 285
287 if (normalizedNodes.length == 1) { 286 if (normalizedNodes.length == 1) {
288 Node node = normalizedNodes.single; 287 Node node = normalizedNodes.single;
289 if (node is Element && node.classes.contains('lineNumber')) { 288 if (node is Element && node.classes.contains('lineNumber')) {
290 print('Single line change: ${node.outerHtml}'); 289 print('Single line change: ${node.outerHtml}');
291 290
291 removeShadowRootPolyfill(node);
292
292 String currentText = node.text; 293 String currentText = node.text;
293 294
294 trySelection = new TrySelection(node, selection); 295 trySelection = new TrySelection(node, selection);
295 trySelection.updateText(currentText); 296 trySelection.updateText(currentText);
296 297
297 editor.isMalformedInput = false; 298 editor.isMalformedInput = false;
298 int offset = 0; 299 int offset = 0;
299 List<Node> nodes = <Node>[]; 300 List<Node> nodes = <Node>[];
300 301
301 String state = ''; 302 String state = '';
(...skipping 12 matching lines...) Expand all
314 node.parent.insertAllBefore(nodes, node); 315 node.parent.insertAllBefore(nodes, node);
315 node.remove(); 316 node.remove();
316 trySelection.adjust(selection); 317 trySelection.adjust(selection);
317 318
318 // Discard highlighting mutations. 319 // Discard highlighting mutations.
319 observer.takeRecords(); 320 observer.takeRecords();
320 return; 321 return;
321 } 322 }
322 } 323 }
323 324
325 removeShadowRootPolyfill(mainEditorPane);
326
324 String currentText = mainEditorPane.text; 327 String currentText = mainEditorPane.text;
325 trySelection.updateText(currentText); 328 trySelection.updateText(currentText);
326 329
327 context.currentCompilationUnit.content = currentText; 330 context.currentCompilationUnit.content = currentText;
328 331
329 editor.seenIdentifiers = new Set<String>.from(mock.identifiers); 332 editor.seenIdentifiers = new Set<String>.from(mock.identifiers);
330 333
331 editor.isMalformedInput = false; 334 editor.isMalformedInput = false;
332 int offset = 0; 335 int offset = 0;
333 List<Node> nodes = <Node>[]; 336 List<Node> nodes = <Node>[];
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
528 event.preventDefault(); 531 event.preventDefault();
529 move(1); 532 move(1);
530 } 533 }
531 534
532 void moveUp(Event event) { 535 void moveUp(Event event) {
533 event.preventDefault(); 536 event.preventDefault();
534 move(-1); 537 move(-1);
535 } 538 }
536 539
537 void move(int direction) { 540 void move(int direction) {
538 Element element = editor.moveActive(direction); 541 Element element = editor.moveActive(direction, ui);
539 if (element == null) return; 542 if (element == null) return;
540 var text = activeCompletion.firstChild; 543 var text = activeCompletion.firstChild;
541 String prefix = ""; 544 String prefix = "";
542 if (text is Text) prefix = text.data.trim(); 545 if (text is Text) prefix = text.data.trim();
543 updateInlineSuggestion(prefix, element.text); 546 updateInlineSuggestion(prefix, element.text);
544 } 547 }
545 548
546 void endCompletion({bool acceptSuggestion: false}) { 549 void endCompletion({bool acceptSuggestion: false}) {
547 if (acceptSuggestion) { 550 if (acceptSuggestion) {
548 suggestionAccepted(); 551 suggestionAccepted();
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
594 597
595 int anchorOffset = selection.anchorOffset; 598 int anchorOffset = selection.anchorOffset;
596 599
597 String prefix = text.data.substring(0, anchorOffset).trim(); 600 String prefix = text.data.substring(0, anchorOffset).trim();
598 if (prefix.isEmpty) { 601 if (prefix.isEmpty) {
599 return endCompletion(); 602 return endCompletion();
600 } 603 }
601 604
602 num height = activeCompletion.getBoundingClientRect().height; 605 num height = activeCompletion.getBoundingClientRect().height;
603 activeCompletion.classes.add('active'); 606 activeCompletion.classes.add('active');
604 ui.nodes.clear(); 607 Node root = getShadowRoot(ui);
605 608
606 inline = new SpanElement() 609 inline = new SpanElement()
607 ..classes.add('hazed-suggestion'); 610 ..classes.add('hazed-suggestion');
608 Text rest = text.splitText(anchorOffset); 611 Text rest = text.splitText(anchorOffset);
609 text.parentNode.insertBefore(inline, text.nextNode); 612 text.parentNode.insertBefore(inline, text.nextNode);
610 activeCompletion.parentNode.insertBefore( 613 activeCompletion.parentNode.insertBefore(
611 rest, activeCompletion.nextNode); 614 rest, activeCompletion.nextNode);
612 615
613 staticResults = new DivElement() 616 staticResults = new DivElement()
614 ..classes.addAll(['dart-static', 'dart-limited-height']); 617 ..classes.addAll(['dart-static', 'dart-limited-height']);
615 serverResults = new DivElement() 618 serverResults = new DivElement()
616 ..style.display = 'none' 619 ..style.display = 'none'
617 ..classes.add('dart-server'); 620 ..classes.add('dart-server');
618 ui.nodes.addAll([staticResults, serverResults]); 621 root.nodes.addAll([staticResults, serverResults]);
619 ui.style.top = '${height}px'; 622 ui.style.top = '${height}px';
620 623
621 staticResults.nodes.add(buildCompletionEntry(prefix)); 624 staticResults.nodes.add(buildCompletionEntry(prefix));
622 625
623 updateSuggestions(prefix); 626 updateSuggestions(prefix);
624 } 627 }
625 628
626 void updateInlineSuggestion(String prefix, String suggestion) { 629 void updateInlineSuggestion(String prefix, String suggestion) {
627 inlineSuggestion = suggestion; 630 inlineSuggestion = suggestion;
628 631
629 minWidth = max(minWidth, activeCompletion.getBoundingClientRect().width); 632 minWidth = max(minWidth, activeCompletion.getBoundingClientRect().width);
630 633
631 activeCompletion.style 634 activeCompletion.style
632 ..display = 'inline-block' 635 ..display = 'inline-block'
633 ..minWidth = '${minWidth}px'; 636 ..minWidth = '${minWidth}px';
634 637
635 inline 638 setShadowRoot(inline, suggestion.substring(prefix.length));
636 ..nodes.clear() 639 inline.style.display = '';
637 ..appendText(suggestion.substring(prefix.length))
638 ..style.display = '';
639 640
640 observer.takeRecords(); // Discard mutations. 641 observer.takeRecords(); // Discard mutations.
641 } 642 }
642 643
643 void updateSuggestions(String prefix) { 644 void updateSuggestions(String prefix) {
644 if (prefix.isEmpty) { 645 if (prefix.isEmpty) {
645 return endCompletion(); 646 return endCompletion();
646 } 647 }
647 648
648 Token first = tokenize(prefix); 649 Token first = tokenize(prefix);
(...skipping 10 matching lines...) Expand all
659 num height = ui.getBoundingClientRect().height - borderHeight; 660 num height = ui.getBoundingClientRect().height - borderHeight;
660 ui.style.minHeight = '${height}px'; 661 ui.style.minHeight = '${height}px';
661 662
662 minWidth = 663 minWidth =
663 max(minWidth, activeCompletion.getBoundingClientRect().width); 664 max(minWidth, activeCompletion.getBoundingClientRect().width);
664 665
665 staticResults.nodes.clear(); 666 staticResults.nodes.clear();
666 serverResults.nodes.clear(); 667 serverResults.nodes.clear();
667 668
668 if (inlineSuggestion != null && inlineSuggestion.startsWith(prefix)) { 669 if (inlineSuggestion != null && inlineSuggestion.startsWith(prefix)) {
669 inline 670 setShadowRoot(inline, inlineSuggestion.substring(prefix.length));
670 ..nodes.clear()
671 ..appendText(inlineSuggestion.substring(prefix.length));
672 } 671 }
673 672
674 List<String> results = editor.seenIdentifiers.where( 673 List<String> results = editor.seenIdentifiers.where(
675 (String identifier) { 674 (String identifier) {
676 return identifier != prefix && identifier.startsWith(prefix); 675 return identifier != prefix && identifier.startsWith(prefix);
677 }).toList(growable: false); 676 }).toList(growable: false);
678 results.sort(); 677 results.sort();
679 if (results.isEmpty) results = <String>[prefix]; 678 if (results.isEmpty) results = <String>[prefix];
680 679
681 results.forEach((String completion) { 680 results.forEach((String completion) {
682 staticResults.nodes.add(buildCompletionEntry(completion)); 681 staticResults.nodes.add(buildCompletionEntry(completion));
683 }); 682 });
684 683
685 if (settings.enableDartMind) { 684 if (settings.enableDartMind) {
686 // TODO(ahe): Move this code to its own function or class. 685 // TODO(ahe): Move this code to its own function or class.
687 String encodedArg0 = Uri.encodeComponent('"$prefix"'); 686 String encodedArg0 = Uri.encodeComponent('"$prefix"');
688 String mindQuery = 687 String mindQuery =
689 'http://dart-mind.appspot.com/rpc' 688 'http://dart-mind.appspot.com/rpc'
690 '?action=GetExportingPubCompletions' 689 '?action=GetExportingPubCompletions'
691 '&arg0=$encodedArg0'; 690 '&arg0=$encodedArg0';
692 try { 691 try {
693 var serverWatch = new Stopwatch()..start(); 692 var serverWatch = new Stopwatch()..start();
694 HttpRequest.getString(mindQuery).then((String responseText) { 693 HttpRequest.getString(mindQuery).then((String responseText) {
695 serverWatch.stop(); 694 serverWatch.stop();
696 List<String> serverSuggestions = JSON.decode(responseText); 695 List<String> serverSuggestions = JSON.decode(responseText);
697 if (!serverSuggestions.isEmpty) { 696 if (!serverSuggestions.isEmpty) {
698 updateInlineSuggestion(prefix, serverSuggestions.first); 697 updateInlineSuggestion(prefix, serverSuggestions.first);
699 } 698 }
699 var root = getShadowRoot(ui);
700 for (int i = 1; i < serverSuggestions.length; i++) { 700 for (int i = 1; i < serverSuggestions.length; i++) {
701 String completion = serverSuggestions[i]; 701 String completion = serverSuggestions[i];
702 DivElement where = staticResults; 702 DivElement where = staticResults;
703 int index = results.indexOf(completion); 703 int index = results.indexOf(completion);
704 if (index != -1) { 704 if (index != -1) {
705 List<Element> entries = 705 List<Element> entries = root.querySelectorAll(
706 document.querySelectorAll('.dart-static>.dart-entry'); 706 '.dart-static>.dart-entry');
707 entries[index].classes.add('doubleplusgood'); 707 entries[index].classes.add('doubleplusgood');
708 } else { 708 } else {
709 if (results.length > 3) { 709 if (results.length > 3) {
710 serverResults.style.display = 'block'; 710 serverResults.style.display = 'block';
711 where = serverResults; 711 where = serverResults;
712 } 712 }
713 Element entry = buildCompletionEntry(completion); 713 Element entry = buildCompletionEntry(completion);
714 entry.classes.add('doubleplusgood'); 714 entry.classes.add('doubleplusgood');
715 where.nodes.add(entry); 715 where.nodes.add(entry);
716 } 716 }
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after
883 Node line = findLine(text); 883 Node line = findLine(text);
884 return 884 return
885 line.nextNode == null && 885 line.nextNode == null &&
886 text.parent.nextNode == null && 886 text.parent.nextNode == null &&
887 offset == text.length; 887 offset == text.length;
888 } 888 }
889 889
890 List<String> splitLines(String text) { 890 List<String> splitLines(String text) {
891 return text.split(new RegExp('^', multiLine: true)); 891 return text.split(new RegExp('^', multiLine: true));
892 } 892 }
893
894 void removeCodeCompletion() {
895 List<Node> highlighting =
896 mainEditorPane.querySelectorAll('.dart-code-completion');
897 for (Element element in highlighting) {
898 element.remove();
899 }
900 }
OLDNEW
« no previous file with comments | « dart/site/try/src/html_to_text.dart ('k') | dart/site/try/src/shadow_root.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698