From 3dcef188680e5f83eff1144fa4d98d31a10c8c71 Mon Sep 17 00:00:00 2001 From: hengsin Date: Thu, 15 Jul 2021 23:03:33 +0800 Subject: [PATCH] IDEMPIERE-4841 Info Window: Implement auto hide empty columns (#781) --- .../oracle/202107150800_IDEMPIERE-4841.sql | 10 + .../202107150800_IDEMPIERE-4841.sql | 7 + .../src/org/compiere/model/MSysConfig.java | 1 + .../org/adempiere/webui/info/InfoWindow.java | 4 +- .../org/adempiere/webui/panel/InfoPanel.java | 365 +++++++++++------- 5 files changed, 237 insertions(+), 150 deletions(-) create mode 100644 migration/i8.2z/oracle/202107150800_IDEMPIERE-4841.sql create mode 100644 migration/i8.2z/postgresql/202107150800_IDEMPIERE-4841.sql diff --git a/migration/i8.2z/oracle/202107150800_IDEMPIERE-4841.sql b/migration/i8.2z/oracle/202107150800_IDEMPIERE-4841.sql new file mode 100644 index 0000000000..509af5c409 --- /dev/null +++ b/migration/i8.2z/oracle/202107150800_IDEMPIERE-4841.sql @@ -0,0 +1,10 @@ +SET SQLBLANKLINES ON +SET DEFINE OFF + +-- Jul 15, 2021, 3:50:49 PM MYT +INSERT INTO AD_SysConfig (AD_SysConfig_ID,AD_Client_ID,AD_Org_ID,Created,Updated,CreatedBy,UpdatedBy,IsActive,Name,Value,Description,EntityType,ConfigurationLevel,AD_SysConfig_UU) VALUES (200180,0,0,TO_DATE('2021-07-15 15:50:48','YYYY-MM-DD HH24:MI:SS'),TO_DATE('2021-07-15 15:50:48','YYYY-MM-DD HH24:MI:SS'),100,100,'Y','ZK_INFO_AUTO_HIDE_EMPTY_COLUMNS','N','Y/N - Define if info window will auto hide columns with empty content','D','C','99ba73cd-f64a-418d-bb55-82f4192b1055') +; + +SELECT Register_Migration_Script ('202107150800_IDEMPIERE-4841.sql') FROM DUAL +; + diff --git a/migration/i8.2z/postgresql/202107150800_IDEMPIERE-4841.sql b/migration/i8.2z/postgresql/202107150800_IDEMPIERE-4841.sql new file mode 100644 index 0000000000..08bd79a57b --- /dev/null +++ b/migration/i8.2z/postgresql/202107150800_IDEMPIERE-4841.sql @@ -0,0 +1,7 @@ +-- Jul 15, 2021, 3:50:49 PM MYT +INSERT INTO AD_SysConfig (AD_SysConfig_ID,AD_Client_ID,AD_Org_ID,Created,Updated,CreatedBy,UpdatedBy,IsActive,Name,Value,Description,EntityType,ConfigurationLevel,AD_SysConfig_UU) VALUES (200180,0,0,TO_TIMESTAMP('2021-07-15 15:50:48','YYYY-MM-DD HH24:MI:SS'),TO_TIMESTAMP('2021-07-15 15:50:48','YYYY-MM-DD HH24:MI:SS'),100,100,'Y','ZK_INFO_AUTO_HIDE_EMPTY_COLUMNS','N','Y/N - Define if info window will auto hide columns with empty content','D','C','99ba73cd-f64a-418d-bb55-82f4192b1055') +; + +SELECT Register_Migration_Script ('202107150800_IDEMPIERE-4841.sql') FROM DUAL +; + diff --git a/org.adempiere.base/src/org/compiere/model/MSysConfig.java b/org.adempiere.base/src/org/compiere/model/MSysConfig.java index 23dbb41e93..8390bc2e1d 100644 --- a/org.adempiere.base/src/org/compiere/model/MSysConfig.java +++ b/org.adempiere.base/src/org/compiere/model/MSysConfig.java @@ -189,6 +189,7 @@ public class MSysConfig extends X_AD_SysConfig public static final String ZK_GRID_MOBILE_MAX_COLUMNS = "ZK_GRID_MOBILE_MAX_COLUMNS"; public static final String ZK_GRID_MOBILE_SHOW_CURRENT_ROW_INDICATOR = "ZK_GRID_MOBILE_SHOW_CURRENT_ROW_INDICATOR"; public static final String ZK_GRID_VIEW_USE_DEFER_RENDERING = "ZK_GRID_VIEW_USE_DEFER_RENDERING"; + public static final String ZK_INFO_AUTO_HIDE_EMPTY_COLUMNS = "ZK_INFO_AUTO_HIDE_EMPTY_COLUMNS"; public static final String ZK_INFO_NUM_PAGE_PRELOAD = "ZK_INFO_NUM_PAGE_PRELOAD"; public static final String ZK_INFO_QUERY_TIME_OUT = "ZK_INFO_QUERY_TIME_OUT"; public static final String ZK_LOGIN_ALLOW_CHROME_SAVE_PASSWORD = "ZK_LOGIN_ALLOW_CHROME_SAVE_PASSWORD"; diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/info/InfoWindow.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/info/InfoWindow.java index 85cca3d371..791f8c4bcd 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/info/InfoWindow.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/info/InfoWindow.java @@ -135,8 +135,8 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL /** * */ - private static final long serialVersionUID = 5041961608373943362L; - + private static final long serialVersionUID = 1180753002653812499L; + protected Grid parameterGrid; private Borderlayout layout; private Vbox southBody; diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/InfoPanel.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/InfoPanel.java index 944b4fb6f4..f1f027de76 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/InfoPanel.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/panel/InfoPanel.java @@ -92,6 +92,7 @@ import org.compiere.util.Trx; import org.compiere.util.Util; import org.compiere.util.ValueNamePair; import org.zkoss.zk.au.out.AuEcho; +import org.zkoss.zk.ui.Executions; import org.zkoss.zk.ui.Page; import org.zkoss.zk.ui.event.Event; import org.zkoss.zk.ui.event.EventListener; @@ -124,6 +125,8 @@ import org.zkoss.zul.ext.Sortable; public abstract class InfoPanel extends Window implements EventListener, WTableModelListener, Sortable, IHelpContext { protected static final String INFO_QUERY_TIME_OUT_ERROR = "InfoQueryTimeOutError"; + protected static final String COLUMN_VISIBLE_ORIGINAL = "column.visible.original"; + /** * */ @@ -895,6 +898,7 @@ public abstract class InfoPanel extends Window implements EventListener, model.setMultiple(p_multipleSelection); contentPanel.setData(model, null); } + autoHideEmptyColumns(); restoreSelectedInPage(); updateStatusBar (m_count); setStatusSelected (); @@ -904,7 +908,70 @@ public abstract class InfoPanel extends Window implements EventListener, insertPagingComponent(); } - protected void updateStatusBar (int no){ + /** + * auto hide empty columns + */ + protected void autoHideEmptyColumns() { + String attr = contentPanel.getUuid()+".autoHideEmptyColumns"; + if (Executions.getCurrent().getAttribute(attr) != null) { + return; + } else { + Executions.getCurrent().setAttribute(attr, Boolean.TRUE); + } + + Listhead columns = contentPanel.getListhead(); + List columnList = columns.getChildren(); + int rowCount = model.getSize(); + + for(Listheader column : columnList) { + if (!isAutoHideEmptyColumns()) { + if (!column.isVisible()) { + Object attrValue = column.getAttribute(COLUMN_VISIBLE_ORIGINAL); + if (attrValue != null && attrValue instanceof Boolean) { + Boolean b = (Boolean) attrValue; + if (b.booleanValue()) + column.setVisible(true); + } + } + continue; + } + + boolean hideColumn = false; + if (rowCount > 0) { + hideColumn = true; + for (int i = 0; i < rowCount; i++) { + Object value = model.getDataAt(i, column.getColumnIndex()); + String display = value != null ? value.toString() : ""; + if (!Util.isEmpty(display, true)) { + hideColumn = false; + break; + } + } + } + + if (hideColumn && column.isVisible()) { + column.setVisible(false); + column.setAttribute(COLUMN_VISIBLE_ORIGINAL, Boolean.TRUE); + } else if (!hideColumn && !column.isVisible()) { + Object attrValue = column.getAttribute(COLUMN_VISIBLE_ORIGINAL); + if (attrValue != null && attrValue instanceof Boolean) { + Boolean b = (Boolean) attrValue; + if (b.booleanValue()) + column.setVisible(true); + } + } + } + } + + /** + * + * @return true if info window should auto hide empty columns + */ + protected boolean isAutoHideEmptyColumns() { + return MSysConfig.getBooleanValue(MSysConfig.ZK_INFO_AUTO_HIDE_EMPTY_COLUMNS, false, Env.getAD_Client_ID(Env.getCtx())); + } + + protected void updateStatusBar (int no){ setStatusLine((no == Integer.MAX_VALUE?"?":Integer.toString(no)) + " " + Msg.getMsg(Env.getCtx(), "SearchRows_EnterQuery"), false); setStatusDB(no == Integer.MAX_VALUE?"?":Integer.toString(no)); } @@ -1912,101 +1979,102 @@ public abstract class InfoPanel extends Window implements EventListener, return; } - if (event.getTarget().equals(confirmPanel.getButton(ConfirmPanel.A_OK))) - { - onOk(); - } - else if (event.getTarget() == contentPanel && event.getName().equals(Events.ON_SELECT)) - { - setStatusSelected (); - - SelectEvent selectEvent = (SelectEvent) event; - if (selectEvent.getReference() != null && selectEvent.getReference() instanceof Listitem) - { - Listitem m_lastOnSelectItem = (Listitem) selectEvent.getReference(); - m_lastSelectedIndex = m_lastOnSelectItem.getIndex(); - } + if (event.getTarget().equals(confirmPanel.getButton(ConfirmPanel.A_OK))) + { + onOk(); + } + else if (event.getTarget() == contentPanel && event.getName().equals(Events.ON_SELECT)) + { + setStatusSelected (); + + SelectEvent selectEvent = (SelectEvent) event; + if (selectEvent.getReference() != null && selectEvent.getReference() instanceof Listitem) + { + Listitem m_lastOnSelectItem = (Listitem) selectEvent.getReference(); + m_lastSelectedIndex = m_lastOnSelectItem.getIndex(); + } - enableButtons(); - - }else if (event.getTarget() == contentPanel && event.getName().equals("onAfterRender")){ - //IDEMPIERE-1334 at this event selected item from listBox and model is sync - enableButtons(); - } - else if (event.getTarget() == contentPanel && event.getName().equals(Events.ON_DOUBLE_CLICK)) - { - if (event.getClass().equals(MouseEvent.class)){ - return; - } - if (contentPanel.isMultiple() && m_lastSelectedIndex >= 0) { - - contentPanel.setSelectedIndex(m_lastSelectedIndex); - - model.clearSelection(); - List lsSelectedItem = new ArrayList(); - lsSelectedItem.add(model.getElementAt(m_lastSelectedIndex)); - model.setSelection(lsSelectedItem); - - int m_keyColumnIndex = contentPanel.getKeyColumnIndex(); - for (int i = 0; i < contentPanel.getRowCount(); i++) { - // Find the IDColumn Key - Object data = contentPanel.getModel().getValueAt(i, m_keyColumnIndex); - if (data instanceof IDColumn) { - IDColumn dataColumn = (IDColumn) data; - - if (i == m_lastSelectedIndex) { - dataColumn.setSelected(true); - } - else { - dataColumn.setSelected(false); - } + enableButtons(); + + }else if (event.getTarget() == contentPanel && event.getName().equals("onAfterRender")){ + //IDEMPIERE-1334 at this event selected item from listBox and model is sync + enableButtons(); + } + else if (event.getTarget() == contentPanel && event.getName().equals(Events.ON_DOUBLE_CLICK)) + { + if (event.getClass().equals(MouseEvent.class)){ + return; + } + if (contentPanel.isMultiple() && m_lastSelectedIndex >= 0) { + + contentPanel.setSelectedIndex(m_lastSelectedIndex); + + model.clearSelection(); + List lsSelectedItem = new ArrayList(); + lsSelectedItem.add(model.getElementAt(m_lastSelectedIndex)); + model.setSelection(lsSelectedItem); + + int m_keyColumnIndex = contentPanel.getKeyColumnIndex(); + for (int i = 0; i < contentPanel.getRowCount(); i++) { + // Find the IDColumn Key + Object data = contentPanel.getModel().getValueAt(i, m_keyColumnIndex); + if (data instanceof IDColumn) { + IDColumn dataColumn = (IDColumn) data; + + if (i == m_lastSelectedIndex) { + dataColumn.setSelected(true); + } + else { + dataColumn.setSelected(false); } } - } - onDoubleClick(); - contentPanel.repaint(); - m_lastSelectedIndex = -1; - } - else if (event.getTarget().equals(confirmPanel.getButton(ConfirmPanel.A_REFRESH))) + } + } + onDoubleClick(); + contentPanel.repaint(); + m_lastSelectedIndex = -1; + } + else if (event.getTarget().equals(confirmPanel.getButton(ConfirmPanel.A_REFRESH))) + { + onUserQuery(); + } + else if (event.getTarget().equals(confirmPanel.getButton(ConfirmPanel.A_CANCEL))) + { + m_cancel = true; + dispose(false); + } + else if (event.getTarget().equals(confirmPanel.getButton(ConfirmPanel.A_RESET))) { + resetParameters (); + } + // Elaine 2008/12/16 + else if (event.getTarget().equals(confirmPanel.getButton(ConfirmPanel.A_HISTORY))) + { + if (!contentPanel.getChildren().isEmpty() && contentPanel.getSelectedRowKey()!=null) { - onUserQuery(); + showHistory(); } - else if (event.getTarget().equals(confirmPanel.getButton(ConfirmPanel.A_CANCEL))) + } + else if (event.getTarget().equals(confirmPanel.getButton(ConfirmPanel.A_CUSTOMIZE))) + { + if (!contentPanel.getChildren().isEmpty() && contentPanel.getSelectedRowKey()!=null) { - m_cancel = true; - dispose(false); + customize(); } - else if (event.getTarget().equals(confirmPanel.getButton(ConfirmPanel.A_RESET))) { - resetParameters (); - } - // Elaine 2008/12/16 - else if (event.getTarget().equals(confirmPanel.getButton(ConfirmPanel.A_HISTORY))) + } + // + else if (event.getTarget().equals(confirmPanel.getButton(ConfirmPanel.A_ZOOM))) + { + if (!contentPanel.getChildren().isEmpty() && contentPanel.getSelectedRowKey()!=null) { - if (!contentPanel.getChildren().isEmpty() && contentPanel.getSelectedRowKey()!=null) - { - showHistory(); - } - } - else if (event.getTarget().equals(confirmPanel.getButton(ConfirmPanel.A_CUSTOMIZE))) - { - if (!contentPanel.getChildren().isEmpty() && contentPanel.getSelectedRowKey()!=null) - { - customize(); - } - } - // - else if (event.getTarget().equals(confirmPanel.getButton(ConfirmPanel.A_ZOOM))) - { - if (!contentPanel.getChildren().isEmpty() && contentPanel.getSelectedRowKey()!=null) - { - zoom(); - if (isLookup()) - this.detach(); - } - }else if (event.getTarget().equals(confirmPanel.getButton(ConfirmPanel.A_NEW))) - { - newRecordAction (); + zoom(); + if (isLookup()) + this.detach(); } + } + else if (event.getTarget().equals(confirmPanel.getButton(ConfirmPanel.A_NEW))) + { + newRecordAction (); + } // IDEMPIERE-1334 handle event click into process button start else if (ON_RUN_PROCESS.equals(event.getName())){ // hand echo event after click button process @@ -2037,70 +2105,71 @@ public abstract class InfoPanel extends Window implements EventListener, preRunProcess (processId); } // IDEMPIERE-1334 handle event click into process button end - else if (event.getTarget() == paging) - { - updateListSelected(); - int pgNo = paging.getActivePage(); - if (pgNo == paging.getPageCount()-1 && !isLoadPageNumber()) { - testCount(); - paging.setTotalSize(m_count); - pgNo = paging.getActivePage(); - } + else if (event.getTarget() == paging) + { + updateListSelected(); + int pgNo = paging.getActivePage(); + if (pgNo == paging.getPageCount()-1 && !isLoadPageNumber()) { + testCount(); + paging.setTotalSize(m_count); + pgNo = paging.getActivePage(); + } - if (pageNo != pgNo) - { - - contentPanel.clearSelection(); - - pageNo = pgNo; - int start = pageNo * pageSize; - int end = getOverIntValue ((long)start + pageSize, extra_max_row); - if (end >= m_count) - end = m_count; - List subList = readLine(start, end); - model = new ListModelTable(subList); - model.setSorter(this); - model.addTableModelListener(this); - model.setMultiple(p_multipleSelection); - contentPanel.setData(model, null); - restoreSelectedInPage(); - //contentPanel.setSelectedIndex(0); - - } - } - else if (event.getName().equals(Events.ON_CHANGE)) - { - } - else if (event.getName().equals(WindowContainer.ON_WINDOW_CONTAINER_SELECTION_CHANGED_EVENT)) + if (pageNo != pgNo) { - if (infoWindow != null) - SessionManager.getAppDesktop().updateHelpContext(X_AD_CtxHelp.CTXTYPE_Info, infoWindow.getAD_InfoWindow_ID()); - else - SessionManager.getAppDesktop().updateHelpContext(X_AD_CtxHelp.CTXTYPE_Home, 0); + + contentPanel.clearSelection(); + + pageNo = pgNo; + int start = pageNo * pageSize; + int end = getOverIntValue ((long)start + pageSize, extra_max_row); + if (end >= m_count) + end = m_count; + List subList = readLine(start, end); + model = new ListModelTable(subList); + model.setSorter(this); + model.addTableModelListener(this); + model.setMultiple(p_multipleSelection); + contentPanel.setData(model, null); + restoreSelectedInPage(); + //contentPanel.setSelectedIndex(0); + + } + autoHideEmptyColumns(); + } + else if (event.getName().equals(Events.ON_CHANGE)) + { + } + else if (event.getName().equals(WindowContainer.ON_WINDOW_CONTAINER_SELECTION_CHANGED_EVENT)) + { + if (infoWindow != null) + SessionManager.getAppDesktop().updateHelpContext(X_AD_CtxHelp.CTXTYPE_Info, infoWindow.getAD_InfoWindow_ID()); + else + SessionManager.getAppDesktop().updateHelpContext(X_AD_CtxHelp.CTXTYPE_Home, 0); + } + else if (event.getName().equals(Events.ON_CTRL_KEY)) + { + KeyEvent keyEvent = (KeyEvent) event; + if (LayoutUtils.isReallyVisible(this)) { + this.onCtrlKeyEvent(keyEvent); + } + }else if (event.getName().equals(Events.ON_OK)){// on ok when focus at non parameter component. example grid result + if (m_lookup && contentPanel.getSelectedIndex() >= 0){ + // do nothing when parameter not change and at window mode, or at dialog mode but select non record + onOk(); + } + else if (m_infoWindowID == 0 && event.getTarget() instanceof InfoGeneralPanel) { + onUserQuery(); } - else if (event.getName().equals(Events.ON_CTRL_KEY)) - { - KeyEvent keyEvent = (KeyEvent) event; - if (LayoutUtils.isReallyVisible(this)) { - this.onCtrlKeyEvent(keyEvent); - } - }else if (event.getName().equals(Events.ON_OK)){// on ok when focus at non parameter component. example grid result - if (m_lookup && contentPanel.getSelectedIndex() >= 0){ - // do nothing when parameter not change and at window mode, or at dialog mode but select non record - onOk(); - } - else if (m_infoWindowID == 0 && event.getTarget() instanceof InfoGeneralPanel) { - onUserQuery(); - } - }else if (event.getName().equals(Events.ON_CANCEL) || (event.getTarget().equals(this) && event.getName().equals(Events.ON_CLOSE))){ - m_cancel = true; - dispose(false); - } - //when user push enter keyboard at input parameter field - else - { - // onUserQuery(); // captured now on control key - } + }else if (event.getName().equals(Events.ON_CANCEL) || (event.getTarget().equals(this) && event.getName().equals(Events.ON_CLOSE))){ + m_cancel = true; + dispose(false); + } + //when user push enter keyboard at input parameter field + else + { + // onUserQuery(); // captured now on control key + } } // onEvent public static final int VK_ENTER = '\r';