mirror of
https://github.com/nasa/openmct.git
synced 2025-06-13 12:48:14 +00:00
Refactored out modes, time systems, etc.
This commit is contained in:
@ -22,8 +22,9 @@
|
|||||||
|
|
||||||
define([
|
define([
|
||||||
"./src/TimeConductor",
|
"./src/TimeConductor",
|
||||||
"./src/TimeConductorController",
|
"./src/ui/TimeConductorController",
|
||||||
"./src/MCTConductorAxis",
|
"./src/ui/MCTConductorAxis",
|
||||||
|
"./src/timeSystems/UTCTimeSystem",
|
||||||
"text!./res/templates/time-conductor.html",
|
"text!./res/templates/time-conductor.html",
|
||||||
"text!./res/templates/mode-selector/mode-selector.html",
|
"text!./res/templates/mode-selector/mode-selector.html",
|
||||||
"text!./res/templates/mode-selector/mode-menu.html",
|
"text!./res/templates/mode-selector/mode-menu.html",
|
||||||
@ -32,6 +33,7 @@ define([
|
|||||||
TimeConductor,
|
TimeConductor,
|
||||||
TimeConductorController,
|
TimeConductorController,
|
||||||
MCTConductorAxis,
|
MCTConductorAxis,
|
||||||
|
UTCTimeSystem,
|
||||||
timeConductorTemplate,
|
timeConductorTemplate,
|
||||||
modeSelectorTemplate,
|
modeSelectorTemplate,
|
||||||
modeMenuTemplate,
|
modeMenuTemplate,
|
||||||
@ -52,8 +54,8 @@ define([
|
|||||||
"implementation": TimeConductorController,
|
"implementation": TimeConductorController,
|
||||||
"depends": [
|
"depends": [
|
||||||
"$scope",
|
"$scope",
|
||||||
"$timeout",
|
"timeConductor",
|
||||||
"timeConductor"
|
"timeSystems[]"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -79,6 +81,12 @@ define([
|
|||||||
"key": "mode-menu",
|
"key": "mode-menu",
|
||||||
"template": modeMenuTemplate
|
"template": modeMenuTemplate
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
"timeSystems": [
|
||||||
|
{
|
||||||
|
"implementation": UTCTimeSystem,
|
||||||
|
"depends": ["$timeout"]
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -22,15 +22,15 @@
|
|||||||
<div class="contents">
|
<div class="contents">
|
||||||
<div class="pane left menu-items">
|
<div class="pane left menu-items">
|
||||||
<ul>
|
<ul>
|
||||||
<li ng-repeat="(selected, option) in ngModel.options"
|
<li ng-repeat="option in ngModel.options"
|
||||||
ng-click="ngModel.selected=selected">
|
ng-click="ngModel.selected=option">
|
||||||
<a
|
<a
|
||||||
ng-mouseover="representation.activeMetadata = option"
|
ng-mouseover="representation.activeMetadata = option.metadata"
|
||||||
ng-mouseleave="representation.activeMetadata = undefined">
|
ng-mouseleave="representation.activeMetadata = undefined">
|
||||||
<span class="ui-symbol icon type-icon">
|
<span class="ui-symbol icon type-icon">
|
||||||
{{option.glyph}}
|
{{option.metadata.glyph}}
|
||||||
</span>
|
</span>
|
||||||
{{option.name}}
|
{{option.metadata.name}}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
<span ng-controller="ClickAwayController as modeController">
|
<span ng-controller="ClickAwayController as modeController">
|
||||||
<div class="s-menu-btn"
|
<div class="s-menu-btn"
|
||||||
ng-click="modeController.toggle()">
|
ng-click="modeController.toggle()">
|
||||||
<span class="title-label">{{ngModel.options[ngModel.selected].label}}</span>
|
<span class="title-label">{{ngModel.selected.metadata.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()">
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<div ng-controller="TimeConductorController as tcController"
|
<div ng-controller="TimeConductorController as tcController"
|
||||||
class="l-time-conductor l-flex-col {{modeModel.selected}}-mode">
|
class="l-time-conductor l-flex-col {{modeModel.selected.metadata.key}}-mode {{timeSystemModel.selected.metadata.key}}-time-system">
|
||||||
<!-- Holds inputs and ticks -->
|
<!-- Holds inputs and ticks -->
|
||||||
<div class="l-time-conductor-ticks l-row-elem l-flex-row flex-elem no-margin">
|
<div class="l-time-conductor-ticks l-row-elem l-flex-row flex-elem no-margin">
|
||||||
<form class="abs l-time-conductor-inputs-holder"
|
<form class="abs l-time-conductor-inputs-holder"
|
||||||
@ -17,39 +17,37 @@
|
|||||||
<mct-control key="'datetime-field'"
|
<mct-control key="'datetime-field'"
|
||||||
structure="{
|
structure="{
|
||||||
format: 'utc',
|
format: 'utc',
|
||||||
validate: tcController.validateStart
|
validate: tcController.validation.validateStart
|
||||||
}"
|
}"
|
||||||
ng-model="formModel"
|
ng-model="formModel"
|
||||||
ng-mouseup="tcController.changing['start'] = true"
|
ng-mouseup="changing['start'] = true"
|
||||||
ng-blur="tcController.changing['start'] = false; tcController.updateBoundsFromForm(formModel)"
|
ng-blur="changing['start'] = false; tcController.updateBoundsFromForm(formModel)"
|
||||||
field="'start'"
|
field="'start'"
|
||||||
class="time-range-start">
|
class="time-range-start">
|
||||||
</mct-control>
|
</mct-control>
|
||||||
</span>
|
</span>
|
||||||
<span class="l-time-range-input-w start-delta"
|
<span class="l-time-range-input-w start-delta"
|
||||||
ng-class="{'hide':(modeModel.selected === 'fixed')}">
|
ng-class="{'hide':(modeModel.selected.metadata.key === 'fixed')}">
|
||||||
<mct-control key="'datetime-field'"
|
<mct-control key="'datetime-field'"
|
||||||
structure="{
|
structure="{
|
||||||
format: 'duration',
|
format: 'duration',
|
||||||
validate: tcController.validateStartDelta
|
validate: tcController.validation.validateStartDelta
|
||||||
}"
|
}"
|
||||||
ng-model="formModel"
|
ng-model="formModel"
|
||||||
ng-mouseup="tcController.changing['startDelta'] = true"
|
ng-blur="tcController.updateDeltasFromForm(formModel)"
|
||||||
ng-blur="tcController.changing['startDelta'] = false; tcController.updateDeltasFromForm(formModel)"
|
|
||||||
field="'startDelta'"
|
field="'startDelta'"
|
||||||
class="time-delta-start">
|
class="time-delta-start">
|
||||||
</mct-control>
|
</mct-control>
|
||||||
</span>
|
</span>
|
||||||
<span class="l-time-range-input-w end-delta"
|
<span class="l-time-range-input-w end-delta"
|
||||||
ng-class="{'hide':(modeModel.selected === 'fixed')}">
|
ng-class="{'hide':(modeModel.selected.metadata.key === 'fixed')}">
|
||||||
<mct-control key="'datetime-field'"
|
<mct-control key="'datetime-field'"
|
||||||
structure="{
|
structure="{
|
||||||
format: 'duration',
|
format: 'duration',
|
||||||
validate: tcController.validateEndDelta
|
validate: tcController.validation.validateEndDelta
|
||||||
}"
|
}"
|
||||||
ng-model="formModel"
|
ng-model="formModel"
|
||||||
ng-mouseup="tcController.changing['endDelta'] = true"
|
ng-blur="tcController.updateDeltasFromForm(formModel)"
|
||||||
ng-blur="tcController.changing['endDelta'] = false; tcController.updateDeltasFromForm(formModel)"
|
|
||||||
field="'endDelta'"
|
field="'endDelta'"
|
||||||
class="time-delta-end">
|
class="time-delta-end">
|
||||||
</mct-control>
|
</mct-control>
|
||||||
@ -59,11 +57,11 @@
|
|||||||
<mct-control key="'datetime-field'"
|
<mct-control key="'datetime-field'"
|
||||||
structure="{
|
structure="{
|
||||||
format: 'utc',
|
format: 'utc',
|
||||||
validate: tcController.validateEnd
|
validate: tcController.validation.validateEnd
|
||||||
}"
|
}"
|
||||||
ng-model="formModel"
|
ng-model="formModel"
|
||||||
ng-mouseup="tcController.changing['end'] = true"
|
ng-mouseup="changing['end'] = true"
|
||||||
ng-blur="tcController.changing['end'] = false; tcController.updateBoundsFromForm(formModel)"
|
ng-blur="changing['end'] = false; tcController.updateBoundsFromForm(formModel)"
|
||||||
field="'end'"
|
field="'end'"
|
||||||
class="time-range-end">
|
class="time-range-end">
|
||||||
</mct-control>
|
</mct-control>
|
||||||
@ -87,14 +85,11 @@
|
|||||||
<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"
|
||||||
ng-model="conductorModel.timeSystem"
|
|
||||||
structure="{
|
structure="{
|
||||||
text: 'UTC',
|
text: timeSystemModel.selected.metadata.name,
|
||||||
options: [
|
click: tcController.selectTimeSystem,
|
||||||
{name: 'UTC', key:'utc', glyph:'\u0043'},
|
options: timeSystemModel.options
|
||||||
{name: 'SCET', key:'scet', glyph:'\u0043'},
|
}">
|
||||||
{name: 'SCLK', key:'sclk', glyph:'\u0043'}
|
|
||||||
]}">
|
|
||||||
</mct-control>
|
</mct-control>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
@ -118,7 +118,8 @@ define(['EventEmitter'], function (EventEmitter) {
|
|||||||
TimeConductor.prototype.bounds = function (newBounds) {
|
TimeConductor.prototype.bounds = function (newBounds) {
|
||||||
if (arguments.length > 0) {
|
if (arguments.length > 0) {
|
||||||
throwOnError(this.validateBounds(newBounds));
|
throwOnError(this.validateBounds(newBounds));
|
||||||
this.boundsVal = newBounds;
|
//Create a copy to avoid direct mutation of conductor bounds
|
||||||
|
this.boundsVal = JSON.parse(JSON.stringify(newBounds));
|
||||||
/**
|
/**
|
||||||
* @event TimeConductor#bounds The start time, end time, or
|
* @event TimeConductor#bounds The start time, end time, or
|
||||||
* both have been updated
|
* both have been updated
|
||||||
@ -126,7 +127,8 @@ define(['EventEmitter'], function (EventEmitter) {
|
|||||||
*/
|
*/
|
||||||
this.emit('bounds', this.boundsVal);
|
this.emit('bounds', this.boundsVal);
|
||||||
}
|
}
|
||||||
return this.boundsVal;
|
//Return a copy to prevent direct mutation of time conductor bounds.
|
||||||
|
return JSON.parse(JSON.stringify(this.boundsVal));
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,224 +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 () {
|
|
||||||
|
|
||||||
var FIFTEEN_MINUTES = 15 * 60 * 1000;
|
|
||||||
|
|
||||||
function TimeConductorController($scope, $timeout, conductor) {
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
this.$scope = $scope;
|
|
||||||
this.$timeout = $timeout;
|
|
||||||
this.conductor = conductor;
|
|
||||||
this.startDelta = FIFTEEN_MINUTES;
|
|
||||||
this.endDelta = 0;
|
|
||||||
|
|
||||||
this.changing = {
|
|
||||||
'start': false,
|
|
||||||
'end': false
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.formModel = {
|
|
||||||
startDelta: this.startDelta,
|
|
||||||
endDelta: this.endDelta
|
|
||||||
};
|
|
||||||
|
|
||||||
conductor.on('bounds', function (bounds) {
|
|
||||||
if (!self.changing['start']) {
|
|
||||||
$scope.formModel.start = bounds.start;
|
|
||||||
}
|
|
||||||
if (!self.changing['end']) {
|
|
||||||
$scope.formModel.end = bounds.end;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
conductor.on('follow', function (follow){
|
|
||||||
$scope.followMode = follow;
|
|
||||||
});
|
|
||||||
|
|
||||||
Object.keys(TimeConductorController.prototype).filter(function (key) {
|
|
||||||
return typeof TimeConductorController.prototype[key] === 'function';
|
|
||||||
}).forEach(function (key) {
|
|
||||||
self[key] = self[key].bind(self);
|
|
||||||
});
|
|
||||||
|
|
||||||
$scope.$watch('modeModel.selected', this.switchMode);
|
|
||||||
|
|
||||||
$scope.$watch('timeSystem', function (newTimeSystem, oldTimeSystem) {
|
|
||||||
$scope.modeModel = {
|
|
||||||
selected: 'fixed',
|
|
||||||
options: {
|
|
||||||
'fixed': {
|
|
||||||
glyph: '\ue604',
|
|
||||||
label: 'Fixed',
|
|
||||||
name: 'Fixed Timespan Mode',
|
|
||||||
description: 'Query and explore data that falls between two fixed datetimes.'
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
newTimeSystem.tickSources().forEach(function (tickSource) {
|
|
||||||
var option = {};
|
|
||||||
$scope.modeModel.options.push({
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
$scope.modeModel = {
|
|
||||||
selected: 'fixed',
|
|
||||||
options: {
|
|
||||||
'fixed': {
|
|
||||||
glyph: '\ue604',
|
|
||||||
label: 'Fixed',
|
|
||||||
name: 'Fixed Timespan Mode',
|
|
||||||
description: 'Query and explore data that falls between two fixed datetimes.'
|
|
||||||
},
|
|
||||||
'realtime': {
|
|
||||||
glyph: '\u0043',
|
|
||||||
label: 'Real-time',
|
|
||||||
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.'
|
|
||||||
},
|
|
||||||
'latest': {
|
|
||||||
glyph: '\u0044',
|
|
||||||
label: 'LAD',
|
|
||||||
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.'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$scope.$on('$destroy', function() {
|
|
||||||
if (self.mode) {
|
|
||||||
self.mode();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
self.initialize();
|
|
||||||
}
|
|
||||||
|
|
||||||
TimeConductorController.prototype.initialize = function () {
|
|
||||||
var now = Math.ceil(Date.now() / 1000) * 1000;
|
|
||||||
//Set the time conductor to some default
|
|
||||||
this.conductor.bounds({start: now - FIFTEEN_MINUTES, end: now});
|
|
||||||
|
|
||||||
this.$scope.modeModel.selected = 'fixed';
|
|
||||||
this.conductor.follow(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
TimeConductorController.prototype.validateStart = function (start) {
|
|
||||||
var bounds = this.conductor.bounds();
|
|
||||||
return this.conductor.validateBounds({start: start, end: bounds.end}) === true;
|
|
||||||
};
|
|
||||||
|
|
||||||
TimeConductorController.prototype.validateEnd = function (end) {
|
|
||||||
var bounds = this.conductor.bounds();
|
|
||||||
return this.conductor.validateBounds({start: bounds.start, end: end}) === true;
|
|
||||||
};
|
|
||||||
|
|
||||||
TimeConductorController.prototype.updateBoundsFromForm = function (formModel) {
|
|
||||||
var newBounds = {start: formModel.start, end: formModel.end};
|
|
||||||
|
|
||||||
if (this.conductor.validateBounds(newBounds) === true) {
|
|
||||||
this.conductor.bounds(newBounds);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
TimeConductorController.prototype.validateStartDelta = function (startDelta) {
|
|
||||||
return startDelta > 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
TimeConductorController.prototype.validateEndDelta = function (endDelta) {
|
|
||||||
return endDelta >= 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
TimeConductorController.prototype.validateDeltas = function (formModel) {
|
|
||||||
// Validate that start Delta is some non-zero value, and that end
|
|
||||||
// delta is zero or positive (ie. 'now' or some time in the future).
|
|
||||||
return this.validateStartDelta(formModel.startDelta) && this.validateEndDelta(formModel.endDelta);
|
|
||||||
};
|
|
||||||
|
|
||||||
TimeConductorController.prototype.updateDeltasFromForm = function (formModel) {
|
|
||||||
|
|
||||||
if (this.validateDeltas(formModel)) {
|
|
||||||
//Calculate the previous 'true' end value (without delta)
|
|
||||||
var oldEnd = this.conductor.bounds().end - this.endDelta || 0;
|
|
||||||
|
|
||||||
this.startDelta = formModel.startDelta;
|
|
||||||
this.endDelta = formModel.endDelta;
|
|
||||||
|
|
||||||
var newBounds = {
|
|
||||||
start: oldEnd - this.startDelta,
|
|
||||||
end: oldEnd + this.endDelta
|
|
||||||
};
|
|
||||||
|
|
||||||
this.conductor.bounds(newBounds);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
TimeConductorController.prototype.switchMode = function (newMode) {
|
|
||||||
if (this.mode) {
|
|
||||||
this.mode();
|
|
||||||
}
|
|
||||||
this.mode = TimeConductorController.modes[newMode].call(this);
|
|
||||||
};
|
|
||||||
|
|
||||||
TimeConductorController.modes = {
|
|
||||||
'fixed': function () {
|
|
||||||
this.conductor.follow(false);
|
|
||||||
},
|
|
||||||
'realtime': function () {
|
|
||||||
var tickInterval = 1000;
|
|
||||||
var conductor = this.conductor;
|
|
||||||
var $timeout = this.$timeout;
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
conductor.follow(true);
|
|
||||||
setBoundsToNow(self.startDelta, self.endDelta);
|
|
||||||
|
|
||||||
var timeoutPromise = $timeout(tick, tickInterval);
|
|
||||||
|
|
||||||
function setBoundsToNow(startDelta, endDelta) {
|
|
||||||
var now = Math.ceil(Date.now() / 1000) * 1000;
|
|
||||||
conductor.bounds({start: now - startDelta, end: now + endDelta});
|
|
||||||
}
|
|
||||||
|
|
||||||
function tick() {
|
|
||||||
setBoundsToNow(self.startDelta, self.endDelta);
|
|
||||||
timeoutPromise = $timeout(tick, tickInterval)
|
|
||||||
}
|
|
||||||
|
|
||||||
return function destroy() {
|
|
||||||
$timeout.cancel(timeoutPromise);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'latest': function () {
|
|
||||||
//Don't know what to do here yet...
|
|
||||||
this.conductor.follow(true);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return TimeConductorController;
|
|
||||||
}
|
|
||||||
);
|
|
@ -25,7 +25,7 @@ define(['./TickSource'], function (TickSource) {
|
|||||||
* @implements TickSource
|
* @implements TickSource
|
||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
function LocalClock ($timeout) {
|
function LocalClock ($timeout, period) {
|
||||||
TickSource.call(this);
|
TickSource.call(this);
|
||||||
|
|
||||||
this.metadata = {
|
this.metadata = {
|
||||||
@ -36,7 +36,7 @@ define(['./TickSource'], function (TickSource) {
|
|||||||
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.interval = interval;
|
this.period = period;
|
||||||
this.$timeout = $timeout;
|
this.$timeout = $timeout;
|
||||||
this.timeoutHandle = undefined;
|
this.timeoutHandle = undefined;
|
||||||
}
|
}
|
||||||
@ -44,7 +44,7 @@ define(['./TickSource'], function (TickSource) {
|
|||||||
LocalClock.prototype = Object.create(TickSource.prototype);
|
LocalClock.prototype = Object.create(TickSource.prototype);
|
||||||
|
|
||||||
LocalClock.prototype.start = function () {
|
LocalClock.prototype.start = function () {
|
||||||
this.timeoutHandle = this.$timeout(this.tick.bind(this), this.interval);
|
this.timeoutHandle = this.$timeout(this.tick.bind(this), this.period);
|
||||||
};
|
};
|
||||||
|
|
||||||
LocalClock.prototype.stop = function () {
|
LocalClock.prototype.stop = function () {
|
||||||
@ -58,6 +58,7 @@ define(['./TickSource'], function (TickSource) {
|
|||||||
this.listeners.forEach(function (listener){
|
this.listeners.forEach(function (listener){
|
||||||
listener(now);
|
listener(now);
|
||||||
});
|
});
|
||||||
|
this.timeoutHandle = this.$timeout(this.tick.bind(this), this.period);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -68,19 +69,24 @@ define(['./TickSource'], function (TickSource) {
|
|||||||
* @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.listen = function (listener) {
|
||||||
this.listeners.push(listener);
|
var listeners = this.listeners;
|
||||||
|
listeners.push(listener);
|
||||||
|
|
||||||
if (this.listeners.length === 1){
|
if (listeners.length === 1){
|
||||||
this.start();
|
this.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
return function () {
|
return function () {
|
||||||
this.listeners.splice(listeners.indexOf(listener));
|
listeners.splice(listeners.indexOf(listener));
|
||||||
if (this.listeners.length === 0) {
|
if (listeners.length === 0) {
|
||||||
this.stop();
|
this.stop();
|
||||||
}
|
}
|
||||||
}.bind(this);
|
}.bind(this);
|
||||||
};
|
};
|
||||||
|
|
||||||
return TimeSystem;
|
LocalClock.prototype.type = function () {
|
||||||
|
return 'clock';
|
||||||
|
};
|
||||||
|
|
||||||
|
return LocalClock;
|
||||||
});
|
});
|
||||||
|
@ -41,5 +41,14 @@ define([], function () {
|
|||||||
throw new Error('Not implemented');
|
throw new Error('Not implemented');
|
||||||
};
|
};
|
||||||
|
|
||||||
return TimeSystem;
|
/**
|
||||||
|
* What does this source tick on? A clock, or data availability.
|
||||||
|
* Information is required to support time conductor modes.
|
||||||
|
* @returns {string} type One of 'clock' or 'data'
|
||||||
|
*/
|
||||||
|
TickSource.prototype.type = function () {
|
||||||
|
throw new Error('Not implemented');
|
||||||
|
}
|
||||||
|
|
||||||
|
return TickSource;
|
||||||
});
|
});
|
||||||
|
@ -26,7 +26,16 @@ define([], function () {
|
|||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
function TimeSystem () {
|
function TimeSystem () {
|
||||||
|
/**
|
||||||
|
* @typedef TimeSystemMetadata
|
||||||
|
* @property {string} key
|
||||||
|
* @property {string} name
|
||||||
|
* @property {string} description
|
||||||
|
*
|
||||||
|
* @type {TimeSystemMetadata}
|
||||||
|
*/
|
||||||
this.metadata = undefined;
|
this.metadata = undefined;
|
||||||
|
this._tickSources = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
TimeSystem.prototype.formats = function () {
|
TimeSystem.prototype.formats = function () {
|
||||||
@ -37,7 +46,12 @@ define([], function () {
|
|||||||
throw new Error('Not implemented');
|
throw new Error('Not implemented');
|
||||||
};
|
};
|
||||||
|
|
||||||
TimeSystem.prototype.defaultBounds = function () {
|
/**
|
||||||
|
*
|
||||||
|
* @returns {TimeSystemDefault[]} At least one set of default values for
|
||||||
|
* this time system.
|
||||||
|
*/
|
||||||
|
TimeSystem.prototype.defaults = function () {
|
||||||
throw new Error('Not implemented');
|
throw new Error('Not implemented');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -25,17 +25,25 @@ define([
|
|||||||
'./LocalClock',
|
'./LocalClock',
|
||||||
'../../../../commonUI/formats/src/UTCTimeFormat'
|
'../../../../commonUI/formats/src/UTCTimeFormat'
|
||||||
], function (TimeSystem, LocalClock, UTCTimeFormat) {
|
], function (TimeSystem, LocalClock, UTCTimeFormat) {
|
||||||
var FIFTEEN_MINUTES = 15 * 60 * 1000;
|
var FIFTEEN_MINUTES = 15 * 60 * 1000,
|
||||||
|
DEFAULT_PERIOD = 1000;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* This time system supports UTC dates and provides a ticking clock source.
|
||||||
* @implements TimeSystem
|
* @implements TimeSystem
|
||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
function UTCTimeSystem ($timeout) {
|
function UTCTimeSystem ($timeout) {
|
||||||
TimeSystem.call(this);
|
TimeSystem.call(this);
|
||||||
|
|
||||||
|
this.metadata = {
|
||||||
|
'key': 'utc',
|
||||||
|
'name': 'UTC',
|
||||||
|
'glyph': '\u0043'
|
||||||
|
};
|
||||||
|
|
||||||
this._formats = [new UTCTimeFormat()];
|
this._formats = [new UTCTimeFormat()];
|
||||||
this._tickSources = [new LocalClock($timeout)];
|
this._tickSources = [new LocalClock($timeout, DEFAULT_PERIOD)];
|
||||||
}
|
}
|
||||||
|
|
||||||
UTCTimeSystem.prototype = Object.create(TimeSystem.prototype);
|
UTCTimeSystem.prototype = Object.create(TimeSystem.prototype);
|
||||||
@ -48,9 +56,16 @@ define([
|
|||||||
return this._tickSources;
|
return this._tickSources;
|
||||||
};
|
};
|
||||||
|
|
||||||
UTCTimeSystem.prototype.defaultBounds = function () {
|
UTCTimeSystem.prototype.defaults = function () {
|
||||||
var now = Math.ceil(Date.now() / 1000) * 1000;
|
var now = Math.ceil(Date.now() / 1000) * 1000;
|
||||||
return {start: now - FIFTEEN_MINUTES, end: now};
|
return [
|
||||||
|
{
|
||||||
|
key: 'utc-default',
|
||||||
|
name: 'UTC time system defaults',
|
||||||
|
deltas: {start: FIFTEEN_MINUTES, end: 0},
|
||||||
|
bounds: {start: now - FIFTEEN_MINUTES, end: now}
|
||||||
|
}
|
||||||
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
return UTCTimeSystem;
|
return UTCTimeSystem;
|
||||||
|
@ -28,14 +28,9 @@ define(
|
|||||||
function ($, d3) {
|
function ($, d3) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The mct-control will dynamically include the control
|
* The mct-conductor-axis renders a horizontal axis with regular
|
||||||
* for a form element based on a symbolic key. Individual
|
* labelled 'ticks'. It requires 'start' and 'end' integer values to
|
||||||
* controls are defined under the extension category
|
* be specified as attributes.
|
||||||
* `controls`; this allows plug-ins to introduce new form
|
|
||||||
* control types while still making use of the form
|
|
||||||
* generator to ensure an overall consistent form style.
|
|
||||||
* @constructor
|
|
||||||
* @memberof platform/forms
|
|
||||||
*/
|
*/
|
||||||
function MCTConductorAxis(conductor) {
|
function MCTConductorAxis(conductor) {
|
||||||
|
|
||||||
@ -66,6 +61,7 @@ define(
|
|||||||
setScale(conductor.bounds().start, conductor.bounds().end);
|
setScale(conductor.bounds().start, conductor.bounds().end);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//On conductor bounds changes, redraw ticks
|
||||||
conductor.on('bounds', function (bounds) {
|
conductor.on('bounds', function (bounds) {
|
||||||
setScale(bounds.start, bounds.end);
|
setScale(bounds.start, bounds.end);
|
||||||
});
|
});
|
||||||
@ -84,14 +80,7 @@ define(
|
|||||||
priority: 1000,
|
priority: 1000,
|
||||||
|
|
||||||
// Link function
|
// Link function
|
||||||
link: link,
|
link: link
|
||||||
|
|
||||||
// Pass through Angular's normal input field attributes
|
|
||||||
scope: {
|
|
||||||
// Used to choose which form control to use
|
|
||||||
start: "=",
|
|
||||||
end: "="
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
218
platform/features/conductor-v2/src/ui/TimeConductorController.js
Normal file
218
platform/features/conductor-v2/src/ui/TimeConductorController.js
Normal file
@ -0,0 +1,218 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* 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(
|
||||||
|
[
|
||||||
|
'./modes/FixedMode',
|
||||||
|
'./modes/RealtimeMode',
|
||||||
|
'./modes/LADMode',
|
||||||
|
'./TimeConductorValidation'
|
||||||
|
],
|
||||||
|
function (FixedMode, RealtimeMode, LADMode, TimeConductorValidation) {
|
||||||
|
|
||||||
|
function TimeConductorController($scope, conductor, timeSystems) {
|
||||||
|
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
//Bind all class functions to 'this'
|
||||||
|
Object.keys(TimeConductorController.prototype).filter(function (key) {
|
||||||
|
return typeof TimeConductorController.prototype[key] === 'function';
|
||||||
|
}).forEach(function (key) {
|
||||||
|
self[key] = self[key].bind(self);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.conductor = conductor;
|
||||||
|
// Construct the provided time system definitions
|
||||||
|
this.timeSystems = timeSystems.map(function (timeSystemConstructor){
|
||||||
|
return timeSystemConstructor();
|
||||||
|
});
|
||||||
|
// Populate a list of modes supported by the time conductor
|
||||||
|
this.modes = [
|
||||||
|
new FixedMode(this.conductor, this.timeSystems),
|
||||||
|
new RealtimeMode(this.conductor, this.timeSystems),
|
||||||
|
new LADMode(this.conductor, this.timeSystems)
|
||||||
|
];
|
||||||
|
|
||||||
|
this.validation = new TimeConductorValidation(conductor);
|
||||||
|
this.$scope = $scope;
|
||||||
|
this.initializeScope($scope);
|
||||||
|
|
||||||
|
conductor.on('bounds', this.setBounds);
|
||||||
|
conductor.on('follow', function (follow){
|
||||||
|
$scope.followMode = follow;
|
||||||
|
});
|
||||||
|
|
||||||
|
//Set the time conductor mode to the first one in the list,
|
||||||
|
// effectively initializing the time conductor
|
||||||
|
this.setMode(this.modes[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
TimeConductorController.prototype.initializeScope = function ($scope) {
|
||||||
|
$scope.timeSystemModel = {
|
||||||
|
selected: undefined,
|
||||||
|
options: []
|
||||||
|
};
|
||||||
|
$scope.modeModel = {
|
||||||
|
selected: undefined,
|
||||||
|
options: this.modes
|
||||||
|
};
|
||||||
|
$scope.formModel = {
|
||||||
|
start: 0,
|
||||||
|
end: 0
|
||||||
|
};
|
||||||
|
$scope.changing = {
|
||||||
|
'start': false,
|
||||||
|
'end': false
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.$watch('modeModel.selected', this.setMode);
|
||||||
|
$scope.$watch('timeSystem', this.setTimeSystem);
|
||||||
|
|
||||||
|
$scope.$on('$destroy', function() {
|
||||||
|
var mode = $scope.modeModel.selected;
|
||||||
|
if (mode && mode.destroy) {
|
||||||
|
mode.destroy();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the bounds change in the time conductor. Synchronizes
|
||||||
|
* the bounds values in the time conductor with those in the form
|
||||||
|
* @param bounds
|
||||||
|
*/
|
||||||
|
TimeConductorController.prototype.setBounds = function (bounds) {
|
||||||
|
if (!this.$scope.changing['start']) {
|
||||||
|
this.$scope.formModel.start = bounds.start;
|
||||||
|
}
|
||||||
|
if (!this.$scope.changing['end']) {
|
||||||
|
this.$scope.formModel.end = bounds.end;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when form values are changed. Synchronizes the form with
|
||||||
|
* the time conductor
|
||||||
|
* @param formModel
|
||||||
|
*/
|
||||||
|
TimeConductorController.prototype.updateBoundsFromForm = function (formModel) {
|
||||||
|
var newBounds = {start: formModel.start, end: formModel.end};
|
||||||
|
|
||||||
|
if (this.conductor.validateBounds(newBounds) === true) {
|
||||||
|
this.conductor.bounds(newBounds);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the delta values in the form change. Validates and
|
||||||
|
* sets the new deltas on the Mode.
|
||||||
|
* @param formModel
|
||||||
|
* @see TimeConductorMode
|
||||||
|
*/
|
||||||
|
TimeConductorController.prototype.updateDeltasFromForm = function (formModel) {
|
||||||
|
var mode = this.$scope.modeModel.selected,
|
||||||
|
deltas = mode.deltas();
|
||||||
|
|
||||||
|
if (deltas !== undefined && this.validation.validateDeltas(formModel)) {
|
||||||
|
//Sychronize deltas between form and mode
|
||||||
|
mode.deltas({start: formModel.startDelta, end: formModel.endDelta});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Change the selected Time Conductor mode. This will call destroy
|
||||||
|
* and initialization functions on the relevant modes, setting
|
||||||
|
* default values for bound and deltas in the form.
|
||||||
|
* @param newMode
|
||||||
|
* @param oldMode
|
||||||
|
*/
|
||||||
|
TimeConductorController.prototype.setMode = function (newMode, oldMode) {
|
||||||
|
if (newMode !== oldMode) {
|
||||||
|
if (oldMode && oldMode.destroy) {
|
||||||
|
oldMode.destroy();
|
||||||
|
}
|
||||||
|
newMode.initialize();
|
||||||
|
|
||||||
|
this.$scope.modeModel.selected = newMode;
|
||||||
|
|
||||||
|
//Synchronize scope with time system on mode
|
||||||
|
this.$scope.timeSystemModel.options = newMode.timeSystems().map(function (timeSystem) {
|
||||||
|
return timeSystem.metadata;
|
||||||
|
});
|
||||||
|
this.$scope.timeSystemModel.selected = newMode.selectedTimeSystem();
|
||||||
|
this.setDefaultsFromTimeSystem(newMode.selectedTimeSystem());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
TimeConductorController.prototype.setDefaultsFromTimeSystem = function (timeSystem) {
|
||||||
|
var defaults = timeSystem.defaults()[0];
|
||||||
|
var deltas = defaults.deltas;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the selected mode defines deltas, set them in the form
|
||||||
|
*/
|
||||||
|
if (deltas !== undefined) {
|
||||||
|
this.$scope.formModel.startDelta = deltas.start;
|
||||||
|
this.$scope.formModel.endDelta = deltas.end;
|
||||||
|
} else {
|
||||||
|
this.$scope.formModel.startDelta = 0;
|
||||||
|
this.$scope.formModel.endDelta = 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows time system to be changed by key. This supports selection
|
||||||
|
* from the menu. Resolves a TimeSystem object and then invokes
|
||||||
|
* TimeConductorController#setTimeSystem
|
||||||
|
* @param key
|
||||||
|
* @see TimeConductorController#setTimeSystem
|
||||||
|
*/
|
||||||
|
TimeConductorController.prototype.selectTimeSystem = function(key){
|
||||||
|
var selected = this.timeSystems.find(function (timeSystem){
|
||||||
|
return timeSystem.metadata.key === key;
|
||||||
|
});
|
||||||
|
this.setTimeSystem(selected);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the selected time system. Will populate form with the default
|
||||||
|
* bounds and deltas defined in the selected time system.
|
||||||
|
* @param newTimeSystem
|
||||||
|
*/
|
||||||
|
TimeConductorController.prototype.setTimeSystem = function (newTimeSystem) {
|
||||||
|
if (newTimeSystem && newTimeSystem !== this.$scope.timeSystemModel.selected) {
|
||||||
|
this.$scope.timeSystemModel.selected = newTimeSystem;
|
||||||
|
var mode = this.$scope.modeModel.selected;
|
||||||
|
mode.selectedTimeSystem(newTimeSystem);
|
||||||
|
this.setDefaultsFromTimeSystem(newTimeSystem);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return TimeConductorController;
|
||||||
|
}
|
||||||
|
);
|
@ -0,0 +1,79 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* 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 () {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Form validation for the TimeConductorController.
|
||||||
|
* @param conductor
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
function TimeConductorValidation(conductor) {
|
||||||
|
var self = this;
|
||||||
|
this.conductor = conductor
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Bind all class functions to 'this'
|
||||||
|
*/
|
||||||
|
Object.keys(TimeConductorValidation.prototype).filter(function (key) {
|
||||||
|
return typeof TimeConductorValidation.prototype[key] === 'function';
|
||||||
|
}).forEach(function (key) {
|
||||||
|
self[key] = self[key].bind(self);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
TimeConductorValidation.prototype.validateStart = function (start) {
|
||||||
|
var bounds = this.conductor.bounds();
|
||||||
|
return this.conductor.validateBounds({start: start, end: bounds.end}) === true;
|
||||||
|
};
|
||||||
|
|
||||||
|
TimeConductorValidation.prototype.validateEnd = function (end) {
|
||||||
|
var bounds = this.conductor.bounds();
|
||||||
|
return this.conductor.validateBounds({start: bounds.start, end: end}) === true;
|
||||||
|
};
|
||||||
|
|
||||||
|
TimeConductorValidation.prototype.validateStartDelta = function (startDelta) {
|
||||||
|
return startDelta > 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
TimeConductorValidation.prototype.validateEndDelta = function (endDelta) {
|
||||||
|
return endDelta >= 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates the delta values in the form model. Deltas are offsets
|
||||||
|
* from a fixed point in time, and are used in follow modes as the
|
||||||
|
* primary determinant of conductor bounds.
|
||||||
|
* @param formModel
|
||||||
|
* @returns {*}
|
||||||
|
*/
|
||||||
|
TimeConductorValidation.prototype.validateDeltas = function (formModel) {
|
||||||
|
// Validate that start Delta is some non-zero value, and that end
|
||||||
|
// delta is zero or positive (ie. 'now' or some time in the future).
|
||||||
|
return this.validateStartDelta(formModel.startDelta) && this.validateEndDelta(formModel.endDelta);
|
||||||
|
};
|
||||||
|
|
||||||
|
return TimeConductorValidation;
|
||||||
|
}
|
||||||
|
);
|
78
platform/features/conductor-v2/src/ui/modes/FixedMode.js
Normal file
78
platform/features/conductor-v2/src/ui/modes/FixedMode.js
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* 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(
|
||||||
|
['./TimeConductorMode'],
|
||||||
|
function (TimeConductorMode) {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles time conductor behavior when it is in 'fixed' mode. In
|
||||||
|
* fixed mode, the time conductor is bound by two dates and does not
|
||||||
|
* progress.
|
||||||
|
* @param conductor
|
||||||
|
* @param timeSystems
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
function FixedMode(conductor, timeSystems) {
|
||||||
|
var metadata = {
|
||||||
|
key: 'fixed',
|
||||||
|
glyph: '\ue604',
|
||||||
|
label: 'Fixed',
|
||||||
|
name: 'Fixed Timespan Mode',
|
||||||
|
description: 'Query and explore data that falls between two fixed datetimes.'
|
||||||
|
};
|
||||||
|
|
||||||
|
TimeConductorMode.call(this, metadata, conductor, timeSystems);
|
||||||
|
}
|
||||||
|
|
||||||
|
FixedMode.prototype = Object.create(TimeConductorMode.prototype);
|
||||||
|
|
||||||
|
FixedMode.prototype.initialize = function () {
|
||||||
|
TimeConductorMode.prototype.initialize.apply(this);
|
||||||
|
this.conductor.follow(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines behavior to occur when selected time system changes. In
|
||||||
|
* this case, sets default bounds on the time conductor.
|
||||||
|
* @param timeSystem
|
||||||
|
* @returns {*}
|
||||||
|
*/
|
||||||
|
FixedMode.prototype.selectedTimeSystem = function (timeSystem){
|
||||||
|
TimeConductorMode.prototype.selectedTimeSystem.apply(this, arguments);
|
||||||
|
|
||||||
|
if (timeSystem) {
|
||||||
|
var defaults = timeSystem.defaults()[0];
|
||||||
|
|
||||||
|
var bounds = {
|
||||||
|
start: defaults.bounds.start,
|
||||||
|
end: defaults.bounds.end
|
||||||
|
};
|
||||||
|
|
||||||
|
this.conductor.timeSystem(timeSystem, bounds);
|
||||||
|
}
|
||||||
|
return this._selectedTimeSystem;
|
||||||
|
};
|
||||||
|
|
||||||
|
return FixedMode;
|
||||||
|
}
|
||||||
|
);
|
147
platform/features/conductor-v2/src/ui/modes/FollowMode.js
Normal file
147
platform/features/conductor-v2/src/ui/modes/FollowMode.js
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* 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(
|
||||||
|
['./TimeConductorMode'],
|
||||||
|
function (TimeConductorMode) {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A parent class for Realtime and LAD modes, which both advance the
|
||||||
|
* time conductor bounds over time. The event that advances the time
|
||||||
|
* conductor is abstracted to a TickSource. Unlike FixedMode, the
|
||||||
|
* two 'follow' modes define 'deltas' which are offsets from a fixed
|
||||||
|
* end point. Thus, in follow mode, the end time of the conductor is
|
||||||
|
* the mode relevant, with both offsets defined relative to it.
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
function FollowMode(metadata, conductor, timeSystems) {
|
||||||
|
TimeConductorMode.call(this, metadata, conductor, timeSystems);
|
||||||
|
|
||||||
|
this._deltas = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
FollowMode.prototype = Object.create(TimeConductorMode.prototype);
|
||||||
|
|
||||||
|
FollowMode.prototype.initialize = function () {
|
||||||
|
TimeConductorMode.prototype.initialize.apply(this);
|
||||||
|
this.conductor.follow(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @param time
|
||||||
|
*/
|
||||||
|
FollowMode.prototype.tick = function (time) {
|
||||||
|
var deltas = this.deltas();
|
||||||
|
this.conductor.bounds({
|
||||||
|
start: time - deltas.start,
|
||||||
|
end: time + deltas.end
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @param tickSource
|
||||||
|
*/
|
||||||
|
FollowMode.prototype.listenToTickSource = function () {
|
||||||
|
if (this._selectedTimeSystem &&
|
||||||
|
this._timeSystems[0]) {
|
||||||
|
|
||||||
|
var tickSource = this._timeSystems[0].tickSources()[0];
|
||||||
|
if (tickSource) {
|
||||||
|
this.tickSourceUnlisten = tickSource.listen(this.tick.bind(this));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* On time system change, default the bounds values in the time
|
||||||
|
* conductor, using the deltas associated with this mode.
|
||||||
|
* @param timeSystem
|
||||||
|
* @returns {TimeSystem}
|
||||||
|
*/
|
||||||
|
FollowMode.prototype.selectedTimeSystem = function (timeSystem) {
|
||||||
|
TimeConductorMode.prototype.selectedTimeSystem.apply(this, arguments);
|
||||||
|
|
||||||
|
if (timeSystem) {
|
||||||
|
var defaults = timeSystem.defaults()[0];
|
||||||
|
|
||||||
|
if (arguments.length > 0) {
|
||||||
|
var bounds = {
|
||||||
|
start: defaults.bounds.start,
|
||||||
|
end: defaults.bounds.end
|
||||||
|
};
|
||||||
|
|
||||||
|
if (defaults.deltas) {
|
||||||
|
bounds.start = bounds.end - defaults.deltas.start;
|
||||||
|
bounds.end = bounds.end + defaults.deltas.end;
|
||||||
|
this._deltas = JSON.parse(JSON.stringify(defaults.deltas));
|
||||||
|
}
|
||||||
|
|
||||||
|
this.conductor.timeSystem(timeSystem, bounds);
|
||||||
|
|
||||||
|
this.listenToTickSource();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this._selectedTimeSystem;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get or set the current value for the deltas used by this time system.
|
||||||
|
* On change, the new deltas will be used to calculate and set the
|
||||||
|
* bounds on the time conductor.
|
||||||
|
* @param deltas
|
||||||
|
* @returns {TimeSystemDeltas}
|
||||||
|
*/
|
||||||
|
FollowMode.prototype.deltas = function (deltas) {
|
||||||
|
if (arguments.length !== 0) {
|
||||||
|
var oldEnd = this.conductor.bounds().end;
|
||||||
|
|
||||||
|
if (this._deltas && this._deltas.end){
|
||||||
|
//Calculate the previous 'true' end value (without delta)
|
||||||
|
oldEnd = oldEnd - this._deltas.end;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._deltas = deltas;
|
||||||
|
|
||||||
|
var newBounds = {
|
||||||
|
start: oldEnd - this._deltas.start,
|
||||||
|
end: oldEnd + this._deltas.end
|
||||||
|
};
|
||||||
|
|
||||||
|
this.conductor.bounds(newBounds);
|
||||||
|
}
|
||||||
|
return this._deltas;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop listening to tick sources
|
||||||
|
*/
|
||||||
|
FollowMode.prototype.destroy = function () {
|
||||||
|
if (this.tickSourceUnlisten) {
|
||||||
|
this.tickSourceUnlisten();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return FollowMode;
|
||||||
|
}
|
||||||
|
);
|
56
platform/features/conductor-v2/src/ui/modes/LADMode.js
Normal file
56
platform/features/conductor-v2/src/ui/modes/LADMode.js
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* 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(
|
||||||
|
['./FollowMode'],
|
||||||
|
function (FollowMode) {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Supports the 'Latest Available Data' mode of the time conductor.
|
||||||
|
* This is a special case of FollowMode that advances on 'data' type
|
||||||
|
* tick sources.
|
||||||
|
* @param conductor
|
||||||
|
* @param timeSystems
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
function LADMode(conductor, timeSystems) {
|
||||||
|
var metadata = {
|
||||||
|
key: 'latest',
|
||||||
|
glyph: '\u0044',
|
||||||
|
label: 'LAD',
|
||||||
|
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.'
|
||||||
|
};
|
||||||
|
var filteredTimeSystems = timeSystems.filter(function (timeSystem){
|
||||||
|
return timeSystem.tickSources().some(function (tickSource){
|
||||||
|
return tickSource.type() === 'data';
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
FollowMode.call(this, metadata, conductor, filteredTimeSystems);
|
||||||
|
}
|
||||||
|
|
||||||
|
LADMode.prototype = Object.create(FollowMode.prototype);
|
||||||
|
|
||||||
|
return LADMode;
|
||||||
|
}
|
||||||
|
);
|
55
platform/features/conductor-v2/src/ui/modes/RealtimeMode.js
Normal file
55
platform/features/conductor-v2/src/ui/modes/RealtimeMode.js
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* 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(
|
||||||
|
['./FollowMode'],
|
||||||
|
function (FollowMode) {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class representing the 'realtime' mode of the time conductor.
|
||||||
|
* This is a special case of FollowMode that only supports 'clock'
|
||||||
|
* type tick sources.
|
||||||
|
* @param conductor
|
||||||
|
* @param timeSystems
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
function RealtimeMode(conductor, timeSystems) {
|
||||||
|
var metadata = {
|
||||||
|
key: 'realtime',
|
||||||
|
glyph: '\u0043',
|
||||||
|
label: 'Real-time',
|
||||||
|
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.'
|
||||||
|
};
|
||||||
|
var filteredTimeSystems = timeSystems.filter(function (timeSystem){
|
||||||
|
return timeSystem.tickSources().some(function (tickSource){
|
||||||
|
return tickSource.type() === 'clock';
|
||||||
|
});
|
||||||
|
});
|
||||||
|
FollowMode.call(this, metadata, conductor, filteredTimeSystems);
|
||||||
|
}
|
||||||
|
|
||||||
|
RealtimeMode.prototype = Object.create(FollowMode.prototype);
|
||||||
|
|
||||||
|
return RealtimeMode;
|
||||||
|
}
|
||||||
|
);
|
@ -0,0 +1,82 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* 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 () {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Supports mode-specific time conductor behavior. This class
|
||||||
|
* defines a parent with default behavior that specific modes are
|
||||||
|
* expected to override.
|
||||||
|
*
|
||||||
|
* @interface
|
||||||
|
* @constructor
|
||||||
|
* @param {TimeConductorMetadata} metadata
|
||||||
|
*/
|
||||||
|
function TimeConductorMode(metadata, conductor, timeSystems) {
|
||||||
|
this.metadata = metadata;
|
||||||
|
|
||||||
|
this.conductor = conductor;
|
||||||
|
this._timeSystems = timeSystems;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function is called when mode becomes active (ie. is selected)
|
||||||
|
*/
|
||||||
|
TimeConductorMode.prototype.initialize = function () {
|
||||||
|
this.selectedTimeSystem(this._timeSystems[0]);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the time systems supported by this mode. Modes are
|
||||||
|
* expected to determine which time systems they will support by
|
||||||
|
* filtering a provided list of all time systems.
|
||||||
|
*
|
||||||
|
* @returns {TimeSystem[]} The time systems supported by this mode
|
||||||
|
*/
|
||||||
|
TimeConductorMode.prototype.timeSystems = function () {
|
||||||
|
return this._timeSystems;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get or set the currently selected time system
|
||||||
|
* @param timeSystem
|
||||||
|
* @returns {TimeSystem} the currently selected time system
|
||||||
|
*/
|
||||||
|
TimeConductorMode.prototype.selectedTimeSystem = function (timeSystem) {
|
||||||
|
if (arguments.length > 0) {
|
||||||
|
if (this._timeSystems.indexOf(timeSystem) === -1){
|
||||||
|
throw new Error("Unsupported time system");
|
||||||
|
} else {
|
||||||
|
this._selectedTimeSystem = timeSystem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this._selectedTimeSystem;
|
||||||
|
};
|
||||||
|
|
||||||
|
TimeConductorMode.prototype.destroy = function () {
|
||||||
|
};
|
||||||
|
|
||||||
|
return TimeConductorMode;
|
||||||
|
}
|
||||||
|
);
|
Reference in New Issue
Block a user