TeaWeb/shared/js/ui/tree/RendererMove.tsx
2020-09-27 16:49:04 +02:00

116 lines
No EOL
3.5 KiB
TypeScript

import {ReactComponentBase} from "tc-shared/ui/react-elements/ReactComponentBase";
import * as React from "react";
import * as ReactDOM from "react-dom";
import {LogCategory, logWarn} from "tc-shared/log";
const moveStyle = require("./TreeEntryMove.scss");
export interface TreeEntryMoveProps {
onMoveEnd: (point: { x: number, y: number }) => void;
onMoveCancel: () => void;
}
export interface TreeEntryMoveState {
active: boolean;
begin: { x: number, y: number };
description: string;
}
export class RendererMove extends ReactComponentBase<TreeEntryMoveProps, TreeEntryMoveState> {
private readonly domContainer;
private readonly documentMouseOutListener;
private readonly documentMouseListener;
private readonly refContainer: React.RefObject<HTMLDivElement>;
private current: { x: number, y: number };
constructor(props) {
super(props);
this.refContainer = React.createRef();
this.domContainer = document.createElement("div");
this.documentMouseOutListener = (e: MouseEvent) => {
if (e.type === "mouseup") {
if (e.button !== 0) return;
this.props.onMoveEnd({x: e.pageX, y: e.pageY});
} else {
this.props.onMoveCancel();
}
this.disableEntryMove();
};
this.documentMouseListener = (e: MouseEvent) => {
this.current = {x: e.pageX, y: e.pageY};
const container = this.refContainer.current;
if (!container) return;
container.style.top = e.pageY + "px";
container.style.left = e.pageX + "px";
};
}
componentDidMount() {
document.body.append(this.domContainer);
}
componentWillUnmount() {
this.domContainer.remove();
}
enableEntryMove(description: string, begin: { x: number, y: number }, current: { x: number, y: number }, callback_enabled?: () => void) {
this.current = current;
this.setState({
active: true,
begin: begin,
description: description
}, callback_enabled);
document.addEventListener("mousemove", this.documentMouseListener);
document.addEventListener("mouseleave", this.documentMouseOutListener);
document.addEventListener("mouseup", this.documentMouseOutListener);
}
private disableEntryMove() {
this.setState({
active: false
});
document.removeEventListener("mousemove", this.documentMouseListener);
document.removeEventListener("mouseleave", this.documentMouseOutListener);
document.removeEventListener("mouseup", this.documentMouseOutListener);
}
protected defaultState(): TreeEntryMoveState {
return {
active: false,
begin: { x: 0, y: 0 },
description: ""
}
}
isActive() {
return this.state.active;
}
render() {
if (!this.state.active)
return null;
return ReactDOM.createPortal(this.renderPortal(), this.domContainer);
}
private renderPortal() {
if(!this.current) {
logWarn(LogCategory.CHANNEL, tr("Tried to render the move container without a current position"));
return null;
}
return (
<div style={{ top: this.current.y, left: this.current.x }} className={moveStyle.moveContainer}
ref={this.refContainer}>
{this.state.description}
</div>
);
}
}