feat: initial commit web-cad-neu with docker-compose, frontend and backend
This commit is contained in:
@@ -0,0 +1,195 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user