forked from mirrors/gecko-dev
154 lines
4.4 KiB
JavaScript
154 lines
4.4 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/. */
|
|
|
|
/* eslint-env browser */
|
|
"use strict";
|
|
|
|
// A box with a start and a end pane, separated by a dragable splitter that
|
|
// allows the user to resize the relative widths of the panes.
|
|
//
|
|
// +-----------------------+---------------------+
|
|
// | | |
|
|
// | | |
|
|
// | S |
|
|
// | Start Pane p End Pane |
|
|
// | l |
|
|
// | i |
|
|
// | t |
|
|
// | t |
|
|
// | e |
|
|
// | r |
|
|
// | | |
|
|
// | | |
|
|
// +-----------------------+---------------------+
|
|
|
|
const {
|
|
DOM: dom,
|
|
createClass,
|
|
PropTypes,
|
|
} = require("devtools/client/shared/vendor/react");
|
|
const { assert } = require("devtools/shared/DevToolsUtils");
|
|
|
|
module.exports = createClass({
|
|
displayName: "HSplitBox",
|
|
|
|
propTypes: {
|
|
// The contents of the start pane.
|
|
start: PropTypes.any.isRequired,
|
|
|
|
// The contents of the end pane.
|
|
end: PropTypes.any.isRequired,
|
|
|
|
// The relative width of the start pane, expressed as a number between 0 and
|
|
// 1. The relative width of the end pane is 1 - startWidth. For example,
|
|
// with startWidth = .5, both panes are of equal width; with startWidth =
|
|
// .25, the start panel will take up 1/4 width and the end panel will take
|
|
// up 3/4 width.
|
|
startWidth: PropTypes.number,
|
|
|
|
// A minimum css width value for the start and end panes.
|
|
minStartWidth: PropTypes.any,
|
|
minEndWidth: PropTypes.any,
|
|
|
|
// A callback fired when the user drags the splitter to resize the relative
|
|
// pane widths. The function is passed the startWidth value that would put
|
|
// the splitter underneath the users mouse.
|
|
onResize: PropTypes.func.isRequired,
|
|
},
|
|
|
|
getDefaultProps() {
|
|
return {
|
|
startWidth: 0.5,
|
|
minStartWidth: "20px",
|
|
minEndWidth: "20px",
|
|
};
|
|
},
|
|
|
|
getInitialState() {
|
|
return {
|
|
mouseDown: false
|
|
};
|
|
},
|
|
|
|
componentDidMount() {
|
|
document.defaultView.top.addEventListener("mouseup", this._onMouseUp,
|
|
false);
|
|
document.defaultView.top.addEventListener("mousemove", this._onMouseMove,
|
|
false);
|
|
},
|
|
|
|
componentWillUnmount() {
|
|
document.defaultView.top.removeEventListener("mouseup", this._onMouseUp,
|
|
false);
|
|
document.defaultView.top.removeEventListener("mousemove", this._onMouseMove,
|
|
false);
|
|
},
|
|
|
|
_onMouseDown(event) {
|
|
if (event.button !== 0) {
|
|
return;
|
|
}
|
|
|
|
this.setState({ mouseDown: true });
|
|
event.preventDefault();
|
|
},
|
|
|
|
_onMouseUp(event) {
|
|
if (event.button !== 0 || !this.state.mouseDown) {
|
|
return;
|
|
}
|
|
|
|
this.setState({ mouseDown: false });
|
|
event.preventDefault();
|
|
},
|
|
|
|
_onMouseMove(event) {
|
|
if (!this.state.mouseDown) {
|
|
return;
|
|
}
|
|
|
|
const rect = this.refs.box.getBoundingClientRect();
|
|
const { left, right } = rect;
|
|
const width = right - left;
|
|
const relative = event.clientX - left;
|
|
this.props.onResize(relative / width);
|
|
|
|
event.preventDefault();
|
|
},
|
|
|
|
render() {
|
|
/* eslint-disable no-shadow */
|
|
const { start, end, startWidth, minStartWidth, minEndWidth } = this.props;
|
|
assert(startWidth => 0 && startWidth <= 1,
|
|
"0 <= this.props.startWidth <= 1");
|
|
/* eslint-enable */
|
|
return dom.div(
|
|
{
|
|
className: "h-split-box",
|
|
ref: "box",
|
|
},
|
|
|
|
dom.div(
|
|
{
|
|
className: "h-split-box-pane",
|
|
style: { flex: startWidth, minWidth: minStartWidth },
|
|
},
|
|
start
|
|
),
|
|
|
|
dom.div({
|
|
className: "devtools-side-splitter",
|
|
onMouseDown: this._onMouseDown,
|
|
}),
|
|
|
|
dom.div(
|
|
{
|
|
className: "h-split-box-pane",
|
|
style: { flex: 1 - startWidth, minWidth: minEndWidth },
|
|
},
|
|
end
|
|
)
|
|
);
|
|
}
|
|
});
|