Files
web-cad/frontend/src/canvas/LayerManager.ts
T

196 lines
4.9 KiB
TypeScript

import type { CADLayer } from '../types/cad.types';
export class LayerManager {
private layers: Map<string, CADLayer> = new Map();
private activeLayerId: string = '';
addLayer(layer: CADLayer): void {
this.layers.set(layer.id, layer);
if (!this.activeLayerId) this.activeLayerId = layer.id;
}
removeLayer(id: string): void {
this.layers.delete(id);
if (this.activeLayerId === id) {
const first = this.layers.keys().next();
this.activeLayerId = first.done ? '' : first.value;
}
}
getLayer(id: string): CADLayer | undefined {
return this.layers.get(id);
}
getLayers(): CADLayer[] {
return Array.from(this.layers.values()).sort((a, b) => a.sortOrder - b.sortOrder);
}
getVisibleLayers(): CADLayer[] {
return this.getLayers().filter(l => l.visible && !l.locked);
}
setActiveLayer(id: string): void {
if (this.layers.has(id)) this.activeLayerId = id;
}
getActiveLayer(): CADLayer | undefined {
return this.layers.get(this.activeLayerId);
}
getActiveLayerId(): string {
return this.activeLayerId;
}
toggleVisibility(id: string): void {
const layer = this.layers.get(id);
if (layer) layer.visible = !layer.visible;
}
toggleLock(id: string): void {
const layer = this.layers.get(id);
if (layer) layer.locked = !layer.locked;
}
clear(): void {
this.layers.clear();
this.activeLayerId = '';
}
/**
* Rename a layer.
*/
renameLayer(id: string, name: string): void {
const layer = this.layers.get(id);
if (layer) layer.name = name;
}
/**
* Update layer properties.
*/
updateLayer(id: string, props: Partial<CADLayer>): void {
const layer = this.layers.get(id);
if (layer) {
Object.assign(layer, props);
}
}
/**
* Set parent for a layer (tree structure).
*/
setParent(id: string, parentId: string | null): void {
const layer = this.layers.get(id);
if (!layer) return;
// Prevent circular references
if (parentId) {
let current: string | null = parentId;
while (current) {
if (current === id) return; // Would create a cycle
const parent = this.layers.get(current);
if (!parent) break;
current = parent.parentId;
}
}
layer.parentId = parentId;
}
/**
* Get child layers of a parent.
*/
getChildLayers(parentId: string | null): CADLayer[] {
return this.getLayers().filter(l => l.parentId === parentId);
}
/**
* Get layer tree structure.
*/
getLayerTree(): Array<CADLayer & { children: CADLayer[] }> {
const buildTree = (parentId: string | null): Array<CADLayer & { children: CADLayer[] }> => {
return this.getChildLayers(parentId).map(layer => ({
...layer,
children: buildTree(layer.id),
}));
};
return buildTree(null);
}
/**
* Move layer to a new position in the sort order.
*/
moveLayer(id: string, newSortOrder: number): void {
const layer = this.layers.get(id);
if (!layer) return;
layer.sortOrder = newSortOrder;
}
/**
* Duplicate a layer with all its properties.
*/
duplicateLayer(id: string): CADLayer | null {
const layer = this.layers.get(id);
if (!layer) return null;
const newId = `layer_${Date.now()}_${Math.random().toString(36).slice(2, 7)}`;
const copy: CADLayer = {
...layer,
id: newId,
name: `${layer.name} (Kopie)`,
sortOrder: layer.sortOrder + 1,
parentId: layer.parentId,
};
this.layers.set(newId, copy);
return copy;
}
/**
* Filter layers by criteria.
*/
filterLayers(criteria: {
visible?: boolean;
locked?: boolean;
color?: string;
lineType?: string;
nameContains?: string;
}): CADLayer[] {
return this.getLayers().filter(l => {
if (criteria.visible !== undefined && l.visible !== criteria.visible) return false;
if (criteria.locked !== undefined && l.locked !== criteria.locked) return false;
if (criteria.color && l.color !== criteria.color) return false;
if (criteria.lineType && l.lineType !== criteria.lineType) return false;
if (criteria.nameContains && !l.name.toLowerCase().includes(criteria.nameContains.toLowerCase())) return false;
return true;
});
}
/**
* Get all descendant layer IDs (children, grandchildren, etc.).
*/
getDescendantIds(id: string): string[] {
const result: string[] = [];
const collect = (parentId: string) => {
for (const layer of this.layers.values()) {
if (layer.parentId === parentId) {
result.push(layer.id);
collect(layer.id);
}
}
};
collect(id);
return result;
}
/**
* Check if a layer is locked.
*/
isLocked(id: string): boolean {
const layer = this.layers.get(id);
return layer ? layer.locked : false;
}
/**
* Get layer color.
*/
getLayerColor(id: string): string | undefined {
const layer = this.layers.get(id);
return layer?.color;
}
}