package org.activityinfo.ui.client.component.table.filter; /* * #%L * ActivityInfo Server * %% * Copyright (C) 2009 - 2013 UNICEF * %% * 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.common.base.Strings; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.gwt.cell.client.CheckboxCell; import com.google.gwt.core.client.GWT; import com.google.gwt.dom.client.Style; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.KeyUpEvent; import com.google.gwt.event.dom.client.KeyUpHandler; import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiField; import com.google.gwt.uibinder.client.UiHandler; import com.google.gwt.user.cellview.client.Column; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.HTMLPanel; import com.google.gwt.view.client.DefaultSelectionEventManager; import com.google.gwt.view.client.ListDataProvider; import com.google.gwt.view.client.MultiSelectionModel; import org.activityinfo.core.client.ProjectionKeyProvider; import org.activityinfo.core.shared.Projection; import org.activityinfo.core.shared.criteria.Criteria; import org.activityinfo.core.shared.criteria.CriteriaUnion; import org.activityinfo.core.shared.criteria.CriteriaVisitor; import org.activityinfo.core.shared.criteria.FieldCriteria; import org.activityinfo.ui.client.widget.DataGrid; import org.activityinfo.ui.client.component.table.FieldColumn; import org.activityinfo.ui.client.component.table.InstanceTable; import org.activityinfo.ui.client.widget.TextBox; import java.util.*; /** * @author yuriyz on 4/3/14. */ public class FilterContentString extends Composite implements FilterContent { public static final String FILTER_GRID_HEIGHT = "250px"; public static final int CHECKBOX_COLUMN_WIDTH = 20; /** * Search box is shown if number of items is more or equals to SEARCH_BOX_PRESENCE_ITEM_COUNT. * Otherwise it's removed from filter panel. */ private static final int SEARCH_BOX_PRESENCE_ITEM_COUNT = 7; interface FilterContentStringUiBinder extends UiBinder<HTMLPanel, FilterContentString> { } private static FilterContentStringUiBinder uiBinder = GWT.create(FilterContentStringUiBinder.class); private final ListDataProvider<Projection> tableDataProvider = new ListDataProvider<>(); private final MultiSelectionModel<Projection> selectionModel = new MultiSelectionModel<>(new ProjectionKeyProvider()); private final FieldColumn column; private final InstanceTable table; private final DataGrid<Projection> filterGrid; private final List<Projection> allItems; @UiField TextBox textBox; @UiField HTMLPanel gridContainer; @UiField HTMLPanel textBoxContainer; public FilterContentString(InstanceTable table, FieldColumn column) { FilterDataGridResources.INSTANCE.dataGridStyle().ensureInjected(); initWidget(uiBinder.createAndBindUi(this)); this.table = table; this.column = column; textBox.addKeyUpHandler(new KeyUpHandler() { @Override public void onKeyUp(KeyUpEvent event) { filterData(); } }); final Column<Projection, Boolean> checkColumn = new Column<Projection, Boolean>(new CheckboxCell(true, false)) { @Override public Boolean getValue(Projection object) { return selectionModel.isSelected(object); } }; filterGrid = new DataGrid<>(100, FilterDataGridResources.INSTANCE); filterGrid.setSelectionModel(selectionModel, DefaultSelectionEventManager .<Projection>createCheckboxManager()); filterGrid.addColumn(checkColumn); filterGrid.addColumn(column); filterGrid.setColumnWidth(checkColumn, CHECKBOX_COLUMN_WIDTH, Style.Unit.PX); filterGrid.setHeight(FILTER_GRID_HEIGHT); filterGrid.setAutoHeaderRefreshDisabled(true); filterGrid.setAutoFooterRefreshDisabled(true); tableDataProvider.addDataDisplay(filterGrid); allItems = extractItems(table.getTable().getVisibleItems()); if (allItems.size() < SEARCH_BOX_PRESENCE_ITEM_COUNT) { textBoxContainer.remove(textBox); } filterData(); initByCriteriaVisit(); gridContainer.add(filterGrid); } private void initByCriteriaVisit() { final Criteria criteria = column.getCriteria(); if (criteria != null) { final CriteriaVisitor initializationVisitor = new CriteriaVisitor() { @Override public void visitFieldCriteria(FieldCriteria fieldCriteria) { for (Projection projection : allItems) { final Object valueAsObject = column.getFieldValue(projection); if (Objects.equals(valueAsObject, fieldCriteria.getValue())) { selectionModel.setSelected(projection, true); } } } @Override public void visitUnion(CriteriaUnion criteriaUnion) { for (Criteria criteria : criteriaUnion.getElements()) { criteria.accept(this); } } }; criteria.accept(initializationVisitor); } } private List<Projection> extractItems(List<Projection> visibleItems) { final SortedMap<String, Projection> labelToProjectionMap = Maps.newTreeMap(); for (Projection projection : visibleItems) { final String value = column.getValue(projection); if (!Strings.isNullOrEmpty(value) && !labelToProjectionMap.containsKey(value)) { labelToProjectionMap.put(value, projection); } } return Lists.newArrayList(labelToProjectionMap.values()); } private void filterData() { final String stringFilter = textBox.getValue(); final List<Projection> toShow = Lists.newArrayList(); for (Projection projection : allItems) { final String value = column.getValue(projection); if (Strings.isNullOrEmpty(stringFilter) || value.contains(stringFilter)) { toShow.add(projection); } } tableDataProvider.setList(toShow); } @Override public Criteria getCriteria() { final Set<Projection> selectedSet = selectionModel.getSelectedSet(); final List<Criteria> criteriaList = Lists.newArrayList(); for (Projection projection : selectedSet) { criteriaList.add(new FieldCriteria(column.getNode().getPath(), column.getFieldValue(projection))); } return new CriteriaUnion(criteriaList); } private void selectAll(boolean selectState) { for (Projection projection : tableDataProvider.getList()) { selectionModel.setSelected(projection, selectState); } } @UiHandler("selectAllButton") public void onSelectAll(ClickEvent event) { selectAll(true); } @UiHandler("deselectAllButton") public void onDeselectAll(ClickEvent event) { selectAll(false); } }