
org.gwt.advanced.client.ui.widget.ComboBox Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of advanced-gwt Show documentation
Show all versions of advanced-gwt Show documentation
The set of useful GWT components
/*
* Copyright 2008-2012 Sergey Skladchikov
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.gwt.advanced.client.ui.widget;
import com.google.gwt.dom.client.EventTarget;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.event.dom.client.*;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.ToggleButton;
import com.google.gwt.user.client.ui.Widget;
import org.gwt.advanced.client.datamodel.ComboBoxDataModel;
import org.gwt.advanced.client.datamodel.ListDataModel;
import org.gwt.advanced.client.datamodel.ListModelEvent;
import org.gwt.advanced.client.datamodel.ListModelListener;
import org.gwt.advanced.client.ui.widget.combo.ComboBoxChangeEvent;
import org.gwt.advanced.client.ui.widget.combo.DefaultListItemFactory;
import org.gwt.advanced.client.ui.widget.combo.DropDownPosition;
import org.gwt.advanced.client.ui.widget.combo.ListItemFactory;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* This is a combo box widget implementation.
*
* @author Sergey Skladchikov
* @since 1.2.0
*/
public class ComboBox extends TextButtonPanel
implements HasAllFocusHandlers, HasAllKeyHandlers, HasClickHandlers, ListModelListener, HasChangeHandlers {
/** a combo box data model */
private ListDataModel model;
/** a list item factory */
private ListItemFactory listItemFactory;
/** a list popup panel */
private ListPopupPanel listPanel;
/** a combo box delegate listener */
private DelegateHandler delegateHandler;
/** a keyboard events listener that switches off default browser handling and replaces it with conponents' */
private ComboBoxKeyboardManager keyboardManager;
/** a flag that is true
if any control key is pressed */
private boolean keyPressed;
/**
* Setter for property 'model'.
*
* @param model Value to set for property 'model'.
*/
public void setModel(T model) {
if (model != null && this.model != model) {
if (this.model != null)
this.model.removeListModelListener(this);
this.model = model;
this.model.addListModelListener(this);
prepareSelectedValue();
}
}
/**
* Setter for property 'listItemFactory'.
*
* @param listItemFactory Value to set for property 'listItemFactory'.
*/
public void setListItemFactory(ListItemFactory listItemFactory) {
if (listItemFactory != null)
this.listItemFactory = listItemFactory;
if (isListPanelOpened())
getListPanel().prepareList();
}
@Override
public HandlerRegistration addBlurHandler(BlurHandler handler) {
return addHandler(handler, BlurEvent.getType());
}
@Override
public HandlerRegistration addFocusHandler(FocusHandler handler) {
return addHandler(handler, FocusEvent.getType());
}
@Override
public HandlerRegistration addKeyUpHandler(KeyUpHandler handler) {
return addHandler(handler, KeyUpEvent.getType());
}
@Override
public HandlerRegistration addKeyDownHandler(KeyDownHandler handler) {
return addHandler(handler, KeyDownEvent.getType());
}
@Override
public HandlerRegistration addKeyPressHandler(KeyPressHandler handler) {
return addHandler(handler, KeyPressEvent.getType());
}
/**
* Note that handlers added by this method will receive
* {@link org.gwt.advanced.client.ui.widget.combo.ComboBoxChangeEvent}s.
*
* @param handler the change handler
* @return a handler registration.
*/
@Override
public HandlerRegistration addChangeHandler(ChangeHandler handler) {
return addHandler(handler, ChangeEvent.getType());
}
@Override
public HandlerRegistration addClickHandler(ClickHandler handler) {
return addHandler(handler, ClickEvent.getType());
}
/**
* Getter for property 'model'.
*
* @return Value for property 'model'.
*/
public ListDataModel getModel() {
if (model == null) {
model = new ComboBoxDataModel();
model.addListModelListener(this);
}
return model;
}
/**
* Getter for property 'listItemFactory'.
*
* @return Value for property 'listItemFactory'.
*/
public ListItemFactory getListItemFactory() {
if (listItemFactory == null)
listItemFactory = new DefaultListItemFactory();
return listItemFactory;
}
/**
* This method sets focus on this widget.
* But note that the combo box is not a focus event sourcer. It siply delegtes this functionality
* to the text box.
*
* @param focus is a flag of focus.
*/
public void setFocus(boolean focus) {
if (isCustomTextAllowed())
getSelectedValue().setFocus(focus);
else
getChoiceButton().setFocus(focus);
}
/**
* This method check the list panel status.
*
* @return true
if it's opened.
*/
public boolean isListPanelOpened() {
return !getListPanel().isHidden();
}
/**
* This method returns a value currently displayed in the text box.
*
* @return a text value.
*/
public String getText() {
return getSelectedValue().getText();
}
/**
* Gets a number of visible rows.
* Values <= 0 interpreted as undefined.
*
* @return a visible rows to be displayed without scrolling.
*/
public int getVisibleRows() {
return getListPanel().getVisibleRows();
}
/**
* Sets visible rows number.
* You can pass a value <= 0. It will mean that this parameter in undefined.
*
* @param visibleRows is a number of rows to be displayed without scrolling.
*/
public void setVisibleRows(int visibleRows) {
getListPanel().setVisibleRows(visibleRows);
}
/**
* Sets an item index that must be displayed on top.
* If the item is outside the currently visible area the list will be scrolled down
* to this item.
*
* @param index is an index of the item that must be displayed on top of the visible area.
*/
public void setStartItemIndex(int index) {
getListPanel().setStartItemIndex(index);
}
public int getStartItemIndex() {
return getListPanel().getStartItemIndex();
}
/**
* Sets text to the selected value box but doesn't change anything
* in the list of items.
*
* @param text is a text to set.
*/
public void setText(String text) {
getSelectedValue().setText(text);
}
/**
* This method returns a selected item.
*
* @return is a selected item.
*/
public Object getSelected() {
return getModel().getSelected();
}
/**
* This method returns a selected item index.
*
* @return is a selected item index.
*/
public int getSelectedIndex() {
return getModel().getSelectedIndex();
}
/**
* This method returns a selected item ID.
*
* @return is a selected item ID.
*/
public String getSelectedId() {
return getModel().getSelectedId();
}
/**
* This method sets the selected item ID.
*
* @param id is an item ID to select.
*/
public void setSelectedId(String id) {
getModel().setSelectedId(id);
}
/**
* This method sets the selected item index.
*
* @param index a selected item index.
*/
public void setSelectedIndex(int index) {
getModel().setSelectedIndex(index);
}
/**
* Opens / closes list popup panel by request.
*
* @param opened true
means "show".
*/
public void setListPopupOpened(boolean opened) {
if (opened)
getListPanel().show();
else
getListPanel().hide();
}
/**
* This method gets a widget that is currently selected in the drop down list.
*
* @return null
if the drop down list is collapsed.
*/
public Widget getSelectedWidget() {
if (isListPanelOpened() && getModel().getSelectedIndex() >= 0) {
FlowPanel list = getListPanel().getList();
if (list.getWidgetCount() > getModel().getSelectedIndex())
return list.getWidget(getModel().getSelectedIndex());
return null;
} else {
return null;
}
}
/** {@inheritDoc} */
public void cleanSelection() {
super.cleanSelection();
getModel().clear();
}
/**
* Gets a highlight row number.
* Note that sometimes this value is not equal to the selected row.
*
* @return a highlight row number or -1
if nothing is highlight.
*/
public int getHighlightRow() {
return getListPanel().getHighlightRow();
}
/**
* Sets a highlight row number and display the row as selected but not actually
* select it.
*
* @param row is a row number to highlight. If it's out of range thus method does nothing.
*/
public void setHighlightRow(int row) {
getListPanel().setHighlightRow(row);
}
/**
* This method gets an actual number of items displayed in the drop down.
*
* @return an item count.
*/
public int getItemCount() {
return getListPanel().getItemCount();
}
/**
* Gets an item by its index
* If index < 0 or index >= {@link #getItemCount()} it throws an exception.
*
* @param index is an index of the item to get.
* @return a foudn item.
* @throws IndexOutOfBoundsException if index is invalid.
*/
public Widget getItem(int index) {
return getListPanel().getItem(index);
}
/**
* Gets an item index if it's displayed in the drop down list.
* Otherwise returns -1
.
*
* @param item an item that is required to return.
* @return an item index value or -1
.
*/
public int getItemIndex(Widget item) {
return getListPanel().getItemIndex(item);
}
/**
* This method shows the drop down list.
*
* @param prepareList forces the list to be prepared (refreshed) before displaying.
*/
public void showList(boolean prepareList) {
getListPanel().show();
if (prepareList)
getListPanel().prepareList();
if (getItemCount() <= 0)
getListPanel().hide();
}
/**
* Moves the cursor up or down.
*
* @param step is a number of items relative to the current cursor position.
*/
public void moveCursor(int step) {
int row = getListPanel().getHighlightRow();
if (step == 0 || row + step < 0 || row + step >= getItemCount())
return;
row += step;
if (row != getListPanel().getHighlightRow()) {
if (row >= getModel().getCount())
row = getModel().getCount() - 1;
if (row < 0)
row = 0;
getListPanel().setHighlightRow(row);
Widget item = getListPanel().getList().getWidget(row);
getListPanel().ensureVisible(item);
}
}
/** Hides the drop down list. */
public void hideList() {
getListPanel().hide();
getChoiceButton().setDown(false);
}
/**
* Selects the specified item in the model and in the drop down list.
*
* @param row is a row index to select
*/
public void select(int row) {
getModel().setSelectedIndex(row);
getListPanel().hide();
getSelectedValue().removeStyleName("selected-row");
getChoiceButton().setDown(false);
}
/** {@inheritDoc} */
public void onModelEvent(ListModelEvent event) {
if (event.getType() == ListModelEvent.ADD_ITEM) {
add(event);
} else if (event.getType() == ListModelEvent.CLEAN) {
clean(event);
} else if (event.getType() == ListModelEvent.REMOVE_ITEM) {
remove(event);
} else if (event.getType() == ListModelEvent.SELECT_ITEM) {
select(event);
}
getListPanel().adjustSize();
}
/**
* Checks whether the lazy rendering option is enabled.
*
* @return a result of check.
*/
public boolean isLazyRenderingEnabled() {
return getListPanel().isLazyRenderingEnabled();
}
/**
* Enables or disables lazy rendering option.
* If this option is enabled the widget displays only several items on lazily renders other ones on scroll down.
* By default lazy rendering is disabled. Switch it on for really large (over 500 items) lists only.
* Note that lazy rendering is not lazy data loading. The second one means that the data is loaded into
* the model on request where as the first option assumes that all necessary data has already been loaded and put
* into the model. If you need lazy loading please consider using {@link SuggestionBox} and
* {@link org.gwt.advanced.client.datamodel.SuggestionBoxDataModel}.
*
* @param lazyRenderingEnabled is an option value.
*/
public void setLazyRenderingEnabled(boolean lazyRenderingEnabled) {
getListPanel().setLazyRenderingEnabled(lazyRenderingEnabled);
}
/**
* Gets applied position of the drop down list.
*
* @return a drop down list position value.
*/
public DropDownPosition getDropDownPosition() {
return getListPanel().getDropDownPosition();
}
/**
* Sets applied position of the drop down list.
* Being set the drop down is immediately applied if the list is opened.
*
* @param dropDownPosition is a drop down list position value.
*/
public void setDropDownPosition(DropDownPosition dropDownPosition) {
getListPanel().setDropDownPosition(dropDownPosition);
}
/**
* Adds a new visual item into the drop down list every time when it's added into the data
* model.
*
* @param event is an event containing data about the item.
*/
protected void add(ListModelEvent event) {
if (isListPanelOpened()) {
for (Map.Entry entry : event.getItemIndexes().entrySet()) {
if (entry.getValue() <= getItemCount()) {
Widget item = getListItemFactory().createWidget(event.getSource().get(entry.getKey()));
item = getListPanel().adoptItemWidget(item);
if (entry.getValue() < getListPanel().getList().getWidgetCount()) {
getListPanel().getList().insert(item, entry.getValue());
} else {
getListPanel().getList().add(item);
}
} else {
getListPanel().prepareList();
if (getItemCount() <= 0)
getListPanel().hide();
}
}
}
}
/**
* This method cleans the drop down list on each data clean.
*
* @param event is a clean event.
*/
@SuppressWarnings({"UnusedDeclaration"})
protected void clean(ListModelEvent event) {
if (isListPanelOpened()) {
getListPanel().getList().clear();
getListPanel().hide();
}
}
/**
* Removes a visual item from the drop down list if the remove event is received.
*
* @param event is an event that contains data of the removed item.
*/
protected void remove(ListModelEvent event) {
if (isListPanelOpened()) {
for (Map.Entry entry : event.getItemIndexes().entrySet()) {
if (entry.getValue() < getListPanel().getList().getWidgetCount()) {
getListPanel().remove(getListPanel().getList().getWidget(entry.getValue()));
if (getListPanel().getList().getWidgetCount() <= 0)
getListPanel().hide();
}
}
}
}
/**
* Highlights the visual item in the drop down list if it's selected in the model.
*
* @param event is an event that contains data about selected item.
*/
protected void select(ListModelEvent event) {
if (event.getItemIndex() >= 0) {
if (isListPanelOpened()) {
getListPanel().setHighlightRow(event.getItemIndex());
}
setText(getListItemFactory().convert(model.getSelected()));
}
}
/** {@inheritDoc} */
protected String getDefaultImageName() {
return "drop-down.gif";
}
/**
* Returns true
if cursor is moved by a control key.
*
* @return a flag value.
*/
protected boolean isKeyPressed() {
return keyPressed;
}
/**
* Sets the value of the key pressed flag.
*
* @param keyPressed is a key pressed flag value.
*/
protected void setKeyPressed(boolean keyPressed) {
this.keyPressed = keyPressed;
}
/** {@inheritDoc} */
protected void prepareSelectedValue() {
super.prepareSelectedValue();
getSelectedValue().setText(getListItemFactory().convert(getModel().getSelected()));
}
/** {@inheritDoc} */
protected void addComponentListeners() {
TextBox value = getSelectedValue();
ToggleButton button = getChoiceButton();
getListPanel().addChangeHandler(getDelegateHandler());
value.addChangeHandler(getDelegateHandler());
button.addFocusHandler(getDelegateHandler());
value.addFocusHandler(getDelegateHandler());
button.addBlurHandler(getDelegateHandler());
value.addBlurHandler(getDelegateHandler());
value.addClickHandler(getDelegateHandler());
button.addClickHandler(getDelegateHandler());
value.addKeyUpHandler(getDelegateHandler());
value.addKeyDownHandler(getDelegateHandler());
value.addKeyPressHandler(getDelegateHandler());
}
/**
* Getter for property 'listPanel'.
*
* @return Value for property 'listPanel'.
*/
protected ListPopupPanel getListPanel() {
if (listPanel == null) {
listPanel = new ListPopupPanel(this);
}
return listPanel;
}
/**
* Getter for property 'delegateHandler'.
*
* @return Value for property 'delegateHandler'.
*/
protected DelegateHandler getDelegateHandler() {
if (delegateHandler == null)
delegateHandler = new DelegateHandler();
return delegateHandler;
}
/**
* This method gets a keybord manager implementation for the component.
*
* @return an instance of the manager.
*/
protected ComboBoxKeyboardManager getKeyboardManager() {
if (keyboardManager == null)
keyboardManager = new ComboBoxKeyboardManager();
return keyboardManager;
}
/** Universal handler that delegates all events handling to custom handlers. */
protected class DelegateHandler implements FocusHandler, BlurHandler, ClickHandler,
ChangeHandler, KeyUpHandler, KeyDownHandler, KeyPressHandler {
/** a list of focused controls */
private Set
© 2015 - 2025 Weber Informatics LLC | Privacy Policy