Removed bundle definition of MctAxisController

Documenting code
This commit is contained in:
Henry 2016-10-24 15:13:45 -07:00
parent a942541724
commit 93735bc404
16 changed files with 232 additions and 137 deletions

View File

@ -95,8 +95,15 @@ define([
})[0][0];
}
/**
* Returns a description of the current range of the time conductor's
* bounds.
* @param timeRange
* @returns {*}
*/
UTCTimeFormat.prototype.timeUnits = function (timeRange) {
var momentified = moment.duration(timeRange);
return [
["Decades", function (r) {
return r.years() > 15;

View File

@ -73,15 +73,6 @@ define([
"formatService"
]
},
{
"key": "ConductorAxisController",
"implementation": ConductorAxisController,
"depends": [
"openmct",
"formatService",
"timeConductorViewService"
]
},
{
"key": "ConductorTOIController",
"implementation": ConductorTOIController,

View File

@ -1,15 +0,0 @@
<a class="l-page-button s-icon-button icon-pointer-left"></a>
<div class="l-data-visualization">
<!-- Note:
- val-to-right should be applied when l-toi-holder left < 160px
-->
<div class="l-toi-holder"
ng-class="{ 'pinned': true, 'val-to-right': false }"
ng-click="this.pinned = false"
style="left: 70%">
<div class="l-toi">
<div class="l-toi-val">2016-09-15 21:31:30.000Z</div>
</div>
</div>
</div>
<a class="l-page-button align-right s-icon-button icon-pointer-right"></a>

View File

@ -120,8 +120,8 @@
class="time-conductor-zoom-current-range flex-elem flex-fixed holder">{{timeUnits}}</span>
<input class="time-conductor-zoom flex-elem" type="range"
ng-model="tcController.currentZoom"
ng-mouseUp="tcController.zoomStop(tcController.currentZoom)"
ng-change="tcController.zoomDrag(tcController.currentZoom)"
ng-mouseUp="tcController.onZoomStop(tcController.currentZoom)"
ng-change="tcController.onZoom(tcController.currentZoom)"
min="0.01"
step="0.01"
max="0.99" />

View File

@ -32,20 +32,15 @@ define(
* labelled 'ticks'. It requires 'start' and 'end' integer values to
* be specified as attributes.
*/
function ConductorAxisController(openmct, formatService, conductorViewService) {
function ConductorAxisController(openmct, formatService, conductorViewService, scope, element) {
// Dependencies
this.d3 = d3;
this.formatService = formatService;
this.conductor = openmct.conductor;
this.conductorViewService = conductorViewService;
// Runtime properties (set by 'link' function)
this.target = undefined;
this.xScale = undefined;
this.xAxis = undefined;
this.axisElement = undefined;
this.scope = scope;
this.initialized = false;
this.msPerPixel = undefined;
this.bounds = this.conductor.bounds();
this.timeSystem = this.conductor.timeSystem();
@ -56,6 +51,8 @@ define(
}).forEach(function (key) {
this[key] = ConductorAxisController.prototype[key].bind(this);
}.bind(this));
this.initialize(element);
}
ConductorAxisController.prototype.destroy = function () {
@ -65,70 +62,18 @@ define(
this.conductorViewService.off("zoom-stop", this.onZoomStop)
};
ConductorAxisController.prototype.changeBounds = function (bounds) {
this.bounds = bounds;
if (this.initialized && !this.zooming) {
this.setScale();
}
};
ConductorAxisController.prototype.setScale = function () {
var width = this.target.offsetWidth;
var timeSystem = this.conductor.timeSystem();
var bounds = this.bounds;
if (timeSystem.isUTCBased()) {
this.xScale = this.xScale || this.d3.scaleUtc();
this.xScale.domain([new Date(bounds.start), new Date(bounds.end)]);
} else {
this.xScale = this.xScale || this.d3.scaleLinear();
this.xScale.domain([bounds.start, bounds.end]);
}
this.xScale.range([PADDING, width - PADDING * 2]);
this.axisElement.call(this.xAxis);
this.msPerPixel = (bounds.end - bounds.start) / width;
};
ConductorAxisController.prototype.changeTimeSystem = function (timeSystem) {
this.timeSystem = timeSystem;
var key = timeSystem.formats()[0];
if (this.initialized && key !== undefined) {
var format = this.formatService.getFormat(key);
var bounds = this.conductor.bounds();
if (timeSystem.isUTCBased()) {
this.xScale = this.d3.scaleUtc();
} else {
this.xScale = this.d3.scaleLinear();
}
this.xAxis.scale(this.xScale);
//Define a custom format function
this.xAxis.tickFormat(function (tickValue) {
// Normalize date representations to numbers
if (tickValue instanceof Date) {
tickValue = tickValue.getTime();
}
return format.format(tickValue, {
min: bounds.start,
max: bounds.end
});
});
this.axisElement.call(this.xAxis);
}
};
ConductorAxisController.prototype.link = function (scope, element) {
/**
* Set defaults, and apply d3 axis to the
* @param scope
* @param element
*/
ConductorAxisController.prototype.initialize = function (element) {
this.target = element[0].firstChild;
this.scope = scope;
var height = this.target.offsetHeight;
var vis = this.d3.select(this.target)
.append("svg:svg")
.attr("width", "100%")
.attr("height", height);
.append("svg:svg")
.attr("width", "100%")
.attr("height", height);
this.xAxis = this.d3.axisTop();
@ -153,6 +98,73 @@ define(
this.conductorViewService.on("zoom-stop", this.onZoomStop);
};
ConductorAxisController.prototype.changeBounds = function (bounds) {
this.bounds = bounds;
if (this.initialized && !this.zooming) {
this.setScale();
}
};
/**
* Set the scale of the axis, based on current conductor bounds.
*/
ConductorAxisController.prototype.setScale = function () {
var width = this.target.offsetWidth;
var timeSystem = this.conductor.timeSystem();
var bounds = this.bounds;
if (timeSystem.isUTCBased()) {
this.xScale = this.xScale || this.d3.scaleUtc();
this.xScale.domain([new Date(bounds.start), new Date(bounds.end)]);
} else {
this.xScale = this.xScale || this.d3.scaleLinear();
this.xScale.domain([bounds.start, bounds.end]);
}
this.xScale.range([PADDING, width - PADDING * 2]);
this.axisElement.call(this.xAxis);
this.msPerPixel = (bounds.end - bounds.start) / width;
};
/**
* When the time system changes, update the scale and formatter used
* for showing times.
* @param timeSystem
*/
ConductorAxisController.prototype.changeTimeSystem = function (timeSystem) {
this.timeSystem = timeSystem;
var key = timeSystem.formats()[0];
if (this.initialized && key !== undefined) {
var format = this.formatService.getFormat(key);
var bounds = this.conductor.bounds();
//The D3 scale used depends on the type of time system as d3
// supports UTC out of the box.
if (timeSystem.isUTCBased()) {
this.xScale = this.d3.scaleUtc();
} else {
this.xScale = this.d3.scaleLinear();
}
this.xAxis.scale(this.xScale);
//Define a custom format function
this.xAxis.tickFormat(function (tickValue) {
// Normalize date representations to numbers
if (tickValue instanceof Date) {
tickValue = tickValue.getTime();
}
return format.format(tickValue, {
min: bounds.start,
max: bounds.end
});
});
this.axisElement.call(this.xAxis);
}
};
ConductorAxisController.prototype.panStop = function () {
//resync view bounds with time conductor bounds
this.conductorViewService.emit("pan-stop");
@ -170,6 +182,12 @@ define(
this.zooming = false;
};
/**
* Initiate panning via a click + drag gesture on the time conductor
* scale. Panning triggers a "pan" event
* @param {number} delta the offset from the original click event
* @see TimeConductorViewService#
*/
ConductorAxisController.prototype.pan = function (delta) {
if (!this.conductor.follow()) {
var deltaInMs = delta[0] * this.msPerPixel;

View File

@ -59,6 +59,14 @@ define(
this.conductorViewService.off('pan', this.setOffsetFromBounds);
};
/**
* Given some bounds, set horizontal position of TOI indicator based
* on current conductor TOI value. Bounds are provided so that
* ephemeral bounds from zoom and pan events can be used as well
* as current conductor bounds, allowing TOI to be updated in
* realtime during scroll and zoom.
* @param {TimeConductorBounds} bounds
*/
ConductorTOIController.prototype.setOffsetFromBounds = function (bounds) {
var toi = this.conductor.timeOfInterest();
if (toi !== undefined) {
@ -79,7 +87,12 @@ define(
}
};
/**
* Set time of interest
* @param e The angular $event object
*/
ConductorTOIController.prototype.click = function (e) {
//TOI is set using the alt key modified + primary click
if (e.altKey) {
var element = $(e.currentTarget);
var width = element.width();

View File

@ -20,7 +20,7 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
define([], function () {
define(['./ConductorAxisController'], function (ConductorAxisController) {
function MctConductorAxis() {
/**
@ -30,11 +30,15 @@ define([], function () {
*/
return {
controller: 'ConductorAxisController',
controller: [
'openmct',
'formatService',
'timeConductorViewService',
'$scope',
'$element',
ConductorAxisController
],
controllerAs: 'axis',
link: function(scope, element, attrs, controller){
controller.link(scope, element);
},
restrict: 'E',
priority: 1000,

View File

@ -114,34 +114,39 @@ define(
this.conductorViewService.off('pan-stop', this.onPanStop);
};
TimeConductorController.prototype.onPan = function (bounds) {
this.panning = true;
this.$scope.boundsModel.start = bounds.start;
this.$scope.boundsModel.end = bounds.end;
};
TimeConductorController.prototype.onPanStop = function () {
this.panning = false;
};
TimeConductorController.prototype.changeBounds = function (bounds) {
if (!this.zooming && !this.panning) {
this.setFormFromBounds(bounds);
}
};
/**
* Does the currently selected time system support zooming? To
* support zooming a time system must, at a minimum, define some
* values for maximum and minimum zoom levels. Additionally
* TimeFormats, a related concept, may also support providing time
* unit feedback for the zoom level label, eg "seconds, minutes,
* hours, etc..."
* @returns {boolean}
*/
TimeConductorController.prototype.supportsZoom = function () {
var timeSystem = this.conductor.timeSystem();
return timeSystem &&
timeSystem.defaults() &&
timeSystem.defaults().zoom;
};
/**
* Called when the bounds change in the time conductor. Synchronizes
* the bounds values in the time conductor with those in the form
*
* @private
* @param {TimeConductorBounds}
*/
TimeConductorController.prototype.setFormFromBounds = function (bounds) {
if (!this.zooming && ! this.panning) {
this.$scope.boundsModel.start = bounds.start;
this.$scope.boundsModel.end = bounds.end;
if (this.supportsZoom) {
if (this.supportsZoom()) {
this.currentZoom = this.toSliderValue(bounds.end - bounds.start);
this.toTimeUnits(bounds.end - bounds.start);
}
@ -157,7 +162,9 @@ define(
};
/**
* @private
* On mode change, populate form based on time systems available
* from the selected mode.
* @param mode
*/
TimeConductorController.prototype.setFormFromMode = function (mode) {
this.$scope.modeModel.selectedKey = mode;
@ -169,25 +176,22 @@ define(
});
};
/**
* @private
*/
TimeConductorController.prototype.setFormFromDeltas = function (deltas) {
this.$scope.boundsModel.startDelta = deltas.start;
this.$scope.boundsModel.endDelta = deltas.end;
};
/**
* @private
* Initialize the form when time system changes.
* @param timeSystem
*/
TimeConductorController.prototype.setFormFromTimeSystem = function (timeSystem) {
var timeSystemModel = this.$scope.timeSystemModel;
timeSystemModel.selected = timeSystem;
timeSystemModel.format = timeSystem.formats()[0];
timeSystemModel.deltaFormat = timeSystem.deltaFormat();
this.supportsZoom = timeSystem.defaults().zoom !== undefined;
if (this.supportsZoom) {
if (this.supportsZoom()) {
timeSystemModel.minZoom = timeSystem.defaults().zoom.min;
timeSystemModel.maxZoom = timeSystem.defaults().zoom.max;
}
@ -261,7 +265,6 @@ define(
* Sets the selected time system. Will populate form with the default
* bounds and deltas defined in the selected time system.
*
* @private
* @param newTimeSystem
*/
TimeConductorController.prototype.changeTimeSystem = function (newTimeSystem) {
@ -277,6 +280,12 @@ define(
}
};
/**
* Takes a time span and calculates a slider increment value, used
* to set the horizontal offset of the slider.
* @param {number} timeSpan a duration of time, in ms
* @returns {number} a value between 0.01 and 0.99, in increments of .01
*/
TimeConductorController.prototype.toSliderValue = function (timeSpan) {
var timeSystem = this.conductor.timeSystem();
if (timeSystem) {
@ -286,6 +295,11 @@ define(
}
};
/**
* Given a time span, set a label for the units of time that it,
* roughly, represents. Leverages
* @param {TimeSpan} timeSpan
*/
TimeConductorController.prototype.toTimeUnits = function (timeSpan) {
if (this.conductor.timeSystem()) {
var timeFormat = this.formatService.getFormat(this.conductor.timeSystem().formats()[0]);
@ -293,7 +307,14 @@ define(
}
};
TimeConductorController.prototype.zoomDrag = function(sliderValue) {
/**
* Zooming occurs when the user manipulates the zoom slider.
* Zooming updates the scale and bounds fields immediately, but does
* not trigger a bounds change to other views until the mouse button
* is released.
* @param bounds
*/
TimeConductorController.prototype.onZoom = function(sliderValue) {
var zoomDefaults = this.conductor.timeSystem().defaults().zoom;
var timeSpan = Math.pow((1 - sliderValue), 4) * (zoomDefaults.min - zoomDefaults.max);
@ -309,7 +330,7 @@ define(
}
};
TimeConductorController.prototype.zoomStop = function () {
TimeConductorController.prototype.onZoomStop = function () {
this.updateBoundsFromForm(this.$scope.boundsModel);
this.updateDeltasFromForm(this.$scope.boundsModel);
this.zooming = false;
@ -317,6 +338,24 @@ define(
this.conductorViewService.emit('zoom-stop');
};
/**
* Panning occurs when the user grabs the conductor scale and drags
* it left or right to slide the window of time represented by the
* conductor. Panning updates the scale and bounds fields
* immediately, but does not trigger a bounds change to other views
* until the mouse button is released.
* @param bounds
*/
TimeConductorController.prototype.onPan = function (bounds) {
this.panning = true;
this.$scope.boundsModel.start = bounds.start;
this.$scope.boundsModel.end = bounds.end;
};
TimeConductorController.prototype.onPanStop = function () {
this.panning = false;
};
return TimeConductorController;
}
);

View File

@ -186,6 +186,11 @@ define(
return this.dlts;
};
/**
*
* @param deltas
* @returns {TimeConductorBounds}
*/
TimeConductorMode.prototype.calculateBoundsFromDeltas = function (deltas) {
var oldEnd = this.conductor.bounds().end;
@ -202,9 +207,9 @@ define(
};
/**
* Performs zoom calculation. Will calculate new bounds and deltas
* based on desired timeSpan
* @param timeSpan
* Calculates bounds and deltas based on a timeSpan. Collectively
* the bounds and deltas will constitute the new zoom level.
* @param {number} timeSpan time duration in ms.
*/
TimeConductorMode.prototype.calculateZoom = function (timeSpan) {
var zoom = {};

View File

@ -32,6 +32,7 @@ define(
* exposes details of the UI that are not represented on the
* TimeConductor API itself such as modes and deltas.
*
* @memberof platform.features.conductor
* @param conductor
* @param timeSystems
* @constructor
@ -203,6 +204,15 @@ define(
return this.currentMode.availableTimeSystems();
};
/**
* Zoom to given time span. Will fire a zoom event with new zoom
* bounds. Zoom bounds emitted in this way are considered ephemeral
* and should be overridden by any time conductor bounds events. Does
* not set bounds globally.
* @param {number} zoom A time duration in ms
* @fires platform.features.conductor.TimeConductorViewService~zoom
* @see module:openmct.TimeConductor#bounds
*/
TimeConductorViewService.prototype.zoom = function (timeSpan) {
var zoom = this.currentMode.calculateZoom(timeSpan);
this.emit("zoom", zoom);

View File

@ -65,6 +65,10 @@ define(
}
};
/**
* When time system is changed, update the formatter used to
* display the current TOI label
*/
TimeOfInterestController.prototype.changeTimeSystem = function (timeSystem) {
this.format = this.formatService.getFormat(timeSystem.formats()[0]);
};
@ -78,6 +82,10 @@ define(
this.conductor.timeOfInterest(undefined);
};
/**
* Sends out a time of interest event with the effect of resetting
* the TOI displayed in views.
*/
TimeOfInterestController.prototype.resync = function () {
this.conductor.timeOfInterest(this.conductor.timeOfInterest());
};

View File

@ -195,6 +195,9 @@ define(
true // Lossless
);
replot();
changeTimeOfInterest(conductor.timeOfInterest());
conductor.on("timeOfInterest", changeTimeOfInterest);
}
// Release the current subscription (called when scope is destroyed)
@ -280,10 +283,6 @@ define(
new PlotAxis("ranges", [], AXIS_DEFAULTS[1])
];
changeTimeOfInterest(conductor.timeOfInterest());
conductor.on("timeOfInterest", changeTimeOfInterest);
// Watch for changes to the selected axis
$scope.$watch("axes[0].active.key", domainRequery);
$scope.$watch("axes[1].active.key", rangeRequery);

View File

@ -98,6 +98,10 @@ define(
$scope.$on('add:row', this.addRow);
$scope.$on('remove:row', this.removeRow);
/**
* Populated from the default-sort attribute on MctTable
* directive tag.
*/
$scope.$watch('defaultSort', function (defaultSort) {
$scope.sortColumn = defaultSort;
$scope.sortDirection = 'asc';
@ -108,7 +112,11 @@ define(
*/
$scope.resize = this.setElementSizes;
// Time conductor integration
/**
* Scope variable that is populated from the 'time-columns'
* attribute on the MctTable tag. Indicates which columns, while
* sorted, can be used for indicated time of interest.
*/
$scope.$watch("timeColumns", function (timeColumns){
if (timeColumns) {
this.destroyConductorListeners();
@ -208,6 +216,7 @@ define(
};
/**
* Return first visible row, based on current scroll state.
* @private
*/
MCTTableController.prototype.firstVisible = function () {
@ -228,6 +237,7 @@ define(
};
/**
* Return last visible row, based on current scroll state.
* @private
*/
MCTTableController.prototype.lastVisible = function () {
@ -550,8 +560,11 @@ define(
this.$scope.displayRows = this.filterAndSort(newRows || []);
this.resize(newRows).then(this.setVisibleRows)
//Timeout following setVisibleRows to allow digest to
// perform DOM changes, otherwise scrollTo won't work.
.then(this.$timeout)
.then(function() {
//If TOI specified, scroll to it
var timeOfInterest = this.conductor.timeOfInterest();
if (timeOfInterest) {
this.setTimeOfInterest(timeOfInterest);

View File

@ -77,6 +77,11 @@ define(
this.conductor.off('timeSystem', this.sortByTimeSystem);
}
/**
* Based on the selected time system, find a matching domain column
* to sort by. By default will just match on key.
* @param timeSystem
*/
TelemetryTableController.prototype.sortByTimeSystem = function (timeSystem) {
var scope = this.$scope;
scope.defaultSort = undefined;
@ -89,9 +94,6 @@ define(
}
};
/**
* @private
*/
TelemetryTableController.prototype.unregisterChangeListeners = function () {
this.changeListeners.forEach(function (listener) {
return listener && listener();

View File

@ -97,7 +97,12 @@ define(
enableFilter: "=?",
enableSort: "=?",
autoScroll: "=?",
// Used to indicate which columns contain time data. This
// will be used for determining when the table is sorted
// by the column that can be used for time conductor
// time of interest.
timeColumns: "=?",
// Indicate the column that should be sorted on by default
defaultSort: "=?"
}
};

View File

@ -54,10 +54,6 @@ define(['EventEmitter'], function (EventEmitter) {
TimeConductor.prototype = Object.create(EventEmitter.prototype);
TimeConductor.prototype.on = function (event) {
EventEmitter.prototype.on.apply(this, arguments);
};
/**
* Validate the given bounds. This can be used for pre-validation of
* bounds, for example by views validating user inputs.