Merge branch 'master' of https://github.com/nasa/openmctweb into open18

This commit is contained in:
Sarah Hale 2015-06-24 11:26:52 -07:00
commit e7ce0f2ded
6 changed files with 86 additions and 12 deletions
platform

@ -35,7 +35,7 @@
</div>
<div class="abs object-holder">
<mct-representation key="representation.selected.key"
mct-object="domainObject">
mct-object="representation.selected.key && domainObject">
</mct-representation>
</div>
</div>

@ -90,6 +90,10 @@ define(
function lookupPanels(ids) {
var configuration = $scope.configuration || {};
// ids is read from model.composition and may be undefined;
// fall back to an array if that occurs
ids = ids || [];
// Pull panel positions from configuration
rawPositions = shallowCopy(configuration.panels || {}, ids);

@ -155,6 +155,16 @@ define(
}
}
// Switch from WebGL to plain 2D if context is lost
function fallbackFromWebGL() {
element.html(TEMPLATE);
canvas = element.find("canvas")[0];
chart = getChart([Canvas2DChart], canvas);
if (chart) {
doDraw(scope.draw);
}
}
// Try to initialize a chart.
chart = getChart([GLChart, Canvas2DChart], canvas);
@ -164,6 +174,11 @@ define(
return;
}
// WebGL is a bit of a special case; it may work, then fail
// later for various reasons, so we need to listen for this
// and fall back to plain canvas drawing when it occurs.
canvas.addEventListener("webglcontextlost", fallbackFromWebGL);
// Check for resize, on a timer
activeInterval = $interval(drawIfResized, 1000);
@ -192,4 +207,4 @@ define(
return MCTChart;
}
);
);

@ -36,6 +36,7 @@ define(
mockElement,
mockCanvas,
mockGL,
mockC2d,
mockPromise,
mctChart;
@ -47,13 +48,14 @@ define(
mockScope =
jasmine.createSpyObj("$scope", ["$watchCollection", "$on"]);
mockElement =
jasmine.createSpyObj("element", ["find"]);
jasmine.createSpyObj("element", ["find", "html"]);
mockInterval.cancel = jasmine.createSpy("cancelInterval");
mockPromise = jasmine.createSpyObj("promise", ["then"]);
// mct-chart uses GLChart, so it needs WebGL API
mockCanvas = jasmine.createSpyObj("canvas", [ "getContext" ]);
mockCanvas =
jasmine.createSpyObj("canvas", [ "getContext", "addEventListener" ]);
mockGL = jasmine.createSpyObj(
"gl",
[
@ -81,6 +83,7 @@ define(
"drawArrays"
]
);
mockC2d = jasmine.createSpyObj('c2d', ['clearRect']);
mockGL.ARRAY_BUFFER = "ARRAY_BUFFER";
mockGL.DYNAMIC_DRAW = "DYNAMIC_DRAW";
mockGL.TRIANGLE_FAN = "TRIANGLE_FAN";
@ -93,7 +96,9 @@ define(
});
mockElement.find.andReturn([mockCanvas]);
mockCanvas.getContext.andReturn(mockGL);
mockCanvas.getContext.andCallFake(function (type) {
return { webgl: mockGL, '2d': mockC2d }[type];
});
mockInterval.andReturn(mockPromise);
mctChart = new MCTChart(mockInterval, mockLog);
@ -169,6 +174,15 @@ define(
expect(mockLog.warn).toHaveBeenCalled();
});
it("falls back to Canvas 2d API if WebGL context is lost", function () {
mctChart.link(mockScope, mockElement);
expect(mockCanvas.addEventListener)
.toHaveBeenCalledWith("webglcontextlost", jasmine.any(Function));
expect(mockCanvas.getContext).not.toHaveBeenCalledWith('2d');
mockCanvas.addEventListener.mostRecentCall.args[1]();
expect(mockCanvas.getContext).toHaveBeenCalledWith('2d');
});
it("logs nothing in nominal situations (WebGL available)", function () {
// Complement the previous test
mctChart.link(mockScope, mockElement);
@ -197,4 +211,4 @@ define(
});
}
);
);

@ -93,15 +93,18 @@ define(
function link($scope, element, attrs) {
var activeRepresenters = representers.map(function (Representer) {
return new Representer($scope, element, attrs);
});
return new Representer($scope, element, attrs);
}),
toClear = [], // Properties to clear out of scope on change
counter = 0;
// Populate scope with any capabilities indicated by the
// representation's extension definition
function refreshCapabilities() {
var domainObject = $scope.domainObject,
representation = lookup($scope.key, domainObject),
uses = ((representation || {}).uses || []);
uses = ((representation || {}).uses || []),
myCounter = counter;
if (domainObject) {
// Update model
@ -115,10 +118,16 @@ define(
" for representation ",
$scope.key
].join(""));
$q.when(
domainObject.useCapability(used)
).then(function (c) {
$scope[used] = c;
// Avoid clobbering capabilities from
// subsequent representations;
// Angular reuses scopes.
if (counter === myCounter) {
$scope[used] = c;
}
});
});
}
@ -130,8 +139,7 @@ define(
function refresh() {
var domainObject = $scope.domainObject,
representation = lookup($scope.key, domainObject),
uses = ((representation || {}).uses || []),
gestureKeys = ((representation || {}).gestures || []);
uses = ((representation || {}).uses || []);
// Create an empty object named "representation", for this
// representation to store local variables into.
@ -152,9 +160,19 @@ define(
$log.warn("No representation found for " + $scope.key);
}
// Clear out the scope from the last representation
toClear.forEach(function (property) {
delete $scope[property];
});
// Populate scope with fields associated with the current
// domain object (if one has been passed in)
if (domainObject) {
// Track how many representations we've made in this scope,
// to ensure that the correct representations are matched to
// the correct object/key pairs.
counter += 1;
// Initialize any capabilities
refreshCapabilities();
@ -168,6 +186,10 @@ define(
activeRepresenters.forEach(function (representer) {
representer.represent(representation, domainObject);
});
// Track which properties we want to clear from scope
// next change object/key pair changes
toClear = uses.concat(['model']);
}
}

@ -181,6 +181,25 @@ define(
// Should have gotten a warning - that's an unknown key
expect(mockLog.warn).toHaveBeenCalled();
});
it("clears out obsolete peroperties from scope", function () {
mctRepresentation.link(mockScope, mockElement);
mockScope.key = "def";
mockScope.domainObject = mockDomainObject;
mockDomainObject.useCapability.andReturn("some value");
// Trigger the watch
mockScope.$watch.calls[0].args[1]();
expect(mockScope.testCapability).toBeDefined();
// Change the view
mockScope.key = "xyz";
// Trigger the watch again; should clear capability from scope
mockScope.$watch.calls[0].args[1]();
expect(mockScope.testCapability).toBeUndefined();
});
});
}
);