// Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. /** * This is a view class showing tree-menu. * @param {Object} profiler Must have addListener method. * @construct */ var MenuView = function(profiler) { this.profiler_ = profiler; this.placeholder_ = '#category-menu'; // Update graph view and menu view when profiler model changed. profiler.addListener('changed', this.redraw_.bind(this)); profiler.addListener('changed:selected', this.selectNode_.bind(this)); }; /** * Highlight the node being selected. * @param {string} id Model id. * @private */ MenuView.prototype.selectNode_ = function(id) { var $tree = this.$tree_; var node = $tree.tree('getNodeById', id); $tree.tree('selectNode', node); $tree.tree('scrollToNode', node); }; /** * Update menu view when model updated. * @param {Array.<Object>} models * @private */ MenuView.prototype.redraw_ = function(models) { function convert(origin, target) { target.label = origin.name; target.id = origin.id; if ('children' in origin) { target.children = []; origin.children.forEach(function(originChild) { var targetChild = {}; target.children.push(targetChild); convert(originChild, targetChild); }); } } function merge(left, right) { if (!('children' in right) && 'children' in left) return; if ('children' in right && !('children' in left)) left.children = right.children; if ('children' in right && 'children' in left) { right.children.forEach(function(child) { // Find child with the same label in right tree. var index = left.children.reduce(function(previous, current, index) { if (child.label === current.label) return index; return previous; }, -1); if (index === -1) left.children.push(child); else merge(child, left.children[index]); }); } } var self = this; // Merge trees in all snapshots. var union = null; models.forEach(function(model) { var data = {}; convert(model, data); if (!union) union = data; else merge(union, data); }); // Draw breakdown menu. var data = [union]; if (!this.$tree_) { this.$tree_ = $(this.placeholder_).tree({ data: data, autoOpen: true, onCreateLi: function(node, $li) { // TODO(junjianx): Add checkbox to decide the breakdown visibility. } }); // Delegate click event to profiler. this.$tree_.bind('tree.click', function(event) { event.preventDefault(); self.profiler_.setSelected(event.node.id); }); } else { this.$tree_.tree('loadData', data); } };