blob: 9a5da1f0d85fd482209279e6d0fcdd73c98c7cd9 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2014 Formal Mind GmbH.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Michael Jastram - initial API and implementation
******************************************************************************/
package org.eclipse.rmf.reqif10.search.filter.ui;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ComboViewer;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.rmf.reqif10.AttributeDefinition;
import org.eclipse.rmf.reqif10.ReqIF;
import org.eclipse.rmf.reqif10.SpecType;
import org.eclipse.rmf.reqif10.search.filter.AbstractTextFilter;
import org.eclipse.rmf.reqif10.search.filter.DateFilter;
import org.eclipse.rmf.reqif10.search.filter.IFilter;
import org.eclipse.rmf.reqif10.search.filter.StringFilter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
/**
* The {@link FilterPanel} initially only offers the selection of Attributes.
* Upon selecting one, the fitting criteria are offered by instantiating the
* correct {@link FilterControl}.
*
* @author jastram
*/
public class FilterPanel extends Composite {
private ReqIF reqif;
private ComboViewer attributeCombo;
/**
* This constructor creates an empty {@link FilterPanel}.
*/
public FilterPanel(final Composite parent, ReqIF reqif) {
super(parent, SWT.BORDER);
this.reqif = reqif;
setLayout(new GridLayout(3, false));
createCloseButton(parent);
createAttributeCombo();
}
/**
* This constructor uses an existing {@link IFilter} to populate the panel.
*/
public FilterPanel(Composite parent, ReqIF reqif, IFilter filter) {
this(parent, reqif);
// see whether the attribute of the filter still exists
Object[] input = ((Object[])attributeCombo.getInput());
int attributeIndex = Arrays.asList(input).indexOf(filter.getAttribute());
if (attributeIndex == -1) return;
attributeCombo.getCombo().select(attributeIndex);
FilterControl filterControl = FilterControl.createFilterControl(this, filter);
filterControl.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
layout();
getParent().pack();
}
/**
* The close button disposes the {@link FilterPanel} and repacks the parent.
* @param parent
*/
private void createCloseButton(final Composite parent) {
Label close = new Label(this, SWT.FLAT);
close.setText("\u2716");
close.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false));
close.addMouseListener(new MouseAdapter() {
@Override
public void mouseUp(MouseEvent e) {
dispose();
parent.pack();
}
});
}
/**
* Create the combo that contains both internal attributes and the model's
* attributes. Upon selection change, the corresponding
* {@link FilterControl} is built.
*/
private void createAttributeCombo() {
attributeCombo = new ComboViewer(this, SWT.DROP_DOWN | SWT.BORDER
| SWT.READ_ONLY);
GridData layoutData = new GridData(SWT.LEFT, SWT.CENTER, false, false);
layoutData.widthHint = 180;
attributeCombo.getControl().setLayoutData(layoutData);
attributeCombo.setLabelProvider(new AttributeLabelProvider());
attributeCombo.setContentProvider(new ArrayContentProvider());
attributeCombo.setInput(createAttributeInput().toArray());
attributeCombo
.addSelectionChangedListener(new ISelectionChangedListener() {
@Override
public void selectionChanged(SelectionChangedEvent event) {
if (!event.getSelection().isEmpty()) {
Object selectedAttr = ((IStructuredSelection) event
.getSelection()).getFirstElement();
attributeChanged(selectedAttr);
}
}
});
}
/**
* Create a {@link List} that acts as the input for {@link #attributeCombo}.
* The list is first sorted by {@link SpecType} and then sorted by
* {@link AttributeDefinition}.
*/
private List<?> createAttributeInput() {
List<? super Object> list = new ArrayList<Object>();
// Internal Attributes
list.addAll(Arrays.asList(StringFilter.InternalAttribute.values()));
list.addAll(Arrays.asList(DateFilter.InternalAttribute.values()));
// All Attributes in the model
Map<String, AttributeDefinition> attributes = new HashMap<String, AttributeDefinition>();
for (SpecType specType : reqif.getCoreContent().getSpecTypes()) {
for (AttributeDefinition ad : specType.getSpecAttributes()) {
attributes.put(specType.getLongName() + "." + ad.getLongName() + "." + ad.getIdentifier(), ad);
}
}
// Add them in alphabetical order.
List<String> sortedKeys = new ArrayList<String>(attributes.keySet());
Collections.sort(sortedKeys);
for (String key : sortedKeys) {
list.add(attributes.get(key));
}
return list;
}
/**
* Reacts to attribute changes by creating the correct {@link FilterControl}
* . If there already is a {@link FilterControl}, it is discarded.
*/
protected void attributeChanged(Object attribute) {
if (getFilterControl() != null) getFilterControl().dispose();
FilterControl filterControl;
if (attribute instanceof AbstractTextFilter.InternalAttribute) {
filterControl = FilterControl.createFilterControl(this,
(AbstractTextFilter.InternalAttribute) attribute);
} else if (attribute instanceof DateFilter.InternalAttribute) {
filterControl = FilterControl.createFilterControl(this,
(DateFilter.InternalAttribute) attribute);
} else if (attribute instanceof AttributeDefinition) {
filterControl = FilterControl.createFilterControl(this,
(AttributeDefinition) attribute);
} else {
MessageDialog.openError(getShell(), "Invalid Selection",
"Cannot handle (yet): " + attribute);
filterControl = null;
}
filterControl.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true,
false));
layout();
getParent().pack();
}
/**
* @return the current FilterControl, or null of not set.
*/
private FilterControl getFilterControl() {
if (getChildren().length != 3) return null;
Control control = getChildren()[2];
if (! (control instanceof FilterControl)) return null;
return (FilterControl) control;
}
/**
* @return the {@link IFilter} representing the state of the
* {@link FilterPanel}, or null if not set or incorrectly configured.
*/
public IFilter getFilter() {
return getFilterControl() == null ? null : getFilterControl().getFilter();
}
/**
* To handle objects in the Attribute dropdown, instead of just Strings..
*/
class AttributeLabelProvider extends LabelProvider {
@Override
public String getText(Object element) {
if (element instanceof AttributeDefinition) {
AttributeDefinition ad = (AttributeDefinition)element;
SpecType specType = (SpecType) ad.eContainer();
return ad.getLongName() + " (" + specType.getLongName() + ")";
}
return element.toString();
}
}
}