/**
* Copyright 2007-2010 非也
* All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License v3 as published by the Free Software
* Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along
* with this library; if not, see http://www.gnu.org/licenses/lgpl.html.
*
*/
package org.fireflow.webdesigner.transformer;
import java.awt.Dimension;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.fireflow.model.ModelElement;
import org.fireflow.model.io.SerializerException;
import org.fireflow.pdl.fpdl.diagram.ActivityShape;
import org.fireflow.pdl.fpdl.diagram.AssociationShape;
import org.fireflow.pdl.fpdl.diagram.CommentShape;
import org.fireflow.pdl.fpdl.diagram.ConnectorShape;
import org.fireflow.pdl.fpdl.diagram.Diagram;
import org.fireflow.pdl.fpdl.diagram.DiagramElement;
import org.fireflow.pdl.fpdl.diagram.EndNodeShape;
import org.fireflow.pdl.fpdl.diagram.GroupShape;
import org.fireflow.pdl.fpdl.diagram.LaneShape;
import org.fireflow.pdl.fpdl.diagram.MessageFlowShape;
import org.fireflow.pdl.fpdl.diagram.NodeShape;
import org.fireflow.pdl.fpdl.diagram.PoolShape;
import org.fireflow.pdl.fpdl.diagram.ProcessNodeShape;
import org.fireflow.pdl.fpdl.diagram.RouterShape;
import org.fireflow.pdl.fpdl.diagram.StartNodeShape;
import org.fireflow.pdl.fpdl.diagram.TransitionShape;
import org.fireflow.pdl.fpdl.diagram.figure.Figure;
import org.fireflow.pdl.fpdl.diagram.figure.Line;
import org.fireflow.pdl.fpdl.diagram.figure.Rectangle;
import org.fireflow.pdl.fpdl.diagram.figure.part.Bounds;
import org.fireflow.pdl.fpdl.diagram.figure.part.BoundsImpl;
import org.fireflow.pdl.fpdl.diagram.figure.part.FulfilStyle;
import org.fireflow.pdl.fpdl.diagram.figure.part.Label;
import org.fireflow.pdl.fpdl.diagram.figure.part.LabelImpl;
import org.fireflow.pdl.fpdl.diagram.figure.part.Point;
import org.fireflow.pdl.fpdl.io.FPDLNames;
import org.fireflow.pdl.fpdl.process.Activity;
import org.fireflow.pdl.fpdl.process.EndNode;
import org.fireflow.pdl.fpdl.process.Router;
import org.fireflow.pdl.fpdl.process.StartNode;
import org.fireflow.pdl.fpdl.process.WorkflowProcess;
import org.w3c.dom.CDATASection;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Text;
/**
*
* @author 非也 nychen2000@163.com
* Fire Workflow 官方网站:www.firesoa.com 或者 www.fireflow.org
*
*/
public class FpdlDiagramSerializerSvgImpl extends AbstractFpdlDiagramSerializer {
private Log log = LogFactory.getLog(FpdlDiagramSerializerSvgImpl.class);
private static final String BASIC_CIRCLE_MARKER_ID = "BASIC_CIRCLE_MARKER";
private static final String BASIC_BLOCK_ARROW_MARKER_ID = "BASIC_BLOCK_ARROW_MARKER";
private static final String BASIC_BLOCK_ARROW_MARKER2_ID = "BASIC_BLOCK_ARROW_MARKER2";//空心
private Element defsElement = null;
private Map<String,Element> circleMarkerMap = new HashMap<String,Element>();
private Map<String,Element> blockArrowMarkerMap = new HashMap<String,Element>();
private Map<String,Element> blockArrowMarker2Map = new HashMap<String,Element>();
/* (non-Javadoc)
* @see org.fireflow.clientwidget.transformer.FpdlDiagramSerializer#serializeDiagramToDoc(org.fireflow.pdl.fpdl.process.WorkflowProcess, java.lang.String)
*/
public Document serializeDiagramToDoc(WorkflowProcess workflowProcess,
String subProcessName) throws SerializerException {
_init(workflowProcess,subProcessName);
//构造根节点
Element root = document.createElement("svg");
root.setAttribute("id", diagram.getId());
if (diagram.getWorkflowElementRef()!=null){
root.setAttribute(FPDLNames.REF,diagram.getWorkflowElementRef().getId());
}
root.setAttribute("version", "1.1");
root.setAttribute("xmlns", "http://www.w3.org/2000/svg");
root.setAttribute("xmlns:xlink","http://www.w3.org/1999/xlink");
root.setAttribute("onload", "fireflowSvgInit('"+diagram.getId()+"');");
root.setAttribute("onunload", "fireflowSvgDestroy('"+diagram.getId()+"')");
document.appendChild(root);
//构造javascript
Element scriptElm = document.createElement("script");
scriptElm.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href",
this.resourcePathPrefix+"/org/fireflow/clientwidget/resources/jquery-ui-1.10.3.custom/js/jquery-1.10.2.min.js");
root.appendChild(scriptElm);
scriptElm = document.createElement("script");
scriptElm.setAttribute("type","application/ecmascript");
root.appendChild(scriptElm);
String data = "$ff=$;";
CDATASection cdata = document.createCDATASection(data);
scriptElm.appendChild(cdata);
scriptElm = document.createElement("script");
scriptElm.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href",
this.resourcePathPrefix+"/org/fireflow/webdesigner/resources/svg/FireflowSvgControl.js");
root.appendChild(scriptElm);
//构造defs节点
defsElement = document.createElement("defs");
root.appendChild(defsElement);
//构造markers
//圆形
Element circleMk = document.createElement("marker");
circleMk.setAttribute("id", BASIC_CIRCLE_MARKER_ID);
circleMk.setAttribute("markerWidth", "8");
circleMk.setAttribute("markerHeight", "8");
circleMk.setAttribute("refX", "4");
circleMk.setAttribute("refY", "4");
circleMk.setAttribute("markerUnits","userSpaceOnUse");
defsElement.appendChild(circleMk);
Element circleTmp = document.createElement("circle");
circleTmp.setAttribute("cx", "4");
circleTmp.setAttribute("cy", "4");
circleTmp.setAttribute("r", "4");
circleTmp.setAttribute("style", "stroke:#000000;fill:none;stroke-dasharray:2 0;");
circleMk.appendChild(circleTmp);
circleMarkerMap.put("#000000", circleMk);
//实心的Block形态的三角形
Element blockArrowMk = document.createElement("marker");
blockArrowMk.setAttribute("id", BASIC_BLOCK_ARROW_MARKER_ID);
blockArrowMk.setAttribute("markerWidth", "13");
blockArrowMk.setAttribute("markerHeight", "12");
blockArrowMk.setAttribute("refX", "11");
blockArrowMk.setAttribute("refY", "6");
blockArrowMk.setAttribute("orient","auto");
blockArrowMk.setAttribute("markerUnits","userSpaceOnUse");
defsElement.appendChild(blockArrowMk);
Element blockArrow = document.createElement("path");
blockArrow.setAttribute("d", "M2,2 L2,10 L11,6 L2,2");
blockArrow.setAttribute("style", "stroke:none;fill:#000000;");
blockArrowMk.appendChild(blockArrow);
blockArrowMarkerMap.put("#000000", blockArrowMk);
//空心的的Block形态的三角形
Element blockArrowMk2 = document.createElement("marker");
blockArrowMk2.setAttribute("id", BASIC_BLOCK_ARROW_MARKER2_ID);
blockArrowMk2.setAttribute("markerWidth", "13");
blockArrowMk2.setAttribute("markerHeight", "12");
blockArrowMk2.setAttribute("refX", "11");
blockArrowMk2.setAttribute("refY", "6");
blockArrowMk2.setAttribute("orient","auto");
blockArrowMk2.setAttribute("markerUnits","userSpaceOnUse");
defsElement.appendChild(blockArrowMk2);
Element blockArrow2 = document.createElement("path");
blockArrow2.setAttribute("d", "M2,2 L2,10 L11,6 L2,2");
blockArrow2.setAttribute("style", "stroke:#000000;fill:none;stroke-dasharray:2,0;");
blockArrowMk2.appendChild(blockArrow2);
blockArrowMarker2Map.put("#000000", blockArrowMk2);
//构造id=viewport的g节点
Element g = document.createElement("g");
g.setAttribute("id", "viewport");
root.appendChild(g);
//流程节点
List<ProcessNodeShape> processNodeShapeList = diagram
.getProcessNodeShapes();
if (processNodeShapeList!=null && processNodeShapeList.size()>0){
for (ProcessNodeShape nodeShape : processNodeShapeList) {
Element cell = this.transformProcessNodeShape2Svg(nodeShape,true);
if (cell!=null){
g.appendChild(cell);
}
}
}
//注释
List<CommentShape> commentShapeList = diagram.getComments();
if (commentShapeList!=null && commentShapeList.size()>0){
for (CommentShape commentShape : commentShapeList){
Element cell = transformCommentShape2Svg(commentShape,true);
if (cell!=null){
g.appendChild(cell);
}
}
}
//Group
List<GroupShape> groupShapeList = diagram.getGroups();
if (groupShapeList!=null && groupShapeList.size()>0){
for (GroupShape groupShape : groupShapeList){
Element cell = transformGroupShape2Svg(groupShape,true);
if (cell!=null){
g.appendChild(cell);
}
}
}
//Pool
List<PoolShape> poolShapeList = diagram.getPools();
if (poolShapeList!=null && poolShapeList.size()>0){
for (PoolShape poolShape:poolShapeList){
Element cell = this.transformPool2Svg(poolShape, true);
if (cell!=null){
g.appendChild(cell);
}
}
}
//
//transition
List<TransitionShape> transitionShapeList = diagram.getTransitions();
if (transitionShapeList!=null && transitionShapeList.size()>0){
for (TransitionShape transitionShape : transitionShapeList){
Element cell = transformConnectorShape2Svg(transitionShape);
if (cell!=null){
g.appendChild(cell);
}
}
}
//association
List<AssociationShape> associationShapeList = diagram.getAssociations();
if(associationShapeList!=null && associationShapeList.size()>0){
for (AssociationShape associationShape : associationShapeList){
Element cell = transformConnectorShape2Svg(associationShape);
if (cell!=null){
g.appendChild(cell);
}
}
}
//
// //messageflow
List<MessageFlowShape> messageFlowShapeList = diagram.getMessageFlows();
if (messageFlowShapeList!=null && messageFlowShapeList.size()>0){
for (MessageFlowShape messageFlowShape : messageFlowShapeList){
Element cell = this.transformConnectorShape2Svg(messageFlowShape);
if (cell!=null){
g.appendChild(cell);
}
}
}
//根据图形长宽,设置root属性
int width = this.rightDownX-this.leftTopX;
int height = this.rightDownY - this.leftTopY;
root.setAttribute("width", Integer.toString(width));
root.setAttribute("height", Integer.toString(height));
/*
int origX = 0;
int origY = 0;
if (this.leftTopX<0){
origX = this.leftTopX;
}
if (this.leftTopY<0){
origY = this.leftTopY;
}
root.setAttribute("coordorigin", origX+","+origY);
*/
return document;
}
private Element transformProcessNodeShape2Svg(ProcessNodeShape nodeShape,boolean isTopLevelElem){
Element cell = null;
if (nodeShape instanceof StartNodeShape){
cell = this.transformStartNodeShape2Svg((StartNodeShape)nodeShape,isTopLevelElem,true);
}
else if (nodeShape instanceof EndNodeShape){
cell = this.transformEndNodeShape2Svg((EndNodeShape)nodeShape,isTopLevelElem);
}
else if (nodeShape instanceof RouterShape){
cell = this.transformRouterShape2Svg((RouterShape)nodeShape,isTopLevelElem);
}
else if (nodeShape instanceof ActivityShape){
cell = this.transformActivityShape2Svg((ActivityShape)nodeShape,true);
}
//ModelElement wfElm = nodeShape.getWorkflowElementRef();
return cell;
}
/**
*
* @param nodeShape
* @param isTopLevelElem
* @return
*/
private Element transformActivityShape2Svg(ActivityShape nodeShape,boolean isTopLevelElem){
Activity activity = (Activity)nodeShape.getWorkflowElementRef();
String imgUri = _getActivityImgUri(activity);
//1、构造viewport
Bounds newportBounds = _getViewPortBounds(nodeShape);
Rectangle figure = (Rectangle)nodeShape.getFigure();
Element nodeGroup = document.createElement("g");
nodeGroup.setAttribute(FPDLNames.ID, nodeShape.getId());
nodeGroup.setAttribute(TYPE, FPDLNames.ACTIVITY);
ModelElement wfElmRef = nodeShape.getWorkflowElementRef();
String wfElmId = wfElmRef==null?"":wfElmRef.getId();
String wfElmName = wfElmRef==null?"":wfElmRef.getName();
if (wfElmRef!=null){
nodeGroup.setAttribute(FPDLNames.REF, wfElmId);
}
//2、Activity边框
Bounds rectBounds = figure.getBounds().copy();
int thick = rectBounds.getThick();
int newWidth = rectBounds.getWidth()-thick;
int newHeight = rectBounds.getHeight()-thick;
Element rect = document.createElement("rect");
rect.setAttribute("x",Integer.toString(newportBounds.getX()+thick/2));
rect.setAttribute("y", Integer.toString(newportBounds.getY()+thick/2));
rect.setAttribute("width", Integer.toString(newWidth));
rect.setAttribute("height", Integer.toString(newHeight));
rect.setAttribute("rx", Integer.toString(rectBounds.getCornerRadius()));
rect.setAttribute("ry", Integer.toString(rectBounds.getCornerRadius()));
nodeGroup.appendChild(rect);
StringBuffer rectStyle = (new StringBuffer());
//2.1 画笔
if (figure.getBounds()!=null){
rectStyle.append("stroke-width:").append(Integer.toString(thick<0?1:thick)).append("px;");
String color = rectBounds.getColor();
rectStyle.append("stroke:").append((color==null || color.trim().equals(""))?"#000000":color).append(";");
String lineType = rectBounds.getLineType();
if (Bounds.LINETYPE_DOTTED.equals(lineType)
|| Bounds.LINETYPE_DASHED.equals(lineType)
|| Bounds.LINETYPE_DASHDOTTED.equals(lineType)){
String dashArray = rectBounds.getDashArray();
if (dashArray==null || dashArray.trim().equals("")){
if (Bounds.LINETYPE_DOTTED.equals(lineType)){
dashArray = DEFAULT_DOT_DASHARRAY;
}else if (Bounds.LINETYPE_DASHED.equals(lineType)){
dashArray = DEFAULT_DASH_DASHARRAY;
}else if (Bounds.LINETYPE_DASHDOTTED.equals(lineType)){
dashArray = DEFAULT_DOTDASH_DASHARRAY;
}
}
rectStyle.append("stroke-dasharray: ").append(dashArray).append(";");
}
}
//2.2填充
if (figure.getFulfilStyle()!=null){
//首先往defsElement中插入一个grandient
String gradientElmId = wfElmName+"_fill_pattern";
Element gradientElm = document.createElement("linearGradient");
gradientElm.setAttribute("id", gradientElmId);
gradientElm.setAttribute("spreadMethod", "pad");
String color1 = figure.getFulfilStyle().getColor1();
Element stop1 = document.createElement("stop");
stop1.setAttribute("offset", "0%");
stop1.setAttribute("stop-color", color1);
stop1.setAttribute("stop-opacity", "1");
String color2 = figure.getFulfilStyle().getColor2();
Element stop2 = document.createElement("stop");
stop2.setAttribute("offset", "100%");
stop2.setAttribute("stop-color", color2);
stop2.setAttribute("stop-opacity", "1");
String gradient = figure.getFulfilStyle().getGradientStyle();
if (gradient==null || gradient.trim().equals("") || FulfilStyle.GRADIENT_STYLE_NONE.equals(gradient)){
gradientElm.appendChild(stop2);
}else{
gradientElm.appendChild(stop1);
gradientElm.appendChild(stop2);
if (FulfilStyle.GRADIENT_STYLE_TOP2DOWN.equals(gradient)){
gradientElm.setAttribute("x1", "0%");
gradientElm.setAttribute("y1", "0%");
gradientElm.setAttribute("x2", "0%");
gradientElm.setAttribute("y2", "100%");
}
else if (FulfilStyle.GRADIENT_STYLE_UPPERLEFT2LOWERRIGHT.equals(gradient)){
gradientElm.setAttribute("x1", "0%");
gradientElm.setAttribute("y1", "0%");
gradientElm.setAttribute("x2", "100%");
gradientElm.setAttribute("y2", "100%");
}
else if (FulfilStyle.GRADIENT_STYLE_UPPERRIGHT2LOWERLEFT.equals(gradient)){
gradientElm.setAttribute("x1", "100%");
gradientElm.setAttribute("y1", "0%");
gradientElm.setAttribute("x2", "0%");
gradientElm.setAttribute("y2", "100%");
}else if (FulfilStyle.GRADIENT_STYLE_LEFT2RIGHT.equals(gradient)){
gradientElm.setAttribute("x1", "0%");
gradientElm.setAttribute("y1", "0%");
gradientElm.setAttribute("x2", "100%");
gradientElm.setAttribute("y2", "0%");//从左到右
}else{
gradientElm.setAttribute("x1", "0%");
gradientElm.setAttribute("y1", "0%");
gradientElm.setAttribute("x2", "100%");
gradientElm.setAttribute("y2", "0%");//从左到右
}
}
this.defsElement.appendChild(gradientElm);
rectStyle.append("fill:url(#").append(gradientElmId).append(");");
}else{
rectStyle.append("fill:none;");
}
rect.setAttribute("style", rectStyle.toString());
//2.3 activity的名称
String displayName = activity.getDisplayName();
if (displayName == null || displayName.trim().equals("")) {
displayName = activity.getName();
}
int padding = 6;
int spacing = 5;
//构造textbox
int textBoxPaddingY = (SVC_LOGO_RADIUS * 2 + padding+spacing );
int textBoxPaddingX = padding ;
Label contentLabel = null;
int fontSize = DEFAULT_FONT_SIZE;
if (figure.getContentLabel()!=null){
contentLabel = figure.getContentLabel().copy();
fontSize = contentLabel.getFontSize();
}else{
contentLabel = new LabelImpl();
contentLabel.setFontSize(fontSize);
}
contentLabel.setText(displayName);
Element textRect = this.drawActivityText(nodeShape, FPDLNames.ACTIVITY,
newportBounds.getX()+textBoxPaddingX, newportBounds.getY()+textBoxPaddingY,
rectBounds.getWidth()-textBoxPaddingX*2, rectBounds.getHeight()-textBoxPaddingY*2, contentLabel);
if (textRect!=null){
nodeGroup.appendChild(textRect);
}
//图形logo
if (imgUri!=null){
Element nodeImg = document.createElement("image");
nodeImg.setAttribute("x",Integer.toString( newportBounds.getX()+padding+thick));
nodeImg.setAttribute("y",Integer.toString( newportBounds.getY()+padding+thick));
nodeImg.setAttribute("width",Integer.toString( SVC_LOGO_RADIUS*2));
nodeImg.setAttribute("height",Integer.toString( SVC_LOGO_RADIUS*2));
nodeImg.setAttribute("xlink:href", this.resourcePathPrefix+imgUri);
nodeGroup.appendChild(nodeImg);
}
//构造attatched event node
List<DiagramElement> children = nodeShape.getChildren();
if (children!=null && children.size()>0){
//1、首先构造坐标系
Element attachedEvtSvg = document.createElement("svg");
attachedEvtSvg.setAttribute("x", Integer.toString(rectBounds.getX()));
attachedEvtSvg.setAttribute("y", Integer.toString(rectBounds.getY()+rectBounds.getHeight()-IMG_RADIUS));
attachedEvtSvg.setAttribute("width", Integer.toString(rectBounds.getWidth()));
attachedEvtSvg.setAttribute("height", Integer.toString(IMG_RADIUS*2+DEFAULT_FONT_SIZE+IconTextGap));
nodeGroup.appendChild(attachedEvtSvg);
for (DiagramElement child : children){
Element elm = this.transformStartNodeShape2Svg((StartNodeShape)child, false,false);
attachedEvtSvg.appendChild(elm);
}
}
if (isTopLevelElem){
_refreshDiagramSize(newportBounds);
}
return nodeGroup;
}
private Element drawActivityText(DiagramElement diagramElement,String elementType,
int x, int y, int w, int h,
Label label)
{
Element result = null;
String text = label.getText();
String fontColor = label.getFontColor();
// String fontFamily = "FangSong_GB2312";//mxUtils.getString(style,
//mxConstants.STYLE_FONTFAMILY, mxConstants.DEFAULT_FONTFAMILIES);
int fontSize = label.getFontSize();
String fireFontStyle = label.getFontStyle();
boolean isItalic = false;
if (Label.FONT_STYLE_ITALIC.equals(fireFontStyle) ||
Label.FONT_STYLE_ITALIC_BOLD.equals(fireFontStyle)){
isItalic = true;
}
// int fontStyle = mxUtils.getInt(style, mxConstants.STYLE_FONTSTYLE);
String weight = "normal";
if (Label.FONT_STYLE_BOLD.equals(fireFontStyle) ||
Label.FONT_STYLE_ITALIC_BOLD.equals(fireFontStyle)){
weight = "bold";
}
String uline = "none";
if (text != null && text.length() > 0)
{
Element foreignObject = document.createElement("foreignObject");
foreignObject.setAttribute("x", Integer.toString(x));
foreignObject.setAttribute("y", Integer.toString(y));
foreignObject.setAttribute("width", Integer.toString(w));
foreignObject.setAttribute("height", Integer.toString(h));
foreignObject.setAttribute("requiredFeatures", "http://www.w3.org/TR/SVG11/feature#Extensibility");
Element textDiv = document.createElement("div");
foreignObject.appendChild(textDiv);
textDiv.setAttribute("xmlns","http://www.w3.org/1999/xhtml");
textDiv.setAttribute("onmouseover", "this.style.cursor='pointer';");
textDiv.setAttribute("onmouseout","this.style.cursor='default';");
StringBuffer styleBufP = new StringBuffer();
//
styleBufP.append("width:").append(w).append("px;")
.append("height:").append(h).append("px;")
.append("text-align:center;word-wrap:break-word;");
//行高 等于 fontSize+3像素
styleBufP.append("line-height:100%;");
styleBufP.append("font-weight:").append(weight).append(";")
.append("font-size:").append(String.valueOf(fontSize)).append("px;")
.append("color:").append(fontColor).append(";")
.append("text-decoration:none;");
if (isItalic)
{
styleBufP.append("font-style:").append( "italic").append(";");
}
textDiv.setAttribute("style", styleBufP.toString());
//构造click handler,diagramId
StringBuffer clickHandler = new StringBuffer();
clickHandler.append("on_element_click(")
.append("'").append(diagramElement.getId()).append("',");
ModelElement wfElement = diagramElement.getWorkflowElementRef();
//构造click handler wfElement Id
if (wfElement!=null){
clickHandler.append("'").append(wfElement.getId()).append("',");
}else{
clickHandler.append("'',");
}
//构造click handler --element type
clickHandler.append("'").append(elementType).append("',");
//构造click handler --process id
clickHandler.append("'").append(workflowProcess.getId()).append("',");
//构造click handler --subprocess name
clickHandler.append("'").append(this.subProcessName).append("');");
textDiv.setAttribute("onclick", clickHandler.toString());
textDiv.appendChild(document.createTextNode(text));
result = foreignObject;
}
return result;
}
private Element drawActivityText_bak(DiagramElement diagramElement,String elementType,
int x, int y, int w, int h,
Label label)
{
Element result = null;
String text = label.getText();
String fontColor = label.getFontColor();
String fontFamily = "FangSong_GB2312";//mxUtils.getString(style,
//mxConstants.STYLE_FONTFAMILY, mxConstants.DEFAULT_FONTFAMILIES);
int fontSize = label.getFontSize();
String fireFontStyle = label.getFontStyle();
boolean isItalic = false;
if (Label.FONT_STYLE_ITALIC.equals(fireFontStyle) ||
Label.FONT_STYLE_ITALIC_BOLD.equals(fireFontStyle)){
isItalic = true;
}
// int fontStyle = mxUtils.getInt(style, mxConstants.STYLE_FONTSTYLE);
String weight = "normal";
if (Label.FONT_STYLE_BOLD.equals(fireFontStyle) ||
Label.FONT_STYLE_ITALIC_BOLD.equals(fireFontStyle)){
weight = "bold";
}
String uline = "none";
if (text != null && text.length() > 0)
{
// Applies the opacity
float opacity = 100;
String transform = null;
// if (!mxUtils.isTrue(style, mxConstants.STYLE_HORIZONTAL, true))
// {
// double cx = x + w / 2;
// double cy = y + h / 2;
// transform = "rotate(270 " + cx + " " + cy + ")";
// }
//0、构造switch元素
Element switchElm = document.createElement("switch");
result = switchElm;
//1、首先svg1.2的textarea元素
Element g = document.createElement("g");
g.setAttribute("requiredFeatures", "http://www.w3.org/Graphics/SVG/feature/1.2/#TextFlow");
switchElm.appendChild(g);
Element textArea = document.createElement("textArea");
textArea.setAttribute("width", Integer.toString(w));
textArea.setAttribute("height", Integer.toString(h));
textArea.setAttribute("font-weight", weight);
textArea.setAttribute("text-decoration", uline);
if (isItalic)
{
textArea.setAttribute("font-style", "italic");
}
textArea.setAttribute("font-size", String.valueOf(fontSize));
textArea.setAttribute("font-family", fontFamily);
textArea.setAttribute("fill", fontColor);
if (opacity != 100)
{
String value = String.valueOf(opacity / 100);
textArea.setAttribute("fill-opacity", value);
textArea.setAttribute("stroke-opacity", value);
}
g.appendChild(textArea);
textArea.appendChild(document.createTextNode(text));
//2、创建foreignObject
Element foreignObject = document.createElement("foreignObject");
foreignObject.setAttribute("x", Integer.toString(x));
foreignObject.setAttribute("y", Integer.toString(y));
foreignObject.setAttribute("width", Integer.toString(w));
foreignObject.setAttribute("height", Integer.toString(h));
foreignObject.setAttribute("requiredFeatures", "http://www.w3.org/TR/SVG11/feature#Extensibility");
switchElm.appendChild(foreignObject);
StringBuffer styleBuf = new StringBuffer();
styleBuf.append("font-weight:").append(weight).append(";")
.append("font-size:").append(String.valueOf(fontSize)).append("px;")
.append("font-family:").append(fontFamily).append(";")
.append("color:").append(fontColor).append(";");
if (isItalic)
{
styleBuf.append("font-style:").append( "italic").append(";");
}
Element pElem = document.createElement("p");
pElem.setAttribute("style", styleBuf.toString());
pElem.setAttribute("xmlns","http://www.w3.org/1999/xhtml");
pElem.appendChild(document.createTextNode(text));
foreignObject.appendChild(pElem);
//4、构造text节点
Element textElm = null;
textElm = document.createElement("text");
textElm.setAttribute("font-weight", weight);
textElm.setAttribute("font-decoration", uline);
if (isItalic)
{
textElm.setAttribute("font-style", "italic");
}
textElm.setAttribute("font-size", String.valueOf(fontSize));
textElm.setAttribute("font-family", fontFamily);
textElm.setAttribute("fill", fontColor);
if (opacity != 100)
{
String value = String.valueOf(opacity / 100);
textElm.setAttribute("fill-opacity", value);
textElm.setAttribute("stroke-opacity", value);
}
String[] lines = text.split("\n");
y += fontSize
+ (h - lines.length * (fontSize ))
/ 2 - 2;
String align = "center";
String anchor = "start";
if (align.equals("right"))
{
anchor = "end";
x += w - 0;//mxConstants.LABEL_INSET ;
}
else if (align.equals("center"))
{
anchor = "middle";
x += w / 2;
}
else
{
x += 0;//mxConstants.LABEL_INSET ;
}
textElm.setAttribute("text-anchor", anchor);
for (int i = 0; i < lines.length; i++)
{
Element tspan = document.createElement("tspan");
tspan.setAttribute("x", String.valueOf(x));
tspan.setAttribute("y", String.valueOf(y));
tspan.appendChild(document.createTextNode(lines[i]));
textElm.appendChild(tspan);
y += fontSize + 0;// mxConstants.LINESPACING;
}
if (transform != null)
{
textElm.setAttribute("transform", transform);
}
switchElm.appendChild(textElm);
//appendSvgElement(switchElm);//为什么要append在根节点呢?
}
return result;
}
/**
*
* @param nodeShape
* @param isTopLevelElem
* @return
*/
private Element transformRouterShape2Svg(RouterShape nodeShape,boolean isTopLevelElem){
String imgUri = _getSynchronizerNodeImgUri(nodeShape);
Router node = (Router)nodeShape.getWorkflowElementRef();
//计算start node group的大小以及位置
Bounds bounds = _getViewPortBounds(nodeShape);
Figure figure = nodeShape.getFigure();
Element nodeGroup = document.createElement("g");
//id 等属性
nodeGroup.setAttribute(FPDLNames.ID, nodeShape.getId());
nodeGroup.setAttribute(TYPE, FPDLNames.ROUTER);
ModelElement wfElmRef = nodeShape.getWorkflowElementRef();
if (wfElmRef!=null){
nodeGroup.setAttribute(FPDLNames.REF, wfElmRef==null?"":wfElmRef.getId());
}
Element nodeImg = document.createElement("image");
nodeImg.setAttribute("width", Integer.toString(IMG_RADIUS*2));
nodeImg.setAttribute("height", Integer.toString(IMG_RADIUS*2));
nodeImg.setAttribute("x", Integer.toString(bounds.getX()+(bounds.getWidth()/2-IMG_RADIUS)));
nodeImg.setAttribute("y", Integer.toString(bounds.getY()));
nodeImg.setAttribute("xlink:href", this.resourcePathPrefix+imgUri);
nodeGroup.appendChild(nodeImg);
String displayName = node.getDisplayName();
if(displayName!=null && !displayName.trim().equals("")){
Label titleLabel = null;
int fontSize = DEFAULT_FONT_SIZE;
if (figure.getTitleLabel()!=null){
titleLabel = figure.getTitleLabel().copy();
fontSize = titleLabel.getFontSize();
}else{
titleLabel = new LabelImpl();
titleLabel.setFontSize(fontSize);
}
titleLabel.setText(displayName);
Element textRect = this.buildTextBox(nodeShape,FPDLNames.ROUTER,
bounds.getX(), bounds.getY()+(IMG_RADIUS*2+IconTextGap),
bounds.getWidth(), (int)(fontSize), titleLabel, "middle");
nodeGroup.appendChild(textRect);
}
if (isTopLevelElem){
_refreshDiagramSize(bounds);
}
return nodeGroup;
}
/**
*
* @param nodeShape
* @param isTopLevelElem
* @return
*/
private Element transformEndNodeShape2Svg(EndNodeShape nodeShape,boolean isTopLevelElem){
String imgUri = _getSynchronizerNodeImgUri(nodeShape);
EndNode node = (EndNode)nodeShape.getWorkflowElementRef();
//计算start node group的大小以及位置
Bounds bounds = _getViewPortBounds(nodeShape);
Figure figure = nodeShape.getFigure();
Element nodeGroup = document.createElement("g");
nodeGroup.setAttribute(FPDLNames.ID, nodeShape.getId());
nodeGroup.setAttribute(TYPE, FPDLNames.END_NODE);
ModelElement wfElmRef = nodeShape.getWorkflowElementRef();
if (wfElmRef!=null){
nodeGroup.setAttribute(FPDLNames.REF, wfElmRef==null?"":wfElmRef.getId());
}
Element nodeImg = document.createElement("image");
nodeImg.setAttribute("width", Integer.toString(IMG_RADIUS*2));
nodeImg.setAttribute("height", Integer.toString(IMG_RADIUS*2));
nodeImg.setAttribute("x", Integer.toString(bounds.getX()+(bounds.getWidth()/2-IMG_RADIUS)));
nodeImg.setAttribute("y", Integer.toString(bounds.getY()));
nodeImg.setAttribute("xlink:href", this.resourcePathPrefix+imgUri);
nodeGroup.appendChild(nodeImg);
String displayName = node.getDisplayName();
if(displayName!=null && !displayName.trim().equals("")){
Label titleLabel = null;
int fontSize = DEFAULT_FONT_SIZE;
if (figure.getTitleLabel()!=null){
titleLabel = figure.getTitleLabel().copy();
fontSize = titleLabel.getFontSize();
}else{
titleLabel = new LabelImpl();
titleLabel.setFontSize(fontSize);
}
titleLabel.setText(displayName);
Element textRect = this.buildTextBox(nodeShape,FPDLNames.END_NODE,
bounds.getX(), bounds.getY()+(IMG_RADIUS*2+IconTextGap),
bounds.getWidth(), (int)(fontSize), titleLabel, "middle");
nodeGroup.appendChild(textRect);
}
if (isTopLevelElem){
_refreshDiagramSize(bounds);
}
return nodeGroup;
}
/**
*
* @param startNodeShape
* @param isTopLevelElem
* @return
*/
private Element transformStartNodeShape2Svg(StartNodeShape startNodeShape,boolean isTopLevelElem,boolean showLabel){
String imgUri = _getSynchronizerNodeImgUri(startNodeShape);
StartNode startNode = (StartNode)startNodeShape.getWorkflowElementRef();
//计算start node group的大小以及位置
Bounds bounds = _getViewPortBounds(startNodeShape);
Figure figure = startNodeShape.getFigure();
Element startNodeGroup = document.createElement("g");
//id 等属性
startNodeGroup.setAttribute(FPDLNames.ID, startNodeShape.getId());
startNodeGroup.setAttribute(TYPE, FPDLNames.START_NODE);
ModelElement wfElmRef = startNodeShape.getWorkflowElementRef();
if (wfElmRef!=null){
startNodeGroup.setAttribute(FPDLNames.REF, wfElmRef==null?"":wfElmRef.getId());
}
Element startNodeImg = document.createElement("image");
startNodeImg.setAttribute("width", Integer.toString(IMG_RADIUS*2));
startNodeImg.setAttribute("height", Integer.toString(IMG_RADIUS*2));
startNodeImg.setAttribute("x", Integer.toString(bounds.getX()+(bounds.getWidth()/2-IMG_RADIUS)));
startNodeImg.setAttribute("y", Integer.toString(bounds.getY()));
startNodeImg.setAttribute("xlink:href", this.resourcePathPrefix+imgUri);
startNodeGroup.appendChild(startNodeImg);
if (showLabel){
String displayName = startNode.getDisplayName();
if(displayName!=null && !displayName.trim().equals("")){
Label titleLabel = null;
int fontSize = DEFAULT_FONT_SIZE;
if (figure.getTitleLabel()!=null){
titleLabel = figure.getTitleLabel().copy();
fontSize = titleLabel.getFontSize();
}else{
titleLabel = new LabelImpl();
titleLabel.setFontSize(fontSize);
}
titleLabel.setText(displayName);
Element textRect = this.buildTextBox(startNodeShape,FPDLNames.START_NODE,
bounds.getX(), bounds.getY()+(IMG_RADIUS*2+IconTextGap),
bounds.getWidth(), (int)(fontSize), titleLabel,"middle");
startNodeGroup.appendChild(textRect);
}
}
if (isTopLevelElem){
_refreshDiagramSize(bounds);
}
return startNodeGroup;
}
private Element buildTextBox(DiagramElement diagramElement,String elementType,int left,int top,int width,int height,
Label label,String textAlign){
return buildTextBox(diagramElement,elementType,left,top,width,height,label,textAlign,"middle",true);
}
private Element buildTextBox(DiagramElement diagramElement,String elementType,int left,int top,int width,int height,
Label label,String textAlign,String valign,boolean ishorizonal){
int fontSize = label.getFontSize();
String fontColor = label.getFontColor();
String fontStyle = label.getFontStyle();
if (fontStyle==null || fontStyle.trim().equals("")){
fontStyle = Label.FONT_STYLE_NORMAL;
}
Element textBox = document.createElement("text");
if (ishorizonal){//横向文字坐标
if("middle".equals(textAlign)){
textBox.setAttribute("x", Integer.toString(left+width/2));
}else if ("start".equals(textAlign)){
textBox.setAttribute("x", Integer.toString(left));
}else if ("end".equals(textAlign)){
textBox.setAttribute("x", Integer.toString(left+width));
}else{
textBox.setAttribute("x", Integer.toString(left));
}
textBox.setAttribute("y", Integer.toString(top+height));
}else{
//纵向文字坐标,TODO 仅处理middle的情况
String x = Integer.toString(left+fontSize);
String y = Integer.toString(top+height/2);
textBox.setAttribute("x", x);
textBox.setAttribute("y", y);
//旋转90度
textBox.setAttribute("transform", "rotate(270 "+x+","+y+")");
}
StringBuffer textStyle = new StringBuffer();
if (!ishorizonal){
//firefox 不支持writting-mode
//textStyle.append("writing-mode: tb;");
}
textStyle.append("text-anchor:").append(textAlign).append(";")
.append("font-size:").append(fontSize).append("px;")
// .append("letter-spacing:").append("1px;")
.append("fill:").append(fontColor).append(";")
.append("stroke:none;");
if (fontStyle.equals(Label.FONT_STYLE_BOLD)){
textStyle.append("font-weight:").append("bold;");
}else if (fontStyle.equals(Label.FONT_STYLE_ITALIC)){
textStyle.append("font-style:").append("italic;");
}else if (fontStyle.equals(Label.FONT_STYLE_ITALIC_BOLD)){
textStyle.append("font-weight:").append("bold;");
textStyle.append("font-style:").append("italic;");
}
textBox.setAttribute("style", textStyle.toString());
textBox.setAttribute("onmouseover", "this.style.cursor='pointer';");
textBox.setAttribute("onmouseout", "this.style.cursor='default';");
//构造click handler,diagramId
StringBuffer clickHandler = new StringBuffer();
clickHandler.append("on_element_click(")
.append("'").append(diagramElement.getId()).append("',");
ModelElement wfElement = diagramElement.getWorkflowElementRef();
//构造click handler wfElement Id
if (wfElement!=null){
clickHandler.append("'").append(wfElement.getId()).append("',");
}else{
clickHandler.append("'',");
}
//构造click handler --element type
clickHandler.append("'").append(elementType).append("',");
//构造click handler --process id
clickHandler.append("'").append(workflowProcess.getId()).append("',");
//构造click handler --subprocess name
clickHandler.append("'").append(this.subProcessName).append("');");
textBox.setAttribute("onclick", clickHandler.toString());
Text textNode = document.createTextNode(label.getText());
textBox.appendChild(textNode);
return textBox;
}
private Element transformGroupShape2Svg(GroupShape nodeShape, boolean isTopLevelElem){
//1、构造viewport
Bounds viewportBounds = _getViewPortBounds(nodeShape);
Rectangle figure = (Rectangle)nodeShape.getFigure();
Element nodeGroup = document.createElement("g");
nodeGroup.setAttribute(FPDLNames.ID, nodeShape.getId());
nodeGroup.setAttribute(TYPE, FPDLNames.GROUP);
ModelElement wfElmRef = nodeShape.getWorkflowElementRef();
if (wfElmRef!=null){
nodeGroup.setAttribute(FPDLNames.REF, wfElmRef==null?"":wfElmRef.getId());
}
//2、Group边框
Bounds rectBounds = figure.getBounds().copy();
int thick = rectBounds.getThick();
int newWidth = rectBounds.getWidth()-thick;
int newHeight = rectBounds.getHeight()-thick;
Element rect = document.createElement("rect");
rect.setAttribute("x",Integer.toString(viewportBounds.getX()+thick/2));
rect.setAttribute("y", Integer.toString(viewportBounds.getY()+thick/2));
rect.setAttribute("width", Integer.toString(newWidth));
rect.setAttribute("height", Integer.toString(newHeight));
rect.setAttribute("rx", Integer.toString(rectBounds.getCornerRadius()));
rect.setAttribute("ry", Integer.toString(rectBounds.getCornerRadius()));
nodeGroup.appendChild(rect);
StringBuffer rectStyle = (new StringBuffer());
//2.1 画笔
if (figure.getBounds()!=null){
rectStyle.append("stroke-width:").append(Integer.toString(thick<0?1:thick)).append("px;");
String color = rectBounds.getColor();
rectStyle.append("stroke:").append((color==null || color.trim().equals(""))?"#000000":color).append(";");
String lineType = rectBounds.getLineType();
if (Bounds.LINETYPE_DOTTED.equals(lineType)
|| Bounds.LINETYPE_DASHED.equals(lineType)
|| Bounds.LINETYPE_DASHDOTTED.equals(lineType)){
String dashArray = rectBounds.getDashArray();
if (dashArray==null || dashArray.trim().equals("")){
dashArray = DEFAULT_GROUP_DASHARRAY;
}
rectStyle.append("stroke-dasharray: ").append(dashArray).append(";");
}
}
//2.2填充
if (figure.getFulfilStyle()!=null){
//首先往defsElement中插入一个grandient
String gradientElmId = nodeShape.getId()+"_fill_pattern";
Element gradientElm = document.createElement("linearGradient");
gradientElm.setAttribute("id", gradientElmId);
gradientElm.setAttribute("spreadMethod", "pad");
String color1 = figure.getFulfilStyle().getColor1();
Element stop1 = document.createElement("stop");
stop1.setAttribute("offset", "0%");
stop1.setAttribute("stop-color", color1);
stop1.setAttribute("stop-opacity", "1");
String color2 = figure.getFulfilStyle().getColor2();
Element stop2 = document.createElement("stop");
stop2.setAttribute("offset", "100%");
stop2.setAttribute("stop-color", color2);
stop2.setAttribute("stop-opacity", "1");
String gradient = figure.getFulfilStyle().getGradientStyle();
if (gradient==null || gradient.trim().equals("") || FulfilStyle.GRADIENT_STYLE_NONE.equals(gradient)){
gradientElm.appendChild(stop2);
}else{
gradientElm.appendChild(stop1);
gradientElm.appendChild(stop2);
if (FulfilStyle.GRADIENT_STYLE_TOP2DOWN.equals(gradient)){
gradientElm.setAttribute("x1", "0%");
gradientElm.setAttribute("y1", "0%");
gradientElm.setAttribute("x2", "0%");
gradientElm.setAttribute("y2", "100%");
}
else if (FulfilStyle.GRADIENT_STYLE_UPPERLEFT2LOWERRIGHT.equals(gradient)){
gradientElm.setAttribute("x1", "0%");
gradientElm.setAttribute("y1", "0%");
gradientElm.setAttribute("x2", "100%");
gradientElm.setAttribute("y2", "100%");
}
else if (FulfilStyle.GRADIENT_STYLE_UPPERRIGHT2LOWERLEFT.equals(gradient)){
gradientElm.setAttribute("x1", "100%");
gradientElm.setAttribute("y1", "0%");
gradientElm.setAttribute("x2", "0%");
gradientElm.setAttribute("y2", "100%");
}else if (FulfilStyle.GRADIENT_STYLE_LEFT2RIGHT.equals(gradient)){
gradientElm.setAttribute("x1", "0%");
gradientElm.setAttribute("y1", "0%");
gradientElm.setAttribute("x2", "100%");
gradientElm.setAttribute("y2", "0%");//从左到右
}else{
gradientElm.setAttribute("x1", "0%");
gradientElm.setAttribute("y1", "0%");
gradientElm.setAttribute("x2", "100%");
gradientElm.setAttribute("y2", "0%");//从左到右
}
}
this.defsElement.appendChild(gradientElm);
rectStyle.append("fill:url(#").append(gradientElmId).append(");");
}else{
rectStyle.append("fill:none;");
}
rect.setAttribute("style", rectStyle.toString());
//2.3 label的名称
String title = figure.getTitle();
if (title!=null && !title.trim().equals("")){
//构造textbox
int paddingLeft = thick;
Label titleLabel = figure.getTitleLabel();
int fontSize = titleLabel.getFontSize();
int width = rectBounds.getWidth()-paddingLeft*2;//一般而言,width不可能小于2倍thick
if (width<0){
width = 0;
}
int textRectHeight = (int)(fontSize+2);//设置一定的余量
int check = GROUP_TITLE_HEIGHT-textRectHeight-thick;
int paddingTop = thick;
int height = textRectHeight;
if (check>0){
paddingTop = thick+(int)(check/2);
}else{
height = GROUP_TITLE_HEIGHT-thick;
}
Element textRect = this.buildTextBox(nodeShape,FPDLNames.GROUP,
viewportBounds.getX()+paddingLeft,viewportBounds.getY()+ paddingTop,
width, height,
titleLabel,"middle");
nodeGroup.appendChild(textRect);
}
if (isTopLevelElem){
_refreshDiagramSize(viewportBounds);
}
//3、构造子节点
List<DiagramElement> children = nodeShape.getChildren();
if (children!=null && children.size()>0){
//构造一个新的view port,该viewport应该和group边框匹配
Element childrenGroup = document.createElement("svg");
childrenGroup.setAttribute("x", Integer.toString(viewportBounds.getX()+thick));
childrenGroup.setAttribute("y", Integer.toString(viewportBounds.getY()+GROUP_TITLE_HEIGHT));
childrenGroup.setAttribute("width", Integer.toString(rectBounds.getWidth()-thick*2));
childrenGroup.setAttribute("height", Integer.toString(rectBounds.getHeight()-GROUP_TITLE_HEIGHT-thick));
for (DiagramElement diagramElm : children){
if (diagramElm instanceof ProcessNodeShape){
Element elm = this.transformProcessNodeShape2Svg((ProcessNodeShape)diagramElm, false);
if (elm!=null){
childrenGroup.appendChild(elm);
}
}
// else if (diagramElm instanceof CommentShape){
// Element elm = this.transformCommentShape2Vml((CommentShape)diagramElm, false);
// if (elm!=null){
// childrenGroup.appendChild(elm);
// }
// }
}
nodeGroup.appendChild(childrenGroup);
}
return nodeGroup;
}
private Element drawCommentText(DiagramElement diagramElement,String elementType,
int x, int y, int w, int h,
Label label)
{
Element result = null;
String text = label.getText();
String fontColor = label.getFontColor();
// String fontFamily = "FangSong_GB2312";//mxUtils.getString(style,
//mxConstants.STYLE_FONTFAMILY, mxConstants.DEFAULT_FONTFAMILIES);
int fontSize = label.getFontSize();
String fireFontStyle = label.getFontStyle();
boolean isItalic = false;
if (Label.FONT_STYLE_ITALIC.equals(fireFontStyle) ||
Label.FONT_STYLE_ITALIC_BOLD.equals(fireFontStyle)){
isItalic = true;
}
// int fontStyle = mxUtils.getInt(style, mxConstants.STYLE_FONTSTYLE);
String weight = "normal";
if (Label.FONT_STYLE_BOLD.equals(fireFontStyle) ||
Label.FONT_STYLE_ITALIC_BOLD.equals(fireFontStyle)){
weight = "bold";
}
String uline = "none";
if (text != null && text.length() > 0)
{
Element foreignObject = document.createElement("foreignObject");
foreignObject.setAttribute("x", Integer.toString(x));
foreignObject.setAttribute("y", Integer.toString(y));
foreignObject.setAttribute("width", Integer.toString(w));
foreignObject.setAttribute("height", Integer.toString(h));
foreignObject.setAttribute("requiredFeatures", "http://www.w3.org/TR/SVG11/feature#Extensibility");
Element textDiv = document.createElement("div");
textDiv.setAttribute("xmlns","http://www.w3.org/1999/xhtml");
foreignObject.appendChild(textDiv);
StringBuffer styleBuf = new StringBuffer();
//
styleBuf.append("width:").append(w).append("px;")
.append("height:").append(h).append("px;")
.append("word-wrap:break-word;");
//行高 等于 fontSize+3像素
styleBuf.append("line-height:100%;");
styleBuf.append("font-weight:").append(weight).append(";")
.append("font-size:").append(String.valueOf(fontSize)).append("px;")
.append("color:").append(fontColor).append(";");
if (isItalic)
{
styleBuf.append("font-style:").append( "italic").append(";");
}
textDiv.setAttribute("style", styleBuf.toString());
StringTokenizer tokenizer = new StringTokenizer(text,"\n",true);
while (tokenizer.hasMoreTokens()){
String tmpStr = tokenizer.nextToken();
if (tmpStr.equals("\n")){
Element brElm = document.createElement("br");
textDiv.appendChild(brElm);
}else{
Element pElem = document.createElement("span");
pElem.appendChild(document.createTextNode(tmpStr));
textDiv.appendChild(pElem);
}
}
result = foreignObject;
}
return result;
}
private Element transformCommentShape2Svg(CommentShape commentShape,boolean isTopLevelElm){
//1、构造view port
Bounds viewportBounds = _getViewPortBounds(commentShape);
Rectangle figure = (Rectangle)commentShape.getFigure();
Element nodeGroup = document.createElement("g");
nodeGroup.setAttribute(FPDLNames.ID, commentShape.getId());
nodeGroup.setAttribute(TYPE, FPDLNames.COMMENT);
ModelElement wfElmRef = commentShape.getWorkflowElementRef();
if (wfElmRef!=null){
nodeGroup.setAttribute(FPDLNames.REF, wfElmRef==null?"":wfElmRef.getId());
}
//2、Comment边框
Bounds rectBounds = figure.getBounds().copy();
int thick = rectBounds.getThick();
int newWidth = rectBounds.getWidth()-thick;
int newHeight = rectBounds.getHeight()-thick;
Element polyline = document.createElement("path");
StringBuffer pointList = new StringBuffer();
pointList.append("M ").append(rectBounds.getX()+(int)(rectBounds.getWidth()/3)).append(" ").append(rectBounds.getY()).append(" ")
.append("L ").append(rectBounds.getX()).append(" ").append(rectBounds.getY()).append(" ")
.append("L ").append(rectBounds.getX()).append(" ").append(rectBounds.getY()+rectBounds.getHeight()).append(" ")
.append("L ").append(rectBounds.getX()+(int)(rectBounds.getWidth()/3)).append(" ").append(rectBounds.getY()+rectBounds.getHeight());
polyline.setAttribute("d", pointList.toString());
polyline.setAttribute("fill", "none");
nodeGroup.appendChild(polyline);
//2.1 画笔
StringBuffer polylineStyle = (new StringBuffer());
if (figure.getBounds()!=null){
polylineStyle.append("stroke-width:").append(Integer.toString(thick<0?1:thick)).append("px;");
String color = rectBounds.getColor();
polylineStyle.append("stroke:").append((color==null || color.trim().equals(""))?"#000000":color).append(";");
String lineType = rectBounds.getLineType();
if (Bounds.LINETYPE_DOTTED.equals(lineType)
|| Bounds.LINETYPE_DASHED.equals(lineType)
|| Bounds.LINETYPE_DASHDOTTED.equals(lineType)){
String dashArray = rectBounds.getDashArray();
if (dashArray==null || dashArray.trim().equals("")){
if (Bounds.LINETYPE_DOTTED.equals(lineType)){
dashArray = DEFAULT_DOT_DASHARRAY;
}else if (Bounds.LINETYPE_DASHED.equals(lineType)){
dashArray = DEFAULT_DASH_DASHARRAY;
}else if (Bounds.LINETYPE_DASHDOTTED.equals(lineType)){
dashArray = DEFAULT_DOTDASH_DASHARRAY;
}
}
polylineStyle.append("stroke-dasharray: ").append(dashArray).append(";");
}
}
polyline.setAttribute("style", polylineStyle.toString());
//2.2 内容区域填充
Element contentBackground = document.createElement("rect");
contentBackground.setAttribute("x", Integer.toString(rectBounds.getX()+thick+1));
contentBackground.setAttribute("y", Integer.toString(rectBounds.getY()+thick+1));
contentBackground.setAttribute("width", Integer.toString(newWidth-2));
contentBackground.setAttribute("height", Integer.toString(newHeight-2));
nodeGroup.appendChild(contentBackground);
StringBuffer contentBackgroundStyle = (new StringBuffer());
contentBackgroundStyle.append("stroke:none;");
if (figure.getFulfilStyle()!=null){
//首先往defsElement中插入一个grandient
String gradientElmId = commentShape.getId()+"_fill_pattern";
Element gradientElm = document.createElement("linearGradient");
gradientElm.setAttribute("id", gradientElmId);
gradientElm.setAttribute("spreadMethod", "pad");
String color1 = figure.getFulfilStyle().getColor1();
Element stop1 = document.createElement("stop");
stop1.setAttribute("offset", "0%");
stop1.setAttribute("stop-color", color1);
stop1.setAttribute("stop-opacity", "1");
String color2 = figure.getFulfilStyle().getColor2();
Element stop2 = document.createElement("stop");
stop2.setAttribute("offset", "100%");
stop2.setAttribute("stop-color", color2);
stop2.setAttribute("stop-opacity", "1");
String gradient = figure.getFulfilStyle().getGradientStyle();
if (gradient==null || gradient.trim().equals("") || FulfilStyle.GRADIENT_STYLE_NONE.equals(gradient)){
gradientElm.appendChild(stop2);
}else{
gradientElm.appendChild(stop1);
gradientElm.appendChild(stop2);
if (FulfilStyle.GRADIENT_STYLE_TOP2DOWN.equals(gradient)){
gradientElm.setAttribute("x1", "0%");
gradientElm.setAttribute("y1", "0%");
gradientElm.setAttribute("x2", "0%");
gradientElm.setAttribute("y2", "100%");
}
else if (FulfilStyle.GRADIENT_STYLE_UPPERLEFT2LOWERRIGHT.equals(gradient)){
gradientElm.setAttribute("x1", "0%");
gradientElm.setAttribute("y1", "0%");
gradientElm.setAttribute("x2", "100%");
gradientElm.setAttribute("y2", "100%");
}
else if (FulfilStyle.GRADIENT_STYLE_UPPERRIGHT2LOWERLEFT.equals(gradient)){
gradientElm.setAttribute("x1", "100%");
gradientElm.setAttribute("y1", "0%");
gradientElm.setAttribute("x2", "0%");
gradientElm.setAttribute("y2", "100%");
}else if (FulfilStyle.GRADIENT_STYLE_LEFT2RIGHT.equals(gradient)){
gradientElm.setAttribute("x1", "0%");
gradientElm.setAttribute("y1", "0%");
gradientElm.setAttribute("x2", "100%");
gradientElm.setAttribute("y2", "0%");//从左到右
}else{
gradientElm.setAttribute("x1", "0%");
gradientElm.setAttribute("y1", "0%");
gradientElm.setAttribute("x2", "100%");
gradientElm.setAttribute("y2", "0%");//从左到右
}
}
this.defsElement.appendChild(gradientElm);
contentBackgroundStyle.append("fill:url(#").append(gradientElmId).append(");");
}else{
contentBackgroundStyle.append("fill:none;");
}
contentBackground.setAttribute("style", contentBackgroundStyle.toString());
//comment的内容
String contentTxt = figure.getContent();
if (contentTxt!=null && !contentTxt.trim().equals("")){
//构造textbox
int padding = 4;
int spacing = 0;
int textBoxPadding = (padding+thick);
Label contentLabel = figure.getContentLabel().copy();
Element textRect = this.drawCommentText(commentShape,FPDLNames.COMMENT,
viewportBounds.getX()+textBoxPadding, viewportBounds.getY()+textBoxPadding,
newWidth-textBoxPadding*2, newHeight -textBoxPadding*2,
contentLabel);
nodeGroup.appendChild(textRect);
}
if (isTopLevelElm){
_refreshDiagramSize(viewportBounds);
}
return nodeGroup;
}
private Element transformPool2Svg(PoolShape nodeShape, boolean isTopLevelElem){
//1、构造viewport
Bounds viewportBounds = _getViewPortBounds(nodeShape);
Rectangle figure = (Rectangle)nodeShape.getFigure();
Element nodeGroup = document.createElement("g");
nodeGroup.setAttribute(FPDLNames.ID, nodeShape.getId());
nodeGroup.setAttribute(TYPE, FPDLNames.POOL);
ModelElement wfElmRef = nodeShape.getWorkflowElementRef();
if (wfElmRef!=null){
nodeGroup.setAttribute(FPDLNames.REF, wfElmRef==null?"":wfElmRef.getId());
}
//2、构造pool边框
Bounds rectBounds = figure.getBounds().copy();
int thick = rectBounds.getThick();
int newWidth = rectBounds.getWidth()-thick;
int newHeight = rectBounds.getHeight()-thick;
Element rect = document.createElement("rect");
rect.setAttribute("x",Integer.toString( rectBounds.getX()+thick/2));
rect.setAttribute("y",Integer.toString( rectBounds.getY()+thick/2));
rect.setAttribute("width", Integer.toString(newWidth));
rect.setAttribute("height", Integer.toString(newHeight));
nodeGroup.appendChild(rect);
Element line = document.createElement("line");
if (Diagram.VERTICAL.equals(diagram.getDirection())){
line.setAttribute("x1", Integer.toString(rectBounds.getX()+thick));
line.setAttribute("y1", Integer.toString(rectBounds.getY()+POOL_LANE_TITLE_HEIGHT));
line.setAttribute("x2", Integer.toString(rectBounds.getX()+(thick+newWidth)));
line.setAttribute("y2", Integer.toString(rectBounds.getY()+POOL_LANE_TITLE_HEIGHT));
}else{
line.setAttribute("x1", Integer.toString(rectBounds.getX()+POOL_LANE_TITLE_HEIGHT));
line.setAttribute("y1", Integer.toString(rectBounds.getY()+thick));
line.setAttribute("x2", Integer.toString(rectBounds.getX()+POOL_LANE_TITLE_HEIGHT));
line.setAttribute("y2", Integer.toString(rectBounds.getY()+(thick+newHeight)));
}
nodeGroup.appendChild(line);
//2.1画笔
StringBuffer rectStyle = (new StringBuffer());
//2.1 画笔
if (figure.getBounds()!=null){
rectStyle.append("stroke-width:").append(Integer.toString(thick<0?1:thick)).append("px;");
String color = rectBounds.getColor();
rectStyle.append("stroke:").append((color==null || color.trim().equals(""))?"#000000":color).append(";");
String lineType = rectBounds.getLineType();
if (Bounds.LINETYPE_DOTTED.equals(lineType)
|| Bounds.LINETYPE_DASHED.equals(lineType)
|| Bounds.LINETYPE_DASHDOTTED.equals(lineType)){
String dashArray = rectBounds.getDashArray();
if (dashArray==null || dashArray.trim().equals("")){
if (Bounds.LINETYPE_DOTTED.equals(lineType)){
dashArray = DEFAULT_DOT_DASHARRAY;
}else if (Bounds.LINETYPE_DASHED.equals(lineType)){
dashArray = DEFAULT_DASH_DASHARRAY;
}else if (Bounds.LINETYPE_DASHDOTTED.equals(lineType)){
dashArray = DEFAULT_DOTDASH_DASHARRAY;
}
}
rectStyle.append("stroke-dasharray: ").append(dashArray).append(";");
}
}
line.setAttribute("style", rectStyle.toString());
//2.2填充
if (figure.getFulfilStyle()!=null){
//首先往defsElement中插入一个grandient
String gradientElmId = nodeShape.getId()+"_fill_pattern";
Element gradientElm = document.createElement("linearGradient");
gradientElm.setAttribute("id", gradientElmId);
gradientElm.setAttribute("spreadMethod", "pad");
String color1 = figure.getFulfilStyle().getColor1();
Element stop1 = document.createElement("stop");
stop1.setAttribute("offset", "0%");
stop1.setAttribute("stop-color", color1);
stop1.setAttribute("stop-opacity", "1");
String color2 = figure.getFulfilStyle().getColor2();
Element stop2 = document.createElement("stop");
stop2.setAttribute("offset", "100%");
stop2.setAttribute("stop-color", color2);
stop2.setAttribute("stop-opacity", "1");
String gradient = figure.getFulfilStyle().getGradientStyle();
if (gradient==null || gradient.trim().equals("") || FulfilStyle.GRADIENT_STYLE_NONE.equals(gradient)){
gradientElm.appendChild(stop2);
}else{
gradientElm.appendChild(stop1);
gradientElm.appendChild(stop2);
if (FulfilStyle.GRADIENT_STYLE_TOP2DOWN.equals(gradient)){
gradientElm.setAttribute("x1", "0%");
gradientElm.setAttribute("y1", "0%");
gradientElm.setAttribute("x2", "0%");
gradientElm.setAttribute("y2", "100%");
}
else if (FulfilStyle.GRADIENT_STYLE_UPPERLEFT2LOWERRIGHT.equals(gradient)){
gradientElm.setAttribute("x1", "0%");
gradientElm.setAttribute("y1", "0%");
gradientElm.setAttribute("x2", "100%");
gradientElm.setAttribute("y2", "100%");
}
else if (FulfilStyle.GRADIENT_STYLE_UPPERRIGHT2LOWERLEFT.equals(gradient)){
gradientElm.setAttribute("x1", "100%");
gradientElm.setAttribute("y1", "0%");
gradientElm.setAttribute("x2", "0%");
gradientElm.setAttribute("y2", "100%");
}else if (FulfilStyle.GRADIENT_STYLE_LEFT2RIGHT.equals(gradient)){
gradientElm.setAttribute("x1", "0%");
gradientElm.setAttribute("y1", "0%");
gradientElm.setAttribute("x2", "100%");
gradientElm.setAttribute("y2", "0%");//从左到右
}else{
gradientElm.setAttribute("x1", "0%");
gradientElm.setAttribute("y1", "0%");
gradientElm.setAttribute("x2", "100%");
gradientElm.setAttribute("y2", "0%");//从左到右
}
}
this.defsElement.appendChild(gradientElm);
rectStyle.append("fill:url(#").append(gradientElmId).append(");");
}else{
rectStyle.append("fill:none;");
}
rect.setAttribute("style", rectStyle.toString());
//2.3 label的名称
String title = figure.getTitle();
if (title!=null && !title.trim().equals("")){
//构造textbox
int paddingLeft = ( thick);
Label titleLabel = figure.getTitleLabel().copy();
int fontSize = titleLabel.getFontSize();;
int textRectHeight = (int)(fontSize+2);//设置一定的余量
int check = POOL_LANE_TITLE_HEIGHT-textRectHeight-thick;
int paddingTop = thick;
if (check>0){
paddingTop = thick+(int)(check/2);
}else{
textRectHeight = POOL_LANE_TITLE_HEIGHT-thick;
}
//纵向泳道
if (Diagram.VERTICAL.equals(diagram.getDirection())){
int width = rectBounds.getWidth()-paddingLeft*2;//一般而言,width不可能小于2倍thick
if (width<0){
width = 0;
}
Element textRect = this.buildTextBox(nodeShape,FPDLNames.POOL,
rectBounds.getX()+paddingLeft, rectBounds.getY()+paddingTop,
width, textRectHeight,
titleLabel,"middle");
nodeGroup.appendChild(textRect);
}
else{//横向泳道
int height = rectBounds.getHeight()-paddingLeft*2;
Element textRect = this.buildTextBox(nodeShape,FPDLNames.POOL,
rectBounds.getX()+paddingTop,rectBounds.getY()+paddingLeft,
textRectHeight,
height,
titleLabel, "middle","middle",false);
nodeGroup.appendChild(textRect);
}
}
if (isTopLevelElem){
_refreshDiagramSize(viewportBounds);
}
//3、构造子节点
List<DiagramElement> children = nodeShape.getChildren();
if (children!=null && children.size()>0){
//构造一个新的坐标系统
Element childrenGroup = document.createElement("svg");
// StringBuffer tmpStyle = new StringBuffer();
if (Diagram.VERTICAL.equals(diagram.getDirection())){
childrenGroup.setAttribute("x", Integer.toString(rectBounds.getX()+thick));
childrenGroup.setAttribute("y", Integer.toString(rectBounds.getY()+POOL_LANE_TITLE_HEIGHT));
childrenGroup.setAttribute("width", Integer.toString(newWidth));
childrenGroup.setAttribute("height", Integer.toString(rectBounds.getHeight()-GROUP_TITLE_HEIGHT-thick));
}else{
childrenGroup.setAttribute("x", Integer.toString(rectBounds.getX()+POOL_LANE_TITLE_HEIGHT));
childrenGroup.setAttribute("y", Integer.toString(rectBounds.getY()+thick));
childrenGroup.setAttribute("width", Integer.toString(rectBounds.getWidth()-POOL_LANE_TITLE_HEIGHT-thick));
childrenGroup.setAttribute("height", Integer.toString(newHeight));
// tmpStyle.append("position:absolute;")
// .append("left:").append().append("px;")
// .append("top:").append().append("px;")
// .append("width:").append().append("px;")
// .append("height:").append(newHeight).append("px");
}
// if (Diagram.VERTICAL.equals(diagram.getDirection())){
// StringBuffer coordSizeBufTmp = new StringBuffer();
// coordSizeBufTmp.append(newWidth).append(",").append(rectBounds.getHeight()-GROUP_TITLE_HEIGHT-thick);
// childrenGroup.setAttribute("coordsize", coordSizeBufTmp.toString());
// }else{
// StringBuffer coordSizeBufTmp = new StringBuffer();
// coordSizeBufTmp.append(viewportBounds.getWidth()-POOL_LANE_TITLE_HEIGHT-thick).append(",").append(newHeight);
// childrenGroup.setAttribute("coordsize", coordSizeBufTmp.toString());
// }
int offset = 0;
int laneCount = children.size();
for (int index = 0;index<laneCount;index++){
DiagramElement diagramElm = children.get(index);
if (diagramElm instanceof LaneShape){
LaneShape laneShape = (LaneShape)diagramElm;
Element elm = this.transformLane2Svg(laneShape, offset,index,laneCount);
if (elm!=null){
childrenGroup.appendChild(elm);
}
Rectangle rectTmp = (Rectangle)laneShape.getFigure();
Bounds tmpBounds = rectTmp.getBounds();
if (Diagram.VERTICAL.equals(diagram.getDirection())){
offset = offset+tmpBounds.getWidth();
}else{
offset = offset+tmpBounds.getHeight();
}
}
}
nodeGroup.appendChild(childrenGroup);
}
return nodeGroup;
}
private Element transformLane2Svg(LaneShape nodeShape,int offset,int laneIndex,int laneCount){
Bounds viewportBounds = _getViewPortBounds(nodeShape);
Rectangle figure = (Rectangle)nodeShape.getFigure();
Element nodeGroup = document.createElement("g");
int x = 0;
int y = 0;
if (Diagram.VERTICAL.equals(diagram.getDirection())) {
x = offset;
y = 0;
} else {
x = 0;
y = offset;
}
nodeGroup.setAttribute(FPDLNames.ID, nodeShape.getId());
nodeGroup.setAttribute(TYPE, FPDLNames.LANE);
ModelElement wfElmRef = nodeShape.getWorkflowElementRef();
if (wfElmRef!=null){
nodeGroup.setAttribute(FPDLNames.REF, wfElmRef==null?"":wfElmRef.getId());
}
Bounds rectBounds = figure.getBounds().copy();
int thick = rectBounds.getThick();
int newWidth = rectBounds.getWidth()-thick*2;
int newHeight = rectBounds.getHeight()-thick*2;
String title = figure.getTitle();
//1、填充
Element rect = document.createElement("rect");
rect.setAttribute("width", Integer.toString(newWidth));
rect.setAttribute("height", Integer.toString(newHeight));
rect.setAttribute("x", Integer.toString(x+thick));
rect.setAttribute("y", Integer.toString(y+thick));
nodeGroup.appendChild(rect);
StringBuffer fillStyle = new StringBuffer();
fillStyle.append("stroke:none;");
if (figure.getFulfilStyle()!=null){
//首先往defsElement中插入一个grandient
String gradientElmId = nodeShape.getId()+"_fill_pattern";
Element gradientElm = document.createElement("linearGradient");
gradientElm.setAttribute("id", gradientElmId);
gradientElm.setAttribute("spreadMethod", "pad");
String color1 = figure.getFulfilStyle().getColor1();
Element stop1 = document.createElement("stop");
stop1.setAttribute("offset", "0%");
stop1.setAttribute("stop-color", color1);
stop1.setAttribute("stop-opacity", "1");
String color2 = figure.getFulfilStyle().getColor2();
Element stop2 = document.createElement("stop");
stop2.setAttribute("offset", "100%");
stop2.setAttribute("stop-color", color2);
stop2.setAttribute("stop-opacity", "1");
String gradient = figure.getFulfilStyle().getGradientStyle();
if (gradient==null || gradient.trim().equals("") || FulfilStyle.GRADIENT_STYLE_NONE.equals(gradient)){
gradientElm.appendChild(stop2);
}else{
gradientElm.appendChild(stop1);
gradientElm.appendChild(stop2);
if (FulfilStyle.GRADIENT_STYLE_TOP2DOWN.equals(gradient)){
gradientElm.setAttribute("x1", "0%");
gradientElm.setAttribute("y1", "0%");
gradientElm.setAttribute("x2", "0%");
gradientElm.setAttribute("y2", "100%");
}
else if (FulfilStyle.GRADIENT_STYLE_UPPERLEFT2LOWERRIGHT.equals(gradient)){
gradientElm.setAttribute("x1", "0%");
gradientElm.setAttribute("y1", "0%");
gradientElm.setAttribute("x2", "100%");
gradientElm.setAttribute("y2", "100%");
}
else if (FulfilStyle.GRADIENT_STYLE_UPPERRIGHT2LOWERLEFT.equals(gradient)){
gradientElm.setAttribute("x1", "100%");
gradientElm.setAttribute("y1", "0%");
gradientElm.setAttribute("x2", "0%");
gradientElm.setAttribute("y2", "100%");
}else if (FulfilStyle.GRADIENT_STYLE_LEFT2RIGHT.equals(gradient)){
gradientElm.setAttribute("x1", "0%");
gradientElm.setAttribute("y1", "0%");
gradientElm.setAttribute("x2", "100%");
gradientElm.setAttribute("y2", "0%");//从左到右
}else{
gradientElm.setAttribute("x1", "0%");
gradientElm.setAttribute("y1", "0%");
gradientElm.setAttribute("x2", "100%");
gradientElm.setAttribute("y2", "0%");//从左到右
}
}
this.defsElement.appendChild(gradientElm);
fillStyle.append("fill:url(#").append(gradientElmId).append(");");
}else{
fillStyle.append("fill:none;");
}
rect.setAttribute("style", fillStyle.toString());
//2、边框
StringBuffer strokeStyle = (new StringBuffer());
//2.1 画笔
if (figure.getBounds()!=null){
strokeStyle.append("stroke-width:").append(Integer.toString(thick<0?1:thick)).append("px;");
String color = rectBounds.getColor();
strokeStyle.append("stroke:").append((color==null || color.trim().equals(""))?"#000000":color).append(";");
String lineType = rectBounds.getLineType();
if (Bounds.LINETYPE_DOTTED.equals(lineType)
|| Bounds.LINETYPE_DASHED.equals(lineType)
|| Bounds.LINETYPE_DASHDOTTED.equals(lineType)){
String dashArray = rectBounds.getDashArray();
if (dashArray==null || dashArray.trim().equals("")){
if (Bounds.LINETYPE_DOTTED.equals(lineType)){
dashArray = DEFAULT_DOT_DASHARRAY;
}else if (Bounds.LINETYPE_DASHED.equals(lineType)){
dashArray = DEFAULT_DASH_DASHARRAY;
}else if (Bounds.LINETYPE_DASHDOTTED.equals(lineType)){
dashArray = DEFAULT_DOTDASH_DASHARRAY;
}
}
strokeStyle.append("stroke-dasharray: ").append(dashArray).append(";");
}
}
// lane边框
if (Diagram.VERTICAL.equals(diagram.getDirection())){
//横线2
if (title!=null && !title.trim().equals("")){
Element line = document.createElement("line");
line.setAttribute("x1", Integer.toString(x+thick));
line.setAttribute("y1", Integer.toString(y+POOL_LANE_TITLE_HEIGHT));
// String from = thick + "," + POOL_LANE_TITLE_HEIGHT;
// line.setAttribute("from", from);
line.setAttribute("x2", Integer.toString(x+(thick+newWidth)));
line.setAttribute("y2", Integer.toString(y+POOL_LANE_TITLE_HEIGHT));
// String to = (thick+newWidth) + "," + POOL_LANE_TITLE_HEIGHT;
// line.setAttribute("to", to);
if (strokeStyle!=null){
line.setAttribute("style", strokeStyle.toString());
}
nodeGroup.appendChild(line);
}
//竖线
if (laneIndex > 0) {
Element line = document.createElement("line");
line.setAttribute("x1", Integer.toString(x+thick));
line.setAttribute("y1", Integer.toString(y+thick));
// String from = thick + "," + thick;
// line.setAttribute("from", from);
line.setAttribute("x2", Integer.toString(x+(thick+newHeight)));
line.setAttribute("y2", Integer.toString(y+thick));
// String to = (thick+newHeight) + "," + (thick );
// line.setAttribute("to", to);
if (strokeStyle!=null){
line.setAttribute("style", strokeStyle.toString());
}
nodeGroup.appendChild(line);
}
}else{
//竖线1
//竖线2
if (title!=null && !title.trim().equals("")){
Element line = document.createElement("line");
line.setAttribute("x1", Integer.toString(x+POOL_LANE_TITLE_HEIGHT));
line.setAttribute("y1", Integer.toString(y+thick));
// String from = POOL_LANE_TITLE_HEIGHT + "," + thick;
// line.setAttribute("from", from);
line.setAttribute("x2", Integer.toString(x+POOL_LANE_TITLE_HEIGHT));
line.setAttribute("y2", Integer.toString(y+(thick + newHeight)));
// String to = POOL_LANE_TITLE_HEIGHT + "," + (thick + newHeight);
// line.setAttribute("to", to);
if (strokeStyle!=null){
line.setAttribute("style", strokeStyle.toString());
}
nodeGroup.appendChild(line);
}
//横线
if (laneIndex > 0) {
Element line = document.createElement("line");
line.setAttribute("x1", Integer.toString(x+thick));
line.setAttribute("y1", Integer.toString(y+thick));
// String from = thick + "," + thick;
// line.setAttribute("from", from);
line.setAttribute("x2", Integer.toString(x+(thick+newWidth)));
line.setAttribute("y2", Integer.toString(y+thick));
// String to = (thick+newWidth) + "," + (thick );
// line.setAttribute("to", to);
if (strokeStyle!=null){
line.setAttribute("style", strokeStyle.toString());
}
nodeGroup.appendChild(line);
}
}
//3、label的名称
if (title!=null && !title.trim().equals("")){
int paddingLeft = ( thick);
Label titleLabel = figure.getTitleLabel().copy();
int fontSize = titleLabel.getFontSize();
int textRectHeight = (int)(fontSize+2);//设置一定的余量
int check = POOL_LANE_TITLE_HEIGHT-textRectHeight-thick;
int paddingTop = thick;
if (check>0){
paddingTop = thick+(int)(check/2);
}else{
textRectHeight = POOL_LANE_TITLE_HEIGHT-thick;
}
//纵向泳道
if (Diagram.VERTICAL.equals(diagram.getDirection())){
int width = rectBounds.getWidth()-paddingLeft*2;//一般而言,width不可能小于2倍thick
if (width<0){
width = 0;
}
Element textRect = this.buildTextBox(nodeShape,FPDLNames.LANE,x+paddingLeft, y+paddingTop,
width, textRectHeight,
titleLabel, "middle");
nodeGroup.appendChild(textRect);
}
else{//横向泳道
int height = rectBounds.getHeight()-paddingLeft*2;
Element textRect = this.buildTextBox(nodeShape,FPDLNames.LANE,x+paddingTop,y+paddingLeft,
textRectHeight,
height,
titleLabel, "middle","middle",false);
nodeGroup.appendChild(textRect);
}
}
//4、构造子节点
List<DiagramElement> children = nodeShape.getChildren();
if (children!=null && children.size()>0){
//构造一个新的坐标系统
Element childrenGroup = document.createElement("svg");
if (Diagram.VERTICAL.equals(diagram.getDirection())){
childrenGroup.setAttribute("x", Integer.toString(x+thick));
childrenGroup.setAttribute("y", Integer.toString(y+POOL_LANE_TITLE_HEIGHT));
childrenGroup.setAttribute("width", Integer.toString(newWidth));
childrenGroup.setAttribute("height", Integer.toString(rectBounds.getHeight()-GROUP_TITLE_HEIGHT-thick));
}else{
childrenGroup.setAttribute("x", Integer.toString(x+POOL_LANE_TITLE_HEIGHT));
childrenGroup.setAttribute("y", Integer.toString(y+thick));
childrenGroup.setAttribute("width", Integer.toString(rectBounds.getWidth()-POOL_LANE_TITLE_HEIGHT-thick));
childrenGroup.setAttribute("height", Integer.toString(newHeight));
}
for (DiagramElement diagramElm : children){
if (diagramElm instanceof ProcessNodeShape){
Element elm = this.transformProcessNodeShape2Svg((ProcessNodeShape)diagramElm, false);
if (elm!=null){
childrenGroup.appendChild(elm);
}
}
else if (diagramElm instanceof CommentShape){
Element elm = this.transformCommentShape2Svg((CommentShape)diagramElm, false);
if (elm!=null){
childrenGroup.appendChild(elm);
}
}
else if (diagram instanceof GroupShape){
Element elm = this.transformGroupShape2Svg((GroupShape)diagram, false);
if (elm!=null){
childrenGroup.appendChild(elm);
}
}
}
nodeGroup.appendChild(childrenGroup);
}
return nodeGroup;
}
private Element transformConnectorShape2Svg(ConnectorShape connectorShape){
NodeShape fromNodeShape = connectorShape.getFromNode();
NodeShape toNodeShape = connectorShape.getToNode();
ModelElement wfElm = connectorShape.getWorkflowElementRef();
String wfElmId = wfElm==null?"null":wfElm.getId();
if (fromNodeShape==null || toNodeShape==null){
log.warn("TransitionShape[Id="+connectorShape.getId()+
",WfElemId="+wfElmId+"]的 from_node或者to_node为空,无法绘制该连接线");
return null;
}
Bounds absoluteFromNodeBounds = this._getAbsoluteBounds(fromNodeShape);
Bounds absoluteToNodeBounds = this._getAbsoluteBounds(toNodeShape);
if (absoluteFromNodeBounds==null || absoluteToNodeBounds==null){
log.warn("TransitionShape[Id="+connectorShape.getId()+
",WfElemId="+wfElmId+"]的 from_node或者to_node的bounds为空,无法绘制该连接线");
return null;
}
Line fireLine = (Line)connectorShape.getFigure();
List<Point> linePoints = fireLine.getPoints();
Point fromRefPoint = null;//from_anchor的参考点
Point toRefPoint = null;//to_anchor的参考点
if (linePoints==null || linePoints.size()==0){
fromRefPoint = new Point();
fromRefPoint.setX(absoluteToNodeBounds.getX()+absoluteToNodeBounds.getWidth()/2);
fromRefPoint.setY(absoluteToNodeBounds.getY()+absoluteToNodeBounds.getHeight()/2);
}else{
fromRefPoint = linePoints.get(0);
}
if (linePoints==null || linePoints.size()==0){
toRefPoint = new Point();
toRefPoint.setX(absoluteFromNodeBounds.getX()+absoluteFromNodeBounds.getWidth()/2);
toRefPoint.setY(absoluteFromNodeBounds.getY()+absoluteFromNodeBounds.getHeight()/2);
}else{
toRefPoint = linePoints.get(linePoints.size()-1);
}
//计算from_anchor
Point fromAnchor = null;
fromAnchor = _calculateAnchor(fromNodeShape,absoluteFromNodeBounds,fromRefPoint);
//计算to_anchor
Point toAnchor = null;
toAnchor = _calculateAnchor(toNodeShape,absoluteToNodeBounds,toRefPoint);
Element groupElement = document.createElement("g");
String elementType = null;
groupElement.setAttribute(FPDLNames.ID, connectorShape.getId());
if (connectorShape instanceof TransitionShape){
elementType = FPDLNames.TRANSITION;
}
else if (connectorShape instanceof MessageFlowShape){
elementType = FPDLNames.MESSAGEFLOW;
}
else if (connectorShape instanceof AssociationShape){
elementType = FPDLNames.ASSOCIATION;
}
groupElement.setAttribute(TYPE, elementType);
ModelElement wfElmRef = connectorShape.getWorkflowElementRef();
if (wfElmRef!=null){
groupElement.setAttribute(FPDLNames.REF, wfElmRef==null?"":wfElmRef.getId());
}
//polyline
Element polylineElm = document.createElement("polyline");
groupElement.appendChild(polylineElm);
polylineElm.setAttribute("points", _makePointsSeq(fromAnchor.copy(),toAnchor.copy(),linePoints));
//2.1 画笔
StringBuffer lineStyle = (new StringBuffer());
Bounds lineBounds = fireLine.getBounds();
String color = "#000000";
if (lineBounds!=null){
int thick = lineBounds.getThick();
lineStyle.append("stroke-width:").append(Integer.toString(thick<0?1:thick)).append("px;");
color = lineBounds.getColor();
color = (color==null || color.trim().equals(""))?"#000000":color;
lineStyle.append("stroke:").append(color).append(";");
String lineType = lineBounds.getLineType();
if (Bounds.LINETYPE_DOTTED.equals(lineType)
|| Bounds.LINETYPE_DASHED.equals(lineType)
|| Bounds.LINETYPE_DASHDOTTED.equals(lineType)){
String dashArray = lineBounds.getDashArray();
if (dashArray==null || dashArray.trim().equals("")){
if (connectorShape instanceof AssociationShape){
dashArray = DEFAULT_ASSOC_DASHARRAY;
}else if (connectorShape instanceof MessageFlowShape){
dashArray = DEFAULT_MESSAGEFLOW_DASHARRAY;
}
else{
if (Bounds.LINETYPE_DOTTED.equals(lineType)){
dashArray = DEFAULT_DOT_DASHARRAY;
}else if (Bounds.LINETYPE_DASHED.equals(lineType)){
dashArray = DEFAULT_DASH_DASHARRAY;
}else if (Bounds.LINETYPE_DASHDOTTED.equals(lineType)){
dashArray = DEFAULT_DOTDASH_DASHARRAY;
}
}
}
lineStyle.append("stroke-dasharray: ").append(lineBounds.getDashArray()).append(";");
}
}
//箭头尾
if (connectorShape instanceof TransitionShape){
Element mkElm = this.blockArrowMarkerMap.get(color);
String mkId = BASIC_BLOCK_ARROW_MARKER_ID;
if (mkElm!=null){
mkId = mkElm.getAttribute("id");
}else{
//创建新的marker
Element mkElmOriginal = this.blockArrowMarkerMap.get("#000000");
if (mkElmOriginal!=null){
Element newElm = (Element)mkElmOriginal.cloneNode(true);
mkId = connectorShape.getId()+"_end_marker";
newElm.setAttribute("id", mkId);
Element pathElm = (Element)newElm.getFirstChild();
pathElm.setAttribute("style", "stroke:none;fill:"+color+";");
blockArrowMarkerMap.put(color, newElm);
this.defsElement.appendChild(newElm);
}
}
polylineElm.setAttribute("marker-end", "url(#"+mkId+")");
}
else if (connectorShape instanceof MessageFlowShape){
Element mkElm = this.circleMarkerMap.get(color);
String mkId = BASIC_CIRCLE_MARKER_ID;
if (mkElm!=null){
mkId = mkElm.getAttribute("id");
}else{
//创建新的marker
Element mkElmOriginal = this.circleMarkerMap.get("#000000");
if (mkElmOriginal!=null){
Element newElm = (Element)mkElmOriginal.cloneNode(true);
mkId = connectorShape.getId()+"_start_marker";
newElm.setAttribute("id", mkId);
Element pathElm = (Element)newElm.getFirstChild();
pathElm.setAttribute("style", "stroke:"+color+";fill:none;stroke-dasharray:2,0;");
circleMarkerMap.put(color, newElm);
this.defsElement.appendChild(newElm);
}
}
polylineElm.setAttribute("marker-start", "url(#"+mkId+")");
mkElm = this.blockArrowMarker2Map.get(color);
mkId = BASIC_BLOCK_ARROW_MARKER2_ID;
if (mkElm!=null){
mkId = mkElm.getAttribute("id");
}else{
//创建新的marker
Element mkElmOriginal = this.blockArrowMarker2Map.get("#000000");
if (mkElmOriginal!=null){
Element newElm = (Element)mkElmOriginal.cloneNode(true);
mkId = connectorShape.getId()+"_end_marker";
newElm.setAttribute("id", mkId);
Element pathElm = (Element)newElm.getFirstChild();
pathElm.setAttribute("style", "stroke:"+color+";fill:none;stroke-dasharray:2,0;");
blockArrowMarker2Map.put(color, newElm);
this.defsElement.appendChild(newElm);
}
}
polylineElm.setAttribute("marker-end", "url(#"+mkId+")");
}
//填充
lineStyle.append("fill:none;");
polylineElm.setAttribute("style", lineStyle.toString());
//构造标题
Label lb = fireLine.getTitleLabel();
String displayName = null;
if (wfElm!=null){
displayName = wfElm.getDisplayName();
}else{
displayName = fireLine.getTitle();
}
if (displayName!=null
&& !displayName.trim().equals("")){
Point labelRelativePos = fireLine.getLabelPosition();
//labelAbsPos是label的中心点
Point labelAbsPos = _getLabelAbsolutePosition(fromAnchor.copy(),toAnchor.copy(),linePoints,labelRelativePos);
Label titleLabel = null;
if (lb==null){
titleLabel = new LabelImpl();
titleLabel.setFontSize(DEFAULT_FONT_SIZE);
}else{
titleLabel = lb.copy();
}
titleLabel.setText(displayName);
Dimension dimension = _calculateFontSize(titleLabel.getText(),titleLabel.getFontSize());
labelAbsPos.setX(labelAbsPos.getX()-dimension.width/2);
labelAbsPos.setY(labelAbsPos.getY()-dimension.height/2);
Element textRect = this.buildTextBox(connectorShape,elementType,labelAbsPos.getX(), labelAbsPos.getY(),
dimension.width, dimension.height, titleLabel,"middle");
groupElement.appendChild(textRect);
//重设画布大小
Bounds boundsTmp = new BoundsImpl();
boundsTmp.setX(labelAbsPos.getX());
boundsTmp.setY(labelAbsPos.getY());
boundsTmp.setWidth(dimension.width);
boundsTmp.setHeight(dimension.height);
this._refreshDiagramSize(boundsTmp);
}
//重设画布大小
List<Point> tmpList = new ArrayList<Point>();
tmpList.addAll(linePoints);
tmpList.add(fromAnchor);
tmpList.add(toAnchor);
_refreshDiagramSize(tmpList);
return groupElement;
}
}