diff options
Diffstat (limited to 'org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/ui/wizard/TracFilterQueryPage.java')
-rw-r--r-- | org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/ui/wizard/TracFilterQueryPage.java | 444 |
1 files changed, 444 insertions, 0 deletions
diff --git a/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/ui/wizard/TracFilterQueryPage.java b/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/ui/wizard/TracFilterQueryPage.java new file mode 100644 index 000000000..a34059130 --- /dev/null +++ b/org.eclipse.mylyn.trac.ui/src/org/eclipse/mylyn/internal/trac/ui/wizard/TracFilterQueryPage.java @@ -0,0 +1,444 @@ +/******************************************************************************* + * Copyright (c) 2004, 2007 Mylyn project committers and others. + * 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 + *******************************************************************************/ + +package org.eclipse.mylyn.internal.trac.ui.wizard; + +import java.util.ArrayList; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.mylyn.commons.core.StatusHandler; +import org.eclipse.mylyn.internal.trac.core.ITracClient; +import org.eclipse.mylyn.internal.trac.core.model.TracSearch; +import org.eclipse.mylyn.internal.trac.core.model.TracSearchFilter; +import org.eclipse.mylyn.internal.trac.core.model.TracSearchFilter.CompareOperator; +import org.eclipse.mylyn.internal.trac.core.util.TracUtils; +import org.eclipse.mylyn.internal.trac.ui.TracUiPlugin; +import org.eclipse.mylyn.tasks.core.IRepositoryQuery; +import org.eclipse.mylyn.tasks.core.TaskRepository; +import org.eclipse.mylyn.tasks.ui.wizards.AbstractRepositoryQueryPage; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.ScrolledComposite; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; + +/** + * @author Steffen Pingel + */ +public class TracFilterQueryPage extends AbstractRepositoryQueryPage { + + private static final String TITLE = "New Trac Query"; + + private static final String DESCRIPTION = "Add search filters to define query."; + + private static final String TITLE_QUERY_TITLE = "Query Title"; + + private Text titleText; + + private Composite scrollComposite; + + /* Maintain order of criterions in order to be able to restore this later. */ + private final Set<SearchField> visibleSearchFields = new LinkedHashSet<SearchField>(); + + private List<SearchField> searchFields; + + public TracFilterQueryPage(TaskRepository repository, IRepositoryQuery query) { + super(TITLE, repository, query); + setTitle(TITLE); + setDescription(DESCRIPTION); + } + + @Override + public void applyTo(IRepositoryQuery query) { + query.setUrl(getQueryUrl(getTaskRepository().getRepositoryUrl())); + query.setSummary(getQueryTitle()); + } + + public void createControl(Composite parent) { + Composite composite = new Composite(parent, SWT.NONE); + composite.setLayoutData(new GridData()); + composite.setLayout(new GridLayout(1, false)); + + createTitleGroup(composite); + + ScrolledComposite scrolledComposite = new ScrolledComposite(composite, SWT.V_SCROLL | SWT.BORDER); + GridData gd = new GridData(GridData.FILL, GridData.FILL, true, true); + scrolledComposite.setExpandHorizontal(true); + scrolledComposite.setLayoutData(gd); + + scrollComposite = new Composite(scrolledComposite, SWT.None); + scrolledComposite.setContent(scrollComposite); + scrollComposite.setLayout(new GridLayout(4, false)); + + createAddFilterGroup(composite); + + if (getQuery() != null) { + titleText.setText(getQuery().getSummary()); + TracSearch search = TracUtils.toTracSearch(getQuery()); + if (search != null) { + restoreWidgetValues(search); + } + } + + setControl(composite); + } + + @Override + public String getQueryTitle() { + return (titleText != null) ? titleText.getText() : null; + } + + private void restoreWidgetValues(TracSearch search) { + List<TracSearchFilter> filters = search.getFilters(); + for (TracSearchFilter filter : filters) { + SearchField field = getSearchField(filter.getFieldName()); + if (field != null) { + showSearchField(field, filter); + } else { + StatusHandler.log(new Status(IStatus.WARNING, TracUiPlugin.ID_PLUGIN, + "Ignoring invalid search filter: " + filter)); + } + } + } + + private SearchField getSearchField(String fieldName) { + for (SearchField searchField : searchFields) { + if (searchField.getFieldName().equals(fieldName)) { + return searchField; + } + } + return null; + } + + private void createAddFilterGroup(Composite parent) { + GridLayout layout; + GridData gd; + + Composite composite = new Composite(parent, SWT.NONE); + layout = new GridLayout(2, false); + composite.setLayout(layout); + composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + gd = new GridData(GridData.BEGINNING | GridData.FILL_HORIZONTAL | GridData.GRAB_HORIZONTAL); + composite.setLayoutData(gd); + + Label label = new Label(composite, SWT.LEFT); + label.setText("Select to add filter: "); + + // condition + final Combo filterCombo = new Combo(composite, SWT.SINGLE | SWT.BORDER | SWT.READ_ONLY); + + searchFields = new ArrayList<SearchField>(); + searchFields.add(new TextSearchField("summary", "Summary")); + searchFields.add(new TextSearchField("reporter", "Reporter")); + searchFields.add(new TextSearchField("owner", "Owner")); + searchFields.add(new TextSearchField("type", "Type")); + searchFields.add(new TextSearchField("status", "Status")); + searchFields.add(new TextSearchField("priority", "Priority")); + searchFields.add(new TextSearchField("milestone", "Milestone")); + searchFields.add(new TextSearchField("component", "Component")); + searchFields.add(new TextSearchField("version", "Version")); + searchFields.add(new TextSearchField("resoution", "Resolution")); + searchFields.add(new TextSearchField("keywords", "Keywords")); + searchFields.add(new TextSearchField("cc", "CC")); + + filterCombo.add(""); + for (SearchField field : searchFields) { + filterCombo.add(field.getDisplayName()); + } + + filterCombo.addModifyListener(new ModifyListener() { + public void modifyText(ModifyEvent e) { + if (filterCombo.getText().length() > 0) { + SearchField field = searchFields.get(filterCombo.getSelectionIndex() - 1); + showSearchField(field, null); + filterCombo.setText(""); + } + } + }); + } + + private void createTitleGroup(Composite composite) { + Group group = new Group(composite, SWT.NONE); + group.setText(TITLE_QUERY_TITLE); + group.setLayout(new GridLayout(1, false)); + GridData gd = new GridData(GridData.FILL_HORIZONTAL); + group.setLayoutData(gd); + + titleText = new Text(group, SWT.BORDER); + gd = new GridData(GridData.FILL_HORIZONTAL | GridData.GRAB_HORIZONTAL); + titleText.setLayoutData(gd); + + titleText.addKeyListener(new KeyListener() { + public void keyPressed(KeyEvent e) { + // ignore + } + + public void keyReleased(KeyEvent e) { + getContainer().updateButtons(); + } + }); + } + + @Override + public boolean isPageComplete() { + if (titleText != null && titleText.getText().length() > 0) { + return true; + } + return false; + } + + private void showSearchField(SearchField field, TracSearchFilter filter) { + assert filter == null || !visibleSearchFields.contains(field); + + if (!visibleSearchFields.contains(field)) { + field.createControls(scrollComposite, filter); + visibleSearchFields.add(field); + } else { + field.addControl(scrollComposite); + } + updateScrollPane(); + } + + public String getQueryUrl(String repsitoryUrl) { + TracSearch search = new TracSearch(); + for (SearchField field : visibleSearchFields) { + search.addFilter(field.getFilter()); + } + + StringBuilder sb = new StringBuilder(); + sb.append(repsitoryUrl); + sb.append(ITracClient.QUERY_URL); + sb.append(search.toUrl()); + return sb.toString(); + } + + private void hideSearchField(SearchField field) { + visibleSearchFields.remove(field); + } + + private void updateScrollPane() { + scrollComposite.setSize(scrollComposite.computeSize(SWT.DEFAULT, SWT.DEFAULT)); + scrollComposite.layout(); + } + + private abstract class SearchField { + + protected String fieldName; + + private final String displayName; + + public SearchField(String fieldName, String displayName) { + this.fieldName = fieldName; + this.displayName = displayName; + } + + public abstract void createControls(Composite parent, TracSearchFilter filter); + + public abstract void addControl(Composite parent); + + public String getFieldName() { + return fieldName; + } + + public String getDisplayName() { + return displayName; + } + + public abstract TracSearchFilter getFilter(); + + } + + private class TextSearchField extends SearchField { + + private final CompareOperator[] compareOperators = { CompareOperator.CONTAINS, CompareOperator.CONTAINS_NOT, + CompareOperator.BEGINS_WITH, CompareOperator.ENDS_WITH, CompareOperator.IS, CompareOperator.IS_NOT, }; + + private List<TextCriterion> criterions; + + public TextSearchField(String fieldName, String displayName) { + super(fieldName, displayName); + } + + @Override + public void createControls(Composite parent, TracSearchFilter filter) { + if (filter != null) { + TextCriterion first = addCriterion(parent); + first.setCondition(filter.getOperator()); + List<String> values = filter.getValues(); + if (!values.isEmpty()) { + first.setSearchText(values.get(0)); + for (int i = 1; i < values.size(); i++) { + TextCriterion criterion = addCriterion(parent); + criterion.setSearchText(values.get(1)); + } + } + } else { + addCriterion(parent); + } + + } + + @Override + public void addControl(Composite parent) { + addCriterion(parent); + } + + public TextCriterion addCriterion(Composite parent) { + TextCriterion criterion = new TextCriterion(); + if (criterions == null) { + criterions = new ArrayList<TextCriterion>(); + criterion.createControl(parent); + } else { + criterion.createControl(parent, criterions.get(criterions.size() - 1)); + } + criterions.add(criterion); + return criterion; + } + + @Override + public TracSearchFilter getFilter() { + TracSearchFilter newFilter = new TracSearchFilter(getFieldName()); + newFilter.setOperator(criterions.get(0).getCondition()); + for (TextCriterion criterion : criterions) { + newFilter.addValue(criterion.getSearchText()); + } + return newFilter; + } + + public void removeCriterion(TextCriterion criterion) { + int i = criterions.indexOf(criterion); + if (i == -1) { + throw new RuntimeException(); + } + if (i == 0) { + // the first criterion is special since it contains the compare + // operator combo + if (criterions.size() > 1) { + // copy the value from the second criterion to the first + TextCriterion sourceCriterion = criterions.get(1); + criterion.searchText.setText(sourceCriterion.searchText.getText()); + removeCriterionByIndex(1); + } else { + // no more criterions, remove all controls + removeCriterionByIndex(0); + hideSearchField(this); + } + } else { + removeCriterionByIndex(i); + } + } + + private void removeCriterionByIndex(int i) { + criterions.get(i).remove(); + criterions.remove(i); + updateScrollPane(); + } + + private class TextCriterion { + + private Combo conditionCombo; + + private Text searchText; + + private Label label; + + private Button removeButton; + + public void createControl(Composite parent) { + label = new Label(parent, SWT.LEFT); + label.setText(getDisplayName() + ": "); + + conditionCombo = new Combo(parent, SWT.SINGLE | SWT.BORDER | SWT.READ_ONLY); + for (CompareOperator op : compareOperators) { + conditionCombo.add(op.toString()); + } + conditionCombo.setText(compareOperators[0].toString()); + + createSearchTextAndRemoveButton(parent); + } + + public void createControl(Composite parent, TextCriterion top) { + label = new Label(parent, SWT.RIGHT); + GridData gd = new GridData(); + gd.horizontalAlignment = SWT.END; + gd.horizontalSpan = 2; + label.setLayoutData(gd); + label.setText("or"); + + createSearchTextAndRemoveButton(parent); + + label.moveBelow(top.removeButton); + searchText.moveBelow(label); + removeButton.moveBelow(searchText); + } + + private void createSearchTextAndRemoveButton(Composite parent) { + searchText = new Text(parent, SWT.BORDER); + GridData gd = new GridData(GridData.GRAB_HORIZONTAL | GridData.FILL_HORIZONTAL); + searchText.setLayoutData(gd); + + removeButton = new Button(parent, SWT.PUSH); + removeButton.setText("-"); + removeButton.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(org.eclipse.swt.events.SelectionEvent e) { + TextSearchField.this.removeCriterion(TextCriterion.this); + } + }); + } + + public void remove() { + label.dispose(); + if (conditionCombo != null) { + conditionCombo.dispose(); + } + searchText.dispose(); + removeButton.dispose(); + } + + public CompareOperator getCondition() { + return (conditionCombo != null) ? compareOperators[conditionCombo.getSelectionIndex()] : null; + } + + public String getSearchText() { + return searchText.getText(); + } + + public boolean setCondition(CompareOperator operator) { + if (conditionCombo != null) { + int i = conditionCombo.indexOf(operator.toString()); + if (i != -1) { + conditionCombo.select(i); + return true; + } + } + return false; + } + + public void setSearchText(String text) { + searchText.setText(text); + } + + } + } + +} |