import { fabric } from 'fabric' ; import Handler from './Handler' ; import { FabricObject } from '../utils' ; import { NodeObject } from '../objects/Node' ; import { LinkObject } from '../objects/Link' ; class NodeHandler { handler : Handler ; constructor ( handler ) { this . handler = handler ; } param { NodeObject } target param { NodeObject [ ] } nodes param { string } direction getNodePath = ( target , nodes = [ ] , direction = 'init' ) => { if ( target ) { if ( direction === 'to' || direction === 'init' ) { if ( target . toPort ) { target . toPort . links . forEach ( link => { if ( link . fromNode ) { nodes . push ( link . fromNode ) ; this . getNodePath ( link . fromNode , nodes , 'to' ) ; } } ) ; } if ( direction === 'init' ) { nodes . push ( target ) ; } } if ( direction === 'from' || direction === 'init' ) { target . fromPort . forEach ( port => { port . links . forEach ( link => { if ( link . toNode ) { nodes . push ( link . toNode ) ; this . getNodePath ( link . toNode , nodes , 'from' ) ; } } ) ; } ) ; } } } ; param { string [ ] } path selectByPath = ( path ? ) => { if ( ! path || ! path . length ) { return ; } const targetObjects = this . handler . objects . filter ( object => path . some ( id => id === object . id ) ) ; const nonTargetObjects = this . handler . objects . filter ( object => path . some ( id => id !== object . id ) ) ; nonTargetObjects . forEach ( ( object ) => { if ( object . superType === 'link' ) { const { fromNode , toNode } = object as LinkObject ; if ( fromNode && toNode ) { const fromIndex = targetObjects . findIndex ( obj => obj . id === fromNode . id ) ; const toIndex = targetObjects . findIndex ( obj => obj . id === toNode . id ) ; if ( fromIndex >= 0 && targetObjects [ fromIndex ] && toIndex >= 0 && targetObjects [ toIndex ] ) { object . set ( { opacity : 1 , shadow : { color : object . stroke , } , } ) ; this . highlightingNode ( object , 300 ) ; this . handler . canvas . requestRenderAll ( ) ; return ; } } } object . set ( { opacity : 0.2 , } ) ; if ( object . superType === 'node' ) { if ( object . toPort ) { object . toPort . set ( { opacity : 0.2 , } ) ; } object . fromPort . forEach ( ( port ) => { port . set ( { opacity : 0.2 , } ) ; } ) ; } if ( ! object . animating ) { object . set ( 'shadow' , { blur : 0 , } ) ; } } ) ; targetObjects . forEach ( ( object ) => { object . set ( { opacity : 1 , shadow : { color : object . stroke , } , } ) ; this . highlightingNode ( object , 300 ) ; if ( object . toPort ) { object . toPort . set ( { opacity : 1 , } ) ; } if ( object . fromPort ) { object . fromPort . forEach ( ( port ) => { port . set ( { opacity : 1 , } ) ; } ) ; } } ) ; this . handler . canvas . requestRenderAll ( ) ; } ; param { string } id selectById = ( id ) => { this . handler . objects . forEach ( ( object ) => { if ( id === object . id ) { object . set ( 'shadow' , { color : object . stroke , blur : 50 , } as fabric . Shadow ) ; return ; } else if ( id === object . nodeId ) { return ; } object . set ( 'shadow' , { blur : 0 , } as fabric . Shadow ) ; } ) ; this . handler . canvas . requestRenderAll ( ) ; } ; /**
     * Deselect nodes
     */ deselect = ( ) => { this . handler . objects . forEach ( ( object ) => { object . set ( { opacity : 1 , } ) ; if ( object . superType === 'node' ) { const node = object as NodeObject ; if ( node . toPort ) { node . toPort . set ( { opacity : 1 , } ) ; } node . fromPort . forEach ( port => { port . set ( { opacity : 1 , } ) ; } ) ; } if ( ! object . animating ) { const node = object as FabricObject ; node . set ( 'shadow' , { blur : 0 , } as fabric . Shadow ) ; } } ) ; this . handler . canvas . renderAll ( ) ; } ; param { string [ ] } path highlightingByPath = ( path ? ) => { if ( ! path || ! path . length ) { return ; } const targetObjects = this . handler . objects . filter ( ( obj ) => path . some ( id => id === obj . id ) ) ; const nonTargetObjects = this . handler . objects . filter ( ( obj ) => path . some ( id => id !== obj . id ) ) ; const lastObject = targetObjects . filter ( ( obj ) => obj . id === path [ path . length - 1 ] ) [ 0 ] ; targetObjects . forEach ( ( object ) => { if ( lastObject ) { object . set ( 'shadow' , { color : lastObject . stroke , } as fabric . Shadow ) ; } else { object . set ( 'shadow' , { color : object . stroke , } as fabric . Shadow ) ; } this . highlightingNode ( object ) ; this . handler . canvas . requestRenderAll ( ) ; } ) ; nonTargetObjects . forEach ( ( object ) => { if ( object . superType === 'link' ) { const { fromNode , toNode } = object ; if ( fromNode && toNode ) { const fromIndex = targetObjects . findIndex ( ( obj ) => obj . id === fromNode . id ) ; const toIndex = targetObjects . findIndex ( ( obj ) => obj . id === toNode . id ) ; if ( fromIndex >= 0 && targetObjects [ fromIndex ] && toIndex >= 0 && targetObjects [ toIndex ] ) { if ( lastObject ) { object . set ( 'shadow' , { color : lastObject . stroke , } as fabric . Shadow ) ; } else { object . set ( 'shadow' , { color : object . stroke , } as fabric . Shadow ) ; } this . highlightingNode ( object ) ; this . highlightingLink ( object , lastObject ) ; return ; } } } } ) ; this . handler . canvas . requestRenderAll ( ) ; } ; param { FabricObject } object param { FabricObject } targetObject param { number } duration highlightingLink = ( object , targetObject , duration = 500 ) => { object . animation = { duration , type : 'flash' , stroke : targetObject ? targetObject . stroke : object . stroke , loop : 1 , delay : 0 , } ; this . handler . animationHandler . play ( object . id , false ) ; } ; param { * } object param { number } duration param { number } minBlur param { number } maxBlur highlightingNode = ( object , duration = 500 , minBlur = 0 , maxBlur = 50 ) => { const onComplete = ( ) => { if ( object . shadow . blur === maxBlur ) { object . animating = true ; object . animate ( 'shadow.blur' , minBlur , { easing : fabric . util . ease . easeInOutQuad , onChange : ( value ) => { object . shadow . blur = value ; this . handler . canvas . requestRenderAll ( ) ; } , onComplete : ( ) => { object . animating = false ; if ( object . superType === 'link' ) { object . set ( { stroke : object . originStroke , } ) ; } } , } ) ; } } ; object . animating = true ; object . animate ( 'shadow.blur' , maxBlur , { easing : fabric . util . ease . easeInOutQuad , duration , onChange : ( value ) => { object . shadow . blur = value ; this . handler . canvas . requestRenderAll ( ) ; } , onComplete , } ) ; } ; } export default NodeHandler ;