Skip to content

Commit

Permalink
Merge pull request #565 from bradh/os467
Browse files Browse the repository at this point in the history
fix(state): Support save / restore of timeline slices.
  • Loading branch information
schmidtk authored May 27, 2019
2 parents 3a3d79b + 9f4f8b9 commit c02a4a9
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 8 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@
"opensphere-build-docs": "^1.0.0",
"opensphere-build-index": "^1.0.0",
"opensphere-build-resolver": "^5.0.0",
"opensphere-state-schema": "^2.1.0",
"opensphere-state-schema": "^2.3.0",
"postcss-cli": "^5.0.0",
"replace": "^0.3.0",
"rimraf": "^2.5.4",
Expand Down
70 changes: 67 additions & 3 deletions src/os/state/v4/timestate.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,12 @@ os.state.v4.TimeTag = {
HOLDS: 'heldIntervals',
HOLD_ITEM: 'held',
SEQ_INTERVAL: 'interval',
TIME: 'time'
TIME: 'time',
SLICES: 'slices',
SLICE: 'slice',
SLICE_INTERVAL: 'sliceInterval',
INTERVAL_START: 'intervalStart',
INTERVAL_END: 'intervalEnd'
};


Expand Down Expand Up @@ -170,6 +175,7 @@ os.state.v4.TimeState.prototype.loadInternal = function(obj, id) {
}

tlc.setHoldRanges(this.readIntervalsAsRangeSet_(obj, os.state.v4.TimeTag.HOLDS));
tlc.setSliceRanges(this.readSlicesAsRangeSet_(obj));
}

// set the active window position. this needs to be called after auto configure, or these values will be overridden.
Expand Down Expand Up @@ -255,7 +261,7 @@ os.state.v4.TimeState.prototype.saveInternal = function(options, rootObj) {
// NOTE: v4 heldIntervals can include an optional key element
// which should be associated with a specific layer. Currently,
// we do not support this feature, so the following
// just reaads all the interval elements.
// just reads all the interval elements.
rootObj.appendChild(this.holdRangeToXml_(tlc.getHoldRanges()));
}

Expand All @@ -268,6 +274,10 @@ os.state.v4.TimeState.prototype.saveInternal = function(options, rootObj) {
os.xml.appendElement(os.state.v4.TimeTag.PLAY_STATE, animation, playState);
}

if (tlc.hasSliceRanges()) {
rootObj.appendChild(this.sliceRangesToXml_(tlc.getSliceRanges()));
}

os.xml.appendElement(os.state.v4.TimeTag.DURATION, rootObj, tlc.getDuration());

this.saveComplete(options, rootObj);
Expand Down Expand Up @@ -405,7 +415,7 @@ os.state.v4.TimeState.prototype.readDuration_ = function(element, range) {


/**
* Reads a collection of intervals and retruns a RangeSet
* Reads a collection of intervals and returns a RangeSet
* @param {!Element} element
* @param {string} tag
* @return {goog.math.RangeSet}
Expand Down Expand Up @@ -520,3 +530,57 @@ os.state.v4.TimeState.prototype.parsePeriod = function(period) {

return null;
};

/**
* Returns slice intervals element for timeranges.
* @param {Array<goog.math.Range>} sliceRanges
* @return {!Element}
* @private
*/
os.state.v4.TimeState.prototype.sliceRangesToXml_ = function(sliceRanges) {
var slices = os.xml.createElement(os.state.v4.TimeTag.SLICES);

for (var i = 0; i < sliceRanges.length; i++) {
var slice = os.xml.createElement(os.state.v4.TimeTag.SLICE);
slices.appendChild(slice);
var interval = os.xml.createElement(os.state.v4.TimeTag.SLICE_INTERVAL);
slice.appendChild(interval);
var range = sliceRanges[i];
os.xml.appendElement(os.state.v4.TimeTag.INTERVAL_START, interval, range.start);
os.xml.appendElement(os.state.v4.TimeTag.INTERVAL_END, interval, range.end);
}
return slices;
};

/**
* Reads a collection of slices and returns a RangeSet
* @param {!Element} element
* @return {goog.math.RangeSet}
* @private
*/
os.state.v4.TimeState.prototype.readSlicesAsRangeSet_ = function(element) {
var rangeSet = new goog.math.RangeSet();
if (element) {
var slicesElement = element.querySelector(os.state.v4.TimeTag.SLICES);
if (slicesElement) {
var intervals = slicesElement.querySelectorAll(os.state.v4.TimeTag.SLICE_INTERVAL);
for (var i = 0; i < intervals.length; i = i + 1) {
var interval = intervals[i];
rangeSet.add(this.sliceIntervalToRange_(interval));
}
}
}
return rangeSet;
};

/**
* Returns a range for a given slice interval
* @param {!Element} interval
* @return {goog.math.Range}
* @private
*/
os.state.v4.TimeState.prototype.sliceIntervalToRange_ = function(interval) {
var intervalStart = +interval.querySelector(os.state.v4.TimeTag.INTERVAL_START).textContent;
var intervalEnd = +interval.querySelector(os.state.v4.TimeTag.INTERVAL_END).textContent;
return new goog.math.Range(intervalStart, intervalEnd);
};
2 changes: 1 addition & 1 deletion test/os.xsd.mock.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ os.test.xsd.loadStateXsdFiles = function() {
var stateFileRoot = '/opensphere-state-schema/src/main/xsd/';
var p = goog.Promise.withResolver();

// retun the cached result, if it exists.
// return the cached result, if it exists.
if (os.test.xsd.stateCache_) {
p.resolve(os.test.xsd.stateCache_);
return p.promise;
Expand Down
18 changes: 15 additions & 3 deletions test/os/state/v4/timestate.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,16 @@ describe('os.state.v4.TimeState', function() {
var holdEndDate = os.time.parseMoment('1971-06-12T01:15:11Z',
[os.state.v4.TimeState.DATE_FORMAT], true);
var holdRange = new goog.math.Range(holdStartDate.valueOf(), holdEndDate.valueOf());
// make sure this is empty bfeore the test.
// make sure this is empty before the test.
tlc.clearHoldRanges();
tlc.addHoldRange(holdRange);

// Slice ranges
var sliceRange1 = new goog.math.Range(20, 50);
var sliceRange2 = new goog.math.Range(20000, 5000000);
tlc.addSliceRange(sliceRange1);
tlc.addSliceRange(sliceRange2);

tlc.setCurrent(animateEndDate.valueOf());
tlc.setFps(1);
tlc.setOffset(1000002);
Expand All @@ -53,6 +59,7 @@ describe('os.state.v4.TimeState', function() {
spyOn(tlc, 'setDuration').andCallThrough();
spyOn(tlc, 'setAnimateRanges').andCallThrough();
spyOn(tlc, 'setHoldRanges').andCallThrough();
spyOn(tlc, 'setSliceRanges').andCallThrough();
spyOn(tlc, 'setCurrent').andCallThrough();
spyOn(tlc, 'setSkip').andCallThrough();
spyOn(tlc, 'setFps').andCallThrough();
Expand All @@ -76,7 +83,7 @@ describe('os.state.v4.TimeState', function() {
// waiting for the xsd files to load
waitsFor(function() {
return (resultSchemas !== null);
}, 'Wait for XSD(s) to laod', 2 * jasmine.DEFAULT_TIMEOUT_INTERVAL);
}, 'Wait for XSD(s) to load', 2 * jasmine.DEFAULT_TIMEOUT_INTERVAL);

// Runs the tests.
runs(function() {
Expand All @@ -89,6 +96,7 @@ describe('os.state.v4.TimeState', function() {
var duration = tlc.getDuration();
var aRanges = tlc.animateRanges_.clone();
var hRanges = tlc.holdRanges_.clone();
var sRanges = tlc.sliceRanges_.clone();
var current = tlc.getCurrent();
var skip = tlc.getSkip();
var fps = tlc.getFps();
Expand All @@ -111,7 +119,7 @@ describe('os.state.v4.TimeState', function() {
expect(tlc.setDuration).toHaveBeenCalled();
// When the timeline controler is loaded from a state, it goes
// through an auto-configuration step that computes a
// good duration, I believe that a ticket was written againt
// good duration, I believe that a ticket was written against
// using the stored value...?
expect(tlc.setDuration.mostRecentCall.args[0]).not.toBe(duration);

Expand All @@ -123,6 +131,10 @@ describe('os.state.v4.TimeState', function() {
expect(goog.math.RangeSet.equals(hRanges,
tlc.setHoldRanges.mostRecentCall.args[0])).toBe(true);

expect(tlc.setSliceRanges).toHaveBeenCalled();
expect(goog.math.RangeSet.equals(sRanges,
tlc.setSliceRanges.mostRecentCall.args[0])).toBe(true);

expect(tlc.setCurrent).toHaveBeenCalled();
expect(tlc.setCurrent.mostRecentCall.args[0]).toBe(current);

Expand Down

0 comments on commit c02a4a9

Please sign in to comment.