iDempiere ERP. Workflow Editor 預設的編輯的欄位數為4個。 (圖 1)
在較複雜的Workflow設計圖時,可能就不敷使用。本篇文章說明如何修改Soruce code來增加欄位。
在 JIRA 提供 Patch檔或參考下列說明。
https://idempiere.atlassian.net/browse/IDEMPIERE-5431
我們在工作列上增加一個 NumberBox,可以用來任意調整Workflow 畫布的欄位數。變更後按Refresh即可變更畫布欄位數。(圖 2)
畫布欄位數預設值為 4, 也可以透過System Configuration 來設定預設值 (關鍵字為 WORKFLOW_EDITOR_COLUMNS)
org.adempiere.webui.apps.wf.WFNodeContainer 增加一個 setNoOfColumns method
public int getNoOfColumns() {
return noOfColumns;
}
public void setNoOfColumns(int noOfColumns) {
this.noOfColumns = noOfColumns;
}
org.adempiere.webui.apps.wf.WFEditor
增加一個 NumbreBox
private NumberBox columnsBox;
在initForm method中,將NumberBox 加入Toolbar
NumberBox預設值為4,
columnsBox = new NumberBox(true);
columnsBox.setValue(MSysConfig.getIntValue("WORKFLOW_EDITOR_COLUMNS", 4,Env.getAD_Client_ID(Env.getCtx())));
toolbar.appendChild(columnsBox);
在 load method 中加入
nodeContainer.setNoOfColumns(columnsBox.getValue().intValue());
for(int c = 0; c < 4; c++) {
改成下列程式碼
for(int c = 0; c < columnsBox.getValue().intValue(); c++) {
WFNodeContainer及WFEditor 完整程式如下。
/******************************************************************************
* Copyright (C) 2008 Low Heng Sin *
* This program is free software; you can redistribute it and/or modify it *
* under the terms version 2 of the GNU General Public License 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 General Public License along *
* with this program; if not, write to the Free Software Foundation, Inc., *
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
*****************************************************************************/
package org.adempiere.webui.apps.wf;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import org.adempiere.webui.apps.AEnv;
import org.adempiere.webui.component.ConfirmPanel;
import org.adempiere.webui.component.ListItem;
import org.adempiere.webui.component.Listbox;
import org.adempiere.webui.component.ListboxFactory;
import org.adempiere.webui.component.NumberBox;
import org.adempiere.webui.component.Textbox;
import org.adempiere.webui.component.ToolBar;
import org.adempiere.webui.component.Window;
import org.adempiere.webui.event.DialogEvents;
import org.adempiere.webui.panel.ADForm;
import org.adempiere.webui.theme.ThemeManager;
import org.adempiere.webui.util.ZKUpdateUtil;
import org.compiere.apps.wf.WFGraphLayout;
import org.compiere.apps.wf.WFNodeWidget;
import org.compiere.model.MRole;
import org.compiere.model.MSysConfig;
import org.compiere.util.DB;
import org.compiere.util.Env;
import org.compiere.util.KeyNamePair;
import org.compiere.util.Msg;
import org.compiere.util.Util;
import org.compiere.wf.MWFNode;
import org.compiere.wf.MWFNodeNext;
import org.compiere.wf.MWorkflow;
import org.zkoss.zhtml.Table;
import org.zkoss.zhtml.Td;
import org.zkoss.zhtml.Tr;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.event.DropEvent;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zul.Borderlayout;
import org.zkoss.zul.Center;
import org.zkoss.zul.Div;
import org.zkoss.zul.Hbox;
import org.zkoss.zul.Label;
import org.zkoss.zul.Menupopup;
import org.zkoss.zul.North;
import org.zkoss.zul.Separator;
import org.zkoss.zul.South;
import org.zkoss.zul.Space;
import org.zkoss.zul.Toolbarbutton;
import org.zkoss.zul.Vbox;
/**
*
* @author Low Heng Sin
*
*/
public class WFEditor extends ADForm {
/**
*
*/
private static final long serialVersionUID = 4293422396394778274L;
private Listbox workflowList;
private int m_workflowId = 0;
private Toolbarbutton zoomButton;
private Toolbarbutton refreshButton;
private Toolbarbutton newButton;
private Table table;
private Center center;
private MWorkflow m_wf;
private WFNodeContainer nodeContainer;
private NumberBox columnsBox;
@Override
protected void initForm() {
ZKUpdateUtil.setHeight(this, "100%");
Borderlayout layout = new Borderlayout();
layout.setStyle("width: 100%; height: 100%; position: relative;");
appendChild(layout);
String sql;
boolean isBaseLanguage = Env.isBaseLanguage(Env.getCtx(), "AD_Workflow");
if (isBaseLanguage)
sql = MRole.getDefault().addAccessSQL(
"SELECT AD_Workflow_ID, Name FROM AD_Workflow WHERE IsActive='Y' ORDER BY 2",
"AD_Workflow", MRole.SQL_NOTQUALIFIED, MRole.SQL_RO); // all
else
sql = MRole.getDefault().addAccessSQL(
"SELECT AD_Workflow.AD_Workflow_ID, AD_Workflow_Trl.Name FROM AD_Workflow INNER JOIN AD_Workflow_Trl ON (AD_Workflow.AD_Workflow_ID=AD_Workflow_Trl.AD_Workflow_ID) "
+ " WHERE AD_Workflow.IsActive='Y' AND AD_Workflow_Trl.AD_Language='"+Env.getAD_Language(Env.getCtx())+"' ORDER BY 2","AD_Workflow", MRole.SQL_FULLYQUALIFIED, MRole.SQL_RO); // all
KeyNamePair[] pp = DB.getKeyNamePairs(sql, true);
workflowList = ListboxFactory.newDropdownListbox();
for (KeyNamePair knp : pp) {
workflowList.addItem(knp);
}
workflowList.addEventListener(Events.ON_SELECT, this);
North north = new North();
layout.appendChild(north);
ToolBar toolbar = new ToolBar();
north.appendChild(toolbar);
toolbar.appendChild(workflowList);
// Zoom
zoomButton = new Toolbarbutton();
if (ThemeManager.isUseFontIconForImage())
zoomButton.setIconSclass("z-icon-Zoom");
else
zoomButton.setImage(ThemeManager.getThemeResource("images/Zoom16.png"));
toolbar.appendChild(zoomButton);
zoomButton.addEventListener(Events.ON_CLICK, this);
zoomButton.setTooltiptext(Util.cleanAmp(Msg.getMsg(Env.getCtx(), "Zoom")));
// New Node
newButton = new Toolbarbutton();
if (ThemeManager.isUseFontIconForImage())
newButton.setIconSclass("z-icon-New");
else
newButton.setImage(ThemeManager.getThemeResource("images/New16.png"));
toolbar.appendChild(newButton);
newButton.addEventListener(Events.ON_CLICK, this);
newButton.setTooltiptext(Msg.getMsg(Env.getCtx(), "CreateNewNode"));
// Refresh
refreshButton = new Toolbarbutton();
if (ThemeManager.isUseFontIconForImage())
refreshButton.setIconSclass("z-icon-Refresh");
else
refreshButton.setImage(ThemeManager.getThemeResource("images/Refresh16.png"));
toolbar.appendChild(refreshButton);
refreshButton.addEventListener(Events.ON_CLICK, this);
refreshButton.setTooltiptext(Util.cleanAmp(Msg.getMsg(Env.getCtx(), "Refresh")));
ZKUpdateUtil.setHeight(north, "30px");
columnsBox = new NumberBox(true);
columnsBox.setValue(MSysConfig.getIntValue("WORKFLOW_EDITOR_COLUMNS", 4,Env.getAD_Client_ID(Env.getCtx())));
toolbar.appendChild(columnsBox);
createTable();
center = new Center();
layout.appendChild(center);
center.setAutoscroll(true);
center.appendChild(table);
ConfirmPanel confirmPanel = new ConfirmPanel(true);
confirmPanel.addActionListener(this);
South south = new South();
layout.appendChild(south);
south.appendChild(confirmPanel);
ZKUpdateUtil.setHeight(south, "36px");
}
private void createTable() {
table = new Table();
table.setDynamicProperty("cellpadding", "0");
table.setDynamicProperty("cellspacing", "0");
table.setDynamicProperty("border", "none");
table.setStyle("margin:0;padding:0");
}
@Override
public void onEvent(Event event) throws Exception {
if (event.getTarget().getId().equals(ConfirmPanel.A_CANCEL))
this.detach();
else if (event.getTarget().getId().equals(ConfirmPanel.A_OK))
this.detach();
else if (event.getTarget() == workflowList) {
center.removeChild(table);
createTable();
center.appendChild(table);
ListItem item = workflowList.getSelectedItem();
KeyNamePair knp = item != null ? item.toKeyNamePair() : null;
if (knp != null && knp.getKey() > 0) {
load(knp.getKey(), true);
}
}
else if (event.getTarget() == zoomButton) {
if (workflowList.getSelectedIndex() > 0)
zoom();
}
else if (event.getTarget() == refreshButton) {
if (workflowList.getSelectedIndex() > 0)
reload(m_workflowId, true);
}
else if (event.getTarget() == newButton) {
if (workflowList.getSelectedIndex() > 0)
createNewNode();
}
else if (event.getTarget() instanceof WFPopupItem) {
WFPopupItem item = (WFPopupItem) event.getTarget();
item.execute(this);
}
else if (event.getName().equals(Events.ON_DROP)) {
DropEvent dropEvent = (DropEvent) event;
Integer AD_WF_Node_ID = (Integer) dropEvent.getDragged().getAttribute("AD_WF_Node_ID");
Integer xPosition = (Integer) event.getTarget().getAttribute("Node.XPosition");
Integer yPosition = (Integer) event.getTarget().getAttribute("Node.YPosition");
if (AD_WF_Node_ID != null) {
WFNodeWidget widget = (WFNodeWidget) nodeContainer.getGraphScene().findWidget(AD_WF_Node_ID);
if (widget != null) {
widget.getModel().setXPosition(xPosition);
widget.getModel().setYPosition(yPosition);
widget.getModel().saveEx();
reload(m_workflowId, true);
}
}
}
}
private void createNewNode() {
String nameLabel = Msg.getElement(Env.getCtx(), MWFNode.COLUMNNAME_Name);
String title = Msg.getMsg(Env.getCtx(), "CreateNewNode");
final Window w = new Window();
w.setTitle(title);
Vbox vbox = new Vbox();
w.appendChild(vbox);
vbox.appendChild(new Separator());
Hbox hbox = new Hbox();
hbox.appendChild(new Label(nameLabel));
hbox.appendChild(new Space());
final Textbox text = new Textbox();
hbox.appendChild(text);
vbox.appendChild(hbox);
vbox.appendChild(new Separator());
final ConfirmPanel panel = new ConfirmPanel(true, false, false, false, false, false, false);
vbox.appendChild(panel);
panel.addActionListener(Events.ON_CLICK, new EventListener<Event>() {
public void onEvent(Event event) throws Exception {
if (event.getTarget() == panel.getButton(ConfirmPanel.A_CANCEL)) {
text.setText("");
}
w.onClose();
}
});
ZKUpdateUtil.setWidth(w, "250px");
w.setBorder("normal");
w.setPage(this.getPage());
w.addEventListener(DialogEvents.ON_WINDOW_CLOSE, new EventListener<Event>() {
@Override
public void onEvent(Event event) throws Exception {
String name = text.getText();
if (name != null && name.length() > 0)
{
int AD_Client_ID = Env.getAD_Client_ID(Env.getCtx());
MWFNode node = new MWFNode(m_wf, name, name);
node.setClientOrg(AD_Client_ID, 0);
node.saveEx();
reload(m_wf.getAD_Workflow_ID(), true);
}
}
});
w.doHighlighted();
}
protected void reload(int workflowId, boolean reread) {
center.removeChild(table);
createTable();
center.appendChild(table);
load(workflowId, reread);
}
private void load(int workflowId, boolean reread) {
// Get Workflow
m_wf = MWorkflow.get(Env.getCtx(), workflowId);
m_workflowId = workflowId;
nodeContainer = new WFNodeContainer();
nodeContainer.setNoOfColumns(columnsBox.getValue().intValue());
nodeContainer.setWorkflow(m_wf);
if (reread) {
m_wf.reloadNodes();
}
// Add Nodes for Paint
MWFNode[] nodes = m_wf.getNodes(true, Env.getAD_Client_ID(Env.getCtx()));
List<Integer> added = new ArrayList<Integer>();
for (int i = 0; i < nodes.length; i++)
{
if (!added.contains(nodes[i].getAD_WF_Node_ID()))
nodeContainer.addNode(nodes[i]);
}
// Add lines
for (int i = 0; i < nodes.length; i++)
{
MWFNodeNext[] nexts = nodes[i].getTransitions(Env.getAD_Client_ID(Env.getCtx()));
for (int j = 0; j < nexts.length; j++)
{
nodeContainer.addEdge(nexts[j]);
}
}
Dimension dimension = nodeContainer.getDimension();
BufferedImage bi = new BufferedImage (dimension.width, dimension.height, BufferedImage.TYPE_INT_ARGB);
Graphics2D graphics = bi.createGraphics();
nodeContainer.validate(graphics);
nodeContainer.paint(graphics);
try {
int row = nodeContainer.getRowCount();
for(int i = 0; i < row+1; i++) {
Tr tr = new Tr();
table.appendChild(tr);
for(int c = 0; c < columnsBox.getValue().intValue(); c++) {
BufferedImage t = new BufferedImage(WFGraphLayout.COLUMN_WIDTH, WFGraphLayout.ROW_HEIGHT, BufferedImage.TYPE_INT_ARGB);
Graphics2D tg = t.createGraphics();
Td td = new Td();
td.setStyle("border: 1px dotted lightgray");
tr.appendChild(td);
if (i < row)
{
int x = c * WFGraphLayout.COLUMN_WIDTH;
int y = i * WFGraphLayout.ROW_HEIGHT;
tg.drawImage(bi.getSubimage(x, y, WFGraphLayout.COLUMN_WIDTH, WFGraphLayout.ROW_HEIGHT), 0, 0, null);
org.zkoss.zul.Image image = new org.zkoss.zul.Image();
image.setContent(t);
td.appendChild(image);
String imgStyle = "border:none;margin:0;padding:0";
WFNodeWidget widget = nodeContainer.findWidget(i+1, c+1);
if (widget != null)
{
MWFNode node = widget.getModel();
if (node.getHelp(true) != null) {
image.setTooltiptext(node.getHelp(true));
}
image.setAttribute("AD_WF_Node_ID", node.getAD_WF_Node_ID());
image.addEventListener(Events.ON_CLICK, new EventListener<Event>() {
public void onEvent(Event event) throws Exception {
showNodeMenu(event.getTarget());
}
});
image.setDraggable("WFNode");
imgStyle = imgStyle + ";cursor:pointer";
}
else
{
image.setDroppable("WFNode");
image.addEventListener(Events.ON_DROP, this);
image.setAttribute("Node.XPosition", c+1);
image.setAttribute("Node.YPosition", i+1);
}
image.setStyle(imgStyle);
}
else
{
Div div = new Div();
ZKUpdateUtil.setWidth(div, (WFGraphLayout.COLUMN_WIDTH) + "px");
ZKUpdateUtil.setHeight(div, (WFGraphLayout.ROW_HEIGHT) + "px");
div.setAttribute("Node.XPosition", c+1);
div.setAttribute("Node.YPosition", i+1);
div.setDroppable("WFNode");
div.addEventListener(Events.ON_DROP, this);
td.appendChild(div);
}
tg.dispose();
}
}
} catch (Exception e) {
logger.log(Level.SEVERE, e.getLocalizedMessage(), e);
}
}
protected void showNodeMenu(Component target) {
Integer AD_WF_Node_ID = (Integer) target.getAttribute("AD_WF_Node_ID");
if (AD_WF_Node_ID != null) {
WFNodeWidget widget = (WFNodeWidget) nodeContainer.getGraphScene().findWidget(AD_WF_Node_ID);
if (widget != null) {
MWFNode node = widget.getModel();
Menupopup popupMenu = new Menupopup();
if (node.getAD_Client_ID() == Env.getAD_Client_ID(Env.getCtx()))
{
// Zoom
addMenuItem(popupMenu, Util.cleanAmp(Msg.getMsg(Env.getCtx(), "Zoom")), node, WFPopupItem.WFPOPUPITEM_ZOOM);
// Properties
addMenuItem(popupMenu, Msg.getMsg(Env.getCtx(), "Properties"), node, WFPopupItem.WFPOPUPITEM_PROPERTIES);
// Delete node
String title = Msg.getMsg(Env.getCtx(), "DeleteNode") +
": " + node.getName(true);
addMenuItem(popupMenu, title, node, WFPopupItem.WFPOPUPITEM_DELETENODE);
}
MWFNode[] nodes = m_wf.getNodes(true, Env.getAD_Client_ID(Env.getCtx()));
MWFNodeNext[] lines = node.getTransitions(Env.getAD_Client_ID(Env.getCtx()));
// Add New Line
for (MWFNode nn : nodes)
{
if (nn.getAD_WF_Node_ID() == node.getAD_WF_Node_ID())
continue; // same
if (nn.getAD_WF_Node_ID() == node.getAD_Workflow().getAD_WF_Node_ID())
continue; // don't add line to starting node
boolean found = false;
for (MWFNodeNext line : lines)
{
if (nn.getAD_WF_Node_ID() == line.getAD_WF_Next_ID())
{
found = true; // line already exists
break;
}
}
if (!found) {
// Check that inverse line doesn't exist
for (MWFNodeNext revline : nn.getTransitions(Env.getAD_Client_ID(Env.getCtx()))) {
if (node.getAD_WF_Node_ID() == revline.getAD_WF_Next_ID())
{
found = true; // inverse line already exists
break;
}
}
}
if (!found)
{
String title = Msg.getMsg(Env.getCtx(), "AddLine")
+ ": " + node.getName(true) + " -> " + nn.getName(true);
addMenuItem(popupMenu, title, node, nn.getAD_WF_Node_ID());
}
}
// Delete Lines
for (MWFNodeNext line : lines)
{
if (line.getAD_Client_ID() != Env.getAD_Client_ID(Env.getCtx()))
continue;
MWFNode next = MWFNode.get(Env.getCtx(), line.getAD_WF_Next_ID());
String title = Msg.getMsg(Env.getCtx(), "DeleteLine")
+ ": " + node.getName(true) + " -> " + next.getName(true);
addMenuItem(popupMenu, title, line);
}
popupMenu.setPage(target.getPage());
popupMenu.open(target);
}
}
}
/**
* Zoom to WorkFlow
*/
private void zoom()
{
if (m_workflowId > 0) {
AEnv.zoom(MWorkflow.Table_ID, m_workflowId);
}
} // zoom
/**
* Add Menu Item to - add new line to node
* @param menu base menu
* @param title title
*/
private void addMenuItem (Menupopup menu, String title, MWFNode node, int AD_WF_NodeTo_ID)
{
WFPopupItem item = new WFPopupItem (title, node, AD_WF_NodeTo_ID);
menu.appendChild(item);
item.addEventListener(Events.ON_CLICK, this);
} // addMenuItem
/**
* Add Menu Item to - delete line
* @param menu base menu
* @param title title
*/
private void addMenuItem (Menupopup menu, String title, MWFNodeNext line)
{
WFPopupItem item = new WFPopupItem (title, line);
menu.appendChild(item);
item.addEventListener(Events.ON_CLICK, this);
} // addMenuItem
}
/******************************************************************************
* Copyright (C) 2008 Low Heng Sin *
* This program is free software; you can redistribute it and/or modify it *
* under the terms version 2 of the GNU General Public License 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 General Public License along *
* with this program; if not, write to the Free Software Foundation, Inc., *
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
*****************************************************************************/
package org.adempiere.webui.apps.wf;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.util.HashMap;
import java.util.Map;
import org.compiere.apps.wf.WFGraphLayout;
import org.compiere.apps.wf.WFNodeWidget;
import org.compiere.apps.wf.WorkflowGraphScene;
import org.compiere.model.X_AD_Workflow;
import org.compiere.util.CLogger;
import org.compiere.wf.MWFNode;
import org.compiere.wf.MWFNodeNext;
import org.compiere.wf.MWorkflow;
import org.netbeans.api.visual.graph.GraphScene;
import org.netbeans.api.visual.graph.layout.GraphLayout;
import org.netbeans.api.visual.layout.LayoutFactory;
import org.netbeans.api.visual.layout.SceneLayout;
/**
*
* @author Low Heng Sin
*
*/
public class WFNodeContainer
{
/** Logger */
@SuppressWarnings("unused")
private static final CLogger log = CLogger.getCLogger(WFNodeContainer.class);
/** The Workflow */
private MWorkflow m_wf = null;
private int currentRow = 1;
private int currentColumn = 0;
private int noOfColumns = 8;
private int maxColumn = 0;
private int rowCount = 0;
private WorkflowGraphScene graphScene = new WorkflowGraphScene();
private Map<Integer, Integer[]> matrix = null;
/**
* WFContentPanel
*/
public WFNodeContainer ()
{
matrix = new HashMap<Integer, Integer[]>();
} // WFContentPanel
/**
* Set Workflow
* @param wf workflow
*/
public void setWorkflow (MWorkflow wf)
{
m_wf = wf;
} // setWorkflow
public int getNoOfColumns() {
return noOfColumns;
}
public void setNoOfColumns(int noOfColumns) {
this.noOfColumns = noOfColumns;
}
/**
* Remove All and their listeners
*/
public void removeAll ()
{
graphScene = new WorkflowGraphScene();
currentColumn = 0;
currentRow = 1;
matrix = new HashMap<Integer, Integer[]>();
} // removeAll
public void addNode(MWFNode node) {
int oldRow = currentRow;
int oldColumn = currentColumn;
if (node.getXPosition() > 0 && node.getYPosition() > 0) {
currentColumn = node.getXPosition();
currentRow = node.getYPosition();
if (currentColumn > noOfColumns) {
currentColumn = 1;
currentRow ++;
}
} else if (currentColumn == noOfColumns) {
currentColumn = 1;
if (m_wf.getWorkflowType().equals(X_AD_Workflow.WORKFLOWTYPE_General)) {
currentRow++;
} else {
currentRow = currentRow + 2;
}
} else {
if (m_wf.getWorkflowType().equals(X_AD_Workflow.WORKFLOWTYPE_General) || currentColumn == 0) {
currentColumn++;
} else {
currentColumn = currentColumn + 2;
if (currentColumn > noOfColumns) {
currentColumn = 1;
currentRow = currentRow + 2;
}
}
}
if (currentRow > rowCount) {
rowCount = currentRow;
}
Integer[] nodes = matrix.get(currentRow);
if (nodes == null) {
nodes = new Integer[noOfColumns];
matrix.put(currentRow, nodes);
} else {
//detect collision
while (nodes[currentColumn - 1] != null) {
if (nodes[currentColumn - 1] == node.getAD_WF_Node_ID()) {
break;
} else if (currentColumn == noOfColumns) {
currentColumn = 1;
currentRow ++;
nodes = matrix.get(currentRow);
if (nodes == null) {
nodes = new Integer[noOfColumns];
matrix.put(currentRow, nodes);
}
} else {
currentColumn ++;
}
}
}
WFNodeWidget w = (WFNodeWidget) graphScene.addNode(node.getAD_WF_Node_ID());
w.setColumn(currentColumn);
w.setRow(currentRow);
nodes[currentColumn - 1] = node.getAD_WF_Node_ID();
if (currentColumn > maxColumn) {
maxColumn = currentColumn;
}
if (currentRow < oldRow) {
currentRow = oldRow;
currentColumn = oldColumn;
} else if ( currentRow == oldRow && currentColumn < oldColumn) {
currentColumn = oldColumn;
}
}
public void addEdge(MWFNodeNext edge) {
graphScene.addEdge(edge);
graphScene.setEdgeSource(edge, edge.getAD_WF_Node_ID());
graphScene.setEdgeTarget(edge, edge.getAD_WF_Next_ID());
}
/**
*
* @param row row #, starting from 1
* @param column column #, starting from 1
* @return WFNodeWidget
*/
public WFNodeWidget findWidget(int row, int column) {
WFNodeWidget widget = null;
Integer[] nodeRow = matrix.get(row);
if (nodeRow != null && column <= nodeRow.length) {
widget = (WFNodeWidget) graphScene.findWidget(nodeRow[column - 1]);
}
return widget;
}
/**
* Get Bounds of WF Node Icon
* @param AD_WF_Node_ID node id
* @return bounds of node with ID or null
*/
public Rectangle findBounds (int AD_WF_Node_ID)
{
WFNodeWidget widget = (WFNodeWidget) graphScene.findWidget(AD_WF_Node_ID);
if (widget == null)
return null;
Point p = widget.getPreferredLocation();
return new Rectangle(p.x, p.y, WFNodeWidget.NODE_WIDTH, WFNodeWidget.NODE_HEIGHT);
} // findBounds
public Dimension getDimension()
{
return new Dimension(noOfColumns * WFGraphLayout.COLUMN_WIDTH, currentRow * WFGraphLayout.ROW_HEIGHT);
}
public void validate(Graphics2D graphics)
{
GraphLayout<Integer, MWFNodeNext> graphLayout = new WFGraphLayout();
graphLayout.setAnimated(false);
SceneLayout sceneGraphLayout = LayoutFactory.createSceneGraphLayout (graphScene, graphLayout);
sceneGraphLayout.invokeLayoutImmediately();
graphScene.validate(graphics);
}
public void paint(Graphics2D graphics) {
graphScene.paint(graphics);
}
public int getRowCount() {
return rowCount;
}
public int getCurrentRow() {
return currentRow;
}
public int getCurrentColumn() {
return currentColumn;
}
public int getColumnCount() {
return noOfColumns;
}
public int getMaxColumnWithNode() {
return maxColumn;
}
public GraphScene<Integer, MWFNodeNext> getGraphScene() {
return graphScene;
}
} // WFContentPanel