/****************************************************************************** * 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.component; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.swing.table.AbstractTableModel; import org.adempiere.webui.LayoutUtils; import org.adempiere.webui.editor.WEditor; 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.zkoss.zk.ui.event.Event; import org.zkoss.zk.ui.event.EventListener; import org.zkoss.zk.ui.event.Events; import org.zkoss.zkex.zul.Borderlayout; import org.zkoss.zkex.zul.Center; import org.zkoss.zkex.zul.South; import org.zkoss.zul.Paging; import org.zkoss.zul.event.ZulEvents; /** * Grid view implemented using the Listbox component * @author Low Heng Sin * */ public class ListPanel 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 GridTableListModel listModel; private Paging paging; private GridTabListItemRenderer renderer; private South south; public static final String PAGE_SIZE_KEY = "ZK_PAGING_SIZE"; public ListPanel() { this(0); } /** * @param windowNo */ public ListPanel(int windowNo) { this.windowNo = windowNo; listbox = new Listbox(); south = new South(); this.appendChild(south); //default paging size pageSize = MSysConfig.getIntValue(PAGE_SIZE_KEY, 100); } /** * * @param gridTab */ public void init(GridTab gridTab) { if (init) return; this.gridTab = gridTab; tableModel = gridTab.getTableModel(); numColumns = tableModel.getColumnCount(); gridField = ((GridTable)tableModel).getFields(); setupColumns(); render(); updateListIndex(true); this.init = true; } /** * * @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 { if (renderer != null) renderer.stopEditing(false); int oldSelected = listbox.getSelectedIndex(); updateListIndex(false); if (listbox.getSelectedIndex() == oldSelected && oldSelected >= 0) listModel.updateComponent(oldSelected); } } else init(gridTab); } /** * * @param gridTab */ public void refresh(GridTab gridTab) { if (this.gridTab != gridTab) { init = false; init(gridTab); } else { renderer.stopEditing(false); listbox.setModel(listModel); updateListIndex(true); } } /** * Update listbox selection to sync with grid current row pointer changes */ public void updateListIndex() { updateListIndex(false); } /** * Update listbox selection to sync with grid current row pointer changes * @param updateSelectionOnly if true, doesn't attempt to refresh current row from model */ public void updateListIndex(boolean updateSelectionOnly) { int rowIndex = gridTab.isOpen() ? gridTab.getCurrentRow() : -1; if (pageSize > 0) { if (paging.getTotalSize() != gridTab.getRowCount()) paging.setTotalSize(gridTab.getRowCount()); int pgIndex = rowIndex % pageSize; int pgNo = (rowIndex - pgIndex) / pageSize; boolean pgChange = false; if (listModel.getPage() != pgNo) { listModel.setPage(pgNo); pgChange = true; } if (paging.getActivePage() != pgNo) { paging.setActivePage(pgNo); } if (listbox.getSelectedIndex() != pgIndex) { if (!updateSelectionOnly) { renderer.stopEditing(false); if (!pgChange) { listModel.updateComponent(listbox.getSelectedIndex()); } listModel.updateComponent(pgIndex); } listbox.setSelectedIndex(pgIndex); } } else { if (listbox.getSelectedIndex() != rowIndex) { if (!updateSelectionOnly) { renderer.stopEditing(false); listModel.updateComponent(listbox.getSelectedIndex()); listModel.updateComponent(rowIndex); } listbox.setSelectedIndex(rowIndex); } } } /** * Set paging size * @param pageSize */ public void setPageSize(int pageSize) { this.pageSize = pageSize; } public void clear() { this.getChildren().clear(); } /** * * @param bool */ public void showGrid(boolean bool) { if (bool) this.setVisible(true); else this.setVisible(false); } private void setupColumns() { if (init) return; ListHead header = new ListHead(); header.setSizable(true); Map<Integer, String> colnames = new HashMap<Integer, String>(); int index = 0; for (int i = 0; i < numColumns; i++) { if (gridField[i].isDisplayed()) { colnames.put(index, gridField[i].getHeader()); index++; ListHeader colHeader = new ListHeader(); colHeader.setSort("auto"); colHeader.setLabel(gridField[i].getHeader()); 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() { LayoutUtils.addSclass("adtab-grid-panel", this); listbox.setVflex(true); listbox.setFixedLayout(true); listbox.addEventListener(Events.ON_SELECT, this); LayoutUtils.addSclass("adtab-grid", listbox); updateModel(); Center center = new Center(); center.appendChild(listbox); this.appendChild(center); if (pageSize > 0) { paging = new Paging(); paging.setPageSize(pageSize); paging.setTotalSize(tableModel.getRowCount()); paging.setDetailed(true); south.appendChild(paging); paging.addEventListener(ZulEvents.ON_PAGING, this); renderer.setPaging(paging); this.getParent().invalidate(); } else { south.setVisible(false); } } private void updateModel() { listModel = new GridTableListModel((GridTable)tableModel, windowNo); listModel.setPageSize(pageSize); if (renderer != null) renderer.stopEditing(false); renderer = new GridTabListItemRenderer(gridTab, windowNo); listbox.setItemRenderer(renderer); listbox.setModel(listModel); } /** * deactive panel */ public void deactivate() { if (renderer != null) renderer.stopEditing(false); } public void onEvent(Event event) throws Exception { if (event == null) return; else if (event.getTarget() == listbox) { int index = listbox.getSelectedIndex(); onSelectedRowChange(index); } else if (event.getTarget() == paging) { int pgNo = paging.getActivePage(); if (pgNo != listModel.getPage()) { listbox.clearSelection(); listModel.setPage(pgNo); listbox.setSelectedIndex(0); onSelectedRowChange(0); } } } private void onSelectedRowChange(int index) { if (updateModelIndex()) { listModel.updateComponent(index); listbox.setSelectedIndex(index); } else if (!renderer.isInitialize()) { listModel.updateComponent(index); listbox.setSelectedIndex(index); } } private boolean updateModelIndex() { int rowIndex = listbox.getSelectedIndex(); if (pageSize > 0) { int start = listModel.getPage() * listModel.getPageSize(); rowIndex = start + rowIndex; } if (gridTab.getCurrentRow() != rowIndex) { renderer.stopEditing(true); gridTab.navigate(rowIndex); return true; } return false; } /** * * @return Listbox */ public Listbox getListbox() { return listbox; } /** * validate the display properties of fields of current row * @param col */ public void dynamicDisplay(int col) { if (!gridTab.isOpen()) { return; } // Selective if (col > 0) return; boolean noData = gridTab.getRowCount() == 0; List<WEditor> list = renderer.getEditors(); for (WEditor comp : list) { GridField mField = comp.getGridField(); if (mField != null && mField.getIncluded_Tab_ID() <= 0) { if (noData) { comp.setReadWrite(false); } else { comp.dynamicDisplay(); boolean rw = mField.isEditable(true); // r/w - check Context comp.setReadWrite(rw); } } } // all components } /** * * @param windowNo */ public void setWindowNo(int windowNo) { this.windowNo = windowNo; } }