package fr.openwide.core.wicket.more.markup.html.select2; import java.util.Collection; import java.util.List; import org.apache.wicket.AttributeModifier; import org.apache.wicket.Component; import org.apache.wicket.markup.html.form.IChoiceRenderer; import org.apache.wicket.model.IModel; import org.apache.wicket.model.LoadableDetachableModel; import org.retzlaff.select2.Select2Behavior; import org.retzlaff.select2.Select2Settings; import com.google.common.base.Supplier; import fr.openwide.core.wicket.markup.html.form.ListMultipleChoice; import fr.openwide.core.wicket.markup.html.model.ConcreteCollectionToCollectionWrapperModel; import fr.openwide.core.wicket.more.markup.html.model.MultipleChoicesWrapperModel; import fr.openwide.core.wicket.more.markup.html.select2.util.DropDownChoiceWidth; import fr.openwide.core.wicket.more.markup.html.select2.util.IDropDownChoiceWidth; import fr.openwide.core.wicket.more.markup.html.select2.util.Select2Utils; public abstract class GenericSelect2DropDownMultipleChoice<T> extends ListMultipleChoice<T> { private static final long serialVersionUID = -6179538711780820058L; private IDropDownChoiceWidth width = DropDownChoiceWidth.AUTO; private MultipleChoicesWrapperModel<T> choicesWrapperModel; private final Select2Behavior<T, T> select2Behavior; /** * @param id The wicket ID. * @param collectionModel The model containing the selected elements. * @param collectionSupplier A factory for new, empty collections to be put in <code>collectionModel</code> * @param choicesModel The model containing the selectable elements. * @param renderer The choice renderer. */ protected <C extends Collection<T>> GenericSelect2DropDownMultipleChoice( String id, IModel<C> collectionModel, Supplier<? extends C> collectionSupplier, IModel<? extends Collection<? extends T>> choicesModel, IChoiceRenderer<? super T> renderer) { super(id); setModel(new ConcreteCollectionToCollectionWrapperModel<T, C>(collectionModel, collectionSupplier)); choicesWrapperModel = new MultipleChoicesWrapperModel<T>(collectionModel, choicesModel); setChoices(choicesWrapperModel); setSelectedObjectForcedInChoices(true); setChoiceRenderer(renderer); select2Behavior = Select2Behavior.forChoice(this); fillSelect2Settings(select2Behavior.getSettings()); add(select2Behavior); } @SuppressWarnings("unchecked") protected void ensureChoicesModelIsWrapped() { /* * Ideally this wrapping should be done in setChoices(IModel) or in wrap(IModel), * but those methods cannot be overriden... */ IModel<? extends List<? extends T>> choicesModel = getChoicesModel(); if (choicesModel != choicesWrapperModel) { if (choicesModel instanceof MultipleChoicesWrapperModel) { this.choicesWrapperModel = (MultipleChoicesWrapperModel<T>) choicesModel; } else { this.choicesWrapperModel = new MultipleChoicesWrapperModel<>(getModel(), choicesModel); setChoices(choicesWrapperModel); } } } @Override protected void onInitialize() { ensureChoicesModelIsWrapped(); super.onInitialize(); add(new AttributeModifier("style", new LoadableDetachableModel<String>() { private static final long serialVersionUID = 1L; @Override protected String load() { return "width: " + width.getWidth(); } }) { private static final long serialVersionUID = 1L; @Override public boolean isEnabled(Component component) { return width != null; } }); } @Override protected void onConfigure() { ensureChoicesModelIsWrapped(); super.onConfigure(); if (isRequired()) { Select2Utils.setRequiredSettings(getSettings()); } } protected void fillSelect2Settings(Select2Settings settings) { Select2Utils.setDefaultSettings(settings); } protected final Select2Settings getSettings() { return select2Behavior.getSettings(); } public GenericSelect2DropDownMultipleChoice<T> setWidth(IDropDownChoiceWidth width) { this.width = width; return this; } public boolean isSelectedObjectForcedInChoices() { return choicesWrapperModel.isSelectedObjectForcedInChoices(); } public GenericSelect2DropDownMultipleChoice<T> setSelectedObjectForcedInChoices(boolean selectedObjectForcedInChoices) { choicesWrapperModel.setSelectedObjectForcedInChoices(selectedObjectForcedInChoices); return this; } }