/**
* @classdesc
* Secondary visualization layer to draw labels
* @constructor
*/
var LabelDrawer = function(svgOrigin,algo){
/////////////////
//PRIVATE
var leftMargin = 10;
var xRange = +svgOrigin.attr("width") || 400;
yRange = +svgOrigin.attr("height") || 300;
var wS = global_NodeLayout['borderWidth'];
var margin = {top: global_KnotenRadius+wS, right: global_KnotenRadius+wS, bottom: global_KnotenRadius+2*wS, left: global_KnotenRadius+leftMargin},
width = xRange - margin.left - margin.right,
height = yRange - margin.top - margin.bottom;
this.margin = margin;
var radius = global_KnotenRadius;//20;
svgOrigin
.attr({version: '1.1' , xmlns:"http://www.w3.org/2000/svg"})
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
var svg = svgOrigin.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var svg_timewindow=svg.append("rect").attr("class", "timewindow");
var svg_labels=svg.append("g").attr("id", "labels");
var x = d3.scale.linear()
.range([margin.left, width-margin.right]);
var y = d3.scale.linear()
.range([height-margin.top, margin.bottom]);
x.domain([0,10]);
y.domain([0,10]);
//Axis
var xAxis = d3.svg.axis().scale(x).orient("bottom");
var yAxis = d3.svg.axis().scale(y).orient("left");
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.append("text")
.attr("class", "label")
.attr("x", width)
.attr("y", 0)
.style("text-anchor", "end")
.text("time");
svg.append("g")
.attr("class", "y axis")
.attr("transform", "translate(10,0)")
.call(yAxis)
.append("text")
.attr("class", "label")
// .attr("transform", "rotate(-90)")
//.attr("x",10)
//.attr("y", -3)
.attr("dy", ".71em")
.style("text-anchor", "end")
.style("fill","magenta")
.text("cost")
var transform = function(d){
return "translate(" + x(d.x) + "," + y(d.y) + ")"
;};
/////////////////
//PRIVILEDGED
this.reset = function(){
}
this.clear = function(){
svg_labels.selectAll("g").remove();
};
this.type="LabelDrawer";
this.graph = Graph.instance;
this.svgOrigin = svgOrigin;
var that = this
var labelEndTransform = function(d){
var d = d || {resources:[0,0]};
return "translate("+x(d.resources[0])+","+y(d.resources[1])+")";
}
var generatePathCoordinatesFromLabel = function(d,repeatParentAtEnd){
var pathinfo = [];
var current=d;
var i=5;
do{
pathinfo.push(current.resources);
if(current.wait){
pathinfo.push([current.resources[0]-current.wait,current.resources[1]]);
}
}
while((current=Graph.Label.get(current.parentId)) && i--);
pathinfo.reverse();
if(repeatParentAtEnd && pathinfo.length>=2){
pathinfo[pathinfo.length-1]=pathinfo[pathinfo.length-2];
}
return pathinfo;//.reverse();
}
var lineFunction = d3.svg.line()
.x(function(d) { return x(d[0]); })
.y(function(d) { return y(d[1]); })
.interpolate("linear");//basis");
this.updateLabels = function(s,userChoseFilter){
if(!userChoseFilter){
if(s.id==STATUS_PATH_EXTEND_FEASIBLE || s.id==STATUS_PATH_EXTEND_UNFEASIBLE){
algo.setResidentNodeFilter(Graph.Label.get(s.l_dashId).nodeId,true);
}else if(s.currentNodeIdDominance != null && (s.id==STATUS_DOMINANCE || s.id==STATUS_DOMINANCE_NODE)){
algo.setResidentNodeFilter(s.currentNodeIdDominance,true);
}else{
algo.setResidentNodeFilter("all",true);
}
}
//var labels = s.U.concat(s.P)
//if(s.currentLabel) labels.push(s.currentLabel);
//if(s.l_dash) labels.push(s.l_dash);
var labels = [];//Graph.Label.labels.values();
if(s.lId){
labels.push(Graph.Label.get(s.lId));
}
if(s.l_dashId){
labels.push(Graph.Label.get(s.l_dashId));
}
for(var i=0; i<s.U.length; i++){
labels.push(Graph.Label.get(s.U[i]));
}
for(var i=0; i<s.P.length; i++){
labels.push(Graph.Label.get(s.P[i]));
}
if(s.residentNodeFilterId != "all"){
labels = labels.filter(function(d){
return d.nodeId == s.residentNodeFilterId;
})
}
// console.log(labels);
// console.log(s.U,s.lId,s.P);
x.domain([0,Math.max(d3.max(labels, function(d) { return d.resources[0];})||0,10)]);
y.domain([0,Math.max(d3.max(labels, function(d) { return d.resources[1];})||0,10)]);
// var xAxis = d3.svg.axis().scale(x).orient("bottom");
// var yAxis = d3.svg.axis().scale(y).orient("left");
var t = svg.transition();//.duration(750);
t.select("g.y.axis").call(yAxis);
t.select("g.x.axis").call(xAxis);
this.updateTimeWindow(s);
// DATA JOIN
// Join new data with old elements, if any.
var selection = svg_labels.selectAll(".label")
.data(labels,function(d){return d.id});
// ENTER
// Create new elements as needed.
var enterSelection =
selection.enter().append("g")
.attr("class","label unselectable");
enterSelection
.attr("opacity","1e-6")
.transition().duration(500)
.attr("opacity","1");
var enterSelectionLabelPath = enterSelection.append("path")
.attr("class","labelpath") //is not transformed
.style("stroke", "gray")
.style("fill","none")
var enterSelectionLabelEnd = enterSelection.append("g")
.attr("class","labelend")
.style("cursor","pointer")
.on("click", function(d) {
algo.setHighlightPathForLabel(d.id,false,true);
console.log(d);
//highlight path for this label
})
enterSelectionLabelEnd
.append("rect")
.attr({"rx":50, "ry":5, "height":20, "y":-10})
.style({"fill":"red", "stroke-width":2});// , "fill-opacity":1});
enterSelectionLabelEnd
.append("text")
.style("text-anchor", "middle")
.attr("dominant-baseline","middle")
.text(function(d){return d.id});
// .append("path")
// .attr("d",shapeFun)
// .attr("fill",labelColor2)
//.attr("r", 10)
// .on("mouseenter",function(d){
// var label = d;
// while(label && label.arc){
// label.arc.highlight=true;
// label=label.parent;
// }
// updateEdges()
// console.log(d);
// })
// .on("mouseleave",function(d){
// var label = d;
// while(label && label.arc){
// label.arc.highlight=false;
// label=label.parent;
// }
// updateEdges()
// console.log(d);
// })
// selection.enter().selectAll(".labelend")
// ENTER + UPDATE
// Appending to the enter selection expands the update selection to include
// entering elements; so, operations on the update selection after appending to
// the enter selection will apply to both entering and updating nodes.
selection.selectAll(".labelend")
.attr("transform",function(d){
return labelEndTransform(d.id == s.l_dashId ? Graph.Label.get(d.parentId) : d)
})// start at parent position and transition to new position
.transition().duration(500)
.attr("transform",labelEndTransform)
selection.selectAll("path")
.style("stroke-width",function(d){return d.id==s.highlightPathForLabelId ? 4 : 2;})
.style("stroke-dasharray",function(d){
return (d.id == algo.getState().l_dashId) ? "5,5" : "0";
})
.style("stroke",function(d){
if(d.id == s.l_dashId) return "orange";
else if(d.id == s.lId) return "red";
else if(d.id == s.minCostLabelId) return "magenta";
return "gray"
})
.attr("d",function(d){
var coords = generatePathCoordinatesFromLabel(d,d.id == s.l_dashId);
return lineFunction(coords);
})
.transition().duration(500)
.attr("d",function(d){
var coords = generatePathCoordinatesFromLabel(d,false);
return lineFunction(coords);
})
// .transition()
// .style("stroke",function(d){
// if(d==algo.s.currentLabel){
// return "red";
// }else{
// return "black"
// }
// })
// .attr("opacity",function(d){
// return (d==algo.s.currentLabel || d.nodeId == currentNode || currentArc && currentArc.end==currentLabel.node) ? 1 : 0;
// })
selection.selectAll(".labelend rect")
.attr("width",10)//function(d){return d.id.length*7})
.attr("x",-5)//function(d){return d.id.length*(-3.5)})
.style("fill",function(d){
// if(s.id == algo.STATUS_DOMINANCE){
// return algo.dominanceStepNodeColors(d.nodeId);
// }
if(d.id == s.minCostLabelId) return "magenta";
if(d.id == s.lId) return const_Colors.CurrentNodeColor;
if(d.id == s.l_dashId) return "orange";
if(s.U.some(function(a){return a==d.id})) return const_Colors.PQColor;
if(s.P.some(function(a){return a==d.id})) return const_Colors.FinishedNodeColor;
})
.style("stroke",function(d){
return "black";
// if(s.currentLabel && d.id==s.currentLabel.id) return const_Colors.NodeBorderHighlight;
})
.style("stroke-width",function(d){
return d.id == s.highlightPathForLabelId ? 2 : 0.5;
})
// EXIT
// Remove old elements as needed.
selection.exit()
.attr("opacity","1")
.transition().duration(500)
.attr("opacity","1e-6")
.remove();
} //end updateNodes()
this.updateTimeWindow = function(s){
if(s.residentNodeFilterId == "all"){
svg_timewindow
// .attr("opacity","1")
// .transition().duration(500)
.attr("opacity",1e-6)
}else{
var residentNode = Graph.instance.nodes.get(s.residentNodeFilterId);
var yVals = y.range();
var xStart = x(residentNode.resources[0]);
var www = x(residentNode.resources[1])-xStart;
if(www<=0){
www=6;
xStart-=3;
}
svg_timewindow.attr({
x : xStart,
width : www,
y: yVals[1],
height : yVals[0]+margin.top,
opacity : 1
})
}
}
} //end constructor GraphDrawer