MWSE/public/studio/window.js

293 lines
9.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

export default class DWindow extends EventTarget {
static allWindows = []; // açık pencereler
static zCounter = 1; // global sayaç
static normalizeThreshold = 9999; // yeniden sıfırlama eşiği
/** @type {JQuery<HTMLElement>} */ panel = null;
/** @type {JQuery<HTMLElement>} */ title = null;
/** @type {JQuery<HTMLElement>} */ content = null;
/** @type {JQuery<HTMLElement>} */ headtext = null;
constructor() {
super();
this.initpanel();
this.enableFocus();
DWindow.allWindows.push(this);
this.bringToFront();
requestAnimationFrame(()=>{
this.enableDragging();
this.enableResize();
})
}
activeDragging = true;
activeResizing = true;
initpanel() {
this.panel = $(`<div></div>`).css({
width: 450,
//height: 500,
position: "fixed",
left: (Math.random() * 300 | 0) + 100,
top: (Math.random() * 100 | 0) + 100,
boxShadow: "black 0px 0px 20px -10px",
borderRadius: "10px",
backgroundColor: "#3333335b",
backdropFilter: "blur(3px)",
border: "solid 1px #a2a2a2",
display: "flex",
flexDirection: "column",
outlineOffset: "-5px",
//overflow: "hidden",
userSelect: "none",
minWidth: "max-content",
minHeight: "max-content"
});
$("body").append(this.panel);
this.title = $(`<div></div>`).css({
display: "flex",
flex: "0 0 auto",
flexDirection: "row",
lineHeight: "2em",
backgroundColor: "#333333",
color: "white",
paddingLeft: "10px",
cursor: "move",
borderTopLeftRadius: "10px",
borderTopRightRadius: "10px",
});
this.content = $(`<div></div>`).css({
flex: "1 1 auto",
overflow: "auto",
borderBottomRightRadius: "10px",
borderBottomLeftRadius: "10px",
padding: "20px"
});
this.panel.append(this.title, this.content);
this.initTitle();
}
initTitle() {
this.headtext = $("<div>Başlıksız pencere</div>");
const divider = $("<div style='flex:1 1 auto'></div>");
this.exitbtn = $("<div><span class='btn btn-sm material-symbols-outlined text-white'>close</span></div>");
this.exitbtn.on('click',()=>{
this.dispatchEvent(new Event("close"));
})
this.title.append(
this.headtext,
divider,
this.exitbtn
);
}
enableDragging() {
let isDragging = false;
let startX, startY, startLeft, startTop;
this.title.on("mousedown", (e) => {
if(this.activeDragging == false){
return;
}
let isInput = $(e.target).closest("button, input, select, textarea,.btn");
if (isInput.length) return;
e.preventDefault();
isDragging = true;
startX = e.pageX;
startY = e.pageY;
startLeft = parseFloat(this.panel.css("left"));
startTop = parseFloat(this.panel.css("top"));
$("body").css("user-select", "none");
this.dispatchEvent(new Event("dragging"));
this.panel.css("box-shadow","black 0px 0px 40px -20px");
this.panel.css("backdrop-filter","blur(10px)");
});
$(document).on("mousemove", (e) => {
if (!isDragging) return;
const dx = e.pageX - startX;
const dy = e.pageY - startY;
this.panel.css({
left: startLeft + dx,
top: startTop + dy,
});
});
$(document).on("mouseup", () => {
if (isDragging) {
isDragging = false;
this.panel.css("box-shadow","black 0px 0px 20px -10px");
this.panel.css("backdrop-filter","blur(3px)");
$("body").css("user-select", "auto");
this.dispatchEvent(new Event("draggingend"));
}
});
}
enableResize() {
const offset = 5; // panelin dışından 5px alan
let resizing = false;
let resizeDir = "";
let startX, startY, startW, startH, startL, startT;
const minW = 200, minH = 150;
// overlay divleri oluştur
const handles = {};
const names = ["n","s","e","w","ne","nw","se","sw"];
names.forEach(n => {
handles[n] = $('<div></div>').css({
position: "absolute",
zIndex: 1000,
background: "transparent",
cursor: n + "-resize",
transition: "all 0.5s all",
outlineOffset: "3px"
}).appendTo(this.panel);
});
// boyut ve pozisyonlarını ayarla
const updateHandles = () => {
const w = this.panel.outerWidth();
const h = this.panel.outerHeight();
// kenarlar
handles.n.css({ top: -offset, left: 0, width: w, height: offset*2 });
handles.s.css({ bottom: -offset, left: 0, width: w, height: offset*2 });
handles.w.css({ top: 0, left: -offset, width: offset*2, height: h });
handles.e.css({ top: 0, right: -offset, width: offset*2, height: h });
// köşeler
handles.nw.css({ top: -offset, left: -offset, width: offset*2, height: offset*2 });
handles.ne.css({ top: -offset, right: -offset, width: offset*2, height: offset*2 });
handles.sw.css({ bottom: -offset, left: -offset, width: offset*2, height: offset*2 });
handles.se.css({ bottom: -offset, right: -offset, width: offset*2, height: offset*2 });
};
updateHandles();
$(window).on("resize", updateHandles);
let activeDir = null;
// resize eventleri
names.forEach(dir => {
handles[dir].on("mousedown", (e) => {
if(this.activeResizing == false){
return;
}
activeDir = e.target;
e.preventDefault();
e.stopPropagation();
resizing = true;
resizeDir = dir;
startX = e.pageX;
startY = e.pageY;
startW = this.panel.outerWidth();
startH = this.panel.outerHeight();
startL = parseFloat(this.panel.css("left"));
startT = parseFloat(this.panel.css("top"));
this.dispatchEvent(new Event("resizing"));
$("body").css("user-select","none");
});
});
$(document).on("mousemove", (e) => {
if (!resizing) return;
const dx = e.pageX - startX;
const dy = e.pageY - startY;
let newW = startW;
let newH = startH;
let newL = startL;
let newT = startT;
if (resizeDir.includes("e")) newW = Math.max(minW, startW + dx);
if (resizeDir.includes("w")) { newW = Math.max(minW, startW - dx); newL = startL + (startW - newW); }
if (resizeDir.includes("s")) newH = Math.max(minH, startH + dy);
if (resizeDir.includes("n")) { newH = Math.max(minH, startH - dy); newT = startT + (startH - newH); }
this.panel.css({ width: newW, height: newH, left: newL, top: newT });
updateHandles();
$(activeDir).css("outline", "solid 2px #00ff00");
});
$(document).on("mouseup", () => {
if (resizing) {
resizing = false;
$("body").css("user-select","auto");
$(activeDir).css("outline", "solid 0px #00ff00");
this.dispatchEvent(new Event("resizingend"));
}
});
}
enableFocus() {
this.panel.on("mousedown", () => {
this.bringToFront();
});
}
bringToFront() {
if (DWindow.zCounter > DWindow.normalizeThreshold) {
DWindow.normalizeZ();
}
DWindow.zCounter++;
this.panel.css("z-index", DWindow.zCounter);
}
showing = true;
show(){
this.dispatchEvent(new Event("show"));
this.panel.show();
this.showing = true;
}
hide(){
this.dispatchEvent(new Event("hide"));
this.panel.hide();
this.showing = false;
}
toggle(){
this.showing ? this.hide() : this.show();
}
exit(){
this.dispatchEvent(new Event("exit"));
this.panel.remove();
}
/** @type {DWindow} */
parent = null;
/** @param {DWindow} parent */
enableDialog(parent){
this.parent = parent;
this.parent.activeDragging = false;
this.parent.activeResizing = false;
this.parent.panel.css('pointer-events',"none");
this.parent.panel.css('filter',"grayscale(1)");
let [{
left: parentL,
top: parentT,
width: parentW,
height: parentH
}] = this.parent.panel[0].getClientRects();
let [{
width: childW,
height: childH
}] = this.panel[0].getClientRects();
let newLeft = parentL + (parentW - childW) / 2;
let newTop = parentT + (parentH - childH) / 2;
debugger;
newLeft = Math.max(newLeft, 20);
newTop = Math.max(newTop, 20);
newLeft = Math.min(newLeft, screen.availWidth - 100);
newTop = Math.min(newTop, screen.availHeight - 100);
Object.assign(this.panel[0].style, {
left: `${Math.round(newLeft)}px`,
top: `${Math.round(newTop)}px`
});
}
/** @param {DWindow} parent */
disableDialog(){
this.parent.activeDragging = true;
this.parent.activeResizing = true;
this.parent.panel.css('pointer-events',"all");
this.parent.panel.css('filter',"initial");
}
}