From e1c6a92c0591fee41b1b01a6fb29c8025466c26b Mon Sep 17 00:00:00 2001 From: Heng Sin Low Date: Fri, 18 Jul 2008 18:55:04 +0000 Subject: [PATCH] * Added initial support for tree tab. --- .../webui/component/SimpleTreeModel.java | 84 ++++++++ .../org/adempiere/webui/panel/ADTabpanel.java | 184 +++++++++++++++--- 2 files changed, 245 insertions(+), 23 deletions(-) create mode 100644 zkwebui/WEB-INF/src/org/adempiere/webui/component/SimpleTreeModel.java diff --git a/zkwebui/WEB-INF/src/org/adempiere/webui/component/SimpleTreeModel.java b/zkwebui/WEB-INF/src/org/adempiere/webui/component/SimpleTreeModel.java new file mode 100644 index 0000000000..b9580daabc --- /dev/null +++ b/zkwebui/WEB-INF/src/org/adempiere/webui/component/SimpleTreeModel.java @@ -0,0 +1,84 @@ +/****************************************************************************** + * 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. * + * 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.util.ArrayList; +import java.util.Enumeration; + +import org.compiere.model.MTreeNode; +import org.zkoss.lang.Objects; +import org.zkoss.zul.SimpleTreeNode; +import org.zkoss.zul.Treecell; +import org.zkoss.zul.Treeitem; +import org.zkoss.zul.TreeitemRenderer; +import org.zkoss.zul.Treerow; + +/** + * + * @author Low Heng Sin + * + */ +public class SimpleTreeModel extends org.zkoss.zul.SimpleTreeModel implements TreeitemRenderer { + + public SimpleTreeModel(SimpleTreeNode root) { + super(root); + } + + public static SimpleTreeModel createFrom(MTreeNode root) { + SimpleTreeModel model = null; + Enumeration nodeEnum = root.children(); + + SimpleTreeNode stRoot = new SimpleTreeNode(root, new ArrayList()); + while(nodeEnum.hasMoreElements()) { + MTreeNode childNode = (MTreeNode)nodeEnum.nextElement(); + SimpleTreeNode stNode = new SimpleTreeNode(childNode, new ArrayList()); + stRoot.getChildren().add(stNode); + if (childNode.getChildCount() > 0) { + populate(stNode, childNode); + } + } + model = new SimpleTreeModel(stRoot); + return model; + } + + private static void populate(SimpleTreeNode stNode, MTreeNode root) { + Enumeration nodeEnum = root.children(); + while(nodeEnum.hasMoreElements()) { + MTreeNode childNode = (MTreeNode)nodeEnum.nextElement(); + SimpleTreeNode stChildNode = new SimpleTreeNode(childNode, new ArrayList()); + stNode.getChildren().add(stChildNode); + if (childNode.getChildCount() > 0) { + populate(stChildNode, childNode); + } + } + } + + public void render(Treeitem ti, Object node) { + Treecell tc = new Treecell(Objects.toString(node)); + Treerow tr = null; + if(ti.getTreerow()==null){ + tr = new Treerow(); + tr.setParent(ti); + }else{ + tr = ti.getTreerow(); + tr.getChildren().clear(); + } + tc.setParent(tr); + + ti.setValue(node); + } + +} diff --git a/zkwebui/WEB-INF/src/org/adempiere/webui/panel/ADTabpanel.java b/zkwebui/WEB-INF/src/org/adempiere/webui/panel/ADTabpanel.java index 5429448a9b..1c53084124 100644 --- a/zkwebui/WEB-INF/src/org/adempiere/webui/panel/ADTabpanel.java +++ b/zkwebui/WEB-INF/src/org/adempiere/webui/panel/ADTabpanel.java @@ -23,6 +23,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.logging.Level; import org.adempiere.webui.LayoutUtils; import org.adempiere.webui.component.Bandbox; @@ -33,6 +34,7 @@ import org.adempiere.webui.component.Label; import org.adempiere.webui.component.Listbox; import org.adempiere.webui.component.Row; import org.adempiere.webui.component.Rows; +import org.adempiere.webui.component.SimpleTreeModel; import org.adempiere.webui.component.ToolBar; import org.adempiere.webui.editor.IZoomableEditor; import org.adempiere.webui.editor.WButtonEditor; @@ -50,6 +52,8 @@ import org.compiere.model.GridTab; import org.compiere.model.GridTable; import org.compiere.model.GridWindow; import org.compiere.model.MLookup; +import org.compiere.model.MTree; +import org.compiere.model.MTreeNode; import org.compiere.model.X_AD_FieldGroup; import org.compiere.util.CLogger; import org.compiere.util.Env; @@ -62,9 +66,17 @@ import org.zkoss.zk.ui.HtmlBasedComponent; 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.West; import org.zkoss.zul.Div; import org.zkoss.zul.Separator; +import org.zkoss.zul.SimpleTreeNode; import org.zkoss.zul.Toolbarbutton; +import org.zkoss.zul.Tree; +import org.zkoss.zul.Treecol; +import org.zkoss.zul.Treecols; +import org.zkoss.zul.Treeitem; /** * @@ -76,7 +88,8 @@ import org.zkoss.zul.Toolbarbutton; * @author Ashley G Ramdass * @date Feb 25, 2007 * @version $Revision: 0.10 $ - * + * + * @author Low Heng Sin */ public class ADTabpanel extends Div implements Evaluatee, EventListener, DataStatusListener, ValueChangeListener, IADTabpanel @@ -116,6 +129,10 @@ DataStatusListener, ValueChangeListener, IADTabpanel private Map> fieldGroupHeaders = new HashMap>(); private ArrayList rowList; + + private Component formComponent = null; + + private Tree tree = null; public ADTabpanel() { @@ -134,14 +151,15 @@ DataStatusListener, ValueChangeListener, IADTabpanel grid = new Grid(); //have problem moving the following out as css class grid.setWidth("99%"); - grid.setHeight("100%"); - grid.setStyle("margin:0; padding:0; position: absolute"); + grid.setHeight("100%"); grid.setSclass("grid-no-striped"); + grid.setStyle("margin:0; padding:0; position: absolute"); grid.setOddRowSclass("even"); listPanel = new GridPanel(); - listPanel.getListbox().addEventListener(Events.ON_DOUBLE_CLICK, this); + listPanel.getListbox().addEventListener(Events.ON_DOUBLE_CLICK, this); + } public void init(AbstractADWindowPanel winPanel, int windowNo, GridTab gridTab, @@ -152,12 +170,51 @@ DataStatusListener, ValueChangeListener, IADTabpanel this.gridTab = gridTab; this.windowPanel = winPanel; gridTab.addDataStatusListener(this); + + this.getChildren().clear(); + + int AD_Tree_ID = 0; + if (gridTab.isTreeTab()) + AD_Tree_ID = MTree.getDefaultAD_Tree_ID ( + Env.getAD_Client_ID(Env.getCtx()), gridTab.getKeyColumnName()); + if (gridTab.isTreeTab() && AD_Tree_ID != 0) + { + Borderlayout layout = new Borderlayout(); + layout.setParent(this); + layout.setStyle("width: 100%; height: 100%; position: absolute;"); + + tree = new Tree(); + tree.setStyle("border: none"); + West west = new West(); + west.appendChild(tree); + west.setWidth("300px"); + west.setCollapsible(true); + west.setSplittable(true); + west.setAutoscroll(true); + layout.appendChild(west); + + Center center = new Center(); + center.setFlex(true); + center.appendChild(grid); + layout.appendChild(center); + + formComponent = layout; + tree.addEventListener(Events.ON_SELECT, this); + } + else + { + this.appendChild(grid); + formComponent = grid; + } + this.appendChild(listPanel); + listPanel.setVisible(false); } public void createUI() { if (uiCreated) return; + uiCreated = true; Rows rows = new Rows(); GridField fields[] = gridTab.getFields(); Row row = new Row(); @@ -334,7 +391,25 @@ DataStatusListener, ValueChangeListener, IADTabpanel } grid.appendChild(rows); - uiCreated = true; + if (gridTab.isTreeTab() && tree != null) { + int AD_Tree_ID = MTree.getDefaultAD_Tree_ID ( + Env.getAD_Client_ID(Env.getCtx()), gridTab.getKeyColumnName()); + MTree vTree = new MTree (Env.getCtx(), AD_Tree_ID, false, true, null); + MTreeNode root = vTree.getRoot(); + SimpleTreeModel treeModel = SimpleTreeModel.createFrom(root); + + Treecols treeCols = new Treecols(); + tree.appendChild(treeCols); + Treecol treeCol = new Treecol(); + treeCols.appendChild(treeCol); + tree.setPageSize(-1); + try { + tree.setTreeitemRenderer(treeModel); + tree.setModel(treeModel); + } catch (Exception e) { + logger.log(Level.SEVERE, "Failed to setup tree"); + } + } } private Component createSpacer() { @@ -525,17 +600,6 @@ DataStatusListener, ValueChangeListener, IADTabpanel public void activate(boolean activate) { - if (!this.getChildren().contains(grid)) - { - this.appendChild(grid); - } - - if (!this.getChildren().contains(listPanel)) - { - this.appendChild(listPanel); - listPanel.setVisible(false); - } - if (listPanel.isVisible()) { if (activate) listPanel.activate(gridTab); @@ -543,7 +607,7 @@ DataStatusListener, ValueChangeListener, IADTabpanel listPanel.deactivate(); } else { if (activate) - grid.setVisible(activate); + formComponent.setVisible(activate); } } @@ -586,10 +650,44 @@ DataStatusListener, ValueChangeListener, IADTabpanel } else if (event.getTarget() instanceof Listbox) { this.switchRowPresentation(); + } + else if (event.getTarget() == tree) { + Treeitem item = tree.getSelectedItem(); + navigateTo((SimpleTreeNode)item.getValue()); } } - public void dataStatusChanged(DataStatusEvent e) + private void navigateTo(SimpleTreeNode value) { + MTreeNode treeNode = (MTreeNode) value.getData(); + // We Have a TreeNode + int nodeID = treeNode.getNode_ID(); + // root of tree selected - ignore + //if (nodeID == 0) + //return; + + // Search all rows for mode id + int size = gridTab.getRowCount(); + int row = -1; + for (int i = 0; i < size; i++) + { + if (gridTab.getKeyID(i) == nodeID) + { + row = i; + break; + } + } + if (row == -1) + { + if (nodeID > 0) + logger.log(Level.WARNING, "Tab does not have ID with Node_ID=" + nodeID); + return; + } + + // Navigate to node row + gridTab.navigate(row); + } + + public void dataStatusChanged(DataStatusEvent e) { //TODO: ignore non-ui thread event for now if (Executions.getCurrent() == null) return; @@ -629,9 +727,49 @@ DataStatusListener, ValueChangeListener, IADTabpanel } //if (col >= 0) dynamicDisplay(col); + + //sync tree + if (tree != null) { + setSelectedNode(gridTab.getRecord_ID()); + } } - public void valueChange(ValueChangeEvent e) + private void setSelectedNode(int recordId) { + if (recordId < 0) return; + + if (tree.getSelectedItem() != null) { + SimpleTreeNode treeNode = (SimpleTreeNode) tree.getSelectedItem().getValue(); + MTreeNode data = (MTreeNode) treeNode.getData(); + if (data.getNode_ID() == recordId) return; + } + + SimpleTreeModel model = (SimpleTreeModel) tree.getModel(); + SimpleTreeNode root = (SimpleTreeNode) model.getRoot(); + SimpleTreeNode treeNode = find(model, root, recordId); + if (treeNode != null) { + int[] path = model.getPath(model.getRoot(), treeNode); + Treeitem ti = tree.renderItemByPath(path); + tree.setSelectedItem(ti); + } + } + + private SimpleTreeNode find(SimpleTreeModel model, SimpleTreeNode root, int recordId) { + MTreeNode data = (MTreeNode) root.getData(); + if (data.getNode_ID() == recordId) + return root; + if (model.isLeaf(root)) + return null; + int cnt = model.getChildCount(root); + for(int i = 0; i < cnt; i++ ) { + SimpleTreeNode child = (SimpleTreeNode) model.getChild(root, i); + SimpleTreeNode treeNode = find(model, child, recordId); + if (treeNode != null) + return treeNode; + } + return null; + } + + public void valueChange(ValueChangeEvent e) { if (gridTab.isProcessed()) // only active records { @@ -681,12 +819,12 @@ DataStatusListener, ValueChangeListener, IADTabpanel } // ValueChange public void switchRowPresentation() { - if (grid.isVisible()) { - grid.setVisible(false); + if (formComponent.isVisible()) { + formComponent.setVisible(false); } else { - grid.setVisible(true); + formComponent.setVisible(true); } - listPanel.setVisible(!grid.isVisible()); + listPanel.setVisible(!formComponent.isVisible()); if (listPanel.isVisible()) { listPanel.activate(gridTab); }