Blame devtools/client/responsive.html/components/ResizableViewport.js

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