519 lines
10 KiB
JavaScript
519 lines
10 KiB
JavaScript
|
|
|
|||
|
|
var orderIndex = 1000;
|
|||
|
|
|
|||
|
|
export class WindowController {
|
|||
|
|
|
|||
|
|
win = null;
|
|||
|
|
titlebar = null;
|
|||
|
|
canvas = null;
|
|||
|
|
resizers = null;
|
|||
|
|
btnClose = null;
|
|||
|
|
btnMaximize = null;
|
|||
|
|
|
|||
|
|
isSnapped = false;
|
|||
|
|
isMaximized = false;
|
|||
|
|
isDragging = false;
|
|||
|
|
dragType = null;
|
|||
|
|
currentResizer = null;
|
|||
|
|
|
|||
|
|
savedPosition = null;
|
|||
|
|
savedBeforeMaximize = null;
|
|||
|
|
|
|||
|
|
order = orderIndex++;
|
|||
|
|
|
|||
|
|
startX = 0;
|
|||
|
|
startY = 0;
|
|||
|
|
startLeft = 100;
|
|||
|
|
startTop = 100;
|
|||
|
|
startWidth = 500;
|
|||
|
|
startHeight = 500;
|
|||
|
|
|
|||
|
|
width = this.startWidth;
|
|||
|
|
|
|||
|
|
height = this.startHeight;
|
|||
|
|
|
|||
|
|
constructor() {
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
setElement( element ) {
|
|||
|
|
|
|||
|
|
this.canvas = element;
|
|||
|
|
|
|||
|
|
console.log("set element",element);
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
create( element ) {
|
|||
|
|
|
|||
|
|
var windowFrame = document.createElement( "div" );
|
|||
|
|
|
|||
|
|
windowFrame.id = "win"
|
|||
|
|
|
|||
|
|
windowFrame.style.width = this.startWidth + "px";
|
|||
|
|
|
|||
|
|
windowFrame.style.height = this.startHeight + "px";
|
|||
|
|
|
|||
|
|
|
|||
|
|
windowFrame.style.left = this.startLeft + "px";
|
|||
|
|
|
|||
|
|
windowFrame.style.top = this.startTop + "px";
|
|||
|
|
|
|||
|
|
|
|||
|
|
// Title bar
|
|||
|
|
var titleBar = document.createElement( "div" );
|
|||
|
|
titleBar.className = "titlebar";
|
|||
|
|
titleBar.textContent = "Source Code Graph";
|
|||
|
|
|
|||
|
|
var buttons = document.createElement( "div" );
|
|||
|
|
buttons.className = "buttons";
|
|||
|
|
|
|||
|
|
var btnMaximize = document.createElement( "button" );
|
|||
|
|
btnMaximize.id = "btnMaximize";
|
|||
|
|
btnMaximize.title = "Maximize";
|
|||
|
|
btnMaximize.textContent = "m";
|
|||
|
|
|
|||
|
|
var btnClose = document.createElement( "button" );
|
|||
|
|
btnClose.id = "btnClose";
|
|||
|
|
btnClose.title = "Close";
|
|||
|
|
btnClose.textContent = "×";
|
|||
|
|
|
|||
|
|
buttons.appendChild( btnMaximize );
|
|||
|
|
buttons.appendChild( btnClose );
|
|||
|
|
titleBar.appendChild( buttons );
|
|||
|
|
windowFrame.appendChild( titleBar );
|
|||
|
|
|
|||
|
|
// Content
|
|||
|
|
var content = document.createElement( "div" );
|
|||
|
|
content.className = "content";
|
|||
|
|
|
|||
|
|
|
|||
|
|
console.log(this.canvas);
|
|||
|
|
|
|||
|
|
content.appendChild( this.canvas );
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
windowFrame.appendChild( content );
|
|||
|
|
|
|||
|
|
// Resizers
|
|||
|
|
var resizerClasses = [
|
|||
|
|
"top-left", "top", "top-right", "right",
|
|||
|
|
"bottom-right", "bottom", "bottom-left", "left"
|
|||
|
|
];
|
|||
|
|
|
|||
|
|
this.resizers = new Array();
|
|||
|
|
|
|||
|
|
for (var i = 0; i < resizerClasses.length; i++) {
|
|||
|
|
|
|||
|
|
var resizer = document.createElement( "div" );
|
|||
|
|
|
|||
|
|
resizer.className = "resizer " + resizerClasses[i];
|
|||
|
|
|
|||
|
|
windowFrame.appendChild( resizer );
|
|||
|
|
|
|||
|
|
this.resizers.push(resizer)
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
this.win = windowFrame;
|
|||
|
|
this.titlebar = titleBar;
|
|||
|
|
|
|||
|
|
this.btnClose = btnClose;
|
|||
|
|
this.btnMaximize = btnMaximize;
|
|||
|
|
|
|||
|
|
this.titlebar.addEventListener("mousedown", this.onTitlebarMouseDown.bind(this));
|
|||
|
|
|
|||
|
|
this.resizers.forEach(this.bindResizer.bind(this));
|
|||
|
|
|
|||
|
|
this.btnClose.addEventListener("click", this.onCloseClick.bind(this));
|
|||
|
|
this.btnMaximize.addEventListener("click", this.onMaximizeClick.bind(this));
|
|||
|
|
|
|||
|
|
document.body.appendChild( windowFrame );
|
|||
|
|
|
|||
|
|
this.win.addEventListener("mousedown", this.reOrder.bind( this ) );
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
setup() {
|
|||
|
|
|
|||
|
|
this.create();
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
setGraphExplorer( graphExplorer ) {
|
|||
|
|
|
|||
|
|
this.graphExplorer = graphExplorer;
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
saveWindowState() {
|
|||
|
|
|
|||
|
|
this.savedPosition = {
|
|||
|
|
left: this.win.offsetLeft,
|
|||
|
|
top: this.win.offsetTop,
|
|||
|
|
width: this.win.offsetWidth,
|
|||
|
|
height: this.win.offsetHeight
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
hide() {
|
|||
|
|
|
|||
|
|
this.win.style.display = "none"
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
show() {
|
|||
|
|
|
|||
|
|
this.win.style.display = "flex"
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
restoreWindowState() {
|
|||
|
|
|
|||
|
|
if (!this.savedPosition) return;
|
|||
|
|
|
|||
|
|
this.win.style.left = this.savedPosition.left + "px";
|
|||
|
|
this.win.style.top = this.savedPosition.top + "px";
|
|||
|
|
this.win.style.width = this.savedPosition.width + "px";
|
|||
|
|
this.win.style.height = this.savedPosition.height + "px";
|
|||
|
|
|
|||
|
|
this.savedPosition = null;
|
|||
|
|
this.isSnapped = false;
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
resizeCanvas() {
|
|||
|
|
|
|||
|
|
const style = getComputedStyle(this.win);
|
|||
|
|
const width = parseInt(style.width);
|
|||
|
|
const height = parseInt(style.height);
|
|||
|
|
|
|||
|
|
//this.canvas.width = width;
|
|||
|
|
//this.canvas.height = height;
|
|||
|
|
//this.canvas.style.width = width + "px";
|
|||
|
|
//this.canvas.style.height = height + "px";
|
|||
|
|
|
|||
|
|
//console.log(this.graphExplorer);
|
|||
|
|
|
|||
|
|
if(this.graphExplorer)
|
|||
|
|
this.graphExplorer.onResize( width, height );
|
|||
|
|
//this.draw();
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
snapWindow(mouseX, mouseY) {
|
|||
|
|
|
|||
|
|
if (this.isMaximized) return;
|
|||
|
|
|
|||
|
|
const snapMargin = 30;
|
|||
|
|
const vw = window.innerWidth;
|
|||
|
|
const vh = window.innerHeight;
|
|||
|
|
|
|||
|
|
const nearLeft = mouseX <= snapMargin;
|
|||
|
|
const nearRight = mouseX >= vw - snapMargin;
|
|||
|
|
const nearTop = mouseY <= snapMargin;
|
|||
|
|
const nearBottom = mouseY >= vh - snapMargin;
|
|||
|
|
|
|||
|
|
if (!this.isSnapped && (nearLeft || nearRight || nearTop || nearBottom)) {
|
|||
|
|
|
|||
|
|
this.saveWindowState();
|
|||
|
|
this.isSnapped = true;
|
|||
|
|
|
|||
|
|
} else if (!nearLeft && !nearRight && !nearTop && !nearBottom && this.isSnapped) {
|
|||
|
|
|
|||
|
|
this.restoreWindowState();
|
|||
|
|
return;
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (!this.isSnapped) return;
|
|||
|
|
|
|||
|
|
if (nearTop && nearLeft) {
|
|||
|
|
|
|||
|
|
this.setWindowRect(0, 0, vw / 2, vh / 2);
|
|||
|
|
|
|||
|
|
} else if (nearTop && nearRight) {
|
|||
|
|
|
|||
|
|
this.setWindowRect(vw / 2, 0, vw / 2, vh / 2);
|
|||
|
|
|
|||
|
|
} else if (nearBottom && nearLeft) {
|
|||
|
|
|
|||
|
|
this.setWindowRect(0, vh / 2, vw / 2, vh / 2);
|
|||
|
|
|
|||
|
|
} else if (nearBottom && nearRight) {
|
|||
|
|
|
|||
|
|
this.setWindowRect(vw / 2, vh / 2, vw / 2, vh / 2);
|
|||
|
|
|
|||
|
|
} else if (nearTop) {
|
|||
|
|
|
|||
|
|
this.setWindowRect(0, 0, vw, vh / 2);
|
|||
|
|
|
|||
|
|
} else if (nearBottom) {
|
|||
|
|
|
|||
|
|
this.setWindowRect(0, vh / 2, vw, vh / 2);
|
|||
|
|
|
|||
|
|
} else if (nearLeft) {
|
|||
|
|
|
|||
|
|
this.setWindowRect(0, 0, vw / 2, vh);
|
|||
|
|
|
|||
|
|
} else if (nearRight) {
|
|||
|
|
|
|||
|
|
this.setWindowRect(vw / 2, 0, vw / 2, vh);
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
this.resizeCanvas();
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
setWindowRect(left, top, width, height) {
|
|||
|
|
|
|||
|
|
this.win.style.left = Math.floor(left) + "px";
|
|||
|
|
this.win.style.top = Math.floor(top) + "px";
|
|||
|
|
this.win.style.width = Math.floor(width) + "px";
|
|||
|
|
this.win.style.height = Math.floor(height) + "px";
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
onTitlebarMouseDown(event) {
|
|||
|
|
|
|||
|
|
event.preventDefault();
|
|||
|
|
|
|||
|
|
this.dragType = "move";
|
|||
|
|
|
|||
|
|
const offsetX = event.clientX - this.win.offsetLeft;
|
|||
|
|
const offsetY = event.clientY - this.win.offsetTop;
|
|||
|
|
|
|||
|
|
if (this.isSnapped) {
|
|||
|
|
|
|||
|
|
this.restoreWindowState();
|
|||
|
|
|
|||
|
|
this.startX = event.clientX;
|
|||
|
|
this.startY = event.clientY;
|
|||
|
|
this.startLeft = event.clientX - 100;
|
|||
|
|
this.startTop = event.clientY - offsetY;
|
|||
|
|
|
|||
|
|
this.win.style.left = this.startLeft + "px";
|
|||
|
|
this.win.style.top = this.startTop + "px";
|
|||
|
|
|
|||
|
|
} else {
|
|||
|
|
|
|||
|
|
this.startX = event.clientX;
|
|||
|
|
this.startY = event.clientY;
|
|||
|
|
this.startLeft = this.win.offsetLeft;
|
|||
|
|
this.startTop = this.win.offsetTop;
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
this.isDragging = true;
|
|||
|
|
|
|||
|
|
document.addEventListener("mousemove", this.onDragMove);
|
|||
|
|
document.addEventListener("mouseup", this.onDragEnd);
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
onDragMove = (event) => {
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
event.preventDefault();
|
|||
|
|
|
|||
|
|
if (!this.isDragging) return;
|
|||
|
|
|
|||
|
|
const dx = event.clientX - this.startX;
|
|||
|
|
const dy = event.clientY - this.startY;
|
|||
|
|
|
|||
|
|
if (this.dragType === "move") {
|
|||
|
|
|
|||
|
|
let newLeft = this.startLeft + dx;
|
|||
|
|
let newTop = this.startTop + dy;
|
|||
|
|
|
|||
|
|
newLeft = Math.max(0, Math.min(window.innerWidth - this.win.offsetWidth, newLeft));
|
|||
|
|
newTop = Math.max(0, Math.min(window.innerHeight - this.win.offsetHeight, newTop));
|
|||
|
|
|
|||
|
|
this.win.style.left = newLeft + "px";
|
|||
|
|
this.win.style.top = newTop + "px";
|
|||
|
|
|
|||
|
|
this.snapWindow(event.clientX, event.clientY);
|
|||
|
|
|
|||
|
|
} else if (this.dragType === "resize") {
|
|||
|
|
|
|||
|
|
let newWidth = this.startWidth;
|
|||
|
|
let newHeight = this.startHeight;
|
|||
|
|
let newLeft = this.startLeft;
|
|||
|
|
let newTop = this.startTop;
|
|||
|
|
|
|||
|
|
switch (this.currentResizer) {
|
|||
|
|
case "top":
|
|||
|
|
newHeight = this.startHeight - dy;
|
|||
|
|
newTop = this.startTop + dy;
|
|||
|
|
break;
|
|||
|
|
case "bottom":
|
|||
|
|
newHeight = this.startHeight + dy;
|
|||
|
|
break;
|
|||
|
|
case "left":
|
|||
|
|
newWidth = this.startWidth - dx;
|
|||
|
|
newLeft = this.startLeft + dx;
|
|||
|
|
break;
|
|||
|
|
case "right":
|
|||
|
|
newWidth = this.startWidth + dx;
|
|||
|
|
break;
|
|||
|
|
case "top-left":
|
|||
|
|
newWidth = this.startWidth - dx;
|
|||
|
|
newLeft = this.startLeft + dx;
|
|||
|
|
newHeight = this.startHeight - dy;
|
|||
|
|
newTop = this.startTop + dy;
|
|||
|
|
break;
|
|||
|
|
case "top-right":
|
|||
|
|
newWidth = this.startWidth + dx;
|
|||
|
|
newHeight = this.startHeight - dy;
|
|||
|
|
newTop = this.startTop + dy;
|
|||
|
|
break;
|
|||
|
|
case "bottom-left":
|
|||
|
|
newWidth = this.startWidth - dx;
|
|||
|
|
newLeft = this.startLeft + dx;
|
|||
|
|
newHeight = this.startHeight + dy;
|
|||
|
|
break;
|
|||
|
|
case "bottom-right":
|
|||
|
|
newWidth = this.startWidth + dx;
|
|||
|
|
newHeight = this.startHeight + dy;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (newWidth > 100) {
|
|||
|
|
this.win.style.width = newWidth + "px";
|
|||
|
|
this.win.style.left = newLeft + "px";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (newHeight > 100) {
|
|||
|
|
this.win.style.height = newHeight + "px";
|
|||
|
|
this.win.style.top = newTop + "px";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
this.resizeCanvas();
|
|||
|
|
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
onDragEnd = () => {
|
|||
|
|
|
|||
|
|
this.isDragging = false;
|
|||
|
|
this.dragType = null;
|
|||
|
|
this.currentResizer = null;
|
|||
|
|
|
|||
|
|
document.removeEventListener("mousemove", this.onDragMove);
|
|||
|
|
document.removeEventListener("mouseup", this.onDragEnd);
|
|||
|
|
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
reOrder() {
|
|||
|
|
|
|||
|
|
orderIndex++;
|
|||
|
|
|
|||
|
|
this.win.style['z-index'] = orderIndex;
|
|||
|
|
|
|||
|
|
|
|||
|
|
console.log("this.win.style['z-index']", this.win.style['z-index']);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
onResizerMouseDown(event) {
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
event.preventDefault();
|
|||
|
|
|
|||
|
|
this.startX = event.clientX;
|
|||
|
|
this.startY = event.clientY;
|
|||
|
|
this.startLeft = this.win.offsetLeft;
|
|||
|
|
this.startTop = this.win.offsetTop;
|
|||
|
|
this.startWidth = this.win.offsetWidth;
|
|||
|
|
this.startHeight = this.win.offsetHeight;
|
|||
|
|
|
|||
|
|
this.isDragging = true;
|
|||
|
|
this.dragType = "resize";
|
|||
|
|
this.currentResizer = event.target.classList[1];
|
|||
|
|
|
|||
|
|
document.addEventListener("mousemove", this.onDragMove);
|
|||
|
|
document.addEventListener("mouseup", this.onDragEnd);
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
bindResizer(resizerElement) {
|
|||
|
|
|
|||
|
|
resizerElement.addEventListener("mousedown", this.onResizerMouseDown.bind(this));
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
maximizeWindow() {
|
|||
|
|
|
|||
|
|
if (this.isMaximized) return;
|
|||
|
|
|
|||
|
|
this.savedBeforeMaximize = {
|
|||
|
|
left: this.win.offsetLeft,
|
|||
|
|
top: this.win.offsetTop,
|
|||
|
|
width: this.win.offsetWidth,
|
|||
|
|
height: this.win.offsetHeight
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
this.setWindowRect(0, 0, window.innerWidth, window.innerHeight);
|
|||
|
|
|
|||
|
|
this.resizeCanvas();
|
|||
|
|
|
|||
|
|
this.isMaximized = true;
|
|||
|
|
this.isSnapped = false;
|
|||
|
|
this.savedPosition = null;
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
restoreFromMaximize() {
|
|||
|
|
|
|||
|
|
if (!this.isMaximized || !this.savedBeforeMaximize) return;
|
|||
|
|
|
|||
|
|
this.setWindowRect(
|
|||
|
|
this.savedBeforeMaximize.left,
|
|||
|
|
this.savedBeforeMaximize.top,
|
|||
|
|
this.savedBeforeMaximize.width,
|
|||
|
|
this.savedBeforeMaximize.height
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
this.resizeCanvas();
|
|||
|
|
|
|||
|
|
this.isMaximized = false;
|
|||
|
|
this.savedBeforeMaximize = null;
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
onMaximizeClick() {
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
if (this.isMaximized) {
|
|||
|
|
|
|||
|
|
this.restoreFromMaximize();
|
|||
|
|
|
|||
|
|
} else {
|
|||
|
|
|
|||
|
|
this.maximizeWindow();
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
onCloseClick() {
|
|||
|
|
|
|||
|
|
this.win.style.display = "none";
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}
|