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);
}