diff --git a/migration/i4.1/oracle/201704031723_IDEMPIERE-3328.sql b/migration/i4.1/oracle/201704031723_IDEMPIERE-3328.sql new file mode 100644 index 0000000000..f1853b7a66 --- /dev/null +++ b/migration/i4.1/oracle/201704031723_IDEMPIERE-3328.sql @@ -0,0 +1,42 @@ +SET SQLBLANKLINES ON +SET DEFINE OFF + +-- IDEMPIERE-3328 +-- Apr 3, 2017 5:18:40 PM CEST +INSERT INTO AD_Element (AD_Element_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,ColumnName,Name,Description,PrintName,EntityType,AD_Element_UU) VALUES (203064,0,0,'Y',TO_DATE('2017-04-03 17:18:40','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2017-04-03 17:18:40','YYYY-MM-DD HH24:MI:SS'),100,'IsLoadAllNodesImmediately','Loads directly all nodes','If checked, all nodes are loaded before tree is displayed','Loads directly all nodes','D','decd8ab6-f0dd-441a-8842-25d9cb9e3b3f') +; + +-- Apr 3, 2017 5:19:13 PM CEST +INSERT INTO AD_Column (AD_Column_ID,Version,Name,Description,AD_Table_ID,ColumnName,DefaultValue,FieldLength,IsKey,IsParent,IsMandatory,IsTranslated,IsIdentifier,SeqNo,IsEncrypted,AD_Reference_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Element_ID,IsUpdateable,IsSelectionColumn,EntityType,IsSyncDatabase,IsAlwaysUpdateable,IsAutocomplete,IsAllowLogging,AD_Column_UU,IsAllowCopy,SeqNoSelection,IsToolbarButton,IsSecure) VALUES (212971,0,'Loads directly all nodes','If checked, all nodes are loaded before tree is displayed',288,'IsLoadAllNodesImmediately','N',1,'N','N','Y','N','N',0,'N',20,0,0,'Y',TO_DATE('2017-04-03 17:19:13','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2017-04-03 17:19:13','YYYY-MM-DD HH24:MI:SS'),100,203064,'Y','N','D','N','N','N','Y','692e44f6-4653-4a06-b68e-05fa3382202d','N',0,'N','N') +; + +-- Apr 3, 2017 5:19:18 PM CEST +ALTER TABLE AD_Tree MODIFY IsLoadAllNodesImmediately CHAR(1) DEFAULT 'N' +; + +-- Apr 3, 2017 5:19:18 PM CEST +UPDATE AD_Tree SET IsLoadAllNodesImmediately='N' WHERE IsLoadAllNodesImmediately IS NULL +; + +-- Apr 3, 2017 5:19:47 PM CEST +INSERT INTO AD_Field (AD_Field_ID,Name,Description,AD_Tab_ID,AD_Column_ID,IsDisplayed,DisplayLength,SeqNo,IsSameLine,IsHeading,IsFieldOnly,IsEncrypted,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,IsReadOnly,IsCentrallyMaintained,EntityType,AD_Field_UU,IsDisplayedGrid,SeqNoGrid,XPosition,ColumnSpan) VALUES (204379,'Loads directly all nodes','If checked, all nodes are loaded before tree is displayed',243,212971,'Y',1,110,'N','N','N','N',0,0,'Y',TO_DATE('2017-04-03 17:19:46','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2017-04-03 17:19:46','YYYY-MM-DD HH24:MI:SS'),100,'N','Y','D','c66c870e-2b9a-41cb-86f8-74c7b9e4b538','Y',110,2,2) +; + +-- Apr 3, 2017 5:20:08 PM CEST +UPDATE AD_Field SET SeqNo=80, AD_Reference_Value_ID=NULL, AD_Val_Rule_ID=NULL, IsToolbarButton=NULL,Updated=TO_DATE('2017-04-03 17:20:08','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=203826 +; + +-- Apr 3, 2017 5:20:08 PM CEST +UPDATE AD_Field SET SeqNo=90, AD_Reference_Value_ID=NULL, AD_Val_Rule_ID=NULL, IsToolbarButton=NULL,Updated=TO_DATE('2017-04-03 17:20:08','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=5228 +; + +-- Apr 3, 2017 5:20:08 PM CEST +UPDATE AD_Field SET SeqNo=100, AD_Reference_Value_ID=NULL, AD_Val_Rule_ID=NULL, IsToolbarButton=NULL,Updated=TO_DATE('2017-04-03 17:20:08','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=12421 +; + +-- Apr 3, 2017 5:20:09 PM CEST +UPDATE AD_Field SET SeqNo=120, AD_Reference_Value_ID=NULL, AD_Val_Rule_ID=NULL, IsToolbarButton=NULL,Updated=TO_DATE('2017-04-03 17:20:09','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=8371 +; + +SELECT register_migration_script('201704031723_IDEMPIERE-3328.sql') FROM dual +; \ No newline at end of file diff --git a/migration/i4.1/postgresql/201704031723_IDEMPIERE-3328.sql b/migration/i4.1/postgresql/201704031723_IDEMPIERE-3328.sql new file mode 100644 index 0000000000..ebb4404946 --- /dev/null +++ b/migration/i4.1/postgresql/201704031723_IDEMPIERE-3328.sql @@ -0,0 +1,39 @@ +-- IDEMPIERE-3328 +-- Apr 3, 2017 5:18:41 PM CEST +INSERT INTO AD_Element (AD_Element_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,ColumnName,Name,Description,PrintName,EntityType,AD_Element_UU) VALUES (203064,0,0,'Y',TO_TIMESTAMP('2017-04-03 17:18:40','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2017-04-03 17:18:40','YYYY-MM-DD HH24:MI:SS'),100,'IsLoadAllNodesImmediately','Loads directly all nodes','If checked, all nodes are loaded before tree is displayed','Loads directly all nodes','D','decd8ab6-f0dd-441a-8842-25d9cb9e3b3f') +; + +-- Apr 3, 2017 5:19:13 PM CEST +INSERT INTO AD_Column (AD_Column_ID,Version,Name,Description,AD_Table_ID,ColumnName,DefaultValue,FieldLength,IsKey,IsParent,IsMandatory,IsTranslated,IsIdentifier,SeqNo,IsEncrypted,AD_Reference_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Element_ID,IsUpdateable,IsSelectionColumn,EntityType,IsSyncDatabase,IsAlwaysUpdateable,IsAutocomplete,IsAllowLogging,AD_Column_UU,IsAllowCopy,SeqNoSelection,IsToolbarButton,IsSecure) VALUES (212971,0,'Loads directly all nodes','If checked, all nodes are loaded before tree is displayed',288,'IsLoadAllNodesImmediately','N',1,'N','N','Y','N','N',0,'N',20,0,0,'Y',TO_TIMESTAMP('2017-04-03 17:19:13','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2017-04-03 17:19:13','YYYY-MM-DD HH24:MI:SS'),100,203064,'Y','N','D','N','N','N','Y','692e44f6-4653-4a06-b68e-05fa3382202d','N',0,'N','N') +; + +-- Apr 3, 2017 5:19:18 PM CEST +INSERT INTO t_alter_column values('ad_tree','IsLoadAllNodesImmediately','CHAR(1)',null,'N') +; + +-- Apr 3, 2017 5:19:18 PM CEST +UPDATE AD_Tree SET IsLoadAllNodesImmediately='N' WHERE IsLoadAllNodesImmediately IS NULL +; + +-- Apr 3, 2017 5:19:47 PM CEST +INSERT INTO AD_Field (AD_Field_ID,Name,Description,AD_Tab_ID,AD_Column_ID,IsDisplayed,DisplayLength,SeqNo,IsSameLine,IsHeading,IsFieldOnly,IsEncrypted,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,IsReadOnly,IsCentrallyMaintained,EntityType,AD_Field_UU,IsDisplayedGrid,SeqNoGrid,XPosition,ColumnSpan) VALUES (204379,'Loads directly all nodes','If checked, all nodes are loaded before tree is displayed',243,212971,'Y',1,110,'N','N','N','N',0,0,'Y',TO_TIMESTAMP('2017-04-03 17:19:46','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2017-04-03 17:19:46','YYYY-MM-DD HH24:MI:SS'),100,'N','Y','D','c66c870e-2b9a-41cb-86f8-74c7b9e4b538','Y',110,2,2) +; + +-- Apr 3, 2017 5:20:08 PM CEST +UPDATE AD_Field SET SeqNo=80, AD_Reference_Value_ID=NULL, AD_Val_Rule_ID=NULL, IsToolbarButton=NULL,Updated=TO_TIMESTAMP('2017-04-03 17:20:08','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=203826 +; + +-- Apr 3, 2017 5:20:08 PM CEST +UPDATE AD_Field SET SeqNo=90, AD_Reference_Value_ID=NULL, AD_Val_Rule_ID=NULL, IsToolbarButton=NULL,Updated=TO_TIMESTAMP('2017-04-03 17:20:08','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=5228 +; + +-- Apr 3, 2017 5:20:08 PM CEST +UPDATE AD_Field SET SeqNo=100, AD_Reference_Value_ID=NULL, AD_Val_Rule_ID=NULL, IsToolbarButton=NULL,Updated=TO_TIMESTAMP('2017-04-03 17:20:08','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=12421 +; + +-- Apr 3, 2017 5:20:09 PM CEST +UPDATE AD_Field SET SeqNo=120, AD_Reference_Value_ID=NULL, AD_Val_Rule_ID=NULL, IsToolbarButton=NULL,Updated=TO_TIMESTAMP('2017-04-03 17:20:09','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=8371 +; + +SELECT register_migration_script('201704031723_IDEMPIERE-3328.sql') FROM dual +; \ No newline at end of file diff --git a/org.adempiere.base/src/org/compiere/model/I_AD_Tree.java b/org.adempiere.base/src/org/compiere/model/I_AD_Tree.java index 91cf5e0d86..9f56102014 100644 --- a/org.adempiere.base/src/org/compiere/model/I_AD_Tree.java +++ b/org.adempiere.base/src/org/compiere/model/I_AD_Tree.java @@ -167,6 +167,19 @@ public interface I_AD_Tree */ public boolean isDefault(); + /** Column name IsLoadAllNodesImmediately */ + public static final String COLUMNNAME_IsLoadAllNodesImmediately = "IsLoadAllNodesImmediately"; + + /** Set Loads directly all nodes. + * If checked, all nodes are loaded before tree is displayed + */ + public void setIsLoadAllNodesImmediately (boolean IsLoadAllNodesImmediately); + + /** Get Loads directly all nodes. + * If checked, all nodes are loaded before tree is displayed + */ + public boolean isLoadAllNodesImmediately(); + /** Column name IsTreeDrivenByValue */ public static final String COLUMNNAME_IsTreeDrivenByValue = "IsTreeDrivenByValue"; diff --git a/org.adempiere.base/src/org/compiere/model/MTree_Base.java b/org.adempiere.base/src/org/compiere/model/MTree_Base.java index cddca0eeaf..c70411cae8 100644 --- a/org.adempiere.base/src/org/compiere/model/MTree_Base.java +++ b/org.adempiere.base/src/org/compiere/model/MTree_Base.java @@ -20,6 +20,7 @@ import java.sql.ResultSet; import java.util.Properties; import org.compiere.util.CCache; +import org.compiere.util.DB; /** * Base Tree Model. @@ -330,7 +331,7 @@ public class MTree_Base extends X_AD_Tree if ("M_Product".equals(tableName) || "C_BPartner".equals(tableName) || "AD_Org".equals(tableName) || "C_Campaign".equals(tableName)) return "x.AD_PrintColor_ID"; - return "NULL"; + return "NULL"; } // getSourceTableName @@ -397,5 +398,10 @@ public class MTree_Base extends X_AD_Tree return success; } // afterSave - + + /** Returns true if should load all tree nodes immediately */ + public static boolean isLoadAllNodesImmediately(int treeID, String trxName) { + return DB.getSQLValueStringEx(trxName, "SELECT IsLoadAllNodesImmediately FROM AD_Tree WHERE AD_Tree_ID = ?", treeID).equals("Y"); + } + } // MTree_Base diff --git a/org.adempiere.base/src/org/compiere/model/X_AD_Tree.java b/org.adempiere.base/src/org/compiere/model/X_AD_Tree.java index 663a59da7e..d5508954c9 100644 --- a/org.adempiere.base/src/org/compiere/model/X_AD_Tree.java +++ b/org.adempiere.base/src/org/compiere/model/X_AD_Tree.java @@ -30,7 +30,7 @@ public class X_AD_Tree extends PO implements I_AD_Tree, I_Persistent /** * */ - private static final long serialVersionUID = 20161030L; + private static final long serialVersionUID = 20170403L; /** Standard Constructor */ public X_AD_Tree (Properties ctx, int AD_Tree_ID, String trxName) @@ -41,6 +41,8 @@ public class X_AD_Tree extends PO implements I_AD_Tree, I_Persistent setAD_Tree_ID (0); setIsAllNodes (false); setIsDefault (false); +// N + setIsLoadAllNodesImmediately (false); // N setIsTreeDrivenByValue (false); // N @@ -207,6 +209,30 @@ public class X_AD_Tree extends PO implements I_AD_Tree, I_Persistent return false; } + /** Set Loads directly all nodes. + @param IsLoadAllNodesImmediately + If checked, all nodes are loaded before tree is displayed + */ + public void setIsLoadAllNodesImmediately (boolean IsLoadAllNodesImmediately) + { + set_Value (COLUMNNAME_IsLoadAllNodesImmediately, Boolean.valueOf(IsLoadAllNodesImmediately)); + } + + /** Get Loads directly all nodes. + @return If checked, all nodes are loaded before tree is displayed + */ + public boolean isLoadAllNodesImmediately () + { + Object oo = get_Value(COLUMNNAME_IsLoadAllNodesImmediately); + if (oo != null) + { + if (oo instanceof Boolean) + return ((Boolean)oo).booleanValue(); + return "Y".equals(oo); + } + return false; + } + /** Set Driven by Search Key. @param IsTreeDrivenByValue Driven by Search Key */ public void setIsTreeDrivenByValue (boolean IsTreeDrivenByValue) diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/ADTreePanel.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/ADTreePanel.java index 5a7f9d6b16..51a6dada68 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/ADTreePanel.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/ADTreePanel.java @@ -20,6 +20,7 @@ import org.adempiere.webui.component.ToolBarButton; import org.adempiere.webui.panel.TreeSearchPanel; import org.adempiere.webui.util.TreeUtils; import org.adempiere.webui.util.ZKUpdateUtil; +import org.compiere.model.MTree_Base; import org.compiere.util.Env; import org.compiere.util.Msg; import org.compiere.util.Util; @@ -42,8 +43,7 @@ public class ADTreePanel extends Panel implements EventListener /** * */ - private static final long serialVersionUID = -6868506934553777046L; - + private static final long serialVersionUID = 164816320839461191L; private static final String ON_EXPAND_MENU_EVENT = "onExpandMenu"; private TreeSearchPanel pnlSearch; private Tree tree; @@ -75,6 +75,8 @@ public class ADTreePanel extends Panel implements EventListener { this.AD_Tree_ID = AD_Tree_ID; SimpleTreeModel.initADTree(tree, AD_Tree_ID, windowNo); + if (MTree_Base.isLoadAllNodesImmediately(AD_Tree_ID, null)) + TreeUtils.collapseTree(tree, true); pnlSearch.initialise(); return true; } diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/form/WTreeMaintenance.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/form/WTreeMaintenance.java index 5e5d1df1c0..e95203b2e0 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/form/WTreeMaintenance.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/apps/form/WTreeMaintenance.java @@ -34,11 +34,13 @@ import org.adempiere.webui.panel.CustomForm; import org.adempiere.webui.panel.IFormController; import org.adempiere.webui.session.SessionManager; import org.adempiere.webui.theme.ThemeManager; +import org.adempiere.webui.util.TreeUtils; import org.adempiere.webui.util.ZKUpdateUtil; import org.adempiere.webui.window.FDialog; import org.compiere.apps.form.TreeMaintenance; import org.compiere.model.MTree; import org.compiere.model.MTreeNode; +import org.compiere.model.MTree_Base; import org.compiere.util.Env; import org.compiere.util.KeyNamePair; import org.compiere.util.Msg; @@ -322,8 +324,11 @@ public class WTreeMaintenance extends TreeMaintenance implements IFormController centerTree.getTreefoot().detach(); if (centerTree.getTreechildren() != null) centerTree.getTreechildren().detach(); - + SimpleTreeModel.initADTree(centerTree, m_tree.getAD_Tree_ID(), m_WindowNo); + if (MTree_Base.isLoadAllNodesImmediately(m_tree.getAD_Tree_ID(), null)) + TreeUtils.collapseTree(centerTree, false); + } // action_fillTree /** diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/util/TreeUtils.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/util/TreeUtils.java index c4457e8639..fce4ae5238 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/util/TreeUtils.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/util/TreeUtils.java @@ -13,11 +13,17 @@ *****************************************************************************/ package org.adempiere.webui.util; +import java.util.Collection; +import java.util.Iterator; + +import org.zkoss.zk.ui.Component; import org.zkoss.zul.DefaultTreeNode; import org.zkoss.zul.Tree; import org.zkoss.zul.TreeModel; +import org.zkoss.zul.TreeNode; import org.zkoss.zul.Treechildren; import org.zkoss.zul.Treeitem; +import org.zkoss.zul.ext.TreeOpenableModel; /** * @@ -137,4 +143,74 @@ public class TreeUtils { } return false; } + + /** + * travel all node of tree, at selected node, call callback function + * @param tree + * @param nodeModel + * @param isRootNode + * @param processNode + */ + static public void collapseTree (Component treeObject, boolean isOpen){ + if (treeObject instanceof Tree) { + Tree tree = (Tree)treeObject; + if (tree.getModel() != null && tree.getModel() instanceof TreeOpenableModel){ + collapseTreeModel ((TreeOpenableModel)tree.getModel(), isOpen, null); + return; + } + } + + if (treeObject instanceof Treeitem) {// Tree also is Treeitem + Treeitem treeitem = (Treeitem) treeObject; + treeitem.setOpen(isOpen); + } + Collection com = treeObject.getChildren(); + if (com != null) { + for (Iterator iterator = com.iterator(); iterator.hasNext();) { + collapseTree((Component) iterator.next(), isOpen); + + } + } + } + + static protected void collapseTreeModel (TreeOpenableModel treeModelOpenable, boolean isOpen, T treeNode){ + if (!isOpen){ + treeModelOpenable.clearOpen(); + return;//done, easy to close all node + }else{ + if (!(treeModelOpenable instanceof TreeModel)){ + return;//model have to be a instance of TreeModel. because it provide method to add open object + } + + if (treeNode != null && !(treeNode instanceof TreeNode)){ + return; //don't support, at least it's TreeNode to travel child node + } + + @SuppressWarnings("unchecked") + TreeModel treeModel = (TreeModel)treeModelOpenable; + + if (treeNode == null){// get from model + Object rootNode = treeModel.getRoot(); + if (!(rootNode instanceof TreeNode)){ + return;//don't support, at least it's TreeNode to travel child node + } + + @SuppressWarnings("unchecked") + TreeNode node = (TreeNode)rootNode; + collapseTreeModel (treeModelOpenable, isOpen, node); + }else{//child node + + TreeNode node = (TreeNode)treeNode; + + treeModelOpenable.addOpenPath(treeModel.getPath(treeNode)); + + + if (node.getChildren() != null) { + for (TreeNode childNode : node.getChildren()){ + collapseTreeModel (treeModelOpenable, isOpen, childNode); + } + } + } + } + } }