import autobind from "autobind-decorator" ; import { action , makeObservable , observable } from "mobx" ; import LayoutProperties , { ILayoutProperties } from "../modals/LayoutProperties" ; import { IColorValueMap , IProfileMetaData } from "../ui/react-pathway-mapper" ; import CBioPortalAccessor from "../utils/CBioPortalAccessor" ; import SVGExporter from "../utils/SVGExporter" ; import GenomicDataOverlayManager from "./GenomicDataOverlayManager" ; import ShareDBManager from "./ShareDBManager" ; const _ = require ( 'lodash' ) ; export default class EditorActionsManager { public static defaultLayoutProperties : ILayoutProperties = { name : 'fcose' , nodeRepulsion : 4500 , idealEdgeLength : 50 , edgeElasticity : 0.45 , nestingFactor : 0.1 , gravity : 0.25 , numIter : 2500 , tile : true , animate : true , randomize : false , gravityRangeCompound : 1.5 , gravityCompound : 1.0 , gravityRange : 3.8 , tilingPaddingVertical : 10 , tilingPaddingHorizontal : 10 , initialEnergyOnIncremental : 0.5 , animationDuration : 2000 , animationEasing : 'cubic-bezier(0.17,0.72,0.41,0.98)' , nodeDimensionsIncludeLabels : true } ; public cy : any ; public genomicDataOverlayManager : GenomicDataOverlayManager ; public edgeEditing : any ; public selectedNodeStack : any ; public layoutProperties : ILayoutProperties ; private FIT_CONSTANT : number ; private observers : any [ ] ; private svgExporter : SVGExporter ; private undoRedoManager : any ; private isCbioPortal : boolean ; private isCollaborative : boolean ; private shareDBManager : ShareDBManager ; private portalAccessor : CBioPortalAccessor ; private viewUtilities : any ; @ observable private profiles : IProfileMetaData [ ] ; @ observable private genomicDataOverlayColorScheme : IColorValueMap ; private colorSchemeChangeCallback : ( IColorValueMap ) => void ; constructor ( isCollaborative , shareDBManager , cyInst , isCBioPortal , undoRedoManager , portalAccessor , profiles , genomicDataOverlayColorScheme , colorSchemeChangeCallback ) { makeObservable ( this ) ; this . cy = cyInst ; this . isCollaborative = isCollaborative ; this . isCbioPortal = isCBioPortal ; this . profiles = profiles ; this . genomicDataOverlayColorScheme = genomicDataOverlayColorScheme ; this . colorSchemeChangeCallback = colorSchemeChangeCallback ; const edgeEditingOptions = { bendPositionsFunction : function ( ele ) { return ele . data ( 'bendPointPositions' ) ; } , controlPositionsFunction : function ( ele ) { return ele . data ( 'controlPointPositions' ) ; } , undoable : true , anchorShapeSizeFactor : 6 , enabled : ! this . isCbioPortal , handleReconnectEdge : this . isCollaborative ? this . reconnectEdge . bind ( this ) : undefined , enableMultipleAnchorRemovalOption : true } ; if ( ! this . isCbioPortal ) { this . edgeEditing = this . cy . edgeEditing ( edgeEditingOptions ) ; } this . portalAccessor = portalAccessor ; if ( this . isCollaborative ) { this . shareDBManager = shareDBManager ; } this . FIT_CONSTANT = 50 ; this . layoutProperties = _ . clone ( EditorActionsManager . defaultLayoutProperties ) ; this . observers = [ ] ; this . genomicDataOverlayManager = new GenomicDataOverlayManager ( this . cy ) ; this . svgExporter = new SVGExporter ( this . edgeEditing , this ) ; this . selectedNodeStack = { } ; this . undoRedoManager = undoRedoManager ; this . undoRedoManager . action ( "changePositions" , this . doChangePosition , this . undoChangePosition ) ; this . undoRedoManager . action ( "changeNodeSize" , this . doChangeNodeSize , this . undoChangeNodeSize ) ; this . undoRedoManager . action ( "changeCompoundSize" , this . doChangeCompoundSize , this . undoChangeCompoundSize ) ; this . undoRedoManager . action ( "changeName" , this . doChangename , this . undoChangeName ) ; this . undoRedoManager . action ( "hideNode" , this . doHide , this . undoHide ) ; this . undoRedoManager . action ( "showAllNodes" , this . doShow , this . undoShow ) ; this . undoRedoManager . action ( "highlightInvalidGenes" , this . doHighlightInvalidGenes , this . undoHighlightInvalidGenes ) ; this . undoRedoManager . action ( "removeHighlightInvalidGenes" , this . undoHighlightInvalidGenes , this . doHighlightInvalidGenes ) ; this . undoRedoManager . action ( "highlightOthers" , this . doHighlight , this . undoHighlight ) ; this . undoRedoManager . action ( "removeOtherHighlight" , this . undoHighlight , this . doHighlight ) ; } ; @ action . bound setProfile ( index , profile ) { this . profiles [ index ] = profile ; } @ action . bound addProfile ( profile ) { this . profiles . push ( profile ) ; } @ action . bound removeProfiles ( ) { this . profiles . length = 0 ; } @ action . bound setGenomicDataOverlayColorScheme ( scheme ) { this . genomicDataOverlayColorScheme = scheme ; } @ autobind setViewUtilities ( viewUtilitiesRef ) { this . viewUtilities = viewUtilitiesRef ; } getGenomicDataOverlayColorScheme ( ) { return this . genomicDataOverlayColorScheme ; } handleChangePositionByAlignment ( movedNodeArr ) { if ( this . isCollaborative ) this . shareDBManager . changeElementsPositionByAlignment ( movedNodeArr ) ; else this . undoRedoManager . do ( "changePositions" , movedNodeArr ) ; } ; doChangePosition ( movedNodes ) { const newMovedNodes = [ ] ; for ( let i = 0 ; i < movedNodes . length ; i ++ ) { const currentNodePosition = { x : movedNodes [ i ] . node . position ( ) . x , y : movedNodes [ i ] . node . position ( ) . y } ; newMovedNodes . push ( { node : movedNodes [ i ] . node , oldPosition : currentNodePosition , nextPosition : movedNodes [ i ] . nextPosition } ) ; movedNodes [ i ] . node . position ( movedNodes [ i ] . nextPosition ) ; } return newMovedNodes ; } ; undoChangePosition ( movedNodes ) { var newMovedNodes = [ ] ; for ( var i = 0 ; i < movedNodes . length ; i ++ ) { var currentNodePosition = { x : movedNodes [ i ] . node . position ( ) . x , y : movedNodes [ i ] . node . position ( ) . y } ; newMovedNodes . push ( { node : movedNodes [ i ] . node , oldPosition : movedNodes [ i ] . oldPosition , nextPosition : currentNodePosition } ) ; movedNodes [ i ] . node . position ( movedNodes [ i ] . oldPosition ) ; } return newMovedNodes ; } ; changeNodePositionsByArrows ( selectedNodes ) { if ( this . isCollaborative ) this . shareDBManager . changeNodePositionsShareDB ( selectedNodes ) ; } ; doChangeNodeSize ( args ) { args . ele . data ( 'w' , args . newWidth ) ; args . ele . data ( 'h' , args . newHeight ) ; return args ; } ; undoChangeNodeSize ( args ) { args . ele . data ( 'w' , args . oldWidth ) ; args . ele . data ( 'h' , args . oldHeight ) ; return args ; } ; doChangeCompoundSize ( args ) { args . ele . style ( 'min-width' , args . newMinWidth ) ; args . ele . style ( 'min-width-bias-left' , args . newMinWidthBiasLeft ) ; args . ele . style ( 'min-width-bias-right' , args . newMinWidthBiasRight ) ; args . ele . style ( 'min-height' , args . newMinHeight ) ; args . ele . style ( 'min-height-bias-top' , args . newMinHeightBiasTop ) ; args . ele . style ( 'min-height-bias-bottom' , args . newMinHeightBiasBottom ) ; return args ; } ; undoChangeCompoundSize ( args ) { if ( args . oldMinWidth == undefined ) { args . ele . style ( 'min-width' , 0 ) ; args . ele . style ( 'min-width-bias-left' , 0 ) ; args . ele . style ( 'min-width-bias-right' , 0 ) ; } else { args . ele . style ( 'min-width' , args . oldMinWidth ) ; args . ele . style ( 'min-width-bias-left' , args . oldMinWidthBiasLeft ) ; args . ele . style ( 'min-width-bias-right' , args . oldMinWidthBiasRight ) ; } if ( args . oldMinHeight == undefined ) { args . ele . style ( 'min-height' , 0 ) ; args . ele . style ( 'min-height-bias-top' , 0 ) ; args . ele . style ( 'min-height-bias-bottom' , 0 ) ; } else { args . ele . style ( 'min-height' , args . oldMinHeight ) ; args . ele . style ( 'min-height-bias-top' , args . oldMinHeightBiasTop ) ; args . ele . style ( 'min-height-bias-bottom' , args . oldMinHeightBiasBottom ) ; } return args ; } ; changeName ( ele , newName ) { if ( this . isCollaborative ) { this . shareDBManager . changeName ( ele , newName ) ; } else { this . changeNameCy ( ele , newName ) ; } } ; changeNameCy ( ele , newName ) { var currentName = ele . data ( 'name' ) ; var args = { ele : ele , oldName : currentName , newName : newName } ; this . undoRedoManager . do ( 'changeName' , args ) ; } ; doChangename ( args ) { var currentName = args . ele . data ( 'name' ) ; var newArgs = { ele : args . ele , newName : args . newName , oldName : currentName } ; args . ele . data ( 'name' , args . newName ) ; return newArgs ; } ; undoChangeName ( args ) { var currentName = args . ele . data ( 'name' ) ; var newArgs = { ele : args . ele , newName : args . newName , oldName : currentName } ; args . ele . data ( 'name' , args . oldName ) ; return newArgs ; } ; hideSelectedNodes ( ) { var sel = this . cy . nodes ( ":selected" ) ; var nodesToHide = sel ; var b = true ; sel . parent ( ) . each ( ( parent ) => { b = true ; parent . children ( ) . each ( function ( ch ) { if ( ! ch . selected ( ) ) { if ( ch . visible ( ) ) b = false ; } } ) ; if ( b ) nodesToHide = nodesToHide . add ( parent ) ; } ) ; this . cy . elements ( ":selected" ) . unselect ( ) ; if ( this . isCollaborative ) this . shareDBManager . changeVisibility ( nodesToHide , true ) ; else this . undoRedoManager . do ( 'hideNode' , nodesToHide ) ; } ; @ autobind doHide ( args ) { this . viewUtilities . hide ( args ) ; return args ; } ; @ autobind undoHide ( args ) { this . viewUtilities . show ( args ) ; return args ; } ; showAllNodes ( ) { var hid = this . cy . nodes ( ":hidden" ) ; if ( this . isCollaborative ) this . shareDBManager . changeVisibility ( hid , false ) ; else this . undoRedoManager . do ( 'showAllNodes' , hid ) ; } ; @ autobind doShow ( args ) { this . viewUtilities . show ( args ) ; return args ; } ; @ autobind undoShow ( args ) { this . viewUtilities . hide ( args ) ; return args ; } ; highlightElementsInitially ( invalidHighlightedGenesIDs , invalidGenesIDs , highlightedGenesIDs , highlightedEdgesIDs , hiddenGenesIDs ) { for ( var i in invalidHighlightedGenesIDs ) { this . cy . $ ( '#' + invalidHighlightedGenesIDs [ i ] ) . addClass ( 'invalidGeneHighlight' ) ; } for ( var i in invalidGenesIDs ) { this . cy . $ ( '#' + invalidGenesIDs [ i ] ) . addClass ( 'invalidGene' ) ; } for ( var i in highlightedGenesIDs ) { this . cy . $ ( '#' + highlightedGenesIDs [ i ] ) . addClass ( 'highlightedNode' ) ; } for ( var i in highlightedEdgesIDs ) { this . cy . $ ( '#' + highlightedEdgesIDs [ i ] ) . addClass ( 'highlightedEdge' ) ; } for ( var i in hiddenGenesIDs ) { this . viewUtilities . hide ( this . cy . $ ( '#' + hiddenGenesIDs [ i ] ) ) ; } } ; validateGenes ( ) { var geneSymbols = this . getGeneSymbols ( ) ; this . portalAccessor . validateGenes ( geneSymbols , this ) ; } getGeneSymbols ( ) { var geneSymbols = [ ] ; this . cy . nodes ( ) . forEach ( function ( gene ) { if ( gene . data ( ) . type === "GENE" ) geneSymbols . push ( gene . data ( ) . name ) ; } ) ; return geneSymbols ; } highlightInvalidGenes ( validGeneSymbols ) { if ( this . isCollaborative ) { var invalidGenes = [ ] ; this . cy . nodes ( ) . forEach ( function ( gene ) { if ( gene . data ( ) . type === "GENE" ) { var geneName = gene . data ( ) . name ; if ( validGeneSymbols . indexOf ( geneName ) < 0 ) invalidGenes . push ( gene . id ( ) ) ; } } ) ; this . shareDBManager . changeHighlightInvalidGenes ( invalidGenes , true ) ; } else { var highlightedGenes = this . cy . collection ( ) ; this . cy . nodes ( ) . forEach ( function ( gene ) { if ( gene . data ( ) . type === "GENE" ) { var geneName = gene . data ( ) . name ; if ( validGeneSymbols . indexOf ( geneName ) < 0 ) highlightedGenes = highlightedGenes . add ( gene ) ; } } ) ; var nodesToAddInvalidHighlight = this . cy . collection ( ) ; highlightedGenes . forEach ( function ( ele ) { if ( ! ele . hasClass ( 'invalidGeneHighlight' ) && ! ele . hasClass ( 'invalidGene' ) ) nodesToAddInvalidHighlight = nodesToAddInvalidHighlight . union ( ele ) ; } ) ; this . undoRedoManager . do ( 'highlightInvalidGenes' , nodesToAddInvalidHighlight ) ; } } removeInvalidGeneHighlights ( actions ) { if ( this . isCollaborative ) { var geneIDs = [ ] ; this . cy . nodes ( ) . forEach ( function ( gene ) { if ( gene . data ( ) . type === "GENE" ) { if ( gene . hasClass ( 'invalidGeneHighlight' ) || gene . hasClass ( 'invalidGene' ) ) geneIDs . push ( gene . id ( ) ) ; } } ) ; this . shareDBManager . changeHighlightInvalidGenes ( geneIDs , false ) ; } else { var nodesToRemoveInvalidHighlight = this . cy . collection ( ) ; this . cy . nodes ( ) . forEach ( function ( ele ) { if ( ele . hasClass ( 'invalidGeneHighlight' ) || ele . hasClass ( 'invalidGene' ) ) nodesToRemoveInvalidHighlight = nodesToRemoveInvalidHighlight . union ( ele ) ; } ) ; actions . push ( { name : "removeHighlightInvalidGenes" , param : nodesToRemoveInvalidHighlight } ) ; } } doHighlightInvalidGenes ( args ) { args . each ( function ( n ) { if ( n . hasClass ( 'highlightedNode' ) ) { n . removeClass ( 'highlightedNode' ) ; n . addClass ( "invalidGeneHighlight" ) ; } else n . addClass ( "invalidGene" ) ; } ) ; return args ; } ; undoHighlightInvalidGenes ( args ) { args . each ( function ( n ) { if ( n . hasClass ( 'invalidGeneHighlight' ) ) { n . removeClass ( 'invalidGeneHighlight' ) ; n . addClass ( "highlightedNode" ) ; } else n . removeClass ( "invalidGene" ) ; } ) ; return args ; } highlightSelected ( ) { var sel = this . cy . elements ( ":selected" ) ; sel . unselect ( ) ; var elementsToHighlight = this . cy . collection ( ) ; sel . forEach ( function ( ele ) { if ( ! ele . hasClass ( 'invalidGeneHighlight' ) && ! ele . hasClass ( 'highlightedNode' ) && ! ele . hasClass ( 'highlightedEdge' ) ) elementsToHighlight = elementsToHighlight . union ( ele ) ; } ) ; if ( this . isCollaborative ) this . shareDBManager . changeHighlight ( elementsToHighlight , true ) ; else this . undoRedoManager . do ( 'highlightOthers' , elementsToHighlight ) ; } ; highlightNeighbors ( ) { var sel = this . cy . elements ( ":selected" ) ; var neighbors = sel . neighborhood ( ) ; neighbors = neighbors . union ( sel ) ; neighbors . unselect ( ) ; var elementsToHighlight = this . cy . collection ( ) ; neighbors . forEach ( function ( ele ) { if ( ! ele . hasClass ( 'invalidGeneHighlight' ) && ! ele . hasClass ( 'highlightedNode' ) && ! ele . hasClass ( 'highlightedEdge' ) ) elementsToHighlight = elementsToHighlight . union ( ele ) ; } ) ; if ( this . isCollaborative ) this . shareDBManager . changeHighlight ( elementsToHighlight , true ) ; else this . undoRedoManager . do ( 'highlightOthers' , elementsToHighlight ) ; } ; highlightBySearch ( args ) { if ( this . isCollaborative ) this . shareDBManager . changeHighlight ( args , true ) ; else this . undoRedoManager . do ( 'highlightOthers' , args ) ; } ; removeOtherHighlight ( actions ) { var nodesToRemoveHighlight = this . cy . collection ( ) ; this . cy . elements ( ) . forEach ( function ( ele ) { if ( ele . hasClass ( 'highlightedNode' ) || ele . hasClass ( 'highlightedEdge' ) || ele . hasClass ( 'invalidGeneHighlight' ) ) nodesToRemoveHighlight = nodesToRemoveHighlight . add ( ele ) ; } ) ; if ( this . isCollaborative ) this . shareDBManager . changeHighlight ( nodesToRemoveHighlight , false ) ; else actions . push ( { name : "removeOtherHighlight" , param : nodesToRemoveHighlight } ) ; } ; doHighlight ( args ) { args . each ( function ( n ) { if ( n . isEdge ( ) ) n . addClass ( "highlightedEdge" ) ; else { if ( n . hasClass ( 'invalidGene' ) ) { n . removeClass ( "invalidGene" ) ; n . addClass ( "invalidGeneHighlight" ) ; } else n . addClass ( "highlightedNode" ) ; } } ) ; return args ; } ; undoHighlight ( args ) { args . each ( function ( n ) { if ( n . isEdge ( ) ) n . removeClass ( "highlightedEdge" ) ; else { if ( n . hasClass ( 'invalidGeneHighlight' ) ) { n . removeClass ( "invalidGeneHighlight" ) ; n . addClass ( "invalidGene" ) ; } else n . removeClass ( "highlightedNode" ) ; } } ) ; return args ; } ; removeAllHighlight ( ) { let actions = [ ] ; this . removeInvalidGeneHighlights ( actions ) ; this . removeOtherHighlight ( actions ) ; this . cy . undoRedo ( ) . do ( "batch" , actions ) ; } ; postLayout ( ) { if ( this . isCollaborative ) { var movedNodes = this . cy . collection ( ) ; var parentNodes = this . cy . collection ( ) ; this . cy . nodes ( ) . forEach ( function ( node ) { if ( ! node . isParent ( ) ) movedNodes = movedNodes . add ( node ) ; else parentNodes = parentNodes . add ( node ) ; } ) ; this . moveElements ( movedNodes ) ; this . moveElements ( parentNodes ) ; var newState = { zoomLevel : this . cy . zoom ( ) , panLevel : this . cy . pan ( ) } ; this . updateGlobalOptions ( newState ) ; } } ; getEmptyGroupID ( ) { if ( this . isCollaborative ) return this . shareDBManager . getEmptyGroupID ( ) ; else return this . genomicDataOverlayManager . getEmptyGroupID ( ) ; } ; groupGenomicData ( cancerNames , groupID ) { return this . shareDBManager . groupGenomicData ( cancerNames , groupID ) ; } ; addPubmedIDs ( edge , pubmedIDs ) { if ( this . isCollaborative ) { this . shareDBManager . addPubmedIDs ( edge . id ( ) , pubmedIDs ) ; } else { var pubmedArray = edge . data ( 'pubmedIDs' ) ; var validPubmedIDs = _ . filter ( pubmedIDs , function ( id ) { return ! isNaN ( id ) ; } ) ; pubmedArray . push . apply ( pubmedArray , validPubmedIDs ) ; edge . data ( 'pubmedIDs' , _ . uniq ( pubmedArray ) ) ; } } removePubmedID ( edge , pubmedIDs ) { if ( this . isCollaborative ) { this . shareDBManager . removePubmedID ( edge . id ( ) , pubmedIDs ) ; } else { var pubmedArray = edge . data ( 'pubmedIDs' ) ; edge . data ( 'pubmedIDs' , _ . difference ( pubmedArray , pubmedIDs ) ) ; } } updateEdgeAnchorPoints ( edge ) { if ( this . isCollaborative ) { var edgeCurveStyle = edge . css ( 'curve-style' ) ; var numberOfAnchorPoints = 0 ; var anchors = this . edgeEditing ?. getAnchorsAsArray ( edge ) ; if ( anchors !== undefined ) numberOfAnchorPoints = anchors . length / 2 ; var anchorPointsArray = [ ] ; for ( var j = 0 ; j < numberOfAnchorPoints ; j ++ ) { anchorPointsArray . push ( { x : anchors [ 2 * j ] , y : anchors [ 2 * j + 1 ] } ) ; } this . shareDBManager . updateEdgeAnchorPoints ( edge . id ( ) , anchorPointsArray , edgeCurveStyle ) ; } } pushSelectedNodeStack ( ele ) { this . selectedNodeStack [ ele . id ( ) ] = ele ; } removeElementFromSelectedNodeStack ( ele ) { var nodeID = ele . id ( ) ; if ( nodeID in this . selectedNodeStack ) delete this . selectedNodeStack [ ele . id ( ) ] ; } clearSelectedNodeStack ( ) { this . selectedNodeStack = { } ; } exportSVG ( ) { return this . svgExporter . exportGraph ( this . cy . nodes ( ) , this . cy . edges ( ) ) ; } registerObserver ( observer ) { this . observers . push ( observer ) ; } ; notifyObservers ( ) { for ( var i in this . observers ) { var observer = this . observers [ i ] ; observer . notify ( ) ; } } ; registerGenomicDataObserver ( observer ) { this . genomicDataOverlayManager . registerObserver ( observer ) ; } updateGenomicDataVisibility ( dataMap ) { if ( this . isCollaborative ) { this . shareDBManager . addGenomicVisibilityData ( dataMap ) ; } else { for ( var _key in dataMap ) { this . genomicDataOverlayManager . updateGenomicDataVisibility ( _key , dataMap [ _key ] ) ; } this . genomicDataOverlayManager . showGenomicData ( ) ; } } updateGenomicDataColorScheme ( colorValueMap ) { this . setGenomicDataOverlayColorScheme ( colorValueMap ) ; if ( this . isCollaborative ) { this . shareDBManager . updateGenomicDataOverlayColorScheme ( colorValueMap ) ; } else { this . genomicDataOverlayManager . updateColorScheme ( colorValueMap ) ; this . genomicDataOverlayManager . showGenomicData ( ) ; } } getGlobalOptions ( ) { return { zoomLevel : this . cy . zoom ( ) , panLevel : this . cy . pan ( ) } ; } changeGlobalOptions ( op ) { var globalOptions = op . li ; this . cy . zoom ( globalOptions . zoomLevel ) ; this . cy . pan ( globalOptions . panLevel ) ; } updateGlobalOptions ( newOptions ) { if ( this . isCollaborative ) this . shareDBManager . updateGlobalOptions ( newOptions ) ; } saveLayoutProperties ( newLayoutProps ) { if ( this . isCollaborative ) { this . shareDBManager . updateLayoutProperties ( newLayoutProps ) ; } else { this . layoutProperties = _ . clone ( newLayoutProps ) ; } } ; updateLayoutPropertiesCallback ( op ) { var newLayoutProps = op . li ; this . layoutProperties = _ . clone ( newLayoutProps ) ; LayoutProperties . layoutProperties = _ . clone ( this . layoutProperties ) ; this . notifyObservers ( ) ; } ; performLayout ( ) { this . undoRedoManager . do ( "layout" , { options : this . layoutProperties , eles : null , zoom : this . cy . zoom ( ) , pan : this . cy . pan ( ) } ) ; } ; addNode ( nodeData , posData ) { if ( this . isCollaborative ) { this . addNewNodeToShareDB ( nodeData , posData ) ; } else { this . addNodetoCy ( nodeData , posData ) ; } } ; addNodes ( nodes ) { for ( var i in nodes ) { this . addNode ( nodes [ i ] . data , nodes [ i ] . position ) ; } } ; addNodesCy ( nodes ) { var nodeArr = [ ] ; for ( var i in nodes ) { var nodeData = nodes [ i ] . data ; var posData = nodes [ i ] . position ; var newNode = { group : "nodes" , data : nodeData , position : { } } ; if ( nodeData . parent === undefined ) { delete newNode . data . parent ; } if ( posData ) { newNode . position = { x : posData . x , y : posData . y } ; } nodeArr [ i ] = newNode ; } this . cy . add ( nodeArr ) ; this . cy . nodes ( ) . updateCompoundBounds ( ) ; } ; addNodetoCy ( nodeData , posData ) { var newNode = { group : "nodes" , data : nodeData , position : { } } ; if ( nodeData . parent === undefined ) { delete newNode . data . parent ; } if ( posData ) { newNode . position = { x : posData . x , y : posData . y } ; } this . cy . nodes ( ) . updateCompoundBounds ( ) ; this . undoRedoManager . do ( "add" , newNode ) ; } ; shareDBNodeAddRemoveEventCallBack ( op ) { var isRemove = Object . keys ( op ) [ 1 ] === 'od' ; var node = op . oi || op . od ; if ( isRemove ) { var nodeID = op . p [ 1 ] ; var cyEle = this . cy . $ ( "#" + nodeID ) ; this . removeElementCy ( cyEle ) ; this . cy . nodes ( ) . updateCompoundBounds ( ) ; } else { this . addNewNodeLocally ( node ) ; } } ; addNewNodeLocally ( realtimeNode ) { var nodeData = { id : realtimeNode . id , type : realtimeNode . type , name : realtimeNode . name , parent : realtimeNode . parent , w : realtimeNode . w , h : realtimeNode . h } ; if ( realtimeNode . x != "undefined" && realtimeNode . y != "undefined" ) { this . addNodetoCy ( nodeData , { x : realtimeNode . x , y : realtimeNode . y } ) ; } else { this . addNodetoCy ( nodeData , null ) ; } this . cy . nodes ( ) . updateCompoundBounds ( ) ; } ; addNewNodeToShareDB ( nodeData , posData ) { this . shareDBManager . addNewNode ( nodeData , posData ) ; } ; addEdge ( edgeData ) { if ( this . isCollaborative ) { this . addNewEdgeShareDB ( edgeData ) ; } else { this . addNewEdgetoCy ( edgeData ) ; } } ; addEdges ( edges ) { for ( var i in edges ) { this . addEdge ( edges [ i ] . data ) ; } } ; addEdgesCy ( edges ) { const newEdges = [ ] ; for ( var i in edges ) { const newEdge = { group : "edges" , data : edges [ i ] . data } ; newEdges . push ( newEdge ) ; } this . cy . add ( newEdges ) ; } ; addNewEdgeShareDB ( edgeData ) { this . shareDBManager . addNewEdge ( edgeData ) ; } ; addNewEdgetoCy ( edgeData ) { var newEdge = { group : "edges" , data : edgeData } ; this . undoRedoManager . do ( "add" , newEdge ) ; } ; shareDBEdgeAddRemoveEventCallBack ( op ) { var isRemove = Object . keys ( op ) [ 1 ] === 'od' ; var edge = op . oi || op . od ; if ( isRemove ) { var edgeID = op . p [ 1 ] ; var cyEle = this . cy . $ ( "#" + edgeID ) ; this . removeElementCy ( cyEle ) ; } else { this . addNewEdgeLocally ( edge ) ; } } ; addNewElementsLocally ( realTimeNodeArray , realTimeEdgeArray ) { const nodeList = [ ] ; const nodeMap = { } ; for ( var i in realTimeNodeArray ) { var realTimeNode = realTimeNodeArray [ i ] ; var nodeID = realTimeNode . id ; var nodeWidth = ( realTimeNode . w == undefined ) ? 150 : realTimeNode . w ; var nodeHeight = ( realTimeNode . h == undefined ) ? 52 : realTimeNode . h ; var compoundMinWidth = ( realTimeNode . minWidth == undefined ) ? 0 : realTimeNode . minWidth ; var compoundMinWidthBiasLeft = ( realTimeNode . minWidthBiasLeft == undefined ) ? 0 : realTimeNode . minWidthBiasLeft ; var compoundMinWidthBiasRight = ( realTimeNode . minWidthBiasRight == undefined ) ? 0 : realTimeNode . minWidthBiasRight ; var compoundMinHeight = ( realTimeNode . minHeight == undefined ) ? 0 : realTimeNode . minHeight ; var compoundMinHeightBiasTop = ( realTimeNode . minHeightBiasTop == undefined ) ? 0 : realTimeNode . minHeightBiasTop ; var compoundMinHeightBiasBottom = ( realTimeNode . minHeightBiasBottom == undefined ) ? 0 : realTimeNode . minHeightBiasBottom ; const nodeData = { group : 'nodes' , position : { } , data : { id : nodeID , type : realTimeNode . type , name : realTimeNode . name , parent : realTimeNode . parent , w : nodeWidth , h : nodeHeight } , style : { 'min-width' : compoundMinWidth , 'min-width-bias-left' : compoundMinWidthBiasLeft , 'min-width-bias-right' : compoundMinWidthBiasRight , 'min-height' : compoundMinHeight , 'min-height-bias-top' : compoundMinHeightBiasTop , 'min-height-bias-bottom' : compoundMinHeightBiasBottom } } ; if ( nodeData . data . parent === undefined ) { delete nodeData . data . parent ; } if ( realTimeNode . x && realTimeNode . y ) { nodeData . position = { x : realTimeNode . x , y : realTimeNode . y } ; } nodeMap [ nodeID ] = nodeData ; nodeList . push ( nodeData ) ; } var edgeList = [ ] ; for ( var i in realTimeEdgeArray ) { var edge = realTimeEdgeArray [ i ] ; var edgeID = edge . id ; if ( ! ( edge . source in nodeMap && edge . target in nodeMap ) ) continue ; var tmpData = { id : edgeID , type : edge . type , source : edge . source , target : edge . target , pubmedIDs : edge . pubmedIDs , name : edge . name , } ; if ( edge . edgeCurveStyle == "unbundled-bezier" ) { tmpData [ 'controlPointPositions' ] = edge . anchorPoints ; } else { tmpData [ 'bendPointPositions' ] = edge . anchorPoints ; } var edgeData = { group : 'edges' , data : tmpData } ; edgeList . push ( edgeData ) ; } this . cy . add ( nodeList ) ; this . cy . add ( edgeList ) ; this . edgeEditing ?. initAnchorPoints ( this . cy . edges ( ) ) ; this . cy . nodes ( ) . updateCompoundBounds ( ) ; } addNewEdgeLocally ( edge ) { var edgeData = { id : edge . id , type : edge . type , source : edge . source , target : edge . target , pubmedIDs : edge . pubmedIDs , name : edge . name } ; if ( edge . edgeCurveStyle == "unbundled-bezier" ) { edgeData [ 'controlPointPositions' ] = edge . anchorPoints ; } else { edgeData [ 'bendPointPositions' ] = edge . anchorPoints ; } this . addNewEdgetoCy ( edgeData ) ; this . edgeEditing ?. initAnchorPoints ( this . cy . getElementById ( edge . id ) ) ; } ; reconnectEdge ( sourceID , targetID , edgeData ) { if ( this . isCollaborative ) { var edge = this . cy . getElementById ( edgeData . id ) ; this . reconnectEdgeInShareDB ( sourceID , targetID , edgeData ) ; } else { var location = { source : sourceID , target : targetID } ; var edge = this . cy . getElementById ( edgeData . id ) ; edge . move ( location ) ; } return this . cy . getElementById ( edgeData . id ) ; } ; reconnectEdgeInShareDB ( sourceID , targetID , edgeData ) { this . shareDBManager . reconnectEdge ( sourceID , targetID , edgeData ) ; } ; removeElement ( ele ) { if ( this . isCollaborative ) { this . removeElementsFromShareDB ( ele ) ; } else { this . removeElementsCy ( ele ) ; } } ; removeElementCy ( ele ) { this . undoRedoManager . do ( "remove" , ele ) ; } ; removeElementsCy ( ele ) { this . undoRedoManager . do ( "remove" , ele ) ; } ; removeElementsFromShareDB ( eles ) { var self = this ; eles . forEach ( function ( ele ) { self . shareDBManager . removeElement ( ele . id ( ) ) ; } ) ; } ; removeElementFromShareDB ( ele ) { this . shareDBManager . removeElement ( ele . id ( ) ) ; } ; changeParents ( eles , newParentId ) { if ( this . isCollaborative ) { this . changeParentShareDB ( eles , newParentId ) ; } else { var parentData = newParentId ? newParentId : null ; const dim = [ ] ; const id = [ ] ; eles . forEach ( function ( ele ) { var parameters = { id : ele . id ( ) , width : ele . data ( "w" ) , height : ele . data ( "h" ) } ; dim . push ( parameters ) ; id . push ( ele . id ( ) ) ; } ) ; const parentElem = this . cy . getElementById ( parentData ) ; var param = { firstTime : true , parentData : parentData , nodes : eles , posDiffX : ( ! parentData ) ? 0 : parentElem . position ( 'x' ) - eles [ 0 ] . position ( 'x' ) , posDiffY : ( ! parentData ) ? 0 : parentElem . position ( 'y' ) - eles [ 0 ] . position ( 'y' ) } ; this . undoRedoManager . do ( 'changeParent' , param ) ; var collection = this . cy . collection ( ) ; for ( var i in id ) { var elementById = this . cy . getElementById ( id [ i ] ) ; collection = collection . add ( elementById ) ; } collection . forEach ( function ( ele , i ) { if ( ele . id ( ) == dim [ i ] . id ) ele . data ( "w" , dim [ i ] . width ) ; ele . data ( "h" , dim [ i ] . height ) ; } ) ; } } ; changeParentShareDB ( eles , newParentId ) { var classRef = this ; function getTopLevelParents ( eles ) { var tpMostNodes = classRef . cy . collection ( ) ; const parentMap = { } ; eles . forEach ( function ( node ) { if ( node . isParent ( ) ) parentMap [ node . id ( ) ] = node ; } ) ; eles . forEach ( function ( node ) { var nodeParent = node . parent ( ) ; if ( parentMap [ nodeParent . id ( ) ] === undefined ) tpMostNodes = tpMostNodes . union ( node ) ; } ) ; return tpMostNodes ; } class NodeObj { public nodeRef : any ; public children : any ; constructor ( nodeObj ) { this . nodeRef = nodeObj ; this . children = [ ] ; } } var connectedEdges = eles . connectedEdges ( ) ; function traverseNodes ( eles , rootNodeObj ) { eles . forEach ( function ( ele ) { connectedEdges = connectedEdges . union ( ele . connectedEdges ( ) ) ; if ( ele . isParent ( ) ) { rootNodeObj . children . push ( new NodeObj ( ele ) ) ; var lengthOfChildrenArray = rootNodeObj . children . length ; traverseNodes ( ele . children ( ) , rootNodeObj . children [ lengthOfChildrenArray - 1 ] ) ; } else { rootNodeObj . children . push ( new NodeObj ( ele ) ) ; } } ) ; } var topMostNodes = getTopLevelParents ( eles ) ; var rootNodeR = new NodeObj ( null ) ; traverseNodes ( topMostNodes , rootNodeR ) ; this . shareDBManager . changeParent ( rootNodeR , newParentId , connectedEdges ) ; } ; changeParentCy ( eles , newParentId ) { let lockedNodes = { } ; const self = this ; function removeNodes ( nodes ) { let removedEles = nodes . connectedEdges ( ) . remove ( ) ; const children = nodes . children ( ) ; if ( children != null && children . length > 0 ) { children . forEach ( function ( childNode ) { lockedNodes [ childNode . id ( ) ] = true ; } ) ; removedEles = removedEles . union ( removeNodes ( children ) ) ; } removedEles = removedEles . union ( nodes . remove ( ) ) ; self . cy . nodes ( ) . updateCompoundBounds ( ) ; return removedEles ; } var removedEles = removeNodes ( eles ) ; this . undoRedoManager . do ( "remove" , removedEles ) ; for ( var i = 0 ; i < removedEles . length ; i ++ ) { var removedNode = removedEles [ i ] ; if ( removedNode . isEdge ( ) || lockedNodes [ removedNode . id ( ) ] ) { continue ; } removedNode . _private . data . parent = newParentId ; if ( removedNode . _private . parent ) { delete removedNode . _private . parent ; } } self . cy . add ( removedEles ) ; this . undoRedoManager . do ( "add" , removedEles ) ; self . cy . nodes ( ) . updateCompoundBounds ( ) ; } ; moveElements ( eles ) { var classRef = this ; if ( this . isCollaborative ) { eles . forEach ( function ( ele ) { classRef . shareDBManager . moveElement ( ele ) ; } ) ; } } ; resizeElements ( ele ) { if ( this . isCollaborative ) { if ( ! ele . isParent ( ) ) { var previousWidth = ele . width ( ) ; var previousHeight = ele . height ( ) ; this . shareDBManager . resizeElement ( ele , previousWidth , previousHeight ) ; } else { var minWidth = ele . style ( 'min-width' ) ; var minWidthBiasLeft = ele . style ( 'min-width-bias-left' ) ; var minWidthBiasRight = ele . style ( 'min-width-bias-right' ) ; var minHeight = ele . style ( 'min-height' ) ; var minHeightBiasTop = ele . style ( 'min-height-bias-top' ) ; var minHeightBiasBottom = ele . style ( 'min-height-bias-bottom' ) ; this . shareDBManager . resizeCompound ( ele , minWidth , minWidthBiasLeft , minWidthBiasRight , minHeight , minHeightBiasTop , minHeightBiasBottom ) ; } } } ; mergeGraph ( nodes , edges ) { if ( this . isCollaborative ) { this . shareDBManager . mergeGraph ( nodes , edges ) ; } else { this . mergeGraphCy ( nodes , edges ) ; } this . fitGraph ( ) ; } ; mergeGraphCy ( nodes , edges ) { const nodesToBeAdded = [ ] ; const edgesToBeAdded = [ ] ; const nodeMap = { } ; for ( var index in nodes ) { var ele = nodes [ index ] ; nodeMap [ ele . data . id ] = ele ; if ( this . cy . filter ( 'node[name = "' + ele . data . name + '"]' ) . length <= 0 ) { nodesToBeAdded . push ( ele ) ; } } this . cy . add ( nodesToBeAdded ) ; for ( var index in edges ) { var ele = edges [ index ] ; var sourceNode = nodeMap [ ele . data . source ] ; var targetNode = nodeMap [ ele . data . target ] ; var cySourceNode = this . cy . nodes ( '[name="' + sourceNode . data . name + '"]' ) ; var targetNode = this . cy . nodes ( '[name="' + targetNode . data . name + '"]' ) ; if ( cySourceNode . length > 0 ) { ele . data . source = cySourceNode . id ( ) ; } if ( targetNode . length > 0 ) { ele . data . target = targetNode . id ( ) ; } if ( targetNode . length < 0 && cySourceNode . length < 0 ) { continue ; } var edgesBtw = this . cy . filter ( 'edge[source = "' + cySourceNode . id ( ) + '"][target = "' + targetNode . id ( ) + '"]' ) ; var isFound = false ; edgesBtw . forEach ( function ( edge ) { if ( edge . data ( ) . type == ele . data . type ) { isFound = true ; return false ; } return true ; } ) ; if ( ! isFound ) { delete ele . data . id ; edgesToBeAdded . push ( ele ) ; } } this . cy . add ( edgesToBeAdded ) ; } ; fitGraph ( ) { if ( this . isCollaborative ) { this . cy . fit ( this . FIT_CONSTANT ) ; var newState = { zoomLevel : this . cy . zoom ( ) , panLevel : this . cy . pan ( ) } ; this . updateGlobalOptions ( newState ) ; } else { this . cy . fit ( this . FIT_CONSTANT ) ; } } loadFile ( nodes , edges ) { if ( this . isCollaborative ) { this . loadfileShareDB ( nodes , edges ) ; } else { this . loadFileCy ( nodes , edges ) ; } this . edgeEditing ?. initAnchorPoints ( this . cy . edges ( ) ) ; this . fitGraph ( ) ; } ; loadFileCy ( nodes , edges ) { this . removeElementCy ( this . cy . elements ( ) ) ; this . addNodesCy ( nodes ) ; this . addEdgesCy ( edges ) ; } ; loadfileShareDB ( nodes , edges ) { this . shareDBManager . loadGraph ( nodes , edges ) ; } ; removeAllElements ( ) { if ( this . isCollaborative ) { this . shareDBManager . removeAllElements ( ) ; } else { this . cy . remove ( this . cy . elements ( ) ) ; } } ; updateHighlight ( ele , isHighlighted ) { if ( isHighlighted ) this . undoRedoManager . do ( 'highlightOthers' , ele ) ; else this . undoRedoManager . do ( 'removeOtherHighlight' , ele ) ; } ; @ autobind updateVisibility ( ele , isHidden ) { if ( isHidden ) this . viewUtilities . hide ( ele ) ; else this . viewUtilities . show ( ele ) ; } ; updateElementCallback ( op ) { var ele = op . oi ; var eleID = ele . id ; var cyEle = this . cy . $ ( "#" + eleID ) ; this . changeNameCy ( cyEle , ele . name ) ; if ( cyEle . isNode ( ) ) { if ( cyEle . isParent ( ) ) { cyEle . style ( "min-width" , ele . minWidth ) ; cyEle . style ( "min-width-bias-left" , ele . minWidthBiasLeft ) ; cyEle . style ( "min-width-bias-right" , ele . minWidthBiasRight ) ; cyEle . style ( "min-height" , ele . minHeight ) ; cyEle . style ( "min-height-bias-top" , ele . minHeightBiasTop ) ; cyEle . style ( "min-height-bias-bottom" , ele . minHeightBiasBottom ) ; } else { cyEle . data ( 'w' , ele . w ) ; cyEle . data ( 'h' , ele . h ) ; cyEle . position ( { x : ele . x , y : ele . y } ) ; } this . updateVisibility ( cyEle , ele . isHidden ) ; this . updateHighlight ( cyEle , ele . isHighlighted ) ; if ( ele . isInvalidGene ) { this . doHighlightInvalidGenes ( cyEle ) ; } else { this . undoHighlightInvalidGenes ( cyEle ) ; } } else if ( cyEle . isEdge ( ) ) { var pubmedArray = ele . pubmedIDs ; cyEle . data ( 'pubmedIDs' , pubmedArray ) ; this . updateHighlight ( cyEle , ele . isHighlighted ) ; var anchorPoints = ele . anchorPoints ; if ( ele . source !== cyEle . source ( ) . id ( ) || ele . target !== cyEle . target ( ) . id ( ) ) { var location = { source : ele . source , target : ele . target } ; cyEle . move ( location ) ; this . edgeEditing ?. initAnchorPoints ( cyEle ) ; } else { if ( ele . edgeCurveStyle === "bezier" ) { const anchors = this . edgeEditing ?. getAnchorsAsArray ( cyEle ) ; if ( anchors && anchors . length > 0 ) { for ( let i = 0 ; i < anchors . length / 2 ; i ++ ) { this . edgeEditing ?. deleteSelectedAnchor ( cyEle , 0 ) ; } } } else if ( ele . edgeCurveStyle === "unbundled-bezier" ) { cyEle . data ( 'controlPointPositions' , anchorPoints ) ; } else { cyEle . data ( 'bendPointPositions' , anchorPoints ) ; } this . edgeEditing ?. initAnchorPoints ( cyEle ) ; } } } ; getGenomicDataSVG ( node ) { return this . genomicDataOverlayManager . generateSVGForNode ( node ) ; } getOncoprintDataSVG ( node ) { return this . genomicDataOverlayManager . generateOncoprintForPatientNode ( node ) ; } removeGenomicData ( ) { if ( this . isCollaborative ) { this . shareDBManager . clearGenomicData ( ) ; } else { this . genomicDataOverlayManager . clearAllGenomicData ( ) ; this . genomicDataOverlayManager . hideGenomicData ( ) ; this . genomicDataOverlayManager . notifyObservers ( ) ; } } addGenomicData ( genomicData ) { const groupID = this . getEmptyGroupID ( ) ; if ( this . isCollaborative ) { var parsedGenomicData = this . genomicDataOverlayManager . prepareGenomicDataShareDB ( genomicData ) ; this . shareDBManager . addGenomicData ( parsedGenomicData . genomicDataMap ) ; this . shareDBManager . groupGenomicData ( Object . keys ( parsedGenomicData . visibilityMap ) , groupID ) ; let currentVisibleGenomicDataCount = this . genomicDataOverlayManager . countVisibleGenomicDataByType ( ) ; Object . keys ( parsedGenomicData . visibilityMap ) . forEach ( study => { if ( parsedGenomicData . visibilityMap [ study ] && ( currentVisibleGenomicDataCount >= 6 ) ) { parsedGenomicData . visibilityMap [ study ] = false ; } else if ( parsedGenomicData . visibilityMap [ study ] ) { currentVisibleGenomicDataCount ++ ; } } ) ; this . shareDBManager . addGenomicVisibilityData ( parsedGenomicData . visibilityMap ) ; } else { this . genomicDataOverlayManager . addGenomicDataLocally ( genomicData , groupID ) ; } } adjustVisibilityShareDB ( profileId , isEnabled ) { const targetProfileIndex = this . profiles . map ( profile => profile . profileId ) . indexOf ( profileId ) ; this . setProfile ( targetProfileIndex , { ... this . profiles [ targetProfileIndex ] , enabled : isEnabled } ) ; } addToProfiles ( profileId ) { if ( this . profiles . map ( profile => profile . profileId ) . includes ( profileId ) ) { return ; } this . addProfile ( { profileId : profileId , enabled : true } ) ; } addPortalGenomicData ( genomicData , groupID ) { if ( this . isCollaborative ) { var parsedGenomicData = this . genomicDataOverlayManager . preparePortalGenomicDataShareDB ( genomicData ) ; this . shareDBManager . addGenomicData ( parsedGenomicData . genomicDataMap ) ; this . shareDBManager . groupGenomicData ( Object . keys ( parsedGenomicData . visibilityMap ) , groupID ) ; this . shareDBManager . addGenomicVisibilityData ( parsedGenomicData . visibilityMap ) ; } else { this . genomicDataOverlayManager . addPortalGenomicData ( genomicData , groupID ) ; } } shareDBGenomicDataHandler ( op ) { var isRemove = Object . keys ( op ) [ 1 ] === 'od' ; var newData = op . oi ; var geneSymbol = op . p [ 1 ] ; if ( ! isRemove ) { this . genomicDataOverlayManager . addGenomicDataWithGeneSymbol ( geneSymbol , newData ) ; } else { this . genomicDataOverlayManager . removeGenomicDataWithGeneSymbol ( geneSymbol ) ; } } shareDBGenomicDataGroupChangeHandler ( op ) { var isRemove = Object . keys ( op ) [ 1 ] === 'od' ; var data = op . oi ; var key = op . p [ 1 ] ; if ( ! isRemove ) { this . genomicDataOverlayManager . addGenomicGroupData ( key , data ) ; if ( data . length !== 1 ) { console . log ( "Grouped genomic data expected to be of length 1" ) ; } data . forEach ( ( profileId ) => { this . addToProfiles ( profileId ) ; } ) ; } else if ( ! data ) { this . genomicDataOverlayManager . clearAllGenomicData ( ) ; } this . genomicDataOverlayManager . showGenomicData ( ( node ) => { this . resizeElements ( node ) ; } ) ; this . genomicDataOverlayManager . notifyObservers ( ) ; } shareDBGenomicDataVisibilityHandler ( op ) { var data = op . oi ; var key = op . p [ 1 ] ; var isRemove = Object . keys ( op ) [ 1 ] === 'od' ; if ( ! isRemove ) { this . genomicDataOverlayManager . addGenomicVisData ( key , data ) ; this . adjustVisibilityShareDB ( key , data ) ; } else { this . genomicDataOverlayManager . removeGenomicVisData ( ) ; this . removeProfiles ( ) ; } this . genomicDataOverlayManager . showGenomicData ( ( node ) => { this . resizeElements ( node ) ; } ) ; this . genomicDataOverlayManager . notifyObservers ( ) ; } updateGenomicDataColorSchemeHandler ( op ) { let colorScheme = op . li ; this . setGenomicDataOverlayColorScheme ( colorScheme ) ; this . colorSchemeChangeCallback ( colorScheme ) ; this . genomicDataOverlayManager . updateColorScheme ( colorScheme ) ; this . genomicDataOverlayManager . showGenomicData ( ( node ) => { this . resizeElements ( node ) ; } ) ; this . genomicDataOverlayManager . notifyObservers ( ) ; } resizeNodesToContent ( nodes ) { if ( this . isCollaborative ) { const visibleNumberOfData = this . genomicDataOverlayManager . countVisibleGenomicDataByType ( ) ; const labelWithData = 148 + ( visibleNumberOfData - 3 ) * 36 ; const rt = this . shareDBManager ; nodes . forEach ( function ( ele ) { if ( ! ele . isParent ( ) ) { var newWidth = 150 ; var newHeight = 52 ; if ( ele . data ( 'name' ) != "" ) { var labelLength = ele . style ( 'label' ) . length * 10 + 6 ; newWidth = labelLength ; newHeight = 24 ; } if ( ele . data ( 'type' ) !== "PROCESS" && visibleNumberOfData > 0 ) { newHeight = 52 ; if ( visibleNumberOfData < 4 ) { if ( 150 > newWidth ) newWidth = 150 ; } else { if ( labelWithData > newWidth ) newWidth = labelWithData ; } } rt . setSizeOfElement ( ele , newWidth , newHeight ) ; } else { rt . resizeCompound ( ele , 0 , 0 , 0 , 0 , 0 , 0 ) ; } } ) ; } else { const ur = this . cy . undoRedo ( ) ; const actions = [ ] ; const visibleNumberOfData = this . genomicDataOverlayManager . countVisibleGenomicDataByType ( ) ; const labelWithData = 150 + ( visibleNumberOfData - 3 ) * 36 ; nodes . forEach ( function ( ele ) { if ( ! ele . isParent ( ) ) { let newWidth = 150 ; let newHeight = 52 ; if ( ele . data ( 'name' ) != "" ) { var labelLength = ele . style ( 'label' ) . length * 6 + 24 ; newWidth = labelLength ; newHeight = 24 ; } if ( ele . data ( 'type' ) !== "PROCESS" && visibleNumberOfData > 0 ) { newHeight = 52 ; if ( visibleNumberOfData < 4 ) { if ( 150 > newWidth ) newWidth = 150 ; } else { if ( labelWithData > newWidth ) newWidth = labelWithData ; } } const args = { ele : ele , oldWidth : ele . width ( ) , newWidth : newWidth , oldHeight : ele . height ( ) , newHeight : newHeight } ; actions . push ( { name : "changeNodeSize" , param : args } ) ; } else { const args = { ele : ele , oldMinWidth : ele . style ( "min-width" ) , newMinWidth : 0 , oldMinWidthBiasLeft : ele . style ( "min-width-bias-left" ) , newMinWidthBiasLeft : 0 , oldMinWidthBiasRight : ele . style ( "min-width-bias-right" ) , newMinWidthBiasRight : 0 , oldMinHeight : ele . style ( "min-height" ) , newMinHeight : 0 , oldMinHeightBiasTop : ele . style ( "min-height-bias-top" ) , newMinHeightBiasTop : 0 , oldMinHeightBiasBottom : ele . style ( "min-height-bias-bottom" ) , newMinHeightBiasBottom : 0 } ; actions . push ( { name : "changeCompoundSize" , param : args } ) ; } } ) ; ur . do ( "batch" , actions ) ; } this . cy . nodeEditing ( 'get' ) . refreshGrapples ( ) ; } ; }