package org.sigmah.client.ui.widget.form; /* * #%L * Sigmah * %% * Copyright (C) 2010 - 2016 URD * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program. If not, see * <http://www.gnu.org/licenses/gpl-3.0.html>. * #L% */ import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.FlexTable; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.Panel; import com.google.gwt.user.client.ui.Widget; import com.extjs.gxt.ui.client.data.ModelData; import com.extjs.gxt.ui.client.event.ButtonEvent; import com.extjs.gxt.ui.client.event.SelectionListener; import com.extjs.gxt.ui.client.store.ListStore; import com.extjs.gxt.ui.client.store.StoreEvent; import com.extjs.gxt.ui.client.store.StoreListener; import com.extjs.gxt.ui.client.widget.button.Button; import com.extjs.gxt.ui.client.widget.form.ComboBox; import com.extjs.gxt.ui.client.widget.form.Field; import org.sigmah.client.i18n.I18N; import org.sigmah.client.ui.res.icon.IconImageBundle; import org.sigmah.client.ui.widget.button.ClickableLabel; import org.sigmah.client.util.ClientUtils; public class ListComboBox<T extends ModelData> extends Composite { private ListStore<T> dataStore = new ListStore<T>(); private ListStore<T> availableValuesStore = new ListStore<T>(); private String noAvailableValueTooltip; private ComboBox<T> comboBox; private String valueField; private String displayField; private FlexTable flexTable; private FlowPanel formPanel; private Panel rootPanel; private boolean enabled = true; public ListComboBox(String valueField, String displayField) { super(); this.valueField = valueField; this.displayField = displayField; dataStore.addStoreListener(new StoreListener<T>() { @Override public void storeAdd(StoreEvent<T> se) { super.storeAdd(se); ListComboBox.this.buildComponent(); } @Override public void storeClear(StoreEvent<T> se) { super.storeClear(se); ListComboBox.this.buildComponent(); } @Override public void storeRemove(StoreEvent<T> se) { super.storeRemove(se); ListComboBox.this.buildComponent(); } @Override public void storeDataChanged(StoreEvent<T> se) { super.storeDataChanged(se); ListComboBox.this.buildComponent(); } }); availableValuesStore.addStoreListener(new StoreListener<T>() { @Override public void storeAdd(StoreEvent<T> se) { super.storeAdd(se); ListComboBox.this.buildComponent(); } @Override public void storeClear(StoreEvent<T> se) { super.storeClear(se); ListComboBox.this.buildComponent(); } @Override public void storeRemove(StoreEvent<T> se) { super.storeRemove(se); ListComboBox.this.buildComponent(); } }); } public void initComponent() { rootPanel = new FlowPanel(); flexTable = new FlexTable(); flexTable.setWidth("300px"); buildComponent(); initWidget(rootPanel); } public ListStore<T> getListStore() { return dataStore; } public ListStore<T> getAvailableValuesStore() { return availableValuesStore; } public Field<T> getField() { return comboBox; } public void copyAvailableValueStore(ListStore<T> store) { availableValuesStore.add(store.getModels()); store.addStoreListener(new StoreListener<T>() { @Override public void storeAdd(StoreEvent<T> se) { super.storeAdd(se); availableValuesStore.add(se.getModels()); } @Override public void storeRemove(StoreEvent<T> se) { super.storeRemove(se); for (T model : se.getModels()) { availableValuesStore.remove(model); } } }); } public void setNoAvailableValueTooltip(String noAvailableValueTooltip) { this.noAvailableValueTooltip = noAvailableValueTooltip; } public boolean isEnabled() { return enabled; } public void setEnabled(boolean enabled) { this.enabled = enabled; } protected void buildComponent() { if (rootPanel == null) { // not yet initialized return; } rootPanel.clear(); formPanel = new FlowPanel(); formPanel.addStyleName("list-combobox__form"); if (enabled) { comboBox = Forms.combobox(null, false, valueField, displayField, availableValuesStore); comboBox.setStyleName("list-combobox__form__choices"); if (availableValuesStore.getModels().isEmpty() && !ClientUtils.isBlank(noAvailableValueTooltip)) { comboBox.setToolTip(noAvailableValueTooltip); } formPanel.add(comboBox); Button addButton = new Button(I18N.CONSTANTS.addItem(), IconImageBundle.ICONS.add()); addButton.addSelectionListener(new SelectionListener<ButtonEvent>() { @Override public void componentSelected(ButtonEvent event) { T value = comboBox.getValue(); if (value == null) { return; } if (dataStore.findModel(valueField, value.get(valueField)) != null) { return; } availableValuesStore.remove(value); dataStore.add(value); } }); formPanel.add(addButton); } else { comboBox = null; } formPanel.setWidth("100%"); rootPanel.add(formPanel); FlowPanel elementsPanel = new FlowPanel(); elementsPanel.setStyleName("list-combobox__elements"); for (int i = 0; i < dataStore.getModels().size(); i++) { final T element = dataStore.getModels().get(i); Widget label; if (enabled) { label = new ClickableLabel(element.get(displayField).toString()); label.addStyleName("list-combobox__elements__element"); ((ClickableLabel)label).addClickHandler(new ClickHandler() { @Override public void onClick(final ClickEvent event) { availableValuesStore.add(element); dataStore.remove(element); } }); } else { label = new Label(i == 0 ? element.get(displayField).toString() : ", " + element.get(displayField).toString()); } elementsPanel.add(label); } rootPanel.add(elementsPanel); } protected Panel getButtonPanel() { return formPanel; } }