diff --git a/platform/features/layout/src/FixedController.js b/platform/features/layout/src/FixedController.js index afef3355b4..d40699ff8a 100644 --- a/platform/features/layout/src/FixedController.js +++ b/platform/features/layout/src/FixedController.js @@ -1,8 +1,8 @@ /*global define*/ define( - ['./LayoutDrag', './LayoutSelection', './FixedProxy', './elements/ElementProxies'], - function (LayoutDrag, LayoutSelection, FixedProxy, ElementProxies) { + ['./LayoutSelection', './FixedProxy', './elements/ElementProxies', './FixedDragHandle'], + function (LayoutSelection, FixedProxy, ElementProxies, FixedDragHandle) { "use strict"; var DEFAULT_DIMENSIONS = [ 2, 1 ], @@ -27,6 +27,7 @@ define( names = {}, // Cache names by ID values = {}, // Cache values by ID elementProxiesById = {}, + handles = [], selection; // Refresh cell styles (e.g. because grid extent changed) @@ -52,6 +53,16 @@ define( } } + // Generate a specific drag handle + function generateDragHandle(elementHandle) { + return new FixedDragHandle(elementHandle, gridSize, $scope.commit); + } + + // Generate drag handles for an element + function generateDragHandles(element) { + return element.handles().map(generateDragHandle); + } + // Convert from element x/y/width/height to an // apropriate ng-style argument, to position elements. function convertPosition(elementProxy) { @@ -275,11 +286,13 @@ define( return elementProxies; }, /** - * Check if the element is currently selected. + * Check if the element is currently selected, or (if no + * argument is supplied) get the currently selected element. * @returns {boolean} true if selected */ selected: function (element) { - return selection && selection.selected(element); + return selection && ((arguments.length > 0) ? + selection.selected(element) : selection.get()); }, /** * Set the active user selection in this view. @@ -288,6 +301,7 @@ define( select: function (element) { if (selection) { selection.select(element); + handles = generateDragHandles(element); } }, /** @@ -296,8 +310,16 @@ define( clearSelection: function () { if (selection) { selection.deselect(); + handles = []; } }, + /** + * Get drag handles. + * @returns {Array} drag handles for the current selection + */ + handles: function () { + return handles; + }, /** * Start a drag gesture to move/resize a frame. * diff --git a/platform/features/layout/src/FixedDragHandle.js b/platform/features/layout/src/FixedDragHandle.js new file mode 100644 index 0000000000..d01af84223 --- /dev/null +++ b/platform/features/layout/src/FixedDragHandle.js @@ -0,0 +1,52 @@ +/*global define*/ + +define( + [], + function () { + 'use strict'; + + + // 8 by 8 pixels + var DRAG_HANDLE_SIZE = [ 8, 8 ]; + + /** + * Template-displayable drag handle for an element in fixed + * position mode. + * @constructor + */ + function FixedDragHandle(elementHandle, gridSize, commit) { + var self = {}; + + function getStyle() { + // Adjust from grid to pixel coordinates + var x = elementHandle.x() * gridSize[0], + y = elementHandle.y() * gridSize[1]; + + // Convert to a CSS style centered on that point + return { + left: (x - DRAG_HANDLE_SIZE[0] / 2) + 'px', + right: (x - DRAG_HANDLE_SIZE[1] / 2) + 'px', + width: DRAG_HANDLE_SIZE[0] + 'px', + height: DRAG_HANDLE_SIZE[1] + 'px' + }; + } + + function noop() { + + } + + return { + /** + * Get a CSS style to position this drag handle. + * @returns CSS style object (for `ng-style`) + */ + style: getStyle, + startDrag: noop, + continueDrag: noop, + endDrag: noop + }; + } + + return FixedDragHandle; + } +); \ No newline at end of file diff --git a/platform/features/layout/src/elements/ElementProxy.js b/platform/features/layout/src/elements/ElementProxy.js index 7d5fa3540b..a041acf092 100644 --- a/platform/features/layout/src/elements/ElementProxy.js +++ b/platform/features/layout/src/elements/ElementProxy.js @@ -1,8 +1,8 @@ /*global define*/ define( - ['./AccessorMutator'], - function (AccessorMutator) { + ['./AccessorMutator', './ResizeHandle'], + function (AccessorMutator, ResizeHandle) { "use strict"; // Index deltas for changes in order @@ -29,6 +29,8 @@ define( * @param {Array} elements the full array of elements */ function ElementProxy(element, index, elements) { + var handles = [ new ResizeHandle(element, 1, 1) ]; + return { /** * The element as stored in the view configuration. @@ -97,6 +99,13 @@ define( if (elements[index] === element) { elements.splice(index, 1); } + }, + /** + * Get handles to control specific features of this element, + * e.g. corner size. + */ + handles: function () { + return handles; } }; } diff --git a/platform/features/layout/src/elements/ResizeHandle.js b/platform/features/layout/src/elements/ResizeHandle.js new file mode 100644 index 0000000000..bd9a3687e9 --- /dev/null +++ b/platform/features/layout/src/elements/ResizeHandle.js @@ -0,0 +1,43 @@ +/*global define*/ +define( + [], + function () { + 'use strict'; + + /** + * Handle for changing width/height properties of an element. + * This is used to support drag handles for different + * element types in a fixed position view. + * @constructor + */ + function ResizeHandle(element, minWidth, minHeight) { + // Ensure reasonable defaults + minWidth = minWidth || 0; + minHeight = minHeight || 0; + + return { + x: function (value) { + if (arguments.length > 0) { + element.width = Math.max( + minWidth, + value - element.x + ); + } + return element.x + element.width; + }, + y: function (value) { + if (arguments.length > 0) { + element.height = Math.max( + minHeight, + value - element.y + ); + } + return element.y + element.height; + } + }; + } + + return ResizeHandle; + + } +); \ No newline at end of file