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 7984de97fe..32013cfeaa 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 @@ -3,13 +3,14 @@ */ package org.adempiere.webui.info; -import java.math.BigDecimal; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Timestamp; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Properties; import java.util.TreeMap; import java.util.logging.Level; @@ -32,7 +33,6 @@ import org.adempiere.webui.component.EditorBox; import org.adempiere.webui.component.Grid; import org.adempiere.webui.component.GridFactory; import org.adempiere.webui.component.Label; -import org.adempiere.webui.component.ListModelTable; import org.adempiere.webui.component.Menupopup; import org.adempiere.webui.component.Row; import org.adempiere.webui.component.Rows; @@ -95,10 +95,12 @@ import org.zkoss.zul.Div; import org.zkoss.zul.ListModelList; import org.zkoss.zul.Menuitem; import org.zkoss.zul.North; +import org.zkoss.zul.Paging; import org.zkoss.zul.Separator; import org.zkoss.zul.South; import org.zkoss.zul.Space; import org.zkoss.zul.Vbox; +import org.zkoss.zul.Vlayout; /** * AD_InfoWindow implementation @@ -123,6 +125,7 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL /** embedded Panel **/ Tabbox embeddedPane = new Tabbox(); ArrayList embeddedWinList = new ArrayList (); + Map relatedMap = new HashMap<>(); /** Max Length of Fields */ public static final int FIELDLENGTH = 20; @@ -236,11 +239,12 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL // get index of link column indexData = p_layout.length + columnDataIndex.get(embed.getParentLinkColumnID()); } - refresh(contentPanel.getValueAt(row,indexData),embed); + RelatedInfoWindow relatedInfoWindow = relatedMap.get(embed.getInfowin().getAD_InfoWindow_ID()); + relatedInfoWindow.refresh(contentPanel.getValueAt(row,indexData)); }// refresh for all }else{ for (EmbedWinInfo embed : embeddedWinList) { - refresh(embed); + reset(embed); } } } @@ -630,6 +634,7 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL String s_sqlFrom = embedInfo.getFromClause(); /** Where Clause */ String s_sqlWhere = relatedInfo.getLinkColumnName() + "=?"; + String s_sqlCount = "SELECT COUNT(*) FROM " + s_sqlFrom + " WHERE " + s_sqlWhere; m_sqlEmbedded = embeddedTbl.prepareTable(s_layoutEmbedded, s_sqlFrom, s_sqlWhere, false, tableName); embeddedTbl.setMultiSelection(false); @@ -639,10 +644,19 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL embeddedTbl.getModel().addTableModelListener(this); ZKUpdateUtil.setVflex(embeddedTbl, "1"); - + Paging embeddedPaging = new Paging(); + embeddedPaging.setPageSize(pageSize); + embeddedPaging.setTotalSize(0); + ZKUpdateUtil.setHflex(embeddedPaging, "1"); + embeddedPaging.setMold("os"); + embeddedPaging.setVisible(false); + embeddedPaging.setSclass("infowindow-related-paging"); + //Xolali - add embeddedTbl to list, add m_sqlembedded to list EmbedWinInfo ewinInfo = new EmbedWinInfo(embedInfo,embeddedTbl,m_sqlEmbedded,relatedInfo.getLinkColumnName(), relatedInfo.getLinkInfoColumn(), relatedInfo.getParentRelatedColumn_ID()); embeddedWinList.add(ewinInfo); + RelatedInfoWindow relatedInfoWindow = new RelatedInfoWindow(ewinInfo, this, embeddedPaging, s_sqlCount, s_layoutEmbedded); + relatedMap.put(embedInfo.getAD_InfoWindow_ID(), relatedInfoWindow); MInfoWindow riw = (MInfoWindow) relatedInfo.getRelatedInfo(); String tabTitle; @@ -655,7 +669,11 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL Tabpanel desktopTabPanel = new Tabpanel(); //desktopTabPanel. ZKUpdateUtil.setHeight(desktopTabPanel, "100%"); - desktopTabPanel.appendChild(embeddedTbl); + Vlayout vlayout = new Vlayout(); + ZKUpdateUtil.setVflex(vlayout, "1"); + desktopTabPanel.appendChild(vlayout); + vlayout.appendChild(embeddedPaging); + vlayout.appendChild(embeddedTbl); tabPanels.appendChild(desktopTabPanel); } @@ -1055,7 +1073,7 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL * or parentLink of infoRelateWindow. * * this function just add column name of hidden infoWindow to end of query - * @param sqlMain main sql to append column + * @param sqlMain main sql to append column * @param listInfoColumn list of PO contain infoColumnID, this infoColumnID will add to query * @return sql after append column */ @@ -1176,7 +1194,7 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL div.setStyle("width :100%; height: 100%"); ZKUpdateUtil.setVflex(div, "1"); ZKUpdateUtil.setHflex(div, "1"); - div.appendChild(contentPanel); + div.appendChild(contentPanel); Borderlayout inner = new Borderlayout(); ZKUpdateUtil.setWidth(inner, "100%"); @@ -1889,56 +1907,10 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL } /** - * @author xolali IDEMPIERE-1045 - * refresh(Object obj, EmbedWinInfo relatedInfo) + * reset to empty + * @param relatedInfo */ - protected void refresh(Object obj, EmbedWinInfo relatedInfo) - { - StringBuilder sql = new StringBuilder(); - sql.append(relatedInfo.getInfoSql()); // delete get sql method from MInfoWindow - if (log.isLoggable(Level.FINEST)) - log.finest(sql.toString()); - - Object linkPara = null; - if (obj != null && obj instanceof IDColumn){ - IDColumn ID = (IDColumn) obj; - linkPara = ID.getRecord_ID(); - }else if (obj != null){ - linkPara = obj.toString(); - }else { - //TODO:hard case - } - - PreparedStatement pstmt = null; - ResultSet rs = null; - try - { - pstmt = DB.prepareStatement(relatedInfo.getInfoSql(), null); - //TODO: implicit type conversion. will exception in some case must recheck - if (relatedInfo.getTypeDataOfLink().equals(String.class)){ - pstmt.setString(1, (String)linkPara); - }else if (relatedInfo.getTypeDataOfLink().equals(int.class)){ - pstmt.setInt(1, Integer.parseInt(linkPara.toString())); - - }else{ - pstmt.setObject(1, linkPara); - } - - rs = pstmt.executeQuery(); - loadEmbedded(rs, relatedInfo); - } - catch (Exception e) - { - log.log(Level.WARNING, sql.toString(), e); - } - finally - { - DB.close(rs, pstmt); - rs = null; pstmt = null; - } - } // refresh - - protected void refresh(EmbedWinInfo relatedInfo){ + protected void reset(EmbedWinInfo relatedInfo){ if (relatedInfo.getInfoTbl() != null){ if (((WListbox)relatedInfo.getInfoTbl()).getModel() != null) ((WListbox)relatedInfo.getInfoTbl()).getModel().clear(); @@ -1946,38 +1918,6 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL ((WListbox)relatedInfo.getInfoTbl()).clear(); } } - - /** - * @author xolali IDEMPIERE-1045 - * loadEmbedded(ResultSet rs, EmbedWinInfo info) - */ - public void loadEmbedded(ResultSet rs, EmbedWinInfo info) throws SQLException{ - - ListModelTable model; - ArrayList list = new ArrayList(); - list = getInfoColumnslayout(info.getInfowin()); - - // Convert ArrayList to Array - ColumnInfo[] s_layoutEmbedded = new ColumnInfo[list.size()]; - list.toArray(s_layoutEmbedded); - List data = new ArrayList(); - ArrayList lines = new ArrayList(); - - while (rs.next()) - { - try { - data = readData(rs, s_layoutEmbedded); - } catch (SQLException e) { - //Xolali - Auto-generated catch block - e.printStackTrace(); - } - lines.add(data); - } - model = new ListModelTable(lines); - - WListbox content = (WListbox) info.getInfoTbl(); - content.setData(model, null); - } /** * @author xolali IDEMPIERE-1045 @@ -2005,79 +1945,6 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL return gridField; } - protected ArrayList readData(ResultSet rs, ColumnInfo[] p_layout) throws SQLException { - - int colOffset = 1; // columns start with 1 - ArrayList data = new ArrayList(); - for (int col = 0; col < p_layout.length; col++) - { - Object value = null; - Class c = p_layout[col].getColClass(); - int colIndex = col + colOffset; - if (c == IDColumn.class) - { - value = new IDColumn(rs.getInt(colIndex)); - } - else if (c == Boolean.class) - value = new Boolean("Y".equals(rs.getString(colIndex))); - else if (c == Timestamp.class) - value = rs.getTimestamp(colIndex); - else if (c == BigDecimal.class) - value = rs.getBigDecimal(colIndex); - else if (c == Double.class) - value = new Double(rs.getDouble(colIndex)); - else if (c == Integer.class) - value = new Integer(rs.getInt(colIndex)); - else if (c == KeyNamePair.class) - { - if (p_layout[col].isKeyPairCol()) - { - String display = rs.getString(colIndex); - int key = rs.getInt(colIndex+1); - if (! rs.wasNull()) { - value = new KeyNamePair(key, display); - } - colOffset++; - } - else - { - int key = rs.getInt(colIndex); - if (! rs.wasNull()) { - WEditor editor = editorMap.get(p_layout[col].getColSQL()); // rework this, it will fail - if (editor != null) - { - editor.setValue(key); - value = new KeyNamePair(key, editor.getDisplayTextForGridView(key)); - } - else - { - value = new KeyNamePair(key, Integer.toString(key)); - } - } - } - } - else if (c == ValueNamePair.class) - { - String key = rs.getString(colIndex); - WEditor editor = editorMap.get(p_layout[col].getColSQL()); - if (editor != null) - { - value = new ValueNamePair(key, editor.getDisplayTextForGridView(key)); - } - else - { - value = new ValueNamePair(key, key); - } - } - else - { - value = rs.getString(colIndex); - } - data.add(value); - } - - return data; - } /** @@ -2093,7 +1960,7 @@ public class InfoWindow extends InfoPanel implements ValueChangeListener, EventL // cancel editor not display if (wEditor == null || !wEditor.isVisible() || wEditor.getGridField() == null){ continue; -} + } isValid = isValid & validateField (wEditor); } diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/info/RelatedInfoWindow.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/info/RelatedInfoWindow.java new file mode 100644 index 0000000000..8cdd578352 --- /dev/null +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/info/RelatedInfoWindow.java @@ -0,0 +1,587 @@ +/****************************************************************************** + * Project: Trek Global ERP * + * Copyright (C) 2009-2018 Trek Global Corporation * + * 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.info; + +import java.math.BigDecimal; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.logging.Level; + +import org.adempiere.webui.component.ListModelTable; +import org.adempiere.webui.component.WListItemRenderer; +import org.adempiere.webui.component.WListbox; +import org.adempiere.webui.editor.WEditor; +import org.compiere.minigrid.ColumnInfo; +import org.compiere.minigrid.EmbedWinInfo; +import org.compiere.minigrid.IDColumn; +import org.compiere.model.MSysConfig; +import org.compiere.util.CLogger; +import org.compiere.util.DB; +import org.compiere.util.KeyNamePair; +import org.compiere.util.Trx; +import org.compiere.util.Util; +import org.compiere.util.ValueNamePair; +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.Paging; +import org.zkoss.zul.event.PagingEvent; +import org.zkoss.zul.event.ZulEvents; +import org.zkoss.zul.ext.Sortable; + +/** + * @author hengsin + * + */ +public class RelatedInfoWindow implements EventListener, Sortable{ + + private final static int DEFAULT_PAGE_PRELOAD = 4; + + private EmbedWinInfo info; + + private int m_count; + private int pageNo; + private List cache; + private int cacheStart; + private int cacheEnd; + private Object parentId; + protected Paging paging; + protected Map editorMap = new HashMap(); + private InfoWindow parentInfoWindow; + + protected CLogger log = CLogger.getCLogger(getClass()); + + private ListModelTable model; + + private String m_sqlUserOrder; + private boolean m_useDatabasePaging = false; + + private String m_infoSqlCount; + protected int numPagePreLoad = MSysConfig.getIntValue(MSysConfig.ZK_INFO_NUM_PAGE_PRELOAD, DEFAULT_PAGE_PRELOAD); + protected boolean isHasNextPage = false; + + private ColumnInfo[] columnsLayout; + + /** + * @param infoWindow + * @param embeddedPaging + * @param layoutEmbedded + * + */ + public RelatedInfoWindow(EmbedWinInfo info, InfoWindow infoWindow, Paging embeddedPaging, String infoSqlCount, ColumnInfo[] layoutEmbedded) { + this.info = info; + parentInfoWindow = infoWindow; + this.paging = embeddedPaging; + m_infoSqlCount = infoSqlCount; + + columnsLayout = layoutEmbedded; + } + + public void refresh(Object id) { + parentId = id; + + + cache = null; + cacheStart = cacheEnd = 0; + + if (info.getInfowin().isLoadPageNum()) { + testCount(); + } else { + m_count = Integer.MAX_VALUE; + } + m_useDatabasePaging = (m_count > 1000 || m_count > (parentInfoWindow.getPageSize()*4)); + + renderItems(); + } + + private void testCount() { + m_count = 0; + Object linkPara = null; + if (parentId != null && parentId instanceof IDColumn){ + IDColumn ID = (IDColumn) parentId; + linkPara = ID.getRecord_ID(); + }else if (parentId != null){ + linkPara = parentId.toString(); + } + if (linkPara != null) { + if (info.getTypeDataOfLink().equals(String.class)){ + m_count = DB.getSQLValue((String)null, m_infoSqlCount, (String)linkPara); + }else if (info.getTypeDataOfLink().equals(int.class)){ + m_count = DB.getSQLValue((String)null, m_infoSqlCount, Integer.parseInt(linkPara.toString())); + }else{ + m_count = DB.getSQLValue((String)null, m_infoSqlCount, linkPara); + } + } + } + + private void renderItems() { + int pageSize = parentInfoWindow.getPageSize(); + WListbox contentPanel = (WListbox) info.getInfoTbl(); + if (m_count > 0) + { + if (m_count > pageSize && paging != null) + { + paging.setVisible(true); + paging.setPageSize(pageSize); + paging.setTotalSize(m_count); + paging.setDetailed(false); + paging.addEventListener(ZulEvents.ON_PAGING, this); + + List subList = readLine(0, pageSize); + model = new ListModelTable(subList); + model.setSorter(this); + model.setMultiple(false); + contentPanel.setData(model, null); + + pageNo = 0; + } + else + { + if (paging != null) + { + paging.setTotalSize(m_count); + paging.setActivePage(0); + paging.setVisible(false); + pageNo = 0; + } + model = new ListModelTable(readLine(0, -1)); + model.setSorter(this); + model.setMultiple(false); + contentPanel.setData(model, null); + } + } + else + { + if (paging != null) + { + paging.setTotalSize(m_count); + paging.setActivePage(0); + paging.setVisible(false); + pageNo = 0; + } + model = new ListModelTable(new ArrayList()); + model.setMultiple(false); + contentPanel.setData(model, null); + } + contentPanel.getParent().invalidate(); + } + + @Override + public void onEvent(Event event) throws Exception { + if (event.getTarget() == paging) + { + WListbox contentPanel = (WListbox) info.getInfoTbl(); + int pageSize = parentInfoWindow.getPageSize(); + int pgNo = paging.getActivePage(); + if (pgNo == paging.getPageCount()-1 && !info.getInfowin().isLoadPageNum()) { + 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, 1); + if (end >= m_count) + end = m_count; + List subList = readLine(start, end); + model = new ListModelTable(subList); + model.setSorter(this); + model.setMultiple(false); + contentPanel.setData(model, null); + + contentPanel.setSelectedIndex(0); + } + } + } + + /** + * @return the cacheStart + */ + protected int getCacheStart() { + return cacheStart; + } + + /** + * @param cacheStart the cacheStart to set + */ + private void setCacheStart(int cacheStart) { + this.cacheStart = cacheStart; + } + + /** + * @return the cacheEnd + */ + protected int getCacheEnd() { + return cacheEnd; + } + + private List getSubList (int fromIndex, int toIndex, List line){ + if (toIndex > line.size()) + toIndex = line.size(); + + if (fromIndex >= line.size()) + fromIndex = line.size(); + + // case line.size = 0 + if (fromIndex < 0) + fromIndex = 0; + + return line.subList(fromIndex, toIndex); + } + + /** + * when calculator value at bound, sometime value is overflow by data type + * this function calculator at high type for avoid it + * @param overValue + * @return + */ + private int getOverIntValue (long overValue){ + return getOverIntValue (overValue, 0); + } + + /** + * see {@link #getOverIntValue(long)}. when value over max_value set it near max_value. + * @param overValue + * @param extra + * @return + */ + private int getOverIntValue (long overValue, int extra){ + if (overValue >= Integer.MAX_VALUE) + overValue = Integer.MAX_VALUE - extra; + + return (int)overValue; + } + + private List readLine(int start, int end) { + int pageSize = parentInfoWindow.getPageSize(); + + //cacheStart & cacheEnd - 1 based index, start & end - 0 based index + if (getCacheStart() >= 1 && cacheEnd > getCacheStart()) + { + if (m_useDatabasePaging) + { + if (start+1 >= getCacheStart() && end+1 <= cacheEnd) + { + return end == -1 ? cache : getSubList(start-getCacheStart()+1, end-getCacheStart()+1, cache); + } + } + else + { + if (end >= cacheEnd || end <= 0) + { + end = cacheEnd; + } + return getSubList (start, end, cache); + } + } + + setCacheStart(getOverIntValue((long)start + 1 - (pageSize * numPagePreLoad))); + if (getCacheStart() <= 0) + setCacheStart(1); + + if (end == -1) + { + cacheEnd = m_count; + } + else + { + cacheEnd = getOverIntValue(end + 1 + (pageSize * numPagePreLoad)); + if (cacheEnd > m_count) + cacheEnd = m_count; + } + + cache = new ArrayList(); + + PreparedStatement m_pstmt = null; + ResultSet m_rs = null; + String dataSql = null; + + long startTime = System.currentTimeMillis(); + dataSql = info.getInfoSql(); + if (!Util.isEmpty(m_sqlUserOrder)) { + dataSql = dataSql + m_sqlUserOrder; + } + isHasNextPage = false; + if (log.isLoggable(Level.FINER)) + log.finer(dataSql); + Trx trx = null; + try + { + //https://jdbc.postgresql.org/documentation/head/query.html#query-with-cursor + String trxName = Trx.createTrxName("RelatedInfoLoad:"); + trx = Trx.get(trxName, true); + trx.setDisplayName(getClass().getName()+"_readLine"); + m_pstmt = DB.prepareStatement(dataSql, trxName); + Object linkPara = null; + if (parentId != null && parentId instanceof IDColumn){ + IDColumn ID = (IDColumn) parentId; + linkPara = ID.getRecord_ID(); + }else if (parentId != null){ + linkPara = parentId.toString(); + } + if (info.getTypeDataOfLink().equals(String.class)){ + m_pstmt.setString(1, (String)linkPara); + }else if (info.getTypeDataOfLink().equals(int.class)){ + m_pstmt.setInt(1, Integer.parseInt(linkPara.toString())); + + }else{ + m_pstmt.setObject(1, linkPara); + } + if (log.isLoggable(Level.FINE)) + log.fine("Start query - " + (System.currentTimeMillis()-startTime) + "ms"); + m_pstmt.setFetchSize(100); + m_rs = m_pstmt.executeQuery(); + if (log.isLoggable(Level.FINE)) + log.fine("End query - " + (System.currentTimeMillis()-startTime) + "ms"); + //skips the row that we dont need if we can't use native db paging + if (end > start && m_useDatabasePaging && !DB.getDatabase().isPagingSupported()) + { + for (int i = 0; i < getCacheStart() - 1; i++) + { + if (!m_rs.next()) + break; + } + } + + int rowPointer = getCacheStart()-1; + while (m_rs.next()) + { + rowPointer++; + cache.add(readData(m_rs)); + //check now of rows loaded, break if we hit the suppose end + if (m_useDatabasePaging && rowPointer >= cacheEnd) + { + isHasNextPage = true; + break; + } + } + } + + catch (SQLException e) + { + log.log(Level.SEVERE, dataSql, e); + } + + finally + { + DB.close(m_rs, m_pstmt); + if (trx != null) + trx.close(); + } + + if (end > cacheEnd || end <= 0) + { + end = cacheEnd; + } + validateEndPage (); + + if (end == -1) + { + return cache; + } + else + { + int fromIndex = start-getCacheStart()+1; + int toIndex = end-getCacheStart()+1; + return getSubList(fromIndex, toIndex, cache); + } + } + + private ArrayList readData(ResultSet rs) throws SQLException { + + int colOffset = 1; // columns start with 1 + ArrayList data = new ArrayList(); + for (int col = 0; col < columnsLayout.length; col++) + { + Object value = null; + Class c = columnsLayout[col].getColClass(); + int colIndex = col + colOffset; + if (c == IDColumn.class) + { + value = new IDColumn(rs.getInt(colIndex)); + } + else if (c == Boolean.class) + value = new Boolean("Y".equals(rs.getString(colIndex))); + else if (c == Timestamp.class) + value = rs.getTimestamp(colIndex); + else if (c == BigDecimal.class) + value = rs.getBigDecimal(colIndex); + else if (c == Double.class) + value = new Double(rs.getDouble(colIndex)); + else if (c == Integer.class) + value = new Integer(rs.getInt(colIndex)); + else if (c == KeyNamePair.class) + { + if (columnsLayout[col].isKeyPairCol()) + { + String display = rs.getString(colIndex); + int key = rs.getInt(colIndex+1); + if (! rs.wasNull()) { + value = new KeyNamePair(key, display); + } + colOffset++; + } + else + { + int key = rs.getInt(colIndex); + if (! rs.wasNull()) { + WEditor editor = editorMap.get(columnsLayout[col].getColSQL()); // rework this, it will fail + if (editor != null) + { + editor.setValue(key); + value = new KeyNamePair(key, editor.getDisplayTextForGridView(key)); + } + else + { + value = new KeyNamePair(key, Integer.toString(key)); + } + } + } + } + else if (c == ValueNamePair.class) + { + String key = rs.getString(colIndex); + WEditor editor = editorMap.get(columnsLayout[col].getColSQL()); + if (editor != null) + { + value = new ValueNamePair(key, editor.getDisplayTextForGridView(key)); + } + else + { + value = new ValueNamePair(key, key); + } + } + else + { + value = rs.getString(colIndex); + } + data.add(value); + } + + return data; + } + + @Override + public void sort(Comparator cmpr, boolean ascending) { + + WListItemRenderer.ColumnComparator lsc = (WListItemRenderer.ColumnComparator) cmpr; + if (m_useDatabasePaging) + { + int col = lsc.getColumnIndex(); + String colsql = columnsLayout[col].getColSQL().trim(); + int lastSpaceIdx = colsql.lastIndexOf(" "); + if (lastSpaceIdx > 0) + { + String tmp = colsql.substring(0, lastSpaceIdx).trim(); + char last = tmp.charAt(tmp.length() - 1); + if (tmp.toLowerCase().endsWith("as")) + { + colsql = colsql.substring(lastSpaceIdx).trim(); + } + else if (!(last == '*' || last == '-' || last == '+' || last == '/' || last == '>' || last == '<' || last == '=')) + { + tmp = colsql.substring(lastSpaceIdx).trim(); + if (tmp.startsWith("\"") && tmp.endsWith("\"")) + { + colsql = colsql.substring(lastSpaceIdx).trim(); + } + else + { + boolean hasAlias = true; + for(int i = 0; i < tmp.length(); i++) + { + char c = tmp.charAt(i); + if (Character.isLetterOrDigit(c)) + { + continue; + } + else + { + hasAlias = false; + break; + } + } + if (hasAlias) + { + colsql = colsql.substring(lastSpaceIdx).trim(); + } + } + } + } + m_sqlUserOrder = " ORDER BY " + colsql; + if (!ascending) + m_sqlUserOrder += " DESC "; + refresh(parentId); + } + else + { + Collections.sort(cache, lsc); + renderItems(); + } + } + + @Override + public String getSortDirection(Comparator cmpr) { + return "natural"; + } + + /** + * after query from database, process validate. + * if end page include in cache, process calculate total record + * if current page is out of page (no record is query) process query count to detect end page + */ + protected void validateEndPage (){ + if (paging == null || info.getInfowin().isLoadPageNum()) + return; + + if (!isHasNextPage){ + int pageSize = parentInfoWindow.getPageSize(); + int extraPage = ((cache.size() % pageSize > 0)?1:0); + int pageInCache = cache.size() / pageSize + extraPage; + + if (pageInCache == 0 || pageInCache <= numPagePreLoad){ + // selected page is out of page + testCount(); + extraPage = ((m_count % pageSize > 0)?1:0); + pageInCache = m_count / pageSize + extraPage; + // this one will set current page to end page + paging.setTotalSize(m_count); + if (m_count <= pageSize) + paging.setVisible(false); + Event pagingEvent = new PagingEvent("onPaging", paging, paging.getPageCount() - 1); + Events.postEvent(pagingEvent); + }else if (pageInCache > numPagePreLoad){ + // current page isn't end page. but page in cache has end page. + int prePage = pageNo - numPagePreLoad; + int readTotalRecord = (prePage > 0?prePage:0) * pageSize + cache.size(); + paging.setTotalSize(readTotalRecord); + m_count = readTotalRecord; + } + } + } +} 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 136ffb586a..b764513f7d 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 @@ -2285,5 +2285,9 @@ public abstract class InfoPanel extends Window implements EventListener, public void setGridfield(GridField m_gridfield) { this.m_gridfield = m_gridfield; } + + public int getPageSize() { + return pageSize; + } } // Info