From b9ab97eb7fdaf7d6689b5a86cad39fd12e6e5150 Mon Sep 17 00:00:00 2001 From: Aaron Doubek-Kraft Date: Wed, 28 Jun 2017 12:37:14 -0700 Subject: [PATCH] [Fixed Position] Add ability to work in pixel space Fix code style issues per Victor's review Add toggle to work in pixel space or grid space, per the issue description. Each element stores a boolean property that determines whether or not it snaps to grid space or pixel space. Coordinates are converted between spaces on toggle, preserving the size of the element in pixels. To complete: change UI element for toggle to a checkbox. --- platform/features/fixed/bundle.js | 17 ++- .../layout/res/templates/elements/line.html | 12 +- .../features/layout/src/FixedController.js | 9 +- .../features/layout/src/FixedDragHandle.js | 10 +- platform/features/layout/src/FixedProxy.js | 1 + .../features/layout/src/elements/BoxProxy.js | 5 +- .../layout/src/elements/ElementProxy.js | 112 +++++++++++++++++- .../layout/src/elements/ImageProxy.js | 5 +- .../layout/src/elements/LineHandle.js | 8 +- .../features/layout/src/elements/LineProxy.js | 13 +- .../layout/src/elements/ResizeHandle.js | 8 +- .../layout/src/elements/TelemetryProxy.js | 9 +- .../features/layout/src/elements/TextProxy.js | 5 +- 13 files changed, 178 insertions(+), 36 deletions(-) diff --git a/platform/features/fixed/bundle.js b/platform/features/fixed/bundle.js index 64f08d97ca..559149ff0c 100644 --- a/platform/features/fixed/bundle.js +++ b/platform/features/fixed/bundle.js @@ -177,7 +177,7 @@ define([ "name": "Y1", "cssClass": "l-input-sm", "control" : "numberfield", - "min": 0 + "min": "0" }, { "property": "editX2", @@ -212,6 +212,21 @@ define([ "control": "numberfield", "description": "Resize object width", "min": "1" + }, + { + "method": "setUnits", + "name": "Units", + "control": "menu-button", + "options": [ + { + "name": "px", + "key": "px" + }, + { + "name": "grid", + "key": "grid" + } + ] } ] }, diff --git a/platform/features/layout/res/templates/elements/line.html b/platform/features/layout/res/templates/elements/line.html index f040a8abc6..402a70bd41 100644 --- a/platform/features/layout/res/templates/elements/line.html +++ b/platform/features/layout/res/templates/elements/line.html @@ -19,12 +19,12 @@ this source code distribution or the Licensing information page available at runtime from the About dialog for additional information. --> - - + diff --git a/platform/features/layout/src/FixedController.js b/platform/features/layout/src/FixedController.js index 613a146974..de3c5a32f6 100644 --- a/platform/features/layout/src/FixedController.js +++ b/platform/features/layout/src/FixedController.js @@ -75,7 +75,7 @@ define( // Convert from element x/y/width/height to an // appropriate ng-style argument, to position elements. function convertPosition(elementProxy) { - var gridSize = self.gridSize; + var gridSize = elementProxy.getGridSize(); // Multiply position/dimensions by grid size return { left: (gridSize[0] * elementProxy.x()) + 'px', @@ -114,6 +114,7 @@ define( self.gridSize = layoutGrid; self.elementProxies.forEach(function (elementProxy) { + elementProxy.setGridSize(self.gridSize); elementProxy.style = convertPosition(elementProxy); }); } @@ -121,7 +122,7 @@ define( // Decorate an element for display function makeProxyElement(element, index, elements) { var ElementProxy = ElementProxies[element.type], - e = ElementProxy && new ElementProxy(element, index, elements); + e = ElementProxy && new ElementProxy(element, index, elements, self.gridSize); if (e) { // Provide a displayable position (convert from grid to px) @@ -254,7 +255,8 @@ define( color: "", titled: true, width: DEFAULT_DIMENSIONS[0], - height: DEFAULT_DIMENSIONS[1] + height: DEFAULT_DIMENSIONS[1], + useGrid: true }); //Re-initialize objects, and subscribe to new object @@ -518,4 +520,3 @@ define( return FixedController; } ); - diff --git a/platform/features/layout/src/FixedDragHandle.js b/platform/features/layout/src/FixedDragHandle.js index ca3f8f78fd..7ff5fb0576 100644 --- a/platform/features/layout/src/FixedDragHandle.js +++ b/platform/features/layout/src/FixedDragHandle.js @@ -47,9 +47,10 @@ define( * @memberof platform/features/layout.FixedDragHandle# */ FixedDragHandle.prototype.style = function () { + var gridSize = this.elementHandle.getGridSize(); // Adjust from grid to pixel coordinates - var x = this.elementHandle.x() * this.gridSize[0], - y = this.elementHandle.y() * this.gridSize[1]; + var x = this.elementHandle.x() * gridSize[0], + y = this.elementHandle.y() * gridSize[1]; // Convert to a CSS style centered on that point return { @@ -78,13 +79,14 @@ define( * started */ FixedDragHandle.prototype.continueDrag = function (delta) { + var gridSize = this.elementHandle.getGridSize(); if (this.dragging) { // Update x/y positions (snapping to grid) this.elementHandle.x( - this.dragging.x + Math.round(delta[0] / this.gridSize[0]) + this.dragging.x + Math.round(delta[0] / gridSize[0]) ); this.elementHandle.y( - this.dragging.y + Math.round(delta[1] / this.gridSize[1]) + this.dragging.y + Math.round(delta[1] / gridSize[1]) ); // Invoke update callback if (this.update) { diff --git a/platform/features/layout/src/FixedProxy.js b/platform/features/layout/src/FixedProxy.js index 8d2c03f7f2..6e62b26249 100644 --- a/platform/features/layout/src/FixedProxy.js +++ b/platform/features/layout/src/FixedProxy.js @@ -61,6 +61,7 @@ define( element.width = element.width || 1; element.height = element.height || 1; element.type = type; + element.useGrid = true; // Finally, add it to the view's configuration addElementCallback(element); diff --git a/platform/features/layout/src/elements/BoxProxy.js b/platform/features/layout/src/elements/BoxProxy.js index 6d80d8c1f9..a18d8f3fba 100644 --- a/platform/features/layout/src/elements/BoxProxy.js +++ b/platform/features/layout/src/elements/BoxProxy.js @@ -37,10 +37,11 @@ define( * @param element the fixed position element, as stored in its * configuration * @param index the element's index within its array + * @param {number[]} gridSize the current layout grid size in [x,y] from * @param {Array} elements the full array of elements */ - function BoxProxy(element, index, elements) { - var proxy = new ElementProxy(element, index, elements); + function BoxProxy(element, index, elements, gridSize) { + var proxy = new ElementProxy(element, index, elements, gridSize); /** * Get/set this element's fill color. (Omitting the diff --git a/platform/features/layout/src/elements/ElementProxy.js b/platform/features/layout/src/elements/ElementProxy.js index 7d75219adb..94ac7555b6 100644 --- a/platform/features/layout/src/elements/ElementProxy.js +++ b/platform/features/layout/src/elements/ElementProxy.js @@ -32,6 +32,10 @@ define( bottom: Number.NEGATIVE_INFINITY }; + // Mininmum pixel height and width for objects + var MIN_WIDTH = 10; + var MIN_HEIGHT = 10; + // Ensure a value is non-negative (for x/y setters) function clamp(value) { return Math.max(value, 0); @@ -51,17 +55,29 @@ define( * @param element the fixed position element, as stored in its * configuration * @param index the element's index within its array + * @param {number[]} gridSize the current layout grid size in [x,y] from * @param {Array} elements the full array of elements */ - function ElementProxy(element, index, elements) { - this.resizeHandles = [new ResizeHandle(element, 1, 1)]; - + function ElementProxy(element, index, elements, gridSize) { /** * The element as stored in the view configuration. * @memberof platform/features/layout.ElementProxy# */ this.element = element; + /** + * The current grid size of the layout. + * @memberof platform/features/layout.ElementProxy# + */ + this.gridSize = gridSize; + + this.resizeHandles = [new ResizeHandle( + this.element, + this.getMinWidth(), + this.getMinHeight(), + this.getGridSize() + )]; + /** * Get and/or set the x position of this element. * Units are in fixed position grid space. @@ -108,6 +124,7 @@ define( this.index = index; this.elements = elements; + this.useGrid = element.useGrid; } /** @@ -156,6 +173,95 @@ define( return this.resizeHandles; }; + /** + * Set whether this elements's position is determined in terms of grid + * units or pixels. + * @param {string} key Which unit to use, px or grid + */ + ElementProxy.prototype.setUnits = function (key) { + if (key === 'px' && this.element.useGrid === true) { + this.element.useGrid = false; + this.convertCoordsTo('px'); + } else if (key === 'grid' && this.element.useGrid === false) { + this.element.useGrid = true; + this.convertCoordsTo('grid'); + } + }; + + /** + * Convert this element's coordinates and size from pixels to grid units, + * or vice-versa. + * @param {string} unit When called with 'px', converts grid units to + * pixels; when called with 'grid', snaps element + * to grid units + */ + ElementProxy.prototype.convertCoordsTo = function (unit) { + var gridSize = this.gridSize; + var element = this.element; + var minWidth = this.getMinWidth(); + var minHeight = this.getMinHeight(); + if (unit === 'px') { + element.x = element.x * gridSize[0]; + element.y = element.y * gridSize[1]; + element.width = element.width * gridSize[0]; + element.height = element.height * gridSize[1]; + if (element.x2 && element.y2) { + element.x2 = element.x2 * gridSize[0]; + element.y2 = element.y2 * gridSize[1]; + } + } else if (unit === 'grid') { + element.x = Math.round(element.x / gridSize[0]); + element.y = Math.round(element.y / gridSize[1]); + element.width = Math.max(Math.round(element.width / gridSize[0]), minWidth); + element.height = Math.max(Math.round(element.height / gridSize[1]), minHeight); + if (element.x2 && element.y2) { + element.x2 = Math.round(element.x2 / gridSize[0]); + element.y2 = Math.round(element.y2 / gridSize[1]); + } + } + }; + + /** + * Returns which grid size the element is currently using. + * @return {number[]} The current grid size in [x,y] form if the element + * is currently using the grid, [1,1] if it is using + * pixels. + */ + ElementProxy.prototype.getGridSize = function () { + var gridSize; + if (this.element.useGrid) { + gridSize = this.gridSize; + } else { + gridSize = [1,1]; + } + return gridSize; + }; + + /** + * Set the current grid size stored by this element proxy + * @param {number[]} gridSize The current layout grid size in [x,y] form + */ + ElementProxy.prototype.setGridSize = function (gridSize) { + this.gridSize = gridSize; + }; + + /** + * Get the current minimum element width in grid units + * @return {number} The current minimum element width + */ + ElementProxy.prototype.getMinWidth = function () { + return Math.ceil(MIN_WIDTH / this.getGridSize()[0]); + + }; + + /** + * Get the current minimum element height in grid units + * @return {number} The current minimum element height + */ + ElementProxy.prototype.getMinHeight = function () { + return Math.ceil(MIN_HEIGHT / this.getGridSize()[1]); + }; + return ElementProxy; } ); diff --git a/platform/features/layout/src/elements/ImageProxy.js b/platform/features/layout/src/elements/ImageProxy.js index 1ff5b83ee1..0477d7b444 100644 --- a/platform/features/layout/src/elements/ImageProxy.js +++ b/platform/features/layout/src/elements/ImageProxy.js @@ -36,10 +36,11 @@ define( * configuration * @param index the element's index within its array * @param {Array} elements the full array of elements + * @param {number[]} gridSize the current layout grid size in [x,y] from * @augments {platform/features/layout.ElementProxy} */ - function ImageProxy(element, index, elements) { - var proxy = new ElementProxy(element, index, elements); + function ImageProxy(element, index, elements, gridSize) { + var proxy = new ElementProxy(element, index, elements, gridSize); /** * Get and/or set the displayed text of this element. diff --git a/platform/features/layout/src/elements/LineHandle.js b/platform/features/layout/src/elements/LineHandle.js index d51d5b4631..d9c30238e2 100644 --- a/platform/features/layout/src/elements/LineHandle.js +++ b/platform/features/layout/src/elements/LineHandle.js @@ -35,14 +35,16 @@ define( * @param {string} yProperty field which stores x position * @param {string} xOther field which stores x of other end * @param {string} yOther field which stores y of other end + * @param {number[]} gridSize the current layout grid size in [x,y] from * @implements {platform/features/layout.ElementHandle} */ - function LineHandle(element, xProperty, yProperty, xOther, yOther) { + function LineHandle(element, xProperty, yProperty, xOther, yOther, gridSize) { this.element = element; this.xProperty = xProperty; this.yProperty = yProperty; this.xOther = xOther; this.yOther = yOther; + this.gridSize = gridSize; } LineHandle.prototype.x = function (value) { @@ -83,6 +85,10 @@ define( return element[yProperty]; }; + LineHandle.prototype.getGridSize = function () { + return this.gridSize; + }; + return LineHandle; } diff --git a/platform/features/layout/src/elements/LineProxy.js b/platform/features/layout/src/elements/LineProxy.js index e121561061..f1cebfa78b 100644 --- a/platform/features/layout/src/elements/LineProxy.js +++ b/platform/features/layout/src/elements/LineProxy.js @@ -21,8 +21,8 @@ *****************************************************************************/ define( - ['./ElementProxy', './LineHandle','./AccessorMutator'], - function (ElementProxy, LineHandle,AccessorMutator) { + ['./ElementProxy', './LineHandle', './AccessorMutator'], + function (ElementProxy, LineHandle, AccessorMutator) { /** * Selection/diplay proxy for line elements of a fixed position @@ -33,13 +33,14 @@ define( * configuration * @param index the element's index within its array * @param {Array} elements the full array of elements + * @param {number[]} gridSize the current layout grid size in [x,y] from * @augments {platform/features/layout.ElementProxy} */ - function LineProxy(element, index, elements) { - var proxy = new ElementProxy(element, index, elements), + function LineProxy(element, index, elements, gridSize) { + var proxy = new ElementProxy(element, index, elements, gridSize), handles = [ - new LineHandle(element, 'x', 'y', 'x2', 'y2'), - new LineHandle(element, 'x2', 'y2', 'x', 'y') + new LineHandle(element, 'x', 'y', 'x2', 'y2', proxy.getGridSize()), + new LineHandle(element, 'x2', 'y2', 'x', 'y', proxy.getGridSize()) ]; /** diff --git a/platform/features/layout/src/elements/ResizeHandle.js b/platform/features/layout/src/elements/ResizeHandle.js index 7c5d7384db..f2c3526bf1 100644 --- a/platform/features/layout/src/elements/ResizeHandle.js +++ b/platform/features/layout/src/elements/ResizeHandle.js @@ -35,12 +35,14 @@ define( * @memberof platform/features/layout * @constructor */ - function ResizeHandle(element, minWidth, minHeight) { + function ResizeHandle(element, minWidth, minHeight, gridSize) { this.element = element; // Ensure reasonable defaults this.minWidth = minWidth || 0; this.minHeight = minHeight || 0; + + this.gridSize = gridSize; } ResizeHandle.prototype.x = function (value) { @@ -65,6 +67,10 @@ define( return element.y + element.height; }; + ResizeHandle.prototype.getGridSize = function () { + return this.gridSize; + }; + return ResizeHandle; } diff --git a/platform/features/layout/src/elements/TelemetryProxy.js b/platform/features/layout/src/elements/TelemetryProxy.js index 57668cddd8..bff852af9e 100644 --- a/platform/features/layout/src/elements/TelemetryProxy.js +++ b/platform/features/layout/src/elements/TelemetryProxy.js @@ -21,8 +21,8 @@ *****************************************************************************/ define( - ['./TextProxy','./AccessorMutator'], - function (TextProxy,AccessorMutator) { + ['./TextProxy'], + function (TextProxy) { // Method names to expose from this proxy var HIDE = 'hideTitle', SHOW = 'showTitle'; @@ -39,10 +39,11 @@ define( * configuration * @param index the element's index within its array * @param {Array} elements the full array of elements + * @param {number[]} gridSize the current layout grid size in [x,y] form * @augments {platform/features/layout.ElementProxy} */ - function TelemetryProxy(element, index, elements) { - var proxy = new TextProxy(element, index, elements); + function TelemetryProxy(element, index, elements, gridSize) { + var proxy = new TextProxy(element, index, elements, gridSize); // Toggle the visibility of the title function toggle() { diff --git a/platform/features/layout/src/elements/TextProxy.js b/platform/features/layout/src/elements/TextProxy.js index 4d76d9d896..939c88c5ef 100644 --- a/platform/features/layout/src/elements/TextProxy.js +++ b/platform/features/layout/src/elements/TextProxy.js @@ -36,10 +36,11 @@ define( * configuration * @param index the element's index within its array * @param {Array} elements the full array of elements + * @param {number[]} gridSize the current layout grid size in [x,y] from * @augments {platform/features/layout.ElementProxy} */ - function TextProxy(element, index, elements) { - var proxy = new BoxProxy(element, index, elements); + function TextProxy(element, index, elements, gridSize) { + var proxy = new BoxProxy(element, index, elements, gridSize); /** * Get and/or set the text color of this element.