Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 /** | 5 /** |
| 6 * @fileoverview Classes related to cursors that point to and select parts of | 6 * @fileoverview Classes related to cursors that point to and select parts of |
| 7 * the automation tree. | 7 * the automation tree. |
| 8 */ | 8 */ |
| 9 | 9 |
| 10 goog.provide('cursors.Cursor'); | 10 goog.provide('cursors.Cursor'); |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 77 cursors.Cursor = function(node, index) { | 77 cursors.Cursor = function(node, index) { |
| 78 // Compensate for specific issues in Blink. | 78 // Compensate for specific issues in Blink. |
| 79 // TODO(dtseng): Pass through affinity; if upstream, skip below. | 79 // TODO(dtseng): Pass through affinity; if upstream, skip below. |
| 80 if (node.role == RoleType.STATIC_TEXT && node.name.length == index) { | 80 if (node.role == RoleType.STATIC_TEXT && node.name.length == index) { |
| 81 // Re-interpret this case as the beginning of the next node. | 81 // Re-interpret this case as the beginning of the next node. |
| 82 var nextNode = AutomationUtil.findNextNode( | 82 var nextNode = AutomationUtil.findNextNode( |
| 83 node, Dir.FORWARD, AutomationPredicate.leafOrStaticText); | 83 node, Dir.FORWARD, AutomationPredicate.leafOrStaticText); |
| 84 | 84 |
| 85 // The exception is when a user types at the end of a line. In that case, | 85 // The exception is when a user types at the end of a line. In that case, |
| 86 // staying on the current node is appropriate. | 86 // staying on the current node is appropriate. |
| 87 if (node && node.nextOnLine && nextNode) { | 87 if (node && node.nextOnLine && node.nextOnLine.role && nextNode) { |
| 88 node = nextNode; | 88 node = nextNode; |
| 89 index = 0; | 89 index = 0; |
| 90 } | 90 } |
| 91 } else if ( | 91 } else if ( |
| 92 node.role == RoleType.GENERIC_CONTAINER && node.state.richlyEditable && | 92 node.role == RoleType.GENERIC_CONTAINER && node.state.richlyEditable && |
| 93 (node.firstChild && | 93 (node.firstChild && |
| 94 (node.firstChild.role == RoleType.LINE_BREAK || | 94 (node.firstChild.role == RoleType.LINE_BREAK || |
| 95 node.firstChild.role == RoleType.STATIC_TEXT))) { | 95 node.firstChild.role == RoleType.STATIC_TEXT))) { |
| 96 // Re-interpret this case as pointing to the text under the div. | 96 // Re-interpret this case as pointing to the text under the div. |
| 97 node = node.find({role: RoleType.INLINE_TEXT_BOX}) || node; | 97 node = node.find({role: RoleType.INLINE_TEXT_BOX}) || node; |
| 98 } | 98 } |
| 99 | 99 |
| 100 /** @type {number} @private */ | 100 /** @type {number} @private */ |
| 101 this.index_ = index; | 101 this.index_ = index; |
| 102 /** @type {Array<AutomationNode>} @private */ | 102 /** @type {Array<AutomationNode>} @private */ |
| 103 this.ancestry_ = []; | 103 this.ancestry_ = []; |
| 104 /** @type {!Array<number>} @private */ | |
| 105 this.recoveryChildIndex_ = []; | |
| 106 | |
| 104 var nodeWalker = node; | 107 var nodeWalker = node; |
| 105 while (nodeWalker) { | 108 while (nodeWalker) { |
| 106 this.ancestry_.push(nodeWalker); | 109 this.ancestry_.push(nodeWalker); |
| 110 this.recoveryChildIndex_.push(nodeWalker.indexInParent); | |
|
dmazzoni
2017/07/06 21:17:06
I like this idea in general but how about a tiny b
David Tseng
2017/07/06 22:15:44
I'm actually something slightly different here tha
| |
| 107 nodeWalker = nodeWalker.parent; | 111 nodeWalker = nodeWalker.parent; |
| 108 if (nodeWalker && nodeWalker.role == RoleType.WINDOW) | 112 if (nodeWalker && nodeWalker.role == RoleType.WINDOW) |
| 109 break; | 113 break; |
| 110 } | 114 } |
| 111 }; | 115 }; |
| 112 | 116 |
| 113 /** | 117 /** |
| 114 * Convenience method to construct a Cursor from a node. | 118 * Convenience method to construct a Cursor from a node. |
| 115 * @param {!AutomationNode} node | 119 * @param {!AutomationNode} node |
| 116 * @return {!cursors.Cursor} | 120 * @return {!cursors.Cursor} |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 183 firstValidNode.root != undefined) { | 187 firstValidNode.root != undefined) { |
| 184 return firstValidNode; | 188 return firstValidNode; |
| 185 } | 189 } |
| 186 // If we have to walk up to an ancestor, reset the index to NODE_INDEX. | 190 // If we have to walk up to an ancestor, reset the index to NODE_INDEX. |
| 187 this.index_ = cursors.NODE_INDEX; | 191 this.index_ = cursors.NODE_INDEX; |
| 188 } | 192 } |
| 189 return null; | 193 return null; |
| 190 }, | 194 }, |
| 191 | 195 |
| 192 /** | 196 /** |
| 197 * Returns the node. If the node is invalid since the last time it | |
| 198 * was accessed, attempts to recover it based on a child index. | |
| 199 * @return {AutomationNode} | |
| 200 */ | |
| 201 get recoveryNode() { | |
| 202 for (var i = 0; i < this.ancestry_.length; i++) { | |
| 203 var firstValidNode = this.ancestry_[i]; | |
| 204 if (firstValidNode != null && firstValidNode.role !== undefined && | |
| 205 firstValidNode.root != undefined) { | |
| 206 if (i == 0) | |
| 207 return firstValidNode; | |
| 208 | |
| 209 // Otherwise, attempt to recover. | |
| 210 var node = firstValidNode; | |
| 211 for (var j = i - 1; j >= 0; j--) { | |
| 212 var index = this.recoveryChildIndex_[j]; | |
| 213 var children = node.children; | |
| 214 if (!children[index]) | |
| 215 return node; | |
| 216 node = children[index]; | |
| 217 } | |
| 218 return node; | |
| 219 } | |
| 220 } | |
| 221 return null; | |
| 222 }, | |
| 223 | |
| 224 /** | |
| 193 * @return {number} | 225 * @return {number} |
| 194 */ | 226 */ |
| 195 get index() { | 227 get index() { |
| 196 return this.index_; | 228 return this.index_; |
| 197 }, | 229 }, |
| 198 | 230 |
| 199 | 231 |
| 200 /** | 232 /** |
| 201 * A node appropriate for making selections. | 233 * A node appropriate for making selections. |
| 202 * @return {AutomationNode} | 234 * @return {AutomationNode} |
| (...skipping 564 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 767 /** | 799 /** |
| 768 * Returns whether this range has valid start and end cursors. | 800 * Returns whether this range has valid start and end cursors. |
| 769 * @return {boolean} | 801 * @return {boolean} |
| 770 */ | 802 */ |
| 771 isValid: function() { | 803 isValid: function() { |
| 772 return this.start.isValid() && this.end.isValid(); | 804 return this.start.isValid() && this.end.isValid(); |
| 773 } | 805 } |
| 774 }; | 806 }; |
| 775 | 807 |
| 776 }); // goog.scope | 808 }); // goog.scope |
| OLD | NEW |