* sync with branches/adempiere341 revision 6548

This commit is contained in:
Heng Sin Low 2008-10-01 22:45:11 +00:00
parent abac6d0953
commit 421a92eb02
31 changed files with 2112 additions and 130 deletions

View File

@ -28,6 +28,7 @@ import java.util.logging.Level;
import org.adempiere.webui.apps.AEnv;
import org.adempiere.webui.apps.ProcessDialog;
import org.adempiere.webui.apps.graph.WPAPanel;
import org.adempiere.webui.apps.wf.WFPanel;
import org.adempiere.webui.component.Button;
import org.adempiere.webui.component.DesktopTabpanel;
import org.adempiere.webui.component.Tabbox;
@ -44,9 +45,11 @@ import org.adempiere.webui.part.AbstractUIPart;
import org.adempiere.webui.part.WindowContainer;
import org.adempiere.webui.window.ADWindow;
import org.adempiere.webui.window.InfoSchedule;
import org.adempiere.webui.window.WTask;
import org.compiere.model.MMenu;
import org.compiere.model.MQuery;
import org.compiere.model.MRole;
import org.compiere.model.MTask;
import org.compiere.model.MTree;
import org.compiere.model.MTreeNode;
import org.compiere.util.CLogger;
@ -728,6 +731,14 @@ public class Desktop extends AbstractUIPart implements MenuListener, Serializabl
{
openForm(menu.getAD_Form_ID());
}
else if(menu.getAction().equals(MMenu.ACTION_WorkFlow))
{
openWorkflow(menu.getAD_Workflow_ID());
}
else if(menu.getAction().equals(MMenu.ACTION_Task))
{
openTask(menu.getAD_Task_ID());
}
else
{
throw new ApplicationException("Menu Action not yet implemented: " + menu.getAction());
@ -736,6 +747,15 @@ public class Desktop extends AbstractUIPart implements MenuListener, Serializabl
/**
*
* @param taskId
*/
public void openTask(int taskId) {
MTask task = new MTask(Env.getCtx(), taskId, null);
new WTask(task.getName(), task);
}
/**
*
* @param processId
* @param soTrx
* @return ProcessDialog
@ -768,6 +788,19 @@ public class Desktop extends AbstractUIPart implements MenuListener, Serializabl
return form;
}
/**
*
* @param workflow_ID
*/
public void openWorkflow(int workflow_ID) {
WFPanel p = new WFPanel();
p.load(workflow_ID);
DesktopTabpanel tabPanel = new DesktopTabpanel();
p.setParent(tabPanel);
windowContainer.addWindow(tabPanel, p.getWorkflow().getName(), true);
}
/**
*
* @param windowId
@ -777,10 +810,13 @@ public class Desktop extends AbstractUIPart implements MenuListener, Serializabl
ADWindow adWindow = new ADWindow(Env.getCtx(), windowId);
DesktopTabpanel tabPanel = new DesktopTabpanel();
adWindow.createPart(tabPanel);
windowContainer.addWindow(tabPanel, adWindow.getTitle(), true);
return adWindow;
if (adWindow.createPart(tabPanel) != null) {
windowContainer.addWindow(tabPanel, adWindow.getTitle(), true);
return adWindow;
} else {
//user cancel
return null;
}
}
/**

View File

@ -103,4 +103,10 @@ public interface IDesktop {
* @return ADWindow
*/
public ADWindow openWindow(int windowId);
/**
* Open operating system task window
* @param task_ID
*/
public void openTask(int task_ID);
}

View File

@ -29,8 +29,8 @@ import org.compiere.util.ContextProvider;
*/
public class ZkContextProvider implements ContextProvider {
private final ServerContextCallback callback = new ServerContextCallback();
private final Properties context = (Properties) Enhancer.create(Properties.class, callback);
private final static ServerContextCallback callback = new ServerContextCallback();
private final static Properties context = (Properties) Enhancer.create(Properties.class, callback);
/**
* Get server context proxy

View File

@ -618,7 +618,11 @@ public final class AEnv
if (zoomQuery == null || value != null)
{
zoomQuery = new MQuery(); // ColumnName might be changed in MTab.validateQuery
zoomQuery.addRestriction(lookup.getColumnName(), MQuery.EQUAL, value);
String column = lookup.getColumnName();
//strip off table name, fully qualify name doesn't work when zoom into detail tab
if (column.indexOf(".") > 0)
column = column.substring(column.indexOf(".")+1);
zoomQuery.addRestriction(column, MQuery.EQUAL, value);
zoomQuery.setRecordCount(1); // guess
}
int windowId = lookup.getZoom(zoomQuery);

View File

@ -0,0 +1,548 @@
/******************************************************************************
* Product: Adempiere ERP & CRM Smart Business Solution *
* Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. *
* 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. *
* For the text or an alternative of this public license, you may reach us *
* ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA *
* or via info@compiere.org or http://www.compiere.org/license.html *
*****************************************************************************/
package org.adempiere.webui.apps.form;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.logging.Level;
import org.adempiere.webui.LayoutUtils;
import org.adempiere.webui.component.Button;
import org.adempiere.webui.component.Checkbox;
import org.adempiere.webui.component.Label;
import org.adempiere.webui.component.Listbox;
import org.adempiere.webui.component.Panel;
import org.adempiere.webui.component.SimpleListModel;
import org.adempiere.webui.component.SimpleTreeModel;
import org.adempiere.webui.panel.ADForm;
import org.adempiere.webui.session.SessionManager;
import org.adempiere.webui.window.FDialog;
import org.compiere.model.MRole;
import org.compiere.model.MTree;
import org.compiere.model.MTreeNode;
import org.compiere.model.MTree_Node;
import org.compiere.model.MTree_NodeBP;
import org.compiere.model.MTree_NodeMM;
import org.compiere.model.MTree_NodePR;
import org.compiere.util.CLogger;
import org.compiere.util.DB;
import org.compiere.util.Env;
import org.compiere.util.KeyNamePair;
import org.compiere.util.Msg;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zkex.zul.Borderlayout;
import org.zkoss.zkex.zul.Center;
import org.zkoss.zkex.zul.East;
import org.zkoss.zkex.zul.North;
import org.zkoss.zul.ListModel;
import org.zkoss.zul.SimpleTreeNode;
import org.zkoss.zul.Space;
import org.zkoss.zul.Splitter;
import org.zkoss.zul.Tree;
import org.zkoss.zul.Treeitem;
/**
* Tree Maintenance
*
* @author Jorg Janke
* @version $Id: VTreeMaintenance.java,v 1.3 2006/07/30 00:51:28 jjanke Exp $
*/
public class WTreeMaintenance extends ADForm implements EventListener
{
/** Active Tree */
private MTree m_tree;
/** Logger */
private static CLogger log = CLogger.getCLogger(WTreeMaintenance.class);
private Borderlayout mainLayout = new Borderlayout ();
private Panel northPanel = new Panel ();
private Label treeLabel = new Label ();
private Listbox treeField;
private Button bAddAll = new Button ();
private Button bAdd = new Button ();
private Button bDelete = new Button ();
private Button bDeleteAll = new Button ();
private Checkbox cbAllNodes = new Checkbox ();
private Label treeInfo = new Label ();
//
private Splitter splitPane = new Splitter();
private Tree centerTree;
private Listbox centerList = new Listbox();
@Override
public void initForm()
{
try
{
preInit();
jbInit ();
action_loadTree();
LayoutUtils.sendDeferLayoutEvent(mainLayout, 100);
}
catch (Exception ex)
{
log.log(Level.SEVERE, "VTreeMaintenance.init", ex);
}
} // init
/**
* Fill Tree Combo
*/
private void preInit()
{
KeyNamePair[] trees = DB.getKeyNamePairs(MRole.getDefault().addAccessSQL(
"SELECT AD_Tree_ID, Name FROM AD_Tree WHERE TreeType NOT IN ('BB','PC') ORDER BY 2",
"AD_Tree", MRole.SQL_NOTQUALIFIED, MRole.SQL_RW), false);
treeField = new Listbox(trees);
treeField.setMold("select");
treeField.addActionListener(this);
treeField.setSelectedIndex(0);
//
centerTree = new Tree();
centerTree.addEventListener(Events.ON_SELECT, this);
} // preInit
/**
* Static init
* @throws Exception
*/
private void jbInit () throws Exception
{
bAddAll.setSrc("images/FastBack24.png");
bAdd.setSrc("images/StepBack24.png");
bDelete.setSrc("images/StepForward24.png");
bDeleteAll.setSrc("images/FastForward24.png");
this.setWidth("99%");
this.setHeight("100%");
this.setStyle("position: absolute; padding: 0; margin: 0");
this.appendChild (mainLayout);
mainLayout.setWidth("100%");
mainLayout.setHeight("100%");
mainLayout.setStyle("position: absolute");
treeLabel.setText (Msg.translate(Env.getCtx(), "AD_Tree_ID"));
cbAllNodes.setEnabled (false);
cbAllNodes.setText (Msg.translate(Env.getCtx(), "IsAllNodes"));
treeInfo.setText (" ");
bAdd.setTooltiptext("Add to Tree");
bAddAll.setTooltiptext("Add ALL to Tree");
bDelete.setTooltiptext("Delete from Tree");
bDeleteAll.setTooltiptext("Delete ALL from Tree");
bAdd.addActionListener(this);
bAddAll.addActionListener(this);
bDelete.addActionListener(this);
bDeleteAll.addActionListener(this);
North north = new North();
mainLayout.appendChild(north);
north.appendChild(northPanel);
north.setHeight("28px");
//
northPanel.appendChild (treeLabel);
northPanel.appendChild (new Space());
northPanel.appendChild (treeField);
northPanel.appendChild (new Space());
northPanel.appendChild (cbAllNodes);
northPanel.appendChild (new Space());
northPanel.appendChild (treeInfo);
northPanel.appendChild (new Space());
northPanel.appendChild (bAddAll);
northPanel.appendChild (new Space());
northPanel.appendChild (bAdd);
northPanel.appendChild (new Space());
northPanel.appendChild (bDelete);
northPanel.appendChild (new Space());
northPanel.appendChild (bDeleteAll);
//
Center center = new Center();
mainLayout.appendChild(center);
center.appendChild(centerTree);
center.setFlex(true);
center.setAutoscroll(true);
East east = new East();
mainLayout.appendChild(east);
east.appendChild(centerList);
east.setCollapsible(false);
east.setSplittable(true);
east.setWidth("45%");
centerList.setVflex(true);
centerList.setFixedLayout(true);
centerList.addEventListener(Events.ON_SELECT, this);
} // jbInit
/**
* Dispose
*/
public void dispose()
{
SessionManager.getAppDesktop().closeActiveWindow();
} // dispose
/**
* Action Listener
* @param e event
*/
public void onEvent (Event e)
{
if (e.getTarget() == treeField)
{
action_loadTree();
LayoutUtils.sendDeferLayoutEvent(mainLayout, 100);
}
else if (e.getTarget() == bAddAll)
action_treeAddAll();
else if (e.getTarget() == bAdd)
{
SimpleListModel model = (SimpleListModel) centerList.getModel();
int i = centerList.getSelectedIndex();
if (i >= 0) {
action_treeAdd((ListItem)model.getElementAt(i));
}
}
else if (e.getTarget() == bDelete)
{
SimpleListModel model = (SimpleListModel) centerList.getModel();
int i = centerList.getSelectedIndex();
if (i >= 0) {
action_treeDelete((ListItem)model.getElementAt(i));
}
}
else if (e.getTarget() == bDeleteAll)
action_treeDeleteAll();
else if (e.getTarget() == centerList)
onListSelection(e);
else if (e.getTarget() == centerTree)
onTreeSelection(e);
} // actionPerformed
/**
* Action: Fill Tree with all nodes
*/
private void action_loadTree()
{
KeyNamePair tree = treeField.getSelectedItem().toKeyNamePair();
log.info("Tree=" + tree);
if (tree.getKey() <= 0)
{
SimpleListModel tmp = new SimpleListModel();
centerList.setItemRenderer(tmp);
centerList.setModel(tmp);
return;
}
// Tree
m_tree = new MTree (Env.getCtx(), tree.getKey(), null);
cbAllNodes.setSelected(m_tree.isAllNodes());
bAddAll.setEnabled(!m_tree.isAllNodes());
bAdd.setEnabled(!m_tree.isAllNodes());
bDelete.setEnabled(!m_tree.isAllNodes());
bDeleteAll.setEnabled(!m_tree.isAllNodes());
//
String fromClause = m_tree.getSourceTableName(false); // fully qualified
String columnNameX = m_tree.getSourceTableName(true);
String actionColor = m_tree.getActionColorName();
// List
SimpleListModel model = new SimpleListModel();
String sql = "SELECT t." + columnNameX
+ "_ID,t.Name,t.Description,t.IsSummary,"
+ actionColor
+ " FROM " + fromClause
// + " WHERE t.IsActive='Y'" // R/O
+ " ORDER BY 2";
sql = MRole.getDefault().addAccessSQL(sql,
"t", MRole.SQL_FULLYQUALIFIED, MRole.SQL_RO);
log.config(sql);
//
PreparedStatement pstmt = null;
ResultSet rs = null;
try
{
pstmt = DB.prepareStatement (sql, null);
rs = pstmt.executeQuery ();
while (rs.next ())
{
ListItem item = new ListItem(rs.getInt(1), rs.getString(2),
rs.getString(3), "Y".equals(rs.getString(4)), rs.getString(5));
model.addElement(item);
}
}
catch (Exception e)
{
log.log(Level.SEVERE, sql, e);
}
finally
{
DB.close(rs, pstmt);
rs = null; pstmt = null;
}
// List
log.config("#" + model.getSize());
centerList.setItemRenderer(model);
centerList.setModel(model);
// Tree
try {
centerTree.setModel(null);
} catch (Exception e) {
}
if (centerTree.getTreecols() != null)
centerTree.getTreecols().detach();
if (centerTree.getTreefoot() != null)
centerTree.getTreefoot().detach();
if (centerTree.getTreechildren() != null)
centerTree.getTreechildren().detach();
SimpleTreeModel.initADTree(centerTree, m_tree.getAD_Tree_ID(), m_WindowNo);
} // action_fillTree
/**
* List Selection Listener
* @param e event
*/
private void onListSelection(Event e)
{
ListItem selected = null;
try
{
SimpleListModel model = (SimpleListModel) centerList.getModel();
int i = centerList.getSelectedIndex();
selected = (ListItem)model.getElementAt(i);
}
catch (Exception ex)
{
}
log.info("Selected=" + selected);
if (selected != null) // allow add if not in tree
{
SimpleTreeModel tm = (SimpleTreeModel) centerTree.getModel();
SimpleTreeNode stn = tm.find(tm.getRoot(), selected.id);
if (stn != null) {
int[] path = tm.getPath(tm.getRoot(), stn);
Treeitem ti = centerTree.renderItemByPath(path);
ti.setSelected(true);
}
bAdd.setEnabled(stn == null);
}
} // valueChanged
/**
* Tree selection
* @param e event
*/
private void onTreeSelection (Event e)
{
Treeitem ti = centerTree.getSelectedItem();
SimpleTreeNode stn = (SimpleTreeNode) ti.getValue();
MTreeNode tn = (MTreeNode)stn.getData();
log.info(tn.toString());
if (tn == null)
return;
ListModel model = centerList.getModel();
int size = model.getSize();
int index = -1;
for (index = 0; index < size; index++)
{
ListItem item = (ListItem)model.getElementAt(index);
if (item.id == tn.getNode_ID())
break;
}
centerList.setSelectedIndex(index);
} // propertyChange
/**
* Action: Add Node to Tree
* @param item item
*/
private void action_treeAdd(ListItem item)
{
log.info("Item=" + item);
if (item != null)
{
SimpleTreeModel model = (SimpleTreeModel) centerTree.getModel();
SimpleTreeNode stn = model.find(model.getRoot(), item.id);
if (stn != null) {
MTreeNode tNode = (MTreeNode) stn.getData();
tNode.setName(item.name);
tNode.setAllowsChildren(item.isSummary);
tNode.setImageIndicator(item.imageIndicator);
model.nodeUpdated(stn);
Treeitem ti = centerTree.renderItemByPath(model.getPath(model.getRoot(), stn));
ti.setTooltiptext(item.description);
} else {
stn = new SimpleTreeNode(new MTreeNode(item.id, 0, item.name, item.description, 0, item.isSummary,
item.imageIndicator, false, null), new ArrayList<Object>());
model.addNode(stn);
}
// May cause Error if in tree
if (m_tree.isProduct())
{
MTree_NodePR node = new MTree_NodePR (m_tree, item.id);
node.save();
}
else if (m_tree.isBPartner())
{
MTree_NodeBP node = new MTree_NodeBP (m_tree, item.id);
node.save();
}
else if (m_tree.isMenu())
{
MTree_NodeMM node = new MTree_NodeMM (m_tree, item.id);
node.save();
}
else
{
MTree_Node node = new MTree_Node (m_tree, item.id);
node.save();
}
}
} // action_treeAdd
/**
* Action: Delete Node from Tree
* @param item item
*/
private void action_treeDelete(ListItem item)
{
log.info("Item=" + item);
if (item != null)
{
SimpleTreeModel model = (SimpleTreeModel) centerTree.getModel();
SimpleTreeNode stn = model.find(model.getRoot(), item.id);
if (stn != null)
model.removeNode(stn);
//
if (m_tree.isProduct())
{
MTree_NodePR node = MTree_NodePR.get (m_tree, item.id);
if (node != null)
node.delete(true);
}
else if (m_tree.isBPartner())
{
MTree_NodeBP node = MTree_NodeBP.get (m_tree, item.id);
if (node != null)
node.delete(true);
}
else if (m_tree.isMenu())
{
MTree_NodeMM node = MTree_NodeMM.get (m_tree, item.id);
if (node != null)
node.delete(true);
}
else
{
MTree_Node node = MTree_Node.get (m_tree, item.id);
if (node != null)
node.delete(true);
}
}
} // action_treeDelete
/**
* Action: Add All Nodes to Tree
*/
private void action_treeAddAll()
{
log.info("");
ListModel model = centerList.getModel();
int size = model.getSize();
int index = -1;
for (index = 0; index < size; index++)
{
ListItem item = (ListItem)model.getElementAt(index);
action_treeAdd(item);
}
} // action_treeAddAll
/**
* Action: Delete All Nodes from Tree
*/
private void action_treeDeleteAll()
{
log.info("");
//TODO: translation
if (FDialog.ask(m_WindowNo, null, "Remove all item(s) from tree?")) {
ListModel model = centerList.getModel();
int size = model.getSize();
int index = -1;
for (index = 0; index < size; index++)
{
ListItem item = (ListItem)model.getElementAt(index);
action_treeDelete(item);
}
}
} // action_treeDeleteAll
/**************************************************************************
* Tree Maintenance List Item
*/
class ListItem
{
/**
* ListItem
* @param ID
* @param Name
* @param Description
* @param summary
* @param ImageIndicator
*/
public ListItem (int ID, String Name, String Description,
boolean summary, String ImageIndicator)
{
id = ID;
name = Name;
description = Description;
isSummary = summary;
imageIndicator = ImageIndicator;
} // ListItem
/** ID */
public int id;
/** Name */
public String name;
/** Description */
public String description;
/** Summary */
public boolean isSummary;
/** Indicator */
public String imageIndicator; // Menu - Action
/**
* To String
* @return String Representation
*/
public String toString ()
{
String retValue = name;
if (description != null && description.length() > 0)
retValue += " (" + description + ")";
return retValue;
} // toString
} // ListItem
} // VTreeMaintenance

View File

@ -0,0 +1,136 @@
/******************************************************************************
* 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.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.util.logging.Level;
import javax.imageio.ImageIO;
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.VerticalBox;
import org.adempiere.webui.panel.ADForm;
import org.compiere.apps.wf.WFLine;
import org.compiere.model.MRole;
import org.compiere.util.DB;
import org.compiere.util.Env;
import org.compiere.util.KeyNamePair;
import org.compiere.wf.MWFNode;
import org.compiere.wf.MWFNodeNext;
import org.compiere.wf.MWorkflow;
import org.zkoss.image.AImage;
import org.zkoss.image.Image;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zul.Imagemap;
import org.zkoss.zul.Separator;
/**
*
* TODO: implement support for edit
* @author Low Heng Sin
*
*/
public class WFEditor extends ADForm {
private Listbox workflowList;
private Imagemap imageMap;
@Override
protected void initForm() {
VerticalBox vbox = new VerticalBox();
appendChild(vbox);
String sql = MRole.getDefault().addAccessSQL(
"SELECT AD_Workflow_ID, Name FROM AD_Workflow ORDER BY 2",
"AD_Workflow", MRole.SQL_NOTQUALIFIED, 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);
vbox.appendChild(workflowList);
vbox.appendChild(new Separator());
imageMap = new Imagemap();
vbox.appendChild(imageMap);
ConfirmPanel confirmPanel = new ConfirmPanel(true);
confirmPanel.addActionListener(this);
vbox.appendChild(new Separator());
vbox.appendChild(confirmPanel);
}
@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) {
ListItem item = workflowList.getSelectedItem();
KeyNamePair knp = item != null ? item.toKeyNamePair() : null;
if (knp != null && knp.getKey() > 0) {
load(knp.getKey());
} else {
Image dummy = null;
imageMap.setContent(dummy);
}
}
}
private void load(int workflowId) {
// Get Workflow
MWorkflow wf = new MWorkflow (Env.getCtx(), workflowId, null);
WFNodeContainer nodeContainer = new WFNodeContainer();
nodeContainer.setWorkflow(wf);
// Add Nodes for Paint
MWFNode[] nodes = wf.getNodes(true, Env.getAD_Client_ID(Env.getCtx()));
for (int i = 0; i < nodes.length; i++)
{
WFNode wfn = new WFNode (nodes[i]);
nodeContainer.add (wfn);
// Add Lines
MWFNodeNext[] nexts = nodes[i].getTransitions(Env.getAD_Client_ID(Env.getCtx()));
for (int j = 0; j < nexts.length; j++)
nodeContainer.add (new WFLine (nexts[j]));
}
Dimension dimension = nodeContainer.getDimension();
BufferedImage bi = new BufferedImage (dimension.width + 2, dimension.height + 2, BufferedImage.TYPE_INT_ARGB);
nodeContainer.paint(bi.createGraphics());
ByteArrayOutputStream os = new ByteArrayOutputStream();
try {
ImageIO.write(bi, "png", os);
AImage imageContent = new AImage("workflow.png", os.toByteArray());
imageMap.setWidth(dimension.width + "px");
imageMap.setHeight(dimension.height + "px");
imageMap.setContent(imageContent);
} catch (Exception e) {
logger.log(Level.SEVERE, e.getLocalizedMessage(), e);
}
}
}

View File

@ -0,0 +1,107 @@
/******************************************************************************
* 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.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.font.LineBreakMeasurer;
import java.awt.font.TextAttribute;
import java.awt.font.TextLayout;
import java.text.AttributedCharacterIterator;
import java.text.AttributedString;
import org.compiere.apps.wf.WFIcon;
import org.compiere.wf.MWFNode;
/**
*
* @author Low Heng Sin
*
*/
public class WFNode {
/** Size of the Node */
private static Dimension s_size = new Dimension (120, 50);
private MWFNode m_node;
private WFIcon m_icon;
private Rectangle m_bounds;
/**
* Create WF Node
* @param node model
*/
public WFNode (MWFNode node) {
m_node = node;
m_icon = new WFIcon(node.getAction());
m_bounds = new Rectangle(m_node.getXPosition(), m_node.getYPosition(), s_size.width,
s_size.height);
}
public void paint(Graphics2D g2D) {
m_icon.paintIcon(null, g2D, 0, 0);
// Paint Text
g2D.setPaint(Color.BLACK);
Font base = new Font(null);
Font font = new Font(base.getName(), Font.ITALIC | Font.BOLD, base.getSize());
//
AttributedString aString = new AttributedString(m_node.getName(true));
aString.addAttribute(TextAttribute.FONT, font);
aString.addAttribute(TextAttribute.FOREGROUND, Color.BLACK);
AttributedCharacterIterator iter = aString.getIterator();
//
LineBreakMeasurer measurer = new LineBreakMeasurer(iter, g2D.getFontRenderContext());
float width = s_size.width - m_icon.getIconWidth() - 2;
TextLayout layout = measurer.nextLayout(width);
float xPos = m_icon.getIconWidth();
float yPos = layout.getAscent() + 2;
//
layout.draw(g2D, xPos, yPos);
width = s_size.width - 4; // 2 pt
while (measurer.getPosition() < iter.getEndIndex())
{
layout = measurer.nextLayout(width);
yPos += layout.getAscent() + layout.getDescent() + layout.getLeading();
layout.draw(g2D, 2, yPos);
}
}
/**
*
* @return AD_WF_Node_ID
*/
public int getAD_WF_Node_ID() {
return m_node.getAD_WF_Node_ID();
}
public Rectangle getBounds() {
return m_bounds;
}
public MWFNode getNode() {
return m_node;
}
/**
*
* @param x
* @param y
* @param width
* @param height
*/
public void setBounds(int x, int y, int width, int height) {
m_bounds = new Rectangle(x, y, width, height);
}
}

View File

@ -0,0 +1,212 @@
/******************************************************************************
* 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.*;
import java.util.*;
import org.compiere.apps.wf.WFLine;
import org.compiere.util.*;
import org.compiere.wf.*;
/**
*
* @author Low Heng Sin
*
*/
public class WFNodeContainer
{
/**
* WFContentPanel
*/
public WFNodeContainer ()
{
} // WFContentPanel
/** Logger */
private static CLogger log = CLogger.getCLogger(WFNodeContainer.class);
/** Node List */
private ArrayList<WFNode> m_nodes = new ArrayList<WFNode>();
/** Line List */
private ArrayList<WFLine> m_lines = new ArrayList<WFLine>();
/** The Workflow */
private MWorkflow m_wf = null;
/**
* Set Workflow
* @param wf workflow
*/
public void setWorkflow (MWorkflow wf)
{
m_wf = wf;
} // setWorkflow
/**
* Remove All and their listeners
*/
public void removeAll ()
{
m_nodes.clear();
m_lines.clear();
} // removeAll
/**
* Add Component and add Mouse Listener
* @param comp component
* @return component
*/
public void add (WFNode node)
{
m_nodes.add(node);
} // add
/**
*
* @param line
*/
public void add(WFLine line)
{
m_lines.add(line);
}
/**
* Create Lines.
* Called by WF Layout Manager
*/
protected void createLines()
{
log.fine("Lines #" + m_lines.size());
for (int i = 0; i < m_lines.size(); i++)
{
WFLine line = (WFLine)m_lines.get(i);
Rectangle from = findBounds (line.getAD_WF_Node_ID());
Rectangle to = findBounds (line.getAD_WF_Next_ID());
line.setFromTo(from, to);
// same bounds as parent
// line.setBounds(0,0, width, height);
} // for all lines
}
/**
* Get Bounds of WF Node Icon
* @param AD_WF_Node_ID node id
* @return bounds of node with ID or null
*/
private Rectangle findBounds (int AD_WF_Node_ID)
{
for (int i = 0; i < m_nodes.size(); i++)
{
WFNode node = (WFNode)m_nodes.get(i);
if (node.getAD_WF_Node_ID() == AD_WF_Node_ID)
return node.getBounds();
}
return null;
} // findBounds
public Dimension getDimension()
{
if (needLayout())
updateLayout();
int width = 0;
int height = 0;
// Go through all node
for (int i = 0; i < m_nodes.size(); i++)
{
WFNode node = m_nodes.get(i);
Rectangle rect = node.getBounds();
if (rect.x + rect.width > width)
width = rect.x + rect.width;
if (rect.y + rect.height > height)
height = rect.y + rect.height;
} // for all components
return new Dimension(width, height);
}
/**************************************************************************
* Paint Component.
* Paint Lines directly as not added.
* @param g graphics
*/
public void paint(Graphics2D g)
{
for (int i = 0; i < m_nodes.size(); i++)
{
WFNode node = m_nodes.get(i);
Rectangle rect = node.getBounds();
g.setColor(Color.BLACK);
g.drawRect(rect.x, rect.y, rect.width, rect.height);
Graphics2D t = (Graphics2D) g.create(rect.x, rect.y, rect.width, rect.height);
node.paint(t);
t.dispose();
} // for all components
createLines();
// Paint Lines
for (int i = 0; i < m_lines.size(); i++)
{
WFLine line = (WFLine)m_lines.get(i);
line.paint(g);
}
} // paint
private void updateLayout() {
int x = 5;
int y = 5;for (int i = 0; i < m_nodes.size(); i++)
{
WFNode node = m_nodes.get(i);
Rectangle rect = node.getBounds();
node.setBounds(x, y, rect.width, rect.height);
// next pos
if (x == 5)
x = 230;
else
{
x = 5;
y += 100;
}
}
}
/**
* Need Layout
* @param parent parent
* @return true if we need to layout
*/
private boolean needLayout ()
{
// Go through all components
for (int i = 0; i < m_nodes.size(); i++)
{
WFNode node = m_nodes.get(i);
Rectangle rect = node.getBounds();
if (rect.x == 0 && rect.y == 0)
{
return true;
}
}
return false;
} // needLayout
public ArrayList<WFNode> getNodes() {
return m_nodes;
}
} // WFContentPanel

View File

@ -0,0 +1,246 @@
/******************************************************************************
* 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.Rectangle;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.util.*;
import java.util.logging.*;
import javax.imageio.ImageIO;
import org.adempiere.webui.component.Panel;
import org.adempiere.webui.component.VerticalBox;
import org.adempiere.webui.exception.ApplicationException;
import org.adempiere.webui.session.SessionManager;
import org.compiere.apps.wf.WFLine;
import org.compiere.util.*;
import org.compiere.wf.*;
import org.zkoss.image.AImage;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zk.ui.event.MouseEvent;
import org.zkoss.zul.Area;
import org.zkoss.zul.Div;
import org.zkoss.zul.Html;
import org.zkoss.zul.Imagemap;
import org.zkoss.zul.Separator;
/**
* WorkFlow Panel
*
* @author Low Heng Sin
*/
public class WFPanel extends Panel implements EventListener
{
/**
* Create Workflow Panel
*/
public WFPanel ()
{
try
{
jbInit();
}
catch(Exception e)
{
log.log(Level.SEVERE, "WFPanel", e);
}
m_WindowNo = SessionManager.getAppDesktop().registerWindow(this);
} // WFPanel
/** Window No */
private int m_WindowNo = 0;
/** Workflow Model */
private MWorkflow m_wf = null;
/** Context */
private Properties m_ctx = Env.getCtx();
/** Logger */
private static CLogger log = CLogger.getCLogger(WFPanel.class);
// IO
private WFNodeContainer nodeContainer = new WFNodeContainer();
private Html infoTextPane = new Html();
private Div contentPanel = new Div();
//
/**
* Static Init
* <pre>
* centerScrollPane
* centerPanel
* south Panel
* infoScrollPane
* buttonPanel
* </pre>
* @throws Exception
*/
private void jbInit() throws Exception
{
VerticalBox vbox = new VerticalBox();
appendChild(vbox);
// Center
contentPanel.setStyle("width: 100%; heigh: 100%; overflow: auto;");
vbox.appendChild(new Separator());
vbox.appendChild(contentPanel);
vbox.appendChild(new Separator());
vbox.appendChild(infoTextPane);
vbox.setHeights("85%,15%");
vbox.setStyle("padding-left: 10px");
} // jbInit
/**
* Dispose
* @see org.compiere.apps.form.FormPanel#dispose()
*/
public void dispose()
{
SessionManager.getAppDesktop().closeActiveWindow();
} // dispose
/**
* Load Workflow & Nodes
* @param AD_Workflow_ID ID
*/
public void load (int AD_Workflow_ID)
{
log.fine("AD_Workflow_ID=" + AD_Workflow_ID);
if (AD_Workflow_ID == 0)
return;
int AD_Client_ID = Env.getAD_Client_ID(Env.getCtx());
// Get Workflow
m_wf = new MWorkflow (Env.getCtx(), AD_Workflow_ID, null);
nodeContainer.removeAll();
nodeContainer.setWorkflow(m_wf);
// Add Nodes for Paint
MWFNode[] nodes = m_wf.getNodes(true, AD_Client_ID);
for (int i = 0; i < nodes.length; i++)
{
WFNode wfn = new WFNode (nodes[i]);
nodeContainer.add (wfn);
// Add Lines
MWFNodeNext[] nexts = nodes[i].getTransitions(AD_Client_ID);
for (int j = 0; j < nexts.length; j++)
nodeContainer.add (new WFLine (nexts[j]));
}
Dimension dimension = nodeContainer.getDimension();
BufferedImage bi = new BufferedImage (dimension.width + 2, dimension.height + 2, BufferedImage.TYPE_INT_ARGB);
nodeContainer.paint(bi.createGraphics());
ByteArrayOutputStream os = new ByteArrayOutputStream();
try {
ImageIO.write(bi, "png", os);
AImage imageContent = new AImage("workflow.png", os.toByteArray());
Imagemap image = new Imagemap();
image.setWidth(dimension.width + "px");
image.setHeight(dimension.height + "px");
image.setContent(imageContent);
contentPanel.appendChild(image);
image.addEventListener(Events.ON_CLICK, this);
for(WFNode node : nodeContainer.getNodes()) {
Area area = new Area();
Rectangle rect = node.getBounds();
area.setCoords(rect.x + "," + rect.y + "," + (rect.x+rect.width) + ","
+ (rect.y+rect.height));
image.appendChild(area);
area.setId("WFN_"+node.getAD_WF_Node_ID());
StringBuffer tooltip = new StringBuffer();
String s = node.getNode().getDescription(true);
if (s != null && s.trim().length() > 0)
tooltip.append(s);
String h = node.getNode().getHelp(true);
if (h != null && h.trim().length() > 0) {
if (tooltip.length() > 0)
tooltip.append(". ");
tooltip.append(h);
}
area.setTooltiptext(tooltip.toString());
}
} catch (Exception e) {
log.log(Level.SEVERE, e.getLocalizedMessage(), e);
}
// Info Text
StringBuffer msg = new StringBuffer("");
msg.append("<H2>").append(m_wf.getName(true)).append("</H2>");
String s = m_wf.getDescription(true);
if (s != null && s.length() > 0)
msg.append("<B>").append(s).append("</B>");
s = m_wf.getHelp(true);
if (s != null && s.length() > 0)
msg.append("<BR>").append(s);
infoTextPane.setContent(msg.toString());
} // load
/**
* String Representation
* @return info
*/
public String toString()
{
StringBuffer sb = new StringBuffer("WorkflowPanel[");
if (m_wf != null)
sb.append(m_wf.getAD_Workflow_ID());
sb.append("]");
return sb.toString();
} // toString
public MWorkflow getWorkflow()
{
return m_wf;
}
public void onEvent(Event event) throws Exception {
if (Events.ON_CLICK.equals(event.getName()) && event instanceof MouseEvent) {
MouseEvent me = (MouseEvent) event;
String areaId = me.getArea();
if (areaId != null && areaId.startsWith("WFN_")) {
int id = Integer.valueOf(areaId.substring(4));
for(WFNode node : nodeContainer.getNodes()) {
if (node.getAD_WF_Node_ID() == id) {
start(node);
break;
}
}
}
}
}
private void start(WFNode node) {
MWFNode wfn = node.getNode();
if (wfn.getAD_Window_ID() > 0) {
SessionManager.getAppDesktop().openWindow(wfn.getAD_Window_ID());
} else if (wfn.getAD_Form_ID() > 0) {
SessionManager.getAppDesktop().openForm(wfn.getAD_Form_ID());
} else if (wfn.getAD_Process_ID() > 0) {
SessionManager.getAppDesktop().openProcessDialog(wfn.getAD_Process_ID(), false);
} else if (wfn.getAD_Task_ID() > 0) {
SessionManager.getAppDesktop().openTask(wfn.getAD_Task_ID());
} else {
throw new ApplicationException("Action not yet implemented: " + wfn.getAction());
}
}
} // WFPanel

View File

@ -0,0 +1,128 @@
/******************************************************************************
* 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.component;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.adempiere.webui.apps.AEnv;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zul.Timebox;
/**
*
* @author Low Heng Sin
*
*/
public class DatetimeBox extends Panel {
private Datebox dateBox;
private Timebox timeBox;
public DatetimeBox() {
dateBox = new Datebox();
timeBox = new Timebox();
appendChild(dateBox);
appendChild(timeBox);
initComponents();
}
private void initComponents() {
dateBox.setStyle("display: inline");
timeBox.setStyle("display: inline");
timeBox.setButtonVisible(false);
String style = AEnv.isFirefox2() ? "display: inline" : "display: inline-block";
style = style + ";white-space:nowrap";
this.setStyle(style);
}
/**
* @param date
*/
public void setValue(Date date) {
dateBox.setValue(date);
timeBox.setValue(date);
}
/**
* @param text
*/
public void setText(String text) {
if (text != null && text.trim().length() > 0)
{
String[] s = text.split("\\s");
dateBox.setText(s[0]);
timeBox.setText(s[1]);
}
else
{
dateBox.setValue(null);
timeBox.setValue(null);
}
}
/**
* @return String
*/
public String getText() {
return dateBox.getText() + " " + timeBox.getText();
}
@Override
public boolean addEventListener(String evtnm, EventListener listener) {
return dateBox.addEventListener(evtnm, listener) && timeBox.addEventListener(evtnm, listener);
}
/**
* @return boolean
*/
public boolean isEnabled() {
return !dateBox.isReadonly();
}
/**
* @param readWrite
*/
public void setEnabled(boolean readWrite) {
dateBox.setDisabled(!readWrite);
timeBox.setDisabled(!readWrite);
dateBox.setButtonVisible(readWrite);
}
/**
* @return date
*/
public Date getValue() {
Date d = dateBox.getValue();
Date t = timeBox.getValue();
if (d != null && t != null) {
d.setHours(t.getHours());
d.setMinutes(t.getMinutes());
d.setSeconds(t.getSeconds());
}
return d;
}
/**
*
* @param dateFormat
*/
public void setDateFormat(SimpleDateFormat dateFormat) {
dateBox.setFormat(dateFormat.toPattern());
}
}

View File

@ -59,6 +59,7 @@ public class EditorBox extends Panel
private void initComponents()
{
txt = new Textbox();
txt.setStyle("display: inline;");
btn = new Button();
this.appendChild(txt);
@ -67,6 +68,7 @@ public class EditorBox extends Panel
btn.setSclass("editor-button");
String style = AEnv.isFirefox2() ? "display: inline" : "display: inline-block";
style = style + ";white-space:nowrap";
this.setStyle(style);
}

View File

@ -17,13 +17,13 @@
package org.adempiere.webui.component;
import org.adempiere.webui.apps.AEnv;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zul.Hbox;
/**
* URL Box
*/
public class FilenameBox extends Hbox
public class FilenameBox extends Panel
{
private static final long serialVersionUID = 1L;
@ -51,11 +51,15 @@ public class FilenameBox extends Hbox
private void initComponents()
{
textbox = new Textbox();
textbox.setWidth("100%");
textbox.setStyle("display: inline");
button = new Button();
button.setHeight("98%");
button.setSclass("editor-button");
appendChild(textbox);
appendChild(button);
String style = AEnv.isFirefox2() ? "display: inline" : "display: inline-block";
style = style + ";white-space:nowrap";
this.setStyle(style);
}
public void setText(String value)

View File

@ -53,12 +53,14 @@ public class Locationbox extends Panel
private void initComponents()
{
txt = new Textbox();
txt.setStyle("display: inline");
btn = new Button();
btn.setSclass("editor-button");
this.appendChild(txt);
this.appendChild(btn);
String style = AEnv.isFirefox2() ? "display: inline" : "display: inline-block";
style = style + ";white-space:nowrap";
this.setStyle(style);
}

View File

@ -25,6 +25,7 @@ import org.adempiere.webui.apps.AEnv;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zul.Decimalbox;
import org.zkoss.zul.Div;
import org.zkoss.zul.Hbox;
import org.zkoss.zul.Popup;
import org.zkoss.zul.Vbox;
@ -37,7 +38,7 @@ import org.zkoss.zul.Vbox;
*
* @author Low Heng Sin
*/
public class NumberBox extends Panel
public class NumberBox extends Div
{
private static final long serialVersionUID = 1L;
@ -66,6 +67,7 @@ public class NumberBox extends Panel
decimalBox = new Decimalbox();
if (integral)
decimalBox.setScale(0);
decimalBox.setStyle("display: inline;");
btn = new Button();
btn.setImage("/images/Calculator16.png");
@ -73,12 +75,13 @@ public class NumberBox extends Panel
Popup popup = getCalculatorPopup();
btn.setSclass("editor-button");
btn.setPopup(popup);
btn.setStyle("text-align: center");
btn.setStyle("text-align: center;");
appendChild(decimalBox);
appendChild(btn);
appendChild(popup);
String style = AEnv.isFirefox2() ? "display: inline" : "display: inline-block";
style = style + ";white-space:nowrap";
this.setStyle(style);
}

View File

@ -51,13 +51,15 @@ public class PAttributebox extends Panel
private void initComponents()
{
textBox = new Textbox();
textBox.setStyle("display: inline");
button = new Button();
button.setSclass("editor-button");
appendChild(textBox);
appendChild(button);
String style = AEnv.isFirefox2() ? "display: inline" : "display: inline-block";
this.setStyle(style);
style = style + ";white-space:nowrap";
this.setStyle(style + ";overflow: hidden");
}
public void setText(String value)

View File

@ -22,8 +22,9 @@ import java.beans.PropertyChangeSupport;
import org.adempiere.webui.apps.AEnv;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zul.Div;
public class Searchbox extends Panel
public class Searchbox extends Div
{
private static final long serialVersionUID = 1L;
private PropertyChangeSupport m_propertyChangeListeners = new PropertyChangeSupport(this);
@ -49,12 +50,14 @@ public class Searchbox extends Panel
private void initComponents()
{
txt = new Textbox();
txt.setStyle("display: inline;");
btn = new Button();
btn.setSclass("editor-button");
appendChild(txt);
appendChild(btn);
String style = AEnv.isFirefox2() ? "display: inline" : "display: inline-block";
style = style + ";white-space:nowrap";
this.setStyle(style);
}

View File

@ -1,97 +0,0 @@
/******************************************************************************
* Product: Posterita Ajax UI *
* Copyright (C) 2007 Posterita Ltd. All Rights Reserved. *
* 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. *
* For the text or an alternative of this public license, you may reach us *
* Posterita Ltd., 3, Draper Avenue, Quatre Bornes, Mauritius *
* or via info@posterita.org or http://www.posterita.org/ *
*****************************************************************************/
package org.adempiere.webui.component;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import org.zkoss.zk.ui.event.EventListener;
public class Searchbox2 extends Bandbox
{
private static final long serialVersionUID = 1L;
private PropertyChangeSupport m_propertyChangeListeners = new PropertyChangeSupport(this);
// private Textbox txt;
// private Button btn;
public Searchbox2()
{
initComponents();
}
public Searchbox2(String text)
{
initComponents();
setText(text);
}
public void setButtonImage(String imageSrc)
{
this.setImage(imageSrc);
}
private void initComponents()
{
// txt = new Textbox();
// txt.setWidth("100%");
// btn = new Button();
// btn.setHeight("98%");
// appendChild(txt);
// appendChild(btn);
}
// public void setText(String value)
// {
// txt.setText(value);
// }
// public String getText()
// {
// return txt.getText();
// }
public void setEnabled(boolean enabled)
{
setReadonly(!enabled);
// txt.setReadonly(!enabled);
// btn.setEnabled(enabled);
}
public boolean isEnabled()
{
return !isReadonly();
// return txt.isReadonly();
}
public boolean addEventListener(String evtnm, EventListener listener)
{
return super.addEventListener(evtnm, listener);
// if("onClick".equals(evtnm))
// {
// return btn.addEventListener(evtnm, listener);
// }
// else
// {
// return txt.addEventListener(evtnm, listener);
// }
}
public synchronized void addPropertyChangeListener(PropertyChangeListener l)
{
m_propertyChangeListeners.addPropertyChangeListener(l);
}
}

View File

@ -219,4 +219,12 @@ public class SimpleTreeModel extends org.zkoss.zul.SimpleTreeModel implements Tr
}
return null;
}
public void nodeUpdated(SimpleTreeNode node) {
SimpleTreeNode parent = getParent(node);
if (parent != null) {
int i = parent.getChildren().indexOf(node);
fireEvent(parent, i, i, TreeDataEvent.CONTENTS_CHANGED);
}
}
}

View File

@ -19,7 +19,6 @@ package org.adempiere.webui.component;
import org.adempiere.webui.apps.AEnv;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zul.Hbox;
/**
* URL Box
@ -52,12 +51,14 @@ public class Urlbox extends Panel
private void initComponents()
{
txtUrl = new Textbox();
txtUrl.setStyle("display: inline;");
btnUrl = new Button();
btnUrl.setSclass("editor-button");
appendChild(txtUrl);
appendChild(btnUrl);
String style = AEnv.isFirefox2() ? "display: inline" : "display: inline-block";
style = style + ";white-space:nowrap";
this.setStyle(style);
}

View File

@ -25,6 +25,7 @@ import org.adempiere.webui.component.Datebox;
import org.adempiere.webui.event.ValueChangeEvent;
import org.compiere.model.GridField;
import org.compiere.util.CLogger;
import org.compiere.util.DisplayType;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.Events;
@ -53,6 +54,7 @@ public class WDateEditor extends WEditor
public WDateEditor(GridField gridField)
{
super(new Datebox(), gridField);
init();
}
@ -74,11 +76,12 @@ public class WDateEditor extends WEditor
{
super(new Datebox(), label, description, mandatory, readonly, updateable);
setColumnName("Date");
init();
}
public WDateEditor()
{
this("Date", "Date", false, false, true);
this("Date", "Date", false, false, true);
} // VDate
/**
@ -94,6 +97,11 @@ public class WDateEditor extends WEditor
{
super(new Datebox(), columnName, title, null, mandatory, readonly, updateable);
}
private void init()
{
getComponent().setFormat(DisplayType.getDateFormat().toPattern());
}
public void onEvent(Event event)
{

View File

@ -0,0 +1,189 @@
/******************************************************************************
* 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.editor;
import java.sql.Timestamp;
import java.util.Date;
import org.adempiere.webui.component.DatetimeBox;
import org.adempiere.webui.event.ValueChangeEvent;
import org.compiere.model.GridField;
import org.compiere.util.CLogger;
import org.compiere.util.DisplayType;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.Events;
/**
*
* @author Low Heng Sin
*/
public class WDatetimeEditor extends WEditor
{
private static final String[] LISTENER_EVENTS = {Events.ON_CHANGE};
private static final CLogger logger;
static
{
logger = CLogger.getCLogger(WDatetimeEditor.class);
}
private Timestamp oldValue = new Timestamp(0);
/**
*
* @param gridField
*/
public WDatetimeEditor(GridField gridField)
{
super(new DatetimeBox(), gridField);
init();
}
/**
* Constructor for use if a grid field is unavailable
*
* @param label
* column name (not displayed)
* @param description
* description of component
* @param mandatory
* whether a selection must be made
* @param readonly
* whether or not the editor is read only
* @param updateable
* whether the editor contents can be changed
*/
public WDatetimeEditor (String label, String description, boolean mandatory, boolean readonly, boolean updateable)
{
super(new DatetimeBox(), label, description, mandatory, readonly, updateable);
setColumnName("Datetime");
init();
}
public WDatetimeEditor()
{
this("Datetime", "Datetime", false, false, true);
} // VDate
/**
*
* @param columnName
* @param mandatory
* @param readonly
* @param updateable
* @param title
*/
public WDatetimeEditor(String columnName, boolean mandatory, boolean readonly, boolean updateable,
String title)
{
super(new DatetimeBox(), columnName, title, null, mandatory, readonly, updateable);
init();
}
private void init()
{
getComponent().setDateFormat(DisplayType.getDateFormat());
}
public void onEvent(Event event)
{
Date date = getComponent().getValue();
Timestamp newValue = null;
if (date != null)
{
newValue = new Timestamp(date.getTime());
}
ValueChangeEvent changeEvent = new ValueChangeEvent(this, this.getColumnName(), oldValue, newValue);
super.fireValueChange(changeEvent);
oldValue = newValue;
}
@Override
public String getDisplay()
{
// Elaine 2008/07/29
return getComponent().getText();
//
}
@Override
public Object getValue()
{
// Elaine 2008/07/25
if(getComponent().getValue() == null) return null;
return new Timestamp(getComponent().getValue().getTime());
//
}
@Override
public boolean isMandatory()
{
return false;
}
@Override
public void setMandatory(boolean mandatory)
{
}
@Override
public void setValue(Object value)
{
if (value == null || value.toString().trim().length() == 0)
{
oldValue = null;
getComponent().setValue(null);
}
else if (value instanceof Timestamp)
{
getComponent().setValue((Timestamp)value);
oldValue = (Timestamp)value;
}
else
{
try
{
getComponent().setText(value.toString());
} catch (Exception e) {}
if (getComponent().getValue() != null)
oldValue = new Timestamp(getComponent().getValue().getTime());
else
oldValue = null;
}
}
@Override
public DatetimeBox getComponent() {
return (DatetimeBox) component;
}
@Override
public boolean isReadWrite() {
return getComponent().isEnabled();
}
@Override
public void setReadWrite(boolean readWrite) {
getComponent().setEnabled(readWrite);
}
public String[] getEvents()
{
return LISTENER_EVENTS;
}
}

View File

@ -109,6 +109,8 @@ public class WebEditorFactory
{
if (displayType == DisplayType.Time)
editor = new WTimeEditor(gridField);
else if (displayType == DisplayType.DateTime)
editor = new WDatetimeEditor(gridField);
else
editor = new WDateEditor(gridField);
}

View File

@ -192,6 +192,8 @@ public abstract class ADForm extends Window implements EventListener
webClassName = "org.adempiere.webui.apps.form.WArchiveViewer"; // TEMP
else if ("org.compiere.apps.wf.WFActivity".equals(richClassName))
webClassName = "org.adempiere.webui.apps.wf.WWFActivity"; // TEMP
else if ("org.compiere.apps.wf.WFPanel".equals(richClassName))
webClassName = "org.adempiere.webui.apps.wf.WFEditor";
else
webClassName = translateFormClassName(richClassName);

View File

@ -75,6 +75,7 @@ import org.zkoss.zkex.zul.West;
import org.zkoss.zul.Div;
import org.zkoss.zul.Separator;
import org.zkoss.zul.SimpleTreeNode;
import org.zkoss.zul.Space;
import org.zkoss.zul.Toolbarbutton;
import org.zkoss.zul.Tree;
import org.zkoss.zul.Treeitem;
@ -360,7 +361,7 @@ DataStatusListener, ValueChangeListener, IADTabpanel
//can't stretch bandbox & datebox
if (!(editor.getComponent() instanceof Bandbox) &&
!(editor.getComponent() instanceof Datebox)) {
String width = AEnv.isFirefox2() ? "99%" : "100%";
String width = "99%";
((HtmlBasedComponent)editor.getComponent()).setWidth(width);
}
}
@ -404,11 +405,7 @@ DataStatusListener, ValueChangeListener, IADTabpanel
}
private Component createSpacer() {
Span span = new Span();
Text text = new Text("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;");
text.setParent(span);
span.setStyle("width: 100%");
return span;
return new Space();
}
public void dynamicDisplay (int col)

View File

@ -118,6 +118,8 @@ public abstract class AbstractADWindowPanel extends AbstractUIPart implements To
private boolean m_uiLocked;
private boolean m_findCancelled;
public AbstractADWindowPanel(Properties ctx, int windowNo)
{
this.ctx = ctx;
@ -201,6 +203,9 @@ public abstract class AbstractADWindowPanel extends AbstractUIPart implements To
if (tab == 0)
{
query = initialQuery(query, gTab);
if (gTab.isHighVolume() && m_findCancelled)
return false;
if (query != null && query.getRecordCount() <= 1)
{
// goSingleRow = true;
@ -211,6 +216,7 @@ public abstract class AbstractADWindowPanel extends AbstractUIPart implements To
m_onlyCurrentRows = false;
gTab.setQuery(query);
}
curTab = gTab;
curTabIndex = tab;
}
@ -309,6 +315,7 @@ public abstract class AbstractADWindowPanel extends AbstractUIPart implements To
// Show Query
if (require)
{
m_findCancelled = false;
GridField[] findFields = mTab.getFields();
FindWindow find = new FindWindow(curWindowNo,
mTab.getName(), mTab.getAD_Table_ID(), mTab.getTableName(),
@ -317,7 +324,10 @@ public abstract class AbstractADWindowPanel extends AbstractUIPart implements To
// Title is not set when the number of rows is below the minRecords parameter (10)
find.setVisible(true);
AEnv.showWindow(find);
query = find.getQuery();
if (!find.isCancel())
query = find.getQuery();
else
m_findCancelled = true;
find = null;
}
}

View File

@ -166,7 +166,7 @@ public class MenuPanel extends Panel implements EventListener
if (mChildNode.isReport())
treeitem.setImage("/images/mReport.png");
else if (mChildNode.isProcess())
else if (mChildNode.isProcess() || mChildNode.isTask())
treeitem.setImage("/images/mProcess.png");
else if (mChildNode.isWorkFlow())
treeitem.setImage("/images/mWorkFlow.png");

View File

@ -0,0 +1,206 @@
/******************************************************************************
* 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.util;
import java.io.*;
import java.util.logging.*;
import org.compiere.util.CLogger;
/**
* Execute OS Task
*
* @author Low Heng Sin
*/
public class OSTask extends Thread
{
/**
* Create Process with cmd
* @param cmd o/s command
*/
public OSTask (String cmd)
{
m_cmd = cmd;
} // Task
private String m_cmd;
private Process m_child = null;
private StringBuffer m_out = new StringBuffer();
private StringBuffer m_err = new StringBuffer();
/** The Output Stream of process */
private InputStream m_outStream;
/** The Error Output Stream of process */
private InputStream m_errStream;
/** The Input Stream of process */
private OutputStream m_inStream;
/** Logger */
private static CLogger log = CLogger.getCLogger(OSTask.class);
/** Read Out */
private Thread m_outReader = new Thread()
{
public void run()
{
log.fine("outReader");
try
{
int c;
while ((c = m_outStream.read()) != -1 && !isInterrupted())
{
m_out.append((char)c);
}
m_outStream.close();
}
catch (IOException ioe)
{
log.log(Level.SEVERE, "outReader", ioe);
}
log.fine("outReader - done");
} // run
}; // m_outReader
/** Read Out */
private Thread m_errReader = new Thread()
{
public void run()
{
log.fine("errReader");
try
{
int c;
while ((c = m_errStream.read()) != -1 && !isInterrupted())
{
m_err.append((char)c);
}
m_errStream.close();
}
catch (IOException ioe)
{
log.log(Level.SEVERE, "errReader", ioe);
}
log.fine("errReader - done");
} // run
}; // m_errReader
/**
* Execute it
*/
public void run()
{
log.info(m_cmd);
try
{
m_child = Runtime.getRuntime().exec(m_cmd);
//
m_outStream = m_child.getInputStream();
m_errStream = m_child.getErrorStream();
m_inStream = m_child.getOutputStream();
//
if (checkInterrupted())
return;
m_outReader.start();
m_errReader.start();
Integer exitValue = null;
while(exitValue == null)
{
//
try
{
Thread.sleep(500);
if (checkInterrupted())
return;
int i = m_child.exitValue();
exitValue = new Integer(i);
}
catch (Exception ie)
{
log.log(Level.INFO, "(ie) - " + ie);
}
// ExitValue
log.config("done");
}
}
catch (IOException ioe)
{
log.log(Level.SEVERE, "(ioe)", ioe);
}
} // run
/**
* Check if interrupted
* @return true if interrupted
*/
private boolean checkInterrupted()
{
if (isInterrupted())
{
log.config("interrupted");
// interrupt child processes
if (m_child != null)
m_child.destroy();
m_child = null;
if (m_outReader != null && m_outReader.isAlive())
m_outReader.interrupt();
m_outReader = null;
if (m_errReader != null && m_errReader.isAlive())
m_errReader.interrupt();
m_errReader = null;
// close Streams
if (m_inStream != null)
try { m_inStream.close(); } catch (Exception e) {}
m_inStream = null;
if (m_outStream != null)
try { m_outStream.close(); } catch (Exception e) {}
m_outStream = null;
if (m_errStream != null)
try { m_errStream.close(); } catch (Exception e) {}
m_errStream = null;
//
return true;
}
return false;
} // checkInterrupted
/**
* Get Out Info
* @return StringBuffer
*/
public StringBuffer getOut()
{
return m_out;
} // getOut
/**
* Get Err Info
* @return StringBuffer
*/
public StringBuffer getErr()
{
return m_err;
} // getErr
/**
* Get The process input stream - i.e. we output to it
* @return OutputStream
*/
public OutputStream getInStream()
{
return m_inStream;
} // getInStream
} // Task

View File

@ -77,10 +77,16 @@ public class ADWindow extends AbstractUIPart
windowPanelComponent = windowPanel.createPart(parent);
windowPanelComponent.setAttribute("ADWindow", this);
windowPanelComponent.setAttribute("desktop.windowno", windowNo);
windowPanel.initPanel(adWindowId, query);
_title = windowPanel.getTitle();
return windowPanelComponent;
if (windowPanel.initPanel(adWindowId, query))
{
_title = windowPanel.getTitle();
return windowPanelComponent;
}
else
{
windowPanelComponent.detach();
return null;
}
}
public Component getComponent() {

View File

@ -654,7 +654,7 @@ public class FindWindow extends Window implements EventListener,ValueChangeListe
public void onEvent(Event event) throws Exception
{
if ("onSelect".equals(event.getName()))
if (Events.ON_SELECT.equals(event.getName()))
{
if (event.getTarget() instanceof Listbox)
{
@ -685,7 +685,7 @@ public class FindWindow extends Window implements EventListener,ValueChangeListe
parseUserQuery(userQueries[index]);
}
} //
else if ("onClick".equals(event.getName()))
else if (Events.ON_CLICK.equals(event.getName()))
{
// Toolbar Buttons actions
if(event.getTarget() instanceof ToolBarButton)
@ -726,6 +726,7 @@ public class FindWindow extends Window implements EventListener,ValueChangeListe
}
else if("btnCancel".equals(btn.getName()))
{
m_isCancel = true;
dispose();
}
else if ("btnNew".equals(btn.getName()))
@ -757,7 +758,7 @@ public class FindWindow extends Window implements EventListener,ValueChangeListe
}
}
}
else if ("onOK".equals(event.getName()))
else if (Events.ON_OK.equals(event.getName()))
{
if (winLookupRecord.equals(event.getTarget()))
{
@ -1714,5 +1715,12 @@ public class FindWindow extends Window implements EventListener,ValueChangeListe
Clients.response(new AuFocus(m_sEditors.get(0).getComponent()));
}
/**
*
* @return true if dialog cancel by user, false otherwise
*/
public boolean isCancel() {
return m_isCancel;
}
} // FindPanel

View File

@ -0,0 +1,193 @@
/******************************************************************************
* Product: Adempiere ERP & CRM Smart Business Solution *
* Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. *
* 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. *
* For the text or an alternative of this public license, you may reach us *
* ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA *
* or via info@compiere.org or http://www.compiere.org/license.html *
*****************************************************************************/
package org.adempiere.webui.window;
import java.util.logging.*;
import org.adempiere.webui.LayoutUtils;
import org.adempiere.webui.component.ConfirmPanel;
import org.adempiere.webui.component.Window;
import org.adempiere.webui.session.SessionManager;
import org.adempiere.webui.util.OSTask;
import org.compiere.util.*;
import org.compiere.model.*;
import org.zkoss.zk.ui.DesktopUnavailableException;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zkex.zul.Borderlayout;
import org.zkoss.zkex.zul.Center;
import org.zkoss.zkex.zul.South;
import org.zkoss.zul.Div;
import org.zkoss.zul.Html;
/**
* Application Task
*
* @author Jorg Janke
* @version $Id: ATask.java,v 1.2 2006/07/30 00:51:27 jjanke Exp $
*
* @author Low Heng Sin
*/
public class WTask extends Window implements EventListener
{
/**
* Start Application Task
* @param task task model
*/
public static void start (final String title, final MTask task)
{
new WTask(title, task);
} // start
private MTask m_task;
private Thread taskThread;
/**************************************************************************
* Full Constructor
* @param title title
* @param task task
*/
public WTask (String title, MTask task)
{
super ();
setTitle(title);
try
{
zkInit();
setAttribute(Window.MODE_KEY, Window.MODE_EMBEDDED);
//
m_task = task;
if (task.isServerProcess())
info.setContent("Executing on Server ...");
else
info.setContent("Executing locally ...");
SessionManager.getAppDesktop().showWindow(this);
Events.echoEvent("executeTask", this, null);
}
catch(Exception e)
{
log.log(Level.SEVERE, task.toString(), e);
}
} // ATask
public void executeTask() {
Runnable runnable = new Runnable() {
public void run() {
//get full control of desktop
org.zkoss.zk.ui.Desktop desktop = WTask.this.getDesktop();
String cmd = Msg.parseTranslation(Env.getCtx(), m_task.getOS_Command()).trim();
if (cmd == null || cmd.equals(""))
info.setContent("Cannot execute '" + m_task.getOS_Command() + "'");
OSTask osTask = new OSTask(cmd);
osTask.start();
while (true) {
try {
Thread.sleep(500);
Executions.activate(desktop);
try {
StringBuffer sb = new StringBuffer();
sb.append(osTask.getOut())
.append("<br>-----------<br>")
.append(osTask.getErr())
.append("<br>-----------");
info.setContent(sb.toString().replace("\n", "<br>"));
if (!osTask.isAlive())
{
confirmPanel.getButton(ConfirmPanel.A_CANCEL).setEnabled(false);
confirmPanel.getOKButton().setEnabled(true);
break;
}
} finally{
//release full control of desktop
Executions.deactivate(desktop);
}
} catch (DesktopUnavailableException e) {
log.log(Level.SEVERE, e.getLocalizedMessage(), e);
} catch (InterruptedException e) {
log.log(Level.WARNING, e.getLocalizedMessage(), e);
osTask.interrupt();
break;
}
}
}
};
taskThread = new Thread(runnable);
taskThread.start();
}
/** Logger */
private static CLogger log = CLogger.getCLogger(WTask.class);
private ConfirmPanel confirmPanel = new ConfirmPanel(true);
private Html info = new Html();
/**
* Static Layout
* @throws Exception
*/
private void zkInit() throws Exception
{
Borderlayout layout = new Borderlayout();
layout.setWidth("100%");
layout.setHeight("100%");
layout.setStyle("position: absolute;");
this.setHeight("100%");
this.setWidth("100%");
appendChild(layout);
Center center = new Center();
layout.appendChild(center);
Div div = new Div();
div.setStyle("width: 100%; height:100%; overflow: auto");
div.appendChild(info);
center.appendChild(div);
center.setFlex(true);
South south = new South();
layout.appendChild(south);
south.setStyle("border: none");
south.appendChild(confirmPanel);
//
confirmPanel.addActionListener(this);
confirmPanel.getOKButton().setEnabled(false);
LayoutUtils.sendDeferLayoutEvent(layout, 100);
} // jbInit
/**
* Action Listener
* @param e
*/
public void onEvent(Event e)
{
if (taskThread != null && taskThread.isAlive())
taskThread.interrupt();
SessionManager.getAppDesktop().closeActiveWindow();
} // actionPerformed
} // ATask

View File

@ -27,7 +27,16 @@ html,body {
.disableFilter img {
opacity: 0.2;
filter: progid : DXImageTransform . Microsoft . Alpha(opacity = 20);
-moz-opacity: 0.2;
-moz-opacity: 0.2;
}
.depressed {
border-style: inset;
border-width: 1px;
border-color: #CCCCCC;
background-color: #E4E3DC;
-moz-border-radius: 5px;
padding: 1px 4px 1px 4px;
}
.header {
@ -56,6 +65,7 @@ html,body {
height: 22px;
width: 26px;
padding: 0px;
display: inline;
}
.editor-button img {