package au.com.vaadinutils.fields; import org.vaadin.tokenfield.TokenField; /** * Provides a text box that auto-completes to build up a list of entities. */ import au.com.vaadinutils.crud.CrudEntity; import au.com.vaadinutils.dao.JpaBaseDao; import com.vaadin.addon.jpacontainer.JPAContainer; import com.vaadin.shared.ui.combobox.FilteringMode; import com.vaadin.ui.Button; import com.vaadin.ui.Notification; import com.vaadin.ui.themes.Reindeer; public class EntityAutoCompleteField<E extends CrudEntity, D extends JpaBaseDao<E, Long>> extends TokenField { private static final long serialVersionUID = 1L; private JpaBaseDao<E, Long> dao; private AutoCompleteParent<E> parent; public EntityAutoCompleteField(JPAContainer<E> container, D dao, String fieldLabel, AutoCompleteParent<E> parent) { super(fieldLabel); this.dao = dao; this.parent = parent; this.setStyleName(TokenField.STYLE_TOKENFIELD); this.setInputPrompt(""); this.setContainerDataSource(container); this.setWidth("100%"); // width... this.setInputWidth("100%"); // and input width separately this.setFilteringMode(FilteringMode.CONTAINS); // suggest this.setTokenCaptionPropertyId("fullname"); // use container item property // "name" in input this.setRememberNewTokens(false); // we can opt to do this ourselves this.setImmediate(true); } /** * Called when the user hits 'enter' or the 'tab' key to indicate that they * have finished entering entities. The tokenId may contain one or more * comma separated entities or entity ids. * * The tokenId can either be a Long in which case it is the id of an * existing entity or can be a string in which case it is the text the user * typed in as the token meaning that the tag does not already exist. */ @Override protected void onTokenInput(Object tokenId) { if (tokenId instanceof String) { Notification.show("The entity " + tokenId + " does not exist."); } else { // The token Id is an Entity Id of type Long. Long entityId = (Long) tokenId; E entity = dao.findById(entityId); if (entity != null) { // Now check if the entity is already associated with the entity if (parent.hasEntity(entity)) { Notification.show(getTokenCaption(entity.getId()) + " is already associated with this entity"); } else { parent.attachEntity(entity); this.addToken(entity.getId()); } } else throw new IllegalStateException("Entity with id=" + entityId + " is missing from db."); } } @Override protected void rememberToken(String tokenId) { String[] tokens = tokenId.split(","); for (String token : tokens) { token = token.trim(); if (token.length() > 0) { super.rememberToken(token); } } } // customize caption protected void configureTokenButton(Object tokenId, Button button) { // custom caption if (tokenId instanceof Long) { Long tagid = (Long) tokenId; E entity = dao.findById(tagid); button.setCaption(entity.getName() + " x"); button.setDescription("Click to remove"); button.setIcon(getTokenIcon(tokenId)); button.setStyleName(Reindeer.BUTTON_LINK); } else { @SuppressWarnings("unchecked") E entity = (E) tokenId; button.setCaption(entity.getName() + " x"); button.setDescription("Click to remove"); button.setIcon(getTokenIcon(tokenId)); button.setStyleName(Reindeer.BUTTON_LINK); } // throw new // IllegalArgumentException("Expected tokenId to be a Entity instead found a " // + tokenId.getClass().getName()); } /** * The users has clicked the token which we treat as a delete. */ @Override protected void onTokenClick(Object tokenId) { @SuppressWarnings("unchecked") E entity = (E) tokenId; parent.detachEntity(entity); super.onTokenClick(tokenId); } }