Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(187)

Unified Diff: chrome/browser/resources/chromeos/chromevox/cvox2/background/editing.js

Issue 2540553002: Implement rich editable line output (Closed)
Patch Set: Fix plain text line braille. Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/resources/chromeos/chromevox/cvox2/background/editing.js
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/editing.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/editing.js
index 43b60fa2e33a895665bba72defb95631aac1f16f..4d40067b035e09515e8516578ac052ec11485667 100644
--- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/editing.js
+++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/editing.js
@@ -22,7 +22,7 @@ goog.scope(function() {
var AutomationEvent = chrome.automation.AutomationEvent;
var AutomationNode = chrome.automation.AutomationNode;
var Cursor = cursors.Cursor;
-var Dir = AutomationUtil.Dir;
+var Dir = constants.Dir;
var EventType = chrome.automation.EventType;
var Range = cursors.Range;
var RoleType = chrome.automation.RoleType;
@@ -41,6 +41,12 @@ editing.TextEditHandler = function(node) {
this.node_ = node;
};
+/**
+ * Flag set to indicate whether ChromeVox uses experimental rich text support.
+ * @type {boolean}
+ */
+editing.useRichText = false;
+
editing.TextEditHandler.prototype = {
/** @return {!AutomationNode} */
get node() {
@@ -66,8 +72,15 @@ editing.TextEditHandler.prototype = {
*/
function TextFieldTextEditHandler(node) {
editing.TextEditHandler.call(this, node);
- /** @type {AutomationEditableText} @private */
- this.editableText_ = new AutomationEditableText(node);
+
+ chrome.automation.getDesktop(function(desktop) {
+ var useRichText = editing.useRichText &&
+ node.state.richlyEditable;
+
+ /** @private {!AutomationEditableText} */
+ this.editableText_ = useRichText ?
+ new AutomationRichEditableText(node) : new AutomationEditableText(node);
+ }.bind(this));
}
TextFieldTextEditHandler.prototype = {
@@ -199,6 +212,138 @@ AutomationEditableText.prototype = {
}
};
+
+/**
+ * A |ChromeVoxEditableTextBase| that implements text editing feedback
+ * for automation tree text fields using anchor and focus selection.
+ * @constructor
+ * @param {!AutomationNode} node
+ * @extends {AutomationEditableText}
+ */
+function AutomationRichEditableText(node) {
+ AutomationEditableText.call(this, node);
+
+ var root = this.node_.root;
+ if (!root || !root.anchorObject || !root.focusObject)
+ return;
+
+ this.range = new cursors.Range(
+ new cursors.Cursor(root.anchorObject, root.anchorOffset || 0),
+ new cursors.Cursor(root.focusObject, root.focusOffset || 0));
+}
+
+AutomationRichEditableText.prototype = {
+ __proto__: AutomationEditableText.prototype,
+
+ /** @override */
+ onUpdate: function() {
+ var root = this.node_.root;
+ if (!root.anchorObject || !root.focusObject)
+ return;
+
+ var cur = new cursors.Range(
+ new cursors.Cursor(root.anchorObject, root.anchorOffset || 0),
+ new cursors.Cursor(root.focusObject, root.focusOffset || 0));
+ var prev = this.range;
+
+ this.range = cur;
+
+ if (prev.start.node == cur.start.node &&
+ prev.end.node == cur.end.node &&
+ cur.start.node == cur.end.node) {
+ // Plain text: diff the two positions.
+ this.changed(new cvox.TextChangeEvent(
+ root.anchorObject.name || '',
+ root.anchorOffset || 0,
+ root.focusOffset || 0,
+ true));
+
+ var lineIndex = this.getLineIndex(this.start);
+ var brailleLineStart = this.getLineStart(lineIndex);
+ var brailleLineEnd = this.getLineEnd(lineIndex);
+ var buff = new Spannable(this.value);
+ buff.setSpan(new cvox.ValueSpan(0), brailleLineStart, brailleLineEnd);
+
+ var selStart = this.start - brailleLineStart;
+ var selEnd = this.end - brailleLineStart;
+ buff.setSpan(new cvox.ValueSelectionSpan(), selStart, selEnd);
+ cvox.ChromeVox.braille.write(new cvox.NavBraille({text: buff,
+ startIndex: selStart,
+ endIndex: selEnd}));
+ return;
+ } else {
+ // Rich text:
+ // If the position is collapsed, expand to the current line.
+ var start = cur.start;
+ var end = cur.end;
+ if (start.equals(end)) {
+ start = start.move(Unit.LINE, Movement.BOUND, Dir.BACKWARD);
+ end = end.move(Unit.LINE, Movement.BOUND, Dir.FORWARD);
+ }
+ var range = new cursors.Range(start, end);
+ var output = new Output().withRichSpeechAndBraille(
+ range, prev, Output.EventType.NAVIGATE);
+
+ // This position is not describable.
+ if (!output.hasSpeech) {
+ cvox.ChromeVox.tts.speak('blank', cvox.QueueMode.CATEGORY_FLUSH);
+ cvox.ChromeVox.braille.write(
+ new cvox.NavBraille({text: '', startIndex: 0, endIndex: 0}));
+ } else {
+ output.go();
+ }
+ }
+
+ // Keep the other members in sync for any future editable text base state
+ // machine changes.
+ this.value = cur.start.node.name || '';
+ this.start = cur.start.index;
+ this.end = cur.start.index;
+ },
+
+ /** @override */
+ describeSelectionChanged: function(evt) {
+ // Ignore end of text announcements.
+ if ((this.start + 1) == evt.start && evt.start == this.value.length)
+ return;
+
+ cvox.ChromeVoxEditableTextBase.prototype.describeSelectionChanged.call(
+ this, evt);
+ },
+
+ /** @override */
+ getLineIndex: function(charIndex) {
+ var breaks = this.getLineBreaks_();
+ var index = 0;
+ while (index < breaks.length && breaks[index] <= charIndex)
+ ++index;
+ return index;
+ },
+
+ /** @override */
+ getLineStart: function(lineIndex) {
+ if (lineIndex == 0)
+ return 0;
+ var breaks = this.getLineBreaks_();
+ return breaks[lineIndex - 1] ||
+ this.node_.root.focusObject.value.length;
+ },
+
+ /** @override */
+ getLineEnd: function(lineIndex) {
+ var breaks = this.getLineBreaks_();
+ var value = this.node_.root.focusObject.name;
+ if (lineIndex >= breaks.length)
+ return value.length;
+ return breaks[lineIndex];
+ },
+
+ /** @override */
+ getLineBreaks_: function() {
+ return this.node_.root.focusObject.lineStartOffsets || [];
+ }
+};
+
/**
* @param {!AutomationNode} node The root editable node, i.e. the root of a
* contenteditable subtree or a text field.

Powered by Google App Engine
This is Rietveld 408576698