diff --git a/platform/features/plot/src/PlotController.js b/platform/features/plot/src/PlotController.js index 2aef3e3418..75339b2133 100644 --- a/platform/features/plot/src/PlotController.js +++ b/platform/features/plot/src/PlotController.js @@ -83,10 +83,9 @@ define( // Populate the scope with axis information (specifically, options // available for each axis.) function setupAxes(metadatas) { - $scope.axes = [ - new PlotAxis("domain", metadatas, AXIS_DEFAULTS[0]), - new PlotAxis("range", metadatas, AXIS_DEFAULTS[1]) - ]; + $scope.axes.forEach(function (axis) { + axis.updateMetadata(metadatas); + }); } // Trigger an update of a specific subplot; @@ -142,6 +141,7 @@ define( self.pending = false; if (handle) { setupModes(handle.getTelemetryObjects()); + setupAxes(handle.getMetadata()); } if (updater) { updater.update(); @@ -168,6 +168,15 @@ define( } } + // Requery for data entirely + function replot() { + if (handle) { + recreateUpdater(); + requestTelemetry(); + } + } + + // Create a new subscription; telemetrySubscriber gets // to do the meaningful work here. function subscribe(domainObject) { @@ -197,11 +206,15 @@ define( // Respond to a display bounds change (requery for data) function changeDisplayBounds(event, bounds) { + var domainAxis = $scope.axes[0]; + domainAxis.chooseOption(bounds.domain); + plotTelemetryFormatter + .setDomainFormat(domainAxis.active.format); + self.pending = true; releaseSubscription(); subscribe($scope.domainObject); setBasePanZoom(bounds); - $scope.axes[0].choose(bounds.domain); } function updateDomainFormat(format) { @@ -219,6 +232,17 @@ define( self.pending = true; + // Initialize axes; will get repopulated when telemetry + // metadata becomes available. + $scope.axes = [ + new PlotAxis("domain", [], AXIS_DEFAULTS[0]), + new PlotAxis("range", [], AXIS_DEFAULTS[1]) + ]; + + // Request new data whenever domain selection changes; + // ordering and bounding of data may change. + $scope.$watch("axes[0].active.key", replot); + // Subscribe to telemetry when a domain object becomes available $scope.$watch('domainObject', subscribe); diff --git a/platform/features/plot/src/elements/PlotAxis.js b/platform/features/plot/src/elements/PlotAxis.js index cee7acef8a..127e52f9c0 100644 --- a/platform/features/plot/src/elements/PlotAxis.js +++ b/platform/features/plot/src/elements/PlotAxis.js @@ -46,21 +46,9 @@ define( * */ function PlotAxis(axisType, metadatas, defaultValue) { - var keys = {}, - options = []; - - // Look through all metadata objects and assemble a list - // of all possible domain or range options - function buildOptionsForMetadata(m) { - (m[axisType] || []).forEach(function (option) { - if (!keys[option.key]) { - keys[option.key] = true; - options.push(option); - } - }); - } - - (metadatas || []).forEach(buildOptionsForMetadata); + this.axisType = axisType; + this.defaultValue = defaultValue; + this.optionKeys = {}; /** * The currently chosen option for this axis. An @@ -68,7 +56,7 @@ define( * directly form the plot template. * @memberof platform/features/plot.PlotAxis# */ - this.active = options[0] || defaultValue; + this.active = defaultValue; /** * The set of options applicable for this axis; @@ -77,17 +65,62 @@ define( * human-readable names respectively) * @memberof platform/features/plot.PlotAxis# */ - this.options = options; + this.options = []; + + // Initialize options from metadata objects + this.updateMetadata(metadatas); } - PlotAxis.prototype.choose = function (key) { - var i; - for (i = 0; i < this.options.length; i += 1) { - if (this.options[i].key === key) { - this.active = this.options[i]; - return; - } + + /** + * Update axis options to reflect current metadata. + * @memberof platform/features/plot.PlotAxis + */ + PlotAxis.prototype.updateMetadata = function (metadatas) { + var axisType = this.axisType, + optionKeys = this.optionKeys, + newOptions = {}, + toAdd = []; + + function isValid(option) { + return option && optionKeys[option.key]; } + + metadatas.forEach(function (m) { + (m[axisType + 's'] || []).forEach(function (option) { + var key = option.key; + if (!optionKeys[key] && !newOptions[key]) { + toAdd.push(option); + } + newOptions[option.key] = true; + }); + }); + + optionKeys = this.optionKeys = newOptions; + + // General approach here is to avoid changing object + // instances unless something has really changed, since + // Angular is watching; don't want to trigger extra digests. + if (!this.options.every(isValid)) { + this.options = this.options.filter(isValid); + } + + if (toAdd.length > 0) { + this.options = this.options.concat(toAdd); + } + + if (!isValid(this.active)) { + this.active = this.options[0] || this.defaultValue; + } + }; + + PlotAxis.prototype.chooseOption = function (key) { + var self = this; + this.options.forEach(function (option) { + if (option.key === key) { + self.active = option; + } + }); }; return PlotAxis;