You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
100 lines
2.5 KiB
JavaScript
100 lines
2.5 KiB
JavaScript
'use strict';
|
|
|
|
const React = require("react");
|
|
const createReactClass = require("create-react-class");
|
|
const classnames = require("classnames");
|
|
|
|
const renderIf = require("../../util/render-if");
|
|
const windowTitleContext = require("./window-title-context");
|
|
|
|
function cancelEvent(event) {
|
|
/* NOTE: This is used on mousedown events for controls like the CloseButton, to ensure that a click-and-drag on a titlebar control cannot start a window drag operation. */
|
|
event.stopPropagation();
|
|
}
|
|
|
|
function relativePosition(event, bounds) {
|
|
let relativeX = event.clientX - bounds.x;
|
|
let relativeY = event.clientY - bounds.y;
|
|
|
|
return {
|
|
x: relativeX,
|
|
y: relativeY
|
|
};
|
|
}
|
|
|
|
function CloseButton({onClick}) {
|
|
return (
|
|
<div className="button close" onClick={onClick} onMouseDown={cancelEvent}>
|
|
✖
|
|
</div>
|
|
);
|
|
}
|
|
|
|
let TitleBar = createReactClass({
|
|
displayName: "TitleBar",
|
|
setRef: function (ref) {
|
|
this.setState({
|
|
ref: ref
|
|
});
|
|
},
|
|
handleMouseDown: function (event) {
|
|
let bounds = this.state.ref.getBoundingClientRect();
|
|
|
|
let relativeX = event.clientX - bounds.x;
|
|
let relativeY = event.clientY - bounds.y;
|
|
|
|
this.props.onMouseDown(event, relativeX, relativeY);
|
|
},
|
|
render: function () {
|
|
return (
|
|
<div ref={this.setRef} className="titleBar" onMouseDown={this.handleMouseDown}>
|
|
<div className="title">
|
|
{this.props.title}
|
|
</div>
|
|
|
|
<div className="buttons">
|
|
{this.props.extraButtons}
|
|
<CloseButton onClick={this.props.onClose} />
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
});
|
|
|
|
function Resizer({onMouseDown}) {
|
|
let [ref, setRef] = React.useState(null);
|
|
|
|
function onMouseDown_(event) {
|
|
let {x, y} = relativePosition(event, ref.getBoundingClientRect());
|
|
|
|
onMouseDown(event, x, y);
|
|
event.stopPropagation();
|
|
}
|
|
|
|
return (
|
|
<div className="resizer" ref={setRef} onMouseDown={onMouseDown_}>
|
|
<div className="arrow" />
|
|
</div>
|
|
);
|
|
}
|
|
|
|
module.exports = function Window({elementRef, style, window: window_, onMouseDown, onTitleMouseDown, onClose, onResizerMouseDown}) {
|
|
let [windowTitle, setWindowTitle] = React.useState("");
|
|
|
|
return (
|
|
<div ref={elementRef} className={classnames("window", {active: window_.isActive})} style={style} onMouseDown={onMouseDown}>
|
|
<TitleBar title={windowTitle} onMouseDown={onTitleMouseDown} onClose={onClose} />
|
|
|
|
<windowTitleContext.Provider value={setWindowTitle}>
|
|
<div className="body">
|
|
<div className="contents">
|
|
{window_.contents}
|
|
</div>
|
|
|
|
{renderIf(window_.resizable, <Resizer onMouseDown={onResizerMouseDown} />)}
|
|
</div>
|
|
</windowTitleContext.Provider>
|
|
</div>
|
|
);
|
|
};
|