/****************************************************************************** * Product: Posterita Ajax UI * * Copyright (C) 2007 Posterita Ltd. All Rights Reserved. * * 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. * * For the text or an alternative of this public license, you may reach us * * Posterita Ltd., 3, Draper Avenue, Quatre Bornes, Mauritius * * or via info@posterita.org or http://www.posterita.org/ * *****************************************************************************/ package org.adempiere.webui.editor; import java.beans.PropertyChangeEvent; import javax.swing.event.ListDataEvent; import javax.swing.event.ListDataListener; import org.adempiere.webui.ValuePreference; import org.adempiere.webui.apps.AEnv; import org.adempiere.webui.component.Combobox; 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.Lookup; import org.compiere.model.MRole; import org.compiere.util.CLogger; import org.compiere.util.DisplayType; import org.compiere.util.Env; import org.compiere.util.KeyNamePair; import org.compiere.util.NamePair; import org.compiere.util.ValueNamePair; import org.zkoss.zk.ui.event.Event; import org.zkoss.zk.ui.event.Events; import org.zkoss.zul.Comboitem; /** * * @author <a href="mailto:agramdass@gmail.com">Ashley G Ramdass</a> * @date Mar 12, 2007 * @version $Revision: 0.10 $ */ public class WTableDirEditor extends WEditor implements ListDataListener, ContextMenuListener, IZoomableEditor { public final static String[] LISTENER_EVENTS = {Events.ON_SELECT}; @SuppressWarnings("unused") private static final CLogger logger; static { logger = CLogger.getCLogger(WTableDirEditor.class); } private Lookup lookup; private Object oldValue; private WEditorPopupMenu popupMenu; public WTableDirEditor(GridField gridField) { super(new Combobox(), gridField); lookup = gridField.getLookup(); init(); } /** * Constructor for use if a grid field is unavailable * * @param lookup Store of selectable data * @param label column name (not displayed) * @param description description of component * @param mandatory whether a selection must be made * @param readonly whether or not the editor is read only * @param updateable whether the editor contents can be changed */ public WTableDirEditor(Lookup lookup, String label, String description, boolean mandatory, boolean readonly, boolean updateable) { super(new Combobox(), label, description, mandatory, readonly, updateable); if (lookup == null) { throw new IllegalArgumentException("Lookup cannot be null"); } this.lookup = lookup; super.setColumnName(lookup.getColumnName()); init(); } /** * For ease of porting swing form * @param columnName * @param mandatory * @param isReadOnly * @param isUpdateable * @param lookup */ public WTableDirEditor(String columnName, boolean mandatory, boolean isReadOnly, boolean isUpdateable, Lookup lookup) { super(new Combobox(), columnName, null, null, mandatory, isReadOnly, isUpdateable); if (lookup == null) { throw new IllegalArgumentException("Lookup cannot be null"); } this.lookup = lookup; init(); } private void init() { getComponent().setWidth("200px"); getComponent().setAutocomplete(true); getComponent().setAutodrop(true); getComponent().addEventListener(Events.ON_BLUR, this); boolean zoom= false; if (lookup != null) { lookup.addListDataListener(this); //always need the empty item for zk to work correctly lookup.setMandatory(false); if ((lookup.getDisplayType() == DisplayType.List && Env.getContextAsInt(Env.getCtx(), "#AD_Role_ID") == 0) || lookup.getDisplayType() != DisplayType.List) { zoom= true; } //no need to refresh readonly lookup if (isReadWrite()) lookup.refresh(); refreshList(); } if (gridField != null) { popupMenu = new WEditorPopupMenu(zoom, true, true); if (gridField != null && gridField.getGridTab() != null) { WFieldRecordInfo.addMenu(popupMenu); } getComponent().setContext(popupMenu.getId()); } } @Override public String getDisplay() { String display = null; Comboitem selItem = getComponent().getSelectedItem(); if (selItem != null) { display = selItem.getLabel(); } return display; } @Override public Object getValue() { Object retVal = null; Comboitem selItem = getComponent().getSelectedItem(); if (selItem != null) { retVal = selItem.getValue(); if ((retVal instanceof Integer) && (Integer)retVal == -1) retVal = null; } return retVal; } public void setValue(Object value) { if (value != null && (value instanceof Integer || value instanceof String)) { getComponent().setValue(value); if (!getComponent().isSelected(value)) { if (isReadWrite() && lookup != null) lookup.refresh(); Object curValue = oldValue; oldValue = value; refreshList(); //still not in list, reset to zero if (!getComponent().isSelected(value)) { if (value instanceof Integer && gridField.getDisplayType() != DisplayType.ID) // for IDs is ok to be out of the list { getComponent().setValue(null); if (curValue == null) curValue = value; ValueChangeEvent changeEvent = new ValueChangeEvent(this, this.getColumnName(), curValue, null); super.fireValueChange(changeEvent); oldValue = null; } } } else { oldValue = value; } } else { getComponent().setValue(null); oldValue = value; } } @Override public Combobox getComponent() { return (Combobox) component; } @Override public boolean isReadWrite() { return getComponent().isEnabled(); } @Override public void setReadWrite(boolean readWrite) { getComponent().setEnabled(readWrite); } private void refreshList() { if (getComponent().getItemCount() > 0) getComponent().removeAllItems(); if (isReadWrite()) { if (lookup != null) { int size = lookup.getSize(); boolean found = false; for (int i = 0; i < size; i++) { Object obj = lookup.getElementAt(i); if (obj instanceof KeyNamePair) { KeyNamePair lookupKNPair = (KeyNamePair) obj; getComponent().appendItem(lookupKNPair.getName(), lookupKNPair.getKey()); if (!found && oldValue != null && oldValue instanceof Integer && lookupKNPair.getKey() == (Integer)oldValue) { found = true; } } else if (obj instanceof ValueNamePair) { ValueNamePair lookupKNPair = (ValueNamePair) obj; getComponent().appendItem(lookupKNPair.getName(), lookupKNPair.getValue()); if (!found && oldValue != null && lookupKNPair.getValue().equals(oldValue.toString())) { found = true; } } } if (!found && oldValue != null) { NamePair pair = lookup.getDirect(oldValue, false, false); if (pair != null) { if (pair instanceof KeyNamePair) { int key = ((KeyNamePair)pair).getKey(); getComponent().appendItem(pair.getName(), key); } else if (pair instanceof ValueNamePair) { ValueNamePair valueNamePair = (ValueNamePair) pair; getComponent().appendItem(valueNamePair.getName(), valueNamePair.getValue()); } } } } } else { if (lookup != null) { NamePair pair = lookup.getDirect(oldValue, false, false); if (pair != null) { if (pair instanceof KeyNamePair) { int key = ((KeyNamePair)pair).getKey(); getComponent().appendItem(pair.getName(), key); } else if (pair instanceof ValueNamePair) { ValueNamePair valueNamePair = (ValueNamePair) pair; getComponent().appendItem(valueNamePair.getName(), valueNamePair.getValue()); } } } } getComponent().setValue(oldValue); } public void onEvent(Event event) { if (Events.ON_SELECT.equalsIgnoreCase(event.getName())) { Object newValue = getValue(); if (isValueChange(newValue)) { ValueChangeEvent changeEvent = new ValueChangeEvent(this, this.getColumnName(), oldValue, newValue); super.fireValueChange(changeEvent); oldValue = newValue; } } else if (Events.ON_BLUR.equalsIgnoreCase(event.getName())) { Comboitem item = getComponent().getSelectedItem(); if (item == null) { setValue(oldValue); } else { //on select not fire for empty label item if (item.getLabel().equals("")) { Object newValue = getValue(); if (isValueChange(newValue)) { ValueChangeEvent changeEvent = new ValueChangeEvent(this, this.getColumnName(), oldValue, newValue); super.fireValueChange(changeEvent); oldValue = newValue; } } } } } private boolean isValueChange(Object newValue) { return (oldValue == null && newValue != null) || (oldValue != null && newValue == null) || ((oldValue != null && newValue != null) && !oldValue.equals(newValue)); } public String[] getEvents() { return LISTENER_EVENTS; } public void contentsChanged(ListDataEvent e) { refreshList(); } public void intervalAdded(ListDataEvent e) {} public void intervalRemoved(ListDataEvent e) {} public WEditorPopupMenu getPopupMenu() { return popupMenu; } public void actionRefresh() { if (lookup != null) { Object curValue = getValue(); if (isReadWrite()) lookup.refresh(); refreshList(); if (curValue != null) { setValue(curValue); } } } /* (non-Javadoc) * @see org.adempiere.webui.editor.IZoomableEditor#actionZoom() */ public void actionZoom() { AEnv.actionZoom(lookup, getValue()); } public void onMenu(ContextMenuEvent evt) { if (WEditorPopupMenu.REQUERY_EVENT.equals(evt.getContextEvent())) { actionRefresh(); } else if (WEditorPopupMenu.ZOOM_EVENT.equals(evt.getContextEvent())) { actionZoom(); } else if (WEditorPopupMenu.PREFERENCE_EVENT.equals(evt.getContextEvent())) { if (MRole.getDefault().isShowPreference()) ValuePreference.start (this.getGridField(), getValue()); return; } else if (WEditorPopupMenu.CHANGE_LOG_EVENT.equals(evt.getContextEvent())) { WFieldRecordInfo.start(gridField); } } public void propertyChange(PropertyChangeEvent evt) { if ("FieldValue".equals(evt.getPropertyName())) { setValue(evt.getNewValue()); } } @Override public void dynamicDisplay() { if ((lookup != null) && (!lookup.isValidated() || !lookup.isLoaded())) this.actionRefresh(); } }