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 |