// Copyright (c) 2012 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.
'use strict';
/**
* @fileoverview FindControl and FindController.
*/
base.require('tracing.timeline_track_view');
base.require('tracing.filter');
base.require('ui.overlay');
base.exportTo('tracing', function() {
/**
* FindControl
* @constructor
* @extends {ui.Overlay}
*/
var FindControl = ui.define('div');
FindControl.prototype = {
__proto__: ui.Overlay.prototype,
decorate: function() {
ui.Overlay.prototype.decorate.call(this);
this.className = 'find-control';
this.hitCountEl_ = document.createElement('div');
this.hitCountEl_.className = 'hit-count-label';
this.hitCountEl_.textContent = '1 of 7';
var findPreviousBn = document.createElement('div');
findPreviousBn.className = 'button find-previous';
findPreviousBn.textContent = '\u2190';
findPreviousBn.addEventListener('click', this.findPrevious_.bind(this));
var findNextBn = document.createElement('div');
findNextBn.className = 'button find-next';
findNextBn.textContent = '\u2192';
findNextBn.addEventListener('click', this.findNext_.bind(this));
// Filter input element.
this.filterEl_ = document.createElement('input');
this.filterEl_.type = 'input';
this.filterEl_.addEventListener('input',
this.filterTextChanged_.bind(this));
this.filterEl_.addEventListener('keydown', function(e) {
if (e.keyCode == 13) {
if (e.shiftKey)
this.findPrevious_();
else
this.findNext_();
} else if (e.keyCode == 27) {
this.filterEl_.blur();
this.updateHitCountEl_();
}
}.bind(this));
this.filterEl_.addEventListener('blur', function(e) {
this.updateHitCountEl_();
}.bind(this));
this.filterEl_.addEventListener('focus', function(e) {
this.controller.reset();
this.filterTextChanged_();
this.filterEl_.select();
}.bind(this));
// Prevent that the input text is deselected after focusing the find
// control with the mouse.
this.filterEl_.addEventListener('mouseup', function(e) {
e.preventDefault();
});
// Attach everything.
this.appendChild(this.filterEl_);
this.appendChild(findPreviousBn);
this.appendChild(findNextBn);
this.appendChild(this.hitCountEl_);
this.updateHitCountEl_();
},
get controller() {
return this.controller_;
},
set controller(c) {
this.controller_ = c;
this.updateHitCountEl_();
},
focus: function() {
this.filterEl_.focus();
},
filterTextChanged_: function() {
this.controller.filterText = this.filterEl_.value;
this.updateHitCountEl_();
},
findNext_: function() {
if (this.controller)
this.controller.findNext();
this.updateHitCountEl_();
},
findPrevious_: function() {
if (this.controller)
this.controller.findPrevious();
this.updateHitCountEl_();
},
updateHitCountEl_: function() {
if (!this.controller || document.activeElement != this.filterEl_) {
this.hitCountEl_.textContent = '';
return;
}
var i = this.controller.currentHitIndex;
var n = this.controller.filterHits.length;
if (n == 0)
this.hitCountEl_.textContent = '0 of 0';
else
this.hitCountEl_.textContent = (i + 1) + ' of ' + n;
}
};
function FindController() {
this.timeline_ = undefined;
this.model_ = undefined;
this.filterText_ = '';
this.filterHits_ = new tracing.Selection();
this.filterHitsDirty_ = true;
this.currentHitIndex_ = -1;
};
FindController.prototype = {
__proto__: Object.prototype,
get timeline() {
return this.timeline_;
},
set timeline(t) {
this.timeline_ = t;
this.filterHitsDirty_ = true;
},
get filterText() {
return this.filterText_;
},
set filterText(f) {
if (f == this.filterText_)
return;
this.filterText_ = f;
this.filterHitsDirty_ = true;
this.showHits_(this.filterHits);
},
get filterHits() {
if (this.filterHitsDirty_) {
this.filterHitsDirty_ = false;
this.filterHits_.clear();
this.currentHitIndex_ = -1;
if (this.timeline_ && this.filterText.length) {
var filter = new tracing.TitleFilter(this.filterText);
this.timeline.addAllObjectsMatchingFilterToSelection(
filter, this.filterHits_);
}
}
return this.filterHits_;
},
get currentHitIndex() {
return this.currentHitIndex_;
},
showHits_: function(selection, zoom, pan) {
if (!this.timeline)
return;
this.timeline.selection = selection;
if (zoom)
this.timeline.zoomToSelection();
else if (pan)
this.timeline.panToSelection();
},
find_: function(dir) {
var firstHit = this.currentHitIndex_ === -1;
if (firstHit && dir < 0)
this.currentHitIndex_ = 0;
var N = this.filterHits.length;
this.currentHitIndex_ = (this.currentHitIndex_ + dir + N) % N;
// We allow the zoom level to change only on the first hit. But, when
// then cycling through subsequent changes, restrict it to panning.
var zoom = firstHit;
var pan = true;
var subSelection = this.filterHits.subSelection(this.currentHitIndex_);
this.showHits_(subSelection, zoom, pan);
},
findNext: function() {
this.find_(1);
},
findPrevious: function() {
this.find_(-1);
},
reset: function() {
this.filterText_ = '';
this.filterHitsDirty_ = true;
}
};
return {
FindControl: FindControl,
FindController: FindController
};
});