import * as d3 from "d3"; import {LayoutScale} from "./scale"; function layoutDragLimits(d, dLayout, domain, constrainDrag: boolean){ //min x drag limit if(d.minDragLimit !== undefined){ dLayout.minDragLimit = d.minDragLimit; } if (constrainDrag) { if(dLayout.minDragLimit === undefined || dLayout.minDragLimit < domain[0]){ dLayout.minDragLimit = domain[0]; } } //max x drag limit if(d.maxDragLimit !== undefined) { dLayout.maxDragLimit = d.maxDragLimit; } if (constrainDrag) { if(dLayout.maxDragLimit === undefined || dLayout.maxDragLimit > domain[1]){ dLayout.maxDragLimit = domain[1]; } } } export function lineAnnotationLayoutCreator(constrainDrag: boolean = true) { // layout extender return function (dataModel, layoutScale: LayoutScale) { let xDomain, yDomain; if(dataModel.xValueMap){ xDomain = d3.extent(dataModel.dataArray, dataModel.xValueMap); layoutScale.extendDomainX(xDomain); } if(dataModel.yValueMap){ yDomain = d3.extent(dataModel.dataArray, dataModel.yValueMap); layoutScale.extendDomainY(yDomain); } // layouter return function(){ let x1: number, x2: number, y1: number, y2: number, dLayout: any, viewModel: any = { dataArray: [] }, xDomainExtent = layoutScale.xDomainExtent, yDomainExtent = layoutScale.yDomainExtent, xRangeExtent = layoutScale.xRangeExtent, yRangeExtent = layoutScale.yRangeExtent, hasSlope = false; for (let d of dataModel.dataArray) { dLayout = { key: d.key }; dLayout.isInterceptX = d.xintercept !== undefined; dLayout.hasDragX = d.drag === "x"; dLayout.isInterceptY = d.yintercept !== undefined; dLayout.hasDragY = d.drag === "y"; dLayout.hasDrag = (dLayout.hasDragX || dLayout.hasDragY); dLayout.hasSlope = (d.slope !== undefined && d.slope !== 0); if(dataModel.labelMap){ dLayout.label = dataModel.labelMap(d); viewModel.hasLabel = true; } if (d.x1 && d.x2 && d.y1 && d.y2) { x1 = d.x1; x2 = d.x2; y1 = d.y1; y2 = d.y2; } else if (dLayout.isInterceptX) { x1 = d.xintercept; x2 = d.xintercept; y1 = yDomainExtent[0]; y2 = yDomainExtent[1]; } else if (dLayout.isInterceptY) { x1 = xDomainExtent[0]; x2 = xDomainExtent[1]; y1 = d.yintercept; y2 = d.yintercept; } else if (dLayout.hasSlope) { y1 = yDomainExtent[0]; y2 = yDomainExtent[1]; if(!d.intercept){ d.intercept = 0; } x1 = (y1 - d.intercept) / d.slope; x2 = (y2 - d.intercept) / d.slope; } else { throw "Invalid line"; } dLayout.x1 = layoutScale.xScale(x1); dLayout.x2 = layoutScale.xScale(x2); dLayout.y1 = layoutScale.yScale(y1); dLayout.y2 = layoutScale.yScale(y2); //label location if (dLayout.isInterceptX) { dLayout.y1 = layoutScale.drawArea.height - layoutScale.drawArea.bottom; dLayout.y2 = layoutScale.drawArea.top; if(d.valueLabelOffsetY){ dLayout.y1 = dLayout.y1 + d.valueLabelOffsetY; } dLayout.lx = dLayout.x1; dLayout.ly = dLayout.y1; dLayout.lineLength = dLayout.y1 - dLayout.y2; } else if (dLayout.isInterceptY) { dLayout.x1 = layoutScale.drawArea.left; dLayout.x2 = layoutScale.drawArea.width - layoutScale.drawArea.right; if(d.valueLabelOffsetX){ dLayout.x2 = dLayout.x2 + d.valueLabelOffsetX; } dLayout.lx = dLayout.x2; dLayout.ly = dLayout.y1; dLayout.lineLength = dLayout.x2 - dLayout.x1; } else if (dLayout.hasSlope) { dLayout.lx = dLayout.x1 - layoutScale.drawArea.left * 0.5; dLayout.ly = dLayout.y1 + layoutScale.drawArea.bottom * 0.5; } if (dLayout.hasDragX) { layoutDragLimits(d, dLayout, layoutScale.xDomainExtent, constrainDrag); } else if (dLayout.hasDragY) { layoutDragLimits(d, dLayout, layoutScale.yDomainExtent, constrainDrag); } dLayout.data = d; viewModel.dataArray.push(dLayout); } viewModel.keyMap = function(d){ return d.key; }; return viewModel; } } } //currently only for vertical bar chart view models export function convertBarViewModel(barViewModel, layoutScale: LayoutScale, constrainDrag: boolean = true){ let dLayout: any, data: any, lineViewModel = { dataArray: [] }, xRangeExtent = layoutScale.xRangeExtent, yRangeExtent = layoutScale.yRangeExtent; for(let d of barViewModel.dataArray){ dLayout = { key: "line-" + d.key, x1: d.x, x2: (d.x + d.width), y1: d.y, y2: d.y, lx: 0, ly: 0, keyMap: function(d){ return d.key; } }; dLayout.data = d; if (d.drag === "x") { layoutDragLimits(d, dLayout, layoutScale.xDomainExtent, constrainDrag); } else if (d.drag === "y") { layoutDragLimits(d, dLayout, layoutScale.yDomainExtent, constrainDrag); } dLayout.lineLength = dLayout.x2 - dLayout.x1; lineViewModel.dataArray.push(dLayout); } return lineViewModel; }