UNPKG

cytoscape-tidytree

Version:

Cytoscape.js layout extension for positioning trees

3 lines (2 loc) 5.24 kB
"use strict";(()=>{var l=class a{lowY;index;nxt;constructor(e,t,n){this.lowY=e,this.index=t,this.nxt=n}static updateIYL(e,t,n){for(;n!=null&&e>=n.lowY;)n=n.nxt;return new a(e,t,n)}},h=class{isExtra;w;h;x;y;c;prelim=0;mod=0;shift=0;change=0;tl;tr;el;er;msel;mser;constructor(e,t,n,o,i=!1){this.w=e,this.h=t,this.y=n,this.c=o,this.isExtra=i}layout(){this.firstWalk(),this.secondWalk(0)}firstWalk(){if(this.c.length==0){this.setExtremes();return}this.c[0].firstWalk();let e=l.updateIYL(this.c[0].el.bottom(),0,void 0);for(let t=1;t<this.c.length;t++){this.c[t].firstWalk();let n=this.c[t].er.bottom();this.separate(t,e),e=l.updateIYL(n,t,e)}this.positionRoot(),this.setExtremes()}setExtremes(){this.c.length==0?(this.el=this,this.er=this,this.msel=this.mser=0):(this.el=this.c[0].el,this.msel=this.c[0].msel,this.er=this.c[this.c.length-1].er,this.mser=this.c[this.c.length-1].mser)}separate(e,t){let n=this.c[e-1],o=n.mod,i=this.c[e],d=i.mod,u=!0;for(;n!==void 0&&i!==void 0;){n.bottom()>t.lowY&&(t=t.nxt);let s=o+n.prelim+n.w-(d+i.prelim);(s>0||u&&s<=0)&&(d+=s,this.moveSubtree(e,t.index,s)),u=!1;let r=n.bottom(),c=i.bottom();r<=c&&(n=n.nextRightContour(),n!==void 0&&(o+=n.mod)),r>=c&&(i=i.nextLeftContour(),i!==void 0&&(d+=i.mod))}n==null&&i!=null?this.setLeftThread(e,i,d):n!=null&&i==null&&this.setRightThread(e,n,o)}moveSubtree(e,t,n){this.c[e].mod+=n,this.c[e].msel+=n,this.c[e].mser+=n,this.distributeExtra(e,t,n)}nextLeftContour(){return this.c.length==0?this.tl:this.c[0]}nextRightContour(){return this.c.length==0?this.tr:this.c[this.c.length-1]}bottom(){return this.y+this.h}setLeftThread(e,t,n){let o=this.c[0].el;o.tl=t;let i=n-t.mod-this.c[0].msel;o.mod+=i,o.prelim-=i,this.c[0].el=this.c[e].el,this.c[0].msel=this.c[e].msel}setRightThread(e,t,n){let o=this.c[e].er;o.tr=t;let i=n-t.mod-this.c[e].mser;o.mod+=i,o.prelim-=i,this.c[e].er=this.c[e-1].er,this.c[e].mser=this.c[e-1].mser}positionRoot(){this.prelim=(this.c[0].prelim+this.c[0].mod+this.c[this.c.length-1].mod+this.c[this.c.length-1].prelim+this.c[this.c.length-1].w)/2-this.w/2}secondWalk(e){e+=this.mod,this.x=this.prelim+e,this.addChildSpacing();for(let t of this.c)t.secondWalk(e)}distributeExtra(e,t,n){if(t!=e-1){let o=e-t;this.c[t+1].shift+=n/o,this.c[e].shift-=n/o,this.c[e].change-=n-n/o}}addChildSpacing(){let e=0,t=0;for(let n of this.c)e+=n.shift,t+=e+n.change,n.mod+=t}};var m=class{options;constructor(e){this.options={horizontalSpacing:10,verticalSpacing:20,lineWidth:3,layerHeight:void 0,...e}}run(e){let t=this.makeTree(e,e.customY);return t.layout(),this.setLayoutResult(e,t),t}makeTree(e,t=0){let n=e.w+this.options.horizontalSpacing,o=e.h+this.options.verticalSpacing,i=e.extraVerticalSpacing??0,d=this.options.layerHeight;d!==void 0&&(o=Math.ceil(o/d)*d,i=Math.round(i/d)*d),e.customY!==void 0&&(i=e.customY-t,e.y=t+i),e.y=t+i;let u=new h(n,o,e.y,e.children.map(s=>this.makeTree(s,e.y+o)));return i<0&&console.warn("Node has negative extra space, ignoring",e),i>0?new h(this.options.lineWidth,i,t,[u],!0):u}setLayoutResult(e,t){t.isExtra&&(t=t.c[0]),e.x=t.x+this.options.horizontalSpacing/2,e.children.forEach((n,o)=>this.setLayoutResult(n,t.c[o]))}};var p=class{name="tidytree";dataOnly=!1;horizontalSpacing=20;verticalSpacing=40;direction="TB";extraVerticalSpacings={};customYs={};lineWidth=5;layerHeight=void 0;edgeComparator=void 0;sizeGetter=()=>({});fit=!0;padding=30;pan=void 0;zoom=void 0;spacingFactor=1;transform=(e,t)=>t;animate=!1;animationDuration=500;animationEasing=void 0;animateFilter=()=>!0;ready=void 0;stop=void 0;nodeDimensionsIncludeLabels=!0};function f(a){this.options={...new p,...a}}f.prototype.createTreeData=function(){let a=this.options.nodeDimensionsIncludeLabels??!0,e=this.options.eles,t=this.options.customYs,n=this.options.extraVerticalSpacings,o=new Set;for(let s of e.nodes()){let r={...s.layoutDimensions({nodeDimensionsIncludeLabels:a}),...this.options.sizeGetter(s)};(this.options.direction==="LR"||this.options.direction==="RL")&&([r.w,r.h]=[r.h,r.w]);let c={id:s.id(),w:r.w,h:r.h,children:[],extraVerticalSpacing:n[s.id()],customY:t[s.id()]===void 0?void 0:t[s.id()]-r.h/2};s.scratch("tidytree",c),o.add(c)}let i=this.options.edgeComparator,d=i===void 0?e.edges():e.edges().sort(i);for(let s of d){let r=s.source().scratch("tidytree"),c=s.target().scratch("tidytree");o.has(c)&&(r.children.push(c),o.delete(c))}if(o.size===0){let s=e.nodes().first(),r=s.scratch("tidytree");o.add(r);for(let c of s.incomers("node")){let y=c.scratch("tidytree"),g=y.children.indexOf(r);g!==-1&&y.children.splice(g,1)}}return{w:0,h:0,children:Array.from(o),customY:Math.min(-this.options.verticalSpacing,-(this.options.layerHeight??0))}};f.prototype.run=function(){let a=this.createTreeData(),e=new m(this.options).run(a),t=this.options.eles.nodes();return this.options.dataOnly||t.layoutPositions(this,this.options,n=>{let o=n.scratch("tidytree"),i={x:o.x+o.w/2,y:o.y+o.h/2};return(this.options.direction==="LR"||this.options.direction==="RL")&&([i.x,i.y]=[i.y,i.x]),this.options.direction==="BT"&&(i.y=-i.y),this.options.direction==="RL"&&(i.x=-i.x),i}),{treeData:a,tree:e}};function b(a){a("layout","tidytree",f)}typeof window.cytoscape<"u"&&b(window.cytoscape);})(); //# sourceMappingURL=cytoscape-tidytree.min.js.map