Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 Processes events related to editing text and emits the | 6 * @fileoverview Processes events related to editing text and emits the |
| 7 * appropriate spoken and braille feedback. | 7 * appropriate spoken and braille feedback. |
| 8 */ | 8 */ |
| 9 | 9 |
| 10 goog.provide('editing.TextEditHandler'); | 10 goog.provide('editing.TextEditHandler'); |
| 11 | 11 |
| 12 goog.require('AutomationTreeWalker'); | 12 goog.require('AutomationTreeWalker'); |
| 13 goog.require('AutomationUtil'); | 13 goog.require('AutomationUtil'); |
| 14 goog.require('Output'); | 14 goog.require('Output'); |
| 15 goog.require('Output.EventType'); | 15 goog.require('Output.EventType'); |
| 16 goog.require('cursors.Cursor'); | 16 goog.require('cursors.Cursor'); |
| 17 goog.require('cursors.Range'); | 17 goog.require('cursors.Range'); |
| 18 goog.require('cvox.BrailleBackground'); | 18 goog.require('cvox.BrailleBackground'); |
| 19 goog.require('cvox.ChromeVoxEditableTextBase'); | 19 goog.require('cvox.ChromeVoxEditableTextBase'); |
| 20 goog.require('cvox.LibLouis.FormType'); | |
| 20 | 21 |
| 21 goog.scope(function() { | 22 goog.scope(function() { |
| 22 var AutomationEvent = chrome.automation.AutomationEvent; | 23 var AutomationEvent = chrome.automation.AutomationEvent; |
| 23 var AutomationNode = chrome.automation.AutomationNode; | 24 var AutomationNode = chrome.automation.AutomationNode; |
| 24 var Cursor = cursors.Cursor; | 25 var Cursor = cursors.Cursor; |
| 25 var Dir = constants.Dir; | 26 var Dir = constants.Dir; |
| 26 var EventType = chrome.automation.EventType; | 27 var EventType = chrome.automation.EventType; |
| 28 var FormType = cvox.LibLouis.FormType; | |
| 27 var Range = cursors.Range; | 29 var Range = cursors.Range; |
| 28 var RoleType = chrome.automation.RoleType; | 30 var RoleType = chrome.automation.RoleType; |
| 29 var StateType = chrome.automation.StateType; | 31 var StateType = chrome.automation.StateType; |
| 30 var Movement = cursors.Movement; | 32 var Movement = cursors.Movement; |
| 31 var Unit = cursors.Unit; | 33 var Unit = cursors.Unit; |
| 32 | 34 |
| 33 /** | 35 /** |
| 34 * A handler for automation events in a focused text field or editable root | 36 * A handler for automation events in a focused text field or editable root |
| 35 * such as a |contenteditable| subtree. | 37 * such as a |contenteditable| subtree. |
| 36 * @constructor | 38 * @constructor |
| (...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 315 .go(); | 317 .go(); |
| 316 } else if (!cur.hasCollapsedSelection()) { | 318 } else if (!cur.hasCollapsedSelection()) { |
| 317 // This is a selection. | 319 // This is a selection. |
| 318 cvox.ChromeVox.tts.speak(cur.selectedText, cvox.QueueMode.CATEGORY_FLUSH); | 320 cvox.ChromeVox.tts.speak(cur.selectedText, cvox.QueueMode.CATEGORY_FLUSH); |
| 319 cvox.ChromeVox.tts.speak(Msgs.getMsg('selected'), cvox.QueueMode.QUEUE); | 321 cvox.ChromeVox.tts.speak(Msgs.getMsg('selected'), cvox.QueueMode.QUEUE); |
| 320 this.brailleCurrentRichLine_(); | 322 this.brailleCurrentRichLine_(); |
| 321 } else { | 323 } else { |
| 322 // Describe the current line. This accounts for previous/current | 324 // Describe the current line. This accounts for previous/current |
| 323 // selections and picking the line edge boundary that changed (as computed | 325 // selections and picking the line edge boundary that changed (as computed |
| 324 // above). This is also the code path for describing paste. | 326 // above). This is also the code path for describing paste. |
| 325 cvox.ChromeVox.tts.speak(cur.text, cvox.QueueMode.CATEGORY_FLUSH); | 327 this.speakCurrentRichLine_(prev); |
| 326 this.brailleCurrentRichLine_(); | 328 this.brailleCurrentRichLine_(); |
| 327 } | 329 } |
| 328 | 330 |
| 329 // The state in EditableTextBase needs to get updated with the new line | 331 // The state in EditableTextBase needs to get updated with the new line |
| 330 // contents, so that subsequent intra-line changes get the right state | 332 // contents, so that subsequent intra-line changes get the right state |
| 331 // transitions. | 333 // transitions. |
| 332 this.value = cur.text; | 334 this.value = cur.text; |
| 333 this.start = cur.startOffset; | 335 this.start = cur.startOffset; |
| 334 this.end = cur.endOffset; | 336 this.end = cur.endOffset; |
| 335 }, | 337 }, |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 378 | 380 |
| 379 if (msgs.length) { | 381 if (msgs.length) { |
| 380 msgs.forEach(function(msg) { | 382 msgs.forEach(function(msg) { |
| 381 cvox.ChromeVox.tts.speak( | 383 cvox.ChromeVox.tts.speak( |
| 382 Msgs.getMsg(msg), cvox.QueueMode.QUEUE, | 384 Msgs.getMsg(msg), cvox.QueueMode.QUEUE, |
| 383 cvox.AbstractTts.PERSONALITY_ANNOTATION); | 385 cvox.AbstractTts.PERSONALITY_ANNOTATION); |
| 384 }); | 386 }); |
| 385 } | 387 } |
| 386 }, | 388 }, |
| 387 | 389 |
| 390 /** | |
| 391 * @param {editing.EditableLine} prevLine | |
| 392 * @private | |
| 393 */ | |
| 394 speakCurrentRichLine_: function(prevLine) { | |
| 395 var prev = prevLine ? prevLine.startContainer_ : this.node_; | |
| 396 var lineNodes = | |
| 397 this.line_.value_.getSpansInstanceOf(this.node_.constructor); | |
| 398 var queueMode = cvox.QueueMode.CATEGORY_FLUSH; | |
| 399 for (var i = 0, cur; cur = lineNodes[i]; i++) { | |
| 400 if (cur.children.length) | |
| 401 continue; | |
| 402 new Output() | |
| 403 .withRichSpeech( | |
| 404 Range.fromNode(cur), Range.fromNode(prev), | |
| 405 Output.EventType.NAVIGATE) | |
| 406 .withQueueMode(queueMode) | |
| 407 .go(); | |
| 408 prev = cur; | |
| 409 queueMode = cvox.QueueMode.QUEUE; | |
| 410 } | |
| 411 }, | |
| 412 | |
| 388 /** @private */ | 413 /** @private */ |
| 389 brailleCurrentRichLine_: function() { | 414 brailleCurrentRichLine_: function() { |
| 390 var cur = this.line_; | 415 var cur = this.line_; |
| 391 var value = cur.value_; | 416 var value = new Spannable(cur.value_); |
| 417 if (!this.node_.constructor) | |
| 418 return; | |
| 419 value.getSpansInstanceOf(this.node_.constructor).forEach(function(span) { | |
| 420 var parent = span.parent; | |
|
dmazzoni
2017/06/27 21:21:52
Rather than always checking the parent, I'd only g
David Tseng
2017/06/27 23:52:41
Acknowledged.
| |
| 421 if (!parent || parent.role != RoleType.STATIC_TEXT) | |
| 422 return; | |
| 423 var formType = FormType.PLAIN_TEXT; | |
| 424 if (parent.bold) | |
| 425 formType |= FormType.BOLD; | |
| 426 if (parent.italic) | |
| 427 formType |= FormType.ITALIC; | |
| 428 if (parent.underline) | |
| 429 formType |= FormType.UNDERLINE; | |
| 430 if (formType == FormType.PLAIN_TEXT) | |
| 431 return; | |
| 432 var start = value.getSpanStart(span); | |
| 433 var end = value.getSpanEnd(span); | |
| 434 value.setSpan(new cvox.FormSpan(formType), start, end); | |
| 435 }); | |
| 392 value.setSpan(new cvox.ValueSpan(0), 0, cur.value_.length); | 436 value.setSpan(new cvox.ValueSpan(0), 0, cur.value_.length); |
| 393 value.setSpan( | 437 value.setSpan( |
| 394 new cvox.ValueSelectionSpan(), cur.startOffset, cur.endOffset); | 438 new cvox.ValueSelectionSpan(), cur.startOffset, cur.endOffset); |
| 395 cvox.ChromeVox.braille.write(new cvox.NavBraille( | 439 cvox.ChromeVox.braille.write(new cvox.NavBraille( |
| 396 {text: value, startIndex: cur.startOffset, endIndex: cur.endOffset})); | 440 {text: value, startIndex: cur.startOffset, endIndex: cur.endOffset})); |
| 397 }, | 441 }, |
| 398 | 442 |
| 399 /** @override */ | 443 /** @override */ |
| 400 describeSelectionChanged: function(evt) { | 444 describeSelectionChanged: function(evt) { |
| 401 // Note that since Chrome allows for selection to be placed immediately at | 445 // Note that since Chrome allows for selection to be placed immediately at |
| (...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 766 * @return {boolean} | 810 * @return {boolean} |
| 767 */ | 811 */ |
| 768 isSameLineAndSelection: function(otherLine) { | 812 isSameLineAndSelection: function(otherLine) { |
| 769 return this.isSameLine(otherLine) && | 813 return this.isSameLine(otherLine) && |
| 770 this.startOffset == otherLine.startOffset && | 814 this.startOffset == otherLine.startOffset && |
| 771 this.endOffset == otherLine.endOffset; | 815 this.endOffset == otherLine.endOffset; |
| 772 } | 816 } |
| 773 }; | 817 }; |
| 774 | 818 |
| 775 }); | 819 }); |
| OLD | NEW |