
org.gwt.advanced.client.ui.widget.SuggestionBox 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.event.dom.client.*;
import com.google.gwt.user.client.Timer;
import org.gwt.advanced.client.datamodel.ListDataModel;
import org.gwt.advanced.client.datamodel.ListModelEvent;
import org.gwt.advanced.client.datamodel.SuggestionBoxDataModel;
import org.gwt.advanced.client.datamodel.SuggestionModelEvent;
import org.gwt.advanced.client.ui.SuggestionBoxListener;
import java.util.ArrayList;
import java.util.List;
/**
* This class implements suggestion box logic.
* To use it properly you should specify the data model that is instance of
* the {@link org.gwt.advanced.client.datamodel.SuggestionBoxDataModel} class. Otherwise it will work as
* a simple combo box.
* See also {@link #setModel(org.gwt.advanced.client.datamodel.SuggestionBoxDataModel)}.
*
* @author Sergey Skladchikov
* @since 1.2.0
*/
public class SuggestionBox extends ComboBox {
/**
* default request timeout between last expression change and getting data
*/
public static final int DEFAULT_REQUEST_TIMEOUT = 500;
/**
* suggestion expression length
*/
private int expressionLength;
/**
* a list of suggestion box listeners
*/
private List suggestionBoxListeners;
/**
* a timer that is activated when the text box catches focus
*/
private Timer timer;
/**
* a focus handler that is invoked when the text box catches focus
*/
private ExpressionFocusHandler focusHandler;
/**
* a keyboard listener to set focus when a user types any text
*/
private ExpressionKeyboardHandler keyboardHandler;
/**
* request timeout value
*/
private int requestTimeout = DEFAULT_REQUEST_TIMEOUT;
/** flag that stores model initialization status */
private boolean modelInitialized;
/**
* Constructs a new SuggestionBox.
* By default the minimal expression length is 3
.
*/
public SuggestionBox() {
this(3);
}
/**
* Constructs an instance of this class and allows specifying the minimal length of the expression.
*
* @param expressionLength is an expression length.
*/
public SuggestionBox(int expressionLength) {
this.expressionLength = expressionLength;
setCustomTextAllowed(true);
setChoiceButtonVisible(false);
}
/**
* Getter for property 'expressionLength'.
*
* @return Value for property 'expressionLength'.
*/
public int getExpressionLength() {
return expressionLength;
}
/**
* Setter for property 'expressionLength'.
*
* @param expressionLength Value to set for property 'expressionLength'.
*/
public void setExpressionLength(int expressionLength) {
this.expressionLength = expressionLength;
}
/**
* Gets a timeout value between last expression change and getting data.
*
* @return a request timeout value.
*/
public int getRequestTimeout() {
return requestTimeout;
}
/**
* Sets the request timeout value.
* Set it to control how often the widget will request a server for data.
*
* @param requestTimeout is a request timeout value in msc.
*/
public void setRequestTimeout(int requestTimeout) {
this.requestTimeout = requestTimeout;
}
/**
* Setter for property 'model'.
*
* @param model Value to set for property 'model'.
*/
public void setModel(SuggestionBoxDataModel model) {
if (model != null) {
this.modelInitialized = true;
super.setModel(model);
addSuggestionBoxListener(model);
}
}
/** {@inheritDoc} */
@Override
public SuggestionBoxDataModel getModel() {
if (!modelInitialized) {
setModel(new SuggestionBoxDataModel(null));
}
return (SuggestionBoxDataModel) super.getModel();
}
/**
* Adds a new suggestion box listener that will be invoked on expression change.
*
* @param listener is a listener to be added.
*/
public void addSuggestionBoxListener(SuggestionBoxListener listener) {
removeSuggestionBoxListener(listener);
getSuggestionBoxListeners().add(listener);
}
/**
* This method removes the suggestion box listener.
*
* @param listener a suggestion box listener instance to remove.
*/
public void removeSuggestionBoxListener(SuggestionBoxListener listener) {
getSuggestionBoxListeners().remove(listener);
}
/**
* This method returns an expression entered by a user for drop down list selection.
* If the associated model is not {@link org.gwt.advanced.client.datamodel.SuggestionBoxDataModel} it retuns
* null
.
*
* @return an expression value.
*/
public String getExpression() {
ListDataModel comboBoxDataModel = getModel();
if (comboBoxDataModel instanceof SuggestionBoxDataModel)
return ((SuggestionBoxDataModel) comboBoxDataModel).getExpression();
else
return null;
}
/**
* Sets the expression value and displays it in the text box.
*
* @param expression is an expression to be applied.
*/
public void setExpression(String expression) {
ListDataModel comboBoxDataModel = getModel();
if (comboBoxDataModel instanceof SuggestionBoxDataModel) {
((SuggestionBoxDataModel) comboBoxDataModel).setExpression(expression);
getSelectedValue().setText(expression);
}
}
/**
* Immediately refreshes the list of values which may match the expression.
* Use this method if whant to open the popup list from the
* {@link org.gwt.advanced.client.datamodel.ListCallbackHandler} implementation and values are NOT cached on a
* client side.
*
* @deprecated you don't have to invoke this method since the list is updated on data model changes.
*/
public void refreshList() {
}
/**
* {@inheritDoc}
*/
public void cleanSelection() {
super.cleanSelection();
getModel().setExpression(null);
}
/**
* Additionally listens for events produced by the
* {@link org.gwt.advanced.client.datamodel.SuggestionBoxDataModel}.
*
* {@inheritDoc}
*/
public void onModelEvent(ListModelEvent event) {
if (event.getType() == SuggestionModelEvent.EXPRESSION_CHANGED
&& !getText().equals(((SuggestionModelEvent) event).getExpression())) {
setText(((SuggestionModelEvent) event).getExpression());
getListPanel().adjustSize();
} else if (event.getType() != SuggestionModelEvent.EXPRESSION_CHANGED) {
super.onModelEvent(event);
}
}
/**
* Additionally cleans the list every time when the first item is added.
* In other cases works like the same method in the super class.
*
* @param event is an event containing data about the added item.
*/
protected void add(ListModelEvent event) {
getTimer().cancel();
if (!isListPanelOpened()) {
getListPanel().getList().clear();
getListPanel().getScrollPanel().setWidth(getOffsetWidth() + "px");
getListPanel().show();
}
super.add(event);
getListPanel().selectRow(getModel().getSelectedIndex());
}
/**
* {@inheritDoc}
*/
protected void addComponentListeners() {
getSelectedValue().addFocusHandler(getExpressionFocusHandler());
getSelectedValue().addBlurHandler(getExpressionFocusHandler());
getSelectedValue().addKeyUpHandler(getExpressionKeyboardHandler());
getSelectedValue().addChangeHandler(getExpressionKeyboardHandler());
getSelectedValue().addClickHandler(getDelegateHandler());
getSelectedValue().addKeyDownHandler(getDelegateHandler());
getSelectedValue().addKeyPressHandler(getDelegateHandler());
getChoiceButton().addFocusHandler(getDelegateHandler());
getChoiceButton().addBlurHandler(getDelegateHandler());
getChoiceButton().addClickHandler(getDelegateHandler());
getListPanel().addChangeHandler(getDelegateHandler());
}
/**
* Getter for property 'suggestionBoxListeners'.
*
* @return Value for property 'suggestionBoxListeners'.
*/
protected List getSuggestionBoxListeners() {
if (suggestionBoxListeners == null)
suggestionBoxListeners = new ArrayList();
return suggestionBoxListeners;
}
/**
* Getter for property 'timer'.
*
* @return Value for property 'timer'.
*/
protected Timer getTimer() {
if (timer == null)
timer = new ExpressionTimer();
return timer;
}
/**
* Getter for property 'focusHandler'.
*
* @return Value for property 'focusHandler'.
*/
public ExpressionFocusHandler getExpressionFocusHandler() {
if (focusHandler == null)
focusHandler = new ExpressionFocusHandler();
return focusHandler;
}
/** {@inheritDoc} */
public void showList(boolean prepareList) {
getTimer().schedule(getRequestTimeout());
}
/**
* Getter for property 'keyboardHandler'.
*
* @return Value for property 'keyboardHandler'.
*/
protected ExpressionKeyboardHandler getExpressionKeyboardHandler() {
if (keyboardHandler == null)
keyboardHandler = new ExpressionKeyboardHandler();
return keyboardHandler;
}
/**
* Immediately cancels the {@link #timer} if it's run.
*/
protected void cancelTimer() {
getTimer().cancel();
}
/**
* This is a focus listener that starts / cancels the timer.
*/
protected class ExpressionFocusHandler implements FocusHandler, BlurHandler {
/**
* {@inheritDoc}
*/
@Override
public void onFocus(FocusEvent event) {
getTimer().schedule(getRequestTimeout());
}
/**
* {@inheritDoc}
*/
@Override
public void onBlur(BlurEvent event) {
getTimer().cancel();
}
}
/**
* This handler is invoked when a user types any text and sets focus
*/
protected class ExpressionKeyboardHandler implements KeyUpHandler, ChangeHandler {
/** last expression value before an event */
private String lastExpression;
/**
* {@inheritDoc}
*/
@Override
public void onChange(ChangeEvent event) {
getTimer().cancel();
setSelectedId(null);
}
/**
* {@inheritDoc}
*/
@Override
public void onKeyUp(KeyUpEvent event) {
if (!getText().equals(lastExpression) && event.getNativeKeyCode() != KeyCodes.KEY_ENTER) {
lastExpression = getText();
setSelectedId(null);
getTimer().schedule(getRequestTimeout());
}
}
}
/**
* This is a timer that displays the list of items.
*/
protected class ExpressionTimer extends Timer {
/**
* {@inheritDoc}
*/
public void run() {
String text = getSelectedValue().getText();
if (text.length() < getExpressionLength())
return;
for (SuggestionBoxListener listener : getSuggestionBoxListeners())
listener.onChange(text);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy