import com.google.gwt.user.client.ui.PopupPanel.PositionCallback;
import com.google.gwt.user.client.ui.SuggestOracle.Suggestion;
import com.google.gwt.user.client.ui.TextBox;
-import com.google.gwt.user.client.ui.Widget;
import com.vaadin.terminal.gwt.client.ApplicationConnection;
import com.vaadin.terminal.gwt.client.BrowserInfo;
import com.vaadin.terminal.gwt.client.EventId;
import com.vaadin.terminal.gwt.client.Focusable;
-import com.vaadin.terminal.gwt.client.VPaintableWidget;
import com.vaadin.terminal.gwt.client.UIDL;
import com.vaadin.terminal.gwt.client.Util;
import com.vaadin.terminal.gwt.client.VConsole;
* TODO needs major refactoring (to be extensible etc)
*/
@SuppressWarnings("deprecation")
-public class VFilterSelect extends Composite implements VPaintableWidget, Field,
- KeyDownHandler, KeyUpHandler, ClickHandler, FocusHandler, BlurHandler,
- Focusable {
+public class VFilterSelect extends Composite implements Field, KeyDownHandler,
+ KeyUpHandler, ClickHandler, FocusHandler, BlurHandler, Focusable {
/**
* Represents a suggestion in the suggestion popup box
private static final String Z_INDEX = "30000";
- private final SuggestionMenu menu;
+ protected final SuggestionMenu menu;
private final Element up = DOM.createDiv();
private final Element down = DOM.createDiv();
return keyboardSelectedItem;
}
- private void setKeyboardSelectedItem(MenuItem firstItem) {
+ protected void setKeyboardSelectedItem(MenuItem firstItem) {
keyboardSelectedItem = firstItem;
}
/**
* The text box where the filter is written
*/
- private final TextBox tb = new TextBox() {
+ protected final TextBox tb = new TextBox() {
/*
* (non-Javadoc)
*
public void onBrowserEvent(Event event) {
super.onBrowserEvent(event);
if (client != null) {
- client.handleTooltipEvent(event, VFilterSelect.this);
+ client.handleWidgetTooltipEvent(event, VFilterSelect.this);
}
}
};
};
- private final SuggestionPopup suggestionPopup = new SuggestionPopup();
+ protected final SuggestionPopup suggestionPopup = new SuggestionPopup();
/**
* Used when measuring the width of the popup
public void onBrowserEvent(Event event) {
super.onBrowserEvent(event);
if (client != null) {
- client.handleTooltipEvent(event, VFilterSelect.this);
+ client.handleWidgetTooltipEvent(event, VFilterSelect.this);
}
/*
private final Image selectedItemIcon = new Image();
- private ApplicationConnection client;
+ protected ApplicationConnection client;
- private String paintableId;
+ protected String paintableId;
- private int currentPage;
+ protected int currentPage;
/**
* A collection of available suggestions (options) as received from the
* server.
*/
- private final List<FilterSelectSuggestion> currentSuggestions = new ArrayList<FilterSelectSuggestion>();
+ protected final List<FilterSelectSuggestion> currentSuggestions = new ArrayList<FilterSelectSuggestion>();
- private boolean immediate;
+ protected boolean immediate;
- private String selectedOptionKey;
+ protected String selectedOptionKey;
- private boolean waitingForFilteringResponse = false;
- private boolean updateSelectionWhenReponseIsReceived = false;
+ protected boolean waitingForFilteringResponse = false;
+ protected boolean updateSelectionWhenReponseIsReceived = false;
private boolean tabPressedWhenPopupOpen = false;
- private boolean initDone = false;
+ protected boolean initDone = false;
- private String lastFilter = "";
+ protected String lastFilter = "";
- private enum Select {
+ protected enum Select {
NONE, FIRST, LAST
};
- private Select selectPopupItemWhenResponseIsReceived = Select.NONE;
+ protected Select selectPopupItemWhenResponseIsReceived = Select.NONE;
/**
* The current suggestion selected from the dropdown. This is one of the
* values in currentSuggestions except when filtering, in this case
* currentSuggestion might not be in currentSuggestions.
*/
- private FilterSelectSuggestion currentSuggestion;
+ protected FilterSelectSuggestion currentSuggestion;
- private int totalMatches;
- private boolean allowNewItem;
- private boolean nullSelectionAllowed;
- private boolean nullSelectItem;
- private boolean enabled;
- private boolean readonly;
+ protected int totalMatches;
+ protected boolean allowNewItem;
+ protected boolean nullSelectionAllowed;
+ protected boolean nullSelectItem;
+ protected boolean enabled;
+ protected boolean readonly;
- private int filteringmode = FILTERINGMODE_OFF;
+ protected int filteringmode = FILTERINGMODE_OFF;
// shown in unfocused empty field, disappears on focus (e.g "Search here")
private static final String CLASSNAME_PROMPT = "prompt";
- private static final String ATTR_INPUTPROMPT = "prompt";
+ protected static final String ATTR_INPUTPROMPT = "prompt";
public static final String ATTR_NO_TEXT_INPUT = "noInput";
- private String inputPrompt = "";
- private boolean prompting = false;
+ protected String inputPrompt = "";
+ protected boolean prompting = false;
// Set true when popupopened has been clicked. Cleared on each UIDL-update.
// This handles the special case where are not filtering yet and the
// selected value has changed on the server-side. See #2119
- private boolean popupOpenerClicked;
+ protected boolean popupOpenerClicked;
private String width = null;
private int textboxPadding = -1;
private int componentPadding = -1;
- private int suggestionPopupMinWidth = 0;
+ protected int suggestionPopupMinWidth = 0;
private int popupWidth = -1;
/*
* Stores the last new item string to avoid double submissions. Cleared on
* uidl updates
*/
- private String lastNewItemString;
- private boolean focused = false;
+ protected String lastNewItemString;
+ protected boolean focused = false;
private int horizPaddingAndBorder = 2;
/**
currentPage = page;
}
- /*
- * (non-Javadoc)
- *
- * @see
- * com.vaadin.terminal.gwt.client.Paintable#updateFromUIDL(com.vaadin.terminal
- * .gwt.client.UIDL, com.vaadin.terminal.gwt.client.ApplicationConnection)
- */
- @SuppressWarnings("deprecation")
- public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
- paintableId = uidl.getId();
- this.client = client;
-
- readonly = uidl.hasAttribute("readonly");
- enabled = !uidl.hasAttribute("disabled");
-
- tb.setEnabled(enabled);
- updateReadOnly();
-
- if (client.updateComponent(this, uidl, true)) {
- return;
- }
-
- // Inverse logic here to make the default case (text input enabled)
- // work without additional UIDL messages
- boolean noTextInput = uidl.hasAttribute(ATTR_NO_TEXT_INPUT)
- && uidl.getBooleanAttribute(ATTR_NO_TEXT_INPUT);
- setTextInputEnabled(!noTextInput);
-
- // not a FocusWidget -> needs own tabindex handling
- if (uidl.hasAttribute("tabindex")) {
- tb.setTabIndex(uidl.getIntAttribute("tabindex"));
- }
-
- if (uidl.hasAttribute("filteringmode")) {
- filteringmode = uidl.getIntAttribute("filteringmode");
- }
-
- immediate = uidl.hasAttribute("immediate");
-
- nullSelectionAllowed = uidl.hasAttribute("nullselect");
-
- nullSelectItem = uidl.hasAttribute("nullselectitem")
- && uidl.getBooleanAttribute("nullselectitem");
-
- currentPage = uidl.getIntVariable("page");
-
- if (uidl.hasAttribute("pagelength")) {
- pageLength = uidl.getIntAttribute("pagelength");
- }
-
- if (uidl.hasAttribute(ATTR_INPUTPROMPT)) {
- // input prompt changed from server
- inputPrompt = uidl.getStringAttribute(ATTR_INPUTPROMPT);
- } else {
- inputPrompt = "";
- }
-
- suggestionPopup.updateStyleNames(uidl);
-
- allowNewItem = uidl.hasAttribute("allownewitem");
- lastNewItemString = null;
-
- currentSuggestions.clear();
- if (!waitingForFilteringResponse) {
- /*
- * Clear the current suggestions as the server response always
- * includes the new ones. Exception is when filtering, then we need
- * to retain the value if the user does not select any of the
- * options matching the filter.
- */
- currentSuggestion = null;
- /*
- * Also ensure no old items in menu. Unless cleared the old values
- * may cause odd effects on blur events. Suggestions in menu might
- * not necessary exist in select at all anymore.
- */
- suggestionPopup.menu.clearItems();
-
- }
-
- final UIDL options = uidl.getChildUIDL(0);
- if (uidl.hasAttribute("totalMatches")) {
- totalMatches = uidl.getIntAttribute("totalMatches");
- } else {
- totalMatches = 0;
- }
-
- // used only to calculate minimum popup width
- String captions = Util.escapeHTML(inputPrompt);
-
- for (final Iterator<?> i = options.getChildIterator(); i.hasNext();) {
- final UIDL optionUidl = (UIDL) i.next();
- final FilterSelectSuggestion suggestion = new FilterSelectSuggestion(
- optionUidl);
- currentSuggestions.add(suggestion);
- if (optionUidl.hasAttribute("selected")) {
- if (!waitingForFilteringResponse || popupOpenerClicked) {
- String newSelectedOptionKey = Integer.toString(suggestion
- .getOptionKey());
- if (!newSelectedOptionKey.equals(selectedOptionKey)
- || suggestion.getReplacementString().equals(
- tb.getText())) {
- // Update text field if we've got a new selection
- // Also update if we've got the same text to retain old
- // text selection behavior
- setPromptingOff(suggestion.getReplacementString());
- selectedOptionKey = newSelectedOptionKey;
- }
- }
- currentSuggestion = suggestion;
- setSelectedItemIcon(suggestion.getIconUri());
- }
-
- // Collect captions so we can calculate minimum width for textarea
- if (captions.length() > 0) {
- captions += "|";
- }
- captions += Util.escapeHTML(suggestion.getReplacementString());
- }
-
- if ((!waitingForFilteringResponse || popupOpenerClicked)
- && uidl.hasVariable("selected")
- && uidl.getStringArrayVariable("selected").length == 0) {
- // select nulled
- if (!waitingForFilteringResponse || !popupOpenerClicked) {
- if (!focused) {
- /*
- * client.updateComponent overwrites all styles so we must
- * ALWAYS set the prompting style at this point, even though
- * we think it has been set already...
- */
- prompting = false;
- setPromptingOn();
- } else {
- // we have focus in field, prompting can't be set on,
- // instead just clear the input
- tb.setValue("");
- }
- }
- selectedOptionKey = null;
- }
-
- if (waitingForFilteringResponse
- && lastFilter.toLowerCase().equals(
- uidl.getStringVariable("filter"))) {
- suggestionPopup.showSuggestions(currentSuggestions, currentPage,
- totalMatches);
- waitingForFilteringResponse = false;
- if (!popupOpenerClicked
- && selectPopupItemWhenResponseIsReceived != Select.NONE) {
- // we're paging w/ arrows
- if (selectPopupItemWhenResponseIsReceived == Select.LAST) {
- suggestionPopup.menu.selectLastItem();
- } else {
- suggestionPopup.menu.selectFirstItem();
- }
-
- // This is used for paging so we update the keyboard selection
- // variable as well.
- MenuItem activeMenuItem = suggestionPopup.menu
- .getSelectedItem();
- suggestionPopup.menu.setKeyboardSelectedItem(activeMenuItem);
-
- // Update text field to contain the correct text
- setTextboxText(activeMenuItem.getText());
- tb.setSelectionRange(lastFilter.length(), activeMenuItem
- .getText().length() - lastFilter.length());
-
- selectPopupItemWhenResponseIsReceived = Select.NONE; // reset
- }
- if (updateSelectionWhenReponseIsReceived) {
- suggestionPopup.menu.doPostFilterSelectedItemAction();
- }
- }
-
- // Calculate minumum textarea width
- suggestionPopupMinWidth = minWidth(captions);
-
- popupOpenerClicked = false;
-
- if (!initDone) {
- updateRootWidth();
- }
-
- // Focus dependent style names are lost during the update, so we add
- // them here back again
- if (focused) {
- addStyleDependentName("focus");
- }
-
- initDone = true;
- }
-
- private void updateReadOnly() {
+ protected void updateReadOnly() {
tb.setReadOnly(readonly || !textInputEnabled);
}
- private void setTextInputEnabled(boolean textInputEnabled) {
+ protected void setTextInputEnabled(boolean textInputEnabled) {
// Always update styles as they might have been overwritten
if (textInputEnabled) {
removeStyleDependentName(STYLE_NO_INPUT);
* @param text
* the text to set in the text box
*/
- private void setTextboxText(final String text) {
+ protected void setTextboxText(final String text) {
tb.setText(text);
}
* Turns prompting on. When prompting is turned on a command prompt is shown
* in the text box if nothing has been entered.
*/
- private void setPromptingOn() {
+ protected void setPromptingOn() {
if (!prompting) {
prompting = true;
addStyleDependentName(CLASSNAME_PROMPT);
* @param text
* The text the text box should contain.
*/
- private void setPromptingOff(String text) {
+ protected void setPromptingOff(String text) {
setTextboxText(text);
if (prompting) {
prompting = false;
* @param iconUri
* The URI of the icon
*/
- private void setSelectedItemIcon(String iconUri) {
+ protected void setSelectedItemIcon(String iconUri) {
if (iconUri == null || iconUri == "") {
panel.remove(selectedItemIcon);
updateRootWidth();
/**
* Calculate minimum width for FilterSelect textarea
*/
- private native int minWidth(String captions)
+ protected native int minWidth(String captions)
/*-{
if(!captions || captions.length <= 0)
return 0;
}
addStyleDependentName("focus");
- if (client.hasEventListeners(this, EventId.FOCUS)) {
+ if (client.hasWidgetEventListeners(this, EventId.FOCUS)) {
client.updateVariable(paintableId, EventId.FOCUS, "", true);
}
}
}
removeStyleDependentName("focus");
- if (client.hasEventListeners(this, EventId.BLUR)) {
+ if (client.hasWidgetEventListeners(this, EventId.BLUR)) {
client.updateVariable(paintableId, EventId.BLUR, "", true);
}
}
* Calculates the width of the select if the select has undefined width.
* Should be called when the width changes or when the icon changes.
*/
- private void updateRootWidth() {
+ protected void updateRootWidth() {
if (width == null) {
/*
* When the width is not specified we must specify width for root
super.onDetach();
suggestionPopup.hide();
}
-
- public Widget getWidgetForPaintable() {
- return this;
- }
}
--- /dev/null
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+package com.vaadin.terminal.gwt.client.ui;
+
+import java.util.Iterator;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.user.client.ui.Widget;
+import com.vaadin.terminal.gwt.client.ApplicationConnection;
+import com.vaadin.terminal.gwt.client.UIDL;
+import com.vaadin.terminal.gwt.client.Util;
+import com.vaadin.terminal.gwt.client.ui.VFilterSelect.FilterSelectSuggestion;
+
+public class VFilterSelectPaintable extends VAbstractPaintableWidget {
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.vaadin.terminal.gwt.client.Paintable#updateFromUIDL(com.vaadin.terminal
+ * .gwt.client.UIDL, com.vaadin.terminal.gwt.client.ApplicationConnection)
+ */
+ @SuppressWarnings("deprecation")
+ public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
+ // Save details
+ getWidgetForPaintable().client = client;
+ getWidgetForPaintable().paintableId = uidl.getId();
+
+ getWidgetForPaintable().readonly = uidl.hasAttribute("readonly");
+ getWidgetForPaintable().enabled = !uidl.hasAttribute("disabled");
+
+ getWidgetForPaintable().tb.setEnabled(getWidgetForPaintable().enabled);
+ getWidgetForPaintable().updateReadOnly();
+
+ if (client.updateComponent(this, uidl, true)) {
+ return;
+ }
+
+ // Inverse logic here to make the default case (text input enabled)
+ // work without additional UIDL messages
+ boolean noTextInput = uidl
+ .hasAttribute(VFilterSelect.ATTR_NO_TEXT_INPUT)
+ && uidl.getBooleanAttribute(VFilterSelect.ATTR_NO_TEXT_INPUT);
+ getWidgetForPaintable().setTextInputEnabled(!noTextInput);
+
+ // not a FocusWidget -> needs own tabindex handling
+ if (uidl.hasAttribute("tabindex")) {
+ getWidgetForPaintable().tb.setTabIndex(uidl
+ .getIntAttribute("tabindex"));
+ }
+
+ if (uidl.hasAttribute("filteringmode")) {
+ getWidgetForPaintable().filteringmode = uidl
+ .getIntAttribute("filteringmode");
+ }
+
+ getWidgetForPaintable().immediate = uidl.hasAttribute("immediate");
+
+ getWidgetForPaintable().nullSelectionAllowed = uidl
+ .hasAttribute("nullselect");
+
+ getWidgetForPaintable().nullSelectItem = uidl
+ .hasAttribute("nullselectitem")
+ && uidl.getBooleanAttribute("nullselectitem");
+
+ getWidgetForPaintable().currentPage = uidl.getIntVariable("page");
+
+ if (uidl.hasAttribute("pagelength")) {
+ getWidgetForPaintable().pageLength = uidl
+ .getIntAttribute("pagelength");
+ }
+
+ if (uidl.hasAttribute(VFilterSelect.ATTR_INPUTPROMPT)) {
+ // input prompt changed from server
+ getWidgetForPaintable().inputPrompt = uidl
+ .getStringAttribute(VFilterSelect.ATTR_INPUTPROMPT);
+ } else {
+ getWidgetForPaintable().inputPrompt = "";
+ }
+
+ getWidgetForPaintable().suggestionPopup.updateStyleNames(uidl);
+
+ getWidgetForPaintable().allowNewItem = uidl
+ .hasAttribute("allownewitem");
+ getWidgetForPaintable().lastNewItemString = null;
+
+ getWidgetForPaintable().currentSuggestions.clear();
+ if (!getWidgetForPaintable().waitingForFilteringResponse) {
+ /*
+ * Clear the current suggestions as the server response always
+ * includes the new ones. Exception is when filtering, then we need
+ * to retain the value if the user does not select any of the
+ * options matching the filter.
+ */
+ getWidgetForPaintable().currentSuggestion = null;
+ /*
+ * Also ensure no old items in menu. Unless cleared the old values
+ * may cause odd effects on blur events. Suggestions in menu might
+ * not necessary exist in select at all anymore.
+ */
+ getWidgetForPaintable().suggestionPopup.menu.clearItems();
+
+ }
+
+ final UIDL options = uidl.getChildUIDL(0);
+ if (uidl.hasAttribute("totalMatches")) {
+ getWidgetForPaintable().totalMatches = uidl
+ .getIntAttribute("totalMatches");
+ } else {
+ getWidgetForPaintable().totalMatches = 0;
+ }
+
+ // used only to calculate minimum popup width
+ String captions = Util.escapeHTML(getWidgetForPaintable().inputPrompt);
+
+ for (final Iterator<?> i = options.getChildIterator(); i.hasNext();) {
+ final UIDL optionUidl = (UIDL) i.next();
+ final FilterSelectSuggestion suggestion = getWidgetForPaintable().new FilterSelectSuggestion(
+ optionUidl);
+ getWidgetForPaintable().currentSuggestions.add(suggestion);
+ if (optionUidl.hasAttribute("selected")) {
+ if (!getWidgetForPaintable().waitingForFilteringResponse
+ || getWidgetForPaintable().popupOpenerClicked) {
+ String newSelectedOptionKey = Integer.toString(suggestion
+ .getOptionKey());
+ if (!newSelectedOptionKey
+ .equals(getWidgetForPaintable().selectedOptionKey)
+ || suggestion.getReplacementString().equals(
+ getWidgetForPaintable().tb.getText())) {
+ // Update text field if we've got a new selection
+ // Also update if we've got the same text to retain old
+ // text selection behavior
+ getWidgetForPaintable().setPromptingOff(
+ suggestion.getReplacementString());
+ getWidgetForPaintable().selectedOptionKey = newSelectedOptionKey;
+ }
+ }
+ getWidgetForPaintable().currentSuggestion = suggestion;
+ getWidgetForPaintable().setSelectedItemIcon(
+ suggestion.getIconUri());
+ }
+
+ // Collect captions so we can calculate minimum width for textarea
+ if (captions.length() > 0) {
+ captions += "|";
+ }
+ captions += Util.escapeHTML(suggestion.getReplacementString());
+ }
+
+ if ((!getWidgetForPaintable().waitingForFilteringResponse || getWidgetForPaintable().popupOpenerClicked)
+ && uidl.hasVariable("selected")
+ && uidl.getStringArrayVariable("selected").length == 0) {
+ // select nulled
+ if (!getWidgetForPaintable().waitingForFilteringResponse
+ || !getWidgetForPaintable().popupOpenerClicked) {
+ if (!getWidgetForPaintable().focused) {
+ /*
+ * client.updateComponent overwrites all styles so we must
+ * ALWAYS set the prompting style at this point, even though
+ * we think it has been set already...
+ */
+ getWidgetForPaintable().prompting = false;
+ getWidgetForPaintable().setPromptingOn();
+ } else {
+ // we have focus in field, prompting can't be set on,
+ // instead just clear the input
+ getWidgetForPaintable().tb.setValue("");
+ }
+ }
+ getWidgetForPaintable().selectedOptionKey = null;
+ }
+
+ if (getWidgetForPaintable().waitingForFilteringResponse
+ && getWidgetForPaintable().lastFilter.toLowerCase().equals(
+ uidl.getStringVariable("filter"))) {
+ getWidgetForPaintable().suggestionPopup.showSuggestions(
+ getWidgetForPaintable().currentSuggestions,
+ getWidgetForPaintable().currentPage,
+ getWidgetForPaintable().totalMatches);
+ getWidgetForPaintable().waitingForFilteringResponse = false;
+ if (!getWidgetForPaintable().popupOpenerClicked
+ && getWidgetForPaintable().selectPopupItemWhenResponseIsReceived != VFilterSelect.Select.NONE) {
+ // we're paging w/ arrows
+ if (getWidgetForPaintable().selectPopupItemWhenResponseIsReceived == VFilterSelect.Select.LAST) {
+ getWidgetForPaintable().suggestionPopup.menu
+ .selectLastItem();
+ } else {
+ getWidgetForPaintable().suggestionPopup.menu
+ .selectFirstItem();
+ }
+
+ // This is used for paging so we update the keyboard selection
+ // variable as well.
+ MenuItem activeMenuItem = getWidgetForPaintable().suggestionPopup.menu
+ .getSelectedItem();
+ getWidgetForPaintable().suggestionPopup.menu
+ .setKeyboardSelectedItem(activeMenuItem);
+
+ // Update text field to contain the correct text
+ getWidgetForPaintable()
+ .setTextboxText(activeMenuItem.getText());
+ getWidgetForPaintable().tb.setSelectionRange(
+ getWidgetForPaintable().lastFilter.length(),
+ activeMenuItem.getText().length()
+ - getWidgetForPaintable().lastFilter.length());
+
+ getWidgetForPaintable().selectPopupItemWhenResponseIsReceived = VFilterSelect.Select.NONE; // reset
+ }
+ if (getWidgetForPaintable().updateSelectionWhenReponseIsReceived) {
+ getWidgetForPaintable().suggestionPopup.menu
+ .doPostFilterSelectedItemAction();
+ }
+ }
+
+ // Calculate minumum textarea width
+ getWidgetForPaintable().suggestionPopupMinWidth = getWidgetForPaintable()
+ .minWidth(captions);
+
+ getWidgetForPaintable().popupOpenerClicked = false;
+
+ if (!getWidgetForPaintable().initDone) {
+ getWidgetForPaintable().updateRootWidth();
+ }
+
+ // Focus dependent style names are lost during the update, so we add
+ // them here back again
+ if (getWidgetForPaintable().focused) {
+ getWidgetForPaintable().addStyleDependentName("focus");
+ }
+
+ getWidgetForPaintable().initDone = true;
+ }
+
+ @Override
+ protected Widget createWidget() {
+ return GWT.create(VFilterSelect.class);
+ }
+
+ @Override
+ public VFilterSelect getWidgetForPaintable() {
+ return (VFilterSelect) super.getWidgetForPaintable();
+ }
+}