gt: 			if (lookupCache != null)
context: /******************************************************************************
   * 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.sql.Timestamp;
  import java.text.SimpleDateFormat;
  import java.util.ArrayList;
  import java.util.HashMap;
  import java.util.List;
  import java.util.Map;
  import java.util.Map.Entry;
  
  import org.adempiere.webui.editor.WButtonEditor;
  import org.adempiere.webui.editor.WEditor;
  import org.adempiere.webui.editor.WEditorPopupMenu;
  import org.adempiere.webui.editor.WebEditorFactory;
  import org.adempiere.webui.event.ContextMenuListener;
  import org.adempiere.webui.panel.AbstractADWindowPanel;
  import org.adempiere.webui.session.SessionManager;
  import org.adempiere.webui.util.GridTabDataBinder;
  import org.adempiere.webui.window.ADWindow;
  import org.compiere.model.GridField;
  import org.compiere.model.GridTab;
  import org.compiere.util.DisplayType;
  import org.compiere.util.NamePair;
  import org.zkoss.zk.ui.Component;
  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.Image;
  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.Paging;
  import org.zkoss.zul.RendererCtrl;
  
  /**
   * ListItem renderer for GridTab list box.
   * @author hengsin
   *
   */
  public class GridTabListItemRenderer implements ListitemRenderer, ListitemRendererExt, RendererCtrl {
  
  	private static final int MAX_TEXT_LENGTH = 60;
  	private GridTab gridTab;
  	private int windowNo;
  	private GridTabDataBinder dataBinder;
  	private Map<GridField, WEditor> editors = new HashMap<GridField, WEditor>();
  	private Paging paging;
  
  	/**
  	 * 
  	 * @param gridTab
  	 * @param windowNo
  	 */
  	public GridTabListItemRenderer(GridTab gridTab, int windowNo) {
  		this.gridTab = gridTab;
  		this.windowNo = windowNo;
  		this.dataBinder = new GridTabDataBinder(gridTab);
  	}
  	
  	/**
  	 * @param listitem
  	 * @param data
  	 * @see ListitemRenderer#render(Listitem, Object)
  	 */
  	public void render(Listitem listitem, Object data) throws Exception {
  		//don't render if not visible
  		for(Component c = listitem.getParent(); c != null; c = c.getParent()) {
  			if (!c.isVisible())
  				return;
  		}
  		Object[] values = (Object[])data;
  		int columnCount = gridTab.getTableModel().getColumnCount();
  		GridField[] gridField = gridTab.getFields();
  		for (int i = 0; i < columnCount; i++) {
  			if (!gridField[i].isDisplayed()) {
  				continue;
  			}
  			if (editors.get(gridField[i]) == null)
  				editors.put(gridField[i], WebEditorFactory.getEditor(gridField[i], true));
  			
  			int rowIndex = listitem.getIndex();			
  			if (paging != null && paging.getPageSize() > 0) {
  				rowIndex = (paging.getActivePage() * paging.getPageSize()) + rowIndex;
  			}
  			Listcell cell = null;
  			if (rowIndex == gridTab.getCurrentRow() && gridField[i].isEditable(true)) {
  				cell = getEditorCell(gridField[i], values[i], i);
  				cell.setParent(listitem);
  			} else {
  				if (gridField[i].getDisplayType() == DisplayType.YesNo) {
  					cell = new Listcell("", null);
  					cell.setParent(listitem);
  					cell.setStyle("text-align:center");
  					createReadonlyCheckbox(values[i], cell);
  				} else {
  					String text = getDisplayText(values[i], i);
  					String display = text;
  					if (text != null && text.length() > MAX_TEXT_LENGTH)
  						display = text.substring(0, MAX_TEXT_LENGTH - 3) + "...";
  					cell = new Listcell(display, null);
  					cell.setParent(listitem);
  					if (text != null && text.length() > MAX_TEXT_LENGTH)
  						cell.setTooltiptext(text);
  					if (DisplayType.isNumeric(gridField[i].getDisplayType())) {
  						cell.setStyle("text-align:right");
  					} else if (gridField[i].getDisplayType() == DisplayType.Image) {
  						cell.setStyle("text-align:center");
  					}
  				}
  			}
  			CellListener listener = new CellListener((Listbox) listitem.getParent());
  			cell.addEventListener(Events.ON_DOUBLE_CLICK, listener);
  		}
  	}
  
  	private void createReadonlyCheckbox(Object value, Listcell cell) {
  		Checkbox checkBox = new Checkbox();
  		if (value != null && "true".equalsIgnoreCase(value.toString()))
  			checkBox.setChecked(true);
  		else
  			checkBox.setChecked(false);
  		checkBox.setDisabled(true);
  		checkBox.setParent(cell);
  	}
  
  	private Listcell getEditorCell(GridField gridField, Object object, int i) {
  		Listcell cell = new Listcell("", null);
  		WEditor editor = editors.get(gridField);
  		if (editor != null)  {
  			if (editor instanceof WButtonEditor)
              {
  				Object window = SessionManager.getAppDesktop().findWindow(windowNo);
              	if (window != null && window instanceof ADWindow)
              	{
              		AbstractADWindowPanel windowPanel = ((ADWindow)window).getADWindowPanel();
              		((WButtonEditor)editor).addActionListener(windowPanel);
              	}            		
              }
  			else
  			{
  				editor.addValueChangeListener(dataBinder);
  			}
  			cell.appendChild(editor.getComponent());
  			if (editor.getComponent() instanceof Checkbox || editor.getComponent() instanceof Image) {
  				cell.setStyle("text-align:center");
  			}
  			else if (DisplayType.isNumeric(gridField.getDisplayType())) {
  				cell.setStyle("text-align:right");
  			}
  			gridField.addPropertyChangeListener(editor);
  			editor.setValue(gridField.getValue());
  			WEditorPopupMenu popupMenu = editor.getPopupMenu();
              
              if (popupMenu != null)
              {
              	popupMenu.addMenuListener((ContextMenuListener)editor);
              	cell.appendChild(popupMenu);
              }
              
              //streach component to fill grid cell
              editor.fillHorizontal();
  		}
  		
  		return cell;
  	}
  	
  	/**
  	 * Detach all editor and optionally set the current value of the editor as cell label.
  	 * @param updateCellLabel
  	 */
  	public void stopEditing(boolean updateCellLabel) {
  		for (Entry<GridField, WEditor> entry : editors.entrySet()) {
  			if (entry.getValue().getComponent().getParent() != null) {
  				if (updateCellLabel) {
  					Listcell cell = (Listcell) entry.getValue().getComponent().getParent();
  					if (entry.getKey().getDisplayType() == DisplayType.YesNo) {
  						cell.setLabel("");
  						createReadonlyCheckbox(entry.getValue().getValue(), cell);
  					} else {				
  						cell.setLabel(getDisplayText(entry.getValue().getValue(), getColumnIndex(entry.getKey())));
  					}
  				}
  				entry.getValue().getComponent().detach();
  				entry.getKey().removePropertyChangeListener(entry.getValue());
  				entry.getValue().removeValuechangeListener(dataBinder);
  			}
  		}
  	}
  
  	private int getColumnIndex(GridField field) {
  		GridField[] fields = gridTab.getFields();
  		for(int i = 0; i < fields.length; i++) {
  			if (fields[i] == field)
  				return i;
  		}
  		return 0;
  	}
  
  	/**
  	 * @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 Map<Integer, Map<Object, String>> lookupCache = null;
  	
  	private String getDisplayText(Object value, int columnIndex)
  	{
  		if (value == null)
  			return "";
  		
  		GridField[] gridField = gridTab.getFields();
  		if (gridField[columnIndex].isEncryptedField())
  		{
  			return "********";
  		}
  		else if (gridField[columnIndex].isLookup())
      	{
  			if (value == null) return "";
  			
  