зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1241326 - Implement resize handles to change viewport size on drag r=jryans
This commit is contained in:
Родитель
639ffd2893
Коммит
0843c76b88
|
@ -17,6 +17,9 @@ createEnum([
|
|||
// Add an additional viewport to display the document.
|
||||
"ADD_VIEWPORT",
|
||||
|
||||
// Resize the viewport.
|
||||
"RESIZE_VIEWPORT",
|
||||
|
||||
// Rotate the viewport.
|
||||
"ROTATE_VIEWPORT",
|
||||
|
||||
|
|
|
@ -4,7 +4,11 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const { ADD_VIEWPORT, ROTATE_VIEWPORT } = require("./index");
|
||||
const {
|
||||
ADD_VIEWPORT,
|
||||
RESIZE_VIEWPORT,
|
||||
ROTATE_VIEWPORT
|
||||
} = require("./index");
|
||||
|
||||
module.exports = {
|
||||
|
||||
|
@ -17,6 +21,18 @@ module.exports = {
|
|||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Resize the viewport.
|
||||
*/
|
||||
resizeViewport(id, width, height) {
|
||||
return {
|
||||
type: RESIZE_VIEWPORT,
|
||||
id,
|
||||
width,
|
||||
height,
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Rotate the viewport.
|
||||
*/
|
||||
|
|
|
@ -8,7 +8,7 @@ const { createClass, createFactory, PropTypes } =
|
|||
require("devtools/client/shared/vendor/react");
|
||||
const { connect } = require("devtools/client/shared/vendor/react-redux");
|
||||
|
||||
const { rotateViewport } = require("./actions/viewports");
|
||||
const { resizeViewport, rotateViewport } = require("./actions/viewports");
|
||||
const Types = require("./types");
|
||||
const Viewports = createFactory(require("./components/viewports"));
|
||||
|
||||
|
@ -34,6 +34,8 @@ let App = createClass({
|
|||
location,
|
||||
viewports,
|
||||
onRotateViewport: id => dispatch(rotateViewport(id)),
|
||||
onResizeViewport: (id, width, height) =>
|
||||
dispatch(resizeViewport(id, width, height)),
|
||||
});
|
||||
},
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const { DOM: dom, createClass } =
|
||||
const { DOM: dom, createClass, PropTypes } =
|
||||
require("devtools/client/shared/vendor/react");
|
||||
|
||||
const Types = require("../types");
|
||||
|
@ -17,6 +17,7 @@ module.exports = createClass({
|
|||
location: Types.location.isRequired,
|
||||
width: Types.viewport.width.isRequired,
|
||||
height: Types.viewport.height.isRequired,
|
||||
isResizing: PropTypes.bool.isRequired,
|
||||
},
|
||||
|
||||
render() {
|
||||
|
@ -24,11 +25,17 @@ module.exports = createClass({
|
|||
location,
|
||||
width,
|
||||
height,
|
||||
isResizing,
|
||||
} = this.props;
|
||||
|
||||
let className = "browser";
|
||||
if (isResizing) {
|
||||
className += " resizing";
|
||||
}
|
||||
|
||||
return dom.iframe(
|
||||
{
|
||||
className: "browser",
|
||||
className,
|
||||
src: location,
|
||||
width,
|
||||
height,
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
DevToolsModules(
|
||||
'browser.js',
|
||||
'resizable-viewport.js',
|
||||
'viewport-toolbar.js',
|
||||
'viewport.js',
|
||||
'viewports.js',
|
||||
|
|
|
@ -0,0 +1,143 @@
|
|||
/* 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 Types = require("../types");
|
||||
const Browser = createFactory(require("./browser"));
|
||||
const ViewportToolbar = createFactory(require("./viewport-toolbar"));
|
||||
|
||||
const VIEWPORT_MIN_WIDTH = 280;
|
||||
const VIEWPORT_MIN_HEIGHT = 280;
|
||||
|
||||
module.exports = createClass({
|
||||
|
||||
displayName: "ResizableViewport",
|
||||
|
||||
propTypes: {
|
||||
location: Types.location.isRequired,
|
||||
viewport: PropTypes.shape(Types.viewport).isRequired,
|
||||
onResizeViewport: PropTypes.func.isRequired,
|
||||
onRotateViewport: 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;
|
||||
let deltaX = 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);
|
||||
|
||||
this.setState({
|
||||
lastClientX,
|
||||
lastClientY
|
||||
});
|
||||
},
|
||||
|
||||
render() {
|
||||
let {
|
||||
location,
|
||||
viewport,
|
||||
onRotateViewport,
|
||||
} = this.props;
|
||||
|
||||
return dom.div(
|
||||
{
|
||||
className: "resizable-viewport",
|
||||
},
|
||||
ViewportToolbar({
|
||||
onRotateViewport,
|
||||
}),
|
||||
Browser({
|
||||
location,
|
||||
width: viewport.width,
|
||||
height: viewport.height,
|
||||
isResizing: this.state.isResizing
|
||||
}),
|
||||
dom.div({
|
||||
className: "viewport-resize-handle",
|
||||
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,
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
});
|
|
@ -8,8 +8,7 @@ const { DOM: dom, createClass, createFactory, PropTypes } =
|
|||
require("devtools/client/shared/vendor/react");
|
||||
|
||||
const Types = require("../types");
|
||||
const Browser = createFactory(require("./browser"));
|
||||
const ViewportToolbar = createFactory(require("./viewport-toolbar"));
|
||||
const ResizableViewport = createFactory(require("./resizable-viewport"));
|
||||
|
||||
module.exports = createClass({
|
||||
|
||||
|
@ -18,6 +17,7 @@ module.exports = createClass({
|
|||
propTypes: {
|
||||
location: Types.location.isRequired,
|
||||
viewport: PropTypes.shape(Types.viewport).isRequired,
|
||||
onResizeViewport: PropTypes.func.isRequired,
|
||||
onRotateViewport: PropTypes.func.isRequired,
|
||||
},
|
||||
|
||||
|
@ -25,20 +25,19 @@ module.exports = createClass({
|
|||
let {
|
||||
location,
|
||||
viewport,
|
||||
onResizeViewport,
|
||||
onRotateViewport,
|
||||
} = this.props;
|
||||
|
||||
return dom.div(
|
||||
{
|
||||
className: "viewport"
|
||||
className: "viewport",
|
||||
},
|
||||
ViewportToolbar({
|
||||
onRotateViewport,
|
||||
}),
|
||||
Browser({
|
||||
ResizableViewport({
|
||||
location,
|
||||
width: viewport.width,
|
||||
height: viewport.height,
|
||||
viewport,
|
||||
onResizeViewport,
|
||||
onRotateViewport,
|
||||
})
|
||||
);
|
||||
},
|
||||
|
|
|
@ -17,6 +17,7 @@ module.exports = createClass({
|
|||
propTypes: {
|
||||
location: Types.location.isRequired,
|
||||
viewports: PropTypes.arrayOf(PropTypes.shape(Types.viewport)).isRequired,
|
||||
onResizeViewport: PropTypes.func.isRequired,
|
||||
onRotateViewport: PropTypes.func.isRequired,
|
||||
},
|
||||
|
||||
|
@ -24,6 +25,7 @@ module.exports = createClass({
|
|||
let {
|
||||
location,
|
||||
viewports,
|
||||
onResizeViewport,
|
||||
onRotateViewport,
|
||||
} = this.props;
|
||||
|
||||
|
@ -36,6 +38,8 @@ module.exports = createClass({
|
|||
key: viewport.id,
|
||||
location,
|
||||
viewport,
|
||||
onResizeViewport: (width, height) =>
|
||||
onResizeViewport(viewport.id, width, height),
|
||||
onRotateViewport: () => onRotateViewport(viewport.id),
|
||||
});
|
||||
})
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
<!-- 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/. -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="#A5A5A5">
|
||||
<path d="M16 3.2L3.1 16h1.7L16 4.9zM16 7.2L7.1 16h1.8L16 8.9zM16 11.1L11.1 16h1.8l3.1-3.1z" />
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 392 B |
|
@ -5,5 +5,6 @@
|
|||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DevToolsModules(
|
||||
'grippers.svg',
|
||||
'rotate-viewport.svg',
|
||||
)
|
||||
|
|
|
@ -13,6 +13,10 @@
|
|||
--viewport-box-shadow: 0 4px 4px 0 rgba(105, 105, 105, 0.26);
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
html, body {
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
|
@ -57,6 +61,10 @@ body {
|
|||
box-shadow: var(--viewport-box-shadow);
|
||||
}
|
||||
|
||||
.resizable-viewport {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/**
|
||||
* Viewport Toolbar
|
||||
*/
|
||||
|
@ -96,7 +104,51 @@ body {
|
|||
mask-image: url("./images/rotate-viewport.svg");
|
||||
}
|
||||
|
||||
/**
|
||||
* Viewport Browser
|
||||
*/
|
||||
|
||||
.browser {
|
||||
display: block;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.browser.resizing {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* Viewport Resize Handles
|
||||
*/
|
||||
|
||||
.viewport-resize-handle {
|
||||
position: absolute;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
background-image: url("./images/grippers.svg");
|
||||
background-position: bottom right;
|
||||
padding: 0 1px 1px 0;
|
||||
background-repeat: no-repeat;
|
||||
background-origin: content-box;
|
||||
cursor: se-resize;
|
||||
}
|
||||
|
||||
.viewport-horizontal-resize-handle {
|
||||
position: absolute;
|
||||
width: 5px;
|
||||
height: calc(100% - 16px);
|
||||
right: -4px;
|
||||
top: 0;
|
||||
cursor: e-resize;
|
||||
}
|
||||
|
||||
.viewport-vertical-resize-handle {
|
||||
position: absolute;
|
||||
width: calc(100% - 16px);
|
||||
height: 5px;
|
||||
left: 0;
|
||||
bottom: -4px;
|
||||
cursor: s-resize;
|
||||
}
|
||||
|
|
|
@ -4,7 +4,11 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const { ADD_VIEWPORT, ROTATE_VIEWPORT } = require("../actions/index");
|
||||
const {
|
||||
ADD_VIEWPORT,
|
||||
RESIZE_VIEWPORT,
|
||||
ROTATE_VIEWPORT,
|
||||
} = require("../actions/index");
|
||||
|
||||
let nextViewportId = 0;
|
||||
|
||||
|
@ -25,6 +29,19 @@ let reducers = {
|
|||
return [...viewports, Object.assign({}, INITIAL_VIEWPORT)];
|
||||
},
|
||||
|
||||
[RESIZE_VIEWPORT](viewports, { id, width, height }) {
|
||||
return viewports.map(viewport => {
|
||||
if (viewport.id !== id) {
|
||||
return viewport;
|
||||
}
|
||||
|
||||
return Object.assign({}, viewport, {
|
||||
width,
|
||||
height,
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
[ROTATE_VIEWPORT](viewports, { id }) {
|
||||
return viewports.map(viewport => {
|
||||
if (viewport.id !== id) {
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test resizing the viewport.
|
||||
|
||||
const { addViewport, resizeViewport } =
|
||||
require("devtools/client/responsive.html/actions/viewports");
|
||||
|
||||
add_task(function*() {
|
||||
let store = Store();
|
||||
const { getState, dispatch } = store;
|
||||
|
||||
dispatch(addViewport());
|
||||
dispatch(resizeViewport(0, 500, 500));
|
||||
|
||||
let viewport = getState().viewports[0];
|
||||
equal(viewport.width, 500, "Resized width of 500");
|
||||
equal(viewport.height, 500, "Resized height of 500");
|
||||
});
|
|
@ -6,4 +6,5 @@ firefox-appdir = browser
|
|||
|
||||
[test_add_viewport.js]
|
||||
[test_change_location.js]
|
||||
[test_resize_viewport.js]
|
||||
[test_rotate_viewport.js]
|
||||
|
|
Загрузка…
Ссылка в новой задаче