openmct/platform/features/plot/src/PlotController.js
Victor Woeltjen bb708e9a05 [Plot] Separate out formatter
Separate out plot label formatter to simplify PlotController,
to simplify test and maintenance. WTD-533
2014-12-01 15:28:20 -08:00

228 lines
7.6 KiB
JavaScript

/*global define,moment,Promise*/
/**
* Module defining PlotController. Created by vwoeltje on 11/12/14.
*/
define(
[
"./PlotPreparer",
"./PlotPalette",
"./PlotPanZoomStack",
"./PlotPosition",
"./PlotTickGenerator",
"./PlotFormatter"
],
function (PlotPreparer, PlotPalette, PlotPanZoomStack, PlotPosition, PlotTickGenerator, PlotFormatter) {
"use strict";
var AXIS_DEFAULTS = [
{ "name": "Time" },
{ "name": "Value" }
],
DOMAIN_TICKS = 5,
RANGE_TICKS = 7;
/**
*
* @constructor
*/
function PlotController($scope) {
var mousePosition,
marqueeStart,
panZoomStack = new PlotPanZoomStack([], []),
formatter = new PlotFormatter(),
domainOffset;
// Utility, for map/forEach loops. Index 0 is domain,
// index 1 is range.
function formatValue(v, i) {
return (i ?
formatter.formatRangeValue :
formatter.formatDomainValue)(v);
}
function mousePositionToDomainRange(mousePosition, domainOffset) {
return new PlotPosition(
mousePosition.x,
mousePosition.y,
mousePosition.width,
mousePosition.height,
panZoomStack,
domainOffset
).getPosition();
}
function updateMarqueeBox() {
$scope.draw.boxes = marqueeStart ?
[{
start: mousePositionToDomainRange(marqueeStart),
end: mousePositionToDomainRange(mousePosition),
color: [1, 1, 1, 0.5 ]
}] : undefined;
}
function updateDrawingBounds() {
var panZoom = panZoomStack.getPanZoom();
$scope.draw.dimensions = panZoom.dimensions;
$scope.draw.origin = panZoom.origin;
}
function plotTelemetry() {
var telemetry, prepared, tickGenerator, data;
telemetry = $scope.telemetry;
if (!telemetry) {
return;
}
data = telemetry.getResponse();
prepared = new PlotPreparer(
data,
($scope.axes[0].active || {}).key,
($scope.axes[1].active || {}).key
);
tickGenerator = new PlotTickGenerator(prepared, formatter);
$scope.axes[0].ticks =
tickGenerator.generateDomainTicks(DOMAIN_TICKS);
$scope.axes[1].ticks =
tickGenerator.generateRangeTicks(RANGE_TICKS);
panZoomStack.setBasePanZoom(
prepared.getOrigin(),
prepared.getDimensions()
);
domainOffset = prepared.getDomainOffset();
$scope.draw.lines = prepared.getBuffers().map(function (buf, i) {
return {
buffer: buf,
color: PlotPalette.getFloatColor(i),
points: buf.length / 2
};
});
updateDrawingBounds();
updateMarqueeBox();
}
function setupAxes(metadatas) {
var domainKeys = {},
rangeKeys = {},
domains = [],
ranges = [];
function buildOptionsForMetadata(m) {
(m.domains || []).forEach(function (domain) {
if (!domainKeys[domain.key]) {
domainKeys[domain.key] = true;
domains.push(domain);
}
});
(m.ranges || []).forEach(function (range) {
if (!rangeKeys[range.key]) {
rangeKeys[range.key] = true;
ranges.push(range);
}
});
}
(metadatas || []).
forEach(buildOptionsForMetadata);
[domains, ranges].forEach(function (options, i) {
var active = $scope.axes[i].active;
$scope.axes[i].options = options;
if (!active || !active.key) {
$scope.axes[i].active =
options[0] || AXIS_DEFAULTS[i];
}
});
}
function toMousePosition($event) {
var target = $event.target,
bounds = target.getBoundingClientRect();
return {
x: $event.clientX - bounds.left,
y: $event.clientY - bounds.top,
width: bounds.width,
height: bounds.height
};
}
function marqueeZoom(start, end) {
var a = mousePositionToDomainRange(start),
b = mousePositionToDomainRange(end),
origin = [
Math.min(a[0], b[0]),
Math.min(a[1], b[1])
],
dimensions = [
Math.max(a[0], b[0]) - origin[0],
Math.max(a[1], b[1]) - origin[1]
];
panZoomStack.pushPanZoom(origin, dimensions);
}
$scope.axes = [ {}, {} ];
$scope.$watch("telemetry.getMetadata()", setupAxes);
$scope.$on("telemetryUpdate", plotTelemetry);
$scope.draw = {};
return {
getColor: function (index) {
return PlotPalette.getStringColor(index);
},
getHoverCoordinates: function () {
return mousePosition ?
mousePositionToDomainRange(
mousePosition,
domainOffset
).map(formatValue) : [];
},
hover: function ($event) {
mousePosition = toMousePosition($event);
if (marqueeStart) {
updateMarqueeBox();
}
},
startMarquee: function ($event) {
mousePosition = marqueeStart = toMousePosition($event);
updateMarqueeBox();
},
endMarquee: function ($event) {
mousePosition = toMousePosition($event);
if (marqueeStart) {
marqueeZoom(marqueeStart, mousePosition);
marqueeStart = undefined;
updateMarqueeBox();
updateDrawingBounds();
}
},
isZoomed: function () {
return panZoomStack.getDepth() > 1;
},
stepBackPanZoom: function () {
panZoomStack.popPanZoom();
updateDrawingBounds();
},
unzoom: function () {
panZoomStack.clearPanZoom();
updateDrawingBounds();
}
};
}
return PlotController;
}
);