From 0df809741ab6df8008219ddfda9fc4c8b82ccf93 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Tue, 27 Jan 2015 10:00:06 -0800 Subject: [PATCH 1/2] [Representation] Refresh only capabilities on modified When changes to a domain object's modification timestamp are detected, refresh only the capabilities associated with that domain object (instead of rebuilding the whole view.) Specifically avoids latency when layout views are rebuilt, WTD-716. --- .../representation/src/MCTRepresentation.js | 49 ++++++++++++------- .../test/MCTRepresentationSpec.js | 8 +-- 2 files changed, 35 insertions(+), 22 deletions(-) diff --git a/platform/representation/src/MCTRepresentation.js b/platform/representation/src/MCTRepresentation.js index a0250bc43b..1cecf7a981 100644 --- a/platform/representation/src/MCTRepresentation.js +++ b/platform/representation/src/MCTRepresentation.js @@ -57,6 +57,34 @@ define( return new Representer($scope, element, attrs); }); + // Populate scope with any capabilities indicated by the + // representation's extension definition + function refreshCapabilities() { + var representation = representationMap[$scope.key], + domainObject = $scope.domainObject, + uses = ((representation || {}).uses || []); + + if (domainObject) { + // Update model + $scope.model = domainObject.getModel(); + + // Provide any of the capabilities requested + uses.forEach(function (used) { + $log.debug([ + "Requesting capability ", + used, + " for representation ", + $scope.key + ].join("")); + $q.when( + domainObject.useCapability(used) + ).then(function (c) { + $scope[used] = c; + }); + }); + } + } + // General-purpose refresh mechanism; should set up the scope // as appropriate for current representation key and // domain object. @@ -88,29 +116,14 @@ define( // Populate scope with fields associated with the current // domain object (if one has been passed in) if (domainObject) { - // Always provide the model, as "model" - $scope.model = domainObject.getModel(); + // Initialize any capabilities + refreshCapabilities(); // Also provide the view configuration, // for the specific view $scope.configuration = ($scope.model.configuration || {})[$scope.key] || {}; - // Also provide any of the capabilities requested - uses.forEach(function (used) { - $log.debug([ - "Requesting capability ", - used, - " for representation ", - $scope.key - ].join("")); - $q.when( - domainObject.useCapability(used) - ).then(function (c) { - $scope[used] = c; - }); - }); - // Finally, wire up any additional behavior (such as // gestures) associated with this representation. activeRepresenters.forEach(function (representer) { @@ -130,7 +143,7 @@ define( // Finally, also update when there is a new version of that // same domain object; these changes should be tracked in the // model's "modified" field, by the mutation capability. - $scope.$watch("domainObject.getModel().modified", refresh); + $scope.$watch("domainObject.getModel().modified", refreshCapabilities); // Do one initial refresh, so that we don't need another // digest iteration just to populate the scope. Failure to diff --git a/platform/representation/test/MCTRepresentationSpec.js b/platform/representation/test/MCTRepresentationSpec.js index ee44c626a6..835c40b71b 100644 --- a/platform/representation/test/MCTRepresentationSpec.js +++ b/platform/representation/test/MCTRepresentationSpec.js @@ -115,7 +115,7 @@ define( mockScope.key = "abc"; // Trigger the watch - mockScope.$watch.mostRecentCall.args[1](); + mockScope.$watch.calls[0].args[1](); expect(mockScope.inclusion).toEqual("a/b/c/template.html"); }); @@ -126,7 +126,7 @@ define( mockScope.key = "xyz"; // Trigger the watch - mockScope.$watch.mostRecentCall.args[1](); + mockScope.$watch.calls[0].args[1](); expect(mockScope.inclusion).toEqual("x/y/z/template.html"); }); @@ -138,7 +138,7 @@ define( mockScope.domainObject = mockDomainObject; // Trigger the watch - mockScope.$watch.mostRecentCall.args[1](); + mockScope.$watch.calls[0].args[1](); expect(mockDomainObject.useCapability) .toHaveBeenCalledWith("testCapability"); @@ -155,7 +155,7 @@ define( expect(mockLog.warn).not.toHaveBeenCalled(); // Trigger the watch - mockScope.$watch.mostRecentCall.args[1](); + mockScope.$watch.calls[0].args[1](); // Should have gotten a warning - that's an unknown key expect(mockLog.warn).toHaveBeenCalled(); From 2b4517cff634ce7247bc5c93b839fac126360737 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Tue, 27 Jan 2015 10:22:50 -0800 Subject: [PATCH 2/2] [Layout] Update on composition change Update frame positions when model.composition changes, instead of when model changes. Ensures correct display after changes to avoid redrawing on every update, WTD-716. --- platform/features/layout/src/LayoutController.js | 9 ++++----- .../features/layout/test/LayoutControllerSpec.js | 12 ++++++------ 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/platform/features/layout/src/LayoutController.js b/platform/features/layout/src/LayoutController.js index 9ebab58017..70a5126d78 100644 --- a/platform/features/layout/src/LayoutController.js +++ b/platform/features/layout/src/LayoutController.js @@ -66,9 +66,8 @@ define( } // Compute panel positions based on the layout's object model - function lookupPanels(model) { - var configuration = $scope.configuration || {}, - ids = (model || {}).composition || []; + function lookupPanels(ids) { + var configuration = $scope.configuration || {}; // Pull panel positions from configuration rawPositions = shallowCopy(configuration.panels || {}, ids); @@ -77,14 +76,14 @@ define( positions = {}; // Update width/height that we are tracking - gridSize = (model || {}).layoutGrid || DEFAULT_GRID_SIZE; + gridSize = ($scope.model || {}).layoutGrid || DEFAULT_GRID_SIZE; // Compute positions and add defaults where needed ids.forEach(populatePosition); } // Position panes when the model field changes - $scope.$watch("model", lookupPanels); + $scope.$watch("model.composition", lookupPanels); return { /** diff --git a/platform/features/layout/test/LayoutControllerSpec.js b/platform/features/layout/test/LayoutControllerSpec.js index ba21822dec..f80b356d74 100644 --- a/platform/features/layout/test/LayoutControllerSpec.js +++ b/platform/features/layout/test/LayoutControllerSpec.js @@ -38,15 +38,15 @@ define( // Model changes will indicate that panel positions // may have changed, for instance. - it("watches for changes to model", function () { + it("watches for changes to composition", function () { expect(mockScope.$watch).toHaveBeenCalledWith( - "model", + "model.composition", jasmine.any(Function) ); }); it("provides styles for frames, from configuration", function () { - mockScope.$watch.mostRecentCall.args[1](testModel); + mockScope.$watch.mostRecentCall.args[1](testModel.composition); expect(controller.getFrameStyle("a")).toEqual({ top: "320px", left: "640px", @@ -59,7 +59,7 @@ define( var styleB, styleC; // b and c do not have configured positions - mockScope.$watch.mostRecentCall.args[1](testModel); + mockScope.$watch.mostRecentCall.args[1](testModel.composition); styleB = controller.getFrameStyle("b"); styleC = controller.getFrameStyle("c"); @@ -76,7 +76,7 @@ define( it("allows panels to be dragged", function () { // Populate scope - mockScope.$watch.mostRecentCall.args[1](testModel); + mockScope.$watch.mostRecentCall.args[1](testModel.composition); // Verify precondtion expect(testConfiguration.panels.b).not.toBeDefined(); @@ -95,7 +95,7 @@ define( it("invokes commit after drag", function () { // Populate scope - mockScope.$watch.mostRecentCall.args[1](testModel); + mockScope.$watch.mostRecentCall.args[1](testModel.composition); // Add a commit method to scope mockScope.commit = jasmine.createSpy("commit");