| 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 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 127 while (rNode && (rNode.role == RoleType.INLINE_TEXT_BOX || | 127 while (rNode && (rNode.role == RoleType.INLINE_TEXT_BOX || |
| 128 rNode.role == RoleType.STATIC_TEXT)) | 128 rNode.role == RoleType.STATIC_TEXT)) |
| 129 rNode = rNode.parent; | 129 rNode = rNode.parent; |
| 130 | 130 |
| 131 // Ignore indicies for now. | 131 // Ignore indicies for now. |
| 132 | 132 |
| 133 return lNode === rNode && lNode != undefined; | 133 return lNode === rNode && lNode != undefined; |
| 134 }, | 134 }, |
| 135 | 135 |
| 136 /** | 136 /** |
| 137 * Compares this cursor with |rhs|. |
| 138 * @param {cursors.Cursor} rhs |
| 139 * @return Dir.BACKWARD if |rhs| comes before this cursor in |
| 140 * document order. Forward otherwise. |
| 141 */ |
| 142 compare: function(rhs) { |
| 143 if (!this.node || !rhs.node) |
| 144 return Dir.FORWARD; |
| 145 |
| 146 if (rhs.node == this.node) |
| 147 return rhs.index < this.index ? Dir.BACKWARD : Dir.FORWARD; |
| 148 return AutomationUtil.getDirection(this.node, rhs.node); |
| 149 }, |
| 150 |
| 151 /** |
| 137 * Returns the node. If the node is invalid since the last time it | 152 * Returns the node. If the node is invalid since the last time it |
| 138 * was accessed, moves the cursor to the nearest valid ancestor first. | 153 * was accessed, moves the cursor to the nearest valid ancestor first. |
| 139 * @return {AutomationNode} | 154 * @return {AutomationNode} |
| 140 */ | 155 */ |
| 141 get node() { | 156 get node() { |
| 142 for (var i = 0; i < this.ancestry_.length; i++) { | 157 for (var i = 0; i < this.ancestry_.length; i++) { |
| 143 var firstValidNode = this.ancestry_[i]; | 158 var firstValidNode = this.ancestry_[i]; |
| 144 if (firstValidNode != null && firstValidNode.role !== undefined && | 159 if (firstValidNode != null && firstValidNode.role !== undefined && |
| 145 firstValidNode.root != undefined) { | 160 firstValidNode.root != undefined) { |
| 146 return firstValidNode; | 161 return firstValidNode; |
| (...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 357 case Movement.DIRECTIONAL: | 372 case Movement.DIRECTIONAL: |
| 358 var pred = unit == Unit.TEXT ? | 373 var pred = unit == Unit.TEXT ? |
| 359 AutomationPredicate.leaf : AutomationPredicate.object; | 374 AutomationPredicate.leaf : AutomationPredicate.object; |
| 360 newNode = AutomationUtil.findNextNode(newNode, dir, pred) || | 375 newNode = AutomationUtil.findNextNode(newNode, dir, pred) || |
| 361 originalNode; | 376 originalNode; |
| 362 newIndex = cursors.NODE_INDEX; | 377 newIndex = cursors.NODE_INDEX; |
| 363 break; | 378 break; |
| 364 } | 379 } |
| 365 break; | 380 break; |
| 366 case Unit.LINE: | 381 case Unit.LINE: |
| 367 newIndex = 0; | 382 var deepEquivalent = this.deepEquivalent; |
| 383 newNode = deepEquivalent.node || newNode; |
| 384 newIndex = deepEquivalent.index || 0; |
| 385 |
| 368 switch (movement) { | 386 switch (movement) { |
| 369 case Movement.BOUND: | 387 case Movement.BOUND: |
| 370 newNode = AutomationUtil.findNodeUntil(newNode, dir, | 388 newNode = AutomationUtil.findNodeUntil(newNode, dir, |
| 371 AutomationPredicate.linebreak, true); | 389 AutomationPredicate.linebreak, true); |
| 372 newNode = newNode || originalNode; | 390 newNode = newNode || originalNode; |
| 373 newIndex = | 391 newIndex = |
| 374 dir == Dir.FORWARD ? AutomationUtil.getText(newNode).length : 0; | 392 dir == Dir.FORWARD ? AutomationUtil.getText(newNode).length : 0; |
| 375 break; | 393 break; |
| 376 case Movement.DIRECTIONAL: | 394 case Movement.DIRECTIONAL: |
| 377 newNode = AutomationUtil.findNodeUntil( | 395 newNode = AutomationUtil.findNodeUntil( |
| 378 newNode, dir, AutomationPredicate.linebreak); | 396 newNode, dir, AutomationPredicate.linebreak); |
| 379 break; | 397 break; |
| 380 } | 398 } |
| 381 break; | 399 break; |
| 382 default: | 400 default: |
| 383 throw Error('Unrecognized unit: ' + unit); | 401 throw Error('Unrecognized unit: ' + unit); |
| 384 } | 402 } |
| 385 newNode = newNode || originalNode; | 403 newNode = newNode || originalNode; |
| 386 newIndex = goog.isDef(newIndex) ? newIndex : this.index_; | 404 newIndex = goog.isDef(newIndex) ? newIndex : this.index_; |
| 387 return new cursors.Cursor(newNode, newIndex); | 405 return new cursors.Cursor(newNode, newIndex); |
| 388 }, | 406 }, |
| 389 | 407 |
| 390 /** | 408 /** |
| 409 * Returns the deepest equivalent cursor. |
| 410 * @return {cursors.Cursor} |
| 411 */ |
| 412 get deepEquivalent() { |
| 413 var newNode = this.node; |
| 414 var newIndex = this.index_; |
| 415 while (newNode.firstChild) { |
| 416 if (newNode.role == RoleType.STATIC_TEXT) { |
| 417 // Text offset. |
| 418 // Re-interpret the index as an offset into an inlineTextBox. |
| 419 var target = newNode.firstChild; |
| 420 var length = 0; |
| 421 while (target && length < newIndex) { |
| 422 if (length <= newIndex && newIndex < (length + target.name.length)) |
| 423 break; |
| 424 length += target.name.length; |
| 425 target = target.nextSibling; |
| 426 } |
| 427 if (target) { |
| 428 newNode = target; |
| 429 newIndex = newIndex - length; |
| 430 } |
| 431 break; |
| 432 } else if (newNode.role != RoleType.INLINE_TEXT_BOX && |
| 433 newNode.children[newIndex]) { |
| 434 // Valid node offset. |
| 435 newNode = newNode.children[newIndex]; |
| 436 newIndex = 0; |
| 437 } else { |
| 438 // Invalid offset. |
| 439 break; |
| 440 } |
| 441 } |
| 442 |
| 443 return new cursors.Cursor(newNode, newIndex); |
| 444 }, |
| 445 |
| 446 /** |
| 391 * Returns whether this cursor points to a valid position. | 447 * Returns whether this cursor points to a valid position. |
| 392 * @return {boolean} | 448 * @return {boolean} |
| 393 */ | 449 */ |
| 394 isValid: function() { | 450 isValid: function() { |
| 395 return this.node != null; | 451 return this.node != null; |
| 396 } | 452 } |
| 397 }; | 453 }; |
| 398 | 454 |
| 399 /** | 455 /** |
| 400 * A cursors.Cursor that wraps from beginning to end and vice versa when moved. | 456 * A cursors.Cursor that wraps from beginning to end and vice versa when moved. |
| (...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 687 /** | 743 /** |
| 688 * Returns whether this range has valid start and end cursors. | 744 * Returns whether this range has valid start and end cursors. |
| 689 * @return {boolean} | 745 * @return {boolean} |
| 690 */ | 746 */ |
| 691 isValid: function() { | 747 isValid: function() { |
| 692 return this.start.isValid() && this.end.isValid(); | 748 return this.start.isValid() && this.end.isValid(); |
| 693 } | 749 } |
| 694 }; | 750 }; |
| 695 | 751 |
| 696 }); // goog.scope | 752 }); // goog.scope |
| OLD | NEW |