UNPKG

@antv/x6

Version:

JavaScript diagramming library that uses SVG and HTML for rendering.

296 lines (251 loc) 7.38 kB
import { Attr, PortLayout, PortLabelLayout } from '../registry' import { JSONObject, ObjectExt } from '../util' import { Point, Rectangle } from '../geometry' import { Size, KeyValue } from '../types' import { Markup } from '../view' export class PortManager { ports: PortManager.Port[] groups: { [name: string]: PortManager.Group } constructor(data: PortManager.Metadata) { this.ports = [] this.groups = {} this.init(ObjectExt.cloneDeep(data)) } getPorts() { return this.ports } getGroup(groupName?: string | null) { return groupName != null ? this.groups[groupName] : null } getPortsByGroup(groupName?: string): PortManager.Port[] { return this.ports.filter( (p) => p.group === groupName || (p.group == null && groupName == null), ) } getPortsLayoutByGroup(groupName: string | undefined, elemBBox: Rectangle) { const ports = this.getPortsByGroup(groupName) const group = groupName ? this.getGroup(groupName) : null const groupPosition = group ? group.position : null const groupPositionName = groupPosition ? groupPosition.name : null let layoutFn: PortLayout.Definition<any> if (groupPositionName != null) { const fn = PortLayout.registry.get(groupPositionName) if (fn == null) { return PortLayout.registry.onNotFound(groupPositionName) } layoutFn = fn } else { layoutFn = PortLayout.presets.left } const portsArgs = ports.map( (port) => (port && port.position && port.position.args) || {}, ) const groupArgs = (groupPosition && groupPosition.args) || {} const layouts = layoutFn(portsArgs, elemBBox, groupArgs) return layouts.map<PortManager.LayoutResult>((portLayout, index) => { const port = ports[index] return { portLayout, portId: port.id!, portSize: port.size, portAttrs: port.attrs, labelSize: port.label.size, labelLayout: this.getPortLabelLayout( port, Point.create(portLayout.position), elemBBox, ), } }) } protected init(data: PortManager.Metadata) { const { groups, items } = data if (groups != null) { Object.keys(groups).forEach((key) => { this.groups[key] = this.parseGroup(groups[key]) }) } if (Array.isArray(items)) { items.forEach((item) => { this.ports.push(this.parsePort(item)) }) } } protected parseGroup(group: PortManager.GroupMetadata) { return { ...group, label: this.getLabel(group, true), position: this.getPortPosition(group.position, true), } as PortManager.Group } protected parsePort(port: PortManager.PortMetadata) { const result = { ...port } as PortManager.Port const group = this.getGroup(port.group) || ({} as PortManager.Group) result.markup = result.markup || group.markup result.attrs = ObjectExt.merge({}, group.attrs, result.attrs) result.position = this.createPosition(group, result) result.label = ObjectExt.merge({}, group.label, this.getLabel(result)) result.zIndex = this.getZIndex(group, result) result.size = { ...group.size, ...result.size } as Size return result } protected getZIndex( group: PortManager.Group, port: PortManager.PortMetadata, ) { if (typeof port.zIndex === 'number') { return port.zIndex } if (typeof group.zIndex === 'number' || group.zIndex === 'auto') { return group.zIndex } return 'auto' } protected createPosition( group: PortManager.Group, port: PortManager.PortMetadata, ) { return ObjectExt.merge( { name: 'left', args: {}, }, group.position, { args: port.args }, ) as PortManager.PortPosition } protected getPortPosition( position?: PortManager.PortPositionMetadata, setDefault = false, ): PortManager.PortPosition { if (position == null) { if (setDefault) { return { name: 'left', args: {} } } } else { if (typeof position === 'string') { return { name: position, args: {}, } } if (Array.isArray(position)) { return { name: 'absolute', args: { x: position[0], y: position[1] }, } } if (typeof position === 'object') { return position } } return { args: {} } } protected getPortLabelPosition( position?: PortManager.PortLabelPositionMetadata, setDefault = false, ): PortManager.PortLabelPosition { if (position == null) { if (setDefault) { return { name: 'left', args: {} } } } else { if (typeof position === 'string') { return { name: position, args: {}, } } if (typeof position === 'object') { return position } } return { args: {} } } protected getLabel(item: PortManager.GroupMetadata, setDefaults = false) { const label = item.label || {} label.position = this.getPortLabelPosition(label.position, setDefaults) return label as PortManager.Label } protected getPortLabelLayout( port: PortManager.Port, portPosition: Point, elemBBox: Rectangle, ) { const name = port.label.position.name || 'left' const args = port.label.position.args || {} const layoutFn = PortLabelLayout.registry.get(name) || PortLabelLayout.presets.left if (layoutFn) { return layoutFn(portPosition, elemBBox, args) } return null } } export namespace PortManager { export interface Metadata { groups?: { [name: string]: GroupMetadata } items: PortMetadata[] } export type PortPosition = | Partial<PortLayout.NativeItem> | Partial<PortLayout.ManaualItem> export type PortPositionMetadata = | PortLayout.NativeNames | Exclude<string, PortLayout.NativeNames> | Point.PointData // absolute layout | PortPosition export type PortLabelPosition = | Partial<PortLabelLayout.NativeItem> | Partial<PortLabelLayout.ManaualItem> export type PortLabelPositionMetadata = | PortLabelLayout.NativeNames | Exclude<string, PortLabelLayout.NativeNames> | PortLabelPosition export interface LabelMetadata { markup?: Markup size?: Size position?: PortLabelPositionMetadata } export interface Label { markup: string size?: Size position: PortLabelPosition } interface Common { markup: Markup attrs: Attr.CellAttrs zIndex: number | 'auto' size?: Size } export interface GroupMetadata extends Partial<Common>, KeyValue { label?: LabelMetadata position?: PortPositionMetadata } export interface Group extends Partial<Common> { label: Label position: PortPosition } interface PortBase { group?: string /** * Arguments for the port layout function. */ args?: JSONObject } export interface PortMetadata extends Partial<Common>, PortBase, KeyValue { id?: string label?: LabelMetadata } export interface Port extends Group, PortBase { id: string } export interface LayoutResult { portId: string portAttrs?: Attr.CellAttrs portSize?: Size portLayout: PortLayout.Result labelSize?: Size labelLayout: PortLabelLayout.Result | null } }