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

Side by Side Diff: chrome/browser/resources/chromeos/chromevox/braille/braille_display_manager.js

Issue 2496823002: Implement word wrapping and panning in multiline Braille. (Closed)
Patch Set: Addressed code reviews. Created 4 years, 1 month 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 unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 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 Puts text on a braille display. 6 * @fileoverview Puts text on a braille display.
7 * 7 *
8 */ 8 */
9 9
10 goog.provide('cvox.BrailleDisplayManager'); 10 goog.provide('cvox.BrailleDisplayManager');
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
46 this.translatedContent_ = new ArrayBuffer(0); 46 this.translatedContent_ = new ArrayBuffer(0);
47 /** 47 /**
48 * @type {!ArrayBuffer} 48 * @type {!ArrayBuffer}
49 * @private 49 * @private
50 */ 50 */
51 this.displayedContent_ = this.translatedContent_; 51 this.displayedContent_ = this.translatedContent_;
52 /** 52 /**
53 * @type {cvox.PanStrategy} 53 * @type {cvox.PanStrategy}
54 * @private 54 * @private
55 */ 55 */
56 this.panStrategy_ = new cvox.WrappingPanStrategy(); 56 this.panStrategy_ = new cvox.PanStrategy();
57 /** 57 /**
58 * @type {function(!cvox.BrailleKeyEvent, !cvox.NavBraille)} 58 * @type {function(!cvox.BrailleKeyEvent, !cvox.NavBraille)}
59 * @private 59 * @private
60 */ 60 */
61 this.commandListener_ = function() {}; 61 this.commandListener_ = function() {};
62 /** 62 /**
63 * Current display state used for width calculations. This is different from 63 * Current display state used for width calculations. This is different from
64 * realDisplayState_ if the braille captions feature is enabled and there is 64 * realDisplayState_ if the braille captions feature is enabled and there is
65 * no hardware display connected. Otherwise, it is the same object 65 * no hardware display connected. Otherwise, it is the same object
66 * as realDisplayState_. 66 * as realDisplayState_.
67 * @type {!cvox.BrailleDisplayState} 67 * @type {!cvox.BrailleDisplayState}
68 * @private 68 * @private
69 */ 69 */
70 this.displayState_ = {available: false, textRowCount: undefined, 70 this.displayState_ = {available: false, textRowCount: undefined,
71 textColumnCount: undefined}; 71 textColumnCount: undefined};
72 /** 72 /**
73 * State reported from the chrome api, reflecting a real hardware 73 * State reported from the chrome api, reflecting a real hardware
74 * display. 74 * display.
75 * @type {!cvox.BrailleDisplayState} 75 * @type {!cvox.BrailleDisplayState}
76 * @private 76 * @private
77 */ 77 */
78 this.realDisplayState_ = this.displayState_; 78 this.realDisplayState_ = this.displayState_;
79 /**
80 * @type {!Array<number>}
81 * @private
82 */
83 this.textToBraille_ = [];
84 /**
85 * @type {!Array<number>}
86 * @private
87 */
88 this.brailleToText_ = [];
89 79
90 translatorManager.addChangeListener(function() { 80 translatorManager.addChangeListener(function() {
91 this.translateContent_(this.content_, this.expansionType_); 81 this.translateContent_(this.content_, this.expansionType_);
92 }.bind(this)); 82 }.bind(this));
93 83
94 chrome.storage.onChanged.addListener(function(changes, area) { 84 chrome.storage.onChanged.addListener(function(changes, area) {
95 if (area == 'local' && 'brailleWordWrap' in changes) { 85 if (area == 'local' && 'brailleWordWrap' in changes) {
96 this.updatePanStrategy_(changes.brailleWordWrap.newValue); 86 this.updatePanStrategy_(changes.brailleWordWrap.newValue);
97 } 87 }
98 }.bind(this)); 88 }.bind(this));
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
151 }; 141 };
152 142
153 143
154 /** 144 /**
155 * @param {!cvox.BrailleDisplayState} newState Display state reported 145 * @param {!cvox.BrailleDisplayState} newState Display state reported
156 * by the extension API. 146 * by the extension API.
157 * @private 147 * @private
158 */ 148 */
159 cvox.BrailleDisplayManager.prototype.refreshDisplayState_ = function( 149 cvox.BrailleDisplayManager.prototype.refreshDisplayState_ = function(
160 newState) { 150 newState) {
161 var oldSize = this.displayState_.textColumnCount * 151 var oldColumnCount = this.displayState_.textColumnCount || 0;
162 this.displayState_.textRowCount || 0; 152 var oldRowCount = this.displayState_.textRowCount || 0;
163 this.realDisplayState_ = newState; 153 this.realDisplayState_ = newState;
164 if (newState.available) { 154 if (newState.available) {
165 this.displayState_ = newState; 155 this.displayState_ = newState;
156 // Update the dimensions of the virtual braille captions display those
157 // of a real physical display when one is plugged in.
158 localStorage['virtualBrailleRows'] = newState.textRowCount;
159 localStorage['virtualBrailleColumns'] = newState.textColumnCount;
166 } else { 160 } else {
167 this.displayState_ = 161 this.displayState_ =
168 cvox.BrailleCaptionsBackground.getVirtualDisplayState(); 162 cvox.BrailleCaptionsBackground.getVirtualDisplayState();
169 } 163 }
170 var newSize = this.displayState_.textColumnCount * 164 var newColumnCount = this.displayState_.textColumnCount || 0;
171 this.displayState_.textRowCount || 0; 165 var newRowCount = this.displayState_.textRowCount || 0;
172 if (oldSize != newSize) { 166 if (oldColumnCount != newColumnCount || oldRowCount != newRowCount) {
173 this.panStrategy_.setDisplaySize(newSize); 167 this.panStrategy_.setDisplaySize(newRowCount, newColumnCount);
David Tseng 2016/11/15 17:54:59 Make the display size a pair i.e. @type {{rows: nu
ultimatedbz 2016/11/19 03:11:58 Done. The parameters are still the same, but the i
174 } 168 }
175 this.refresh_(); 169 this.refresh_();
176 }; 170 };
177 171
178 172
179 /** 173 /**
180 * Called when the state of braille captions changes. 174 * Called when the state of braille captions changes.
181 * @private 175 * @private
182 */ 176 */
183 cvox.BrailleDisplayManager.prototype.onCaptionsStateChanged_ = function() { 177 cvox.BrailleDisplayManager.prototype.onCaptionsStateChanged_ = function() {
184 // Force reevaluation of the display state based on our stored real 178 // Force reevaluation of the display state based on our stored real
185 // hardware display state, meaning that if a real display is connected, 179 // hardware display state, meaning that if a real display is connected,
186 // that takes precedence over the state from the captions 'virtual' display. 180 // that takes precedence over the state from the captions 'virtual' display.
187 this.refreshDisplayState_(this.realDisplayState_); 181 this.refreshDisplayState_(this.realDisplayState_);
188 }; 182 };
189 183
190 184
191 /** @private */ 185 /**
186 * Refreshes what is shown on the physical braille display and the virtual
187 * braille captions display.
188 * @private */
192 cvox.BrailleDisplayManager.prototype.refresh_ = function() { 189 cvox.BrailleDisplayManager.prototype.refresh_ = function() {
193 if (!this.displayState_.available) { 190 if (!this.displayState_.available) {
194 return; 191 return;
195 } 192 }
196 var viewPort = this.panStrategy_.viewPort; 193 var brailleBuf = this.panStrategy_.getCurrentBrailleSlice();
David Tseng 2016/11/15 17:54:59 Slice seems wrong in terms of multiline; maybe cal
ultimatedbz 2016/11/19 03:11:58 Done.
197 var buf = this.displayedContent_.slice(viewPort.start, viewPort.end); 194 var textBuf = this.panStrategy_.getCurrentTextSlice();
198 if (this.realDisplayState_.available) { 195 if (this.realDisplayState_.available) {
199 chrome.brailleDisplayPrivate.writeDots(buf, buf.byteLength, 1); 196 chrome.brailleDisplayPrivate.writeDots(brailleBuf,
197 brailleBuf.byteLength, 1);
200 } 198 }
201 if (cvox.BrailleCaptionsBackground.isEnabled()) { 199 if (cvox.BrailleCaptionsBackground.isEnabled()) {
202 var start = this.brailleToTextPosition_(viewPort.start); 200 cvox.BrailleCaptionsBackground.setContent(textBuf, brailleBuf,
203 var end = this.brailleToTextPosition_(viewPort.end); 201 this.panStrategy_.brailleToText, this.panStrategy_.offsetsForSlices);
204 cvox.BrailleCaptionsBackground.setContent(
205 this.content_.text.toString().substring(start, end), buf,
206 this.brailleToText_);
207 } 202 }
208 }; 203 };
209 204
210
211 /** 205 /**
212 * @param {!cvox.NavBraille} newContent New display content. 206 * @param {!cvox.NavBraille} newContent New display content.
213 * @param {cvox.ExpandingBrailleTranslator.ExpansionType} newExpansionType 207 * @param {cvox.ExpandingBrailleTranslator.ExpansionType} newExpansionType
214 * How the value part of of the new content should be expanded 208 * How the value part of of the new content should be expanded
215 * with regards to contractions. 209 * with regards to contractions.
216 * @private 210 * @private
217 */ 211 */
218 cvox.BrailleDisplayManager.prototype.translateContent_ = function( 212 cvox.BrailleDisplayManager.prototype.translateContent_ = function(
219 newContent, newExpansionType) { 213 newContent, newExpansionType) {
220 var writeTranslatedContent = function(cells, textToBraille, brailleToText) { 214 var writeTranslatedContent = function(cells, textToBraille, brailleToText) {
221 this.content_ = newContent; 215 this.content_ = newContent;
222 this.expansionType_ = newExpansionType; 216 this.expansionType_ = newExpansionType;
223 this.textToBraille_ = textToBraille;
224 this.brailleToText_ = brailleToText;
225 var startIndex = this.content_.startIndex; 217 var startIndex = this.content_.startIndex;
226 var endIndex = this.content_.endIndex; 218 var endIndex = this.content_.endIndex;
227 var targetPosition; 219 var targetPosition;
228 if (startIndex >= 0) { 220 if (startIndex >= 0) {
229 var translatedStartIndex; 221 var translatedStartIndex;
230 var translatedEndIndex; 222 var translatedEndIndex;
231 if (startIndex >= textToBraille.length) { 223 if (startIndex >= textToBraille.length) {
232 // Allow the cells to be extended with one extra cell for 224 // Allow the cells to be extended with one extra cell for
233 // a carret after the last character. 225 // a carret after the last character.
234 var extCells = new ArrayBuffer(cells.byteLength + 1); 226 var extCells = new ArrayBuffer(cells.byteLength + 1);
235 new Uint8Array(extCells).set(new Uint8Array(cells)); 227 new Uint8Array(extCells).set(cells);
236 // Last byte is initialized to 0. 228 // Last byte is initialized to 0.
237 cells = extCells; 229 cells = extCells;
238 translatedStartIndex = cells.byteLength - 1; 230 translatedStartIndex = cells.byteLength - 1;
239 } else { 231 } else {
240 translatedStartIndex = textToBraille[startIndex]; 232 translatedStartIndex = textToBraille[startIndex];
241 } 233 }
242 if (endIndex >= textToBraille.length) { 234 if (endIndex >= textToBraille.length) {
243 // endIndex can't be past-the-end of the last cell unless 235 // endIndex can't be past-the-end of the last cell unless
244 // startIndex is too, so we don't have to do another 236 // startIndex is too, so we don't have to do another
245 // extension here. 237 // extension here.
246 translatedEndIndex = cells.byteLength; 238 translatedEndIndex = cells.byteLength;
247 } else { 239 } else {
248 translatedEndIndex = textToBraille[endIndex]; 240 translatedEndIndex = textToBraille[endIndex];
249 } 241 }
250 this.translatedContent_ = cells; 242 this.translatedContent_ = cells;
251 // Copy the translated content to a separate buffer and add the cursor 243 // Copy the translated content to a separate buffer and add the cursor
252 // to it. 244 // to it.
253 this.displayedContent_ = new ArrayBuffer(cells.byteLength); 245 this.displayedContent_ = new ArrayBuffer(cells.byteLength);
254 new Uint8Array(this.displayedContent_).set(new Uint8Array(cells)); 246 new Uint8Array(this.displayedContent_).set(cells);
255 this.writeCursor_(this.displayedContent_, 247 this.writeCursor_(this.displayedContent_,
256 translatedStartIndex, translatedEndIndex); 248 translatedStartIndex, translatedEndIndex);
257 targetPosition = translatedStartIndex; 249 targetPosition = translatedStartIndex;
258 } else { 250 } else {
259 this.translatedContent_ = this.displayedContent_ = cells; 251 this.translatedContent_ = this.displayedContent_ = cells;
260 targetPosition = 0; 252 targetPosition = 0;
261 } 253 }
262 this.panStrategy_.setContent(this.translatedContent_, targetPosition); 254 this.panStrategy_.setContent(this.content_.text.toString(),
255 this.translatedContent_, brailleToText);
256
263 this.refresh_(); 257 this.refresh_();
264 }.bind(this); 258 }.bind(this);
265 259
266 var translator = this.translatorManager_.getExpandingTranslator(); 260 var translator = this.translatorManager_.getExpandingTranslator();
267 if (!translator) { 261 if (!translator) {
268 writeTranslatedContent(new ArrayBuffer(0), [], []); 262 writeTranslatedContent(new ArrayBuffer(0), [], []);
269 } else { 263 } else {
270 translator.translate( 264 translator.translate(
271 newContent.text, 265 newContent.text,
272 newExpansionType, 266 newExpansionType,
273 writeTranslatedContent); 267 writeTranslatedContent);
274 } 268 }
275 }; 269 };
276 270
277 271
278 /** 272 /**
279 * @param {cvox.BrailleKeyEvent} event The key event. 273 * @param {cvox.BrailleKeyEvent} event The key event.
280 * @private 274 * @private
281 */ 275 */
282 cvox.BrailleDisplayManager.prototype.onKeyEvent_ = function(event) { 276 cvox.BrailleDisplayManager.prototype.onKeyEvent_ = function(event) {
283 switch (event.command) { 277 switch (event.command) {
284 case cvox.BrailleKeyCommand.PAN_LEFT: 278 case cvox.BrailleKeyCommand.PAN_LEFT:
285 this.panLeft_(); 279 this.panLeft_();
286 break; 280 break;
287 case cvox.BrailleKeyCommand.PAN_RIGHT: 281 case cvox.BrailleKeyCommand.PAN_RIGHT:
288 this.panRight_(); 282 this.panRight_();
289 break; 283 break;
290 case cvox.BrailleKeyCommand.ROUTING: 284 case cvox.BrailleKeyCommand.ROUTING:
285 /* TODO
David Tseng 2016/11/15 17:54:59 The goal is to get this cl checked in, so please r
ultimatedbz 2016/11/15 19:31:57 I do intend to complete this block, but for the ti
David Tseng 2016/11/15 21:36:38 I would not accept this cl without this working as
ultimatedbz 2016/11/15 21:58:09 I think you are assuming that I want to commit the
ultimatedbz 2016/11/19 03:11:58 As per our offline conversation, I will leave the
ultimatedbz 2016/11/19 03:11:58 I just implemented a solution to your problem. I'm
291 event.displayPosition = this.brailleToTextPosition_( 286 event.displayPosition = this.brailleToTextPosition_(
292 event.displayPosition + this.panStrategy_.viewPort.start); 287 event.displayPosition + this.panStrategy_.viewPort.start);
293 // fall through 288 // fall through
289 // */
294 default: 290 default:
295 this.commandListener_(event, this.content_); 291 this.commandListener_(event, this.content_);
296 break; 292 break;
297 } 293 }
298 }; 294 };
299 295
300 296
301 /** 297 /**
302 * Shift the display by one full display size and refresh the content. 298 * Shift the display by one full display size and refresh the content.
303 * Sends the appropriate command if the display is already at the leftmost 299 * Sends the appropriate command if the display is already at the leftmost
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
361 /** 357 /**
362 * Returns the text position corresponding to an absolute braille position, 358 * Returns the text position corresponding to an absolute braille position,
363 * that is not accounting for the current pan position. 359 * that is not accounting for the current pan position.
364 * @private 360 * @private
365 * @param {number} braillePosition Braille position relative to the startof 361 * @param {number} braillePosition Braille position relative to the startof
366 * the translated content. 362 * the translated content.
367 * @return {number} The mapped position in code units. 363 * @return {number} The mapped position in code units.
368 */ 364 */
369 cvox.BrailleDisplayManager.prototype.brailleToTextPosition_ = 365 cvox.BrailleDisplayManager.prototype.brailleToTextPosition_ =
370 function(braillePosition) { 366 function(braillePosition) {
371 var mapping = this.brailleToText_; 367 // TODO I'll need to support this function
368 var mapping = this.panStrategy_.brailleToText;
372 if (braillePosition < 0) { 369 if (braillePosition < 0) {
373 // This shouldn't happen. 370 // This shouldn't happen.
374 console.error('WARNING: Braille position < 0: ' + braillePosition); 371 console.error('WARNING: Braille position < 0: ' + braillePosition);
375 return 0; 372 return 0;
376 } else if (braillePosition >= mapping.length) { 373 } else if (braillePosition >= mapping.length) {
377 // This happens when the user clicks on the right part of the display 374 // This happens when the user clicks on the right part of the display
378 // when it is not entirely filled with content. Allow addressing the 375 // when it is not entirely filled with content. Allow addressing the
379 // position after the last character. 376 // position after the last character.
380 return this.content_.text.length; 377 return this.content_.text.length;
381 } else { 378 } else {
382 return mapping[braillePosition]; 379 return mapping[braillePosition];
383 } 380 }
384 }; 381 };
385 382
386 383
387 /** 384 /**
388 * @param {boolean} wordWrap 385 * @param {boolean} wordWrap
389 * @private 386 * @private
390 */ 387 */
391 cvox.BrailleDisplayManager.prototype.updatePanStrategy_ = function(wordWrap) { 388 cvox.BrailleDisplayManager.prototype.updatePanStrategy_ = function(wordWrap) {
392 var newStrategy = wordWrap ? new cvox.WrappingPanStrategy() : 389 this.panStrategy_.setPanStrategy(wordWrap);
393 new cvox.FixedPanStrategy();
394 newStrategy.setDisplaySize(this.displayState_.textColumnCount || 0);
395 newStrategy.setContent(this.translatedContent_,
396 this.panStrategy_.viewPort.start);
397 this.panStrategy_ = newStrategy;
398 this.refresh_(); 390 this.refresh_();
399 }; 391 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698