org.zkoss.zul.Selectbox Maven / Gradle / Ivy
/* Selectbox.java
Purpose:
Description:
History:
Fri Sep 30 10:53:25 TST 2011, Created by jumperchen
Copyright (C) 2011 Potix Corporation. All Rights Reserved.
{{IS_RIGHT
This program is distributed under LGPL Version 3.0 in the hope that
it will be useful, but WITHOUT ANY WARRANTY.
}}IS_RIGHT
*/
package org.zkoss.zul;
import java.util.LinkedHashSet;
import java.util.Set;
import org.zkoss.lang.Classes;
import org.zkoss.lang.Objects;
import org.zkoss.xel.VariableResolver;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.HtmlBasedComponent;
import org.zkoss.zk.ui.Page;
import org.zkoss.zk.ui.UiException;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zk.ui.event.SelectEvent;
import org.zkoss.zk.ui.sys.ShadowElementsCtrl;
import org.zkoss.zk.ui.util.ComponentCloneListener;
import org.zkoss.zk.ui.util.ForEachStatus;
import org.zkoss.zk.ui.util.Template;
import org.zkoss.zul.event.ListDataEvent;
import org.zkoss.zul.event.ListDataListener;
import org.zkoss.zul.ext.Selectable;
/**
* A light weight dropdown list.
*
* Default {@link #getZclass}: z-selectbox. It does not create child widgets for
* each data, so the memory usage is much lower at the server. However, the
* implementation is based on HTML SELECT and OPTION tags, so the functionality
* is not as rich as {@link Listbox}.
*
* @author jumperchen
* @since 6.0.0
*/
@SuppressWarnings("serial")
public class Selectbox extends HtmlBasedComponent {
private String _name;
private boolean _disabled;
private int _jsel = -1;
private transient ListModel> _model;
private transient ListDataListener _dataListener;
private transient ItemRenderer> _renderer;
private static final String ATTR_ON_INIT_RENDER_POSTED = "org.zkoss.zul.onInitLaterPosted";
private transient boolean _childable;
private transient String[] _tmpdatas;
static {
addClientEvent(Selectbox.class, Events.ON_SELECT, CE_DUPLICATE_IGNORE | CE_IMPORTANT);
addClientEvent(Selectbox.class, Events.ON_FOCUS, CE_DUPLICATE_IGNORE);
addClientEvent(Selectbox.class, Events.ON_BLUR, CE_DUPLICATE_IGNORE);
}
public String getZclass() {
return _zclass == null ? "z-selectbox" : _zclass;
}
/**
* Returns the index of the selected item (-1 if no one is selected).
*/
public int getSelectedIndex() {
return _jsel;
}
/**
* Selects the item with the given index.
*/
public void setSelectedIndex(int jsel) {
if (jsel < -1)
jsel = -1;
if (jsel != _jsel) {
_jsel = jsel;
smartUpdate("selectedIndex", jsel);
}
}
/**
* Returns the renderer to render each item, or null if the default renderer
* is used.
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public ItemRenderer getItemRenderer() {
return (ItemRenderer) _renderer;
}
/**
* Sets the renderer which is used to render each item if {@link #getModel}
* is not null.
*
*
* Note: changing a render will not cause the selectbox to re-render. If you
* want it to re-render, you could assign the same model again (i.e.,
* setModel(null) and than setModel(oldModel)), or fire an {@link ListDataEvent} event.
*
* @param renderer
* the renderer, or null to use the default.
* @exception UiException
* if failed to initialize with the model
*/
public void setItemRenderer(ItemRenderer> renderer) {
if (_renderer != renderer) {
_renderer = renderer;
postOnInitRender(); // Bug ZK-2607
invalidate();
}
}
/**
* Sets the renderer by use of a class name. It creates an instance
* automatically.
*/
@SuppressWarnings("rawtypes")
public void setItemRenderer(String clsnm) throws ClassNotFoundException, NoSuchMethodException,
IllegalAccessException, InstantiationException, java.lang.reflect.InvocationTargetException {
if (clsnm != null)
setItemRenderer((ItemRenderer) Classes.newInstanceByThread(clsnm));
}
/**
* Returns whether it is disabled.
*
* Default: false.
*/
public boolean isDisabled() {
return _disabled;
}
protected boolean isChildable() {
return _childable;
}
/**
* Sets whether it is disabled.
*/
public void setDisabled(boolean disabled) {
if (_disabled != disabled) {
_disabled = disabled;
smartUpdate("disabled", _disabled);
}
}
/**
* Returns the name of this component.
*
* Default: null.
*
* The name is used only to work with "legacy" Web application that handles
* user's request by servlets. It works only with HTTP/HTML-based browsers.
* It doesn't work with other kind of clients.
*
* Don't use this method if your application is purely based on ZK's
* event-driven model.
*/
public String getName() {
return _name;
}
/**
* Sets the name of this component.
*
* The name is used only to work with "legacy" Web application that handles
* user's request by servlets. It works only with HTTP/HTML-based browsers.
* It doesn't work with other kind of clients.
*
* Don't use this method if your application is purely based on ZK's
* event-driven model.
*
* @param name
* the name of this component.
*/
public void setName(String name) {
if (name != null && name.length() == 0)
name = null;
if (!Objects.equals(_name, name)) {
_name = name;
smartUpdate("name", name);
}
}
private void initDataListener() {
if (_dataListener == null)
_dataListener = new ListDataListener() {
public void onChange(ListDataEvent event) {
switch (event.getType()) {
case ListDataEvent.SELECTION_CHANGED:
doSelectionChanged();
return; //nothing changed so need to rerender
case ListDataEvent.MULTIPLE_CHANGED:
return; //nothing to do
}
postOnInitRender();
}
};
_model.addListDataListener(_dataListener);
}
private void doSelectionChanged() {
final Selectable