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 { private readonly domContainer; private readonly documentMouseOutListener; private readonly documentMouseListener; private readonly refContainer: React.RefObject; 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 (
{this.state.description}
); } }