text: /* Copyright 2005-2015 Alfresco Software, Ltd.
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  function _bpmnGetColor(element, defaultColor)
  {
      var strokeColor;
      if(element.current) {
          strokeColor = CURRENT_COLOR;
      } else if(element.completed) {
          strokeColor = COMPLETED_COLOR;
      } else {
          strokeColor = defaultColor;
      }
      return strokeColor;
  }
  
  function _drawPool(pool)
  {
  	var rect = paper.rect(pool.x, pool.y, pool.width, pool.height);
  
  	rect.attr({"stroke-width": 1,
  		"stroke": "#000000",
  		"fill": "white"
   	});
  
  	if (pool.name)
  	{
  		var poolName = paper.text(pool.x + 14, pool.y + (pool.height / 2), pool.name).attr({
  	        "text-anchor" : "middle",
  	        "font-family" : "Arial",
  	        "font-size" : "12",
  	        "fill" : "#000000"
  	  	});
  
  		poolName.transform("r270");
  	}
  
  	if (pool.lanes)
  	{
  		for (var i = 0; i < pool.lanes.length; i++)
  		{
  			var lane = pool.lanes[i];
  			_drawLane(lane);
  		}
  	}
  }
  
  function _drawLane(lane)
  {
  	var rect = paper.rect(lane.x, lane.y, lane.width, lane.height);
  
  	rect.attr({"stroke-width": 1,
  		"stroke": "#000000",
  		"fill": "white"
   	});
  
  	if (lane.name)
  	{
  		var laneName = paper.text(lane.x + 10, lane.y + (lane.height / 2), lane.name).attr({
  	        "text-anchor" : "middle",
  	        "font-family" : "Arial",
  	        "font-size" : "12",
  	        "fill" : "#000000"
  	  	});
  
  		laneName.transform("r270");
  	}
  }
  
  function _drawSubProcess(element)
  {
  	var rect = paper.rect(element.x, element.y, element.width, element.height, 4);
  
  	var strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);
  
  	rect.attr({"stroke-width": 1,
  		"stroke": strokeColor,
  		"fill": "white"
   	});
  }
  
  function _drawTransaction(element)
  {
  	var rect = paper.rect(element.x, element.y, element.width, element.height, 4);
  
  	var strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);
  
  	rect.attr({"stroke-width": 1,
  		"stroke": strokeColor,
  		"fill": "white"
   	});
  
  	var borderRect = paper.rect(element.x + 2, element.y + 2, element.width - 4, element.height -4, 4);
  
  	borderRect.attr({"stroke-width": 1,
  		"stroke": "black",
  		"fill": "none"
   	});
  }
  
  function _drawEventSubProcess(element)
  {
  	var rect = paper.rect(element.x, element.y, element.width, element.height, 4);
  	var strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);
  
  	rect.attr({"stroke-width": 1,
  		"stroke": strokeColor,
  		"stroke-dasharray": ".",
  		"fill": "white"
   	});
  }
  
  function _drawAdhocSubProcess(element)
  {
  	var rect = paper.rect(element.x, element.y, element.width, element.height, 4);
  
  	var strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);
  
  	rect.attr({"stroke-width": 1,
  		"stroke": strokeColor,
  		"fill": "white"
   	});
  
   	paper.text(element.x + (element.width / 2), element.y + element.height - 8).attr({
          "text-anchor" : "middle",
          "font-family" : "Arial",
          "font-size" : 20,
          "text" : "~",
          "fill" : "#373e48"
    	});
  }
  
  function _drawStartEvent(element)
  {
  	var startEvent = _drawEvent(element, NORMAL_STROKE, 15);
  	startEvent.click(function() {
  		_zoom(true);
  	});
  	_addHoverLogic(element, "circle", MAIN_STROKE_COLOR);
  }
  
  function _drawEndEvent(element)
  {
  	var endEvent = _drawEvent(element, ENDEVENT_STROKE, 14);
  	endEvent.click(function() {
  		_zoom(false);
  	});
  	_addHoverLogic(element, "circle", MAIN_STROKE_COLOR);
  }
  
  function _drawEvent(element, strokeWidth, radius)
  {
  	var x = element.x + (element.width / 2);
  	var y = element.y + (element.height / 2);
  
  	var circle = paper.circle(x, y, radius);
  
  	var strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);
  
      // Fill
      var eventFillColor = _determineCustomFillColor(element, "#ffffff");
  
      // Opacity
      var eventOpacity = 1.0;
      if (customActivityBackgroundOpacity) {
          eventOpacity = customActivityBackgroundOpacity;
      }
  
  	if (element.interrupting === undefined || element.interrupting) {
  		circle.attr({
  		    "stroke-width": strokeWidth,
  			"stroke": strokeColor,
  			"fill": eventFillColor,
  	        "fill-opacity": eventOpacity
  	 	});
  
  	} else {
  		circle.attr({
  		    "stroke-width": strokeWidth,
  			"stroke": strokeColor,
  			"stroke-dasharray": ".",
  			"fill": eventFillColor,
  	        "fill-opacity": eventOpacity
  	 	});
  	}
  
  	circle.id = element.id;
  
  	_drawEventIcon(paper, element);
  
  	return circle;
  }
  
  function _drawServiceTask(element)
  {
  	_drawTask(element);
  	if (element.taskType === "mail")
  	{
  		_drawSendTaskIcon(paper, element.x + 4, element.y + 4);
  	}
  	else if (element.taskType === "camel")
  	{
  		_drawCamelTaskIcon(paper, element.x + 4, element.y + 4);
  	}
  	else if (element.taskType === "mule")
  	{
  		_drawMuleTaskIcon(paper, element.x + 4, element.y + 4);
  	}
      else if (element.taskType === "http")
      {
          _drawHttpTaskIcon(paper, element.x + 4, element.y + 4);
      }
      else if (element.taskType === "shell")
      {
          _drawShellTaskIcon(paper, element.x + 4, element.y + 4);
      }
      else if (element.taskType === "dmn") {
          _drawDecisionTaskIcon(paper, element.x + 4, element.y + 4);
      }
      else if (element.stencilIconId)
  	{
  		paper.image("../service/stencilitem/" + element.stencilIconId + "/icon", element.x + 4, element.y + 4, 16, 16);
  	}
  	else
  	{
  		_drawServiceTaskIcon(paper, element.x + 4, element.y + 4);
  	}
  	_addHoverLogic(element, "rect", ACTIVITY_STROKE_COLOR);
  }
  
  function _drawSendEventServiceTask(element)
  {
      _drawTask(element);
      _drawSendTaskIcon(paper, element.x + 4, element.y + 4);
      _addHoverLogic(element, "rect", ACTIVITY_STROKE_COLOR);
  }
  
  function _drawHttpServiceTask(element)
  {
      _drawTask(element);
      _drawHttpTaskIcon(paper, element.x + 4, element.y + 4);
      _addHoverLogic(element, "rect", ACTIVITY_STROKE_COLOR);
  }
  
  function _drawCallActivity(element)
  {
      var width = element.width - (CALL_ACTIVITY_STROKE / 2);
      var height = element.height - (CALL_ACTIVITY_STROKE / 2);
  
      var rect = paper.rect(element.x, element.y, width, height, 4);
  
      var strokeColor = _bpmnGetColor(element, ACTIVITY_STROKE_COLOR);
  
      // Fill
      var callActivityFillColor = _determineCustomFillColor(element, ACTIVITY_FILL_COLOR);
  
      // Opacity
      var callActivityOpacity = 1.0;
      if (customActivityBackgroundOpacity) {
          callActivityOpacity = customActivityBackgroundOpacity;
      }
  
      rect.attr({"stroke-width": CALL_ACTIVITY_STROKE,
          "stroke": strokeColor,
          "fill": callActivityFillColor,
          "fill-opacity": callActivityOpacity
      });
  
      rect.id = element.id;
  
      if (element.name) {
          this._drawMultilineText(element.name, element.x, element.y, element.width, element.height, "middle", "middle", 11);
      }
      _addHoverLogic(element, "rect", ACTIVITY_STROKE_COLOR);
  }
  
  function _drawScriptTask(element)
  {
  	_drawTask(element);
  	_drawScriptTaskIcon(paper, element.x + 4, element.y + 4);
  	_addHoverLogic(element, "rect", ACTIVITY_STROKE_COLOR);
  }
  
  function _drawUserTask(element)
  {
  	_drawTask(element);
  	_drawUserTaskIcon(paper, element.x + 4, element.y + 4);
  	_addHoverLogic(element, "rect", ACTIVITY_STROKE_COLOR);
  }
  
  function _drawBusinessRuleTask(element)
  {
  	_drawTask(element);
  	_drawBusinessRuleTaskIcon(paper, element.x + 4, element.y + 4);
  	_addHoverLogic(element, "rect", ACTIVITY_STROKE_COLOR);
  }
  
  function _drawManualTask(element)
  {
  	_drawTask(element);
  	_drawManualTaskIcon(paper, element.x + 4, element.y + 4);
  	_addHoverLogic(element, "rect", ACTIVITY_STROKE_COLOR);
  }
  
  function _drawSendTask(element)
  {
      _drawTask(element);
      _drawSendTaskIcon(paper, element.x + 4, element.y + 4);
      _addHoverLogic(element, "rect", ACTIVITY_STROKE_COLOR);
  }
  
  function _drawReceiveTask(element)
  {
  	_drawTask(element);
  	_drawReceiveTaskIcon(paper, element.x, element.y);
  	_addHoverLogic(element, "rect", ACTIVITY_STROKE_COLOR);
  }
  
  function _drawTask(element)
  {
      var rectAttrs = {};
  
      // Stroke
      var strokeColor = _bpmnGetColor(element, ACTIVITY_STROKE_COLOR);
      rectAttrs['stroke'] = strokeColor;
  
      var strokeWidth;
      if (strokeColor === ACTIVITY_STROKE_COLOR) {
          strokeWidth = TASK_STROKE;
      } else {
          strokeWidth = TASK_HIGHLIGHT_STROKE;
      }
  
  	var width = element.width - (strokeWidth / 2);
  	var height = element.height - (strokeWidth / 2);
  
  	var rect = paper.rect(element.x, element.y, width, height, 4);
      rectAttrs['stroke-width'] = strokeWidth;
  
      // Fill
  	var fillColor = _determineCustomFillColor(element, ACTIVITY_FILL_COLOR);
      rectAttrs['fill'] = fillColor;
  
      // Opacity
      if (customActivityBackgroundOpacity) {
          rectAttrs['fill-opacity'] = customActivityBackgroundOpacity;
      }
  
  	rect.attr(rectAttrs);
  	rect.id = element.id;
  
  	if (element.name) {
  		this._drawMultilineText(element.name, element.x, element.y, element.width, element.height, "middle", "middle", 11);
  	}
  }
  
  function _drawExclusiveGateway(element)
  {
  	_drawGateway(element);
  	var quarterWidth = element.width / 4;
  	var quarterHeight = element.height / 4;
  
  	var iks = paper.path(
  		"M" + (element.x + quarterWidth + 3) + " " + (element.y + quarterHeight + 3) +
  		"L" + (element.x + 3 * quarterWidth - 3) + " " + (element.y + 3 * quarterHeight - 3) +
  		"M" + (element.x + quarterWidth + 3) + " " + (element.y + 3 * quarterHeight - 3) +
  		"L" + (element.x + 3 * quarterWidth - 3) + " " + (element.y + quarterHeight + 3)
  	);
  
  	var strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);
  
      // Fill
      var gatewayFillColor = _determineCustomFillColor(element, ACTIVITY_FILL_COLOR);
  
      // Opacity
      var gatewayOpacity = 1.0;
      if (customActivityBackgroundOpacity) {
          gatewayOpacity = customActivityBackgroundOpacity;
      }
  
  
      iks.attr({"stroke-width": 3, "stroke": strokeColor, "fill": gatewayFillColor, "fill-opacity": gatewayOpacity});
  
  	_addHoverLogic(element, "rhombus", MAIN_STROKE_COLOR);
  }
  
  function _drawParallelGateway(element)
  {
  	_drawGateway(element);
  
  	var strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);
  
  	var path1 = paper.path("M 6.75,16 L 25.75,16 M 16,6.75 L 16,25.75");
  
      // Fill
      var gatewayFillColor = _determineCustomFillColor(element, ACTIVITY_FILL_COLOR);
  
      // Opacity
      var gatewayOpacity = 1.0;
      if (customActivityBackgroundOpacity) {
          gatewayOpacity = customActivityBackgroundOpacity;
      }
  
  	path1.attr({
  		"stroke-width": 3,
  		"stroke": strokeColor,
  		"fill": gatewayFillColor,
          "fill-opacity": gatewayOpacity
  	});
  
  	path1.transform("T" + (element.x + 4) + "," + (element.y + 4));
  
  	_addHoverLogic(element, "rhombus", MAIN_STROKE_COLOR);
  }
  
  function _drawInclusiveGateway(element)
  {
  	_drawGateway(element);
  
  	var strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);
  
  	var circle1 = paper.circle(element.x + (element.width / 2), element.y + (element.height / 2), 9.75);
  
      // Fill
      var gatewayFillColor = _determineCustomFillColor(element, ACTIVITY_FILL_COLOR);
  
      // Opacity
      var gatewayOpacity = 1.0;
      if (customActivityBackgroundOpacity) {
          gatewayOpacity = customActivityBackgroundOpacity;
      }
  
  	circle1.attr({
  		"stroke-width": 2.5,
  		"stroke": strokeColor,
  		"fill": gatewayFillColor,
          "fill-opacity": gatewayOpacity
  	});
  
  	_addHoverLogic(element, "rhombus", MAIN_STROKE_COLOR);
  }
  
  function _drawEventGateway(element)
  {
  	_drawGateway(element);
  
  	var strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);
  
  	var circle1 = paper.circle(element.x + (element.width / 2), element.y + (element.height / 2), 10.4);
  
      // Fill
      var gatewayFillColor = _determineCustomFillColor(element, ACTIVITY_FILL_COLOR);
  
      // Opacity
      var gatewayOpacity = 1.0;
      if (customActivityBackgroundOpacity) {
          gatewayOpacity = customActivityBackgroundOpacity;
      }
  
  	circle1.attr({
  		"stroke-width": 0.5,
  		"stroke": strokeColor,
  		"fill": gatewayFillColor,
          "fill-opacity": gatewayOpacity
      });
  
  	var circle2 = paper.circle(element.x + (element.width / 2), element.y + (element.height / 2), 11.7);
  	circle2.attr({
  		"stroke-width": 0.5,
  		"stroke": strokeColor,
          "fill": gatewayFillColor,
          "fill-opacity": gatewayOpacity
  	});
  
  	var path1 = paper.path("M 20.327514,22.344972 L 11.259248,22.344216 L 8.4577203,13.719549 L 15.794545,8.389969 L 23.130481,13.720774 L 20.327514,22.344972 z");
  	path1.attr({
  		"stroke-width": 1.39999998,
  		"stroke": strokeColor,
          "fill": gatewayFillColor,
          "fill-opacity": gatewayOpacity,
  		"stroke-linejoin": "bevel"
  	});
  
  	path1.transform("T" + (element.x + 4) + "," + (element.y + 4));
  
  	_addHoverLogic(element, "rhombus", MAIN_STROKE_COLOR);
  }
  
  function _drawGateway(element)
  {
      var strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);
  
  	var rhombus = paper.path("M" + element.x + " " + (element.y + (element.height / 2)) +
  		"L" + (element.x + (element.width / 2)) + " " + (element.y + element.height) +
  		"L" + (element.x + element.width) + " " + (element.y + (element.height / 2)) +
  		"L" + (element.x + (element.width / 2)) + " " + element.y + "z"
  	);
  
      // Fill
      var gatewayFillColor = _determineCustomFillColor(element, ACTIVITY_FILL_COLOR);
  
      // Opacity
      var gatewayOpacity = 1.0;
      if (customActivityBackgroundOpacity) {
          gatewayOpacity = customActivityBackgroundOpacity;
      }
  
  	rhombus.attr("stroke-width", 2);
  	rhombus.attr("stroke", strokeColor);
  	rhombus.attr("fill", gatewayFillColor);
      rhombus.attr("fill-opacity", gatewayOpacity);
  
  	rhombus.id = element.id;
  
  	return rhombus;
  }
  
  function _drawBoundaryEvent(element)
  {
  	var x = element.x + (element.width / 2);
  	var y = element.y + (element.height / 2);
  
  	var circle = paper.circle(x, y, 15);
  
  	var strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);
  
   	if (element.cancelActivity)  {
  		circle.attr({
  		    "stroke-width": 1,
  			"stroke": strokeColor,
  			"fill": "white"
  	 	});
  
  	} else {
  		circle.attr({
  		    "stroke-width": 1,
  		    "stroke-dasharray": ".",
  			"stroke": strokeColor,
  			"fill": "white"
  	 	});
  	}
  
  	var innerCircle = paper.circle(x, y, 12);
  
  	if (element.cancelActivity)  {
  		innerCircle.attr({"stroke-width": 1,
  			"stroke": strokeColor,
  			"fill": "none"
  	 	});
  
  	} else {
  		innerCircle.attr({
  		    "stroke-width": 1,
  		    "stroke-dasharray": ".",
  			"stroke": strokeColor,
  			"fill": "none"
  	 	});
  	}
  
  	_drawEventIcon(paper, element);
  	_addHoverLogic(element, "circle", MAIN_STROKE_COLOR);
  
  	circle.id = element.id;
  	innerCircle.id = element.id + "_inner";
  }
  
  function _drawIntermediateCatchEvent(element)
  {
  	var x = element.x + (element.width / 2);
  	var y = element.y + (element.height / 2);
  
  	var circle = paper.circle(x, y, 15);
  
  	var strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);
  
  	circle.attr({"stroke-width": 1,
  		"stroke": strokeColor,
  		"fill": "white"
   	});
  
  	var innerCircle = paper.circle(x, y, 12);
  
  	innerCircle.attr({"stroke-width": 1,
  		"stroke": strokeColor,
  		"fill": "none"
   	});
  
  	_drawEventIcon(paper, element);
  	_addHoverLogic(element, "circle", MAIN_STROKE_COLOR);
  
  	circle.id = element.id;
  	innerCircle.id = element.id + "_inner";
  }
  
  function _drawThrowEvent(element)
  {
  	var x = element.x + (element.width / 2);
  	var y = element.y + (element.height / 2);
  
  	var circle = paper.circle(x, y, 15);
  
  	var strokeColor = _bpmnGetColor(element, MAIN_STROKE_COLOR);
  
  	circle.attr({"stroke-width": 1,
  		"stroke": strokeColor,
  		"fill": "white"
   	});
  
  	var innerCircle = paper.circle(x, y, 12);
  
  	innerCircle.attr({"stroke-width": 1,
  		"stroke": strokeColor,
  		"fill": "none"
   	});
  
  	_drawEventIcon(paper, element);
  	_addHoverLogic(element, "circle", MAIN_STROKE_COLOR);
  
  	circle.id = element.id;
  	innerCircle.id = element.id + "_inner";
  }
  
  function _drawMultilineText(text, x, y, boxWidth, boxHeight, horizontalAnchor, verticalAnchor, fontSize)
  {
  	if (!text || text == "")
  	{
  		return;
  	}
  
  	var textBoxX, textBoxY;
      var width = boxWidth - (2 * TEXT_PADDING);
  
      if (horizontalAnchor === "middle")
      {
      	textBoxX = x + (boxWidth / 2);
      }
      else if (horizontalAnchor === "start")
      {
      	textBoxX = x;
      }
  
      textBoxY = y + (boxHeight / 2);
  
   	var t = paper.text(textBoxX + TEXT_PADDING, textBoxY + TEXT_PADDING).attr({
          "text-anchor" : horizontalAnchor,
          "font-family" : "Arial",
          "font-size" : fontSize,
          "fill" : "#373e48"
    	});
  
      var abc = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
      t.attr({
          "text" : abc
      });
      var letterWidth = t.getBBox().width / abc.length;
  
      t.attr({
          "text" : text
      });
      var removedLineBreaks = text.split("\n");
      var x = 0, s = [];
      for (var r = 0; r < removedLineBreaks.length; r++)
      {
    	    var words = removedLineBreaks[r].split(" ");
    	    for ( var i = 0; i < words.length; i++) {
  
    	        var l = words[i].length;
    	        if (x + (l * letterWidth) > width) {
    	            s.push("\n");
    	            x = 0;
    	        }
    	        x += l * letterWidth;
    	        s.push(words[i] + " ");
    	    }
  	  	s.push("\n");
          x = 0;
      }
      t.attr({
      	"text" : s.join("")
      });
  
      if (verticalAnchor && verticalAnchor === "top")
      {
      	t.attr({"y": y + (t.getBBox().height / 2)});
      }
  }
  
  function _drawTextAnnotation(element)
  {
  	var path1 = paper.path("M20,1 L1,1 L1,50 L20,50");
  	path1.attr({
  		"stroke": "#585858",
  		"fill": "none"
   	});
  
  	var annotation = paper.set();
  	annotation.push(path1);
  
  	annotation.transform("T" + element.x + "," + element.y);
  
  	if (element.text) {
  		this._drawMultilineText(element.text, element.x + 2, element.y, element.width, element.height, "start", "middle", 11);
  	}
  }
  
  function _drawFlow(flow){
  
  	var polyline = new Polyline(flow.id, flow.waypoints, SEQUENCEFLOW_STROKE, paper);
  
  	var strokeColor = _bpmnGetColor(flow, MAIN_STROKE_COLOR);
  
  	polyline.element = paper.path(polyline.path);
  	polyline.element.attr({"stroke-width":SEQUENCEFLOW_STROKE});
  	polyline.element.attr({"stroke":strokeColor});
  
  	polyline.element.id = flow.id;
  
  	var lastLineIndex = polyline.getLinesCount() - 1;
  	var line = polyline.getLine(lastLineIndex);
  
  	if (line == undefined) return;
  
  	if (flow.type == "connection" && flow.conditions)
  	{
  		var middleX = (line.x1 + line.x2) / 2;
  		var middleY = (line.y1 + line.y2) / 2;
  		var image = paper.image("../editor/images/condition-flow.png", middleX - 8, middleY - 8, 16, 16);
  	}
  
  	var polylineInvisible = new Polyline(flow.id, flow.waypoints, SEQUENCEFLOW_STROKE, paper);
  
  	polylineInvisible.element = paper.path(polyline.path);
  	polylineInvisible.element.attr({
  			"opacity": 0,
  			"stroke-width": 8,
              "stroke" : "#000000"
  	});
  
      if (flow.name) {
          var firstLine = polyline.getLine(0);
  
          var angle;
          if (firstLine.x1 !== firstLine.x2) {
              angle = Math.atan((firstLine.y2 - firstLine.y1) / (firstLine.x2 - firstLine.x1));
          } else if (firstLine.y1 < firstLine.y2) {
              angle = Math.PI / 2;
          } else {
              angle = -Math.PI / 2;
  		}
  		var flowName = paper.text(firstLine.x1, firstLine.y1, flow.name).attr({
  			"text-anchor": "middle",
  			"font-family" : "Arial",
  			"font-size" : "12",
  			"fill" : "#000000"
  		});
  
          var offsetX = (flowName.getBBox().width / 2 + 5);
          var offsetY = -(flowName.getBBox().height / 2 + 5);
  
          if (firstLine.x1 > firstLine.x2) {
              offsetX = -offsetX;
          }
          var rotatedOffsetX = offsetX * Math.cos(angle) - offsetY * Math.sin(angle);
          var rotatedOffsetY = offsetX * Math.sin(angle) + offsetY * Math.cos(angle);
  
          flowName.attr({
  			x: firstLine.x1 + rotatedOffsetX,
  			y: firstLine.y1 + rotatedOffsetY
  		});
  
          flowName.transform("r" + ((angle) * 180) / Math.PI);
      }
  
  	_showTip(jQuery(polylineInvisible.element.node), flow);
  
  	polylineInvisible.element.mouseover(function() {
  		paper.getById(polyline.element.id).attr({"stroke":"blue"});
  	});
  
  	polylineInvisible.element.mouseout(function() {
  		paper.getById(polyline.element.id).attr({"stroke":"#585858"});
  	});
  
  	_drawArrowHead(line);
  }
  
  function _drawAssociation(flow){
  
  	var polyline = new Polyline(flow.id, flow.waypoints, ASSOCIATION_STROKE, paper);
  
  	polyline.element = paper.path(polyline.path);
  	polyline.element.attr({"stroke-width": ASSOCIATION_STROKE});
  	polyline.element.attr({"stroke-dasharray": ". "});
  	polyline.element.attr({"stroke":"#585858"});
  
  	polyline.element.id = flow.id;
  
  	var polylineInvisible = new Polyline(flow.id, flow.waypoints, ASSOCIATION_STROKE, paper);
  
  	polylineInvisible.element = paper.path(polyline.path);
  	polylineInvisible.element.attr({
  			"opacity": 0,
  			"stroke-width": 8,
              "stroke" : "#000000"
  	});
  
  	_showTip(jQuery(polylineInvisible.element.node), flow);
  
  	polylineInvisible.element.mouseover(function() {
  		paper.getById(polyline.element.id).attr({"stroke":"blue"});
  	});
  
  	polylineInvisible.element.mouseout(function() {
  		paper.getById(polyline.element.id).attr({"stroke":"#585858"});
  	});
  }
  
  function _drawArrowHead(line, connectionType)
  {
  	var doubleArrowWidth = 2 * ARROW_WIDTH;
  
  	var arrowHead = paper.path("M0 0L-" + (ARROW_WIDTH / 2 + .5) + " -" + doubleArrowWidth + "L" + (ARROW_WIDTH/2 + .5) + " -" + doubleArrowWidth + "z");
  
  	// anti smoothing
  	if (this.strokeWidth%2 == 1)
  		line.x2 += .5, line.y2 += .5;
  
  	arrowHead.transform("t" + line.x2 + "," + line.y2 + "");
  	arrowHead.transform("...r" + Raphael.deg(line.angle - Math.PI / 2) + " " + 0 + " " + 0);
  
  	arrowHead.attr("fill", "#585858");
  
  	arrowHead.attr("stroke-width", SEQUENCEFLOW_STROKE);
  	arrowHead.attr("stroke", "#585858");
  
  	return arrowHead;
  }
  
  function _determineCustomFillColor(element, defaultColor) {
  
      var color;
  
      // By name
      if (customActivityColors && customActivityColors[element.name]) {
          color = customActivityColors[element.name];
      }
  
      if (color !== null && color !== undefined) {
          return color;
      }
  
      // By id
      if (customActivityColors && customActivityColors[element.id]) {
          color = customActivityColors[element.id];
      }
  
      if (color !== null && color !== undefined) {
          return color;
      }
  
      return defaultColor;
  }
  