package edu.ualberta.med.biobank.widgets.report;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import edu.ualberta.med.biobank.common.reports.filters.FilterOperator;
import edu.ualberta.med.biobank.common.wrappers.ReportWrapper;
import edu.ualberta.med.biobank.model.EntityFilter;
import edu.ualberta.med.biobank.model.ReportFilter;
import edu.ualberta.med.biobank.model.ReportFilterValue;
public class FilterSelectWidget extends Composite {
private final ReportWrapper report;
private final Map<Integer, FilterRow> filterRowMap = new LinkedHashMap<Integer, FilterRow>();
private final Map<Integer, FilterData> previousDataMap = new HashMap<Integer, FilterData>();
private final Collection<ChangeListener<FilterChangeEvent>> listeners = new ArrayList<ChangeListener<FilterChangeEvent>>();
private Composite container;
public FilterSelectWidget(Composite parent, int style, ReportWrapper report) {
super(parent, style);
this.report = report;
init();
createContainer();
report.addPropertyChangeListener(
ReportWrapper.REPORT_COLUMN_COLLECTION_CACHE_KEY,
new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent event) {
if (!isDisposed()) {
createContainer();
}
}
});
}
public ReportWrapper getReport() {
return report;
}
public Collection<ReportFilter> getReportFilters() {
Set<ReportFilter> rfs = new HashSet<ReportFilter>();
int filterPosition = 0;
for (FilterRow filterRow : filterRowMap.values()) {
EntityFilter entityFilter = filterRow.getEntityFilter();
ReportFilter reportFilter = new ReportFilter();
reportFilter.setPosition(filterPosition);
reportFilter.setEntityFilter(entityFilter);
reportFilter.setReportFilterValues(filterRow.getValues());
if (filterRow.getOperator() != null) {
reportFilter.setOperator(filterRow.getOperator().getId());
}
rfs.add(reportFilter);
filterPosition++;
}
return rfs;
}
public void addFilterChangedListener(
ChangeListener<FilterChangeEvent> listener) {
if (!listeners.contains(listener)) {
listeners.add(listener);
}
}
public void removeFilterChangedListener(
ChangeListener<FilterChangeEvent> listener) {
listeners.remove(listener);
}
public FilterRow getFilterRow(EntityFilter entityFilter) {
return filterRowMap.get(entityFilter.getId());
}
public FilterRow addFilterRow(EntityFilter entityFilter) {
FilterRow filterRow = null;
Integer id = entityFilter.getId();
if (!filterRowMap.containsKey(id)) {
showContainer(true);
filterRow = new FilterRow(this, container, SWT.NONE, entityFilter);
filterRowMap.put(id, filterRow);
recall(filterRow);
}
return filterRow;
}
void notifyListeners(FilterChangeEvent event) {
for (ChangeListener<FilterChangeEvent> listener : listeners) {
listener.handleEvent(event);
}
}
void removeFilterRow(EntityFilter entityFilter) {
Integer id = entityFilter.getId();
FilterRow filterRow = filterRowMap.get(id);
if (filterRow != null) {
remember(filterRow);
filterRowMap.remove(id);
filterRow.dispose();
if (filterRowMap.isEmpty()) {
showContainer(false);
}
}
}
private void init() {
GridLayout layout = new GridLayout(1, false);
layout.horizontalSpacing = 0;
layout.verticalSpacing = 0;
layout.marginWidth = 0;
layout.marginHeight = 0;
layout.marginBottom = 15;
setLayout(layout);
GridData layoutData = new GridData(GridData.FILL_HORIZONTAL);
layoutData.grabExcessHorizontalSpace = true;
layoutData.minimumHeight = 0;
setLayoutData(layoutData);
}
private void disposeRows() {
if (container != null && !container.isDisposed()) {
container.dispose();
}
filterRowMap.clear();
}
private void createContainer() {
disposeRows();
container = new Composite(this, SWT.NONE);
GridLayout layout = new GridLayout(1, false);
layout.horizontalSpacing = 0;
layout.verticalSpacing = 0;
layout.marginWidth = 0;
layout.marginHeight = 0;
container.setLayout(layout);
GridData layoutData = new GridData(GridData.FILL_HORIZONTAL);
layoutData.grabExcessHorizontalSpace = true;
layoutData.minimumHeight = 0;
layoutData.horizontalIndent = 0;
layoutData.verticalIndent = 0;
container.setLayoutData(layoutData);
showContainer(false);
Collection<ReportFilter> reportFilters = report
.getReportFilterCollection();
for (ReportFilter reportFilter : reportFilters) {
addFilterRow(reportFilter);
}
}
private void showContainer(boolean isShown) {
if (isShown == container.getVisible()) {
return;
}
GridData layoutData = (GridData) container.getLayoutData();
layoutData.exclude = !isShown;
container.setVisible(isShown);
}
private FilterRow addFilterRow(ReportFilter reportFilter) {
FilterRow filterRow = addFilterRow(reportFilter.getEntityFilter());
if (filterRow != null) {
// it's important to set the operator before setting the values so
// that if the values do not apply to the default operator they will
// not be lost
if (reportFilter.getOperator() != null) {
filterRow.setOperatorId(reportFilter.getOperator());
}
filterRow.setValues(reportFilter.getReportFilterValues());
}
return filterRow;
}
private static class FilterData {
public Collection<ReportFilterValue> values;
public FilterOperator op;
}
private void remember(FilterRow filterRow) {
FilterData data = new FilterData();
data.op = filterRow.getOperator();
data.values = filterRow.getValues();
previousDataMap.put(filterRow.getEntityFilter().getId(), data);
}
private void recall(FilterRow filterRow) {
Integer id = filterRow.getEntityFilter().getId();
FilterData data = previousDataMap.get(id);
if (data != null) {
filterRow.setOperator(data.op);
filterRow.setValues(data.values);
}
}
}