All files / src/hierarchy disconnected-layout.ts

100% Statements 38/38
100% Branches 18/18
100% Functions 3/3
100% Lines 38/38

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85            2226x             5x 2x   3x 3x 3x   3x 17x 17x 17x   3x 15x 32x 32x 32x     3x                             5x 5x 5x 5x 5x   5x 26x 26x 26x 26x       26x 2x 2x 2x     26x 26x   26x 2x 2x         24x     26x 26x      
import { SUBPROCESS_MIN_HEIGHT, SUBPROCESS_MIN_WIDTH } from '../di-constants';
import type { Bounds, Point } from '../types';
import { getArtifactDimensions } from './artifact-layout';
import { offsetAndCollectChildren, type ScopeLayoutResult } from './subprocess-layout';
 
export function isEventSubProcess(el: any): boolean {
  return el.$type === 'bpmn:SubProcess' && el.triggeredByEvent === true;
}
 
export function computeCurrentDiagramBounds(
  shapes: Array<{ bounds: Bounds }>,
  edges: Array<{ waypoints: Point[] }>
): { minX: number; maxX: number; maxY: number } {
  if (shapes.length === 0) {
    return { minX: 100, maxX: 500, maxY: 40 };
  }
  let minX = shapes[0].bounds.x;
  let maxX = shapes[0].bounds.x + shapes[0].bounds.width;
  let maxY = shapes[0].bounds.y + shapes[0].bounds.height;
 
  for (const s of shapes) {
    minX = Math.min(minX, s.bounds.x);
    maxX = Math.max(maxX, s.bounds.x + s.bounds.width);
    maxY = Math.max(maxY, s.bounds.y + s.bounds.height);
  }
  for (const e of edges) {
    for (const wp of e.waypoints) {
      minX = Math.min(minX, wp.x);
      maxX = Math.max(maxX, wp.x);
      maxY = Math.max(maxY, wp.y);
    }
  }
  return { minX, maxX, maxY };
}
 
export interface DisconnectedLayoutContext {
  childScopeResults: Map<string, ScopeLayoutResult>;
  boundsMap: Map<string, Bounds>;
  shapes: Array<{ element: any; bounds: Bounds; isExpanded?: boolean }>;
  edges: Array<{ element: any; waypoints: Point[]; isFeedback?: boolean }>;
}
 
export function layoutDisconnectedElements(
  items: any[],
  diagramBounds: { minX: number; maxX: number; maxY: number },
  ctx: DisconnectedLayoutContext
): void {
  const rowStartX = diagramBounds.minX;
  const rowBoundaryX = Math.max(diagramBounds.maxX, rowStartX + 600);
  let currentX = rowStartX;
  let currentY = diagramBounds.maxY + 60;
  let rowMaxHeight = 0;
 
  for (const item of items) {
    const childResult = isEventSubProcess(item) ? ctx.childScopeResults.get(item.id) : undefined;
    const itemDim = childResult ? undefined : getArtifactDimensions(item);
    const width = childResult ? Math.max(SUBPROCESS_MIN_WIDTH, childResult.width) : itemDim!.width;
    const height = childResult
      ? Math.max(SUBPROCESS_MIN_HEIGHT, childResult.height)
      : itemDim!.height;
 
    if (currentX > rowStartX && currentX + width > rowBoundaryX) {
      currentX = rowStartX;
      currentY += rowMaxHeight + 40;
      rowMaxHeight = 0;
    }
 
    const bounds: Bounds = { x: currentX, y: currentY, width, height };
    ctx.boundsMap.set(item.id, bounds);
 
    if (childResult) {
      ctx.shapes.push({ element: item, bounds, isExpanded: true });
      offsetAndCollectChildren(childResult, bounds, {
        shapes: ctx.shapes,
        edges: ctx.edges,
      });
    } else {
      ctx.shapes.push({ element: item, bounds });
    }
 
    currentX += width + 40;
    rowMaxHeight = Math.max(rowMaxHeight, height);
  }
}