gwt.material.design.addins.client.ui.MaterialAutoComplete.java Source code

Java tutorial

Introduction

Here is the source code for gwt.material.design.addins.client.ui.MaterialAutoComplete.java

Source

package gwt.material.design.addins.client.ui;

/*
 * #%L
 * GwtMaterial
 * %%
 * Copyright (C) 2015 GwtMaterialDesign
 * %%
 * 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.
 * #L%
 */

import com.google.gwt.dom.client.Document;
import com.google.gwt.event.dom.client.*;
import com.google.gwt.event.logical.shared.SelectionEvent;
import com.google.gwt.event.logical.shared.SelectionHandler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.ui.*;
import gwt.material.design.addins.client.base.MaterialSuggestionOracle;
import gwt.material.design.addins.client.constants.AutocompleteType;
import gwt.material.design.client.base.*;
import gwt.material.design.client.base.mixin.CssTypeMixin;
import gwt.material.design.client.base.mixin.ErrorMixin;
import gwt.material.design.client.base.mixin.ProgressMixin;
import gwt.material.design.client.constants.IconType;
import gwt.material.design.client.constants.ProgressType;
import gwt.material.design.client.ui.MaterialChip;
import gwt.material.design.client.ui.MaterialLabel;
import gwt.material.design.client.ui.html.ListItem;
import gwt.material.design.client.ui.html.UnorderedList;

import java.util.*;

//@formatter:off
/**
 * Use GWT Autocomplete to search for matches from local or remote data sources.
 * We used MultiWordSuggestOracle to populate the list to be added on the
 * autocomplete values.
 *
 * <h3>UiBinder Usage:</h3>
 * <pre>
 * {@code
 *  <m:MaterialAutoComplete ui:field="autocomplete" placeholder="States" />}
 * </pre>
 *
 * @author kevzlou7979
 * @see <a href="http://gwt-material-demo.herokuapp.com/#autocompletes">Material AutoComplete</a>
 */
//@formatter:on
public class MaterialAutoComplete extends MaterialWidget
        implements HasError, HasPlaceholder, HasValue<List<? extends SuggestOracle.Suggestion>>, HasProgress,
        HasKeyUpHandlers, HasType<AutocompleteType> {

    private List<String> itemValues = new ArrayList<>();
    private List<ListItem> itemsHighlighted = new ArrayList<>();
    private FlowPanel panel = new FlowPanel();
    private UnorderedList list = new UnorderedList();
    private MultiWordSuggestOracle suggestions;
    private TextBox itemBox = new TextBox();
    private int limit = 0;
    private MaterialLabel lblError = new MaterialLabel();
    private Map<String, Map.Entry<SuggestOracle.Suggestion, MaterialChip>> suggestionMap = new LinkedHashMap<>();

    private final ErrorMixin<MaterialAutoComplete, MaterialLabel> errorMixin = new ErrorMixin<>(this, lblError,
            list);
    private final ProgressMixin<MaterialAutoComplete> progressMixin = new ProgressMixin<>(this);
    public final CssTypeMixin<AutocompleteType, MaterialAutoComplete> typeMixin = new CssTypeMixin<>(this);

    /**
     * Use MaterialAutocomplete to search for matches from
     * local or remote data sources.
     */
    public MaterialAutoComplete() {
        super(Document.get().createDivElement());
        add(panel);
    }

    /**
     * Use MaterialAutocomplete to search for matches from
     * local or remote data sources.
     */
    public MaterialAutoComplete(MaterialSuggestionOracle suggestions) {
        this();
        generateAutoComplete(suggestions);
    }

    /**
     * Generate and build the List Items to be set on Auto Complete box.
     */
    private void generateAutoComplete(MaterialSuggestionOracle suggestions) {
        list.setStyleName("multiValueSuggestBox-list");
        this.suggestions = suggestions;
        final ListItem item = new ListItem();

        item.setStyleName("multiValueSuggestBox-input-token");
        final SuggestBox box = new SuggestBox(suggestions, itemBox);
        String autocompleteId = DOM.createUniqueId();
        itemBox.getElement().setId(autocompleteId);

        item.add(box);
        list.add(item);

        itemBox.addKeyDownHandler(new KeyDownHandler() {
            public void onKeyDown(KeyDownEvent event) {
                switch (event.getNativeKeyCode()) {
                case KeyCodes.KEY_ENTER:
                    addItem(itemBox, list);
                    break;

                case KeyCodes.KEY_BACKSPACE:
                    if (itemBox.getValue().trim().isEmpty()) {
                        if (itemsHighlighted.isEmpty()) {
                            if (itemValues.size() > 0) {
                                ListItem li = (ListItem) list.getWidget(list.getWidgetCount() - 2);
                                MaterialChip p = (MaterialChip) li.getWidget(0);
                                if (itemValues.contains(p.getText())) {
                                    itemValues.remove(p.getText());
                                }
                                list.remove(li);
                            }
                        }
                    }

                case KeyCodes.KEY_DELETE:
                    if (itemBox.getValue().trim().isEmpty()) {
                        for (ListItem li : itemsHighlighted) {
                            li.removeFromParent();
                            MaterialChip p = (MaterialChip) li.getWidget(0);
                            itemValues.remove(p.getText());
                        }
                        itemsHighlighted.clear();
                    }
                    itemBox.setFocus(true);
                    break;
                }
            }
        });

        itemBox.addClickHandler(new ClickHandler() {

            @Override
            public void onClick(ClickEvent event) {
                box.showSuggestionList();
            }
        });

        box.addSelectionHandler(new SelectionHandler<SuggestOracle.Suggestion>() {
            public void onSelection(SelectionEvent<SuggestOracle.Suggestion> selectionEvent) {
                addItem(itemBox, list);
            }
        });

        panel.add(list);
        panel.getElement().setAttribute("onclick", "document.getElementById('" + autocompleteId + "').focus()");
        panel.add(lblError);
        box.setFocus(true);
    }

    /**
     * Adding the item value using Material Chips added on auto complete box
     */
    private void addItem(final TextBox itemBox, final UnorderedList list) {
        if (getLimit() > 0) {
            if (itemValues.size() == getLimit()) {
                itemBox.setValue("");
                return;
            }
        }

        String value = itemBox.getValue();
        if (value != null && !"".equals(value.trim()) && !itemValues.contains(value.trim())) {

            final ListItem displayItem = new ListItem();
            displayItem.setStyleName("multiValueSuggestBox-token");

            String imageChip = value;
            String textChip = value;
            final MaterialChip chip = new MaterialChip();

            String s = "<img src=\"";
            if (imageChip.contains(s)) {
                int ix = imageChip.indexOf(s) + s.length();
                imageChip = imageChip.substring(ix, imageChip.indexOf("\"", ix + 1));
                chip.setUrl(imageChip);
                textChip = textChip.replaceAll("[<](/)?img[^>]*[>]", "");
            }
            chip.setIconType(IconType.CLOSE);
            chip.setText(textChip);
            chip.addClickHandler(new ClickHandler() {
                public void onClick(ClickEvent clickEvent) {
                    if (itemsHighlighted.contains(displayItem)) {
                        chip.removeStyleName("blue white-text");
                        itemsHighlighted.remove(displayItem);
                    } else {
                        chip.addStyleName("blue white-text");
                        itemsHighlighted.add(displayItem);
                    }
                }
            });

            chip.getIcon().addClickHandler(new ClickHandler() {
                public void onClick(ClickEvent clickEvent) {
                    itemValues.remove(chip.getText());
                    list.remove(displayItem);
                }
            });

            if (!itemValues.contains(textChip)) {
                displayItem.add(chip);
                itemValues.add(chip.getText());
                list.insert(displayItem, list.getWidgetCount() - 1);
                itemBox.setValue("");
                itemBox.setFocus(true);
            } else {
                itemBox.setValue("");
            }
        } else {
            itemBox.setValue("");
        }
    }

    /**
     * Clear the chip items on the autocomplete box
     */
    public void clear() {
        ListItem tagToRemove;
        int num = list.getWidgetCount();
        for (int i = num - 1; i >= 0; i--) {
            tagToRemove = ((ListItem) list.getWidget(i));
            tagToRemove.removeFromParent();
        }
    }

    /**
     * @return the item values on  autocomplete
     */
    public List<String> getItemValues() {
        return itemValues;
    }

    /**
     * @param itemValues the itemsSelected to set
     */
    public void setItemValues(List<String> itemValues) {
        this.itemValues = itemValues;
    }

    /**
     * @return the itemsHighlighted
     */
    public List<ListItem> getItemsHighlighted() {
        return itemsHighlighted;
    }

    /**
     * @param itemsHighlighted the itemsHighlighted to set
     */
    public void setItemsHighlighted(List<ListItem> itemsHighlighted) {
        this.itemsHighlighted = itemsHighlighted;
    }

    /**
     * @return the suggestions
     */
    public MultiWordSuggestOracle getSuggestions() {
        return suggestions;
    }

    /**
     * @param suggestions the suggestions to set
     */
    public void setSuggestions(MaterialSuggestionOracle suggestions) {
        this.suggestions = suggestions;
        generateAutoComplete(suggestions);
    }

    public int getLimit() {
        return limit;
    }

    public void setLimit(int limit) {
        this.limit = limit;
    }

    @Override
    public String getPlaceholder() {
        return itemBox.getElement().getAttribute("placeholder");
    }

    @Override
    public void setPlaceholder(String placeholder) {
        itemBox.getElement().setAttribute("placeholder", placeholder);
    }

    @Override
    public void setError(String error) {
        errorMixin.setError(error);
    }

    @Override
    public void setSuccess(String success) {
        errorMixin.setSuccess(success);
    }

    @Override
    public void clearErrorOrSuccess() {
        errorMixin.clearErrorOrSuccess();
    }

    @Override
    public void showProgress(ProgressType type) {
        progressMixin.showProgress(type);
    }

    @Override
    public void setPercent(double percent) {
        progressMixin.setPercent(percent);
    }

    @Override
    public void hideProgress() {
        progressMixin.hideProgress();
    }

    @Override
    public HandlerRegistration addKeyUpHandler(KeyUpHandler handler) {
        return itemBox.addKeyUpHandler(handler);
    }

    @Override
    public void setType(AutocompleteType type) {
        typeMixin.setType(type);
    }

    @Override
    public AutocompleteType getType() {
        return typeMixin.getType();
    }

    @Override
    public List<? extends SuggestOracle.Suggestion> getValue() {
        Collection<Map.Entry<SuggestOracle.Suggestion, MaterialChip>> values = suggestionMap.values();
        List<SuggestOracle.Suggestion> retList = new ArrayList<>(values.size());
        for (Map.Entry<SuggestOracle.Suggestion, MaterialChip> value : values) {
            retList.add(value.getKey());
        }
        return retList;
    }

    @Override
    public void setValue(List<? extends SuggestOracle.Suggestion> value) {
        setValue(value, false);
    }

    @Override
    public void setValue(List<? extends SuggestOracle.Suggestion> value, boolean fireEvents) {
        clear();
        if (value != null) {
            for (SuggestOracle.Suggestion suggestion : value) {
                //addItem(suggestion);
            }
        }
        if (fireEvents) {
            ValueChangeEvent.fire(this, getValue());
        }
    }

    private void addItem(Suggestion suggestion) {
    }

    @Override
    public HandlerRegistration addValueChangeHandler(
            ValueChangeHandler<List<? extends SuggestOracle.Suggestion>> handler) {
        return addHandler(handler, ValueChangeEvent.getType());
    }
}