| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 library trydart.selection; | |
| 6 | |
| 7 import 'dart:html' show | |
| 8 CharacterData, | |
| 9 Element, | |
| 10 Node, | |
| 11 NodeFilter, | |
| 12 Selection, | |
| 13 Text, | |
| 14 TreeWalker; | |
| 15 | |
| 16 import 'shadow_root.dart' show | |
| 17 WALKER_NEXT, | |
| 18 WALKER_RETURN, | |
| 19 walkNodes; | |
| 20 | |
| 21 import 'decoration.dart'; | |
| 22 | |
| 23 class TrySelection { | |
| 24 final Node root; | |
| 25 Node anchorNode; | |
| 26 int anchorOffset; | |
| 27 | |
| 28 String text; | |
| 29 int globalOffset = -1; | |
| 30 | |
| 31 TrySelection(this.root, Selection selection) | |
| 32 : anchorNode = isCollapsed(selection) ? selection.anchorNode : null, | |
| 33 anchorOffset = isCollapsed(selection) ? selection.anchorOffset : -1; | |
| 34 | |
| 35 TrySelection.empty(this.root) | |
| 36 : anchorNode = null, | |
| 37 anchorOffset = -1; | |
| 38 | |
| 39 Text addNodeFromSubstring(int start, | |
| 40 int end, | |
| 41 List<Node> nodes, | |
| 42 [Decoration decoration]) { | |
| 43 if (start == end) return null; | |
| 44 | |
| 45 Text textNode = new Text(text.substring(start, end)); | |
| 46 | |
| 47 if (start <= globalOffset && globalOffset <= end) { | |
| 48 anchorNode = textNode; | |
| 49 anchorOffset = globalOffset - start; | |
| 50 } | |
| 51 | |
| 52 nodes.add(decoration == null ? textNode : decoration.applyTo(textNode)); | |
| 53 | |
| 54 return textNode; | |
| 55 } | |
| 56 | |
| 57 void adjust(Selection selection) { | |
| 58 if (anchorOffset >= 0) { | |
| 59 selection.collapse(anchorNode, anchorOffset); | |
| 60 } | |
| 61 } | |
| 62 | |
| 63 void updateText(String newText) { | |
| 64 text = newText; | |
| 65 globalOffset = computeGlobalOffset(root, anchorNode, anchorOffset); | |
| 66 } | |
| 67 | |
| 68 TrySelection copyWithRoot(Node root) { | |
| 69 return new TrySelection.empty(root) | |
| 70 ..anchorNode = anchorNode | |
| 71 ..anchorOffset = anchorOffset; | |
| 72 } | |
| 73 | |
| 74 /// Computes the global offset, that is, the offset from [root]. | |
| 75 static int computeGlobalOffset(Node root, Node anchorNode, int anchorOffset) { | |
| 76 if (anchorOffset == -1) return -1; | |
| 77 | |
| 78 int offset = 0; | |
| 79 bool found = false; | |
| 80 walkNodes(root, (Node node) { | |
| 81 if (anchorNode == node) { | |
| 82 offset += anchorOffset; | |
| 83 found = true; | |
| 84 return WALKER_RETURN; | |
| 85 } | |
| 86 switch (node.nodeType) { | |
| 87 case Node.CDATA_SECTION_NODE: | |
| 88 case Node.TEXT_NODE: | |
| 89 CharacterData text = node; | |
| 90 offset += text.data.length; | |
| 91 break; | |
| 92 } | |
| 93 return WALKER_NEXT; | |
| 94 }); | |
| 95 return found ? offset : -1; | |
| 96 } | |
| 97 } | |
| 98 | |
| 99 bool isCollapsed(Selection selection) { | |
| 100 // Firefox and Chrome don't agree on if the selection is collapsed if there | |
| 101 // is no node selected. | |
| 102 return selection.isCollapsed && selection.anchorNode != null; | |
| 103 } | |
| OLD | NEW |