已經可以比較好的運行JBPM了,但是如果能以圖形化的方式顯示工作流,并且把當前節點高亮顯示,這樣可用性就更好了,用戶可以很輕松的看到當前流程到哪個節點了。
我發現JBPM的starters-kit的例子中就有類似的效果,所以決定分析一下它是怎么實現的。
打開網頁,瀏覽到有顯示當前工作流節點的頁面,查看到此頁面的地址為task.jsp,發現其中的核心代碼如下:
<jbpm:processimage task="${taskBean.taskInstanceId}"/>
這里使用了JBPM提供的jbpm:processimage標簽,此標簽定義在jbpm.tld中,這個Tag的類為org.jbpm.webapp.tag.ProcessImageTag。所以只要使用這個標簽我們就可以很輕松的在Web頁面中顯示圖形化的工作流了。
那么如果是在Swing、SWT等非Web界面中也想顯示這種效果怎么辦呢?那么讓我們來分析一下ProcessImageTag類。
private void retrieveByteArrays() {
try {
FileDefinition fileDefinition = processDefinition.getFileDefinition();
gpdBytes = fileDefinition.getBytes("gpd.xml");
imageBytes = fileDefinition.getBytes("processimage.jpg");
} catch (Exception e) {
e.printStackTrace();
}
}
gpd.xml中記錄的是節點的位置關系,processimage.jpg是圖形化的圖片(只是基圖,沒有高亮顯示當前節點),這兩個文件是JBPM的Eclipse插件自動生成的。
得到流程實例當前節點的方法:
private void initialize() {
JbpmContext jbpmContext = JbpmContext.getCurrentJbpmContext();
if (this.taskInstanceId > 0) {
TaskInstance taskInstance = jbpmContext.getTaskMgmtSession().loadTaskInstance(taskInstanceId);
currentToken = taskInstance.getToken();
}
else
{
if (this.tokenInstanceId > 0)
currentToken = jbpmContext.getGraphSession().loadToken(this.tokenInstanceId);
}
processDefinition = currentToken.getProcessInstance().getProcessDefinition();
}
從currentToken中可以得到當前節點在顯示的時候的長度、寬度、橫縱坐標等值。得到的方式如下:
private int[] extractBoxConstraint(Element root) {
int[] result = new int[4];
String nodeName = currentToken.getNode().getName();
XPath xPath = new DefaultXPath("http://node[@name='" + nodeName + "']");
Element node = (Element) xPath.selectSingleNode(root);
result[0] = Integer.valueOf(node.attribute("x").getValue()).intValue();
result[1] = Integer.valueOf(node.attribute("y").getValue()).intValue();
result[2] = Integer.valueOf(node.attribute("width").getValue()).intValue();
result[3] = Integer.valueOf(node.attribute("height").getValue()).intValue();
return result;
}
這樣用<div/>標簽就可以將當前節點框上一個紅色的框框了:
jspOut.println("<div style='position:relative; background-image:url(" + imageLink + "); width: " + imageDimension[0] + "px; height: " + imageDimension[1] + "px;'>");
//詳細代碼參考:writeTable方法
原來高亮顯示是在原有的圖片上疊加一個高亮的框框實現的。所以如果要顯示在Swing、SWT中的話也只要參考這個思路,在當前節點位置顯示一個高亮的框框就可以了!