| OLD | NEW |
| (Empty) |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 /** | |
| 6 * This is a view class showing tree-menu. | |
| 7 * @param {Object} profiler Must have addListener method. | |
| 8 * @construct | |
| 9 */ | |
| 10 var MenuView = function(profiler) { | |
| 11 this.profiler_ = profiler; | |
| 12 this.placeholder_ = '#category-menu'; | |
| 13 | |
| 14 // Update graph view and menu view when profiler model changed. | |
| 15 profiler.addListener('changed', this.redraw_.bind(this)); | |
| 16 profiler.addListener('changed:selected', this.selectNode_.bind(this)); | |
| 17 }; | |
| 18 | |
| 19 /** | |
| 20 * Highlight the node being selected. | |
| 21 * @param {string} id Model id. | |
| 22 * @private | |
| 23 */ | |
| 24 MenuView.prototype.selectNode_ = function(id) { | |
| 25 var $tree = this.$tree_; | |
| 26 var node = $tree.tree('getNodeById', id); | |
| 27 $tree.tree('selectNode', node); | |
| 28 $tree.tree('scrollToNode', node); | |
| 29 }; | |
| 30 | |
| 31 /** | |
| 32 * Update menu view when model updated. | |
| 33 * @param {Array.<Object>} models | |
| 34 * @private | |
| 35 */ | |
| 36 MenuView.prototype.redraw_ = function(models) { | |
| 37 function convert(origin, target) { | |
| 38 target.label = origin.name; | |
| 39 target.id = origin.id; | |
| 40 | |
| 41 if ('children' in origin) { | |
| 42 target.children = []; | |
| 43 origin.children.forEach(function(originChild) { | |
| 44 var targetChild = {}; | |
| 45 target.children.push(targetChild); | |
| 46 convert(originChild, targetChild); | |
| 47 }); | |
| 48 } | |
| 49 } | |
| 50 | |
| 51 function merge(left, right) { | |
| 52 if (!('children' in right) && 'children' in left) | |
| 53 return; | |
| 54 if ('children' in right && !('children' in left)) | |
| 55 left.children = right.children; | |
| 56 if ('children' in right && 'children' in left) { | |
| 57 right.children.forEach(function(child) { | |
| 58 // Find child with the same label in right tree. | |
| 59 var index = left.children.reduce(function(previous, current, index) { | |
| 60 if (child.label === current.label) | |
| 61 return index; | |
| 62 return previous; | |
| 63 }, -1); | |
| 64 if (index === -1) | |
| 65 left.children.push(child); | |
| 66 else | |
| 67 merge(child, left.children[index]); | |
| 68 }); | |
| 69 } | |
| 70 } | |
| 71 | |
| 72 var self = this; | |
| 73 | |
| 74 // Merge trees in all snapshots. | |
| 75 var union = null; | |
| 76 models.forEach(function(model) { | |
| 77 var data = {}; | |
| 78 convert(model, data); | |
| 79 if (!union) | |
| 80 union = data; | |
| 81 else | |
| 82 merge(union, data); | |
| 83 }); | |
| 84 | |
| 85 // Draw breakdown menu. | |
| 86 var data = [union]; | |
| 87 if (!this.$tree_) { | |
| 88 this.$tree_ = $(this.placeholder_).tree({ | |
| 89 data: data, | |
| 90 autoOpen: true, | |
| 91 onCreateLi: function(node, $li) { | |
| 92 // TODO(junjianx): Add checkbox to decide the breakdown visibility. | |
| 93 } | |
| 94 }); | |
| 95 | |
| 96 // Delegate click event to profiler. | |
| 97 this.$tree_.bind('tree.click', function(event) { | |
| 98 event.preventDefault(); | |
| 99 self.profiler_.setSelected(event.node.id); | |
| 100 }); | |
| 101 } else { | |
| 102 this.$tree_.tree('loadData', data); | |
| 103 } | |
| 104 }; | |
| OLD | NEW |