[Layout] Layout rebuilds after resize/reposition #32

This commit is contained in:
Henry 2015-11-24 13:05:00 -08:00
parent d6e2895666
commit c84de00e80
3 changed files with 75 additions and 23 deletions

View File

@ -9,7 +9,7 @@
"glyph": "L", "glyph": "L",
"type": "layout", "type": "layout",
"templateUrl": "templates/layout.html", "templateUrl": "templates/layout.html",
"uses": [ "composition" ], "uses": [],
"gestures": [ "drop" ] "gestures": [ "drop" ]
}, },
{ {

View File

@ -58,14 +58,14 @@ define(
return copy; 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 || {}; 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 // Pull panel positions from configuration
self.rawPositions = self.rawPositions =
shallowCopy(configuration.panels || {}, ids); shallowCopy(configuration.panels || {}, ids);
@ -81,7 +81,7 @@ define(
ids.forEach(function (id, index) { ids.forEach(function (id, index) {
self.populatePosition(id, index); self.populatePosition(id, index);
}); });
} };
// Update grid size when it changed // Update grid size when it changed
function updateGridSize(layoutGrid) { function updateGridSize(layoutGrid) {
@ -92,7 +92,7 @@ define(
// Only update panel positions if this actually changed things // Only update panel positions if this actually changed things
if (self.gridSize[0] !== oldSize[0] || if (self.gridSize[0] !== oldSize[0] ||
self.gridSize[1] !== oldSize[1]) { self.gridSize[1] !== oldSize[1]) {
lookupPanels(Object.keys(self.positions)); self.layoutPanels(Object.keys(self.positions));
} }
} }
@ -127,6 +127,25 @@ define(
e.preventDefault(); 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 // End drag; we don't want to put $scope into this
// because it triggers "cpws" (copy window or scope) // because it triggers "cpws" (copy window or scope)
// errors in Angular. // errors in Angular.
@ -156,8 +175,8 @@ define(
// Watch for changes to the grid size in the model // Watch for changes to the grid size in the model
$scope.$watch("model.layoutGrid", updateGridSize); $scope.$watch("model.layoutGrid", updateGridSize);
// Position panes when the model field changes // Update composed objects on screen, and position panes
$scope.$watch("model.composition", lookupPanels); $scope.$watch("model.composition", refreshComposition);
// Position panes where they are dropped // Position panes where they are dropped
$scope.$on("mctDrop", handleDrop); $scope.$on("mctDrop", handleDrop);

View File

@ -19,7 +19,7 @@
* this source code distribution or the Licensing information page available * this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information. * 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( define(
["../src/LayoutController"], ["../src/LayoutController"],
@ -31,7 +31,28 @@ define(
mockEvent, mockEvent,
testModel, testModel,
testConfiguration, 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 () { beforeEach(function () {
mockScope = jasmine.createSpyObj( mockScope = jasmine.createSpyObj(
@ -43,9 +64,9 @@ define(
[ 'preventDefault' ] [ 'preventDefault' ]
); );
testModel = { testModel = {};
composition: [ "a", "b", "c" ]
}; mockComposition = ["a", "b", "c"];
testConfiguration = { testConfiguration = {
panels: { panels: {
@ -56,10 +77,15 @@ define(
} }
}; };
mockCompositionCapability = mockPromise(mockComposition.map(mockDomainObject));
mockScope.domainObject = mockDomainObject("mockDomainObject");
mockScope.model = testModel; mockScope.model = testModel;
mockScope.configuration = testConfiguration; mockScope.configuration = testConfiguration;
spyOn(mockScope.domainObject, "useCapability").andCallThrough();
controller = new LayoutController(mockScope); controller = new LayoutController(mockScope);
spyOn(controller, "layoutPanels").andCallThrough();
}); });
// Model changes will indicate that panel positions // 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 () { 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({ expect(controller.getFrameStyle("a")).toEqual({
top: "320px", top: "320px",
left: "640px", left: "640px",
@ -85,7 +121,7 @@ define(
var styleB, styleC; var styleB, styleC;
// b and c do not have configured positions // b and c do not have configured positions
mockScope.$watch.mostRecentCall.args[1](testModel.composition); mockScope.$watch.mostRecentCall.args[1]();
styleB = controller.getFrameStyle("b"); styleB = controller.getFrameStyle("b");
styleC = controller.getFrameStyle("c"); styleC = controller.getFrameStyle("c");
@ -102,7 +138,7 @@ define(
it("allows panels to be dragged", function () { it("allows panels to be dragged", function () {
// Populate scope // Populate scope
mockScope.$watch.mostRecentCall.args[1](testModel.composition); mockScope.$watch.mostRecentCall.args[1]();
// Verify precondtion // Verify precondtion
expect(testConfiguration.panels.b).not.toBeDefined(); expect(testConfiguration.panels.b).not.toBeDefined();
@ -121,7 +157,7 @@ define(
it("invokes commit after drag", function () { it("invokes commit after drag", function () {
// Populate scope // Populate scope
mockScope.$watch.mostRecentCall.args[1](testModel.composition); mockScope.$watch.mostRecentCall.args[1]();
// Do a drag // Do a drag
controller.startDrag("b", [1, 1], [0, 0]); controller.startDrag("b", [1, 1], [0, 0]);
@ -147,7 +183,6 @@ define(
expect(testConfiguration.panels.d).not.toBeDefined(); expect(testConfiguration.panels.d).not.toBeDefined();
// Notify that a drop occurred // Notify that a drop occurred
testModel.composition.push('d');
mockScope.$on.mostRecentCall.args[1]( mockScope.$on.mostRecentCall.args[1](
mockEvent, mockEvent,
'd', 'd',
@ -167,7 +202,6 @@ define(
mockEvent.defaultPrevented = true; mockEvent.defaultPrevented = true;
// Notify that a drop occurred // Notify that a drop occurred
testModel.composition.push('d');
mockScope.$on.mostRecentCall.args[1]( mockScope.$on.mostRecentCall.args[1](
mockEvent, mockEvent,
'd', 'd',
@ -201,7 +235,6 @@ define(
mockScope.$watch.calls[0].args[1](testModel.layoutGrid); mockScope.$watch.calls[0].args[1](testModel.layoutGrid);
// Notify that a drop occurred // Notify that a drop occurred
testModel.composition.push('d');
mockScope.$on.mostRecentCall.args[1]( mockScope.$on.mostRecentCall.args[1](
mockEvent, mockEvent,
'd', 'd',