blob: 5a4b226fa4ebdad8d607273599737c2c99a84300 [file] [log] [blame]
<!DOCTYPE html>
<!--
Copyright (c) 2015 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.
-->
<link rel="import" href="/base/event_target.html">
<link rel="import" href="/base/task.html">
<link rel="import" href="/core/selection.html">
<link rel="import" href="/core/brushing_state.html">
<link rel="import" href="/core/timeline_viewport.html">
<link rel="import" href="/core/ui_state.html">
<link rel="import" href="/model/selection_state.html">
<script>
'use strict';
tr.exportTo('tr.c', function() {
var BrushingState = tr.c.BrushingState;
var Selection = tr.c.Selection;
var SelectionState = tr.model.SelectionState;
var Viewport = tr.c.TimelineViewport;
function SelectionController(timelineView) {
tr.b.EventTarget.call(this);
this.timelineView_ = timelineView;
this.currentBrushingState_ = new BrushingState();
this.onPopState_ = this.onPopState_.bind(this);
this.historyEnabled_ = false;
this.selections_ = {};
}
SelectionController.prototype = {
__proto__: tr.b.EventTarget.prototype,
dispatchChangeEvent_: function() {
var e = new tr.b.Event('change', false, false);
this.dispatchEvent(e);
},
get model() {
if (!this.timelineView_)
return undefined;
return this.timelineView_.model;
},
get trackView() {
if (!this.timelineView_)
return undefined;
return this.timelineView_.trackView;
},
get viewport() {
if (!this.timelineView_)
return undefined;
if (!this.timelineView_.trackView)
return undefined;
return this.timelineView_.trackView.viewport;
},
/* History system */
get historyEnabled() {
return this.historyEnabled_;
},
set historyEnabled(historyEnabled) {
this.historyEnabled_ = !!historyEnabled;
if (historyEnabled)
window.addEventListener('popstate', this.onPopState_);
else
window.removeEventListener('popstate', this.onPopState_);
},
modelWillChange: function() {
if (this.currentBrushingState_.isAppliedToModel)
this.currentBrushingState_.unapplyFromModelSelectionState();
},
modelDidChange: function() {
this.selections_ = {};
this.currentBrushingState_.applyToModelSelectionState(this.model);
var e = new tr.b.Event('model-changed', false, false);
this.dispatchEvent(e);
},
onUserInitiatedSelectionChange_: function() {
var selection = this.selection;
if (this.historyEnabled) {
// Save the selection so that when back button is pressed,
// it could be retrieved.
this.selections_[selection.guid] = selection;
var state = {
selection_guid: selection.guid
};
window.history.pushState(state, document.title);
}
},
onPopState_: function(e) {
if (e.state === null)
return;
var selection = this.selections_[e.state.selection_guid];
if (selection) {
var newState = this.currentBrushingState_.clone();
newState.selection = selection;
this.currentBrushingState = newState;
}
e.stopPropagation();
},
get selection() {
return this.currentBrushingState_.selection;
},
get findMatches() {
return this.currentBrushingState_.findMatches;
},
get selectionOfInterest() {
return this.currentBrushingState_.selectionOfInterest;
},
get currentBrushingState() {
return this.currentBrushingState_;
},
set currentBrushingState(newBrushingState) {
if (newBrushingState.isAppliedToModel)
throw new Error('Cannot apply this state, it is applied');
// This function uses value-equality on the states so that state can
// changed to a clone of itself without causing a change event, while
// still having the actual state object change to the new clone.
var hasValueChanged = !this.currentBrushingState_.equals(
newBrushingState);
if (newBrushingState !== this.currentBrushingState_ &&
hasValueChanged == false) {
this.currentBrushingState_.transferModelOwnershipToClone(
newBrushingState);
this.currentBrushingState_ = newBrushingState;
return;
}
if (this.currentBrushingState_.isAppliedToModel)
this.currentBrushingState_.unapplyFromModelSelectionState();
this.currentBrushingState_ = newBrushingState;
if (this.model)
this.currentBrushingState_.applyToModelSelectionState(this.model);
this.dispatchChangeEvent_();
},
/**
* @param {Filter} filter The filter to use for finding matches.
* @param {Selection} selection The selection to add matches to.
* @return {Task} which performs the filtering.
*/
addAllEventsMatchingFilterToSelectionAsTask: function(filter, selection) {
var timelineView = this.timelineView_.trackView;
if (!timelineView)
return new tr.b.Task();
return timelineView.addAllEventsMatchingFilterToSelectionAsTask(
filter, selection);
},
findTextChangedTo: function(allPossibleMatches) {
var newBrushingState = this.currentBrushingState_.clone();
newBrushingState.findMatches = allPossibleMatches;
this.currentBrushingState = newBrushingState;
},
findFocusChangedTo: function(currentFocus) {
var newBrushingState = this.currentBrushingState_.clone();
newBrushingState.selection = currentFocus;
this.currentBrushingState = newBrushingState;
this.onUserInitiatedSelectionChange_();
},
findTextCleared: function() {
if (this.xNavStringMarker_ !== undefined) {
this.model.removeAnnotation(this.xNavStringMarker_);
this.xNavStringMarker_ = undefined;
}
if (this.guideLineAnnotation_ !== undefined) {
this.model.removeAnnotation(this.guideLineAnnotation_);
this.guideLineAnnotation_ = undefined;
}
var newBrushingState = this.currentBrushingState_.clone();
newBrushingState.selection = new Selection();
newBrushingState.findMatches = new Selection();
this.currentBrushingState = newBrushingState;
this.onUserInitiatedSelectionChange_();
},
uiStateFromString: function(string) {
return tr.c.UIState.fromUserFriendlyString(
this.model, this.viewport, string);
},
navToPosition: function(uiState, showNavLine) {
this.trackView.navToPosition(uiState, showNavLine);
},
changeSelectionFromTimeline: function(selection) {
var newBrushingState = this.currentBrushingState_.clone();
newBrushingState.selection = selection;
newBrushingState.findMatches = new Selection();
this.currentBrushingState = newBrushingState;
this.onUserInitiatedSelectionChange_();
},
showScriptControlSelection: function(selection) {
var newBrushingState = this.currentBrushingState_.clone();
newBrushingState.selection = selection;
newBrushingState.findMatches = new Selection();
this.currentBrushingState = newBrushingState;
},
changeSelectionFromRequestSelectionChangeEvent: function(selection) {
var newBrushingState = this.currentBrushingState_.clone();
newBrushingState.selection = selection;
newBrushingState.findMatches = new Selection();
this.currentBrushingState = newBrushingState;
this.onUserInitiatedSelectionChange_();
},
changeAnalysisViewRelatedEvents: function(selection) {
var newBrushingState = this.currentBrushingState_.clone();
newBrushingState.analysisViewRelatedEvents = selection;
this.currentBrushingState = newBrushingState;
}
};
return {
SelectionController: SelectionController
};
});
</script>