196 lines
4.9 KiB
TypeScript
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;
|
|
}
|
|
}
|