diff options
author | Artur Signell <artur@vaadin.com> | 2012-08-30 16:25:57 +0300 |
---|---|---|
committer | Artur Signell <artur@vaadin.com> | 2012-08-30 16:25:57 +0300 |
commit | 51eb105ee6af55bc8972ab3e860c38a11194b5bd (patch) | |
tree | 89f35e0b71c2dc0117490e44aef0d1f15a304387 /server/src/com/vaadin/ui/Select.java | |
parent | 876182aaa34682503338a4dcdd119b3ebc256f97 (diff) | |
download | vaadin-framework-51eb105ee6af55bc8972ab3e860c38a11194b5bd.tar.gz vaadin-framework-51eb105ee6af55bc8972ab3e860c38a11194b5bd.zip |
Merged Select with ComboBox (#2869)
Select now extends ComboBox instead of vice versa
Select is now deprecated in favor of ComboBox
Diffstat (limited to 'server/src/com/vaadin/ui/Select.java')
-rw-r--r-- | server/src/com/vaadin/ui/Select.java | 753 |
1 files changed, 3 insertions, 750 deletions
diff --git a/server/src/com/vaadin/ui/Select.java b/server/src/com/vaadin/ui/Select.java index 853a1efeab..ef8ba6d307 100644 --- a/server/src/com/vaadin/ui/Select.java +++ b/server/src/com/vaadin/ui/Select.java @@ -16,25 +16,9 @@ package com.vaadin.ui; -import java.util.ArrayList; import java.util.Collection; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; import com.vaadin.data.Container; -import com.vaadin.data.util.filter.SimpleStringFilter; -import com.vaadin.event.FieldEvents; -import com.vaadin.event.FieldEvents.BlurEvent; -import com.vaadin.event.FieldEvents.BlurListener; -import com.vaadin.event.FieldEvents.FocusEvent; -import com.vaadin.event.FieldEvents.FocusListener; -import com.vaadin.server.PaintException; -import com.vaadin.server.PaintTarget; -import com.vaadin.server.Resource; /** * <p> @@ -51,59 +35,10 @@ import com.vaadin.server.Resource; * * @author Vaadin Ltd. * @since 3.0 + * @deprecated as of 7.0. Use {@link ComboBox} instead. */ -@SuppressWarnings("serial") -public class Select extends AbstractSelect implements AbstractSelect.Filtering, - FieldEvents.BlurNotifier, FieldEvents.FocusNotifier { - - /** - * Holds value of property pageLength. 0 disables paging. - */ - protected int pageLength = 10; - - private int columns = 0; - - // Current page when the user is 'paging' trough options - private int currentPage = -1; - - private int filteringMode = FILTERINGMODE_STARTSWITH; - - private String filterstring; - private String prevfilterstring; - - /** - * Number of options that pass the filter, excluding the null item if any. - */ - private int filteredSize; - - /** - * Cache of filtered options, used only by the in-memory filtering system. - */ - private List<Object> filteredOptions; - - /** - * Flag to indicate that request repaint is called by filter request only - */ - private boolean optionRequest; - - /** - * True if the container is being filtered temporarily and item set change - * notifications should be suppressed. - */ - private boolean filteringContainer; - - /** - * Flag to indicate whether to scroll the selected item visible (select the - * page on which it is) when opening the popup or not. Only applies to - * single select mode. - * - * This requires finding the index of the item, which can be expensive in - * many large lazy loading containers. - */ - private boolean scrollToSelectedItem = true; - - /* Constructors */ - +@Deprecated +public class Select extends ComboBox { /* Component methods */ public Select() { @@ -122,686 +57,4 @@ public class Select extends AbstractSelect implements AbstractSelect.Filtering, super(caption); } - /** - * Paints the content of this component. - * - * @param target - * the Paint Event. - * @throws PaintException - * if the paint operation failed. - */ - @Override - public void paintContent(PaintTarget target) throws PaintException { - if (isMultiSelect()) { - // background compatibility hack. This object shouldn't be used for - // multiselect lists anymore (ListSelect instead). This fallbacks to - // a simpler paint method in super class. - super.paintContent(target); - // Fix for #4553 - target.addAttribute("type", "legacy-multi"); - return; - } - - // clear caption change listeners - getCaptionChangeListener().clear(); - - // The tab ordering number - if (getTabIndex() != 0) { - target.addAttribute("tabindex", getTabIndex()); - } - - // If the field is modified, but not committed, set modified attribute - if (isModified()) { - target.addAttribute("modified", true); - } - - if (isNewItemsAllowed()) { - target.addAttribute("allownewitem", true); - } - - boolean needNullSelectOption = false; - if (isNullSelectionAllowed()) { - target.addAttribute("nullselect", true); - needNullSelectOption = (getNullSelectionItemId() == null); - if (!needNullSelectOption) { - target.addAttribute("nullselectitem", true); - } - } - - // Constructs selected keys array - String[] selectedKeys; - if (isMultiSelect()) { - selectedKeys = new String[((Set<?>) getValue()).size()]; - } else { - selectedKeys = new String[(getValue() == null - && getNullSelectionItemId() == null ? 0 : 1)]; - } - - target.addAttribute("pagelength", pageLength); - - target.addAttribute("filteringmode", getFilteringMode()); - - // Paints the options and create array of selected id keys - int keyIndex = 0; - - target.startTag("options"); - - if (currentPage < 0) { - optionRequest = false; - currentPage = 0; - filterstring = ""; - } - - boolean nullFilteredOut = filterstring != null - && !"".equals(filterstring) - && filteringMode != FILTERINGMODE_OFF; - // null option is needed and not filtered out, even if not on current - // page - boolean nullOptionVisible = needNullSelectOption && !nullFilteredOut; - - // first try if using container filters is possible - List<?> options = getOptionsWithFilter(nullOptionVisible); - if (null == options) { - // not able to use container filters, perform explicit in-memory - // filtering - options = getFilteredOptions(); - filteredSize = options.size(); - options = sanitetizeList(options, nullOptionVisible); - } - - final boolean paintNullSelection = needNullSelectOption - && currentPage == 0 && !nullFilteredOut; - - if (paintNullSelection) { - target.startTag("so"); - target.addAttribute("caption", ""); - target.addAttribute("key", ""); - target.endTag("so"); - } - - final Iterator<?> i = options.iterator(); - // Paints the available selection options from data source - - while (i.hasNext()) { - - final Object id = i.next(); - - if (!isNullSelectionAllowed() && id != null - && id.equals(getNullSelectionItemId()) && !isSelected(id)) { - continue; - } - - // Gets the option attribute values - final String key = itemIdMapper.key(id); - final String caption = getItemCaption(id); - final Resource icon = getItemIcon(id); - getCaptionChangeListener().addNotifierForItem(id); - - // Paints the option - target.startTag("so"); - if (icon != null) { - target.addAttribute("icon", icon); - } - target.addAttribute("caption", caption); - if (id != null && id.equals(getNullSelectionItemId())) { - target.addAttribute("nullselection", true); - } - target.addAttribute("key", key); - if (isSelected(id) && keyIndex < selectedKeys.length) { - target.addAttribute("selected", true); - selectedKeys[keyIndex++] = key; - } - target.endTag("so"); - } - target.endTag("options"); - - target.addAttribute("totalitems", size() - + (needNullSelectOption ? 1 : 0)); - if (filteredSize > 0 || nullOptionVisible) { - target.addAttribute("totalMatches", filteredSize - + (nullOptionVisible ? 1 : 0)); - } - - // Paint variables - target.addVariable(this, "selected", selectedKeys); - if (isNewItemsAllowed()) { - target.addVariable(this, "newitem", ""); - } - - target.addVariable(this, "filter", filterstring); - target.addVariable(this, "page", currentPage); - - currentPage = -1; // current page is always set by client - - optionRequest = true; - } - - /** - * Returns the filtered options for the current page using a container - * filter. - * - * As a size effect, {@link #filteredSize} is set to the total number of - * items passing the filter. - * - * The current container must be {@link Filterable} and {@link Indexed}, and - * the filtering mode must be suitable for container filtering (tested with - * {@link #canUseContainerFilter()}). - * - * Use {@link #getFilteredOptions()} and - * {@link #sanitetizeList(List, boolean)} if this is not the case. - * - * @param needNullSelectOption - * @return filtered list of options (may be empty) or null if cannot use - * container filters - */ - protected List<?> getOptionsWithFilter(boolean needNullSelectOption) { - Container container = getContainerDataSource(); - - if (pageLength == 0) { - // no paging: return all items - filteredSize = container.size(); - return new ArrayList<Object>(container.getItemIds()); - } - - if (!(container instanceof Filterable) - || !(container instanceof Indexed) - || getItemCaptionMode() != ITEM_CAPTION_MODE_PROPERTY) { - return null; - } - - Filterable filterable = (Filterable) container; - - Filter filter = buildFilter(filterstring, filteringMode); - - // adding and removing filters leads to extraneous item set - // change events from the underlying container, but the ComboBox does - // not process or propagate them based on the flag filteringContainer - if (filter != null) { - filteringContainer = true; - filterable.addContainerFilter(filter); - } - - Indexed indexed = (Indexed) container; - - int indexToEnsureInView = -1; - - // if not an option request (item list when user changes page), go - // to page with the selected item after filtering if accepted by - // filter - Object selection = getValue(); - if (isScrollToSelectedItem() && !optionRequest && !isMultiSelect() - && selection != null) { - // ensure proper page - indexToEnsureInView = indexed.indexOfId(selection); - } - - filteredSize = container.size(); - currentPage = adjustCurrentPage(currentPage, needNullSelectOption, - indexToEnsureInView, filteredSize); - int first = getFirstItemIndexOnCurrentPage(needNullSelectOption, - filteredSize); - int last = getLastItemIndexOnCurrentPage(needNullSelectOption, - filteredSize, first); - - List<Object> options = new ArrayList<Object>(); - for (int i = first; i <= last && i < filteredSize; ++i) { - options.add(indexed.getIdByIndex(i)); - } - - // to the outside, filtering should not be visible - if (filter != null) { - filterable.removeContainerFilter(filter); - filteringContainer = false; - } - - return options; - } - - /** - * Constructs a filter instance to use when using a Filterable container in - * the <code>ITEM_CAPTION_MODE_PROPERTY</code> mode. - * - * Note that the client side implementation expects the filter string to - * apply to the item caption string it sees, so changing the behavior of - * this method can cause problems. - * - * @param filterString - * @param filteringMode - * @return - */ - protected Filter buildFilter(String filterString, int filteringMode) { - Filter filter = null; - - if (null != filterString && !"".equals(filterString)) { - switch (filteringMode) { - case FILTERINGMODE_OFF: - break; - case FILTERINGMODE_STARTSWITH: - filter = new SimpleStringFilter(getItemCaptionPropertyId(), - filterString, true, true); - break; - case FILTERINGMODE_CONTAINS: - filter = new SimpleStringFilter(getItemCaptionPropertyId(), - filterString, true, false); - break; - } - } - return filter; - } - - @Override - public void containerItemSetChange(Container.ItemSetChangeEvent event) { - if (!filteringContainer) { - super.containerItemSetChange(event); - } - } - - /** - * Makes correct sublist of given list of options. - * - * If paint is not an option request (affected by page or filter change), - * page will be the one where possible selection exists. - * - * Detects proper first and last item in list to return right page of - * options. Also, if the current page is beyond the end of the list, it will - * be adjusted. - * - * @param options - * @param needNullSelectOption - * flag to indicate if nullselect option needs to be taken into - * consideration - */ - private List<?> sanitetizeList(List<?> options, boolean needNullSelectOption) { - - if (pageLength != 0 && options.size() > pageLength) { - - int indexToEnsureInView = -1; - - // if not an option request (item list when user changes page), go - // to page with the selected item after filtering if accepted by - // filter - Object selection = getValue(); - if (isScrollToSelectedItem() && !optionRequest && !isMultiSelect() - && selection != null) { - // ensure proper page - indexToEnsureInView = options.indexOf(selection); - } - - int size = options.size(); - currentPage = adjustCurrentPage(currentPage, needNullSelectOption, - indexToEnsureInView, size); - int first = getFirstItemIndexOnCurrentPage(needNullSelectOption, - size); - int last = getLastItemIndexOnCurrentPage(needNullSelectOption, - size, first); - return options.subList(first, last + 1); - } else { - return options; - } - } - - /** - * Returns the index of the first item on the current page. The index is to - * the underlying (possibly filtered) contents. The null item, if any, does - * not have an index but takes up a slot on the first page. - * - * @param needNullSelectOption - * true if a null option should be shown before any other options - * (takes up the first slot on the first page, not counted in - * index) - * @param size - * number of items after filtering (not including the null item, - * if any) - * @return first item to show on the UI (index to the filtered list of - * options, not taking the null item into consideration if any) - */ - private int getFirstItemIndexOnCurrentPage(boolean needNullSelectOption, - int size) { - // Not all options are visible, find out which ones are on the - // current "page". - int first = currentPage * pageLength; - if (needNullSelectOption && currentPage > 0) { - first--; - } - return first; - } - - /** - * Returns the index of the last item on the current page. The index is to - * the underlying (possibly filtered) contents. If needNullSelectOption is - * true, the null item takes up the first slot on the first page, - * effectively reducing the first page size by one. - * - * @param needNullSelectOption - * true if a null option should be shown before any other options - * (takes up the first slot on the first page, not counted in - * index) - * @param size - * number of items after filtering (not including the null item, - * if any) - * @param first - * index in the filtered view of the first item of the page - * @return index in the filtered view of the last item on the page - */ - private int getLastItemIndexOnCurrentPage(boolean needNullSelectOption, - int size, int first) { - // page length usable for non-null items - int effectivePageLength = pageLength - - (needNullSelectOption && (currentPage == 0) ? 1 : 0); - return Math.min(size - 1, first + effectivePageLength - 1); - } - - /** - * Adjusts the index of the current page if necessary: make sure the current - * page is not after the end of the contents, and optionally go to the page - * containg a specific item. There are no side effects but the adjusted page - * index is returned. - * - * @param page - * page number to use as the starting point - * @param needNullSelectOption - * true if a null option should be shown before any other options - * (takes up the first slot on the first page, not counted in - * index) - * @param indexToEnsureInView - * index of an item that should be included on the page (in the - * data set, not counting the null item if any), -1 for none - * @param size - * number of items after filtering (not including the null item, - * if any) - */ - private int adjustCurrentPage(int page, boolean needNullSelectOption, - int indexToEnsureInView, int size) { - if (indexToEnsureInView != -1) { - int newPage = (indexToEnsureInView + (needNullSelectOption ? 1 : 0)) - / pageLength; - page = newPage; - } - // adjust the current page if beyond the end of the list - if (page * pageLength > size) { - page = (size + (needNullSelectOption ? 1 : 0)) / pageLength; - } - return page; - } - - /** - * Filters the options in memory and returns the full filtered list. - * - * This can be less efficient than using container filters, so use - * {@link #getOptionsWithFilter(boolean)} if possible (filterable container - * and suitable item caption mode etc.). - * - * @return - */ - protected List<?> getFilteredOptions() { - if (null == filterstring || "".equals(filterstring) - || FILTERINGMODE_OFF == filteringMode) { - prevfilterstring = null; - filteredOptions = new LinkedList<Object>(getItemIds()); - return filteredOptions; - } - - if (filterstring.equals(prevfilterstring)) { - return filteredOptions; - } - - Collection<?> items; - if (prevfilterstring != null - && filterstring.startsWith(prevfilterstring)) { - items = filteredOptions; - } else { - items = getItemIds(); - } - prevfilterstring = filterstring; - - filteredOptions = new LinkedList<Object>(); - for (final Iterator<?> it = items.iterator(); it.hasNext();) { - final Object itemId = it.next(); - String caption = getItemCaption(itemId); - if (caption == null || caption.equals("")) { - continue; - } else { - caption = caption.toLowerCase(); - } - switch (filteringMode) { - case FILTERINGMODE_CONTAINS: - if (caption.indexOf(filterstring) > -1) { - filteredOptions.add(itemId); - } - break; - case FILTERINGMODE_STARTSWITH: - default: - if (caption.startsWith(filterstring)) { - filteredOptions.add(itemId); - } - break; - } - } - - return filteredOptions; - } - - /** - * Invoked when the value of a variable has changed. - * - * @see com.vaadin.ui.AbstractComponent#changeVariables(java.lang.Object, - * java.util.Map) - */ - @Override - public void changeVariables(Object source, Map<String, Object> variables) { - // Not calling super.changeVariables due the history of select - // component hierarchy - - // Selection change - if (variables.containsKey("selected")) { - final String[] ka = (String[]) variables.get("selected"); - - if (isMultiSelect()) { - // Multiselect mode - - // TODO Optimize by adding repaintNotNeeded whan applicaple - - // Converts the key-array to id-set - final LinkedList<Object> s = new LinkedList<Object>(); - for (int i = 0; i < ka.length; i++) { - final Object id = itemIdMapper.get(ka[i]); - if (id != null && containsId(id)) { - s.add(id); - } - } - - // Limits the deselection to the set of visible items - // (non-visible items can not be deselected) - final Collection<?> visible = getVisibleItemIds(); - if (visible != null) { - @SuppressWarnings("unchecked") - Set<Object> newsel = (Set<Object>) getValue(); - if (newsel == null) { - newsel = new HashSet<Object>(); - } else { - newsel = new HashSet<Object>(newsel); - } - newsel.removeAll(visible); - newsel.addAll(s); - setValue(newsel, true); - } - } else { - // Single select mode - if (ka.length == 0) { - - // Allows deselection only if the deselected item is visible - final Object current = getValue(); - final Collection<?> visible = getVisibleItemIds(); - if (visible != null && visible.contains(current)) { - setValue(null, true); - } - } else { - final Object id = itemIdMapper.get(ka[0]); - if (id != null && id.equals(getNullSelectionItemId())) { - setValue(null, true); - } else { - setValue(id, true); - } - } - } - } - - String newFilter; - if ((newFilter = (String) variables.get("filter")) != null) { - // this is a filter request - currentPage = ((Integer) variables.get("page")).intValue(); - filterstring = newFilter; - if (filterstring != null) { - filterstring = filterstring.toLowerCase(); - } - requestRepaint(); - } else if (isNewItemsAllowed()) { - // New option entered (and it is allowed) - final String newitem = (String) variables.get("newitem"); - if (newitem != null && newitem.length() > 0) { - getNewItemHandler().addNewItem(newitem); - // rebuild list - filterstring = null; - prevfilterstring = null; - } - } - - if (variables.containsKey(FocusEvent.EVENT_ID)) { - fireEvent(new FocusEvent(this)); - } - if (variables.containsKey(BlurEvent.EVENT_ID)) { - fireEvent(new BlurEvent(this)); - } - - } - - @Override - @Deprecated - public void requestRepaint() { - markAsDirty(); - } - - @Override - public void setFilteringMode(int filteringMode) { - this.filteringMode = filteringMode; - } - - @Override - public int getFilteringMode() { - return filteringMode; - } - - @Override - public void addBlurListener(BlurListener listener) { - addListener(BlurEvent.EVENT_ID, BlurEvent.class, listener, - BlurListener.blurMethod); - } - - /** - * @deprecated Since 7.0, replaced by {@link #addBlurListener(BlurListener)} - **/ - @Deprecated - public void addListener(BlurListener listener) { - addBlurListener(listener); - } - - @Override - public void removeBlurListener(BlurListener listener) { - removeListener(BlurEvent.EVENT_ID, BlurEvent.class, listener); - } - - /** - * @deprecated Since 7.0, replaced by - * {@link #removeBlurListener(BlurListener)} - **/ - @Deprecated - public void removeListener(BlurListener listener) { - removeBlurListener(listener); - } - - @Override - public void addFocusListener(FocusListener listener) { - addListener(FocusEvent.EVENT_ID, FocusEvent.class, listener, - FocusListener.focusMethod); - } - - /** - * @deprecated Since 7.0, replaced by - * {@link #addFocusListener(FocusListener)} - **/ - @Deprecated - public void addListener(FocusListener listener) { - addFocusListener(listener); - } - - @Override - public void removeFocusListener(FocusListener listener) { - removeListener(FocusEvent.EVENT_ID, FocusEvent.class, listener); - } - - /** - * @deprecated Since 7.0, replaced by - * {@link #removeFocusListener(FocusListener)} - **/ - @Deprecated - public void removeListener(FocusListener listener) { - removeFocusListener(listener); - } - - /** - * @deprecated use {@link ListSelect}, {@link OptionGroup} or - * {@link TwinColSelect} instead - * @see com.vaadin.ui.AbstractSelect#setMultiSelect(boolean) - * @throws UnsupportedOperationException - * if trying to activate multiselect mode - */ - @Deprecated - @Override - public void setMultiSelect(boolean multiSelect) { - if (multiSelect) { - throw new UnsupportedOperationException("Multiselect not supported"); - } - } - - /** - * @deprecated use {@link ListSelect}, {@link OptionGroup} or - * {@link TwinColSelect} instead - * - * @see com.vaadin.ui.AbstractSelect#isMultiSelect() - */ - @Deprecated - @Override - public boolean isMultiSelect() { - return super.isMultiSelect(); - } - - /** - * Sets whether to scroll the selected item visible (directly open the page - * on which it is) when opening the combo box popup or not. Only applies to - * single select mode. - * - * This requires finding the index of the item, which can be expensive in - * many large lazy loading containers. - * - * @param scrollToSelectedItem - * true to find the page with the selected item when opening the - * selection popup - */ - public void setScrollToSelectedItem(boolean scrollToSelectedItem) { - this.scrollToSelectedItem = scrollToSelectedItem; - } - - /** - * Returns true if the select should find the page with the selected item - * when opening the popup (single select combo box only). - * - * @see #setScrollToSelectedItem(boolean) - * - * @return true if the page with the selected item will be shown when - * opening the popup - */ - public boolean isScrollToSelectedItem() { - return scrollToSelectedItem; - } - } |