mirror of
https://github.com/nasa/openmct.git
synced 2025-06-26 19:12:02 +00:00
Compare commits
5 Commits
expose-vue
...
time-api
Author | SHA1 | Date | |
---|---|---|---|
be476aff43 | |||
d62a3ca494 | |||
d77ea6c024 | |||
fae7cd69da | |||
80432710e0 |
@ -20,7 +20,7 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define(['../../../platform/features/conductor/core/src/timeSystems/LocalClock'], function (LocalClock) {
|
define(['../../../src/plugins/utcTimeSystem/LocalClock'], function (LocalClock) {
|
||||||
/**
|
/**
|
||||||
* @implements TickSource
|
* @implements TickSource
|
||||||
* @constructor
|
* @constructor
|
||||||
@ -28,14 +28,12 @@ define(['../../../platform/features/conductor/core/src/timeSystems/LocalClock'],
|
|||||||
function LADTickSource ($timeout, period) {
|
function LADTickSource ($timeout, period) {
|
||||||
LocalClock.call(this, $timeout, period);
|
LocalClock.call(this, $timeout, period);
|
||||||
|
|
||||||
this.metadata = {
|
this.key = 'test-lad';
|
||||||
key: 'test-lad',
|
this.mode = 'lad';
|
||||||
mode: 'lad',
|
this.cssClass = 'icon-clock';
|
||||||
cssClass: 'icon-clock',
|
this.label = 'Latest Available Data';
|
||||||
label: 'Latest Available Data',
|
this.name = 'Latest available data';
|
||||||
name: 'Latest available data',
|
this.description = 'Monitor real-time streaming data as it comes in. The Time Conductor and displays will automatically advance themselves based on a UTC clock.';
|
||||||
description: 'Monitor real-time streaming data as it comes in. The Time Conductor and displays will automatically advance themselves based on a UTC clock.'
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
LADTickSource.prototype = Object.create(LocalClock.prototype);
|
LADTickSource.prototype = Object.create(LocalClock.prototype);
|
||||||
|
|
||||||
|
@ -21,10 +21,9 @@
|
|||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define([
|
define([
|
||||||
'../../../platform/features/conductor/core/src/timeSystems/TimeSystem',
|
'../../../src/plugins/utcTimeSystem/LocalClock',
|
||||||
'../../../platform/features/conductor/core/src/timeSystems/LocalClock',
|
|
||||||
'./LADTickSource'
|
'./LADTickSource'
|
||||||
], function (TimeSystem, LocalClock, LADTickSource) {
|
], function (LocalClock, LADTickSource) {
|
||||||
var THIRTY_MINUTES = 30 * 60 * 1000,
|
var THIRTY_MINUTES = 30 * 60 * 1000,
|
||||||
DEFAULT_PERIOD = 1000;
|
DEFAULT_PERIOD = 1000;
|
||||||
|
|
||||||
@ -34,25 +33,20 @@ define([
|
|||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
function LocalTimeSystem ($timeout) {
|
function LocalTimeSystem ($timeout) {
|
||||||
TimeSystem.call(this);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Some metadata, which will be used to identify the time system in
|
* Some metadata, which will be used to identify the time system in
|
||||||
* the UI
|
* the UI
|
||||||
* @type {{key: string, name: string, glyph: string}}
|
* @type {{key: string, name: string, glyph: string}}
|
||||||
*/
|
*/
|
||||||
this.metadata = {
|
this.key = 'local';
|
||||||
'key': 'local',
|
this.name = 'Local';
|
||||||
'name': 'Local',
|
this.cssClass = '\u0043';
|
||||||
'glyph': '\u0043'
|
|
||||||
};
|
|
||||||
|
|
||||||
this.fmts = ['local-format'];
|
this.fmts = ['local-format'];
|
||||||
this.sources = [new LocalClock($timeout, DEFAULT_PERIOD), new LADTickSource($timeout, DEFAULT_PERIOD)];
|
this.sources = [new LocalClock($timeout, DEFAULT_PERIOD), new LADTickSource($timeout, DEFAULT_PERIOD)];
|
||||||
}
|
}
|
||||||
|
|
||||||
LocalTimeSystem.prototype = Object.create(TimeSystem.prototype);
|
|
||||||
|
|
||||||
LocalTimeSystem.prototype.formats = function () {
|
LocalTimeSystem.prototype.formats = function () {
|
||||||
return this.fmts;
|
return this.fmts;
|
||||||
};
|
};
|
||||||
@ -65,6 +59,10 @@ define([
|
|||||||
return this.sources;
|
return this.sources;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
LocalTimeSystem.prototype.isUTCBased = function () {
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
LocalTimeSystem.prototype.defaults = function (key) {
|
LocalTimeSystem.prototype.defaults = function (key) {
|
||||||
var now = Math.ceil(Date.now() / 1000) * 1000;
|
var now = Math.ceil(Date.now() / 1000) * 1000;
|
||||||
return {
|
return {
|
||||||
|
@ -84,11 +84,5 @@ define([
|
|||||||
return new Main().run(defaultRegistry);
|
return new Main().run(defaultRegistry);
|
||||||
});
|
});
|
||||||
|
|
||||||
// For now, install conductor by default
|
|
||||||
openmct.install(openmct.plugins.Conductor({
|
|
||||||
showConductor: false
|
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
return openmct;
|
return openmct;
|
||||||
});
|
});
|
||||||
|
@ -41,7 +41,7 @@ define(
|
|||||||
scope,
|
scope,
|
||||||
element
|
element
|
||||||
) {
|
) {
|
||||||
this.conductor = openmct.conductor;
|
this.timeAPI = openmct.time;
|
||||||
this.scope = scope;
|
this.scope = scope;
|
||||||
this.element = element;
|
this.element = element;
|
||||||
|
|
||||||
@ -51,24 +51,26 @@ define(
|
|||||||
}
|
}
|
||||||
|
|
||||||
ConductorRepresenter.prototype.boundsListener = function (bounds) {
|
ConductorRepresenter.prototype.boundsListener = function (bounds) {
|
||||||
|
var timeSystem = this.timeAPI.getTimeSystem(this.timeAPI.timeSystem());
|
||||||
this.scope.$broadcast('telemetry:display:bounds', {
|
this.scope.$broadcast('telemetry:display:bounds', {
|
||||||
start: bounds.start,
|
start: bounds.start,
|
||||||
end: bounds.end,
|
end: bounds.end,
|
||||||
domain: this.conductor.timeSystem().metadata.key
|
domain: timeSystem
|
||||||
}, this.conductor.follow());
|
}, this.timeAPI.follow());
|
||||||
};
|
};
|
||||||
|
|
||||||
ConductorRepresenter.prototype.timeSystemListener = function (timeSystem) {
|
ConductorRepresenter.prototype.timeSystemListener = function (key) {
|
||||||
var bounds = this.conductor.bounds();
|
var bounds = this.timeAPI.bounds();
|
||||||
|
var timeSystem = this.timeAPI.getTimeSystem(key);
|
||||||
this.scope.$broadcast('telemetry:display:bounds', {
|
this.scope.$broadcast('telemetry:display:bounds', {
|
||||||
start: bounds.start,
|
start: bounds.start,
|
||||||
end: bounds.end,
|
end: bounds.end,
|
||||||
domain: timeSystem.metadata.key
|
domain: timeSystem
|
||||||
}, this.conductor.follow());
|
}, this.timeAPI.follow());
|
||||||
};
|
};
|
||||||
|
|
||||||
ConductorRepresenter.prototype.followListener = function () {
|
ConductorRepresenter.prototype.followListener = function () {
|
||||||
this.boundsListener(this.conductor.bounds());
|
this.boundsListener(this.timeAPI.bounds());
|
||||||
};
|
};
|
||||||
|
|
||||||
// Handle a specific representation of a specific domain object
|
// Handle a specific representation of a specific domain object
|
||||||
@ -76,16 +78,16 @@ define(
|
|||||||
if (representation.key === 'browse-object') {
|
if (representation.key === 'browse-object') {
|
||||||
this.destroy();
|
this.destroy();
|
||||||
|
|
||||||
this.conductor.on("bounds", this.boundsListener);
|
this.timeAPI.on("bounds", this.boundsListener);
|
||||||
this.conductor.on("timeSystem", this.timeSystemListener);
|
this.timeAPI.on("timeSystem", this.timeSystemListener);
|
||||||
this.conductor.on("follow", this.followListener);
|
this.timeAPI.on("follow", this.followListener);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ConductorRepresenter.prototype.destroy = function destroy() {
|
ConductorRepresenter.prototype.destroy = function destroy() {
|
||||||
this.conductor.off("bounds", this.boundsListener);
|
this.timeAPI.off("bounds", this.boundsListener);
|
||||||
this.conductor.off("timeSystem", this.timeSystemListener);
|
this.timeAPI.off("timeSystem", this.timeSystemListener);
|
||||||
this.conductor.off("follow", this.followListener);
|
this.timeAPI.off("follow", this.followListener);
|
||||||
};
|
};
|
||||||
|
|
||||||
return ConductorRepresenter;
|
return ConductorRepresenter;
|
||||||
|
@ -71,8 +71,7 @@ define([
|
|||||||
"openmct",
|
"openmct",
|
||||||
"timeConductorViewService",
|
"timeConductorViewService",
|
||||||
"formatService",
|
"formatService",
|
||||||
"DEFAULT_TIMECONDUCTOR_MODE",
|
"CONDUCTOR_CONFIG"
|
||||||
"SHOW_TIMECONDUCTOR"
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -151,13 +150,6 @@ define([
|
|||||||
"link": "https://github.com/d3/d3/blob/master/LICENSE"
|
"link": "https://github.com/d3/d3/blob/master/LICENSE"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"constants": [
|
|
||||||
{
|
|
||||||
"key": "DEFAULT_TIMECONDUCTOR_MODE",
|
|
||||||
"value": "realtime",
|
|
||||||
"priority": "fallback"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"formats": [
|
"formats": [
|
||||||
{
|
{
|
||||||
"key": "number",
|
"key": "number",
|
||||||
|
@ -22,8 +22,8 @@
|
|||||||
<div class="contents">
|
<div class="contents">
|
||||||
<div class="pane left menu-items">
|
<div class="pane left menu-items">
|
||||||
<ul>
|
<ul>
|
||||||
<li ng-repeat="(key, metadata) in ngModel.options"
|
<li ng-repeat="metadata in ngModel.options"
|
||||||
ng-click="ngModel.selectedKey=key">
|
ng-click="ngModel.selected = metadata">
|
||||||
<a ng-mouseover="ngModel.activeMetadata = metadata"
|
<a ng-mouseover="ngModel.activeMetadata = metadata"
|
||||||
ng-mouseleave="ngModel.activeMetadata = undefined"
|
ng-mouseleave="ngModel.activeMetadata = undefined"
|
||||||
class="menu-item-a {{metadata.cssClass}}">
|
class="menu-item-a {{metadata.cssClass}}">
|
||||||
@ -33,8 +33,7 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="pane right menu-item-description">
|
<div class="pane right menu-item-description">
|
||||||
<div
|
<div class="desc-area ui-symbol icon type-icon {{ngModel.activeMetadata.cssClass}}"></div>
|
||||||
class="desc-area ui-symbol icon type-icon {{ngModel.activeMetadata.cssClass}}"></div>
|
|
||||||
<div class="desc-area title">
|
<div class="desc-area title">
|
||||||
{{ngModel.activeMetadata.name}}
|
{{ngModel.activeMetadata.name}}
|
||||||
</div>
|
</div>
|
||||||
|
@ -22,8 +22,7 @@
|
|||||||
<span ng-controller="ClickAwayController as modeController">
|
<span ng-controller="ClickAwayController as modeController">
|
||||||
<div class="s-menu-button"
|
<div class="s-menu-button"
|
||||||
ng-click="modeController.toggle()">
|
ng-click="modeController.toggle()">
|
||||||
<span class="title-label">{{ngModel.options[ngModel.selectedKey]
|
<span class="title-label">{{ngModel.selected.name}}</span>
|
||||||
.label}}</span>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="menu super-menu mini mode-selector-menu"
|
<div class="menu super-menu mini mode-selector-menu"
|
||||||
ng-show="modeController.isActive()">
|
ng-show="modeController.isActive()">
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<!-- Parent holder for time conductor. follow-mode | fixed-mode -->
|
<!-- Parent holder for time conductor. follow-mode | fixed-mode -->
|
||||||
<div ng-controller="TimeConductorController as tcController"
|
<div ng-controller="TimeConductorController as tcController"
|
||||||
class="holder grows flex-elem l-flex-row l-time-conductor {{modeModel.selectedKey}}-mode {{timeSystemModel.selected.metadata.key}}-time-system"
|
class="holder grows flex-elem l-flex-row l-time-conductor {{modeModel.selectedKey}}-mode {{timeSystemModel.selected.metadata.key}}-time-system"
|
||||||
ng-class="{'status-panning': tcController.panning}" ng-show="showTimeConductor">
|
ng-class="{'status-panning': tcController.panning}">
|
||||||
<div class="flex-elem holder time-conductor-icon">
|
<div class="flex-elem holder time-conductor-icon">
|
||||||
<div class="hand-little"></div>
|
<div class="hand-little"></div>
|
||||||
<div class="hand-big"></div>
|
<div class="hand-big"></div>
|
||||||
@ -99,14 +99,14 @@
|
|||||||
<div class="l-time-conductor-controls l-row-elem l-flex-row flex-elem">
|
<div class="l-time-conductor-controls l-row-elem l-flex-row flex-elem">
|
||||||
<mct-include
|
<mct-include
|
||||||
key="'mode-selector'"
|
key="'mode-selector'"
|
||||||
ng-model="modeModel"
|
ng-model="tcController.menu"
|
||||||
class="holder flex-elem menus-up mode-selector">
|
class="holder flex-elem menus-up mode-selector">
|
||||||
</mct-include>
|
</mct-include>
|
||||||
<mct-control
|
<mct-control
|
||||||
key="'menu-button'"
|
key="'menu-button'"
|
||||||
class="holder flex-elem menus-up time-system"
|
class="holder flex-elem menus-up time-system"
|
||||||
structure="{
|
structure="{
|
||||||
text: timeSystemModel.selected.metadata.name,
|
text: timeSystemModel.selected.name,
|
||||||
click: tcController.selectTimeSystemByKey,
|
click: tcController.selectTimeSystemByKey,
|
||||||
options: timeSystemModel.options
|
options: timeSystemModel.options
|
||||||
}">
|
}">
|
||||||
|
@ -1,47 +0,0 @@
|
|||||||
/*****************************************************************************
|
|
||||||
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
|
||||||
* as represented by the Administrator of the National Aeronautics and Space
|
|
||||||
* Administration. All rights reserved.
|
|
||||||
*
|
|
||||||
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
|
|
||||||
* "License"); you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
* License for the specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*
|
|
||||||
* Open MCT Web includes source code licensed under additional open source
|
|
||||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
|
||||||
* this source code distribution or the Licensing information page available
|
|
||||||
* at runtime from the About dialog for additional information.
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
define([], function () {
|
|
||||||
/**
|
|
||||||
* A tick source is an event generator such as a timing signal, or
|
|
||||||
* indicator of data availability, which can be used to advance the Time
|
|
||||||
* Conductor. Usage is simple, a listener registers a callback which is
|
|
||||||
* invoked when this source 'ticks'.
|
|
||||||
*
|
|
||||||
* @interface
|
|
||||||
* @constructor
|
|
||||||
*/
|
|
||||||
function TickSource() {
|
|
||||||
this.listeners = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param callback Function to be called when this tick source ticks.
|
|
||||||
* @returns an 'unlisten' function that will remove the callback from
|
|
||||||
* the registered listeners
|
|
||||||
*/
|
|
||||||
TickSource.prototype.listen = function (callback) {
|
|
||||||
throw new Error('Not implemented');
|
|
||||||
};
|
|
||||||
|
|
||||||
return TickSource;
|
|
||||||
});
|
|
@ -1,107 +0,0 @@
|
|||||||
/*****************************************************************************
|
|
||||||
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
|
||||||
* as represented by the Administrator of the National Aeronautics and Space
|
|
||||||
* Administration. All rights reserved.
|
|
||||||
*
|
|
||||||
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
|
|
||||||
* "License"); you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
* License for the specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*
|
|
||||||
* Open MCT Web includes source code licensed under additional open source
|
|
||||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
|
||||||
* this source code distribution or the Licensing information page available
|
|
||||||
* at runtime from the About dialog for additional information.
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
define([], function () {
|
|
||||||
/**
|
|
||||||
* @interface
|
|
||||||
* @constructor
|
|
||||||
*/
|
|
||||||
function TimeSystem() {
|
|
||||||
/**
|
|
||||||
* @typedef TimeSystemMetadata
|
|
||||||
* @property {string} key
|
|
||||||
* @property {string} name
|
|
||||||
* @property {string} description
|
|
||||||
*
|
|
||||||
* @type {TimeSystemMetadata}
|
|
||||||
*/
|
|
||||||
this.metadata = undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Time formats are defined as extensions. Time systems that implement
|
|
||||||
* this interface should provide an array of format keys supported by them.
|
|
||||||
*
|
|
||||||
* @returns {string[]} An array of time format keys
|
|
||||||
*/
|
|
||||||
TimeSystem.prototype.formats = function () {
|
|
||||||
throw new Error('Not implemented');
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef DeltaFormat
|
|
||||||
* @property {string} type the type of MctControl used to represent this
|
|
||||||
* field. Typically 'datetime-field' for UTC based dates, or 'textfield'
|
|
||||||
* otherwise
|
|
||||||
* @property {string} [format] An optional field specifying the
|
|
||||||
* Format to use for delta fields in this time system.
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* Specifies a format for deltas in this time system.
|
|
||||||
*
|
|
||||||
* @returns {DeltaFormat} a delta format specifier
|
|
||||||
*/
|
|
||||||
TimeSystem.prototype.deltaFormat = function () {
|
|
||||||
throw new Error('Not implemented');
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the tick sources supported by this time system. Tick sources
|
|
||||||
* are event generators that can be used to advance the time conductor
|
|
||||||
* @returns {TickSource[]} The tick sources supported by this time system.
|
|
||||||
*/
|
|
||||||
TimeSystem.prototype.tickSources = function () {
|
|
||||||
throw new Error('Not implemented');
|
|
||||||
};
|
|
||||||
|
|
||||||
/***
|
|
||||||
*
|
|
||||||
* @typedef {object} TimeConductorZoom
|
|
||||||
* @property {number} min The largest time span that the time
|
|
||||||
* conductor can display in this time system. ie. the span of the time
|
|
||||||
* conductor in its most zoomed out state.
|
|
||||||
* @property {number} max The smallest time span that the time
|
|
||||||
* conductor can display in this time system. ie. the span of the time
|
|
||||||
* conductor bounds in its most zoomed in state.
|
|
||||||
*
|
|
||||||
* @typedef {object} TimeSystemDefault
|
|
||||||
* @property {TimeConductorDeltas} deltas The deltas to apply by default
|
|
||||||
* when this time system is active. Applies to real-time modes only
|
|
||||||
* @property {TimeConductorBounds} bounds The bounds to apply by default
|
|
||||||
* when this time system is active
|
|
||||||
* @property {TimeConductorZoom} zoom Default min and max zoom levels
|
|
||||||
* @returns {TimeSystemDefault[]} At least one set of default values for
|
|
||||||
* this time system.
|
|
||||||
*/
|
|
||||||
TimeSystem.prototype.defaults = function () {
|
|
||||||
throw new Error('Not implemented');
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return {boolean}
|
|
||||||
*/
|
|
||||||
TimeSystem.prototype.isUTCBased = function () {
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
return TimeSystem;
|
|
||||||
});
|
|
@ -35,14 +35,14 @@ define(
|
|||||||
function ConductorAxisController(openmct, formatService, conductorViewService, scope, element) {
|
function ConductorAxisController(openmct, formatService, conductorViewService, scope, element) {
|
||||||
// Dependencies
|
// Dependencies
|
||||||
this.formatService = formatService;
|
this.formatService = formatService;
|
||||||
this.conductor = openmct.conductor;
|
this.timeAPI = openmct.time;
|
||||||
this.conductorViewService = conductorViewService;
|
this.conductorViewService = conductorViewService;
|
||||||
|
|
||||||
this.scope = scope;
|
this.scope = scope;
|
||||||
this.initialized = false;
|
this.initialized = false;
|
||||||
|
|
||||||
this.bounds = this.conductor.bounds();
|
this.bounds = this.timeAPI.bounds();
|
||||||
this.timeSystem = this.conductor.timeSystem();
|
this.timeSystem = this.timeAPI.timeSystem();
|
||||||
|
|
||||||
//Bind all class functions to 'this'
|
//Bind all class functions to 'this'
|
||||||
Object.keys(ConductorAxisController.prototype).filter(function (key) {
|
Object.keys(ConductorAxisController.prototype).filter(function (key) {
|
||||||
@ -58,8 +58,8 @@ define(
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
ConductorAxisController.prototype.destroy = function () {
|
ConductorAxisController.prototype.destroy = function () {
|
||||||
this.conductor.off('timeSystem', this.changeTimeSystem);
|
this.timeAPI.off('timeSystem', this.changeTimeSystem);
|
||||||
this.conductor.off('bounds', this.changeBounds);
|
this.timeAPI.off('bounds', this.changeBounds);
|
||||||
this.conductorViewService.off("zoom", this.onZoom);
|
this.conductorViewService.off("zoom", this.onZoom);
|
||||||
this.conductorViewService.off("zoom-stop", this.onZoomStop);
|
this.conductorViewService.off("zoom-stop", this.onZoomStop);
|
||||||
};
|
};
|
||||||
@ -87,8 +87,8 @@ define(
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Respond to changes in conductor
|
//Respond to changes in conductor
|
||||||
this.conductor.on("timeSystem", this.changeTimeSystem);
|
this.timeAPI.on("timeSystem", this.changeTimeSystem);
|
||||||
this.conductor.on("bounds", this.changeBounds);
|
this.timeAPI.on("bounds", this.changeBounds);
|
||||||
|
|
||||||
this.scope.$on("$destroy", this.destroy);
|
this.scope.$on("$destroy", this.destroy);
|
||||||
|
|
||||||
@ -111,7 +111,7 @@ define(
|
|||||||
*/
|
*/
|
||||||
ConductorAxisController.prototype.setScale = function () {
|
ConductorAxisController.prototype.setScale = function () {
|
||||||
var width = this.target.offsetWidth;
|
var width = this.target.offsetWidth;
|
||||||
var timeSystem = this.conductor.timeSystem();
|
var timeSystem = this.timeAPI.getTimeSystem(this.timeAPI.timeSystem());
|
||||||
var bounds = this.bounds;
|
var bounds = this.bounds;
|
||||||
|
|
||||||
if (timeSystem.isUTCBased()) {
|
if (timeSystem.isUTCBased()) {
|
||||||
@ -134,13 +134,15 @@ define(
|
|||||||
* When the time system changes, update the scale and formatter used for showing times.
|
* When the time system changes, update the scale and formatter used for showing times.
|
||||||
* @param timeSystem
|
* @param timeSystem
|
||||||
*/
|
*/
|
||||||
ConductorAxisController.prototype.changeTimeSystem = function (timeSystem) {
|
ConductorAxisController.prototype.changeTimeSystem = function (key) {
|
||||||
this.timeSystem = timeSystem;
|
var timeSystem = this.timeAPI.getTimeSystem(key);
|
||||||
|
|
||||||
|
this.timeSystem = key;
|
||||||
|
|
||||||
var key = timeSystem.formats()[0];
|
var key = timeSystem.formats()[0];
|
||||||
if (key !== undefined) {
|
if (key !== undefined) {
|
||||||
var format = this.formatService.getFormat(key);
|
var format = this.formatService.getFormat(key);
|
||||||
var bounds = this.conductor.bounds();
|
var bounds = this.timeAPI.bounds();
|
||||||
|
|
||||||
//The D3 scale used depends on the type of time system as d3
|
//The D3 scale used depends on the type of time system as d3
|
||||||
// supports UTC out of the box.
|
// supports UTC out of the box.
|
||||||
@ -178,7 +180,7 @@ define(
|
|||||||
ConductorAxisController.prototype.panStop = function () {
|
ConductorAxisController.prototype.panStop = function () {
|
||||||
//resync view bounds with time conductor bounds
|
//resync view bounds with time conductor bounds
|
||||||
this.conductorViewService.emit("pan-stop");
|
this.conductorViewService.emit("pan-stop");
|
||||||
this.conductor.bounds(this.bounds);
|
this.timeAPI.bounds(this.bounds);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -214,9 +216,9 @@ define(
|
|||||||
* @fires platform.features.conductor.ConductorAxisController~pan
|
* @fires platform.features.conductor.ConductorAxisController~pan
|
||||||
*/
|
*/
|
||||||
ConductorAxisController.prototype.pan = function (delta) {
|
ConductorAxisController.prototype.pan = function (delta) {
|
||||||
if (!this.conductor.follow()) {
|
if (!this.timeAPI.follow()) {
|
||||||
var deltaInMs = delta[0] * this.msPerPixel;
|
var deltaInMs = delta[0] * this.msPerPixel;
|
||||||
var bounds = this.conductor.bounds();
|
var bounds = this.timeAPI.bounds();
|
||||||
var start = Math.floor((bounds.start - deltaInMs) / 1000) * 1000;
|
var start = Math.floor((bounds.start - deltaInMs) / 1000) * 1000;
|
||||||
var end = Math.floor((bounds.end - deltaInMs) / 1000) * 1000;
|
var end = Math.floor((bounds.end - deltaInMs) / 1000) * 1000;
|
||||||
this.bounds = {
|
this.bounds = {
|
||||||
|
@ -30,7 +30,7 @@ define(
|
|||||||
* @memberof platform.features.conductor
|
* @memberof platform.features.conductor
|
||||||
*/
|
*/
|
||||||
function ConductorTOIController($scope, openmct, conductorViewService) {
|
function ConductorTOIController($scope, openmct, conductorViewService) {
|
||||||
this.conductor = openmct.conductor;
|
this.timeAPI = openmct.time;
|
||||||
this.conductorViewService = conductorViewService;
|
this.conductorViewService = conductorViewService;
|
||||||
|
|
||||||
//Bind all class functions to 'this'
|
//Bind all class functions to 'this'
|
||||||
@ -40,11 +40,11 @@ define(
|
|||||||
this[key] = ConductorTOIController.prototype[key].bind(this);
|
this[key] = ConductorTOIController.prototype[key].bind(this);
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
|
|
||||||
this.conductor.on('timeOfInterest', this.changeTimeOfInterest);
|
this.timeAPI.on('timeOfInterest', this.changeTimeOfInterest);
|
||||||
this.conductorViewService.on('zoom', this.setOffsetFromZoom);
|
this.conductorViewService.on('zoom', this.setOffsetFromZoom);
|
||||||
this.conductorViewService.on('pan', this.setOffsetFromBounds);
|
this.conductorViewService.on('pan', this.setOffsetFromBounds);
|
||||||
|
|
||||||
var timeOfInterest = this.conductor.timeOfInterest();
|
var timeOfInterest = this.timeAPI.timeOfInterest();
|
||||||
if (timeOfInterest) {
|
if (timeOfInterest) {
|
||||||
this.changeTimeOfInterest(timeOfInterest);
|
this.changeTimeOfInterest(timeOfInterest);
|
||||||
}
|
}
|
||||||
@ -56,7 +56,7 @@ define(
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
ConductorTOIController.prototype.destroy = function () {
|
ConductorTOIController.prototype.destroy = function () {
|
||||||
this.conductor.off('timeOfInterest', this.changeTimeOfInterest);
|
this.timeAPI.off('timeOfInterest', this.changeTimeOfInterest);
|
||||||
this.conductorViewService.off('zoom', this.setOffsetFromZoom);
|
this.conductorViewService.off('zoom', this.setOffsetFromZoom);
|
||||||
this.conductorViewService.off('pan', this.setOffsetFromBounds);
|
this.conductorViewService.off('pan', this.setOffsetFromBounds);
|
||||||
};
|
};
|
||||||
@ -70,7 +70,7 @@ define(
|
|||||||
* @param {TimeConductorBounds} bounds
|
* @param {TimeConductorBounds} bounds
|
||||||
*/
|
*/
|
||||||
ConductorTOIController.prototype.setOffsetFromBounds = function (bounds) {
|
ConductorTOIController.prototype.setOffsetFromBounds = function (bounds) {
|
||||||
var toi = this.conductor.timeOfInterest();
|
var toi = this.timeAPI.timeOfInterest();
|
||||||
if (toi !== undefined) {
|
if (toi !== undefined) {
|
||||||
var offset = toi - bounds.start;
|
var offset = toi - bounds.start;
|
||||||
var duration = bounds.end - bounds.start;
|
var duration = bounds.end - bounds.start;
|
||||||
@ -94,7 +94,7 @@ define(
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
ConductorTOIController.prototype.changeTimeOfInterest = function () {
|
ConductorTOIController.prototype.changeTimeOfInterest = function () {
|
||||||
var bounds = this.conductor.bounds();
|
var bounds = this.timeAPI.bounds();
|
||||||
if (bounds) {
|
if (bounds) {
|
||||||
this.setOffsetFromBounds(bounds);
|
this.setOffsetFromBounds(bounds);
|
||||||
}
|
}
|
||||||
@ -112,10 +112,10 @@ define(
|
|||||||
var width = element.width();
|
var width = element.width();
|
||||||
var relativeX = e.pageX - element.offset().left;
|
var relativeX = e.pageX - element.offset().left;
|
||||||
var percX = relativeX / width;
|
var percX = relativeX / width;
|
||||||
var bounds = this.conductor.bounds();
|
var bounds = this.timeAPI.bounds();
|
||||||
var timeRange = bounds.end - bounds.start;
|
var timeRange = bounds.end - bounds.start;
|
||||||
|
|
||||||
this.conductor.timeOfInterest(timeRange * percX + bounds.start);
|
this.timeAPI.timeOfInterest(timeRange * percX + bounds.start);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -47,8 +47,7 @@ define(
|
|||||||
openmct,
|
openmct,
|
||||||
conductorViewService,
|
conductorViewService,
|
||||||
formatService,
|
formatService,
|
||||||
DEFAULT_MODE,
|
config
|
||||||
SHOW_TIMECONDUCTOR
|
|
||||||
) {
|
) {
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
@ -64,19 +63,22 @@ define(
|
|||||||
this.$window = $window;
|
this.$window = $window;
|
||||||
this.$location = $location;
|
this.$location = $location;
|
||||||
this.conductorViewService = conductorViewService;
|
this.conductorViewService = conductorViewService;
|
||||||
this.conductor = openmct.conductor;
|
this.timeAPI = openmct.time;
|
||||||
this.modes = conductorViewService.availableModes();
|
this.modes = conductorViewService.availableModes();
|
||||||
this.validation = new TimeConductorValidation(this.conductor);
|
this.validation = new TimeConductorValidation(this.timeAPI);
|
||||||
this.formatService = formatService;
|
this.formatService = formatService;
|
||||||
|
this.config = config;
|
||||||
|
|
||||||
//Check if the default mode defined is actually available
|
var options = this.optionsFromConfig(config);
|
||||||
if (this.modes[DEFAULT_MODE] === undefined) {
|
this.menu = {
|
||||||
DEFAULT_MODE = 'fixed';
|
selected: options[0],
|
||||||
}
|
options: options
|
||||||
this.DEFAULT_MODE = DEFAULT_MODE;
|
};
|
||||||
|
|
||||||
// Construct the provided time system definitions
|
// Construct the provided time system definitions
|
||||||
this.timeSystems = conductorViewService.systems;
|
this.timeSystems = config.menuOptions.map(function (menuOption){
|
||||||
|
return openmct.time.getTimeSystem(menuOption.timeSystem);
|
||||||
|
});
|
||||||
|
|
||||||
this.initializeScope();
|
this.initializeScope();
|
||||||
var searchParams = JSON.parse(JSON.stringify(this.$location.search()));
|
var searchParams = JSON.parse(JSON.stringify(this.$location.search()));
|
||||||
@ -84,9 +86,9 @@ define(
|
|||||||
this.setStateFromSearchParams(searchParams);
|
this.setStateFromSearchParams(searchParams);
|
||||||
|
|
||||||
//Set the initial state of the UI from the conductor state
|
//Set the initial state of the UI from the conductor state
|
||||||
var timeSystem = this.conductor.timeSystem();
|
var timeSystem = this.timeAPI.timeSystem();
|
||||||
if (timeSystem) {
|
if (timeSystem) {
|
||||||
this.changeTimeSystem(this.conductor.timeSystem());
|
this.changeTimeSystem(timeSystem);
|
||||||
}
|
}
|
||||||
|
|
||||||
var deltas = this.conductorViewService.deltas();
|
var deltas = this.conductorViewService.deltas();
|
||||||
@ -94,7 +96,7 @@ define(
|
|||||||
this.setFormFromDeltas(deltas);
|
this.setFormFromDeltas(deltas);
|
||||||
}
|
}
|
||||||
|
|
||||||
var bounds = this.conductor.bounds();
|
var bounds = this.timeAPI.bounds();
|
||||||
if (bounds && bounds.start !== undefined && bounds.end !== undefined) {
|
if (bounds && bounds.start !== undefined && bounds.end !== undefined) {
|
||||||
this.changeBounds(bounds);
|
this.changeBounds(bounds);
|
||||||
}
|
}
|
||||||
@ -105,12 +107,31 @@ define(
|
|||||||
}.bind(this));
|
}.bind(this));
|
||||||
|
|
||||||
//Respond to any subsequent conductor changes
|
//Respond to any subsequent conductor changes
|
||||||
this.conductor.on('bounds', this.changeBounds);
|
this.timeAPI.on('bounds', this.changeBounds);
|
||||||
this.conductor.on('timeSystem', this.changeTimeSystem);
|
this.timeAPI.on('timeSystem', this.changeTimeSystem);
|
||||||
|
|
||||||
this.$scope.showTimeConductor = SHOW_TIMECONDUCTOR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TimeConductorController.prototype.optionsFromConfig = function (config) {
|
||||||
|
var options = [{
|
||||||
|
name: 'Fixed Timespan Mode',
|
||||||
|
description: 'Query and explore data that falls between two fixed datetimes',
|
||||||
|
cssClass: 'icon-calendar',
|
||||||
|
clock: undefined
|
||||||
|
}];
|
||||||
|
var timeAPI = this.timeAPI;
|
||||||
|
|
||||||
|
(config.menuOptions || []).forEach(function (menuOption) {
|
||||||
|
options.push({
|
||||||
|
name: menuOption.name,
|
||||||
|
description: menuOption.description,
|
||||||
|
cssClass: menuOption.cssClass || '',
|
||||||
|
clock: timeAPI.getClock(menuOption.clock)
|
||||||
|
});
|
||||||
|
}.bind(this));
|
||||||
|
|
||||||
|
return options;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used as a url search param setter in place of $location.search(...)
|
* Used as a url search param setter in place of $location.search(...)
|
||||||
*
|
*
|
||||||
@ -129,7 +150,7 @@ define(
|
|||||||
*/
|
*/
|
||||||
TimeConductorController.prototype.initializeScope = function () {
|
TimeConductorController.prototype.initializeScope = function () {
|
||||||
//Set time Conductor bounds in the form
|
//Set time Conductor bounds in the form
|
||||||
this.$scope.boundsModel = this.conductor.bounds();
|
this.$scope.boundsModel = this.timeAPI.bounds();
|
||||||
|
|
||||||
//If conductor has a time system selected already, populate the
|
//If conductor has a time system selected already, populate the
|
||||||
//form from it
|
//form from it
|
||||||
@ -154,11 +175,11 @@ define(
|
|||||||
//Set mode from url if changed
|
//Set mode from url if changed
|
||||||
if (searchParams[SEARCH.MODE] === undefined ||
|
if (searchParams[SEARCH.MODE] === undefined ||
|
||||||
searchParams[SEARCH.MODE] !== this.$scope.modeModel.selectedKey) {
|
searchParams[SEARCH.MODE] !== this.$scope.modeModel.selectedKey) {
|
||||||
this.setMode(searchParams[SEARCH.MODE] || this.DEFAULT_MODE);
|
this.setMode(searchParams[SEARCH.MODE] || 'fixed');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (searchParams[SEARCH.TIME_SYSTEM] &&
|
if (searchParams[SEARCH.TIME_SYSTEM] &&
|
||||||
searchParams[SEARCH.TIME_SYSTEM] !== this.conductor.timeSystem().metadata.key) {
|
searchParams[SEARCH.TIME_SYSTEM] !== this.timeAPI.timeSystem()) {
|
||||||
//Will select the specified time system on the conductor
|
//Will select the specified time system on the conductor
|
||||||
this.selectTimeSystemByKey(searchParams[SEARCH.TIME_SYSTEM]);
|
this.selectTimeSystemByKey(searchParams[SEARCH.TIME_SYSTEM]);
|
||||||
}
|
}
|
||||||
@ -184,7 +205,7 @@ define(
|
|||||||
!isNaN(searchParams[SEARCH.END_BOUND]);
|
!isNaN(searchParams[SEARCH.END_BOUND]);
|
||||||
|
|
||||||
if (validBounds) {
|
if (validBounds) {
|
||||||
this.conductor.bounds({
|
this.timeAPI.bounds({
|
||||||
start: parseInt(searchParams[SEARCH.START_BOUND]),
|
start: parseInt(searchParams[SEARCH.START_BOUND]),
|
||||||
end: parseInt(searchParams[SEARCH.END_BOUND])
|
end: parseInt(searchParams[SEARCH.END_BOUND])
|
||||||
});
|
});
|
||||||
@ -195,8 +216,8 @@ define(
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
TimeConductorController.prototype.destroy = function () {
|
TimeConductorController.prototype.destroy = function () {
|
||||||
this.conductor.off('bounds', this.changeBounds);
|
this.timeAPI.off('bounds', this.changeBounds);
|
||||||
this.conductor.off('timeSystem', this.changeTimeSystem);
|
this.timeAPI.off('timeSystem', this.changeTimeSystem);
|
||||||
|
|
||||||
this.conductorViewService.off('pan', this.onPan);
|
this.conductorViewService.off('pan', this.onPan);
|
||||||
this.conductorViewService.off('pan-stop', this.onPanStop);
|
this.conductorViewService.off('pan-stop', this.onPanStop);
|
||||||
@ -253,10 +274,7 @@ define(
|
|||||||
this.$scope.modeModel.selectedKey = mode;
|
this.$scope.modeModel.selectedKey = mode;
|
||||||
//Synchronize scope with time system on mode
|
//Synchronize scope with time system on mode
|
||||||
this.$scope.timeSystemModel.options =
|
this.$scope.timeSystemModel.options =
|
||||||
this.conductorViewService.availableTimeSystems()
|
this.conductorViewService.availableTimeSystems();
|
||||||
.map(function (t) {
|
|
||||||
return t.metadata;
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -289,7 +307,7 @@ define(
|
|||||||
* @param formModel
|
* @param formModel
|
||||||
*/
|
*/
|
||||||
TimeConductorController.prototype.setBounds = function (boundsModel) {
|
TimeConductorController.prototype.setBounds = function (boundsModel) {
|
||||||
this.conductor.bounds({
|
this.timeAPI.bounds({
|
||||||
start: boundsModel.start,
|
start: boundsModel.start,
|
||||||
end: boundsModel.end
|
end: boundsModel.end
|
||||||
});
|
});
|
||||||
@ -364,7 +382,7 @@ define(
|
|||||||
})[0];
|
})[0];
|
||||||
if (selected) {
|
if (selected) {
|
||||||
this.supportsZoom = !!(selected.defaults() && selected.defaults().zoom);
|
this.supportsZoom = !!(selected.defaults() && selected.defaults().zoom);
|
||||||
this.conductor.timeSystem(selected, selected.defaults().bounds);
|
this.timeAPI.timeSystem(selected, selected.defaults().bounds);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -376,9 +394,11 @@ define(
|
|||||||
*
|
*
|
||||||
* @param newTimeSystem
|
* @param newTimeSystem
|
||||||
*/
|
*/
|
||||||
TimeConductorController.prototype.changeTimeSystem = function (newTimeSystem) {
|
TimeConductorController.prototype.changeTimeSystem = function (key) {
|
||||||
|
var newTimeSystem = this.timeAPI.getTimeSystem(key);
|
||||||
|
|
||||||
//Set time system in URL on change
|
//Set time system in URL on change
|
||||||
this.setParam(SEARCH.TIME_SYSTEM, newTimeSystem.metadata.key);
|
this.setParam(SEARCH.TIME_SYSTEM, key);
|
||||||
|
|
||||||
if (newTimeSystem && (newTimeSystem !== this.$scope.timeSystemModel.selected)) {
|
if (newTimeSystem && (newTimeSystem !== this.$scope.timeSystemModel.selected)) {
|
||||||
this.supportsZoom = !!(newTimeSystem.defaults() && newTimeSystem.defaults().zoom);
|
this.supportsZoom = !!(newTimeSystem.defaults() && newTimeSystem.defaults().zoom);
|
||||||
@ -401,9 +421,9 @@ define(
|
|||||||
* @returns {number} a value between 0.01 and 0.99, in increments of .01
|
* @returns {number} a value between 0.01 and 0.99, in increments of .01
|
||||||
*/
|
*/
|
||||||
TimeConductorController.prototype.toSliderValue = function (timeSpan) {
|
TimeConductorController.prototype.toSliderValue = function (timeSpan) {
|
||||||
var timeSystem = this.conductor.timeSystem();
|
var timeSystem = this.timeAPI.getTimeSystem(this.timeAPI.timeSystem());
|
||||||
if (timeSystem) {
|
if (timeSystem) {
|
||||||
var zoomDefaults = this.conductor.timeSystem().defaults().zoom;
|
var zoomDefaults = timeSystem.defaults().zoom;
|
||||||
var perc = timeSpan / (zoomDefaults.min - zoomDefaults.max);
|
var perc = timeSpan / (zoomDefaults.min - zoomDefaults.max);
|
||||||
return 1 - Math.pow(perc, 1 / 4);
|
return 1 - Math.pow(perc, 1 / 4);
|
||||||
}
|
}
|
||||||
@ -415,8 +435,9 @@ define(
|
|||||||
* @param {TimeSpan} timeSpan
|
* @param {TimeSpan} timeSpan
|
||||||
*/
|
*/
|
||||||
TimeConductorController.prototype.toTimeUnits = function (timeSpan) {
|
TimeConductorController.prototype.toTimeUnits = function (timeSpan) {
|
||||||
if (this.conductor.timeSystem()) {
|
var timeSystem = this.timeAPI.getTimeSystem(this.timeAPI.timeSystem());
|
||||||
var timeFormat = this.formatService.getFormat(this.conductor.timeSystem().formats()[0]);
|
if (this.timeAPI.timeSystem()) {
|
||||||
|
var timeFormat = this.formatService.getFormat(timeSystem.formats()[0]);
|
||||||
this.$scope.timeUnits = timeFormat.timeUnits && timeFormat.timeUnits(timeSpan);
|
this.$scope.timeUnits = timeFormat.timeUnits && timeFormat.timeUnits(timeSpan);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -429,7 +450,8 @@ define(
|
|||||||
* @param bounds
|
* @param bounds
|
||||||
*/
|
*/
|
||||||
TimeConductorController.prototype.onZoom = function (sliderValue) {
|
TimeConductorController.prototype.onZoom = function (sliderValue) {
|
||||||
var zoomDefaults = this.conductor.timeSystem().defaults().zoom;
|
var timeSystem = this.timeAPI.getTimeSystem(this.timeAPI.timeSystem());
|
||||||
|
var zoomDefaults = timeSystem.defaults().zoom;
|
||||||
var timeSpan = Math.pow((1 - sliderValue), 4) * (zoomDefaults.min - zoomDefaults.max);
|
var timeSpan = Math.pow((1 - sliderValue), 4) * (zoomDefaults.min - zoomDefaults.max);
|
||||||
|
|
||||||
var zoom = this.conductorViewService.zoom(timeSpan);
|
var zoom = this.conductorViewService.zoom(timeSpan);
|
||||||
|
@ -31,38 +31,23 @@ define(
|
|||||||
* @memberof platform.features.conductor
|
* @memberof platform.features.conductor
|
||||||
* @param {TimeConductorMetadata} metadata
|
* @param {TimeConductorMetadata} metadata
|
||||||
*/
|
*/
|
||||||
function TimeConductorMode(metadata, conductor, timeSystems) {
|
function TimeConductorMode(metadata, timeAPI) {
|
||||||
this.conductor = conductor;
|
this.timeAPI = timeAPI;
|
||||||
|
|
||||||
this.mdata = metadata;
|
this.mdata = metadata;
|
||||||
this.deltasVal = undefined;
|
|
||||||
this.source = undefined;
|
|
||||||
this.sourceUnlisten = undefined;
|
|
||||||
this.systems = timeSystems;
|
|
||||||
this.availableSources = undefined;
|
|
||||||
this.changeTimeSystem = this.changeTimeSystem.bind(this);
|
this.changeTimeSystem = this.changeTimeSystem.bind(this);
|
||||||
this.tick = this.tick.bind(this);
|
|
||||||
|
var timeSystem = this.timeAPI.timeSystem();
|
||||||
|
|
||||||
//Set the time system initially
|
//Set the time system initially
|
||||||
if (conductor.timeSystem()) {
|
if (timeSystem) {
|
||||||
this.changeTimeSystem(conductor.timeSystem());
|
this.changeTimeSystem(timeSystem);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Listen for subsequent changes to time system
|
//Listen for subsequent changes to time system
|
||||||
conductor.on('timeSystem', this.changeTimeSystem);
|
timeAPI.on('timeSystem', this.changeTimeSystem);
|
||||||
|
|
||||||
if (metadata.key === 'fixed') {
|
this.availableSystems = timeAPI.availableTimeSystems();
|
||||||
//Fixed automatically supports all time systems
|
|
||||||
this.availableSystems = timeSystems;
|
|
||||||
} else {
|
|
||||||
this.availableSystems = timeSystems.filter(function (timeSystem) {
|
|
||||||
//Only include time systems that have tick sources that
|
|
||||||
// support the current mode
|
|
||||||
return timeSystem.tickSources().some(function (tickSource) {
|
|
||||||
return metadata.key === tickSource.metadata.mode;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -70,7 +55,8 @@ define(
|
|||||||
* @param timeSystem
|
* @param timeSystem
|
||||||
* @returns {TimeSystem} the currently selected time system
|
* @returns {TimeSystem} the currently selected time system
|
||||||
*/
|
*/
|
||||||
TimeConductorMode.prototype.changeTimeSystem = function (timeSystem) {
|
TimeConductorMode.prototype.changeTimeSystem = function (key) {
|
||||||
|
var timeSystem = this.timeAPI.getTimeSystem(key);
|
||||||
// On time system change, apply default deltas
|
// On time system change, apply default deltas
|
||||||
var defaults = timeSystem.defaults() || {
|
var defaults = timeSystem.defaults() || {
|
||||||
bounds: {
|
bounds: {
|
||||||
@ -83,20 +69,8 @@ define(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.conductor.bounds(defaults.bounds);
|
this.timeAPI.bounds(defaults.bounds);
|
||||||
this.deltas(defaults.deltas);
|
this.deltas(defaults.deltas);
|
||||||
|
|
||||||
// Tick sources are mode-specific, so restrict tick sources to only those supported by the current mode.
|
|
||||||
var key = this.mdata.key;
|
|
||||||
var tickSources = timeSystem.tickSources();
|
|
||||||
if (tickSources) {
|
|
||||||
this.availableSources = tickSources.filter(function (source) {
|
|
||||||
return source.metadata.mode === key;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set an appropriate tick source from the new time system
|
|
||||||
this.tickSource(this.availableTickSources(timeSystem)[0]);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -110,15 +84,6 @@ define(
|
|||||||
return this.availableSystems;
|
return this.availableSystems;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Tick sources are mode-specific. This returns a filtered list of the tick sources available in the currently selected mode
|
|
||||||
* @param timeSystem
|
|
||||||
* @returns {Array.<T>}
|
|
||||||
*/
|
|
||||||
TimeConductorMode.prototype.availableTickSources = function (timeSystem) {
|
|
||||||
return this.availableSources;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get or set tick source. Setting tick source will also start
|
* Get or set tick source. Setting tick source will also start
|
||||||
* listening to it and unlisten from any existing tick source
|
* listening to it and unlisten from any existing tick source
|
||||||
@ -127,49 +92,28 @@ define(
|
|||||||
*/
|
*/
|
||||||
TimeConductorMode.prototype.tickSource = function (tickSource) {
|
TimeConductorMode.prototype.tickSource = function (tickSource) {
|
||||||
if (arguments.length > 0) {
|
if (arguments.length > 0) {
|
||||||
if (this.sourceUnlisten) {
|
var timeSystem = this.timeAPI.getTimeSystem(this.timeAPI.timeSystem());
|
||||||
this.sourceUnlisten();
|
var defaults = timeSystem.defaults() || {
|
||||||
}
|
bounds: {
|
||||||
this.source = tickSource;
|
start: 0,
|
||||||
if (tickSource) {
|
end: 0
|
||||||
this.sourceUnlisten = tickSource.listen(this.tick);
|
},
|
||||||
//Now following a tick source
|
deltas: {
|
||||||
this.conductor.follow(true);
|
start: 0,
|
||||||
} else {
|
end: 0
|
||||||
this.conductor.follow(false);
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
|
this.timeAPI.tickSource(tickSource, defaults.deltas);
|
||||||
}
|
}
|
||||||
return this.source;
|
return this.timeAPI.tickSource();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
TimeConductorMode.prototype.destroy = function () {
|
TimeConductorMode.prototype.destroy = function () {
|
||||||
this.conductor.off('timeSystem', this.changeTimeSystem);
|
this.timeAPI.off('timeSystem', this.changeTimeSystem);
|
||||||
|
|
||||||
if (this.sourceUnlisten) {
|
|
||||||
this.sourceUnlisten();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
* @param {number} time some value that is valid in the current TimeSystem
|
|
||||||
*/
|
|
||||||
TimeConductorMode.prototype.tick = function (time) {
|
|
||||||
var deltas = this.deltas();
|
|
||||||
var startTime = time;
|
|
||||||
var endTime = time;
|
|
||||||
|
|
||||||
if (deltas) {
|
|
||||||
startTime = time - deltas.start;
|
|
||||||
endTime = time + deltas.end;
|
|
||||||
}
|
|
||||||
this.conductor.bounds({
|
|
||||||
start: startTime,
|
|
||||||
end: endTime
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -182,12 +126,13 @@ define(
|
|||||||
TimeConductorMode.prototype.deltas = function (deltas) {
|
TimeConductorMode.prototype.deltas = function (deltas) {
|
||||||
if (arguments.length !== 0) {
|
if (arguments.length !== 0) {
|
||||||
var bounds = this.calculateBoundsFromDeltas(deltas);
|
var bounds = this.calculateBoundsFromDeltas(deltas);
|
||||||
this.deltasVal = deltas;
|
this.timeAPI.clockOffsets(deltas);
|
||||||
|
|
||||||
if (this.metadata().key !== 'fixed') {
|
if (this.metadata().key !== 'fixed') {
|
||||||
this.conductor.bounds(bounds);
|
this.timeAPI.bounds(bounds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return this.deltasVal;
|
return this.timeAPI.clockOffsets();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -195,11 +140,12 @@ define(
|
|||||||
* @returns {TimeConductorBounds}
|
* @returns {TimeConductorBounds}
|
||||||
*/
|
*/
|
||||||
TimeConductorMode.prototype.calculateBoundsFromDeltas = function (deltas) {
|
TimeConductorMode.prototype.calculateBoundsFromDeltas = function (deltas) {
|
||||||
var oldEnd = this.conductor.bounds().end;
|
var oldEnd = this.timeAPI.bounds().end;
|
||||||
|
var offsets = this.timeAPI.clockOffsets();
|
||||||
|
|
||||||
if (this.deltasVal && this.deltasVal.end !== undefined) {
|
if (offsets && offsets.end !== undefined) {
|
||||||
//Calculate the previous raw end value (without delta)
|
//Calculate the previous raw end value (without delta)
|
||||||
oldEnd = oldEnd - this.deltasVal.end;
|
oldEnd = oldEnd - offsets.end;
|
||||||
}
|
}
|
||||||
|
|
||||||
var bounds = {
|
var bounds = {
|
||||||
@ -222,18 +168,19 @@ define(
|
|||||||
*/
|
*/
|
||||||
TimeConductorMode.prototype.calculateZoom = function (timeSpan) {
|
TimeConductorMode.prototype.calculateZoom = function (timeSpan) {
|
||||||
var zoom = {};
|
var zoom = {};
|
||||||
|
var offsets;
|
||||||
|
|
||||||
// If a tick source is defined, then the concept of 'now' is
|
// If a tick source is defined, then the concept of 'now' is
|
||||||
// important. Calculate zoom based on 'now'.
|
// important. Calculate zoom based on 'now'.
|
||||||
if (this.tickSource()) {
|
if (this.timeAPI.follow()) {
|
||||||
|
offsets = this.timeAPI.clockOffsets();
|
||||||
zoom.deltas = {
|
zoom.deltas = {
|
||||||
start: timeSpan,
|
start: timeSpan,
|
||||||
end: this.deltasVal.end
|
end: offsets.end
|
||||||
};
|
};
|
||||||
zoom.bounds = this.calculateBoundsFromDeltas(zoom.deltas);
|
zoom.bounds = this.calculateBoundsFromDeltas(zoom.deltas);
|
||||||
// Calculate bounds based on deltas;
|
|
||||||
} else {
|
} else {
|
||||||
var bounds = this.conductor.bounds();
|
var bounds = this.timeAPI.bounds();
|
||||||
var center = bounds.start + ((bounds.end - bounds.start)) / 2;
|
var center = bounds.start + ((bounds.end - bounds.start)) / 2;
|
||||||
bounds.start = center - timeSpan / 2;
|
bounds.start = center - timeSpan / 2;
|
||||||
bounds.end = center + timeSpan / 2;
|
bounds.end = center + timeSpan / 2;
|
||||||
|
@ -29,9 +29,9 @@ define(
|
|||||||
* @param conductor
|
* @param conductor
|
||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
function TimeConductorValidation(conductor) {
|
function TimeConductorValidation(timeAPI) {
|
||||||
var self = this;
|
var self = this;
|
||||||
this.conductor = conductor;
|
this.timeAPI = timeAPI;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Bind all class functions to 'this'
|
* Bind all class functions to 'this'
|
||||||
@ -47,13 +47,13 @@ define(
|
|||||||
* Validation methods below are invoked directly from controls in the TimeConductor form
|
* Validation methods below are invoked directly from controls in the TimeConductor form
|
||||||
*/
|
*/
|
||||||
TimeConductorValidation.prototype.validateStart = function (start) {
|
TimeConductorValidation.prototype.validateStart = function (start) {
|
||||||
var bounds = this.conductor.bounds();
|
var bounds = this.timeAPI.bounds();
|
||||||
return this.conductor.validateBounds({start: start, end: bounds.end}) === true;
|
return this.timeAPI.validateBounds({start: start, end: bounds.end}) === true;
|
||||||
};
|
};
|
||||||
|
|
||||||
TimeConductorValidation.prototype.validateEnd = function (end) {
|
TimeConductorValidation.prototype.validateEnd = function (end) {
|
||||||
var bounds = this.conductor.bounds();
|
var bounds = this.timeAPI.bounds();
|
||||||
return this.conductor.validateBounds({start: bounds.start, end: end}) === true;
|
return this.timeAPI.validateBounds({start: bounds.start, end: end}) === true;
|
||||||
};
|
};
|
||||||
|
|
||||||
TimeConductorValidation.prototype.validateStartDelta = function (startDelta) {
|
TimeConductorValidation.prototype.validateStartDelta = function (startDelta) {
|
||||||
|
@ -41,11 +41,7 @@ define(
|
|||||||
|
|
||||||
EventEmitter.call(this);
|
EventEmitter.call(this);
|
||||||
|
|
||||||
this.systems = timeSystems.map(function (timeSystemConstructor) {
|
this.timeAPI = openmct.time;
|
||||||
return timeSystemConstructor();
|
|
||||||
});
|
|
||||||
|
|
||||||
this.conductor = openmct.conductor;
|
|
||||||
this.currentMode = undefined;
|
this.currentMode = undefined;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -67,39 +63,25 @@ define(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
function hasTickSource(sourceType, timeSystem) {
|
|
||||||
return timeSystem.tickSources().some(function (tickSource) {
|
|
||||||
return tickSource.metadata.mode === sourceType;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
var timeSystemsForMode = function (sourceType) {
|
|
||||||
return this.systems.filter(hasTickSource.bind(this, sourceType));
|
|
||||||
}.bind(this);
|
|
||||||
|
|
||||||
//Only show 'real-time mode' if appropriate time systems available
|
//Only show 'real-time mode' if appropriate time systems available
|
||||||
if (timeSystemsForMode('realtime').length > 0) {
|
var realtimeMode = {
|
||||||
var realtimeMode = {
|
key: 'realtime',
|
||||||
key: 'realtime',
|
cssClass: 'icon-clock',
|
||||||
cssClass: 'icon-clock',
|
label: 'Real-time',
|
||||||
label: 'Real-time',
|
name: 'Real-time Mode',
|
||||||
name: 'Real-time Mode',
|
description: 'Monitor real-time streaming data as it comes in. The Time Conductor and displays will automatically advance themselves based on a UTC clock.'
|
||||||
description: 'Monitor real-time streaming data as it comes in. The Time Conductor and displays will automatically advance themselves based on a UTC clock.'
|
};
|
||||||
};
|
this.availModes[realtimeMode.key] = realtimeMode;
|
||||||
this.availModes[realtimeMode.key] = realtimeMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Only show 'LAD mode' if appropriate time systems available
|
//Only show 'LAD mode' if appropriate time systems available
|
||||||
if (timeSystemsForMode('lad').length > 0) {
|
var ladMode = {
|
||||||
var ladMode = {
|
key: 'lad',
|
||||||
key: 'lad',
|
cssClass: 'icon-database',
|
||||||
cssClass: 'icon-database',
|
label: 'LAD',
|
||||||
label: 'LAD',
|
name: 'LAD Mode',
|
||||||
name: 'LAD Mode',
|
description: 'Latest Available Data mode monitors real-time streaming data as it comes in. The Time Conductor and displays will only advance when data becomes available.'
|
||||||
description: 'Latest Available Data mode monitors real-time streaming data as it comes in. The Time Conductor and displays will only advance when data becomes available.'
|
};
|
||||||
};
|
this.availModes[ladMode.key] = ladMode;
|
||||||
this.availModes[ladMode.key] = ladMode;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TimeConductorViewService.prototype = Object.create(EventEmitter.prototype);
|
TimeConductorViewService.prototype = Object.create(EventEmitter.prototype);
|
||||||
@ -126,25 +108,25 @@ define(
|
|||||||
TimeConductorViewService.prototype.mode = function (newModeKey) {
|
TimeConductorViewService.prototype.mode = function (newModeKey) {
|
||||||
function contains(timeSystems, ts) {
|
function contains(timeSystems, ts) {
|
||||||
return timeSystems.filter(function (t) {
|
return timeSystems.filter(function (t) {
|
||||||
return t.metadata.key === ts.metadata.key;
|
return t.key === ts.key;
|
||||||
}).length > 0;
|
}).length > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arguments.length === 1) {
|
if (arguments.length === 1) {
|
||||||
var timeSystem = this.conductor.timeSystem();
|
var timeSystem = this.timeAPI.getTimeSystem(this.timeAPI.timeSystem());
|
||||||
var modes = this.availableModes();
|
var modes = this.availableModes();
|
||||||
var modeMetaData = modes[newModeKey];
|
var modeMetaData = modes[newModeKey];
|
||||||
|
|
||||||
if (this.currentMode) {
|
if (this.currentMode) {
|
||||||
this.currentMode.destroy();
|
this.currentMode.destroy();
|
||||||
}
|
}
|
||||||
this.currentMode = new TimeConductorMode(modeMetaData, this.conductor, this.systems);
|
this.currentMode = new TimeConductorMode(modeMetaData, this.timeAPI);
|
||||||
|
|
||||||
// If no time system set on time conductor, or the currently selected time system is not available in
|
// If no time system set on time conductor, or the currently selected time system is not available in
|
||||||
// the new mode, default to first available time system
|
// the new mode, default to first available time system
|
||||||
if (!timeSystem || !contains(this.currentMode.availableTimeSystems(), timeSystem)) {
|
if (!timeSystem || !contains(this.currentMode.availableTimeSystems(), timeSystem)) {
|
||||||
timeSystem = this.currentMode.availableTimeSystems()[0];
|
timeSystem = this.currentMode.availableTimeSystems()[0];
|
||||||
this.conductor.timeSystem(timeSystem, timeSystem.defaults().bounds);
|
this.timeAPI.timeSystem(timeSystem.key, timeSystem.defaults().bounds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return this.currentMode ? this.currentMode.metadata().key : undefined;
|
return this.currentMode ? this.currentMode.metadata().key : undefined;
|
||||||
@ -201,7 +183,7 @@ define(
|
|||||||
* mode. Time systems and tick sources are mode dependent
|
* mode. Time systems and tick sources are mode dependent
|
||||||
*/
|
*/
|
||||||
TimeConductorViewService.prototype.availableTimeSystems = function () {
|
TimeConductorViewService.prototype.availableTimeSystems = function () {
|
||||||
return this.currentMode.availableTimeSystems();
|
return this.timeAPI.availableTimeSystems();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -31,7 +31,7 @@ define(
|
|||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
function TimeOfInterestController($scope, openmct, formatService) {
|
function TimeOfInterestController($scope, openmct, formatService) {
|
||||||
this.conductor = openmct.conductor;
|
this.timeAPI = openmct.time;
|
||||||
this.formatService = formatService;
|
this.formatService = formatService;
|
||||||
this.format = undefined;
|
this.format = undefined;
|
||||||
this.toiText = undefined;
|
this.toiText = undefined;
|
||||||
@ -44,11 +44,11 @@ define(
|
|||||||
this[key] = TimeOfInterestController.prototype[key].bind(this);
|
this[key] = TimeOfInterestController.prototype[key].bind(this);
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
|
|
||||||
this.conductor.on('timeOfInterest', this.changeTimeOfInterest);
|
this.timeAPI.on('timeOfInterest', this.changeTimeOfInterest);
|
||||||
this.conductor.on('timeSystem', this.changeTimeSystem);
|
this.timeAPI.on('timeSystem', this.changeTimeSystem);
|
||||||
if (this.conductor.timeSystem()) {
|
if (this.timeAPI.timeSystem()) {
|
||||||
this.changeTimeSystem(this.conductor.timeSystem());
|
this.changeTimeSystem(this.timeAPI.timeSystem());
|
||||||
var toi = this.conductor.timeOfInterest();
|
var toi = this.timeAPI.timeOfInterest();
|
||||||
if (toi) {
|
if (toi) {
|
||||||
this.changeTimeOfInterest(toi);
|
this.changeTimeOfInterest(toi);
|
||||||
}
|
}
|
||||||
@ -76,7 +76,8 @@ define(
|
|||||||
* When time system is changed, update the formatter used to
|
* When time system is changed, update the formatter used to
|
||||||
* display the current TOI label
|
* display the current TOI label
|
||||||
*/
|
*/
|
||||||
TimeOfInterestController.prototype.changeTimeSystem = function (timeSystem) {
|
TimeOfInterestController.prototype.changeTimeSystem = function (key) {
|
||||||
|
var timeSystem = this.timeAPI.getTimeSystem(key);
|
||||||
this.format = this.formatService.getFormat(timeSystem.formats()[0]);
|
this.format = this.formatService.getFormat(timeSystem.formats()[0]);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -84,8 +85,8 @@ define(
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
TimeOfInterestController.prototype.destroy = function () {
|
TimeOfInterestController.prototype.destroy = function () {
|
||||||
this.conductor.off('timeOfInterest', this.changeTimeOfInterest);
|
this.timeAPI.off('timeOfInterest', this.changeTimeOfInterest);
|
||||||
this.conductor.off('timeSystem', this.changeTimeSystem);
|
this.timeAPI.off('timeSystem', this.changeTimeSystem);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -93,7 +94,7 @@ define(
|
|||||||
* Time Conductor
|
* Time Conductor
|
||||||
*/
|
*/
|
||||||
TimeOfInterestController.prototype.dismiss = function () {
|
TimeOfInterestController.prototype.dismiss = function () {
|
||||||
this.conductor.timeOfInterest(undefined);
|
this.timeAPI.timeOfInterest(undefined);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -101,7 +102,7 @@ define(
|
|||||||
* the TOI displayed in views.
|
* the TOI displayed in views.
|
||||||
*/
|
*/
|
||||||
TimeOfInterestController.prototype.resync = function () {
|
TimeOfInterestController.prototype.resync = function () {
|
||||||
this.conductor.timeOfInterest(this.conductor.timeOfInterest());
|
this.timeAPI.timeOfInterest(this.timeAPI.timeOfInterest());
|
||||||
};
|
};
|
||||||
|
|
||||||
return TimeOfInterestController;
|
return TimeOfInterestController;
|
||||||
|
@ -82,7 +82,7 @@ define(
|
|||||||
lastRange,
|
lastRange,
|
||||||
lastDomain,
|
lastDomain,
|
||||||
handle;
|
handle;
|
||||||
var conductor = openmct.conductor;
|
var timeAPI = openmct.time;
|
||||||
|
|
||||||
// Populate the scope with axis information (specifically, options
|
// Populate the scope with axis information (specifically, options
|
||||||
// available for each axis.)
|
// available for each axis.)
|
||||||
@ -185,7 +185,7 @@ define(
|
|||||||
|
|
||||||
function changeTimeOfInterest(timeOfInterest) {
|
function changeTimeOfInterest(timeOfInterest) {
|
||||||
if (timeOfInterest !== undefined) {
|
if (timeOfInterest !== undefined) {
|
||||||
var bounds = conductor.bounds();
|
var bounds = timeAPI.bounds();
|
||||||
var range = bounds.end - bounds.start;
|
var range = bounds.end - bounds.start;
|
||||||
$scope.toiPerc = ((timeOfInterest - bounds.start) / range) * 100;
|
$scope.toiPerc = ((timeOfInterest - bounds.start) / range) * 100;
|
||||||
$scope.toiPinned = true;
|
$scope.toiPinned = true;
|
||||||
@ -208,8 +208,8 @@ define(
|
|||||||
);
|
);
|
||||||
replot();
|
replot();
|
||||||
|
|
||||||
changeTimeOfInterest(conductor.timeOfInterest());
|
changeTimeOfInterest(timeAPI.timeOfInterest());
|
||||||
conductor.on("timeOfInterest", changeTimeOfInterest);
|
timeAPI.on("timeOfInterest", changeTimeOfInterest);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Release the current subscription (called when scope is destroyed)
|
// Release the current subscription (called when scope is destroyed)
|
||||||
@ -218,7 +218,7 @@ define(
|
|||||||
handle.unsubscribe();
|
handle.unsubscribe();
|
||||||
handle = undefined;
|
handle = undefined;
|
||||||
}
|
}
|
||||||
conductor.off("timeOfInterest", changeTimeOfInterest);
|
timeAPI.off("timeOfInterest", changeTimeOfInterest);
|
||||||
}
|
}
|
||||||
|
|
||||||
function requery() {
|
function requery() {
|
||||||
@ -262,7 +262,7 @@ define(
|
|||||||
requery();
|
requery();
|
||||||
}
|
}
|
||||||
self.setUnsynchedStatus($scope.domainObject, follow && self.isZoomed());
|
self.setUnsynchedStatus($scope.domainObject, follow && self.isZoomed());
|
||||||
changeTimeOfInterest(conductor.timeOfInterest());
|
changeTimeOfInterest(timeAPI.timeOfInterest());
|
||||||
}
|
}
|
||||||
|
|
||||||
this.modeOptions = new PlotModeOptions([], subPlotFactory);
|
this.modeOptions = new PlotModeOptions([], subPlotFactory);
|
||||||
@ -286,11 +286,11 @@ define(
|
|||||||
];
|
];
|
||||||
|
|
||||||
//Are some initialized bounds defined?
|
//Are some initialized bounds defined?
|
||||||
var bounds = conductor.bounds();
|
var bounds = timeAPI.bounds();
|
||||||
if (bounds &&
|
if (bounds &&
|
||||||
bounds.start !== undefined &&
|
bounds.start !== undefined &&
|
||||||
bounds.end !== undefined) {
|
bounds.end !== undefined) {
|
||||||
changeDisplayBounds(undefined, conductor.bounds(), conductor.follow());
|
changeDisplayBounds(undefined, timeAPI.bounds(), timeAPI.follow());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Watch for changes to the selected axis
|
// Watch for changes to the selected axis
|
||||||
|
@ -27,7 +27,7 @@ define(
|
|||||||
this.resultsHeader = this.element.find('.mct-table>thead').first();
|
this.resultsHeader = this.element.find('.mct-table>thead').first();
|
||||||
this.sizingTableBody = this.element.find('.sizing-table>tbody').first();
|
this.sizingTableBody = this.element.find('.sizing-table>tbody').first();
|
||||||
this.$scope.sizingRow = {};
|
this.$scope.sizingRow = {};
|
||||||
this.conductor = openmct.conductor;
|
this.timeApi = openmct.time;
|
||||||
this.toiFormatter = undefined;
|
this.toiFormatter = undefined;
|
||||||
this.formatService = formatService;
|
this.formatService = formatService;
|
||||||
this.callbacks = {};
|
this.callbacks = {};
|
||||||
@ -65,6 +65,7 @@ define(
|
|||||||
this.scrollable.on('scroll', this.onScroll);
|
this.scrollable.on('scroll', this.onScroll);
|
||||||
|
|
||||||
$scope.visibleRows = [];
|
$scope.visibleRows = [];
|
||||||
|
$scope.displayRows = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set default values for optional parameters on a given scope
|
* Set default values for optional parameters on a given scope
|
||||||
@ -113,7 +114,7 @@ define(
|
|||||||
$scope.sortDirection = 'asc';
|
$scope.sortDirection = 'asc';
|
||||||
}
|
}
|
||||||
self.setRows($scope.rows);
|
self.setRows($scope.rows);
|
||||||
self.setTimeOfInterestRow(self.conductor.timeOfInterest());
|
self.setTimeOfInterestRow(self.timeApi.timeOfInterest());
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -159,13 +160,13 @@ define(
|
|||||||
if (timeColumns) {
|
if (timeColumns) {
|
||||||
this.destroyConductorListeners();
|
this.destroyConductorListeners();
|
||||||
|
|
||||||
this.conductor.on('timeSystem', this.changeTimeSystem);
|
this.timeApi.on('timeSystem', this.changeTimeSystem);
|
||||||
this.conductor.on('timeOfInterest', this.changeTimeOfInterest);
|
this.timeApi.on('timeOfInterest', this.changeTimeOfInterest);
|
||||||
this.conductor.on('bounds', this.changeBounds);
|
this.timeApi.on('bounds', this.changeBounds);
|
||||||
|
|
||||||
// If time system defined, set initially
|
// If time system defined, set initially
|
||||||
if (this.conductor.timeSystem()) {
|
if (this.timeApi.timeSystem()) {
|
||||||
this.changeTimeSystem(this.conductor.timeSystem());
|
this.changeTimeSystem(this.timeApi.timeSystem());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
@ -182,13 +183,14 @@ define(
|
|||||||
}
|
}
|
||||||
|
|
||||||
MCTTableController.prototype.destroyConductorListeners = function () {
|
MCTTableController.prototype.destroyConductorListeners = function () {
|
||||||
this.conductor.off('timeSystem', this.changeTimeSystem);
|
this.timeApi.off('timeSystem', this.changeTimeSystem);
|
||||||
this.conductor.off('timeOfInterest', this.changeTimeOfInterest);
|
this.timeApi.off('timeOfInterest', this.changeTimeOfInterest);
|
||||||
this.conductor.off('bounds', this.changeBounds);
|
this.timeApi.off('bounds', this.changeBounds);
|
||||||
};
|
};
|
||||||
|
|
||||||
MCTTableController.prototype.changeTimeSystem = function () {
|
MCTTableController.prototype.changeTimeSystem = function () {
|
||||||
var format = this.conductor.timeSystem().formats()[0];
|
var timeSystem = this.timeApi.getTimeSystem(this.timeApi.timeSystem());
|
||||||
|
var format = timeSystem.formats()[0];
|
||||||
this.toiFormatter = this.formatService.getFormat(format);
|
this.toiFormatter = this.formatService.getFormat(format);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -220,7 +222,7 @@ define(
|
|||||||
}
|
}
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
|
|
||||||
var toi = this.conductor.timeOfInterest();
|
var toi = this.timeApi.timeOfInterest();
|
||||||
if (toi !== -1) {
|
if (toi !== -1) {
|
||||||
this.setTimeOfInterestRow(toi);
|
this.setTimeOfInterestRow(toi);
|
||||||
}
|
}
|
||||||
@ -681,7 +683,7 @@ define(
|
|||||||
// perform DOM changes, otherwise scrollTo won't work.
|
// perform DOM changes, otherwise scrollTo won't work.
|
||||||
.then(function () {
|
.then(function () {
|
||||||
//If TOI specified, scroll to it
|
//If TOI specified, scroll to it
|
||||||
var timeOfInterest = this.conductor.timeOfInterest();
|
var timeOfInterest = this.timeApi.timeOfInterest();
|
||||||
if (timeOfInterest) {
|
if (timeOfInterest) {
|
||||||
this.setTimeOfInterestRow(timeOfInterest);
|
this.setTimeOfInterestRow(timeOfInterest);
|
||||||
this.scrollToRow(this.$scope.toiRowIndex);
|
this.scrollToRow(this.$scope.toiRowIndex);
|
||||||
@ -779,7 +781,7 @@ define(
|
|||||||
* @param bounds
|
* @param bounds
|
||||||
*/
|
*/
|
||||||
MCTTableController.prototype.changeBounds = function (bounds) {
|
MCTTableController.prototype.changeBounds = function (bounds) {
|
||||||
this.setTimeOfInterestRow(this.conductor.timeOfInterest());
|
this.setTimeOfInterestRow(this.timeApi.timeOfInterest());
|
||||||
if (this.$scope.toiRowIndex !== -1) {
|
if (this.$scope.toiRowIndex !== -1) {
|
||||||
this.scrollToRow(this.$scope.toiRowIndex);
|
this.scrollToRow(this.$scope.toiRowIndex);
|
||||||
}
|
}
|
||||||
@ -794,7 +796,7 @@ define(
|
|||||||
if (selectedTime &&
|
if (selectedTime &&
|
||||||
this.toiFormatter.validate(selectedTime) &&
|
this.toiFormatter.validate(selectedTime) &&
|
||||||
event.altKey) {
|
event.altKey) {
|
||||||
this.conductor.timeOfInterest(this.toiFormatter.parse(selectedTime));
|
this.timeApi.timeOfInterest(this.toiFormatter.parse(selectedTime));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -64,7 +64,7 @@ define(
|
|||||||
$scope.rows = [];
|
$scope.rows = [];
|
||||||
this.table = new TableConfiguration($scope.domainObject,
|
this.table = new TableConfiguration($scope.domainObject,
|
||||||
openmct);
|
openmct);
|
||||||
this.lastBounds = this.openmct.conductor.bounds();
|
this.lastBounds = this.openmct.time.bounds();
|
||||||
this.lastRequestTime = 0;
|
this.lastRequestTime = 0;
|
||||||
this.telemetry = new TelemetryCollection();
|
this.telemetry = new TelemetryCollection();
|
||||||
|
|
||||||
@ -95,7 +95,7 @@ define(
|
|||||||
this.registerChangeListeners();
|
this.registerChangeListeners();
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
|
|
||||||
this.setScroll(this.openmct.conductor.follow());
|
this.setScroll(this.openmct.time.follow());
|
||||||
|
|
||||||
this.$scope.$on("$destroy", this.destroy);
|
this.$scope.$on("$destroy", this.destroy);
|
||||||
}
|
}
|
||||||
@ -122,7 +122,7 @@ define(
|
|||||||
|
|
||||||
if (timeSystem) {
|
if (timeSystem) {
|
||||||
this.table.columns.forEach(function (column) {
|
this.table.columns.forEach(function (column) {
|
||||||
if (column.getKey() === timeSystem.metadata.key) {
|
if (column.getKey() === timeSystem) {
|
||||||
sortColumn = column;
|
sortColumn = column;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -151,9 +151,9 @@ define(
|
|||||||
}.bind(this)
|
}.bind(this)
|
||||||
);
|
);
|
||||||
|
|
||||||
this.openmct.conductor.on('timeSystem', this.sortByTimeSystem);
|
this.openmct.time.on('timeSystem', this.sortByTimeSystem);
|
||||||
this.openmct.conductor.on('bounds', this.changeBounds);
|
this.openmct.time.on('bounds', this.changeBounds);
|
||||||
this.openmct.conductor.on('follow', this.setScroll);
|
this.openmct.time.on('follow', this.setScroll);
|
||||||
|
|
||||||
this.telemetry.on('added', this.addRowsToTable);
|
this.telemetry.on('added', this.addRowsToTable);
|
||||||
this.telemetry.on('discarded', this.removeRowsFromTable);
|
this.telemetry.on('discarded', this.removeRowsFromTable);
|
||||||
@ -188,7 +188,7 @@ define(
|
|||||||
* @param {openmct.TimeConductorBounds~TimeConductorBounds} bounds
|
* @param {openmct.TimeConductorBounds~TimeConductorBounds} bounds
|
||||||
*/
|
*/
|
||||||
TelemetryTableController.prototype.changeBounds = function (bounds) {
|
TelemetryTableController.prototype.changeBounds = function (bounds) {
|
||||||
var follow = this.openmct.conductor.follow();
|
var follow = this.openmct.time.follow();
|
||||||
var isTick = follow &&
|
var isTick = follow &&
|
||||||
bounds.start !== this.lastBounds.start &&
|
bounds.start !== this.lastBounds.start &&
|
||||||
bounds.end !== this.lastBounds.end;
|
bounds.end !== this.lastBounds.end;
|
||||||
@ -207,9 +207,9 @@ define(
|
|||||||
*/
|
*/
|
||||||
TelemetryTableController.prototype.destroy = function () {
|
TelemetryTableController.prototype.destroy = function () {
|
||||||
|
|
||||||
this.openmct.conductor.off('timeSystem', this.sortByTimeSystem);
|
this.openmct.time.off('timeSystem', this.sortByTimeSystem);
|
||||||
this.openmct.conductor.off('bounds', this.changeBounds);
|
this.openmct.time.off('bounds', this.changeBounds);
|
||||||
this.openmct.conductor.off('follow', this.setScroll);
|
this.openmct.time.off('follow', this.setScroll);
|
||||||
|
|
||||||
this.subscriptions.forEach(function (subscription) {
|
this.subscriptions.forEach(function (subscription) {
|
||||||
subscription();
|
subscription();
|
||||||
@ -260,7 +260,7 @@ define(
|
|||||||
// if data matches selected time system
|
// if data matches selected time system
|
||||||
this.telemetry.sort(undefined);
|
this.telemetry.sort(undefined);
|
||||||
|
|
||||||
var timeSystem = this.openmct.conductor.timeSystem();
|
var timeSystem = this.openmct.time.timeSystem();
|
||||||
if (timeSystem) {
|
if (timeSystem) {
|
||||||
this.sortByTimeSystem(timeSystem);
|
this.sortByTimeSystem(timeSystem);
|
||||||
}
|
}
|
||||||
@ -278,7 +278,7 @@ define(
|
|||||||
TelemetryTableController.prototype.getHistoricalData = function (objects) {
|
TelemetryTableController.prototype.getHistoricalData = function (objects) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var openmct = this.openmct;
|
var openmct = this.openmct;
|
||||||
var bounds = openmct.conductor.bounds();
|
var bounds = openmct.time.bounds();
|
||||||
var scope = this.$scope;
|
var scope = this.$scope;
|
||||||
var rowData = [];
|
var rowData = [];
|
||||||
var processedObjects = 0;
|
var processedObjects = 0;
|
||||||
@ -432,7 +432,7 @@ define(
|
|||||||
var scope = this.$scope;
|
var scope = this.$scope;
|
||||||
|
|
||||||
this.telemetry.clear();
|
this.telemetry.clear();
|
||||||
this.telemetry.bounds(this.openmct.conductor.bounds());
|
this.telemetry.bounds(this.openmct.time.bounds());
|
||||||
|
|
||||||
this.$scope.loading = true;
|
this.$scope.loading = true;
|
||||||
|
|
||||||
|
@ -163,15 +163,15 @@ define(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (request.start === undefined && request.end === undefined) {
|
if (request.start === undefined && request.end === undefined) {
|
||||||
bounds = this.openmct.conductor.bounds();
|
bounds = this.openmct.time.bounds();
|
||||||
fullRequest.start = bounds.start;
|
fullRequest.start = bounds.start;
|
||||||
fullRequest.end = bounds.end;
|
fullRequest.end = bounds.end;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request.domain === undefined) {
|
if (request.domain === undefined) {
|
||||||
timeSystem = this.openmct.conductor.timeSystem();
|
timeSystem = this.openmct.time.timeSystem();
|
||||||
if (timeSystem !== undefined) {
|
if (timeSystem !== undefined) {
|
||||||
fullRequest.domain = timeSystem.metadata.key;
|
fullRequest.domain = timeSystem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,7 +83,7 @@ define([
|
|||||||
* @memberof module:openmct.MCT#
|
* @memberof module:openmct.MCT#
|
||||||
* @name conductor
|
* @name conductor
|
||||||
*/
|
*/
|
||||||
this.conductor = new api.TimeConductor();
|
this.time = new api.TimeAPI();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An interface for interacting with the composition of domain objects.
|
* An interface for interacting with the composition of domain objects.
|
||||||
|
@ -1,122 +0,0 @@
|
|||||||
/*****************************************************************************
|
|
||||||
* Open MCT, Copyright (c) 2014-2016, United States Government
|
|
||||||
* as represented by the Administrator of the National Aeronautics and Space
|
|
||||||
* Administration. All rights reserved.
|
|
||||||
*
|
|
||||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
|
||||||
* "License"); you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
* License for the specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*
|
|
||||||
* Open MCT includes source code licensed under additional open source
|
|
||||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
|
||||||
* this source code distribution or the Licensing information page available
|
|
||||||
* at runtime from the About dialog for additional information.
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
define(['./TimeConductor'], function (TimeConductor) {
|
|
||||||
describe("The Time Conductor", function () {
|
|
||||||
var tc,
|
|
||||||
timeSystem,
|
|
||||||
bounds,
|
|
||||||
eventListener,
|
|
||||||
toi,
|
|
||||||
follow;
|
|
||||||
|
|
||||||
beforeEach(function () {
|
|
||||||
tc = new TimeConductor();
|
|
||||||
timeSystem = {};
|
|
||||||
bounds = {start: 0, end: 0};
|
|
||||||
eventListener = jasmine.createSpy("eventListener");
|
|
||||||
toi = 111;
|
|
||||||
follow = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Supports setting and querying of time of interest and and follow mode", function () {
|
|
||||||
expect(tc.timeOfInterest()).not.toBe(toi);
|
|
||||||
tc.timeOfInterest(toi);
|
|
||||||
expect(tc.timeOfInterest()).toBe(toi);
|
|
||||||
|
|
||||||
expect(tc.follow()).not.toBe(follow);
|
|
||||||
tc.follow(follow);
|
|
||||||
expect(tc.follow()).toBe(follow);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Allows setting of valid bounds", function () {
|
|
||||||
bounds = {start: 0, end: 1};
|
|
||||||
expect(tc.bounds()).not.toBe(bounds);
|
|
||||||
expect(tc.bounds.bind(tc, bounds)).not.toThrow();
|
|
||||||
expect(tc.bounds()).toEqual(bounds);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Disallows setting of invalid bounds", function () {
|
|
||||||
bounds = {start: 1, end: 0};
|
|
||||||
expect(tc.bounds()).not.toEqual(bounds);
|
|
||||||
expect(tc.bounds.bind(tc, bounds)).toThrow();
|
|
||||||
expect(tc.bounds()).not.toEqual(bounds);
|
|
||||||
|
|
||||||
bounds = {start: 1};
|
|
||||||
expect(tc.bounds()).not.toEqual(bounds);
|
|
||||||
expect(tc.bounds.bind(tc, bounds)).toThrow();
|
|
||||||
expect(tc.bounds()).not.toEqual(bounds);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Allows setting of time system with bounds", function () {
|
|
||||||
expect(tc.timeSystem()).not.toBe(timeSystem);
|
|
||||||
expect(tc.timeSystem.bind(tc, timeSystem, bounds)).not.toThrow();
|
|
||||||
expect(tc.timeSystem()).toBe(timeSystem);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Disallows setting of time system without bounds", function () {
|
|
||||||
expect(tc.timeSystem()).not.toBe(timeSystem);
|
|
||||||
expect(tc.timeSystem.bind(tc, timeSystem)).toThrow();
|
|
||||||
expect(tc.timeSystem()).not.toBe(timeSystem);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Emits an event when time system changes", function () {
|
|
||||||
expect(eventListener).not.toHaveBeenCalled();
|
|
||||||
tc.on("timeSystem", eventListener);
|
|
||||||
tc.timeSystem(timeSystem, bounds);
|
|
||||||
expect(eventListener).toHaveBeenCalledWith(timeSystem);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Emits an event when time of interest changes", function () {
|
|
||||||
expect(eventListener).not.toHaveBeenCalled();
|
|
||||||
tc.on("timeOfInterest", eventListener);
|
|
||||||
tc.timeOfInterest(toi);
|
|
||||||
expect(eventListener).toHaveBeenCalledWith(toi);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Emits an event when bounds change", function () {
|
|
||||||
expect(eventListener).not.toHaveBeenCalled();
|
|
||||||
tc.on("bounds", eventListener);
|
|
||||||
tc.bounds(bounds);
|
|
||||||
expect(eventListener).toHaveBeenCalledWith(bounds);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Emits an event when follow mode changes", function () {
|
|
||||||
expect(eventListener).not.toHaveBeenCalled();
|
|
||||||
tc.on("follow", eventListener);
|
|
||||||
tc.follow(follow);
|
|
||||||
expect(eventListener).toHaveBeenCalledWith(follow);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("If bounds are set and TOI lies inside them, do not change TOI", function () {
|
|
||||||
tc.timeOfInterest(6);
|
|
||||||
tc.bounds({start: 1, end: 10});
|
|
||||||
expect(tc.timeOfInterest()).toEqual(6);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("If bounds are set and TOI lies outside them, reset TOI", function () {
|
|
||||||
tc.timeOfInterest(11);
|
|
||||||
tc.bounds({start: 1, end: 10});
|
|
||||||
expect(tc.timeOfInterest()).toBeUndefined();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
@ -21,7 +21,7 @@
|
|||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define([
|
define([
|
||||||
'./TimeConductor',
|
'./time/TimeAPI',
|
||||||
'./objects/ObjectAPI',
|
'./objects/ObjectAPI',
|
||||||
'./composition/CompositionAPI',
|
'./composition/CompositionAPI',
|
||||||
'./types/TypeRegistry',
|
'./types/TypeRegistry',
|
||||||
@ -29,7 +29,7 @@ define([
|
|||||||
'./ui/GestureAPI',
|
'./ui/GestureAPI',
|
||||||
'./telemetry/TelemetryAPI'
|
'./telemetry/TelemetryAPI'
|
||||||
], function (
|
], function (
|
||||||
TimeConductor,
|
TimeAPI,
|
||||||
ObjectAPI,
|
ObjectAPI,
|
||||||
CompositionAPI,
|
CompositionAPI,
|
||||||
TypeRegistry,
|
TypeRegistry,
|
||||||
@ -38,7 +38,7 @@ define([
|
|||||||
TelemetryAPI
|
TelemetryAPI
|
||||||
) {
|
) {
|
||||||
return {
|
return {
|
||||||
TimeConductor: TimeConductor,
|
TimeAPI: TimeAPI,
|
||||||
ObjectAPI: ObjectAPI,
|
ObjectAPI: ObjectAPI,
|
||||||
CompositionAPI: CompositionAPI,
|
CompositionAPI: CompositionAPI,
|
||||||
Dialog: Dialog,
|
Dialog: Dialog,
|
||||||
|
@ -22,6 +22,8 @@
|
|||||||
|
|
||||||
define(['EventEmitter'], function (EventEmitter) {
|
define(['EventEmitter'], function (EventEmitter) {
|
||||||
|
|
||||||
|
var tick;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The public API for setting and querying time conductor state. The
|
* The public API for setting and querying time conductor state. The
|
||||||
* time conductor is the means by which the temporal bounds of a view
|
* time conductor is the means by which the temporal bounds of a view
|
||||||
@ -35,7 +37,7 @@ define(['EventEmitter'], function (EventEmitter) {
|
|||||||
* @interface
|
* @interface
|
||||||
* @memberof module:openmct
|
* @memberof module:openmct
|
||||||
*/
|
*/
|
||||||
function TimeConductor() {
|
function TimeAPI() {
|
||||||
EventEmitter.call(this);
|
EventEmitter.call(this);
|
||||||
|
|
||||||
//The Time System
|
//The Time System
|
||||||
@ -48,21 +50,68 @@ define(['EventEmitter'], function (EventEmitter) {
|
|||||||
end: undefined
|
end: undefined
|
||||||
};
|
};
|
||||||
|
|
||||||
//Default to fixed mode
|
this.timeSystems = new Map();
|
||||||
this.followMode = false;
|
this.clocks = new Map();
|
||||||
|
this.activeClock = undefined;
|
||||||
|
this.offsets = undefined;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tick is not exposed via public API, even @privately to avoid misuse.
|
||||||
|
*/
|
||||||
|
|
||||||
|
tick = function (timestamp) {
|
||||||
|
var newBounds = {
|
||||||
|
start: timestamp + this.offsets.start,
|
||||||
|
end: timestamp + this.offsets.end
|
||||||
|
};
|
||||||
|
|
||||||
|
this.boundsVal = newBounds;
|
||||||
|
this.emit('bounds', this.boundsVal, true);
|
||||||
|
|
||||||
|
// If a bounds change results in a TOI outside of the current
|
||||||
|
// bounds, unset it
|
||||||
|
if (this.toi < newBounds.start || this.toi > newBounds.end) {
|
||||||
|
this.timeOfInterest(undefined);
|
||||||
|
}
|
||||||
|
}.bind(this);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TimeConductor.prototype = Object.create(EventEmitter.prototype);
|
TimeAPI.prototype = Object.create(EventEmitter.prototype);
|
||||||
|
|
||||||
|
TimeAPI.prototype.addTimeSystem = function (timeSystem) {
|
||||||
|
this.timeSystems.set(timeSystem.key, timeSystem);
|
||||||
|
};
|
||||||
|
|
||||||
|
TimeAPI.prototype.availableTimeSystems = function (key) {
|
||||||
|
return Array.from(this.timeSystems.values());
|
||||||
|
}
|
||||||
|
|
||||||
|
TimeAPI.prototype.getTimeSystem = function (key) {
|
||||||
|
return this.timeSystems.get(key);
|
||||||
|
};
|
||||||
|
|
||||||
|
TimeAPI.prototype.addClock = function (clock) {
|
||||||
|
this.clocks.set(clock.key, clock);
|
||||||
|
};
|
||||||
|
|
||||||
|
TimeAPI.prototype.getClock = function (key) {
|
||||||
|
return this.clocks.get(key);
|
||||||
|
};
|
||||||
|
|
||||||
|
TimeAPI.prototype.availableClocks = function (key) {
|
||||||
|
return Array.from(this.availableClocks.values());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validate the given bounds. This can be used for pre-validation of
|
* Validate the given bounds. This can be used for pre-validation of
|
||||||
* bounds, for example by views validating user inputs.
|
* bounds, for example by views validating user inputs.
|
||||||
* @param bounds The start and end time of the conductor.
|
* @param bounds The start and end time of the conductor.
|
||||||
* @returns {string | true} A validation error, or true if valid
|
* @returns {string | true} A validation error, or true if valid
|
||||||
* @memberof module:openmct.TimeConductor#
|
* @memberof module:openmct.TimeAPI#
|
||||||
* @method validateBounds
|
* @method validateBounds
|
||||||
*/
|
*/
|
||||||
TimeConductor.prototype.validateBounds = function (bounds) {
|
TimeAPI.prototype.validateBounds = function (bounds) {
|
||||||
if ((bounds.start === undefined) ||
|
if ((bounds.start === undefined) ||
|
||||||
(bounds.end === undefined) ||
|
(bounds.end === undefined) ||
|
||||||
isNaN(bounds.start) ||
|
isNaN(bounds.start) ||
|
||||||
@ -75,51 +124,25 @@ define(['EventEmitter'], function (EventEmitter) {
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Get or set the follow mode of the time conductor. In follow mode the
|
|
||||||
* time conductor ticks, regularly updating the bounds from a timing
|
|
||||||
* source appropriate to the selected time system and mode of the time
|
|
||||||
* conductor.
|
|
||||||
* @fires module:openmct.TimeConductor~follow
|
|
||||||
* @param {boolean} followMode
|
|
||||||
* @returns {boolean}
|
|
||||||
* @memberof module:openmct.TimeConductor#
|
|
||||||
* @method follow
|
|
||||||
*/
|
|
||||||
TimeConductor.prototype.follow = function (followMode) {
|
|
||||||
if (arguments.length > 0) {
|
|
||||||
this.followMode = followMode;
|
|
||||||
/**
|
|
||||||
* The TimeConductor has toggled into or out of follow mode.
|
|
||||||
* @event follow
|
|
||||||
* @memberof module:openmct.TimeConductor~
|
|
||||||
* @property {boolean} followMode true if follow mode is
|
|
||||||
* enabled, otherwise false.
|
|
||||||
*/
|
|
||||||
this.emit('follow', this.followMode);
|
|
||||||
}
|
|
||||||
return this.followMode;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {Object} TimeConductorBounds
|
* @typedef {Object} TimeConductorBounds
|
||||||
* @property {number} start The start time displayed by the time conductor in ms since epoch. Epoch determined by current time system
|
* @property {number} start The start time displayed by the time conductor in ms since epoch. Epoch determined by current time system
|
||||||
* @property {number} end The end time displayed by the time conductor in ms since epoch.
|
* @property {number} end The end time displayed by the time conductor in ms since epoch.
|
||||||
* @memberof module:openmct.TimeConductor~
|
* @memberof module:openmct.TimeAPI~
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get or set the start and end time of the time conductor. Basic validation
|
* Get or set the start and end time of the time conductor. Basic validation
|
||||||
* of bounds is performed.
|
* of bounds is performed.
|
||||||
*
|
*
|
||||||
* @param {module:openmct.TimeConductorBounds~TimeConductorBounds} newBounds
|
* @param {module:openmct.TimeAPI~TimeConductorBounds} newBounds
|
||||||
* @throws {Error} Validation error
|
* @throws {Error} Validation error
|
||||||
* @fires module:openmct.TimeConductor~bounds
|
* @fires module:openmct.TimeAPI~bounds
|
||||||
* @returns {module:openmct.TimeConductorBounds~TimeConductorBounds}
|
* @returns {module:openmct.TimeAPI~TimeConductorBounds}
|
||||||
* @memberof module:openmct.TimeConductor#
|
* @memberof module:openmct.TimeAPI#
|
||||||
* @method bounds
|
* @method bounds
|
||||||
*/
|
*/
|
||||||
TimeConductor.prototype.bounds = function (newBounds) {
|
TimeAPI.prototype.bounds = function (newBounds) {
|
||||||
if (arguments.length > 0) {
|
if (arguments.length > 0) {
|
||||||
var validationResult = this.validateBounds(newBounds);
|
var validationResult = this.validateBounds(newBounds);
|
||||||
if (validationResult !== true) {
|
if (validationResult !== true) {
|
||||||
@ -130,10 +153,12 @@ define(['EventEmitter'], function (EventEmitter) {
|
|||||||
/**
|
/**
|
||||||
* The start time, end time, or both have been updated.
|
* The start time, end time, or both have been updated.
|
||||||
* @event bounds
|
* @event bounds
|
||||||
* @memberof module:openmct.TimeConductor~
|
* @memberof module:openmct.TimeAPI~
|
||||||
* @property {TimeConductorBounds} bounds
|
* @property {TimeConductorBounds} bounds The newly updated bounds
|
||||||
|
* @property {boolean} [tick] `true` if the bounds update was due to
|
||||||
|
* a "tick" event (ie. was an automatic update), false otherwise.
|
||||||
*/
|
*/
|
||||||
this.emit('bounds', this.boundsVal);
|
this.emit('bounds', this.boundsVal, false);
|
||||||
|
|
||||||
// If a bounds change results in a TOI outside of the current
|
// If a bounds change results in a TOI outside of the current
|
||||||
// bounds, unset it
|
// bounds, unset it
|
||||||
@ -146,34 +171,40 @@ define(['EventEmitter'], function (EventEmitter) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get or set the time system of the TimeConductor. Time systems determine
|
* Get or set the time system of the TimeAPI. Time systems determine
|
||||||
* units, epoch, and other aspects of time representation. When changing
|
* units, epoch, and other aspects of time representation. When changing
|
||||||
* the time system in use, new valid bounds must also be provided.
|
* the time system in use, new valid bounds must also be provided.
|
||||||
* @param {TimeSystem} newTimeSystem
|
* @param {TimeSystem} newTimeSystem
|
||||||
* @param {module:openmct.TimeConductor~TimeConductorBounds} bounds
|
* @param {module:openmct.TimeAPI~TimeConductorBounds} bounds
|
||||||
* @fires module:openmct.TimeConductor~timeSystem
|
* @fires module:openmct.TimeAPI~timeSystem
|
||||||
* @returns {TimeSystem} The currently applied time system
|
* @returns {TimeSystem} The currently applied time system
|
||||||
* @memberof module:openmct.TimeConductor#
|
* @memberof module:openmct.TimeAPI#
|
||||||
* @method timeSystem
|
* @method timeSystem
|
||||||
*/
|
*/
|
||||||
TimeConductor.prototype.timeSystem = function (newTimeSystem, bounds) {
|
TimeAPI.prototype.timeSystem = function (newTimeSystem, bounds) {
|
||||||
if (arguments.length >= 2) {
|
if (arguments.length >= 2) {
|
||||||
this.system = newTimeSystem;
|
if (newTimeSystem === 'undefined') {
|
||||||
|
throw "Please provide a time system";
|
||||||
|
}
|
||||||
|
if (this.timeSystems.get(newTimeSystem) === undefined){
|
||||||
|
throw "Unknown time system " + newTimeSystem + ". Has it been registered with 'addTimeSystem'?";
|
||||||
|
}
|
||||||
|
this.system = this.timeSystems.get(newTimeSystem);
|
||||||
/**
|
/**
|
||||||
* The time system used by the time
|
* The time system used by the time
|
||||||
* conductor has changed. A change in Time System will always be
|
* conductor has changed. A change in Time System will always be
|
||||||
* followed by a bounds event specifying new query bounds.
|
* followed by a bounds event specifying new query bounds.
|
||||||
*
|
*
|
||||||
* @event module:openmct.TimeConductor~timeSystem
|
* @event module:openmct.TimeAPI~timeSystem
|
||||||
* @property {TimeSystem} The value of the currently applied
|
* @property {TimeSystem} The value of the currently applied
|
||||||
* Time System
|
* Time System
|
||||||
* */
|
* */
|
||||||
this.emit('timeSystem', this.system);
|
this.emit('timeSystem', this.system.key);
|
||||||
this.bounds(bounds);
|
this.bounds(bounds);
|
||||||
} else if (arguments.length === 1) {
|
} else if (arguments.length === 1) {
|
||||||
throw new Error('Must set bounds when changing time system');
|
throw new Error('Must set bounds when changing time system');
|
||||||
}
|
}
|
||||||
return this.system;
|
return this.system && this.system.key;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -181,19 +212,19 @@ define(['EventEmitter'], function (EventEmitter) {
|
|||||||
* focus of the current view. It can be manipulated by the user from the
|
* focus of the current view. It can be manipulated by the user from the
|
||||||
* time conductor or from other views.The time of interest can
|
* time conductor or from other views.The time of interest can
|
||||||
* effectively be unset by assigning a value of 'undefined'.
|
* effectively be unset by assigning a value of 'undefined'.
|
||||||
* @fires module:openmct.TimeConductor~timeOfInterest
|
* @fires module:openmct.TimeAPI~timeOfInterest
|
||||||
* @param newTOI
|
* @param newTOI
|
||||||
* @returns {number} the current time of interest
|
* @returns {number} the current time of interest
|
||||||
* @memberof module:openmct.TimeConductor#
|
* @memberof module:openmct.TimeAPI#
|
||||||
* @method timeOfInterest
|
* @method timeOfInterest
|
||||||
*/
|
*/
|
||||||
TimeConductor.prototype.timeOfInterest = function (newTOI) {
|
TimeAPI.prototype.timeOfInterest = function (newTOI) {
|
||||||
if (arguments.length > 0) {
|
if (arguments.length > 0) {
|
||||||
this.toi = newTOI;
|
this.toi = newTOI;
|
||||||
/**
|
/**
|
||||||
* The Time of Interest has moved.
|
* The Time of Interest has moved.
|
||||||
* @event timeOfInterest
|
* @event timeOfInterest
|
||||||
* @memberof module:openmct.TimeConductor~
|
* @memberof module:openmct.TimeAPI~
|
||||||
* @property {number} Current time of interest
|
* @property {number} Current time of interest
|
||||||
*/
|
*/
|
||||||
this.emit('timeOfInterest', this.toi);
|
this.emit('timeOfInterest', this.toi);
|
||||||
@ -201,5 +232,63 @@ define(['EventEmitter'], function (EventEmitter) {
|
|||||||
return this.toi;
|
return this.toi;
|
||||||
};
|
};
|
||||||
|
|
||||||
return TimeConductor;
|
/**
|
||||||
|
* Return the follow state of the Conductor.
|
||||||
|
* @returns {boolean} `true` if conductor is currently following a tick source.
|
||||||
|
* `false` otherwise.
|
||||||
|
*/
|
||||||
|
TimeAPI.prototype.follow = function () {
|
||||||
|
return this.activeClock !== undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the active clock. Tick source will be immediately subscribed to
|
||||||
|
* and ticking will begin. Offsets from 'now' must also be provided.
|
||||||
|
* @param {string} key the key of the tick source to activate
|
||||||
|
* @param {ClockOffsets} offsets on each tick these will be used to calculate
|
||||||
|
* the start and end bounds. This maintains a sliding time window of a fixed
|
||||||
|
* width that automatically updates.
|
||||||
|
*/
|
||||||
|
TimeAPI.prototype.clock = function (key, offsets) {
|
||||||
|
if (arguments.length === 2) {
|
||||||
|
if (!this.clocks.has(key)){
|
||||||
|
throw "Unknown clock '" + key + "'. Has it been registered with 'addClock'?";
|
||||||
|
}
|
||||||
|
if (this.activeClock !== undefined) {
|
||||||
|
this.activeClock.off("tick", tick);
|
||||||
|
} else {
|
||||||
|
this.emit("follow", true);
|
||||||
|
}
|
||||||
|
if (key !== undefined) {
|
||||||
|
this.activeClock = this.clocks.get(key);
|
||||||
|
this.offsets = offsets;
|
||||||
|
this.activeClock.on("tick", tick);
|
||||||
|
} else {
|
||||||
|
this.activeClock = undefined;
|
||||||
|
this.emit("follow", false);
|
||||||
|
}
|
||||||
|
} else if (arguments.length === 1){
|
||||||
|
throw "When setting clock, clock offsets must also be provided"
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.activeClock && this.activeClock.key;
|
||||||
|
};
|
||||||
|
|
||||||
|
TimeAPI.prototype.clockOffsets = function (offsets) {
|
||||||
|
if (arguments.length > 0) {
|
||||||
|
this.offsets = offsets;
|
||||||
|
this.emit("clockOffsets", offsets);
|
||||||
|
}
|
||||||
|
// TODO: Should setting clock offsets trigger a bounds event, or wait until next tick?
|
||||||
|
return this.offsets;
|
||||||
|
};
|
||||||
|
|
||||||
|
TimeAPI.prototype.stopClock = function () {
|
||||||
|
if (this.activeClock) {
|
||||||
|
this.activeClock.off("tick", tick);
|
||||||
|
this.activeClock = undefined;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return TimeAPI;
|
||||||
});
|
});
|
216
src/api/time/TimeAPISpec.js
Normal file
216
src/api/time/TimeAPISpec.js
Normal file
@ -0,0 +1,216 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT, Copyright (c) 2014-2016, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*
|
||||||
|
* Open MCT includes source code licensed under additional open source
|
||||||
|
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||||
|
* this source code distribution or the Licensing information page available
|
||||||
|
* at runtime from the About dialog for additional information.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
define(['./TimeAPI'], function (TimeAPI) {
|
||||||
|
describe("The Time API", function () {
|
||||||
|
var api,
|
||||||
|
timeSystemKey,
|
||||||
|
timeSystem,
|
||||||
|
bounds,
|
||||||
|
eventListener,
|
||||||
|
toi,
|
||||||
|
follow;
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
api = new TimeAPI();
|
||||||
|
timeSystemKey = "timeSystemKey";
|
||||||
|
timeSystem = {key: timeSystemKey};
|
||||||
|
bounds = {start: 0, end: 0};
|
||||||
|
eventListener = jasmine.createSpy("eventListener");
|
||||||
|
toi = 111;
|
||||||
|
follow = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Supports setting and querying of time of interest", function () {
|
||||||
|
expect(api.timeOfInterest()).not.toBe(toi);
|
||||||
|
api.timeOfInterest(toi);
|
||||||
|
expect(api.timeOfInterest()).toBe(toi);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Allows setting of valid bounds", function () {
|
||||||
|
bounds = {start: 0, end: 1};
|
||||||
|
expect(api.bounds()).not.toBe(bounds);
|
||||||
|
expect(api.bounds.bind(api, bounds)).not.toThrow();
|
||||||
|
expect(api.bounds()).toEqual(bounds);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Disallows setting of invalid bounds", function () {
|
||||||
|
bounds = {start: 1, end: 0};
|
||||||
|
expect(api.bounds()).not.toEqual(bounds);
|
||||||
|
expect(api.bounds.bind(api, bounds)).toThrow();
|
||||||
|
expect(api.bounds()).not.toEqual(bounds);
|
||||||
|
|
||||||
|
bounds = {start: 1};
|
||||||
|
expect(api.bounds()).not.toEqual(bounds);
|
||||||
|
expect(api.bounds.bind(api, bounds)).toThrow();
|
||||||
|
expect(api.bounds()).not.toEqual(bounds);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Allows setting of previously registered time system with bounds", function () {
|
||||||
|
api.addTimeSystem(timeSystem);
|
||||||
|
expect(api.timeSystem()).not.toBe(timeSystemKey);
|
||||||
|
expect(function() {
|
||||||
|
api.timeSystem(timeSystemKey, bounds);
|
||||||
|
}).not.toThrow();
|
||||||
|
expect(api.timeSystem()).toBe(timeSystemKey);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Disallows setting of time system without bounds", function () {
|
||||||
|
api.addTimeSystem(timeSystem);
|
||||||
|
expect(api.timeSystem()).not.toBe(timeSystemKey);
|
||||||
|
expect(function () {
|
||||||
|
api.timeSystem(timeSystemKey)
|
||||||
|
}).toThrow();
|
||||||
|
expect(api.timeSystem()).not.toBe(timeSystemKey);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Emits an event when time system changes", function () {
|
||||||
|
api.addTimeSystem(timeSystem);
|
||||||
|
expect(eventListener).not.toHaveBeenCalled();
|
||||||
|
api.on("timeSystem", eventListener);
|
||||||
|
api.timeSystem(timeSystemKey, bounds);
|
||||||
|
expect(eventListener).toHaveBeenCalledWith(timeSystemKey);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Emits an event when time of interest changes", function () {
|
||||||
|
expect(eventListener).not.toHaveBeenCalled();
|
||||||
|
api.on("timeOfInterest", eventListener);
|
||||||
|
api.timeOfInterest(toi);
|
||||||
|
expect(eventListener).toHaveBeenCalledWith(toi);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Emits an event when bounds change", function () {
|
||||||
|
expect(eventListener).not.toHaveBeenCalled();
|
||||||
|
api.on("bounds", eventListener);
|
||||||
|
api.bounds(bounds);
|
||||||
|
expect(eventListener).toHaveBeenCalledWith(bounds, false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("If bounds are set and TOI lies inside them, do not change TOI", function () {
|
||||||
|
api.timeOfInterest(6);
|
||||||
|
api.bounds({start: 1, end: 10});
|
||||||
|
expect(api.timeOfInterest()).toEqual(6);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("If bounds are set and TOI lies outside them, reset TOI", function () {
|
||||||
|
api.timeOfInterest(11);
|
||||||
|
api.bounds({start: 1, end: 10});
|
||||||
|
expect(api.timeOfInterest()).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Maintains delta during tick", function () {
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it("Allows registered time system to be activated", function () {
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Allows a registered tick source to be activated", function () {
|
||||||
|
var mockTickSource = jasmine.createSpyObj("mockTickSource", [
|
||||||
|
"on",
|
||||||
|
"off",
|
||||||
|
"currentValue"
|
||||||
|
]);
|
||||||
|
mockTickSource.key = 'mockTickSource'
|
||||||
|
});
|
||||||
|
|
||||||
|
describe(" when enabling a tick source", function () {
|
||||||
|
var mockTickSource;
|
||||||
|
var anotherMockTickSource;
|
||||||
|
var mockOffsets = {
|
||||||
|
start: 0,
|
||||||
|
end: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
mockTickSource = jasmine.createSpyObj("clock", [
|
||||||
|
"on",
|
||||||
|
"off"
|
||||||
|
]);
|
||||||
|
mockTickSource.key = "mts";
|
||||||
|
|
||||||
|
anotherMockTickSource = jasmine.createSpyObj("clock", [
|
||||||
|
"on",
|
||||||
|
"off"
|
||||||
|
]);
|
||||||
|
anotherMockTickSource.key = "amts";
|
||||||
|
|
||||||
|
api.addClock(mockTickSource);
|
||||||
|
api.addClock(anotherMockTickSource);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("a new tick listener is registered", function () {
|
||||||
|
api.clock("mts", mockOffsets);
|
||||||
|
expect(mockTickSource.on).toHaveBeenCalledWith("tick", jasmine.any(Function));
|
||||||
|
});
|
||||||
|
|
||||||
|
it("listener of existing tick source is reregistered", function () {
|
||||||
|
api.clock("mts", mockOffsets);
|
||||||
|
api.clock("amts", mockOffsets);
|
||||||
|
expect(mockTickSource.off).toHaveBeenCalledWith("tick", jasmine.any(Function));
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Follow correctly reflects whether the conductor is following a " +
|
||||||
|
"tick source", function () {
|
||||||
|
expect(api.follow()).toBe(false);
|
||||||
|
api.clock("mts", mockOffsets);
|
||||||
|
expect(api.follow()).toBe(true);
|
||||||
|
api.stopClock();
|
||||||
|
expect(api.follow()).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("emits an event when follow mode changes", function () {
|
||||||
|
var callback = jasmine.createSpy("followCallback");
|
||||||
|
expect(api.follow()).toBe(false);
|
||||||
|
|
||||||
|
api.on("follow", callback);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it("on tick, observes deltas, and indicates tick in bounds callback", function () {
|
||||||
|
var mockTickSource = jasmine.createSpyObj("clock", [
|
||||||
|
"on",
|
||||||
|
"off"
|
||||||
|
]);
|
||||||
|
var tickCallback;
|
||||||
|
var boundsCallback = jasmine.createSpy("boundsCallback");
|
||||||
|
var clockOffsets = {
|
||||||
|
start: -100,
|
||||||
|
end: 100
|
||||||
|
};
|
||||||
|
mockTickSource.key = "mts";
|
||||||
|
|
||||||
|
api.addClock(mockTickSource);
|
||||||
|
api.clock("mts", clockOffsets);
|
||||||
|
|
||||||
|
api.on("bounds", boundsCallback);
|
||||||
|
|
||||||
|
tickCallback = mockTickSource.on.mostRecentCall.args[1]
|
||||||
|
tickCallback(1000);
|
||||||
|
expect(boundsCallback).toHaveBeenCalledWith({
|
||||||
|
start: 900,
|
||||||
|
end: 1100
|
||||||
|
}, true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -68,7 +68,6 @@ define([
|
|||||||
'../platform/features/fixed/bundle',
|
'../platform/features/fixed/bundle',
|
||||||
'../platform/features/conductor/core/bundle',
|
'../platform/features/conductor/core/bundle',
|
||||||
'../platform/features/conductor/compatibility/bundle',
|
'../platform/features/conductor/compatibility/bundle',
|
||||||
'../platform/features/conductor/utcTimeSystem/bundle',
|
|
||||||
'../platform/features/imagery/bundle',
|
'../platform/features/imagery/bundle',
|
||||||
'../platform/features/layout/bundle',
|
'../platform/features/layout/bundle',
|
||||||
'../platform/features/my-items/bundle',
|
'../platform/features/my-items/bundle',
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
define([
|
define([
|
||||||
'lodash',
|
'lodash',
|
||||||
'../../platform/features/conductor/utcTimeSystem/src/UTCTimeSystem',
|
'./utcTimeSystem/plugin',
|
||||||
'../../example/generator/plugin',
|
'../../example/generator/plugin',
|
||||||
'../../platform/features/autoflow/plugin'
|
'../../platform/features/autoflow/plugin'
|
||||||
], function (
|
], function (
|
||||||
@ -48,14 +48,7 @@ define([
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
plugins.UTCTimeSystem = function () {
|
plugins.UTCTimeSystem = UTCTimeSystem;
|
||||||
return function (openmct) {
|
|
||||||
openmct.legacyExtension("timeSystems", {
|
|
||||||
"implementation": UTCTimeSystem,
|
|
||||||
"depends": ["$timeout"]
|
|
||||||
});
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A tabular view showing the latest values of multiple telemetry points at
|
* A tabular view showing the latest values of multiple telemetry points at
|
||||||
@ -68,48 +61,25 @@ define([
|
|||||||
*/
|
*/
|
||||||
plugins.AutoflowView = AutoflowPlugin;
|
plugins.AutoflowView = AutoflowPlugin;
|
||||||
|
|
||||||
var conductorInstalled = false;
|
plugins.Conductor = function (config) {
|
||||||
|
/*
|
||||||
plugins.Conductor = function (options) {
|
{
|
||||||
if (!options) {
|
// Default 'fixed' configuration shows last 30 mins of data. May also provide specific bounds.
|
||||||
options = {};
|
{timeSystems: ['utc'], defaultDeltas: {start: 30 * ONE_MINUTE, end: 0}, zoomOutLimit: ONE_YEAR, zoomInLimit: ONE_MINUTE},
|
||||||
|
// Some tick source driven menu options
|
||||||
|
{clock: 'localClock', timeSystems: ['utc'], defaultDeltas: {start: 15 * ONE_MINUTE, end: 0}, zoomOutLimit: ONE_YEAR, zoomInLimit: ONE_MINUTE},
|
||||||
|
{clock: 'latestAvailable', timeSystems: ['utc'], defaultDeltas: {start: 15 * 60 * 1000, end: 0}}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
function applyDefaults(openmct, timeConductorViewService) {
|
|
||||||
var defaults = {};
|
|
||||||
var timeSystem = timeConductorViewService.systems.find(function (ts) {
|
|
||||||
return ts.metadata.key === options.defaultTimeSystem;
|
|
||||||
});
|
|
||||||
if (timeSystem !== undefined) {
|
|
||||||
openmct.conductor.timeSystem(timeSystem, defaults.bounds);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return function (openmct) {
|
return function (openmct) {
|
||||||
openmct.legacyExtension('constants', {
|
openmct.legacyExtension('constants', {
|
||||||
key: 'DEFAULT_TIMECONDUCTOR_MODE',
|
key: 'CONDUCTOR_CONFIG',
|
||||||
value: options.showConductor ? 'fixed' : 'realtime',
|
value: config,
|
||||||
priority: conductorInstalled ? 'mandatory' : 'fallback'
|
priority: 'mandatory'
|
||||||
});
|
});
|
||||||
if (options.showConductor !== undefined) {
|
|
||||||
openmct.legacyExtension('constants', {
|
|
||||||
key: 'SHOW_TIMECONDUCTOR',
|
|
||||||
value: options.showConductor,
|
|
||||||
priority: conductorInstalled ? 'mandatory' : 'fallback'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (options.defaultTimeSystem !== undefined || options.defaultTimespan !== undefined) {
|
|
||||||
openmct.legacyExtension('runs', {
|
|
||||||
implementation: applyDefaults,
|
|
||||||
depends: ["openmct", "timeConductorViewService"]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!conductorInstalled) {
|
openmct.legacyRegistry.enable('platform/features/conductor/core');
|
||||||
openmct.legacyRegistry.enable('platform/features/conductor/core');
|
openmct.legacyRegistry.enable('platform/features/conductor/compatibility');
|
||||||
openmct.legacyRegistry.enable('platform/features/conductor/compatibility');
|
|
||||||
}
|
|
||||||
conductorInstalled = true;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -20,46 +20,53 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define(['./TickSource'], function (TickSource) {
|
define(['EventEmitter'], function (EventEmitter) {
|
||||||
/**
|
/**
|
||||||
* @implements TickSource
|
* @implements TickSource
|
||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
function LocalClock($timeout, period) {
|
function LocalClock(period) {
|
||||||
TickSource.call(this);
|
EventEmitter.call(this);
|
||||||
|
|
||||||
this.metadata = {
|
/*
|
||||||
key: 'local',
|
Metadata fields
|
||||||
mode: 'realtime',
|
*/
|
||||||
cssClass: 'icon-clock',
|
this.key = 'local';
|
||||||
label: 'Real-time',
|
this.mode = 'realtime';
|
||||||
name: 'Real-time Mode',
|
this.cssClass = 'icon-clock';
|
||||||
description: 'Monitor real-time streaming data as it comes in. The Time Conductor and displays will automatically advance themselves based on a UTC clock.'
|
this.label = 'Real-time';
|
||||||
};
|
this.name = 'Real-time Mode';
|
||||||
|
this.description = 'Monitor real-time streaming data as it comes in. The ' +
|
||||||
|
'Time Conductor and displays will automatically advance themselves ' +
|
||||||
|
'based on a UTC clock.';
|
||||||
|
|
||||||
this.period = period;
|
this.period = period;
|
||||||
this.$timeout = $timeout;
|
|
||||||
this.timeoutHandle = undefined;
|
this.timeoutHandle = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
LocalClock.prototype = Object.create(TickSource.prototype);
|
LocalClock.prototype = Object.create(EventEmitter.prototype);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
LocalClock.prototype.start = function () {
|
LocalClock.prototype.start = function () {
|
||||||
this.timeoutHandle = this.$timeout(this.tick.bind(this), this.period);
|
this.timeoutHandle = setTimeout(this.tick.bind(this), this.period);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
LocalClock.prototype.stop = function () {
|
LocalClock.prototype.stop = function () {
|
||||||
if (this.timeoutHandle) {
|
if (this.timeoutHandle) {
|
||||||
this.$timeout.cancel(this.timeoutHandle);
|
clearTimeout(this.timeoutHandle);
|
||||||
|
this.timeoutHandle = undefined;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
LocalClock.prototype.tick = function () {
|
LocalClock.prototype.tick = function () {
|
||||||
var now = Date.now();
|
var now = Date.now();
|
||||||
this.listeners.forEach(function (listener) {
|
this.emit("tick", now);
|
||||||
listener(now);
|
this.timeoutHandle = setTimeout(this.tick.bind(this), this.period);
|
||||||
});
|
|
||||||
this.timeoutHandle = this.$timeout(this.tick.bind(this), this.period);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -69,20 +76,30 @@ define(['./TickSource'], function (TickSource) {
|
|||||||
* @param listener
|
* @param listener
|
||||||
* @returns {function} a function for deregistering the provided listener
|
* @returns {function} a function for deregistering the provided listener
|
||||||
*/
|
*/
|
||||||
LocalClock.prototype.listen = function (listener) {
|
LocalClock.prototype.on = function (event, listener) {
|
||||||
var listeners = this.listeners;
|
var result = this.on.apply(this, arguments);
|
||||||
listeners.push(listener);
|
|
||||||
|
|
||||||
if (listeners.length === 1) {
|
if (this.listeners(event).length === 1) {
|
||||||
this.start();
|
this.start();
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
return function () {
|
/**
|
||||||
listeners.splice(listeners.indexOf(listener));
|
* Register a listener for the local clock. When it ticks, the local
|
||||||
if (listeners.length === 0) {
|
* clock will provide the current local system time
|
||||||
this.stop();
|
*
|
||||||
}
|
* @param listener
|
||||||
}.bind(this);
|
* @returns {function} a function for deregistering the provided listener
|
||||||
|
*/
|
||||||
|
LocalClock.prototype.off = function (event, listener) {
|
||||||
|
var result = this.off.apply(this, arguments);
|
||||||
|
|
||||||
|
if (this.listeners(event).length === 0) {
|
||||||
|
this.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
return LocalClock;
|
return LocalClock;
|
@ -20,38 +20,28 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define([
|
define([], function () {
|
||||||
'../../core/src/timeSystems/TimeSystem',
|
var FIFTEEN_MINUTES = 15 * 60 * 1000;
|
||||||
'../../core/src/timeSystems/LocalClock'
|
|
||||||
], function (TimeSystem, LocalClock) {
|
|
||||||
var FIFTEEN_MINUTES = 15 * 60 * 1000,
|
|
||||||
DEFAULT_PERIOD = 100;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This time system supports UTC dates and provides a ticking clock source.
|
* This time system supports UTC dates and provides a ticking clock source.
|
||||||
* @implements TimeSystem
|
* @implements TimeSystem
|
||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
function UTCTimeSystem($timeout) {
|
function UTCTimeSystem() {
|
||||||
TimeSystem.call(this);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Some metadata, which will be used to identify the time system in
|
* Some metadata, which will be used to identify the time system in
|
||||||
* the UI
|
* the UI
|
||||||
* @type {{key: string, name: string, cssClass: string}}
|
* @type {{key: string, name: string, cssClass: string}}
|
||||||
*/
|
*/
|
||||||
this.metadata = {
|
this.key = 'utc';
|
||||||
'key': 'utc',
|
this.name = 'UTC';
|
||||||
'name': 'UTC',
|
this.cssClass = 'icon-clock';
|
||||||
'cssClass': 'icon-clock'
|
|
||||||
};
|
|
||||||
|
|
||||||
this.fmts = ['utc'];
|
this.fmts = ['utc'];
|
||||||
this.sources = [new LocalClock($timeout, DEFAULT_PERIOD)];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
UTCTimeSystem.prototype = Object.create(TimeSystem.prototype);
|
|
||||||
|
|
||||||
UTCTimeSystem.prototype.formats = function () {
|
UTCTimeSystem.prototype.formats = function () {
|
||||||
return this.fmts;
|
return this.fmts;
|
||||||
};
|
};
|
||||||
@ -60,8 +50,8 @@ define([
|
|||||||
return 'duration';
|
return 'duration';
|
||||||
};
|
};
|
||||||
|
|
||||||
UTCTimeSystem.prototype.tickSources = function () {
|
UTCTimeSystem.prototype.isUTCBased = function () {
|
||||||
return this.sources;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
UTCTimeSystem.prototype.defaults = function () {
|
UTCTimeSystem.prototype.defaults = function () {
|
@ -21,20 +21,16 @@
|
|||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define([
|
define([
|
||||||
"./src/UTCTimeSystem",
|
"./UTCTimeSystem",
|
||||||
"legacyRegistry"
|
"./LocalClock"
|
||||||
], function (
|
], function (
|
||||||
UTCTimeSystem,
|
UTCTimeSystem,
|
||||||
legacyRegistry
|
LocalClock
|
||||||
) {
|
) {
|
||||||
legacyRegistry.register("platform/features/conductor/utcTimeSystem", {
|
return function () {
|
||||||
"extensions": {
|
return function (openmct) {
|
||||||
"timeSystems": [
|
openmct.time.addTimeSystem(new UTCTimeSystem());
|
||||||
{
|
openmct.time.addClock(new LocalClock());
|
||||||
"implementation": UTCTimeSystem,
|
|
||||||
"depends": ["$timeout"]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
});
|
});
|
Reference in New Issue
Block a user