math_shifter.js revision cedac228d2dd51db4b79ea1e72c7f249408ee061
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
3// found in the LICENSE file.
4
5/**
6 * @fileoverview A class for walking mathml expressions.
7 */
8
9goog.provide('cvox.MathShifter');
10
11goog.require('cvox.AbstractShifter');
12goog.require('cvox.BrailleUtil');
13goog.require('cvox.CursorSelection');
14goog.require('cvox.DomUtil');
15goog.require('cvox.MathmlStore');
16goog.require('cvox.MathmlStoreRules');
17goog.require('cvox.NavDescription');
18goog.require('cvox.SpeechRuleEngine');
19goog.require('cvox.TraverseMath');
20
21
22/**
23 * @constructor
24 * @extends {cvox.AbstractShifter}
25 * @param {cvox.CursorSelection=} sel A cursor selection.
26 */
27cvox.MathShifter = function(sel) {
28  goog.base(this);
29
30  /**
31   * Indicates the depth of the currently read expression.
32   * @type {number}
33   * @private
34   */
35  this.level_ = 0;
36
37  /**
38   * Indicates the vertical direction of movement (true for up, false for down).
39   * @type {boolean}
40   * @private
41   */
42  this.direction_ = false;
43
44  /**
45   * Indicates whether or not we've bumped against an edge in the math
46   * structure.
47   * @private
48   */
49  this.bumped_ = false;
50
51cvox.TraverseMath.getInstance().initialize(sel.start.node);
52};
53goog.inherits(cvox.MathShifter, cvox.AbstractShifter);
54
55
56/**
57 * @override
58 */
59cvox.MathShifter.prototype.next = function(sel) {
60  // Delegate to TraverseMath which manages selection inside of the math tree.
61  var r = sel.isReversed();
62  this.bumped_ = !cvox.TraverseMath.getInstance().nextSibling(r);
63  var attachedNode = cvox.TraverseMath.getInstance().getAttachedActiveNode();
64  return attachedNode ? cvox.CursorSelection.fromNode(attachedNode) : sel;
65};
66
67
68/**
69 * @override
70 */
71cvox.MathShifter.prototype.sync = function(sel) {
72  var attachedNode = cvox.TraverseMath.getInstance().getAttachedActiveNode();
73  return attachedNode ? cvox.CursorSelection.fromNode(attachedNode) : sel;
74};
75
76
77/**
78 * @override
79 */
80cvox.MathShifter.prototype.getName = function() {
81  return cvox.ChromeVox.msgs.getMsg('math_shifter');
82};
83
84
85/**
86 * @override
87 */
88cvox.MathShifter.prototype.getDescription = function(prevSel, sel) {
89  var descs = cvox.SpeechRuleEngine.getInstance().evaluateNode(
90      cvox.TraverseMath.getInstance().activeNode);
91  if (this.bumped_ && descs.length > 0) {
92    descs[0].pushEarcon(cvox.AbstractEarcons.WRAP_EDGE);
93  }
94  return descs;
95};
96
97
98/**
99 * @override
100 */
101cvox.MathShifter.prototype.getBraille = function(prevSel, sel) {
102  return new cvox.NavBraille({
103    text: cvox.BrailleUtil.getTemplated(prevSel.start.node, sel.start.node)
104  });
105};
106
107
108/**
109 * @override
110 */
111cvox.MathShifter.prototype.getGranularityMsg = function() {
112  return this.direction_ ? 'up to level ' + this.level_ :
113      'down to level ' + this.level_;
114};
115
116
117/**
118 * @override
119 */
120cvox.MathShifter.prototype.makeLessGranular = function() {
121  this.level_ = this.level_ > 0 ? this.level_ - 1 : 0;
122  this.direction_ = true;
123  this.bumped_ = !cvox.TraverseMath.getInstance().nextParentChild(true);
124};
125
126
127/**
128 * @override
129 */
130cvox.MathShifter.prototype.makeMoreGranular = function() {
131  this.direction_ = false;
132  this.bumped_ = !cvox.TraverseMath.getInstance().nextParentChild(false);
133  if (!this.bumped_) {
134    this.level_++;
135  }
136};
137
138
139/**
140 * @override
141 */
142cvox.MathShifter.create = function(sel) {
143  if (cvox.DomPredicates.mathPredicate(
144      cvox.DomUtil.getAncestors(sel.start.node))) {
145    var mathNode = cvox.DomUtil.getContainingMath(sel.end.node);
146    cvox.TraverseMath.getInstance().initialize(mathNode);
147    cvox.SpeechRuleEngine.getInstance().parameterize(
148        cvox.MathmlStore.getInstance());
149    // TODO (sorge) Embed these changes into a local context menu/options menu.
150    var dynamicCstr = cvox.MathStore.createDynamicConstraint(
151        cvox.TraverseMath.getInstance().domain,
152        cvox.TraverseMath.getInstance().style);
153    cvox.SpeechRuleEngine.getInstance().setDynamicConstraint(dynamicCstr);
154    return new cvox.MathShifter(sel);
155  }
156  return null;
157};
158
159
160/**
161 * The active domain of the MathShifter.
162 *
163 * @return {string} The name of the current Math Domain.
164 */
165cvox.MathShifter.prototype.getDomainMsg = function() {
166  return cvox.TraverseMath.getInstance().domain;
167};
168