diff options
Diffstat (limited to 'devtools/client/responsive.html/components/resizable-viewport.js')
-rw-r--r-- | devtools/client/responsive.html/components/resizable-viewport.js | 195 |
1 files changed, 195 insertions, 0 deletions
diff --git a/devtools/client/responsive.html/components/resizable-viewport.js b/devtools/client/responsive.html/components/resizable-viewport.js new file mode 100644 index 000000000..1d94cd052 --- /dev/null +++ b/devtools/client/responsive.html/components/resizable-viewport.js @@ -0,0 +1,195 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* global window */ + +"use strict"; + +const { DOM: dom, createClass, createFactory, PropTypes } = + require("devtools/client/shared/vendor/react"); + +const Constants = require("../constants"); +const Types = require("../types"); +const Browser = createFactory(require("./browser")); +const ViewportToolbar = createFactory(require("./viewport-toolbar")); + +const VIEWPORT_MIN_WIDTH = Constants.MIN_VIEWPORT_DIMENSION; +const VIEWPORT_MIN_HEIGHT = Constants.MIN_VIEWPORT_DIMENSION; + +module.exports = createClass({ + + displayName: "ResizableViewport", + + propTypes: { + devices: PropTypes.shape(Types.devices).isRequired, + location: Types.location.isRequired, + screenshot: PropTypes.shape(Types.screenshot).isRequired, + swapAfterMount: PropTypes.bool.isRequired, + viewport: PropTypes.shape(Types.viewport).isRequired, + onBrowserMounted: PropTypes.func.isRequired, + onChangeDevice: PropTypes.func.isRequired, + onContentResize: PropTypes.func.isRequired, + onRemoveDevice: PropTypes.func.isRequired, + onResizeViewport: PropTypes.func.isRequired, + onRotateViewport: PropTypes.func.isRequired, + onUpdateDeviceModalOpen: PropTypes.func.isRequired, + }, + + getInitialState() { + return { + isResizing: false, + lastClientX: 0, + lastClientY: 0, + ignoreX: false, + ignoreY: false, + }; + }, + + onResizeStart({ target, clientX, clientY }) { + window.addEventListener("mousemove", this.onResizeDrag, true); + window.addEventListener("mouseup", this.onResizeStop, true); + + this.setState({ + isResizing: true, + lastClientX: clientX, + lastClientY: clientY, + ignoreX: target === this.refs.resizeBarY, + ignoreY: target === this.refs.resizeBarX, + }); + }, + + onResizeStop() { + window.removeEventListener("mousemove", this.onResizeDrag, true); + window.removeEventListener("mouseup", this.onResizeStop, true); + + this.setState({ + isResizing: false, + lastClientX: 0, + lastClientY: 0, + ignoreX: false, + ignoreY: false, + }); + }, + + onResizeDrag({ clientX, clientY }) { + if (!this.state.isResizing) { + return; + } + + let { lastClientX, lastClientY, ignoreX, ignoreY } = this.state; + // the viewport is centered horizontally, so horizontal resize resizes + // by twice the distance the mouse was dragged - on left and right side. + let deltaX = 2 * (clientX - lastClientX); + let deltaY = (clientY - lastClientY); + + if (ignoreX) { + deltaX = 0; + } + if (ignoreY) { + deltaY = 0; + } + + let width = this.props.viewport.width + deltaX; + let height = this.props.viewport.height + deltaY; + + if (width < VIEWPORT_MIN_WIDTH) { + width = VIEWPORT_MIN_WIDTH; + } else { + lastClientX = clientX; + } + + if (height < VIEWPORT_MIN_HEIGHT) { + height = VIEWPORT_MIN_HEIGHT; + } else { + lastClientY = clientY; + } + + // Update the viewport store with the new width and height. + this.props.onResizeViewport(width, height); + // Change the device selector back to an unselected device + // TODO: Bug 1332754: Logic like this probably belongs in the action creator. + if (this.props.viewport.device) { + // In bug 1329843 and others, we may eventually stop this approach of removing the + // the properties of the device on resize. However, at the moment, there is no + // way to edit dPR when a device is selected, and there is no UI at all for editing + // UA, so it's important to keep doing this for now. + this.props.onRemoveDevice(); + } + + this.setState({ + lastClientX, + lastClientY + }); + }, + + render() { + let { + devices, + location, + screenshot, + swapAfterMount, + viewport, + onBrowserMounted, + onChangeDevice, + onContentResize, + onResizeViewport, + onRotateViewport, + onUpdateDeviceModalOpen, + } = this.props; + + let resizeHandleClass = "viewport-resize-handle"; + if (screenshot.isCapturing) { + resizeHandleClass += " hidden"; + } + + let contentClass = "viewport-content"; + if (this.state.isResizing) { + contentClass += " resizing"; + } + + return dom.div( + { + className: "resizable-viewport", + }, + ViewportToolbar({ + devices, + selectedDevice: viewport.device, + onChangeDevice, + onResizeViewport, + onRotateViewport, + onUpdateDeviceModalOpen, + }), + dom.div( + { + className: contentClass, + style: { + width: viewport.width + "px", + height: viewport.height + "px", + }, + }, + Browser({ + location, + swapAfterMount, + onBrowserMounted, + onContentResize, + }) + ), + dom.div({ + className: resizeHandleClass, + onMouseDown: this.onResizeStart, + }), + dom.div({ + ref: "resizeBarX", + className: "viewport-horizontal-resize-handle", + onMouseDown: this.onResizeStart, + }), + dom.div({ + ref: "resizeBarY", + className: "viewport-vertical-resize-handle", + onMouseDown: this.onResizeStart, + }) + ); + }, + +}); |