/** * Copyright (C) 2011 BonitaSoft S.A. * BonitaSoft, 31 rue Gustave Eiffel - 38000 Grenoble * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2.0 of the License, or * (at your option) any later version. * * 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, see <http://www.gnu.org/licenses/>. */ package org.bonitasoft.forms.client.view.widget; import java.util.List; import java.util.Map; import org.bonitasoft.forms.client.model.FormFieldValue; import org.bonitasoft.forms.client.model.ReducedFormFieldAvailableValue; import org.bonitasoft.forms.client.model.ReducedFormWidget; import org.bonitasoft.forms.client.model.WidgetType; import org.bonitasoft.forms.client.rpc.FormsServiceAsync; import org.bonitasoft.forms.client.view.FormsAsyncCallback; import org.bonitasoft.forms.client.view.SupportedFieldTypes; import org.bonitasoft.forms.client.view.common.RpcFormsServices; import com.google.gwt.core.client.GWT; import com.google.gwt.dom.client.Document; import com.google.gwt.event.dom.client.DomEvent; import com.google.gwt.event.dom.client.KeyPressEvent; import com.google.gwt.event.dom.client.KeyPressHandler; import com.google.gwt.event.dom.client.KeyUpEvent; import com.google.gwt.event.dom.client.KeyUpHandler; import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.MultiWordSuggestOracle; import com.google.gwt.user.client.ui.SuggestBox; import com.google.gwt.user.client.ui.SuggestBox.DefaultSuggestionDisplay; import com.google.gwt.user.client.ui.TextBox; /** * Generic form flow AsyncSuggestBox widget * * @author qixiang.zhang */ public class AsyncSuggestBoxWidget extends Composite { /** * The default refresh delay */ protected static final int DEFAULT_REFRESH_DELAY = 1000; /** * the flow panel used to display the widget */ protected FlowPanel flowPanel; /** * widget field type */ protected WidgetType widgetType; /** * SuggestBox widget */ protected SuggestBox asyncSuggestBox; /** * The form ID */ protected String formID; /** * The URL context */ protected Map<String, Object> contextMap; /** * Form Widget */ protected ReducedFormWidget formWidget; /** * old asyncSuggestBox value */ protected String oldValue; /** * Default constructor. * * @param formAsyncSuggestBoxData * the Suggestbox data * @param formID * @param contextMap * @param pageId * @param isCurrentValue * @param fieldValue * the field's available value */ public AsyncSuggestBoxWidget(final ReducedFormWidget formAsyncSuggestBoxData, final String formID, final Map<String, Object> contextMap, final FormFieldValue fieldValue) { this.formID = formID; this.contextMap = contextMap; formWidget = formAsyncSuggestBoxData; flowPanel = new FlowPanel(); createWidget(formAsyncSuggestBoxData, fieldValue); initWidget(flowPanel); } /** * Create AsyncSuggestBox * * @param formAsyncSuggestBoxData * @param fieldValue */ protected void createWidget(final ReducedFormWidget formAsyncSuggestBoxData, final FormFieldValue fieldValue) { widgetType = formAsyncSuggestBoxData.getType(); final TextBox textBox = new TextBox(); textBox.setReadOnly(formAsyncSuggestBoxData.isReadOnly()); final DefaultSuggestionDisplay suggestionDisplay = new DefaultSuggestionDisplay(); final String popupStyle = formAsyncSuggestBoxData.getItemsStyle(); if (popupStyle != null && popupStyle.length() > 0) { suggestionDisplay.setPopupStyleName(popupStyle); } final MultiWordSuggestOracle oracle = new MultiWordSuggestOracle(); for (final ReducedFormFieldAvailableValue availableValue : formAsyncSuggestBoxData.getAvailableValues()) { oracle.add(availableValue.getValue()); } asyncSuggestBox = new SuggestBox(oracle, textBox, suggestionDisplay); int refreshDelay = formAsyncSuggestBoxData.getDelayMillis(); if (refreshDelay <= 0) { refreshDelay = DEFAULT_REFRESH_DELAY; } asyncSuggestBox.addKeyUpHandler(new AsyncSuggestBoxKeyUpHandler(refreshDelay)); asyncSuggestBox.addKeyPressHandler(new AsyncSuggestBoxKeyPressHandler()); asyncSuggestBox.setValue(getStringValue(fieldValue)); if (formAsyncSuggestBoxData.getMaxItems() > 0) { asyncSuggestBox.setLimit(formAsyncSuggestBoxData.getMaxItems() - 1); } flowPanel.add(asyncSuggestBox); } /** * @return AsyncSuggestBox type */ public WidgetType getWidgetType() { return widgetType; } /** * @return the suggest box widget */ public SuggestBox getAsyncSuggestBox() { return asyncSuggestBox; } /** * @return async SuggestBox of value */ public String getValue() { return asyncSuggestBox.getValue(); } /** * Get the string value of a {@link FormFieldValue} * * @param fieldValue * the {@link FormFieldValue} * @return a String */ protected String getStringValue(final FormFieldValue fieldValue) { String value = null; if (SupportedFieldTypes.JAVA_STRING_CLASSNAME.equals(fieldValue.getValueType())) { value = (String) fieldValue.getValue(); } else if (fieldValue.getValue() != null) { value = fieldValue.getValue().toString(); } return value; } /** * Set the value of the AsyncSuggestBox * * @param fieldValue */ public void setValue(final String value, final boolean fireEvents) { asyncSuggestBox.setValue(value, fireEvents); } /** * Set the available values of the widget (for list widgets only) * * @param availableValues */ public void setAvailableValues(final List<ReducedFormFieldAvailableValue> availableValues, final boolean fireEvents) { final MultiWordSuggestOracle oracle = (MultiWordSuggestOracle) asyncSuggestBox.getSuggestOracle(); oracle.clear(); for (final ReducedFormFieldAvailableValue availableValue : availableValues) { oracle.add(availableValue.getValue()); } if (fireEvents) { DomEvent.fireNativeEvent(Document.get().createChangeEvent(), asyncSuggestBox); } } /** * AsyncSuggestBox KeyPressHandler * */ protected class AsyncSuggestBoxKeyPressHandler implements KeyPressHandler { /** * {@inheritDoc} */ @Override public void onKeyPress(final KeyPressEvent event) { oldValue = asyncSuggestBox.getText(); } } /** * AsyncSuggestBox KeyUpHandler * */ protected class AsyncSuggestBoxKeyUpHandler implements KeyUpHandler { /** * DelayMillis to call RPC */ int delayMillis; /** * Async Suggest Box of value */ String content; /** * Default constructor. * * @param delayMillis */ public AsyncSuggestBoxKeyUpHandler(final int delayMillis) { this.delayMillis = delayMillis; } Timer timer = new Timer() { @Override public void run() { final FormsServiceAsync formsServiceAsync = RpcFormsServices.getFormsService(); final FormFieldValue currentFieldValue = new FormFieldValue(content, SupportedFieldTypes.JAVA_STRING_CLASSNAME); // RPC Call formsServiceAsync.getFormAsyncAvailableValues(formID, contextMap, formWidget, currentFieldValue, new GetAsyncAvailableValuesHandler()); } }; /** * {@inheritDoc} */ @Override public void onKeyUp(final KeyUpEvent event) { if (!event.isUpArrow() && !event.isDownArrow()) { ((DefaultSuggestionDisplay) asyncSuggestBox.getSuggestionDisplay()).hideSuggestions(); } timer.cancel(); content = asyncSuggestBox.getText(); if (content.trim().length() > 0 && !content.equals(oldValue)) { timer.schedule(delayMillis); } } } /** * Handler for available values update * */ protected class GetAsyncAvailableValuesHandler extends FormsAsyncCallback<List<ReducedFormFieldAvailableValue>> { @Override public void onSuccess(final List<ReducedFormFieldAvailableValue> result) { final MultiWordSuggestOracle oracle = (MultiWordSuggestOracle) asyncSuggestBox.getSuggestOracle(); oracle.clear(); for (final ReducedFormFieldAvailableValue resultValue : result) { oracle.add(resultValue.getValue()); } asyncSuggestBox.showSuggestionList(); } @Override public void onUnhandledFailure(final Throwable caught) { final MultiWordSuggestOracle oracle = (MultiWordSuggestOracle) asyncSuggestBox.getSuggestOracle(); oracle.clear(); GWT.log("Async SuggestBox KeyUpHandler", caught); } } }