From e2d26b3a974f2e19ec9cf33ff366daeea1d6eb86 Mon Sep 17 00:00:00 2001 From: Heng Sin Low Date: Tue, 19 Jul 2016 17:41:02 +0800 Subject: [PATCH] 1006181 Speed-up windows - Field to show read-only grid. (IDEMPIERE-3269) --- .../oracle/201607191600_Ticket_1006181.sql | 154 +++++++ .../201607191600_Ticket_1006181.sql | 151 +++++++ .../src/org/compiere/model/GridTab.java | 14 + .../src/org/compiere/model/GridTable.java | 4 + .../src/org/compiere/model/SystemIDs.java | 2 + .../src/org/compiere/util/DisplayType.java | 10 +- .../selection/GridTabSelectionListView.java | 379 ++++++++++++++++++ .../GridTabSelectionListViewRenderer.java | 257 ++++++++++++ .../editor/grid/selection/GridTableRow.java | 47 +++ .../selection/SimpleGridTableListModel.java | 154 +++++++ .../WGridTabMultiSelectionEditor.java | 240 +++++++++++ .../WGridTabSingleSelectionEditor.java | 191 +++++++++ .../webui/factory/DefaultEditorFactory.java | 10 + 13 files changed, 1612 insertions(+), 1 deletion(-) create mode 100644 migration/i3.1/oracle/201607191600_Ticket_1006181.sql create mode 100644 migration/i3.1/postgresql/201607191600_Ticket_1006181.sql create mode 100644 org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/grid/selection/GridTabSelectionListView.java create mode 100644 org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/grid/selection/GridTabSelectionListViewRenderer.java create mode 100644 org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/grid/selection/GridTableRow.java create mode 100644 org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/grid/selection/SimpleGridTableListModel.java create mode 100644 org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/grid/selection/WGridTabMultiSelectionEditor.java create mode 100644 org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/grid/selection/WGridTabSingleSelectionEditor.java diff --git a/migration/i3.1/oracle/201607191600_Ticket_1006181.sql b/migration/i3.1/oracle/201607191600_Ticket_1006181.sql new file mode 100644 index 0000000000..5fbe086802 --- /dev/null +++ b/migration/i3.1/oracle/201607191600_Ticket_1006181.sql @@ -0,0 +1,154 @@ +SET SQLBLANKLINES ON +SET DEFINE OFF + +-- Jul 15, 2016 6:12:46 PM MYT +-- 1006181 Speed-up windows - Field to show read-only grid +UPDATE AD_Field SET Included_Tab_ID = NULL WHERE Included_Tab_ID IS NOT NULL +; + +INSERT INTO AD_Reference (AD_Reference_ID,Name,AD_Reference_UU,IsOrderByValue,AD_Org_ID,ValidationType,Updated,IsActive,CreatedBy,UpdatedBy,AD_Client_ID,Created,EntityType) VALUES (200127,'Single Selection Grid','ce2bb5f1-efab-44ba-b5b7-7308a509c39c','N',0,'D',TO_DATE('2016-07-15 18:12:40','YYYY-MM-DD HH24:MI:SS'),'Y',100,100,0,TO_DATE('2016-07-15 18:12:40','YYYY-MM-DD HH24:MI:SS'),'D') +; + +-- Jul 15, 2016 6:13:13 PM MYT +INSERT INTO AD_Reference (AD_Reference_ID,Name,AD_Reference_UU,IsOrderByValue,AD_Org_ID,ValidationType,Updated,IsActive,CreatedBy,UpdatedBy,AD_Client_ID,Created,EntityType) VALUES (200128,'Multiple Selection Grid','ca6d9bef-47eb-4278-a11f-20a8a99257cd','N',0,'D',TO_DATE('2016-07-15 18:13:13','YYYY-MM-DD HH24:MI:SS'),'Y',100,100,0,TO_DATE('2016-07-15 18:13:13','YYYY-MM-DD HH24:MI:SS'),'D') +; + +-- Jul 15, 2016 6:24:20 PM MYT +UPDATE AD_Field SET SeqNo=120,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=6432 +; + +-- Jul 15, 2016 6:24:20 PM MYT +UPDATE AD_Field SET SeqNo=130,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=132 +; + +-- Jul 15, 2016 6:24:21 PM MYT +UPDATE AD_Field SET SeqNo=140,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=200276 +; + +-- Jul 15, 2016 6:24:21 PM MYT +UPDATE AD_Field SET SeqNo=150,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=200771 +; + +-- Jul 15, 2016 6:24:21 PM MYT +UPDATE AD_Field SET SeqNo=160,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=924 +; + +-- Jul 15, 2016 6:24:21 PM MYT +UPDATE AD_Field SET SeqNo=170,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=133 +; + +-- Jul 15, 2016 6:24:21 PM MYT +UPDATE AD_Field SET SeqNo=180,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=137 +; + +-- Jul 15, 2016 6:24:21 PM MYT +UPDATE AD_Field SET SeqNo=190,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=200274 +; + +-- Jul 15, 2016 6:24:21 PM MYT +UPDATE AD_Field SET SeqNo=200,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=138 +; + +-- Jul 15, 2016 6:24:21 PM MYT +UPDATE AD_Field SET SeqNo=210,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=202362 +; + +-- Jul 15, 2016 6:24:21 PM MYT +UPDATE AD_Field SET SeqNo=220,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=142 +; + +-- Jul 15, 2016 6:24:21 PM MYT +UPDATE AD_Field SET SeqNo=230,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=8343 +; + +-- Jul 15, 2016 6:24:21 PM MYT +UPDATE AD_Field SET SeqNo=240,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=140 +; + +-- Jul 15, 2016 6:24:21 PM MYT +UPDATE AD_Field SET SeqNo=250,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=202341 +; + +-- Jul 15, 2016 6:24:21 PM MYT +UPDATE AD_Field SET SeqNo=260,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=141 +; + +-- Jul 15, 2016 6:24:21 PM MYT +UPDATE AD_Field SET SeqNo=270,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=200350 +; + +-- Jul 15, 2016 6:24:21 PM MYT +UPDATE AD_Field SET SeqNo=280,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=200348 +; + +-- Jul 15, 2016 6:24:21 PM MYT +UPDATE AD_Field SET SeqNo=290,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=200349 +; + +-- Jul 15, 2016 6:24:21 PM MYT +UPDATE AD_Field SET SeqNo=300,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=204213 +; + +-- Jul 15, 2016 6:24:21 PM MYT +UPDATE AD_Field SET SeqNo=310,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=204214 +; + +-- Jul 15, 2016 6:24:21 PM MYT +UPDATE AD_Field SET SeqNo=320,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=13425 +; + +-- Jul 15, 2016 6:24:21 PM MYT +UPDATE AD_Field SET SeqNo=330,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=200837 +; + +-- Jul 15, 2016 6:24:21 PM MYT +UPDATE AD_Field SET SeqNo=340,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=54402 +; + +-- Jul 15, 2016 6:24:22 PM MYT +UPDATE AD_Field SET SeqNo=350,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=54401 +; + +-- Jul 15, 2016 6:24:22 PM MYT +UPDATE AD_Field SET SeqNo=360,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=200838 +; + +-- Jul 15, 2016 6:24:22 PM MYT +UPDATE AD_Field SET SeqNo=370,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=200834 +; + +-- Jul 15, 2016 6:24:22 PM MYT +UPDATE AD_Field SET SeqNo=380,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=13424 +; + +-- Jul 15, 2016 6:24:22 PM MYT +UPDATE AD_Field SET SeqNo=390,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=62468 +; + +-- Jul 15, 2016 6:24:22 PM MYT +UPDATE AD_Field SET SeqNo=400,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=53280 +; + +-- Jul 15, 2016 6:24:22 PM MYT +UPDATE AD_Field SET SeqNo=410,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=200836 +; + +-- Jul 15, 2016 6:24:22 PM MYT +UPDATE AD_Field SET SeqNo=420,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=200835 +; + +-- Jul 15, 2016 6:24:22 PM MYT +UPDATE AD_Field SET SeqNo=430,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=136 +; + +-- Jul 15, 2016 6:24:22 PM MYT +UPDATE AD_Field SET SeqNo=440,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=139 +; + +-- Jul 15, 2016 6:27:18 PM MYT +UPDATE AD_Field SET DisplayLogic='@AD_Column_ID.AD_Reference_ID@=200127|@AD_Column_ID.AD_Reference_ID@=200128', IsActive='Y', SeqNoGrid=120,Updated=TO_DATE('2016-07-15 18:27:18','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=6432 +; + +SELECT register_migration_script('201607191600_Ticket_1006181.sql') FROM dual +; + diff --git a/migration/i3.1/postgresql/201607191600_Ticket_1006181.sql b/migration/i3.1/postgresql/201607191600_Ticket_1006181.sql new file mode 100644 index 0000000000..f87ccc66b9 --- /dev/null +++ b/migration/i3.1/postgresql/201607191600_Ticket_1006181.sql @@ -0,0 +1,151 @@ +-- Jul 15, 2016 6:12:46 PM MYT +-- 1006181 Speed-up windows - Field to show read-only grid +UPDATE AD_Field SET Included_Tab_ID = NULL WHERE Included_Tab_ID IS NOT NULL +; + +INSERT INTO AD_Reference (AD_Reference_ID,Name,AD_Reference_UU,IsOrderByValue,AD_Org_ID,ValidationType,Updated,IsActive,CreatedBy,UpdatedBy,AD_Client_ID,Created,EntityType) VALUES (200127,'Single Selection Grid','ce2bb5f1-efab-44ba-b5b7-7308a509c39c','N',0,'D',TO_TIMESTAMP('2016-07-15 18:12:40','YYYY-MM-DD HH24:MI:SS'),'Y',100,100,0,TO_TIMESTAMP('2016-07-15 18:12:40','YYYY-MM-DD HH24:MI:SS'),'D') +; + +-- Jul 15, 2016 6:13:13 PM MYT +INSERT INTO AD_Reference (AD_Reference_ID,Name,AD_Reference_UU,IsOrderByValue,AD_Org_ID,ValidationType,Updated,IsActive,CreatedBy,UpdatedBy,AD_Client_ID,Created,EntityType) VALUES (200128,'Multiple Selection Grid','ca6d9bef-47eb-4278-a11f-20a8a99257cd','N',0,'D',TO_TIMESTAMP('2016-07-15 18:13:13','YYYY-MM-DD HH24:MI:SS'),'Y',100,100,0,TO_TIMESTAMP('2016-07-15 18:13:13','YYYY-MM-DD HH24:MI:SS'),'D') +; + +-- Jul 15, 2016 6:24:20 PM MYT +UPDATE AD_Field SET SeqNo=120,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=6432 +; + +-- Jul 15, 2016 6:24:20 PM MYT +UPDATE AD_Field SET SeqNo=130,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=132 +; + +-- Jul 15, 2016 6:24:21 PM MYT +UPDATE AD_Field SET SeqNo=140,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=200276 +; + +-- Jul 15, 2016 6:24:21 PM MYT +UPDATE AD_Field SET SeqNo=150,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=200771 +; + +-- Jul 15, 2016 6:24:21 PM MYT +UPDATE AD_Field SET SeqNo=160,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=924 +; + +-- Jul 15, 2016 6:24:21 PM MYT +UPDATE AD_Field SET SeqNo=170,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=133 +; + +-- Jul 15, 2016 6:24:21 PM MYT +UPDATE AD_Field SET SeqNo=180,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=137 +; + +-- Jul 15, 2016 6:24:21 PM MYT +UPDATE AD_Field SET SeqNo=190,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=200274 +; + +-- Jul 15, 2016 6:24:21 PM MYT +UPDATE AD_Field SET SeqNo=200,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=138 +; + +-- Jul 15, 2016 6:24:21 PM MYT +UPDATE AD_Field SET SeqNo=210,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=202362 +; + +-- Jul 15, 2016 6:24:21 PM MYT +UPDATE AD_Field SET SeqNo=220,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=142 +; + +-- Jul 15, 2016 6:24:21 PM MYT +UPDATE AD_Field SET SeqNo=230,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=8343 +; + +-- Jul 15, 2016 6:24:21 PM MYT +UPDATE AD_Field SET SeqNo=240,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=140 +; + +-- Jul 15, 2016 6:24:21 PM MYT +UPDATE AD_Field SET SeqNo=250,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=202341 +; + +-- Jul 15, 2016 6:24:21 PM MYT +UPDATE AD_Field SET SeqNo=260,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=141 +; + +-- Jul 15, 2016 6:24:21 PM MYT +UPDATE AD_Field SET SeqNo=270,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=200350 +; + +-- Jul 15, 2016 6:24:21 PM MYT +UPDATE AD_Field SET SeqNo=280,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=200348 +; + +-- Jul 15, 2016 6:24:21 PM MYT +UPDATE AD_Field SET SeqNo=290,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=200349 +; + +-- Jul 15, 2016 6:24:21 PM MYT +UPDATE AD_Field SET SeqNo=300,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=204213 +; + +-- Jul 15, 2016 6:24:21 PM MYT +UPDATE AD_Field SET SeqNo=310,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=204214 +; + +-- Jul 15, 2016 6:24:21 PM MYT +UPDATE AD_Field SET SeqNo=320,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=13425 +; + +-- Jul 15, 2016 6:24:21 PM MYT +UPDATE AD_Field SET SeqNo=330,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=200837 +; + +-- Jul 15, 2016 6:24:21 PM MYT +UPDATE AD_Field SET SeqNo=340,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=54402 +; + +-- Jul 15, 2016 6:24:22 PM MYT +UPDATE AD_Field SET SeqNo=350,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=54401 +; + +-- Jul 15, 2016 6:24:22 PM MYT +UPDATE AD_Field SET SeqNo=360,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=200838 +; + +-- Jul 15, 2016 6:24:22 PM MYT +UPDATE AD_Field SET SeqNo=370,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=200834 +; + +-- Jul 15, 2016 6:24:22 PM MYT +UPDATE AD_Field SET SeqNo=380,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=13424 +; + +-- Jul 15, 2016 6:24:22 PM MYT +UPDATE AD_Field SET SeqNo=390,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=62468 +; + +-- Jul 15, 2016 6:24:22 PM MYT +UPDATE AD_Field SET SeqNo=400,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=53280 +; + +-- Jul 15, 2016 6:24:22 PM MYT +UPDATE AD_Field SET SeqNo=410,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=200836 +; + +-- Jul 15, 2016 6:24:22 PM MYT +UPDATE AD_Field SET SeqNo=420,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=200835 +; + +-- Jul 15, 2016 6:24:22 PM MYT +UPDATE AD_Field SET SeqNo=430,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=136 +; + +-- Jul 15, 2016 6:24:22 PM MYT +UPDATE AD_Field SET SeqNo=440,IsDisplayed='Y', Updated=Now(), UpdatedBy=100 WHERE AD_Field_ID=139 +; + +-- Jul 15, 2016 6:27:18 PM MYT +UPDATE AD_Field SET DisplayLogic='@AD_Column_ID.AD_Reference_ID@=200127|@AD_Column_ID.AD_Reference_ID@=200128', IsActive='Y', SeqNoGrid=120,Updated=TO_TIMESTAMP('2016-07-15 18:27:18','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=6432 +; + +SELECT register_migration_script('201607191600_Ticket_1006181.sql') FROM dual +; + diff --git a/org.adempiere.base/src/org/compiere/model/GridTab.java b/org.adempiere.base/src/org/compiere/model/GridTab.java index be6ee8ef77..5bb961f489 100644 --- a/org.adempiere.base/src/org/compiere/model/GridTab.java +++ b/org.adempiere.base/src/org/compiere/model/GridTab.java @@ -1286,6 +1286,11 @@ public class GridTab implements DataStatusListener, Evaluatee, Serializable { return m_keyColumnName; } // getKeyColumnName + + public int getKeyColumnIndex() + { + return m_mTable.getKeyColumnIndex(); + } /** * Set Name of the Key Column @@ -3338,4 +3343,13 @@ public class GridTab implements DataStatusListener, Evaluatee, Serializable selection.clear(); } + public GridWindow getGridWindow() + { + return this.m_window; + } + + public GridTabVO getVO() + { + return m_vo; + } } // GridTab diff --git a/org.adempiere.base/src/org/compiere/model/GridTable.java b/org.adempiere.base/src/org/compiere/model/GridTable.java index 2324809613..3d310a76f0 100644 --- a/org.adempiere.base/src/org/compiere/model/GridTable.java +++ b/org.adempiere.base/src/org/compiere/model/GridTable.java @@ -3948,4 +3948,8 @@ public class GridTable extends AbstractTableModel m_lastSortColumnIndex = -1; m_lastSortedAscending = true; } + + public int getKeyColumnIndex() { + return m_indexKeyColumn; + } } diff --git a/org.adempiere.base/src/org/compiere/model/SystemIDs.java b/org.adempiere.base/src/org/compiere/model/SystemIDs.java index 9500ee8825..d80a915946 100644 --- a/org.adempiere.base/src/org/compiere/model/SystemIDs.java +++ b/org.adempiere.base/src/org/compiere/model/SystemIDs.java @@ -117,6 +117,8 @@ public class SystemIDs public final static int REFERENCE_DATATYPE_YES_NO = 20; public final static int REFERENCE_DATATYPE_CHART = 53370; public final static int REFERENCE_DATATYPE_DASHBOARD_CONTENT = 200122; + public final static int REFERENCE_DATATYPE_SINGLE_SELECTION_GRID = 200127; + public final static int REFERENCE_DATATYPE_MULTIPLE_SELECTION_GRID = 200128; public final static int REFERENCE_AD_USER = 110; public final static int REFERENCE_DOCUMENTACTION = 135; diff --git a/org.adempiere.base/src/org/compiere/util/DisplayType.java b/org.adempiere.base/src/org/compiere/util/DisplayType.java index 6ea07bca94..eb6b2609eb 100644 --- a/org.adempiere.base/src/org/compiere/util/DisplayType.java +++ b/org.adempiere.base/src/org/compiere/util/DisplayType.java @@ -51,6 +51,8 @@ import static org.compiere.model.SystemIDs.REFERENCE_DATATYPE_URL; import static org.compiere.model.SystemIDs.REFERENCE_DATATYPE_YES_NO; import static org.compiere.model.SystemIDs.REFERENCE_DATATYPE_CHART; import static org.compiere.model.SystemIDs.REFERENCE_DATATYPE_DASHBOARD_CONTENT; +import static org.compiere.model.SystemIDs.REFERENCE_DATATYPE_SINGLE_SELECTION_GRID; +import static org.compiere.model.SystemIDs.REFERENCE_DATATYPE_MULTIPLE_SELECTION_GRID; import java.text.DateFormat; import java.text.DecimalFormat; @@ -147,6 +149,10 @@ public final class DisplayType public static final int Chart = REFERENCE_DATATYPE_CHART; public static final int DashboardContent = REFERENCE_DATATYPE_DASHBOARD_CONTENT; + + public static final int SingleSelectionGrid = REFERENCE_DATATYPE_SINGLE_SELECTION_GRID; + + public static final int MultipleSelectionGrid = REFERENCE_DATATYPE_MULTIPLE_SELECTION_GRID; /** * - New Display Type @@ -262,7 +268,9 @@ public final class DisplayType if (displayType == String || displayType == Text || displayType == TextLong || displayType == Memo || displayType == FilePath || displayType == FileName - || displayType == URL || displayType == PrinterName) + || displayType == URL || displayType == PrinterName + || displayType == SingleSelectionGrid + || displayType == MultipleSelectionGrid) return true; List factoryList = Service.locator().list(IDisplayTypeFactory.class).getServices(); diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/grid/selection/GridTabSelectionListView.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/grid/selection/GridTabSelectionListView.java new file mode 100644 index 0000000000..431e9f42c6 --- /dev/null +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/grid/selection/GridTabSelectionListView.java @@ -0,0 +1,379 @@ +/****************************************************************************** + * 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.grid.selection; + + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; + +import javax.swing.table.AbstractTableModel; + +import org.adempiere.model.MTabCustomization; +import org.adempiere.webui.component.Label; +import org.adempiere.webui.component.ListHead; +import org.adempiere.webui.component.ListHeader; +import org.adempiere.webui.component.Listbox; +import org.compiere.model.GridField; +import org.compiere.model.GridTab; +import org.compiere.model.GridTable; +import org.compiere.model.MSysConfig; +import org.compiere.util.DisplayType; +import org.compiere.util.Env; +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.zul.Borderlayout; +import org.zkoss.zul.Center; +import org.zkoss.zul.ListModel; +import org.zkoss.zul.South; +import org.zkoss.zul.ext.Selectable; + +/** + * Read only grid view for single or multi selection + * @author Low Heng Sin + * + */ +public class GridTabSelectionListView extends Borderlayout implements EventListener +{ + /** + * + */ + private static final long serialVersionUID = 4145737989132101461L; + + private static final int MIN_COLUMN_WIDTH = 100; + + private static final int MAX_COLUMN_WIDTH = 300; + + private Listbox listbox = null; + + private int pageSize = 100; + + private GridField[] gridField; + private AbstractTableModel tableModel; + + private int numColumns = 5; + + private int windowNo; + + private GridTab gridTab; + + private boolean init; + + private SimpleGridTableListModel listModel; + + private GridTabSelectionListViewRenderer renderer; + + private South south; + + private Map columnWidthMap; + + private Label selectedLabel; + + public GridTabSelectionListView(boolean multiple) + { + this(multiple, 0); + } + + /** + * @param windowNo + */ + public GridTabSelectionListView(boolean multiple, int windowNo) + { + this.windowNo = windowNo; + listbox = new Listbox(); + listbox.setCheckmark(true); + listbox.setMultiple(multiple); + south = new South(); + this.appendChild(south); + + //default paging size + pageSize = MSysConfig.getIntValue(MSysConfig.ZK_PAGING_SIZE, 100); + listbox.setMold("paging"); + listbox.setPageSize(pageSize); + + setStyle("min-height: 200px;"); + } + + /** + * + * @param gridTab + */ + public void init(GridTab gridTab) + { + if (init) return; + + setupFields(gridTab); + + setupColumns(); + render(); + + this.init = true; + } + + private void setupFields(GridTab gridTab) { + this.gridTab = gridTab; + tableModel = gridTab.getTableModel(); + GridField[] tmpFields = ((GridTable)tableModel).getFields(); + MTabCustomization tabCustomization = MTabCustomization.get(Env.getCtx(), Env.getAD_User_ID(Env.getCtx()), gridTab.getAD_Tab_ID(), null); + if (tabCustomization != null && tabCustomization.getAD_Tab_Customization_ID() > 0 + && tabCustomization.getCustom() != null && tabCustomization.getCustom().trim().length() > 0) { + String custom = tabCustomization.getCustom().trim(); + String[] customComponent = custom.split(";"); + String[] fieldIds = customComponent[0].split("[,]"); + List fieldList = new ArrayList(); + for(String fieldIdStr : fieldIds) { + fieldIdStr = fieldIdStr.trim(); + if (fieldIdStr.length() == 0) continue; + int AD_Field_ID = Integer.parseInt(fieldIdStr); + for(GridField gridField : tmpFields) { + if (gridField.getAD_Field_ID() == AD_Field_ID) { + fieldList.add(gridField); + break; + } + } + } + gridField = fieldList.toArray(new GridField[0]); + if (customComponent.length == 2) { + String[] widths = customComponent[1].split("[,]"); + for(int i = 0; i< gridField.length; i++) { + columnWidthMap.put(gridField[i].getAD_Field_ID(), widths[i]); + } + } + } else { + gridField = tmpFields; + } + numColumns = gridField.length; + } + + /** + * + * @return boolean + */ + public boolean isInit() { + return init; + } + + /** + * + * @param gridTab + */ + public void activate(GridTab gridTab) { + if (isInit()) + { + if (this.gridTab != gridTab) + { + init = false; + init(gridTab); + } + } + else + init(gridTab); + } + + /** + * + * @param gridTab + */ + public void refresh(GridTab gridTab) { + gridTab.query(false, 0, 0); + gridTab.getTableModel().fireTableDataChanged(); + + if (this.gridTab != gridTab) + { + init = false; + init(gridTab); + } + } + + /** + * Set paging size + * @param pageSize + */ + public void setPageSize(int pageSize) + { + this.pageSize = pageSize; + } + + public void clear() + { + this.getChildren().clear(); + } + + private void setupColumns() + { + if (init) return; + + ListHead header = new ListHead(); + header.setSizable(true); + + ListHeader selectionHeader = new ListHeader(); + selectionHeader.setWidth("40px"); + selectionHeader.setAlign("center"); + header.appendChild(selectionHeader); + + Map colnames = new HashMap(); + int index = 0; + for (int i = 0; i < numColumns; i++) + { + if (gridField[i].isDisplayed() && gridField[i].isDisplayedGrid()) + { + colnames.put(index, gridField[i].getHeader()); + index++; + ListHeader colHeader = new ListHeader(); + colHeader.setSort("auto"); + colHeader.setLabel(gridField[i].getHeader()); + if (columnWidthMap != null && columnWidthMap.get(gridField[i].getAD_Field_ID()) != null) { + colHeader.setWidth(columnWidthMap.get(gridField[i].getAD_Field_ID())); + } else { + int l = DisplayType.isNumeric(gridField[i].getDisplayType()) + ? 100 : gridField[i].getDisplayLength() * 9; + if (gridField[i].getHeader().length() * 9 > l) + l = gridField[i].getHeader().length() * 9; + if (l > MAX_COLUMN_WIDTH) + l = MAX_COLUMN_WIDTH; + else if ( l < MIN_COLUMN_WIDTH) + l = MIN_COLUMN_WIDTH; + colHeader.setWidth(Integer.toString(l) + "px"); + } + header.appendChild(colHeader); + } + } + listbox.appendChild(header); + } + + private void render() + { + listbox.setStyle("min-height: 200px"); + listbox.setVflex(true); + listbox.setHflex("1"); + listbox.setSizedByContent(true); + listbox.addEventListener(Events.ON_SELECT, this); + + updateModel(); + + Center center = new Center(); + center.appendChild(listbox); + this.appendChild(center); + + selectedLabel = new Label(Msg.getMsg(Env.getCtx(), "Selected") + " : 0"); + south.appendChild(selectedLabel); + } + + private void updateModel() { + listModel = new SimpleGridTableListModel((GridTable)tableModel, windowNo); + listModel.setMultiple(listbox.isMultiple()); + renderer = new GridTabSelectionListViewRenderer(gridTab, windowNo); + renderer.setListView(this); + + listbox.setItemRenderer(renderer); + listbox.setModel(listModel); + } + + /** + * deactive panel + */ + public void deactivate() { + } + + public void onEvent(Event event) throws Exception + { + if (event == null) + return; + else if (event.getTarget() == listbox) + { + int count = listbox.getSelectedCount(); + selectedLabel.setValue(Msg.getMsg(Env.getCtx(), "Selected") + " : " + count); + } + } + + /** + * + * @return Listbox + */ + public Listbox getListbox() { + return listbox; + } + + /** + * + * @param windowNo + */ + public void setWindowNo(int windowNo) { + this.windowNo = windowNo; + } + + public GridField[] getFields() { + return gridField; + } + + /* (non-Javadoc) + * @see org.zkoss.zk.ui.AbstractComponent#addEventListener(int, java.lang.String, org.zkoss.zk.ui.event.EventListener) + */ + @Override + public boolean addEventListener(int priority, String evtnm, + EventListener listener) { + if (Events.ON_SELECT.equals(evtnm)) { + return listbox.addEventListener(priority, evtnm, listener); + } else { + return super.addEventListener(priority, evtnm, listener); + } + } + + public void setSelectedIndices(int[] selectedIndices) { + ListModel model = listbox.getModel(); + if (model != null && model instanceof Selectable) { + Collection selection = new HashSet(); + @SuppressWarnings("unchecked") + Selectable selectable = (Selectable) model; + for (int selected : selectedIndices) { + selection.add(model.getElementAt(selected)); + } + + selectable.setSelection(selection); + } else { + listbox.setSelectedIndices(selectedIndices); + } + selectedLabel.setValue(Msg.getMsg(Env.getCtx(), "Selected") + " : " + selectedIndices.length); + } + + public void clearSelection() { + ListModel model = listbox.getModel(); + if (model != null && model instanceof Selectable) { + Selectable selectable = (Selectable) model; + selectable.clearSelection(); + } else { + listbox.clearSelection(); + } + selectedLabel.setValue(Msg.getMsg(Env.getCtx(), "Selected") + " : 0"); + } + + public void setSelectedIndex(int selected) { + ListModel model = listbox.getModel(); + if (model != null && model instanceof Selectable) { + @SuppressWarnings("unchecked") + Selectable selectable = (Selectable) model; + Collection selection = new HashSet(); + selection.add(model.getElementAt(selected)); + selectable.setSelection(selection); + selectedLabel.setValue(Msg.getMsg(Env.getCtx(), "Selected") + " : " + selection.size()); + } else { + listbox.setSelectedIndex(selected); + selectedLabel.setValue(Msg.getMsg(Env.getCtx(), "Selected") + " : " + listbox.getSelectedCount()); + } + } +} diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/grid/selection/GridTabSelectionListViewRenderer.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/grid/selection/GridTabSelectionListViewRenderer.java new file mode 100644 index 0000000000..2fa74c357a --- /dev/null +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/grid/selection/GridTabSelectionListViewRenderer.java @@ -0,0 +1,257 @@ +/******************************************************************************* + * Copyright (C) 2016 Trek Global Inc. * + * Copyright (C) 2016 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.grid.selection; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.adempiere.webui.component.ListCell; +import org.adempiere.webui.component.ListItem; +import org.adempiere.webui.editor.WEditor; +import org.adempiere.webui.editor.WebEditorFactory; +import org.compiere.model.GridField; +import org.compiere.model.GridTab; +import org.compiere.util.DisplayType; +import org.zkoss.zk.ui.Component; +import org.zkoss.zul.Listbox; +import org.zkoss.zul.Listcell; +import org.zkoss.zul.Listitem; +import org.zkoss.zul.ListitemRenderer; +import org.zkoss.zul.ListitemRendererExt; +import org.zkoss.zul.RendererCtrl; + +/** + * ListItem renderer for GridTabSelectionListView + * @author hengsin + * + */ +public class GridTabSelectionListViewRenderer implements ListitemRenderer, ListitemRendererExt, RendererCtrl { + + private static final int MAX_TEXT_LENGTH = 60; + private GridTab gridTab; + @SuppressWarnings("unused") + private int windowNo; + private Map editors = new HashMap(); + private GridTabSelectionListView listView; + + /** + * + * @param gridTab + * @param windowNo + */ + public GridTabSelectionListViewRenderer(GridTab gridTab, int windowNo) { + this.gridTab = gridTab; + this.windowNo = windowNo; + } + + /** + * @param listitem + * @param data + * @see ListitemRenderer#render(Listitem, Object) + */ + @Override + public void render(Listitem listitem, GridTableRow data, int index) throws Exception { + //don't render if not visible + if (listView != null && !listView.isVisible()) { + return; + } + + GridField[] listViewFields = listView.getFields(); + int columnCount = listViewFields.length; + + GridField[] gridTabFields = gridTab.getFields(); + boolean isGridViewCustomized = gridTabFields.length != listViewFields.length; + if (!isGridViewCustomized) { + for(int i = 0; i < gridTabFields.length; i++) { + if (listViewFields[i].getAD_Field_ID() != gridTabFields[i].getAD_Field_ID()) { + isGridViewCustomized = true; + break; + } + } + } + + for(Component c = listitem.getParent(); c != null; c = c.getParent()) { + if (!c.isVisible()) + return; + } + Object[] values = null; + if (!isGridViewCustomized) { + values = data.getValues(); + } else { + List dataList = new ArrayList(); + for(GridField gridField : listViewFields) { + for(int i = 0; i < gridTabFields.length; i++) { + if (gridField.getAD_Field_ID() == gridTabFields[i].getAD_Field_ID()) { + dataList.add(data.getValues()[i]); + break; + } + } + } + values = dataList.toArray(new Object[0]); + } + + Listcell selectionCell = new Listcell(); + listitem.appendChild(selectionCell); + + for (int i = 0; i < columnCount; i++) { + if (!listViewFields[i].isDisplayedGrid()) { + continue; + } + if (!editors.containsKey(listViewFields[i])) { + WEditor editor = null; + int displayType = listViewFields[i].getDisplayType(); + if (displayType != DisplayType.YesNo && displayType != DisplayType.Image && displayType != DisplayType.Chart && + displayType != DisplayType.Button && displayType != DisplayType.DashboardContent) { + editor = WebEditorFactory.getEditor(listViewFields[i], true); + editor.setReadWrite(false); + } + editors.put(listViewFields[i], editor); + } + + Listcell cell = renderCell(listViewFields[i], values[i]); + cell.setParent(listitem); + } + } + + private Listcell renderCell(GridField gridField, Object value) { + Listcell cell; + if (gridField.getDisplayType() == DisplayType.YesNo) { + cell = new Listcell("", null); + cell.setStyle("text-align:center"); + WEditor editor = WebEditorFactory.getEditor(gridField, true); + editor.setReadWrite(false); + editor.setValue(value); + cell.appendChild(editor.getComponent()); + } else if (gridField.getDisplayType() == DisplayType.Image || gridField.getDisplayType() == DisplayType.Chart) { + WEditor editor = WebEditorFactory.getEditor(gridField, true); + editor.setReadWrite(false); + editor.setValue(value); + cell = new Listcell("", null); + cell.appendChild(editor.getComponent()); + } else { + String text = getDisplayText(gridField, value); + String display = text; + if (text != null && text.length() > MAX_TEXT_LENGTH) + display = text.substring(0, MAX_TEXT_LENGTH - 3) + "..."; + cell = new Listcell(display, null); + if (text != null && text.length() > MAX_TEXT_LENGTH) + cell.setTooltiptext(text); + if (DisplayType.isNumeric(gridField.getDisplayType())) { + cell.setStyle("text-align:right"); + } else if (gridField.getDisplayType() == DisplayType.Image) { + cell.setStyle("text-align:center"); + } + } + return cell; + } + + /** + * @see ListitemRendererExt#getControls() + */ + public int getControls() { + return DETACH_ON_RENDER; + } + + /** + * @param item + * @see ListitemRendererExt#newListcell(Listitem) + */ + public Listcell newListcell(Listitem item) { + ListCell listCell = new ListCell(); + listCell.applyProperties(); + listCell.setParent(item); + return listCell; + } + + /** + * @param listbox + * @see ListitemRendererExt#newListitem(Listbox) + */ + public Listitem newListitem(Listbox listbox) { + ListItem item = new ListItem(); + item.applyProperties(); + return item; + } + + private String getDisplayText(GridField gridField, Object value) + { + if (value == null) + return ""; + + if (gridField.isEncryptedField()) + { + return "********"; + } + else if (DisplayType.Button == gridField.getDisplayType()) + { + return ""; + } + else + { + WEditor editor = editors.get(gridField); + if (editor != null) + return editor.getDisplayTextForGridView(value); + else + return value.toString(); + } + } + + /** + * Is renderer initialize + * @return boolean + */ + public boolean isInitialize() { + return !editors.isEmpty(); + } + + /** + * + * @return active editor list + */ + public List getEditors() { + List editorList = new ArrayList(); + if (!editors.isEmpty()) + editorList.addAll(editors.values()); + + return editorList; + } + + /** + * @see RendererCtrl#doCatch(Throwable) + */ + public void doCatch(Throwable ex) throws Throwable { + } + + /** + * @see RendererCtrl#doFinally() + */ + public void doFinally() { + } + + /** + * @see RendererCtrl#doTry() + */ + public void doTry() { + } + + public void setListView (GridTabSelectionListView listView) { + this.listView = listView; + } + + public GridTabSelectionListView getListView() { + return listView; + } +} diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/grid/selection/GridTableRow.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/grid/selection/GridTableRow.java new file mode 100644 index 0000000000..ee0a043d4b --- /dev/null +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/grid/selection/GridTableRow.java @@ -0,0 +1,47 @@ +/** + * + */ +package org.adempiere.webui.editor.grid.selection; + +/** + * @author hengsin + * + */ +public class GridTableRow { + + private int id; + private Object[] values; + + /** + * + */ + public GridTableRow(int id, Object[] values) { + this.id = id; + this.values = values; + } + + /* (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + return id; + } + + public Object[] getValues() { + return values; + } + + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (obj instanceof GridTableRow && obj != null) { + GridTableRow that = (GridTableRow) obj; + if (this.id > 0 && that.id == this.id) + return true; + } + return false; + } +} diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/grid/selection/SimpleGridTableListModel.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/grid/selection/SimpleGridTableListModel.java new file mode 100644 index 0000000000..41f4f45288 --- /dev/null +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/grid/selection/SimpleGridTableListModel.java @@ -0,0 +1,154 @@ +/******************************************************************************* + * Copyright (C) 2016 Trek Global Inc. * + * Copyright (C) 2016 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.grid.selection; + +import java.util.Comparator; + +import javax.swing.event.TableModelEvent; +import javax.swing.event.TableModelListener; + +import org.adempiere.webui.util.SortComparator; +import org.compiere.model.GridField; +import org.compiere.model.GridTable; +import org.zkoss.zk.ui.Executions; +import org.zkoss.zul.AbstractListModel; +import org.zkoss.zul.ListModel; +import org.zkoss.zul.ListitemComparator; +import org.zkoss.zul.event.ListDataEvent; +import org.zkoss.zul.ext.Sortable; + +/** + * + * @author Low Heng Sin + * + */ +public class SimpleGridTableListModel extends AbstractListModel implements TableModelListener, Sortable { + + /** + * + */ + private static final long serialVersionUID = 698185856751242764L; + private GridTable tableModel; + @SuppressWarnings("unused") + private GridField[] gridField; + @SuppressWarnings("unused") + private int windowNo; + + /** + * + * @param tableModel + * @param windowNo + */ + public SimpleGridTableListModel(GridTable tableModel, int windowNo) { + this.tableModel = tableModel; + this.windowNo = windowNo; + gridField = tableModel.getFields(); + tableModel.addTableModelListener(this); + } + + /** + * @param rowIndex + * @see ListModel#getElementAt(int) + */ + public GridTableRow getElementAt(int rowIndex) { + GridTableRow row = null; + int columnCount = tableModel.getColumnCount(); + Object[] values = new Object[columnCount]; + if (rowIndex < tableModel.getRowCount()) { + for (int i = 0; i < columnCount; i++) { + values[i] = tableModel.getValueAt(rowIndex, i); + } + row = new GridTableRow(tableModel.getKeyID(rowIndex), values); + } + + return row; + } + + /** + * Get total number of rows + * @return int + * @see ListModel#getSize() + */ + public int getSize() { + return tableModel.getRowCount(); + } + + /** + * Request components that attached to this model to re-render a row. + * @param row + */ + public void updateComponent(int row) { + updateComponent(row, row); + } + + /** + * Request components that attached to this model to re-render a range of row. + * @param fromRow + * @param toRow + */ + public void updateComponent(int fromRow, int toRow) { + //must run from the UI thread + if (Executions.getCurrent() != null) { + fireEvent(ListDataEvent.CONTENTS_CHANGED, fromRow, toRow); + } + } + + /** + * @param cmpr + * @param ascending + * @see ListModelExt#sort(Comparator, boolean) + */ + public void sort(Comparator cmpr, boolean ascending) { + //use default zk comparator + if (cmpr instanceof ListitemComparator) { + ListitemComparator lic = (ListitemComparator) cmpr; + tableModel.sort(lic.getListheader().getColumnIndex(), ascending); + } else if (cmpr instanceof SortComparator) { + SortComparator sc = (SortComparator)cmpr; + tableModel.sort(sc.getColumnIndex(), ascending); + } + fireEvent(ListDataEvent.CONTENTS_CHANGED, -1, -1); + } + + /** + * @param e + * @see TableModelListener#tableChanged(TableModelEvent) + */ + public void tableChanged(TableModelEvent e) { + if (Executions.getCurrent() != null) { + if (e.getType() == TableModelEvent.DELETE) + { + fireEvent(ListDataEvent.INTERVAL_REMOVED, e.getFirstRow(), e.getLastRow()); + } + else if (e.getType() == TableModelEvent.INSERT) + { + fireEvent(ListDataEvent.INTERVAL_ADDED, e.getFirstRow(), e.getLastRow()); + } + else if (e.getLastRow() == Integer.MAX_VALUE) + { + fireEvent(ListDataEvent.CONTENTS_CHANGED, -1, -1); + } + else + { + fireEvent(ListDataEvent.CONTENTS_CHANGED, e.getFirstRow(), e.getLastRow()); + } + } + } + + @Override + public String getSortDirection(Comparator cmpr) { + return "natural"; + } + +} diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/grid/selection/WGridTabMultiSelectionEditor.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/grid/selection/WGridTabMultiSelectionEditor.java new file mode 100644 index 0000000000..89e983d258 --- /dev/null +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/grid/selection/WGridTabMultiSelectionEditor.java @@ -0,0 +1,240 @@ +/******************************************************************************* + * Copyright (C) 2016 Trek Global Inc. * + * Copyright (C) 2016 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.grid.selection; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import org.adempiere.webui.ValuePreference; +import org.adempiere.webui.component.Listbox; +import org.adempiere.webui.editor.WEditor; +import org.adempiere.webui.editor.WEditorPopupMenu; +import org.adempiere.webui.event.ContextMenuEvent; +import org.adempiere.webui.event.ContextMenuListener; +import org.adempiere.webui.event.ValueChangeEvent; +import org.adempiere.webui.window.WFieldRecordInfo; +import org.compiere.model.GridField; +import org.compiere.model.GridTab; +import org.compiere.model.GridTabVO; +import org.compiere.model.GridWindow; +import org.compiere.util.Env; +import org.compiere.util.Util; +import org.zkoss.zk.ui.event.Event; +import org.zkoss.zk.ui.event.Events; +import org.zkoss.zul.ListModel; +import org.zkoss.zul.ext.Selectable; + +/** + * + * @author hengsin + * + */ +public class WGridTabMultiSelectionEditor extends WEditor implements ContextMenuListener +{ + private static final String[] LISTENER_EVENTS = {Events.ON_SELECT}; + + private Object oldValue; + + private boolean tableEditor = false; + + private GridTab listViewGridTab = null; + + private String currentLinkValue = null; + + public WGridTabMultiSelectionEditor(GridField gridField) { + this(gridField, false); + } + + public WGridTabMultiSelectionEditor(GridField gridField, boolean tableEditor) + { + super(new GridTabSelectionListView(true, gridField.getWindowNo()), gridField); + this.tableEditor = tableEditor; + init(); + } + + @Override + public GridTabSelectionListView getComponent() { + return (GridTabSelectionListView) component; + } + + @Override + public boolean isReadWrite() { + return !getComponent().getListbox().isEnabled(); + } + + @Override + public void setReadWrite(boolean readWrite) { + getComponent().getListbox().setEnabled(readWrite); + } + + private void init() + { + if (tableEditor) + setVisible(false); + else if (gridField != null) + { + int AD_Tab_ID = gridField.getIncluded_Tab_ID(); + GridWindow gridWindow = gridField.getGridTab().getGridWindow(); + int count = gridWindow.getTabCount(); + for(int i = 0; i < count; i++) + { + GridTab t = gridWindow.getTab(i); + if (t.getAD_Tab_ID() == AD_Tab_ID) + { + GridTabVO vo = t.getVO(); + listViewGridTab = new GridTab(vo, gridWindow); + listViewGridTab.setLinkColumnName(t.getLinkColumnName()); + getComponent().init(listViewGridTab); + break; + } + } + } + } + + public void onEvent(Event event) + { + if (Events.ON_SELECT.equals(event.getName())) + { + Object newValue = null; + Listbox listbox = getComponent().getListbox(); + ListModel model = listbox.getModel(); + if (model != null && model instanceof Selectable) + { + StringBuilder buffer = new StringBuilder(); + @SuppressWarnings("unchecked") + Selectable selectable = (Selectable) model; + Set selection = selectable.getSelection(); + for(GridTableRow row : selection) + { + if (buffer.length() > 0) + buffer.append(","); + buffer.append(row.hashCode()); + } + newValue = buffer.toString(); + } + else + { + int[] selection = getComponent().getListbox().getSelectedIndices(); + StringBuilder buffer = new StringBuilder(); + for(int rowIndex : selection) + { + int id = listViewGridTab.getKeyID(rowIndex); + if (buffer.length() > 0) + buffer.append(","); + buffer.append(id); + } + newValue = buffer.toString(); + } + if (oldValue != null && newValue != null && oldValue.equals(newValue)) { + return; + } + if (oldValue == null && newValue == null) { + return; + } + Object prevValue = oldValue; + oldValue = newValue; + ValueChangeEvent changeEvent = new ValueChangeEvent(this, this.getColumnName(), prevValue, newValue); + super.fireValueChange(changeEvent); + } + } + + @Override + public String getDisplay() + { + return oldValue != null ? oldValue.toString() : ""; + } + + @Override + public Object getValue() + { + return oldValue; + } + + @Override + public void setValue(Object value) + { + if (value == null && oldValue == null) + { + return; + } + else if (value != null && oldValue != null && value.equals(oldValue)) + { + return; + } + oldValue = value; + updateSlectedIndices(); + } + + private void updateSlectedIndices() { + if (!Util.isEmpty((String)oldValue)) + { + List list = new ArrayList(); + String[] selected = ((String)oldValue).split("[,]"); + for(String s : selected) { + int id = Integer.parseInt(s); + for(int i = 0; i < listViewGridTab.getRowCount(); i++) { + if (listViewGridTab.getKeyID(i) == id) { + list.add(i); + break; + } + } + } + int[] selectedIndices = new int[list.size()]; + for(int i = 0; i < selectedIndices.length; i++) + { + selectedIndices[i] = list.get(i); + } + getComponent().setSelectedIndices(selectedIndices); + } + else + { + getComponent().clearSelection(); + } + } + + @Override + public String[] getEvents() + { + return LISTENER_EVENTS; + } + + public void onMenu(ContextMenuEvent evt) + { + if (WEditorPopupMenu.PREFERENCE_EVENT.equals(evt.getContextEvent())) + { + if (isShowPreference()) + ValuePreference.start (getComponent(), this.getGridField(), getValue()); + return; + } + else if (WEditorPopupMenu.CHANGE_LOG_EVENT.equals(evt.getContextEvent())) + { + WFieldRecordInfo.start(gridField); + } + } + + @Override + public void dynamicDisplay() { + String name = listViewGridTab.getLinkColumnName(); + String linkValue = Env.getContext(Env.getCtx(), gridField.getWindowNo(), name); + if ((currentLinkValue == null && linkValue != null) + || (currentLinkValue != null && linkValue == null) + || (currentLinkValue != null && linkValue != null && !currentLinkValue.equals(linkValue))) + { + getComponent().refresh(listViewGridTab); + updateSlectedIndices(); + } + } +} diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/grid/selection/WGridTabSingleSelectionEditor.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/grid/selection/WGridTabSingleSelectionEditor.java new file mode 100644 index 0000000000..ed963cf48f --- /dev/null +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/editor/grid/selection/WGridTabSingleSelectionEditor.java @@ -0,0 +1,191 @@ +/******************************************************************************* + * Copyright (C) 2016 Trek Global Inc. * + * Copyright (C) 2016 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.grid.selection; + +import org.adempiere.webui.ValuePreference; +import org.adempiere.webui.editor.WEditor; +import org.adempiere.webui.editor.WEditorPopupMenu; +import org.adempiere.webui.event.ContextMenuEvent; +import org.adempiere.webui.event.ContextMenuListener; +import org.adempiere.webui.event.ValueChangeEvent; +import org.adempiere.webui.window.WFieldRecordInfo; +import org.compiere.model.GridField; +import org.compiere.model.GridTab; +import org.compiere.model.GridTabVO; +import org.compiere.model.GridWindow; +import org.compiere.util.Env; +import org.compiere.util.Util; +import org.zkoss.zk.ui.event.Event; +import org.zkoss.zk.ui.event.Events; + +/** + * + * @author hengsin + * + */ +public class WGridTabSingleSelectionEditor extends WEditor implements ContextMenuListener +{ + private static final String[] LISTENER_EVENTS = {Events.ON_SELECT}; + + private Object oldValue; + + private boolean tableEditor = false; + + private GridTab listViewGridTab = null; + + private String currentLinkValue = null; + + public WGridTabSingleSelectionEditor(GridField gridField) { + this(gridField, false); + } + + public WGridTabSingleSelectionEditor(GridField gridField, boolean tableEditor) + { + super(new GridTabSelectionListView(false, gridField.getWindowNo()), gridField); + this.tableEditor = tableEditor; + init(); + } + + @Override + public GridTabSelectionListView getComponent() { + return (GridTabSelectionListView) component; + } + + @Override + public boolean isReadWrite() { + return !getComponent().getListbox().isEnabled(); + } + + @Override + public void setReadWrite(boolean readWrite) { + getComponent().getListbox().setEnabled(readWrite); + } + + private void init() + { + if (tableEditor) + setVisible(false); + else if (gridField != null) + { + int AD_Tab_ID = gridField.getIncluded_Tab_ID(); + GridWindow gridWindow = gridField.getGridTab().getGridWindow(); + int count = gridWindow.getTabCount(); + for(int i = 0; i < count; i++) + { + GridTab t = gridWindow.getTab(i); + if (t.getAD_Tab_ID() == AD_Tab_ID) + { + GridTabVO vo = t.getVO(); + listViewGridTab = new GridTab(vo, gridWindow); + listViewGridTab.setLinkColumnName(t.getLinkColumnName()); + getComponent().init(listViewGridTab); + break; + } + } + } + } + + public void onEvent(Event event) + { + if (Events.ON_SELECT.equals(event.getName())) + { + int selected = getComponent().getListbox().getSelectedIndex(); + Object newValue = selected >= 0 ? Integer.toString(listViewGridTab.getKeyID(selected)) : null; + if (oldValue != null && newValue != null && oldValue.equals(newValue)) { + return; + } + if (oldValue == null && newValue == null) { + return; + } + ValueChangeEvent changeEvent = new ValueChangeEvent(this, this.getColumnName(), oldValue, newValue); + super.fireValueChange(changeEvent); + oldValue = newValue; + } + } + + @Override + public String getDisplay() + { + return oldValue != null ? oldValue.toString() : ""; + } + + @Override + public Object getValue() + { + return oldValue; + } + + @Override + public void setValue(Object value) + { + if (value == null && oldValue == null) + { + return; + } + else if (value != null && oldValue != null && value.equals(oldValue)) + { + return; + } + oldValue = value; + updateSlectedIndices(); + } + + private void updateSlectedIndices() { + getComponent().clearSelection(); + if (!Util.isEmpty((String)oldValue)) + { + int id = Integer.parseInt((String) oldValue); + for(int i = 0; i < listViewGridTab.getRowCount(); i++) { + if (listViewGridTab.getKeyID(i) == id) { + getComponent().setSelectedIndex(i); + return; + } + } + } + } + + @Override + public String[] getEvents() + { + return LISTENER_EVENTS; + } + + public void onMenu(ContextMenuEvent evt) + { + if (WEditorPopupMenu.PREFERENCE_EVENT.equals(evt.getContextEvent())) + { + if (isShowPreference()) + ValuePreference.start (getComponent(), this.getGridField(), getValue()); + return; + } + else if (WEditorPopupMenu.CHANGE_LOG_EVENT.equals(evt.getContextEvent())) + { + WFieldRecordInfo.start(gridField); + } + } + + @Override + public void dynamicDisplay() { + String name = listViewGridTab.getLinkColumnName(); + String linkValue = Env.getContext(Env.getCtx(), gridField.getWindowNo(), name); + if ((currentLinkValue == null && linkValue != null) + || (currentLinkValue != null && linkValue == null) + || (currentLinkValue != null && linkValue != null && !currentLinkValue.equals(linkValue))) + { + getComponent().refresh(listViewGridTab); + updateSlectedIndices(); + } + } +} diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/factory/DefaultEditorFactory.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/factory/DefaultEditorFactory.java index 21d6e8fb51..95d31750d9 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/factory/DefaultEditorFactory.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/factory/DefaultEditorFactory.java @@ -38,6 +38,8 @@ import org.adempiere.webui.editor.WTimeEditor; import org.adempiere.webui.editor.WUnknownEditor; import org.adempiere.webui.editor.WUrlEditor; import org.adempiere.webui.editor.WYesNoEditor; +import org.adempiere.webui.editor.grid.selection.WGridTabMultiSelectionEditor; +import org.adempiere.webui.editor.grid.selection.WGridTabSingleSelectionEditor; import org.compiere.model.GridField; import org.compiere.model.GridTab; import org.compiere.util.DisplayType; @@ -189,6 +191,14 @@ public class DefaultEditorFactory implements IEditorFactory { { editor = new WAssignmentEditor(gridField); } + else if (displayType == DisplayType.SingleSelectionGrid) + { + editor = new WGridTabSingleSelectionEditor(gridField, tableEditor); + } + else if (displayType == DisplayType.MultipleSelectionGrid) + { + editor = new WGridTabMultiSelectionEditor(gridField, tableEditor); + } else { editor = new WUnknownEditor(gridField);