Home | History | Annotate | Download | only in walkers
      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 
      9 goog.provide('cvox.MathShifter');
     10 
     11 goog.require('cvox.AbstractShifter');
     12 goog.require('cvox.BrailleUtil');
     13 goog.require('cvox.CursorSelection');
     14 goog.require('cvox.DomUtil');
     15 goog.require('cvox.MathmlStore');
     16 goog.require('cvox.MathmlStoreRules');
     17 goog.require('cvox.NavDescription');
     18 goog.require('cvox.SpeechRuleEngine');
     19 goog.require('cvox.TraverseMath');
     20 
     21 
     22 /**
     23  * @constructor
     24  * @extends {cvox.AbstractShifter}
     25  * @param {cvox.CursorSelection=} sel A cursor selection.
     26  */
     27 cvox.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 
     51 cvox.TraverseMath.getInstance().initialize(sel.start.node);
     52 };
     53 goog.inherits(cvox.MathShifter, cvox.AbstractShifter);
     54 
     55 
     56 /**
     57  * @override
     58  */
     59 cvox.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  */
     71 cvox.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  */
     80 cvox.MathShifter.prototype.getName = function() {
     81   return cvox.ChromeVox.msgs.getMsg('math_shifter');
     82 };
     83 
     84 
     85 /**
     86  * @override
     87  */
     88 cvox.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  */
    101 cvox.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  */
    111 cvox.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  */
    120 cvox.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  */
    130 cvox.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  */
    142 cvox.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  */
    165 cvox.MathShifter.prototype.getDomainMsg = function() {
    166   return cvox.TraverseMath.getInstance().domain;
    167 };
    168