diff --git a/platform/features/layout/bundle.json b/platform/features/layout/bundle.json index df5bd9413c..3f710d4371 100644 --- a/platform/features/layout/bundle.json +++ b/platform/features/layout/bundle.json @@ -9,7 +9,7 @@ "glyph": "L", "type": "layout", "templateUrl": "templates/layout.html", - "uses": [ "composition" ], + "uses": [], "gestures": [ "drop" ] }, { diff --git a/platform/features/layout/src/LayoutController.js b/platform/features/layout/src/LayoutController.js index d7906dd0fa..68de8b3bac 100644 --- a/platform/features/layout/src/LayoutController.js +++ b/platform/features/layout/src/LayoutController.js @@ -58,14 +58,14 @@ define( return copy; } - // Compute panel positions based on the layout's object model - function lookupPanels(ids) { + /** + * Compute panel positions based on the layout's object model. + * Defined as member function to facilitate testing. + * @private + */ + LayoutController.prototype.layoutPanels = function layoutPanels (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 self.rawPositions = shallowCopy(configuration.panels || {}, ids); @@ -81,7 +81,7 @@ define( ids.forEach(function (id, index) { self.populatePosition(id, index); }); - } + }; // Update grid size when it changed function updateGridSize(layoutGrid) { @@ -92,7 +92,7 @@ define( // Only update panel positions if this actually changed things if (self.gridSize[0] !== oldSize[0] || self.gridSize[1] !== oldSize[1]) { - lookupPanels(Object.keys(self.positions)); + self.layoutPanels(Object.keys(self.positions)); } } @@ -127,6 +127,25 @@ define( e.preventDefault(); } + function getComposition(domainObject){ + return domainObject.useCapability('composition'); + } + + function composeView (composition){ + $scope.composition = composition; + return composition.map(function (object) { + return object.getId(); + }) || []; + } + + //Will fetch fully contextualized composed objects, and populate + // scope with them. + function refreshComposition() { + return getComposition($scope.domainObject) + .then(composeView) + .then(self.layoutPanels); + } + // End drag; we don't want to put $scope into this // because it triggers "cpws" (copy window or scope) // errors in Angular. @@ -156,8 +175,8 @@ define( // Watch for changes to the grid size in the model $scope.$watch("model.layoutGrid", updateGridSize); - // Position panes when the model field changes - $scope.$watch("model.composition", lookupPanels); + // Update composed objects on screen, and position panes + $scope.$watch("model.composition", refreshComposition); // Position panes where they are dropped $scope.$on("mctDrop", handleDrop); diff --git a/platform/features/layout/test/LayoutControllerSpec.js b/platform/features/layout/test/LayoutControllerSpec.js index 085f7766a2..eb17df62fe 100644 --- a/platform/features/layout/test/LayoutControllerSpec.js +++ b/platform/features/layout/test/LayoutControllerSpec.js @@ -19,7 +19,7 @@ * this source code distribution or the Licensing information page available * at runtime from the About dialog for additional information. *****************************************************************************/ -/*global define,describe,it,expect,beforeEach,jasmine*/ +/*global define,describe,it,expect,beforeEach,jasmine,spyOn*/ define( ["../src/LayoutController"], @@ -31,7 +31,28 @@ define( mockEvent, testModel, testConfiguration, - controller; + controller, + mockCompositionCapability, + mockComposition; + + function mockPromise(value){ + return { + then: function (thenFunc) { + return mockPromise(thenFunc(value)); + } + }; + } + + function mockDomainObject(id){ + return { + getId: function() { + return id; + }, + useCapability: function() { + return mockCompositionCapability; + } + }; + } beforeEach(function () { mockScope = jasmine.createSpyObj( @@ -43,9 +64,9 @@ define( [ 'preventDefault' ] ); - testModel = { - composition: [ "a", "b", "c" ] - }; + testModel = {}; + + mockComposition = ["a", "b", "c"]; testConfiguration = { panels: { @@ -56,10 +77,15 @@ define( } }; + mockCompositionCapability = mockPromise(mockComposition.map(mockDomainObject)); + + mockScope.domainObject = mockDomainObject("mockDomainObject"); mockScope.model = testModel; mockScope.configuration = testConfiguration; + spyOn(mockScope.domainObject, "useCapability").andCallThrough(); controller = new LayoutController(mockScope); + spyOn(controller, "layoutPanels").andCallThrough(); }); // Model changes will indicate that panel positions @@ -71,8 +97,18 @@ define( ); }); + it("Retrieves updated composition from composition capability", function () { + mockScope.$watch.mostRecentCall.args[1](); + expect(mockScope.domainObject.useCapability).toHaveBeenCalledWith( + "composition" + ); + expect(controller.layoutPanels).toHaveBeenCalledWith( + mockComposition + ); + }); + it("provides styles for frames, from configuration", function () { - mockScope.$watch.mostRecentCall.args[1](testModel.composition); + mockScope.$watch.mostRecentCall.args[1](); expect(controller.getFrameStyle("a")).toEqual({ top: "320px", left: "640px", @@ -85,7 +121,7 @@ define( var styleB, styleC; // b and c do not have configured positions - mockScope.$watch.mostRecentCall.args[1](testModel.composition); + mockScope.$watch.mostRecentCall.args[1](); styleB = controller.getFrameStyle("b"); styleC = controller.getFrameStyle("c"); @@ -102,7 +138,7 @@ define( it("allows panels to be dragged", function () { // Populate scope - mockScope.$watch.mostRecentCall.args[1](testModel.composition); + mockScope.$watch.mostRecentCall.args[1](); // Verify precondtion expect(testConfiguration.panels.b).not.toBeDefined(); @@ -121,7 +157,7 @@ define( it("invokes commit after drag", function () { // Populate scope - mockScope.$watch.mostRecentCall.args[1](testModel.composition); + mockScope.$watch.mostRecentCall.args[1](); // Do a drag controller.startDrag("b", [1, 1], [0, 0]); @@ -147,7 +183,6 @@ define( expect(testConfiguration.panels.d).not.toBeDefined(); // Notify that a drop occurred - testModel.composition.push('d'); mockScope.$on.mostRecentCall.args[1]( mockEvent, 'd', @@ -167,7 +202,6 @@ define( mockEvent.defaultPrevented = true; // Notify that a drop occurred - testModel.composition.push('d'); mockScope.$on.mostRecentCall.args[1]( mockEvent, 'd', @@ -201,7 +235,6 @@ define( mockScope.$watch.calls[0].args[1](testModel.layoutGrid); // Notify that a drop occurred - testModel.composition.push('d'); mockScope.$on.mostRecentCall.args[1]( mockEvent, 'd',