修改
This commit is contained in:
@@ -1,3 +1,5 @@
|
|||||||
|
import type { TWindowFormState } from '@/core/window/types/WindowFormTypes.ts'
|
||||||
|
|
||||||
/** 拖拽移动开始的回调 */
|
/** 拖拽移动开始的回调 */
|
||||||
type TDragStartCallback = (x: number, y: number) => void;
|
type TDragStartCallback = (x: number, y: number) => void;
|
||||||
/** 拖拽移动中的回调 */
|
/** 拖拽移动中的回调 */
|
||||||
@@ -16,9 +18,6 @@ type TResizeDirection =
|
|||||||
| 'bottom-left'
|
| 'bottom-left'
|
||||||
| 'bottom-right';
|
| 'bottom-right';
|
||||||
|
|
||||||
/** 窗口状态 */
|
|
||||||
type TWindowState = 'default' | 'minimized' | 'maximized';
|
|
||||||
|
|
||||||
/** 元素边界 */
|
/** 元素边界 */
|
||||||
interface IElementRect {
|
interface IElementRect {
|
||||||
/** 宽度 */
|
/** 宽度 */
|
||||||
@@ -88,7 +87,7 @@ interface IDraggableResizableOptions {
|
|||||||
onResizeEnd?: (data: IResizeCallbackData) => void;
|
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 onResizeMove?: (data: IResizeCallbackData) => void;
|
||||||
private onResizeEnd?: (data: IResizeCallbackData) => void;
|
private onResizeEnd?: (data: IResizeCallbackData) => void;
|
||||||
|
|
||||||
private onWindowStateChange?: (state: TWindowState) => void;
|
private onWindowStateChange?: (state: TWindowFormState) => void;
|
||||||
|
|
||||||
private isDragging = false;
|
private isDragging = false;
|
||||||
private currentDirection: TResizeDirection | null = null;
|
private currentDirection: TResizeDirection | null = null;
|
||||||
@@ -158,7 +157,7 @@ export class DraggableResizableWindow {
|
|||||||
private mutationObserver: MutationObserver;
|
private mutationObserver: MutationObserver;
|
||||||
private animationFrame?: number;
|
private animationFrame?: number;
|
||||||
|
|
||||||
private state: TWindowState = 'default';
|
private _windowFormState: TWindowFormState = 'default';
|
||||||
/** 元素信息 */
|
/** 元素信息 */
|
||||||
private targetBounds: IElementRect;
|
private targetBounds: IElementRect;
|
||||||
/** 最小化前的元素信息 */
|
/** 最小化前的元素信息 */
|
||||||
@@ -167,8 +166,8 @@ export class DraggableResizableWindow {
|
|||||||
private targetPreMaximizedBounds?: IElementRect;
|
private targetPreMaximizedBounds?: IElementRect;
|
||||||
private taskbarElementId: string;
|
private taskbarElementId: string;
|
||||||
|
|
||||||
get windowState() {
|
get windowFormState() {
|
||||||
return this.state;
|
return this._windowFormState;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(options: IDraggableResizableOptions) {
|
constructor(options: IDraggableResizableOptions) {
|
||||||
@@ -261,7 +260,7 @@ export class DraggableResizableWindow {
|
|||||||
document.removeEventListener('mousemove', this.checkDragStart);
|
document.removeEventListener('mousemove', this.checkDragStart);
|
||||||
document.removeEventListener('mouseup', this.cancelPendingDrag);
|
document.removeEventListener('mouseup', this.cancelPendingDrag);
|
||||||
|
|
||||||
if (this.state === 'maximized') {
|
if (this._windowFormState === 'maximized') {
|
||||||
const preRect = this.targetPreMaximizedBounds!;
|
const preRect = this.targetPreMaximizedBounds!;
|
||||||
const rect = this.target.getBoundingClientRect();
|
const rect = this.target.getBoundingClientRect();
|
||||||
const relX = e.clientX / rect.width;
|
const relX = e.clientX / rect.width;
|
||||||
@@ -583,9 +582,9 @@ export class DraggableResizableWindow {
|
|||||||
|
|
||||||
// 最小化到任务栏
|
// 最小化到任务栏
|
||||||
public minimize() {
|
public minimize() {
|
||||||
if (this.state === 'minimized') return;
|
if (this._windowFormState === 'minimized') return;
|
||||||
this.targetPreMinimizeBounds = { ...this.targetBounds }
|
this.targetPreMinimizeBounds = { ...this.targetBounds }
|
||||||
this.state = 'minimized';
|
this._windowFormState = 'minimized';
|
||||||
|
|
||||||
const taskbar = document.querySelector(this.taskbarElementId);
|
const taskbar = document.querySelector(this.taskbarElementId);
|
||||||
if (!taskbar) throw new Error('任务栏元素未找到');
|
if (!taskbar) throw new Error('任务栏元素未找到');
|
||||||
@@ -603,9 +602,9 @@ export class DraggableResizableWindow {
|
|||||||
|
|
||||||
/** 最大化 */
|
/** 最大化 */
|
||||||
public maximize() {
|
public maximize() {
|
||||||
if (this.state === 'maximized') return;
|
if (this._windowFormState === 'maximized') return;
|
||||||
this.targetPreMaximizedBounds = { ...this.targetBounds }
|
this.targetPreMaximizedBounds = { ...this.targetBounds }
|
||||||
this.state = 'maximized';
|
this._windowFormState = 'maximized';
|
||||||
|
|
||||||
const rect = this.target.getBoundingClientRect();
|
const rect = this.target.getBoundingClientRect();
|
||||||
|
|
||||||
@@ -624,19 +623,19 @@ export class DraggableResizableWindow {
|
|||||||
|
|
||||||
/** 恢复到默认窗体状态 */
|
/** 恢复到默认窗体状态 */
|
||||||
public restore(onComplete?: () => void) {
|
public restore(onComplete?: () => void) {
|
||||||
if (this.state === 'default') return;
|
if (this._windowFormState === 'default') return;
|
||||||
let b: IElementRect;
|
let b: IElementRect;
|
||||||
if ((this.state as TWindowState) === 'minimized' && this.targetPreMinimizeBounds) {
|
if ((this._windowFormState as TWindowFormState) === 'minimized' && this.targetPreMinimizeBounds) {
|
||||||
// 最小化恢复,恢复到最小化前的状态
|
// 最小化恢复,恢复到最小化前的状态
|
||||||
b = 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;
|
b = this.targetPreMaximizedBounds;
|
||||||
} else {
|
} else {
|
||||||
b = this.targetBounds;
|
b = this.targetBounds;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.state = 'default';
|
this._windowFormState = 'default';
|
||||||
|
|
||||||
this.target.style.display = 'block';
|
this.target.style.display = 'block';
|
||||||
|
|
||||||
@@ -696,7 +695,7 @@ export class DraggableResizableWindow {
|
|||||||
this.target.style.height = `${targetH}px`;
|
this.target.style.height = `${targetH}px`;
|
||||||
this.applyPosition(targetX, targetY, true);
|
this.applyPosition(targetX, targetY, true);
|
||||||
onComplete?.();
|
onComplete?.();
|
||||||
this.onWindowStateChange?.(this.state);
|
this.onWindowStateChange?.(this._windowFormState);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
requestAnimationFrame(step);
|
requestAnimationFrame(step);
|
||||||
|
|||||||
@@ -1,6 +1,15 @@
|
|||||||
import type { IProcess } from '@/core/process/IProcess.ts'
|
import type { IProcess } from '@/core/process/IProcess.ts'
|
||||||
|
import type { TWindowFormState } from '@/core/window/types/WindowFormTypes.ts'
|
||||||
|
|
||||||
export interface IWindowForm {
|
export interface IWindowForm {
|
||||||
|
/** 窗体id */
|
||||||
get id(): string;
|
get id(): string;
|
||||||
|
/** 窗体所属的进程 */
|
||||||
get proc(): IProcess | undefined;
|
get proc(): IProcess | undefined;
|
||||||
|
/** 窗体元素 */
|
||||||
|
get windowFormEle(): HTMLElement;
|
||||||
|
/** 窗体状态 */
|
||||||
|
get windowFormState(): TWindowFormState;
|
||||||
|
/** 关闭窗体 */
|
||||||
|
closeWindowForm(): void;
|
||||||
}
|
}
|
||||||
@@ -14,8 +14,8 @@ export default class WindowFormImpl implements IWindowForm {
|
|||||||
private dom: HTMLElement;
|
private dom: HTMLElement;
|
||||||
private drw: DraggableResizableWindow;
|
private drw: DraggableResizableWindow;
|
||||||
private pos: WindowFormPos = { x: 0, y: 0 };
|
private pos: WindowFormPos = { x: 0, y: 0 };
|
||||||
private width: number = 0;
|
private width: number;
|
||||||
private height: number = 0;
|
private height: number;
|
||||||
|
|
||||||
public get id() {
|
public get id() {
|
||||||
return this._id;
|
return this._id;
|
||||||
@@ -26,6 +26,12 @@ export default class WindowFormImpl implements IWindowForm {
|
|||||||
private get desktopRootDom() {
|
private get desktopRootDom() {
|
||||||
return XSystem.instance.desktopRootDom;
|
return XSystem.instance.desktopRootDom;
|
||||||
}
|
}
|
||||||
|
public get windowFormEle() {
|
||||||
|
return this.dom;
|
||||||
|
}
|
||||||
|
public get windowFormState() {
|
||||||
|
return this.drw.windowFormState
|
||||||
|
}
|
||||||
|
|
||||||
constructor(proc: IProcess, config: IWindowFormConfig) {
|
constructor(proc: IProcess, config: IWindowFormConfig) {
|
||||||
this._procId = proc.id;
|
this._procId = proc.id;
|
||||||
@@ -34,20 +40,21 @@ export default class WindowFormImpl implements IWindowForm {
|
|||||||
x: config.left ?? 0,
|
x: config.left ?? 0,
|
||||||
y: config.top ?? 0
|
y: config.top ?? 0
|
||||||
}
|
}
|
||||||
this.width = config.width ?? 0;
|
this.width = config.width ?? 200;
|
||||||
this.height = config.height ?? 0;
|
this.height = config.height ?? 100;
|
||||||
|
|
||||||
this.createWindowFrom();
|
this.createWindowFrom();
|
||||||
}
|
}
|
||||||
|
|
||||||
private createWindowFrom() {
|
private createWindowFrom() {
|
||||||
this.dom = this.windowFormEle();
|
this.dom = this.createWindowFormEle();
|
||||||
this.dom.style.position = 'absolute';
|
this.dom.style.position = 'absolute';
|
||||||
this.dom.style.width = `${this.width}px`;
|
this.dom.style.width = `${this.width}px`;
|
||||||
this.dom.style.height = `${this.height}px`;
|
this.dom.style.height = `${this.height}px`;
|
||||||
this.dom.style.zIndex = '10';
|
this.dom.style.zIndex = '10';
|
||||||
|
|
||||||
const header = this.dom.querySelector('.title-bar') as HTMLElement;
|
const header = this.dom.querySelector('.title-bar') as HTMLElement;
|
||||||
|
const content = this.dom.querySelector('.window-content') as HTMLElement;
|
||||||
this.drw = new DraggableResizableWindow({
|
this.drw = new DraggableResizableWindow({
|
||||||
target: this.dom,
|
target: this.dom,
|
||||||
handle: header,
|
handle: header,
|
||||||
@@ -67,13 +74,13 @@ export default class WindowFormImpl implements IWindowForm {
|
|||||||
this.desktopRootDom.appendChild(this.dom);
|
this.desktopRootDom.appendChild(this.dom);
|
||||||
}
|
}
|
||||||
|
|
||||||
private closeWindowForm() {
|
public closeWindowForm() {
|
||||||
this.drw.destroy();
|
this.drw.destroy();
|
||||||
this.desktopRootDom.removeChild(this.dom);
|
this.desktopRootDom.removeChild(this.dom);
|
||||||
this.proc?.event.notifyEvent('onProcessWindowFormExit', this.id)
|
this.proc?.event.notifyEvent('onProcessWindowFormExit', this.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
private windowFormEle() {
|
private createWindowFormEle() {
|
||||||
const template = document.createElement('template');
|
const template = document.createElement('template');
|
||||||
template.innerHTML = `
|
template.innerHTML = `
|
||||||
<div class="window">
|
<div class="window">
|
||||||
@@ -85,10 +92,7 @@ export default class WindowFormImpl implements IWindowForm {
|
|||||||
<div class="close btn" title="关闭">×</div>
|
<div class="close btn" title="关闭">×</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="window-content">
|
<div class="window-content"></div>
|
||||||
<p>这是一个纯静态的 Windows 风格窗体示例。</p>
|
|
||||||
<p>你可以在这里放置任何内容。</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
const fragment = template.content.cloneNode(true) as DocumentFragment;
|
const fragment = template.content.cloneNode(true) as DocumentFragment;
|
||||||
@@ -99,7 +103,7 @@ export default class WindowFormImpl implements IWindowForm {
|
|||||||
|
|
||||||
windowElement.querySelector('.btn.maximize')
|
windowElement.querySelector('.btn.maximize')
|
||||||
?.addEventListener('click', () => {
|
?.addEventListener('click', () => {
|
||||||
if (this.drw.windowState === 'maximized') {
|
if (this.drw.windowFormState === 'maximized') {
|
||||||
this.drw.restore()
|
this.drw.restore()
|
||||||
} else {
|
} else {
|
||||||
this.drw.maximize()
|
this.drw.maximize()
|
||||||
|
|||||||
@@ -5,3 +5,6 @@ export interface WindowFormPos {
|
|||||||
x: number;
|
x: number;
|
||||||
y: number;
|
y: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 窗口状态 */
|
||||||
|
export type TWindowFormState = 'default' | 'minimized' | 'maximized';
|
||||||
|
|||||||
Reference in New Issue
Block a user