From 7f21cc044db578504aa17145b1d3c713f52aca34 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Wed, 14 Jan 2015 17:48:57 -0800 Subject: [PATCH 01/22] [Fixed Position] Initial template Add initial template, declaration for fixed position view, WTD-615. --- platform/features/layout/bundle.json | 8 ++++++ .../features/layout/res/templates/fixed.html | 26 +++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 platform/features/layout/res/templates/fixed.html diff --git a/platform/features/layout/bundle.json b/platform/features/layout/bundle.json index 67d91281fe..80de35aacd 100644 --- a/platform/features/layout/bundle.json +++ b/platform/features/layout/bundle.json @@ -10,6 +10,14 @@ "type": "layout", "templateUrl": "templates/layout.html", "uses": [ "composition" ] + }, + { + "key": "fixed", + "name": "Fixed Position", + "glyph": "3", + "type": "telemetry.panel", + "templateUrl": "templates/fixed.html", + "uses": [ "composition" ] } ], "representations": [ diff --git a/platform/features/layout/res/templates/fixed.html b/platform/features/layout/res/templates/fixed.html new file mode 100644 index 0000000000..206ce97954 --- /dev/null +++ b/platform/features/layout/res/templates/fixed.html @@ -0,0 +1,26 @@ +
+ + + +
+ +
+ + +
+ + + + + + + +
+ +
\ No newline at end of file From 9d25359aa35dab9c5efd1365ea3a859e2ecbddd0 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Thu, 15 Jan 2015 17:04:03 -0800 Subject: [PATCH 02/22] [Fixed Position] Allow views to populate toolbar Add a toolbar representer to share enough scope that views become capable of populating toolbars. Needed for toolbar of fixed position view, WTD-615. --- .../edit/res/templates/edit-object.html | 13 +++++-- .../commonUI/edit/src/ToolbarRepresenter.js | 37 +++++++++++++++++++ 2 files changed, 47 insertions(+), 3 deletions(-) create mode 100644 platform/commonUI/edit/src/ToolbarRepresenter.js diff --git a/platform/commonUI/edit/res/templates/edit-object.html b/platform/commonUI/edit/res/templates/edit-object.html index a27016a3a4..c7339d0c4e 100644 --- a/platform/commonUI/edit/res/templates/edit-object.html +++ b/platform/commonUI/edit/res/templates/edit-object.html @@ -2,13 +2,20 @@ mct-object="domainObject" ng-model="representation"> -
- +
+ + + +
+ toolbar="toolbar" + mct-object="representation.selected.key && domainObject">
diff --git a/platform/commonUI/edit/src/ToolbarRepresenter.js b/platform/commonUI/edit/src/ToolbarRepresenter.js new file mode 100644 index 0000000000..97a424fc83 --- /dev/null +++ b/platform/commonUI/edit/src/ToolbarRepresenter.js @@ -0,0 +1,37 @@ +/*global define*/ + +define( + [], + function () { + + function ToolbarRepresenter(scope, element, attrs) { + var parent = scope.$parent; + + function represent(domainObject, representation) { + // New domain object, clear out the tool bar + parent.toolbar = {}; + scope.toolbar = parent.toolbar; + } + + return { + /** + * Set the current representation in use, and the domain + * object being represented. + * + * @param {RepresentationDefinition} representation the + * definition of the representation in use + * @param {DomainObject} domainObject the domain object + * being represented + */ + represent: represent, + /** + * Release any resources associated with this representer. + */ + destroy: function () {} + }; + } + + return ToolbarRepresenter; + + } +); \ No newline at end of file From 1b2ebf125078c94fc9febbfe722db89289dea611 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Thu, 15 Jan 2015 18:29:31 -0800 Subject: [PATCH 03/22] [Fixed] Add Fixed Position controller Add controller for fixed position view (initially, as copied from Layout view.) WTD-615. --- .../features/layout/res/templates/fixed.html | 2 - .../features/layout/src/FixedController.js | 172 ++++++++++++++++++ 2 files changed, 172 insertions(+), 2 deletions(-) create mode 100644 platform/features/layout/src/FixedController.js diff --git a/platform/features/layout/res/templates/fixed.html b/platform/features/layout/res/templates/fixed.html index 206ce97954..af63b80b68 100644 --- a/platform/features/layout/res/templates/fixed.html +++ b/platform/features/layout/res/templates/fixed.html @@ -1,8 +1,6 @@
- -
diff --git a/platform/features/layout/src/FixedController.js b/platform/features/layout/src/FixedController.js new file mode 100644 index 0000000000..10c19eb3e7 --- /dev/null +++ b/platform/features/layout/src/FixedController.js @@ -0,0 +1,172 @@ +/*global define*/ + +define( + ['./LayoutDrag'], + function (LayoutDrag) { + "use strict"; + + var DEFAULT_DIMENSIONS = [ 12, 8 ], + DEFAULT_GRID_SIZE = [32, 32]; + + /** + * The FixedController is responsible for supporting the + * Fixed Position view. It arranges frames according to saved + * configuration and provides methods for updating these based on + * mouse movement. + * @constructor + * @param {Scope} $scope the controller's Angular scope + */ + function FixedController($scope) { + var gridSize = DEFAULT_GRID_SIZE, + activeDrag, + activeDragId, + rawPositions = {}, + positions = {}; + + // Utility function to copy raw positions from configuration, + // without writing directly to configuration (to avoid triggering + // persistence from watchers during drags). + function shallowCopy(obj, keys) { + var copy = {}; + keys.forEach(function (k) { + copy[k] = obj[k]; + }); + return copy; + } + + // Convert from { positions: ..., dimensions: ... } to an + // apropriate ng-style argument, to position frames. + function convertPosition(raw) { + // Multiply position/dimensions by grid size + return { + left: (gridSize[0] * raw.position[0]) + 'px', + top: (gridSize[1] * raw.position[1]) + 'px', + width: (gridSize[0] * raw.dimensions[0]) + 'px', + height: (gridSize[1] * raw.dimensions[1]) + 'px' + }; + } + + // Generate a default position (in its raw format) for a frame. + // Use an index to ensure that default positions are unique. + function defaultPosition(index) { + return { + position: [index, index], + dimensions: DEFAULT_DIMENSIONS + }; + } + + // Store a computed position for a contained frame by its + // domain object id. Called in a forEach loop, so arguments + // are as expected there. + function populatePosition(id, index) { + rawPositions[id] = + rawPositions[id] || defaultPosition(index || 0); + positions[id] = + convertPosition(rawPositions[id]); + } + + // Compute panel positions based on the layout's object model + function lookupPanels(model) { + var configuration = $scope.configuration || {}, + ids = (model || {}).composition || []; + + // Pull panel positions from configuration + rawPositions = shallowCopy(configuration.panels || {}, ids); + + // Clear prior computed positions + positions = {}; + + // Update width/height that we are tracking + gridSize = (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); + + return { + /** + * Get a style object for a frame with the specified domain + * object identifier, suitable for use in an `ng-style` + * directive to position a frame as configured for this layout. + * @param {string} id the object identifier + * @returns {Object.} an object with + * appropriate left, width, etc fields for positioning + */ + getStyle: function (id) { + // Called in a loop, so just look up; the "positions" + // object is kept up to date by a watch. + return positions[id]; + }, + /** + * Start a drag gesture to move/resize a frame. + * + * The provided position and dimensions factors will determine + * whether this is a move or a resize, and what type it + * will be. For instance, a position factor of [1, 1] + * will move a frame along with the mouse as the drag + * proceeds, while a dimension factor of [0, 0] will leave + * dimensions unchanged. Combining these in different + * ways results in different handles; a position factor of + * [1, 0] and a dimensions factor of [-1, 0] will implement + * a left-edge resize, as the horizontal position will move + * with the mouse while the horizontal dimensions shrink in + * kind (and vertical properties remain unmodified.) + * + * @param {string} id the identifier of the domain object + * in the frame being manipulated + * @param {number[]} posFactor the position factor + * @param {number[]} dimFactor the dimensions factor + */ + startDrag: function (id, posFactor, dimFactor) { + activeDragId = id; + activeDrag = new LayoutDrag( + rawPositions[id], + posFactor, + dimFactor, + gridSize + ); + }, + /** + * Continue an active drag gesture. + * @param {number[]} delta the offset, in pixels, + * of the current pointer position, relative + * to its position when the drag started + */ + continueDrag: function (delta) { + if (activeDrag) { + rawPositions[activeDragId] = + activeDrag.getAdjustedPosition(delta); + populatePosition(activeDragId); + } + }, + /** + * End the active drag gesture. This will update the + * view configuration. + */ + endDrag: function () { + // Write to configuration; this is watched and + // saved by the EditRepresenter. + $scope.configuration = + $scope.configuration || {}; + // Make sure there is a "panels" field in the + // view configuration. + $scope.configuration.panels = + $scope.configuration.panels || {}; + // Store the position of this panel. + $scope.configuration.panels[activeDragId] = + rawPositions[activeDragId]; + // Mark this object as dirty to encourage persistence + if ($scope.commit) { + $scope.commit("Moved frame."); + } + } + }; + + } + + return FixedController; + } +); \ No newline at end of file From d453e593086e73360e93e8dacf597e01c15de7ed Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Thu, 15 Jan 2015 18:36:48 -0800 Subject: [PATCH 04/22] [Fixed Position] Expose controller Expose Fixed Position controller in order to begin implementing Fixed Position view and editing behavior. WTD-615. --- platform/features/layout/bundle.json | 5 +++++ platform/features/layout/res/templates/fixed.html | 9 +++++---- platform/features/layout/src/FixedController.js | 12 ++++++------ 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/platform/features/layout/bundle.json b/platform/features/layout/bundle.json index 80de35aacd..5d073da347 100644 --- a/platform/features/layout/bundle.json +++ b/platform/features/layout/bundle.json @@ -31,6 +31,11 @@ "key": "LayoutController", "implementation": "LayoutController.js", "depends": [ "$scope" ] + }, + { + "key": "FixedController", + "implementation": "FixedController.js", + "depends": [ "$scope" ] } ], "types": [ diff --git a/platform/features/layout/res/templates/fixed.html b/platform/features/layout/res/templates/fixed.html index af63b80b68..3f480c72e8 100644 --- a/platform/features/layout/res/templates/fixed.html +++ b/platform/features/layout/res/templates/fixed.html @@ -4,10 +4,11 @@
-
- - +
+ {{childObject.getModel().name}} +
+
+ {{controller.getValue(childObject.getId())}}
diff --git a/platform/features/layout/src/FixedController.js b/platform/features/layout/src/FixedController.js index 10c19eb3e7..ff43e6c4b0 100644 --- a/platform/features/layout/src/FixedController.js +++ b/platform/features/layout/src/FixedController.js @@ -5,8 +5,8 @@ define( function (LayoutDrag) { "use strict"; - var DEFAULT_DIMENSIONS = [ 12, 8 ], - DEFAULT_GRID_SIZE = [32, 32]; + var DEFAULT_DIMENSIONS = [ 2, 1 ], + DEFAULT_GRID_SIZE = [64, 16]; /** * The FixedController is responsible for supporting the @@ -153,14 +153,14 @@ define( $scope.configuration || {}; // Make sure there is a "panels" field in the // view configuration. - $scope.configuration.panels = - $scope.configuration.panels || {}; + $scope.configuration.elements = + $scope.configuration.elements || {}; // Store the position of this panel. - $scope.configuration.panels[activeDragId] = + $scope.configuration.elements[activeDragId] = rawPositions[activeDragId]; // Mark this object as dirty to encourage persistence if ($scope.commit) { - $scope.commit("Moved frame."); + $scope.commit("Moved element."); } } }; From b2bfa2b09b156adfd4006ee97f08e5986d7b2c25 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Thu, 15 Jan 2015 18:48:11 -0800 Subject: [PATCH 05/22] [Fixed Position] Populate background grid Add a background grid to fixed position view, WTD-615. --- .../features/layout/res/templates/fixed.html | 14 +++++++- .../features/layout/src/FixedController.js | 35 ++++++++++++++++++- 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/platform/features/layout/res/templates/fixed.html b/platform/features/layout/res/templates/fixed.html index 3f480c72e8..1675cd2cde 100644 --- a/platform/features/layout/res/templates/fixed.html +++ b/platform/features/layout/res/templates/fixed.html @@ -1,7 +1,19 @@ -
+ +
+
+ + + +
diff --git a/platform/features/layout/src/FixedController.js b/platform/features/layout/src/FixedController.js index ff43e6c4b0..a959775120 100644 --- a/platform/features/layout/src/FixedController.js +++ b/platform/features/layout/src/FixedController.js @@ -6,7 +6,8 @@ define( "use strict"; var DEFAULT_DIMENSIONS = [ 2, 1 ], - DEFAULT_GRID_SIZE = [64, 16]; + DEFAULT_GRID_SIZE = [64, 16], + DEFAULT_GRID_EXTENT = [4, 4]; /** * The FixedController is responsible for supporting the @@ -18,8 +19,10 @@ define( */ function FixedController($scope) { var gridSize = DEFAULT_GRID_SIZE, + gridExtent = DEFAULT_GRID_EXTENT, activeDrag, activeDragId, + cellStyles = [], rawPositions = {}, positions = {}; @@ -34,6 +37,25 @@ define( return copy; } + // Refresh cell styles (e.g. because grid extent changed) + function refreshCellStyles() { + var x, y; + + cellStyles = []; + + for (x = 0; x < gridExtent[0]; x += 1) { + for (y = 0; y < gridExtent[1]; y += 1) { + // Position blocks; subtract out border size from w/h + cellStyles.push({ + left: x * gridSize[0] + 'px', + top: y * gridSize[1] + 'px', + width: gridSize[0] - 2 + 'px', + height: gridSize[1] - 2 + 'px' + }); + } + } + } + // Convert from { positions: ..., dimensions: ... } to an // apropriate ng-style argument, to position frames. function convertPosition(raw) { @@ -86,7 +108,18 @@ define( // Position panes when the model field changes $scope.$watch("model", lookupPanels); + refreshCellStyles(); + return { + /** + * Get styles for all background cells, as will populate the + * ng-style tag. + * @memberof FixedController# + * @returns {Array} cell styles + */ + getCellStyles: function () { + return cellStyles; + }, /** * Get a style object for a frame with the specified domain * object identifier, suitable for use in an `ng-style` From bd068f31c5a4d220f90723804c73cc4c3d2b08eb Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Thu, 15 Jan 2015 18:53:59 -0800 Subject: [PATCH 06/22] [Fixed Position] Fill available area with grid Fill available space with background grid for fixed position view, WTD-615. --- .../features/layout/res/templates/fixed.html | 3 ++- platform/features/layout/src/FixedController.js | 17 +++++++++++++++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/platform/features/layout/res/templates/fixed.html b/platform/features/layout/res/templates/fixed.html index 1675cd2cde..95af6c0c05 100644 --- a/platform/features/layout/res/templates/fixed.html +++ b/platform/features/layout/res/templates/fixed.html @@ -1,7 +1,8 @@
+ ng-controller="FixedController as controller" + mct-resize="controller.setBounds(bounds)">
Date: Thu, 15 Jan 2015 19:03:34 -0800 Subject: [PATCH 07/22] [Fixed Position] Position/style telemetry cells Position telemetry elements in fixed position view appropriately. WTD-615. --- platform/features/layout/res/templates/fixed.html | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/platform/features/layout/res/templates/fixed.html b/platform/features/layout/res/templates/fixed.html index 95af6c0c05..b7b99ec21c 100644 --- a/platform/features/layout/res/templates/fixed.html +++ b/platform/features/layout/res/templates/fixed.html @@ -10,18 +10,16 @@ ng-style="cell">
- - - +
-
+
{{childObject.getModel().name}}
-
- {{controller.getValue(childObject.getId())}} +
+ X{{controller.getValue(childObject.getId())}}
From 2960d4cdc26e9d09aac0bf6de89138010b8921e6 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Thu, 15 Jan 2015 19:07:49 -0800 Subject: [PATCH 08/22] [Fixed Position] All subscription callback to be undefined Allow callback provided when subscribing to telemetry using telemetrySubscriber to be omitted; this permits usage of the resulting subscription more directly from controllers, such as for fixed position view, WTD-615. --- platform/telemetry/src/TelemetrySubscription.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/platform/telemetry/src/TelemetrySubscription.js b/platform/telemetry/src/TelemetrySubscription.js index 5e929d8ee4..c8d3914726 100644 --- a/platform/telemetry/src/TelemetrySubscription.js +++ b/platform/telemetry/src/TelemetrySubscription.js @@ -58,7 +58,10 @@ define( // Invoke the observer callback to notify that new streaming // data has become available. function fireCallback() { - callback(); + // Fire callback, if one was provided + if (callback) { + callback(); + } // Clear the pending flag so that future updates will // schedule this callback. updatePending = false; From ec211a067ac220aa009b062a79b94053eb96cfca Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Thu, 15 Jan 2015 19:16:15 -0800 Subject: [PATCH 09/22] [Fixed Position] Show telemetry values Show telemetry values in cells in fixed position views. WTD-615. --- platform/features/layout/bundle.json | 2 +- .../features/layout/src/FixedController.js | 47 ++++++++++++++++++- 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/platform/features/layout/bundle.json b/platform/features/layout/bundle.json index 5d073da347..760cd2a686 100644 --- a/platform/features/layout/bundle.json +++ b/platform/features/layout/bundle.json @@ -35,7 +35,7 @@ { "key": "FixedController", "implementation": "FixedController.js", - "depends": [ "$scope" ] + "depends": [ "$scope", "telemetrySubscriber", "telemetryFormatter" ] } ], "types": [ diff --git a/platform/features/layout/src/FixedController.js b/platform/features/layout/src/FixedController.js index 9ddf68d3fc..70a1ecc170 100644 --- a/platform/features/layout/src/FixedController.js +++ b/platform/features/layout/src/FixedController.js @@ -17,11 +17,13 @@ define( * @constructor * @param {Scope} $scope the controller's Angular scope */ - function FixedController($scope) { + function FixedController($scope, telemetrySubscriber, telemetryFormatter) { var gridSize = DEFAULT_GRID_SIZE, gridExtent = DEFAULT_GRID_EXTENT, activeDrag, activeDragId, + subscription, + values = {}, cellStyles = [], rawPositions = {}, positions = {}; @@ -105,9 +107,43 @@ define( ids.forEach(populatePosition); } + function updateValue(telemetryObject) { + var id = telemetryObject && telemetryObject.getId(); + if (id) { + values[id] = telemetryFormatter.formatRangeValue( + subscription.getRangeValue(telemetryObject) + ); + } + } + + // Update telemetry values based on new data available + function updateValues() { + if (subscription) { + subscription.getTelemetryObjects().forEach(updateValue); + } + } + + // Subscribe to telemetry updates for this domain object + function subscribe(domainObject) { + // Clear any old values + values = {}; + + // Release existing subscription (if any) + if (subscription) { + subscription.unsubscribe(); + } + + // Make a new subscription + subscription = domainObject && + telemetrySubscriber.subscribe(domainObject, updateValues); + } + // Position panes when the model field changes $scope.$watch("model", lookupPanels); + // Subscribe to telemetry when an object is available + $scope.$watch("domainObject", subscribe); + refreshCellStyles(); return { @@ -120,6 +156,15 @@ define( getCellStyles: function () { return cellStyles; }, + /** + * Get the current data value for the specified domain object. + * @memberof FixedController# + * @param {string} id the domain object identifier + * @returns {string} the displayable data value + */ + getValue: function (id) { + return values[id]; + }, /** * Set the size of the viewable fixed position area. * @memberof FixedController# From 082b55564478eb08e0dd40d23e924006da45a94d Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Fri, 16 Jan 2015 09:47:29 -0800 Subject: [PATCH 10/22] [Fixed Position] Persist drag positions Persist element positions after drag in fixed position view, WTD-615. --- platform/features/layout/res/templates/fixed.html | 2 +- platform/features/layout/src/FixedController.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/features/layout/res/templates/fixed.html b/platform/features/layout/res/templates/fixed.html index b7b99ec21c..b91f3e524b 100644 --- a/platform/features/layout/res/templates/fixed.html +++ b/platform/features/layout/res/templates/fixed.html @@ -19,7 +19,7 @@ {{childObject.getModel().name}}
- X{{controller.getValue(childObject.getId())}} + {{controller.getValue(childObject.getId())}}
diff --git a/platform/features/layout/src/FixedController.js b/platform/features/layout/src/FixedController.js index 70a1ecc170..6eb93e9fc2 100644 --- a/platform/features/layout/src/FixedController.js +++ b/platform/features/layout/src/FixedController.js @@ -95,7 +95,7 @@ define( ids = (model || {}).composition || []; // Pull panel positions from configuration - rawPositions = shallowCopy(configuration.panels || {}, ids); + rawPositions = shallowCopy(configuration.elements || {}, ids); // Clear prior computed positions positions = {}; From abe4be92385ef48523f1ef7c5ce10946c5684995 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Tue, 17 Feb 2015 08:30:42 -0800 Subject: [PATCH 11/22] [Fixed Position] Remove unused representer Remove unused representer for view toolbars; clean up for WTD-889. --- .../commonUI/edit/src/ToolbarRepresenter.js | 37 ------------------- 1 file changed, 37 deletions(-) delete mode 100644 platform/commonUI/edit/src/ToolbarRepresenter.js diff --git a/platform/commonUI/edit/src/ToolbarRepresenter.js b/platform/commonUI/edit/src/ToolbarRepresenter.js deleted file mode 100644 index 97a424fc83..0000000000 --- a/platform/commonUI/edit/src/ToolbarRepresenter.js +++ /dev/null @@ -1,37 +0,0 @@ -/*global define*/ - -define( - [], - function () { - - function ToolbarRepresenter(scope, element, attrs) { - var parent = scope.$parent; - - function represent(domainObject, representation) { - // New domain object, clear out the tool bar - parent.toolbar = {}; - scope.toolbar = parent.toolbar; - } - - return { - /** - * Set the current representation in use, and the domain - * object being represented. - * - * @param {RepresentationDefinition} representation the - * definition of the representation in use - * @param {DomainObject} domainObject the domain object - * being represented - */ - represent: represent, - /** - * Release any resources associated with this representer. - */ - destroy: function () {} - }; - } - - return ToolbarRepresenter; - - } -); \ No newline at end of file From 71a132d374c4701245d36f002f2637196d98aeb8 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Tue, 17 Feb 2015 08:32:35 -0800 Subject: [PATCH 12/22] [Fixed Position] Improve doc of FixedController Improve documentation for Fixed Position controller, WTD-889. --- platform/features/layout/src/FixedController.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/platform/features/layout/src/FixedController.js b/platform/features/layout/src/FixedController.js index 6eb93e9fc2..2028a2d4e4 100644 --- a/platform/features/layout/src/FixedController.js +++ b/platform/features/layout/src/FixedController.js @@ -107,6 +107,7 @@ define( ids.forEach(populatePosition); } + // Update the displayed value for this object function updateValue(telemetryObject) { var id = telemetryObject && telemetryObject.getId(); if (id) { @@ -144,6 +145,7 @@ define( // Subscribe to telemetry when an object is available $scope.$watch("domainObject", subscribe); + // Initialize styles (position etc.) for cells refreshCellStyles(); return { From c2b1775d756e624187e940308c49a77bd3396357 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Tue, 17 Feb 2015 08:35:32 -0800 Subject: [PATCH 13/22] [Fixed Position] Free up resources Free up resources when a fixed position view is destroyed, WTD-889. --- platform/features/layout/src/FixedController.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/platform/features/layout/src/FixedController.js b/platform/features/layout/src/FixedController.js index 2028a2d4e4..9dc59c1764 100644 --- a/platform/features/layout/src/FixedController.js +++ b/platform/features/layout/src/FixedController.js @@ -124,6 +124,14 @@ define( } } + // Free up subscription to telemetry + function releaseSubscription() { + if (subscription) { + subscription.unsubscribe(); + subscription = undefined; + } + } + // Subscribe to telemetry updates for this domain object function subscribe(domainObject) { // Clear any old values @@ -145,6 +153,9 @@ define( // Subscribe to telemetry when an object is available $scope.$watch("domainObject", subscribe); + // Free up subscription on destroy + $scope.$on("$destroy", releaseSubscription); + // Initialize styles (position etc.) for cells refreshCellStyles(); From 8d6b2186469521a86d6ac3c85cecc900ba90692f Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Tue, 17 Feb 2015 09:03:23 -0800 Subject: [PATCH 14/22] [Fixed Position] Add initial spec Add initial spec for FixedController to satisfy minimum coverage requirements, in preparation for review. WTD-889. --- .../layout/test/FixedControllerSpec.js | 162 ++++++++++++++++++ platform/features/layout/test/suite.json | 1 + 2 files changed, 163 insertions(+) create mode 100644 platform/features/layout/test/FixedControllerSpec.js diff --git a/platform/features/layout/test/FixedControllerSpec.js b/platform/features/layout/test/FixedControllerSpec.js new file mode 100644 index 0000000000..0293905909 --- /dev/null +++ b/platform/features/layout/test/FixedControllerSpec.js @@ -0,0 +1,162 @@ +/*global define,describe,it,expect,beforeEach,jasmine*/ + +define( + ["../src/FixedController"], + function (FixedController) { + "use strict"; + + describe("The Fixed Position controller", function () { + var mockScope, + mockSubscriber, + mockFormatter, + mockDomainObject, + mockSubscription, + testGrid, + testModel, + testValues, + controller; + + // Utility function; find a watch for a given expression + function findWatch(expr) { + var watch; + mockScope.$watch.calls.forEach(function (call) { + if (call.args[0] === expr) { + watch = call.args[1]; + } + }); + return watch; + } + + function makeMockDomainObject(id) { + var mockObject = jasmine.createSpyObj( + 'domainObject-' + id, + [ 'getId' ] + ); + mockObject.getId.andReturn(id); + return mockObject; + } + + beforeEach(function () { + mockScope = jasmine.createSpyObj( + '$scope', + [ "$on", "$watch" ] + ); + mockSubscriber = jasmine.createSpyObj( + 'telemetrySubscriber', + [ 'subscribe' ] + ); + mockFormatter = jasmine.createSpyObj( + 'telemetryFormatter', + [ 'formatDomainValue', 'formatRangeValue' ] + ); + mockDomainObject = jasmine.createSpyObj( + 'domainObject', + [ 'getId', 'getModel', 'getCapability' ] + ); + mockSubscription = jasmine.createSpyObj( + 'subscription', + [ 'unsubscribe', 'getTelemetryObjects', 'getRangeValue' ] + ); + + testGrid = [ 123, 456 ]; + testModel = { + composition: ['a', 'b', 'c'], + layoutGrid: testGrid + }; + testValues = { a: 10, b: 42, c: 31.42 }; + + mockSubscriber.subscribe.andReturn(mockSubscription); + mockSubscription.getTelemetryObjects.andReturn( + testModel.composition.map(makeMockDomainObject) + ); + mockSubscription.getRangeValue.andCallFake(function (o) { + return testValues[o.getId()]; + }); + mockFormatter.formatRangeValue.andCallFake(function (v) { + return "Formatted " + v; + }); + + controller = new FixedController( + mockScope, + mockSubscriber, + mockFormatter + ); + }); + + it("provides styles for cells", function () { + expect(controller.getCellStyles()) + .toEqual(jasmine.any(Array)); + }); + + it("subscribes when a domain object is available", function () { + mockScope.domainObject = mockDomainObject; + findWatch("domainObject")(mockDomainObject); + expect(mockSubscriber.subscribe).toHaveBeenCalledWith( + mockDomainObject, + jasmine.any(Function) + ); + }); + + it("releases subscriptions when domain objects change", function () { + mockScope.domainObject = mockDomainObject; + + // First pass - should simply should subscribe + findWatch("domainObject")(mockDomainObject); + expect(mockSubscription.unsubscribe).not.toHaveBeenCalled(); + expect(mockSubscriber.subscribe.calls.length).toEqual(1); + + // Object changes - should unsubscribe then resubscribe + findWatch("domainObject")(mockDomainObject); + expect(mockSubscription.unsubscribe).toHaveBeenCalled(); + expect(mockSubscriber.subscribe.calls.length).toEqual(2); + }); + + it("configures view based on model", function () { + mockScope.model = testModel; + findWatch("model")(mockScope.model); + // Should have styles for all elements of composition + expect(controller.getStyle('a')).toBeDefined(); + expect(controller.getStyle('b')).toBeDefined(); + expect(controller.getStyle('c')).toBeDefined(); + expect(controller.getStyle('d')).not.toBeDefined(); + }); + + it("provides values for telemetry elements", function () { + // Initialize + mockScope.domainObject = mockDomainObject; + mockScope.model = testModel; + findWatch("domainObject")(mockDomainObject); + findWatch("model")(mockScope.model); + + // Invoke the subscription callback + mockSubscriber.subscribe.mostRecentCall.args[1](); + + // Formatted values should be available + expect(controller.getValue('a')).toEqual("Formatted 10"); + expect(controller.getValue('b')).toEqual("Formatted 42"); + expect(controller.getValue('c')).toEqual("Formatted 31.42"); + }); + + it("adds grid cells to fill boundaries", function () { + var s1 = { + width: testGrid[0] * 8, + height: testGrid[1] * 4 + }, + s2 = { + width: testGrid[0] * 10, + height: testGrid[1] * 6 + }; + + mockScope.model = testModel; + findWatch("model")(mockScope.model); + + // Set first bounds + controller.setBounds(s1); + expect(controller.getCellStyles().length).toEqual(32); // 8 * 4 + // Set new bounds + controller.setBounds(s2); + expect(controller.getCellStyles().length).toEqual(60); // 10 * 6 + }); + }); + } +); \ No newline at end of file diff --git a/platform/features/layout/test/suite.json b/platform/features/layout/test/suite.json index 9fbd76b85f..6e62994ff5 100644 --- a/platform/features/layout/test/suite.json +++ b/platform/features/layout/test/suite.json @@ -1,4 +1,5 @@ [ + "FixedController", "LayoutController", "LayoutDrag" ] \ No newline at end of file From 4190941bfb1037d12370e26b5c9fca8821626894 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Tue, 17 Feb 2015 10:01:27 -0800 Subject: [PATCH 15/22] [Views] Broadcast event on drop Broadcast an event when drag-drop domain object composition occurs, such that the view in question may utilize the drop coordinates (e.g. to position elements in a layout or fixed position view.) WTD-877. --- .../representation/src/gestures/DropGesture.js | 18 ++++++++++++++++++ .../src/gestures/GestureConstants.js | 6 +++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/platform/representation/src/gestures/DropGesture.js b/platform/representation/src/gestures/DropGesture.js index bcd49713fe..00faa83710 100644 --- a/platform/representation/src/gestures/DropGesture.js +++ b/platform/representation/src/gestures/DropGesture.js @@ -20,6 +20,19 @@ define( */ function DropGesture($q, element, domainObject) { + function broadcastDrop(id, event) { + // Find the relevant scope... + var scope = element && element.scope && element.scope(); + if (scope && scope.$broadcast) { + // ...and broadcast the event. This allows specific + // views to have post-drop behavior which depends on + // drop position. + scope.$broadcast( + GestureConstants.MCT_DROP_EVENT, + { id: id, dropEvent: event } + ); + } + } function doPersist() { var persistence = domainObject.getCapability("persistence"); @@ -60,6 +73,11 @@ define( } } )).then(function (result) { + // Broadcast the drop event if it was successful + if (result) { + broadcastDrop(id, event); + } + // If mutation was successful, persist the change return result && doPersist(); }); diff --git a/platform/representation/src/gestures/GestureConstants.js b/platform/representation/src/gestures/GestureConstants.js index ae35fa439f..126a7b3981 100644 --- a/platform/representation/src/gestures/GestureConstants.js +++ b/platform/representation/src/gestures/GestureConstants.js @@ -14,5 +14,9 @@ define({ * An estimate for the dimensions of a context menu, used for * positioning. */ - MCT_MENU_DIMENSIONS: [ 170, 200 ] + MCT_MENU_DIMENSIONS: [ 170, 200 ], + /** + * Identifier for drop events. + */ + MCT_DROP_EVENT: 'mctDrop' }); \ No newline at end of file From e158f2811ca1fd4600b6f21c0d5a315b81cfa1d7 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Tue, 17 Feb 2015 10:03:48 -0800 Subject: [PATCH 16/22] [Views] Wire in drop gesture Support drop gesture from fixed position view and from layout view, WTD-877. --- platform/features/layout/bundle.json | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/platform/features/layout/bundle.json b/platform/features/layout/bundle.json index 760cd2a686..0ce44d3016 100644 --- a/platform/features/layout/bundle.json +++ b/platform/features/layout/bundle.json @@ -9,7 +9,8 @@ "glyph": "L", "type": "layout", "templateUrl": "templates/layout.html", - "uses": [ "composition" ] + "uses": [ "composition" ], + "gestures": [ "drop" ] }, { "key": "fixed", @@ -17,7 +18,8 @@ "glyph": "3", "type": "telemetry.panel", "templateUrl": "templates/fixed.html", - "uses": [ "composition" ] + "uses": [ "composition" ], + "gestures": [ "drop" ] } ], "representations": [ From 01d953bf4580be461a38b75b980d2a92bd1ce622 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Tue, 17 Feb 2015 10:23:10 -0800 Subject: [PATCH 17/22] [Layout] Position frames on drop Position frames within a layout based on the position where they were dropped into the layout, WTD-877. --- .../features/layout/src/LayoutController.js | 20 +++++++++++++++++++ .../src/gestures/DropGesture.js | 13 ++++++++++-- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/platform/features/layout/src/LayoutController.js b/platform/features/layout/src/LayoutController.js index 70a5126d78..9843252afb 100644 --- a/platform/features/layout/src/LayoutController.js +++ b/platform/features/layout/src/LayoutController.js @@ -85,6 +85,26 @@ define( // Position panes when the model field changes $scope.$watch("model.composition", lookupPanels); + // Position panes where they are dropped + $scope.$on("mctDrop", function (e, id, position) { + // Make sure there is a "panels" field in the + // view configuration. + $scope.configuration.panels = + $scope.configuration.panels || {}; + // Store the position of this panel. + $scope.configuration.panels[id] = { + position: [ + Math.floor(position.x / gridSize[0]), + Math.floor(position.y / gridSize[1]) + ], + dimensions: DEFAULT_DIMENSIONS + }; + // Mark change as persistable + if ($scope.commit) { + $scope.commit("Dropped a frame."); + } + }); + return { /** * Get a style object for a frame with the specified domain diff --git a/platform/representation/src/gestures/DropGesture.js b/platform/representation/src/gestures/DropGesture.js index 00faa83710..985fe102d3 100644 --- a/platform/representation/src/gestures/DropGesture.js +++ b/platform/representation/src/gestures/DropGesture.js @@ -22,14 +22,23 @@ define( function DropGesture($q, element, domainObject) { function broadcastDrop(id, event) { // Find the relevant scope... - var scope = element && element.scope && element.scope(); + var scope = element && element.scope && element.scope(), + rect; if (scope && scope.$broadcast) { + // Get the representation's bounds, to convert + // drop position + rect = element[0].getBoundingClientRect(); + // ...and broadcast the event. This allows specific // views to have post-drop behavior which depends on // drop position. scope.$broadcast( GestureConstants.MCT_DROP_EVENT, - { id: id, dropEvent: event } + id, + { + x: event.pageX - rect.left, + y: event.pageY - rect.top + } ); } } From ef4ed506051cdf58a21aae80d8fe364f29b1b9be Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Tue, 17 Feb 2015 10:25:31 -0800 Subject: [PATCH 18/22] [Layout] Separate out handleDrop Separate drop-handling into a non-anonymous function in LayoutController to satisfy code style guidelines; WTD-877. --- platform/features/layout/src/LayoutController.js | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/platform/features/layout/src/LayoutController.js b/platform/features/layout/src/LayoutController.js index 9843252afb..6eaefbfe88 100644 --- a/platform/features/layout/src/LayoutController.js +++ b/platform/features/layout/src/LayoutController.js @@ -82,11 +82,8 @@ define( ids.forEach(populatePosition); } - // Position panes when the model field changes - $scope.$watch("model.composition", lookupPanels); - - // Position panes where they are dropped - $scope.$on("mctDrop", function (e, id, position) { + // Position a panel after a drop event + function handleDrop(e, id, position) { // Make sure there is a "panels" field in the // view configuration. $scope.configuration.panels = @@ -103,7 +100,13 @@ define( if ($scope.commit) { $scope.commit("Dropped a frame."); } - }); + } + + // Position panes when the model field changes + $scope.$watch("model.composition", lookupPanels); + + // Position panes where they are dropped + $scope.$on("mctDrop", handleDrop); return { /** From 136dddab86c20339bf6ff546ab6c6887644c8cfe Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Tue, 17 Feb 2015 10:27:35 -0800 Subject: [PATCH 19/22] [Fixed Position] Position elements where dropped Position elements where they are dropped in Fixed Position view, WTD-877 --- .../features/layout/src/FixedController.js | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/platform/features/layout/src/FixedController.js b/platform/features/layout/src/FixedController.js index 9dc59c1764..29fb15fafb 100644 --- a/platform/features/layout/src/FixedController.js +++ b/platform/features/layout/src/FixedController.js @@ -147,6 +147,26 @@ define( telemetrySubscriber.subscribe(domainObject, updateValues); } + // Position a panel after a drop event + function handleDrop(e, id, position) { + // Make sure there is a "elements" field in the + // view configuration. + $scope.configuration.elements = + $scope.configuration.elements || {}; + // Store the position of this element. + $scope.configuration.elements[id] = { + position: [ + Math.floor(position.x / gridSize[0]), + Math.floor(position.y / gridSize[1]) + ], + dimensions: DEFAULT_DIMENSIONS + }; + // Mark change as persistable + if ($scope.commit) { + $scope.commit("Dropped a frame."); + } + } + // Position panes when the model field changes $scope.$watch("model", lookupPanels); @@ -156,6 +176,9 @@ define( // Free up subscription on destroy $scope.$on("$destroy", releaseSubscription); + // Position panes where they are dropped + $scope.$on("mctDrop", handleDrop); + // Initialize styles (position etc.) for cells refreshCellStyles(); From 553101100b94a92b7727511f37e96ab7af54ae7f Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Tue, 17 Feb 2015 10:34:13 -0800 Subject: [PATCH 20/22] [Fixed Position] Refresh subscriptions Refresh subscriptions when composition changes, such as due to a drag-drop addition of an element to the view. WTD-877. --- .../features/layout/src/FixedController.js | 18 +++++++++++++----- .../layout/test/FixedControllerSpec.js | 6 +++--- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/platform/features/layout/src/FixedController.js b/platform/features/layout/src/FixedController.js index 29fb15fafb..928dd770e8 100644 --- a/platform/features/layout/src/FixedController.js +++ b/platform/features/layout/src/FixedController.js @@ -90,9 +90,9 @@ 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 || {}; + ids = ids || []; // Pull panel positions from configuration rawPositions = shallowCopy(configuration.elements || {}, ids); @@ -101,7 +101,7 @@ 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); @@ -147,6 +147,14 @@ define( telemetrySubscriber.subscribe(domainObject, updateValues); } + // Handle changes in the object's composition + function updateComposition(ids) { + // Populate panel positions + lookupPanels(ids); + // Resubscribe - objects in view have changed + subscribe($scope.domainObject); + } + // Position a panel after a drop event function handleDrop(e, id, position) { // Make sure there is a "elements" field in the @@ -168,7 +176,7 @@ define( } // Position panes when the model field changes - $scope.$watch("model", lookupPanels); + $scope.$watch("model.composition", updateComposition); // Subscribe to telemetry when an object is available $scope.$watch("domainObject", subscribe); diff --git a/platform/features/layout/test/FixedControllerSpec.js b/platform/features/layout/test/FixedControllerSpec.js index 0293905909..8b5990069c 100644 --- a/platform/features/layout/test/FixedControllerSpec.js +++ b/platform/features/layout/test/FixedControllerSpec.js @@ -113,7 +113,7 @@ define( it("configures view based on model", function () { mockScope.model = testModel; - findWatch("model")(mockScope.model); + findWatch("model.composition")(mockScope.model.composition); // Should have styles for all elements of composition expect(controller.getStyle('a')).toBeDefined(); expect(controller.getStyle('b')).toBeDefined(); @@ -126,7 +126,7 @@ define( mockScope.domainObject = mockDomainObject; mockScope.model = testModel; findWatch("domainObject")(mockDomainObject); - findWatch("model")(mockScope.model); + findWatch("model.composition")(mockScope.model.composition); // Invoke the subscription callback mockSubscriber.subscribe.mostRecentCall.args[1](); @@ -148,7 +148,7 @@ define( }; mockScope.model = testModel; - findWatch("model")(mockScope.model); + findWatch("model.composition")(mockScope.model.composition); // Set first bounds controller.setBounds(s1); From 156f05342160b3be80b5719eb01721c8b6a0d6b9 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Tue, 17 Feb 2015 10:50:02 -0800 Subject: [PATCH 21/22] [Fixed Position] Add specs for drop Add specs related to positioning of objects based on drop position, WTD-877. --- .../features/layout/src/FixedController.js | 4 ++ .../features/layout/src/LayoutController.js | 4 ++ .../layout/test/FixedControllerSpec.js | 40 ++++++++++++++++++- .../layout/test/LayoutControllerSpec.js | 32 +++++++++++++-- 4 files changed, 75 insertions(+), 5 deletions(-) diff --git a/platform/features/layout/src/FixedController.js b/platform/features/layout/src/FixedController.js index 928dd770e8..07f0f99731 100644 --- a/platform/features/layout/src/FixedController.js +++ b/platform/features/layout/src/FixedController.js @@ -157,6 +157,8 @@ define( // Position a panel after a drop event function handleDrop(e, id, position) { + // Ensure that configuration field is populated + $scope.configuration = $scope.configuration || {}; // Make sure there is a "elements" field in the // view configuration. $scope.configuration.elements = @@ -173,6 +175,8 @@ define( if ($scope.commit) { $scope.commit("Dropped a frame."); } + // Populate template-facing position for this id + populatePosition(id); } // Position panes when the model field changes diff --git a/platform/features/layout/src/LayoutController.js b/platform/features/layout/src/LayoutController.js index 6eaefbfe88..c8e057d0f8 100644 --- a/platform/features/layout/src/LayoutController.js +++ b/platform/features/layout/src/LayoutController.js @@ -84,6 +84,8 @@ define( // Position a panel after a drop event function handleDrop(e, id, position) { + // Ensure that configuration field is populated + $scope.configuration = $scope.configuration || {}; // Make sure there is a "panels" field in the // view configuration. $scope.configuration.panels = @@ -100,6 +102,8 @@ define( if ($scope.commit) { $scope.commit("Dropped a frame."); } + // Populate template-facing position for this id + populatePosition(id); } // Position panes when the model field changes diff --git a/platform/features/layout/test/FixedControllerSpec.js b/platform/features/layout/test/FixedControllerSpec.js index 8b5990069c..61c8773907 100644 --- a/platform/features/layout/test/FixedControllerSpec.js +++ b/platform/features/layout/test/FixedControllerSpec.js @@ -27,6 +27,17 @@ define( return watch; } + // As above, but for $on calls + function findOn(expr) { + var on; + mockScope.$on.calls.forEach(function (call) { + if (call.args[0] === expr) { + on = call.args[1]; + } + }); + return on; + } + function makeMockDomainObject(id) { var mockObject = jasmine.createSpyObj( 'domainObject-' + id, @@ -39,7 +50,7 @@ define( beforeEach(function () { mockScope = jasmine.createSpyObj( '$scope', - [ "$on", "$watch" ] + [ "$on", "$watch", "commit" ] ); mockSubscriber = jasmine.createSpyObj( 'telemetrySubscriber', @@ -157,6 +168,33 @@ define( controller.setBounds(s2); expect(controller.getCellStyles().length).toEqual(60); // 10 * 6 }); + + it("listens for drop events", function () { + // Layout should position panels according to + // where the user dropped them, so it needs to + // listen for drop events. + expect(mockScope.$on).toHaveBeenCalledWith( + 'mctDrop', + jasmine.any(Function) + ); + + // Verify precondition + expect(controller.getStyle('d')).not.toBeDefined(); + + // Notify that a drop occurred + testModel.composition.push('d'); + findOn('mctDrop')( + {}, + 'd', + { x: 300, y: 100 } + ); + expect(controller.getStyle('d')).toBeDefined(); + + // Should have triggered commit (provided by + // EditRepresenter) with some message. + expect(mockScope.commit) + .toHaveBeenCalledWith(jasmine.any(String)); + }); }); } ); \ No newline at end of file diff --git a/platform/features/layout/test/LayoutControllerSpec.js b/platform/features/layout/test/LayoutControllerSpec.js index f80b356d74..3096cac1a2 100644 --- a/platform/features/layout/test/LayoutControllerSpec.js +++ b/platform/features/layout/test/LayoutControllerSpec.js @@ -14,7 +14,7 @@ define( beforeEach(function () { mockScope = jasmine.createSpyObj( "$scope", - [ "$watch" ] + [ "$watch", "$on", "commit" ] ); testModel = { @@ -97,9 +97,6 @@ define( // Populate scope mockScope.$watch.mostRecentCall.args[1](testModel.composition); - // Add a commit method to scope - mockScope.commit = jasmine.createSpy("commit"); - // Do a drag controller.startDrag("b", [1, 1], [0, 0]); controller.continueDrag([100, 100]); @@ -110,6 +107,33 @@ define( expect(mockScope.commit) .toHaveBeenCalledWith(jasmine.any(String)); }); + + it("listens for drop events", function () { + // Layout should position panels according to + // where the user dropped them, so it needs to + // listen for drop events. + expect(mockScope.$on).toHaveBeenCalledWith( + 'mctDrop', + jasmine.any(Function) + ); + + // Verify precondition + expect(testConfiguration.panels.d).not.toBeDefined(); + + // Notify that a drop occurred + testModel.composition.push('d'); + mockScope.$on.mostRecentCall.args[1]( + {}, + 'd', + { x: 300, y: 100 } + ); + expect(testConfiguration.panels.d).toBeDefined(); + + // Should have triggered commit (provided by + // EditRepresenter) with some message. + expect(mockScope.commit) + .toHaveBeenCalledWith(jasmine.any(String)); + }); }); } ); \ No newline at end of file From 0510705f3a52d64f6e4e853d3464b7d1007cb920 Mon Sep 17 00:00:00 2001 From: Victor Woeltjen Date: Tue, 17 Feb 2015 10:56:38 -0800 Subject: [PATCH 22/22] [Representation] Update docs Update documentation to reflect that an event is broadcast when drops occur. WTD-877. --- platform/representation/README.md | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/platform/representation/README.md b/platform/representation/README.md index 2408f645f8..cf4d2bee6b 100644 --- a/platform/representation/README.md +++ b/platform/representation/README.md @@ -1,4 +1,4 @@ -This bundle introduces the notion of "representations" to Open MCT Web, +This bundle introduces the notion of "representations" to Open MCT Web, primarily via an Angular directive, `mct-representation`. A representation is used to display domain objects as Angular templates. @@ -107,9 +107,14 @@ introduces three specific gestures as "built in" options, listed by key: drag-drop domain object composition. * `drop`: Representations with this gesture can serve as drop targets for drag-drop domain object composition. + * When a drop occurs, an `mctDrop` event will be broadcast with two + arguments (in addition to Angular's event object): The domain object + identifier for the dropped object, and the position (with `x` and `y` + properties in pixels) of the drop, relative to the top-left of the + representation which features the drop gesture. * `menu`: Representations with this gesture will provide a custom context menu (instead of the browser default). - * It should be noted that this gesture does _not_ define the appearance - or functionality of this menu; rather, it simply adds a - representation of key `context-menu` to the document at an appropriate - location. This representation will be supplied by the commonUI bundle. \ No newline at end of file + * It should be noted that this gesture does _not_ define the appearance + or functionality of this menu; rather, it simply adds a + representation of key `context-menu` to the document at an appropriate + location. This representation will be supplied by the commonUI bundle. \ No newline at end of file