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

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: removed unnecessary files 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 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
163 this.realDisplayState_ = newState; 153 this.realDisplayState_ = newState;
164 if (newState.available) { 154 if (newState.available) {
165 this.displayState_ = newState; 155 this.displayState_ = newState;
166 } else { 156 } else {
167 this.displayState_ = 157 this.displayState_ =
168 cvox.BrailleCaptionsBackground.getVirtualDisplayState(); 158 cvox.BrailleCaptionsBackground.getVirtualDisplayState();
169 } 159 }
170 var newSize = this.displayState_.textColumnCount * 160 var newSize = this.displayState_.textColumnCount *
171 this.displayState_.textRowCount || 0; 161 this.displayState_.textRowCount || 0;
172 if (oldSize != newSize) { 162 if (oldSize != newSize) {
173 this.panStrategy_.setDisplaySize(newSize); 163 // TODO might need to change when display is plugged in.
David Tseng 2016/11/14 21:05:08 This is going to break for real devices. Look at t
ultimatedbz 2016/11/15 18:04:02 Right, I'm thinking that if a newState is availabl
164 this.panStrategy_.setDisplaySize(parseInt(
165 localStorage['virtualBrailleRows'], 10),
166 parseInt(localStorage['virtualBrailleColumns'], 10));
174 } 167 }
175 this.refresh_(); 168 this.refresh_();
176 }; 169 };
177 170
178 171
179 /** 172 /**
180 * Called when the state of braille captions changes. 173 * Called when the state of braille captions changes.
181 * @private 174 * @private
182 */ 175 */
183 cvox.BrailleDisplayManager.prototype.onCaptionsStateChanged_ = function() { 176 cvox.BrailleDisplayManager.prototype.onCaptionsStateChanged_ = function() {
184 // Force reevaluation of the display state based on our stored real 177 // Force reevaluation of the display state based on our stored real
185 // hardware display state, meaning that if a real display is connected, 178 // hardware display state, meaning that if a real display is connected,
186 // that takes precedence over the state from the captions 'virtual' display. 179 // that takes precedence over the state from the captions 'virtual' display.
187 this.refreshDisplayState_(this.realDisplayState_); 180 this.refreshDisplayState_(this.realDisplayState_);
188 }; 181 };
189 182
190 183
191 /** @private */ 184 /**
185 * Refreshes what is shown on the physical braille display and the virtual
186 * braille captions display.
187 * @private */
192 cvox.BrailleDisplayManager.prototype.refresh_ = function() { 188 cvox.BrailleDisplayManager.prototype.refresh_ = function() {
193 if (!this.displayState_.available) { 189 if (!this.displayState_.available) {
194 return; 190 return;
195 } 191 }
196 var viewPort = this.panStrategy_.viewPort; 192 var brailleBuf = this.panStrategy_.getCurrentBrailleSlice();
197 var buf = this.displayedContent_.slice(viewPort.start, viewPort.end); 193 var textBuf = this.panStrategy_.getCurrentTextSlice();
198 if (this.realDisplayState_.available) { 194 if (this.realDisplayState_.available) {
199 chrome.brailleDisplayPrivate.writeDots(buf, buf.byteLength, 1); 195 chrome.brailleDisplayPrivate.writeDots(brailleBuf,
196 brailleBuf.byteLength, 1);
200 } 197 }
201 if (cvox.BrailleCaptionsBackground.isEnabled()) { 198 if (cvox.BrailleCaptionsBackground.isEnabled()) {
202 var start = this.brailleToTextPosition_(viewPort.start); 199 cvox.BrailleCaptionsBackground.setContent(textBuf, brailleBuf,
203 var end = this.brailleToTextPosition_(viewPort.end); 200 this.panStrategy_.brailleToText, this.panStrategy_.offsetsForSlices);
204 cvox.BrailleCaptionsBackground.setContent(
205 this.content_.text.toString().substring(start, end), buf,
206 this.brailleToText_);
207 } 201 }
208 }; 202 };
209 203
210
211 /** 204 /**
212 * @param {!cvox.NavBraille} newContent New display content. 205 * @param {!cvox.NavBraille} newContent New display content.
213 * @param {cvox.ExpandingBrailleTranslator.ExpansionType} newExpansionType 206 * @param {cvox.ExpandingBrailleTranslator.ExpansionType} newExpansionType
214 * How the value part of of the new content should be expanded 207 * How the value part of of the new content should be expanded
215 * with regards to contractions. 208 * with regards to contractions.
216 * @private 209 * @private
217 */ 210 */
218 cvox.BrailleDisplayManager.prototype.translateContent_ = function( 211 cvox.BrailleDisplayManager.prototype.translateContent_ = function(
219 newContent, newExpansionType) { 212 newContent, newExpansionType) {
220 var writeTranslatedContent = function(cells, textToBraille, brailleToText) { 213 var writeTranslatedContent = function(cells, textToBraille, brailleToText) {
221 this.content_ = newContent; 214 this.content_ = newContent;
222 this.expansionType_ = newExpansionType; 215 this.expansionType_ = newExpansionType;
223 this.textToBraille_ = textToBraille;
224 this.brailleToText_ = brailleToText;
225 var startIndex = this.content_.startIndex; 216 var startIndex = this.content_.startIndex;
226 var endIndex = this.content_.endIndex; 217 var endIndex = this.content_.endIndex;
227 var targetPosition; 218 var targetPosition;
228 if (startIndex >= 0) { 219 if (startIndex >= 0) {
229 var translatedStartIndex; 220 var translatedStartIndex;
230 var translatedEndIndex; 221 var translatedEndIndex;
231 if (startIndex >= textToBraille.length) { 222 if (startIndex >= textToBraille.length) {
232 // Allow the cells to be extended with one extra cell for 223 // Allow the cells to be extended with one extra cell for
233 // a carret after the last character. 224 // a carret after the last character.
234 var extCells = new ArrayBuffer(cells.byteLength + 1); 225 var extCells = new ArrayBuffer(cells.byteLength + 1);
235 new Uint8Array(extCells).set(new Uint8Array(cells)); 226 new Uint8Array(extCells).set(cells);
236 // Last byte is initialized to 0. 227 // Last byte is initialized to 0.
237 cells = extCells; 228 cells = extCells;
238 translatedStartIndex = cells.byteLength - 1; 229 translatedStartIndex = cells.byteLength - 1;
239 } else { 230 } else {
240 translatedStartIndex = textToBraille[startIndex]; 231 translatedStartIndex = textToBraille[startIndex];
241 } 232 }
242 if (endIndex >= textToBraille.length) { 233 if (endIndex >= textToBraille.length) {
243 // endIndex can't be past-the-end of the last cell unless 234 // endIndex can't be past-the-end of the last cell unless
244 // startIndex is too, so we don't have to do another 235 // startIndex is too, so we don't have to do another
245 // extension here. 236 // extension here.
246 translatedEndIndex = cells.byteLength; 237 translatedEndIndex = cells.byteLength;
247 } else { 238 } else {
248 translatedEndIndex = textToBraille[endIndex]; 239 translatedEndIndex = textToBraille[endIndex];
249 } 240 }
250 this.translatedContent_ = cells; 241 this.translatedContent_ = cells;
251 // Copy the translated content to a separate buffer and add the cursor 242 // Copy the translated content to a separate buffer and add the cursor
252 // to it. 243 // to it.
253 this.displayedContent_ = new ArrayBuffer(cells.byteLength); 244 this.displayedContent_ = new ArrayBuffer(cells.byteLength);
254 new Uint8Array(this.displayedContent_).set(new Uint8Array(cells)); 245 new Uint8Array(this.displayedContent_).set(cells);
255 this.writeCursor_(this.displayedContent_, 246 this.writeCursor_(this.displayedContent_,
256 translatedStartIndex, translatedEndIndex); 247 translatedStartIndex, translatedEndIndex);
257 targetPosition = translatedStartIndex; 248 targetPosition = translatedStartIndex;
258 } else { 249 } else {
259 this.translatedContent_ = this.displayedContent_ = cells; 250 this.translatedContent_ = this.displayedContent_ = cells;
260 targetPosition = 0; 251 targetPosition = 0;
261 } 252 }
262 this.panStrategy_.setContent(this.translatedContent_, targetPosition); 253 this.panStrategy_.setContent(this.content_.text.toString(),
254 this.translatedContent_, brailleToText);
255
263 this.refresh_(); 256 this.refresh_();
264 }.bind(this); 257 }.bind(this);
265 258
266 var translator = this.translatorManager_.getExpandingTranslator(); 259 var translator = this.translatorManager_.getExpandingTranslator();
267 if (!translator) { 260 if (!translator) {
268 writeTranslatedContent(new ArrayBuffer(0), [], []); 261 writeTranslatedContent(new ArrayBuffer(0), [], []);
269 } else { 262 } else {
270 translator.translate( 263 translator.translate(
271 newContent.text, 264 newContent.text,
272 newExpansionType, 265 newExpansionType,
273 writeTranslatedContent); 266 writeTranslatedContent);
274 } 267 }
275 }; 268 };
276 269
277 270
278 /** 271 /**
279 * @param {cvox.BrailleKeyEvent} event The key event. 272 * @param {cvox.BrailleKeyEvent} event The key event.
280 * @private 273 * @private
281 */ 274 */
282 cvox.BrailleDisplayManager.prototype.onKeyEvent_ = function(event) { 275 cvox.BrailleDisplayManager.prototype.onKeyEvent_ = function(event) {
283 switch (event.command) { 276 switch (event.command) {
284 case cvox.BrailleKeyCommand.PAN_LEFT: 277 case cvox.BrailleKeyCommand.PAN_LEFT:
285 this.panLeft_(); 278 this.panLeft_();
286 break; 279 break;
287 case cvox.BrailleKeyCommand.PAN_RIGHT: 280 case cvox.BrailleKeyCommand.PAN_RIGHT:
288 this.panRight_(); 281 this.panRight_();
289 break; 282 break;
290 case cvox.BrailleKeyCommand.ROUTING: 283 case cvox.BrailleKeyCommand.ROUTING:
284 /* TODO
291 event.displayPosition = this.brailleToTextPosition_( 285 event.displayPosition = this.brailleToTextPosition_(
292 event.displayPosition + this.panStrategy_.viewPort.start); 286 event.displayPosition + this.panStrategy_.viewPort.start);
293 // fall through 287 // fall through
288 // */
David Tseng 2016/11/14 21:05:08 Please don't comment out code like this with a TOD
ultimatedbz 2016/11/15 00:01:17 Hey David! Noted, my intentions weren't for this t
294 default: 289 default:
295 this.commandListener_(event, this.content_); 290 this.commandListener_(event, this.content_);
296 break; 291 break;
297 } 292 }
298 }; 293 };
299 294
300 295
301 /** 296 /**
302 * Shift the display by one full display size and refresh the content. 297 * 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 298 * 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 /** 356 /**
362 * Returns the text position corresponding to an absolute braille position, 357 * Returns the text position corresponding to an absolute braille position,
363 * that is not accounting for the current pan position. 358 * that is not accounting for the current pan position.
364 * @private 359 * @private
365 * @param {number} braillePosition Braille position relative to the startof 360 * @param {number} braillePosition Braille position relative to the startof
366 * the translated content. 361 * the translated content.
367 * @return {number} The mapped position in code units. 362 * @return {number} The mapped position in code units.
368 */ 363 */
369 cvox.BrailleDisplayManager.prototype.brailleToTextPosition_ = 364 cvox.BrailleDisplayManager.prototype.brailleToTextPosition_ =
370 function(braillePosition) { 365 function(braillePosition) {
371 var mapping = this.brailleToText_; 366 // TODO I'll need to support this function
367 var mapping = this.panStrategy_.brailleToText;
372 if (braillePosition < 0) { 368 if (braillePosition < 0) {
373 // This shouldn't happen. 369 // This shouldn't happen.
374 console.error('WARNING: Braille position < 0: ' + braillePosition); 370 console.error('WARNING: Braille position < 0: ' + braillePosition);
375 return 0; 371 return 0;
376 } else if (braillePosition >= mapping.length) { 372 } else if (braillePosition >= mapping.length) {
377 // This happens when the user clicks on the right part of the display 373 // 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 374 // when it is not entirely filled with content. Allow addressing the
379 // position after the last character. 375 // position after the last character.
380 return this.content_.text.length; 376 return this.content_.text.length;
381 } else { 377 } else {
382 return mapping[braillePosition]; 378 return mapping[braillePosition];
383 } 379 }
384 }; 380 };
385 381
386 382
387 /** 383 /**
388 * @param {boolean} wordWrap 384 * @param {boolean} wordWrap
389 * @private 385 * @private
390 */ 386 */
391 cvox.BrailleDisplayManager.prototype.updatePanStrategy_ = function(wordWrap) { 387 cvox.BrailleDisplayManager.prototype.updatePanStrategy_ = function(wordWrap) {
392 var newStrategy = wordWrap ? new cvox.WrappingPanStrategy() : 388 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_(); 389 this.refresh_();
399 }; 390 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698