diff --git a/src/core/utils/DraggableResizableWindow.ts b/src/core/utils/DraggableResizableWindow.ts index 9f0436c..3993ebf 100644 --- a/src/core/utils/DraggableResizableWindow.ts +++ b/src/core/utils/DraggableResizableWindow.ts @@ -1,3 +1,5 @@ +import type { TWindowFormState } from '@/core/window/types/WindowFormTypes.ts' + /** 拖拽移动开始的回调 */ type TDragStartCallback = (x: number, y: number) => void; /** 拖拽移动中的回调 */ @@ -16,9 +18,6 @@ type TResizeDirection = | 'bottom-left' | 'bottom-right'; -/** 窗口状态 */ -type TWindowState = 'default' | 'minimized' | 'maximized'; - /** 元素边界 */ interface IElementRect { /** 宽度 */ @@ -88,7 +87,7 @@ interface IDraggableResizableOptions { onResizeEnd?: (data: IResizeCallbackData) => void; /** 窗口状态改变回调 */ - onWindowStateChange?: (state: TWindowState) => void; + onWindowStateChange?: (state: TWindowFormState) => void; } /** 拖拽的范围边界 */ @@ -124,7 +123,7 @@ export class DraggableResizableWindow { private onResizeMove?: (data: IResizeCallbackData) => void; private onResizeEnd?: (data: IResizeCallbackData) => void; - private onWindowStateChange?: (state: TWindowState) => void; + private onWindowStateChange?: (state: TWindowFormState) => void; private isDragging = false; private currentDirection: TResizeDirection | null = null; @@ -158,7 +157,7 @@ export class DraggableResizableWindow { private mutationObserver: MutationObserver; private animationFrame?: number; - private state: TWindowState = 'default'; + private _windowFormState: TWindowFormState = 'default'; /** 元素信息 */ private targetBounds: IElementRect; /** 最小化前的元素信息 */ @@ -167,8 +166,8 @@ export class DraggableResizableWindow { private targetPreMaximizedBounds?: IElementRect; private taskbarElementId: string; - get windowState() { - return this.state; + get windowFormState() { + return this._windowFormState; } constructor(options: IDraggableResizableOptions) { @@ -261,7 +260,7 @@ export class DraggableResizableWindow { document.removeEventListener('mousemove', this.checkDragStart); document.removeEventListener('mouseup', this.cancelPendingDrag); - if (this.state === 'maximized') { + if (this._windowFormState === 'maximized') { const preRect = this.targetPreMaximizedBounds!; const rect = this.target.getBoundingClientRect(); const relX = e.clientX / rect.width; @@ -583,9 +582,9 @@ export class DraggableResizableWindow { // 最小化到任务栏 public minimize() { - if (this.state === 'minimized') return; + if (this._windowFormState === 'minimized') return; this.targetPreMinimizeBounds = { ...this.targetBounds } - this.state = 'minimized'; + this._windowFormState = 'minimized'; const taskbar = document.querySelector(this.taskbarElementId); if (!taskbar) throw new Error('任务栏元素未找到'); @@ -603,9 +602,9 @@ export class DraggableResizableWindow { /** 最大化 */ public maximize() { - if (this.state === 'maximized') return; + if (this._windowFormState === 'maximized') return; this.targetPreMaximizedBounds = { ...this.targetBounds } - this.state = 'maximized'; + this._windowFormState = 'maximized'; const rect = this.target.getBoundingClientRect(); @@ -624,19 +623,19 @@ export class DraggableResizableWindow { /** 恢复到默认窗体状态 */ public restore(onComplete?: () => void) { - if (this.state === 'default') return; + if (this._windowFormState === 'default') return; let b: IElementRect; - if ((this.state as TWindowState) === 'minimized' && this.targetPreMinimizeBounds) { + if ((this._windowFormState as TWindowFormState) === 'minimized' && this.targetPreMinimizeBounds) { // 最小化恢复,恢复到最小化前的状态 b = this.targetPreMinimizeBounds; - } else if ((this.state as TWindowState) === 'maximized' && this.targetPreMaximizedBounds) { + } else if ((this._windowFormState as TWindowFormState) === 'maximized' && this.targetPreMaximizedBounds) { // 最大化恢复,恢复到最大化前的默认状态 b = this.targetPreMaximizedBounds; } else { b = this.targetBounds; } - this.state = 'default'; + this._windowFormState = 'default'; this.target.style.display = 'block'; @@ -696,7 +695,7 @@ export class DraggableResizableWindow { this.target.style.height = `${targetH}px`; this.applyPosition(targetX, targetY, true); onComplete?.(); - this.onWindowStateChange?.(this.state); + this.onWindowStateChange?.(this._windowFormState); } }; requestAnimationFrame(step); diff --git a/src/core/window/IWindowForm.ts b/src/core/window/IWindowForm.ts index 9a85e2b..344f7b9 100644 --- a/src/core/window/IWindowForm.ts +++ b/src/core/window/IWindowForm.ts @@ -1,6 +1,15 @@ import type { IProcess } from '@/core/process/IProcess.ts' +import type { TWindowFormState } from '@/core/window/types/WindowFormTypes.ts' export interface IWindowForm { + /** 窗体id */ get id(): string; + /** 窗体所属的进程 */ get proc(): IProcess | undefined; + /** 窗体元素 */ + get windowFormEle(): HTMLElement; + /** 窗体状态 */ + get windowFormState(): TWindowFormState; + /** 关闭窗体 */ + closeWindowForm(): void; } \ No newline at end of file diff --git a/src/core/window/impl/WindowFormImpl.ts b/src/core/window/impl/WindowFormImpl.ts index 8925b15..21f5aa4 100644 --- a/src/core/window/impl/WindowFormImpl.ts +++ b/src/core/window/impl/WindowFormImpl.ts @@ -14,8 +14,8 @@ export default class WindowFormImpl implements IWindowForm { private dom: HTMLElement; private drw: DraggableResizableWindow; private pos: WindowFormPos = { x: 0, y: 0 }; - private width: number = 0; - private height: number = 0; + private width: number; + private height: number; public get id() { return this._id; @@ -26,6 +26,12 @@ export default class WindowFormImpl implements IWindowForm { private get desktopRootDom() { return XSystem.instance.desktopRootDom; } + public get windowFormEle() { + return this.dom; + } + public get windowFormState() { + return this.drw.windowFormState + } constructor(proc: IProcess, config: IWindowFormConfig) { this._procId = proc.id; @@ -34,20 +40,21 @@ export default class WindowFormImpl implements IWindowForm { x: config.left ?? 0, y: config.top ?? 0 } - this.width = config.width ?? 0; - this.height = config.height ?? 0; + this.width = config.width ?? 200; + this.height = config.height ?? 100; this.createWindowFrom(); } private createWindowFrom() { - this.dom = this.windowFormEle(); + this.dom = this.createWindowFormEle(); this.dom.style.position = 'absolute'; this.dom.style.width = `${this.width}px`; this.dom.style.height = `${this.height}px`; this.dom.style.zIndex = '10'; const header = this.dom.querySelector('.title-bar') as HTMLElement; + const content = this.dom.querySelector('.window-content') as HTMLElement; this.drw = new DraggableResizableWindow({ target: this.dom, handle: header, @@ -67,13 +74,13 @@ export default class WindowFormImpl implements IWindowForm { this.desktopRootDom.appendChild(this.dom); } - private closeWindowForm() { + public closeWindowForm() { this.drw.destroy(); this.desktopRootDom.removeChild(this.dom); this.proc?.event.notifyEvent('onProcessWindowFormExit', this.id) } - private windowFormEle() { + private createWindowFormEle() { const template = document.createElement('template'); template.innerHTML = `
@@ -85,10 +92,7 @@ export default class WindowFormImpl implements IWindowForm {
×
-
-

这是一个纯静态的 Windows 风格窗体示例。

-

你可以在这里放置任何内容。

-
+
` const fragment = template.content.cloneNode(true) as DocumentFragment; @@ -99,7 +103,7 @@ export default class WindowFormImpl implements IWindowForm { windowElement.querySelector('.btn.maximize') ?.addEventListener('click', () => { - if (this.drw.windowState === 'maximized') { + if (this.drw.windowFormState === 'maximized') { this.drw.restore() } else { this.drw.maximize() diff --git a/src/core/window/types/WindowFormTypes.ts b/src/core/window/types/WindowFormTypes.ts index a13792f..494c7f8 100644 --- a/src/core/window/types/WindowFormTypes.ts +++ b/src/core/window/types/WindowFormTypes.ts @@ -5,3 +5,6 @@ export interface WindowFormPos { x: number; y: number; } + +/** 窗口状态 */ +export type TWindowFormState = 'default' | 'minimized' | 'maximized';