| Index: chrome/browser/resources/options/chromeos/display_layout_manager.js
|
| diff --git a/chrome/browser/resources/options/chromeos/display_layout_manager.js b/chrome/browser/resources/options/chromeos/display_layout_manager.js
|
| index f264393e5c7ea3fd388f3ffd6d490972524b41f6..17317ac111ba4b5c9658398ab6d35484ba3b0045 100644
|
| --- a/chrome/browser/resources/options/chromeos/display_layout_manager.js
|
| +++ b/chrome/browser/resources/options/chromeos/display_layout_manager.js
|
| @@ -42,7 +42,7 @@ options.DisplayPosition;
|
| * layoutType: options.DisplayLayoutType,
|
| * name: string,
|
| * offset: number,
|
| - * originalPosition: !options.DisplayPosition,
|
| + * originalDivOffsets: !options.DisplayPosition,
|
| * parentId: string
|
| * }}
|
| */
|
| @@ -57,7 +57,7 @@ cr.define('options', function() {
|
| * @param {!options.DisplayPosition} point The point to check the position.
|
| * @return {options.DisplayLayoutType}
|
| */
|
| - function getPositionToRectangle(rect, point) {
|
| + function getLayoutTypeForPosition(rect, point) {
|
| // Separates the area into four (LEFT/RIGHT/TOP/BOTTOM) by the diagonals of
|
| // the rect, and decides which area the display should reside.
|
| var diagonalSlope = rect.height / rect.width;
|
| @@ -78,30 +78,22 @@ cr.define('options', function() {
|
| }
|
|
|
| /**
|
| - * Snaps the region [point, width] to [basePoint, baseWidth] if
|
| - * the [point, width] is close enough to the base's edge.
|
| - * @param {number} point The starting point of the region.
|
| - * @param {number} width The width of the region.
|
| - * @param {number} basePoint The starting point of the base region.
|
| - * @param {number} baseWidth The width of the base region.
|
| - * @return {number} The moved point. Returns the point itself if it doesn't
|
| - * need to snap to the edge.
|
| - * @private
|
| + * @param {options.DisplayLayoutType} layoutType
|
| + * @return {!options.DisplayLayoutType}
|
| */
|
| - function snapToEdge(point, width, basePoint, baseWidth) {
|
| - // If the edge of the region is smaller than this, it will snap to the
|
| - // base's edge.
|
| - /** @const */ var SNAP_DISTANCE_PX = 16;
|
| -
|
| - var startDiff = Math.abs(point - basePoint);
|
| - var endDiff = Math.abs(point + width - (basePoint + baseWidth));
|
| - // Prefer the closer one if both edges are close enough.
|
| - if (startDiff < SNAP_DISTANCE_PX && startDiff < endDiff)
|
| - return basePoint;
|
| - else if (endDiff < SNAP_DISTANCE_PX)
|
| - return basePoint + baseWidth - width;
|
| -
|
| - return point;
|
| + function invertLayoutType(layoutType) {
|
| + switch (layoutType) {
|
| + case options.DisplayLayoutType.RIGHT:
|
| + return options.DisplayLayoutType.LEFT;
|
| + case options.DisplayLayoutType.LEFT:
|
| + return options.DisplayLayoutType.RIGHT;
|
| + case options.DisplayLayoutType.TOP:
|
| + return options.DisplayLayoutType.BOTTOM;
|
| + case options.DisplayLayoutType.BOTTOM:
|
| + return options.DisplayLayoutType.TOP;
|
| + }
|
| + assertNotReached();
|
| + return layoutType;
|
| }
|
|
|
| /**
|
| @@ -139,6 +131,29 @@ cr.define('options', function() {
|
| displayAreaOffset_: null,
|
|
|
| /**
|
| + * Creates a DisplayLayout object representing the display.
|
| + * @param {string} id
|
| + * @param {string} name
|
| + * @param {options.DisplayBounds} bounds
|
| + * @param {!options.DisplayLayoutType} layoutType
|
| + * @param {string} parentId
|
| + * @return {!options.DisplayLayout}
|
| + * @private
|
| + */
|
| + createDisplayLayout: function(id, name, bounds, layoutType, parentId) {
|
| + return {
|
| + bounds: bounds,
|
| + div: null,
|
| + id: id,
|
| + layoutType: layoutType,
|
| + name: name,
|
| + offset: 0,
|
| + originalDivOffsets: {x: 0, y: 0},
|
| + parentId: parentId
|
| + };
|
| + },
|
| +
|
| + /**
|
| * Adds a display to the layout map.
|
| * @param {options.DisplayLayout} displayLayout
|
| */
|
| @@ -236,10 +251,10 @@ cr.define('options', function() {
|
| var baseLayout = this.getBaseLayout_(displayLayout);
|
| var baseDiv = baseLayout.div;
|
|
|
| - newPosition.x = snapToEdge(
|
| + newPosition.x = this.snapToEdge_(
|
| newPosition.x, div.offsetWidth, baseDiv.offsetLeft,
|
| baseDiv.offsetWidth);
|
| - newPosition.y = snapToEdge(
|
| + newPosition.y = this.snapToEdge_(
|
| newPosition.y, div.offsetHeight, baseDiv.offsetTop,
|
| baseDiv.offsetHeight);
|
|
|
| @@ -259,86 +274,38 @@ cr.define('options', function() {
|
| // a single parent with one child.
|
| var isPrimary = displayLayout.parentId == '';
|
|
|
| - // layoutType is always stored in the child layout.
|
| - var layoutType =
|
| - isPrimary ? baseLayout.layoutType : displayLayout.layoutType;
|
| -
|
| - switch (getPositionToRectangle(baseBounds, newCenter)) {
|
| - case options.DisplayLayoutType.RIGHT:
|
| - layoutType = isPrimary ? options.DisplayLayoutType.LEFT :
|
| - options.DisplayLayoutType.RIGHT;
|
| - break;
|
| - case options.DisplayLayoutType.LEFT:
|
| - layoutType = isPrimary ? options.DisplayLayoutType.RIGHT :
|
| - options.DisplayLayoutType.LEFT;
|
| - break;
|
| - case options.DisplayLayoutType.TOP:
|
| - layoutType = isPrimary ? options.DisplayLayoutType.BOTTOM :
|
| - options.DisplayLayoutType.TOP;
|
| - break;
|
| - case options.DisplayLayoutType.BOTTOM:
|
| - layoutType = isPrimary ? options.DisplayLayoutType.TOP :
|
| - options.DisplayLayoutType.BOTTOM;
|
| - break;
|
| - }
|
| + var layoutType = getLayoutTypeForPosition(baseBounds, newCenter);
|
| + if (isPrimary)
|
| + layoutType = invertLayoutType(layoutType);
|
|
|
| if (layoutType == options.DisplayLayoutType.LEFT ||
|
| layoutType == options.DisplayLayoutType.RIGHT) {
|
| - if (newPosition.y > baseDiv.offsetTop + baseDiv.offsetHeight)
|
| + if (newPosition.y > baseDiv.offsetTop + baseDiv.offsetHeight) {
|
| layoutType = isPrimary ? options.DisplayLayoutType.TOP :
|
| options.DisplayLayoutType.BOTTOM;
|
| - else if (newPosition.y + div.offsetHeight < baseDiv.offsetTop)
|
| + } else if (newPosition.y + div.offsetHeight < baseDiv.offsetTop) {
|
| layoutType = isPrimary ? options.DisplayLayoutType.BOTTOM :
|
| options.DisplayLayoutType.TOP;
|
| + }
|
| } else {
|
| - if (newPosition.x > baseDiv.offsetLeft + baseDiv.offsetWidth)
|
| + if (newPosition.x > baseDiv.offsetLeft + baseDiv.offsetWidth) {
|
| layoutType = isPrimary ? options.DisplayLayoutType.LEFT :
|
| options.DisplayLayoutType.RIGHT;
|
| - else if (newPosition.x + div.offsetWidth < baseDiv.offsetLeft)
|
| + } else if (newPosition.x + div.offsetWidth < baseDiv.offsetLeft) {
|
| layoutType = isPrimary ? options.DisplayLayoutType.RIGHT :
|
| options.DisplayLayoutType.LEFT;
|
| + }
|
| }
|
|
|
| - var layoutToBase;
|
| - if (!isPrimary) {
|
| - displayLayout.layoutType = layoutType;
|
| - layoutToBase = layoutType;
|
| - } else {
|
| + // layoutType is always stored in the child layout.
|
| + if (isPrimary)
|
| baseLayout.layoutType = layoutType;
|
| - switch (layoutType) {
|
| - case options.DisplayLayoutType.RIGHT:
|
| - layoutToBase = options.DisplayLayoutType.LEFT;
|
| - break;
|
| - case options.DisplayLayoutType.LEFT:
|
| - layoutToBase = options.DisplayLayoutType.RIGHT;
|
| - break;
|
| - case options.DisplayLayoutType.TOP:
|
| - layoutToBase = options.DisplayLayoutType.BOTTOM;
|
| - break;
|
| - case options.DisplayLayoutType.BOTTOM:
|
| - layoutToBase = options.DisplayLayoutType.TOP;
|
| - break;
|
| - }
|
| - }
|
| + else
|
| + displayLayout.layoutType = layoutType;
|
|
|
| - switch (layoutToBase) {
|
| - case options.DisplayLayoutType.RIGHT:
|
| - div.style.left = baseDiv.offsetLeft + baseDiv.offsetWidth + 'px';
|
| - div.style.top = newPosition.y + 'px';
|
| - break;
|
| - case options.DisplayLayoutType.LEFT:
|
| - div.style.left = baseDiv.offsetLeft - div.offsetWidth + 'px';
|
| - div.style.top = newPosition.y + 'px';
|
| - break;
|
| - case options.DisplayLayoutType.TOP:
|
| - div.style.top = baseDiv.offsetTop - div.offsetHeight + 'px';
|
| - div.style.left = newPosition.x + 'px';
|
| - break;
|
| - case options.DisplayLayoutType.BOTTOM:
|
| - div.style.top = baseDiv.offsetTop + baseDiv.offsetHeight + 'px';
|
| - div.style.left = newPosition.x + 'px';
|
| - break;
|
| - }
|
| + var layoutToBase = isPrimary ? invertLayoutType(layoutType) : layoutType;
|
| +
|
| + this.setDivPosition_(div, newPosition, baseDiv, layoutToBase);
|
| },
|
|
|
| /**
|
| @@ -348,42 +315,22 @@ cr.define('options', function() {
|
| * @return {boolean} True if the final position differs from the original.
|
| */
|
| finalizePosition: function(id) {
|
| - // Make sure the dragging location is connected.
|
| var displayLayout = this.displayLayoutMap_[id];
|
| var div = displayLayout.div;
|
| var baseLayout = this.getBaseLayout_(displayLayout);
|
| - var baseDiv = baseLayout.div;
|
|
|
| var isPrimary = displayLayout.parentId == '';
|
| var layoutType =
|
| isPrimary ? baseLayout.layoutType : displayLayout.layoutType;
|
|
|
| - // The number of pixels to share the edges between displays.
|
| - /** @const */ var MIN_OFFSET_OVERLAP = 5;
|
| -
|
| - if (layoutType == options.DisplayLayoutType.LEFT ||
|
| - layoutType == options.DisplayLayoutType.RIGHT) {
|
| - var top = Math.max(
|
| - div.offsetTop,
|
| - baseDiv.offsetTop - div.offsetHeight + MIN_OFFSET_OVERLAP);
|
| - top = Math.min(
|
| - top, baseDiv.offsetTop + baseDiv.offsetHeight - MIN_OFFSET_OVERLAP);
|
| - div.style.top = top + 'px';
|
| - } else {
|
| - var left = Math.max(
|
| - div.offsetLeft,
|
| - baseDiv.offsetLeft - div.offsetWidth + MIN_OFFSET_OVERLAP);
|
| - left = Math.min(
|
| - left,
|
| - baseDiv.offsetLeft + baseDiv.offsetWidth - MIN_OFFSET_OVERLAP);
|
| - div.style.left = left + 'px';
|
| - }
|
| + // Make sure the dragging location is connected.
|
| + this.adjustCorners_(div, baseLayout.div, layoutType);
|
|
|
| // Calculate the offset of the child display.
|
| this.calculateOffset_(isPrimary ? baseLayout : displayLayout);
|
|
|
| - return displayLayout.originalPosition.x != div.offsetLeft ||
|
| - displayLayout.originalPosition.y != div.offsetTop;
|
| + return displayLayout.originalDivOffsets.x != div.offsetLeft ||
|
| + displayLayout.originalDivOffsets.y != div.offsetTop;
|
| },
|
|
|
| /**
|
| @@ -442,7 +389,6 @@ cr.define('options', function() {
|
| createDisplayLayoutDiv_: function(id, displayAreaDiv) {
|
| var displayLayout = this.displayLayoutMap_[id];
|
| var parentId = displayLayout.parentId;
|
| - var offset = this.displayAreaOffset_;
|
| if (parentId) {
|
| // Ensure the parent div is created first.
|
| var parentLayout = this.displayLayoutMap_[parentId];
|
| @@ -452,6 +398,7 @@ cr.define('options', function() {
|
|
|
| var div = /** @type {!HTMLElement} */ (document.createElement('div'));
|
| div.className = 'displays-display';
|
| + displayLayout.div = div;
|
|
|
| // div needs to be added to the DOM tree first, otherwise offsetHeight for
|
| // nameContainer below cannot be computed.
|
| @@ -461,13 +408,31 @@ cr.define('options', function() {
|
| nameContainer.textContent = displayLayout.name;
|
| div.appendChild(nameContainer);
|
|
|
| - var bounds = displayLayout.bounds;
|
| - div.style.width = Math.floor(bounds.width * this.visualScale_) + 'px';
|
| - var newHeight = Math.floor(bounds.height * this.visualScale_);
|
| - div.style.height = newHeight + 'px';
|
| + var newHeight =
|
| + Math.floor(displayLayout.bounds.height * this.visualScale_);
|
| nameContainer.style.marginTop =
|
| (newHeight - nameContainer.offsetHeight) / 2 + 'px';
|
|
|
| + this.layoutDivFromBounds_(displayLayout);
|
| +
|
| + displayLayout.originalDivOffsets.x = div.offsetLeft;
|
| + displayLayout.originalDivOffsets.y = div.offsetTop;
|
| +
|
| + this.calculateOffset_(displayLayout);
|
| + },
|
| +
|
| + /**
|
| + * Calculates the div layout for displayLayout.
|
| + * @param {options.DisplayLayout} displayLayout
|
| + */
|
| + layoutDivFromBounds_: function(displayLayout) {
|
| + var div = displayLayout.div;
|
| + var bounds = displayLayout.bounds;
|
| +
|
| + div.style.width = Math.floor(bounds.width * this.visualScale_) + 'px';
|
| + div.style.height = Math.floor(bounds.height * this.visualScale_) + 'px';
|
| +
|
| + var offset = this.displayAreaOffset_;
|
| if (displayLayout.parentId == '') {
|
| div.style.left =
|
| Math.floor(bounds.left * this.visualScale_) + offset.x + 'px';
|
| @@ -503,15 +468,10 @@ cr.define('options', function() {
|
| }
|
| }
|
|
|
| - displayLayout.div = div;
|
| - displayLayout.originalPosition.x = div.offsetLeft;
|
| - displayLayout.originalPosition.y = div.offsetTop;
|
| -
|
| - this.calculateOffset_(displayLayout);
|
| },
|
|
|
| /**
|
| - * Calculates the offset for display |id| relative to its parent.
|
| + * Calculates the offset for displayLayout relative to its parent.
|
| * @param {options.DisplayLayout} displayLayout
|
| */
|
| calculateOffset_: function(displayLayout) {
|
| @@ -548,6 +508,101 @@ cr.define('options', function() {
|
| }
|
| assertNotReached();
|
| return null;
|
| + },
|
| +
|
| + /**
|
| + * Update the location |div| to the position closest to |newPosition| along
|
| + * the edge of |parentDiv| specified by |layoutType|.
|
| + * @param {?HTMLElement} div
|
| + * @param {options.DisplayPosition} newPosition
|
| + * @param {?HTMLElement} parentDiv
|
| + * @param {!options.DisplayLayoutType} layoutType
|
| + * @private
|
| + */
|
| + setDivPosition_(div, newPosition, parentDiv, layoutType) {
|
| + switch (layoutType) {
|
| + case options.DisplayLayoutType.RIGHT:
|
| + div.style.left = parentDiv.offsetLeft + parentDiv.offsetWidth + 'px';
|
| + div.style.top = newPosition.y + 'px';
|
| + break;
|
| + case options.DisplayLayoutType.LEFT:
|
| + div.style.left = parentDiv.offsetLeft - div.offsetWidth + 'px';
|
| + div.style.top = newPosition.y + 'px';
|
| + break;
|
| + case options.DisplayLayoutType.TOP:
|
| + div.style.top = parentDiv.offsetTop - div.offsetHeight + 'px';
|
| + div.style.left = newPosition.x + 'px';
|
| + break;
|
| + case options.DisplayLayoutType.BOTTOM:
|
| + div.style.top = parentDiv.offsetTop + parentDiv.offsetHeight + 'px';
|
| + div.style.left = newPosition.x + 'px';
|
| + break;
|
| + }
|
| + },
|
| +
|
| + /**
|
| + * Snaps the region [point, width] to [basePoint, baseWidth] if
|
| + * the [point, width] is close enough to the base's edge.
|
| + * @param {number} point The starting point of the region.
|
| + * @param {number} width The width of the region.
|
| + * @param {number} basePoint The starting point of the base region.
|
| + * @param {number} baseWidth The width of the base region.
|
| + * @param {number} opt_snapDistance Provide to override the snap distance.
|
| + * 0 means snap at any distance.
|
| + * @return {number} The moved point. Returns the point itself if it doesn't
|
| + * need to snap to the edge.
|
| + * @private
|
| + */
|
| + snapToEdge_: function(
|
| + point, width, basePoint, baseWidth, opt_snapDistance) {
|
| + // If the edge of the region is smaller than this, it will snap to the
|
| + // base's edge.
|
| + /** @const */ var SNAP_DISTANCE_PX = 16;
|
| + var snapDist;
|
| + if (opt_snapDistance !== undefined)
|
| + snapDist = opt_snapDistance;
|
| + else
|
| + snapDist = SNAP_DISTANCE_PX;
|
| + var startDiff = Math.abs(point - basePoint);
|
| + var endDiff = Math.abs(point + width - (basePoint + baseWidth));
|
| + // Prefer the closer one if both edges are close enough.
|
| + if ((!snapDist || startDiff < snapDist) && startDiff < endDiff)
|
| + return basePoint;
|
| + else if (!snapDist || endDiff < SNAP_DISTANCE_PX)
|
| + return basePoint + baseWidth - width;
|
| +
|
| + return point;
|
| + },
|
| +
|
| + /**
|
| + * Ensures that there is a minimum overlap when displays meet at a corner.
|
| + * @param {?HTMLElement} div
|
| + * @param {?HTMLElement} parentDiv
|
| + * @param {options.DisplayLayoutType} layoutType
|
| + * @private
|
| + */
|
| + adjustCorners_: function(div, parentDiv, layoutType) {
|
| + // The number of pixels to share the edges between displays.
|
| + /** @const */ var MIN_OFFSET_OVERLAP = 5;
|
| +
|
| + if (layoutType == options.DisplayLayoutType.LEFT ||
|
| + layoutType == options.DisplayLayoutType.RIGHT) {
|
| + var top = Math.max(
|
| + div.offsetTop,
|
| + parentDiv.offsetTop - div.offsetHeight + MIN_OFFSET_OVERLAP);
|
| + top = Math.min(
|
| + top,
|
| + parentDiv.offsetTop + parentDiv.offsetHeight - MIN_OFFSET_OVERLAP);
|
| + div.style.top = top + 'px';
|
| + } else {
|
| + var left = Math.max(
|
| + div.offsetLeft,
|
| + parentDiv.offsetLeft - div.offsetWidth + MIN_OFFSET_OVERLAP);
|
| + left = Math.min(
|
| + left,
|
| + parentDiv.offsetLeft + parentDiv.offsetWidth - MIN_OFFSET_OVERLAP);
|
| + div.style.left = left + 'px';
|
| + }
|
| }
|
| };
|
|
|
|
|