196 lines
5.2 KiB
JavaScript
196 lines
5.2 KiB
JavaScript
/* 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,
|
|
onRemoveDeviceAssociation: PropTypes.func.isRequired,
|
|
onResizeViewport: PropTypes.func.isRequired,
|
|
onRotateViewport: PropTypes.func.isRequired,
|
|
onUpdateDeviceModal: 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.onRemoveDeviceAssociation();
|
|
}
|
|
|
|
this.setState({
|
|
lastClientX,
|
|
lastClientY
|
|
});
|
|
},
|
|
|
|
render() {
|
|
let {
|
|
devices,
|
|
location,
|
|
screenshot,
|
|
swapAfterMount,
|
|
viewport,
|
|
onBrowserMounted,
|
|
onChangeDevice,
|
|
onContentResize,
|
|
onResizeViewport,
|
|
onRotateViewport,
|
|
onUpdateDeviceModal,
|
|
} = 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,
|
|
viewport,
|
|
onChangeDevice,
|
|
onResizeViewport,
|
|
onRotateViewport,
|
|
onUpdateDeviceModal,
|
|
}),
|
|
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,
|
|
})
|
|
);
|
|
},
|
|
|
|
});
|