1 /** 2 * Copyright (C) 2010-2014 KO GmbH <copyright@kogmbh.com> 3 * 4 * @licstart 5 * This file is part of WebODF. 6 * 7 * WebODF is free software: you can redistribute it and/or modify it 8 * under the terms of the GNU Affero General Public License (GNU AGPL) 9 * as published by the Free Software Foundation, either version 3 of 10 * the License, or (at your option) any later version. 11 * 12 * WebODF is distributed in the hope that it will be useful, but 13 * WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU Affero General Public License for more details. 16 * 17 * You should have received a copy of the GNU Affero General Public License 18 * along with WebODF. If not, see <http://www.gnu.org/licenses/>. 19 * @licend 20 * 21 * @source: http://www.webodf.org/ 22 * @source: https://github.com/kogmbh/WebODF/ 23 */ 24 25 /*global core, gui*/ 26 27 /** 28 * Finds the closest step to the specified offset, but comparing the left and right edges of the 29 * surrounding rectangles to the desired offset. Iteration will continue until the steps 30 * start getting further away from the current closest step. 31 * 32 * @constructor 33 * @implements {gui.VisualStepScanner} 34 * @param {!number} offset Target horizontal offset 35 */ 36 gui.ClosestXOffsetScanner = function (offset) { 37 "use strict"; 38 var self = this, 39 closestDiff, 40 LEFT_TO_RIGHT = gui.StepInfo.VisualDirection.LEFT_TO_RIGHT; 41 42 this.token = undefined; 43 44 /** 45 * Returns true if the supplied edgeOffset is further away from the desired offset 46 * than one previously seen. 47 * 48 * @param {?number} edgeOffset 49 * @return {!boolean} 50 */ 51 function isFurtherFromOffset(edgeOffset) { 52 if (edgeOffset !== null && closestDiff !== undefined) { 53 return Math.abs(edgeOffset - offset) > closestDiff; 54 } 55 return false; 56 } 57 58 /** 59 * Update the closestDiff if the supplied edge is closer to the offset 60 * @param {?number} edge 61 * @return {undefined} 62 */ 63 function updateDiffIfSmaller(edge) { 64 if (edge !== null && isFurtherFromOffset(edge) === false) { 65 closestDiff = Math.abs(edge - offset); 66 } 67 } 68 69 /** 70 * @param {!gui.StepInfo} stepInfo 71 * @param {?ClientRect} previousRect 72 * @param {?ClientRect} nextRect 73 * @return {!boolean} 74 */ 75 this.process = function(stepInfo, previousRect, nextRect) { 76 var edge1, 77 edge2; 78 79 // The cursor is always between the two rects. 80 if (stepInfo.visualDirection === LEFT_TO_RIGHT) { 81 // In an LTR visual direction, the caret is to the right of the previous rect 82 edge1 = previousRect && previousRect.right; 83 // and the left of the next rect 84 edge2 = nextRect && nextRect.left; 85 } else { 86 // In an RTL visual direction, the caret is to the LEFT of the previous rect 87 edge1 = previousRect && previousRect.left; 88 // and the RIGHT of the next rect 89 edge2 = nextRect && nextRect.right; 90 } 91 92 if (isFurtherFromOffset(edge1) || isFurtherFromOffset(edge2)) { 93 // The current step is further away than the previous one, so terminate iteration 94 return true; 95 } 96 if (previousRect || nextRect) { 97 // At least one rectangle is visible, and is therefore a closer step than the last seen one 98 updateDiffIfSmaller(edge1); 99 updateDiffIfSmaller(edge2); 100 self.token = stepInfo.token; 101 } 102 return false; 103 }; 104 };