116 lines
No EOL
3.5 KiB
TypeScript
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>
|
|
);
|
|
}
|
|
} |