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

Side by Side Diff: chrome/browser/resources/chromeos/chromevox/cvox2/background/panel_menu.js

Issue 2443103004: Defer creating ChromeVox node menus to make menus open more quickly. (Closed)
Patch Set: Call finish from all codepaths 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
« no previous file with comments | « chrome/browser/resources/chromeos/chromevox/cvox2/background/panel.js ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 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 A drop-down menu in the ChromeVox panel. 6 * @fileoverview A drop-down menu in the ChromeVox panel.
7 */ 7 */
8 8
9 goog.provide('PanelMenu'); 9 goog.provide('PanelMenu');
10 goog.provide('PanelNodeMenu'); 10 goog.provide('PanelNodeMenu');
11 11
12 goog.require('AutomationTreeWalker');
12 goog.require('Output'); 13 goog.require('Output');
13 goog.require('PanelMenuItem'); 14 goog.require('PanelMenuItem');
14 goog.require('constants'); 15 goog.require('constants');
15 goog.require('cursors.Range'); 16 goog.require('cursors.Range');
16 17
17 /** 18 /**
18 * @param {string} menuMsg The msg id of the menu. 19 * @param {string} menuMsg The msg id of the menu.
19 * @constructor 20 * @constructor
20 */ 21 */
21 PanelMenu = function(menuMsg) { 22 PanelMenu = function(menuMsg) {
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after
222 break; 223 break;
223 } 224 }
224 } 225 }
225 } 226 }
226 }; 227 };
227 228
228 /** 229 /**
229 * @param {string} menuMsg The msg id of the menu. 230 * @param {string} menuMsg The msg id of the menu.
230 * @param {chrome.automation.AutomationNode} node ChromeVox's current position. 231 * @param {chrome.automation.AutomationNode} node ChromeVox's current position.
231 * @param {AutomationPredicate.Unary} pred Filter to use on the document. 232 * @param {AutomationPredicate.Unary} pred Filter to use on the document.
233 * @param {boolean} async If true, populates the menu asynchronously by
234 * posting a task after searching each chunk of nodes.
232 * @extends {PanelMenu} 235 * @extends {PanelMenu}
233 * @constructor 236 * @constructor
234 */ 237 */
235 PanelNodeMenu = function(menuMsg, node, pred) { 238 PanelNodeMenu = function(menuMsg, node, pred, async) {
236 PanelMenu.call(this, menuMsg); 239 PanelMenu.call(this, menuMsg);
237 var nodes = []; 240 this.node_ = node;
238 var selectNext = false; 241 this.pred_ = pred;
239 var activeIndex = -1; 242 this.async_ = async;
240 AutomationUtil.findNodePre(node.root, constants.Dir.FORWARD, 243 this.populate_();
241 /** @type {AutomationPredicate.Unary} */(function(n) { 244 };
242 if (n === node)
243 selectNext = true;
244 245
245 if (pred(n)) { 246 /**
246 var output = new Output(); 247 * The number of nodes to search before posting a task to finish
247 var range = cursors.Range.fromNode(n); 248 * searching.
248 output.withSpeech(range, range, Output.EventType.NAVIGATE); 249 * @const {number}
249 var label = output.toString(); 250 */
250 this.addMenuItem(label, '', function() { 251 PanelNodeMenu.MAX_NODES_BEFORE_ASYNC = 100;
251 chrome.extension.getBackgroundPage().ChromeVoxState
252 .instance['navigateToRange'](cursors.Range.fromNode(n));
253 });
254 if (selectNext) {
255 activeIndex = this.items_.length - 1;
256 selectNext = false;
257 }
258 }
259 }).bind(this)
260 );
261
262 if (!this.items_.length) {
263 this.addMenuItem(
264 Msgs.getMsg('panel_menu_item_none'), '', function() {});
265 this.activateItem(0);
266 }
267 if (activeIndex >= 0)
268 this.activateItem(activeIndex);
269 };
270 252
271 PanelNodeMenu.prototype = { 253 PanelNodeMenu.prototype = {
272 __proto__: PanelMenu.prototype, 254 __proto__: PanelMenu.prototype,
273 255
274 /** @override */ 256 /** @override */
275 activate: function() { 257 activate: function() {
276 var activeItem = this.activeIndex_; 258 var activeItem = this.activeIndex_;
277 PanelMenu.prototype.activate.call(this); 259 PanelMenu.prototype.activate.call(this);
278 this.activateItem(activeItem); 260 this.activateItem(activeItem);
261 },
262
263 /**
264 * Create the AutomationTreeWalker and kick off the search to find
265 * nodes that match the predicate for this menu.
266 * @private
267 */
268 populate_: function() {
269 if (!this.node_) {
270 this.finish_();
271 return;
272 }
273
274 var root = AutomationUtil.getTopLevelRoot(this.node_);
275 if (!root) {
276 this.finish_();
277 return;
278 }
279
280 this.walker_ = new AutomationTreeWalker(
281 root,
282 constants.Dir.FORWARD,
283 {visit: function(node) {
284 return !AutomationPredicate.shouldIgnoreNode(node);
285 }});
286 this.nodeCount_ = 0;
287 this.selectNext_ = false;
288 this.findMoreNodes_();
289 },
290
291 /**
292 * Iterate over nodes from the tree walker. If a node matches the
293 * predicate, add an item to the menu.
294 *
295 * If |this.async_| is true, then after MAX_NODES_BEFORE_ASYNC nodes
296 * have been scanned, call setTimeout to defer searching. This frees
297 * up the main event loop to keep the panel menu responsive, otherwise
298 * it basically freezes up until all of the nodes have been found.
299 * @private
300 */
301 findMoreNodes_: function() {
302 while (this.walker_.next().node) {
303 var node = this.walker_.node;
304 if (node == this.node_)
305 this.selectNext_ = true;
306 if (this.pred_(node)) {
307 var output = new Output();
308 var range = cursors.Range.fromNode(node);
309 output.withSpeech(range, range, Output.EventType.NAVIGATE);
310 var label = output.toString();
311 this.addMenuItem(label, '', function() {
312 chrome.extension.getBackgroundPage().ChromeVoxState
313 .instance['navigateToRange'](cursors.Range.fromNode(node));
314 });
315 if (this.selectNext_) {
316 this.activateItem(this.items_.length - 1);
317 this.selectNext_ = false;
318 }
319 }
320
321 if (this.async_) {
322 this.nodeCount_++;
323 if (this.nodeCount_ >= PanelNodeMenu.MAX_NODES_BEFORE_ASYNC) {
324 this.nodeCount_ = 0;
325 window.setTimeout(this.findMoreNodes_.bind(this), 0);
326 return;
327 }
328 }
329 }
330 this.finish_();
331 },
332
333 /**
334 * Called when we've finished searching for nodes. If no matches were
335 * found, adds an item to the menu indicating none were found.
336 * @private
337 */
338 finish_: function() {
339 if (!this.items_.length) {
340 this.addMenuItem(
341 Msgs.getMsg('panel_menu_item_none'), '', function() {});
342 this.activateItem(0);
343 }
279 } 344 }
280 }; 345 };
OLDNEW
« no previous file with comments | « chrome/browser/resources/chromeos/chromevox/cvox2/background/panel.js ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698