|
import * as util from '../util'; |
|
import * as is from '../is'; |
|
import Set from '../set'; |
|
|
|
|
|
let Element = function( cy, params, restore = true ){ |
|
if( cy === undefined || params === undefined || !is.core( cy ) ){ |
|
util.error( 'An element must have a core reference and parameters set' ); |
|
return; |
|
} |
|
|
|
let group = params.group; |
|
|
|
|
|
if( group == null ){ |
|
if( params.data && params.data.source != null && params.data.target != null ){ |
|
group = 'edges'; |
|
} else { |
|
group = 'nodes'; |
|
} |
|
} |
|
|
|
|
|
if( group !== 'nodes' && group !== 'edges' ){ |
|
util.error( 'An element must be of type `nodes` or `edges`; you specified `' + group + '`' ); |
|
return; |
|
} |
|
|
|
|
|
this.length = 1; |
|
this[0] = this; |
|
|
|
|
|
let _p = this._private = { |
|
cy: cy, |
|
single: true, |
|
data: params.data || {}, |
|
position: params.position || { x: 0, y: 0 }, |
|
autoWidth: undefined, |
|
autoHeight: undefined, |
|
autoPadding: undefined, |
|
compoundBoundsClean: false, |
|
listeners: [], |
|
group: group, |
|
style: {}, |
|
rstyle: {}, |
|
styleCxts: [], |
|
styleKeys: {}, |
|
removed: true, |
|
selected: params.selected ? true : false, |
|
selectable: params.selectable === undefined ? true : ( params.selectable ? true : false ), |
|
locked: params.locked ? true : false, |
|
grabbed: false, |
|
grabbable: params.grabbable === undefined ? true : ( params.grabbable ? true : false ), |
|
pannable: params.pannable === undefined ? (group === 'edges' ? true : false) : ( params.pannable ? true : false ), |
|
active: false, |
|
classes: new Set(), |
|
animation: { |
|
current: [], |
|
queue: [] |
|
}, |
|
rscratch: {}, |
|
scratch: params.scratch || {}, |
|
edges: [], |
|
children: [], |
|
parent: params.parent && params.parent.isNode() ? params.parent : null, |
|
traversalCache: {}, |
|
backgrounding: false, |
|
bbCache: null, |
|
bbCacheShift: { x: 0, y: 0 }, |
|
bodyBounds: null, |
|
overlayBounds: null, |
|
labelBounds: { |
|
all: null, |
|
source: null, |
|
target: null, |
|
main: null |
|
}, |
|
arrowBounds: { |
|
source: null, |
|
target: null, |
|
'mid-source': null, |
|
'mid-target': null |
|
} |
|
}; |
|
|
|
if( _p.position.x == null ){ _p.position.x = 0; } |
|
if( _p.position.y == null ){ _p.position.y = 0; } |
|
|
|
|
|
if( params.renderedPosition ){ |
|
let rpos = params.renderedPosition; |
|
let pan = cy.pan(); |
|
let zoom = cy.zoom(); |
|
|
|
_p.position = { |
|
x: (rpos.x - pan.x) / zoom, |
|
y: (rpos.y - pan.y) / zoom |
|
}; |
|
} |
|
|
|
let classes = []; |
|
if( is.array( params.classes ) ){ |
|
classes = params.classes; |
|
} else if( is.string( params.classes ) ){ |
|
classes = params.classes.split( /\s+/ ); |
|
} |
|
for( let i = 0, l = classes.length; i < l; i++ ){ |
|
let cls = classes[ i ]; |
|
if( !cls || cls === '' ){ continue; } |
|
|
|
_p.classes.add(cls); |
|
} |
|
|
|
this.createEmitter(); |
|
|
|
let bypass = params.style || params.css; |
|
if( bypass ){ |
|
util.warn('Setting a `style` bypass at element creation should be done only when absolutely necessary. Try to use the stylesheet instead.'); |
|
|
|
this.style(bypass); |
|
} |
|
|
|
if( restore === undefined || restore ){ |
|
this.restore(); |
|
} |
|
|
|
}; |
|
|
|
export default Element; |
|
|