1424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
2424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// found in the LICENSE file.
4424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
5424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)/**
6424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) * This is a view class showing tree-menu.
758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) * @param {Object} profiler Must have addListener method.
8424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) * @construct
9424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) */
1058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)var MenuView = function(profiler) {
1158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  this.profiler_ = profiler;
1258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  this.placeholder_ = '#category-menu';
1358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
1458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Update graph view and menu view when profiler model changed.
1558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  profiler.addListener('changed', this.redraw_.bind(this));
1658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  profiler.addListener('changed:selected', this.selectNode_.bind(this));
1758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)};
1858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
1958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)/**
2058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) * Highlight the node being selected.
211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) * @param {string|null} id Model id.
221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) * @param {Object} pos Clicked position. Not used
2358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) * @private
2458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) */
2558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)MenuView.prototype.selectNode_ = function(id) {
2658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  var $tree = this.$tree_;
271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (id == null) {
291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    $tree.tree('selectNode', null);
301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return;
311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
3358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  var node = $tree.tree('getNodeById', id);
3458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  $tree.tree('selectNode', node);
35424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)};
36424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
37424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)/**
38424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) * Update menu view when model updated.
3958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) * @param {Array.<Object>} models
4058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) * @private
41424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) */
4258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)MenuView.prototype.redraw_ = function(models) {
43424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  function convert(origin, target) {
44424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    target.label = origin.name;
4558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    target.id = origin.id;
46424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
47424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    if ('children' in origin) {
48424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      target.children = [];
49424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      origin.children.forEach(function(originChild) {
50424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        var targetChild = {};
51424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        target.children.push(targetChild);
52424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        convert(originChild, targetChild);
53424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      });
54424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    }
55424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
56424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  function merge(origin, target) {
581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (!('children' in origin))
591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      return;
601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (!('children' in target)) {
611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      target.children = origin.children;
62424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      return;
63424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    }
641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    origin.children.forEach(function(child) {
661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      // Find child with the same label in target tree.
671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      var index = target.children.reduce(function(previous, current, index) {
681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        if (child.label === current.label)
691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        return index;
701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        return previous;
711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      }, -1);
721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      if (index === -1)
731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        target.children.push(child);
741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      else
751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        merge(child, target.children[index]);
761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    });
7758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
7858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
7958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  var self = this;
80424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
81424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Merge trees in all snapshots.
82424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  var union = null;
8358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  models.forEach(function(model) {
8458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    var data = {};
8558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    convert(model, data);
86424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    if (!union)
8758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      union = data;
88424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    else
891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      merge(data, union);
90424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  });
91424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
92424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Draw breakdown menu.
9358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  var data = [union];
9458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (!this.$tree_) {
9558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    this.$tree_ = $(this.placeholder_).tree({
9658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      data: data,
9758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      autoOpen: true,
9858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      onCreateLi: function(node, $li) {
9958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        // TODO(junjianx): Add checkbox to decide the breakdown visibility.
10058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      }
10158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    });
10258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
1031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // Delegate events
10458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    this.$tree_.bind('tree.click', function(event) {
10558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      event.preventDefault();
10658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      self.profiler_.setSelected(event.node.id);
10758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    });
1081e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    this.$tree_.bind('tree.close', function(event) {
1091e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      event.preventDefault();
1101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      self.profiler_.unsetSub(event.node.id);
1111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      self.profiler_.setSelected(event.node.id);
1121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    });
11358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  } else {
11458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    this.$tree_.tree('loadData', data);
11558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
116424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)};
117