/*global define*/ define([ '../Core/Clock', '../Core/defined', '../Core/defineProperties', '../Core/destroyObject', '../Core/EventHelper', '../Core/JulianDate', '../ThirdParty/knockout' ], function( Clock, defined, defineProperties, destroyObject, EventHelper, JulianDate, knockout) { "use strict"; /** * A view model which exposes a {@link Clock} for user interfaces. * @alias ClockViewModel * @constructor * * @param {Clock} [clock] The clock object wrapped by this view model, if undefined a new instance will be created. * * @see Clock */ var ClockViewModel = function(clock) { if (!defined(clock)) { clock = new Clock(); } this._clock = clock; this._eventHelper = new EventHelper(); this._eventHelper.add(clock.onTick, this.synchronize, this); var startTime = knockout.observable(clock.startTime); startTime.equalityComparer = JulianDate.equals; /** * Gets the current system time. This property is observable. * @type {JulianDate} * @default JulianDate() */ this.systemTime = knockout.observable(JulianDate.now()); this.systemTime.equalityComparer = JulianDate.equals; knockout.track(this, ['systemTime']); /** * Gets or sets the start time of the clock. This property is observable. * @type {JulianDate} * @default undefined */ this.startTime = undefined; knockout.defineProperty(this, 'startTime', { get : startTime, set : function(value) { startTime(value); clock.startTime = value; } }); var stopTime = knockout.observable(clock.stopTime); stopTime.equalityComparer = JulianDate.equals; /** * Gets or sets the stop time of the clock. This property is observable. * @type {JulianDate} * @default undefined */ this.stopTime = undefined; knockout.defineProperty(this, 'stopTime', { get : stopTime, set : function(value) { clock.stopTime = value; stopTime(value); } }); var currentTime = knockout.observable(clock.currentTime); currentTime.equalityComparer = JulianDate.equals; /** * Gets or sets the current time. This property is observable. * @type {JulianDate} * @default undefined */ this.currentTime = undefined; knockout.defineProperty(this, 'currentTime', { get : currentTime, set : function(value) { clock.currentTime = value; currentTime(value); } }); var multiplier = knockout.observable(clock.multiplier); /** * Gets or sets how much time advances when tick is called, negative values allow for advancing backwards. * If clockStep is set to ClockStep.TICK_DEPENDENT this is the number of seconds to advance. * If clockStep is set to ClockStep.SYSTEM_CLOCK_MULTIPLIER this value is multiplied by the * elapsed system time since the last call to tick. This property is observable. * @type {Number} * @default undefined */ this.multiplier = undefined; knockout.defineProperty(this, 'multiplier', { get : multiplier, set : function(value) { clock.multiplier = value; multiplier(value); } }); var clockStep = knockout.observable(clock.clockStep); clockStep.equalityComparer = function(a, b) { return a === b; }; /** * Gets or sets whether calls to Clock.tick are frame dependent or system clock dependent. * This property is observable. * @type {ClockStep} * @default undefined */ this.clockStep = undefined; knockout.defineProperty(this, 'clockStep', { get : clockStep, set : function(value) { clockStep(value); clock.clockStep = value; } }); var clockRange = knockout.observable(clock.clockRange); clockRange.equalityComparer = function(a, b) { return a === b; }; /** * Gets or sets how tick should behave when startTime or stopTime is reached. * This property is observable. * @type {ClockRange} * @default undefined */ this.clockRange = undefined; knockout.defineProperty(this, 'clockRange', { get : clockRange, set : function(value) { clockRange(value); clock.clockRange = value; } }); var canAnimate = knockout.observable(clock.canAnimate); /** * Gets or sets whether or not Clock.tick can advance time. * This could be false if data is being buffered, for example. * The clock will only tick when both canAnimate and shouldAnimate are true. * This property is observable. * @type {Boolean} * @default undefined */ this.canAnimate = undefined; knockout.defineProperty(this, 'canAnimate', { get : canAnimate, set : function(value) { canAnimate(value); clock.canAnimate = value; } }); var shouldAnimate = knockout.observable(clock.shouldAnimate); /** * Gets or sets whether or not Clock.tick should attempt to advance time. * The clock will only tick when both canAnimate and shouldAnimate are true. * This property is observable. * @type {Boolean} * @default undefined */ this.shouldAnimate = undefined; knockout.defineProperty(this, 'shouldAnimate', { get : shouldAnimate, set : function(value) { shouldAnimate(value); clock.shouldAnimate = value; } }); }; defineProperties(ClockViewModel.prototype, { /** * Gets the underlying Clock. * @memberof ClockViewModel.prototype * * @type {Clock} */ clock : { get : function() { return this._clock; } } }); /** * Updates the view model with the contents of the underlying clock. * Can be called to force an update of the viewModel if the underlying * clock has changed and Clock.tick has not yet been called. */ ClockViewModel.prototype.synchronize = function() { var clock = this._clock; var startTime = clock.startTime; var stopTime = clock.stopTime; var currentTime = clock.currentTime; var multiplier = clock.multiplier; var clockStep = clock.clockStep; var clockRange = clock.clockRange; var canAnimate = clock.canAnimate; var shouldAnimate = clock.shouldAnimate; this.systemTime = JulianDate.now(); this.startTime = startTime; this.stopTime = stopTime; this.currentTime = currentTime; this.multiplier = multiplier; this.clockStep = clockStep; this.clockRange = clockRange; this.canAnimate = canAnimate; this.shouldAnimate = shouldAnimate; }; /** * @returns {Boolean} true if the object has been destroyed, false otherwise. */ ClockViewModel.prototype.isDestroyed = function() { return false; }; /** * Destroys the view model. Should be called to * properly clean up the view model when it is no longer needed. */ ClockViewModel.prototype.destroy = function() { this._eventHelper.removeAll(); destroyObject(this); }; return ClockViewModel; });